diff options
Diffstat (limited to 'gnuradio-core/src')
1368 files changed, 128244 insertions, 0 deletions
diff --git a/gnuradio-core/src/examples/CMakeLists.txt b/gnuradio-core/src/examples/CMakeLists.txt new file mode 100644 index 000000000..01d9eb83e --- /dev/null +++ b/gnuradio-core/src/examples/CMakeLists.txt @@ -0,0 +1,25 @@ +# 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. + +add_subdirectory(mp-sched) +add_subdirectory(msg_passing) +add_subdirectory(network) +add_subdirectory(pfb) +add_subdirectory(tags) +add_subdirectory(volk_benchmark)
\ No newline at end of file diff --git a/gnuradio-core/src/examples/mp-sched/CMakeLists.txt b/gnuradio-core/src/examples/mp-sched/CMakeLists.txt new file mode 100644 index 000000000..d2d910ecf --- /dev/null +++ b/gnuradio-core/src/examples/mp-sched/CMakeLists.txt @@ -0,0 +1,36 @@ +# 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(GrPython) + +GR_PYTHON_INSTALL(PROGRAMS + affinity_set.py + plot_flops.py + run_synthetic.py + synthetic.py + wfm_rcv_pll_to_wav.py + DESTINATION ${GR_PKG_DATA_DIR}/examples/mp-sched + COMPONENT "core_python" +) + +install( + FILES README + DESTINATION ${GR_PKG_DATA_DIR}/examples/mp-sched + COMPONENT "core_python" +) diff --git a/gnuradio-core/src/examples/mp-sched/README b/gnuradio-core/src/examples/mp-sched/README new file mode 100644 index 000000000..ae575437a --- /dev/null +++ b/gnuradio-core/src/examples/mp-sched/README @@ -0,0 +1,2 @@ +These are pieces of code used to test and benchmark the +multi-processor scheduler. diff --git a/gnuradio-core/src/examples/mp-sched/affinity_set.py b/gnuradio-core/src/examples/mp-sched/affinity_set.py new file mode 100755 index 000000000..65e929051 --- /dev/null +++ b/gnuradio-core/src/examples/mp-sched/affinity_set.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python +################################################## +# Gnuradio Python Flow Graph +# Title: Affinity Set Test +################################################## + +from gnuradio import eng_notation +from gnuradio import gr +from gnuradio.eng_option import eng_option +from gnuradio.gr import firdes +from optparse import OptionParser +import sys + +class affinity_set(gr.top_block): + + def __init__(self): + gr.top_block.__init__(self, "Affinity Set Test") + + ################################################## + # Variables + ################################################## + self.samp_rate = samp_rate = 32000 + + ################################################## + # Blocks + ################################################## + vec_len = 1 + self.gr_throttle_0 = gr.throttle(gr.sizeof_gr_complex*vec_len, samp_rate) + self.gr_null_source_0 = gr.null_source(gr.sizeof_gr_complex*vec_len) + self.gr_null_sink_0 = gr.null_sink(gr.sizeof_gr_complex*vec_len) + self.gr_filt_0 = gr.fir_filter_ccc(1, 40000*[0.2+0.3j,]) + self.gr_filt_1 = gr.fir_filter_ccc(1, 40000*[0.2+0.3j,]) + + self.gr_filt_0.set_processor_affinity([0,]) + self.gr_filt_1.set_processor_affinity([0,1]) + + ################################################## + # Connections + ################################################## + self.connect((self.gr_null_source_0, 0), (self.gr_throttle_0, 0)) + self.connect((self.gr_throttle_0, 0), (self.gr_filt_0, 0)) + self.connect((self.gr_filt_0, 0), (self.gr_filt_1, 0)) + self.connect((self.gr_filt_1, 0), (self.gr_null_sink_0, 0)) + + def get_samp_rate(self): + return self.samp_rate + + def set_samp_rate(self, samp_rate): + self.samp_rate = samp_rate + +if __name__ == '__main__': + parser = OptionParser(option_class=eng_option, usage="%prog: [options]") + (options, args) = parser.parse_args() + tb = affinity_set() + tb.start() + + while(1): + ret = raw_input('Enter a new Core # or Press Enter to quit: ') + if(len(ret) == 0): + tb.stop() + sys.exit(0) + elif(ret.lower() == "none"): + tb.gr_filt_0.unset_processor_affinity() + else: + try: + n = int(ret) + except ValueError: + print "Invalid number" + else: + tb.gr_filt_0.set_processor_affinity([n,]) diff --git a/gnuradio-core/src/examples/mp-sched/perf-data/core-duo.dat b/gnuradio-core/src/examples/mp-sched/perf-data/core-duo.dat new file mode 100644 index 000000000..064d1e128 --- /dev/null +++ b/gnuradio-core/src/examples/mp-sched/perf-data/core-duo.dat @@ -0,0 +1,65 @@ +#D Core Duo 1.83 GHz (T2400) + 1 1 5.273e+07 10.010 10.160 0.060 1.021 2.700000e+10 2.697e+09 + 1 2 5.273e+07 10.410 20.180 0.150 1.953 5.400000e+10 5.187e+09 + 1 3 3.516e+07 10.360 20.030 0.150 1.948 5.400000e+10 5.212e+09 + 1 4 2.637e+07 10.100 20.030 0.100 1.993 5.400000e+10 5.347e+09 + 1 5 2.109e+07 10.140 19.980 0.110 1.981 5.400000e+10 5.325e+09 + 1 6 1.758e+07 10.110 20.030 0.110 1.992 5.400000e+10 5.341e+09 + 1 7 1.507e+07 10.120 20.030 0.110 1.990 5.400000e+10 5.336e+09 + 1 8 1.318e+07 10.060 19.980 0.090 1.995 5.400000e+10 5.368e+09 + 2 1 5.273e+07 10.210 20.130 0.260 1.997 5.400000e+10 5.289e+09 + 2 2 2.637e+07 10.110 20.030 0.140 1.995 5.400000e+10 5.341e+09 + 2 3 1.758e+07 10.120 20.010 0.150 1.992 5.400000e+10 5.336e+09 + 2 4 1.318e+07 10.080 19.990 0.110 1.994 5.400000e+10 5.357e+09 + 2 5 1.055e+07 10.050 19.990 0.090 1.998 5.400000e+10 5.373e+09 + 2 6 8.789e+06 10.050 19.980 0.080 1.996 5.400000e+10 5.373e+09 + 2 7 7.533e+06 10.050 19.970 0.090 1.996 5.400000e+10 5.373e+09 + 2 8 6.592e+06 10.040 19.970 0.090 1.998 5.399999e+10 5.378e+09 + 3 1 3.516e+07 10.630 20.130 0.230 1.915 5.400000e+10 5.080e+09 + 3 2 1.758e+07 10.120 20.020 0.170 1.995 5.400000e+10 5.336e+09 + 3 3 1.172e+07 10.140 20.050 0.130 1.990 5.400000e+10 5.325e+09 + 3 4 8.789e+06 10.070 20.010 0.100 1.997 5.400000e+10 5.362e+09 + 3 5 7.031e+06 10.060 19.980 0.100 1.996 5.400000e+10 5.368e+09 + 3 6 5.859e+06 10.060 20.000 0.100 1.998 5.400000e+10 5.368e+09 + 3 7 5.022e+06 10.050 20.010 0.070 1.998 5.400000e+10 5.373e+09 + 3 8 4.395e+06 10.050 19.990 0.070 1.996 5.400000e+10 5.373e+09 + 4 1 2.637e+07 10.180 20.080 0.240 1.996 5.400000e+10 5.305e+09 + 4 2 1.318e+07 10.140 20.000 0.180 1.990 5.400000e+10 5.325e+09 + 4 3 8.789e+06 10.110 20.020 0.120 1.992 5.400000e+10 5.341e+09 + 4 4 6.592e+06 10.080 20.020 0.090 1.995 5.399999e+10 5.357e+09 + 4 5 5.273e+06 10.050 19.990 0.090 1.998 5.399999e+10 5.373e+09 + 4 6 4.395e+06 10.080 20.010 0.080 1.993 5.400000e+10 5.357e+09 + 4 7 3.767e+06 10.070 20.000 0.080 1.994 5.400000e+10 5.362e+09 + 4 8 3.296e+06 10.050 20.000 0.080 1.998 5.399999e+10 5.373e+09 + 5 1 2.109e+07 11.240 20.080 0.260 1.810 5.400000e+10 4.804e+09 + 5 2 1.055e+07 10.130 19.990 0.150 1.988 5.400000e+10 5.331e+09 + 5 3 7.031e+06 10.100 20.020 0.120 1.994 5.400000e+10 5.347e+09 + 5 4 5.273e+06 10.070 20.000 0.090 1.995 5.399999e+10 5.362e+09 + 5 5 4.219e+06 10.100 20.040 0.090 1.993 5.400000e+10 5.347e+09 + 5 6 3.516e+06 10.080 20.000 0.090 1.993 5.400000e+10 5.357e+09 + 5 7 3.013e+06 10.070 20.000 0.100 1.996 5.399998e+10 5.362e+09 + 5 8 2.637e+06 10.070 20.000 0.090 1.995 5.399998e+10 5.362e+09 + 6 1 1.758e+07 10.220 20.100 0.290 1.995 5.400000e+10 5.284e+09 + 6 2 8.789e+06 10.080 20.010 0.130 1.998 5.400000e+10 5.357e+09 + 6 3 5.859e+06 10.090 20.030 0.120 1.997 5.400000e+10 5.352e+09 + 6 4 4.395e+06 10.100 20.030 0.080 1.991 5.400000e+10 5.347e+09 + 6 5 3.516e+06 10.060 20.020 0.080 1.998 5.400000e+10 5.368e+09 + 6 6 2.930e+06 10.070 20.030 0.090 1.998 5.399999e+10 5.362e+09 + 6 7 2.511e+06 10.070 20.030 0.080 1.997 5.399998e+10 5.362e+09 + 6 8 2.197e+06 10.070 20.010 0.090 1.996 5.399998e+10 5.362e+09 + 7 1 1.507e+07 10.420 20.030 0.260 1.947 5.400000e+10 5.182e+09 + 7 2 7.533e+06 10.100 20.010 0.140 1.995 5.400000e+10 5.347e+09 + 7 3 5.022e+06 10.080 20.020 0.120 1.998 5.400000e+10 5.357e+09 + 7 4 3.767e+06 10.080 20.010 0.100 1.995 5.400000e+10 5.357e+09 + 7 5 3.013e+06 10.070 20.030 0.080 1.997 5.399998e+10 5.362e+09 + 7 6 2.511e+06 10.080 20.010 0.090 1.994 5.399998e+10 5.357e+09 + 7 7 2.152e+06 10.080 20.060 0.070 1.997 5.399999e+10 5.357e+09 + 7 8 1.883e+06 10.070 20.040 0.070 1.997 5.399998e+10 5.362e+09 + 8 1 1.318e+07 10.220 20.080 0.270 1.991 5.400000e+10 5.284e+09 + 8 2 6.592e+06 10.100 20.010 0.140 1.995 5.399999e+10 5.347e+09 + 8 3 4.395e+06 10.110 20.020 0.120 1.992 5.400000e+10 5.341e+09 + 8 4 3.296e+06 10.090 20.040 0.090 1.995 5.399999e+10 5.352e+09 + 8 5 2.637e+06 10.090 20.040 0.090 1.995 5.399998e+10 5.352e+09 + 8 6 2.197e+06 10.070 20.040 0.100 2.000 5.399998e+10 5.362e+09 + 8 7 1.883e+06 10.090 20.050 0.080 1.995 5.399998e+10 5.352e+09 + 8 8 1.648e+06 10.090 20.040 0.090 1.995 5.399999e+10 5.352e+09 diff --git a/gnuradio-core/src/examples/mp-sched/perf-data/core2-duo.dat b/gnuradio-core/src/examples/mp-sched/perf-data/core2-duo.dat new file mode 100644 index 000000000..d67dee8e5 --- /dev/null +++ b/gnuradio-core/src/examples/mp-sched/perf-data/core2-duo.dat @@ -0,0 +1,65 @@ +#D Core2 Duo 2.66 GHz (6700) + 1 1 1.406e+08 9.890 10.100 0.230 1.044 7.200000e+10 7.280e+09 + 1 2 1.406e+08 10.400 19.900 0.290 1.941 1.440000e+11 1.385e+10 + 1 3 9.375e+07 11.410 19.950 0.200 1.766 1.440000e+11 1.262e+10 + 1 4 7.031e+07 10.230 19.800 0.230 1.958 1.440000e+11 1.408e+10 + 1 5 5.625e+07 10.640 19.800 0.180 1.878 1.440000e+11 1.353e+10 + 1 6 4.688e+07 10.000 19.780 0.130 1.991 1.440000e+11 1.440e+10 + 1 7 4.018e+07 10.500 19.690 0.180 1.892 1.440000e+11 1.371e+10 + 1 8 3.516e+07 10.020 19.750 0.170 1.988 1.440000e+11 1.437e+10 + 2 1 1.406e+08 10.330 20.000 0.460 1.981 1.440000e+11 1.394e+10 + 2 2 7.031e+07 10.160 19.870 0.270 1.982 1.440000e+11 1.417e+10 + 2 3 4.688e+07 10.210 19.780 0.230 1.960 1.440000e+11 1.410e+10 + 2 4 3.516e+07 10.050 19.730 0.210 1.984 1.440000e+11 1.433e+10 + 2 5 2.812e+07 10.060 19.760 0.170 1.981 1.440000e+11 1.431e+10 + 2 6 2.344e+07 10.030 19.780 0.180 1.990 1.440000e+11 1.436e+10 + 2 7 2.009e+07 10.040 19.820 0.180 1.992 1.440000e+11 1.434e+10 + 2 8 1.758e+07 10.050 19.820 0.180 1.990 1.440000e+11 1.433e+10 + 3 1 9.375e+07 13.140 19.950 0.450 1.553 1.440000e+11 1.096e+10 + 3 2 4.688e+07 10.570 19.840 0.290 1.904 1.440000e+11 1.362e+10 + 3 3 3.125e+07 10.420 19.730 0.280 1.920 1.440000e+11 1.382e+10 + 3 4 2.344e+07 10.120 19.710 0.240 1.971 1.440000e+11 1.423e+10 + 3 5 1.875e+07 10.140 19.750 0.190 1.966 1.440000e+11 1.420e+10 + 3 6 1.562e+07 10.030 19.730 0.190 1.986 1.440000e+11 1.436e+10 + 3 7 1.339e+07 10.020 19.720 0.200 1.988 1.440000e+11 1.437e+10 + 3 8 1.172e+07 9.990 19.720 0.170 1.991 1.440000e+11 1.441e+10 + 4 1 7.031e+07 10.310 19.980 0.460 1.983 1.440000e+11 1.397e+10 + 4 2 3.516e+07 10.300 19.830 0.320 1.956 1.440000e+11 1.398e+10 + 4 3 2.344e+07 10.180 19.780 0.230 1.966 1.440000e+11 1.415e+10 + 4 4 1.758e+07 10.070 19.750 0.220 1.983 1.440000e+11 1.430e+10 + 4 5 1.406e+07 10.090 19.750 0.190 1.976 1.440000e+11 1.427e+10 + 4 6 1.172e+07 10.020 19.720 0.190 1.987 1.440000e+11 1.437e+10 + 4 7 1.004e+07 10.040 19.780 0.190 1.989 1.440000e+11 1.434e+10 + 4 8 8.789e+06 10.000 19.750 0.160 1.991 1.440000e+11 1.440e+10 + 5 1 5.625e+07 11.580 19.930 0.500 1.764 1.440000e+11 1.244e+10 + 5 2 2.812e+07 10.300 19.830 0.320 1.956 1.440000e+11 1.398e+10 + 5 3 1.875e+07 10.240 19.760 0.240 1.953 1.440000e+11 1.406e+10 + 5 4 1.406e+07 10.140 19.880 0.230 1.983 1.440000e+11 1.420e+10 + 5 5 1.125e+07 10.040 19.730 0.200 1.985 1.440000e+11 1.434e+10 + 5 6 9.375e+06 10.030 19.770 0.200 1.991 1.440000e+11 1.436e+10 + 5 7 8.036e+06 10.030 19.780 0.170 1.989 1.440000e+11 1.436e+10 + 5 8 7.031e+06 10.000 19.750 0.180 1.993 1.440000e+11 1.440e+10 + 6 1 4.688e+07 10.340 19.910 0.560 1.980 1.440000e+11 1.393e+10 + 6 2 2.344e+07 10.290 19.770 0.330 1.953 1.440000e+11 1.399e+10 + 6 3 1.562e+07 10.150 19.770 0.270 1.974 1.440000e+11 1.419e+10 + 6 4 1.172e+07 10.170 19.880 0.240 1.978 1.440000e+11 1.416e+10 + 6 5 9.375e+06 10.080 19.780 0.240 1.986 1.440000e+11 1.429e+10 + 6 6 7.812e+06 10.020 19.740 0.220 1.992 1.440000e+11 1.437e+10 + 6 7 6.696e+06 10.050 19.760 0.200 1.986 1.440000e+11 1.433e+10 + 6 8 5.859e+06 10.070 19.750 0.210 1.982 1.440000e+11 1.430e+10 + 7 1 4.018e+07 11.220 19.880 0.530 1.819 1.440000e+11 1.283e+10 + 7 2 2.009e+07 10.280 19.790 0.340 1.958 1.440000e+11 1.401e+10 + 7 3 1.339e+07 10.190 19.760 0.250 1.964 1.440000e+11 1.413e+10 + 7 4 1.004e+07 10.060 19.750 0.240 1.987 1.440000e+11 1.431e+10 + 7 5 8.036e+06 10.070 19.750 0.240 1.985 1.440000e+11 1.430e+10 + 7 6 6.696e+06 10.040 19.810 0.220 1.995 1.440000e+11 1.434e+10 + 7 7 5.740e+06 10.050 19.780 0.210 1.989 1.440000e+11 1.433e+10 + 7 8 5.022e+06 10.010 19.790 0.190 1.996 1.440000e+11 1.439e+10 + 8 1 3.516e+07 10.320 19.900 0.470 1.974 1.440000e+11 1.395e+10 + 8 2 1.758e+07 10.340 19.900 0.320 1.956 1.440000e+11 1.393e+10 + 8 3 1.172e+07 10.130 19.770 0.290 1.980 1.440000e+11 1.422e+10 + 8 4 8.789e+06 10.120 19.780 0.230 1.977 1.440000e+11 1.423e+10 + 8 5 7.031e+06 10.040 19.790 0.200 1.991 1.440000e+11 1.434e+10 + 8 6 5.859e+06 10.050 19.770 0.220 1.989 1.440000e+11 1.433e+10 + 8 7 5.022e+06 10.030 19.800 0.200 1.994 1.440000e+11 1.436e+10 + 8 8 4.395e+06 10.050 19.800 0.210 1.991 1.440000e+11 1.433e+10 diff --git a/gnuradio-core/src/examples/mp-sched/perf-data/dual-quad-core-2.33-clovertown.dat b/gnuradio-core/src/examples/mp-sched/perf-data/dual-quad-core-2.33-clovertown.dat new file mode 100644 index 000000000..fa182c69a --- /dev/null +++ b/gnuradio-core/src/examples/mp-sched/perf-data/dual-quad-core-2.33-clovertown.dat @@ -0,0 +1,257 @@ +#D Dual quad-core Xeon 2.33GHz (Clovertown E5345) + 1 1 1.367e+08 10.980 12.080 0.360 1.133 7.000000e+10 6.375e+09 + 1 2 1.367e+08 12.250 24.310 0.400 2.017 1.400000e+11 1.143e+10 + 1 3 1.367e+08 12.830 36.080 0.580 2.857 2.100000e+11 1.637e+10 + 1 4 1.367e+08 12.600 46.820 0.770 3.777 2.800000e+11 2.222e+10 + 1 5 1.367e+08 12.620 58.850 0.720 4.720 3.500000e+11 2.773e+10 + 1 6 1.367e+08 12.310 69.430 0.860 5.710 4.200000e+11 3.412e+10 + 1 7 1.367e+08 12.720 80.580 0.950 6.410 4.900000e+11 3.852e+10 + 1 8 1.367e+08 12.440 91.530 1.010 7.439 5.600000e+11 4.502e+10 + 1 9 1.367e+08 22.310 102.660 1.080 4.650 6.300000e+11 2.824e+10 + 1 10 1.367e+08 22.610 113.670 1.160 5.079 7.000000e+11 3.096e+10 + 1 11 1.367e+08 22.690 124.730 1.030 5.543 7.700000e+11 3.394e+10 + 1 12 1.367e+08 23.260 136.520 1.030 5.914 8.400000e+11 3.611e+10 + 1 13 1.367e+08 23.330 147.270 1.130 6.361 9.100000e+11 3.901e+10 + 1 14 1.367e+08 24.110 158.070 1.010 6.598 9.800000e+11 4.065e+10 + 1 15 1.367e+08 25.380 168.370 1.080 6.677 1.050000e+12 4.137e+10 + 1 16 1.367e+08 26.660 179.130 1.250 6.766 1.120000e+12 4.201e+10 + 2 1 1.367e+08 11.190 23.330 0.420 2.122 1.400000e+11 1.251e+10 + 2 2 1.367e+08 12.650 46.350 0.940 3.738 2.800000e+11 2.213e+10 + 2 3 1.367e+08 12.510 69.010 0.980 5.595 4.200000e+11 3.357e+10 + 2 4 1.367e+08 13.250 89.330 0.890 6.809 5.600000e+11 4.226e+10 + 2 5 1.367e+08 22.540 113.580 1.150 5.090 7.000000e+11 3.106e+10 + 2 6 1.367e+08 22.940 135.790 1.260 5.974 8.400000e+11 3.662e+10 + 2 7 1.367e+08 24.250 158.360 1.520 6.593 9.800000e+11 4.041e+10 + 2 8 1.367e+08 26.610 179.840 1.490 6.814 1.120000e+12 4.209e+10 + 2 9 1.215e+08 26.860 179.400 1.540 6.736 1.120000e+12 4.170e+10 + 2 10 1.094e+08 26.350 178.740 1.430 6.838 1.120000e+12 4.250e+10 + 2 11 9.943e+07 25.790 177.910 1.350 6.951 1.120000e+12 4.343e+10 + 2 12 9.115e+07 25.200 176.980 1.460 7.081 1.120000e+12 4.444e+10 + 2 13 8.413e+07 24.840 177.320 1.260 7.189 1.120000e+12 4.509e+10 + 2 14 7.812e+07 24.450 176.920 1.130 7.282 1.120000e+12 4.581e+10 + 2 15 7.292e+07 24.280 177.400 1.140 7.353 1.120000e+12 4.613e+10 + 2 16 6.836e+07 23.830 176.290 1.100 7.444 1.120000e+12 4.700e+10 + 3 1 1.367e+08 11.360 34.790 0.930 3.144 2.100000e+11 1.849e+10 + 3 2 1.367e+08 12.560 68.800 1.400 5.589 4.200000e+11 3.344e+10 + 3 3 1.367e+08 22.310 103.250 1.310 4.687 6.300000e+11 2.824e+10 + 3 4 1.367e+08 22.940 136.120 1.500 5.999 8.400000e+11 3.662e+10 + 3 5 1.367e+08 25.240 168.550 1.790 6.749 1.050000e+12 4.160e+10 + 3 6 1.215e+08 26.800 178.710 1.610 6.728 1.120000e+12 4.179e+10 + 3 7 1.042e+08 26.090 178.710 1.490 6.907 1.120000e+12 4.293e+10 + 3 8 9.115e+07 25.420 178.140 1.360 7.061 1.120000e+12 4.406e+10 + 3 9 8.102e+07 24.680 177.260 1.410 7.239 1.120000e+12 4.538e+10 + 3 10 7.292e+07 24.270 176.830 1.390 7.343 1.120000e+12 4.615e+10 + 3 11 6.629e+07 23.890 177.060 1.240 7.463 1.120000e+12 4.688e+10 + 3 12 6.076e+07 23.620 176.290 1.300 7.519 1.120000e+12 4.742e+10 + 3 13 5.609e+07 23.340 176.780 1.230 7.627 1.120000e+12 4.799e+10 + 3 14 5.208e+07 23.140 176.330 1.300 7.676 1.120000e+12 4.840e+10 + 3 15 4.861e+07 23.100 176.940 1.080 7.706 1.120000e+12 4.848e+10 + 3 16 4.557e+07 22.850 176.120 1.060 7.754 1.120000e+12 4.902e+10 + 4 1 1.367e+08 11.440 45.520 1.080 4.073 2.800000e+11 2.448e+10 + 4 2 1.367e+08 12.410 90.020 1.440 7.370 5.600000e+11 4.512e+10 + 4 3 1.367e+08 23.060 135.570 1.600 5.948 8.400000e+11 3.643e+10 + 4 4 1.367e+08 26.720 179.780 1.880 6.799 1.120000e+12 4.192e+10 + 4 5 1.094e+08 26.280 178.110 1.890 6.849 1.120000e+12 4.262e+10 + 4 6 9.115e+07 25.250 177.280 1.700 7.088 1.120000e+12 4.436e+10 + 4 7 7.812e+07 24.880 177.830 1.570 7.211 1.120000e+12 4.502e+10 + 4 8 6.836e+07 24.150 177.240 1.350 7.395 1.120000e+12 4.638e+10 + 4 9 6.076e+07 23.730 176.590 1.370 7.499 1.120000e+12 4.720e+10 + 4 10 5.469e+07 23.380 176.570 1.310 7.608 1.120000e+12 4.790e+10 + 4 11 4.972e+07 23.230 176.400 1.290 7.649 1.120000e+12 4.821e+10 + 4 12 4.557e+07 22.950 176.100 1.250 7.728 1.120000e+12 4.880e+10 + 4 13 4.207e+07 22.980 176.430 1.260 7.732 1.120000e+12 4.874e+10 + 4 14 3.906e+07 22.820 176.300 1.350 7.785 1.120000e+12 4.908e+10 + 4 15 3.646e+07 22.750 176.450 1.220 7.810 1.120000e+12 4.923e+10 + 4 16 3.418e+07 22.620 176.350 1.080 7.844 1.120000e+12 4.951e+10 + 5 1 1.367e+08 12.000 56.890 1.600 4.874 3.500000e+11 2.917e+10 + 5 2 1.367e+08 22.390 112.870 1.920 5.127 7.000000e+11 3.126e+10 + 5 3 1.367e+08 25.170 167.880 2.110 6.754 1.050000e+12 4.172e+10 + 5 4 1.094e+08 26.380 178.010 1.900 6.820 1.120000e+12 4.246e+10 + 5 5 8.750e+07 25.190 177.570 1.660 7.115 1.120000e+12 4.446e+10 + 5 6 7.292e+07 24.400 176.750 1.650 7.311 1.120000e+12 4.590e+10 + 5 7 6.250e+07 24.020 177.580 1.570 7.458 1.120000e+12 4.663e+10 + 5 8 5.469e+07 23.470 176.650 1.350 7.584 1.120000e+12 4.772e+10 + 5 9 4.861e+07 23.200 176.350 1.280 7.656 1.120000e+12 4.828e+10 + 5 10 4.375e+07 23.140 176.230 1.410 7.677 1.120000e+12 4.840e+10 + 5 11 3.977e+07 22.930 176.120 1.320 7.738 1.120000e+12 4.884e+10 + 5 12 3.646e+07 22.740 176.060 1.330 7.801 1.120000e+12 4.925e+10 + 5 13 3.365e+07 22.690 176.450 1.210 7.830 1.120000e+12 4.936e+10 + 5 14 3.125e+07 22.690 176.430 1.230 7.830 1.120000e+12 4.936e+10 + 5 15 2.917e+07 22.690 176.410 1.260 7.830 1.120000e+12 4.936e+10 + 5 16 2.734e+07 22.560 176.150 1.110 7.857 1.120000e+12 4.965e+10 + 6 1 1.367e+08 12.600 68.590 2.230 5.621 4.200000e+11 3.333e+10 + 6 2 1.367e+08 22.830 135.260 2.100 6.017 8.400000e+11 3.679e+10 + 6 3 1.215e+08 26.860 178.470 2.140 6.724 1.120000e+12 4.170e+10 + 6 4 9.115e+07 25.450 177.110 2.060 7.040 1.120000e+12 4.401e+10 + 6 5 7.292e+07 24.510 176.850 1.910 7.293 1.120000e+12 4.570e+10 + 6 6 6.076e+07 23.890 176.450 1.760 7.460 1.120000e+12 4.688e+10 + 6 7 5.208e+07 23.460 175.980 1.540 7.567 1.120000e+12 4.774e+10 + 6 8 4.557e+07 23.150 176.480 1.370 7.683 1.120000e+12 4.838e+10 + 6 9 4.051e+07 22.920 176.030 1.400 7.741 1.120000e+12 4.887e+10 + 6 10 3.646e+07 22.880 176.300 1.350 7.764 1.120000e+12 4.895e+10 + 6 11 3.314e+07 22.830 175.970 1.360 7.767 1.120000e+12 4.906e+10 + 6 12 3.038e+07 22.710 176.040 1.190 7.804 1.120000e+12 4.932e+10 + 6 13 2.804e+07 22.690 176.050 1.340 7.818 1.120000e+12 4.936e+10 + 6 14 2.604e+07 22.650 176.410 1.140 7.839 1.120000e+12 4.945e+10 + 6 15 2.431e+07 22.570 175.940 1.250 7.851 1.120000e+12 4.962e+10 + 6 16 2.279e+07 22.500 175.980 1.170 7.873 1.120000e+12 4.978e+10 + 7 1 1.367e+08 12.960 79.970 2.850 6.390 4.900000e+11 3.781e+10 + 7 2 1.367e+08 24.040 156.540 2.500 6.616 9.800000e+11 4.077e+10 + 7 3 1.042e+08 26.130 178.060 2.210 6.899 1.120000e+12 4.286e+10 + 7 4 7.812e+07 24.860 176.880 1.810 7.188 1.120000e+12 4.505e+10 + 7 5 6.250e+07 24.000 176.590 1.790 7.433 1.120000e+12 4.667e+10 + 7 6 5.208e+07 23.540 176.480 1.670 7.568 1.120000e+12 4.758e+10 + 7 7 4.464e+07 23.180 176.030 1.510 7.659 1.120000e+12 4.832e+10 + 7 8 3.906e+07 22.980 176.500 1.340 7.739 1.120000e+12 4.874e+10 + 7 9 3.472e+07 22.870 175.970 1.280 7.750 1.120000e+12 4.897e+10 + 7 10 3.125e+07 22.730 176.220 1.300 7.810 1.120000e+12 4.927e+10 + 7 11 2.841e+07 22.700 176.030 1.300 7.812 1.120000e+12 4.934e+10 + 7 12 2.604e+07 22.650 176.300 1.210 7.837 1.120000e+12 4.945e+10 + 7 13 2.404e+07 22.580 176.140 1.170 7.853 1.120000e+12 4.960e+10 + 7 14 2.232e+07 22.540 176.550 1.130 7.883 1.120000e+12 4.969e+10 + 7 15 2.083e+07 22.570 175.870 1.260 7.848 1.120000e+12 4.962e+10 + 7 16 1.953e+07 22.520 175.980 1.310 7.873 1.120000e+12 4.973e+10 + 8 1 1.367e+08 13.250 91.770 3.010 7.153 5.600000e+11 4.226e+10 + 8 2 1.367e+08 26.280 178.100 2.980 6.890 1.120000e+12 4.262e+10 + 8 3 9.115e+07 25.510 177.140 2.270 7.033 1.120000e+12 4.390e+10 + 8 4 6.836e+07 24.330 176.850 1.870 7.346 1.120000e+12 4.603e+10 + 8 5 5.469e+07 23.680 176.850 1.690 7.540 1.120000e+12 4.730e+10 + 8 6 4.557e+07 23.430 176.210 1.700 7.593 1.120000e+12 4.780e+10 + 8 7 3.906e+07 23.100 176.680 1.440 7.711 1.120000e+12 4.848e+10 + 8 8 3.418e+07 22.890 176.270 1.430 7.763 1.120000e+12 4.893e+10 + 8 9 3.038e+07 22.760 175.980 1.320 7.790 1.120000e+12 4.921e+10 + 8 10 2.734e+07 22.760 176.340 1.290 7.804 1.120000e+12 4.921e+10 + 8 11 2.486e+07 22.660 176.220 1.170 7.828 1.120000e+12 4.943e+10 + 8 12 2.279e+07 22.660 176.050 1.280 7.826 1.120000e+12 4.943e+10 + 8 13 2.103e+07 22.590 176.170 1.350 7.858 1.120000e+12 4.958e+10 + 8 14 1.953e+07 22.550 176.120 1.320 7.869 1.120000e+12 4.967e+10 + 8 15 1.823e+07 22.590 176.130 1.270 7.853 1.120000e+12 4.958e+10 + 8 16 1.709e+07 22.500 176.090 1.230 7.881 1.120000e+12 4.978e+10 + 9 1 1.367e+08 21.110 101.410 2.640 4.929 6.300000e+11 2.984e+10 + 9 2 1.215e+08 27.400 178.180 2.720 6.602 1.120000e+12 4.088e+10 + 9 3 8.102e+07 25.140 177.370 2.230 7.144 1.120000e+12 4.455e+10 + 9 4 6.076e+07 24.110 176.810 1.910 7.413 1.120000e+12 4.645e+10 + 9 5 4.861e+07 23.460 176.240 1.600 7.581 1.120000e+12 4.774e+10 + 9 6 4.051e+07 23.200 176.310 1.620 7.669 1.120000e+12 4.828e+10 + 9 7 3.472e+07 22.970 176.560 1.540 7.754 1.120000e+12 4.876e+10 + 9 8 3.038e+07 22.920 176.300 1.440 7.755 1.120000e+12 4.887e+10 + 9 9 2.701e+07 22.830 176.090 1.370 7.773 1.120000e+12 4.906e+10 + 9 10 2.431e+07 22.730 175.960 1.430 7.804 1.120000e+12 4.927e+10 + 9 11 2.210e+07 22.750 176.160 1.260 7.799 1.120000e+12 4.923e+10 + 9 12 2.025e+07 22.660 176.100 1.380 7.832 1.120000e+12 4.943e+10 + 9 13 1.870e+07 22.700 176.040 1.400 7.817 1.120000e+12 4.934e+10 + 9 14 1.736e+07 22.620 175.940 1.410 7.840 1.120000e+12 4.951e+10 + 9 15 1.620e+07 22.490 175.910 1.340 7.881 1.120000e+12 4.980e+10 + 9 16 1.519e+07 22.540 175.990 1.330 7.867 1.120000e+12 4.969e+10 + 10 1 1.367e+08 21.730 113.690 2.870 5.364 7.000000e+11 3.221e+10 + 10 2 1.094e+08 26.660 177.920 3.180 6.793 1.120000e+12 4.201e+10 + 10 3 7.292e+07 24.740 176.810 2.090 7.231 1.120000e+12 4.527e+10 + 10 4 5.469e+07 23.880 176.280 2.020 7.466 1.120000e+12 4.690e+10 + 10 5 4.375e+07 23.330 176.510 1.610 7.635 1.120000e+12 4.801e+10 + 10 6 3.646e+07 23.170 176.160 1.680 7.675 1.120000e+12 4.834e+10 + 10 7 3.125e+07 22.950 176.490 1.470 7.754 1.120000e+12 4.880e+10 + 10 8 2.734e+07 22.830 176.260 1.360 7.780 1.120000e+12 4.906e+10 + 10 9 2.431e+07 22.770 175.930 1.410 7.788 1.120000e+12 4.919e+10 + 10 10 2.188e+07 22.680 175.870 1.440 7.818 1.120000e+12 4.938e+10 + 10 11 1.989e+07 22.700 176.140 1.310 7.817 1.120000e+12 4.934e+10 + 10 12 1.823e+07 22.630 176.040 1.430 7.842 1.120000e+12 4.949e+10 + 10 13 1.683e+07 22.640 176.000 1.320 7.832 1.120000e+12 4.947e+10 + 10 14 1.562e+07 22.610 176.160 1.230 7.846 1.120000e+12 4.954e+10 + 10 15 1.458e+07 22.570 176.010 1.290 7.856 1.120000e+12 4.962e+10 + 10 16 1.367e+07 22.640 176.060 1.270 7.833 1.120000e+12 4.947e+10 + 11 1 1.367e+08 22.060 124.440 3.050 5.779 7.700000e+11 3.490e+10 + 11 2 9.943e+07 26.060 178.400 3.000 6.961 1.120000e+12 4.298e+10 + 11 3 6.629e+07 24.380 176.690 2.200 7.338 1.120000e+12 4.594e+10 + 11 4 4.972e+07 23.650 176.730 1.830 7.550 1.120000e+12 4.736e+10 + 11 5 3.977e+07 23.310 176.030 1.780 7.628 1.120000e+12 4.805e+10 + 11 6 3.314e+07 23.050 176.210 1.680 7.718 1.120000e+12 4.859e+10 + 11 7 2.841e+07 22.940 176.300 1.540 7.752 1.120000e+12 4.882e+10 + 11 8 2.486e+07 22.830 175.990 1.530 7.776 1.120000e+12 4.906e+10 + 11 9 2.210e+07 22.760 176.060 1.440 7.799 1.120000e+12 4.921e+10 + 11 10 1.989e+07 22.630 176.010 1.430 7.841 1.120000e+12 4.949e+10 + 11 11 1.808e+07 22.720 176.040 1.390 7.809 1.120000e+12 4.930e+10 + 11 12 1.657e+07 22.640 175.890 1.400 7.831 1.120000e+12 4.947e+10 + 11 13 1.530e+07 22.570 176.090 1.260 7.858 1.120000e+12 4.962e+10 + 11 14 1.420e+07 22.610 176.150 1.450 7.855 1.120000e+12 4.954e+10 + 11 15 1.326e+07 22.550 175.980 1.310 7.862 1.120000e+12 4.967e+10 + 11 16 1.243e+07 22.610 175.920 1.400 7.843 1.120000e+12 4.954e+10 + 12 1 1.367e+08 22.220 136.260 3.390 6.285 8.400000e+11 3.780e+10 + 12 2 9.115e+07 25.610 178.090 2.800 7.063 1.120000e+12 4.373e+10 + 12 3 6.076e+07 24.180 176.320 2.230 7.384 1.120000e+12 4.632e+10 + 12 4 4.557e+07 23.570 176.570 2.010 7.577 1.120000e+12 4.752e+10 + 12 5 3.646e+07 23.210 176.420 1.710 7.675 1.120000e+12 4.826e+10 + 12 6 3.038e+07 23.040 175.910 1.640 7.706 1.120000e+12 4.861e+10 + 12 7 2.604e+07 22.980 176.390 1.510 7.742 1.120000e+12 4.874e+10 + 12 8 2.279e+07 22.840 176.110 1.640 7.782 1.120000e+12 4.904e+10 + 12 9 2.025e+07 22.760 175.950 1.500 7.797 1.120000e+12 4.921e+10 + 12 10 1.823e+07 22.660 175.810 1.600 7.829 1.120000e+12 4.943e+10 + 12 11 1.657e+07 22.710 175.940 1.410 7.809 1.120000e+12 4.932e+10 + 12 12 1.519e+07 22.650 175.870 1.400 7.826 1.120000e+12 4.945e+10 + 12 13 1.402e+07 22.640 176.040 1.260 7.831 1.120000e+12 4.947e+10 + 12 14 1.302e+07 22.650 176.130 1.450 7.840 1.120000e+12 4.945e+10 + 12 15 1.215e+07 22.580 175.990 1.370 7.855 1.120000e+12 4.960e+10 + 12 16 1.139e+07 22.640 175.870 1.440 7.832 1.120000e+12 4.947e+10 + 13 1 1.367e+08 22.640 147.020 3.570 6.652 9.100000e+11 4.019e+10 + 13 2 8.413e+07 25.600 177.820 2.870 7.058 1.120000e+12 4.375e+10 + 13 3 5.609e+07 24.020 176.980 2.270 7.463 1.120000e+12 4.663e+10 + 13 4 4.207e+07 23.440 176.430 2.030 7.613 1.120000e+12 4.778e+10 + 13 5 3.365e+07 23.080 176.110 1.790 7.708 1.120000e+12 4.853e+10 + 13 6 2.804e+07 22.870 176.210 1.600 7.775 1.120000e+12 4.897e+10 + 13 7 2.404e+07 22.940 176.340 1.580 7.756 1.120000e+12 4.882e+10 + 13 8 2.103e+07 22.880 176.050 1.520 7.761 1.120000e+12 4.895e+10 + 13 9 1.870e+07 22.740 176.020 1.400 7.802 1.120000e+12 4.925e+10 + 13 10 1.683e+07 22.710 175.880 1.440 7.808 1.120000e+12 4.932e+10 + 13 11 1.530e+07 22.590 176.040 1.350 7.853 1.120000e+12 4.958e+10 + 13 12 1.402e+07 22.600 175.930 1.380 7.846 1.120000e+12 4.956e+10 + 13 13 1.294e+07 22.710 176.010 1.340 7.809 1.120000e+12 4.932e+10 + 13 14 1.202e+07 22.690 176.270 1.350 7.828 1.120000e+12 4.936e+10 + 13 15 1.122e+07 22.590 175.960 1.290 7.846 1.120000e+12 4.958e+10 + 13 16 1.052e+07 22.610 175.960 1.370 7.843 1.120000e+12 4.954e+10 + 14 1 1.367e+08 23.120 157.180 3.810 6.963 9.800000e+11 4.239e+10 + 14 2 7.812e+07 25.310 177.210 3.020 7.121 1.120000e+12 4.425e+10 + 14 3 5.208e+07 24.130 177.110 2.340 7.437 1.120000e+12 4.642e+10 + 14 4 3.906e+07 23.390 176.660 1.800 7.630 1.120000e+12 4.788e+10 + 14 5 3.125e+07 23.060 176.420 1.750 7.726 1.120000e+12 4.857e+10 + 14 6 2.604e+07 22.890 176.180 1.530 7.764 1.120000e+12 4.893e+10 + 14 7 2.232e+07 22.940 176.060 1.550 7.742 1.120000e+12 4.882e+10 + 14 8 1.953e+07 22.810 176.110 1.500 7.786 1.120000e+12 4.910e+10 + 14 9 1.736e+07 22.750 176.370 1.370 7.813 1.120000e+12 4.923e+10 + 14 10 1.562e+07 22.720 176.020 1.450 7.811 1.120000e+12 4.930e+10 + 14 11 1.420e+07 22.680 176.090 1.310 7.822 1.120000e+12 4.938e+10 + 14 12 1.302e+07 22.710 175.950 1.510 7.814 1.120000e+12 4.932e+10 + 14 13 1.202e+07 22.700 176.100 1.500 7.824 1.120000e+12 4.934e+10 + 14 14 1.116e+07 22.660 176.150 1.460 7.838 1.120000e+12 4.943e+10 + 14 15 1.042e+07 22.680 176.120 1.370 7.826 1.120000e+12 4.938e+10 + 14 16 9.766e+06 22.710 176.110 1.430 7.818 1.120000e+12 4.932e+10 + 15 1 1.367e+08 23.710 168.080 4.140 7.264 1.050000e+12 4.429e+10 + 15 2 7.292e+07 25.170 176.640 2.930 7.134 1.120000e+12 4.450e+10 + 15 3 4.861e+07 23.820 176.980 2.110 7.518 1.120000e+12 4.702e+10 + 15 4 3.646e+07 23.250 176.190 1.970 7.663 1.120000e+12 4.817e+10 + 15 5 2.917e+07 23.050 176.450 1.690 7.728 1.120000e+12 4.859e+10 + 15 6 2.431e+07 22.900 175.980 1.680 7.758 1.120000e+12 4.891e+10 + 15 7 2.083e+07 22.830 176.090 1.640 7.785 1.120000e+12 4.906e+10 + 15 8 1.823e+07 22.850 176.160 1.530 7.776 1.120000e+12 4.902e+10 + 15 9 1.620e+07 22.780 176.390 1.360 7.803 1.120000e+12 4.917e+10 + 15 10 1.458e+07 22.660 176.000 1.440 7.831 1.120000e+12 4.943e+10 + 15 11 1.326e+07 22.660 176.110 1.430 7.835 1.120000e+12 4.943e+10 + 15 12 1.215e+07 22.660 176.150 1.380 7.835 1.120000e+12 4.943e+10 + 15 13 1.122e+07 22.760 175.970 1.580 7.801 1.120000e+12 4.921e+10 + 15 14 1.042e+07 22.670 176.290 1.270 7.832 1.120000e+12 4.940e+10 + 15 15 9.722e+06 22.710 176.060 1.550 7.821 1.120000e+12 4.932e+10 + 15 16 9.115e+06 22.800 176.020 1.490 7.786 1.120000e+12 4.912e+10 + 16 1 1.367e+08 25.470 179.270 4.730 7.224 1.120000e+12 4.397e+10 + 16 2 6.836e+07 24.870 176.820 2.960 7.229 1.120000e+12 4.503e+10 + 16 3 4.557e+07 23.810 176.930 2.250 7.525 1.120000e+12 4.704e+10 + 16 4 3.418e+07 23.240 176.650 1.950 7.685 1.120000e+12 4.819e+10 + 16 5 2.734e+07 23.090 175.940 1.940 7.704 1.120000e+12 4.851e+10 + 16 6 2.279e+07 22.900 176.120 1.680 7.764 1.120000e+12 4.891e+10 + 16 7 1.953e+07 22.890 176.290 1.440 7.765 1.120000e+12 4.893e+10 + 16 8 1.709e+07 22.820 176.040 1.610 7.785 1.120000e+12 4.908e+10 + 16 9 1.519e+07 22.890 175.990 1.470 7.753 1.120000e+12 4.893e+10 + 16 10 1.367e+07 22.700 175.890 1.470 7.813 1.120000e+12 4.934e+10 + 16 11 1.243e+07 22.770 175.960 1.520 7.794 1.120000e+12 4.919e+10 + 16 12 1.139e+07 22.730 176.000 1.430 7.806 1.120000e+12 4.927e+10 + 16 13 1.052e+07 22.670 175.990 1.540 7.831 1.120000e+12 4.940e+10 + 16 14 9.766e+06 22.720 176.130 1.440 7.816 1.120000e+12 4.930e+10 + 16 15 9.115e+06 22.740 176.320 1.360 7.814 1.120000e+12 4.925e+10 + 16 16 8.545e+06 22.680 176.170 1.320 7.826 1.120000e+12 4.938e+10 diff --git a/gnuradio-core/src/examples/mp-sched/perf-data/dual-quad-core-3.00-penryn.dat b/gnuradio-core/src/examples/mp-sched/perf-data/dual-quad-core-3.00-penryn.dat new file mode 100644 index 000000000..57d49ed33 --- /dev/null +++ b/gnuradio-core/src/examples/mp-sched/perf-data/dual-quad-core-3.00-penryn.dat @@ -0,0 +1,257 @@ +#D Dual quad-core Xeon 3.0 GHz (Penryn E5472, 1600 MHz FSB, 5400 chipset) + 1 1 5.000e+07 2.720 3.020 0.110 1.151 2.560000e+10 9.412e+09 + 1 2 5.000e+07 2.870 5.630 0.170 2.021 5.120000e+10 1.784e+10 + 1 3 5.000e+07 2.880 8.380 0.160 2.965 7.680000e+10 2.667e+10 + 1 4 5.000e+07 2.990 11.080 0.200 3.773 1.024000e+11 3.425e+10 + 1 5 5.000e+07 2.950 13.950 0.190 4.793 1.280000e+11 4.339e+10 + 1 6 5.000e+07 3.020 16.620 0.240 5.583 1.536000e+11 5.086e+10 + 1 7 5.000e+07 2.930 19.250 0.200 6.638 1.792000e+11 6.116e+10 + 1 8 5.000e+07 3.170 22.240 0.290 7.107 2.048000e+11 6.461e+10 + 1 9 5.000e+07 5.450 24.410 0.310 4.536 2.304000e+11 4.228e+10 + 1 10 5.000e+07 5.610 27.400 0.370 4.950 2.560000e+11 4.563e+10 + 1 11 5.000e+07 5.680 29.960 0.370 5.340 2.816000e+11 4.958e+10 + 1 12 5.000e+07 5.440 32.490 0.350 6.037 3.072000e+11 5.647e+10 + 1 13 5.000e+07 5.630 35.270 0.400 6.336 3.328000e+11 5.911e+10 + 1 14 5.000e+07 6.270 38.500 0.480 6.217 3.584000e+11 5.716e+10 + 1 15 5.000e+07 6.080 40.880 0.490 6.804 3.840000e+11 6.316e+10 + 1 16 5.000e+07 7.740 43.390 0.600 5.683 4.096000e+11 5.292e+10 + 2 1 5.000e+07 2.820 5.700 0.210 2.096 5.120000e+10 1.816e+10 + 2 2 5.000e+07 2.820 11.130 0.230 4.028 1.024000e+11 3.631e+10 + 2 3 5.000e+07 2.960 16.570 0.320 5.706 1.536000e+11 5.189e+10 + 2 4 5.000e+07 3.110 21.920 0.390 7.174 2.048000e+11 6.585e+10 + 2 5 5.000e+07 5.650 27.550 0.520 4.968 2.560000e+11 4.531e+10 + 2 6 5.000e+07 5.880 32.890 0.440 5.668 3.072000e+11 5.224e+10 + 2 7 5.000e+07 6.750 38.210 0.560 5.744 3.584000e+11 5.310e+10 + 2 8 5.000e+07 6.360 43.480 0.580 6.928 4.096000e+11 6.440e+10 + 2 9 5.000e+07 8.270 48.750 0.730 5.983 4.608000e+11 5.572e+10 + 2 10 5.000e+07 8.210 54.400 0.610 6.700 5.120000e+11 6.236e+10 + 2 11 5.000e+07 8.750 59.760 0.640 6.903 5.632000e+11 6.437e+10 + 2 12 5.000e+07 9.300 65.050 0.700 7.070 6.144000e+11 6.606e+10 + 2 13 5.000e+07 9.990 70.750 0.750 7.157 6.656000e+11 6.663e+10 + 2 14 5.000e+07 10.610 75.950 0.810 7.235 7.168000e+11 6.756e+10 + 2 15 5.000e+07 11.900 80.400 0.870 6.829 7.680000e+11 6.454e+10 + 2 16 5.000e+07 11.820 86.790 0.900 7.419 8.192000e+11 6.931e+10 + 3 1 5.000e+07 2.970 8.300 0.380 2.923 7.680000e+10 2.586e+10 + 3 2 5.000e+07 2.980 16.660 0.390 5.721 1.536000e+11 5.154e+10 + 3 3 5.000e+07 5.480 24.690 0.420 4.582 2.304000e+11 4.204e+10 + 3 4 5.000e+07 5.620 32.820 0.560 5.940 3.072000e+11 5.466e+10 + 3 5 5.000e+07 6.940 40.800 0.620 5.968 3.840000e+11 5.533e+10 + 3 6 5.000e+07 7.860 49.010 0.710 6.326 4.608000e+11 5.863e+10 + 3 7 5.000e+07 8.470 57.130 0.750 6.834 5.376000e+11 6.347e+10 + 3 8 5.000e+07 9.420 65.310 0.820 7.020 6.144000e+11 6.522e+10 + 3 9 5.000e+07 10.350 73.640 0.940 7.206 6.912000e+11 6.678e+10 + 3 10 5.000e+07 11.460 82.230 1.030 7.265 7.680000e+11 6.702e+10 + 3 11 5.000e+07 12.200 89.590 1.050 7.430 8.448000e+11 6.925e+10 + 3 12 5.000e+07 13.040 97.520 1.140 7.566 9.216000e+11 7.067e+10 + 3 13 5.000e+07 14.000 105.560 1.150 7.622 9.984000e+11 7.131e+10 + 3 14 5.000e+07 14.930 113.630 1.210 7.692 1.075200e+12 7.202e+10 + 3 15 5.000e+07 15.920 121.610 1.350 7.724 1.152000e+12 7.236e+10 + 3 16 5.000e+07 16.870 129.770 1.390 7.775 1.228800e+12 7.284e+10 + 4 1 5.000e+07 2.900 11.100 0.340 3.945 1.024000e+11 3.531e+10 + 4 2 5.000e+07 4.380 21.980 0.480 5.128 2.048000e+11 4.676e+10 + 4 3 5.000e+07 5.720 32.800 0.610 5.841 3.072000e+11 5.371e+10 + 4 4 5.000e+07 6.820 43.880 0.700 6.537 4.096000e+11 6.006e+10 + 4 5 5.000e+07 8.150 54.420 0.760 6.771 5.120000e+11 6.282e+10 + 4 6 5.000e+07 9.510 65.180 0.980 6.957 6.144000e+11 6.461e+10 + 4 7 5.000e+07 10.650 76.080 1.020 7.239 7.168000e+11 6.731e+10 + 4 8 5.000e+07 11.880 86.720 1.110 7.393 8.192000e+11 6.896e+10 + 4 9 5.000e+07 13.150 97.920 1.250 7.541 9.216000e+11 7.008e+10 + 4 10 5.000e+07 14.640 109.260 1.410 7.559 1.024000e+12 6.995e+10 + 4 11 5.000e+07 15.710 119.170 1.440 7.677 1.126400e+12 7.170e+10 + 4 12 5.000e+07 16.950 129.960 1.420 7.751 1.228800e+12 7.250e+10 + 4 13 5.000e+07 18.260 140.520 1.620 7.784 1.331200e+12 7.290e+10 + 4 14 5.000e+07 19.610 151.290 1.780 7.806 1.433600e+12 7.311e+10 + 4 15 5.000e+07 21.060 162.760 1.890 7.818 1.536000e+12 7.293e+10 + 4 16 5.000e+07 22.280 172.870 1.980 7.848 1.638400e+12 7.354e+10 + 5 1 5.000e+07 3.040 13.810 0.390 4.671 1.280000e+11 4.211e+10 + 5 2 5.000e+07 5.590 27.510 0.610 5.030 2.560000e+11 4.580e+10 + 5 3 5.000e+07 6.550 40.970 0.780 6.374 3.840000e+11 5.863e+10 + 5 4 5.000e+07 8.520 54.470 0.940 6.504 5.120000e+11 6.009e+10 + 5 5 5.000e+07 9.920 67.950 1.060 6.957 6.400000e+11 6.452e+10 + 5 6 5.000e+07 11.350 81.490 1.180 7.284 7.680000e+11 6.767e+10 + 5 7 5.000e+07 12.910 94.960 1.300 7.456 8.960000e+11 6.940e+10 + 5 8 5.000e+07 14.520 108.510 1.400 7.570 1.024000e+12 7.052e+10 + 5 9 5.000e+07 16.070 122.120 1.620 7.700 1.152000e+12 7.169e+10 + 5 10 5.000e+07 17.950 136.140 1.730 7.681 1.280000e+12 7.131e+10 + 5 11 5.000e+07 19.470 148.330 1.830 7.712 1.408000e+12 7.232e+10 + 5 12 5.000e+07 20.980 162.100 2.030 7.823 1.536000e+12 7.321e+10 + 5 13 5.000e+07 22.670 175.470 2.160 7.835 1.664000e+12 7.340e+10 + 5 14 5.000e+07 24.440 189.630 2.170 7.848 1.792000e+12 7.332e+10 + 5 15 5.000e+07 26.100 203.010 2.450 7.872 1.920000e+12 7.356e+10 + 5 16 5.000e+07 27.720 216.000 2.550 7.884 2.048000e+12 7.388e+10 + 6 1 5.000e+07 2.950 16.560 0.540 5.797 1.536000e+11 5.207e+10 + 6 2 5.000e+07 5.540 32.900 0.720 6.069 3.072000e+11 5.545e+10 + 6 3 5.000e+07 8.490 48.860 1.000 5.873 4.608000e+11 5.428e+10 + 6 4 5.000e+07 10.000 64.670 1.100 6.577 6.144000e+11 6.144e+10 + 6 5 5.000e+07 11.440 81.430 1.310 7.233 7.680000e+11 6.713e+10 + 6 6 5.000e+07 13.250 97.690 1.360 7.475 9.216000e+11 6.955e+10 + 6 7 5.000e+07 15.270 113.730 1.610 7.553 1.075200e+12 7.041e+10 + 6 8 5.000e+07 17.180 129.780 1.820 7.660 1.228800e+12 7.153e+10 + 6 9 5.000e+07 19.200 146.020 1.870 7.703 1.382400e+12 7.200e+10 + 6 10 5.000e+07 21.220 162.290 2.100 7.747 1.536000e+12 7.238e+10 + 6 11 5.000e+07 23.070 178.420 2.160 7.827 1.689600e+12 7.324e+10 + 6 12 5.000e+07 25.120 194.590 2.450 7.844 1.843200e+12 7.338e+10 + 6 13 5.000e+07 27.110 210.640 2.660 7.868 1.996800e+12 7.366e+10 + 6 14 5.000e+07 29.110 226.820 2.750 7.886 2.150400e+12 7.387e+10 + 6 15 5.000e+07 31.130 242.800 2.940 7.894 2.304000e+12 7.401e+10 + 6 16 5.000e+07 33.100 258.790 3.210 7.915 2.457600e+12 7.425e+10 + 7 1 5.000e+07 2.940 19.140 0.590 6.711 1.792000e+11 6.095e+10 + 7 2 5.000e+07 5.920 37.910 1.030 6.578 3.584000e+11 6.054e+10 + 7 3 5.000e+07 8.570 57.010 1.150 6.786 5.376000e+11 6.273e+10 + 7 4 5.000e+07 10.840 76.060 1.320 7.138 7.168000e+11 6.613e+10 + 7 5 5.000e+07 13.070 94.920 1.540 7.380 8.960000e+11 6.855e+10 + 7 6 5.000e+07 15.270 113.790 1.730 7.565 1.075200e+12 7.041e+10 + 7 7 5.000e+07 17.700 132.560 1.960 7.600 1.254400e+12 7.087e+10 + 7 8 5.000e+07 19.930 151.500 2.130 7.708 1.433600e+12 7.193e+10 + 7 9 5.000e+07 22.250 170.570 2.340 7.771 1.612800e+12 7.249e+10 + 7 10 5.000e+07 24.600 189.280 2.450 7.794 1.792000e+12 7.285e+10 + 7 11 5.000e+07 26.950 208.030 2.700 7.819 1.971200e+12 7.314e+10 + 7 12 5.000e+07 29.280 227.070 2.850 7.852 2.150400e+12 7.344e+10 + 7 13 5.000e+07 31.570 245.750 3.040 7.881 2.329600e+12 7.379e+10 + 7 14 5.000e+07 33.930 264.960 3.160 7.902 2.508800e+12 7.394e+10 + 7 15 5.000e+07 36.310 283.960 3.440 7.915 2.688000e+12 7.403e+10 + 7 16 5.000e+07 38.560 302.120 3.630 7.929 2.867200e+12 7.436e+10 + 8 1 5.000e+07 3.200 21.880 0.860 7.106 2.048000e+11 6.400e+10 + 8 2 5.000e+07 5.890 43.450 0.930 7.535 4.096000e+11 6.954e+10 + 8 3 5.000e+07 9.520 65.180 1.250 6.978 6.144000e+11 6.454e+10 + 8 4 5.000e+07 12.200 86.780 1.480 7.234 8.192000e+11 6.715e+10 + 8 5 5.000e+07 14.760 108.420 1.670 7.459 1.024000e+12 6.938e+10 + 8 6 5.000e+07 17.300 129.850 1.960 7.619 1.228800e+12 7.103e+10 + 8 7 5.000e+07 20.020 151.430 2.190 7.673 1.433600e+12 7.161e+10 + 8 8 5.000e+07 22.750 173.550 2.420 7.735 1.638400e+12 7.202e+10 + 8 9 5.000e+07 25.410 194.560 2.760 7.765 1.843200e+12 7.254e+10 + 8 10 5.000e+07 28.410 217.250 2.920 7.750 2.048000e+12 7.209e+10 + 8 11 5.000e+07 30.720 237.990 3.210 7.852 2.252800e+12 7.333e+10 + 8 12 5.000e+07 33.310 259.340 3.280 7.884 2.457600e+12 7.378e+10 + 8 13 5.000e+07 36.000 280.760 3.670 7.901 2.662400e+12 7.396e+10 + 8 14 5.000e+07 38.800 302.570 3.740 7.895 2.867200e+12 7.390e+10 + 8 15 5.000e+07 41.530 324.520 4.060 7.912 3.072000e+12 7.397e+10 + 8 16 5.000e+07 44.060 345.420 4.250 7.936 3.276800e+12 7.437e+10 + 9 1 5.000e+07 5.460 24.660 1.000 4.700 2.304000e+11 4.220e+10 + 9 2 5.000e+07 8.460 49.010 1.200 5.935 4.608000e+11 5.447e+10 + 9 3 5.000e+07 10.810 71.410 1.400 6.735 6.912000e+11 6.394e+10 + 9 4 5.000e+07 13.470 97.570 1.710 7.370 9.216000e+11 6.842e+10 + 9 5 5.000e+07 16.490 121.780 2.130 7.514 1.152000e+12 6.986e+10 + 9 6 5.000e+07 19.540 146.070 2.280 7.592 1.382400e+12 7.075e+10 + 9 7 5.000e+07 22.660 170.830 2.570 7.652 1.612800e+12 7.117e+10 + 9 8 5.000e+07 25.520 194.720 2.760 7.738 1.843200e+12 7.223e+10 + 9 9 5.000e+07 28.400 219.020 3.060 7.820 2.073600e+12 7.301e+10 + 9 10 5.000e+07 31.490 243.030 3.320 7.823 2.304000e+12 7.317e+10 + 9 11 5.000e+07 34.530 267.230 3.420 7.838 2.534400e+12 7.340e+10 + 9 12 5.000e+07 37.520 291.720 3.860 7.878 2.764800e+12 7.369e+10 + 9 13 5.000e+07 40.550 315.780 4.170 7.890 2.995200e+12 7.386e+10 + 9 14 5.000e+07 43.470 339.930 4.290 7.919 3.225600e+12 7.420e+10 + 9 15 5.000e+07 46.820 364.970 4.640 7.894 3.456000e+12 7.381e+10 + 9 16 5.000e+07 49.660 388.630 4.890 7.924 3.686400e+12 7.423e+10 + 10 1 5.000e+07 5.500 27.290 0.980 5.140 2.560000e+11 4.655e+10 + 10 2 5.000e+07 8.480 54.830 1.420 6.633 5.120000e+11 6.038e+10 + 10 3 5.000e+07 11.540 81.580 1.630 7.211 7.680000e+11 6.655e+10 + 10 4 5.000e+07 14.950 108.480 1.860 7.381 1.024000e+12 6.849e+10 + 10 5 5.000e+07 18.330 135.300 2.280 7.506 1.280000e+12 6.983e+10 + 10 6 5.000e+07 21.680 162.380 2.540 7.607 1.536000e+12 7.085e+10 + 10 7 5.000e+07 24.950 189.360 2.730 7.699 1.792000e+12 7.182e+10 + 10 8 5.000e+07 28.280 216.090 3.110 7.751 2.048000e+12 7.242e+10 + 10 9 5.000e+07 31.730 243.290 3.450 7.776 2.304000e+12 7.261e+10 + 10 10 5.000e+07 35.040 270.380 3.680 7.821 2.560000e+12 7.306e+10 + 10 11 5.000e+07 38.340 297.080 4.050 7.854 2.816000e+12 7.345e+10 + 10 12 5.000e+07 41.770 323.840 4.330 7.857 3.072000e+12 7.355e+10 + 10 13 5.000e+07 45.120 351.380 4.710 7.892 3.328000e+12 7.376e+10 + 10 14 5.000e+07 48.360 377.870 4.880 7.915 3.584000e+12 7.411e+10 + 10 15 5.000e+07 51.760 404.740 5.110 7.918 3.840000e+12 7.419e+10 + 10 16 5.000e+07 55.130 431.760 5.430 7.930 4.096000e+12 7.430e+10 + 11 1 5.000e+07 5.570 30.080 1.080 5.594 2.816000e+11 5.056e+10 + 11 2 5.000e+07 9.000 60.230 1.470 6.856 5.632000e+11 6.258e+10 + 11 3 5.000e+07 12.630 89.890 1.770 7.257 8.448000e+11 6.689e+10 + 11 4 5.000e+07 16.290 119.110 2.140 7.443 1.126400e+12 6.915e+10 + 11 5 5.000e+07 19.940 148.730 2.440 7.581 1.408000e+12 7.061e+10 + 11 6 5.000e+07 23.800 178.620 2.790 7.622 1.689600e+12 7.099e+10 + 11 7 5.000e+07 27.480 208.510 3.160 7.703 1.971200e+12 7.173e+10 + 11 8 5.000e+07 31.140 237.820 3.490 7.749 2.252800e+12 7.234e+10 + 11 9 5.000e+07 34.770 267.390 3.800 7.800 2.534400e+12 7.289e+10 + 11 10 5.000e+07 38.510 297.250 4.240 7.829 2.816000e+12 7.312e+10 + 11 11 5.000e+07 42.080 326.570 4.610 7.870 3.097600e+12 7.361e+10 + 11 12 5.000e+07 45.860 356.540 4.590 7.875 3.379200e+12 7.369e+10 + 11 13 5.000e+07 49.570 386.250 5.150 7.896 3.660800e+12 7.385e+10 + 11 14 5.000e+07 53.220 415.630 5.360 7.910 3.942400e+12 7.408e+10 + 11 15 5.000e+07 57.000 445.200 5.870 7.914 4.224000e+12 7.411e+10 + 11 16 5.000e+07 60.800 474.810 6.250 7.912 4.505600e+12 7.411e+10 + 12 1 5.000e+07 5.600 32.770 1.240 6.073 3.072000e+11 5.486e+10 + 12 2 5.000e+07 10.220 65.660 1.600 6.581 6.144000e+11 6.012e+10 + 12 3 5.000e+07 13.680 97.900 2.000 7.303 9.216000e+11 6.737e+10 + 12 4 5.000e+07 17.790 129.710 2.330 7.422 1.228800e+12 6.907e+10 + 12 5 5.000e+07 21.770 162.420 2.700 7.585 1.536000e+12 7.056e+10 + 12 6 5.000e+07 25.770 194.770 3.090 7.678 1.843200e+12 7.153e+10 + 12 7 5.000e+07 29.940 227.290 3.390 7.705 2.150400e+12 7.182e+10 + 12 8 5.000e+07 34.030 259.370 3.860 7.735 2.457600e+12 7.222e+10 + 12 9 5.000e+07 38.070 291.890 4.310 7.780 2.764800e+12 7.262e+10 + 12 10 5.000e+07 42.080 324.370 4.660 7.819 3.072000e+12 7.300e+10 + 12 11 5.000e+07 45.950 356.370 5.000 7.864 3.379200e+12 7.354e+10 + 12 12 5.000e+07 49.960 388.790 5.250 7.887 3.686400e+12 7.379e+10 + 12 13 5.000e+07 54.010 422.050 5.420 7.915 3.993600e+12 7.394e+10 + 12 14 5.000e+07 58.010 453.330 6.120 7.920 4.300800e+12 7.414e+10 + 12 15 5.000e+07 62.080 485.830 6.310 7.928 4.608000e+12 7.423e+10 + 12 16 5.000e+07 66.200 518.060 6.780 7.928 4.915200e+12 7.425e+10 + 13 1 5.000e+07 5.630 35.420 1.300 6.522 3.328000e+11 5.911e+10 + 13 2 5.000e+07 10.730 71.050 1.830 6.792 6.656000e+11 6.203e+10 + 13 3 5.000e+07 14.690 105.710 2.160 7.343 9.984000e+11 6.796e+10 + 13 4 5.000e+07 19.120 140.630 2.510 7.486 1.331200e+12 6.962e+10 + 13 5 5.000e+07 23.600 175.730 3.000 7.573 1.664000e+12 7.051e+10 + 13 6 5.000e+07 27.910 211.000 3.350 7.680 1.996800e+12 7.154e+10 + 13 7 5.000e+07 32.370 246.320 3.860 7.729 2.329600e+12 7.197e+10 + 13 8 5.000e+07 36.790 281.150 4.260 7.758 2.662400e+12 7.237e+10 + 13 9 5.000e+07 41.080 316.080 4.520 7.804 2.995200e+12 7.291e+10 + 13 10 5.000e+07 45.600 352.020 5.090 7.831 3.328000e+12 7.298e+10 + 13 11 5.000e+07 49.760 386.130 5.470 7.870 3.660800e+12 7.357e+10 + 13 12 5.000e+07 54.080 421.160 5.780 7.895 3.993600e+12 7.385e+10 + 13 13 5.000e+07 58.520 455.980 6.170 7.897 4.326400e+12 7.393e+10 + 13 14 5.000e+07 63.000 491.340 6.710 7.906 4.659200e+12 7.396e+10 + 13 15 5.000e+07 67.250 525.920 6.920 7.923 4.992000e+12 7.423e+10 + 13 16 5.000e+07 72.090 560.640 7.160 7.876 5.324800e+12 7.386e+10 + 14 1 5.000e+07 5.670 38.290 1.330 6.988 3.584000e+11 6.321e+10 + 14 2 5.000e+07 10.850 75.880 1.940 7.172 7.168000e+11 6.606e+10 + 14 3 5.000e+07 15.840 114.160 2.400 7.359 1.075200e+12 6.788e+10 + 14 4 5.000e+07 20.610 151.540 2.710 7.484 1.433600e+12 6.956e+10 + 14 5 5.000e+07 25.330 189.160 3.320 7.599 1.792000e+12 7.075e+10 + 14 6 5.000e+07 30.160 227.510 3.670 7.665 2.150400e+12 7.130e+10 + 14 7 5.000e+07 34.730 265.020 3.960 7.745 2.508800e+12 7.224e+10 + 14 8 5.000e+07 39.530 302.550 4.640 7.771 2.867200e+12 7.253e+10 + 14 9 5.000e+07 44.220 340.330 5.180 7.813 3.225600e+12 7.294e+10 + 14 10 5.000e+07 48.800 378.180 5.430 7.861 3.584000e+12 7.344e+10 + 14 11 5.000e+07 53.550 415.790 5.800 7.873 3.942400e+12 7.362e+10 + 14 12 5.000e+07 58.250 453.340 6.430 7.893 4.300800e+12 7.383e+10 + 14 13 5.000e+07 63.150 492.200 6.960 7.904 4.659200e+12 7.378e+10 + 14 14 5.000e+07 67.850 528.470 6.970 7.892 5.017600e+12 7.395e+10 + 14 15 5.000e+07 72.510 566.950 7.720 7.925 5.376000e+12 7.414e+10 + 14 16 5.000e+07 77.230 604.250 8.170 7.930 5.734400e+12 7.425e+10 + 15 1 5.000e+07 5.800 41.070 1.460 7.333 3.840000e+11 6.621e+10 + 15 2 5.000e+07 11.900 80.380 2.190 6.939 7.680000e+11 6.454e+10 + 15 3 5.000e+07 16.990 121.790 2.610 7.322 1.152000e+12 6.780e+10 + 15 4 5.000e+07 22.040 162.330 3.030 7.503 1.536000e+12 6.969e+10 + 15 5 5.000e+07 27.120 202.750 3.460 7.604 1.920000e+12 7.080e+10 + 15 6 5.000e+07 32.290 243.420 3.870 7.658 2.304000e+12 7.135e+10 + 15 7 5.000e+07 37.450 284.300 4.410 7.709 2.688000e+12 7.178e+10 + 15 8 5.000e+07 42.560 323.740 4.890 7.722 3.072000e+12 7.218e+10 + 15 9 5.000e+07 47.440 364.880 5.330 7.804 3.456000e+12 7.285e+10 + 15 10 5.000e+07 52.440 405.400 5.750 7.840 3.840000e+12 7.323e+10 + 15 11 5.000e+07 57.270 445.500 6.070 7.885 4.224000e+12 7.376e+10 + 15 12 5.000e+07 62.450 485.920 6.770 7.889 4.608000e+12 7.379e+10 + 15 13 5.000e+07 67.680 527.540 7.440 7.905 4.992000e+12 7.376e+10 + 15 14 5.000e+07 72.740 566.990 7.790 7.902 5.376000e+12 7.391e+10 + 15 15 5.000e+07 77.760 607.620 8.060 7.918 5.760000e+12 7.407e+10 + 15 16 5.000e+07 82.750 647.630 8.640 7.931 6.144000e+12 7.425e+10 + 16 1 5.000e+07 6.310 43.540 1.790 7.184 4.096000e+11 6.491e+10 + 16 2 5.000e+07 12.340 87.310 2.190 7.253 8.192000e+11 6.639e+10 + 16 3 5.000e+07 17.930 130.440 2.830 7.433 1.228800e+12 6.853e+10 + 16 4 5.000e+07 23.530 173.540 3.140 7.509 1.638400e+12 6.963e+10 + 16 5 5.000e+07 28.910 216.290 3.710 7.610 2.048000e+12 7.084e+10 + 16 6 5.000e+07 34.310 259.400 4.260 7.685 2.457600e+12 7.163e+10 + 16 7 5.000e+07 39.790 302.740 4.620 7.725 2.867200e+12 7.206e+10 + 16 8 5.000e+07 44.970 346.250 5.340 7.818 3.276800e+12 7.287e+10 + 16 9 5.000e+07 50.470 388.870 5.910 7.822 3.686400e+12 7.304e+10 + 16 10 5.000e+07 55.890 432.480 6.140 7.848 4.096000e+12 7.329e+10 + 16 11 5.000e+07 61.250 475.380 6.770 7.872 4.505600e+12 7.356e+10 + 16 12 5.000e+07 66.670 518.940 7.160 7.891 4.915200e+12 7.372e+10 + 16 13 5.000e+07 72.160 562.230 7.890 7.901 5.324800e+12 7.379e+10 + 16 14 5.000e+07 77.600 604.950 8.230 7.902 5.734400e+12 7.390e+10 + 16 15 5.000e+07 82.970 648.420 8.690 7.920 6.144000e+12 7.405e+10 + 16 16 5.000e+07 88.370 690.730 9.460 7.923 6.553600e+12 7.416e+10 diff --git a/gnuradio-core/src/examples/mp-sched/perf-data/js21-altivec.dat b/gnuradio-core/src/examples/mp-sched/perf-data/js21-altivec.dat new file mode 100644 index 000000000..d0b8148f0 --- /dev/null +++ b/gnuradio-core/src/examples/mp-sched/perf-data/js21-altivec.dat @@ -0,0 +1,65 @@ +#D JS21 4-core PPC970M 2.5 GHz (using Altivec) + 1 1 9.766e+07 9.820 10.210 0.360 1.076 5.000000e+10 5.092e+09 + 1 2 9.766e+07 10.620 19.890 0.640 1.933 1.000000e+11 9.416e+09 + 1 3 9.766e+07 10.310 29.590 0.610 2.929 1.500000e+11 1.455e+10 + 1 4 9.766e+07 10.440 39.290 0.680 3.829 2.000000e+11 1.916e+10 + 1 5 7.812e+07 15.730 39.150 0.590 2.526 2.000000e+11 1.271e+10 + 1 6 6.510e+07 13.100 39.080 0.590 3.028 2.000000e+11 1.527e+10 + 1 7 5.580e+07 11.550 39.030 0.500 3.423 2.000000e+11 1.732e+10 + 1 8 4.883e+07 10.410 39.010 0.510 3.796 2.000000e+11 1.921e+10 + 2 1 9.766e+07 10.080 20.070 0.700 2.061 1.000000e+11 9.921e+09 + 2 2 9.766e+07 11.360 39.650 0.960 3.575 2.000000e+11 1.761e+10 + 2 3 6.510e+07 13.120 39.270 0.740 3.050 2.000000e+11 1.524e+10 + 2 4 4.883e+07 10.410 39.110 0.650 3.819 2.000000e+11 1.921e+10 + 2 5 3.906e+07 11.030 39.080 0.610 3.598 2.000000e+11 1.813e+10 + 2 6 3.255e+07 10.640 39.020 0.560 3.720 2.000000e+11 1.880e+10 + 2 7 2.790e+07 10.510 38.980 0.550 3.761 2.000000e+11 1.903e+10 + 2 8 2.441e+07 10.440 38.970 0.570 3.787 2.000000e+11 1.916e+10 + 3 1 9.766e+07 12.130 29.970 0.920 2.547 1.500000e+11 1.237e+10 + 3 2 6.510e+07 13.100 39.300 0.920 3.070 2.000000e+11 1.527e+10 + 3 3 4.340e+07 11.400 39.200 0.760 3.505 2.000000e+11 1.754e+10 + 3 4 3.255e+07 10.730 39.100 0.690 3.708 2.000000e+11 1.864e+10 + 3 5 2.604e+07 10.470 39.010 0.620 3.785 2.000000e+11 1.910e+10 + 3 6 2.170e+07 10.380 39.010 0.620 3.818 2.000000e+11 1.927e+10 + 3 7 1.860e+07 10.280 39.120 0.580 3.862 2.000000e+11 1.946e+10 + 3 8 1.628e+07 10.230 39.000 0.600 3.871 2.000000e+11 1.955e+10 + 4 1 9.766e+07 10.700 39.990 1.540 3.881 2.000000e+11 1.869e+10 + 4 2 4.883e+07 10.530 39.260 0.940 3.818 2.000000e+11 1.899e+10 + 4 3 3.255e+07 10.840 39.140 0.760 3.681 2.000000e+11 1.845e+10 + 4 4 2.441e+07 10.530 39.040 0.680 3.772 2.000000e+11 1.899e+10 + 4 5 1.953e+07 10.380 39.030 0.650 3.823 2.000000e+11 1.927e+10 + 4 6 1.628e+07 10.310 39.020 0.650 3.848 2.000000e+11 1.940e+10 + 4 7 1.395e+07 10.160 38.980 0.620 3.898 2.000000e+11 1.969e+10 + 4 8 1.221e+07 10.150 38.990 0.580 3.899 2.000000e+11 1.970e+10 + 5 1 7.812e+07 14.750 39.780 1.470 2.797 2.000000e+11 1.356e+10 + 5 2 3.906e+07 11.350 39.240 0.950 3.541 2.000000e+11 1.762e+10 + 5 3 2.604e+07 10.720 39.120 0.800 3.724 2.000000e+11 1.866e+10 + 5 4 1.953e+07 10.440 39.060 0.730 3.811 2.000000e+11 1.916e+10 + 5 5 1.562e+07 10.410 39.060 0.690 3.818 2.000000e+11 1.921e+10 + 5 6 1.302e+07 10.260 38.970 0.650 3.862 2.000000e+11 1.949e+10 + 5 7 1.116e+07 10.270 39.020 0.650 3.863 2.000000e+11 1.947e+10 + 5 8 9.766e+06 10.130 39.010 0.660 3.916 2.000000e+11 1.974e+10 + 6 1 6.510e+07 12.850 39.730 1.450 3.205 2.000000e+11 1.556e+10 + 6 2 3.255e+07 10.700 39.300 0.990 3.765 2.000000e+11 1.869e+10 + 6 3 2.170e+07 10.770 39.110 0.810 3.707 2.000000e+11 1.857e+10 + 6 4 1.628e+07 10.570 39.090 0.750 3.769 2.000000e+11 1.892e+10 + 6 5 1.302e+07 10.310 39.040 0.690 3.854 2.000000e+11 1.940e+10 + 6 6 1.085e+07 10.260 39.030 0.700 3.872 2.000000e+11 1.949e+10 + 6 7 9.301e+06 10.170 39.020 0.680 3.904 2.000000e+11 1.967e+10 + 6 8 8.138e+06 10.150 39.020 0.670 3.910 2.000000e+11 1.970e+10 + 7 1 5.580e+07 11.440 39.730 1.500 3.604 2.000000e+11 1.748e+10 + 7 2 2.790e+07 10.950 39.260 0.990 3.676 2.000000e+11 1.826e+10 + 7 3 1.860e+07 10.620 39.140 0.860 3.766 2.000000e+11 1.883e+10 + 7 4 1.395e+07 10.420 39.070 0.750 3.821 2.000000e+11 1.919e+10 + 7 5 1.116e+07 10.290 39.040 0.710 3.863 2.000000e+11 1.944e+10 + 7 6 9.301e+06 10.200 39.040 0.720 3.898 2.000000e+11 1.961e+10 + 7 7 7.972e+06 10.210 39.020 0.670 3.887 2.000000e+11 1.959e+10 + 7 8 6.975e+06 10.160 39.020 0.650 3.905 2.000000e+11 1.969e+10 + 8 1 4.883e+07 10.870 39.950 1.520 3.815 2.000000e+11 1.840e+10 + 8 2 2.441e+07 10.690 39.270 1.000 3.767 2.000000e+11 1.871e+10 + 8 3 1.628e+07 10.540 39.130 0.860 3.794 2.000000e+11 1.898e+10 + 8 4 1.221e+07 10.410 39.110 0.790 3.833 2.000000e+11 1.921e+10 + 8 5 9.766e+06 10.230 39.040 0.710 3.886 2.000000e+11 1.955e+10 + 8 6 8.138e+06 10.260 39.050 0.700 3.874 2.000000e+11 1.949e+10 + 8 7 6.975e+06 10.220 39.100 0.690 3.893 2.000000e+11 1.957e+10 + 8 8 6.104e+06 10.170 39.020 0.650 3.901 2.000000e+11 1.967e+10 diff --git a/gnuradio-core/src/examples/mp-sched/perf-data/js21.dat b/gnuradio-core/src/examples/mp-sched/perf-data/js21.dat new file mode 100644 index 000000000..a23bcebe7 --- /dev/null +++ b/gnuradio-core/src/examples/mp-sched/perf-data/js21.dat @@ -0,0 +1,65 @@ +#D JS21 4-core PPC970MP 2.5 GHz + 1 1 5.273e+07 10.050 10.180 0.290 1.042 2.700000e+10 2.687e+09 + 1 2 5.273e+07 10.240 20.210 0.260 1.999 5.400000e+10 5.273e+09 + 1 3 5.273e+07 10.300 30.090 0.340 2.954 8.100000e+10 7.864e+09 + 1 4 5.273e+07 10.490 40.120 0.490 3.871 1.080000e+11 1.030e+10 + 1 5 4.219e+07 16.010 39.900 0.380 2.516 1.080000e+11 6.746e+09 + 1 6 3.516e+07 13.360 39.920 0.370 3.016 1.080000e+11 8.084e+09 + 1 7 3.013e+07 11.510 39.900 0.330 3.495 1.080000e+11 9.383e+09 + 1 8 2.637e+07 10.420 39.880 0.320 3.858 1.080000e+11 1.036e+10 + 2 1 5.273e+07 10.370 20.340 0.470 2.007 5.400000e+10 5.207e+09 + 2 2 5.273e+07 10.320 40.080 0.550 3.937 1.080000e+11 1.047e+10 + 2 3 3.516e+07 13.340 39.990 0.470 3.033 1.080000e+11 8.096e+09 + 2 4 2.637e+07 10.480 39.970 0.400 3.852 1.080000e+11 1.031e+10 + 2 5 2.109e+07 10.910 39.920 0.390 3.695 1.080000e+11 9.899e+09 + 2 6 1.758e+07 10.610 39.860 0.360 3.791 1.080000e+11 1.018e+10 + 2 7 1.507e+07 10.520 39.890 0.360 3.826 1.080000e+11 1.027e+10 + 2 8 1.318e+07 10.470 39.980 0.350 3.852 1.080000e+11 1.032e+10 + 3 1 5.273e+07 10.230 30.320 0.600 3.022 8.100000e+10 7.918e+09 + 3 2 3.516e+07 13.250 40.050 0.560 3.065 1.080000e+11 8.151e+09 + 3 3 2.344e+07 11.160 40.010 0.470 3.627 1.080000e+11 9.677e+09 + 3 4 1.758e+07 10.710 39.950 0.420 3.769 1.080000e+11 1.008e+10 + 3 5 1.406e+07 10.520 39.920 0.400 3.833 1.080000e+11 1.027e+10 + 3 6 1.172e+07 10.420 39.880 0.380 3.864 1.080000e+11 1.036e+10 + 3 7 1.004e+07 10.340 39.880 0.370 3.893 1.080000e+11 1.044e+10 + 3 8 8.789e+06 10.380 39.960 0.380 3.886 1.080000e+11 1.040e+10 + 4 1 5.273e+07 10.570 40.390 0.890 3.905 1.080000e+11 1.022e+10 + 4 2 2.637e+07 10.690 40.020 0.560 3.796 1.080000e+11 1.010e+10 + 4 3 1.758e+07 10.790 39.980 0.480 3.750 1.080000e+11 1.001e+10 + 4 4 1.318e+07 10.570 39.950 0.430 3.820 1.080000e+11 1.022e+10 + 4 5 1.055e+07 10.440 39.950 0.420 3.867 1.080000e+11 1.034e+10 + 4 6 8.789e+06 10.340 39.900 0.420 3.899 1.080000e+11 1.044e+10 + 4 7 7.533e+06 10.290 39.870 0.410 3.914 1.080000e+11 1.050e+10 + 4 8 6.592e+06 10.270 39.950 0.390 3.928 1.080000e+11 1.052e+10 + 5 1 4.219e+07 15.110 40.290 0.830 2.721 1.080000e+11 7.148e+09 + 5 2 2.109e+07 11.240 40.000 0.580 3.610 1.080000e+11 9.609e+09 + 5 3 1.406e+07 10.710 39.970 0.490 3.778 1.080000e+11 1.008e+10 + 5 4 1.055e+07 10.490 39.980 0.460 3.855 1.080000e+11 1.030e+10 + 5 5 8.438e+06 10.430 39.940 0.440 3.872 1.080000e+11 1.035e+10 + 5 6 7.031e+06 10.280 39.890 0.420 3.921 1.080000e+11 1.051e+10 + 5 7 6.027e+06 10.290 39.870 0.400 3.914 1.080000e+11 1.050e+10 + 5 8 5.273e+06 10.290 39.940 0.400 3.920 1.080000e+11 1.050e+10 + 6 1 3.516e+07 12.880 40.250 0.850 3.191 1.080000e+11 8.385e+09 + 6 2 1.758e+07 10.730 39.980 0.580 3.780 1.080000e+11 1.007e+10 + 6 3 1.172e+07 10.740 39.980 0.490 3.768 1.080000e+11 1.006e+10 + 6 4 8.789e+06 10.510 39.940 0.460 3.844 1.080000e+11 1.028e+10 + 6 5 7.031e+06 10.430 39.920 0.450 3.871 1.080000e+11 1.035e+10 + 6 6 5.859e+06 10.300 39.910 0.430 3.917 1.080000e+11 1.049e+10 + 6 7 5.022e+06 10.290 39.870 0.420 3.915 1.080000e+11 1.050e+10 + 6 8 4.395e+06 10.300 39.950 0.420 3.919 1.080000e+11 1.049e+10 + 7 1 3.013e+07 11.240 40.270 0.860 3.659 1.080000e+11 9.609e+09 + 7 2 1.507e+07 11.040 40.000 0.590 3.677 1.080000e+11 9.783e+09 + 7 3 1.004e+07 10.660 39.970 0.520 3.798 1.080000e+11 1.013e+10 + 7 4 7.533e+06 10.430 39.930 0.470 3.873 1.080000e+11 1.035e+10 + 7 5 6.027e+06 10.390 39.920 0.470 3.887 1.080000e+11 1.039e+10 + 7 6 5.022e+06 10.320 39.910 0.430 3.909 1.080000e+11 1.047e+10 + 7 7 4.305e+06 10.330 39.890 0.420 3.902 1.080000e+11 1.045e+10 + 7 8 3.767e+06 10.300 39.930 0.420 3.917 1.080000e+11 1.049e+10 + 8 1 2.637e+07 10.530 40.290 0.910 3.913 1.080000e+11 1.026e+10 + 8 2 1.318e+07 10.850 40.040 0.610 3.747 1.080000e+11 9.954e+09 + 8 3 8.789e+06 10.500 39.960 0.540 3.857 1.080000e+11 1.029e+10 + 8 4 6.592e+06 10.490 39.960 0.500 3.857 1.080000e+11 1.030e+10 + 8 5 5.273e+06 10.330 39.930 0.480 3.912 1.080000e+11 1.045e+10 + 8 6 4.395e+06 10.340 39.900 0.450 3.902 1.080000e+11 1.044e+10 + 8 7 3.767e+06 10.260 39.900 0.430 3.931 1.080000e+11 1.053e+10 + 8 8 3.296e+06 10.250 39.960 0.430 3.940 1.080000e+11 1.054e+10 diff --git a/gnuradio-core/src/examples/mp-sched/perf-data/ps3-altivec.dat b/gnuradio-core/src/examples/mp-sched/perf-data/ps3-altivec.dat new file mode 100644 index 000000000..dd01b31bd --- /dev/null +++ b/gnuradio-core/src/examples/mp-sched/perf-data/ps3-altivec.dat @@ -0,0 +1,65 @@ +#D Playstation 3 (using Altivec) + 1 1 3.906e+07 10.500 10.580 0.440 1.050 2.000000e+10 1.905e+09 + 1 2 1.953e+07 7.010 13.200 0.400 1.940 2.000000e+10 2.853e+09 + 1 3 1.302e+07 7.540 13.140 0.380 1.793 2.000000e+10 2.653e+09 + 1 4 9.766e+06 7.200 13.620 0.370 1.943 2.000000e+10 2.778e+09 + 1 5 7.812e+06 7.170 13.670 0.340 1.954 2.000000e+10 2.789e+09 + 1 6 6.510e+06 7.010 13.590 0.320 1.984 2.000000e+10 2.853e+09 + 1 7 5.580e+06 6.990 13.530 0.330 1.983 2.000000e+10 2.861e+09 + 1 8 4.883e+06 6.980 13.490 0.320 1.979 2.000000e+10 2.865e+09 + 2 1 1.953e+07 8.110 14.730 0.530 1.882 2.000000e+10 2.466e+09 + 2 2 9.766e+06 7.090 13.570 0.420 1.973 2.000000e+10 2.821e+09 + 2 3 6.510e+06 7.040 13.590 0.410 1.989 2.000000e+10 2.841e+09 + 2 4 4.883e+06 6.990 13.490 0.370 1.983 2.000000e+10 2.861e+09 + 2 5 3.906e+06 6.970 13.480 0.360 1.986 2.000000e+10 2.869e+09 + 2 6 3.255e+06 6.990 13.530 0.370 1.989 2.000000e+10 2.861e+09 + 2 7 2.790e+06 6.890 13.390 0.350 1.994 2.000000e+10 2.903e+09 + 2 8 2.441e+06 6.880 13.380 0.350 1.996 2.000000e+10 2.907e+09 + 3 1 1.302e+07 8.220 13.720 0.510 1.731 2.000000e+10 2.433e+09 + 3 2 6.510e+06 7.050 13.480 0.450 1.976 2.000000e+10 2.837e+09 + 3 3 4.340e+06 6.990 13.460 0.400 1.983 2.000000e+10 2.861e+09 + 3 4 3.255e+06 6.990 13.550 0.380 1.993 2.000000e+10 2.861e+09 + 3 5 2.604e+06 6.920 13.430 0.360 1.993 1.999999e+10 2.890e+09 + 3 6 2.170e+06 6.940 13.460 0.360 1.991 1.999999e+10 2.882e+09 + 3 7 1.860e+06 6.920 13.440 0.360 1.994 2.000000e+10 2.890e+09 + 3 8 1.628e+06 6.890 13.380 0.350 1.993 2.000000e+10 2.903e+09 + 4 1 9.766e+06 7.620 14.550 0.590 1.987 2.000000e+10 2.625e+09 + 4 2 4.883e+06 7.010 13.460 0.440 1.983 2.000000e+10 2.853e+09 + 4 3 3.255e+06 7.040 13.580 0.410 1.987 2.000000e+10 2.841e+09 + 4 4 2.441e+06 6.960 13.470 0.390 1.991 2.000000e+10 2.874e+09 + 4 5 1.953e+06 6.920 13.410 0.370 1.991 2.000000e+10 2.890e+09 + 4 6 1.628e+06 6.950 13.490 0.370 1.994 2.000000e+10 2.878e+09 + 4 7 1.395e+06 6.890 13.350 0.370 1.991 2.000000e+10 2.903e+09 + 4 8 1.221e+06 6.940 13.490 0.360 1.996 2.000000e+10 2.882e+09 + 5 1 7.812e+06 7.680 14.000 0.560 1.896 2.000000e+10 2.604e+09 + 5 2 3.906e+06 7.070 13.460 0.460 1.969 2.000000e+10 2.829e+09 + 5 3 2.604e+06 6.990 13.430 0.420 1.981 1.999999e+10 2.861e+09 + 5 4 1.953e+06 7.010 13.550 0.390 1.989 2.000000e+10 2.853e+09 + 5 5 1.562e+06 6.920 13.430 0.380 1.996 2.000000e+10 2.890e+09 + 5 6 1.302e+06 6.920 13.410 0.380 1.993 1.999999e+10 2.890e+09 + 5 7 1.116e+06 6.920 13.420 0.370 1.993 1.999999e+10 2.890e+09 + 5 8 9.766e+05 6.910 13.360 0.370 1.987 1.999999e+10 2.894e+09 + 6 1 6.510e+06 7.350 13.970 0.630 1.986 2.000000e+10 2.721e+09 + 6 2 3.255e+06 7.040 13.470 0.470 1.980 2.000000e+10 2.841e+09 + 6 3 2.170e+06 7.050 13.600 0.420 1.989 1.999999e+10 2.837e+09 + 6 4 1.628e+06 6.970 13.480 0.400 1.991 2.000000e+10 2.869e+09 + 6 5 1.302e+06 6.990 13.540 0.390 1.993 1.999999e+10 2.861e+09 + 6 6 1.085e+06 6.970 13.470 0.380 1.987 1.999999e+10 2.869e+09 + 6 7 9.301e+05 6.890 13.350 0.380 1.993 1.999999e+10 2.903e+09 + 6 8 8.138e+05 6.920 13.420 0.370 1.993 2.000000e+10 2.890e+09 + 7 1 5.580e+06 7.530 14.030 0.580 1.940 2.000000e+10 2.656e+09 + 7 2 2.790e+06 7.000 13.370 0.460 1.976 2.000000e+10 2.857e+09 + 7 3 1.860e+06 7.000 13.520 0.420 1.991 2.000000e+10 2.857e+09 + 7 4 1.395e+06 7.060 13.590 0.410 1.983 2.000000e+10 2.833e+09 + 7 5 1.116e+06 6.950 13.460 0.390 1.993 1.999999e+10 2.878e+09 + 7 6 9.301e+05 6.950 13.420 0.380 1.986 1.999999e+10 2.878e+09 + 7 7 7.972e+05 6.880 13.300 0.380 1.988 1.999998e+10 2.907e+09 + 7 8 6.975e+05 6.920 13.390 0.380 1.990 1.999998e+10 2.890e+09 + 8 1 4.883e+06 7.440 14.150 0.620 1.985 2.000000e+10 2.688e+09 + 8 2 2.441e+06 6.990 13.400 0.480 1.986 2.000000e+10 2.861e+09 + 8 3 1.628e+06 6.990 13.460 0.430 1.987 2.000000e+10 2.861e+09 + 8 4 1.221e+06 7.020 13.550 0.410 1.989 2.000000e+10 2.849e+09 + 8 5 9.766e+05 6.920 13.370 0.390 1.988 1.999999e+10 2.890e+09 + 8 6 8.138e+05 6.950 13.400 0.390 1.984 2.000000e+10 2.878e+09 + 8 7 6.975e+05 6.930 13.360 0.390 1.984 1.999998e+10 2.886e+09 + 8 8 6.104e+05 6.920 13.390 0.380 1.990 1.999998e+10 2.890e+09 diff --git a/gnuradio-core/src/examples/mp-sched/perf-data/ps3.dat b/gnuradio-core/src/examples/mp-sched/perf-data/ps3.dat new file mode 100644 index 000000000..c9bac37cc --- /dev/null +++ b/gnuradio-core/src/examples/mp-sched/perf-data/ps3.dat @@ -0,0 +1,65 @@ +#D Playstation 3 + 1 1 2.344e+07 9.970 9.960 0.280 1.027 1.200000e+10 1.204e+09 + 1 2 1.172e+07 12.590 24.430 0.400 1.972 1.200000e+10 9.531e+08 + 1 3 7.812e+06 12.200 22.790 0.360 1.898 1.200000e+10 9.836e+08 + 1 4 5.859e+06 12.450 24.440 0.360 1.992 1.200000e+10 9.639e+08 + 1 5 4.688e+06 12.390 24.100 0.360 1.974 1.200000e+10 9.685e+08 + 1 6 3.906e+06 12.360 24.200 0.370 1.988 1.200000e+10 9.709e+08 + 1 7 3.348e+06 12.460 24.390 0.360 1.986 1.200000e+10 9.631e+08 + 1 8 2.930e+06 12.440 24.400 0.360 1.990 1.200000e+10 9.646e+08 + 2 1 1.172e+07 12.580 24.660 0.490 1.999 1.200000e+10 9.539e+08 + 2 2 5.859e+06 12.480 24.290 0.420 1.980 1.200000e+10 9.615e+08 + 2 3 3.906e+06 12.500 24.500 0.400 1.992 1.200000e+10 9.600e+08 + 2 4 2.930e+06 12.440 24.400 0.390 1.993 1.200000e+10 9.646e+08 + 2 5 2.344e+06 12.500 24.510 0.380 1.991 1.200000e+10 9.600e+08 + 2 6 1.953e+06 12.450 24.480 0.380 1.997 1.200000e+10 9.639e+08 + 2 7 1.674e+06 12.450 24.430 0.380 1.993 1.200000e+10 9.639e+08 + 2 8 1.465e+06 12.430 24.450 0.380 1.998 1.199999e+10 9.654e+08 + 3 1 7.812e+06 12.280 23.600 0.460 1.959 1.200000e+10 9.772e+08 + 3 2 3.906e+06 12.690 24.760 0.430 1.985 1.200000e+10 9.456e+08 + 3 3 2.604e+06 12.610 24.700 0.410 1.991 1.200000e+10 9.516e+08 + 3 4 1.953e+06 12.440 24.410 0.400 1.994 1.200000e+10 9.646e+08 + 3 5 1.562e+06 12.400 24.370 0.380 1.996 1.200000e+10 9.677e+08 + 3 6 1.302e+06 12.440 24.450 0.380 1.996 1.200000e+10 9.646e+08 + 3 7 1.116e+06 12.470 24.470 0.380 1.993 1.200000e+10 9.623e+08 + 3 8 9.766e+05 12.440 24.440 0.380 1.995 1.199999e+10 9.646e+08 + 4 1 5.859e+06 12.670 24.710 0.500 1.990 1.200000e+10 9.471e+08 + 4 2 2.930e+06 12.600 24.600 0.440 1.987 1.200000e+10 9.524e+08 + 4 3 1.953e+06 12.490 24.480 0.410 1.993 1.200000e+10 9.608e+08 + 4 4 1.465e+06 12.400 24.340 0.400 1.995 1.199999e+10 9.677e+08 + 4 5 1.172e+06 12.440 24.410 0.390 1.994 1.200000e+10 9.646e+08 + 4 6 9.766e+05 12.440 24.440 0.390 1.996 1.199999e+10 9.646e+08 + 4 7 8.371e+05 12.450 24.420 0.390 1.993 1.199999e+10 9.639e+08 + 4 8 7.324e+05 12.370 24.310 0.380 1.996 1.199999e+10 9.701e+08 + 5 1 4.688e+06 12.890 24.790 0.500 1.962 1.200000e+10 9.310e+08 + 5 2 2.344e+06 12.620 24.680 0.450 1.991 1.200000e+10 9.509e+08 + 5 3 1.562e+06 12.430 24.360 0.410 1.993 1.200000e+10 9.654e+08 + 5 4 1.172e+06 12.420 24.390 0.410 1.997 1.200000e+10 9.662e+08 + 5 5 9.375e+05 12.430 24.380 0.400 1.994 1.200000e+10 9.654e+08 + 5 6 7.812e+05 12.400 24.340 0.400 1.995 1.200000e+10 9.677e+08 + 5 7 6.696e+05 12.360 24.290 0.390 1.997 1.199998e+10 9.709e+08 + 5 8 5.859e+05 12.420 24.370 0.390 1.994 1.199999e+10 9.662e+08 + 6 1 3.906e+06 12.990 25.320 0.560 1.992 1.200000e+10 9.238e+08 + 6 2 1.953e+06 12.610 24.550 0.440 1.982 1.200000e+10 9.516e+08 + 6 3 1.302e+06 12.520 24.310 0.420 1.975 1.200000e+10 9.585e+08 + 6 4 9.766e+05 12.460 24.310 0.420 1.985 1.199999e+10 9.631e+08 + 6 5 7.812e+05 12.440 24.240 0.410 1.982 1.200000e+10 9.646e+08 + 6 6 6.510e+05 12.430 24.170 0.410 1.977 1.199999e+10 9.654e+08 + 6 7 5.580e+05 12.450 24.230 0.410 1.979 1.199998e+10 9.639e+08 + 6 8 4.883e+05 12.490 24.190 0.420 1.970 1.199999e+10 9.608e+08 + 7 1 3.348e+06 13.150 24.280 0.500 1.884 1.200000e+10 9.125e+08 + 7 2 1.674e+06 12.480 24.170 0.430 1.971 1.200000e+10 9.615e+08 + 7 3 1.116e+06 12.480 24.430 0.440 1.993 1.200000e+10 9.615e+08 + 7 4 8.371e+05 12.380 24.270 0.420 1.994 1.199999e+10 9.693e+08 + 7 5 6.696e+05 12.390 24.290 0.430 1.995 1.199998e+10 9.685e+08 + 7 6 5.580e+05 12.430 24.300 0.430 1.990 1.199998e+10 9.654e+08 + 7 7 4.783e+05 12.460 24.360 0.430 1.990 1.199999e+10 9.631e+08 + 7 8 4.185e+05 12.460 24.340 0.430 1.988 1.199998e+10 9.631e+08 + 8 1 2.930e+06 12.960 24.600 0.530 1.939 1.200000e+10 9.259e+08 + 8 2 1.465e+06 12.580 24.240 0.440 1.962 1.199999e+10 9.539e+08 + 8 3 9.766e+05 12.520 24.060 0.430 1.956 1.199999e+10 9.585e+08 + 8 4 7.324e+05 12.420 24.200 0.410 1.981 1.199999e+10 9.662e+08 + 8 5 5.859e+05 12.430 24.310 0.430 1.990 1.199999e+10 9.654e+08 + 8 6 4.883e+05 12.430 24.130 0.420 1.975 1.199999e+10 9.654e+08 + 8 7 4.185e+05 12.800 24.220 0.490 1.930 1.199998e+10 9.375e+08 + 8 8 3.662e+05 12.460 24.340 0.430 1.988 1.199997e+10 9.631e+08 diff --git a/gnuradio-core/src/examples/mp-sched/perf-data/qs21-altivec.dat b/gnuradio-core/src/examples/mp-sched/perf-data/qs21-altivec.dat new file mode 100644 index 000000000..8364be363 --- /dev/null +++ b/gnuradio-core/src/examples/mp-sched/perf-data/qs21-altivec.dat @@ -0,0 +1,65 @@ +#D QS21 dual cell 3.2 GHz (using Altivec) + 1 1 3.516e+07 9.810 10.240 0.430 1.088 1.800000e+10 1.835e+09 + 1 2 3.516e+07 11.650 22.840 0.750 2.025 3.600000e+10 3.090e+09 + 1 3 2.344e+07 9.400 24.860 0.680 2.717 3.600000e+10 3.830e+09 + 1 4 1.758e+07 7.800 26.820 0.740 3.533 3.600000e+10 4.615e+09 + 1 5 1.406e+07 8.810 25.970 0.760 3.034 3.600000e+10 4.086e+09 + 1 6 1.172e+07 8.110 25.710 0.740 3.261 3.600000e+10 4.439e+09 + 1 7 1.004e+07 7.750 26.020 0.710 3.449 3.600000e+10 4.645e+09 + 1 8 8.789e+06 7.290 26.600 0.690 3.743 3.600000e+10 4.938e+09 + 2 1 3.516e+07 10.130 20.690 0.770 2.118 3.600000e+10 3.554e+09 + 2 2 1.758e+07 7.240 26.820 0.920 3.831 3.600000e+10 4.972e+09 + 2 3 1.172e+07 8.090 26.670 0.840 3.400 3.600000e+10 4.450e+09 + 2 4 8.789e+06 7.480 27.010 0.790 3.717 3.600000e+10 4.813e+09 + 2 5 7.031e+06 7.180 26.530 0.740 3.798 3.600000e+10 5.014e+09 + 2 6 5.859e+06 7.060 26.590 0.730 3.870 3.600000e+10 5.099e+09 + 2 7 5.022e+06 7.040 26.610 0.740 3.885 3.600000e+10 5.114e+09 + 2 8 4.395e+06 7.090 27.020 0.730 3.914 3.600000e+10 5.078e+09 + 3 1 2.344e+07 9.670 25.850 1.020 2.779 3.600000e+10 3.723e+09 + 3 2 1.172e+07 7.700 25.940 0.930 3.490 3.600000e+10 4.675e+09 + 3 3 7.812e+06 7.290 26.760 0.830 3.785 3.600000e+10 4.938e+09 + 3 4 5.859e+06 7.210 26.900 0.800 3.842 3.600000e+10 4.993e+09 + 3 5 4.688e+06 7.060 26.690 0.770 3.890 3.600000e+10 5.099e+09 + 3 6 3.906e+06 7.060 26.830 0.810 3.915 3.600000e+10 5.099e+09 + 3 7 3.348e+06 6.960 26.680 0.780 3.945 3.600000e+10 5.172e+09 + 3 8 2.930e+06 6.960 26.600 0.770 3.932 3.599999e+10 5.172e+09 + 4 1 1.758e+07 7.640 28.700 1.250 3.920 3.600000e+10 4.712e+09 + 4 2 8.789e+06 7.230 26.640 0.940 3.815 3.600000e+10 4.979e+09 + 4 3 5.859e+06 7.200 26.800 0.860 3.842 3.600000e+10 5.000e+09 + 4 4 4.395e+06 7.110 26.900 0.840 3.902 3.600000e+10 5.063e+09 + 4 5 3.516e+06 7.020 26.680 0.800 3.915 3.600000e+10 5.128e+09 + 4 6 2.930e+06 6.950 26.700 0.800 3.957 3.599999e+10 5.180e+09 + 4 7 2.511e+06 6.930 26.590 0.800 3.952 3.599999e+10 5.195e+09 + 4 8 2.197e+06 6.960 26.570 0.790 3.931 3.599999e+10 5.172e+09 + 5 1 1.406e+07 8.730 26.540 1.190 3.176 3.600000e+10 4.124e+09 + 5 2 7.031e+06 7.270 26.450 0.960 3.770 3.600000e+10 4.952e+09 + 5 3 4.688e+06 7.100 26.630 0.880 3.875 3.600000e+10 5.070e+09 + 5 4 3.516e+06 7.050 26.700 0.850 3.908 3.600000e+10 5.106e+09 + 5 5 2.812e+06 6.970 26.610 0.830 3.937 3.600000e+10 5.165e+09 + 5 6 2.344e+06 6.980 26.710 0.840 3.947 3.600000e+10 5.158e+09 + 5 7 2.009e+06 6.900 26.470 0.800 3.952 3.599999e+10 5.217e+09 + 5 8 1.758e+06 6.940 26.580 0.820 3.948 3.599999e+10 5.187e+09 + 6 1 1.172e+07 8.200 26.510 1.190 3.378 3.600000e+10 4.390e+09 + 6 2 5.859e+06 7.210 26.590 0.970 3.822 3.600000e+10 4.993e+09 + 6 3 3.906e+06 7.070 26.580 0.910 3.888 3.600000e+10 5.092e+09 + 6 4 2.930e+06 7.090 26.750 0.860 3.894 3.599999e+10 5.078e+09 + 6 5 2.344e+06 7.040 26.830 0.830 3.929 3.600000e+10 5.114e+09 + 6 6 1.953e+06 6.960 26.600 0.830 3.941 3.600000e+10 5.172e+09 + 6 7 1.674e+06 6.940 26.500 0.810 3.935 3.600000e+10 5.187e+09 + 6 8 1.465e+06 6.940 26.540 0.830 3.944 3.599998e+10 5.187e+09 + 7 1 1.004e+07 7.730 26.940 1.190 3.639 3.600000e+10 4.657e+09 + 7 2 5.022e+06 7.240 26.600 0.980 3.809 3.600000e+10 4.972e+09 + 7 3 3.348e+06 7.120 26.680 0.930 3.878 3.600000e+10 5.056e+09 + 7 4 2.511e+06 7.070 26.840 0.890 3.922 3.599999e+10 5.092e+09 + 7 5 2.009e+06 6.980 26.570 0.850 3.928 3.599999e+10 5.158e+09 + 7 6 1.674e+06 6.950 26.530 0.840 3.938 3.600000e+10 5.180e+09 + 7 7 1.435e+06 6.940 26.570 0.860 3.952 3.599998e+10 5.187e+09 + 7 8 1.256e+06 6.980 26.590 0.840 3.930 3.599999e+10 5.158e+09 + 8 1 8.789e+06 7.570 27.360 1.260 3.781 3.600000e+10 4.756e+09 + 8 2 4.395e+06 7.130 26.460 0.980 3.849 3.600000e+10 5.049e+09 + 8 3 2.930e+06 7.060 26.680 0.920 3.909 3.599999e+10 5.099e+09 + 8 4 2.197e+06 7.040 26.670 0.880 3.913 3.599999e+10 5.114e+09 + 8 5 1.758e+06 6.970 26.600 0.860 3.940 3.599999e+10 5.165e+09 + 8 6 1.465e+06 6.940 26.490 0.840 3.938 3.599998e+10 5.187e+09 + 8 7 1.256e+06 6.980 26.630 0.850 3.937 3.599999e+10 5.158e+09 + 8 8 1.099e+06 7.010 26.820 0.860 3.949 3.599997e+10 5.136e+09 diff --git a/gnuradio-core/src/examples/mp-sched/perf-data/qs21.dat b/gnuradio-core/src/examples/mp-sched/perf-data/qs21.dat new file mode 100644 index 000000000..cc628740a --- /dev/null +++ b/gnuradio-core/src/examples/mp-sched/perf-data/qs21.dat @@ -0,0 +1,65 @@ +#D QS21 dual cell 3.2 GHz + 1 1 1.953e+07 8.480 8.730 0.270 1.061 1.000000e+10 1.179e+09 + 1 2 1.953e+07 8.750 17.210 0.460 2.019 2.000000e+10 2.286e+09 + 1 3 1.302e+07 12.390 29.530 0.540 2.427 2.000000e+10 1.614e+09 + 1 4 9.766e+06 10.120 31.500 0.590 3.171 2.000000e+10 1.976e+09 + 1 5 7.812e+06 10.200 31.350 0.610 3.133 2.000000e+10 1.961e+09 + 1 6 6.510e+06 9.520 31.690 0.590 3.391 2.000000e+10 2.101e+09 + 1 7 5.580e+06 9.430 32.610 0.600 3.522 2.000000e+10 2.121e+09 + 1 8 4.883e+06 9.400 34.160 0.620 3.700 2.000000e+10 2.128e+09 + 2 1 1.953e+07 8.800 17.750 0.500 2.074 2.000000e+10 2.273e+09 + 2 2 9.766e+06 8.990 28.900 0.640 3.286 2.000000e+10 2.225e+09 + 2 3 6.510e+06 9.390 32.450 0.660 3.526 2.000000e+10 2.130e+09 + 2 4 4.883e+06 9.220 34.450 0.660 3.808 2.000000e+10 2.169e+09 + 2 5 3.906e+06 9.180 34.730 0.650 3.854 2.000000e+10 2.179e+09 + 2 6 3.255e+06 9.150 34.960 0.650 3.892 2.000000e+10 2.186e+09 + 2 7 2.790e+06 9.140 35.290 0.650 3.932 2.000000e+10 2.188e+09 + 2 8 2.441e+06 9.080 35.240 0.650 3.953 2.000000e+10 2.203e+09 + 3 1 1.302e+07 11.720 28.890 0.740 2.528 2.000000e+10 1.706e+09 + 3 2 6.510e+06 9.390 32.700 0.730 3.560 2.000000e+10 2.130e+09 + 3 3 4.340e+06 9.150 33.930 0.690 3.784 2.000000e+10 2.186e+09 + 3 4 3.255e+06 9.040 34.650 0.680 3.908 2.000000e+10 2.212e+09 + 3 5 2.604e+06 9.090 34.990 0.680 3.924 1.999999e+10 2.200e+09 + 3 6 2.170e+06 9.050 34.870 0.670 3.927 1.999999e+10 2.210e+09 + 3 7 1.860e+06 9.010 34.850 0.660 3.941 2.000000e+10 2.220e+09 + 3 8 1.628e+06 8.980 34.860 0.670 3.957 2.000000e+10 2.227e+09 + 4 1 9.766e+06 9.000 34.680 0.940 3.958 2.000000e+10 2.222e+09 + 4 2 4.883e+06 9.020 34.180 0.740 3.871 2.000000e+10 2.217e+09 + 4 3 3.255e+06 9.150 34.640 0.710 3.863 2.000000e+10 2.186e+09 + 4 4 2.441e+06 9.010 34.780 0.690 3.937 2.000000e+10 2.220e+09 + 4 5 1.953e+06 8.980 34.680 0.690 3.939 2.000000e+10 2.227e+09 + 4 6 1.628e+06 9.050 35.120 0.690 3.957 2.000000e+10 2.210e+09 + 4 7 1.395e+06 9.010 34.900 0.670 3.948 2.000000e+10 2.220e+09 + 4 8 1.221e+06 8.960 34.900 0.680 3.971 2.000000e+10 2.232e+09 + 5 1 7.812e+06 10.150 31.760 0.840 3.212 2.000000e+10 1.970e+09 + 5 2 3.906e+06 9.090 34.040 0.750 3.827 2.000000e+10 2.200e+09 + 5 3 2.604e+06 9.030 34.650 0.720 3.917 1.999999e+10 2.215e+09 + 5 4 1.953e+06 8.990 34.610 0.700 3.928 2.000000e+10 2.225e+09 + 5 5 1.562e+06 9.000 34.920 0.700 3.958 2.000000e+10 2.222e+09 + 5 6 1.302e+06 9.120 35.370 0.690 3.954 1.999999e+10 2.193e+09 + 5 7 1.116e+06 8.910 34.680 0.690 3.970 1.999999e+10 2.245e+09 + 5 8 9.766e+05 8.930 34.790 0.680 3.972 1.999999e+10 2.240e+09 + 6 1 6.510e+06 9.390 31.810 0.840 3.477 2.000000e+10 2.130e+09 + 6 2 3.255e+06 9.000 34.320 0.760 3.898 2.000000e+10 2.222e+09 + 6 3 2.170e+06 8.960 34.310 0.740 3.912 1.999999e+10 2.232e+09 + 6 4 1.628e+06 8.970 34.640 0.730 3.943 2.000000e+10 2.230e+09 + 6 5 1.302e+06 9.110 35.360 0.710 3.959 1.999999e+10 2.195e+09 + 6 6 1.085e+06 8.970 34.750 0.710 3.953 1.999999e+10 2.230e+09 + 6 7 9.301e+05 8.950 34.710 0.700 3.956 1.999999e+10 2.235e+09 + 6 8 8.138e+05 8.920 34.570 0.710 3.955 2.000000e+10 2.242e+09 + 7 1 5.580e+06 9.290 32.840 0.870 3.629 2.000000e+10 2.153e+09 + 7 2 2.790e+06 9.040 34.400 0.770 3.890 2.000000e+10 2.212e+09 + 7 3 1.860e+06 8.940 34.380 0.740 3.928 2.000000e+10 2.237e+09 + 7 4 1.395e+06 8.990 34.820 0.730 3.954 2.000000e+10 2.225e+09 + 7 5 1.116e+06 8.990 34.820 0.720 3.953 1.999999e+10 2.225e+09 + 7 6 9.301e+05 8.940 34.720 0.720 3.964 1.999999e+10 2.237e+09 + 7 7 7.972e+05 8.930 34.700 0.710 3.965 1.999998e+10 2.240e+09 + 7 8 6.975e+05 8.910 34.510 0.700 3.952 1.999998e+10 2.245e+09 + 8 1 4.883e+06 9.070 33.770 0.910 3.824 2.000000e+10 2.205e+09 + 8 2 2.441e+06 9.000 34.340 0.780 3.902 2.000000e+10 2.222e+09 + 8 3 1.628e+06 8.990 34.510 0.740 3.921 2.000000e+10 2.225e+09 + 8 4 1.221e+06 8.980 34.650 0.740 3.941 2.000000e+10 2.227e+09 + 8 5 9.766e+05 8.960 34.700 0.720 3.953 1.999999e+10 2.232e+09 + 8 6 8.138e+05 8.920 34.680 0.710 3.967 2.000000e+10 2.242e+09 + 8 7 6.975e+05 8.900 34.580 0.720 3.966 1.999998e+10 2.247e+09 + 8 8 6.104e+05 8.930 34.590 0.710 3.953 1.999998e+10 2.240e+09 diff --git a/gnuradio-core/src/examples/mp-sched/plot_flops.py b/gnuradio-core/src/examples/mp-sched/plot_flops.py new file mode 100755 index 000000000..d9d810ae2 --- /dev/null +++ b/gnuradio-core/src/examples/mp-sched/plot_flops.py @@ -0,0 +1,98 @@ +#!/usr/bin/env python +# +# 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 this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +""" +Reads output from run_synthetic.py and runs gnuplot showing +GFLOPS as f(npipes, nstages) +""" + +import re +import sys +import os +import tempfile +from optparse import OptionParser + + +def parse_file(input_filename, output): + last = None + desc = '' + for line in open(input_filename, 'r'): + s = line.strip() + if s.startswith('>>>'): # ignore ">>> using SSE cruft" + continue + + if s.startswith('#D'): # machine description + desc = s[2:].strip() + continue + + fields = s.split() + npipes, nstages, flops = fields[0], fields[1], fields[8] + + if last is not None and npipes != last: + output.write('\n') + last = npipes + + output.write(' '.join((npipes, nstages, flops))) + output.write('\n') + + output.flush() + return desc + + +def handle_file(input_filename): + cmd_file = tempfile.NamedTemporaryFile(mode='w+', prefix='pf', suffix='.cmd') + cmd_file_name = cmd_file.name + data_file = tempfile.NamedTemporaryFile(mode='w+', prefix='pf', suffix='.dat') + data_file_name = data_file.name + desc = parse_file(input_filename, data_file) + if len(desc) > 0: + cmd_file.write("set title '%s'\n" % (desc,)) + cmd_file.write("set xlabel 'N pipes'\n") + cmd_file.write("set ylabel 'N stages'\n") + cmd_file.write("set zlabel 'GFLOPS'\n") + cmd_file.write("set key off\n") + cmd_file.write("set view 60, 312\n") + cmd_file.write("set pm3d\n") + cmd_file.write("splot '%s' using 1:2:($3*1e-9) with pm3d at b, '%s' using 1:2:($3*1e-9) with pm3d\n" % ( + data_file_name, data_file_name)) + + cmd_file.flush() + data_file.flush() + + os.system("gnuplot " + cmd_file_name + " -") + + #sys.stdout.write(open(cmd_file_name,'r').read()) + #sys.stdout.write(open(data_file_name,'r').read()) + + +def main(): + usage = "usage: %prog [options] file.dat" + parser = OptionParser(usage=usage) + (options, args) = parser.parse_args() + if len(args) != 1: + parser.print_help() + raise SystemExit, 1 + + handle_file(args[0]) + + +if __name__ == '__main__': + main() diff --git a/gnuradio-core/src/examples/mp-sched/run_synthetic.py b/gnuradio-core/src/examples/mp-sched/run_synthetic.py new file mode 100755 index 000000000..4896bca46 --- /dev/null +++ b/gnuradio-core/src/examples/mp-sched/run_synthetic.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python +# +# 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 this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +""" +Run synthetic.py for npipes in [1,16], nstages in [1,16] +""" + +import re +import sys +import os +import tempfile +from optparse import OptionParser + + +def write_shell_script(f, data_filename, description, ncores, gflops, max_pipes_and_stages): + """ + f is the file to write the script to + data_filename is the where the data ends up + description describes the machine + ncores is the number of cores (used to size the workload) + gflops is the estimated GFLOPS per core (used to size the workload) + """ + + f.write("#!/bin/sh\n") + f.write("(\n") + if description: + f.write("echo '#D %s'\n" % (description,)) + + for npipes in range(1, max_pipes_and_stages + 1): + for nstages in range(1, max_pipes_and_stages + 1): + # We'd like each run of synthetic to take ~10 seconds + desired_time_per_run = 10 + est_gflops_avail = min(nstages * npipes, ncores) * gflops + nsamples = (est_gflops_avail * desired_time_per_run)/(512.0 * nstages * npipes) + nsamples = int(nsamples * 1e9) + + cmd = "./synthetic.py -m -s %d -p %d -N %d\n" % (nstages, npipes, nsamples) + f.write(cmd) + f.write('if test $? -ge 128; then exit 128; fi\n') + + f.write(") 2>&1 | grep --line-buffered -v '^>>>' | tee %s\n" % (data_filename,)) + f.flush() + + + +def main(): + description = """%prog gathers multiprocessor scaling data using the ./synthetic.py benchmark. +All combinations of npipes and nstages between 1 and --max-pipes-and-stages are tried. +The -n and -f options provides hints used to size the workload. We'd like each run +of synthetic to take about 10 seconds. For the full 16x16 case this results in a +total runtime of about 43 minutes, assuming that your values for -n and -f are reasonable. +For x86 machines, assume 3 FLOPS per processor Hz. E.g., 3 GHz machine -> 9 GFLOPS. +plot_flops.py will make pretty graphs from the output data generated by %prog. +""" + usage = "usage: %prog [options] output.dat" + parser = OptionParser(usage=usage, description=description) + parser.add_option("-d", "--description", metavar="DESC", + help="machine description, e.g., \"Dual quad-core Xeon 3 GHz\"", default=None) + parser.add_option("-n", "--ncores", type="int", default=1, + help="number of processor cores [default=%default]") + parser.add_option("-g", "--gflops", metavar="GFLOPS", type="float", default=3.0, + help="estimated GFLOPS per core [default=%default]") + parser.add_option("-m", "--max-pipes-and-stages", metavar="MAX", type="int", default=16, + help="maximum number of pipes and stages to use [default=%default]") + (options, args) = parser.parse_args() + if len(args) != 1: + parser.print_help() + raise SystemExit, 1 + + output_filename = args[0] + + shell = os.popen("/bin/sh", "w") + + write_shell_script(shell, + output_filename, + options.description, + options.ncores, + options.gflops, + options.max_pipes_and_stages) + +if __name__ == '__main__': + main() + diff --git a/gnuradio-core/src/examples/mp-sched/synthetic.py b/gnuradio-core/src/examples/mp-sched/synthetic.py new file mode 100755 index 000000000..5ce1b5eb8 --- /dev/null +++ b/gnuradio-core/src/examples/mp-sched/synthetic.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python +# +# 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 this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +from gnuradio import gr, gru, eng_notation, blks2 +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import os + + +class pipeline(gr.hier_block2): + def __init__(self, nstages, ntaps=256): + """ + Create a pipeline of nstages of gr.fir_filter_fff's connected in serial + terminating in a gr.null_sink. + """ + gr.hier_block2.__init__(self, "pipeline", + gr.io_signature(1, 1, gr.sizeof_float), + gr.io_signature(0, 0, 0)) + taps = ntaps*[1.0/ntaps] + upstream = self + for i in range(nstages): + op = gr.fir_filter_fff(1, taps) + self.connect(upstream, op) + upstream = op + + self.connect(upstream, gr.null_sink(gr.sizeof_float)) + + +class top(gr.top_block): + def __init__(self): + gr.top_block.__init__(self) + + default_nsamples = 10e6 + parser=OptionParser(option_class=eng_option) + parser.add_option("-p", "--npipelines", type="intx", default=1, + metavar="NPIPES", help="the number of pipelines to create (default=%default)") + parser.add_option("-s", "--nstages", type="intx", default=1, + metavar="NSTAGES", help="the number of stages in each pipeline (default=%default)") + parser.add_option("-N", "--nsamples", type="eng_float", default=default_nsamples, + help=("the number of samples to run through the graph (default=%s)" % + (eng_notation.num_to_str(default_nsamples)))) + parser.add_option("-m", "--machine-readable", action="store_true", default=False, + help="enable machine readable output") + + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + self.npipes = options.npipelines + self.nstages = options.nstages + self.nsamples = options.nsamples + self.machine_readable = options.machine_readable + + ntaps = 256 + + # Something vaguely like floating point ops + self.flop = 2 * ntaps * options.npipelines * options.nstages * options.nsamples + + src = gr.null_source(gr.sizeof_float) + head = gr.head(gr.sizeof_float, int(options.nsamples)) + self.connect(src, head) + + for n in range(options.npipelines): + self.connect(head, pipeline(options.nstages, ntaps)) + + +def time_it(tb): + start = os.times() + tb.run() + stop = os.times() + delta = map((lambda a, b: a-b), stop, start) + user, sys, childrens_user, childrens_sys, real = delta + total_user = user + childrens_user + total_sys = sys + childrens_sys + if tb.machine_readable: + print "%3d %3d %.3e %7.3f %7.3f %7.3f %7.3f %.6e %.3e" % ( + tb.npipes, tb.nstages, tb.nsamples, real, total_user, total_sys, (total_user+total_sys)/real, tb.flop, tb.flop/real) + else: + print "npipes %7d" % (tb.npipes,) + print "nstages %7d" % (tb.nstages,) + print "nsamples %s" % (eng_notation.num_to_str(tb.nsamples),) + print "real %7.3f" % (real,) + print "user %7.3f" % (total_user,) + print "sys %7.3f" % (total_sys,) + print "(user+sys)/real %7.3f" % ((total_user + total_sys)/real,) + print "pseudo_flop %s" % (eng_notation.num_to_str(tb.flop),) + print "pseudo_flop/real %s" % (eng_notation.num_to_str(tb.flop/real),) + + +if __name__ == "__main__": + try: + tb = top() + time_it(tb) + except KeyboardInterrupt: + raise SystemExit, 128 + + + + diff --git a/gnuradio-core/src/examples/mp-sched/wfm_rcv_pll_to_wav.py b/gnuradio-core/src/examples/mp-sched/wfm_rcv_pll_to_wav.py new file mode 100755 index 000000000..81613922b --- /dev/null +++ b/gnuradio-core/src/examples/mp-sched/wfm_rcv_pll_to_wav.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python +# +# Copyright 2005,2006,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. +# + +from gnuradio import gr, gru, eng_notation, optfir +from gnuradio import audio +from gnuradio import blks2 +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import sys +import math + +class wfm_rx_block (gr.top_block): + def __init__(self): + gr.top_block.__init__(self) + + usage = "usage: %prog [options] input-samples-320kS.dat output.wav" + parser=OptionParser(option_class=eng_option, usage=usage) + parser.add_option("-V", "--volume", type="eng_float", default=None, + help="set volume (default is midpoint)") + + (options, args) = parser.parse_args() + if len(args) != 2: + parser.print_help() + sys.exit(1) + + input_filename = args[0] + output_filename = args[1] + + self.vol = 0 + + # build graph + + self.src = gr.file_source(gr.sizeof_gr_complex, input_filename, False) + + adc_rate = 64e6 # 64 MS/s + usrp_decim = 200 + usrp_rate = adc_rate / usrp_decim # 320 kS/s + chanfilt_decim = 1 + demod_rate = usrp_rate / chanfilt_decim + audio_decimation = 10 + audio_rate = demod_rate / audio_decimation # 32 kHz + + + chan_filt_coeffs = optfir.low_pass (1, # gain + usrp_rate, # sampling rate + 80e3, # passband cutoff + 115e3, # stopband cutoff + 0.1, # passband ripple + 60) # stopband attenuation + #print len(chan_filt_coeffs) + chan_filt = gr.fir_filter_ccf (chanfilt_decim, chan_filt_coeffs) + + + #self.guts = blks2.wfm_rcv (demod_rate, audio_decimation) + self.guts = blks2.wfm_rcv_pll (demod_rate, audio_decimation) + + # FIXME rework {add,multiply}_const_* to handle multiple streams + self.volume_control_l = gr.multiply_const_ff(self.vol) + self.volume_control_r = gr.multiply_const_ff(self.vol) + + # wave file as final sink + if 1: + sink = gr.wavfile_sink(output_filename, 2, int(audio_rate), 16) + else: + sink = audio.sink (int (audio_rate), + options.audio_output, + False) # ok_to_block + + # now wire it all together + self.connect (self.src, chan_filt, self.guts) + self.connect ((self.guts, 0), self.volume_control_l, (sink, 0)) + self.connect ((self.guts, 1), self.volume_control_r, (sink, 1)) + try: + self.guts.stereo_carrier_pll_recovery.squelch_enable(True) + except: + pass + #print "FYI: This implementation of the stereo_carrier_pll_recovery has no squelch implementation yet" + + if options.volume is None: + g = self.volume_range() + options.volume = float(g[0]+g[1])/2 + + # set initial values + + self.set_vol(options.volume) + try: + self.guts.stereo_carrier_pll_recovery.set_lock_threshold(options.squelch) + except: + pass + #print "FYI: This implementation of the stereo_carrier_pll_recovery has no squelch implementation yet" + + + def set_vol (self, vol): + g = self.volume_range() + self.vol = max(g[0], min(g[1], vol)) + self.volume_control_l.set_k(10**(self.vol/10)) + self.volume_control_r.set_k(10**(self.vol/10)) + + def volume_range(self): + return (-20.0, 0.0, 0.5) + + +if __name__ == '__main__': + tb = wfm_rx_block() + try: + tb.run() + except KeyboardInterrupt: + pass diff --git a/gnuradio-core/src/examples/msg_passing/CMakeLists.txt b/gnuradio-core/src/examples/msg_passing/CMakeLists.txt new file mode 100644 index 000000000..c4b207a1e --- /dev/null +++ b/gnuradio-core/src/examples/msg_passing/CMakeLists.txt @@ -0,0 +1,27 @@ +# 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) + +install( + FILES + strobe.grc + DESTINATION ${GR_PKG_DATA_DIR}/examples/msg_passing + COMPONENT "core_python" +) diff --git a/gnuradio-core/src/examples/msg_passing/hier/test_msg_hier.grc b/gnuradio-core/src/examples/msg_passing/hier/test_msg_hier.grc new file mode 100644 index 000000000..0faed49bc --- /dev/null +++ b/gnuradio-core/src/examples/msg_passing/hier/test_msg_hier.grc @@ -0,0 +1,287 @@ +<?xml version='1.0' encoding='ASCII'?> +<flow_graph> + <timestamp>Mon Dec 10 19:56:24 2012</timestamp> + <block> + <key>options</key> + <param> + <key>id</key> + <value>test_msg_hier</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>title</key> + <value></value> + </param> + <param> + <key>author</key> + <value></value> + </param> + <param> + <key>description</key> + <value></value> + </param> + <param> + <key>window_size</key> + <value>1280, 1024</value> + </param> + <param> + <key>generate_options</key> + <value>hb</value> + </param> + <param> + <key>category</key> + <value>Custom</value> + </param> + <param> + <key>run_options</key> + <value>prompt</value> + </param> + <param> + <key>run</key> + <value>True</value> + </param> + <param> + <key>max_nouts</key> + <value>0</value> + </param> + <param> + <key>realtime_scheduling</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(10, 10)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>pad_source</key> + <param> + <key>id</key> + <value>pad_source_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>label</key> + <value>TEST_PORT</value> + </param> + <param> + <key>type</key> + <value>message</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>optional</key> + <value>False</value> + </param> + <param> + <key>_coordinate</key> + <value>(234, 145)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>pad_source</key> + <param> + <key>id</key> + <value>pad_source_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>label</key> + <value>TEST_PORT2</value> + </param> + <param> + <key>type</key> + <value>message</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>optional</key> + <value>False</value> + </param> + <param> + <key>_coordinate</key> + <value>(167, 54)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>gr_message_strobe</key> + <param> + <key>id</key> + <value>gr_message_strobe_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>msg</key> + <value>pmt.pmt_cons(pmt.PMT_NIL, pmt.pmt_make_u8vector(16,0x77))</value> + </param> + <param> + <key>period</key> + <value>200</value> + </param> + <param> + <key>_coordinate</key> + <value>(362, 81)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>pad_sink</key> + <param> + <key>id</key> + <value>pad_sink_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>label</key> + <value>TEST_PORT</value> + </param> + <param> + <key>type</key> + <value>message</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>optional</key> + <value>True</value> + </param> + <param> + <key>_coordinate</key> + <value>(618, 87)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>gr_message_strobe</key> + <param> + <key>id</key> + <value>gr_message_strobe_0_1</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>msg</key> + <value>pmt.pmt_intern("OUTPUT2")</value> + </param> + <param> + <key>period</key> + <value>100</value> + </param> + <param> + <key>_coordinate</key> + <value>(400, 156)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>pad_sink</key> + <param> + <key>id</key> + <value>pad_sink_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>label</key> + <value>TEST_PORT3</value> + </param> + <param> + <key>type</key> + <value>message</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>optional</key> + <value>True</value> + </param> + <param> + <key>_coordinate</key> + <value>(695, 172)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <connection> + <source_block_id>pad_source_0_0</source_block_id> + <sink_block_id>gr_message_strobe_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>pad_source_0</source_block_id> + <sink_block_id>gr_message_strobe_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>gr_message_strobe_0</source_block_id> + <sink_block_id>pad_sink_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>gr_message_strobe_0_1</source_block_id> + <sink_block_id>pad_sink_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>gr_message_strobe_0_1</source_block_id> + <sink_block_id>pad_sink_0_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> +</flow_graph> diff --git a/gnuradio-core/src/examples/msg_passing/hier/test_msg_hier_topblock.grc b/gnuradio-core/src/examples/msg_passing/hier/test_msg_hier_topblock.grc new file mode 100644 index 000000000..f440b06b3 --- /dev/null +++ b/gnuradio-core/src/examples/msg_passing/hier/test_msg_hier_topblock.grc @@ -0,0 +1,185 @@ +<?xml version='1.0' encoding='ASCII'?> +<flow_graph> + <timestamp>Mon Dec 10 19:56:42 2012</timestamp> + <block> + <key>options</key> + <param> + <key>id</key> + <value>test_msg_hier_topblock</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>title</key> + <value></value> + </param> + <param> + <key>author</key> + <value></value> + </param> + <param> + <key>description</key> + <value></value> + </param> + <param> + <key>window_size</key> + <value>1280, 1024</value> + </param> + <param> + <key>generate_options</key> + <value>no_gui</value> + </param> + <param> + <key>category</key> + <value>Custom</value> + </param> + <param> + <key>run_options</key> + <value>prompt</value> + </param> + <param> + <key>run</key> + <value>True</value> + </param> + <param> + <key>max_nouts</key> + <value>0</value> + </param> + <param> + <key>realtime_scheduling</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(10, 10)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>gr_message_strobe</key> + <param> + <key>id</key> + <value>gr_message_strobe_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>msg</key> + <value>pmt.pmt_intern("UPDATED2")</value> + </param> + <param> + <key>period</key> + <value>3000</value> + </param> + <param> + <key>_coordinate</key> + <value>(51, 88)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>gr_message_strobe</key> + <param> + <key>id</key> + <value>gr_message_strobe_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>msg</key> + <value>pmt.pmt_intern("UPDATED")</value> + </param> + <param> + <key>period</key> + <value>2000</value> + </param> + <param> + <key>_coordinate</key> + <value>(211, 168)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>gr_message_debug</key> + <param> + <key>id</key> + <value>gr_message_debug_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>_coordinate</key> + <value>(758, 71)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>TEST_MSG_HIER</key> + <param> + <key>id</key> + <value>TEST_MSG_HIER_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>_coordinate</key> + <value>(402, 52)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <connection> + <source_block_id>TEST_MSG_HIER_0</source_block_id> + <sink_block_id>gr_message_debug_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>gr_message_strobe_0</source_block_id> + <sink_block_id>TEST_MSG_HIER_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>gr_message_strobe_0_0</source_block_id> + <sink_block_id>TEST_MSG_HIER_0</sink_block_id> + <source_key>0</source_key> + <sink_key>1</sink_key> + </connection> + <connection> + <source_block_id>TEST_MSG_HIER_0</source_block_id> + <sink_block_id>gr_message_debug_0</sink_block_id> + <source_key>0</source_key> + <sink_key>1</sink_key> + </connection> + <connection> + <source_block_id>TEST_MSG_HIER_0</source_block_id> + <sink_block_id>gr_message_debug_0</sink_block_id> + <source_key>1</source_key> + <sink_key>0</sink_key> + </connection> +</flow_graph> diff --git a/gnuradio-core/src/examples/msg_passing/strobe.grc b/gnuradio-core/src/examples/msg_passing/strobe.grc new file mode 100644 index 000000000..7e7e8c345 --- /dev/null +++ b/gnuradio-core/src/examples/msg_passing/strobe.grc @@ -0,0 +1,266 @@ +<?xml version='1.0' encoding='ASCII'?> +<flow_graph> + <timestamp>Thu Dec 6 11:33:08 2012</timestamp> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>samp_rate</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>32000</value> + </param> + <param> + <key>_coordinate</key> + <value>(10, 170)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>gr_pdu_to_tagged_stream</key> + <param> + <key>id</key> + <value>gr_pdu_to_tagged_stream_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>byte</value> + </param> + <param> + <key>_coordinate</key> + <value>(443, 89)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>gr_message_debug</key> + <param> + <key>id</key> + <value>gr_message_debug_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>_coordinate</key> + <value>(1049, 176)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>gr_tagged_stream_to_pdu</key> + <param> + <key>id</key> + <value>gr_tagged_stream_to_pdu_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>byte</value> + </param> + <param> + <key>_coordinate</key> + <value>(870, 89)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>gr_kludge_copy</key> + <param> + <key>id</key> + <value>gr_kludge_copy_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>byte</value> + </param> + <param> + <key>num_ports</key> + <value>1</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(686, 89)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>gr_message_strobe</key> + <param> + <key>id</key> + <value>gr_message_strobe_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>msg</key> + <value>pmt.pmt_intern("TEST")</value> + </param> + <param> + <key>period</key> + <value>1000</value> + </param> + <param> + <key>_coordinate</key> + <value>(423, 177)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>gr_message_strobe</key> + <param> + <key>id</key> + <value>gr_message_strobe_0_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>msg</key> + <value>pmt.pmt_cons( pmt.PMT_NIL, pmt.pmt_make_u8vector(512,0) )</value> + </param> + <param> + <key>period</key> + <value>750</value> + </param> + <param> + <key>_coordinate</key> + <value>(99, 85)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>options</key> + <param> + <key>id</key> + <value>strobe</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>title</key> + <value></value> + </param> + <param> + <key>author</key> + <value></value> + </param> + <param> + <key>description</key> + <value></value> + </param> + <param> + <key>window_size</key> + <value>1280, 1024</value> + </param> + <param> + <key>generate_options</key> + <value>no_gui</value> + </param> + <param> + <key>category</key> + <value>Custom</value> + </param> + <param> + <key>run_options</key> + <value>prompt</value> + </param> + <param> + <key>run</key> + <value>True</value> + </param> + <param> + <key>max_nouts</key> + <value>0</value> + </param> + <param> + <key>realtime_scheduling</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(10, 10)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <connection> + <source_block_id>gr_message_strobe_0_0</source_block_id> + <sink_block_id>gr_pdu_to_tagged_stream_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>gr_message_strobe_0</source_block_id> + <sink_block_id>gr_message_debug_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>gr_tagged_stream_to_pdu_0</source_block_id> + <sink_block_id>gr_message_debug_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>gr_kludge_copy_0</source_block_id> + <sink_block_id>gr_tagged_stream_to_pdu_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>gr_pdu_to_tagged_stream_0</source_block_id> + <sink_block_id>gr_kludge_copy_0</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> +</flow_graph> diff --git a/gnuradio-core/src/examples/network/CMakeLists.txt b/gnuradio-core/src/examples/network/CMakeLists.txt new file mode 100644 index 000000000..902933e29 --- /dev/null +++ b/gnuradio-core/src/examples/network/CMakeLists.txt @@ -0,0 +1,30 @@ +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +GR_PYTHON_INSTALL(PROGRAMS + audio_sink.py + audio_source.py + dial_tone_sink.py + dial_tone_source.py + vector_sink.py + vector_source.py + DESTINATION ${GR_PKG_DATA_DIR}/examples/network + COMPONENT "core_python" +) + diff --git a/gnuradio-core/src/examples/network/audio_sink.py b/gnuradio-core/src/examples/network/audio_sink.py new file mode 100755 index 000000000..72a678816 --- /dev/null +++ b/gnuradio-core/src/examples/network/audio_sink.py @@ -0,0 +1,72 @@ +#!/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 +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import sys + +try: + from gnuradio import audio +except ImportError: + sys.stderr.write("Failed to import gnuradio.audio. Make sure gr-audio component is installed.\n") + sys.exit(1) + +class audio_sink(gr.top_block): + def __init__(self, host, port, pkt_size, sample_rate, eof, wait): + gr.top_block.__init__(self, "audio_sink") + src = gr.udp_source(gr.sizeof_float, host, port, pkt_size, + eof=eof, wait=wait) + dst = audio.sink(sample_rate) + self.connect(src, dst) + +if __name__ == '__main__': + parser = OptionParser(option_class=eng_option) + parser.add_option("", "--host", type="string", default="0.0.0.0", + help="local host name (domain name or IP address)") + parser.add_option("", "--port", type="int", default=65500, + help="port value to listen to for connection") + parser.add_option("", "--packet-size", type="int", default=1472, + help="packet size.") + parser.add_option("-r", "--sample-rate", type="int", default=32000, + help="audio signal sample rate [default=%default]") + parser.add_option("", "--no-eof", action="store_true", default=False, + help="don't send EOF on disconnect") + parser.add_option("", "--no-wait", action="store_true", default=False, + help="don't wait for source") + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + # Create an instance of a hierarchical block + top_block = audio_sink(options.host, options.port, + options.packet_size, options.sample_rate, + not options.no_eof, not options.no_wait) + + try: + # Run forever + top_block.run() + except KeyboardInterrupt: + # Ctrl-C exits + pass + diff --git a/gnuradio-core/src/examples/network/audio_source.py b/gnuradio-core/src/examples/network/audio_source.py new file mode 100755 index 000000000..0baf7d2e9 --- /dev/null +++ b/gnuradio-core/src/examples/network/audio_source.py @@ -0,0 +1,69 @@ +#!/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 +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import sys + +try: + from gnuradio import audio +except ImportError: + sys.stderr.write("Failed to import gnuradio.audio. Make sure gr-audio component is installed.\n") + sys.exit(1) + +class audio_source(gr.top_block): + def __init__(self, host, port, pkt_size, sample_rate, eof): + gr.top_block.__init__(self, "audio_source") + self.audio = audio.source(sample_rate) + self.sink = gr.udp_sink(gr.sizeof_float, host, port, pkt_size, eof=eof) + self.connect(self.audio, self.sink) + +if __name__ == '__main__': + parser = OptionParser(option_class=eng_option) + parser.add_option("", "--host", type="string", default="localhost", + help="Remote host name (domain name or IP address") + parser.add_option("", "--port", type="int", default=65500, + help="port number to connect to") + parser.add_option("", "--packet-size", type="int", default=1472, + help="packet size.") + parser.add_option("-r", "--sample-rate", type="int", default=32000 , + help="audio signal sample rate [default=%default]") + parser.add_option("", "--no-eof", action="store_true", default=False, + help="don't send EOF on disconnect") + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + # Create an instance of a hierarchical block + top_block = audio_source(options.host, options.port, + options.packet_size, options.sample_rate, + not options.no_eof) + + try: + # Run forever + top_block.run() + except KeyboardInterrupt: + # Ctrl-C exits + pass + diff --git a/gnuradio-core/src/examples/network/dial_tone_sink.py b/gnuradio-core/src/examples/network/dial_tone_sink.py new file mode 100755 index 000000000..83ad376c0 --- /dev/null +++ b/gnuradio-core/src/examples/network/dial_tone_sink.py @@ -0,0 +1,65 @@ +#!/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, audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +class dial_tone_sink(gr.top_block): + def __init__(self, host, port, pkt_size, sample_rate, eof, wait): + gr.top_block.__init__(self, "dial_tone_sink") + udp = gr.udp_source(gr.sizeof_float, host, port, pkt_size, + eof=eof, wait=wait) + sink = audio.sink(sample_rate) + self.connect(udp, sink) + +if __name__ == '__main__': + parser = OptionParser(option_class=eng_option) + parser.add_option("", "--host", type="string", default="0.0.0.0", + help="local host name (domain name or IP address)") + parser.add_option("", "--port", type="int", default=65500, + help="port value to listen to for connection") + parser.add_option("", "--packet-size", type="int", default=1472, + help="packet size.") + parser.add_option("-r", "--sample-rate", type="int", default=8000, + help="audio signal sample rate [default=%default]") + parser.add_option("", "--no-eof", action="store_true", default=False, + help="don't send EOF on disconnect") + parser.add_option("", "--no-wait", action="store_true", default=False, + help="don't wait for source") + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + # Create an instance of a hierarchical block + top_block = dial_tone_sink(options.host, options.port, + options.packet_size, options.sample_rate, + not options.no_eof, not options.no_wait) + + try: + # Run forever + top_block.run() + except KeyboardInterrupt: + # Ctrl-C exits + pass + diff --git a/gnuradio-core/src/examples/network/dial_tone_source.py b/gnuradio-core/src/examples/network/dial_tone_source.py new file mode 100755 index 000000000..232a06de8 --- /dev/null +++ b/gnuradio-core/src/examples/network/dial_tone_source.py @@ -0,0 +1,70 @@ +#!/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 +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +class dial_tone_source(gr.top_block): + def __init__(self, host, port, pkt_size, sample_rate, eof): + gr.top_block.__init__(self, "dial_tone_source") + + amplitude = 0.3 + src0 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 350, amplitude) + src1 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 440, amplitude) + add = gr.add_ff() + + # Throttle needed here to account for the other side's audio card sampling rate + thr = gr.throttle(gr.sizeof_float, sample_rate) + sink = gr.udp_sink(gr.sizeof_float, host, port, pkt_size, eof=eof) + self.connect(src0, (add, 0)) + self.connect(src1, (add, 1)) + self.connect(add, thr, sink) + +if __name__ == '__main__': + parser = OptionParser(option_class=eng_option) + parser.add_option("", "--host", type="string", default="localhost", + help="Remote host name (domain name or IP address") + parser.add_option("", "--port", type="int", default=65500, + help="port number to connect to") + parser.add_option("", "--packet-size", type="int", default=1472, + help="packet size.") + parser.add_option("-r", "--sample-rate", type="int", default=8000, + help="audio signal sample rate [default=%default]") + parser.add_option("", "--no-eof", action="store_true", default=False, + help="don't send EOF on disconnect") + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + # Create an instance of a hierarchical block + top_block = dial_tone_source(options.host, options.port, + options.packet_size, options.sample_rate, + not options.no_eof) + + try: + # Run forever + top_block.run() + except KeyboardInterrupt: + # Ctrl-C exits + pass diff --git a/gnuradio-core/src/examples/network/vector_sink.py b/gnuradio-core/src/examples/network/vector_sink.py new file mode 100755 index 000000000..e84a27d9f --- /dev/null +++ b/gnuradio-core/src/examples/network/vector_sink.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +class vector_sink(gr.top_block): + def __init__(self, host, port, pkt_size, eof, wait): + gr.top_block.__init__(self, "vector_sink") + + udp = gr.udp_source(gr.sizeof_float, host, port, pkt_size, + eof=eof, wait=wait) + sink = gr.file_sink(gr.sizeof_float, "received.dat") + self.connect(udp, sink) + +if __name__ == "__main__": + parser = OptionParser(option_class=eng_option) + parser.add_option("", "--host", type="string", default="0.0.0.0", + help="local host name (domain name or IP address)") + parser.add_option("", "--port", type="int", default=65500, + help="port value to listen to for connection") + parser.add_option("", "--packet-size", type="int", default=1471, + help="packet size.") + parser.add_option("", "--no-eof", action="store_true", default=False, + help="don't send EOF on disconnect") + parser.add_option("", "--no-wait", action="store_true", default=False, + help="don't wait for source") + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + # Create an instance of a hierarchical block + top_block = vector_sink(options.host, options.port, + options.packet_size, + not options.no_eof, not options.no_wait) + + try: + # Run forever + top_block.run() + except KeyboardInterrupt: + # Ctrl-C exits + pass + diff --git a/gnuradio-core/src/examples/network/vector_source.py b/gnuradio-core/src/examples/network/vector_source.py new file mode 100755 index 000000000..d322dda3b --- /dev/null +++ b/gnuradio-core/src/examples/network/vector_source.py @@ -0,0 +1,60 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +class vector_source(gr.top_block): + def __init__(self, host, port, pkt_size, eof): + gr.top_block.__init__(self, "vector_source") + data = [i*0.01 for i in range(1000)] + vec = gr.vector_source_f(data, True) + udp = gr.udp_sink(gr.sizeof_float, host, port, pkt_size, eof=eof) + self.connect(vec, udp) + +if __name__ == '__main__': + parser = OptionParser(option_class=eng_option) + parser.add_option("", "--host", type="string", default="localhost", + help="Remote host name (domain name or IP address") + parser.add_option("", "--port", type="int", default=65500, + help="port number to connect to") + parser.add_option("", "--packet-size", type="int", default=1471, + help="packet size.") + parser.add_option("", "--no-eof", action="store_true", default=False, + help="don't send EOF on disconnect") + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + +# Create an instance of a hierarchical block + top_block = vector_source(options.host, options.port, options.packet_size, + not options.no_eof) + + try: + # Run forever + top_block.run() + except KeyboardInterrupt: + # Ctrl-C exits + pass + diff --git a/gnuradio-core/src/examples/pfb/CMakeLists.txt b/gnuradio-core/src/examples/pfb/CMakeLists.txt new file mode 100644 index 000000000..090b2401d --- /dev/null +++ b/gnuradio-core/src/examples/pfb/CMakeLists.txt @@ -0,0 +1,41 @@ +# 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(GrPython) + +GR_PYTHON_INSTALL(PROGRAMS + channelize.py + chirp_channelize.py + decimate.py + fmtest.py + interpolate.py + resampler.py + synth_filter.py + synth_to_chan.py + reconstruction.py + DESTINATION ${GR_PKG_DATA_DIR}/examples/pfb + COMPONENT "core_python" +) + +install( + FILES + resampler_demo.grc + DESTINATION ${GR_PKG_DATA_DIR}/examples/pfb + COMPONENT "core_python" +) diff --git a/gnuradio-core/src/examples/pfb/channelize.py b/gnuradio-core/src/examples/pfb/channelize.py new file mode 100755 index 000000000..442f263f4 --- /dev/null +++ b/gnuradio-core/src/examples/pfb/channelize.py @@ -0,0 +1,191 @@ +#!/usr/bin/env python +# +# Copyright 2009 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, blks2 +import sys, time + +try: + import scipy + from scipy import fftpack +except ImportError: + print "Error: Program requires scipy (see: www.scipy.org)." + sys.exit(1) + +try: + import pylab + from pylab import mlab +except ImportError: + print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)." + sys.exit(1) + +class pfb_top_block(gr.top_block): + def __init__(self): + gr.top_block.__init__(self) + + self._N = 2000000 # number of samples to use + self._fs = 9000 # initial sampling rate + self._M = 9 # Number of channels to channelize + + # Create a set of taps for the PFB channelizer + self._taps = gr.firdes.low_pass_2(1, self._fs, 475.50, 50, + attenuation_dB=100, window=gr.firdes.WIN_BLACKMAN_hARRIS) + + # Calculate the number of taps per channel for our own information + tpc = scipy.ceil(float(len(self._taps)) / float(self._M)) + print "Number of taps: ", len(self._taps) + print "Number of channels: ", self._M + print "Taps per channel: ", tpc + + # Create a set of signals at different frequencies + # freqs lists the frequencies of the signals that get stored + # in the list "signals", which then get summed together + self.signals = list() + self.add = gr.add_cc() + freqs = [-4070, -3050, -2030, -1010, 10, 1020, 2040, 3060, 4080] + for i in xrange(len(freqs)): + self.signals.append(gr.sig_source_c(self._fs, gr.GR_SIN_WAVE, freqs[i], 1)) + self.connect(self.signals[i], (self.add,i)) + + self.head = gr.head(gr.sizeof_gr_complex, self._N) + + # Construct the channelizer filter + self.pfb = blks2.pfb_channelizer_ccf(self._M, self._taps, 1) + + # Construct a vector sink for the input signal to the channelizer + self.snk_i = gr.vector_sink_c() + + # Connect the blocks + self.connect(self.add, self.head, self.pfb) + self.connect(self.add, self.snk_i) + + # Use this to play with the channel mapping + #self.pfb.set_channel_map([5,6,7,8,0,1,2,3,4]) + + # Create a vector sink for each of M output channels of the filter and connect it + self.snks = list() + for i in xrange(self._M): + self.snks.append(gr.vector_sink_c()) + self.connect((self.pfb, i), self.snks[i]) + + +def main(): + tstart = time.time() + + tb = pfb_top_block() + tb.run() + + tend = time.time() + print "Run time: %f" % (tend - tstart) + + if 1: + fig_in = pylab.figure(1, figsize=(16,9), facecolor="w") + fig1 = pylab.figure(2, figsize=(16,9), facecolor="w") + fig2 = pylab.figure(3, figsize=(16,9), facecolor="w") + + Ns = 1000 + Ne = 10000 + + fftlen = 8192 + winfunc = scipy.blackman + fs = tb._fs + + # Plot the input signal on its own figure + d = tb.snk_i.data()[Ns:Ne] + spin_f = fig_in.add_subplot(2, 1, 1) + + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs, + window = lambda d: d*winfunc(fftlen), + scale_by_freq=True) + X_in = 10.0*scipy.log10(abs(X)) + f_in = scipy.arange(-fs/2.0, fs/2.0, fs/float(X_in.size)) + pin_f = spin_f.plot(f_in, X_in, "b") + spin_f.set_xlim([min(f_in), max(f_in)+1]) + spin_f.set_ylim([-200.0, 50.0]) + + spin_f.set_title("Input Signal", weight="bold") + spin_f.set_xlabel("Frequency (Hz)") + spin_f.set_ylabel("Power (dBW)") + + + Ts = 1.0/fs + Tmax = len(d)*Ts + + t_in = scipy.arange(0, Tmax, Ts) + x_in = scipy.array(d) + spin_t = fig_in.add_subplot(2, 1, 2) + pin_t = spin_t.plot(t_in, x_in.real, "b") + pin_t = spin_t.plot(t_in, x_in.imag, "r") + + spin_t.set_xlabel("Time (s)") + spin_t.set_ylabel("Amplitude") + + Ncols = int(scipy.floor(scipy.sqrt(tb._M))) + Nrows = int(scipy.floor(tb._M / Ncols)) + if(tb._M % Ncols != 0): + Nrows += 1 + + # Plot each of the channels outputs. Frequencies on Figure 2 and + # time signals on Figure 3 + fs_o = tb._fs / tb._M + Ts_o = 1.0/fs_o + Tmax_o = len(d)*Ts_o + for i in xrange(len(tb.snks)): + # remove issues with the transients at the beginning + # also remove some corruption at the end of the stream + # this is a bug, probably due to the corner cases + d = tb.snks[i].data()[Ns:Ne] + + sp1_f = fig1.add_subplot(Nrows, Ncols, 1+i) + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs_o, + window = lambda d: d*winfunc(fftlen), + scale_by_freq=True) + X_o = 10.0*scipy.log10(abs(X)) + f_o = scipy.arange(-fs_o/2.0, fs_o/2.0, fs_o/float(X_o.size)) + p2_f = sp1_f.plot(f_o, X_o, "b") + sp1_f.set_xlim([min(f_o), max(f_o)+1]) + sp1_f.set_ylim([-200.0, 50.0]) + + sp1_f.set_title(("Channel %d" % i), weight="bold") + sp1_f.set_xlabel("Frequency (Hz)") + sp1_f.set_ylabel("Power (dBW)") + + x_o = scipy.array(d) + t_o = scipy.arange(0, Tmax_o, Ts_o) + sp2_o = fig2.add_subplot(Nrows, Ncols, 1+i) + p2_o = sp2_o.plot(t_o, x_o.real, "b") + p2_o = sp2_o.plot(t_o, x_o.imag, "r") + sp2_o.set_xlim([min(t_o), max(t_o)+1]) + sp2_o.set_ylim([-2, 2]) + + sp2_o.set_title(("Channel %d" % i), weight="bold") + sp2_o.set_xlabel("Time (s)") + sp2_o.set_ylabel("Amplitude") + + pylab.show() + + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gnuradio-core/src/examples/pfb/chirp_channelize.py b/gnuradio-core/src/examples/pfb/chirp_channelize.py new file mode 100755 index 000000000..1c485ea9d --- /dev/null +++ b/gnuradio-core/src/examples/pfb/chirp_channelize.py @@ -0,0 +1,203 @@ +#!/usr/bin/env python +# +# Copyright 2009 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, blks2 +import sys, time + +try: + import scipy + from scipy import fftpack +except ImportError: + print "Error: Program requires scipy (see: www.scipy.org)." + sys.exit(1) + +try: + import pylab + from pylab import mlab +except ImportError: + print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)." + sys.exit(1) + +class pfb_top_block(gr.top_block): + def __init__(self): + gr.top_block.__init__(self) + + self._N = 200000 # number of samples to use + self._fs = 9000 # initial sampling rate + self._M = 9 # Number of channels to channelize + + # Create a set of taps for the PFB channelizer + self._taps = gr.firdes.low_pass_2(1, self._fs, 500, 20, + attenuation_dB=10, window=gr.firdes.WIN_BLACKMAN_hARRIS) + + # Calculate the number of taps per channel for our own information + tpc = scipy.ceil(float(len(self._taps)) / float(self._M)) + print "Number of taps: ", len(self._taps) + print "Number of channels: ", self._M + print "Taps per channel: ", tpc + + repeated = True + if(repeated): + self.vco_input = gr.sig_source_f(self._fs, gr.GR_SIN_WAVE, 0.25, 110) + else: + amp = 100 + data = scipy.arange(0, amp, amp/float(self._N)) + self.vco_input = gr.vector_source_f(data, False) + + # Build a VCO controlled by either the sinusoid or single chirp tone + # Then convert this to a complex signal + self.vco = gr.vco_f(self._fs, 225, 1) + self.f2c = gr.float_to_complex() + + self.head = gr.head(gr.sizeof_gr_complex, self._N) + + # Construct the channelizer filter + self.pfb = blks2.pfb_channelizer_ccf(self._M, self._taps) + + # Construct a vector sink for the input signal to the channelizer + self.snk_i = gr.vector_sink_c() + + # Connect the blocks + self.connect(self.vco_input, self.vco, self.f2c) + self.connect(self.f2c, self.head, self.pfb) + self.connect(self.f2c, self.snk_i) + + # Create a vector sink for each of M output channels of the filter and connect it + self.snks = list() + for i in xrange(self._M): + self.snks.append(gr.vector_sink_c()) + self.connect((self.pfb, i), self.snks[i]) + + +def main(): + tstart = time.time() + + tb = pfb_top_block() + tb.run() + + tend = time.time() + print "Run time: %f" % (tend - tstart) + + if 1: + fig_in = pylab.figure(1, figsize=(16,9), facecolor="w") + fig1 = pylab.figure(2, figsize=(16,9), facecolor="w") + fig2 = pylab.figure(3, figsize=(16,9), facecolor="w") + fig3 = pylab.figure(4, figsize=(16,9), facecolor="w") + + Ns = 650 + Ne = 20000 + + fftlen = 8192 + winfunc = scipy.blackman + fs = tb._fs + + # Plot the input signal on its own figure + d = tb.snk_i.data()[Ns:Ne] + spin_f = fig_in.add_subplot(2, 1, 1) + + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs, + window = lambda d: d*winfunc(fftlen), + scale_by_freq=True) + X_in = 10.0*scipy.log10(abs(fftpack.fftshift(X))) + f_in = scipy.arange(-fs/2.0, fs/2.0, fs/float(X_in.size)) + pin_f = spin_f.plot(f_in, X_in, "b") + spin_f.set_xlim([min(f_in), max(f_in)+1]) + spin_f.set_ylim([-200.0, 50.0]) + + spin_f.set_title("Input Signal", weight="bold") + spin_f.set_xlabel("Frequency (Hz)") + spin_f.set_ylabel("Power (dBW)") + + + Ts = 1.0/fs + Tmax = len(d)*Ts + + t_in = scipy.arange(0, Tmax, Ts) + x_in = scipy.array(d) + spin_t = fig_in.add_subplot(2, 1, 2) + pin_t = spin_t.plot(t_in, x_in.real, "b") + pin_t = spin_t.plot(t_in, x_in.imag, "r") + + spin_t.set_xlabel("Time (s)") + spin_t.set_ylabel("Amplitude") + + Ncols = int(scipy.floor(scipy.sqrt(tb._M))) + Nrows = int(scipy.floor(tb._M / Ncols)) + if(tb._M % Ncols != 0): + Nrows += 1 + + # Plot each of the channels outputs. Frequencies on Figure 2 and + # time signals on Figure 3 + fs_o = tb._fs / tb._M + Ts_o = 1.0/fs_o + Tmax_o = len(d)*Ts_o + for i in xrange(len(tb.snks)): + # remove issues with the transients at the beginning + # also remove some corruption at the end of the stream + # this is a bug, probably due to the corner cases + d = tb.snks[i].data()[Ns:Ne] + + sp1_f = fig1.add_subplot(Nrows, Ncols, 1+i) + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs_o, + window = lambda d: d*winfunc(fftlen), + scale_by_freq=True) + X_o = 10.0*scipy.log10(abs(X)) + f_o = freq + p2_f = sp1_f.plot(f_o, X_o, "b") + sp1_f.set_xlim([min(f_o), max(f_o)+1]) + sp1_f.set_ylim([-200.0, 50.0]) + + sp1_f.set_title(("Channel %d" % i), weight="bold") + sp1_f.set_xlabel("Frequency (Hz)") + sp1_f.set_ylabel("Power (dBW)") + + x_o = scipy.array(d) + t_o = scipy.arange(0, Tmax_o, Ts_o) + sp2_o = fig2.add_subplot(Nrows, Ncols, 1+i) + p2_o = sp2_o.plot(t_o, x_o.real, "b") + p2_o = sp2_o.plot(t_o, x_o.imag, "r") + sp2_o.set_xlim([min(t_o), max(t_o)+1]) + sp2_o.set_ylim([-2, 2]) + + sp2_o.set_title(("Channel %d" % i), weight="bold") + sp2_o.set_xlabel("Time (s)") + sp2_o.set_ylabel("Amplitude") + + + sp3 = fig3.add_subplot(1,1,1) + p3 = sp3.plot(t_o, x_o.real) + sp3.set_xlim([min(t_o), max(t_o)+1]) + sp3.set_ylim([-2, 2]) + + sp3.set_title("All Channels") + sp3.set_xlabel("Time (s)") + sp3.set_ylabel("Amplitude") + + pylab.show() + + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gnuradio-core/src/examples/pfb/decimate.py b/gnuradio-core/src/examples/pfb/decimate.py new file mode 100755 index 000000000..5322d746d --- /dev/null +++ b/gnuradio-core/src/examples/pfb/decimate.py @@ -0,0 +1,178 @@ +#!/usr/bin/env python +# +# Copyright 2009 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, blks2 +import sys, time + +try: + import scipy + from scipy import fftpack +except ImportError: + print "Error: Program requires scipy (see: www.scipy.org)." + sys.exit(1) + +try: + import pylab + from pylab import mlab +except ImportError: + print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)." + sys.exit(1) + +class pfb_top_block(gr.top_block): + def __init__(self): + gr.top_block.__init__(self) + + self._N = 10000000 # number of samples to use + self._fs = 10000 # initial sampling rate + self._decim = 20 # Decimation rate + + # Generate the prototype filter taps for the decimators with a 200 Hz bandwidth + self._taps = gr.firdes.low_pass_2(1, self._fs, 200, 150, + attenuation_dB=120, window=gr.firdes.WIN_BLACKMAN_hARRIS) + + # Calculate the number of taps per channel for our own information + tpc = scipy.ceil(float(len(self._taps)) / float(self._decim)) + print "Number of taps: ", len(self._taps) + print "Number of filters: ", self._decim + print "Taps per channel: ", tpc + + # Build the input signal source + # We create a list of freqs, and a sine wave is generated and added to the source + # for each one of these frequencies. + self.signals = list() + self.add = gr.add_cc() + freqs = [10, 20, 2040] + for i in xrange(len(freqs)): + self.signals.append(gr.sig_source_c(self._fs, gr.GR_SIN_WAVE, freqs[i], 1)) + self.connect(self.signals[i], (self.add,i)) + + self.head = gr.head(gr.sizeof_gr_complex, self._N) + + # Construct a PFB decimator filter + self.pfb = blks2.pfb_decimator_ccf(self._decim, self._taps, 0) + + # Construct a standard FIR decimating filter + self.dec = gr.fir_filter_ccf(self._decim, self._taps) + + self.snk_i = gr.vector_sink_c() + + # Connect the blocks + self.connect(self.add, self.head, self.pfb) + self.connect(self.add, self.snk_i) + + # Create the sink for the decimated siganl + self.snk = gr.vector_sink_c() + self.connect(self.pfb, self.snk) + + +def main(): + tb = pfb_top_block() + + tstart = time.time() + tb.run() + tend = time.time() + print "Run time: %f" % (tend - tstart) + + if 1: + fig1 = pylab.figure(1, figsize=(16,9)) + fig2 = pylab.figure(2, figsize=(16,9)) + + Ns = 10000 + Ne = 10000 + + fftlen = 8192 + winfunc = scipy.blackman + fs = tb._fs + + # Plot the input to the decimator + + d = tb.snk_i.data()[Ns:Ns+Ne] + sp1_f = fig1.add_subplot(2, 1, 1) + + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs, + window = lambda d: d*winfunc(fftlen), + scale_by_freq=True) + X_in = 10.0*scipy.log10(abs(fftpack.fftshift(X))) + f_in = scipy.arange(-fs/2.0, fs/2.0, fs/float(X_in.size)) + p1_f = sp1_f.plot(f_in, X_in, "b") + sp1_f.set_xlim([min(f_in), max(f_in)+1]) + sp1_f.set_ylim([-200.0, 50.0]) + + sp1_f.set_title("Input Signal", weight="bold") + sp1_f.set_xlabel("Frequency (Hz)") + sp1_f.set_ylabel("Power (dBW)") + + Ts = 1.0/fs + Tmax = len(d)*Ts + + t_in = scipy.arange(0, Tmax, Ts) + x_in = scipy.array(d) + sp1_t = fig1.add_subplot(2, 1, 2) + p1_t = sp1_t.plot(t_in, x_in.real, "b") + p1_t = sp1_t.plot(t_in, x_in.imag, "r") + sp1_t.set_ylim([-tb._decim*1.1, tb._decim*1.1]) + + sp1_t.set_xlabel("Time (s)") + sp1_t.set_ylabel("Amplitude") + + + # Plot the output of the decimator + fs_o = tb._fs / tb._decim + + sp2_f = fig2.add_subplot(2, 1, 1) + d = tb.snk.data()[Ns:Ns+Ne] + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs_o, + window = lambda d: d*winfunc(fftlen), + scale_by_freq=True) + X_o = 10.0*scipy.log10(abs(fftpack.fftshift(X))) + f_o = scipy.arange(-fs_o/2.0, fs_o/2.0, fs_o/float(X_o.size)) + p2_f = sp2_f.plot(f_o, X_o, "b") + sp2_f.set_xlim([min(f_o), max(f_o)+1]) + sp2_f.set_ylim([-200.0, 50.0]) + + sp2_f.set_title("PFB Decimated Signal", weight="bold") + sp2_f.set_xlabel("Frequency (Hz)") + sp2_f.set_ylabel("Power (dBW)") + + + Ts_o = 1.0/fs_o + Tmax_o = len(d)*Ts_o + + x_o = scipy.array(d) + t_o = scipy.arange(0, Tmax_o, Ts_o) + sp2_t = fig2.add_subplot(2, 1, 2) + p2_t = sp2_t.plot(t_o, x_o.real, "b-o") + p2_t = sp2_t.plot(t_o, x_o.imag, "r-o") + sp2_t.set_ylim([-2.5, 2.5]) + + sp2_t.set_xlabel("Time (s)") + sp2_t.set_ylabel("Amplitude") + + pylab.show() + + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gnuradio-core/src/examples/pfb/fmtest.py b/gnuradio-core/src/examples/pfb/fmtest.py new file mode 100755 index 000000000..b9dd9b382 --- /dev/null +++ b/gnuradio-core/src/examples/pfb/fmtest.py @@ -0,0 +1,225 @@ +#!/usr/bin/env python +# +# Copyright 2009 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, blks2 +import sys, math, time + +try: + import scipy + from scipy import fftpack +except ImportError: + print "Error: Program requires scipy (see: www.scipy.org)." + sys.exit(1) + +try: + import pylab +except ImportError: + print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)." + sys.exit(1) + + +class fmtx(gr.hier_block2): + def __init__(self, lo_freq, audio_rate, if_rate): + + gr.hier_block2.__init__(self, "build_fm", + gr.io_signature(1, 1, gr.sizeof_float), # Input signature + gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature + + fmtx = blks2.nbfm_tx (audio_rate, if_rate, max_dev=5e3, tau=75e-6) + + # Local oscillator + lo = gr.sig_source_c (if_rate, # sample rate + gr.GR_SIN_WAVE, # waveform type + lo_freq, #frequency + 1.0, # amplitude + 0) # DC Offset + mixer = gr.multiply_cc () + + self.connect (self, fmtx, (mixer, 0)) + self.connect (lo, (mixer, 1)) + self.connect (mixer, self) + +class fmtest(gr.top_block): + def __init__(self): + gr.top_block.__init__(self) + + self._nsamples = 1000000 + self._audio_rate = 8000 + + # Set up N channels with their own baseband and IF frequencies + self._N = 5 + chspacing = 16000 + freq = [10, 20, 30, 40, 50] + f_lo = [0, 1*chspacing, -1*chspacing, 2*chspacing, -2*chspacing] + + self._if_rate = 4*self._N*self._audio_rate + + # Create a signal source and frequency modulate it + self.sum = gr.add_cc () + for n in xrange(self._N): + sig = gr.sig_source_f(self._audio_rate, gr.GR_SIN_WAVE, freq[n], 0.5) + fm = fmtx(f_lo[n], self._audio_rate, self._if_rate) + self.connect(sig, fm) + self.connect(fm, (self.sum, n)) + + self.head = gr.head(gr.sizeof_gr_complex, self._nsamples) + self.snk_tx = gr.vector_sink_c() + self.channel = blks2.channel_model(0.1) + + self.connect(self.sum, self.head, self.channel, self.snk_tx) + + + # Design the channlizer + self._M = 10 + bw = chspacing/2.0 + t_bw = chspacing/10.0 + self._chan_rate = self._if_rate / self._M + self._taps = gr.firdes.low_pass_2(1, self._if_rate, bw, t_bw, + attenuation_dB=100, + window=gr.firdes.WIN_BLACKMAN_hARRIS) + tpc = math.ceil(float(len(self._taps)) / float(self._M)) + + print "Number of taps: ", len(self._taps) + print "Number of channels: ", self._M + print "Taps per channel: ", tpc + + self.pfb = blks2.pfb_channelizer_ccf(self._M, self._taps) + + self.connect(self.channel, self.pfb) + + # Create a file sink for each of M output channels of the filter and connect it + self.fmdet = list() + self.squelch = list() + self.snks = list() + for i in xrange(self._M): + self.fmdet.append(blks2.nbfm_rx(self._audio_rate, self._chan_rate)) + self.squelch.append(blks2.standard_squelch(self._audio_rate*10)) + self.snks.append(gr.vector_sink_f()) + self.connect((self.pfb, i), self.fmdet[i], self.squelch[i], self.snks[i]) + + def num_tx_channels(self): + return self._N + + def num_rx_channels(self): + return self._M + +def main(): + + fm = fmtest() + + tstart = time.time() + fm.run() + tend = time.time() + + if 1: + fig1 = pylab.figure(1, figsize=(12,10), facecolor="w") + fig2 = pylab.figure(2, figsize=(12,10), facecolor="w") + fig3 = pylab.figure(3, figsize=(12,10), facecolor="w") + + Ns = 10000 + Ne = 100000 + + fftlen = 8192 + winfunc = scipy.blackman + + # Plot transmitted signal + fs = fm._if_rate + + d = fm.snk_tx.data()[Ns:Ns+Ne] + sp1_f = fig1.add_subplot(2, 1, 1) + + X,freq = sp1_f.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs, + window = lambda d: d*winfunc(fftlen), + visible=False) + X_in = 10.0*scipy.log10(abs(fftpack.fftshift(X))) + f_in = scipy.arange(-fs/2.0, fs/2.0, fs/float(X_in.size)) + p1_f = sp1_f.plot(f_in, X_in, "b") + sp1_f.set_xlim([min(f_in), max(f_in)+1]) + sp1_f.set_ylim([-120.0, 20.0]) + + sp1_f.set_title("Input Signal", weight="bold") + sp1_f.set_xlabel("Frequency (Hz)") + sp1_f.set_ylabel("Power (dBW)") + + Ts = 1.0/fs + Tmax = len(d)*Ts + + t_in = scipy.arange(0, Tmax, Ts) + x_in = scipy.array(d) + sp1_t = fig1.add_subplot(2, 1, 2) + p1_t = sp1_t.plot(t_in, x_in.real, "b-o") + #p1_t = sp1_t.plot(t_in, x_in.imag, "r-o") + sp1_t.set_ylim([-5, 5]) + + # Set up the number of rows and columns for plotting the subfigures + Ncols = int(scipy.floor(scipy.sqrt(fm.num_rx_channels()))) + Nrows = int(scipy.floor(fm.num_rx_channels() / Ncols)) + if(fm.num_rx_channels() % Ncols != 0): + Nrows += 1 + + # Plot each of the channels outputs. Frequencies on Figure 2 and + # time signals on Figure 3 + fs_o = fm._audio_rate + for i in xrange(len(fm.snks)): + # remove issues with the transients at the beginning + # also remove some corruption at the end of the stream + # this is a bug, probably due to the corner cases + d = fm.snks[i].data()[Ns:Ne] + + sp2_f = fig2.add_subplot(Nrows, Ncols, 1+i) + X,freq = sp2_f.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs_o, + window = lambda d: d*winfunc(fftlen), + visible=False) + #X_o = 10.0*scipy.log10(abs(fftpack.fftshift(X))) + X_o = 10.0*scipy.log10(abs(X)) + #f_o = scipy.arange(-fs_o/2.0, fs_o/2.0, fs_o/float(X_o.size)) + f_o = scipy.arange(0, fs_o/2.0, fs_o/2.0/float(X_o.size)) + p2_f = sp2_f.plot(f_o, X_o, "b") + sp2_f.set_xlim([min(f_o), max(f_o)+0.1]) + sp2_f.set_ylim([-120.0, 20.0]) + sp2_f.grid(True) + + sp2_f.set_title(("Channel %d" % i), weight="bold") + sp2_f.set_xlabel("Frequency (kHz)") + sp2_f.set_ylabel("Power (dBW)") + + + Ts = 1.0/fs_o + Tmax = len(d)*Ts + t_o = scipy.arange(0, Tmax, Ts) + + x_t = scipy.array(d) + sp2_t = fig3.add_subplot(Nrows, Ncols, 1+i) + p2_t = sp2_t.plot(t_o, x_t.real, "b") + p2_t = sp2_t.plot(t_o, x_t.imag, "r") + sp2_t.set_xlim([min(t_o), max(t_o)+1]) + sp2_t.set_ylim([-1, 1]) + + sp2_t.set_xlabel("Time (s)") + sp2_t.set_ylabel("Amplitude") + + + pylab.show() + + +if __name__ == "__main__": + main() diff --git a/gnuradio-core/src/examples/pfb/interpolate.py b/gnuradio-core/src/examples/pfb/interpolate.py new file mode 100755 index 000000000..98068f220 --- /dev/null +++ b/gnuradio-core/src/examples/pfb/interpolate.py @@ -0,0 +1,233 @@ +#!/usr/bin/env python +# +# Copyright 2009 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, blks2 +import sys, time + +try: + import scipy + from scipy import fftpack +except ImportError: + print "Error: Program requires scipy (see: www.scipy.org)." + sys.exit(1) + +try: + import pylab + from pylab import mlab +except ImportError: + print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)." + sys.exit(1) + +class pfb_top_block(gr.top_block): + def __init__(self): + gr.top_block.__init__(self) + + self._N = 100000 # number of samples to use + self._fs = 2000 # initial sampling rate + self._interp = 5 # Interpolation rate for PFB interpolator + self._ainterp = 5.5 # Resampling rate for the PFB arbitrary resampler + + # Frequencies of the signals we construct + freq1 = 100 + freq2 = 200 + + # Create a set of taps for the PFB interpolator + # This is based on the post-interpolation sample rate + self._taps = gr.firdes.low_pass_2(self._interp, self._interp*self._fs, freq2+50, 50, + attenuation_dB=120, window=gr.firdes.WIN_BLACKMAN_hARRIS) + + # Create a set of taps for the PFB arbitrary resampler + # The filter size is the number of filters in the filterbank; 32 will give very low side-lobes, + # and larger numbers will reduce these even farther + # The taps in this filter are based on a sampling rate of the filter size since it acts + # internally as an interpolator. + flt_size = 32 + self._taps2 = gr.firdes.low_pass_2(flt_size, flt_size*self._fs, freq2+50, 150, + attenuation_dB=120, window=gr.firdes.WIN_BLACKMAN_hARRIS) + + # Calculate the number of taps per channel for our own information + tpc = scipy.ceil(float(len(self._taps)) / float(self._interp)) + print "Number of taps: ", len(self._taps) + print "Number of filters: ", self._interp + print "Taps per channel: ", tpc + + # Create a couple of signals at different frequencies + self.signal1 = gr.sig_source_c(self._fs, gr.GR_SIN_WAVE, freq1, 0.5) + self.signal2 = gr.sig_source_c(self._fs, gr.GR_SIN_WAVE, freq2, 0.5) + self.signal = gr.add_cc() + + self.head = gr.head(gr.sizeof_gr_complex, self._N) + + # Construct the PFB interpolator filter + self.pfb = blks2.pfb_interpolator_ccf(self._interp, self._taps) + + # Construct the PFB arbitrary resampler filter + self.pfb_ar = blks2.pfb_arb_resampler_ccf(self._ainterp, self._taps2, flt_size) + self.snk_i = gr.vector_sink_c() + + #self.pfb_ar.pfb.print_taps() + #self.pfb.pfb.print_taps() + + # Connect the blocks + self.connect(self.signal1, self.head, (self.signal,0)) + self.connect(self.signal2, (self.signal,1)) + self.connect(self.signal, self.pfb) + self.connect(self.signal, self.pfb_ar) + self.connect(self.signal, self.snk_i) + + # Create the sink for the interpolated signals + self.snk1 = gr.vector_sink_c() + self.snk2 = gr.vector_sink_c() + self.connect(self.pfb, self.snk1) + self.connect(self.pfb_ar, self.snk2) + + +def main(): + tb = pfb_top_block() + + tstart = time.time() + tb.run() + tend = time.time() + print "Run time: %f" % (tend - tstart) + + + if 1: + fig1 = pylab.figure(1, figsize=(12,10), facecolor="w") + fig2 = pylab.figure(2, figsize=(12,10), facecolor="w") + fig3 = pylab.figure(3, figsize=(12,10), facecolor="w") + + Ns = 10000 + Ne = 10000 + + fftlen = 8192 + winfunc = scipy.blackman + + # Plot input signal + fs = tb._fs + + d = tb.snk_i.data()[Ns:Ns+Ne] + sp1_f = fig1.add_subplot(2, 1, 1) + + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs, + window = lambda d: d*winfunc(fftlen), + scale_by_freq=True) + X_in = 10.0*scipy.log10(abs(fftpack.fftshift(X))) + f_in = scipy.arange(-fs/2.0, fs/2.0, fs/float(X_in.size)) + p1_f = sp1_f.plot(f_in, X_in, "b") + sp1_f.set_xlim([min(f_in), max(f_in)+1]) + sp1_f.set_ylim([-200.0, 50.0]) + + + sp1_f.set_title("Input Signal", weight="bold") + sp1_f.set_xlabel("Frequency (Hz)") + sp1_f.set_ylabel("Power (dBW)") + + Ts = 1.0/fs + Tmax = len(d)*Ts + + t_in = scipy.arange(0, Tmax, Ts) + x_in = scipy.array(d) + sp1_t = fig1.add_subplot(2, 1, 2) + p1_t = sp1_t.plot(t_in, x_in.real, "b-o") + #p1_t = sp1_t.plot(t_in, x_in.imag, "r-o") + sp1_t.set_ylim([-2.5, 2.5]) + + sp1_t.set_title("Input Signal", weight="bold") + sp1_t.set_xlabel("Time (s)") + sp1_t.set_ylabel("Amplitude") + + + # Plot output of PFB interpolator + fs_int = tb._fs*tb._interp + + sp2_f = fig2.add_subplot(2, 1, 1) + d = tb.snk1.data()[Ns:Ns+(tb._interp*Ne)] + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs, + window = lambda d: d*winfunc(fftlen), + scale_by_freq=True) + X_o = 10.0*scipy.log10(abs(fftpack.fftshift(X))) + f_o = scipy.arange(-fs_int/2.0, fs_int/2.0, fs_int/float(X_o.size)) + p2_f = sp2_f.plot(f_o, X_o, "b") + sp2_f.set_xlim([min(f_o), max(f_o)+1]) + sp2_f.set_ylim([-200.0, 50.0]) + + sp2_f.set_title("Output Signal from PFB Interpolator", weight="bold") + sp2_f.set_xlabel("Frequency (Hz)") + sp2_f.set_ylabel("Power (dBW)") + + Ts_int = 1.0/fs_int + Tmax = len(d)*Ts_int + + t_o = scipy.arange(0, Tmax, Ts_int) + x_o1 = scipy.array(d) + sp2_t = fig2.add_subplot(2, 1, 2) + p2_t = sp2_t.plot(t_o, x_o1.real, "b-o") + #p2_t = sp2_t.plot(t_o, x_o.imag, "r-o") + sp2_t.set_ylim([-2.5, 2.5]) + + sp2_t.set_title("Output Signal from PFB Interpolator", weight="bold") + sp2_t.set_xlabel("Time (s)") + sp2_t.set_ylabel("Amplitude") + + + # Plot output of PFB arbitrary resampler + fs_aint = tb._fs * tb._ainterp + + sp3_f = fig3.add_subplot(2, 1, 1) + d = tb.snk2.data()[Ns:Ns+(tb._interp*Ne)] + X,freq = mlab.psd(d, NFFT=fftlen, noverlap=fftlen/4, Fs=fs, + window = lambda d: d*winfunc(fftlen), + scale_by_freq=True) + X_o = 10.0*scipy.log10(abs(fftpack.fftshift(X))) + f_o = scipy.arange(-fs_aint/2.0, fs_aint/2.0, fs_aint/float(X_o.size)) + p3_f = sp3_f.plot(f_o, X_o, "b") + sp3_f.set_xlim([min(f_o), max(f_o)+1]) + sp3_f.set_ylim([-200.0, 50.0]) + + sp3_f.set_title("Output Signal from PFB Arbitrary Resampler", weight="bold") + sp3_f.set_xlabel("Frequency (Hz)") + sp3_f.set_ylabel("Power (dBW)") + + Ts_aint = 1.0/fs_aint + Tmax = len(d)*Ts_aint + + t_o = scipy.arange(0, Tmax, Ts_aint) + x_o2 = scipy.array(d) + sp3_f = fig3.add_subplot(2, 1, 2) + p3_f = sp3_f.plot(t_o, x_o2.real, "b-o") + p3_f = sp3_f.plot(t_o, x_o1.real, "m-o") + #p3_f = sp3_f.plot(t_o, x_o2.imag, "r-o") + sp3_f.set_ylim([-2.5, 2.5]) + + sp3_f.set_title("Output Signal from PFB Arbitrary Resampler", weight="bold") + sp3_f.set_xlabel("Time (s)") + sp3_f.set_ylabel("Amplitude") + + pylab.show() + + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gnuradio-core/src/examples/pfb/reconstruction.py b/gnuradio-core/src/examples/pfb/reconstruction.py new file mode 100755 index 000000000..59910e4d6 --- /dev/null +++ b/gnuradio-core/src/examples/pfb/reconstruction.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python + +import scipy, math, pylab +from scipy import fftpack +from gnuradio import gr, digital, blks2 + +fftlen = 8192 + +def main(): + N = 10000 + fs = 2000.0 + Ts = 1.0/fs + t = scipy.arange(0, N*Ts, Ts) + + # When playing with the number of channels, be careful about the filter + # specs and the channel map of the synthesizer set below. + nchans = 10 + + # Build the filter(s) + bw = 1000 + tb = 400 + proto_taps = gr.firdes.low_pass_2(1, nchans*fs, bw, tb, 80, + gr.firdes.WIN_BLACKMAN_hARRIS) + print "Filter length: ", len(proto_taps) + + + # Create a modulated signal + npwr = 0.01 + data = scipy.random.randint(0, 256, N) + rrc_taps = gr.firdes.root_raised_cosine(1, 2, 1, 0.35, 41) + + src = gr.vector_source_b(data.astype(scipy.uint8).tolist(), False) + mod = digital.bpsk_mod(samples_per_symbol=2) + chan = gr.channel_model(npwr) + rrc = gr.fft_filter_ccc(1, rrc_taps) + + # Split it up into pieces + channelizer = blks2.pfb_channelizer_ccf(nchans, proto_taps, 2) + + # Put the pieces back together again + syn_taps = [nchans*t for t in proto_taps] + synthesizer = gr.pfb_synthesizer_ccf(nchans, syn_taps, True) + src_snk = gr.vector_sink_c() + snk = gr.vector_sink_c() + + # Remap the location of the channels + # Can be done in synth or channelizer (watch out for rotattions in + # the channelizer) + synthesizer.set_channel_map([ 0, 1, 2, 3, 4, + 15, 16, 17, 18, 19]) + + tb = gr.top_block() + tb.connect(src, mod, chan, rrc, channelizer) + tb.connect(rrc, src_snk) + + vsnk = [] + for i in xrange(nchans): + tb.connect((channelizer,i), (synthesizer, i)) + + vsnk.append(gr.vector_sink_c()) + tb.connect((channelizer,i), vsnk[i]) + + tb.connect(synthesizer, snk) + tb.run() + + sin = scipy.array(src_snk.data()[1000:]) + sout = scipy.array(snk.data()[1000:]) + + + # Plot original signal + fs_in = nchans*fs + f1 = pylab.figure(1, figsize=(16,12), facecolor='w') + s11 = f1.add_subplot(2,2,1) + s11.psd(sin, NFFT=fftlen, Fs=fs_in) + s11.set_title("PSD of Original Signal") + s11.set_ylim([-200, -20]) + + s12 = f1.add_subplot(2,2,2) + s12.plot(sin.real[1000:1500], "o-b") + s12.plot(sin.imag[1000:1500], "o-r") + s12.set_title("Original Signal in Time") + + start = 1 + skip = 4 + s13 = f1.add_subplot(2,2,3) + s13.plot(sin.real[start::skip], sin.imag[start::skip], "o") + s13.set_title("Constellation") + s13.set_xlim([-2, 2]) + s13.set_ylim([-2, 2]) + + # Plot channels + nrows = int(scipy.sqrt(nchans)) + ncols = int(scipy.ceil(float(nchans)/float(nrows))) + + f2 = pylab.figure(2, figsize=(16,12), facecolor='w') + for n in xrange(nchans): + s = f2.add_subplot(nrows, ncols, n+1) + s.psd(vsnk[n].data(), NFFT=fftlen, Fs=fs_in) + s.set_title("Channel {0}".format(n)) + s.set_ylim([-200, -20]) + + # Plot reconstructed signal + fs_out = 2*nchans*fs + f3 = pylab.figure(3, figsize=(16,12), facecolor='w') + s31 = f3.add_subplot(2,2,1) + s31.psd(sout, NFFT=fftlen, Fs=fs_out) + s31.set_title("PSD of Reconstructed Signal") + s31.set_ylim([-200, -20]) + + s32 = f3.add_subplot(2,2,2) + s32.plot(sout.real[1000:1500], "o-b") + s32.plot(sout.imag[1000:1500], "o-r") + s32.set_title("Reconstructed Signal in Time") + + start = 2 + skip = 4 + s33 = f3.add_subplot(2,2,3) + s33.plot(sout.real[start::skip], sout.imag[start::skip], "o") + s33.set_title("Constellation") + s33.set_xlim([-2, 2]) + s33.set_ylim([-2, 2]) + + pylab.show() + + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass + diff --git a/gnuradio-core/src/examples/pfb/resampler.py b/gnuradio-core/src/examples/pfb/resampler.py new file mode 100755 index 000000000..555938d28 --- /dev/null +++ b/gnuradio-core/src/examples/pfb/resampler.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python +# +# Copyright 2009 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, blks2 +import sys + +try: + import scipy +except ImportError: + print "Error: Program requires scipy (see: www.scipy.org)." + sys.exit(1) + +try: + import pylab +except ImportError: + print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)." + sys.exit(1) + +class mytb(gr.top_block): + def __init__(self, fs_in, fs_out, fc, N=10000): + gr.top_block.__init__(self) + + rerate = float(fs_out) / float(fs_in) + print "Resampling from %f to %f by %f " %(fs_in, fs_out, rerate) + + # Creating our own taps + taps = gr.firdes.low_pass_2(32, 32, 0.25, 0.1, 80) + + self.src = gr.sig_source_c(fs_in, gr.GR_SIN_WAVE, fc, 1) + #self.src = gr.noise_source_c(gr.GR_GAUSSIAN, 1) + self.head = gr.head(gr.sizeof_gr_complex, N) + + # A resampler with our taps + self.resamp_0 = blks2.pfb_arb_resampler_ccf(rerate, taps, + flt_size=32) + + # A resampler that just needs a resampling rate. + # Filter is created for us and designed to cover + # entire bandwidth of the input signal. + # An optional atten=XX rate can be used here to + # specify the out-of-band rejection (default=80). + self.resamp_1 = blks2.pfb_arb_resampler_ccf(rerate) + + self.snk_in = gr.vector_sink_c() + self.snk_0 = gr.vector_sink_c() + self.snk_1 = gr.vector_sink_c() + + self.connect(self.src, self.head, self.snk_in) + self.connect(self.head, self.resamp_0, self.snk_0) + self.connect(self.head, self.resamp_1, self.snk_1) + +def main(): + fs_in = 8000 + fs_out = 20000 + fc = 1000 + N = 10000 + + tb = mytb(fs_in, fs_out, fc, N) + tb.run() + + + # Plot PSD of signals + nfftsize = 2048 + fig1 = pylab.figure(1, figsize=(10,10), facecolor="w") + sp1 = fig1.add_subplot(2,1,1) + sp1.psd(tb.snk_in.data(), NFFT=nfftsize, + noverlap=nfftsize/4, Fs = fs_in) + sp1.set_title(("Input Signal at f_s=%.2f kHz" % (fs_in/1000.0))) + sp1.set_xlim([-fs_in/2, fs_in/2]) + + sp2 = fig1.add_subplot(2,1,2) + sp2.psd(tb.snk_0.data(), NFFT=nfftsize, + noverlap=nfftsize/4, Fs = fs_out, + label="With our filter") + sp2.psd(tb.snk_1.data(), NFFT=nfftsize, + noverlap=nfftsize/4, Fs = fs_out, + label="With auto-generated filter") + sp2.set_title(("Output Signals at f_s=%.2f kHz" % (fs_out/1000.0))) + sp2.set_xlim([-fs_out/2, fs_out/2]) + sp2.legend() + + # Plot signals in time + Ts_in = 1.0/fs_in + Ts_out = 1.0/fs_out + t_in = scipy.arange(0, len(tb.snk_in.data())*Ts_in, Ts_in) + t_out = scipy.arange(0, len(tb.snk_0.data())*Ts_out, Ts_out) + + fig2 = pylab.figure(2, figsize=(10,10), facecolor="w") + sp21 = fig2.add_subplot(2,1,1) + sp21.plot(t_in, tb.snk_in.data()) + sp21.set_title(("Input Signal at f_s=%.2f kHz" % (fs_in/1000.0))) + sp21.set_xlim([t_in[100], t_in[200]]) + + sp22 = fig2.add_subplot(2,1,2) + sp22.plot(t_out, tb.snk_0.data(), + label="With our filter") + sp22.plot(t_out, tb.snk_1.data(), + label="With auto-generated filter") + sp22.set_title(("Output Signals at f_s=%.2f kHz" % (fs_out/1000.0))) + r = float(fs_out)/float(fs_in) + sp22.set_xlim([t_out[r * 100], t_out[r * 200]]) + sp22.legend() + + pylab.show() + +if __name__ == "__main__": + main() + diff --git a/gnuradio-core/src/examples/pfb/resampler_demo.grc b/gnuradio-core/src/examples/pfb/resampler_demo.grc new file mode 100644 index 000000000..468636a5c --- /dev/null +++ b/gnuradio-core/src/examples/pfb/resampler_demo.grc @@ -0,0 +1,598 @@ +<?xml version='1.0' encoding='ASCII'?> +<flow_graph> + <timestamp>Sun Aug 23 11:39:47 2009</timestamp> + <block> + <key>options</key> + <param> + <key>id</key> + <value>resampler_demo</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>title</key> + <value></value> + </param> + <param> + <key>author</key> + <value></value> + </param> + <param> + <key>description</key> + <value></value> + </param> + <param> + <key>window_size</key> + <value>1280, 1024</value> + </param> + <param> + <key>generate_options</key> + <value>wx_gui</value> + </param> + <param> + <key>category</key> + <value>Custom</value> + </param> + <param> + <key>run</key> + <value>True</value> + </param> + <param> + <key>realtime_scheduling</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(10, 10)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>import</key> + <param> + <key>id</key> + <value>import_0</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>import</key> + <value>import math</value> + </param> + <param> + <key>_coordinate</key> + <value>(11, 59)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>rs_taps</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>firdes.low_pass(nphases, nphases, frac_bw, 0.5-frac_bw)</value> + </param> + <param> + <key>_coordinate</key> + <value>(273, 154)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>gr_add_const_vxx</key> + <param> + <key>id</key> + <value>adder</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>const</key> + <value>-1.0</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(227, 303)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>gr_throttle</key> + <param> + <key>id</key> + <value>throttle</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>samples_per_second</key> + <value>samp_rate</value> + </param> + <param> + <key>vlen</key> + <value>1</value> + </param> + <param> + <key>_coordinate</key> + <value>(227, 493)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>wxgui_fftsink2</key> + <param> + <key>id</key> + <value>orig_fft</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>complex</value> + </param> + <param> + <key>title</key> + <value>Original Spectrum</value> + </param> + <param> + <key>samp_rate</key> + <value>samp_rate</value> + </param> + <param> + <key>baseband_freq</key> + <value>0</value> + </param> + <param> + <key>y_per_div</key> + <value>10</value> + </param> + <param> + <key>y_divs</key> + <value>10</value> + </param> + <param> + <key>ref_level</key> + <value>30</value> + </param> + <param> + <key>fft_size</key> + <value>1024</value> + </param> + <param> + <key>fft_rate</key> + <value>30</value> + </param> + <param> + <key>peak_hold</key> + <value>False</value> + </param> + <param> + <key>average</key> + <value>False</value> + </param> + <param> + <key>avg_alpha</key> + <value>0</value> + </param> + <param> + <key>grid_pos</key> + <value>1, 0, 1, 3</value> + </param> + <param> + <key>notebook</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(409, 289)</value> + </param> + <param> + <key>_rotation</key> + <value>180</value> + </param> + </block> + <block> + <key>wxgui_fftsink2</key> + <param> + <key>id</key> + <value>resamp_fft</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>complex</value> + </param> + <param> + <key>title</key> + <value>Resampled Spectrum</value> + </param> + <param> + <key>samp_rate</key> + <value>new_rate</value> + </param> + <param> + <key>baseband_freq</key> + <value>0</value> + </param> + <param> + <key>y_per_div</key> + <value>10</value> + </param> + <param> + <key>y_divs</key> + <value>10</value> + </param> + <param> + <key>ref_level</key> + <value>30</value> + </param> + <param> + <key>fft_size</key> + <value>1024</value> + </param> + <param> + <key>fft_rate</key> + <value>30</value> + </param> + <param> + <key>peak_hold</key> + <value>True</value> + </param> + <param> + <key>average</key> + <value>False</value> + </param> + <param> + <key>avg_alpha</key> + <value>0</value> + </param> + <param> + <key>grid_pos</key> + <value>2, 0, 1, 3</value> + </param> + <param> + <key>notebook</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(640, 256)</value> + </param> + <param> + <key>_rotation</key> + <value>180</value> + </param> + </block> + <block> + <key>gr_sig_source_x</key> + <param> + <key>id</key> + <value>tri_source</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>type</key> + <value>float</value> + </param> + <param> + <key>samp_rate</key> + <value>samp_rate</value> + </param> + <param> + <key>waveform</key> + <value>gr.GR_TRI_WAVE</value> + </param> + <param> + <key>freq</key> + <value>0.05</value> + </param> + <param> + <key>amp</key> + <value>2.0</value> + </param> + <param> + <key>offset</key> + <value>0</value> + </param> + <param> + <key>_coordinate</key> + <value>(21, 271)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>gr_frequency_modulator_fc</key> + <param> + <key>id</key> + <value>fm_mod</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>sensitivity</key> + <value>math.pi</value> + </param> + <param> + <key>_coordinate</key> + <value>(411, 493)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>blks2_pfb_arb_resampler_ccf</key> + <param> + <key>id</key> + <value>resampler</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>rate</key> + <value>float(new_rate)/samp_rate</value> + </param> + <param> + <key>taps</key> + <value>rs_taps</value> + </param> + <param> + <key>size</key> + <value>nphases</value> + </param> + <param> + <key>_coordinate</key> + <value>(641, 477)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable</key> + <param> + <key>id</key> + <value>nphases</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>value</key> + <value>32</value> + </param> + <param> + <key>_coordinate</key> + <value>(185, 153)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable_static_text</key> + <param> + <key>id</key> + <value>samp_rate</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>label</key> + <value>Sample Rate</value> + </param> + <param> + <key>value</key> + <value>44100</value> + </param> + <param> + <key>converver</key> + <value>float_converter</value> + </param> + <param> + <key>formatter</key> + <value>None</value> + </param> + <param> + <key>grid_pos</key> + <value>0, 0, 1, 1</value> + </param> + <param> + <key>notebook</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(179, 14)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable_static_text</key> + <param> + <key>id</key> + <value>new_rate</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>label</key> + <value>Resampled Rate</value> + </param> + <param> + <key>value</key> + <value>48000</value> + </param> + <param> + <key>converver</key> + <value>float_converter</value> + </param> + <param> + <key>formatter</key> + <value>None</value> + </param> + <param> + <key>grid_pos</key> + <value>0, 1, 1, 1</value> + </param> + <param> + <key>notebook</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(328, 15)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <block> + <key>variable_static_text</key> + <param> + <key>id</key> + <value>frac_bw</value> + </param> + <param> + <key>_enabled</key> + <value>True</value> + </param> + <param> + <key>label</key> + <value>Fractional Bandwidth</value> + </param> + <param> + <key>value</key> + <value>0.45</value> + </param> + <param> + <key>converver</key> + <value>float_converter</value> + </param> + <param> + <key>formatter</key> + <value>lambda x: "%0.2f"%x</value> + </param> + <param> + <key>grid_pos</key> + <value>0,2,1,1</value> + </param> + <param> + <key>notebook</key> + <value></value> + </param> + <param> + <key>_coordinate</key> + <value>(473, 14)</value> + </param> + <param> + <key>_rotation</key> + <value>0</value> + </param> + </block> + <connection> + <source_block_id>tri_source</source_block_id> + <sink_block_id>adder</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>adder</source_block_id> + <sink_block_id>throttle</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>resampler</source_block_id> + <sink_block_id>resamp_fft</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>fm_mod</source_block_id> + <sink_block_id>resampler</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>fm_mod</source_block_id> + <sink_block_id>orig_fft</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> + <connection> + <source_block_id>throttle</source_block_id> + <sink_block_id>fm_mod</sink_block_id> + <source_key>0</source_key> + <sink_key>0</sink_key> + </connection> +</flow_graph> diff --git a/gnuradio-core/src/examples/pfb/synth_filter.py b/gnuradio-core/src/examples/pfb/synth_filter.py new file mode 100755 index 000000000..c0f7376ec --- /dev/null +++ b/gnuradio-core/src/examples/pfb/synth_filter.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python +# +# Copyright 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, blks2 +import sys + +try: + import scipy +except ImportError: + print "Error: Program requires scipy (see: www.scipy.org)." + sys.exit(1) + +try: + import pylab +except ImportError: + print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)." + sys.exit(1) + +def main(): + N = 1000000 + fs = 8000 + + freqs = [100, 200, 300, 400, 500] + nchans = 7 + + sigs = list() + for fi in freqs: + s = gr.sig_source_c(fs, gr.GR_SIN_WAVE, fi, 1) + sigs.append(s) + + taps = gr.firdes.low_pass_2(len(freqs), fs, fs/float(nchans)/2, 100, 100) + print "Num. Taps = %d (taps per filter = %d)" % (len(taps), + len(taps)/nchans) + filtbank = gr.pfb_synthesizer_ccf(nchans, taps) + + head = gr.head(gr.sizeof_gr_complex, N) + snk = gr.vector_sink_c() + + tb = gr.top_block() + tb.connect(filtbank, head, snk) + + for i,si in enumerate(sigs): + tb.connect(si, (filtbank, i)) + + tb.run() + + if 1: + f1 = pylab.figure(1) + s1 = f1.add_subplot(1,1,1) + s1.plot(snk.data()[1000:]) + + fftlen = 2048 + f2 = pylab.figure(2) + s2 = f2.add_subplot(1,1,1) + winfunc = scipy.blackman + s2.psd(snk.data()[10000:], NFFT=fftlen, + Fs = nchans*fs, + noverlap=fftlen/4, + window = lambda d: d*winfunc(fftlen)) + + pylab.show() + +if __name__ == "__main__": + main() diff --git a/gnuradio-core/src/examples/pfb/synth_to_chan.py b/gnuradio-core/src/examples/pfb/synth_to_chan.py new file mode 100755 index 000000000..18b2e7b53 --- /dev/null +++ b/gnuradio-core/src/examples/pfb/synth_to_chan.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python +# +# Copyright 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, blks2 +import sys + +try: + import scipy +except ImportError: + print "Error: Program requires scipy (see: www.scipy.org)." + sys.exit(1) + +try: + import pylab +except ImportError: + print "Error: Program requires matplotlib (see: matplotlib.sourceforge.net)." + sys.exit(1) + +def main(): + N = 1000000 + fs = 8000 + + freqs = [100, 200, 300, 400, 500] + nchans = 7 + + sigs = list() + fmtx = list() + for fi in freqs: + s = gr.sig_source_f(fs, gr.GR_SIN_WAVE, fi, 1) + fm = blks2.nbfm_tx (fs, 4*fs, max_dev=10000, tau=75e-6) + sigs.append(s) + fmtx.append(fm) + + syntaps = gr.firdes.low_pass_2(len(freqs), fs, fs/float(nchans)/2, 100, 100) + print "Synthesis Num. Taps = %d (taps per filter = %d)" % (len(syntaps), + len(syntaps)/nchans) + chtaps = gr.firdes.low_pass_2(len(freqs), fs, fs/float(nchans)/2, 100, 100) + print "Channelizer Num. Taps = %d (taps per filter = %d)" % (len(chtaps), + len(chtaps)/nchans) + filtbank = gr.pfb_synthesizer_ccf(nchans, syntaps) + channelizer = blks2.pfb_channelizer_ccf(nchans, chtaps) + + noise_level = 0.01 + head = gr.head(gr.sizeof_gr_complex, N) + noise = gr.noise_source_c(gr.GR_GAUSSIAN, noise_level) + addnoise = gr.add_cc() + snk_synth = gr.vector_sink_c() + + tb = gr.top_block() + + tb.connect(noise, (addnoise,0)) + tb.connect(filtbank, head, (addnoise, 1)) + tb.connect(addnoise, channelizer) + tb.connect(addnoise, snk_synth) + + snk = list() + for i,si in enumerate(sigs): + tb.connect(si, fmtx[i], (filtbank, i)) + + for i in xrange(nchans): + snk.append(gr.vector_sink_c()) + tb.connect((channelizer, i), snk[i]) + + tb.run() + + if 1: + channel = 1 + data = snk[channel].data()[1000:] + + f1 = pylab.figure(1) + s1 = f1.add_subplot(1,1,1) + s1.plot(data[10000:10200] ) + s1.set_title(("Output Signal from Channel %d" % channel)) + + fftlen = 2048 + winfunc = scipy.blackman + #winfunc = scipy.hamming + + f2 = pylab.figure(2) + s2 = f2.add_subplot(1,1,1) + s2.psd(data, NFFT=fftlen, + Fs = nchans*fs, + noverlap=fftlen/4, + window = lambda d: d*winfunc(fftlen)) + s2.set_title(("Output PSD from Channel %d" % channel)) + + f3 = pylab.figure(3) + s3 = f3.add_subplot(1,1,1) + s3.psd(snk_synth.data()[1000:], NFFT=fftlen, + Fs = nchans*fs, + noverlap=fftlen/4, + window = lambda d: d*winfunc(fftlen)) + s3.set_title("Output of Synthesis Filter") + + pylab.show() + +if __name__ == "__main__": + main() diff --git a/gnuradio-core/src/examples/tags/CMakeLists.txt b/gnuradio-core/src/examples/tags/CMakeLists.txt new file mode 100644 index 000000000..2d9dc2083 --- /dev/null +++ b/gnuradio-core/src/examples/tags/CMakeLists.txt @@ -0,0 +1,28 @@ +# 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(GrPython) + +GR_PYTHON_INSTALL(PROGRAMS + test_file_tags.py + uhd_burst_detector.py + DESTINATION ${GR_PKG_DATA_DIR}/examples/tags + COMPONENT "core_python" +) + diff --git a/gnuradio-core/src/examples/tags/test_file_tags.py b/gnuradio-core/src/examples/tags/test_file_tags.py new file mode 100755 index 000000000..135626d2c --- /dev/null +++ b/gnuradio-core/src/examples/tags/test_file_tags.py @@ -0,0 +1,55 @@ +#!/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: + import scipy +except ImportError: + print "Error: Program requires scipy (see: www.scipy.org)." + sys.exit(1) + +def main(): + data = scipy.arange(0, 32000, 1).tolist() + trig = 100*[0,] + 100*[1,] + + src = gr.vector_source_s(data, True) + trigger = gr.vector_source_s(trig, True) + + thr = gr.throttle(gr.sizeof_short, 10e3) + ann = gr.annotator_alltoall(1000000, gr.sizeof_short) + tagger = gr.burst_tagger(gr.sizeof_short) + + fsnk = gr.tagged_file_sink(gr.sizeof_short, 1) + + tb = gr.top_block() + tb.connect(src, thr, (tagger, 0)) + tb.connect(trigger, (tagger, 1)) + tb.connect(tagger, fsnk) + + tb.run() + +if __name__ == "__main__": + main() + + diff --git a/gnuradio-core/src/examples/tags/uhd_burst_detector.py b/gnuradio-core/src/examples/tags/uhd_burst_detector.py new file mode 100755 index 000000000..512fc715d --- /dev/null +++ b/gnuradio-core/src/examples/tags/uhd_burst_detector.py @@ -0,0 +1,116 @@ +#!/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 eng_notation +from gnuradio import gr +from gnuradio import uhd +from gnuradio import window +from gnuradio.eng_option import eng_option +from gnuradio.gr import firdes +from optparse import OptionParser + +class uhd_burst_detector(gr.top_block): + def __init__(self, uhd_address, options): + + gr.top_block.__init__(self) + + self.uhd_addr = uhd_address + self.freq = options.freq + self.samp_rate = options.samp_rate + self.gain = options.gain + self.threshold = options.threshold + self.trigger = options.trigger + + self.uhd_src = uhd.single_usrp_source( + device_addr=self.uhd_addr, + stream_args=uhd.stream_args('fc32')) + + self.uhd_src.set_samp_rate(self.samp_rate) + self.uhd_src.set_center_freq(self.freq, 0) + self.uhd_src.set_gain(self.gain, 0) + + taps = firdes.low_pass_2(1, 1, 0.4, 0.1, 60) + self.chanfilt = gr.fir_filter_ccc(10, taps) + self.tagger = gr.burst_tagger(gr.sizeof_gr_complex) + + # Dummy signaler to collect a burst on known periods + data = 1000*[0,] + 1000*[1,] + self.signal = gr.vector_source_s(data, True) + + # Energy detector to get signal burst + ## use squelch to detect energy + self.det = gr.simple_squelch_cc(self.threshold, 0.01) + ## convert to mag squared (float) + self.c2m = gr.complex_to_mag_squared() + ## average to debounce + self.avg = gr.single_pole_iir_filter_ff(0.01) + ## rescale signal for conversion to short + self.scale = gr.multiply_const_ff(2**16) + ## signal input uses shorts + self.f2s = gr.float_to_short() + + # Use file sink burst tagger to capture bursts + self.fsnk = gr.tagged_file_sink(gr.sizeof_gr_complex, self.samp_rate) + + + ################################################## + # Connections + ################################################## + self.connect((self.uhd_src, 0), (self.tagger, 0)) + self.connect((self.tagger, 0), (self.fsnk, 0)) + + if self.trigger: + # Connect a dummy signaler to the burst tagger + self.connect((self.signal, 0), (self.tagger, 1)) + + else: + # Connect an energy detector signaler to the burst tagger + self.connect(self.uhd_src, self.det) + self.connect(self.det, self.c2m, self.avg, self.scale, self.f2s) + self.connect(self.f2s, (self.tagger, 1)) + + def set_samp_rate(self, samp_rate): + self.samp_rate = samp_rate + self.uhd_src_0.set_samp_rate(self.samp_rate) + +if __name__ == '__main__': + parser = OptionParser(option_class=eng_option, usage="%prog: [options]") + parser.add_option("-a", "--address", type="string", default="addr=192.168.10.2", + help="select address of the device [default=%default]") + #parser.add_option("-A", "--antenna", default=None, + # help="select Rx Antenna (only on RFX-series boards)") + parser.add_option("-f", "--freq", type="eng_float", default=450e6, + help="set frequency to FREQ", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=0, + help="set gain in dB [default=%default]") + parser.add_option("-R", "--samp-rate", type="eng_float", default=200000, + help="set USRP sample rate [default=%default]") + parser.add_option("-t", "--threshold", type="float", default=-60, + help="Set the detection power threshold (dBm) [default=%default") + parser.add_option("-T", "--trigger", action="store_true", default=False, + help="Use internal trigger instead of detector [default=%default]") + (options, args) = parser.parse_args() + + uhd_addr = options.address + + tb = uhd_burst_detector(uhd_addr, options) + tb.run() diff --git a/gnuradio-core/src/examples/volk_benchmark/CMakeLists.txt b/gnuradio-core/src/examples/volk_benchmark/CMakeLists.txt new file mode 100644 index 000000000..255d9bf5c --- /dev/null +++ b/gnuradio-core/src/examples/volk_benchmark/CMakeLists.txt @@ -0,0 +1,35 @@ +# 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(PROGRAMS + volk_math.py + volk_plot.py + volk_test_funcs.py + volk_types.py + DESTINATION ${GR_PKG_DATA_DIR}/examples/volk_benchmark + COMPONENT "core_python" +) + +install( + FILES README + DESTINATION ${GR_PKG_DATA_DIR}/examples/volk_benchmark + COMPONENT "core_python" +) diff --git a/gnuradio-core/src/examples/volk_benchmark/README b/gnuradio-core/src/examples/volk_benchmark/README new file mode 100644 index 000000000..c58b40d11 --- /dev/null +++ b/gnuradio-core/src/examples/volk_benchmark/README @@ -0,0 +1,252 @@ +VOLK Benchmarking Scripts + +The Python programs in this directory are designed to help benchmark +and compare Volk enhancements to GNU Radio. There are two kinds of +scripts here: collecting data and displaying the data. + +Data collection is done by running a Volk testing script that will +populate a SQLite database file (volk_results.db by default). The +plotting utility provided here reads from the database files and plots +bar graphs to compare the different installations. + +These benchmarks can be used to compare previous versions of GNU +Radio to using Volk; they can be used to compare different Volk +proto-kernels, as well, by editing the volk_config file; or they could +be used to compare performance between different machines and/or +processors. + + +====================================================================== +Volk Profiling + +Before doing any kind of Volk benchmarking, it is important to run the +volk_profile program. The profiler will build a config file for the +best SIMD architecture for your processor. Run volk_profile that is +installed into $PREFIX/bin. This program tests all known Volk kernels +for each proto-kernel supported by the processor. When finished, it +will write to $HOME/.volk/volk_config the best architecture for the +VOLK function. This file is read when using a function to know the +best version of the function to execute. + +The volk_config file contains a line for each kernel, where each line +looks like: + + volk_<KERNEL_NAME> <ARCHITECTURE> + +The architecture will be something like (sse, sse2, sse3, avx, neon, +etc.), depending on your processor. + + +====================================================================== +Benchmark Tests + +There are currently two benchmark scripts defined for collecting +data. There is one that runs through the type conversions that have +been converted to Volk (volk_types.py) and the other runs through the +math operators converted to using Volk (volk_math.py). + +Script prototypes +Both have the same structure for use: + +---------------------------------------------------------------------- +./volk_<test>.py [-h] -L LABEL [-D DATABASE] [-N NITEMS] [-I ITERATIONS] + [--tests [{0,1,2,3} [{0,1,2,3} ...]]] [--list] + [--all] + +optional arguments: + -h, --help show this help message and exit + -L LABEL, --label LABEL + Label of database table [default: None] + -D DATABASE, --database DATABASE + Database file to store data in [default: + volk_results.db] + -N NITEMS, --nitems NITEMS + Number of items per iterations [default: 1000000000.0] + -I ITERATIONS, --iterations ITERATIONS + Number of iterations [default: 20] + --tests [{0,1,2,3} [{0,1,2,3} ...]] + A list of tests to run; can be a single test or a + space-separated list. + --list List the available tests + --all Run all tests +---------------------------------------------------------------------- + +To run, you specify the tests to run and a label to store along with +the results. To find out what the available tests are, use the +'--list' option. + +To specify a subset of tests, use the '--tests' with space-separated +list of tests numbers (e.g., --tests 0 2 4 9). + +Use the '--all' to run all tests. + +The label specified is used as an identifier for the benchmarking +currently being done. This is required as it is important in +organizing the data in the database (each label is its own +table). Usually, the label will specify the type of run being done, +such as "volk_aligned" or "v3_5_1". In these cases, the "volk_aligned" +label says that this is for a benchmarking using the GNU Radio version +that uses the aligned scheduler and Volk calls in the work +functions. The "v3_5_1" label is if you were benchmarking an installed +version 3.5.1 of GNU Radio, which is pre-Volk. These will then be +plotted against each other to see the timing differences. + +The 'database' option will output the results to a new database +file. This can be useful for separating the output of different runs +or of different benchmarks, such as the types versus the math scripts, +say, or to distinguish results from different computers. + +If rerun using the same database and label, the entries in the table +will simply be replaced by the new results. + +It is often useful to use the 'sqlitebrowser' program to interrogate +the database file farther, if you are interested in the structure or +the raw data. + +Other parameters of this script set the number of items to process and +number of iterations to use when computing the benchmarking +data. These default to 1 billion samples per iteration over 20 +iterations. Expect a default run to take a long time. Using the '-N' +and '-I' options can be used to change the runtime of the benchmarks +but are set high to remove problems of variance between iterations. + +====================================================================== +Plotting Results + +The volk_plot.py script reads a given database file and plots the +results. The default behavior is to read all of the labels stored in +the database and plot them as data sets on a bar graph. This shows the +average time taken to process the number of items given. + +The options for the plotting script are: + +usage: volk_plot.py [-h] [-D DATABASE] [-E] [-P {mean,min,max}] [-% table] + +Plot Volk performance results from a SQLite database. Run one of the volk +tests first (e.g, volk_math.py) + +---------------------------------------------------------------------- +optional arguments: + -h, --help show this help message and exit + -D DATABASE, --database DATABASE + Database file to read data from [default: + volk_results.db] + -E, --errorbars Show error bars (1 standard dev.) + -P {mean,min,max}, --plot {mean,min,max} + Set the type of plot to produce [default: mean] + -% table, --percent table + Show percent difference to the given type [default: + None] +---------------------------------------------------------------------- + +This script allows you to specify the database used (-D), but will +always read all rows from all tables from it and display them. You can +also turn on plotting error bars (1 standard deviation the mean). Be +careful, though, as some older versions of Matplotlib might have an +issue with this option. + +The mean time is only one possible statistic that we might be +interested in when looking at the data. It represents the average user +experience when running a given block. On the other hand, the minimum +runtime best represents the actual performance of a block given +minimal OS interruptions while running. Right now, the data collected +includes the mean, variance, min, and max over the number of +iterations given. Using the '-P' option, you can specify the type of +data to plot (mean, min, or max). + +Another useful way of looking at the data is to compare the percent +improvement of a benchmark compared to another. This is done using the +'-%' option with the provided table (or label) as the baseline. So if +we were interested in comparing how much the 'volk_aligned' was over +'v3_5_1', we would specify '-% v3_5_1' to see this. The plot would +then only show the percent speedup observed using Volk for each of the +blocks. + + +====================================================================== +Benchmarking Walkthrough + +This will walk through an example of benchmarking the new Volk +implementation versus the pre-Volk GNU Radio. It also shows how to +look at the SIMD optimized versions versus the generic +implementations. + +Since we introduced Volk in GNU Radio 3.5.2, we will use the following +labels for our data: + + 1.) volk_aligned: v3.5.2 with volk_profile results in .volk/volk_config + 2.) v3_5_2: v3.5.2 with the generic (non-SIMD) calls to Volk + 3.) v3_5_1: an installation of GNU Radio from version v3.5.1 + +We assume that we have installed two versions of GNU Radio. + + v3.5.2 installed into /opt/gr-3_5_2 + v3.5.1 installed into /opt/gr-3_5_1 + +To test cases 1 and 2 above, we have to run GNU Radio from the v3.5.2 +installation, so we set the following environmental variables. Note +that this is written for Ubuntu 11.10. These commands and directories +may have to be changed depending on your OS and versions. + + export LD_LIBRARY_PATH=/opt/gr-3_5_2/lib + export LD_LIBRARY_PATH=/opt/gr-3_5_2/lib/python2.7/dist-packages + +Now we can run the benchmark tests, so we will focus on the math +operators: + + ./volk_math.py -D volk_results_math.db --all -L volk_aligned + +When this finishes, the 'volk_results_math.db' will contain our +results for this run. + +We next want to run the generic, non-SIMD, calls. This can be done by +changing the Volk kernel settings in $HOME/.volk/volk_config. First, +make a backup of this file. Then edit it and change all architecture +calls (sse, sse2, etc.) to 'generic.' Now, Volk will only call the +generic versions of these functions. So we rerun the benchmark with: + + ./volk_math.py -D volk_results_math.db --all -L v3_5_2 + +Notice that the only thing changed here was the label to 'v3_5_2'. + +Next, we want to collect data for the non-Volk version of GNU +Radio. This is important because some internals to GNU Radio were made +when adding support for Volk, so it is nice to know what the +differences do to our performance. First, we set the environmental +variables to point to the v3.5.1 installation: + + export LD_LIBRARY_PATH=/opt/gr-3_5_1/lib + export LD_LIBRARY_PATH=/opt/gr-3_5_1/lib/python2.7/dist-packages + +And when we run the test, we use the same command line, but the GNU +Radio libraries and Python files used come from v3.5.1. We also change +the label to indicate the different version to store. + + ./volk_math.py -D volk_results_math.db --all -L v3_5_1 + +We now have a database populated with three tables for the three +different labels. We can plot them all together by simply running: + + ./volk_plot.py -D volk_results_math.db + +This will show the average run times for each of the three +configurations for all math functions tested. We might also be +interested to see the difference in performance from the v3.5.1 +version, so we can run: + + ./volk_plot.py -D volk_results_math.db -% v3_5_1 + +That will plot both the 'volk_aligned' and 'v3_5_2' as a percentage +improvement over v3_5_1. A positive value indicates that this version +runs faster than the v3.5.1 version. + + +---------------------------------------------------------------------- + +Another interesting test case could be to compare results on different +processors. So if you have different generation Intels, AMD, or +whatever, you can simply pass the .db file around and run the Volk +benchmark script to populate the database with different results. For +this, you would specify a label like '-L i7_2620M' that indicates the +processor type to uniquely ID the data. + diff --git a/gnuradio-core/src/examples/volk_benchmark/volk_math.py b/gnuradio-core/src/examples/volk_benchmark/volk_math.py new file mode 100755 index 000000000..1d8bf04cc --- /dev/null +++ b/gnuradio-core/src/examples/volk_benchmark/volk_math.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python + +from gnuradio import gr +import argparse +from volk_test_funcs import * + +def multiply_const_cc(N): + k = 3.3 + op = gr.multiply_const_cc(k) + tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_gr_complex, 1, 1) + return tb + +###################################################################### + +def multiply_const_ff(N): + k = 3.3 + op = gr.multiply_const_ff(k) + tb = helper(N, op, gr.sizeof_float, gr.sizeof_float, 1, 1) + return tb + +###################################################################### + +def multiply_cc(N): + op = gr.multiply_cc(1) + tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_gr_complex, 2, 1) + return tb + +###################################################################### + +def multiply_ff(N): + op = gr.multiply_ff() + tb = helper(N, op, gr.sizeof_float, gr.sizeof_float, 2, 1) + return tb + +###################################################################### + +def add_ff(N): + op = gr.add_ff() + tb = helper(N, op, gr.sizeof_float, gr.sizeof_float, 2, 1) + return tb + +###################################################################### + +def conjugate_cc(N): + op = gr.conjugate_cc() + tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_gr_complex, 1, 1) + return tb + +###################################################################### + +def multiply_conjugate_cc(N): + try: + op = gr.multiply_conjugate_cc() + tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_gr_complex, 2, 1) + return tb + + except AttributeError: + class s(gr.hier_block2): + def __init__(self): + gr.hier_block2.__init__(self, "s", + gr.io_signature(2, 2, gr.sizeof_gr_complex), + gr.io_signature(1, 1, gr.sizeof_gr_complex)) + conj = gr.conjugate_cc() + mult = gr.multiply_cc() + self.connect((self,0), (mult,0)) + self.connect((self,1), conj, (mult,1)) + self.connect(mult, self) + + op = s() + tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_gr_complex, 2, 1) + return tb + + +###################################################################### + +def run_tests(func, N, iters): + print("Running Test: {0}".format(func.__name__)) + try: + tb = func(N) + t = timeit(tb, iters) + res = format_results(func.__name__, t) + return res + except AttributeError: + print "\tCould not run test. Skipping." + return None + +def main(): + avail_tests = [multiply_const_cc, + multiply_const_ff, + multiply_cc, + multiply_ff, + add_ff, + conjugate_cc, + multiply_conjugate_cc] + + desc='Time an operation to compare with other implementations. \ + This program runs a simple GNU Radio flowgraph to test a \ + particular math function, mostly to compare the \ + Volk-optimized implementation versus a regular \ + implementation. The results are stored to an SQLite database \ + that can then be read by volk_plot.py to plot the differences.' + parser = argparse.ArgumentParser(description=desc) + parser.add_argument('-L', '--label', type=str, + required=True, default=None, + help='Label of database table [default: %(default)s]') + parser.add_argument('-D', '--database', type=str, + default="volk_results.db", + help='Database file to store data in [default: %(default)s]') + parser.add_argument('-N', '--nitems', type=float, + default=1e9, + help='Number of items per iterations [default: %(default)s]') + parser.add_argument('-I', '--iterations', type=int, + default=20, + help='Number of iterations [default: %(default)s]') + parser.add_argument('--tests', type=int, nargs='*', + choices=xrange(len(avail_tests)), + help='A list of tests to run; can be a single test or a \ + space-separated list.') + parser.add_argument('--list', action='store_true', + help='List the available tests') + parser.add_argument('--all', action='store_true', + help='Run all tests') + args = parser.parse_args() + + if(args.list): + print "Available Tests to Run:" + print "\n".join(["\t{0}: {1}".format(i,f.__name__) for i,f in enumerate(avail_tests)]) + sys.exit(0) + + N = int(args.nitems) + iters = args.iterations + label = args.label + + conn = create_connection(args.database) + new_table(conn, label) + + if args.all: + tests = xrange(len(avail_tests)) + else: + tests = args.tests + + for test in tests: + res = run_tests(avail_tests[test], N, iters) + if res is not None: + replace_results(conn, label, N, iters, res) + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-core/src/examples/volk_benchmark/volk_plot.py b/gnuradio-core/src/examples/volk_benchmark/volk_plot.py new file mode 100755 index 000000000..48f992205 --- /dev/null +++ b/gnuradio-core/src/examples/volk_benchmark/volk_plot.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python + +import sys, math +import argparse +from volk_test_funcs import * + +try: + import matplotlib + import matplotlib.pyplot as plt +except ImportError: + sys.stderr.write("Could not import Matplotlib (http://matplotlib.sourceforge.net/)\n") + sys.exit(1) + +def main(): + desc='Plot Volk performance results from a SQLite database. ' + \ + 'Run one of the volk tests first (e.g, volk_math.py)' + parser = argparse.ArgumentParser(description=desc) + parser.add_argument('-D', '--database', type=str, + default='volk_results.db', + help='Database file to read data from [default: %(default)s]') + parser.add_argument('-E', '--errorbars', + action='store_true', default=False, + help='Show error bars (1 standard dev.)') + parser.add_argument('-P', '--plot', type=str, + choices=['mean', 'min', 'max'], + default='mean', + help='Set the type of plot to produce [default: %(default)s]') + parser.add_argument('-%', '--percent', type=str, + default=None, metavar="table", + help='Show percent difference to the given type [default: %(default)s]') + args = parser.parse_args() + + # Set up global plotting properties + matplotlib.rcParams['figure.subplot.bottom'] = 0.2 + matplotlib.rcParams['figure.subplot.top'] = 0.95 + matplotlib.rcParams['figure.subplot.right'] = 0.98 + matplotlib.rcParams['ytick.labelsize'] = 16 + matplotlib.rcParams['xtick.labelsize'] = 16 + matplotlib.rcParams['legend.fontsize'] = 18 + + # Get list of tables to compare + conn = create_connection(args.database) + tables = list_tables(conn) + M = len(tables) + + # Colors to distinguish each table in the bar graph + # More than 5 tables will wrap around to the start. + colors = ['b', 'r', 'g', 'm', 'k'] + + # Set up figure for plotting + f0 = plt.figure(0, facecolor='w', figsize=(14,10)) + s0 = f0.add_subplot(1,1,1) + + # Create a register of names that exist in all tables + tmp_regs = [] + for table in tables: + # Get results from the next table + res = get_results(conn, table[0]) + + tmp_regs.append(list()) + for r in res: + try: + tmp_regs[-1].index(r['kernel']) + except ValueError: + tmp_regs[-1].append(r['kernel']) + + # Get only those names that are common in all tables + name_reg = tmp_regs[0] + for t in tmp_regs[1:]: + name_reg = list(set(name_reg) & set(t)) + name_reg.sort() + + # Pull the data out for each table into a dictionary + # we can ref the table by it's name and the data associated + # with a given kernel in name_reg by it's name. + # This ensures there is no sorting issue with the data in the + # dictionary, so the kernels are plotted against each other. + table_data = dict() + for i,table in enumerate(tables): + # Get results from the next table + res = get_results(conn, table[0]) + + data = dict() + for r in res: + data[r['kernel']] = r + + table_data[table[0]] = data + + if args.percent is not None: + for i,t in enumerate(table_data): + if args.percent == t: + norm_data = [] + for name in name_reg: + if(args.plot == 'max'): + norm_data.append(table_data[t][name]['max']) + elif(args.plot == 'min'): + norm_data.append(table_data[t][name]['min']) + elif(args.plot == 'mean'): + norm_data.append(table_data[t][name]['avg']) + + + # Plot the results + x0 = xrange(len(name_reg)) + i = 0 + for t in (table_data): + ydata = [] + stds = [] + for name in name_reg: + stds.append(math.sqrt(table_data[t][name]['var'])) + if(args.plot == 'max'): + ydata.append(table_data[t][name]['max']) + elif(args.plot == 'min'): + ydata.append(table_data[t][name]['min']) + elif(args.plot == 'mean'): + ydata.append(table_data[t][name]['avg']) + + if args.percent is not None: + ydata = [-100*(y-n)/y for y,n in zip(ydata,norm_data)] + if(args.percent != t): + # makes x values for this data set placement + # width of bars depends on number of comparisons + wdth = 0.80/(M-1) + x1 = [x + i*wdth for x in x0] + i += 1 + + s0.bar(x1, ydata, width=wdth, + color=colors[(i-1)%M], label=t, + edgecolor='k', linewidth=2) + + else: + # makes x values for this data set placement + # width of bars depends on number of comparisons + wdth = 0.80/M + x1 = [x + i*wdth for x in x0] + i += 1 + + if(args.errorbars is False): + s0.bar(x1, ydata, width=wdth, + color=colors[(i-1)%M], label=t, + edgecolor='k', linewidth=2) + else: + s0.bar(x1, ydata, width=wdth, + yerr=stds, + color=colors[i%M], label=t, + edgecolor='k', linewidth=2, + error_kw={"ecolor": 'k', "capsize":5, + "linewidth":2}) + + nitems = res[0]['nitems'] + if args.percent is None: + s0.set_ylabel("Processing time (sec) [{0:G} items]".format(nitems), + fontsize=22, fontweight='bold', + horizontalalignment='center') + else: + s0.set_ylabel("% Improvement over {0} [{1:G} items]".format( + args.percent, nitems), + fontsize=22, fontweight='bold') + + s0.legend() + s0.set_xticks(x0) + s0.set_xticklabels(name_reg) + for label in s0.xaxis.get_ticklabels(): + label.set_rotation(45) + label.set_fontsize(16) + + plt.show() + +if __name__ == "__main__": + main() diff --git a/gnuradio-core/src/examples/volk_benchmark/volk_test_funcs.py b/gnuradio-core/src/examples/volk_benchmark/volk_test_funcs.py new file mode 100644 index 000000000..0ce25fcc6 --- /dev/null +++ b/gnuradio-core/src/examples/volk_benchmark/volk_test_funcs.py @@ -0,0 +1,171 @@ +#!/usr/bin/env python + +from gnuradio import gr +import math, sys, os, time + +try: + import scipy +except ImportError: + sys.stderr.write("Unable to import Scipy (www.scipy.org)\n") + sys.exit(1) + +try: + import sqlite3 +except ImportError: + sys.stderr.write("Unable to import sqlite3: requires Python 2.5\n") + sys.exit(1) + +def execute(conn, cmd): + ''' + Executes the command cmd to the database opened in connection conn. + ''' + c = conn.cursor() + c.execute(cmd) + conn.commit() + c.close() + +def create_connection(database): + ''' + Returns a connection object to the SQLite database. + ''' + return sqlite3.connect(database) + +def new_table(conn, tablename): + ''' + Create a new table for results. + All results are in the form: [kernel | nitems | iters | avg. time | variance | max time | min time ] + Each table is meant as a different setting (e.g., volk_aligned, volk_unaligned, etc.) + ''' + cols = "kernel text, nitems int, iters int, avg real, var real, max real, min real" + cmd = "create table if not exists {0} ({1})".format( + tablename, cols) + execute(conn, cmd) + +def replace_results(conn, tablename, nitems, iters, res): + ''' + Inserts or replaces the results 'res' dictionary values into the table. + This deletes all old entries of the kernel in this table. + ''' + cmd = "DELETE FROM {0} where kernel='{1}'".format(tablename, res["kernel"]) + execute(conn, cmd) + insert_results(conn, tablename, nitems, iters, res) + +def insert_results(conn, tablename, nitems, iters, res): + ''' + Inserts the results dictionary values into the table. + ''' + cols = "kernel, nitems, iters, avg, var, max, min" + cmd = "INSERT INTO {0} ({1}) VALUES ('{2}', {3}, {4}, {5}, {6}, {7}, {8})".format( + tablename, cols, res["kernel"], nitems, iters, + res["avg"], res["var"], res["max"], res["min"]) + execute(conn, cmd) + +def list_tables(conn): + ''' + Returns a list of all tables in the database. + ''' + cmd = "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name" + c = conn.cursor() + c.execute(cmd) + t = c.fetchall() + c.close() + + return t + +def get_results(conn, tablename): + ''' + Gets all results in tablename. + ''' + cmd = "SELECT * FROM {0}".format(tablename) + c = conn.cursor() + c.execute(cmd) + fetched = c.fetchall() + c.close() + + res = list() + for f in fetched: + r = dict() + r['kernel'] = f[0] + r['nitems'] = f[1] + r['iters'] = f[2] + r['avg'] = f[3] + r['var'] = f[4] + r['min'] = f[5] + r['max'] = f[6] + res.append(r) + + return res + + +class helper(gr.top_block): + ''' + Helper function to run the tests. The parameters are: + N: number of items to process (int) + op: The GR block/hier_block to test + isizeof: the sizeof the input type + osizeof: the sizeof the output type + nsrcs: number of inputs to the op + nsnks: number of outputs of the op + + This function can only handle blocks where all inputs are the same + datatype and all outputs are the same data type + ''' + def __init__(self, N, op, + isizeof=gr.sizeof_gr_complex, + osizeof=gr.sizeof_gr_complex, + nsrcs=1, nsnks=1): + gr.top_block.__init__(self, "helper") + + self.op = op + self.srcs = [] + self.snks = [] + self.head = gr.head(isizeof, N) + + for n in xrange(nsrcs): + self.srcs.append(gr.null_source(isizeof)) + + for n in xrange(nsnks): + self.snks.append(gr.null_sink(osizeof)) + + self.connect(self.srcs[0], self.head, (self.op,0)) + + for n in xrange(1, nsrcs): + self.connect(self.srcs[n], (self.op,n)) + + for n in xrange(nsnks): + self.connect((self.op,n), self.snks[n]) + +def timeit(tb, iterations): + ''' + Given a top block, this function times it for a number of + iterations and stores the time in a list that is returned. + ''' + r = gr.enable_realtime_scheduling() + if r != gr.RT_OK: + print "Warning: failed to enable realtime scheduling" + + times = [] + for i in xrange(iterations): + start_time = time.time() + tb.run() + end_time = time.time() + tb.head.reset() + + times.append(end_time - start_time) + + return times + +def format_results(kernel, times): + ''' + Convinience function to convert the results of the timeit function + into a dictionary. + ''' + res = dict() + res["kernel"] = kernel + res["avg"] = scipy.mean(times) + res["var"] = scipy.var(times) + res["max"] = max(times) + res["min"] = min(times) + return res + + diff --git a/gnuradio-core/src/examples/volk_benchmark/volk_types.py b/gnuradio-core/src/examples/volk_benchmark/volk_types.py new file mode 100755 index 000000000..5dac23c53 --- /dev/null +++ b/gnuradio-core/src/examples/volk_benchmark/volk_types.py @@ -0,0 +1,182 @@ +#!/usr/bin/env python + +from gnuradio import gr +import argparse +from volk_test_funcs import * + +###################################################################### + +def float_to_char(N): + op = gr.float_to_char() + tb = helper(N, op, gr.sizeof_float, gr.sizeof_char, 1, 1) + return tb + +###################################################################### + +def float_to_int(N): + op = gr.float_to_int() + tb = helper(N, op, gr.sizeof_float, gr.sizeof_int, 1, 1) + return tb + +###################################################################### + +def float_to_short(N): + op = gr.float_to_short() + tb = helper(N, op, gr.sizeof_float, gr.sizeof_short, 1, 1) + return tb + +###################################################################### + +def short_to_float(N): + op = gr.short_to_float() + tb = helper(N, op, gr.sizeof_short, gr.sizeof_float, 1, 1) + return tb + +###################################################################### + +def short_to_char(N): + op = gr.short_to_char() + tb = helper(N, op, gr.sizeof_short, gr.sizeof_char, 1, 1) + return tb + +###################################################################### + +def char_to_short(N): + op = gr.char_to_short() + tb = helper(N, op, gr.sizeof_char, gr.sizeof_short, 1, 1) + return tb + +###################################################################### + +def char_to_float(N): + op = gr.char_to_float() + tb = helper(N, op, gr.sizeof_char, gr.sizeof_float, 1, 1) + return tb + +###################################################################### + +def int_to_float(N): + op = gr.int_to_float() + tb = helper(N, op, gr.sizeof_int, gr.sizeof_float, 1, 1) + return tb + +###################################################################### + +def complex_to_float(N): + op = gr.complex_to_float() + tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_float, 1, 2) + return tb + +###################################################################### + +def complex_to_real(N): + op = gr.complex_to_real() + tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_float, 1, 1) + return tb + +###################################################################### + +def complex_to_imag(N): + op = gr.complex_to_imag() + tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_float, 1, 1) + return tb + +###################################################################### + +def complex_to_mag(N): + op = gr.complex_to_mag() + tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_float, 1, 1) + return tb + +###################################################################### + +def complex_to_mag_squared(N): + op = gr.complex_to_mag_squared() + tb = helper(N, op, gr.sizeof_gr_complex, gr.sizeof_float, 1, 1) + return tb + +###################################################################### + + +def run_tests(func, N, iters): + print("Running Test: {0}".format(func.__name__)) + try: + tb = func(N) + t = timeit(tb, iters) + res = format_results(func.__name__, t) + return res + except AttributeError: + print "\tCould not run test. Skipping." + return None + +def main(): + avail_tests = [float_to_char, + float_to_int, + float_to_short, + short_to_float, + short_to_char, + char_to_short, + char_to_float, + int_to_float, + complex_to_float, + complex_to_real, + complex_to_imag, + complex_to_mag, + complex_to_mag_squared] + + desc='Time an operation to compare with other implementations. \ + This program runs a simple GNU Radio flowgraph to test a \ + particular math function, mostly to compare the \ + Volk-optimized implementation versus a regular \ + implementation. The results are stored to an SQLite database \ + that can then be read by volk_plot.py to plot the differences.' + parser = argparse.ArgumentParser(description=desc) + parser.add_argument('-L', '--label', type=str, + required=True, default=None, + help='Label of database table [default: %(default)s]') + parser.add_argument('-D', '--database', type=str, + default="volk_results.db", + help='Database file to store data in [default: %(default)s]') + parser.add_argument('-N', '--nitems', type=float, + default=1e9, + help='Number of items per iterations [default: %(default)s]') + parser.add_argument('-I', '--iterations', type=int, + default=20, + help='Number of iterations [default: %(default)s]') + parser.add_argument('--tests', type=int, nargs='*', + choices=xrange(len(avail_tests)), + help='A list of tests to run; can be a single test or a \ + space-separated list.') + parser.add_argument('--list', action='store_true', + help='List the available tests') + parser.add_argument('--all', action='store_true', + help='Run all tests') + args = parser.parse_args() + + if(args.list): + print "Available Tests to Run:" + print "\n".join(["\t{0}: {1}".format(i,f.__name__) for i,f in enumerate(avail_tests)]) + sys.exit(0) + + N = int(args.nitems) + iters = args.iterations + label = args.label + + conn = create_connection(args.database) + new_table(conn, label) + + if args.all: + tests = xrange(len(avail_tests)) + else: + tests = args.tests + + for test in tests: + res = run_tests(avail_tests[test], N, iters) + if res is not None: + replace_results(conn, label, N, iters, res) + +if __name__ == "__main__": + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-core/src/gen_interpolator_taps/Makefile.am.obsolete b/gnuradio-core/src/gen_interpolator_taps/Makefile.am.obsolete new file mode 100644 index 000000000..cd0edaf5c --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/Makefile.am.obsolete @@ -0,0 +1,39 @@ +# +# Copyright 2002 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 $(top_srcdir)/Makefile.common + +EXTRA_DIST += \ + praxis.txt \ + simpson.h \ + objective_fct.c \ + gen_interpolator_taps.c \ + simpson.c \ + praxis.f + +# if ENABLE_FORTRAN +# noinst_PROGRAMS = gen_interpolator_taps +# noinst_HEADERS = simpson.h +# +# gen_interpolator_taps_SOURCES = gen_interpolator_taps.c objective_fct.c simpson.c praxis.f +# gen_interpolator_taps_LDADD = $(FLIBS) -lm +# +# endif diff --git a/gnuradio-core/src/gen_interpolator_taps/README b/gnuradio-core/src/gen_interpolator_taps/README new file mode 100644 index 000000000..8fe3e2ba3 --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/README @@ -0,0 +1,47 @@ +# +# Copyright 2002 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. +# + + +This file contains the source for gen_interpolator_taps, a program +which generates optimal interpolator taps for a fractional +interpolator. + +The ideal interpolator requires an infinite tap FIR filter to +realize. We design a separate 8 tap filter for each value of mu, +the fractional delay, that we are interested in. The taps are +selected such that the mean squared error between the ideal frequency +response and the approximation is mininimized over all frequencies of +interest. In this implementation we define ``frequencies of +interest'' as those from -B to +B, where B = 1/(4*Ts), where Ts is the +sampling period. + +For a detailed look at what this is all about, please see Chapter 9 of +"Digital Communication Receivers: Synchronization, Channel Estimation +and Signal Processing" by Meyr, Moeneclaey and Fechtel, ISBN 0-471-50275-8 + +NOTE, if you're running gen_interpolator_taps and it seg faults in +RANDOM, you're probably using g77-2.96. The fix is to use g77 3.0 or later + + cd <top_of_build_tree> + rm config.cache + export F77=g77-3.0.4 + ./configure + make diff --git a/gnuradio-core/src/gen_interpolator_taps/gen_interpolator_taps.c b/gnuradio-core/src/gen_interpolator_taps/gen_interpolator_taps.c new file mode 100644 index 000000000..2f359102c --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/gen_interpolator_taps.c @@ -0,0 +1,186 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 <stdio.h> +#include <unistd.h> +#include <stdlib.h> + +#define NSTEPS 10 // how many steps of mu are in the generated table +#define MAX_NSTEPS 256 +#define NTAPS 8 // # of taps in the interpolator +#define MAX_NTAPS 128 + +extern void initpt (double x[], int ntaps); +extern double objective (double x[], int *ntaps); +extern double global_mu; +extern double global_B; + +// fortran +extern double prax2_ (double (fct)(double x[], int *ntaps), + double initv[], int *ntaps, double result[]); + +static void +usage (char *name) +{ + fprintf (stderr, "usage: %s [-v] [-n <nsteps>] [-t <ntaps>] [-B <bw>]\n", name); + exit (1); +} + +static void +printline (double x[], int ntaps, int imu, int nsteps) +{ + int i; + + printf (" { "); + for (i = 0; i < ntaps; i++){ + printf ("%12.5e", x[i]); + if (i != ntaps - 1) + printf (", "); + else + printf (" }, // %3d/%d\n", imu, nsteps); + } +} + +int +main (int argc, char **argv) +{ + double xx[MAX_NSTEPS+1][MAX_NTAPS]; + int ntaps = NTAPS; + int nsteps = NSTEPS; + int i, j; + double result; + double step_size; + int c; + int verbose = 0; + + global_B = 0.25; + + while ((c = getopt (argc, argv, "n:t:B:v")) != EOF){ + switch (c){ + case 'n': + nsteps = strtol (optarg, 0, 0); + break; + + case 't': + ntaps = strtol (optarg, 0, 0); + break; + + case 'B': + global_B = strtod (optarg, 0); + break; + + case 'v': + verbose = 1; + break; + + default: + usage (argv[0]); + break; + } + } + + if ((nsteps & 1) != 0){ + fprintf (stderr, "%s: nsteps must be even\n", argv[0]); + exit (1); + } + + if (nsteps > MAX_NSTEPS){ + fprintf (stderr, "%s: nsteps must be < %d\n", argv[0], MAX_NSTEPS); + exit (1); + } + + if ((ntaps & 1) != 0){ + fprintf (stderr, "%s: ntaps must be even\n", argv[0]); + exit (1); + } + + if (nsteps > MAX_NTAPS){ + fprintf (stderr, "%s: ntaps must be < %d\n", argv[0], MAX_NTAPS); + exit (1); + } + + if (global_B < 0 || global_B > 0.5){ + fprintf (stderr, "%s: bandwidth must be in the range (0, 0.5)\n", argv[0]); + exit (1); + } + + step_size = 1.0/nsteps; + + // the optimizer chokes on the two easy cases (0/N and N/N). We do them by hand... + + for (i = 0; i < ntaps; i++) + xx[0][i] = 0.0; + xx[0][ntaps/2] = 1.0; + + + // compute optimal values for mu <= 0.5 + + for (j = 1; j <= nsteps/2; j++){ + + global_mu = j * step_size; // this determines the MU for which we're computing the taps + + // initialize X to a reasonable starting value + + initpt (&xx[j][0], ntaps); + + // find the value of X that minimizes the value of OBJECTIVE + + result = prax2_ (objective, &xx[j][0], &ntaps, &xx[j][0]); + + if (verbose){ + fprintf (stderr, "Mu: %10.8f\t", global_mu); + fprintf (stderr, "Objective: %g\n", result); + } + } + + // now compute remaining values via symmetry + + for (j = 0; j < nsteps/2; j++){ + for (i = 0; i < ntaps; i++){ + xx[nsteps - j][i] = xx[j][ntaps-i-1]; + } + } + + // now print out the table + + printf ("\ +/*\n\ + * This file was machine generated by gen_interpolator_taps.\n\ + * DO NOT EDIT BY HAND.\n\ + */\n\n"); + + + printf ("static const int NTAPS = %4d;\n", ntaps); + printf ("static const int NSTEPS = %4d;\n", nsteps); + printf ("static const double BANDWIDTH = %g;\n\n", global_B); + + printf ("static const float taps[NSTEPS+1][NTAPS] = {\n"); + printf (" // -4 -3 -2 -1 0 1 2 3 mu\n"); + + + for (i = 0; i <= nsteps; i++) + printline (xx[i], ntaps, i, nsteps); + + printf ("};\n\n"); + + return 0; +} diff --git a/gnuradio-core/src/gen_interpolator_taps/objective_fct.c b/gnuradio-core/src/gen_interpolator_taps/objective_fct.c new file mode 100644 index 000000000..129486d63 --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/objective_fct.c @@ -0,0 +1,124 @@ +/* -*- c -*- */ +/* + * Copyright 2002 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. + */ + +/* + * generate MMSE FIR interpolation table values + */ + +#include <math.h> +#include <assert.h> +#include "simpson.h" + +#define MU 0.5 /* the MU for which we're computing coeffs */ + +#define Ts (1.0) /* sampling period */ +#define B (1.0/(4*Ts)) /* one-sided signal bandwidth */ +//#define B (1.0/(8./3*Ts)) /* one-sided signal bandwidth */ + +static unsigned global_n; +static double *global_h; +double global_mu = MU; +double global_B = B; + +/* + * This function computes the difference squared between the ideal + * interpolator frequency response at frequency OMEGA and the + * approximation defined by the FIR coefficients in global_h[] + * + * See eqn (9-7), "Digital Communication Receivers", Meyr, Moeneclaey + * and Fechtel, Wiley, 1998. + */ + +static double +integrand (double omega) +{ + double real_ideal; + double real_approx; + double real_diff; + double imag_ideal; + double imag_approx; + double imag_diff; + + int i, n; + int I1; + double *h; + + real_ideal = cos (omega * Ts * global_mu); + imag_ideal = sin (omega * Ts * global_mu); + + n = global_n; + h = global_h; + I1 = -(n / 2); + + real_approx = 0; + imag_approx = 0; + + for (i = 0; i < n; i++){ + real_approx += h[i] * cos (-omega * Ts * (i + I1)); + imag_approx += h[i] * sin (-omega * Ts * (i + I1)); + } + + real_diff = real_ideal - real_approx; + imag_diff = imag_ideal - imag_approx; + + return real_diff * real_diff + imag_diff * imag_diff; +} + +/* + * Integrate the difference squared over all frequencies of interest. + */ +double +c_fcn (double *x, int n) +{ + assert ((n & 1) == 0); /* assert n is even */ + global_n = n; + global_h = x; + return qsimp (integrand, -2 * M_PI * global_B, 2 * M_PI * global_B); +} + +/* this is the interface expected by the calling fortran code */ + +double +objective (double x[], int *ndim) +{ + return c_fcn (x, *ndim); +} + +static double +si (double x) +{ + if (fabs (x) < 1e-9) + return 1.0; + + return sin(x) / x; +} + +/* + * starting guess for optimization + */ +void initpt (double x[], int ndim) +{ + int i; + for (i = 0; i < ndim; i++){ + x[i] = si (M_PI * ((double) (i - ndim/2) + global_mu)); + } +} diff --git a/gnuradio-core/src/gen_interpolator_taps/praxis.f b/gnuradio-core/src/gen_interpolator_taps/praxis.f new file mode 100644 index 000000000..9f3e03c97 --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/praxis.f @@ -0,0 +1,1705 @@ +C +C Copyright 2002 Free Software Foundation, Inc. +C +C This file is part of GNU Radio +C +C GNU Radio is free software; you can redistribute it and/or modify +C it under the terms of the GNU General Public License as published by +C the Free Software Foundation; either version 3, or (at your option) +C any later version. +C +C GNU Radio is distributed in the hope that it will be useful, +C but WITHOUT ANY WARRANTY; without even the implied warranty of +C MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +C GNU General Public License for more details. +C +C You should have received a copy of the GNU General Public License +C along with GNU Radio; see the file COPYING. If not, write to +C the Free Software Foundation, Inc., 51 Franklin Street, +C Boston, MA 02110-1301, USA. +C + DOUBLE PRECISION FUNCTION PRAX2(F,INITV,NDIM,OUT) + DOUBLE PRECISION INITV(128),OUT(128), F + INTEGER NDIM + EXTERNAL F +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + +C + N=NDIM + do 10 I=1,N + 10 X(I) = INITV(I) + +C + call praset + +C -1 produces no diagnostic output + jprint = -1 + nfmax = 3000 +C tighter tolerance + T=1.0D-6 +C + call praxis(f) +C + do 30 I=1,N + 30 OUT(I) = X(I) +C + prax2 = fx + return + end + + + SUBROUTINE PRASET +C +C PRASET 1.0 JUNE 1995 +C +C SET INITIAL VALUES FOR SOME QUANTITIES USED IN SUBROUTINE PRAXIS. +C THE USER CAN RESET THESE, IF DESIRED, +C AFTER CALLING PRASET AND BEFORE CALLING PRAXIS. +C +C J. P. CHANDLER, COMPUTER SCIENCE DEPARTMENT, +C OKLAHOMA STATE UNIVERSITY +C +C ON MANY MACHINES, SUBROUTINE PRAXIS WILL CAUSE UNDERFLOW AND/OR +C DIVIDE CHECK WHEN COMPUTING EPSMCH**4 AND EPSMCH**(-4). +C IN THAT CASE, SET EPSMCH=1.0D-9 (OR POSSIBLY EPSMCH=1.0D-8) +C AFTER CALLING SUBROUTINE PRASET. +C + INTEGER N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + INTEGER J +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD + DOUBLE PRECISION A,B,XMID,XPLUS,RZERO,UNITR,RTWO +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH +C + RZERO=0.0D0 + UNITR=1.0D0 + RTWO=2.0D0 +C +C NMAX IS THE DIMENSION OF THE ARRAYS V(*,*), X(*), D(*), +C Q0(*), AND Q1(*). +C + NMAX=128 +C +C NFMAX IS THE MAXIMUM NUMBER OF FUNCTION EVALUATIONS PERMITTED. +C + NFMAX=100000 +C +C LP IS THE LOGICAL UNIT NUMBER FOR PRINTED OUTPUT. +C + LP=6 +C +C T IS A CONVERGENCE TOLERANCE USED IN SUBROUTINE PRAXIS. +C + T=1.0D-5 +C +C JPRINT CONTROLS PRINTED OUTPUT IN PRAXIS. +C + JPRINT=4 +C +C H IS AN ESTIMATE OF THE DISTANCE FROM THE INITIAL POINT +C TO THE SOLUTION. +C + H=1.0D0 +C +C USE BISECTION TO COMPUTE THE VALUE OF EPSMCH, "MACHINE EPSILON". +C EPSMCH IS THE SMALLEST FLOATING POINT (REAL OR DOUBLE PRECISION) +C NUMBER WHICH, WHEN ADDED TO ONE, GIVES A RESULT GREATER THAN ONE. +C + A=RZERO + B=UNITR + 10 XMID=A+(B-A)/RTWO + IF(XMID.LE.A .OR. XMID.GE.B) GO TO 20 + XPLUS=UNITR+XMID + IF(XPLUS.GT.UNITR) THEN + B=XMID + ELSE + A=XMID + ENDIF + GO TO 10 +C + 20 EPSMCH=B +C + DO 30 J=1,NMAX + X(J)=RZERO + 30 CONTINUE +C +C JRANCH = 1 TO USE BRENT'S RANDOM, +C JRANCH = 2 TO USE FUNCTION DRANDM. +C + JRANCH=1 +C + CALL RANINI(4.0D0) +C +C DSEED IS AN INITIAL SEED FOR DRANDM, +C A SUBROUTINE THAT GENERATES PSEUDORANDOM NUMBERS +C UNIFORMLY DISTRIBUTED ON (0,1). +C + DSEED=1234567.0D0 +C +C SCBD IS AN UPPER BOUND ON THE SCALE FACTORS IN PRAXIS. +C IF THE AXES MAY BE BADLY SCALED (WHICH IS TO BE AVOIDED IF +C POSSIBLE) THEN SET SCBD = 10, OTHERWISE 1. +C + SCBD=1.0D0 +C +C ILLCIN IS THE INITIAL VALUE OF ILLC, +C THE FLAG THAT SIGNALS AN ILL-CONDITIONED PROBLEM. +C IF THE PROBLEM IS KNOWN TO BE ILL-CONDITIONED SET ILLCIN=1, +C OTHERWISE 0. +C + ILLCIN=0 +C +C KTM IS A CONVERGENCE SWITCH USED IN PRAXIS. +C KTM+1 IS THE NUMBER OF ITERATIONS WITHOUT IMPROVEMENT +C BEFORE THE ALGORITHM TERMINATES. +C KTM=4 IS VERY CAUTIOUS. +C USUALLY KTM=1 IS SATISFACTORY. +C + KTM=1 +C + RETURN +C +C END PRASET +C + END + SUBROUTINE PRAXIS(F) +C +C PRAXIS 2.0 JUNE 1995 +C +C THE PRAXIS PACKAGE MINIMIZES THE FUNCTION F(X,N) OF N +C VARIABLES X(1),...,X(N), USING THE PRINCIPAL AXIS METHOD. +C F MUST BE A SMOOTH (CONTINUOUSLY DIFFERENTIABLE) FUNCTION. +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973 (ISBN 0-13-022335-2), +C PAGES 156-167 +C +C TRANSLATED FROM ALGOL W TO A.N.S.I. 1966 STANDARD BASIC FORTRAN +C BY ROSALEE TAYLOR AND SUE PINSKI, COMPUTER SCIENCE DEPARTMENT, +C OKLAHOMA STATE UNIVERSITY (DECEMBER 1973). +C +C UPDATED TO A.N.S.I. STANDARD FORTRAN 77 BY J. P. CHANDLER +C COMPUTER SCIENCE DEPARTMENT, OKLAHOMA STATE UNIVERSITY +C +C +C SUBROUTINE PRAXIS CALLS SUBPROGRAMS +C F, MINX, RANDOM (OR DRANDM), QUAD, MINFIT, SORT. +C +C SUBROUTINE QUAD CALLS MINX. +C +C SUBROUTINE MINX CALLS FLIN. +C +C SUBROUTINE FLIN CALLS F. +C +C +C INPUT QUANTITIES (SET IN THE CALLING PROGRAM)... +C +C F FUNCTION F(X,N) TO BE MINIMIZED +C +C X(*) INITIAL GUESS OF MINIMUM +C +C N DIMENSION OF X (NOTE... N MUST BE .GE. 2) +C +C H MAXIMUM STEP SIZE +C +C T TOLERANCE +C +C EPSMCH MACHINE PRECISION +C +C JPRINT PRINT SWITCH +C +C +C OUTPUT QUANTITIES... +C +C X(*) ESTIMATED POINT OF MINIMUM +C +C FX VALUE OF F AT X +C +C NL NUMBER OF LINEAR SEARCHES +C +C NF NUMBER OF FUNCTION EVALUATIONS +C +C V(*,*) EIGENVECTORS OF A +C NEW DIRECTIONS +C +C D(*) EIGENVALUES OF A +C NEW D +C +C Z(*) SCALE FACTORS +C +C +C ON ENTRY X(*) HOLDS A GUESS. ON RETURN IT HOLDS THE ESTIMATED +C POINT OF MINIMUM, WITH (HOPEFULLY) +C ABS(ERROR) LESS THAN SQRT(EPSMCH)*ABS(X) + T, WHERE +C EPSMCH IS THE MACHINE PRECISION, THE SMALLEST NUMBER SUCH THAT +C (1 + EPSMCH) IS GREATER THAN 1. +C +C T IS A TOLERANCE. +C +C H IS THE MAXIMUM STEP SIZE, SET TO ABOUT THE MAXIMUM EXPECTED +C DISTANCE FROM THE GUESS TO THE MINIMUM. IF H IS SET TOO +C SMALL OR TOO LARGE THEN THE INITIAL RATE OF CONVERGENCE WILL +C BE SLOW. +C +C THE USER SHOULD OBSERVE THE COMMENT ON HEURISTIC NUMBERS +C AT THE BEGINNING OF THE SUBROUTINE. +C +C JPRINT CONTROLS THE PRINTING OF INTERMEDIATE RESULTS. +C IT USES SUBROUTINES FLIN, MINX, QUAD, SORT, AND MINFIT. +C IF JPRINT = 1, F IS PRINTED AFTER EVERY N+1 OR N+2 LINEAR +C MINIMIZATIONS, AND FINAL X IS PRINTED, BUT INTERMEDIATE +C X ONLY IF N IS LESS THAN OR EQUAL TO 4. +C IF JPRINT = 2, EIGENVALUES OF A AND SCALE FACTORS ARE ALSO PRINTED. +C IF JPRINT = 3, F AND X ARE PRINTED AFTER EVERY FEW LINEAR +C MINIMIZATIONS. +C IF JPRINT = 4, EIGENVECTORS ARE ALSO PRINTED. +C IF JPRINT = 5, ADDITIONAL DEBUGGING INFORMATION IS ALSO PRINTED. +C +C RANDOM RETURNS A RANDOM NUMBER UNIFORMLY DISTRIBUTED IN (0, 1). +C +C THIS SUBROUTINE IS MACHINE-INDEPENDENT, APART FROM THE +C SPECIFICATION OF EPSMCH. WE ASSUME THAT EPSMCH**(-4) DOES NOT +C OVERFLOW (IF IT DOES THEN EPSMCH MUST BE INCREASED), AND THAT ON +C FLOATING-POINT UNDERFLOW THE RESULT IS SET TO ZERO. +C + INTEGER N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + INTEGER ILLC,I,IK,IM,IMU,J,K,KL,KM1,KT,K2 +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD + DOUBLE PRECISION F, Y,Z,E, DABS,DSQRT,ZABS,ZSQRT,DRANDM, + * HUNDRD,HUNDTH,ONE,PT9,RHALF,TEN,TENTH,TWO,ZERO, + * DF,DLDFAC,DN,F1,XF,XL,T2,RANVAL,ARG, + * VLARGE,VSMALL,XLARGE,XLDS,FXVALU,F1VALU,S,SF,SL +C + EXTERNAL F +C + DIMENSION Y(128),Z(128),E(128) +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH +C + ZABS(ARG)=DABS(ARG) + ZSQRT(ARG)=DSQRT(ARG) +C +C INITIALIZATION... +C + RHALF=0.5D0 + ONE=1.0D0 + TENTH=0.1D0 + HUNDTH=0.01D0 + HUNDRD=100.0D0 + ZERO=0.0D0 + PT9=0.9D0 + TEN=10.0D0 + TWO=2.0D0 +C +C MACHINE DEPENDENT NUMBERS... +C +C ON MANY COMPUTERS, VSMALL WILL UNDERFLOW, +C AND COMPUTING XLARGE MAY CAUSE A DIVISION BY ZERO. +C IN THAT CASE, EPSMCH SHOULD BE SET EQUAL TO 1.0D-9 +C (OR POSSIBLY 1.0D-8) BEFORE CALLING PRAXIS. +C + SMALL=EPSMCH*EPSMCH + VSMALL=SMALL*SMALL + XLARGE=ONE/SMALL + VLARGE=ONE/VSMALL + XM2=ZSQRT(EPSMCH) + XM4=ZSQRT(XM2) +C +C HEURISTIC NUMBERS... +C +C IF THE AXES MAY BE BADLY SCALED (WHICH IS TO BE AVOIDED IF +C POSSIBLE) THEN SET SCBD = 10, OTHERWISE 1. +C +C IF THE PROBLEM IS KNOWN TO BE ILL-CONDITIONED SET ILLC = 1, +C OTHERWISE 0. +C +C KTM+1 IS THE NUMBER OF ITERATIONS WITHOUT IMPROVEMENT +C BEFORE THE ALGORITHM TERMINATES. +C KTM=4 IS VERY CAUTIOUS. +C USUALLY KTM=1 IS SATISFACTORY. +C +C BRENT RECOMMENDED THE FOLLOWING VALUES FOR MOST PROBLEMS... +C +C SCBD=1.0 +C ILLC=0 +C KTM=1 +C +C SCBD, ILLCIN, AND KTM ARE NOW IN COMMON. +C THEY ARE INITIALIZED IN SUBROUTINE PRASET, +C AND CAN BE RESET BY THE USER AFTER CALLING PRASET. +C + ILLC=ILLCIN +C + IF(ILLC.EQ.1) THEN + DLDFAC=TENTH + ELSE + DLDFAC=HUNDTH + ENDIF +C + KT=0 + NL=0 + NF=1 + FX=F(X,N) + QF1=FX + T=SMALL+ZABS(T) + T2=T + DMIN=SMALL + IF(H.LT.HUNDRD*T) H=HUNDRD*T + XLDT=H +C + DO 20 I=1,N + DO 10 J=1,N + V(I,J)=ZERO + 10 CONTINUE + V(I,I)=ONE + 20 CONTINUE +C + QD0=ZERO + D(1)=ZERO +C +C Q0(*) AND Q1(*) ARE PREVIOUS X(*) POINTS, +C INITIALIZED IN PRAXIS, USED IN FLIN, +C AND CHANGED IN QUAD. +C + DO 30 I=1,N + Q1(I)=X(I) +C +C Q0(*) WAS NOT INITIALIZED IN BRENT'S ALGOL PROCEDURE. +C + Q0(I)=X(I) + 30 CONTINUE +C + IF(JPRINT.GT.0) THEN + WRITE(LP,40)NL,NF,FX + 40 FORMAT(/' NL =',I10,5X,'NF =',I10/5X,'FX =',1PG15.7) +C + IF(N.LE.4 .OR. JPRINT.GT.2) THEN + WRITE(LP,50)(X(I),I=1,N) + 50 FORMAT(/8X,'X'/(1X,1PG15.7,4G15.7)) + ENDIF + ENDIF +C +C MAIN LOOP... +C LABEL L0... +C + 60 SF=D(1) + S=ZERO + D(1)=ZERO +C +C MINIMIZE ALONG THE FIRST DIRECTION. +C + IF(JPRINT.GE.5) WRITE(LP,70)D(1),S,FX + 70 FORMAT(/' CALL NO. 1 TO MINX.'/ + * 5X,'D(1) =',1PG15.7,5X,'S =',G15.7,5X,'FX =',G15.7) +C + FXVALU=FX + CALL MINX(1,2,D(1),S,FXVALU,0,F) +C + IF(S.LE.ZERO) THEN + DO 80 I=1,N + V(I,1)=-V(I,1) + 80 CONTINUE + ENDIF +C + IF(SF.LE.PT9*D(1) .OR. PT9*SF.GE.D(1)) THEN +C + IF(N.GE.2) THEN + DO 90 I=2,N + D(I)=ZERO + 90 CONTINUE + ENDIF +C + ENDIF +C + IF(N.LT.2) GO TO 320 + DO 310 K=2,N +C + DO 100 I=1,N + Y(I)=X(I) + 100 CONTINUE +C + SF=FX + IF(KT.GT.0) ILLC=1 +C +C LABEL L1... +C + 110 KL=K + DF=ZERO +C + IF(ILLC.EQ.1) THEN +C +C TAKE A RANDOM STEP TO GET OUT OF A RESOLUTION VALLEY. +C +C PRAXIS ASSUMES THAT RANDOM (OR DRANDM) RETURNS +C A PSEUDORANDOM NUMBER UNIFORMLY DISTRIBUTED IN (0,1), +C AND THAT ANY INITIALIZATION OF THE RANDOM NUMBER GENERATOR +C HAS ALREADY BEEN DONE. +C + DO 130 I=1,N +C + IF(JRANCH.EQ.1) THEN + CALL RANDOM(RANVAL) + ELSE + RANVAL=DRANDM(DSEED) + ENDIF +C + S=(TENTH*XLDT+T2*TEN**KT)*(RANVAL-RHALF) + Z(I)=S +C + DO 120 J=1,N + X(J)=X(J)+S*V(J,I) + 120 CONTINUE + 130 CONTINUE +C + FX=F(X,N) + NF=NF+1 +C + IF(JPRINT.GE.1) WRITE(LP,140)NF,SF,FX + 140 FORMAT(/' ***** RANDOM STEP IN PRAXIS. NF =',I11/ + * 5X,'SF =',1PG15.7,5X,'FX =',G15.7) + ENDIF +C + IF(K.GT.N) GO TO 170 + DO 160 K2=K,N + SL=FX + S=ZERO +C +C MINIMIZE ALONG NON-CONJUGATE DIRECTIONS. +C + IF(JPRINT.GE.5) WRITE(LP,150)K2,D(K2),S,FX + 150 FORMAT(/' CALL NO. 2 TO MINX.'/ + * 5X,'K2 =',I4,5X,'D(K2) =',1PG15.7,5X, + * 'S =',G15.7/5X,'FX =',G15.7) +C + FXVALU=FX + CALL MINX(K2,2,D(K2),S,FXVALU,0,F) +C + IF(ILLC.EQ.1) THEN + S=D(K2)*(S+Z(K2))**2 + ELSE + S=SL-FX + ENDIF +C + IF(DF.LT.S) THEN + DF=S + KL=K2 + ENDIF + 160 CONTINUE +C + 170 IF(ILLC.EQ.0 .AND. DF.LT.ZABS(HUNDRD*EPSMCH*FX)) THEN +C +C NO SUCCESS WITH ILLC=0, SO TRY ONCE WITH ILLC=1 . +C + ILLC=1 +C +C GO TO L1. +C + GO TO 110 + ENDIF +C + IF(K.EQ.2 .AND. JPRINT.GT.1) THEN + WRITE(LP,180)(D(I),I=1,N) + 180 FORMAT(/' NEW D'/(1X,1PG15.7,4G15.7)) + ENDIF +C + KM1=K-1 + IF(KM1.LT.1) GO TO 210 + DO 200 K2=1,KM1 +C +C MINIMIZE ALONG CONJUGATE DIRECTIONS. +C + IF(JPRINT.GE.5) WRITE(LP,190)K2,D(K2),S,FX + 190 FORMAT(/' CALL NO. 3 TO MINX.'/ + * 5X,'K2 =',I4,5X,'D(K2) =',1PG15.7,5X, + * 'S =',G15.7/5X,'FX =',G15.7) +C + S=ZERO + FXVALU=FX + CALL MINX(K2,2,D(K2),S,FXVALU,0,F) + 200 CONTINUE +C + 210 F1=FX + FX=SF +C + XLDS=ZERO + DO 220 I=1,N + SL=X(I) + X(I)=Y(I) + SL=SL-Y(I) + Y(I)=SL + XLDS=XLDS+SL*SL + 220 CONTINUE +C + XLDS=ZSQRT(XLDS) + IF(XLDS.GT.SMALL) THEN +C +C THROW AWAY THE DIRECTION KL AND MINIMIZE ALONG +C THE NEW CONJUGATE DIRECTION. +C + IK=KL-1 + IF(K.GT.IK) GO TO 250 + DO 240 IM=K,IK + I=IK-IM+K +C + DO 230 J=1,N + V(J,I+1)=V(J,I) + 230 CONTINUE +C + D(I+1)=D(I) + 240 CONTINUE +C + 250 D(K)=ZERO +C + DO 260 I=1,N + V(I,K)=Y(I)/XLDS + 260 CONTINUE +C + IF(JPRINT.GE.5) WRITE(LP,270)K,D(K),XLDS,F1 + 270 FORMAT(/' CALL NO. 4 TO MINX.'/ + * 5X,'K =',I4,5X,'D(K) =',1PG15.7,5X, + * 'XLDS =',G15.7/5X,'F1 =',G15.7) +C + F1VALU=F1 + CALL MINX(K,4,D(K),XLDS,F1VALU,1,F) +C + IF(XLDS.LE.ZERO) THEN + XLDS=-XLDS +C + DO 280 I=1,N + V(I,K)=-V(I,K) + 280 CONTINUE + ENDIF + ENDIF +C + XLDT=DLDFAC*XLDT + IF(XLDT.LT.XLDS) XLDT=XLDS +C + IF(JPRINT.GT.0) THEN + WRITE(LP,40)NL,NF,FX + IF(N.LE.4 .OR. JPRINT.GT.2) THEN + WRITE(LP,50)(X(I),I=1,N) + ENDIF + ENDIF +C + T2=ZERO + DO 290 I=1,N + T2=T2+X(I)**2 + 290 CONTINUE + T2=XM2*ZSQRT(T2)+T +C +C SEE IF THE STEP LENGTH EXCEEDS HALF THE TOLERANCE. +C + IF(XLDT.GT.RHALF*T2) THEN + KT=0 + ELSE + KT=KT+1 + ENDIF +C +C IF(...) GO TO L2 +C + IF(KT.GT.KTM) GO TO 550 +C + IF(NF.GE.NFMAX) THEN + WRITE(LP,300)NFMAX + 300 FORMAT(/' IN PRAXIS, NF REACHED THE LIMIT NFMAX =',I11/ + * 5X,'THIS IS AN ABNORMAL TERMINATION.'/ + * 5X,'THE FUNCTION HAS NOT BEEN MINIMIZED AND', + * ' THE RESULTING X(*) VECTOR SHOULD NOT BE USED.') + GO TO 550 + ENDIF +C + 310 CONTINUE +C +C TRY QUADRATIC EXTRAPOLATION IN CASE WE ARE STUCK IN A CURVED VALLEY. +C + 320 CALL QUAD(F) +C + DN=ZERO + DO 330 I=1,N + D(I)=ONE/ZSQRT(D(I)) + IF(DN.LT.D(I)) DN=D(I) + 330 CONTINUE +C + IF(JPRINT.GT.3) THEN +C + WRITE(LP,340) + 340 FORMAT(/' NEW DIRECTIONS') +C + DO 360 I=1,N + WRITE(LP,350)I,(V(I,J),J=1,N) + 350 FORMAT(1X,I5,4X,1PG15.7,4G15.7/(10X,5G15.7)) + 360 CONTINUE + ENDIF +C + DO 380 J=1,N +C + S=D(J)/DN + DO 370 I=1,N + V(I,J)=S*V(I,J) + 370 CONTINUE + 380 CONTINUE +C + IF(SCBD.GT.ONE) THEN +C +C SCALE THE AXES TO TRY TO REDUCE THE CONDITION NUMBER. +C + S=VLARGE + DO 400 I=1,N +C + SL=ZERO + DO 390 J=1,N + SL=SL+V(I,J)**2 + 390 CONTINUE +C + Z(I)=ZSQRT(SL) + IF(Z(I).LT.XM4) Z(I)=XM4 + IF(S.GT.Z(I)) S=Z(I) + 400 CONTINUE +C + DO 410 I=1,N + SL=S/Z(I) + Z(I)=ONE/SL +C + IF(Z(I).GT.SCBD) THEN + SL=ONE/SCBD + Z(I)=SCBD + ENDIF +C +C IT APPEARS THAT THERE ARE TWO MISSING END; STATEMENTS +C AT THIS POINT IN BRENT'S LISTING. +C + 410 CONTINUE + ENDIF +C +C TRANSPOSE V FOR MINFIT. +C + IF(N.LT.2) GO TO 440 + DO 430 I=2,N +C + IMU=I-1 + DO 420 J=1,IMU + S=V(I,J) + V(I,J)=V(J,I) + V(J,I)=S + 420 CONTINUE + 430 CONTINUE +C +C FIND THE SINGULAR VALUE DECOMPOSITION OF V. +C THIS GIVES THE EIGENVALUES AND PRINCIPAL AXES +C OF THE APPROXIMATING QUADRATIC FORM +C WITHOUT SQUARING THE CONDITION NUMBER. +C + 440 CALL MINFIT(N,EPSMCH,VSMALL,V,D,E,NMAX,LP) +C + IF(SCBD.GT.ONE) THEN +C +C UNSCALING... +C + DO 460 I=1,N +C + S=Z(I) + DO 450 J=1,N + V(I,J)=S*V(I,J) + 450 CONTINUE + 460 CONTINUE +C + DO 490 I=1,N +C + S=ZERO + DO 470 J=1,N + S=S+V(J,I)**2 + 470 CONTINUE + S=ZSQRT(S) +C + D(I)=S*D(I) +C + S=ONE/S + DO 480 J=1,N + V(J,I)=S*V(J,I) + 480 CONTINUE + 490 CONTINUE + ENDIF +C + DO 500 I=1,N +C + IF(DN*D(I).GT.XLARGE) THEN + D(I)=VSMALL + ELSE IF(DN*D(I).LT.SMALL) THEN + D(I)=VLARGE + ELSE + D(I)=ONE/(DN*D(I))**2 + ENDIF + 500 CONTINUE +C +C SORT THE NEW EIGENVALUES AND EIGENVECTORS. +C + CALL SORT +C + DMIN=D(N) + IF(DMIN.LT.SMALL) DMIN=SMALL +C + IF(XM2*D(1).GT.DMIN) THEN + ILLC=1 + ELSE + ILLC=0 + ENDIF +C + IF(JPRINT.GT.1 .AND. SCBD.GT.ONE) THEN + WRITE(LP,510)(Z(I),I=1,N) + 510 FORMAT(/' SCALE FACTORS'/(1X,1PG15.7,4G15.7)) + ENDIF +C + IF(JPRINT.GT.1) THEN + WRITE(LP,520)(D(I),I=1,N) + 520 FORMAT(/' EIGENVALUES OF A'/(1X,1PG15.7,4G15.7)) + ENDIF +C + IF(JPRINT.GT.3) THEN +C + WRITE(LP,530) + 530 FORMAT(/' EIGENVECTORS OF A') +C + DO 540 I=1,N + WRITE(LP,350)I,(V(I,J),J=1,N) + 540 CONTINUE + ENDIF +C +C GO BACK TO THE MAIN LOOP. +C GO TO L0 +C +C HANDLE THE CASE N .EQ. 1 IN AN AD HOC WAY. +C (BRENT DID NOT PROVIDE FOR THIS CASE.) +C + IF(N.GE.2) GO TO 60 +C +C LABEL L2... +C + 550 IF(JPRINT.GT.0) THEN + WRITE(LP,560)(X(I),I=1,N) + 560 FORMAT(//7X,'X'/(1X,1PG15.7,4G15.7)) + ENDIF +C + FX=F(X,N) +C + IF(JPRINT.GE.0) WRITE(LP,570)FX,NL,NF + 570 FORMAT(/' EXIT PRAXIS. FX =',1PG25.17,5X,'NL =',I8, + * 5X,'NF =',I9) +C + RETURN +C +C END PRAXIS +C + END + SUBROUTINE QUAD(F) +C +C THIS SUBROUTINE LOOKS FOR THE MINIMUM ALONG +C A CURVE DEFINED BY Q0, Q1, AND X. +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGE 161 +C +C SUBROUTINE QUAD IS CALLED BY SUBROUTINE PRAXIS. +C + INTEGER N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + INTEGER I +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD + DOUBLE PRECISION F, DSQRT,ZSQRT,ARG, + * ONE,QA,QB,QC,S,TWO,XL,ZERO,QF1VAL +C + EXTERNAL F +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH +C + ZSQRT(ARG)=DSQRT(ARG) +C + ZERO=0.0D0 + ONE=1.0D0 +C + S=FX + FX=QF1 + QF1=S + QD1=ZERO +C + DO 10 I=1,N + S=X(I) + XL=Q1(I) + X(I)=XL + Q1(I)=S + QD1=QD1+(S-XL)**2 + 10 CONTINUE +C + QD1=ZSQRT(QD1) + XL=QD1 + S=ZERO +C + IF(QD0.GT.ZERO .AND. QD1.GT.ZERO .AND. NL.GE.3*N*N) THEN +C + IF(JPRINT.GE.1) WRITE(LP,20)NF,QD0,QD1,FX,QF1 + 20 FORMAT(/' ***** CALL MINX FROM QUAD. NF =',I11/ + * 5X,'QD0 =',1PG15.7,5X,'QD1 =',G15.7/ + * 5X,'FX =',G15.7,5X,'QF1 =',G15.7) +C + QF1VAL=QF1 + CALL MINX(0,2,S,XL,QF1VAL,1,F) + QA=XL*(XL-QD1)/(QD0*(QD0+QD1)) + QB=(XL+QD0)*(QD1-XL)/(QD0*QD1) + QC=XL*(XL+QD0)/(QD1*(QD0+QD1)) + ELSE + FX=QF1 + QA=ZERO + QB=ZERO + QC=ONE + ENDIF +C + QD0=QD1 +C + DO 30 I=1,N + S=Q0(I) + Q0(I)=X(I) + X(I)=QA*S+QB*X(I)+QC*Q1(I) + 30 CONTINUE +C + RETURN +C +C END QUAD +C + END + SUBROUTINE MINX(J,NITS,D2,X1,F1,IFK,F) +C +C SUBROUTINE MINX MINIMIZES F FROM X IN THE DIRECTION V(*,J) +C UNLESS J IS LESS THAN 1, WHEN A QUADRATIC SEARCH IS DONE IN +C THE PLANE DEFINED BY Q0, Q1, AND X. +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGES 159-160 +C +C SUBROUTINE MINX IS CALLED BY SUBROUTINES PRAXIS AND QUAD. +C +C D2 AND X1 RETURN RESULTS. +C J, NITS, F1 AND IFK ARE VALUE PARAMETERS THAT RETURN NOTHING. +C DO NOT SEND A COMMON VARIABLE TO MINX FOR PARAMETER F1. +C +C +C D2 IS AN APPROXIMATION TO HALF OF +C THE SECOND DERIVATIVE OF F (OR ZERO). +C +C X1 IS AN ESTIMATE OF DISTANCE TO MINIMUM, +C RETURNED AS THE DISTANCE FOUND. +C +C IF IFK = 1 THEN F1 IS FLIN(X1), OTHERWISE X1 AND F1 ARE +C IGNORED ON ENTRY UNLESS FINAL FX IS GREATER THAN F1. +C +C NITS CONTROLS THE NUMBER OF TIMES AN ATTEMPT IS MADE TO +C HALVE THE INTERVAL. +C + EXTERNAL F +C + INTEGER N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + INTEGER IFK,J,NITS, I,IDZ,K +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD + DOUBLE PRECISION D2,X1, + * DABS,DSQRT,ZABS,ZSQRT,ARG, + * HUNDTH,RHALF,TWO,ZERO, + * DENOM,D1,FM,F0,F1,F2,S,SF1,SX1,T2,XM,X2 +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH +C + ZSQRT(ARG)=DSQRT(ARG) + ZABS(ARG)=DABS(ARG) +C + HUNDTH=0.01D0 + ZERO=0.0D0 + TWO=2.0D0 + RHALF=0.5D0 +C + SF1=F1 + SX1=X1 + K=0 + XM=ZERO + FM=FX + F0=FX +C + IF(D2.LT.EPSMCH) THEN + IDZ=1 + ELSE + IDZ=0 + ENDIF +C +C FIND THE STEP SIZE. +C + S=ZERO + DO 10 I=1,N + S=S+X(I)**2 + 10 CONTINUE + S=ZSQRT(S) +C + IF(IDZ.EQ.1) THEN + DENOM=DMIN + ELSE + DENOM=D2 + ENDIF +C + T2=XM4*ZSQRT(ZABS(FX)/DENOM+S*XLDT)+XM2*XLDT + S=XM4*S+T + IF(IDZ.EQ.1 .AND. T2.GT.S) T2=S + IF(T2.LT.SMALL) T2=SMALL + IF(T2.GT.HUNDTH*H) T2=HUNDTH*H +C + IF(IFK.EQ.1 .AND. F1.LE.FM) THEN + XM=X1 + FM=F1 + ENDIF +C + IF(IFK.EQ.0 .OR. ZABS(X1).LT.T2) THEN +C + IF(X1.GE.ZERO) THEN + X1=T2 + ELSE + X1=-T2 + ENDIF +C + CALL FLIN(X1,J,F,F1) + ENDIF +C + IF(F1.LT.FM) THEN + XM=X1 + FM=F1 + ENDIF +C +C LABEL L0... +C + 20 IF(IDZ.EQ.1) THEN +C +C EVALUATE FLIN AT ANOTHER POINT, +C AND ESTIMATE THE SECOND DERIVATIVE. +C + IF(F0.LT.F1) THEN + X2=-X1 + ELSE + X2=TWO*X1 + ENDIF +C + CALL FLIN(X2,J,F,F2) +C + IF(F2.LE.FM) THEN + XM=X2 + FM=F2 + ENDIF +C + D2=(X2*(F1-F0)-X1*(F2-F0))/(X1*X2*(X1-X2)) +C + IF(JPRINT.GE.5) WRITE(LP,30)X1,X2,F0,F1,F2,D2 + 30 FORMAT(/' COMPUTE D2 IN SUBROUTINE MINX.'/ + * 5X,'X1 =',1PG15.7,5X,'X2 =',G15.7/ + * 5X,'F0 =',G15.7,5X,'F1 =',G15.7,5X,'F2 =',G15.7/ + * 5X,'D2 =',G15.7) + ENDIF +C +C ESTIMATE THE FIRST DERIVATIVE AT 0. +C + D1=(F1-F0)/X1-X1*D2 + IDZ=1 +C +C PREDICT THE MINIMUM. +C + IF(D2.LE.SMALL) THEN +C + IF(D1.LT.ZERO) THEN + X2=H + ELSE + X2=-H + ENDIF +C + ELSE + X2=-RHALF*D1/D2 + ENDIF +C + IF(ZABS(X2).GT.H) THEN +C + IF(X2.GT.ZERO) THEN + X2=H + ELSE + X2=-H + ENDIF + ENDIF +C +C EVALUATE F AT THE PREDICTED MINIMUM. +C LABEL L1... +C + 40 CALL FLIN(X2,J,F,F2) +C + IF(K.LT.NITS .AND. F2.GT.F0) THEN +C +C NO SUCCESS, SO TRY AGAIN. +C + K=K+1 +C +C IF(...) GO TO L0 +C + IF(F0.LT.F1 .AND. X1*X2.GT.ZERO) GO TO 20 + X2=X2/TWO +C +C GO TO L1 +C + GO TO 40 +C + ENDIF +C +C INCREMENT THE ONE-DIMENSIONAL SEARCH COUNTER. +C + NL=NL+1 +C + IF(F2.GT.FM) THEN + X2=XM + ELSE + FM=F2 + ENDIF +C +C GET A NEW ESTIMATE OF THE SECOND DERIVATIVE. +C + IF(ZABS(X2*(X2-X1)).GT.SMALL) THEN + D2=(X2*(F1-F0)-X1*(FM-F0))/(X1*X2*(X1-X2)) +C + IF(JPRINT.GE.5) WRITE(LP,50)X1,X2,F0,FM,F1,D2 + 50 FORMAT(/' RECOMPUTE D2 IN SUBROUTINE MINX.'/ + * 5X,'X1 =',1PG15.7,5X,'X2 =',G15.7/ + * 5X,'F0 =',G15.7,5X,'FM =',G15.7,5X,'F1 =',G15.7/ + * 5X,'D2 =',G15.7) +C + ELSE IF(K.GT.0) THEN + D2=ZERO +C + IF(JPRINT.GE.5) WRITE(LP,60) + 60 FORMAT(/' SET D2=0 IN SUBROUTINE MINX.') + ELSE + D2=D2 + ENDIF +C + IF(D2.LE.SMALL) THEN + D2=SMALL +C + IF(JPRINT.GE.5) WRITE(LP,70)D2 + 70 FORMAT(/' SET D2=SMALL=',1PG15.7,' IN SUBROUTINE MINX.') + ENDIF +C + IF(JPRINT.GE.5) WRITE(LP,80)X1,X2,FX,FM,SF1 + 80 FORMAT(/' SUBROUTINE MINX. X1 =',1PG15.7,5X,'X2 =',G15.7/ + * 5X,'FX =',G15.7,5X,'FM =',G15.7,5X,'SF1 =',G15.7) +C + X1=X2 + FX=FM + IF(SF1.LT.FX) THEN + FX=SF1 + X1=SX1 + ENDIF +C +C UPDATE X FOR A LINEAR SEARCH BUT NOT FOR A PARABOLIC SEARCH. +C + IF(J.GT.0) THEN +C + DO 90 I=1,N + X(I)=X(I)+X1*V(I,J) + 90 CONTINUE + ENDIF +C + IF(JPRINT.GE.5) WRITE(LP,100)D2,X1,F1,FX + 100 FORMAT(/' LEAVE SUBROUTINE MINX.'/ + * 5X,'D2 =',1PG15.7,5X,'X1 =',G15.7,5X,'F1 =',G15.7/ + * 5X,'FX =',G15.7) +C + RETURN +C +C END MINX +C + END + SUBROUTINE FLIN(XL,J,F,FLN) +C +C FLIN IS A FUNCTION OF ONE VARIABLE XL WHICH IS MINIMIZED BY +C SUBROUTINE MINX. +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGES 159-160 +C +C SUBROUTINE FLIN IS CALLED BY SUBROUTINE MINX. +C + INTEGER N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + INTEGER J, I +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD + DOUBLE PRECISION XL,F,FLN, TT, QA,QB,QC +C + DIMENSION TT(128) +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH +C + IF(J.GT.0) THEN +C +C LINEAR SEARCH... +C + DO 10 I=1,N + TT(I)=X(I)+XL*V(I,J) + 10 CONTINUE +C + ELSE +C +C SEARCH ALONG A PARABOLIC SPACE CURVE. +C + QA=XL*(XL-QD1)/(QD0*(QD0+QD1)) + QB=(XL+QD0)*(QD1-XL)/(QD0*QD1) + QC=XL*(XL+QD0)/(QD1*(QD0+QD1)) +C + DO 20 I=1,N + TT(I)=QA*Q0(I)+QB*X(I)+QC*Q1(I) + 20 CONTINUE + ENDIF +C +C INCREMENT FUNCTION EVALUATION COUNTER. +C + NF=NF+1 + FLN=F(TT,N) +C + RETURN +C +C END FLIN +C + END + SUBROUTINE MINFIT(N,EPS,TOL,AB,Q,E,NMAX,LP) +C +C AN IMPROVED VERSION OF MINFIT, RESTRICTED TO M=N, P=0. +C SEE GOLUB AND REINSCH (1970). +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGES 156-158 +C +C G. H. GOLUB AND C. REINSCH, +C "SINGULAR VALUE DECOMPOSITION AND LEAST SQUARES SOLUTIONS', +C NUMERISCHE MATHEMATIK 14 (1970) PAGES 403-420 +C +C THE SINGULAR VALUES OF THE ARRAY AB ARE RETURNED IN Q, +C AND AB IS OVERWRITTEN WITH THE ORTHOGONAL MATRIX V SUCH THAT +C U.DIAG(Q)=AB.V, WHERE U IS ANOTHER ORTHOGONAL MATRIX. +C +C SUBROUTINE MINFIT IS CALLED BY SUBROUTINE PRAXIS. +C + INTEGER N,NMAX,LP, + * I,II,J,JTHIRT,K,KK,KT,L,LL2,LPI,L2 +C + DOUBLE PRECISION EPS,TOL,AB,Q,E, + * DABS,DSQRT,ZABS,ZSQRT,ARG, + * C,DENOM,F,G,H,ONE,X,Y,Z,ZERO,S,TWO +C + DIMENSION AB(NMAX,N),Q(N),E(N) +C + ZABS(ARG)=DABS(ARG) + ZSQRT(ARG)=DSQRT(ARG) +C + JTHIRT=30 +C + ZERO=0.0D0 + ONE=1.0D0 + TWO=2.0D0 +C +C HOUSEHOLDER'S REDUCTION TO BIDIAGONAL FORM... +C + X=ZERO + G=ZERO +C + DO 140 I=1,N + E(I)=G + S=ZERO + L=I+1 +C + DO 10 J=I,N + S=S+AB(J,I)**2 + 10 CONTINUE +C + IF(S.LT.TOL) THEN + G=ZERO + ELSE + F=AB(I,I) +C + IF(F.LT.ZERO) THEN + G=ZSQRT(S) + ELSE + G=-ZSQRT(S) + ENDIF +C + H=F*G-S + AB(I,I)=F-G +C + IF(L.GT.N) GO TO 60 + DO 50 J=L,N +C + F=ZERO + IF(I.GT.N) GO TO 30 + DO 20 K=I,N + F=F+AB(K,I)*AB(K,J) + 20 CONTINUE + 30 F=F/H +C + IF(I.GT.N) GO TO 50 + DO 40 K=I,N + AB(K,J)=AB(K,J)+F*AB(K,I) + 40 CONTINUE + 50 CONTINUE + ENDIF +C + 60 Q(I)=G + S=ZERO +C + IF(I.LE.N) THEN +C + IF(L.GT.N) GO TO 80 + DO 70 J=L,N + S=S+AB(I,J)**2 + 70 CONTINUE + ENDIF +C + 80 IF(S.LT.TOL) THEN + G=ZERO + ELSE + F=AB(I,I+1) +C + IF(F.LT.ZERO) THEN + G=ZSQRT(S) + ELSE + G=-ZSQRT(S) + ENDIF +C + H=F*G-S + AB(I,I+1)=F-G + IF(L.GT.N) GO TO 130 + DO 90 J=L,N + E(J)=AB(I,J)/H + 90 CONTINUE +C + DO 120 J=L,N +C + S=ZERO + DO 100 K=L,N + S=S+AB(J,K)*AB(I,K) + 100 CONTINUE +C + DO 110 K=L,N + AB(J,K)=AB(J,K)+S*E(K) + 110 CONTINUE + 120 CONTINUE + ENDIF +C + 130 Y=ZABS(Q(I))+ZABS(E(I)) +C + IF(Y.GT.X) X=Y + 140 CONTINUE +C +C ACCUMULATION OF RIGHT-HAND TRANSFORMATIONS... +C + DO 210 II=1,N + I=N-II+1 +C + IF(G.NE.ZERO) THEN + H=AB(I,I+1)*G +C + IF(L.GT.N) GO TO 200 + DO 150 J=L,N + AB(J,I)=AB(I,J)/H + 150 CONTINUE +C + DO 180 J=L,N +C + S=ZERO + DO 160 K=L,N + S=S+AB(I,K)*AB(K,J) + 160 CONTINUE +C + DO 170 K=L,N + AB(K,J)=AB(K,J)+S*AB(K,I) + 170 CONTINUE + 180 CONTINUE + ENDIF +C + IF(L.GT.N) GO TO 200 + DO 190 J=L,N + AB(J,I)=ZERO + AB(I,J)=ZERO + 190 CONTINUE +C + 200 AB(I,I)=ONE + G=E(I) + L=I + 210 CONTINUE +C +C DIAGONALIZATION OF THE BIDIAGONAL FORM... +C + EPS=EPS*X + DO 330 KK=1,N + K=N-KK+1 + KT=0 +C +C LABEL TESTFSPLITTING... +C + 220 KT=KT+1 +C + IF(KT.GT.JTHIRT) THEN + E(K)=ZERO + WRITE(LP,230) + 230 FORMAT(' QR FAILED.') + ENDIF +C + DO 240 LL2=1,K + L2=K-LL2+1 + L=L2 +C +C IF(...) GO TO TESTFCONVERGENCE +C + IF(ZABS(E(L)).LE.EPS) GO TO 270 +C +C IF(...) GO TO CANCELLATION +C + IF(ZABS(Q(L-1)).LE.EPS) GO TO 250 + 240 CONTINUE +C +C CANCELLATION OF E(L) IF L IS GREATER THAN 1... +C LABEL CANCELLATION... +C + 250 C=ZERO + S=ONE + IF(L.GT.K) GO TO 270 + DO 260 I=L,K + F=S*E(I) + E(I)=C*E(I) +C +C IF(...) GO TO TESTFCONVERGENCE +C + IF(ZABS(F).LE.EPS) GO TO 270 + G=Q(I) +C + IF(ZABS(F).LT.ZABS(G)) THEN + H=ZABS(G)*ZSQRT(ONE+(F/G)**2) + ELSE IF(F.NE.ZERO) THEN + H=ZABS(F)*ZSQRT(ONE+(G/F)**2) + ELSE + H=ZERO + ENDIF +C + Q(I)=H +C + IF(H.EQ.ZERO) THEN + H=ONE + G=ONE + ENDIF +C +C THE ABOVE REPLACES Q(I) AND H BY SQUARE ROOT OF (G*G+F*F) +C WHICH MAY GIVE INCORRECT RESULTS IF THE SQUARES UNDERFLOW OR IF +C F = G = 0 . +C + C=G/H + S=-F/H + 260 CONTINUE +C +C LABEL TESTFCONVERGENCE... +C + 270 Z=Q(K) +C +C IF(...) GO TO CONVERGENCE +C + IF(L.EQ.K) GO TO 310 +C +C SHIFT FROM BOTTOM 2*2 MINOR. +C + X=Q(L) + Y=Q(K-1) + G=E(K-1) + H=E(K) + F=((Y-Z)*(Y+Z)+(G-H)*(G+H))/(TWO*H*Y) + G=ZSQRT(F*F+ONE) +C + IF(F.LT.ZERO) THEN + DENOM=F-G + ELSE + DENOM=F+G + ENDIF +C + F=((X-Z)*(X+Z)+H*(Y/DENOM-H))/X +C +C NEXT QR TRANSFORMATION... +C + S=ONE + C=ONE + LPI=L+1 + IF(LPI.GT.K) GO TO 300 + DO 290 I=LPI,K + G=E(I) + Y=Q(I) + H=S*G + G=G*C +C + IF(ZABS(F).LT.ZABS(H)) THEN + Z=ZABS(H)*ZSQRT(ONE+(F/H)**2) + ELSE IF(F.NE.ZERO) THEN + Z=ZABS(F)*ZSQRT(ONE+(H/F)**2) + ELSE + Z=ZERO + ENDIF +C + E(I-1)=Z +C + IF(Z.EQ.ZERO) THEN + F=ONE + Z=ONE + ENDIF +C + C=F/Z + S=H/Z + F=X*C+G*S + G=-X*S+G*C + H=Y*S + Y=Y*C +C + DO 280 J=1,N + X=AB(J,I-1) + Z=AB(J,I) + AB(J,I-1)=X*C+Z*S + AB(J,I)=-X*S+Z*C + 280 CONTINUE +C + IF(ZABS(F).LT.ZABS(H)) THEN + Z=ZABS(H)*ZSQRT(ONE+(F/H)**2) + ELSE IF(F.NE.ZERO) THEN + Z=ZABS(F)*ZSQRT(ONE+(H/F)**2) + ELSE + Z=ZERO + ENDIF +C + Q(I-1)=Z +C + IF(Z.EQ.ZERO) THEN + F=ONE + Z=ONE + ENDIF +C + C=F/Z + S=H/Z + F=C*G+S*Y + X=-S*G+C*Y + 290 CONTINUE +C + 300 E(L)=ZERO + E(K)=F + Q(K)=X +C +C GO TO TESTFSPLITTING +C + GO TO 220 +C +C LABEL CONVERGENCE... +C + 310 IF(Z.LT.ZERO) THEN +C +C Q(K) IS MADE NON-NEGATIVE. +C + Q(K)=-Z + DO 320 J=1,N + AB(J,K)=-AB(J,K) + 320 CONTINUE + ENDIF + 330 CONTINUE +C + RETURN +C +C END MINFIT +C + END + SUBROUTINE SORT +C +C THIS SUBROUTINE SORTS THE ELEMENTS OF D +C AND THE CORRESPONDING COLUMNS OF V INTO DESCENDING ORDER. +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGES 158-159 +C + INTEGER N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + INTEGER I,IPI,J,K,NMI +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD + DOUBLE PRECISION S +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH +C + NMI=N-1 + IF(NMI.LT.1) GO TO 50 + DO 40 I=1,NMI + K=I + S=D(I) + IPI=I+1 + IF(IPI.GT.N) GO TO 20 +C + DO 10 J=IPI,N +C + IF(D(J).GT.S) THEN + K=J + S=D(J) + ENDIF + 10 CONTINUE +C + 20 IF(K.GT.I) THEN + D(K)=D(I) + D(I)=S +C + DO 30 J=1,N + S=V(J,I) + V(J,I)=V(J,K) + V(J,K)=S + 30 CONTINUE + ENDIF + 40 CONTINUE +C + 50 RETURN +C +C END SORT +C + END + SUBROUTINE RANINI(RVALUE) +C +C SUBROUTINE RANINI PERFORMS INITIALIZATION FOR SUBROUTINE RANDOM. +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGES 163-164 +C + INTEGER JRAN2,I +C + DOUBLE PRECISION RVALUE,R,RAN3,DMOD,DABS,RAN1 +C + COMMON /COMRAN/ RAN3(127),RAN1,JRAN2 +C + R=DMOD(DABS(RVALUE),8190.0D0)+1 + JRAN2=127 +C + 10 IF(JRAN2.GT.0) THEN + JRAN2=JRAN2-1 + RAN1=-2.0D0**55 +C + DO 20 I=1,7 + R=DMOD(1756.0D0*R,8191.0D0) + RAN1=(RAN1+(R-DMOD(R,32.0D0))/32.0D0)/256.0D0 + 20 CONTINUE +C + RAN3(JRAN2+1)=RAN1 + GO TO 10 + ENDIF +C + RETURN +C +C END RANINI +C + END + SUBROUTINE RANDOM(RANVAL) +C +C SUBROUTINE RANDOM RETURNS A DOUBLE PRECISION PSEUDORANDOM NUMBER +C UNIFORMLY DISTRIBUTED IN (0,1) (INCLUDING 0 BUT NOT 1). +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGES 163-164 +C +C BEFORE THE FIRST CALL TO RANDOM, THE USER MUST +C CALL RANINI(R) ONCE (ONLY) WITH R A DOUBLE PRECISION NUMBER +C EQUAL TO ANY INTEGER VALUE. +C BRENT (PAGE 166) USED THE EQUIVALENT OF +C CALL RANINI(4.0D0) . +C +C THE ALGORITHM USED IN SUBROUTINE RANDOM RETURNS X(N)/2**56, +C WHERE X(N) = X(N-1) + X(N-127) (MOD 2**56) . +C SINCE (1 + X + X**127) IS PRIMITIVE (MOD 2), +C THE PERIOD IS AT LEAST (2**127 - 1), WHICH EXCEEDS 10**38. +C +C SEE "SEMINUMERICAL ALGORITHMS", VOLUME 2 OF +C "THE ART OF COMPUTER PROGRAMMING" BY DONALD E. KNUTH, +C ADDISON-WESLEY 1969, PAGES 26, 34, AND 464. +C +C X(N) IS STORED IN DOUBLE PRECISION AS RAN3 = X(N)/2**56 - 1/2, +C AND ALL DOUBLE PRECISION ARITHMETIC IS EXACT. +C + INTEGER JRAN2 +C + DOUBLE PRECISION RANVAL,RAN3,RAN1 +C + COMMON /COMRAN/ RAN3(127),RAN1,JRAN2 +C + IF(JRAN2.EQ.0) THEN + JRAN2=126 + ELSE + JRAN2=JRAN2-1 + ENDIF +C + RAN1=RAN1+RAN3(JRAN2+1) + IF(RAN1.LT.0.0D0) THEN + RAN1=RAN1+0.5D0 + ELSE + RAN1=RAN1-0.5D0 + ENDIF +C + RAN3(JRAN2+1)=RAN1 + RANVAL=RAN1+0.5D0 +C + RETURN +C +C END RANDOM +C + END + DOUBLE PRECISION FUNCTION DRANDM(DL) +C +C SIMPLE PORTABLE PSEUDORANDOM NUMBER GENERATOR. +C +C DRANDM RETURNS FUNCTION VALUES THAT ARE PSEUDORANDOM +C NUMBERS UNIFORMLY DISTRIBUTED ON THE INTERVAL (0,1). +C +C 'NUMERICAL MATHEMATICS AND COMPUTING' BY WARD CHENEY AND +C DAVID KINCAID, BROOKS/COLE PUBLISHING COMPANY +C (FIRST EDITION, 1980), PAGE 203 +C +C AT THE BEGINNING OF EXECUTION, OR WHENEVER A NEW SEQUENCE IS +C TO BE INITIATED, SET DL EQUAL TO AN INTEGER VALUE BETWEEN +C 1.0D0 AND 2147483646.0D0, INCLUSIVE. DO THIS ONLY ONCE. +C THEREAFTER, DO NOT SET OR ALTER DL IN ANY WAY. +C FUNCTION DRANDM WILL MODIFY DL FOR ITS OWN PURPOSES. +C +C DRANDM USES A MULTIPLICATIVE CONGRUENTIAL METHOD. +C THE NUMBERS GENERATED BY DRANDM SUFFER FROM THE PARALLEL +C PLANES DEFECT DISCOVERED BY G. MARSAGLIA, AND SHOULD NOT BE +C USED WHEN HIGH-QUALITY RANDOMNESS IS REQUIRED. IN THAT +C CASE, USE A "SHUFFLING" METHOD. +C + DOUBLE PRECISION DL,DMOD +C + 10 DL=DMOD(16807.0D0*DL,2147483647.0D0) + DRANDM=DL/2147483647.0D0 + IF(DRANDM.LE.0.0D0 .OR. DRANDM.GE.1.0D0) GO TO 10 + RETURN + END diff --git a/gnuradio-core/src/gen_interpolator_taps/praxis.txt b/gnuradio-core/src/gen_interpolator_taps/praxis.txt new file mode 100644 index 000000000..9d0606566 --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/praxis.txt @@ -0,0 +1,176 @@ +Brent's PRAXIS minimizer is available in FORTRAN 77. July 1995 + +"Algorithms for Minimization Without Derivatives" +by Richard P. Brent, Prentice-Hall, 1973 +ISBN: 0-13-022335-2 + +This book by Brent was a groundbreaking effort. +(I believe that it was his Ph.D. thesis at Stanford.) +His algorithms for finding roots and minima in +one dimension have good performance for typical problems +and guaranteed performance in the worst case. +(A later rootfinder by J. Bus and Dekker gave +a much lower bound for the worst case, +but no better performance in typical problems.) +These algorithms were implemented in both ALGOL W +and FORTRAN by Brent, and have been used fairly widely. + +Brent also gave a multi-dimensional minimization algorithm, +PRAXIS, but only shows an implementation in ALGOL W. +This routine has not been widely used, at least in the U.S. +The PRAXIS package has been translated into FORTRAN +by Rosalee Taylor, Sue Pinski, and me, and +I am making it available via anonymous ftp for use as +freeware (please do not remove our names). + + ftp a.cs.okstate.edu + anonymous + [enter your userid as password] + cd /pub/jpc + get praxis.f + quit + + +Brent's method and its performance + +Newton's method for minimization can find the minimum of a +quadratic function in one iteration, but is sometimes not +convenient to use. In the 1960s, several researchers found +iterative methods that solve quadratic problems exactly in a +finite number of steps. C. S. Smith (1962) and +M. J. D. Powell (1964) devised methods +that had this property and did not require derivatives. +G. W. Stewart modified the Davidon-Fletcher-Powell quasi-Newton +method to use finite difference approximations to approximate +the gradient. Powell's method, or later versions by Zangwill, +were the most successful of the early direct search methods +having the property of finite convergence on quadratic functions. + +Powell's method was programmed at Harwell as subroutine VA04A, +and is available as file va04a.f in the same directory as praxis.f. +VA04A is not extremely robust, and can give underflow, overflow, +or division by zero. va04a.f has several documented patches in it +where I tried to get around various abnormal terminations. +I do not recommend VA04A very strongly. + +Brent's PRAXIS added orthogonalization and several other features +to Powell's method. Brent also dealt carefully with roundoff. + +William H. Press et al. in their book "Numerical Recipes" +comment that +"Brent has a number of other cute tricks up his sleeve, +and his modification of Powell's method is probably +the best presently known." + +Roger Fletcher was less enthusiastic in his review of Brent's book +in The Computer Journal 16 (1973) 314: +"... I am not convinced that the modifications to Powell's +method are the best. Use of eigenvector directions +is not independent of scale changes to the variables, +and the use of searches in random directions is hardly +appealing. Nonetheless all the algorithms are demonstrated +to be competitive by numerical examples." + +The methods of Powell, Brent, et al. require that the function +for which a local minimum is sought must be smooth; +that is, the function and all of its first partial derivatives +must be continuous. + +Brent compared his method to the methods of Powell, of Stewart, +and of Davies, Swann, and Campey. Indirectly, he compared it +also to the Davidon-Fletcher-Powell quasi-Newton method. +He found that his method was about as efficient as the best +of these in most cases, and that it was more robust than others +in some cases. (Pages 139-155 in Brent's book give fair +comparisons to other methods. The results in Table 7.1 on +page 138 are correct, but do not include progress all the way +to convergence, and are therefore not too useful.) + +On least squares problems, all of these general minimization +methods are likely to be inefficient compared to least squares +methods such as the Gauss-Newton or Marquardt methods. + +In addition to the scale dependence that Fletcher deplored, +PRAXIS also had the disadvantage that it required N, the number +of parameters, to be greater than or equal to two. +The failure to handle N=1 is an unnecessary and pointless limitation. + + +The FORTRAN version + +We have followed Brent's PRAXIS rather closely. +I have added a patch to try to handle the case N=1, +and an option to use a simpler pseudorandom number generator, +DRANDM. The handling of N=1 is not guaranteed. + +The user writes a main program and a function subprogram +to compute the function to be minimized. +All communication between the user's main program and PRAXIS +is done via COMMON, except for an EXTERNAL parameter giving +the name of the function subprogram. +The disadvantages of using COMMON are at least two-fold: + + 1) Arrays cannot have adjustable dimensions. + + 2) Because some actual parameters are COMMON variables, + the FORTRAN version of PRAXIS probably will not pass + the Bell Labs PFORT package as being 100% standard FORTRAN. + Nevertheless, this usage will not cause any conflict in + any commercial FORTRAN compiler ever written. + (If it does, I will apologize and rewrite PRAXIS.) + +The advantage of using COMMON is that it is not necessary to pass +about fifteen more parameters every time the user calls PRAXIS. +At present all arrays are dimensioned (20) or (20,20), +and this can easily be increased using two simple global editing +commands. (In this case, increase the value of NMAX.) + +There are no DATA statements in PRAXIS, and it was not necessary +to use any SAVE statements. + +We have used DOUBLE PRECISION for all floating point computations, +as Brent did. We recommend using DOUBLE PRECISION on all computers +except possibly Cray computers, in which REAL is reasonably precise. +The value of "machine epsilon" is computed in subroutine PRASET +using bisection, and is called EPSMCH. +Brent computes EPSMCH**4 and 1/EPSMCH**4 in PRAXIS, +and uses these quantities later. +Because EPSMCH in DOUBLE PRECISION is less than 1E-16, +these fourth powers of EPSMCH and 1/EPSMCH will underflow +and overflow on such machines as VAXs and PCs, +which have a range of only about 1E38, grossly insufficient +for scientific computation. For such machines, Brent recommends +increasing the value of EPSMCH. +EPSMCH=1E-9 or possibly even 1E-8 might be necessary. +A better solution would be to eliminate the explicit use of +these fourth powers, accomplishing the same result implicitly. + +A "bug bounty" of $10 U.S. will be paid by me for the first +notification of any error in PRAXIS. +The same bounty also applies to any substantive poor design +choice (having no redeeming advantages whatever) in the FORTRAN +package. (The patch for N=1 is not included, although any +suggested improvements in that will be considered carefully.) + +praxis.f includes test software to run any of the test problems +that Brent ran, and is set to run at least one case of each problem. +I have run these on an IBM 3090, essentially the same +architecture that Brent used, and obtained essentially the same +results that Brent shows on pages 140-155. The Hilbert problem with +N=12, for which Brent shows no termination results and for which +the results in Table 7.1 are correct but not relevant, +runs a long time; I cut it off at 3000 function evaluations. +I don't particularly like Brent's convergence criterion, +which allows this sort of extremely slow creeping progress, +but have not modified it. + +Please notify me of any problems with this software, +or of any suggested modifications. + +John Chandler +Computer Science Department +Oklahoma State University +Stillwater, Oklahoma 74078, U.S.A. +(405) 744-5676 +jpc@a.cs.okstate.edu + diff --git a/gnuradio-core/src/gen_interpolator_taps/simpson.c b/gnuradio-core/src/gen_interpolator_taps/simpson.c new file mode 100644 index 000000000..31aaae4ae --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/simpson.c @@ -0,0 +1,76 @@ +/* -*- c -*- */ +#include <math.h> +#include <stdio.h> + +#define EPS (1.0e-5) +#define JMAX 16 + +/* + * Compute the Nth stage of refinement of an extended trapezoidal + * rule. FUNC is input as a pointer to a function to be integrated + * between limits A and B. When called with N = 1, the routine + * returns the crudest estimate of the integral from A to B of f(x) + * dx. Subsequent calls with N=2,3,... (in that sequential order) + * will improve the accuracy by adding 2**(N-2) additional interior + * points. + * + * N.B., this function contains static state and IS NEITHER RENTRANT + * NOR THREAD SAFE! + */ + +double +trapzd (double (*func)(double), + double a, double b, + int n) +{ + long double x, tnm, sum, del; + static long double s; + static int it; + int j; + + if (n == 1){ + it = 1; /* # of points to add on the next call */ + s = 0.5 * (b - a) * (func(a) + func(b)); + return s; + } + else { + tnm = it; + del = (b-a)/tnm; /* this is the spacing of the points to be added */ + x = a + 0.5*del; + for (sum = 0.0, j = 1; j <= it; j++, x += del) + sum += func(x); + it *= 2; + s = 0.5 * (s + (b-a) * sum/tnm); /* replace s by it's refined value */ + return s; + } +} + +/* + * Returns the integral of the function FUNC from A to B. The + * parameters EPS can be set to the desired fractional accuracy and + * JMAX so that 2**(JMAX-1) is the maximum allowed number of steps. + * Integration is performed by Simpson's rule. + */ + +double +qsimp (double (*func)(double), + double a, /* lower limit */ + double b) /* upper limit */ +{ + int j; + long double s, st, ost, os; + + ost = os = -1.0e30; + for (j = 1; j <= JMAX; j++){ + st = trapzd (func, a, b, j); + s = (4.0 * st - ost)/3.0; + if (fabs (s - os) < EPS * fabs(os)) + return s; + os = s; + ost = st; + } + fprintf (stderr, "Too many steps in routine QSIMP\n"); + // exit (1); + return s; +} + diff --git a/gnuradio-core/src/gen_interpolator_taps/simpson.h b/gnuradio-core/src/gen_interpolator_taps/simpson.h new file mode 100644 index 000000000..68774f9a2 --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/simpson.h @@ -0,0 +1,3 @@ +double qsimp (double (*func)(double), + double a, double b); + diff --git a/gnuradio-core/src/lib/CMakeLists.txt b/gnuradio-core/src/lib/CMakeLists.txt new file mode 100644 index 000000000..c061a5723 --- /dev/null +++ b/gnuradio-core/src/lib/CMakeLists.txt @@ -0,0 +1,106 @@ +# Copyright 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. + +######################################################################## +# Setup compatibility checks and defines +######################################################################## +include(${CMAKE_CURRENT_SOURCE_DIR}/ConfigChecks.cmake) + +######################################################################## +# Include subdirs rather to populate to the sources lists. +######################################################################## +GR_INCLUDE_SUBDIRECTORY(missing) +GR_INCLUDE_SUBDIRECTORY(runtime) +GR_INCLUDE_SUBDIRECTORY(filter) +GR_INCLUDE_SUBDIRECTORY(viterbi) +GR_INCLUDE_SUBDIRECTORY(general) +GR_INCLUDE_SUBDIRECTORY(gengen) +GR_INCLUDE_SUBDIRECTORY(reed-solomon) +GR_INCLUDE_SUBDIRECTORY(io) +GR_INCLUDE_SUBDIRECTORY(hier) + +list(APPEND gnuradio_core_sources bug_work_around_6.cc) +list(APPEND test_gnuradio_core_sources bug_work_around_6.cc) + +######################################################################## +# Setup the include and linker paths +######################################################################## +include_directories( + ${GNURADIO_CORE_INCLUDE_DIRS} + ${VOLK_INCLUDE_DIRS} + ${GRUEL_INCLUDE_DIRS} + ${Boost_INCLUDE_DIRS} + ${FFTW3F_INCLUDE_DIRS} +) + +link_directories( + ${Boost_LIBRARY_DIRS} + ${FFTW3F_LIBRARY_DIRS} +) + +######################################################################## +# Setup library +######################################################################## +list(APPEND gnuradio_core_libs + gruel + ${Boost_LIBRARIES} + ${FFTW3F_LIBRARIES} +) + +if(FFTW3F_THREADS_LIBRARIES) + list(APPEND gnuradio_core_libs ${FFTW3F_THREADS_LIBRARIES} ) + add_definitions("-DFFTW3F_THREADS") +endif() + +#need to link with librt on ubuntu 11.10 for shm_* +if(LINUX) + list(APPEND gnuradio_core_libs rt) +endif() + +# Link against libvolk +list(APPEND gnuradio_core_libs volk) + +add_library(gnuradio-core SHARED ${gnuradio_core_sources}) +target_link_libraries(gnuradio-core ${gnuradio_core_libs}) +GR_LIBRARY_FOO(gnuradio-core RUNTIME_COMPONENT "core_runtime" DEVEL_COMPONENT "core_devel") +set_target_properties(gnuradio-core PROPERTIES LINK_INTERFACE_LIBRARIES "gruel") + +######################################################################## +# Setup executables +######################################################################## +add_executable(gnuradio-config-info gnuradio-config-info.cc) +target_link_libraries(gnuradio-config-info gnuradio-core ${Boost_LIBRARIES}) +install( + TARGETS gnuradio-config-info + DESTINATION ${GR_RUNTIME_DIR} + COMPONENT "core_runtime" +) + +######################################################################## +# Setup tests +######################################################################## +if(ENABLE_TESTING) + +include_directories(${CPPUNIT_INCLUDE_DIRS}) +link_directories(${CPPUNIT_LIBRARY_DIRS}) + +add_library(test-gnuradio-core SHARED ${test_gnuradio_core_sources}) +target_link_libraries(test-gnuradio-core ${GR_TEST_TARGET_DEPS} ${CPPUNIT_LIBRARIES} ${Boost_LIBRARIES}) + +endif(ENABLE_TESTING) diff --git a/gnuradio-core/src/lib/ConfigChecks.cmake b/gnuradio-core/src/lib/ConfigChecks.cmake new file mode 100644 index 000000000..26b778a7a --- /dev/null +++ b/gnuradio-core/src/lib/ConfigChecks.cmake @@ -0,0 +1,212 @@ +# Copyright 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. + +######################################################################## +INCLUDE(GrMiscUtils) +INCLUDE(CheckCXXSourceCompiles) + +IF(MSVC) #add this directory for our provided headers +LIST(APPEND CMAKE_REQUIRED_INCLUDES ${CMAKE_SOURCE_DIR}/msvc) +ENDIF(MSVC) + +GR_CHECK_HDR_N_DEF(netdb.h HAVE_NETDB_H) +GR_CHECK_HDR_N_DEF(sys/time.h HAVE_SYS_TIME_H) +GR_CHECK_HDR_N_DEF(sys/types.h HAVE_SYS_TYPES_H) +GR_CHECK_HDR_N_DEF(sys/select.h HAVE_SYS_SELECT_H) +GR_CHECK_HDR_N_DEF(sys/socket.h HAVE_SYS_SOCKET_H) +GR_CHECK_HDR_N_DEF(io.h HAVE_IO_H) +GR_CHECK_HDR_N_DEF(sys/mman.h HAVE_SYS_MMAN_H) +GR_CHECK_HDR_N_DEF(sys/ipc.h HAVE_SYS_IPC_H) +GR_CHECK_HDR_N_DEF(sys/shm.h HAVE_SYS_SHM_H) +GR_CHECK_HDR_N_DEF(signal.h HAVE_SIGNAL_H) +GR_CHECK_HDR_N_DEF(netinet/in.h HAVE_NETINET_IN_H) +GR_CHECK_HDR_N_DEF(arpa/inet.h HAVE_ARPA_INET_H) +GR_CHECK_HDR_N_DEF(byteswap.h HAVE_BYTESWAP_H) +GR_CHECK_HDR_N_DEF(linux/ppdev.h HAVE_LINUX_PPDEV_H) +GR_CHECK_HDR_N_DEF(dev/ppbus/ppi.h HAVE_DEV_PPBUS_PPI_H) +GR_CHECK_HDR_N_DEF(unistd.h HAVE_UNISTD_H) +GR_CHECK_HDR_N_DEF(malloc.h HAVE_MALLOC_H) + + +######################################################################## +CHECK_CXX_SOURCE_COMPILES(" + #include <stdio.h> + int main(){snprintf(0, 0, 0); return 0;} + " HAVE_SNPRINTF +) +GR_ADD_COND_DEF(HAVE_SNPRINTF) + +######################################################################## +CHECK_CXX_SOURCE_COMPILES(" + #include <signal.h> + int main(){sigaction(0, 0, 0); return 0;} + " HAVE_SIGACTION +) +GR_ADD_COND_DEF(HAVE_SIGACTION) + +######################################################################## +CHECK_CXX_SOURCE_COMPILES(" + #include <sys/select.h> + int main(){select(0, 0, 0, 0, 0); return 0;} + " HAVE_SELECT +) +GR_ADD_COND_DEF(HAVE_SELECT) + + +######################################################################## +CHECK_CXX_SOURCE_COMPILES(" + #include <unistd.h> + int main(){sysconf(0); return 0;} + " HAVE_SYSCONF +) +GR_ADD_COND_DEF(HAVE_SYSCONF) + +CHECK_CXX_SOURCE_COMPILES(" + #include <unistd.h> + int main(){getpagesize(); return 0;} + " HAVE_GETPAGESIZE +) +GR_ADD_COND_DEF(HAVE_GETPAGESIZE) + + +######################################################################## +CHECK_CXX_SOURCE_COMPILES(" + #include <Winbase.h> + int main(){Sleep(0); return 0;} + " HAVE_SSLEEP +) +GR_ADD_COND_DEF(HAVE_SSLEEP) + +CHECK_CXX_SOURCE_COMPILES(" + #include <time.h> + int main(){nanosleep(0, 0); return 0;} + " HAVE_NANOSLEEP +) +GR_ADD_COND_DEF(HAVE_NANOSLEEP) + +CHECK_CXX_SOURCE_COMPILES(" + #include <sys/time.h> + int main(){gettimeofday(0, 0); return 0;} + " HAVE_GETTIMEOFDAY +) +GR_ADD_COND_DEF(HAVE_GETTIMEOFDAY) + +######################################################################## +CHECK_CXX_SOURCE_COMPILES(" + #include <stdlib.h> + int main(){posix_memalign(0, 0, 0); return 0;} + " HAVE_POSIX_MEMALIGN +) +GR_ADD_COND_DEF(HAVE_POSIX_MEMALIGN) + +CHECK_CXX_SOURCE_COMPILES(" + #include <malloc.h> + int main(){valloc(0); return 0;} + " HAVE_VALLOC +) +GR_ADD_COND_DEF(HAVE_VALLOC) + +ADD_DEFINITIONS(-DALIGNED_MALLOC=0) + +######################################################################## +SET(CMAKE_REQUIRED_LIBRARIES -lpthread) +CHECK_CXX_SOURCE_COMPILES(" + #include <signal.h> + int main(){pthread_sigmask(0, 0, 0); return 0;} + " HAVE_PTHREAD_SIGMASK +) +GR_ADD_COND_DEF(HAVE_PTHREAD_SIGMASK) +SET(CMAKE_REQUIRED_LIBRARIES) + +######################################################################## +CHECK_CXX_SOURCE_COMPILES(" + #include <windows.h> + int main(){ + HANDLE handle; + int size; + LPCTSTR lpName; + handle = CreateFileMapping( + INVALID_HANDLE_VALUE, // use paging file + NULL, // default security + PAGE_READWRITE, // read/write access + 0, // max. object size + size, // buffer size + lpName); // name of mapping object + return 0; + } " HAVE_CREATEFILEMAPPING +) +GR_ADD_COND_DEF(HAVE_CREATEFILEMAPPING) + +######################################################################## +CHECK_INCLUDE_FILE_CXX(windows.h HAVE_WINDOWS_H) +IF(HAVE_WINDOWS_H) + ADD_DEFINITIONS(-DHAVE_WINDOWS_H -DUSING_WINSOCK) + MESSAGE(STATUS "Adding windows libs to gnuradio core libs...") + LIST(APPEND gnuradio_core_libs WS2_32.lib WSock32.lib) +ENDIF(HAVE_WINDOWS_H) + +######################################################################## +SET(CMAKE_REQUIRED_LIBRARIES -lrt) +CHECK_CXX_SOURCE_COMPILES(" + #include <sys/types.h> + #include <sys/mman.h> + int main(){shm_open(0, 0, 0); return 0;} + " HAVE_SHM_OPEN +) +GR_ADD_COND_DEF(HAVE_SHM_OPEN) +SET(CMAKE_REQUIRED_LIBRARIES) + +######################################################################## +CHECK_CXX_SOURCE_COMPILES(" + #define _GNU_SOURCE + #include <math.h> + int main(){double x, sin, cos; sincos(x, &sin, &cos); return 0;} + " HAVE_SINCOS +) +GR_ADD_COND_DEF(HAVE_SINCOS) + +CHECK_CXX_SOURCE_COMPILES(" + #define _GNU_SOURCE + #include <math.h> + int main(){float x, sin, cos; sincosf(x, &sin, &cos); return 0;} + " HAVE_SINCOSF +) +GR_ADD_COND_DEF(HAVE_SINCOSF) + +CHECK_CXX_SOURCE_COMPILES(" + #include <math.h> + int main(){sinf(0); return 0;} + " HAVE_SINF +) +GR_ADD_COND_DEF(HAVE_SINF) + +CHECK_CXX_SOURCE_COMPILES(" + #include <math.h> + int main(){cosf(0); return 0;} + " HAVE_COSF +) +GR_ADD_COND_DEF(HAVE_COSF) + +######################################################################## +CHECK_CXX_SOURCE_COMPILES(" + #include <sys/mman.h> + int main(){mmap(0, 0, 0, 0, 0, 0); return 0;} + " HAVE_MMAP +) +GR_ADD_COND_DEF(HAVE_MMAP) diff --git a/gnuradio-core/src/lib/bug_work_around_6.cc b/gnuradio-core/src/lib/bug_work_around_6.cc new file mode 100644 index 000000000..f8012af0d --- /dev/null +++ b/gnuradio-core/src/lib/bug_work_around_6.cc @@ -0,0 +1,3 @@ +// if libgrio has no sources, it doesn't get built correctly +#include <gruel/attributes.h> +static int gr_bug_work_around_6 __GR_ATTR_UNUSED; diff --git a/gnuradio-core/src/lib/filter/3dnow_float_dotprod_really_simple.S b/gnuradio-core/src/lib/filter/3dnow_float_dotprod_really_simple.S new file mode 100644 index 000000000..546a4a6f3 --- /dev/null +++ b/gnuradio-core/src/lib/filter/3dnow_float_dotprod_really_simple.S @@ -0,0 +1,99 @@ +# +# Copyright 2002 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. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_4_float_blocks is != 0 +# +# +# float +# sse_float_dotprod (const float *input, +# const float *taps, unsigned n_4_float_blocks) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[1] * taps[1]; +# sum2 += input[2] * taps[2]; +# sum3 += input[3] * taps[3]; +# +# input += 4; +# taps += 4; +# +# } while (--n_4_float_blocks != 0); +# +# +# return sum0 + sum1 + sum2 + sum3; +# } +# + + + .file "3dnow_float_dotprod_really_simple.s" +// .version "01.01" +.text + .p2align 4 +.globl sse_float_dotprod + .type sse_float_dotprod,@function +sse_float_dotprod: + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %edx + movl 12(%ebp), %eax + movl 16(%ebp), %ecx + + + # The plan is to get it computing the correct answer, and + # then to unroll and schedule the inner loop. + + pxor %mm4, %mm4 # mm4 = 0 0 + shll $1, %ecx # count * 2 + + .p2align 4 +.Loop1: + movq (%eax), %mm0 + pfmul (%edx), %mm0 + pfadd %mm0, %mm4 + addl $8, %edx + addl $8, %eax + decl %ecx + jne .Loop1 + + # at this point mm4 contains partial sums + + pfacc %mm4, %mm4 + movd %mm4, 16(%ebp) + femms + flds 16(%ebp) + + popl %ebp + ret +.Lfe1: + .size sse_float_dotprod,.Lfe1-sse_float_dotprod + .ident "Hand coded x86 3DNow! assembly" + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/gnuradio-core/src/lib/filter/3dnow_float_dotprod_simple.S b/gnuradio-core/src/lib/filter/3dnow_float_dotprod_simple.S new file mode 100644 index 000000000..c721c3601 --- /dev/null +++ b/gnuradio-core/src/lib/filter/3dnow_float_dotprod_simple.S @@ -0,0 +1,106 @@ +# +# Copyright 2002 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. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_4_float_blocks is != 0 +# +# +# float +# sse_float_dotprod (const float *input, +# const float *taps, unsigned n_4_float_blocks) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[1] * taps[1]; +# sum2 += input[2] * taps[2]; +# sum3 += input[3] * taps[3]; +# +# input += 4; +# taps += 4; +# +# } while (--n_4_float_blocks != 0); +# +# +# return sum0 + sum1 + sum2 + sum3; +# } +# + + + .file "3dnow_float_dotprod_simple.s" +// .version "01.01" +.text + .p2align 4 +.globl sse_float_dotprod + .type sse_float_dotprod,@function +sse_float_dotprod: + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %edx + movl 12(%ebp), %eax + movl 16(%ebp), %ecx + + + # The plan is to get it computing the correct answer, and + # then to unroll and schedule the inner loop. + + pxor %mm4, %mm4 # mm4 = 0 0 + pxor %mm5, %mm5 # mm5 = 0 0 + + .p2align 4 +.Loop1: + movq 0(%eax), %mm0 + movq 8(%eax), %mm1 + + pfmul 0(%edx), %mm0 + pfadd %mm0, %mm4 + + pfmul 8(%edx), %mm1 + pfadd %mm1, %mm5 + + addl $16, %edx + addl $16, %eax + decl %ecx + jne .Loop1 + + # at this point mm4 and mm5 contain partial sums + + pfadd %mm5, %mm4 + pfacc %mm4, %mm4 + movd %mm4, 16(%ebp) + femms + flds 16(%ebp) + + popl %ebp + ret +.Lfe1: + .size sse_float_dotprod,.Lfe1-sse_float_dotprod + .ident "Hand coded x86 3DNow! assembly" + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/gnuradio-core/src/lib/filter/CMakeLists.txt b/gnuradio-core/src/lib/filter/CMakeLists.txt new file mode 100644 index 000000000..088d3376d --- /dev/null +++ b/gnuradio-core/src/lib/filter/CMakeLists.txt @@ -0,0 +1,357 @@ +# Copyright 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. + +######################################################################## +# This file included, use CMake directory variables +######################################################################## + +#set the C language property on the assembly files so the compiler will pick them up +file(GLOB gr_core_filter_asms ${CMAKE_CURRENT_SOURCE_DIR}/*.S) +foreach(gr_core_filter_asm ${gr_core_filter_asms}) + set_property(SOURCE ${gr_core_filter_asm} PROPERTY LANGUAGE C) +endforeach(gr_core_filter_asm) + +#detect 32 or 64 bit compiler +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(i.86|x86|x86_64|amd64)$") + include(CheckTypeSize) + check_type_size("void*" SIZEOF_VOID_P BUILTIN_TYPES_ONLY) + if (${SIZEOF_VOID_P} EQUAL 8) + set(CMAKE_SYSTEM_PROCESSOR_x86 64) + else() + set(CMAKE_SYSTEM_PROCESSOR_x86 32) + endif() +endif() + +######################################################################## +# Generate the makefile.gen, then extract its sources: +# This is a round-about way to extract the sources, +# but it requires minimum changed to the python utils. +# +# The recommended way to do this: +# - Make a generation macro that registers the sources command. +# - List the generation macro with each templated source file. +# - Create a python script (very generic) to perform generation. +# - This way the targets would depend only on their sources. +######################################################################## +execute_process( + COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} -c " +import os, sys +sys.path.append('${GR_CORE_PYTHONPATH}') +sys.path.append('${CMAKE_CURRENT_SOURCE_DIR}') +os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}' +os.environ['gendir'] = '${CMAKE_CURRENT_BINARY_DIR}' +os.environ['do_makefile'] = '1' +os.environ['do_sources'] = '0' +from generate_all import generate_all +generate_all() + " WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} +) + +macro(FILTER_GEN_EXTRACT outvar ext) + execute_process(COMMAND ${PYTHON_EXECUTABLE} -c "import os; print ';'.join( + map(lambda x: os.path.join('${CMAKE_CURRENT_BINARY_DIR}', x.replace('\\\\', '').strip()), + filter(lambda f: '${ext}' in f, open('${CMAKE_CURRENT_BINARY_DIR}/Makefile.gen').readlines() + )))" OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE ${outvar}) + file(TO_CMAKE_PATH "${${outvar}}" ${outvar}) +endmacro(FILTER_GEN_EXTRACT) + +FILTER_GEN_EXTRACT(generated_filter_sources ".cc") +FILTER_GEN_EXTRACT(generated_filter_includes ".h") +FILTER_GEN_EXTRACT(generated_filter_swigs ".i") + +#TODO simplify this list with a triple-threat for loop +set(generated_filter_deps + ${CMAKE_CURRENT_SOURCE_DIR}/generate_all.py + ${CMAKE_CURRENT_SOURCE_DIR}/generate_gr_fir_XXX.py + ${CMAKE_CURRENT_SOURCE_DIR}/generate_gr_fir_filter_XXX.py + ${CMAKE_CURRENT_SOURCE_DIR}/generate_gr_interp_fir_filter_XXX.py + ${CMAKE_CURRENT_SOURCE_DIR}/generate_gr_rational_resampler_base_XXX.py + ${CMAKE_CURRENT_SOURCE_DIR}/generate_gr_fir_sysconfig.py + ${CMAKE_CURRENT_SOURCE_DIR}/generate_gr_fir_sysconfig_generic.py + ${CMAKE_CURRENT_SOURCE_DIR}/generate_gr_fir_util.py + ${CMAKE_CURRENT_SOURCE_DIR}/generate_gr_freq_xlating_fir_filter_XXX.py + ${CMAKE_CURRENT_SOURCE_DIR}/generate_gri_fir_filter_with_buffer_XXX.py + ${CMAKE_CURRENT_SOURCE_DIR}/generate_utils.py + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_XXX.cc.t + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_XXX.h.t + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_XXX_generic.cc.t + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_XXX_generic.h.t + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_filter_XXX.cc.t + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_filter_XXX.h.t + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_filter_XXX.i.t + ${CMAKE_CURRENT_SOURCE_DIR}/gr_interp_fir_filter_XXX.cc.t + ${CMAKE_CURRENT_SOURCE_DIR}/gr_interp_fir_filter_XXX.h.t + ${CMAKE_CURRENT_SOURCE_DIR}/gr_interp_fir_filter_XXX.i.t + ${CMAKE_CURRENT_SOURCE_DIR}/gr_rational_resampler_base_XXX.cc.t + ${CMAKE_CURRENT_SOURCE_DIR}/gr_rational_resampler_base_XXX.h.t + ${CMAKE_CURRENT_SOURCE_DIR}/gr_rational_resampler_base_XXX.i.t + ${CMAKE_CURRENT_SOURCE_DIR}/gr_freq_xlating_fir_filter_XXX.cc.t + ${CMAKE_CURRENT_SOURCE_DIR}/gr_freq_xlating_fir_filter_XXX.h.t + ${CMAKE_CURRENT_SOURCE_DIR}/gr_freq_xlating_fir_filter_XXX.i.t + ${CMAKE_CURRENT_SOURCE_DIR}/gri_fir_filter_with_buffer_XXX.cc.t + ${CMAKE_CURRENT_SOURCE_DIR}/gri_fir_filter_with_buffer_XXX.h.t +) + +add_custom_command( + OUTPUT + ${generated_filter_sources} + ${generated_filter_includes} + ${generated_filter_swigs} + DEPENDS ${generated_filter_deps} + COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} -c + "import os, sys;sys.path.append('${GR_CORE_PYTHONPATH}');sys.path.append('${CMAKE_CURRENT_SOURCE_DIR}');os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}';from generate_all import generate_all;generate_all()" + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "generating filter files" + VERBATIM +) + +add_custom_target(filter_generated DEPENDS + ${generated_filter_sources} + ${generated_filter_includes} + ${generated_filter_swigs} +) + +######################################################################## +# Add target specific files +# May VOLK put a rest to all the insanity below. +######################################################################## +if(MSVC) + list(APPEND gnuradio_core_sources + ${CMAKE_CURRENT_SOURCE_DIR}/sysconfig_generic.cc + ) + list(APPEND test_gnuradio_core_sources + ${CMAKE_CURRENT_SOURCE_DIR}/qa_dotprod_generic.cc + ) +else(MSVC) +if(CMAKE_SYSTEM_PROCESSOR_x86) + list(APPEND gnuradio_core_sources + ${CMAKE_CURRENT_SOURCE_DIR}/sysconfig_x86.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_sysconfig_x86.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_cpu_x86.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_ccc_simd.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_ccc_x86.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_fff_simd.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_fff_x86.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_fsf_simd.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_fsf_x86.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_scc_simd.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_scc_x86.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_fcc_simd.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_fcc_x86.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_ccf_simd.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_ccf_x86.cc + ${CMAKE_CURRENT_SOURCE_DIR}/sse_debug.c + ) + list(APPEND test_gnuradio_core_sources + ${CMAKE_CURRENT_SOURCE_DIR}/qa_dotprod_x86.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_float_dotprod_x86.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_complex_dotprod_x86.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_ccomplex_dotprod_x86.cc + ) +endif() + +if(CMAKE_SYSTEM_PROCESSOR_x86 AND "${CMAKE_SYSTEM_PROCESSOR_x86}" STREQUAL "64") + list(APPEND gnuradio_core_sources + ${CMAKE_CURRENT_SOURCE_DIR}/float_dotprod_sse64.S + ${CMAKE_CURRENT_SOURCE_DIR}/float_dotprod_3dnow64.S + ${CMAKE_CURRENT_SOURCE_DIR}/complex_dotprod_3dnowext64.S + ${CMAKE_CURRENT_SOURCE_DIR}/complex_dotprod_3dnow64.S + ${CMAKE_CURRENT_SOURCE_DIR}/complex_dotprod_sse64.S + ${CMAKE_CURRENT_SOURCE_DIR}/ccomplex_dotprod_3dnowext64.S + ${CMAKE_CURRENT_SOURCE_DIR}/ccomplex_dotprod_3dnow64.S + ${CMAKE_CURRENT_SOURCE_DIR}/ccomplex_dotprod_sse64.S + ${CMAKE_CURRENT_SOURCE_DIR}/fcomplex_dotprod_3dnow64.S + ${CMAKE_CURRENT_SOURCE_DIR}/fcomplex_dotprod_sse64.S + ${CMAKE_CURRENT_SOURCE_DIR}/short_dotprod_mmx64.S + ) +elseif(CMAKE_SYSTEM_PROCESSOR_x86 AND "${CMAKE_SYSTEM_PROCESSOR_x86}" STREQUAL "32") + list(APPEND gnuradio_core_sources + ${CMAKE_CURRENT_SOURCE_DIR}/float_dotprod_sse.S + ${CMAKE_CURRENT_SOURCE_DIR}/float_dotprod_3dnow.S + ${CMAKE_CURRENT_SOURCE_DIR}/complex_dotprod_3dnowext.S + ${CMAKE_CURRENT_SOURCE_DIR}/complex_dotprod_3dnow.S + ${CMAKE_CURRENT_SOURCE_DIR}/complex_dotprod_sse.S + ${CMAKE_CURRENT_SOURCE_DIR}/ccomplex_dotprod_3dnowext.S + ${CMAKE_CURRENT_SOURCE_DIR}/ccomplex_dotprod_3dnow.S + ${CMAKE_CURRENT_SOURCE_DIR}/ccomplex_dotprod_sse.S + ${CMAKE_CURRENT_SOURCE_DIR}/fcomplex_dotprod_3dnow.S + ${CMAKE_CURRENT_SOURCE_DIR}/fcomplex_dotprod_sse.S + ${CMAKE_CURRENT_SOURCE_DIR}/short_dotprod_mmx.S + ) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)") + if(CMAKE_COMPILER_IS_GNUCXX) + add_definitions(-maltivec) + endif() + list(APPEND gnuradio_core_sources + ${CMAKE_CURRENT_SOURCE_DIR}/sysconfig_powerpc.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_sysconfig_powerpc.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_cpu_powerpc.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_fff_altivec.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_altivec.c + ${CMAKE_CURRENT_SOURCE_DIR}/dotprod_fff_altivec.c + ) + list(APPEND test_gnuradio_core_sources + ${CMAKE_CURRENT_SOURCE_DIR}/qa_dotprod_powerpc.cc + ) +elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm") + if(have_mfpu_neon) + add_definitions(-DHAVE_MFPU_NEON) + endif() + list(APPEND gnuradio_core_sources + ${CMAKE_CURRENT_SOURCE_DIR}/sysconfig_armv7_a.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_sysconfig_armv7_a.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_cpu_armv7_a.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_fff_armv7_a.cc + ${CMAKE_CURRENT_SOURCE_DIR}/dotprod_fff_armv7_a.c + ${CMAKE_CURRENT_SOURCE_DIR}/dotprod_ccf_armv7_a.c + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_ccf_armv7_a.cc + ) + list(APPEND test_gnuradio_core_sources + ${CMAKE_CURRENT_SOURCE_DIR}/qa_dotprod_armv7_a.cc + ) +else() + list(APPEND gnuradio_core_sources + ${CMAKE_CURRENT_SOURCE_DIR}/sysconfig_generic.cc + ) + list(APPEND test_gnuradio_core_sources + ${CMAKE_CURRENT_SOURCE_DIR}/qa_dotprod_generic.cc + ) +endif() +endif(MSVC) + +######################################################################## +# Append gnuradio-core library sources +######################################################################## +list(APPEND gnuradio_core_sources + ${generated_filter_sources} + ${CMAKE_CURRENT_SOURCE_DIR}/gri_fft_filter_fff_generic.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gri_fft_filter_ccc_generic.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_sincos.c + ${CMAKE_CURRENT_SOURCE_DIR}/gri_goertzel.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gri_mmse_fir_interpolator.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gri_mmse_fir_interpolator_cc.cc + ${CMAKE_CURRENT_SOURCE_DIR}/complex_dotprod_generic.cc + ${CMAKE_CURRENT_SOURCE_DIR}/ccomplex_dotprod_generic.cc + ${CMAKE_CURRENT_SOURCE_DIR}/float_dotprod_generic.c + ${CMAKE_CURRENT_SOURCE_DIR}/short_dotprod_generic.c +) + +######################################################################## +# Append gnuradio-core test sources +######################################################################## +list(APPEND test_gnuradio_core_sources + ${CMAKE_CURRENT_SOURCE_DIR}/qa_filter.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_fir_ccf.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_fir_fcc.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_fir_fff.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_fir_ccc.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_fir_scc.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_rotator.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gri_mmse_fir_interpolator.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gri_mmse_fir_interpolator_cc.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gri_fir_filter_with_buffer_ccf.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gri_fir_filter_with_buffer_ccc.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gri_fir_filter_with_buffer_fcc.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gri_fir_filter_with_buffer_fff.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gri_fir_filter_with_buffer_fsf.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gri_fir_filter_with_buffer_scc.cc +) + +######################################################################## +# Install runtime headers +######################################################################## +install(FILES + ${generated_filter_includes} + ${CMAKE_CURRENT_SOURCE_DIR}/complex_dotprod_generic.h + ${CMAKE_CURRENT_SOURCE_DIR}/complex_dotprod_x86.h + ${CMAKE_CURRENT_SOURCE_DIR}/fcomplex_dotprod_x86.h + ${CMAKE_CURRENT_SOURCE_DIR}/ccomplex_dotprod_generic.h + ${CMAKE_CURRENT_SOURCE_DIR}/ccomplex_dotprod_x86.h + ${CMAKE_CURRENT_SOURCE_DIR}/float_dotprod_generic.h + ${CMAKE_CURRENT_SOURCE_DIR}/float_dotprod_x86.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_altivec.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_cpu.h + ${CMAKE_CURRENT_SOURCE_DIR}/gri_fft_filter_fff_generic.h + ${CMAKE_CURRENT_SOURCE_DIR}/gri_fft_filter_ccc_generic.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_sysconfig_x86.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fir_sysconfig_powerpc.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_rotator.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_sincos.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_single_pole_iir.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_vec_types.h + ${CMAKE_CURRENT_SOURCE_DIR}/gri_goertzel.h + ${CMAKE_CURRENT_SOURCE_DIR}/gri_iir.h + ${CMAKE_CURRENT_SOURCE_DIR}/gri_mmse_fir_interpolator.h + ${CMAKE_CURRENT_SOURCE_DIR}/gri_mmse_fir_interpolator_cc.h + ${CMAKE_CURRENT_SOURCE_DIR}/qa_filter.h + ${CMAKE_CURRENT_SOURCE_DIR}/short_dotprod_generic.h + ${CMAKE_CURRENT_SOURCE_DIR}/short_dotprod_x86.h + ${CMAKE_CURRENT_SOURCE_DIR}/sse_debug.h + DESTINATION ${GR_INCLUDE_DIR}/gnuradio + COMPONENT "core_devel" +) + +######################################################################## +# Install swig headers +######################################################################## +if(ENABLE_PYTHON) +install(FILES + ${generated_filter_swigs} + ${CMAKE_CURRENT_SOURCE_DIR}/filter.i + ${CMAKE_CURRENT_BINARY_DIR}/filter_generated.i + DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig + COMPONENT "core_swig" +) +endif(ENABLE_PYTHON) + +######################################################################## +# Handle triple-threat files that have cc, h, and i +######################################################################## +set(gr_core_filter_triple_threats + gr_adaptive_fir_ccc + gr_adaptive_fir_ccf + gr_dc_blocker_cc + gr_dc_blocker_ff + gr_fft_filter_ccc + gr_fft_filter_fff + gr_filter_delay_fc + gr_fractional_interpolator_ff + gr_fractional_interpolator_cc + gr_goertzel_fc + gr_hilbert_fc + gr_iir_filter_ffd + gr_single_pole_iir_filter_ff + gr_single_pole_iir_filter_cc + gr_pfb_channelizer_ccf + gr_pfb_synthesizer_ccf + gr_pfb_decimator_ccf + gr_pfb_interpolator_ccf + gr_pfb_arb_resampler_ccf + gr_pfb_arb_resampler_fff + gr_pfb_clock_sync_ccf + gr_pfb_clock_sync_fff +) + +foreach(file_tt ${gr_core_filter_triple_threats}) + list(APPEND gnuradio_core_sources ${CMAKE_CURRENT_SOURCE_DIR}/${file_tt}.cc) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${file_tt}.h DESTINATION ${GR_INCLUDE_DIR}/gnuradio COMPONENT "core_devel") + if(ENABLE_PYTHON) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${file_tt}.i DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig COMPONENT "core_swig") + endif(ENABLE_PYTHON) +endforeach(file_tt ${gr_core_filter_triple_threats}) diff --git a/gnuradio-core/src/lib/filter/Makefile.gen b/gnuradio-core/src/lib/filter/Makefile.gen new file mode 100644 index 000000000..909899c05 --- /dev/null +++ b/gnuradio-core/src/lib/filter/Makefile.gen @@ -0,0 +1,124 @@ +# +# This file is machine generated. All edits will be overwritten +# +GENERATED_H = \ + gr_fir_ccc.h \ + gr_fir_ccc_generic.h \ + gr_fir_ccf.h \ + gr_fir_ccf_generic.h \ + gr_fir_fcc.h \ + gr_fir_fcc_generic.h \ + gr_fir_fff.h \ + gr_fir_fff_generic.h \ + gr_fir_filter_ccc.h \ + gr_fir_filter_ccf.h \ + gr_fir_filter_fcc.h \ + gr_fir_filter_fff.h \ + gr_fir_filter_fsf.h \ + gr_fir_filter_scc.h \ + gr_fir_fsf.h \ + gr_fir_fsf_generic.h \ + gr_fir_scc.h \ + gr_fir_scc_generic.h \ + gr_fir_sysconfig.h \ + gr_fir_sysconfig_generic.h \ + gr_fir_util.h \ + gr_freq_xlating_fir_filter_ccc.h \ + gr_freq_xlating_fir_filter_ccf.h \ + gr_freq_xlating_fir_filter_fcc.h \ + gr_freq_xlating_fir_filter_fcf.h \ + gr_freq_xlating_fir_filter_scc.h \ + gr_freq_xlating_fir_filter_scf.h \ + gr_interp_fir_filter_ccc.h \ + gr_interp_fir_filter_ccf.h \ + gr_interp_fir_filter_fcc.h \ + gr_interp_fir_filter_fff.h \ + gr_interp_fir_filter_fsf.h \ + gr_interp_fir_filter_scc.h \ + gr_rational_resampler_base_ccc.h \ + gr_rational_resampler_base_ccf.h \ + gr_rational_resampler_base_fcc.h \ + gr_rational_resampler_base_fff.h \ + gr_rational_resampler_base_fsf.h \ + gr_rational_resampler_base_scc.h \ + gri_fir_filter_with_buffer_ccc.h \ + gri_fir_filter_with_buffer_ccf.h \ + gri_fir_filter_with_buffer_fcc.h \ + gri_fir_filter_with_buffer_fff.h \ + gri_fir_filter_with_buffer_fsf.h \ + gri_fir_filter_with_buffer_scc.h + + +GENERATED_I = \ + gr_fir_filter_ccc.i \ + gr_fir_filter_ccf.i \ + gr_fir_filter_fcc.i \ + gr_fir_filter_fff.i \ + gr_fir_filter_fsf.i \ + gr_fir_filter_scc.i \ + gr_freq_xlating_fir_filter_ccc.i \ + gr_freq_xlating_fir_filter_ccf.i \ + gr_freq_xlating_fir_filter_fcc.i \ + gr_freq_xlating_fir_filter_fcf.i \ + gr_freq_xlating_fir_filter_scc.i \ + gr_freq_xlating_fir_filter_scf.i \ + gr_interp_fir_filter_ccc.i \ + gr_interp_fir_filter_ccf.i \ + gr_interp_fir_filter_fcc.i \ + gr_interp_fir_filter_fff.i \ + gr_interp_fir_filter_fsf.i \ + gr_interp_fir_filter_scc.i \ + gr_rational_resampler_base_ccc.i \ + gr_rational_resampler_base_ccf.i \ + gr_rational_resampler_base_fcc.i \ + gr_rational_resampler_base_fff.i \ + gr_rational_resampler_base_fsf.i \ + gr_rational_resampler_base_scc.i + +GENERATED_CC = \ + gr_fir_ccc.cc \ + gr_fir_ccc_generic.cc \ + gr_fir_ccf.cc \ + gr_fir_ccf_generic.cc \ + gr_fir_fcc.cc \ + gr_fir_fcc_generic.cc \ + gr_fir_fff.cc \ + gr_fir_fff_generic.cc \ + gr_fir_filter_ccc.cc \ + gr_fir_filter_ccf.cc \ + gr_fir_filter_fcc.cc \ + gr_fir_filter_fff.cc \ + gr_fir_filter_fsf.cc \ + gr_fir_filter_scc.cc \ + gr_fir_fsf.cc \ + gr_fir_fsf_generic.cc \ + gr_fir_scc.cc \ + gr_fir_scc_generic.cc \ + gr_fir_sysconfig.cc \ + gr_fir_sysconfig_generic.cc \ + gr_fir_util.cc \ + gr_freq_xlating_fir_filter_ccc.cc \ + gr_freq_xlating_fir_filter_ccf.cc \ + gr_freq_xlating_fir_filter_fcc.cc \ + gr_freq_xlating_fir_filter_fcf.cc \ + gr_freq_xlating_fir_filter_scc.cc \ + gr_freq_xlating_fir_filter_scf.cc \ + gr_interp_fir_filter_ccc.cc \ + gr_interp_fir_filter_ccf.cc \ + gr_interp_fir_filter_fcc.cc \ + gr_interp_fir_filter_fff.cc \ + gr_interp_fir_filter_fsf.cc \ + gr_interp_fir_filter_scc.cc \ + gr_rational_resampler_base_ccc.cc \ + gr_rational_resampler_base_ccf.cc \ + gr_rational_resampler_base_fcc.cc \ + gr_rational_resampler_base_fff.cc \ + gr_rational_resampler_base_fsf.cc \ + gr_rational_resampler_base_scc.cc \ + gri_fir_filter_with_buffer_ccc.cc \ + gri_fir_filter_with_buffer_ccf.cc \ + gri_fir_filter_with_buffer_fcc.cc \ + gri_fir_filter_with_buffer_fff.cc \ + gri_fir_filter_with_buffer_fsf.cc \ + gri_fir_filter_with_buffer_scc.cc + diff --git a/gnuradio-core/src/lib/filter/README b/gnuradio-core/src/lib/filter/README new file mode 100644 index 000000000..90c1584fc --- /dev/null +++ b/gnuradio-core/src/lib/filter/README @@ -0,0 +1,28 @@ +# +# 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. +# + +This directory holds filtering code, some of which is machine +generated. Which variations are generated is controlled by two +variables. For most everything, the global "signatures" +in generate_utils.py controls. + +For GrFreqXlatingFIRfilter<foo>, the global "fx_signatures" in +generate_GrFreqXlatingFIRfilterXXX.py controls. diff --git a/gnuradio-core/src/lib/filter/assembly.h b/gnuradio-core/src/lib/filter/assembly.h new file mode 100644 index 000000000..32477dfd7 --- /dev/null +++ b/gnuradio-core/src/lib/filter/assembly.h @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 _ASSEMBLY_H_ +#define _ASSEMBLY_H_ + +#if defined (__APPLE__) && defined (__APPLE_CC__) + +// XCode ignores the .scl and .type functions in XCode 2.2.1 and 2.3, +// but creates an error in XCode 2.4. Just ignore them. + +#define GLOB_SYMB(f) _ ## f + +#define DEF_FUNC_HEAD(f) /* none */ + +#define FUNC_TAIL(f) /* none*/ + +#elif !defined (__ELF__) + +/* + * Too bad, the following define does not work as expected --SF + * #define GLOB_SYMB(f) __USER_LABEL_PREFIX__ ## f + */ +#define GLOB_SYMB(f) _ ## f + +#define DEF_FUNC_HEAD(f) \ + .def GLOB_SYMB(f); .scl 2; .type 32; .endef + +#define FUNC_TAIL(f) /* none */ + + +#else /* !__ELF__ */ + + +#define GLOB_SYMB(f) f + +#define DEF_FUNC_HEAD(f) \ + .type GLOB_SYMB(f),@function \ + +#define FUNC_TAIL(f) \ + .Lfe1: \ + .size GLOB_SYMB(f),.Lfe1-GLOB_SYMB(f) + + +#endif /* !__ELF__ */ + + +#endif /* _ASSEMBLY_H_ */ diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow.S b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow.S new file mode 100644 index 000000000..f66356337 --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow.S @@ -0,0 +1,220 @@ +# +# Copyright 2002 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. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_ccomplex_blocks is != 0 +# +# +# ccomplex_dotprod_generic (const float *input, +# const float *taps, unsigned n_2_ccomplex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0] - input[1] * taps[1]; +# sum1 += input[0] * taps[1] + input[1] * taps[0]; +# sum2 += input[2] * taps[2] - input[3] * taps[3]; +# sum3 += input[2] * taps[3] + input[3] * taps[2]; +# +# input += 4; +# taps += 4; +# +# } while (--n_2_ccomplex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +# TODO: prefetch and better scheduling + +#include "assembly.h" + + .file "ccomplex_dotprod_3dnow.S" +// .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(ccomplex_dotprod_3dnow) + DEF_FUNC_HEAD(ccomplex_dotprod_3dnow) +GLOB_SYMB(ccomplex_dotprod_3dnow): + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %eax # input + movl 12(%ebp), %edx # taps + movl 16(%ebp), %ecx # n_2_ccomplex_blocks + + # zero accumulators + + pxor %mm6, %mm6 # mm6 = 0 0 + + movq 0(%eax), %mm0 + + pxor %mm7, %mm7 # mm7 = 0 0 + + movq 0(%edx), %mm2 + + movq 8(%eax), %mm1 + + shrl $1, %ecx # ecx = n_2_ccomplex_blocks / 2 + + movq 8(%edx), %mm3 + + jmp .L1_test + + # + # 4 taps / loop + # something like ?? cycles / loop + # + + .p2align 4 +.Loop1: + +# complex prod: C += A * B, w/ temp Z, mmPN=$80000000 +# +# movq (%eax), %mmA +# movq (%edx), %mmB +# +# # 3DNow! replacement for: pswapd %mmA, %mmZ +# # TODO: optimize the punpckhdq +# movq %mmA, %mmZ +# punpckhdq %mmZ, %mmZ +# punpckldq %mmA, %mmZ +# +# pfmul %mmB, %mmA +# pfmul %mmZ, %mmB +# +# # 3DNow! replacement for: pfpnacc %mmB, %mmA +# pxor %mmPN, %mmA +# pfacc %mmB, %mmA +# +# pfadd %mmA, %mmC + + +# A=mm0, B=mm2, Z=mm4 +# A'=mm1, B'=mm3, Z'=mm5 + + movq %mm0, %mm4 + movq %mm1, %mm5 + punpckhdq %mm4, %mm4 + punpckhdq %mm5, %mm5 + punpckldq %mm0, %mm4 + pfmul %mm2, %mm0 + punpckldq %mm1, %mm5 + pfmul %mm4, %mm2 + pfadd %mm0, %mm6 + movq 16(%edx), %mm0 + pfmul %mm3, %mm1 + pfadd %mm2, %mm7 + movq 16(%eax), %mm2 + pfadd %mm1, %mm6 + pfmul %mm5, %mm3 + movq 24(%edx), %mm1 + + movq %mm0, %mm4 + movq %mm1, %mm5 + + pfadd %mm3, %mm7 + movq 24(%eax), %mm3 + +# unroll + + punpckhdq %mm4, %mm4 + punpckhdq %mm5, %mm5 + punpckldq %mm0, %mm4 + pfmul %mm2, %mm0 + punpckldq %mm1, %mm5 + pfmul %mm4, %mm2 + pfadd %mm0, %mm6 + movq 32(%edx), %mm0 + pfmul %mm3, %mm1 + pfadd %mm2, %mm7 + movq 32(%eax), %mm2 + pfadd %mm1, %mm6 + pfmul %mm5, %mm3 + movq 40(%edx), %mm1 + + addl $32, %eax + addl $32, %edx + + pfadd %mm3, %mm7 + movq 8(%eax), %mm3 + +.L1_test: + decl %ecx + jge .Loop1 + + # We've handled the bulk of multiplies up to here. + # Let's see if original n_2_ccomplex_blocks was odd. + # If so, we've got 2 more taps to do. + + movl 16(%ebp), %ecx # n_2_ccomplex_blocks + andl $1, %ecx + je .Leven + + # The count was odd, do 2 more taps. + # Note that we've already got mm0/mm2 & mm1/mm3 preloaded + # from the main loop. + + movq %mm0, %mm4 + movq %mm1, %mm5 + punpckhdq %mm4, %mm4 + punpckhdq %mm5, %mm5 + punpckldq %mm0, %mm4 + pfmul %mm2, %mm0 + punpckldq %mm1, %mm5 + pfmul %mm4, %mm2 + pfadd %mm0, %mm6 + pfmul %mm3, %mm1 + pfadd %mm2, %mm7 + pfmul %mm5, %mm3 + pfadd %mm1, %mm6 + pfadd %mm3, %mm7 + +.Leven: + # mmNP: negative inversor + + pcmpeqd %mm0, %mm0 # set all bits to 1 + psllq $63, %mm0 # keep only hsb + + pxor %mm0, %mm6 + pfacc %mm7, %mm6 + + movl 20(%ebp), %eax # result + movq %mm6, (%eax) + + femms + + popl %ebp + ret + +FUNC_TAIL(ccomplex_dotprod_3dnow) + .ident "Hand coded x86 3DNow! assembly" + + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow64.S b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow64.S new file mode 100644 index 000000000..e81d21993 --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow64.S @@ -0,0 +1,217 @@ +# +# Copyright 2002,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. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_ccomplex_blocks is != 0 +# +# +# ccomplex_dotprod_generic (const float *input, +# const float *taps, unsigned n_2_ccomplex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0] - input[1] * taps[1]; +# sum1 += input[0] * taps[1] + input[1] * taps[0]; +# sum2 += input[2] * taps[2] - input[3] * taps[3]; +# sum3 += input[2] * taps[3] + input[3] * taps[2]; +# +# input += 4; +# taps += 4; +# +# } while (--n_2_ccomplex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +# TODO: prefetch and better scheduling + +#include "assembly.h" + + + .file "ccomplex_dotprod_3dnow64.S" +// .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(ccomplex_dotprod_3dnow) + DEF_FUNC_HEAD(ccomplex_dotprod_3dnow) +GLOB_SYMB(ccomplex_dotprod_3dnow): + + # intput: rdi, taps: rsi, n_2_ccomplex_blocks: rdx, result: rcx + + mov %rdx, %rax + + # zero accumulators + + pxor %mm6, %mm6 # mm6 = 0 0 + + movq 0(%rdi), %mm0 + + pxor %mm7, %mm7 # mm7 = 0 0 + + movq 0(%rsi), %mm2 + + movq 8(%rdi), %mm1 + + shr $1, %rax # rax = n_2_ccomplex_blocks / 2 + + movq 8(%rsi), %mm3 + + jmp .L1_test + + # + # 4 taps / loop + # something like ?? cycles / loop + # + + .p2align 4 +.Loop1: + +# complex prod: C += A * B, w/ temp Z, mmPN=$80000000 +# +# movq (%rdx), %mmA +# movq (%rsi), %mmB +# +# # 3DNow! replacement for: pswapd %mmA, %mmZ +# # TODO: optimize the punpckhdq +# movq %mmA, %mmZ +# punpckhdq %mmZ, %mmZ +# punpckldq %mmA, %mmZ +# +# pfmul %mmB, %mmA +# pfmul %mmZ, %mmB +# +# # 3DNow! replacement for: pfpnacc %mmB, %mmA +# pxor %mmPN, %mmA +# pfacc %mmB, %mmA +# +# pfadd %mmA, %mmC + + +# A=mm0, B=mm2, Z=mm4 +# A'=mm1, B'=mm3, Z'=mm5 + + movq %mm0, %mm4 + movq %mm1, %mm5 + punpckhdq %mm4, %mm4 + punpckhdq %mm5, %mm5 + punpckldq %mm0, %mm4 + pfmul %mm2, %mm0 + punpckldq %mm1, %mm5 + pfmul %mm4, %mm2 + pfadd %mm0, %mm6 + movq 16(%rsi), %mm0 + pfmul %mm3, %mm1 + pfadd %mm2, %mm7 + movq 16(%rdi), %mm2 + pfadd %mm1, %mm6 + pfmul %mm5, %mm3 + movq 24(%rsi), %mm1 + + movq %mm0, %mm4 + movq %mm1, %mm5 + + pfadd %mm3, %mm7 + movq 24(%rdi), %mm3 + +# unroll + + punpckhdq %mm4, %mm4 + punpckhdq %mm5, %mm5 + punpckldq %mm0, %mm4 + pfmul %mm2, %mm0 + punpckldq %mm1, %mm5 + pfmul %mm4, %mm2 + pfadd %mm0, %mm6 + movq 32(%rsi), %mm0 + pfmul %mm3, %mm1 + pfadd %mm2, %mm7 + movq 32(%rdi), %mm2 + pfadd %mm1, %mm6 + pfmul %mm5, %mm3 + movq 40(%rsi), %mm1 + + add $32, %rdi + add $32, %rsi + + pfadd %mm3, %mm7 + movq 8(%rdi), %mm3 + +.L1_test: + dec %rax + jge .Loop1 + + # We've handled the bulk of multiplies up to here. + # Let's see if original n_2_ccomplex_blocks was odd. + # If so, we've got 2 more taps to do. + + and $1, %rdx + je .Leven + + # The count was odd, do 2 more taps. + # Note that we've already got mm0/mm2 & mm1/mm3 preloaded + # from the main loop. + + movq %mm0, %mm4 + movq %mm1, %mm5 + punpckhdq %mm4, %mm4 + punpckhdq %mm5, %mm5 + punpckldq %mm0, %mm4 + pfmul %mm2, %mm0 + punpckldq %mm1, %mm5 + pfmul %mm4, %mm2 + pfadd %mm0, %mm6 + pfmul %mm3, %mm1 + pfadd %mm2, %mm7 + pfmul %mm5, %mm3 + pfadd %mm1, %mm6 + pfadd %mm3, %mm7 + +.Leven: + # mmNP: negative inversor + + pcmpeqd %mm0, %mm0 # set all bits to 1 + psllq $63, %mm0 # keep only hsb + + pxor %mm0, %mm6 + pfacc %mm7, %mm6 + + movq %mm6, (%rcx) + + femms + + retq + +FUNC_TAIL(ccomplex_dotprod_3dnow) + .ident "Hand coded x86_64 3DNow! assembly" + + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext.S b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext.S new file mode 100644 index 000000000..22c390bdd --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext.S @@ -0,0 +1,195 @@ +# +# Copyright 2002 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. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_ccomplex_blocks is != 0 +# +# +# ccomplex_dotprod_generic (const float *input, +# const float *taps, unsigned n_2_ccomplex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0] - input[1] * taps[1]; +# sum1 += input[0] * taps[1] + input[1] * taps[0]; +# sum2 += input[2] * taps[2] - input[3] * taps[3]; +# sum3 += input[2] * taps[3] + input[3] * taps[2]; +# +# input += 4; +# taps += 4; +# +# } while (--n_2_ccomplex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +# TODO: prefetch and better scheduling + +#include "assembly.h" + + .file "ccomplex_dotprod_3dnowext.S" +// .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(ccomplex_dotprod_3dnowext) + DEF_FUNC_HEAD(ccomplex_dotprod_3dnowext) +GLOB_SYMB(ccomplex_dotprod_3dnowext): + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %eax # input + movl 12(%ebp), %edx # taps + movl 16(%ebp), %ecx # n_2_ccomplex_blocks + + # zero accumulators + + pxor %mm6, %mm6 # mm6 = 0 0 + pxor %mm7, %mm7 # mm7 = 0 0 + + movq 0(%eax), %mm0 + movq 0(%edx), %mm2 + + shrl $1, %ecx # ecx = n_2_ccomplex_blocks / 2 + + movq 8(%eax), %mm1 + movq 8(%edx), %mm3 + + + jmp .L1_test + + # + # 4 taps / loop + # something like ?? cycles / loop + # + + .p2align 4 +.Loop1: + +# complex prod: C += A * B, w/ temp Z +# +# movq 0(%eax), %mmA +# movq 0(%edx), %mmB +# pswapd %mmA, %mmZ +# pfmul %mmB, %mmA +# pfmul %mmZ, %mmB +# pfpnacc %mmB, %mmA +# pfadd %mmA, %mmC + + +# A=mm0, B=mm2, Z=mm4 +# A'=mm1, B'=mm3, Z'=mm5 + + pswapd %mm0, %mm4 + pfmul %mm2, %mm0 + pswapd %mm1, %mm5 + pfmul %mm4, %mm2 + pfmul %mm3, %mm1 + pfpnacc %mm2, %mm0 + pfmul %mm5, %mm3 + movq 16(%edx), %mm2 + pfpnacc %mm3, %mm1 + movq 24(%edx), %mm3 + + pfadd %mm0, %mm6 + movq 16(%eax), %mm0 + pfadd %mm1, %mm7 + movq 24(%eax), %mm1 + +# unroll + + pswapd %mm0, %mm4 + pfmul %mm2, %mm0 + pswapd %mm1, %mm5 + pfmul %mm4, %mm2 + pfmul %mm3, %mm1 + pfpnacc %mm2, %mm0 + pfmul %mm5, %mm3 + movq 32(%edx), %mm2 + pfpnacc %mm3, %mm1 + movq 40(%edx), %mm3 + + pfadd %mm0, %mm6 + movq 32(%eax), %mm0 + pfadd %mm1, %mm7 + movq 40(%eax), %mm1 + + addl $32, %edx + addl $32, %eax + +.L1_test: + decl %ecx + jge .Loop1 + + # We've handled the bulk of multiplies up to here. + # Let's see if original n_2_ccomplex_blocks was odd. + # If so, we've got 2 more taps to do. + + movl 16(%ebp), %ecx # n_2_ccomplex_blocks + andl $1, %ecx + je .Leven + + # The count was odd, do 2 more taps. + # Note that we've already got mm0/mm2 & mm1/mm3 preloaded + # from the main loop. + +# A=mm0, B=mm2, Z=mm4 +# A'=mm1, B'=mm3, Z'=mm5 + + pswapd %mm0, %mm4 + pfmul %mm2, %mm0 + pswapd %mm1, %mm5 + pfmul %mm4, %mm2 + pfmul %mm3, %mm1 + pfpnacc %mm2, %mm0 + pfmul %mm5, %mm3 + pfpnacc %mm3, %mm1 + + pfadd %mm0, %mm6 + pfadd %mm1, %mm7 + +.Leven: + # at this point mm6 and mm7 contain partial sums + + pfadd %mm7, %mm6 + + movl 20(%ebp), %eax # result + movq %mm6, (%eax) + + femms + + popl %ebp + ret + +FUNC_TAIL(ccomplex_dotprod_3dnowext) + .ident "Hand coded x86 3DNow!Ext assembly" + + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext64.S b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext64.S new file mode 100644 index 000000000..75608914b --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext64.S @@ -0,0 +1,192 @@ +# +# Copyright 2002,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. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_ccomplex_blocks is != 0 +# +# +# ccomplex_dotprod_generic (const float *input, +# const float *taps, unsigned n_2_ccomplex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0] - input[1] * taps[1]; +# sum1 += input[0] * taps[1] + input[1] * taps[0]; +# sum2 += input[2] * taps[2] - input[3] * taps[3]; +# sum3 += input[2] * taps[3] + input[3] * taps[2]; +# +# input += 4; +# taps += 4; +# +# } while (--n_2_ccomplex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +# TODO: prefetch and better scheduling + +#include "assembly.h" + + .file "ccomplex_dotprod_3dnowext64.S" +// .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(ccomplex_dotprod_3dnowext) + DEF_FUNC_HEAD(ccomplex_dotprod_3dnowext) +GLOB_SYMB(ccomplex_dotprod_3dnowext): + + # intput: rdi, taps: rsi, n_2_ccomplex_blocks: rdx, result: rcx + + mov %rdx, %rax + + + # zero accumulators + + pxor %mm6, %mm6 # mm6 = 0 0 + pxor %mm7, %mm7 # mm7 = 0 0 + + movq 0(%rdi), %mm0 + movq 0(%rsi), %mm2 + + shr $1, %rax # rax = n_2_ccomplex_blocks / 2 + + movq 8(%rdi), %mm1 + movq 8(%rsi), %mm3 + + + jmp .L1_test + + # + # 4 taps / loop + # something like ?? cycles / loop + # + + .p2align 4 +.Loop1: + +# complex prod: C += A * B, w/ temp Z +# +# movq 0(%rdi), %mmA +# movq 0(%rsi), %mmB +# pswapd %mmA, %mmZ +# pfmul %mmB, %mmA +# pfmul %mmZ, %mmB +# pfpnacc %mmB, %mmA +# pfadd %mmA, %mmC + + +# A=mm0, B=mm2, Z=mm4 +# A'=mm1, B'=mm3, Z'=mm5 + + pswapd %mm0, %mm4 + pfmul %mm2, %mm0 + pswapd %mm1, %mm5 + pfmul %mm4, %mm2 + pfmul %mm3, %mm1 + pfpnacc %mm2, %mm0 + pfmul %mm5, %mm3 + movq 16(%rsi), %mm2 + pfpnacc %mm3, %mm1 + movq 24(%rsi), %mm3 + + pfadd %mm0, %mm6 + movq 16(%rdi), %mm0 + pfadd %mm1, %mm7 + movq 24(%rdi), %mm1 + +# unroll + + pswapd %mm0, %mm4 + pfmul %mm2, %mm0 + pswapd %mm1, %mm5 + pfmul %mm4, %mm2 + pfmul %mm3, %mm1 + pfpnacc %mm2, %mm0 + pfmul %mm5, %mm3 + movq 32(%rsi), %mm2 + pfpnacc %mm3, %mm1 + movq 40(%rsi), %mm3 + + pfadd %mm0, %mm6 + movq 32(%rdi), %mm0 + pfadd %mm1, %mm7 + movq 40(%rdi), %mm1 + + add $32, %rsi + add $32, %rdi + +.L1_test: + dec %rax + jge .Loop1 + + # We've handled the bulk of multiplies up to here. + # Let's see if original n_2_ccomplex_blocks was odd. + # If so, we've got 2 more taps to do. + + and $1, %rdx + je .Leven + + # The count was odd, do 2 more taps. + # Note that we've already got mm0/mm2 & mm1/mm3 preloaded + # from the main loop. + +# A=mm0, B=mm2, Z=mm4 +# A'=mm1, B'=mm3, Z'=mm5 + + pswapd %mm0, %mm4 + pfmul %mm2, %mm0 + pswapd %mm1, %mm5 + pfmul %mm4, %mm2 + pfmul %mm3, %mm1 + pfpnacc %mm2, %mm0 + pfmul %mm5, %mm3 + pfpnacc %mm3, %mm1 + + pfadd %mm0, %mm6 + pfadd %mm1, %mm7 + +.Leven: + # at this point mm6 and mm7 contain partial sums + + pfadd %mm7, %mm6 + + movq %mm6, (%rcx) # result + + femms + + retq + +FUNC_TAIL(ccomplex_dotprod_3dnowext) + .ident "Hand coded x86_64 3DNow!Ext assembly" + + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_generic.cc b/gnuradio-core/src/lib/filter/ccomplex_dotprod_generic.cc new file mode 100644 index 000000000..a6f392211 --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_generic.cc @@ -0,0 +1,58 @@ +/* -*- c -*- */ +/* + * Copyright 2002 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_complex.h> +#include "ccomplex_dotprod_generic.h" + +#include <iostream> + +void +ccomplex_dotprod_generic (const float *input, + const float *taps, unsigned n_2_ccomplex_blocks, + float *result) +{ + gr_complex sum0(0,0); + gr_complex sum1(0,0); + + std::cerr << "Blah!!!\n"; + do { + const gr_complex tap0(taps[0], taps[1]); + const gr_complex tap1(taps[2], taps[3]); + const gr_complex input0(input[0], input[1]); + const gr_complex input1(input[2], input[3]); + + sum0 += input0 * tap0; + sum1 += input1 * tap1; + + input += 8; + taps += 8; + + } while (--n_2_ccomplex_blocks != 0); + + + sum0 += sum1; + result[0] = sum0.real(); + result[1] = sum0.imag(); +} diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_generic.h b/gnuradio-core/src/lib/filter/ccomplex_dotprod_generic.h new file mode 100644 index 000000000..c7d761c07 --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_generic.h @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 _CCOMPLEX_DOTPROD_GENERIC_H_ +#define _CCOMPLEX_DOTPROD_GENERIC_H_ + +#include <gr_core_api.h> + +GR_CORE_API void +ccomplex_dotprod_generic (const float *input, + const float *taps, unsigned n_2_ccomplex_blocks, + float *result); + + +#endif /* _CCOMPLEX_DOTPROD_GENERIC_H_ */ diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse.S b/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse.S new file mode 100644 index 000000000..3d16c352e --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse.S @@ -0,0 +1,198 @@ +# +# Copyright 2002 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. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_ccomplex_blocks is != 0 +# +# +# ccomplex_dotprod_generic (const float *input, +# const float *taps, unsigned n_2_ccomplex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0] - input[1] * taps[1]; +# sum1 += input[0] * taps[1] + input[1] * taps[0]; +# sum2 += input[2] * taps[2] - input[3] * taps[3]; +# sum3 += input[2] * taps[3] + input[3] * taps[2]; +# +# input += 4; +# taps += 4; +# +# } while (--n_2_ccomplex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +# TODO: prefetch and better scheduling + +#include "assembly.h" + + .file "ccomplex_dotprod_sse.S" +// .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(ccomplex_dotprod_sse) + DEF_FUNC_HEAD(ccomplex_dotprod_sse) +GLOB_SYMB(ccomplex_dotprod_sse): + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %eax # input + movl 12(%ebp), %edx # taps + movl 16(%ebp), %ecx # n_2_ccomplex_blocks + + xorps %xmm6, %xmm6 # zero accumulators + + movaps 0(%eax), %xmm0 + + xorps %xmm7, %xmm7 # zero accumulators + + movaps 0(%edx), %xmm2 + + shrl $1, %ecx # ecx = n_2_ccomplex_blocks / 2 + + jmp .L1_test + + # + # 4 taps / loop + # something like ?? cycles / loop + # + + .p2align 4 +.Loop1: + +# complex prod: C += A * B, w/ temp Z & Y (or B), xmmPN=$0x8000000080000000 +# +# movaps (%eax), %xmmA +# movaps (%edx), %xmmB +# +# movaps %xmmA, %xmmZ +# shufps $0xb1, %xmmZ, %xmmZ # swap internals +# +# mulps %xmmB, %xmmA +# mulps %xmmZ, %xmmB +# +# # SSE replacement for: pfpnacc %xmmB, %xmmA +# xorps %xmmPN, %xmmA +# movaps %xmmA, %xmmZ +# unpcklps %xmmB, %xmmA +# unpckhps %xmmB, %xmmZ +# movaps %xmmZ, %xmmY +# shufps $0x44, %xmmA, %xmmZ # b01000100 +# shufps $0xee, %xmmY, %xmmA # b11101110 +# addps %xmmZ, %xmmA +# +# addps %xmmA, %xmmC + +# A=xmm0, B=xmm2, Z=xmm4 +# A'=xmm1, B'=xmm3, Z'=xmm5 + + movaps 16(%eax), %xmm1 + + movaps %xmm0, %xmm4 + mulps %xmm2, %xmm0 + + shufps $0xb1, %xmm4, %xmm4 # swap internals + movaps 16(%edx), %xmm3 + movaps %xmm1, %xmm5 + addps %xmm0, %xmm6 + mulps %xmm3, %xmm1 + shufps $0xb1, %xmm5, %xmm5 # swap internals + addps %xmm1, %xmm6 + mulps %xmm4, %xmm2 + movaps 32(%eax), %xmm0 + addps %xmm2, %xmm7 + mulps %xmm5, %xmm3 + + addl $32, %eax + + movaps 32(%edx), %xmm2 + addps %xmm3, %xmm7 + + addl $32, %edx + + + +.L1_test: + decl %ecx + jge .Loop1 + + # We've handled the bulk of multiplies up to here. + # Let's sse if original n_2_ccomplex_blocks was odd. + # If so, we've got 2 more taps to do. + + movl 16(%ebp), %ecx # n_2_ccomplex_blocks + andl $1, %ecx + je .Leven + + # The count was odd, do 2 more taps. + # Note that we've already got mm0/mm2 preloaded + # from the main loop. + + movaps %xmm0, %xmm4 + mulps %xmm2, %xmm0 + shufps $0xb1, %xmm4, %xmm4 # swap internals + addps %xmm0, %xmm6 + mulps %xmm4, %xmm2 + addps %xmm2, %xmm7 + + +.Leven: + # neg inversor + xorps %xmm1, %xmm1 + movl $0x80000000, 16(%ebp) + movss 16(%ebp), %xmm1 + shufps $0x11, %xmm1, %xmm1 # b00010001 # 0 -0 0 -0 + + # pfpnacc + xorps %xmm1, %xmm6 + + movaps %xmm6, %xmm2 + unpcklps %xmm7, %xmm6 + unpckhps %xmm7, %xmm2 + movaps %xmm2, %xmm3 + shufps $0x44, %xmm6, %xmm2 # b01000100 + shufps $0xee, %xmm3, %xmm6 # b11101110 + addps %xmm2, %xmm6 + + # xmm6 = r1 i2 r3 i4 + movl 20(%ebp), %eax # @result + movhlps %xmm6, %xmm4 # xmm4 = r3 i4 ?? ?? + addps %xmm4, %xmm6 # xmm6 = r1+r3 i2+i4 ?? ?? + movlps %xmm6, (%eax) # store low 2x32 bits (complex) to memory + + popl %ebp + ret + +FUNC_TAIL(ccomplex_dotprod_sse) + .ident "Hand coded x86 SSE assembly" + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse64.S b/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse64.S new file mode 100644 index 000000000..95ac3dac3 --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse64.S @@ -0,0 +1,195 @@ +# +# Copyright 2002,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. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_ccomplex_blocks is != 0 +# +# +# ccomplex_dotprod_generic (const float *input, +# const float *taps, unsigned n_2_ccomplex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0] - input[1] * taps[1]; +# sum1 += input[0] * taps[1] + input[1] * taps[0]; +# sum2 += input[2] * taps[2] - input[3] * taps[3]; +# sum3 += input[2] * taps[3] + input[3] * taps[2]; +# +# input += 4; +# taps += 4; +# +# } while (--n_2_ccomplex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +# TODO: prefetch and better scheduling + +#include "assembly.h" + + + .file "ccomplex_dotprod_sse64.S" +// .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(ccomplex_dotprod_sse) + DEF_FUNC_HEAD(ccomplex_dotprod_sse) +GLOB_SYMB(ccomplex_dotprod_sse): + + # intput: rdi, taps: rsi, n_2_ccomplex_blocks: rdx, result: rcx + + mov %rdx, %rax + + xorps %xmm6, %xmm6 # zero accumulators + + movaps 0(%rdi), %xmm0 + + xorps %xmm7, %xmm7 # zero accumulators + + movaps 0(%rsi), %xmm2 + + shr $1, %rax # rax = n_2_ccomplex_blocks / 2 + + jmp .L1_test + + # + # 4 taps / loop + # something like ?? cycles / loop + # + + .p2align 4 +.Loop1: + +# complex prod: C += A * B, w/ temp Z & Y (or B), xmmPN=$0x8000000080000000 +# +# movaps (%rdi), %xmmA +# movaps (%rsi), %xmmB +# +# movaps %xmmA, %xmmZ +# shufps $0xb1, %xmmZ, %xmmZ # swap internals +# +# mulps %xmmB, %xmmA +# mulps %xmmZ, %xmmB +# +# # SSE replacement for: pfpnacc %xmmB, %xmmA +# xorps %xmmPN, %xmmA +# movaps %xmmA, %xmmZ +# unpcklps %xmmB, %xmmA +# unpckhps %xmmB, %xmmZ +# movaps %xmmZ, %xmmY +# shufps $0x44, %xmmA, %xmmZ # b01000100 +# shufps $0xee, %xmmY, %xmmA # b11101110 +# addps %xmmZ, %xmmA +# +# addps %xmmA, %xmmC + +# A=xmm0, B=xmm2, Z=xmm4 +# A'=xmm1, B'=xmm3, Z'=xmm5 + + movaps 16(%rdi), %xmm1 + + movaps %xmm0, %xmm4 + mulps %xmm2, %xmm0 + + shufps $0xb1, %xmm4, %xmm4 # swap internals + movaps 16(%rsi), %xmm3 + movaps %xmm1, %xmm5 + addps %xmm0, %xmm6 + mulps %xmm3, %xmm1 + shufps $0xb1, %xmm5, %xmm5 # swap internals + addps %xmm1, %xmm6 + mulps %xmm4, %xmm2 + movaps 32(%rdi), %xmm0 + addps %xmm2, %xmm7 + mulps %xmm5, %xmm3 + + add $32, %rdi + + movaps 32(%rsi), %xmm2 + addps %xmm3, %xmm7 + + add $32, %rsi + + + +.L1_test: + dec %rax + jge .Loop1 + + # We've handled the bulk of multiplies up to here. + # Let's sse if original n_2_ccomplex_blocks was odd. + # If so, we've got 2 more taps to do. + + and $1, %rdx + je .Leven + + # The count was odd, do 2 more taps. + # Note that we've already got mm0/mm2 preloaded + # from the main loop. + + movaps %xmm0, %xmm4 + mulps %xmm2, %xmm0 + shufps $0xb1, %xmm4, %xmm4 # swap internals + addps %xmm0, %xmm6 + mulps %xmm4, %xmm2 + addps %xmm2, %xmm7 + + +.Leven: + # neg inversor + xorps %xmm1, %xmm1 + movl $0x80000000, -8(%rsp) + movss -8(%rsp), %xmm1 + shufps $0x11, %xmm1, %xmm1 # b00010001 # 0 -0 0 -0 + + # pfpnacc + xorps %xmm1, %xmm6 + + movaps %xmm6, %xmm2 + unpcklps %xmm7, %xmm6 + unpckhps %xmm7, %xmm2 + movaps %xmm2, %xmm3 + shufps $0x44, %xmm6, %xmm2 # b01000100 + shufps $0xee, %xmm3, %xmm6 # b11101110 + addps %xmm2, %xmm6 + + # xmm6 = r1 i2 r3 i4 + movhlps %xmm6, %xmm4 # xmm4 = r3 i4 ?? ?? + addps %xmm4, %xmm6 # xmm6 = r1+r3 i2+i4 ?? ?? + movlps %xmm6, (%rcx) # store low 2x32 bits (complex) to memory + + retq + +FUNC_TAIL(ccomplex_dotprod_sse) + .ident "Hand coded x86_64 SSE assembly" + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/gnuradio-core/src/lib/filter/ccomplex_dotprod_x86.h b/gnuradio-core/src/lib/filter/ccomplex_dotprod_x86.h new file mode 100644 index 000000000..ebb63c258 --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_x86.h @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 _CCOMPLEX_DOTPROD_X86_H_ +#define _CCOMPLEX_DOTPROD_X86_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void +ccomplex_dotprod_3dnow (const float *input, + const float *taps, unsigned n_2_ccomplex_blocks, float *result); + +void +ccomplex_dotprod_3dnowext (const float *input, + const float *taps, unsigned n_2_ccomplex_blocks, float *result); + +void +ccomplex_dotprod_sse (const float *input, + const float *taps, unsigned n_2_ccomplex_blocks, float *result); + +#ifdef __cplusplus +} +#endif + +#endif /* _CCOMPLEX_DOTPROD_X86_H_ */ diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_3dnow.S b/gnuradio-core/src/lib/filter/complex_dotprod_3dnow.S new file mode 100644 index 000000000..be49bb863 --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_3dnow.S @@ -0,0 +1,192 @@ +# +# Copyright 2002 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. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_complex_blocks is != 0 +# +# +# complex_dotprod_generic (const short *input, +# const float *taps, unsigned n_2_complex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[0] * taps[1]; +# sum2 += input[1] * taps[2]; +# sum3 += input[1] * taps[3]; +# +# input += 2; +# taps += 4; +# +# } while (--n_2_complex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +#include "assembly.h" + + .file "complex_dotprod_3dnow.S" +// .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(complex_dotprod_3dnow) + DEF_FUNC_HEAD(complex_dotprod_3dnow) +GLOB_SYMB(complex_dotprod_3dnow): + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %eax # input + movl 12(%ebp), %edx # taps + movl 16(%ebp), %ecx + + # zero accumulators + + pxor %mm4, %mm4 # mm4 = 0 0 + pxor %mm5, %mm5 # mm5 = 0 0 + pxor %mm6, %mm6 # mm6 = 0 0 + pxor %mm7, %mm7 # mm7 = 0 0 + + + shrl $1, %ecx # ecx = n_2_complex_blocks / 2 + + # pshufw & pi2fw + pxor %mm0, %mm0 + punpcklwd 0(%eax), %mm0 + psrad $16, %mm0 + punpckldq %mm0, %mm0 + pi2fd %mm0, %mm0 + + pxor %mm1, %mm1 + punpcklwd 0(%eax), %mm1 + psrad $16, %mm1 + punpckhdq %mm1, %mm1 + pi2fd %mm1, %mm1 + + pxor %mm2, %mm2 + pxor %mm3, %mm3 + + + jmp .L1_test + + # + # 4 taps / loop + # something like ?? cycles / loop + # + + .p2align 4 +.Loop1: + pfmul 0(%edx), %mm0 + pfadd %mm2, %mm6 + + pxor %mm2, %mm2 + punpcklwd 4(%eax), %mm2 + psrad $16, %mm2 + punpckldq %mm2, %mm2 + + pfmul 8(%edx), %mm1 + pfadd %mm3, %mm7 + pi2fd %mm2, %mm2 + + pxor %mm3, %mm3 + punpcklwd 4(%eax), %mm3 + psrad $16, %mm3 + punpckhdq %mm3, %mm3 + + pfmul 16(%edx), %mm2 + pfadd %mm0, %mm4 + pi2fd %mm3, %mm3 + + pxor %mm0, %mm0 + punpcklwd 8(%eax), %mm0 + psrad $16, %mm0 + punpckldq %mm0, %mm0 + + pfmul 24(%edx), %mm3 + pfadd %mm1, %mm5 + + pxor %mm1, %mm1 + punpcklwd 8(%eax), %mm1 + psrad $16, %mm1 + punpckhdq %mm1, %mm1 + + pi2fd %mm0, %mm0 + pi2fd %mm1, %mm1 + +#TODO: add prefetch + + addl $32, %edx + addl $8, %eax + +.L1_test: + decl %ecx + jge .Loop1 + + # We've handled the bulk of multiplies up to here. + # Now accumulate the final two additions and see if original + # n_2_complex_blocks was odd. If so, we've got 2 more + # taps to do. + + movl 16(%ebp), %ecx + pfadd %mm2, %mm6 + andl $1, %ecx + pfadd %mm3, %mm7 + je .Leven + + # The count was odd, do 2 more taps. + # Note that we've already got mm0 and mm1 preloaded + # from the main loop. + + pfmul 0(%edx), %mm0 + pfadd %mm0, %mm4 + pfmul 8(%edx), %mm1 + pfadd %mm1, %mm5 + +.Leven: + # at this point mm4, mm5, mm6 and mm7 contain partial sums + + pfadd %mm7, %mm6 + pfadd %mm5, %mm4 + + movl 20(%ebp), %eax # result + + pfadd %mm6, %mm4 + + movq %mm4, (%eax) + femms + + popl %ebp + ret + +FUNC_TAIL(complex_dotprod_3dnow) + .ident "Hand coded x86 3DNow! assembly" + + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_3dnow64.S b/gnuradio-core/src/lib/filter/complex_dotprod_3dnow64.S new file mode 100644 index 000000000..f1c813078 --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_3dnow64.S @@ -0,0 +1,187 @@ +# +# Copyright 2002,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. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_complex_blocks is != 0 +# +# +# complex_dotprod_generic (const short *input, +# const float *taps, unsigned n_2_complex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[0] * taps[1]; +# sum2 += input[1] * taps[2]; +# sum3 += input[1] * taps[3]; +# +# input += 2; +# taps += 4; +# +# } while (--n_2_complex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +#include "assembly.h" + + + .file "complex_dotprod_3dnow64.S" +// .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(complex_dotprod_3dnow) + DEF_FUNC_HEAD(complex_dotprod_3dnow) +GLOB_SYMB(complex_dotprod_3dnow): + + # intput: rdi, taps: rsi, n_2_ccomplex_blocks: rdx, result: rcx + + mov %rdx, %rax + + # zero accumulators + + pxor %mm4, %mm4 # mm4 = 0 0 + pxor %mm5, %mm5 # mm5 = 0 0 + pxor %mm6, %mm6 # mm6 = 0 0 + pxor %mm7, %mm7 # mm7 = 0 0 + + + shr $1, %rax # rax = n_2_complex_blocks / 2 + + # pshufw & pi2fw + pxor %mm0, %mm0 + punpcklwd 0(%rdi), %mm0 + psrad $16, %mm0 + punpckldq %mm0, %mm0 + pi2fd %mm0, %mm0 + + pxor %mm1, %mm1 + punpcklwd 0(%rdi), %mm1 + psrad $16, %mm1 + punpckhdq %mm1, %mm1 + pi2fd %mm1, %mm1 + + pxor %mm2, %mm2 + pxor %mm3, %mm3 + + + jmp .L1_test + + # + # 4 taps / loop + # something like ?? cycles / loop + # + + .p2align 4 +.Loop1: + pfmul 0(%rsi), %mm0 + pfadd %mm2, %mm6 + + pxor %mm2, %mm2 + punpcklwd 4(%rdi), %mm2 + psrad $16, %mm2 + punpckldq %mm2, %mm2 + + pfmul 8(%rsi), %mm1 + pfadd %mm3, %mm7 + pi2fd %mm2, %mm2 + + pxor %mm3, %mm3 + punpcklwd 4(%rdi), %mm3 + psrad $16, %mm3 + punpckhdq %mm3, %mm3 + + pfmul 16(%rsi), %mm2 + pfadd %mm0, %mm4 + pi2fd %mm3, %mm3 + + pxor %mm0, %mm0 + punpcklwd 8(%rdi), %mm0 + psrad $16, %mm0 + punpckldq %mm0, %mm0 + + pfmul 24(%rsi), %mm3 + pfadd %mm1, %mm5 + + pxor %mm1, %mm1 + punpcklwd 8(%rdi), %mm1 + psrad $16, %mm1 + punpckhdq %mm1, %mm1 + + pi2fd %mm0, %mm0 + pi2fd %mm1, %mm1 + +#TODO: add prefetch + + add $32, %rsi + add $8, %rdi + +.L1_test: + dec %rax + jge .Loop1 + + # We've handled the bulk of multiplies up to here. + # Now accumulate the final two additions and see if original + # n_2_complex_blocks was odd. If so, we've got 2 more + # taps to do. + + pfadd %mm2, %mm6 + and $1, %rdx + pfadd %mm3, %mm7 + je .Leven + + # The count was odd, do 2 more taps. + # Note that we've already got mm0 and mm1 preloaded + # from the main loop. + + pfmul 0(%rsi), %mm0 + pfadd %mm0, %mm4 + pfmul 8(%rsi), %mm1 + pfadd %mm1, %mm5 + +.Leven: + # at this point mm4, mm5, mm6 and mm7 contain partial sums + + pfadd %mm7, %mm6 + pfadd %mm5, %mm4 + pfadd %mm6, %mm4 + + movq %mm4, (%rcx) + femms + + retq + +FUNC_TAIL(complex_dotprod_3dnow) + .ident "Hand coded x86_64 3DNow! assembly" + + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext.S b/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext.S new file mode 100644 index 000000000..52f04f10c --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext.S @@ -0,0 +1,171 @@ +# +# Copyright 2002 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. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_complex_blocks is != 0 +# +# +# complex_dotprod_generic (const short *input, +# const float *taps, unsigned n_2_complex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[0] * taps[1]; +# sum2 += input[1] * taps[2]; +# sum3 += input[1] * taps[3]; +# +# input += 2; +# taps += 4; +# +# } while (--n_2_complex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +#include "assembly.h" + + .file "complex_dotprod_3dnowext.S" +// .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(complex_dotprod_3dnowext) + DEF_FUNC_HEAD(complex_dotprod_3dnowext) +GLOB_SYMB(complex_dotprod_3dnowext): + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %eax # input + movl 12(%ebp), %edx # taps + movl 16(%ebp), %ecx + + # zero accumulators + + pxor %mm4, %mm4 # mm4 = 0 0 + pxor %mm5, %mm5 # mm5 = 0 0 + pxor %mm6, %mm6 # mm6 = 0 0 + pxor %mm7, %mm7 # mm7 = 0 0 + + + shrl $1, %ecx # ecx = n_2_complex_blocks / 2 + + movd 0(%eax), %mm0 + pshufw $0x55, %mm0, %mm1 # b01010101 + pshufw $0, %mm0, %mm0 + + pxor %mm2, %mm2 + pxor %mm3, %mm3 + + pi2fw %mm1, %mm1 + pi2fw %mm0, %mm0 + + jmp .L1_test + + # + # 4 taps / loop + # something like ?? cycles / loop + # + + .p2align 4 +.Loop1: + pfmul 0(%edx), %mm0 + pfadd %mm2, %mm6 + + pshufw $0, 4(%eax), %mm2 + + pfmul 8(%edx), %mm1 + pfadd %mm3, %mm7 + pi2fw %mm2, %mm2 + + pshufw $0x55, 4(%eax), %mm3 # b01010101 + + pfmul 16(%edx), %mm2 + pi2fw %mm3, %mm3 + pfadd %mm0, %mm4 + + pshufw $0, 8(%eax), %mm0 + + pfmul 24(%edx), %mm3 + pfadd %mm1, %mm5 + + pshufw $0x55, 8(%eax), %mm1 # b01010101 + pi2fw %mm0, %mm0 + +#TODO: add prefetch + + addl $32, %edx + addl $8, %eax + pi2fw %mm1, %mm1 + +.L1_test: + decl %ecx + jge .Loop1 + + # We've handled the bulk of multiplies up to here. + # Now accumulate the final two additions and see if original + # n_2_complex_blocks was odd. If so, we've got 2 more + # taps to do. + + movl 16(%ebp), %ecx + pfadd %mm2, %mm6 + andl $1, %ecx + pfadd %mm3, %mm7 + je .Leven + + # The count was odd, do 2 more taps. + # Note that we've already got mm0 and mm1 preloaded + # from the main loop. + + pfmul 0(%edx), %mm0 + pfadd %mm0, %mm4 + pfmul 8(%edx), %mm1 + pfadd %mm1, %mm5 + +.Leven: + # at this point mm4, mm5, mm6 and mm7 contain partial sums + + pfadd %mm7, %mm6 + pfadd %mm5, %mm4 + + movl 20(%ebp), %eax # result + pfadd %mm6, %mm4 + movq %mm4, (%eax) + + femms + + popl %ebp + ret + +FUNC_TAIL(complex_dotprod_3dnowext) + .ident "Hand coded x86 3DNow!Ext assembly" + + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext64.S b/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext64.S new file mode 100644 index 000000000..6d7ad5ad4 --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext64.S @@ -0,0 +1,168 @@ +# +# Copyright 2002,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. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_complex_blocks is != 0 +# +# +# complex_dotprod_generic (const short *input, +# const float *taps, unsigned n_2_complex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[0] * taps[1]; +# sum2 += input[1] * taps[2]; +# sum3 += input[1] * taps[3]; +# +# input += 2; +# taps += 4; +# +# } while (--n_2_complex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +#include "assembly.h" + + + .file "complex_dotprod_3dnowext64.S" +// .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(complex_dotprod_3dnowext) + DEF_FUNC_HEAD(complex_dotprod_3dnowext) +GLOB_SYMB(complex_dotprod_3dnowext): + + # intput: rdi, taps: rsi, n_2_ccomplex_blocks: rdx, result: rcx + + mov %rdx, %rax + + # zero accumulators + + pxor %mm4, %mm4 # mm4 = 0 0 + pxor %mm5, %mm5 # mm5 = 0 0 + pxor %mm6, %mm6 # mm6 = 0 0 + pxor %mm7, %mm7 # mm7 = 0 0 + + + shr $1, %rax # rax = n_2_complex_blocks / 2 + + movd 0(%rdi), %mm0 + pshufw $0x55, %mm0, %mm1 # b01010101 + pshufw $0, %mm0, %mm0 + + pxor %mm2, %mm2 + pxor %mm3, %mm3 + + pi2fw %mm1, %mm1 + pi2fw %mm0, %mm0 + + jmp .L1_test + + # + # 4 taps / loop + # something like ?? cycles / loop + # + + .p2align 4 +.Loop1: + pfmul 0(%rsi), %mm0 + pfadd %mm2, %mm6 + + pshufw $0, 4(%rdi), %mm2 + + pfmul 8(%rsi), %mm1 + pfadd %mm3, %mm7 + pi2fw %mm2, %mm2 + + pshufw $0x55, 4(%rdi), %mm3 # b01010101 + + pfmul 16(%rsi), %mm2 + pi2fw %mm3, %mm3 + pfadd %mm0, %mm4 + + pshufw $0, 8(%rdi), %mm0 + + pfmul 24(%rsi), %mm3 + pfadd %mm1, %mm5 + + pshufw $0x55, 8(%rdi), %mm1 # b01010101 + pi2fw %mm0, %mm0 + +#TODO: add prefetch + + add $32, %rsi + add $8, %rdi + pi2fw %mm1, %mm1 + +.L1_test: + dec %rax + jge .Loop1 + + # We've handled the bulk of multiplies up to here. + # Now accumulate the final two additions and see if original + # n_2_complex_blocks was odd. If so, we've got 2 more + # taps to do. + + pfadd %mm2, %mm6 + and $1, %rdx + pfadd %mm3, %mm7 + je .Leven + + # The count was odd, do 2 more taps. + # Note that we've already got mm0 and mm1 preloaded + # from the main loop. + + pfmul 0(%rsi), %mm0 + pfadd %mm0, %mm4 + pfmul 8(%rsi), %mm1 + pfadd %mm1, %mm5 + +.Leven: + # at this point mm4, mm5, mm6 and mm7 contain partial sums + + pfadd %mm7, %mm6 + pfadd %mm5, %mm4 + + pfadd %mm6, %mm4 + movq %mm4, (%rcx) + + femms + + retq + +FUNC_TAIL(complex_dotprod_3dnowext) + .ident "Hand coded x86_64 3DNow!Ext assembly" + + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_generic.cc b/gnuradio-core/src/lib/filter/complex_dotprod_generic.cc new file mode 100644 index 000000000..229cbe978 --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_generic.cc @@ -0,0 +1,54 @@ +/* -*- c -*- */ +/* + * Copyright 2002 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_complex.h> +#include "complex_dotprod_generic.h" + + +void +complex_dotprod_generic (const short *input, + const float *taps, unsigned n_2_complex_blocks, + float *result) +{ + gr_complex sum0(0,0); + gr_complex sum1(0,0); + + do { + const gr_complex tap0(taps[0], taps[1]); + const gr_complex tap1(taps[2], taps[3]); + + sum0 += (float)input[0] * tap0; + sum1 += (float)input[1] * tap1; + + input += 4; + taps += 8; + + } while (--n_2_complex_blocks != 0); + + + sum0 += sum1; + result[0] = sum0.real(); + result[1] = sum0.imag(); +} diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_generic.h b/gnuradio-core/src/lib/filter/complex_dotprod_generic.h new file mode 100644 index 000000000..152f6e459 --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_generic.h @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 _COMPLEX_DOTPROD_GENERIC_H_ +#define _COMPLEX_DOTPROD_GENERIC_H_ + +#include <gr_core_api.h> + +GR_CORE_API void +complex_dotprod_generic (const short *input, + const float *taps, unsigned n_2_complex_blocks, + float *result); + + +#endif /* _COMPLEX_DOTPROD_GENERIC_H_ */ diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_sse.S b/gnuradio-core/src/lib/filter/complex_dotprod_sse.S new file mode 100644 index 000000000..fb998cc45 --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_sse.S @@ -0,0 +1,206 @@ +# +# Copyright 2002 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. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_complex_blocks is != 0 +# +# +# complex_dotprod_generic (const short *input, +# const float *taps, unsigned n_2_complex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[0] * taps[1]; +# sum2 += input[1] * taps[2]; +# sum3 += input[1] * taps[3]; +# +# input += 2; +# taps += 4; +# +# } while (--n_2_complex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +# TODO: prefetch and better scheduling + +#include "assembly.h" + + + .file "complex_dotprod_sse.S" +// .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(complex_dotprod_sse) + DEF_FUNC_HEAD(complex_dotprod_sse) +GLOB_SYMB(complex_dotprod_sse): + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %eax # input + movl 12(%ebp), %edx # taps + movl 16(%ebp), %ecx + + + # xmm0 xmm1 xmm2 xmm3 are used to hold taps and the result of mults + # xmm4 xmm5 xmm6 xmm7 are used to hold the accumulated results + + xorps %xmm4, %xmm4 # zero two accumulators + xorps %xmm5, %xmm5 # xmm5 holds zero for use below + + # first handle any non-zero remainder of (n_2_complex_blocks % 4) + + andl $0x3, %ecx + jmp .L1_test + + .p2align 4 +.Loop1: + + pxor %mm0, %mm0 + punpcklwd 0(%eax), %mm0 + psrad $16, %mm0 + cvtpi2ps %mm0, %xmm0 + shufps $0x50, %xmm0, %xmm0 + + mulps (%edx), %xmm0 + addl $0x10, %edx + addl $4, %eax + addps %xmm0, %xmm4 +.L1_test: + decl %ecx + jge .Loop1 + + + # set up for primary loop which is unrolled 4 times + + movl 16(%ebp), %ecx + movaps %xmm5, %xmm6 # zero remaining accumulators + movaps %xmm5, %xmm7 + + shrl $2, %ecx # n_2_complex_blocks / 4 + je .Lcleanup # if zero, take short path + + # finish setup and loop priming + + pxor %mm0, %mm0 + punpcklwd 0(%eax), %mm0 + psrad $16, %mm0 + cvtpi2ps %mm0, %xmm0 + shufps $0x50, %xmm0, %xmm0 + + movaps %xmm5, %xmm2 + + pxor %mm1, %mm1 + punpcklwd 4(%eax), %mm1 + psrad $16, %mm1 + cvtpi2ps %mm1, %xmm1 + shufps $0x50, %xmm1, %xmm1 + + movaps %xmm5, %xmm3 + + # we know ecx is not zero, we checked above, + # hence enter loop at top + + .p2align 4 +.Loop2: + mulps (%edx), %xmm0 + addps %xmm2, %xmm6 + + pxor %mm2, %mm2 + punpcklwd 8(%eax), %mm2 + psrad $16, %mm2 + cvtpi2ps %mm2, %xmm2 + shufps $0x50, %xmm2, %xmm2 + + mulps 0x10(%edx), %xmm1 + addps %xmm3, %xmm7 + + pxor %mm3, %mm3 + punpcklwd 12(%eax), %mm3 + psrad $16, %mm3 + cvtpi2ps %mm3, %xmm3 + shufps $0x50, %xmm3, %xmm3 + + mulps 0x20(%edx), %xmm2 + addps %xmm0, %xmm4 + + pxor %mm0, %mm0 + punpcklwd 16(%eax), %mm0 + psrad $16, %mm0 + cvtpi2ps %mm0, %xmm0 + shufps $0x50, %xmm0, %xmm0 + + mulps 0x30(%edx), %xmm3 + addps %xmm1, %xmm5 + + pxor %mm1, %mm1 + punpcklwd 20(%eax), %mm1 + psrad $16, %mm1 + cvtpi2ps %mm1, %xmm1 + shufps $0x50, %xmm1, %xmm1 + + addl $0x40, %edx + addl $0x10, %eax + decl %ecx + jne .Loop2 + + # OK, now we've done with all the multiplies, but + # we still need to handle the unaccumulated + # products in xmm2 and xmm3 + + addps %xmm2, %xmm6 + addps %xmm3, %xmm7 + + # now we want to add all accumulators into xmm4 + + addps %xmm5, %xmm4 + addps %xmm6, %xmm7 + addps %xmm7, %xmm4 + + + # At this point, xmm4 contains 2x2 partial sums. We need + # to compute a "horizontal complex add" across xmm4. + +.Lcleanup: # xmm4 = r1 i2 r3 i4 + movl 20(%ebp), %eax # @result + movhlps %xmm4, %xmm0 # xmm0 = ?? ?? r1 r2 + addps %xmm4, %xmm0 # xmm0 = ?? ?? r1+r3 i2+i4 + movlps %xmm0, (%eax) # store low 2x32 bits (complex) to memory + + emms + popl %ebp + ret + +FUNC_TAIL(complex_dotprod_sse) + .ident "Hand coded x86 SSE assembly" + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_sse64.S b/gnuradio-core/src/lib/filter/complex_dotprod_sse64.S new file mode 100644 index 000000000..67d3519e4 --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_sse64.S @@ -0,0 +1,202 @@ +# +# Copyright 2002,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. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_complex_blocks is != 0 +# +# +# complex_dotprod_generic (const short *input, +# const float *taps, unsigned n_2_complex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[0] * taps[1]; +# sum2 += input[1] * taps[2]; +# sum3 += input[1] * taps[3]; +# +# input += 2; +# taps += 4; +# +# } while (--n_2_complex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +# TODO: prefetch and better scheduling + +#include "assembly.h" + + + .file "complex_dotprod_sse64.S" +// .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(complex_dotprod_sse) + DEF_FUNC_HEAD(complex_dotprod_sse) +GLOB_SYMB(complex_dotprod_sse): + + # intput: rdi, taps: rsi, n_2_ccomplex_blocks: rdx, result: rcx + + mov %rdx, %rax + + + # xmm0 xmm1 xmm2 xmm3 are used to hold taps and the result of mults + # xmm4 xmm5 xmm6 xmm7 are used to hold the accumulated results + + xorps %xmm4, %xmm4 # zero two accumulators + xorps %xmm5, %xmm5 # xmm5 holds zero for use below + + # first handle any non-zero remainder of (n_2_complex_blocks % 4) + + and $0x3, %rax + jmp .L1_test + + .p2align 4 +.Loop1: + + pxor %mm0, %mm0 + punpcklwd 0(%rdi), %mm0 + psrad $16, %mm0 + cvtpi2ps %mm0, %xmm0 + shufps $0x50, %xmm0, %xmm0 + + mulps (%rsi), %xmm0 + add $0x10, %rsi + add $4, %rdi + addps %xmm0, %xmm4 +.L1_test: + dec %rax + jge .Loop1 + + + # set up for primary loop which is unrolled 4 times + + movaps %xmm5, %xmm6 # zero remaining accumulators + shr $2, %rdx # n_2_complex_blocks / 4 + movaps %xmm5, %xmm7 + + je .Lcleanup # if zero, take short path + + # finish setup and loop priming + + pxor %mm0, %mm0 + punpcklwd 0(%rdi), %mm0 + psrad $16, %mm0 + cvtpi2ps %mm0, %xmm0 + shufps $0x50, %xmm0, %xmm0 + + movaps %xmm5, %xmm2 + + pxor %mm1, %mm1 + punpcklwd 4(%rdi), %mm1 + psrad $16, %mm1 + cvtpi2ps %mm1, %xmm1 + shufps $0x50, %xmm1, %xmm1 + + movaps %xmm5, %xmm3 + + # we know rax is not zero, we checked above, + # hence enter loop at top + + .p2align 4 +.Loop2: + mulps (%rsi), %xmm0 + addps %xmm2, %xmm6 + + pxor %mm2, %mm2 + punpcklwd 8(%rdi), %mm2 + psrad $16, %mm2 + cvtpi2ps %mm2, %xmm2 + shufps $0x50, %xmm2, %xmm2 + + mulps 0x10(%rsi), %xmm1 + addps %xmm3, %xmm7 + + pxor %mm3, %mm3 + punpcklwd 12(%rdi), %mm3 + psrad $16, %mm3 + cvtpi2ps %mm3, %xmm3 + shufps $0x50, %xmm3, %xmm3 + + mulps 0x20(%rsi), %xmm2 + addps %xmm0, %xmm4 + + pxor %mm0, %mm0 + punpcklwd 16(%rdi), %mm0 + psrad $16, %mm0 + cvtpi2ps %mm0, %xmm0 + shufps $0x50, %xmm0, %xmm0 + + mulps 0x30(%rsi), %xmm3 + addps %xmm1, %xmm5 + + pxor %mm1, %mm1 + punpcklwd 20(%rdi), %mm1 + psrad $16, %mm1 + cvtpi2ps %mm1, %xmm1 + shufps $0x50, %xmm1, %xmm1 + + add $0x40, %rsi + add $0x10, %rdi + dec %rdx + jne .Loop2 + + # OK, now we've done with all the multiplies, but + # we still need to handle the unaccumulated + # products in xmm2 and xmm3 + + addps %xmm2, %xmm6 + addps %xmm3, %xmm7 + + # now we want to add all accumulators into xmm4 + + addps %xmm5, %xmm4 + addps %xmm6, %xmm7 + addps %xmm7, %xmm4 + + + # At this point, xmm4 contains 2x2 partial sums. We need + # to compute a "horizontal complex add" across xmm4. + +.Lcleanup: # xmm4 = r1 i2 r3 i4 + movhlps %xmm4, %xmm0 # xmm0 = ?? ?? r1 r2 + addps %xmm4, %xmm0 # xmm0 = ?? ?? r1+r3 i2+i4 + movlps %xmm0, (%rcx) # store low 2x32 bits (complex) to memory + + emms + retq + +FUNC_TAIL(complex_dotprod_sse) + .ident "Hand coded x86_64 SSE assembly" + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/gnuradio-core/src/lib/filter/complex_dotprod_x86.h b/gnuradio-core/src/lib/filter/complex_dotprod_x86.h new file mode 100644 index 000000000..aad9fb5e9 --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_x86.h @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 _COMPLEX_DOTPROD_X86_H_ +#define _COMPLEX_DOTPROD_X86_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void +complex_dotprod_3dnow (const short *input, + const float *taps, unsigned n_2_complex_blocks, float *result); + +void +complex_dotprod_3dnowext (const short *input, + const float *taps, unsigned n_2_complex_blocks, float *result); + +void +complex_dotprod_sse (const short *input, + const float *taps, unsigned n_2_complex_blocks, float *result); + +#ifdef __cplusplus +} +#endif + +#endif /* _COMPLEX_DOTPROD_X86_H_ */ diff --git a/gnuradio-core/src/lib/filter/dotprod_ccf_armv7_a.c b/gnuradio-core/src/lib/filter/dotprod_ccf_armv7_a.c new file mode 100644 index 000000000..c125b49b3 --- /dev/null +++ b/gnuradio-core/src/lib/filter/dotprod_ccf_armv7_a.c @@ -0,0 +1,90 @@ +/* -*- 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <dotprod_ccf_armv7_a.h> + +/*! + * \param x any value + * \param pow2 must be a power of 2 + * \returns \p x rounded down to a multiple of \p pow2. + */ +static inline size_t +gr_p2_round_down(size_t x, size_t pow2) +{ + return x & -pow2; +} + + +#ifndef HAVE_MFPU_NEON + +void +dotprod_ccf_armv7_a(const float *a, const float *b, float *res, size_t n) +{ + size_t i; + res[0] = 0; + res[1] = 0; + + for (i = 0; i < n; i++){ + res[0] += a[2*i] * b[i]; + res[1] += a[2*i+1] * b[i]; + } +} + +#else + +/* + * preconditions: + * + * n > 0 and a multiple of 4 + * a 4-byte aligned + * b 16-byte aligned + */ +void +dotprod_ccf_armv7_a(const float *a, const float *b, float *res, size_t n) +{ + + asm volatile( + "vmov.f32 q14, #0.0 \n\t" + "vmov.f32 q15, #0.0 \n\t" + "1: \n\t" + "subs %2, %2, #4 \n\t" + "vld2.f32 {q0-q1}, [%0]! \n\t" + "vld1.f32 {q2}, [%1]! \n\t" + "vmla.f32 q14, q0, q2 \n\t" + "vmla.f32 q15, q1, q2 \n\t" + "bgt 1b \n\t" + "vpadd.f32 d0, d28, d29 \n\t" + "vpadd.f32 d1, d30, d31 \n\t" + "vpadd.f32 d0, d0, d1 \n\t" + "vst1.f32 {d0}, [%3] \n\t" + + : "+&r"(a), "+&r"(b), "+&r"(n) + : "r"(res) + : "memory", "d0", "d1", "d2", "d3", "d4", "d5", + "d28", "d29", "d30", "d31" ); +} + + +#endif diff --git a/gnuradio-core/src/lib/filter/dotprod_ccf_armv7_a.h b/gnuradio-core/src/lib/filter/dotprod_ccf_armv7_a.h new file mode 100644 index 000000000..e42d6d10b --- /dev/null +++ b/gnuradio-core/src/lib/filter/dotprod_ccf_armv7_a.h @@ -0,0 +1,47 @@ +/* -*- 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef INCLUDED_DOTPROD_CCF_ARMV7_A_H +#define INCLUDED_DOTPROD_CCF_ARMV7_A_H + +#include <stddef.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * <pre> + * + * preconditions: + * + * n > 0 and a multiple of 4 + * a 4-byte aligned + * b 16-byte aligned + * + * </pre> + */ +void dotprod_ccf_armv7_a(const float *a, const float *b, float *res, size_t n); + +#ifdef __cplusplus +} +#endif + +#endif /* INCLUDED_DOTPROD_CCF_ARMV7_A_H */ diff --git a/gnuradio-core/src/lib/filter/dotprod_fff_altivec.c b/gnuradio-core/src/lib/filter/dotprod_fff_altivec.c new file mode 100644 index 000000000..53d6df714 --- /dev/null +++ b/gnuradio-core/src/lib/filter/dotprod_fff_altivec.c @@ -0,0 +1,162 @@ +/* -*- 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <dotprod_fff_altivec.h> +#include <gr_altivec.h> + +/*! + * \param x any value + * \param pow2 must be a power of 2 + * \returns \p x rounded down to a multiple of \p pow2. + */ +static inline size_t +gr_p2_round_down(size_t x, size_t pow2) +{ + return x & -pow2; +} + + +#if 0 + +float +dotprod_fff_altivec(const float *a, const float *b, size_t n) +{ + float sum = 0; + for (size_t i = 0; i < n; i++){ + sum += a[i] * b[i]; + } + return sum; +} + +#else + +/* + * preconditions: + * + * n > 0 and a multiple of 4 + * a 4-byte aligned + * b 16-byte aligned + */ +float +dotprod_fff_altivec(const float *_a, const float *_b, size_t n) +{ + const vec_float4 *a = (const vec_float4 *) _a; + const vec_float4 *b = (const vec_float4 *) _b; + + static const size_t UNROLL_CNT = 4; + + n = gr_p2_round_down(n, 4); + size_t loop_cnt = n / (UNROLL_CNT * FLOATS_PER_VEC); + size_t nleft = n % (UNROLL_CNT * FLOATS_PER_VEC); + + // printf("n = %zd, loop_cnt = %zd, nleft = %zd\n", n, loop_cnt, nleft); + + // Used with vperm to build a* from p* + vec_uchar16 lvsl_a = vec_lvsl(0, _a); + + vec_float4 p0, p1, p2, p3; + vec_float4 a0, a1, a2, a3; + vec_float4 b0, b1, b2, b3; + vec_float4 acc0 = {0, 0, 0, 0}; + vec_float4 acc1 = {0, 0, 0, 0}; + vec_float4 acc2 = {0, 0, 0, 0}; + vec_float4 acc3 = {0, 0, 0, 0}; + + // wind in + + p0 = vec_ld(0*VS, a); + p1 = vec_ld(1*VS, a); + p2 = vec_ld(2*VS, a); + p3 = vec_ld(3*VS, a); + a += UNROLL_CNT; + + a0 = vec_perm(p0, p1, lvsl_a); + b0 = vec_ld(0*VS, b); + p0 = vec_ld(0*VS, a); + + size_t i; + for (i = 0; i < loop_cnt; i++){ + + a1 = vec_perm(p1, p2, lvsl_a); + b1 = vec_ld(1*VS, b); + p1 = vec_ld(1*VS, a); + acc0 = vec_madd(a0, b0, acc0); + + a2 = vec_perm(p2, p3, lvsl_a); + b2 = vec_ld(2*VS, b); + p2 = vec_ld(2*VS, a); + acc1 = vec_madd(a1, b1, acc1); + + a3 = vec_perm(p3, p0, lvsl_a); + b3 = vec_ld(3*VS, b); + p3 = vec_ld(3*VS, a); + acc2 = vec_madd(a2, b2, acc2); + + a += UNROLL_CNT; + b += UNROLL_CNT; + + a0 = vec_perm(p0, p1, lvsl_a); + b0 = vec_ld(0*VS, b); + p0 = vec_ld(0*VS, a); + acc3 = vec_madd(a3, b3, acc3); + } + + /* + * The compiler ought to be able to figure out that 0, 4, 8 and 12 + * are the only possible values for nleft. + */ + switch (nleft){ + case 0: + break; + + case 4: + acc0 = vec_madd(a0, b0, acc0); + break; + + case 8: + a1 = vec_perm(p1, p2, lvsl_a); + b1 = vec_ld(1*VS, b); + acc0 = vec_madd(a0, b0, acc0); + acc1 = vec_madd(a1, b1, acc1); + break; + + case 12: + a1 = vec_perm(p1, p2, lvsl_a); + b1 = vec_ld(1*VS, b); + acc0 = vec_madd(a0, b0, acc0); + a2 = vec_perm(p2, p3, lvsl_a); + b2 = vec_ld(2*VS, b); + acc1 = vec_madd(a1, b1, acc1); + acc2 = vec_madd(a2, b2, acc2); + break; + } + + acc0 = acc0 + acc1; + acc2 = acc2 + acc3; + acc0 = acc0 + acc2; + + return horizontal_add_f(acc0); +} + +#endif diff --git a/gnuradio-core/src/lib/filter/dotprod_fff_altivec.h b/gnuradio-core/src/lib/filter/dotprod_fff_altivec.h new file mode 100644 index 000000000..a52370d56 --- /dev/null +++ b/gnuradio-core/src/lib/filter/dotprod_fff_altivec.h @@ -0,0 +1,50 @@ +/* -*- 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef INCLUDED_DOTPROD_FFF_ALTIVEC_H +#define INCLUDED_DOTPROD_FFF_ALTIVEC_H + +#include <gr_core_api.h> +#include <stddef.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * <pre> + * + * preconditions: + * + * n > 0 and a multiple of 4 + * a 4-byte aligned + * b 16-byte aligned + * + * </pre> + */ +float +dotprod_fff_altivec(const float *a, const float *b, size_t n); + +#ifdef __cplusplus +} +#endif + + +#endif /* INCLUDED_DOTPROD_FFF_ALTIVEC_H */ diff --git a/gnuradio-core/src/lib/filter/dotprod_fff_armv7_a.c b/gnuradio-core/src/lib/filter/dotprod_fff_armv7_a.c new file mode 100644 index 000000000..23bbef033 --- /dev/null +++ b/gnuradio-core/src/lib/filter/dotprod_fff_armv7_a.c @@ -0,0 +1,87 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <dotprod_fff_armv7_a.h> + +/*! + * \param x any value + * \param pow2 must be a power of 2 + * \returns \p x rounded down to a multiple of \p pow2. + */ +static inline size_t +gr_p2_round_down(size_t x, size_t pow2) +{ + return x & -pow2; +} + + +#ifndef HAVE_MFPU_NEON + +float +dotprod_fff_armv7_a(const float *a, const float *b, size_t n) +{ + float sum = 0; + size_t i; + for (i = 0; i < n; i++){ + sum += a[i] * b[i]; + } + return sum; +} + +#else + +/* + * preconditions: + * + * n > 0 and a multiple of 4 + * a 4-byte aligned + * b 16-byte aligned + */ +float +dotprod_fff_armv7_a(const float *a, const float *b, size_t n) +{ + float s = 0; + + asm ("vmov.f32 q8, #0.0 \n\t" + "vmov.f32 q9, #0.0 \n\t" + "1: \n\t" + "subs %3, %3, #8 \n\t" + "vld1.32 {d0,d1,d2,d3}, [%1]! \n\t" + "vld1.32 {d4,d5,d6,d7}, [%2]! \n\t" + "vmla.f32 q8, q0, q2 \n\t" + "vmla.f32 q9, q1, q3 \n\t" + "bgt 1b \n\t" + "vadd.f32 q8, q8, q9 \n\t" + "vpadd.f32 d0, d16, d17 \n\t" + "vadd.f32 %0, s0, s1 \n\t" + : "=w"(s), "+r"(a), "+r"(b), "+r"(n) + :: "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", + "d16", "d17", "d18", "d19"); + + return s; + +} + +#endif diff --git a/gnuradio-core/src/lib/filter/dotprod_fff_armv7_a.h b/gnuradio-core/src/lib/filter/dotprod_fff_armv7_a.h new file mode 100644 index 000000000..6cea45cea --- /dev/null +++ b/gnuradio-core/src/lib/filter/dotprod_fff_armv7_a.h @@ -0,0 +1,50 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef INCLUDED_DOTPROD_FFF_ARMV7_A_H +#define INCLUDED_DOTPROD_FFF_ARMV7_A_H + +#include <gr_core_api.h> +#include <stddef.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/*! + * <pre> + * + * preconditions: + * + * n > 0 and a multiple of 4 + * a 4-byte aligned + * b 16-byte aligned + * + * </pre> + */ +float +dotprod_fff_armv7_a(const float *a, const float *b, size_t n); + +#ifdef __cplusplus +} +#endif + + +#endif /* INCLUDED_DOTPROD_FFF_ARMV7_A_H */ diff --git a/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow.S b/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow.S new file mode 100644 index 000000000..536e46dc1 --- /dev/null +++ b/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow.S @@ -0,0 +1,176 @@ +# +# Copyright 2002 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. +# + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_complex_blocks is != 0 +# +# +# fcomplex_dotprod_generic (const float *input, +# const float *taps, unsigned n_2_complex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[0] * taps[1]; +# sum2 += input[1] * taps[2]; +# sum3 += input[1] * taps[3]; +# +# input += 2; +# taps += 4; +# +# } while (--n_2_complex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +#include "assembly.h" + + + .file "fcomplex_dotprod_3dnow.S" +// .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(fcomplex_dotprod_3dnow) + DEF_FUNC_HEAD(fcomplex_dotprod_3dnow) +GLOB_SYMB(fcomplex_dotprod_3dnow): + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %eax # input + movl 12(%ebp), %edx # taps + movl 16(%ebp), %ecx + + # zero accumulators + + pxor %mm4, %mm4 # mm4 = 0 0 + pxor %mm5, %mm5 # mm5 = 0 0 + pxor %mm6, %mm6 # mm6 = 0 0 + pxor %mm7, %mm7 # mm7 = 0 0 + + shrl $1, %ecx # ecx = n_2_complex_blocks / 2 + + movq 0(%eax), %mm0 + + pxor %mm2, %mm2 + pxor %mm3, %mm3 + + movq %mm0, %mm1 + punpckldq %mm0, %mm0 + punpckhdq %mm1, %mm1 + + + jmp .L1_test + + # + # 4 taps / loop + # something like ?? cycles / loop + # + + .p2align 4 +.Loop1: + pfmul 0(%edx), %mm0 + pfadd %mm2, %mm6 + + movq 8(%eax), %mm2 + + pfadd %mm3, %mm7 + + pfmul 8(%edx), %mm1 + + movq %mm2, %mm3 + punpckldq %mm2, %mm2 + punpckhdq %mm3, %mm3 + + + pfmul 16(%edx), %mm2 + pfadd %mm0, %mm4 + + movq 16(%eax), %mm0 + + pfadd %mm1, %mm5 + + movq %mm0, %mm1 + punpckldq %mm0, %mm0 + + pfmul 24(%edx), %mm3 + + punpckhdq %mm1, %mm1 + + +#TODO: add prefetch? + + addl $32, %edx + addl $16, %eax + +.L1_test: + decl %ecx + jge .Loop1 + + # We've handled the bulk of multiplies up to here. + # Now accumulate the final two additions and see if original + # n_2_complex_blocks was odd. If so, we've got 2 more + # taps to do. + + movl 16(%ebp), %ecx + pfadd %mm2, %mm6 + andl $1, %ecx + pfadd %mm3, %mm7 + je .Leven + + # The count was odd, do 2 more taps. + # Note that we've already got mm0 and mm1 preloaded + # from the main loop. + + pfmul 0(%edx), %mm0 + pfadd %mm0, %mm4 + pfmul 8(%edx), %mm1 + pfadd %mm1, %mm5 + + +.Leven: + # at this point mm4, mm5, mm6 and mm7 contain partial sums + + pfadd %mm7, %mm6 + pfadd %mm5, %mm4 + + movl 20(%ebp), %eax # result + + pfadd %mm6, %mm4 + + movq %mm4, (%eax) + femms + + popl %ebp + ret + +FUNC_TAIL(fcomplex_dotprod_3dnow) + .ident "Hand coded x86 3DNow! assembly" + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow64.S b/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow64.S new file mode 100644 index 000000000..d9a695949 --- /dev/null +++ b/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow64.S @@ -0,0 +1,170 @@ +# +# Copyright 2002,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. +# + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_complex_blocks is != 0 +# +# +# fcomplex_dotprod_generic (const float *input, +# const float *taps, unsigned n_2_complex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[0] * taps[1]; +# sum2 += input[1] * taps[2]; +# sum3 += input[1] * taps[3]; +# +# input += 2; +# taps += 4; +# +# } while (--n_2_complex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +#include "assembly.h" + + + .file "fcomplex_dotprod_3dnow64.S" +// .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(fcomplex_dotprod_3dnow) + DEF_FUNC_HEAD(fcomplex_dotprod_3dnow) +GLOB_SYMB(fcomplex_dotprod_3dnow): + + # intput: rdi, taps: rsi, n_2_ccomplex_blocks: rdx, result: rcx + + mov %rdx, %rax + + # zero accumulators + + pxor %mm4, %mm4 # mm4 = 0 0 + pxor %mm5, %mm5 # mm5 = 0 0 + pxor %mm6, %mm6 # mm6 = 0 0 + pxor %mm7, %mm7 # mm7 = 0 0 + + shr $1, %rax # rax = n_2_complex_blocks / 2 + + movq 0(%rdi), %mm0 + + pxor %mm2, %mm2 + pxor %mm3, %mm3 + + movq %mm0, %mm1 + punpckldq %mm0, %mm0 + punpckhdq %mm1, %mm1 + + + jmp .L1_test + + # + # 4 taps / loop + # something like ?? cycles / loop + # + + .p2align 4 +.Loop1: + pfmul 0(%rsi), %mm0 + pfadd %mm2, %mm6 + + movq 8(%rdi), %mm2 + + pfadd %mm3, %mm7 + + pfmul 8(%rsi), %mm1 + + movq %mm2, %mm3 + punpckldq %mm2, %mm2 + punpckhdq %mm3, %mm3 + + + pfmul 16(%rsi), %mm2 + pfadd %mm0, %mm4 + + movq 16(%rdi), %mm0 + + pfadd %mm1, %mm5 + + movq %mm0, %mm1 + punpckldq %mm0, %mm0 + + pfmul 24(%rsi), %mm3 + + punpckhdq %mm1, %mm1 + + +#TODO: add prefetch? + + add $32, %rsi + add $16, %rdi + +.L1_test: + dec %rax + jge .Loop1 + + # We've handled the bulk of multiplies up to here. + # Now accumulate the final two additions and see if original + # n_2_complex_blocks was odd. If so, we've got 2 more + # taps to do. + + pfadd %mm2, %mm6 + and $1, %rdx + pfadd %mm3, %mm7 + je .Leven + + # The count was odd, do 2 more taps. + # Note that we've already got mm0 and mm1 preloaded + # from the main loop. + + pfmul 0(%rsi), %mm0 + pfadd %mm0, %mm4 + pfmul 8(%rsi), %mm1 + pfadd %mm1, %mm5 + + +.Leven: + # at this point mm4, mm5, mm6 and mm7 contain partial sums + + pfadd %mm7, %mm6 + pfadd %mm5, %mm4 + pfadd %mm6, %mm4 + + movq %mm4, (%rcx) # result + femms + + retq + +FUNC_TAIL(fcomplex_dotprod_3dnow) + .ident "Hand coded x86_64 3DNow! assembly" + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse.S b/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse.S new file mode 100644 index 000000000..4c5e956f2 --- /dev/null +++ b/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse.S @@ -0,0 +1,188 @@ +# +# Copyright 2002 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. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_complex_blocks is != 0 +# +# +# fcomplex_dotprod_generic (const float *input, +# const float *taps, unsigned n_2_complex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[0] * taps[1]; +# sum2 += input[1] * taps[2]; +# sum3 += input[1] * taps[3]; +# +# input += 2; +# taps += 4; +# +# } while (--n_2_complex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +# TODO: prefetch and better scheduling + +#include "assembly.h" + + + .file "fcomplex_dotprod_sse.S" +// .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(fcomplex_dotprod_sse) + DEF_FUNC_HEAD(fcomplex_dotprod_sse) +GLOB_SYMB(fcomplex_dotprod_sse): + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %eax # input + movl 12(%ebp), %edx # taps + movl 16(%ebp), %ecx + + + # xmm0 xmm1 xmm2 xmm3 are used to hold taps and the result of mults + # xmm4 xmm5 xmm6 xmm7 are used to hold the accumulated results + + xorps %xmm4, %xmm4 # zero two accumulators + xorps %xmm5, %xmm5 # xmm5 holds zero for use below + + # first handle any non-zero remainder of (n_2_complex_blocks % 4) + + andl $0x3, %ecx + jmp .L1_test + + .p2align 4 +.Loop1: + + movlps 0(%eax), %xmm0 + shufps $0x50, %xmm0, %xmm0 # b01010000 + + mulps (%edx), %xmm0 + addl $0x10, %edx + addl $8, %eax + addps %xmm0, %xmm4 +.L1_test: + decl %ecx + jge .Loop1 + + + # set up for primary loop which is unrolled 4 times + + movl 16(%ebp), %ecx + movaps %xmm5, %xmm6 # zero remaining accumulators + movaps %xmm5, %xmm7 + + shrl $2, %ecx # n_2_complex_blocks / 4 + je .Lcleanup # if zero, take short path + + # finish setup and loop priming + + movlps 0(%eax), %xmm0 + + movaps %xmm5, %xmm2 + movaps %xmm5, %xmm3 + + movlps 8(%eax), %xmm1 + shufps $0x50, %xmm0, %xmm0 + + shufps $0x50, %xmm1, %xmm1 + + # we know ecx is not zero, we checked above, + # hence enter loop at top + + .p2align 4 +.Loop2: + addps %xmm2, %xmm6 + movlps 0x10(%eax), %xmm2 + + addps %xmm3, %xmm7 + + mulps (%edx), %xmm0 + + movlps 0x18(%eax), %xmm3 + shufps $0x50, %xmm2, %xmm2 + + mulps 0x10(%edx), %xmm1 + + shufps $0x50, %xmm3, %xmm3 + + addps %xmm0, %xmm4 + movlps 0x20(%eax), %xmm0 + + addps %xmm1, %xmm5 + + mulps 0x20(%edx), %xmm2 + + movlps 0x28(%eax), %xmm1 + shufps $0x50, %xmm0, %xmm0 + + mulps 0x30(%edx), %xmm3 + + shufps $0x50, %xmm1, %xmm1 + + addl $0x40, %edx + addl $0x20, %eax + decl %ecx + jne .Loop2 + + # OK, now we've done with all the multiplies, but + # we still need to handle the unaccumulated + # products in xmm2 and xmm3 + + addps %xmm2, %xmm6 + addps %xmm3, %xmm7 + + # now we want to add all accumulators into xmm4 + + addps %xmm5, %xmm4 + addps %xmm6, %xmm7 + addps %xmm7, %xmm4 + + + # At this point, xmm4 contains 2x2 partial sums. We need + # to compute a "horizontal complex add" across xmm4. + +.Lcleanup: # xmm4 = r1 i2 r3 i4 + movl 20(%ebp), %eax # @result + movhlps %xmm4, %xmm0 # xmm0 = ?? ?? r1 r2 + addps %xmm4, %xmm0 # xmm0 = ?? ?? r1+r3 i2+i4 + movlps %xmm0, (%eax) # store low 2x32 bits (complex) to memory + + popl %ebp + ret + +FUNC_TAIL(fcomplex_dotprod_sse) + .ident "Hand coded x86 SSE assembly" + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse64.S b/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse64.S new file mode 100644 index 000000000..53a4f25e0 --- /dev/null +++ b/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse64.S @@ -0,0 +1,183 @@ +# +# Copyright 2002,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. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_2_complex_blocks is != 0 +# +# +# fcomplex_dotprod_generic (const float *input, +# const float *taps, unsigned n_2_complex_blocks, float *result) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[0] * taps[1]; +# sum2 += input[1] * taps[2]; +# sum3 += input[1] * taps[3]; +# +# input += 2; +# taps += 4; +# +# } while (--n_2_complex_blocks != 0); +# +# +# result[0] = sum0 + sum2; +# result[1] = sum1 + sum3; +# } +# + +# TODO: prefetch and better scheduling + +#include "assembly.h" + + + .file "fcomplex_dotprod_sse64.S" +// .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(fcomplex_dotprod_sse) + DEF_FUNC_HEAD(fcomplex_dotprod_sse) +GLOB_SYMB(fcomplex_dotprod_sse): + + # intput: rdi, taps: rsi, n_2_ccomplex_blocks: rdx, result: rcx + + mov %rdx, %rax + + # xmm0 xmm1 xmm2 xmm3 are used to hold taps and the result of mults + # xmm4 xmm5 xmm6 xmm7 are used to hold the accumulated results + + xorps %xmm4, %xmm4 # zero two accumulators + xorps %xmm5, %xmm5 # xmm5 holds zero for use below + + # first handle any non-zero remainder of (n_2_complex_blocks % 4) + + and $0x3, %rax + jmp .L1_test + + .p2align 4 +.Loop1: + + movlps 0(%rdi), %xmm0 + shufps $0x50, %xmm0, %xmm0 # b01010000 + + mulps (%rsi), %xmm0 + add $0x10, %rsi + add $8, %rdi + addps %xmm0, %xmm4 +.L1_test: + dec %rax + jge .Loop1 + + + # set up for primary loop which is unrolled 4 times + + movaps %xmm5, %xmm6 # zero remaining accumulators + movaps %xmm5, %xmm7 + + shr $2, %rdx # n_2_complex_blocks / 4 + je .Lcleanup # if zero, take short path + + # finish setup and loop priming + + movlps 0(%rdi), %xmm0 + + movaps %xmm5, %xmm2 + movaps %xmm5, %xmm3 + + movlps 8(%rdi), %xmm1 + shufps $0x50, %xmm0, %xmm0 + + shufps $0x50, %xmm1, %xmm1 + + # we know rdx is not zero, we checked above, + # hence enter loop at top + + .p2align 4 +.Loop2: + addps %xmm2, %xmm6 + movlps 0x10(%rdi), %xmm2 + + addps %xmm3, %xmm7 + + mulps (%rsi), %xmm0 + + movlps 0x18(%rdi), %xmm3 + shufps $0x50, %xmm2, %xmm2 + + mulps 0x10(%rsi), %xmm1 + + shufps $0x50, %xmm3, %xmm3 + + addps %xmm0, %xmm4 + movlps 0x20(%rdi), %xmm0 + + addps %xmm1, %xmm5 + + mulps 0x20(%rsi), %xmm2 + + movlps 0x28(%rdi), %xmm1 + shufps $0x50, %xmm0, %xmm0 + + mulps 0x30(%rsi), %xmm3 + + shufps $0x50, %xmm1, %xmm1 + + add $0x40, %rsi + add $0x20, %rdi + dec %rdx + jne .Loop2 + + # OK, now we've done with all the multiplies, but + # we still need to handle the unaccumulated + # products in xmm2 and xmm3 + + addps %xmm2, %xmm6 + addps %xmm3, %xmm7 + + # now we want to add all accumulators into xmm4 + + addps %xmm5, %xmm4 + addps %xmm6, %xmm7 + addps %xmm7, %xmm4 + + + # At this point, xmm4 contains 2x2 partial sums. We need + # to compute a "horizontal complex add" across xmm4. + +.Lcleanup: # xmm4 = r1 i2 r3 i4 + movhlps %xmm4, %xmm0 # xmm0 = ?? ?? r1 r2 + addps %xmm4, %xmm0 # xmm0 = ?? ?? r1+r3 i2+i4 + movlps %xmm0, (%rcx) # store low 2x32 bits (complex) to memory + + retq + +FUNC_TAIL(fcomplex_dotprod_sse) + .ident "Hand coded x86_64 SSE assembly" + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/gnuradio-core/src/lib/filter/fcomplex_dotprod_x86.h b/gnuradio-core/src/lib/filter/fcomplex_dotprod_x86.h new file mode 100644 index 000000000..b7eddf936 --- /dev/null +++ b/gnuradio-core/src/lib/filter/fcomplex_dotprod_x86.h @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 _FCOMPLEX_DOTPROD_X86_H_ +#define _FCOMPLEX_DOTPROD_X86_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +void +fcomplex_dotprod_3dnow (const float *input, + const float *taps, unsigned n_2_complex_blocks, float *result); + +void +fcomplex_dotprod_sse (const float *input, + const float *taps, unsigned n_2_complex_blocks, float *result); + +#ifdef __cplusplus +} +#endif + +#endif /* _FCOMPLEX_DOTPROD_X86_H_ */ diff --git a/gnuradio-core/src/lib/filter/filter.i b/gnuradio-core/src/lib/filter/filter.i new file mode 100644 index 000000000..12580aa10 --- /dev/null +++ b/gnuradio-core/src/lib/filter/filter.i @@ -0,0 +1,70 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005,2006,2007,2009 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 <gr_iir_filter_ffd.h> +#include <gr_single_pole_iir_filter_ff.h> +#include <gr_single_pole_iir_filter_cc.h> +#include <gr_hilbert_fc.h> +#include <gr_filter_delay_fc.h> +#include <gr_fft_filter_ccc.h> +#include <gr_fft_filter_fff.h> +#include <gr_fractional_interpolator_ff.h> +#include <gr_fractional_interpolator_cc.h> +#include <gr_goertzel_fc.h> +#include <gr_pfb_channelizer_ccf.h> +#include <gr_pfb_synthesizer_ccf.h> +#include <gr_pfb_decimator_ccf.h> +#include <gr_pfb_interpolator_ccf.h> +#include <gr_pfb_arb_resampler_ccf.h> +#include <gr_pfb_arb_resampler_fff.h> +#include <gr_pfb_clock_sync_ccf.h> +#include <gr_pfb_clock_sync_fff.h> +#include <gr_dc_blocker_cc.h> +#include <gr_dc_blocker_ff.h> +%} + +%include "gr_iir_filter_ffd.i" +%include "gr_single_pole_iir_filter_ff.i" +%include "gr_single_pole_iir_filter_cc.i" +%include "gr_hilbert_fc.i" +%include "gr_filter_delay_fc.i" +%include "gr_fft_filter_ccc.i" +%include "gr_fft_filter_fff.i" +%include "gr_fractional_interpolator_ff.i" +%include "gr_fractional_interpolator_cc.i" +%include "gr_goertzel_fc.i" +%include "gr_pfb_channelizer_ccf.i" +%include "gr_pfb_synthesizer_ccf.i" +%include "gr_pfb_decimator_ccf.i" +%include "gr_pfb_interpolator_ccf.i" +%include "gr_pfb_arb_resampler_ccf.i" +%include "gr_pfb_arb_resampler_fff.i" +%include "gr_pfb_decimator_ccf.i" +%include "gr_pfb_interpolator_ccf.i" +%include "gr_pfb_arb_resampler_ccf.i" +%include "gr_pfb_clock_sync_ccf.i" +%include "gr_pfb_clock_sync_fff.i" +%include "gr_dc_blocker_cc.i" +%include "gr_dc_blocker_ff.i" + +%include "filter_generated.i" diff --git a/gnuradio-core/src/lib/filter/float_dotprod_3dnow.S b/gnuradio-core/src/lib/filter/float_dotprod_3dnow.S new file mode 100644 index 000000000..cdebe9bc3 --- /dev/null +++ b/gnuradio-core/src/lib/filter/float_dotprod_3dnow.S @@ -0,0 +1,152 @@ +# +# Copyright 2002 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. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_4_float_blocks is != 0 +# +# +# float +# float_dotprod_generic (const float *input, +# const float *taps, unsigned n_4_float_blocks) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[1] * taps[1]; +# sum2 += input[2] * taps[2]; +# sum3 += input[3] * taps[3]; +# +# input += 4; +# taps += 4; +# +# } while (--n_4_float_blocks != 0); +# +# +# return sum0 + sum1 + sum2 + sum3; +# } +# + +#include "assembly.h" + + + .file "float_dotprod_3dnow.S" +// .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(float_dotprod_3dnow) + DEF_FUNC_HEAD(float_dotprod_3dnow) +GLOB_SYMB(float_dotprod_3dnow): + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %edx + movl 12(%ebp), %eax + movl 16(%ebp), %ecx + + # zero accumulators + + pxor %mm4, %mm4 # mm4 = 0 0 + pxor %mm5, %mm5 # mm5 = 0 0 + pxor %mm6, %mm6 # mm6 = 0 0 + pxor %mm7, %mm7 # mm7 = 0 0 + + shrl $1, %ecx # ecx = n_4_float_blocks / 2 + movq 0(%eax), %mm0 + movq 8(%eax), %mm1 + pxor %mm2, %mm2 + pxor %mm3, %mm3 + jmp .L1_test + + # + # 8 taps / loop + # something like 6 cycles / loop + # + + .p2align 4 +.Loop1: + pfmul 0(%edx), %mm0 + pfadd %mm2, %mm6 + movq 16(%eax), %mm2 + + pfmul 8(%edx), %mm1 + pfadd %mm3, %mm7 + movq 24(%eax), %mm3 + + pfmul 16(%edx), %mm2 + pfadd %mm0, %mm4 + movq 32(%eax), %mm0 + + pfmul 24(%edx), %mm3 + pfadd %mm1, %mm5 + movq 40(%eax), %mm1 + + addl $32, %edx + addl $32, %eax +.L1_test: + decl %ecx + jge .Loop1 + + # We've handled the bulk of multiplies up to here. + # Now accumulate the final two additions and see if original + # n_4_float_blocks was odd. If so, we've got 4 more + # taps to do. + + movl 16(%ebp), %ecx + pfadd %mm2, %mm6 + andl $1, %ecx + pfadd %mm3, %mm7 + je .Leven + + # The count was odd, do 4 more taps. + # Note that we've already got mm0 and mm1 preloaded + # from the main loop. + + pfmul 0(%edx), %mm0 + pfadd %mm0, %mm4 + pfmul 8(%edx), %mm1 + pfadd %mm1, %mm5 + +.Leven: + # at this point mm4, mm5, mm6 and mm7 contain partial sums + + pfadd %mm7, %mm6 + pfadd %mm5, %mm4 + pfadd %mm6, %mm4 + pfacc %mm4, %mm4 + + movd %mm4, 16(%ebp) + femms + flds 16(%ebp) + + popl %ebp + ret + +FUNC_TAIL(float_dotprod_3dnow) + .ident "Hand coded x86 3DNow! assembly" + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/gnuradio-core/src/lib/filter/float_dotprod_3dnow64.S b/gnuradio-core/src/lib/filter/float_dotprod_3dnow64.S new file mode 100644 index 000000000..1e859d75a --- /dev/null +++ b/gnuradio-core/src/lib/filter/float_dotprod_3dnow64.S @@ -0,0 +1,149 @@ +# +# Copyright 2002,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. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_4_float_blocks is != 0 +# +# +# float +# float_dotprod_generic (const float *input, +# const float *taps, unsigned n_4_float_blocks) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[1] * taps[1]; +# sum2 += input[2] * taps[2]; +# sum3 += input[3] * taps[3]; +# +# input += 4; +# taps += 4; +# +# } while (--n_4_float_blocks != 0); +# +# +# return sum0 + sum1 + sum2 + sum3; +# } +# + +#include "assembly.h" + + + .file "float_dotprod_3dnow64.S" +// .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(float_dotprod_3dnow) + DEF_FUNC_HEAD(float_dotprod_3dnow) +GLOB_SYMB(float_dotprod_3dnow): + + # intput: rdi, taps: rsi, n_2_ccomplex_blocks: rdx + + mov %rdx, %rax + + # zero accumulators + + pxor %mm4, %mm4 # mm4 = 0 0 + pxor %mm5, %mm5 # mm5 = 0 0 + pxor %mm6, %mm6 # mm6 = 0 0 + pxor %mm7, %mm7 # mm7 = 0 0 + + shr $1, %rax # rax = n_4_float_blocks / 2 + movq 0(%rsi), %mm0 + movq 8(%rsi), %mm1 + pxor %mm2, %mm2 + pxor %mm3, %mm3 + jmp .L1_test + + # + # 8 taps / loop + # something like 6 cycles / loop + # + + .p2align 4 +.Loop1: + pfmul 0(%rdi), %mm0 + pfadd %mm2, %mm6 + movq 16(%rsi), %mm2 + + pfmul 8(%rdi), %mm1 + pfadd %mm3, %mm7 + movq 24(%rsi), %mm3 + + pfmul 16(%rdi), %mm2 + pfadd %mm0, %mm4 + movq 32(%rsi), %mm0 + + pfmul 24(%rdi), %mm3 + pfadd %mm1, %mm5 + movq 40(%rsi), %mm1 + + add $32, %rdi + add $32, %rsi +.L1_test: + dec %rax + jge .Loop1 + + # We've handled the bulk of multiplies up to here. + # Now accumulate the final two additions and see if original + # n_4_float_blocks was odd. If so, we've got 4 more + # taps to do. + + pfadd %mm2, %mm6 + and $1, %rdx + pfadd %mm3, %mm7 + je .Leven + + # The count was odd, do 4 more taps. + # Note that we've already got mm0 and mm1 preloaded + # from the main loop. + + pfmul 0(%rdi), %mm0 + pfadd %mm0, %mm4 + pfmul 8(%rdi), %mm1 + pfadd %mm1, %mm5 + +.Leven: + # at this point mm4, mm5, mm6 and mm7 contain partial sums + + pfadd %mm7, %mm6 + pfadd %mm5, %mm4 + pfadd %mm6, %mm4 + pfacc %mm4, %mm4 + + movd %mm4, -8(%rsp) + movss -8(%rsp), %xmm0 + femms + + retq + +FUNC_TAIL(float_dotprod_3dnow) + .ident "Hand coded x86_64 3DNow! assembly" + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/gnuradio-core/src/lib/filter/float_dotprod_generic.c b/gnuradio-core/src/lib/filter/float_dotprod_generic.c new file mode 100644 index 000000000..fb9139036 --- /dev/null +++ b/gnuradio-core/src/lib/filter/float_dotprod_generic.c @@ -0,0 +1,49 @@ +/* -*- c -*- */ +/* + * Copyright 2002 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 "float_dotprod_generic.h" + + +float +float_dotprod_generic (const float *input, + const float *taps, unsigned n_4_float_blocks) +{ + float sum0 = 0; + float sum1 = 0; + float sum2 = 0; + float sum3 = 0; + + do { + + sum0 += input[0] * taps[0]; + sum1 += input[1] * taps[1]; + sum2 += input[2] * taps[2]; + sum3 += input[3] * taps[3]; + + input += 4; + taps += 4; + + } while (--n_4_float_blocks != 0); + + + return sum0 + sum1 + sum2 + sum3; +} diff --git a/gnuradio-core/src/lib/filter/float_dotprod_generic.h b/gnuradio-core/src/lib/filter/float_dotprod_generic.h new file mode 100644 index 000000000..dee967642 --- /dev/null +++ b/gnuradio-core/src/lib/filter/float_dotprod_generic.h @@ -0,0 +1,41 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 _FLOAT_DOTPROD_GENERIC_H_ +#define _FLOAT_DOTPROD_GENERIC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +float +float_dotprod_generic (const float *input, + const float *taps, unsigned n_4_float_blocks); + + +#ifdef __cplusplus +} +#endif + + + +#endif /* _FLOAT_DOTPROD_GENERIC_H_ */ diff --git a/gnuradio-core/src/lib/filter/float_dotprod_sse.S b/gnuradio-core/src/lib/filter/float_dotprod_sse.S new file mode 100644 index 000000000..66604526d --- /dev/null +++ b/gnuradio-core/src/lib/filter/float_dotprod_sse.S @@ -0,0 +1,171 @@ +# +# Copyright 2002 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. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_4_float_blocks is != 0 +# +# +# float +# float_dotprod_generic (const float *input, +# const float *taps, unsigned n_4_float_blocks) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[1] * taps[1]; +# sum2 += input[2] * taps[2]; +# sum3 += input[3] * taps[3]; +# +# input += 4; +# taps += 4; +# +# } while (--n_4_float_blocks != 0); +# +# +# return sum0 + sum1 + sum2 + sum3; +# } +# + +#include "assembly.h" + + + .file "float_dotprod_sse.S" +// .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(float_dotprod_sse) + DEF_FUNC_HEAD(float_dotprod_sse) +GLOB_SYMB(float_dotprod_sse): + pushl %ebp + movl %esp, %ebp + movl 8(%ebp), %edx + movl 12(%ebp), %eax + movl 16(%ebp), %ecx + + + # xmm0 xmm1 xmm2 xmm3 are used to hold taps and the result of mults + # xmm4 xmm5 xmm6 xmm7 are used to hold the accumulated results + + xorps %xmm4, %xmm4 # zero two accumulators + xorps %xmm5, %xmm5 # xmm5 holds zero for use below + + # first handle any non-zero remainder of (n_4_float_blocks % 4) + + andl $0x3, %ecx + jmp .L1_test + + .p2align 4 +.Loop1: + movaps (%eax), %xmm0 + mulps (%edx), %xmm0 + addl $0x10, %edx + addl $0x10, %eax + addps %xmm0, %xmm4 +.L1_test: + decl %ecx + jge .Loop1 + + + # set up for primary loop which is unrolled 4 times + + movl 16(%ebp), %ecx + movaps %xmm5, %xmm6 # zero remaining accumulators + movaps %xmm5, %xmm7 + + shrl $2, %ecx # n_4_float_blocks / 4 + je .Lcleanup # if zero, take short path + + # finish setup and loop priming + + movaps 0x00(%eax), %xmm0 + movaps %xmm5, %xmm2 + movaps 0x10(%eax), %xmm1 + movaps %xmm5, %xmm3 + + # we know ecx is not zero, we checked above, + # hence enter loop at top + + .p2align 4 +.Loop2: + mulps (%edx), %xmm0 + addps %xmm2, %xmm6 + movaps 0x20(%eax), %xmm2 + + mulps 0x10(%edx), %xmm1 + addps %xmm3, %xmm7 + movaps 0x30(%eax), %xmm3 + + mulps 0x20(%edx), %xmm2 + addps %xmm0, %xmm4 + movaps 0x40(%eax), %xmm0 + + mulps 0x30(%edx), %xmm3 + addps %xmm1, %xmm5 + movaps 0x50(%eax), %xmm1 + + addl $0x40, %edx + addl $0x40, %eax + decl %ecx + jne .Loop2 + + # OK, now we've done with all the multiplies, but + # we still need to handle the unaccumulated + # products in xmm2 and xmm3 + + addps %xmm2, %xmm6 + addps %xmm3, %xmm7 + + # now we want to add all accumulators into xmm4 + + addps %xmm5, %xmm4 + addps %xmm6, %xmm7 + addps %xmm7, %xmm4 + + + # At this point, xmm4 contains 4 partial sums. We need + # to compute a "horizontal add" across xmm4. + # This is a fairly nasty operation... + +.Lcleanup: # xmm4 = d1 d2 d3 d4 + xorps %xmm0, %xmm0 # xmm0 = 0 0 0 0 (may be unnecessary) + movhlps %xmm4, %xmm0 # xmm0 = 0 0 d1 d2 + addps %xmm4, %xmm0 # xmm0 = d1 d2 d1+d3 d2+d4 + movaps %xmm0, %xmm1 # xmm1 = d1 d2 d1+d3 d2+d4 + shufps $0xE1, %xmm4, %xmm1 # xmm1 = d1 d2 d2+d4 d1+d3 + addss %xmm1, %xmm0 # xmm1 = d1 d2 d1+d3 d1+d2+d3+d4 + movss %xmm0, 16(%ebp) # store low 32 bits (sum) to memory + flds 16(%ebp) # and load onto FPU stack for return + + popl %ebp + ret + +FUNC_TAIL(float_dotprod_sse) + .ident "Hand coded x86 SSE assembly" + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/gnuradio-core/src/lib/filter/float_dotprod_sse64.S b/gnuradio-core/src/lib/filter/float_dotprod_sse64.S new file mode 100644 index 000000000..0dd0764c5 --- /dev/null +++ b/gnuradio-core/src/lib/filter/float_dotprod_sse64.S @@ -0,0 +1,165 @@ +# +# Copyright 2002,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. +# + + +# input and taps are guarenteed to be 16 byte aligned. +# n_4_float_blocks is != 0 +# +# +# float +# float_dotprod_generic (const float *input, +# const float *taps, unsigned n_4_float_blocks) +# { +# float sum0 = 0; +# float sum1 = 0; +# float sum2 = 0; +# float sum3 = 0; +# +# do { +# +# sum0 += input[0] * taps[0]; +# sum1 += input[1] * taps[1]; +# sum2 += input[2] * taps[2]; +# sum3 += input[3] * taps[3]; +# +# input += 4; +# taps += 4; +# +# } while (--n_4_float_blocks != 0); +# +# +# return sum0 + sum1 + sum2 + sum3; +# } +# + +#include "assembly.h" + + + .file "float_dotprod_sse64.S" +// .version "01.01" +.text + .p2align 4 +.globl GLOB_SYMB(float_dotprod_sse) + DEF_FUNC_HEAD(float_dotprod_sse) +GLOB_SYMB(float_dotprod_sse): + + # intput: rdi, taps: rsi, n_2_ccomplex_blocks: rdx + + mov %rdx, %rax + + # xmm0 xmm1 xmm2 xmm3 are used to hold taps and the result of mults + # xmm4 xmm5 xmm6 xmm7 are used to hold the accumulated results + + xorps %xmm4, %xmm4 # zero two accumulators + xorps %xmm5, %xmm5 # xmm5 holds zero for use below + + # first handle any non-zero remainder of (n_4_float_blocks % 4) + + and $0x3, %rax + jmp .L1_test + + .p2align 4 +.Loop1: + movaps (%rsi), %xmm0 + mulps (%rdi), %xmm0 + add $0x10, %rdi + add $0x10, %rsi + addps %xmm0, %xmm4 +.L1_test: + dec %rax + jge .Loop1 + + + # set up for primary loop which is unrolled 4 times + + movaps %xmm5, %xmm6 # zero remaining accumulators + movaps %xmm5, %xmm7 + + shr $2, %rdx # n_4_float_blocks / 4 + je .Lcleanup # if zero, take short path + + # finish setup and loop priming + + movaps 0x00(%rsi), %xmm0 + movaps %xmm5, %xmm2 + movaps 0x10(%rsi), %xmm1 + movaps %xmm5, %xmm3 + + # we know rdx is not zero, we checked above, + # hence enter loop at top + + .p2align 4 +.Loop2: + mulps (%rdi), %xmm0 + addps %xmm2, %xmm6 + movaps 0x20(%rsi), %xmm2 + + mulps 0x10(%rdi), %xmm1 + addps %xmm3, %xmm7 + movaps 0x30(%rsi), %xmm3 + + mulps 0x20(%rdi), %xmm2 + addps %xmm0, %xmm4 + movaps 0x40(%rsi), %xmm0 + + mulps 0x30(%rdi), %xmm3 + addps %xmm1, %xmm5 + movaps 0x50(%rsi), %xmm1 + + add $0x40, %rdi + add $0x40, %rsi + dec %rdx + jne .Loop2 + + # OK, now we've done with all the multiplies, but + # we still need to handle the unaccumulated + # products in xmm2 and xmm3 + + addps %xmm2, %xmm6 + addps %xmm3, %xmm7 + + # now we want to add all accumulators into xmm4 + + addps %xmm5, %xmm4 + addps %xmm6, %xmm7 + addps %xmm7, %xmm4 + + + # At this point, xmm4 contains 4 partial sums. We need + # to compute a "horizontal add" across xmm4. + # This is a fairly nasty operation... + +.Lcleanup: # xmm4 = d1 d2 d3 d4 + xorps %xmm0, %xmm0 # xmm0 = 0 0 0 0 (may be unnecessary) + movhlps %xmm4, %xmm0 # xmm0 = 0 0 d1 d2 + addps %xmm4, %xmm0 # xmm0 = d1 d2 d1+d3 d2+d4 + movaps %xmm0, %xmm1 # xmm1 = d1 d2 d1+d3 d2+d4 + shufps $0xE1, %xmm4, %xmm1 # xmm1 = d1 d2 d2+d4 d1+d3 + addss %xmm1, %xmm0 # xmm1 = d1 d2 d1+d3 d1+d2+d3+d4 + + retq + +FUNC_TAIL(float_dotprod_sse) + .ident "Hand coded x86_64 SSE assembly" + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/gnuradio-core/src/lib/filter/float_dotprod_x86.h b/gnuradio-core/src/lib/filter/float_dotprod_x86.h new file mode 100644 index 000000000..fd1a2cc93 --- /dev/null +++ b/gnuradio-core/src/lib/filter/float_dotprod_x86.h @@ -0,0 +1,44 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 _FLOAT_DOTPROD_X86_H_ +#define _FLOAT_DOTPROD_X86_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +float +float_dotprod_3dnow (const float *input, + const float *taps, unsigned n_4_float_blocks); + +float +float_dotprod_sse (const float *input, + const float *taps, unsigned n_4_float_blocks); + +#ifdef __cplusplus +} +#endif + + + +#endif /* _FLOAT_DOTPROD_X86_H_ */ diff --git a/gnuradio-core/src/lib/filter/gcc_x86_cpuid.h b/gnuradio-core/src/lib/filter/gcc_x86_cpuid.h new file mode 100644 index 000000000..98eeb33a3 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gcc_x86_cpuid.h @@ -0,0 +1,178 @@ +/* + * Copyright (C) 2007, 2008, 2009 Free Software Foundation, Inc. + * + * This file is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 3, or (at your option) any + * later version. + * + * This file 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. + * + * Under Section 7 of GPL version 3, you are granted additional + * permissions described in the GCC Runtime Library Exception, version + * 3.1, as published by the Free Software Foundation. + * + * You should have received a copy of the GNU General Public License and + * a copy of the GCC Runtime Library Exception along with this program; + * see the files COPYING3 and COPYING.RUNTIME respectively. If not, see + * <http://www.gnu.org/licenses/>. + */ + +/* %ecx */ +#define bit_SSE3 (1 << 0) +#define bit_PCLMUL (1 << 1) +#define bit_SSSE3 (1 << 9) +#define bit_FMA (1 << 12) +#define bit_CMPXCHG16B (1 << 13) +#define bit_SSE4_1 (1 << 19) +#define bit_SSE4_2 (1 << 20) +#define bit_MOVBE (1 << 22) +#define bit_POPCNT (1 << 23) +#define bit_AES (1 << 25) +#define bit_XSAVE (1 << 26) +#define bit_OSXSAVE (1 << 27) +#define bit_AVX (1 << 28) + +/* %edx */ +#define bit_CMPXCHG8B (1 << 8) +#define bit_CMOV (1 << 15) +#define bit_MMX (1 << 23) +#define bit_FXSAVE (1 << 24) +#define bit_SSE (1 << 25) +#define bit_SSE2 (1 << 26) + +/* Extended Features */ +/* %ecx */ +#define bit_LAHF_LM (1 << 0) +#define bit_SSE4a (1 << 6) +#define bit_SSE5 (1 << 11) + +/* %edx */ +#define bit_LM (1 << 29) +#define bit_3DNOWP (1 << 30) +#define bit_3DNOW (1 << 31) + + +#if defined(__i386__) && defined(__PIC__) +/* %ebx may be the PIC register. */ +#if __GNUC__ >= 3 +#define __cpuid(level, a, b, c, d) \ + __asm__ ("xchg{l}\t{%%}ebx, %1\n\t" \ + "cpuid\n\t" \ + "xchg{l}\t{%%}ebx, %1\n\t" \ + : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ + : "0" (level)) + +#define __cpuid_count(level, count, a, b, c, d) \ + __asm__ ("xchg{l}\t{%%}ebx, %1\n\t" \ + "cpuid\n\t" \ + "xchg{l}\t{%%}ebx, %1\n\t" \ + : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ + : "0" (level), "2" (count)) +#else +/* Host GCCs older than 3.0 weren't supporting Intel asm syntax + nor alternatives in i386 code. */ +#define __cpuid(level, a, b, c, d) \ + __asm__ ("xchgl\t%%ebx, %1\n\t" \ + "cpuid\n\t" \ + "xchgl\t%%ebx, %1\n\t" \ + : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ + : "0" (level)) + +#define __cpuid_count(level, count, a, b, c, d) \ + __asm__ ("xchgl\t%%ebx, %1\n\t" \ + "cpuid\n\t" \ + "xchgl\t%%ebx, %1\n\t" \ + : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ + : "0" (level), "2" (count)) +#endif +#else +#define __cpuid(level, a, b, c, d) \ + __asm__ ("cpuid\n\t" \ + : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ + : "0" (level)) + +#define __cpuid_count(level, count, a, b, c, d) \ + __asm__ ("cpuid\n\t" \ + : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ + : "0" (level), "2" (count)) +#endif + +/* Return highest supported input value for cpuid instruction. ext can + be either 0x0 or 0x8000000 to return highest supported value for + basic or extended cpuid information. Function returns 0 if cpuid + is not supported or whatever cpuid returns in eax register. If sig + pointer is non-null, then first four bytes of the signature + (as found in ebx register) are returned in location pointed by sig. */ + +static __inline unsigned int +__get_cpuid_max (unsigned int __ext, unsigned int *__sig) +{ + unsigned int __eax, __ebx, __ecx, __edx; + +#ifndef __x86_64__ +#if __GNUC__ >= 3 + /* See if we can use cpuid. On AMD64 we always can. */ + __asm__ ("pushf{l|d}\n\t" + "pushf{l|d}\n\t" + "pop{l}\t%0\n\t" + "mov{l}\t{%0, %1|%1, %0}\n\t" + "xor{l}\t{%2, %0|%0, %2}\n\t" + "push{l}\t%0\n\t" + "popf{l|d}\n\t" + "pushf{l|d}\n\t" + "pop{l}\t%0\n\t" + "popf{l|d}\n\t" + : "=&r" (__eax), "=&r" (__ebx) + : "i" (0x00200000)); +#else +/* Host GCCs older than 3.0 weren't supporting Intel asm syntax + nor alternatives in i386 code. */ + __asm__ ("pushfl\n\t" + "pushfl\n\t" + "popl\t%0\n\t" + "movl\t%0, %1\n\t" + "xorl\t%2, %0\n\t" + "pushl\t%0\n\t" + "popfl\n\t" + "pushfl\n\t" + "popl\t%0\n\t" + "popfl\n\t" + : "=&r" (__eax), "=&r" (__ebx) + : "i" (0x00200000)); +#endif + + if (!((__eax ^ __ebx) & 0x00200000)) + return 0; +#endif + + /* Host supports cpuid. Return highest supported cpuid input value. */ + __cpuid (__ext, __eax, __ebx, __ecx, __edx); + + if (__sig) + *__sig = __ebx; + + return __eax; +} + +/* Return cpuid data for requested cpuid level, as found in returned + eax, ebx, ecx and edx registers. The function checks if cpuid is + supported and returns 1 for valid cpuid information or 0 for + unsupported cpuid level. All pointers are required to be non-null. */ + +static __inline int +__get_cpuid (unsigned int __level, + unsigned int *__eax, unsigned int *__ebx, + unsigned int *__ecx, unsigned int *__edx) +{ + unsigned int __ext = __level & 0x80000000; + + if (__get_cpuid_max (__ext, 0) < __level) + return 0; + + __cpuid (__level, *__eax, *__ebx, *__ecx, *__edx); + return 1; +} diff --git a/gnuradio-core/src/lib/filter/generate_all.py b/gnuradio-core/src/lib/filter/generate_all.py new file mode 100755 index 000000000..1da9f7209 --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_all.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python +# +# Copyright 2003 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 build_utils import output_glue + +import generate_gr_fir_filter_XXX +import generate_gr_interp_fir_filter_XXX +import generate_gr_rational_resampler_base_XXX +import generate_gr_freq_xlating_fir_filter_XXX +import generate_gr_fir_sysconfig_generic +import generate_gr_fir_sysconfig +import generate_gr_fir_util +import generate_gr_fir_XXX +import generate_gri_fir_filter_with_buffer_XXX + +def generate_all(): + generate_gr_fir_XXX.generate() + generate_gr_fir_filter_XXX.generate() + generate_gr_interp_fir_filter_XXX.generate() + generate_gr_rational_resampler_base_XXX.generate() + generate_gr_freq_xlating_fir_filter_XXX.generate() + generate_gr_fir_sysconfig_generic.generate() + generate_gr_fir_sysconfig.generate() + generate_gr_fir_util.generate() + generate_gri_fir_filter_with_buffer_XXX.generate() + output_glue('filter') + +if __name__ == '__main__': + generate_all() diff --git a/gnuradio-core/src/lib/filter/generate_gr_fir_XXX.py b/gnuradio-core/src/lib/filter/generate_gr_fir_XXX.py new file mode 100755 index 000000000..cf37fbb24 --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_gr_fir_XXX.py @@ -0,0 +1,75 @@ +#!/bin/env python +# -*- python -*- +# +# Copyright 2003 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. +# + +import re +from generate_utils import * + +roots = ['gr_fir_XXX', 'gr_fir_XXX_generic'] + + +# figure out accumulator type. Use biggest of input, output and tap type + +def code3_to_acc_code (code3): + if i_code (code3) == 'c' or o_code (code3) == 'c' or tap_code (code3) == 'c': + return 'c' + if i_code (code3) == 'f' or o_code (code3) == 'f' or tap_code (code3) == 'f': + return 'f' + if i_code (code3) == 'i' or o_code (code3) == 'i' or tap_code (code3) == 'i': + return 'i' + return 'i' # even short short short needs int accumulator + + +def code3_to_input_cast (code3): + if i_code (code3) == 's' and o_code (code3) == 'c': + return '(float)' + return '' + +def expand_h_cc (root, code3): + d = init_dict (root, code3) + expand_template (d, root + '.h.t') + expand_template (d, root + '.cc.t') + +def init_dict (root, code3): + name = re.sub ('X+', code3, root) + d = standard_dict (name, code3) + d['FIR_TYPE'] = 'gr_fir_' + code3 + d['INPUT_CAST'] = code3_to_input_cast (code3) + acc_code = code3_to_acc_code (code3) + d['ACC_TYPE'] = char_to_type[acc_code] + if acc_code == 'c': + d['N_UNROLL'] = '2' + d['VRCOMPLEX_INCLUDE'] = '#include <gr_types.h>' + else: + d['N_UNROLL'] = '4' + d['VRCOMPLEX_INCLUDE'] = '' + return d + + +def generate (): + for r in roots: + for s in fir_signatures: + expand_h_cc (r, s) + + +if __name__ == '__main__': + generate () diff --git a/gnuradio-core/src/lib/filter/generate_gr_fir_filter_XXX.py b/gnuradio-core/src/lib/filter/generate_gr_fir_filter_XXX.py new file mode 100755 index 000000000..50cc586e5 --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_gr_fir_filter_XXX.py @@ -0,0 +1,49 @@ +#!/bin/env python +# -*- python -*- +# +# Copyright 2003,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. +# + +import re +from generate_utils import * + +roots = ['gr_fir_filter_XXX'] + + +def expand_h_cc_i (root, code3): + d = init_dict (root, code3) + expand_template (d, root + '.h.t') + expand_template (d, root + '.cc.t') + expand_template (d, root + '.i.t') + +def init_dict (root, code3): + name = re.sub ('X+', code3, root) + d = standard_dict (name, code3) + d['FIR_TYPE'] = 'gr_fir_' + code3 + return d + +def generate (): + for r in roots: + for s in fir_signatures: + expand_h_cc_i (r, s) + +if __name__ == '__main__': + generate () + diff --git a/gnuradio-core/src/lib/filter/generate_gr_fir_sysconfig.py b/gnuradio-core/src/lib/filter/generate_gr_fir_sysconfig.py new file mode 100755 index 000000000..50d819fd1 --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_gr_fir_sysconfig.py @@ -0,0 +1,133 @@ +#!/bin/env python +# -*- python -*- +# +# Copyright 2003,2009 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 generate_utils import * + + +# ---------------------------------------------------------------- + +def make_gr_fir_sysconfig_h (): + out = open_and_log_name ('gr_fir_sysconfig.h', 'w') + if not out: + return + + out.write (copyright) + + out.write ( +''' +/* + * WARNING: This file is automatically generated by generate_gr_fir_sysconfig.py + * Any changes made to this file will be overwritten. + */ + +#ifndef INCLUDED_GR_FIR_SYSCONFIG_H +#define INCLUDED_GR_FIR_SYSCONFIG_H + +#include <gr_types.h> + +''') + + # for sig in fir_signatures: + # out.write ('class gr_fir_' + sig + ';\n') + + out.write ('#include <gr_fir_util.h>\n') + + out.write ( +''' +/*! + * \\brief abstract base class for configuring the automatic selection of the + * fastest gr_fir for your platform. + * + * This is used internally by gr_fir_util. + */ + +class gr_fir_sysconfig { +public: + virtual ~gr_fir_sysconfig (); + +''') + + for sig in fir_signatures: + out.write ((' virtual gr_fir_%s *create_gr_fir_%s (const std::vector<%s> &taps) = 0;\n' % + (sig, sig, tap_type (sig)))) + + out.write ('\n') + + for sig in fir_signatures: + out.write ((' virtual void get_gr_fir_%s_info (std::vector<gr_fir_%s_info> *info) = 0;\n' % + (sig, sig))) + + out.write ( +''' +}; + +/* + * This returns the single instance of the appropriate derived class. + * This function must be defined only once in the system, and should be defined + * in the platform specific code. + */ + +gr_fir_sysconfig *gr_fir_sysconfig_singleton (); + + +#endif /* INCLUDED_GR_FIR_SYSCONFIG_H */ +''') + out.close () + + +# ---------------------------------------------------------------- + +def make_gr_fir_sysconfig_cc (): + out = open_and_log_name ('gr_fir_sysconfig.cc', 'w') + if not out: + return + + out.write (copyright) + + out.write ( +''' +/* + * WARNING: This file is automatically generated by generate_gr_fir_sysconfig.py + * Any changes made to this file will be overwritten. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_fir_sysconfig.h> + +gr_fir_sysconfig::~gr_fir_sysconfig () +{ +} +''') + out.close () + + +# ---------------------------------------------------------------- + +def generate (): + make_gr_fir_sysconfig_h () + make_gr_fir_sysconfig_cc () + +if __name__ == '__main__': + generate () diff --git a/gnuradio-core/src/lib/filter/generate_gr_fir_sysconfig_generic.py b/gnuradio-core/src/lib/filter/generate_gr_fir_sysconfig_generic.py new file mode 100755 index 000000000..dcbadd30f --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_gr_fir_sysconfig_generic.py @@ -0,0 +1,186 @@ +#!/bin/env python +# -*- python -*- +# +# Copyright 2003,2009 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 generate_utils import * + + +# ---------------------------------------------------------------- + +def make_gr_fir_sysconfig_generic_h (): + out = open_and_log_name ('gr_fir_sysconfig_generic.h', 'w') + if not out: + return + out.write (copyright) + + out.write ( +''' +/* + * WARNING: This file is automatically generated by + * generate_gr_fir_sysconfig_generic.py. + * + * Any changes made to this file will be overwritten. + */ + +#ifndef _GR_FIR_SYSCONFIG_GENERIC_H_ +#define _GR_FIR_SYSCONFIG_GENERIC_H_ + +#include <gr_fir_sysconfig.h> + +''') + + out.write ( +''' +class gr_fir_sysconfig_generic : public gr_fir_sysconfig { +public: +''') + + for sig in fir_signatures: + out.write ((' virtual gr_fir_%s *create_gr_fir_%s (const std::vector<%s> &taps);\n' % + (sig, sig, tap_type (sig)))) + + out.write ('\n') + + for sig in fir_signatures: + out.write ((' virtual void get_gr_fir_%s_info (std::vector<gr_fir_%s_info> *info);\n' % + (sig, sig))) + + out.write ( +''' +}; + + +#endif /* _GR_FIR_SYSCONFIG_GENERIC_H_ */ +''') + out.close () + + +# ---------------------------------------------------------------- + +def make_constructor (sig, out): + out.write (''' +static gr_fir_%s * +make_gr_fir_%s (const std::vector<%s> &taps) +{ + return new gr_fir_%s_generic (taps); +} +''' % (sig, sig, tap_type (sig), sig)) + + +def make_creator (sig, out): + out.write (''' +gr_fir_%s * +gr_fir_sysconfig_generic::create_gr_fir_%s (const std::vector<%s> &taps) +{ + return make_gr_fir_%s (taps); +} +''' % (sig, sig, tap_type (sig), sig)) + + +def make_info (sig, out): + out.write (''' +void +gr_fir_sysconfig_generic::get_gr_fir_%s_info (std::vector<gr_fir_%s_info> *info) +{ + info->resize (1); + (*info)[0].name = "generic"; + (*info)[0].create = make_gr_fir_%s; +} +''' % (sig, sig, sig)) + + +# ---------------------------------------------------------------- + +def make_gr_fir_sysconfig_generic_cc (): + out = open_and_log_name ('gr_fir_sysconfig_generic.cc', 'w') + if not out: + return + out.write (copyright) + + out.write ( +''' +/* + * WARNING: This file is automatically generated by + * generate_gr_fir_sysconfig_generic.py. + * + * Any changes made to this file will be overwritten. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_fir_sysconfig_generic.h> + +''') + + for sig in fir_signatures: + out.write ('#include <gr_fir_%s_generic.h>\n' % (sig)) + + out.write ( +''' +/* + * ---------------------------------------------------------------- + * static functions that serve as constructors returned by info + * ---------------------------------------------------------------- + */ +''') + + for sig in fir_signatures: + make_constructor (sig, out) + + out.write ( +''' +/* + * ---------------------------------------------------------------- + * return instances of the generic C++ versions of these classes. + * ---------------------------------------------------------------- + */ +''') + + for sig in fir_signatures: + make_creator (sig, out) + + out.write ( +''' +/* + * Return info about available implementations. + * + * This is the bottom of the concrete hierarchy, so we set the + * size of the vector to 1, and install our info. Classes derived + * from us invoke us first, then append their own info. + */ +''') + + for sig in fir_signatures: + make_info (sig, out) + + + out.close () + +# ---------------------------------------------------------------- + +def generate (): + make_gr_fir_sysconfig_generic_h () + make_gr_fir_sysconfig_generic_cc () + +if __name__ == '__main__': + generate () diff --git a/gnuradio-core/src/lib/filter/generate_gr_fir_util.py b/gnuradio-core/src/lib/filter/generate_gr_fir_util.py new file mode 100755 index 000000000..79fa51c27 --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_gr_fir_util.py @@ -0,0 +1,190 @@ +#!/bin/env python +# +# Copyright 2003,2009 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 generate_utils import * + +def make_info_struct (out, sig): + out.write ( +''' +struct GR_CORE_API gr_fir_%s_info { + const char *name; // implementation name, e.g., "generic", "SSE", "3DNow!" + gr_fir_%s *(*create)(const std::vector<%s> &taps); +}; +''' % (sig, sig, tap_type(sig))) + +def make_create (out, sig): + out.write (''' static gr_fir_%s *create_gr_fir_%s (const std::vector<%s> &taps); +''' % (sig, sig, tap_type (sig))) + +def make_info (out, sig): + out.write (''' static void get_gr_fir_%s_info (std::vector<gr_fir_%s_info> *info); +''' % (sig, sig)) + + +# ---------------------------------------------------------------- + +def make_gr_fir_util_h (): + out = open_and_log_name ('gr_fir_util.h', 'w') + if not out: + return + out.write (copyright) + + out.write ( +''' +/* + * WARNING: This file is automatically generated by + * generate_gr_fir_util.py. + * + * Any changes made to this file will be overwritten. + */ + +#ifndef INCLUDED_GR_FIR_UTIL_H +#define INCLUDED_GR_FIR_UTIL_H + +/*! + * \\brief routines to create gr_fir_XXX's + * + * This class handles selecting the fastest version of the finite + * implulse response filter available for your platform. This + * interface should be used by the rest of the system for creating + * gr_fir_XXX's. + * + * The trailing suffix has the form _IOT where I codes the input type, + * O codes the output type, and T codes the tap type. + * I,O,T are elements of the set 's' (short), 'f' (float), 'c' (gr_complex), + * 'i' (short) + */ + +#include <gr_core_api.h> +#include <gr_types.h> + +''') + + for sig in fir_signatures: + out.write ('class gr_fir_%s;\n' % sig); + + out.write ('\n// structures returned by get_gr_fir_XXX_info methods\n\n') + + for sig in fir_signatures: + make_info_struct (out, sig) + + out.write (''' +struct GR_CORE_API gr_fir_util { + + // create a fast version of gr_fir_XXX. + +''') + + for sig in fir_signatures: + make_create (out, sig) + + out.write (''' + // Get information about all gr_fir_XXX implementations. + // This is useful for benchmarking, testing, etc without having to + // know a priori what's linked into this image + // + // The caller must pass in a valid pointer to a vector. + // The vector will be filled with structs describing the + // available implementations. + +''') + + for sig in fir_signatures: + make_info (out, sig) + + out.write (''' +}; + +#endif /* INCLUDED_GR_FIR_UTIL_H */ +''') + out.close () + + +# ---------------------------------------------------------------- + +def make_constructor_cc (out, sig): + out.write ( +''' +gr_fir_%s * +gr_fir_util::create_gr_fir_%s (const std::vector<%s> &taps) +{ + return gr_fir_sysconfig_singleton()->create_gr_fir_%s (taps); +} +''' % (sig, sig, tap_type (sig), sig)) + + +def make_info_cc (out, sig): + out.write ( +''' +void +gr_fir_util::get_gr_fir_%s_info (std::vector<gr_fir_%s_info> *info) +{ + gr_fir_sysconfig_singleton()->get_gr_fir_%s_info (info); +} +''' % (sig, sig, sig)) + + +def make_gr_fir_util_cc (): + out = open_and_log_name ('gr_fir_util.cc', 'w') + if not out: + return + out.write (copyright) + out.write (''' + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_fir_util.h> +#include <gr_fir_sysconfig.h> + +// +// There's no problem that can't be solved by the addition of +// another layer of indirection... +// + +// --- constructors --- + +''') + + for sig in fir_signatures: + make_constructor_cc (out, sig) + + out.write (''' +// --- info gatherers --- + +''') + + for sig in fir_signatures: + make_info_cc (out, sig) + + out.close () + + +# ---------------------------------------------------------------- + +def generate (): + make_gr_fir_util_h () + make_gr_fir_util_cc () + +if __name__ == '__main__': + generate () + diff --git a/gnuradio-core/src/lib/filter/generate_gr_freq_xlating_fir_filter_XXX.py b/gnuradio-core/src/lib/filter/generate_gr_freq_xlating_fir_filter_XXX.py new file mode 100755 index 000000000..41c0b2b70 --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_gr_freq_xlating_fir_filter_XXX.py @@ -0,0 +1,53 @@ +#!/bin/env python +# -*- python -*- +# +# Copyright 2003,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. +# + +import re +from generate_utils import * + +# files to generate + +fx_signatures = [ 'scf', 'scc', 'fcf', 'fcc', 'ccf', 'ccc' ] + +roots = ['gr_freq_xlating_fir_filter_XXX'] + +def expand_h_cc_i (root, code3): + d = init_dict (root, code3) + expand_template (d, root + '.h.t') + expand_template (d, root + '.cc.t') + expand_template (d, root + '.i.t') + +def init_dict (root, code3): + name = re.sub ('X+', code3, root) + d = standard_dict (name, code3) + d['FIR_TYPE'] = 'gr_fir_' + i_code (code3) + 'cc' + return d + + +def generate (): + for r in roots: + for s in fx_signatures: + expand_h_cc_i (r, s) + + +if __name__ == '__main__': + generate () diff --git a/gnuradio-core/src/lib/filter/generate_gr_interp_fir_filter_XXX.py b/gnuradio-core/src/lib/filter/generate_gr_interp_fir_filter_XXX.py new file mode 100644 index 000000000..1dcfdaded --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_gr_interp_fir_filter_XXX.py @@ -0,0 +1,48 @@ +#!/bin/env python +# -*- python -*- +# +# Copyright 2003,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. +# + +import re +from generate_utils import * + +roots = ['gr_interp_fir_filter_XXX'] + +def expand_h_cc_i (root, code3): + d = init_dict (root, code3) + expand_template (d, root + '.h.t') + expand_template (d, root + '.cc.t') + expand_template (d, root + '.i.t') + +def init_dict (root, code3): + name = re.sub ('X+', code3, root) + d = standard_dict (name, code3) + d['FIR_TYPE'] = 'gr_fir_' + code3 + return d + +def generate (): + for r in roots: + for s in fir_signatures: + expand_h_cc_i (r, s) + +if __name__ == '__main__': + generate () + diff --git a/gnuradio-core/src/lib/filter/generate_gr_rational_resampler_base_XXX.py b/gnuradio-core/src/lib/filter/generate_gr_rational_resampler_base_XXX.py new file mode 100644 index 000000000..1dafec3fb --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_gr_rational_resampler_base_XXX.py @@ -0,0 +1,48 @@ +#!/bin/env python +# -*- python -*- +# +# Copyright 2003,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. +# + +import re +from generate_utils import * + +roots = ['gr_rational_resampler_base_XXX'] + +def expand_h_cc_i (root, code3): + d = init_dict (root, code3) + expand_template (d, root + '.h.t') + expand_template (d, root + '.cc.t') + expand_template (d, root + '.i.t') + +def init_dict (root, code3): + name = re.sub ('X+', code3, root) + d = standard_dict (name, code3) + d['FIR_TYPE'] = 'gr_fir_' + code3 + return d + +def generate (): + for r in roots: + for s in fir_signatures: + expand_h_cc_i (r, s) + +if __name__ == '__main__': + generate () + diff --git a/gnuradio-core/src/lib/filter/generate_gri_fir_filter_with_buffer_XXX.py b/gnuradio-core/src/lib/filter/generate_gri_fir_filter_with_buffer_XXX.py new file mode 100755 index 000000000..6442fb3dc --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_gri_fir_filter_with_buffer_XXX.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# -*- python -*- +# +# Copyright 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. +# + +import re +from generate_utils import * + +roots = ['gri_fir_filter_with_buffer_XXX',] + +def code3_to_acc_code (code3): + if i_code (code3) == 'c' or o_code (code3) == 'c' or tap_code (code3) == 'c': + return 'c' + if i_code (code3) == 'f' or o_code (code3) == 'f' or tap_code (code3) == 'f': + return 'f' + if i_code (code3) == 'i' or o_code (code3) == 'i' or tap_code (code3) == 'i': + return 'i' + return 'i' # even short short short needs int accumulator + +def code3_to_input_cast (code3): + if i_code (code3) == 's' and o_code (code3) == 'c': + return '(float)' + return '' + +def expand_h_cc (root, code3): + d = init_dict (root, code3) + expand_template (d, root + '.h.t') + expand_template (d, root + '.cc.t') + +def init_dict (root, code3): + name = re.sub ('X+', code3, root) + d = standard_dict (name, code3) + d['INPUT_CAST'] = code3_to_input_cast (code3) + acc_code = code3_to_acc_code (code3) + d['ACC_TYPE'] = char_to_type[acc_code] + return d + + +def generate (): + for r in roots: + for s in fir_signatures: + expand_h_cc (r, s) + + +if __name__ == '__main__': + generate () diff --git a/gnuradio-core/src/lib/filter/generate_utils.py b/gnuradio-core/src/lib/filter/generate_utils.py new file mode 100644 index 000000000..212ea95f9 --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_utils.py @@ -0,0 +1,31 @@ +# +# Copyright 2003,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. +# + +## ----------------------------------------------------------------------- +## signatures defines which variations to generate (input, output, taps) + +fir_signatures = [ 'ccf', 'fcc', 'ccc', 'fff', 'scc', 'fsf' ] + + +## ----------------------------------------------------------------------- + +from build_utils import expand_template, copyright, open_and_log_name, standard_dict +from build_utils_codes import * diff --git a/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccc.cc b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccc.cc new file mode 100644 index 000000000..da407caa0 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccc.cc @@ -0,0 +1,88 @@ +/* -*- 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 <gr_adaptive_fir_ccc.h> +#include <gr_io_signature.h> + +gr_adaptive_fir_ccc::gr_adaptive_fir_ccc(const char *name, int decimation, + const std::vector<gr_complex> &taps) + : gr_sync_decimator (name, + gr_make_io_signature (1, 1, sizeof(gr_complex)), + gr_make_io_signature (1, 1, sizeof(gr_complex)), + decimation), + d_updated(false), d_taps(taps) +{ + set_history(d_taps.size()); +} + +void +gr_adaptive_fir_ccc::set_taps(const std::vector<gr_complex> &taps) +{ + d_new_taps = taps; + d_updated = true; +} + +gr_complex +gr_adaptive_fir_ccc::filter(gr_complex *x) +{ + // Generic dot product of d_taps[] and in[] + gr_complex acc(0.0, 0.0); + int l = d_taps.size(); + for (int k = 0; k < l; k++) + acc += d_taps[l-k-1] * x[k]; + return acc; +} + +int +gr_adaptive_fir_ccc::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gr_complex *in = (gr_complex *)input_items[0]; + gr_complex *out = (gr_complex *)output_items[0]; + + if (d_updated) { + d_taps = d_new_taps; + set_history(d_taps.size()); + d_updated = false; + return 0; // history requirements may have changed. + } + + int j = 0, k, l = d_taps.size(); + for (int i = 0; i < noutput_items; i++) { + out[i] = filter(&in[j]); + + // Adjust taps + d_error = error(out[i]); + for (k = 0; k < l; k++) { + update_tap(d_taps[l-k-1], in[j+k]); + } + + j += decimation(); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccc.h b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccc.h new file mode 100644 index 000000000..d144c3eb4 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccc.h @@ -0,0 +1,62 @@ +/* -*- 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_GR_ADAPTIVE_FIR_CCC_H +#define INCLUDED_GR_ADAPTIVE_FIR_CCC_H + +#include <gr_core_api.h> +#include <gr_sync_decimator.h> + +/*! + * \brief Adaptive FIR filter with gr_complex input, gr_complex output and float taps + * \ingroup filter_blk + */ +class GR_CORE_API gr_adaptive_fir_ccc : public gr_sync_decimator +{ +private: + std::vector<gr_complex> d_new_taps; + bool d_updated; + +protected: + gr_complex d_error; + std::vector<gr_complex> d_taps; + + // Override to calculate error signal per output + virtual gr_complex error(const gr_complex &out) = 0; + + // Override to calculate new weight from old, corresponding input + virtual void update_tap(gr_complex &tap, const gr_complex &in) = 0; + + gr_complex filter(gr_complex *x); + + gr_adaptive_fir_ccc(const char *name, int decimation, + const std::vector<gr_complex> &taps); + +public: + void set_taps(const std::vector<gr_complex> &taps); + + 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/filter/gr_adaptive_fir_ccc.i b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccc.i new file mode 100644 index 000000000..a3c875a3d --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccc.i @@ -0,0 +1,31 @@ +/* -*- 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. + */ + +class gr_adaptive_fir_ccc : public gr_sync_decimator +{ +protected: + gr_adaptive_fir_ccc(char *name, int decimation, + const std::vector<gr_complex> &taps); + +public: + void set_taps(const std::vector<gr_complex> &taps); +}; diff --git a/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccf.cc b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccf.cc new file mode 100644 index 000000000..045d9faf9 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccf.cc @@ -0,0 +1,81 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_adaptive_fir_ccf.h> +#include <gr_io_signature.h> + +gr_adaptive_fir_ccf::gr_adaptive_fir_ccf(const char *name, int decimation, const std::vector<float> &taps) + : gr_sync_decimator (name, + gr_make_io_signature (1, 1, sizeof(gr_complex)), + gr_make_io_signature (1, 1, sizeof(gr_complex)), + decimation), + d_updated(false) +{ + d_taps = taps; + set_history(d_taps.size()); +} + +void gr_adaptive_fir_ccf::set_taps(const std::vector<float> &taps) +{ + d_new_taps = taps; + d_updated = true; +} + +int gr_adaptive_fir_ccf::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gr_complex *in = (gr_complex *)input_items[0]; + gr_complex *out = (gr_complex *)output_items[0]; + + if (d_updated) { + d_taps = d_new_taps; + set_history(d_taps.size()); + d_updated = false; + return 0; // history requirements may have changed. + } + + int j = 0, k, l = d_taps.size(); + for (int i = 0; i < noutput_items; i++) { + // Generic dot product of d_taps[] and in[] + gr_complex sum(0.0, 0.0); + for (k = 0; k < l; k++) + sum += d_taps[l-k-1]*in[j+k]; + out[i] = sum; + + // Adjust taps + d_error = error(sum); + for (k = 0; k < l; k++) { + //printf("%f ", d_taps[k]); + update_tap(d_taps[l-k-1], in[j+k]); + } + //printf("\n"); + + j += decimation(); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccf.h b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccf.h new file mode 100644 index 000000000..7ec78099f --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccf.h @@ -0,0 +1,59 @@ +/* -*- 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_ADAPTIVE_FIR_CCF_H +#define INCLUDED_GR_ADAPTIVE_FIR_CCF_H + +#include <gr_core_api.h> +#include <gr_sync_decimator.h> + +/*! + * \brief Adaptive FIR filter with gr_complex input, gr_complex output and float taps + * \ingroup filter_blk + */ +class GR_CORE_API gr_adaptive_fir_ccf : public gr_sync_decimator +{ +private: + std::vector<float> d_new_taps; + bool d_updated; + +protected: + float d_error; + std::vector<float> d_taps; + + // Override to calculate error signal per output + virtual float error(const gr_complex &out) = 0; + + // Override to calculate new weight from old, corresponding input + virtual void update_tap(float &tap, const gr_complex &in) = 0; + + gr_adaptive_fir_ccf(const char *name, int decimation, const std::vector<float> &taps); + +public: + void set_taps(const std::vector<float> &taps); + + 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/filter/gr_adaptive_fir_ccf.i b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccf.i new file mode 100644 index 000000000..346defd4d --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccf.i @@ -0,0 +1,30 @@ +/* -*- 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. + */ + +class gr_adaptive_fir_ccf : public gr_sync_decimator +{ +protected: + gr_adaptive_fir_ccf(char *name, int decimation, const std::vector<float> &taps); + +public: + void set_taps(const std::vector<float> &taps); +}; diff --git a/gnuradio-core/src/lib/filter/gr_altivec.c b/gnuradio-core/src/lib/filter/gr_altivec.c new file mode 100644 index 000000000..22a67291d --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_altivec.c @@ -0,0 +1,38 @@ +/* -*- 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include <gr_altivec.h> + +void +gr_print_vector_float(FILE *fp, vec_float4 v) +{ + union v_float_u u; + u.v = v; + fprintf(fp, "{ %f, %f, %f, %f }", u.f[0], u.f[1], u.f[2], u.f[3]); +} + +void +gr_pvf(FILE *fp, const char *label, vec_float4 v) +{ + fprintf(fp, "%s = ", label); + gr_print_vector_float(fp, v); + putc('\n', fp); +} diff --git a/gnuradio-core/src/lib/filter/gr_altivec.h b/gnuradio-core/src/lib/filter/gr_altivec.h new file mode 100644 index 000000000..ed11490f5 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_altivec.h @@ -0,0 +1,76 @@ +/* -*- 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef INCLUDED_GR_ALTIVEC_H +#define INCLUDED_GR_ALTIVEC_H + +/* + * N.B., always use "vec_float4" et al. instead of "vector float" to + * ensure portability across the various powerpc compilers. Some of + * them treat "vector" as a context specific keyword, some don't. + * Avoid the problem by always using the defines in vec_types.h + * (included below) + */ + +#include <gr_core_api.h> +#include <altivec.h> +#undef bool // repair namespace pollution +#undef vector // repair namespace pollution + +#ifdef HAVE_VEC_TYPES_H +#include <vec_types.h> // use system version if we've got it +#else +#include <gr_vec_types.h> // fall back to our local copy +#endif +#undef qword // repair namespace pollution + +#include <stddef.h> +#include <stdio.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#define VS sizeof(vec_float4) +#define FLOATS_PER_VEC (sizeof(vec_float4)/sizeof(float)) + +union v_float_u { + vec_float4 v; + float f[FLOATS_PER_VEC]; +}; + +GR_CORE_API void gr_print_vector_float(FILE *fp, vec_float4 v); +GR_CORE_API void gr_pvf(FILE *fp, const char *label, vec_float4 v); + +static inline float +horizontal_add_f(vec_float4 v) +{ + union v_float_u u; + vec_float4 t0 = vec_add(v, vec_sld(v, v, 8)); + vec_float4 t1 = vec_add(t0, vec_sld(t0, t0, 4)); + u.v = t1; + return u.f[0]; +} + +#ifdef __cplusplus +} +#endif + +#endif /* INCLUDED_GR_ALTIVEC_H */ diff --git a/gnuradio-core/src/lib/filter/gr_cpu.h b/gnuradio-core/src/lib/filter/gr_cpu.h new file mode 100644 index 000000000..35824ac1e --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_cpu.h @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2008,2009 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 _GR_CPU_H_ +#define _GR_CPU_H_ + +#include <gr_core_api.h> + +struct GR_CORE_API gr_cpu { + static bool has_mmx (); + static bool has_sse (); + static bool has_sse2 (); + static bool has_sse3 (); + static bool has_ssse3 (); + static bool has_sse4_1 (); + static bool has_sse4_2 (); + static bool has_3dnow (); + static bool has_3dnowext (); + static bool has_altivec (); + static bool has_armv7_a (); +}; + +#endif /* _GR_CPU_H_ */
\ No newline at end of file diff --git a/gnuradio-core/src/lib/filter/gr_cpu_armv7_a.cc b/gnuradio-core/src/lib/filter/gr_cpu_armv7_a.cc new file mode 100644 index 000000000..245049206 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_cpu_armv7_a.cc @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2008,2009 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 <gr_cpu.h> + +bool +gr_cpu::has_mmx () +{ + return false; +} + +bool +gr_cpu::has_sse () +{ + return false; +} + +bool +gr_cpu::has_sse2 () +{ + return false; +} + +bool +gr_cpu::has_3dnow () +{ + return false; +} + +bool +gr_cpu::has_3dnowext () +{ + return false; +} + +bool +gr_cpu::has_altivec () +{ + return false; +} + +bool +gr_cpu::has_armv7_a () +{ + return true; +} diff --git a/gnuradio-core/src/lib/filter/gr_cpu_powerpc.cc b/gnuradio-core/src/lib/filter/gr_cpu_powerpc.cc new file mode 100644 index 000000000..d613f0ae4 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_cpu_powerpc.cc @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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 <gr_cpu.h> + +bool +gr_cpu::has_mmx () +{ + return false; +} + +bool +gr_cpu::has_sse () +{ + return false; +} + +bool +gr_cpu::has_sse2 () +{ + return false; +} + +bool +gr_cpu::has_3dnow () +{ + return false; +} + +bool +gr_cpu::has_3dnowext () +{ + return false; +} + +bool +gr_cpu::has_altivec () +{ + return true; // FIXME assume we've always got it +} + +bool +gr_cpu::has_armv7_a () +{ + return false; +} diff --git a/gnuradio-core/src/lib/filter/gr_cpu_x86.cc b/gnuradio-core/src/lib/filter/gr_cpu_x86.cc new file mode 100644 index 000000000..3acd694d5 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_cpu_x86.cc @@ -0,0 +1,119 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2009 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 <gr_cpu.h> +#include "gcc_x86_cpuid.h" + +/* + * execute CPUID instruction, return EAX, EBX, ECX and EDX values in result + */ +#define cpuid_x86(op, r) __get_cpuid(op, r+0, r+1, r+2, r+3) + +/* + * CPUID functions returning a single datum + */ + +static inline unsigned int cpuid_eax(unsigned int op) +{ + unsigned int regs[4] = {0,0,0,0}; + cpuid_x86 (op, regs); + return regs[0]; +} + +static inline unsigned int cpuid_ebx(unsigned int op) +{ + unsigned int regs[4] = {0,0,0,0}; + cpuid_x86 (op, regs); + return regs[1]; +} + +static inline unsigned int cpuid_ecx(unsigned int op) +{ + unsigned int regs[4] = {0,0,0,0}; + cpuid_x86 (op, regs); + return regs[2]; +} + +static inline unsigned int cpuid_edx(unsigned int op) +{ + unsigned int regs[4] = {0,0,0,0}; + cpuid_x86 (op, regs); + return regs[3]; +} + +// ---------------------------------------------------------------- + +bool +gr_cpu::has_mmx () +{ + unsigned int edx = cpuid_edx (1); // standard features + return (edx & (1 << 23)) != 0; +} + +bool +gr_cpu::has_sse () +{ + unsigned int edx = cpuid_edx (1); // standard features + return (edx & (1 << 25)) != 0; +} + +bool +gr_cpu::has_sse2 () +{ + unsigned int edx = cpuid_edx (1); // standard features + return (edx & (1 << 26)) != 0; +} + +bool +gr_cpu::has_3dnow () +{ + unsigned int extended_fct_count = cpuid_eax (0x80000000); + if (extended_fct_count < 0x80000001) + return false; + + unsigned int extended_features = cpuid_edx (0x80000001); + return (extended_features & (1 << 31)) != 0; +} + +bool +gr_cpu::has_3dnowext () +{ + unsigned int extended_fct_count = cpuid_eax (0x80000000); + if (extended_fct_count < 0x80000001) + return false; + + unsigned int extended_features = cpuid_edx (0x80000001); + return (extended_features & (1 << 30)) != 0; +} + +bool +gr_cpu::has_altivec () +{ + return false; +} + +bool +gr_cpu::has_armv7_a () +{ + return false; +} + diff --git a/gnuradio-core/src/lib/filter/gr_dc_blocker_cc.cc b/gnuradio-core/src/lib/filter/gr_dc_blocker_cc.cc new file mode 100644 index 000000000..0438a193f --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_dc_blocker_cc.cc @@ -0,0 +1,138 @@ +/* -*- 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 <gr_dc_blocker_cc.h> +#include <gr_io_signature.h> +#include <cstdio> + +moving_averager_c::moving_averager_c(int D) + : d_length(D), d_out(0), d_out_d1(0), d_out_d2(0) +{ + d_delay_line = std::deque<gr_complex>(d_length-1, gr_complex(0,0)); +} + +moving_averager_c::~moving_averager_c() +{ +} + +gr_complex +moving_averager_c::filter(gr_complex x) +{ + d_out_d1 = d_out; + d_delay_line.push_back(x); + d_out = d_delay_line[0]; + d_delay_line.pop_front(); + + gr_complex y = x - d_out_d1 + d_out_d2; + d_out_d2 = y; + + return (y / (float)(d_length)); +} + + + +gr_dc_blocker_cc_sptr gr_make_dc_blocker_cc (int D, bool long_form) +{ + return gnuradio::get_initial_sptr(new gr_dc_blocker_cc(D, long_form)); +} + + +gr_dc_blocker_cc::gr_dc_blocker_cc (int D, bool long_form) + : gr_sync_block ("dc_blocker_cc", + gr_make_io_signature (1, 1, sizeof(gr_complex)), + gr_make_io_signature (1, 1, sizeof(gr_complex))), + d_length(D), d_long_form(long_form) +{ + if(d_long_form) { + d_ma_0 = new moving_averager_c(D); + d_ma_1 = new moving_averager_c(D); + d_ma_2 = new moving_averager_c(D); + d_ma_3 = new moving_averager_c(D); + d_delay_line = std::deque<gr_complex>(d_length-1, gr_complex(0,0)); + } + else { + d_ma_0 = new moving_averager_c(D); + d_ma_1 = new moving_averager_c(D); + } +} + +gr_dc_blocker_cc::~gr_dc_blocker_cc() +{ + if(d_long_form) { + delete d_ma_0; + delete d_ma_1; + delete d_ma_2; + delete d_ma_3; + } + else { + delete d_ma_0; + delete d_ma_1; + } +} + +int +gr_dc_blocker_cc::get_group_delay() +{ + if(d_long_form) + return (2*d_length-2); + else + return d_length - 1; +} + +int +gr_dc_blocker_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]; + + if(d_long_form) { + gr_complex y1, y2, y3, y4, d; + for(int i = 0; i < noutput_items; i++) { + y1 = d_ma_0->filter(in[i]); + y2 = d_ma_1->filter(y1); + y3 = d_ma_2->filter(y2); + y4 = d_ma_3->filter(y3); + + d_delay_line.push_back(d_ma_0->delayed_sig()); + d = d_delay_line[0]; + d_delay_line.pop_front(); + + out[i] = d - y4; + } + } + else { + gr_complex y1, y2; + for(int i = 0; i < noutput_items; i++) { + y1 = d_ma_0->filter(in[i]); + y2 = d_ma_1->filter(y1); + out[i] = d_ma_0->delayed_sig() - y2; + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_dc_blocker_cc.h b/gnuradio-core/src/lib/filter/gr_dc_blocker_cc.h new file mode 100644 index 000000000..e4d89a775 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_dc_blocker_cc.h @@ -0,0 +1,111 @@ +/* -*- 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_GR_DC_BLOCKER_CC_H +#define INCLUDED_GR_DC_BLOCKER_CC_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <deque> + +class GR_CORE_API moving_averager_c +{ +public: + moving_averager_c(int D); + ~moving_averager_c(); + + gr_complex filter(gr_complex x); + gr_complex delayed_sig() { return d_out; } + +private: + int d_length; + gr_complex d_out, d_out_d1, d_out_d2; + std::deque<gr_complex> d_delay_line; +}; + +class gr_dc_blocker_cc; +typedef boost::shared_ptr<gr_dc_blocker_cc> gr_dc_blocker_cc_sptr; +GR_CORE_API gr_dc_blocker_cc_sptr gr_make_dc_blocker_cc (int D=32, bool long_form=true); + +/*! + * \class gr_dc_blocker_cc + * \brief a computationally efficient controllable DC blocker + * + * \ingroup filter_blk + * + * This block implements a computationally efficient DC blocker that produces + * a tighter notch filter around DC for a smaller group delay than an + * equivalent FIR filter or using a single pole IIR filter (though the IIR + * filter is computationally cheaper). + * + * The block defaults to using a delay line of length 32 and the long form + * of the filter. Optionally, the delay line length can be changed to alter + * the width of the DC notch (longer lines will decrease the width). + * + * The long form of the filter produces a nearly flat response outside of + * the notch but at the cost of a group delay of 2D-2. + * + * The short form of the filter does not have as flat a response in the + * passband but has a group delay of only D-1 and is cheaper to compute. + * + * The theory behind this block can be found in the paper: + * + * <B><EM>R. Yates, "DC Blocker Algorithms," IEEE Signal Processing Magazine, + * Mar. 2008, pp 132-134.</EM></B> + */ +class GR_CORE_API gr_dc_blocker_cc : public gr_sync_block +{ + private: + /*! + * Build the DC blocker. + * \param D (int) the length of the delay line + * \param long_form (bool) whether to use long (true, default) or short form + */ + friend GR_CORE_API gr_dc_blocker_cc_sptr gr_make_dc_blocker_cc (int D, bool long_form); + + int d_length; + bool d_long_form; + moving_averager_c *d_ma_0; + moving_averager_c *d_ma_1; + moving_averager_c *d_ma_2; + moving_averager_c *d_ma_3; + std::deque<gr_complex> d_delay_line; + + gr_dc_blocker_cc (int D, bool long_form); + +public: + ~gr_dc_blocker_cc (); + + /*! + * Get the blocker's group delay that is based on length of delay lines + */ + int get_group_delay(); + + //int set_length(int D); + + 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/filter/gr_dc_blocker_cc.i b/gnuradio-core/src/lib/filter/gr_dc_blocker_cc.i new file mode 100644 index 000000000..83d05044b --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_dc_blocker_cc.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,dc_blocker_cc); + +gr_dc_blocker_cc_sptr gr_make_dc_blocker_cc (int D=32, bool long_form=true); + +class gr_dc_blocker_cc : public gr_sync_block +{ + private: + gr_dc_blocker_cc (int D, bool long_form); + + public: + ~gr_dc_blocker_cc (); +}; diff --git a/gnuradio-core/src/lib/filter/gr_dc_blocker_ff.cc b/gnuradio-core/src/lib/filter/gr_dc_blocker_ff.cc new file mode 100644 index 000000000..04ee64879 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_dc_blocker_ff.cc @@ -0,0 +1,138 @@ +/* -*- 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 <gr_dc_blocker_ff.h> +#include <gr_io_signature.h> +#include <cstdio> + +moving_averager_f::moving_averager_f(int D) + : d_length(D), d_out(0), d_out_d1(0), d_out_d2(0) +{ + d_delay_line = std::deque<float>(d_length-1, 0); +} + +moving_averager_f::~moving_averager_f() +{ +} + +float +moving_averager_f::filter(float x) +{ + d_out_d1 = d_out; + d_delay_line.push_back(x); + d_out = d_delay_line[0]; + d_delay_line.pop_front(); + + float y = x - d_out_d1 + d_out_d2; + d_out_d2 = y; + + return (y / (float)(d_length)); +} + + + +gr_dc_blocker_ff_sptr gr_make_dc_blocker_ff (int D, bool long_form) +{ + return gnuradio::get_initial_sptr(new gr_dc_blocker_ff(D, long_form)); +} + + +gr_dc_blocker_ff::gr_dc_blocker_ff (int D, bool long_form) + : gr_sync_block ("dc_blocker_ff", + gr_make_io_signature (1, 1, sizeof(float)), + gr_make_io_signature (1, 1, sizeof(float))), + d_length(D), d_long_form(long_form) +{ + if(d_long_form) { + d_ma_0 = new moving_averager_f(D); + d_ma_1 = new moving_averager_f(D); + d_ma_2 = new moving_averager_f(D); + d_ma_3 = new moving_averager_f(D); + d_delay_line = std::deque<float>(d_length-1, 0); + } + else { + d_ma_0 = new moving_averager_f(D); + d_ma_1 = new moving_averager_f(D); + } +} + +gr_dc_blocker_ff::~gr_dc_blocker_ff() +{ + if(d_long_form) { + delete d_ma_0; + delete d_ma_1; + delete d_ma_2; + delete d_ma_3; + } + else { + delete d_ma_0; + delete d_ma_1; + } +} + +int +gr_dc_blocker_ff::get_group_delay() +{ + if(d_long_form) + return (2*d_length-2); + else + return d_length - 1; +} + +int +gr_dc_blocker_ff::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]; + + if(d_long_form) { + float y1, y2, y3, y4, d; + for(int i = 0; i < noutput_items; i++) { + y1 = d_ma_0->filter(in[i]); + y2 = d_ma_1->filter(y1); + y3 = d_ma_2->filter(y2); + y4 = d_ma_3->filter(y3); + + d_delay_line.push_back(d_ma_0->delayed_sig()); + d = d_delay_line[0]; + d_delay_line.pop_front(); + + out[i] = d - y4; + } + } + else { + float y1, y2; + for(int i = 0; i < noutput_items; i++) { + y1 = d_ma_0->filter(in[i]); + y2 = d_ma_1->filter(y1); + out[i] = d_ma_0->delayed_sig() - y2; + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_dc_blocker_ff.h b/gnuradio-core/src/lib/filter/gr_dc_blocker_ff.h new file mode 100644 index 000000000..d69f24835 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_dc_blocker_ff.h @@ -0,0 +1,112 @@ +/* -*- 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_GR_DC_BLOCKER_FF_H +#define INCLUDED_GR_DC_BLOCKER_FF_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <deque> + +class GR_CORE_API moving_averager_f +{ +public: + moving_averager_f(int D); + ~moving_averager_f(); + + float filter(float x); + float delayed_sig() { return d_out; } + +private: + int d_length; + float d_out, d_out_d1, d_out_d2; + std::deque<float> d_delay_line; +}; + + +class gr_dc_blocker_ff; +typedef boost::shared_ptr<gr_dc_blocker_ff> gr_dc_blocker_ff_sptr; +GR_CORE_API gr_dc_blocker_ff_sptr gr_make_dc_blocker_ff (int D=32, bool long_form=true); + +/*! + * \class gr_dc_blocker_ff + * \brief a computationally efficient controllable DC blocker + * + * \ingroup filter_blk + * + * This block implements a computationally efficient DC blocker that produces + * a tighter notch filter around DC for a smaller group delay than an + * equivalent FIR filter or using a single pole IIR filter (though the IIR + * filter is computationally cheaper). + * + * The block defaults to using a delay line of length 32 and the long form + * of the filter. Optionally, the delay line length can be changed to alter + * the width of the DC notch (longer lines will decrease the width). + * + * The long form of the filter produces a nearly flat response outside of + * the notch but at the cost of a group delay of 2D-2. + * + * The short form of the filter does not have as flat a response in the + * passband but has a group delay of only D-1 and is cheaper to compute. + * + * The theory behind this block can be found in the paper: + * + * <B><EM>R. Yates, "DC Blocker Algorithms," IEEE Signal Processing Magazine, + * Mar. 2008, pp 132-134.</EM></B> + */ +class GR_CORE_API gr_dc_blocker_ff : public gr_sync_block +{ + private: + /*! + * Build the DC blocker. + * \param D (int) the length of the delay line + * \param long_form (bool) whether to use long (true, default) or short form + */ + friend GR_CORE_API gr_dc_blocker_ff_sptr gr_make_dc_blocker_ff (int D, bool long_form); + + int d_length; + bool d_long_form; + moving_averager_f *d_ma_0; + moving_averager_f *d_ma_1; + moving_averager_f *d_ma_2; + moving_averager_f *d_ma_3; + std::deque<float> d_delay_line; + + gr_dc_blocker_ff (int D, bool long_form); + +public: + ~gr_dc_blocker_ff (); + + /*! + * Get the blocker's group delay that is based on length of delay lines + */ + int get_group_delay(); + + //int set_length(int D); + + 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/filter/gr_dc_blocker_ff.i b/gnuradio-core/src/lib/filter/gr_dc_blocker_ff.i new file mode 100644 index 000000000..065eb441d --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_dc_blocker_ff.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,dc_blocker_ff); + +gr_dc_blocker_ff_sptr gr_make_dc_blocker_ff (int D=32, bool long_form=true); + +class gr_dc_blocker_ff : public gr_sync_block +{ + private: + gr_dc_blocker_ff (int D, bool long_form); + + public: + ~gr_dc_blocker_ff (); +}; diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.cc b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.cc new file mode 100644 index 000000000..08e231a44 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.cc @@ -0,0 +1,132 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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: This file is automatically generated by generate_gr_fft_filter_XXX.py + * Any changes made to this file will be overwritten. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_fft_filter_ccc.h> +#include <gri_fft_filter_ccc_generic.h> +#include <gr_io_signature.h> +#include <gri_fft.h> +#include <math.h> +#include <assert.h> +#include <stdexcept> +#include <gr_firdes.h> + +#include <cstdio> +#include <iostream> +#include <string.h> + +gr_fft_filter_ccc_sptr gr_make_fft_filter_ccc (int decimation, + const std::vector<gr_complex> &taps, + int nthreads) +{ + return gnuradio::get_initial_sptr(new gr_fft_filter_ccc (decimation, taps, nthreads)); +} + + +gr_fft_filter_ccc::gr_fft_filter_ccc (int decimation, + const std::vector<gr_complex> &taps, + int nthreads) + : gr_sync_decimator ("fft_filter_ccc", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (gr_complex)), + decimation), + d_updated(false) +{ + set_history(1); + +#if 1 // don't enable the sse version until handling it is worked out + d_filter = new gri_fft_filter_ccc_generic(decimation, taps, nthreads); +#else + d_filter = new gri_fft_filter_ccc_sse(decimation, taps); +#endif + + d_new_taps = taps; + d_nsamples = d_filter->set_taps(taps); + set_output_multiple(d_nsamples); +} + +gr_fft_filter_ccc::~gr_fft_filter_ccc () +{ + delete d_filter; +} + +void +gr_fft_filter_ccc::set_taps (const std::vector<gr_complex> &taps) +{ + d_new_taps = taps; + d_updated = true; +} + +std::vector<gr_complex> +gr_fft_filter_ccc::taps () const +{ + return d_new_taps; +} + +void +gr_fft_filter_ccc::set_nthreads(int n) +{ + if(d_filter) + d_filter->set_nthreads(n); +} + +int +gr_fft_filter_ccc::nthreads() const +{ + if(d_filter) + return d_filter->nthreads(); + else + return 0; +} + + +int +gr_fft_filter_ccc::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]; + + if (d_updated){ + d_nsamples = d_filter->set_taps(d_new_taps); + d_updated = false; + set_output_multiple(d_nsamples); + return 0; // output multiple may have changed + } + + assert(noutput_items % d_nsamples == 0); + + d_filter->filter(noutput_items, in, out); + + //assert((out - (gr_complex *) output_items[0]) == noutput_items); + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.h b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.h new file mode 100644 index 000000000..4b478b65f --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.h @@ -0,0 +1,90 @@ +/* -*- 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_FFT_FILTER_CCC_H +#define INCLUDED_GR_FFT_FILTER_CCC_H + +#include <gr_core_api.h> +#include <gr_sync_decimator.h> + +class gr_fft_filter_ccc; +typedef boost::shared_ptr<gr_fft_filter_ccc> gr_fft_filter_ccc_sptr; +GR_CORE_API gr_fft_filter_ccc_sptr +gr_make_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps, + int nthreads=1); + +//class gri_fft_filter_ccc_sse; +class gri_fft_filter_ccc_generic; + +/*! + * \brief Fast FFT filter with gr_complex input, gr_complex output and gr_complex taps + * \ingroup filter_blk + */ +class GR_CORE_API gr_fft_filter_ccc : public gr_sync_decimator +{ + private: + friend GR_CORE_API gr_fft_filter_ccc_sptr + gr_make_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps, + int nthreads); + + int d_nsamples; + bool d_updated; +#if 1 // don't enable the sse version until handling it is worked out + gri_fft_filter_ccc_generic *d_filter; +#else + gri_fft_filter_ccc_sse *d_filter; +#endif + std::vector<gr_complex> d_new_taps; + + /*! + * Construct a FFT filter with the given taps + * + * \param decimation >= 1 + * \param taps complex filter taps + * \param nthreads number of threads for the FFT to use + */ + gr_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps, + int nthreads=1); + + public: + ~gr_fft_filter_ccc (); + + void set_taps (const std::vector<gr_complex> &taps); + std::vector<gr_complex> taps () const; + + /*! + * \brief Set number of threads to use. + */ + void set_nthreads(int n); + + /*! + * \brief Get number of threads being used. + */ + int nthreads() const; + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + + +#endif /* INCLUDED_GR_FFT_FILTER_CCC_H */ diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.i b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.i new file mode 100644 index 000000000..76837b582 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.i @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,fft_filter_ccc) + +gr_fft_filter_ccc_sptr +gr_make_fft_filter_ccc (int decimation, + const std::vector<gr_complex> &taps, + int nthreads=1 + ) throw (std::invalid_argument); + +class gr_fft_filter_ccc : public gr_sync_decimator +{ + private: + gr_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps, + int nthreads=1); + + public: + ~gr_fft_filter_ccc (); + + void set_taps (const std::vector<gr_complex> &taps); + std::vector<gr_complex> taps () const; + + void set_nthreads(int n); + int nthreads() const; + +}; diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_fff.cc b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.cc new file mode 100644 index 000000000..a09feb7f1 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.cc @@ -0,0 +1,123 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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_fft_filter_fff.h> +#include <gri_fft_filter_fff_generic.h> +#include <gr_io_signature.h> +#include <assert.h> +#include <stdexcept> + +#include <cstdio> +#include <iostream> +#include <string.h> + +gr_fft_filter_fff_sptr gr_make_fft_filter_fff (int decimation, + const std::vector<float> &taps, + int nthreads) +{ + return gnuradio::get_initial_sptr(new gr_fft_filter_fff (decimation, taps, nthreads)); +} + + +gr_fft_filter_fff::gr_fft_filter_fff (int decimation, + const std::vector<float> &taps, + int nthreads) + : gr_sync_decimator ("fft_filter_fff", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (float)), + decimation), + d_updated(false) +{ + set_history(1); + +#if 1 // don't enable the sse version until handling it is worked out + d_filter = new gri_fft_filter_fff_generic(decimation, taps, nthreads); +#else + d_filter = new gri_fft_filter_fff_sse(decimation, taps); +#endif + + d_new_taps = taps; + d_nsamples = d_filter->set_taps(taps); + set_output_multiple(d_nsamples); +} + +gr_fft_filter_fff::~gr_fft_filter_fff () +{ + delete d_filter; +} + +void +gr_fft_filter_fff::set_taps (const std::vector<float> &taps) +{ + d_new_taps = taps; + d_updated = true; +} + +std::vector<float> +gr_fft_filter_fff::taps () const +{ + return d_new_taps; +} + +void +gr_fft_filter_fff::set_nthreads(int n) +{ + if(d_filter) + d_filter->set_nthreads(n); +} + +int +gr_fft_filter_fff::nthreads() const +{ + if(d_filter) + return d_filter->nthreads(); + else + return 0; +} + +int +gr_fft_filter_fff::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]; + + if (d_updated){ + d_nsamples = d_filter->set_taps(d_new_taps); + d_updated = false; + set_output_multiple(d_nsamples); + return 0; // output multiple may have changed + } + + assert(noutput_items % d_nsamples == 0); + + d_filter->filter(noutput_items, in, out); + + //assert((out - (float *) output_items[0]) == noutput_items); + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_fff.h b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.h new file mode 100644 index 000000000..309a55135 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.h @@ -0,0 +1,88 @@ +/* -*- 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_FFT_FILTER_FFF_H +#define INCLUDED_GR_FFT_FILTER_FFF_H + +#include <gr_core_api.h> +#include <gr_sync_decimator.h> + +class gr_fft_filter_fff; +typedef boost::shared_ptr<gr_fft_filter_fff> gr_fft_filter_fff_sptr; +GR_CORE_API gr_fft_filter_fff_sptr +gr_make_fft_filter_fff (int decimation, const std::vector<float> &taps, + int nthreads=1); + +class gri_fft_filter_fff_generic; +//class gri_fft_filter_fff_sse; + +/*! + * \brief Fast FFT filter with float input, float output and float taps + * \ingroup filter_blk + */ +class GR_CORE_API gr_fft_filter_fff : public gr_sync_decimator +{ + private: + friend GR_CORE_API gr_fft_filter_fff_sptr + gr_make_fft_filter_fff (int decimation, const std::vector<float> &taps, + int nthreads); + + int d_nsamples; + bool d_updated; +#if 1 // don't enable the sse version until handling it is worked out + gri_fft_filter_fff_generic *d_filter; +#else + gri_fft_filter_fff_sse *d_filter; +#endif + std::vector<float> d_new_taps; + + /*! + * Construct a FFT filter with the given taps + * + * \param decimation >= 1 + * \param taps float filter taps + * \param nthreads number of threads for the FFT to use + */ + gr_fft_filter_fff (int decimation, const std::vector<float> &taps, + int nthreads=1); + + public: + ~gr_fft_filter_fff (); + + void set_taps (const std::vector<float> &taps); + std::vector<float> taps () const; + + /*! + * \brief Set number of threads to use. + */ + void set_nthreads(int n); + + /*! + * \brief Get number of threads being used. + */ + int nthreads() const; + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_FFT_FILTER_FFF_H */ diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_fff.i b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.i new file mode 100644 index 000000000..86c554893 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.i @@ -0,0 +1,45 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,fft_filter_fff) + +gr_fft_filter_fff_sptr +gr_make_fft_filter_fff (int decimation, + const std::vector<float> &taps, + int nthreads=1 + ) throw (std::invalid_argument); + +class gr_fft_filter_fff : public gr_sync_decimator +{ + private: + gr_fft_filter_fff (int decimation, const std::vector<float> &taps, + int nthreads=1); + + public: + ~gr_fft_filter_fff (); + + void set_taps (const std::vector<float> &taps); + std::vector<float> taps () const; + void set_nthreads(int n); + int nthreads() const; + +}; diff --git a/gnuradio-core/src/lib/filter/gr_filter_delay_fc.cc b/gnuradio-core/src/lib/filter/gr_filter_delay_fc.cc new file mode 100644 index 000000000..af8a8e9e7 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_filter_delay_fc.cc @@ -0,0 +1,80 @@ +/* -*- 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_filter_delay_fc.h> +#include <gr_fir_fff.h> +#include <gr_fir_util.h> + +// public constructor +gr_filter_delay_fc_sptr +gr_make_filter_delay_fc (const std::vector<float> &taps) +{ + return gnuradio::get_initial_sptr(new gr_filter_delay_fc (taps)); +} + +gr_filter_delay_fc::gr_filter_delay_fc (const std::vector<float> &taps) + : gr_sync_block ("filter_delay_fc", + gr_make_io_signature (1, 2, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (gr_complex))) +{ + d_fir = gr_fir_util::create_gr_fir_fff (taps); + d_delay = d_fir->ntaps () / 2; + set_history (d_fir->ntaps ()); +} + +gr_filter_delay_fc::~gr_filter_delay_fc () +{ + delete d_fir; +} + +int +gr_filter_delay_fc::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float *in0 = (float *) input_items[0]; + float *in1 = (float *) input_items[1]; + gr_complex *out = (gr_complex *) output_items[0]; + + switch (input_items.size ()){ + case 1: + for (int i = 0; i < noutput_items; i++) + out[i] = gr_complex (in0[i + d_delay], + d_fir->filter (&in0[i])); + break; + + case 2: + for (int j = 0; j < noutput_items; j++) + out[j] = gr_complex (in0[j + d_delay], + d_fir->filter (&in1[j])); + break; + + default: + assert (0); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_filter_delay_fc.h b/gnuradio-core/src/lib/filter/gr_filter_delay_fc.h new file mode 100644 index 000000000..fee11243a --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_filter_delay_fc.h @@ -0,0 +1,73 @@ +/* -*- 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_FILTER_DELAY_FC_H +#define INCLUDED_GR_FILTER_DELAY_FC_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_io_signature.h> +#include <gr_types.h> + +class gr_filter_delay_fc; +typedef boost::shared_ptr<gr_filter_delay_fc> gr_filter_delay_fc_sptr; + +// public constructor +GR_CORE_API gr_filter_delay_fc_sptr gr_make_filter_delay_fc (const std::vector<float> &taps); + +class gr_fir_fff; + +/*! + * \brief Filter-Delay Combination Block. + * \ingroup filter_blk + * + * The block takes one or two float stream and outputs a complex + * stream. If only one float stream is input, the real output is + * a delayed version of this input and the imaginary output is the + * filtered output. If two floats are connected to the input, then + * the real output is the delayed version of the first input, and + * the imaginary output is the filtered output. The delay in the + * real path accounts for the group delay introduced by the filter + * in the imaginary path. The filter taps needs to be calculated + * before initializing this block. + * + */ +class GR_CORE_API gr_filter_delay_fc : public gr_sync_block +{ + public: + ~gr_filter_delay_fc (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + protected: + gr_filter_delay_fc (const std::vector<float> &taps); + + private: + unsigned int d_delay; + gr_fir_fff *d_fir; + + friend GR_CORE_API gr_filter_delay_fc_sptr gr_make_filter_delay_fc (const std::vector<float> &taps); +}; + +#endif /* INCLUDED_GR_FILTER_DELAY_FC_H */ diff --git a/gnuradio-core/src/lib/filter/gr_filter_delay_fc.i b/gnuradio-core/src/lib/filter/gr_filter_delay_fc.i new file mode 100644 index 000000000..54b721cee --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_filter_delay_fc.i @@ -0,0 +1,34 @@ +/* -*- 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,filter_delay_fc); + +gr_filter_delay_fc_sptr gr_make_filter_delay_fc (const std::vector<float> &taps); + +class gr_filter_delay_fc : public gr_sync_block +{ +private: + gr_filter_delay_fc (); +}; + +// ---------------------------------------------------------------- + diff --git a/gnuradio-core/src/lib/filter/gr_fir_XXX.cc.t b/gnuradio-core/src/lib/filter/gr_fir_XXX.cc.t new file mode 100644 index 000000000..2396f0fe6 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_XXX.cc.t @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 <@FIR_TYPE@.h> + +@FIR_TYPE@::~@FIR_TYPE@ () +{ +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_XXX.h.t b/gnuradio-core/src/lib/filter/gr_fir_XXX.h.t new file mode 100644 index 000000000..197bb3cd2 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_XXX.h.t @@ -0,0 +1,124 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2003 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: This file is automatically generated by generate_gr_fir_XXX.py + * Any changes made to this file will be overwritten. + */ + + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_core_api.h> +#include <vector> +@VRCOMPLEX_INCLUDE@ +#include <gr_reverse.h> + +/*! + * \brief Abstract class for FIR with @I_TYPE@ input, @O_TYPE@ output and @TAP_TYPE@ taps + * \ingroup filter_primitive + * + * This is the abstract class for a Finite Impulse Response filter. + * + * The trailing suffix has the form _IOT where I codes the input type, + * O codes the output type, and T codes the tap type. + * I,O,T are elements of the set 's' (short), 'f' (float), 'c' (gr_complex), 'i' (int) + */ + +class GR_CORE_API @FIR_TYPE@ { + +protected: + std::vector<@TAP_TYPE@> d_taps; // reversed taps + +public: + + // CONSTRUCTORS + + /*! + * \brief construct new FIR with given taps. + * + * Note that taps must be in forward order, e.g., coefficient 0 is + * stored in new_taps[0], coefficient 1 is stored in + * new_taps[1], etc. + */ + @FIR_TYPE@ () {} + @FIR_TYPE@ (const std::vector<@TAP_TYPE@> &taps) : d_taps (gr_reverse(taps)) {} + + virtual ~@FIR_TYPE@ (); + + // MANIPULATORS + + /*! + * \brief compute a single output value. + * + * \p input must have ntaps() valid entries. + * input[0] .. input[ntaps() - 1] are referenced to compute the output value. + * + * \returns the filtered input value. + */ + virtual @O_TYPE@ filter (const @I_TYPE@ input[]) = 0; + + /*! + * \brief compute an array of N output values. + * + * \p input must have (n - 1 + ntaps()) valid entries. + * input[0] .. input[n - 1 + ntaps() - 1] are referenced to compute the output values. + */ + virtual void filterN (@O_TYPE@ output[], const @I_TYPE@ input[], + unsigned long n) = 0; + + /*! + * \brief compute an array of N output values, decimating the input + * + * \p input must have (decimate * (n - 1) + ntaps()) valid entries. + * input[0] .. input[decimate * (n - 1) + ntaps() - 1] are referenced to + * compute the output values. + */ + virtual void filterNdec (@O_TYPE@ output[], const @I_TYPE@ input[], + unsigned long n, unsigned decimate) = 0; + + /*! + * \brief install \p new_taps as the current taps. + */ + virtual void set_taps (const std::vector<@TAP_TYPE@> &taps) + { + d_taps = gr_reverse(taps); + } + + // ACCESSORS + + /*! + * \return number of taps in filter. + */ + unsigned ntaps () const { return d_taps.size (); } + + /*! + * \return current taps + */ + virtual const std::vector<@TAP_TYPE@> get_taps () const + { + return gr_reverse(d_taps); + } +}; + +#endif /* @GUARD_NAME@ */ diff --git a/gnuradio-core/src/lib/filter/gr_fir_XXX_generic.cc.t b/gnuradio-core/src/lib/filter/gr_fir_XXX_generic.cc.t new file mode 100644 index 000000000..11b4fd50f --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_XXX_generic.cc.t @@ -0,0 +1,103 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 <@FIR_TYPE@_generic.h> + +#if (@N_UNROLL@ == 4) + +@O_TYPE@ +@FIR_TYPE@_generic::filter (const @I_TYPE@ input[]) +{ + static const int N_UNROLL = 4; + + @ACC_TYPE@ acc0 = 0; + @ACC_TYPE@ acc1 = 0; + @ACC_TYPE@ acc2 = 0; + @ACC_TYPE@ acc3 = 0; + + + unsigned i = 0; + unsigned n = (ntaps () / N_UNROLL) * N_UNROLL; + + for (i = 0; i < n; i += N_UNROLL){ + acc0 += d_taps[i + 0] * @INPUT_CAST@ input[i + 0]; + acc1 += d_taps[i + 1] * @INPUT_CAST@ input[i + 1]; + acc2 += d_taps[i + 2] * @INPUT_CAST@ input[i + 2]; + acc3 += d_taps[i + 3] * @INPUT_CAST@ input[i + 3]; + } + + for (; i < ntaps (); i++) + acc0 += d_taps[i] * @INPUT_CAST@ input[i]; + + return (@O_TYPE@) (acc0 + acc1 + acc2 + acc3); +} + +#else + +@O_TYPE@ +@FIR_TYPE@_generic::filter (const @I_TYPE@ input[]) +{ + static const int N_UNROLL = 2; + + @ACC_TYPE@ acc0 = 0; + @ACC_TYPE@ acc1 = 0; + + unsigned i = 0; + unsigned n = (ntaps () / N_UNROLL) * N_UNROLL; + + for (i = 0; i < n; i += N_UNROLL){ + acc0 += d_taps[i + 0] * @INPUT_CAST@ input[i + 0]; + acc1 += d_taps[i + 1] * @INPUT_CAST@ input[i + 1]; + } + + for (; i < ntaps (); i++) + acc0 += d_taps[i] * @INPUT_CAST@ input[i]; + + return (@O_TYPE@) (acc0 + acc1); +} + +#endif // N_UNROLL + +void +@FIR_TYPE@_generic::filterN (@O_TYPE@ output[], + const @I_TYPE@ input[], + unsigned long n) +{ + for (unsigned i = 0; i < n; i++) + output[i] = filter (&input[i]); +} + +void +@FIR_TYPE@_generic::filterNdec (@O_TYPE@ output[], + const @I_TYPE@ input[], + unsigned long n, + unsigned decimate) +{ + unsigned j = 0; + for (unsigned i = 0; i < n; i++){ + output[i] = filter (&input[j]); + j += decimate; + } +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_XXX_generic.h.t b/gnuradio-core/src/lib/filter/gr_fir_XXX_generic.h.t new file mode 100644 index 000000000..f7382d739 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_XXX_generic.h.t @@ -0,0 +1,78 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_core_api.h> +#include <@FIR_TYPE@.h> + +/*! + * \brief Concrete class for generic implementation of FIR with @I_TYPE@ input, @O_TYPE@ output and @TAP_TYPE@ taps + * + * The trailing suffix has the form _IOT where I codes the input type, + * O codes the output type, and T codes the tap type. + * I,O,T are elements of the set 's' (short), 'f' (float), 'c' (gr_complex), 'i' (int) + */ + +class GR_CORE_API @FIR_TYPE@_generic : public @FIR_TYPE@ { + +public: + + // CREATORS + + @FIR_TYPE@_generic () {} + @FIR_TYPE@_generic (const std::vector<@TAP_TYPE@> &taps) : @FIR_TYPE@ (taps) {} + + // MANIPULATORS + + /*! + * \brief compute a single output value. + * + * \p input must have ntaps() valid entries. + * input[0] .. input[ntaps() - 1] are referenced to compute the output value. + * + * \returns the filtered input value. + */ + virtual @O_TYPE@ filter (const @I_TYPE@ input[]); + + /*! + * \brief compute an array of N output values. + * + * \p input must have (n - 1 + ntaps()) valid entries. + * input[0] .. input[n - 1 + ntaps() - 1] are referenced to compute the output values. + */ + virtual void filterN (@O_TYPE@ output[], const @I_TYPE@ input[], + unsigned long n); + + /*! + * \brief compute an array of N output values, decimating the input + * + * \p input must have (decimate * (n - 1) + ntaps()) valid entries. + * input[0] .. input[decimate * (n - 1) + ntaps() - 1] are referenced to + * compute the output values. + */ + virtual void filterNdec (@O_TYPE@ output[], const @I_TYPE@ input[], + unsigned long n, unsigned decimate); + +}; + +#endif /* @GUARD_NAME@ */ diff --git a/gnuradio-core/src/lib/filter/gr_fir_ccc_simd.cc b/gnuradio-core/src/lib/filter/gr_fir_ccc_simd.cc new file mode 100644 index 000000000..d88b696c9 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_ccc_simd.cc @@ -0,0 +1,142 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_fir_ccc_simd.h> + +#include <assert.h> +#include <malloc16.h> +#include <iostream> +#include <stdexcept> + +using std::cerr; +using std::endl; + +gr_fir_ccc_simd::gr_fir_ccc_simd () + : gr_fir_ccc_generic () +{ + // cerr << "@@@ gr_fir_ccc_simd\n"; + + d_ccomplex_dotprod = 0; + + d_aligned_taps[0] = 0; + d_aligned_taps[1] = 0; + d_aligned_taps[2] = 0; + d_aligned_taps[3] = 0; +} + +gr_fir_ccc_simd::gr_fir_ccc_simd (const std::vector<gr_complex> &new_taps) + : gr_fir_ccc_generic (new_taps) +{ + // cerr << "@@@ gr_fir_ccc_simd\n"; + + d_ccomplex_dotprod = 0; + + d_aligned_taps[0] = 0; + d_aligned_taps[1] = 0; + d_aligned_taps[2] = 0; + d_aligned_taps[3] = 0; + set_taps (new_taps); +} + +gr_fir_ccc_simd::~gr_fir_ccc_simd () +{ + free16Align (d_aligned_taps[0]); + free16Align (d_aligned_taps[1]); + free16Align (d_aligned_taps[2]); + free16Align (d_aligned_taps[3]); +} + +void +gr_fir_ccc_simd::set_taps (const std::vector<gr_complex> &inew_taps) +{ + gr_fir_ccc::set_taps (inew_taps); // call superclass + + const std::vector<gr_complex> new_taps = gr_reverse(inew_taps); + unsigned len = new_taps.size (); + + // Make 4 copies of the coefficients, one for each data alignment + // Note use of special 16-byte-aligned version of calloc() + + for (unsigned i = 0; i < 4; i++){ + free16Align (d_aligned_taps[i]); // free old value + + // this works because the bit representation of a IEEE floating point + // +zero is all zeros. If you're using a different representation, + // you'll need to explictly set the result to the appropriate 0.0 value. + + d_aligned_taps[i] = (float *) calloc16Align (1 + (len + i - 1) / 2, + 2 * 4 * sizeof (float)); + if (d_aligned_taps[i] == 0){ + // throw something... + cerr << "@@@ gr_fir_ccc_simd d_aligned_taps[" << i << "] == 0\n"; + } + + for (unsigned j = 0; j < len; j++) { + d_aligned_taps[i][2*(j+i)] = new_taps[j].real(); + d_aligned_taps[i][2*(j+i)+1] = new_taps[j].imag(); + } + } +} + +gr_complex +gr_fir_ccc_simd::filter (const gr_complex input[]) +{ + if (ntaps () == 0) + return 0.0; + + if (((intptr_t) input & 0x7) != 0) + throw std::invalid_argument("gr_complex must be 8-byte aligned"); + + // Round input data address down to 16 byte boundary + // NB: depending on the alignment of input[], memory + // before input[] will be accessed. The contents don't matter since + // they'll be multiplied by zero coefficients. I can't conceive of any + // situation where this could cause a segfault since memory protection + // in the x86 machines is done on much larger boundaries. + + const gr_complex *ar = (gr_complex *)((unsigned long) input & ~15); + + // Choose one of 4 sets of pre-shifted coefficients. al is both the + // index into d_aligned_taps[] and the number of 0 words padded onto + // that coefficients array for alignment purposes. + + unsigned al = input - ar; + + // call assembler routine to do the work, passing number of 2x4-float blocks. + + // assert (((unsigned long) ar & 15) == 0); + // assert (((unsigned long) d_aligned_taps[al] & 15) == 0); + + // cerr << "ar: " << ar << " d_aligned_taps[ar]: " << d_aligned_taps[al] + // << " (ntaps() + al - 1)/2 + 1: " << (ntaps() + al -1) / 2 + 1 << endl; + + float result[2]; + + d_ccomplex_dotprod ((float*)ar, d_aligned_taps[al], (ntaps() + al - 1) / 2 + 1, result); + + // cerr << "result = " << result[0] << " " << result[1] << endl; + + return gr_complex(result[0], result[1]); +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_ccc_simd.h b/gnuradio-core/src/lib/filter/gr_fir_ccc_simd.h new file mode 100644 index 000000000..ed7249c91 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_ccc_simd.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_FIR_CCC_SIMD_H +#define INCLUDED_GR_FIR_CCC_SIMD_H + +#include <gr_core_api.h> +#include <gr_fir_ccc_generic.h> + +/*! + * \brief common base class for SIMD versions of gr_fir_ccc + * \ingroup filter_primitive + * + * This base class handles alignment issues common to SSE and 3DNOW + * subclasses. + */ + +class GR_CORE_API gr_fir_ccc_simd : public gr_fir_ccc_generic +{ +protected: + typedef void (*ccomplex_dotprod_t)(const float *input, + const float *taps, + unsigned n_2_ccomplex_blocks, + float *result); + + /*! + * \p aligned_taps holds 4 copies of the coefficients preshifted + * by 0, 1, 2, or 3 floats to meet all possible input data alignments. + * This allows us to always fetch data and taps that are 128-bit aligned. + */ + float *d_aligned_taps[4]; + + ccomplex_dotprod_t d_ccomplex_dotprod; // fast dot product primitive + +public: + + // CREATORS + gr_fir_ccc_simd (); + gr_fir_ccc_simd (const std::vector<gr_complex> &taps); + ~gr_fir_ccc_simd (); + + // MANIPULATORS + virtual void set_taps (const std::vector<gr_complex> &taps); + virtual gr_complex filter (const gr_complex input[]); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_ccc_x86.cc b/gnuradio-core/src/lib/filter/gr_fir_ccc_x86.cc new file mode 100644 index 000000000..28bc008e8 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_ccc_x86.cc @@ -0,0 +1,77 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_fir_ccc_x86.h> +#include <ccomplex_dotprod_x86.h> + +/* + * --- 3DNow! version --- + */ + +gr_fir_ccc_3dnow::gr_fir_ccc_3dnow () + : gr_fir_ccc_simd () +{ + d_ccomplex_dotprod = ccomplex_dotprod_3dnow; +} + +gr_fir_ccc_3dnow::gr_fir_ccc_3dnow (const std::vector<gr_complex> &new_taps) + : gr_fir_ccc_simd (new_taps) +{ + d_ccomplex_dotprod = ccomplex_dotprod_3dnow; +} + + +/* + * --- 3DNow!Ext version --- + */ + +gr_fir_ccc_3dnowext::gr_fir_ccc_3dnowext () + : gr_fir_ccc_simd () +{ + d_ccomplex_dotprod = ccomplex_dotprod_3dnowext; +} + +gr_fir_ccc_3dnowext::gr_fir_ccc_3dnowext (const std::vector<gr_complex> &new_taps) + : gr_fir_ccc_simd (new_taps) +{ + d_ccomplex_dotprod = ccomplex_dotprod_3dnowext; +} + + +/* + * --- SSE version --- + */ + +gr_fir_ccc_sse::gr_fir_ccc_sse () + : gr_fir_ccc_simd () +{ + d_ccomplex_dotprod = ccomplex_dotprod_sse; +} + +gr_fir_ccc_sse::gr_fir_ccc_sse (const std::vector<gr_complex> &new_taps) + : gr_fir_ccc_simd (new_taps) +{ + d_ccomplex_dotprod = ccomplex_dotprod_sse; +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_ccc_x86.h b/gnuradio-core/src/lib/filter/gr_fir_ccc_x86.h new file mode 100644 index 000000000..0a9d2c83c --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_ccc_x86.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_FIR_CCC_X86_H +#define INCLUDED_GR_FIR_CCC_X86_H + +#include <gr_core_api.h> +#include <gr_fir_ccc_simd.h> + +/*! + * \brief 3DNow! version of gr_fir_ccc + */ +class GR_CORE_API gr_fir_ccc_3dnow : public gr_fir_ccc_simd +{ +public: + gr_fir_ccc_3dnow (); + gr_fir_ccc_3dnow (const std::vector<gr_complex> &taps); +}; + +class GR_CORE_API gr_fir_ccc_3dnowext : public gr_fir_ccc_simd +{ +public: + gr_fir_ccc_3dnowext (); + gr_fir_ccc_3dnowext (const std::vector<gr_complex> &taps); +}; + +/*! + * \brief SSE version of gr_fir_ccc + */ +class GR_CORE_API gr_fir_ccc_sse : public gr_fir_ccc_simd +{ +public: + gr_fir_ccc_sse (); + gr_fir_ccc_sse (const std::vector<gr_complex> &taps); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_ccf_armv7_a.cc b/gnuradio-core/src/lib/filter/gr_fir_ccf_armv7_a.cc new file mode 100644 index 000000000..d849c3dd5 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_ccf_armv7_a.cc @@ -0,0 +1,91 @@ +/* -*- 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gr_fir_ccf_armv7_a.h> +#include <stdlib.h> +#include <string.h> +#include <stdexcept> +#include <assert.h> +#include <gr_math.h> +#include <dotprod_ccf_armv7_a.h> + +#define FLOATS_PER_VEC 4 + +gr_fir_ccf_armv7_a::gr_fir_ccf_armv7_a() + : gr_fir_ccf_generic(), + d_naligned_taps(0), d_aligned_taps(0) +{ +} + +gr_fir_ccf_armv7_a::gr_fir_ccf_armv7_a (const std::vector<float> &new_taps) + : gr_fir_ccf_generic(new_taps), + d_naligned_taps(0), d_aligned_taps(0) +{ + set_taps(new_taps); +} + +gr_fir_ccf_armv7_a::~gr_fir_ccf_armv7_a() +{ + if (d_aligned_taps){ + free(d_aligned_taps); + d_aligned_taps = 0; + } +} + +void +gr_fir_ccf_armv7_a::set_taps(const std::vector<float> &inew_taps) +{ + gr_fir_ccf_generic::set_taps(inew_taps); // call superclass + d_naligned_taps = gr_p2_round_up(ntaps(), FLOATS_PER_VEC); + + if (d_aligned_taps){ + free(d_aligned_taps); + d_aligned_taps = 0; + } + void *p; + int r = posix_memalign(&p, sizeof(float), d_naligned_taps * sizeof(d_aligned_taps[0])); + if (r != 0){ + throw std::bad_alloc(); + } + d_aligned_taps = (float *) p; + memcpy(d_aligned_taps, &d_taps[0], ntaps() * sizeof(d_aligned_taps[0])); + for (size_t i = ntaps(); i < d_naligned_taps; i++) + d_aligned_taps[i] = 0.0; +} + + +gr_complex +gr_fir_ccf_armv7_a::filter (const gr_complex input[]) +{ + if (d_naligned_taps == 0) + return 0.0; + + gr_complex result; + float *presult = reinterpret_cast<float *>(&result); + const float *pinput = reinterpret_cast<const float *>(input); + + dotprod_ccf_armv7_a(pinput, d_aligned_taps, presult, d_naligned_taps); + return result; +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_ccf_armv7_a.h b/gnuradio-core/src/lib/filter/gr_fir_ccf_armv7_a.h new file mode 100644 index 000000000..e4844bae1 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_ccf_armv7_a.h @@ -0,0 +1,45 @@ +/* -*- 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef INCLUDED_GR_FIR_CCF_ARMV7_A_H +#define INCLUDED_GR_FIR_CCF_ARMV7_A_H + +#include <gr_fir_ccf_generic.h> + +/*! + * \brief armv7_a using NEON coprocessor version of gr_fir_ccf + */ +class gr_fir_ccf_armv7_a : public gr_fir_ccf_generic +{ +protected: + + size_t d_naligned_taps; // number of taps (multiple of 4) + float *d_aligned_taps; // 16-byte aligned, and zero padded to multiple of 4 + +public: + gr_fir_ccf_armv7_a(); + gr_fir_ccf_armv7_a(const std::vector<float> &taps); + ~gr_fir_ccf_armv7_a(); + + virtual void set_taps (const std::vector<float> &taps); + virtual gr_complex filter (const gr_complex input[]); +}; + +#endif /* INCLUDED_GR_FIR_CCF_ARMV7_A*_H */ diff --git a/gnuradio-core/src/lib/filter/gr_fir_ccf_simd.cc b/gnuradio-core/src/lib/filter/gr_fir_ccf_simd.cc new file mode 100644 index 000000000..872415e8e --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_ccf_simd.cc @@ -0,0 +1,141 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_fir_ccf_simd.h> + +#include <assert.h> +#include <malloc16.h> +#include <iostream> +#include <stdexcept> + +using std::cerr; +using std::endl; + +gr_fir_ccf_simd::gr_fir_ccf_simd () + : gr_fir_ccf_generic () +{ + // cerr << "@@@ gr_fir_ccf_simd\n"; + + d_fcomplex_dotprod = 0; + + d_aligned_taps[0] = 0; + d_aligned_taps[1] = 0; + d_aligned_taps[2] = 0; + d_aligned_taps[3] = 0; +} + +gr_fir_ccf_simd::gr_fir_ccf_simd (const std::vector<float> &new_taps) + : gr_fir_ccf_generic (new_taps) +{ + // cerr << "@@@ gr_fir_ccf_simd\n"; + + d_fcomplex_dotprod = 0; + + d_aligned_taps[0] = 0; + d_aligned_taps[1] = 0; + d_aligned_taps[2] = 0; + d_aligned_taps[3] = 0; + set_taps (new_taps); +} + +gr_fir_ccf_simd::~gr_fir_ccf_simd () +{ + free16Align (d_aligned_taps[0]); + free16Align (d_aligned_taps[1]); + free16Align (d_aligned_taps[2]); + free16Align (d_aligned_taps[3]); +} + +void +gr_fir_ccf_simd::set_taps (const std::vector<float> &inew_taps) +{ + gr_fir_ccf::set_taps (inew_taps); // call superclass + const std::vector<float> new_taps = gr_reverse(inew_taps); + + unsigned len = new_taps.size (); + + // Make 4 copies of the coefficients, one for each data alignment + // Note use of special 16-byte-aligned version of calloc() + + for (unsigned i = 0; i < 4; i++){ + free16Align (d_aligned_taps[i]); // free old value + + // this works because the bit representation of a IEEE floating point + // +zero is all zeros. If you're using a different representation, + // you'll need to explictly set the result to the appropriate 0.0 value. + + d_aligned_taps[i] = (float *) calloc16Align (1 + (len + i - 1) / 4, + 4 * sizeof (float)); + if (d_aligned_taps[i] == 0){ + // throw something... + cerr << "@@@ gr_fir_ccf_simd d_aligned_taps[" << i << "] == 0\n"; + } + + for (unsigned j = 0; j < len; j++) + d_aligned_taps[i][j+i] = new_taps[j]; + } +} + +gr_complex +gr_fir_ccf_simd::filter (const gr_complex input[]) +{ + if (ntaps () == 0) + return 0.0; + + if (((intptr_t) input & 0x7) != 0) + throw std::invalid_argument("gr_complex must be 8-byte aligned"); + + // Round input data address down to 16 byte boundary + // NB: depending on the alignment of input[], memory + // before input[] will be accessed. The contents don't matter since + // they'll be multiplied by zero coefficients. I can't conceive of any + // situation where this could cause a segfault since memory protection + // in the x86 machines is done on much larger boundaries. + + const gr_complex *ar = (gr_complex *)((unsigned long) input & ~15); + + // Choose one of 4 sets of pre-shifted coefficients. al is both the + // index into d_aligned_taps[] and the number of 0 words padded onto + // that coefficients array for alignment purposes. + + unsigned al = input - ar; + + // call assembler routine to do the work, passing number of 2x4-float blocks. + + // assert (((unsigned long) ar & 15) == 0); + // assert (((unsigned long) d_aligned_taps[al] & 15) == 0); + + // cerr << "ar: " << ar << " d_aligned_taps[ar]: " << d_aligned_taps[al] + // << " (ntaps() + al - 1)/2 + 1: " << (ntaps() + al -1) / 2 + 1 << endl; + + float result[2]; + + // the trick here is to invert input and taps, and reuse FCC speedup + d_fcomplex_dotprod (d_aligned_taps[al], (float*)ar, (ntaps() + al - 1) / 2 + 1, result); + + // cerr << "result = " << result[0] << " " << result[1] << endl; + + return gr_complex(result[0], result[1]); +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_ccf_simd.h b/gnuradio-core/src/lib/filter/gr_fir_ccf_simd.h new file mode 100644 index 000000000..3c3e7e4f5 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_ccf_simd.h @@ -0,0 +1,66 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_FIR_CCF_SIMD_H +#define INCLUDED_GR_FIR_CCF_SIMD_H + +#include <gr_core_api.h> +#include <gr_fir_ccf_generic.h> + + +/*! + * \brief common base class for SIMD versions of gr_fir_ccf + * \ingroup filter_primitive + * + * This base class handles alignment issues common to SSE and 3DNOW + * subclasses. + */ + +class GR_CORE_API gr_fir_ccf_simd : public gr_fir_ccf_generic +{ +protected: + typedef void (*fcomplex_dotprod_t)(const float *taps, + const float *input, + unsigned n_2_complex_blocks, + float *result); + + /*! + * \p aligned_taps holds 4 copies of the coefficients preshifted + * by 0, 1, 2, or 3 float pairs to meet all possible input data alignments. + * This allows us to always fetch data and taps that are 128-bit aligned. + */ + float *d_aligned_taps[4]; + + fcomplex_dotprod_t d_fcomplex_dotprod; // fast dot product primitive + +public: + + // CREATORS + gr_fir_ccf_simd (); + gr_fir_ccf_simd (const std::vector<float> &taps); + ~gr_fir_ccf_simd (); + + // MANIPULATORS + virtual void set_taps (const std::vector<float> &taps); + virtual gr_complex filter (const gr_complex input[]); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_ccf_x86.cc b/gnuradio-core/src/lib/filter/gr_fir_ccf_x86.cc new file mode 100644 index 000000000..f26d4ecc2 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_ccf_x86.cc @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_fir_ccf_x86.h> +#include <fcomplex_dotprod_x86.h> + +/* + * --- 3DNow! version --- + */ + +gr_fir_ccf_3dnow::gr_fir_ccf_3dnow () + : gr_fir_ccf_simd () +{ + d_fcomplex_dotprod = fcomplex_dotprod_3dnow; +} + +gr_fir_ccf_3dnow::gr_fir_ccf_3dnow (const std::vector<float> &new_taps) + : gr_fir_ccf_simd (new_taps) +{ + d_fcomplex_dotprod = fcomplex_dotprod_3dnow; +} + + +/* + * --- SSE version --- + */ + +gr_fir_ccf_sse::gr_fir_ccf_sse () + : gr_fir_ccf_simd () +{ + d_fcomplex_dotprod = fcomplex_dotprod_sse; +} + +gr_fir_ccf_sse::gr_fir_ccf_sse (const std::vector<float> &new_taps) + : gr_fir_ccf_simd (new_taps) +{ + d_fcomplex_dotprod = fcomplex_dotprod_sse; +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_ccf_x86.h b/gnuradio-core/src/lib/filter/gr_fir_ccf_x86.h new file mode 100644 index 000000000..6b260c3db --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_ccf_x86.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_FIR_CCF_X86_H +#define INCLUDED_GR_FIR_CCF_X86_H + +#include <gr_core_api.h> +#include <gr_fir_ccf_simd.h> + +/*! + * \brief 3DNow! version of gr_fir_ccf + * \ingroup filter_primitive + */ +class GR_CORE_API gr_fir_ccf_3dnow : public gr_fir_ccf_simd +{ +public: + gr_fir_ccf_3dnow (); + gr_fir_ccf_3dnow (const std::vector<float> &taps); +}; + +/*! + * \brief SSE version of gr_fir_ccf + * \ingroup filter_primitive + */ +class GR_CORE_API gr_fir_ccf_sse : public gr_fir_ccf_simd +{ +public: + gr_fir_ccf_sse (); + gr_fir_ccf_sse (const std::vector<float> &taps); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_fcc_simd.cc b/gnuradio-core/src/lib/filter/gr_fir_fcc_simd.cc new file mode 100644 index 000000000..5b75a43fd --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fcc_simd.cc @@ -0,0 +1,139 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_fir_fcc_simd.h> + +#include <assert.h> +#include <malloc16.h> +#include <iostream> + +using std::cerr; +using std::endl; + +gr_fir_fcc_simd::gr_fir_fcc_simd () + : gr_fir_fcc_generic () +{ + // cerr << "@@@ gr_fir_fcc_simd\n"; + + d_fcomplex_dotprod = 0; + + d_aligned_taps[0] = 0; + d_aligned_taps[1] = 0; + d_aligned_taps[2] = 0; + d_aligned_taps[3] = 0; +} + +gr_fir_fcc_simd::gr_fir_fcc_simd (const std::vector<gr_complex> &new_taps) + : gr_fir_fcc_generic (new_taps) +{ + // cerr << "@@@ gr_fir_fcc_simd\n"; + + d_fcomplex_dotprod = 0; + + d_aligned_taps[0] = 0; + d_aligned_taps[1] = 0; + d_aligned_taps[2] = 0; + d_aligned_taps[3] = 0; + set_taps (new_taps); +} + +gr_fir_fcc_simd::~gr_fir_fcc_simd () +{ + free16Align (d_aligned_taps[0]); + free16Align (d_aligned_taps[1]); + free16Align (d_aligned_taps[2]); + free16Align (d_aligned_taps[3]); +} + +void +gr_fir_fcc_simd::set_taps (const std::vector<gr_complex> &inew_taps) +{ + gr_fir_fcc::set_taps (inew_taps); // call superclass + const std::vector<gr_complex> new_taps = gr_reverse(inew_taps); + + unsigned len = new_taps.size (); + + // Make 4 copies of the coefficients, one for each data alignment + // Note use of special 16-byte-aligned version of calloc() + + for (unsigned i = 0; i < 4; i++){ + free16Align (d_aligned_taps[i]); // free old value + + // this works because the bit representation of a IEEE floating point + // +zero is all zeros. If you're using a different representation, + // you'll need to explictly set the result to the appropriate 0.0 value. + + d_aligned_taps[i] = (float *) calloc16Align (1 + (len + i - 1) / 2, + 2 * 4 * sizeof (float)); + if (d_aligned_taps[i] == 0){ + // throw something... + cerr << "@@@ gr_fir_fcc_simd d_aligned_taps[" << i << "] == 0\n"; + } + + for (unsigned j = 0; j < len; j++) { + d_aligned_taps[i][2*(j+i)] = new_taps[j].real(); + d_aligned_taps[i][2*(j+i)+1] = new_taps[j].imag(); + } + } +} + +gr_complex +gr_fir_fcc_simd::filter (const float input[]) +{ + if (ntaps () == 0) + return 0.0; + + + // Round input data address down to 16 byte boundary + // NB: depending on the alignment of input[], memory + // before input[] will be accessed. The contents don't matter since + // they'll be multiplied by zero coefficients. I can't conceive of any + // situation where this could cause a segfault since memory protection + // in the x86 machines is done on much larger boundaries. + + const float *ar = (float *)((unsigned long) input & ~15); + + // Choose one of 4 sets of pre-shifted coefficients. al is both the + // index into d_aligned_taps[] and the number of 0 words padded onto + // that coefficients array for alignment purposes. + + unsigned al = input - ar; + + // call assembler routine to do the work, passing number of 2x4-float blocks. + + // assert (((unsigned long) ar & 15) == 0); + // assert (((unsigned long) d_aligned_taps[al] & 15) == 0); + + // cerr << "ar: " << ar << " d_aligned_taps[ar]: " << d_aligned_taps[al] + // << " (ntaps() + al - 1)/2 + 1: " << (ntaps() + al -1) / 2 + 1 << endl; + + float result[2]; + + d_fcomplex_dotprod (ar, d_aligned_taps[al], (ntaps() + al - 1) / 2 + 1, result); + + // cerr << "result = " << result[0] << " " << result[1] << endl; + + return gr_complex(result[0], result[1]); +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_fcc_simd.h b/gnuradio-core/src/lib/filter/gr_fir_fcc_simd.h new file mode 100644 index 000000000..b7463070b --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fcc_simd.h @@ -0,0 +1,66 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_FIR_FCC_SIMD_H +#define INCLUDED_GR_FIR_FCC_SIMD_H + +#include <gr_core_api.h> +#include <gr_fir_fcc_generic.h> + + +/*! + * \brief common base class for SIMD versions of gr_fir_fcc + * \ingroup filter_primitive + * + * This base class handles alignment issues common to SSE and 3DNOW + * subclasses. + */ + +class GR_CORE_API gr_fir_fcc_simd : public gr_fir_fcc_generic +{ +protected: + typedef void (*fcomplex_dotprod_t)(const float *input, + const float *taps, + unsigned n_2_complex_blocks, + float *result); + + /*! + * \p aligned_taps holds 4 copies of the coefficients preshifted + * by 0, 1, 2, or 3 float pairs to meet all possible input data alignments. + * This allows us to always fetch data and taps that are 128-bit aligned. + */ + float *d_aligned_taps[4]; + + fcomplex_dotprod_t d_fcomplex_dotprod; // fast dot product primitive + +public: + + // CREATORS + gr_fir_fcc_simd (); + gr_fir_fcc_simd (const std::vector<gr_complex> &taps); + ~gr_fir_fcc_simd (); + + // MANIPULATORS + virtual void set_taps (const std::vector<gr_complex> &taps); + virtual gr_complex filter (const float input[]); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_fcc_x86.cc b/gnuradio-core/src/lib/filter/gr_fir_fcc_x86.cc new file mode 100644 index 000000000..d9904133c --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fcc_x86.cc @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_fir_fcc_x86.h> +#include <fcomplex_dotprod_x86.h> + +/* + * --- 3DNow! version --- + */ + +gr_fir_fcc_3dnow::gr_fir_fcc_3dnow () + : gr_fir_fcc_simd () +{ + d_fcomplex_dotprod = fcomplex_dotprod_3dnow; +} + +gr_fir_fcc_3dnow::gr_fir_fcc_3dnow (const std::vector<gr_complex> &new_taps) + : gr_fir_fcc_simd (new_taps) +{ + d_fcomplex_dotprod = fcomplex_dotprod_3dnow; +} + + +/* + * --- SSE version --- + */ + +gr_fir_fcc_sse::gr_fir_fcc_sse () + : gr_fir_fcc_simd () +{ + d_fcomplex_dotprod = fcomplex_dotprod_sse; +} + +gr_fir_fcc_sse::gr_fir_fcc_sse (const std::vector<gr_complex> &new_taps) + : gr_fir_fcc_simd (new_taps) +{ + d_fcomplex_dotprod = fcomplex_dotprod_sse; +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_fcc_x86.h b/gnuradio-core/src/lib/filter/gr_fir_fcc_x86.h new file mode 100644 index 000000000..3fc6c4855 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fcc_x86.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_FIR_FCC_X86_H +#define INCLUDED_GR_FIR_FCC_X86_H + +#include <gr_core_api.h> +#include <gr_fir_fcc_simd.h> + +/*! + * \brief 3DNow! version of gr_fir_fcc + * \ingroup filter_primitive + */ +class GR_CORE_API gr_fir_fcc_3dnow : public gr_fir_fcc_simd +{ +public: + gr_fir_fcc_3dnow (); + gr_fir_fcc_3dnow (const std::vector<gr_complex> &taps); +}; + +/*! + * \brief SSE version of gr_fir_fcc + * \ingroup filter_blk + */ +class GR_CORE_API gr_fir_fcc_sse : public gr_fir_fcc_simd +{ +public: + gr_fir_fcc_sse (); + gr_fir_fcc_sse (const std::vector<gr_complex> &taps); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_fff_altivec.cc b/gnuradio-core/src/lib/filter/gr_fir_fff_altivec.cc new file mode 100644 index 000000000..b81283ce5 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fff_altivec.cc @@ -0,0 +1,84 @@ +/* -*- 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_fir_fff_altivec.h> +#include <stdexcept> +#include <assert.h> +#include <gr_math.h> +#include <gr_altivec.h> +#include <dotprod_fff_altivec.h> +#include <string.h> +#include "posix_memalign.h" + +gr_fir_fff_altivec::gr_fir_fff_altivec() + : gr_fir_fff_generic(), + d_naligned_taps(0), d_aligned_taps(0) +{ +} + +gr_fir_fff_altivec::gr_fir_fff_altivec (const std::vector<float> &new_taps) + : gr_fir_fff_generic(new_taps), + d_naligned_taps(0), d_aligned_taps(0) +{ + set_taps(new_taps); +} + +gr_fir_fff_altivec::~gr_fir_fff_altivec() +{ + if (d_aligned_taps){ + free(d_aligned_taps); + d_aligned_taps = 0; + } +} + +void +gr_fir_fff_altivec::set_taps(const std::vector<float> &inew_taps) +{ + gr_fir_fff_generic::set_taps(inew_taps); // call superclass + d_naligned_taps = gr_p2_round_up(ntaps(), FLOATS_PER_VEC); + + if (d_aligned_taps){ + free(d_aligned_taps); + d_aligned_taps = 0; + } + void *p; + int r = posix_memalign(&p, sizeof(vec_float4), d_naligned_taps * sizeof(d_aligned_taps[0])); + if (r != 0){ + throw std::bad_alloc(); + } + d_aligned_taps = (float *) p; + memcpy(d_aligned_taps, &d_taps[0], ntaps() * sizeof(d_aligned_taps[0])); + for (size_t i = ntaps(); i < d_naligned_taps; i++) + d_aligned_taps[i] = 0.0; +} + + +float +gr_fir_fff_altivec::filter (const float input[]) +{ + if (d_naligned_taps == 0) + return 0.0; + + return dotprod_fff_altivec(input, d_aligned_taps, d_naligned_taps); +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_fff_altivec.h b/gnuradio-core/src/lib/filter/gr_fir_fff_altivec.h new file mode 100644 index 000000000..a3d4a2aae --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fff_altivec.h @@ -0,0 +1,46 @@ +/* -*- 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef INCLUDED_GR_FIR_FFF_ALTIVEC_H +#define INCLUDED_GR_FIR_FFF_ALTIVEC_H + +#include <gr_core_api.h> +#include <gr_fir_fff_generic.h> + +/*! + * \brief altivec version of gr_fir_fff + */ +class GR_CORE_API gr_fir_fff_altivec : public gr_fir_fff_generic +{ +protected: + + size_t d_naligned_taps; // number of taps (multiple of 4) + float *d_aligned_taps; // 16-byte aligned, and zero padded to multiple of 4 + +public: + gr_fir_fff_altivec(); + gr_fir_fff_altivec(const std::vector<float> &taps); + ~gr_fir_fff_altivec(); + + virtual void set_taps (const std::vector<float> &taps); + virtual float filter (const float input[]); +}; + +#endif /* INCLUDED_GR_FIR_FFF_ALTIVEC_H */ diff --git a/gnuradio-core/src/lib/filter/gr_fir_fff_armv7_a.cc b/gnuradio-core/src/lib/filter/gr_fir_fff_armv7_a.cc new file mode 100644 index 000000000..b43725420 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fff_armv7_a.cc @@ -0,0 +1,86 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gr_fir_fff_armv7_a.h> +#include <stdlib.h> +#include <string.h> +#include <stdexcept> +#include <assert.h> +#include <gr_math.h> +#include <dotprod_fff_armv7_a.h> + +#define FLOATS_PER_VEC 8 + +gr_fir_fff_armv7_a::gr_fir_fff_armv7_a() + : gr_fir_fff_generic(), + d_naligned_taps(0), d_aligned_taps(0) +{ +} + +gr_fir_fff_armv7_a::gr_fir_fff_armv7_a (const std::vector<float> &new_taps) + : gr_fir_fff_generic(new_taps), + d_naligned_taps(0), d_aligned_taps(0) +{ + set_taps(new_taps); +} + +gr_fir_fff_armv7_a::~gr_fir_fff_armv7_a() +{ + if (d_aligned_taps){ + free(d_aligned_taps); + d_aligned_taps = 0; + } +} + +void +gr_fir_fff_armv7_a::set_taps(const std::vector<float> &inew_taps) +{ + gr_fir_fff_generic::set_taps(inew_taps); // call superclass + d_naligned_taps = gr_p2_round_up(ntaps(), FLOATS_PER_VEC); + + if (d_aligned_taps){ + free(d_aligned_taps); + d_aligned_taps = 0; + } + void *p; + int r = posix_memalign(&p, sizeof(float), d_naligned_taps * sizeof(d_aligned_taps[0])); + if (r != 0){ + throw std::bad_alloc(); + } + d_aligned_taps = (float *) p; + memcpy(d_aligned_taps, &d_taps[0], ntaps() * sizeof(d_aligned_taps[0])); + for (size_t i = ntaps(); i < d_naligned_taps; i++) + d_aligned_taps[i] = 0.0; +} + + +float +gr_fir_fff_armv7_a::filter (const float input[]) +{ + if (d_naligned_taps == 0) + return 0.0; + + return dotprod_fff_armv7_a(input, d_aligned_taps, d_naligned_taps); +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_fff_armv7_a.h b/gnuradio-core/src/lib/filter/gr_fir_fff_armv7_a.h new file mode 100644 index 000000000..78863d286 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fff_armv7_a.h @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef INCLUDED_GR_FIR_FFF_ARMV7_A_H +#define INCLUDED_GR_FIR_FFF_ARMV7_A_H + +#include <gr_core_api.h> +#include <gr_fir_fff_generic.h> + +/*! + * \brief armv7_a using NEON coprocessor version of gr_fir_fff + */ +class GR_CORE_API gr_fir_fff_armv7_a : public gr_fir_fff_generic +{ +protected: + + size_t d_naligned_taps; // number of taps (multiple of 4) + float *d_aligned_taps; // 16-byte aligned, and zero padded to multiple of 4 + +public: + gr_fir_fff_armv7_a(); + gr_fir_fff_armv7_a(const std::vector<float> &taps); + ~gr_fir_fff_armv7_a(); + + virtual void set_taps (const std::vector<float> &taps); + virtual float filter (const float input[]); +}; + +#endif /* INCLUDED_GR_FIR_FFF_ARMV7_A*_H */ diff --git a/gnuradio-core/src/lib/filter/gr_fir_fff_simd.cc b/gnuradio-core/src/lib/filter/gr_fir_fff_simd.cc new file mode 100644 index 000000000..d6c28ed45 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fff_simd.cc @@ -0,0 +1,134 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_fir_fff_simd.h> + +#include <assert.h> +#include <malloc16.h> +#include <iostream> + +using std::cerr; + +gr_fir_fff_simd::gr_fir_fff_simd () + : gr_fir_fff_generic () +{ + // cerr << "@@@ gr_fir_fff_simd\n"; + + d_float_dotprod = 0; + + d_aligned_taps[0] = 0; + d_aligned_taps[1] = 0; + d_aligned_taps[2] = 0; + d_aligned_taps[3] = 0; +} + +gr_fir_fff_simd::gr_fir_fff_simd (const std::vector<float> &new_taps) + : gr_fir_fff_generic (new_taps) +{ + // cerr << "@@@ gr_fir_fff_simd\n"; + + d_float_dotprod = 0; + + d_aligned_taps[0] = 0; + d_aligned_taps[1] = 0; + d_aligned_taps[2] = 0; + d_aligned_taps[3] = 0; + set_taps (new_taps); +} + +gr_fir_fff_simd::~gr_fir_fff_simd () +{ + free16Align (d_aligned_taps[0]); + free16Align (d_aligned_taps[1]); + free16Align (d_aligned_taps[2]); + free16Align (d_aligned_taps[3]); +} + +void +gr_fir_fff_simd::set_taps (const std::vector<float> &inew_taps) +{ + gr_fir_fff::set_taps (inew_taps); // call superclass + const std::vector<float> new_taps = gr_reverse(inew_taps); + + unsigned len = new_taps.size (); + + // Make 4 copies of the coefficients, one for each data alignment + // Note use of special 16-byte-aligned version of calloc() + + for (unsigned i = 0; i < 4; i++){ + free16Align (d_aligned_taps[i]); // free old value + + // this works because the bit representation of a IEEE floating point + // +zero is all zeros. If you're using a different representation, + // you'll need to explictly set the result to the appropriate 0.0 value. + + d_aligned_taps[i] = (float *) calloc16Align (1 + (len + i - 1) / 4, + 4 * sizeof (float)); + if (d_aligned_taps[i] == 0){ + // throw something... + cerr << "@@@ gr_fir_fff_simd d_aligned_taps[" << i << "] == 0\n"; + } + + for (unsigned j = 0; j < len; j++) + d_aligned_taps[i][j+i] = new_taps[j]; + } +} + +float +gr_fir_fff_simd::filter (const float input[]) +{ + if (ntaps () == 0) + return 0.0; + + + // Round input data address down to 16 byte boundary + // NB: depending on the alignment of input[], memory + // before input[] will be accessed. The contents don't matter since + // they'll be multiplied by zero coefficients. I can't conceive of any + // situation where this could cause a segfault since memory protection + // in the x86 machines is done on much larger boundaries. + + const float *ar = (float *)((unsigned long) input & ~15); + + // Choose one of 4 sets of pre-shifted coefficients. al is both the + // index into d_aligned_taps[] and the number of 0 words padded onto + // that coefficients array for alignment purposes. + + unsigned al = input - ar; + + // call assembler routine to do the work, passing number of 4-float blocks. + + // assert (((unsigned long) ar & 15) == 0); + // assert (((unsigned long) d_aligned_taps[al] & 15) == 0); + + // cerr << "ar: " << ar << " d_aligned_taps[ar]: " << d_aligned_taps[al] + // << " (ntaps() + al - 1)/4 + 1: " << (ntaps() + al -1) / 4 + 1 << endl; + + float r = d_float_dotprod (ar, d_aligned_taps[al], (ntaps() + al - 1) / 4 + 1); + + // cerr << "result = " << r << endl; + + return r; +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_fff_simd.h b/gnuradio-core/src/lib/filter/gr_fir_fff_simd.h new file mode 100644 index 000000000..9d6106266 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fff_simd.h @@ -0,0 +1,64 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_FIR_FFF_SIMD_H +#define INCLUDED_GR_FIR_FFF_SIMD_H + +#include <gr_core_api.h> +#include <gr_fir_fff_generic.h> + +/*! + * \brief common base class for SIMD versions of gr_fir_fff + * \ingroup filter_primitive + * + * This base class handles alignment issues common to SSE and 3DNOW + * subclasses. + */ + +class GR_CORE_API gr_fir_fff_simd : public gr_fir_fff_generic +{ +protected: + typedef float (*float_dotprod_t)(const float *input, + const float *taps, + unsigned n_4_float_blocks); + + /*! + * \p aligned_taps holds 4 copies of the coefficients preshifted + * by 0, 1, 2, or 3 floats to meet all possible input data alignments. + * This allows us to always fetch data and taps that are 128-bit aligned. + */ + float *d_aligned_taps[4]; + + float_dotprod_t d_float_dotprod; // fast dot product primitive + +public: + + // CREATORS + gr_fir_fff_simd (); + gr_fir_fff_simd (const std::vector<float> &taps); + ~gr_fir_fff_simd (); + + // MANIPULATORS + virtual void set_taps (const std::vector<float> &taps); + virtual float filter (const float input[]); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_fff_x86.cc b/gnuradio-core/src/lib/filter/gr_fir_fff_x86.cc new file mode 100644 index 000000000..40ac266be --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fff_x86.cc @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_fir_fff_x86.h> +#include <float_dotprod_x86.h> + +/* + * --- 3DNow! version --- + */ + +gr_fir_fff_3dnow::gr_fir_fff_3dnow () + : gr_fir_fff_simd () +{ + d_float_dotprod = float_dotprod_3dnow; +} + +gr_fir_fff_3dnow::gr_fir_fff_3dnow (const std::vector<float> &new_taps) + : gr_fir_fff_simd (new_taps) +{ + d_float_dotprod = float_dotprod_3dnow; +} + + +/* + * --- SSE version --- + */ + +gr_fir_fff_sse::gr_fir_fff_sse () + : gr_fir_fff_simd () +{ + d_float_dotprod = float_dotprod_sse; +} + +gr_fir_fff_sse::gr_fir_fff_sse (const std::vector<float> &new_taps) + : gr_fir_fff_simd (new_taps) +{ + d_float_dotprod = float_dotprod_sse; +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_fff_x86.h b/gnuradio-core/src/lib/filter/gr_fir_fff_x86.h new file mode 100644 index 000000000..8d451f0c9 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fff_x86.h @@ -0,0 +1,49 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_FIR_FFF_X86_H +#define INCLUDED_GR_FIR_FFF_X86_H + +#include <gr_core_api.h> +#include <gr_fir_fff_simd.h> + +/*! + * \brief 3DNow! version of gr_fir_fff + */ +class GR_CORE_API gr_fir_fff_3dnow : public gr_fir_fff_simd +{ +public: + gr_fir_fff_3dnow (); + gr_fir_fff_3dnow (const std::vector<float> &taps); +}; + +/*! + * \brief SSE version of gr_fir_fff + */ +class GR_CORE_API gr_fir_fff_sse : public gr_fir_fff_simd +{ +public: + gr_fir_fff_sse (); + gr_fir_fff_sse (const std::vector<float> &taps); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.cc.t b/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.cc.t new file mode 100644 index 000000000..39bc75630 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.cc.t @@ -0,0 +1,94 @@ +/* -*- 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: This file is automatically generated by generate_gr_fir_filter_XXX.py + * Any changes made to this file will be overwritten. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <@FIR_TYPE@.h> +#include <gr_fir_util.h> +#include <gr_io_signature.h> + +@SPTR_NAME@ gr_make_@BASE_NAME@ (int decimation, const std::vector<@TAP_TYPE@> &taps) +{ + return gnuradio::get_initial_sptr (new @NAME@ (decimation, taps)); +} + + +@NAME@::@NAME@ (int decimation, const std::vector<@TAP_TYPE@> &taps) + : gr_sync_decimator ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@)), + decimation), + d_updated (false) +{ + d_fir = gr_fir_util::create_@FIR_TYPE@ (taps); + set_history (d_fir->ntaps ()); +} + +@NAME@::~@NAME@ () +{ + delete d_fir; +} + +void +@NAME@::set_taps (const std::vector<@TAP_TYPE@> &taps) +{ + d_new_taps = taps; + d_updated = true; +} + +std::vector<@TAP_TYPE@> +@NAME@::taps () const +{ + return d_new_taps; +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @I_TYPE@ *in = (@I_TYPE@ *) input_items[0]; + @O_TYPE@ *out = (@O_TYPE@ *) output_items[0]; + + if (d_updated) { + d_fir->set_taps (d_new_taps); + set_history (d_fir->ntaps ()); + d_updated = false; + return 0; // history requirements may have changed. + } + + if (decimation() == 1) + d_fir->filterN (out, in, noutput_items); + + else + d_fir->filterNdec (out, in, noutput_items, decimation()); + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.h.t b/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.h.t new file mode 100644 index 000000000..b32e04bd3 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.h.t @@ -0,0 +1,69 @@ +/* -*- 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: This file is automatically generated by generate_gr_fir_filter_XXX.py + * Any changes made to this file will be overwritten. + */ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_core_api.h> +#include <gr_sync_decimator.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; +GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (int decimation, const std::vector<@TAP_TYPE@> &taps); + +class @FIR_TYPE@; + +/*! + * \brief FIR filter with @I_TYPE@ input, @O_TYPE@ output and @TAP_TYPE@ taps + * \ingroup filter_blk + */ +class GR_CORE_API @NAME@ : public gr_sync_decimator +{ + private: + friend GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (int decimation, const std::vector<@TAP_TYPE@> &taps); + + @FIR_TYPE@ *d_fir; + std::vector<@TAP_TYPE@> d_new_taps; + bool d_updated; + + /*! + * Construct a FIR filter with the given taps + */ + @NAME@ (int decimation, const std::vector<@TAP_TYPE@> &taps); + + public: + ~@NAME@ (); + + void set_taps (const std::vector<@TAP_TYPE@> &taps); + std::vector<@TAP_TYPE@> taps () const; + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.i.t b/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.i.t new file mode 100644 index 000000000..d9dc86180 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.i.t @@ -0,0 +1,42 @@ +/* -*- 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: This file is automatically generated by generate_GrFIRfilterXXX.py + * Any changes made to this file will be overwritten. + */ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (int decimation, const std::vector<@TAP_TYPE@> &taps); + +class @NAME@ : public gr_sync_decimator +{ + private: + @NAME@ (int decimation, const std::vector<@TAP_TYPE@> &taps); + + public: + ~@NAME@ (); + + void set_taps (const std::vector<@TAP_TYPE@> &taps); + std::vector<@TAP_TYPE@> taps () const; +}; diff --git a/gnuradio-core/src/lib/filter/gr_fir_fsf_simd.cc b/gnuradio-core/src/lib/filter/gr_fir_fsf_simd.cc new file mode 100644 index 000000000..a49503e6a --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fsf_simd.cc @@ -0,0 +1,133 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_fir_fsf_simd.h> + +#include <assert.h> +#include <malloc16.h> +#include <iostream> + +using std::cerr; + +gr_fir_fsf_simd::gr_fir_fsf_simd () + : gr_fir_fsf_generic () +{ + // cerr << "@@@ gr_fir_fsf_simd\n"; + + d_float_dotprod = 0; + + d_aligned_taps[0] = 0; + d_aligned_taps[1] = 0; + d_aligned_taps[2] = 0; + d_aligned_taps[3] = 0; +} + +gr_fir_fsf_simd::gr_fir_fsf_simd (const std::vector<float> &new_taps) + : gr_fir_fsf_generic (new_taps) +{ + // cerr << "@@@ gr_fir_fsf_simd\n"; + + d_float_dotprod = 0; + + d_aligned_taps[0] = 0; + d_aligned_taps[1] = 0; + d_aligned_taps[2] = 0; + d_aligned_taps[3] = 0; + set_taps (new_taps); +} + +gr_fir_fsf_simd::~gr_fir_fsf_simd () +{ + free16Align (d_aligned_taps[0]); + free16Align (d_aligned_taps[1]); + free16Align (d_aligned_taps[2]); + free16Align (d_aligned_taps[3]); +} + +void +gr_fir_fsf_simd::set_taps (const std::vector<float> &inew_taps) +{ + gr_fir_fsf::set_taps (inew_taps); // call superclass + const std::vector<float> new_taps = gr_reverse(inew_taps); + unsigned len = new_taps.size (); + + // Make 4 copies of the coefficients, one for each data alignment + // Note use of special 16-byte-aligned version of calloc() + + for (unsigned i = 0; i < 4; i++){ + free16Align (d_aligned_taps[i]); // free old value + + // this works because the bit representation of a IEEE floating point + // +zero is all zeros. If you're using a different representation, + // you'll need to explictly set the result to the appropriate 0.0 value. + + d_aligned_taps[i] = (float *) calloc16Align (1 + (len + i - 1) / 4, + 4 * sizeof (float)); + if (d_aligned_taps[i] == 0){ + // throw something... + cerr << "@@@ gr_fir_fsf_simd d_aligned_taps[" << i << "] == 0\n"; + } + + for (unsigned j = 0; j < len; j++) + d_aligned_taps[i][j+i] = new_taps[j]; + } +} + +short +gr_fir_fsf_simd::filter (const float input[]) +{ + if (ntaps () == 0) + return 0; + + + // Round input data address down to 16 byte boundary + // NB: depending on the alignment of input[], memory + // before input[] will be accessed. The contents don't matter since + // they'll be multiplied by zero coefficients. I can't conceive of any + // situation where this could cause a segfault since memory protection + // in the x86 machines is done on much larger boundaries. + + const float *ar = (float *)((unsigned long) input & ~15); + + // Choose one of 4 sets of pre-shifted coefficients. al is both the + // index into d_aligned_taps[] and the number of 0 words padded onto + // that coefficients array for alignment purposes. + + unsigned al = input - ar; + + // call assembler routine to do the work, passing number of 4-float blocks. + + // assert (((unsigned long) ar & 15) == 0); + // assert (((unsigned long) d_aligned_taps[al] & 15) == 0); + + // cerr << "ar: " << ar << " d_aligned_taps[ar]: " << d_aligned_taps[al] + // << " (ntaps() + al - 1)/4 + 1: " << (ntaps() + al -1) / 4 + 1 << endl; + + float r = d_float_dotprod (ar, d_aligned_taps[al], (ntaps() + al - 1) / 4 + 1); + + // cerr << "result = " << r << endl; + + return (short) r; // FIXME? may want to saturate here +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_fsf_simd.h b/gnuradio-core/src/lib/filter/gr_fir_fsf_simd.h new file mode 100644 index 000000000..d63e9dd17 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fsf_simd.h @@ -0,0 +1,64 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 _GR_FIR_FSF_SIMD_H_ +#define _GR_FIR_FSF_SIMD_H_ + +#include <gr_core_api.h> +#include <gr_fir_fsf_generic.h> + +/*! + * \brief common base class for SIMD versions of gr_fir_fsf + * \ingroup filter_primitive + * + * This base class handles alignment issues common to SSE and 3DNOW + * subclasses. + */ + +class GR_CORE_API gr_fir_fsf_simd : public gr_fir_fsf_generic +{ +protected: + typedef float (*float_dotprod_t)(const float *input, + const float *taps, + unsigned n_4_float_blocks); + + /*! + * \p aligned_taps holds 4 copies of the coefficients preshifted + * by 0, 1, 2, or 3 floats to meet all possible input data alignments. + * This allows us to always fetch data and taps that are 128-bit aligned. + */ + float *d_aligned_taps[4]; + + float_dotprod_t d_float_dotprod; // fast dot product primitive + +public: + + // CREATORS + gr_fir_fsf_simd (); + gr_fir_fsf_simd (const std::vector<float> &taps); + ~gr_fir_fsf_simd (); + + // MANIPULATORS + virtual void set_taps (const std::vector<float> &taps); + virtual short filter (const float input[]); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_fsf_x86.cc b/gnuradio-core/src/lib/filter/gr_fir_fsf_x86.cc new file mode 100644 index 000000000..40ba17d3a --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fsf_x86.cc @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_fir_fsf_x86.h> +#include <float_dotprod_x86.h> + +/* + * --- 3DNow! version --- + */ + +gr_fir_fsf_3dnow::gr_fir_fsf_3dnow () + : gr_fir_fsf_simd () +{ + d_float_dotprod = float_dotprod_3dnow; +} + +gr_fir_fsf_3dnow::gr_fir_fsf_3dnow (const std::vector<float> &new_taps) + : gr_fir_fsf_simd (new_taps) +{ + d_float_dotprod = float_dotprod_3dnow; +} + + +/* + * --- SSE version --- + */ + +gr_fir_fsf_sse::gr_fir_fsf_sse () + : gr_fir_fsf_simd () +{ + d_float_dotprod = float_dotprod_sse; +} + +gr_fir_fsf_sse::gr_fir_fsf_sse (const std::vector<float> &new_taps) + : gr_fir_fsf_simd (new_taps) +{ + d_float_dotprod = float_dotprod_sse; +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_fsf_x86.h b/gnuradio-core/src/lib/filter/gr_fir_fsf_x86.h new file mode 100644 index 000000000..df664d5e2 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fsf_x86.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_FIR_FSF_X86_H +#define INCLUDED_GR_FIR_FSF_X86_H + +#include <gr_core_api.h> +#include <gr_fir_fsf_simd.h> + +/*! + * \brief 3DNow! version of gr_fir_fsf + * \ingroup filter_primitive + */ +class GR_CORE_API gr_fir_fsf_3dnow : public gr_fir_fsf_simd +{ +public: + gr_fir_fsf_3dnow (); + gr_fir_fsf_3dnow (const std::vector<float> &taps); +}; + +/*! + * \brief SSE version of gr_fir_fsf + * \ingroup filter_primitive + */ +class GR_CORE_API gr_fir_fsf_sse : public gr_fir_fsf_simd +{ +public: + gr_fir_fsf_sse (); + gr_fir_fsf_sse (const std::vector<float> &taps); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_scc_simd.cc b/gnuradio-core/src/lib/filter/gr_fir_scc_simd.cc new file mode 100644 index 000000000..0b2dd7e61 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_scc_simd.cc @@ -0,0 +1,140 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_fir_scc_simd.h> + +#include <assert.h> +#include <malloc16.h> +#include <iostream> + +using std::cerr; +using std::endl; + +gr_fir_scc_simd::gr_fir_scc_simd () + : gr_fir_scc_generic () +{ + // cerr << "@@@ gr_fir_scc_simd\n"; + + d_complex_dotprod = 0; + + d_aligned_taps[0] = 0; + d_aligned_taps[1] = 0; + d_aligned_taps[2] = 0; + d_aligned_taps[3] = 0; +} + +gr_fir_scc_simd::gr_fir_scc_simd (const std::vector<gr_complex> &new_taps) + : gr_fir_scc_generic (new_taps) +{ + // cerr << "@@@ gr_fir_scc_simd\n"; + + d_complex_dotprod = 0; + + d_aligned_taps[0] = 0; + d_aligned_taps[1] = 0; + d_aligned_taps[2] = 0; + d_aligned_taps[3] = 0; + set_taps (new_taps); +} + +gr_fir_scc_simd::~gr_fir_scc_simd () +{ + free16Align (d_aligned_taps[0]); + free16Align (d_aligned_taps[1]); + free16Align (d_aligned_taps[2]); + free16Align (d_aligned_taps[3]); +} + +void +gr_fir_scc_simd::set_taps (const std::vector<gr_complex> &inew_taps) +{ + gr_fir_scc::set_taps (inew_taps); // call superclass + + const std::vector<gr_complex> new_taps = gr_reverse(inew_taps); + + unsigned len = new_taps.size (); + + // Make 4 copies of the coefficients, one for each data alignment + // Note use of special 16-byte-aligned version of calloc() + + for (unsigned i = 0; i < 4; i++){ + free16Align (d_aligned_taps[i]); // free old value + + // this works because the bit representation of a IEEE floating point + // +zero is all zeros. If you're using a different representation, + // you'll need to explictly set the result to the appropriate 0.0 value. + + d_aligned_taps[i] = (float *) calloc16Align (1 + (len + i - 1) / 2, + 2 * 4 * sizeof (float)); + if (d_aligned_taps[i] == 0){ + // throw something... + cerr << "@@@ gr_fir_scc_simd d_aligned_taps[" << i << "] == 0\n"; + } + + for (unsigned j = 0; j < len; j++) { + d_aligned_taps[i][2*(j+i)] = new_taps[j].real(); + d_aligned_taps[i][2*(j+i)+1] = new_taps[j].imag(); + } + } +} + +gr_complex +gr_fir_scc_simd::filter (const short input[]) +{ + if (ntaps () == 0) + return 0.0; + + + // Round input data address down to 8 byte boundary + // NB: depending on the alignment of input[], memory + // before input[] will be accessed. The contents don't matter since + // they'll be multiplied by zero coefficients. I can't conceive of any + // situation where this could cause a segfault since memory protection + // in the x86 machines is done on much larger boundaries. + + const short *ar = (short *)((unsigned long) input & ~7); + + // Choose one of 4 sets of pre-shifted coefficients. al is both the + // index into d_aligned_taps[] and the number of 0 words padded onto + // that coefficients array for alignment purposes. + + unsigned al = input - ar; + + // call assembler routine to do the work, passing number of 2x4-float blocks. + + // assert (((unsigned long) ar & 7) == 0); + // assert (((unsigned long) d_aligned_taps[al] & 15) == 0); + + // cerr << "ar: " << ar << " d_aligned_taps[ar]: " << d_aligned_taps[al] + // << " (ntaps() + al - 1)/2 + 1: " << (ntaps() + al -1) / 2 + 1 << endl; + + float result[2]; + + d_complex_dotprod (ar, d_aligned_taps[al], (ntaps() + al - 1) / 2 + 1, result); + + // cerr << "result = " << result[0] << " " << result[1] << endl; + + return gr_complex(result[0], result[1]); +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_scc_simd.h b/gnuradio-core/src/lib/filter/gr_fir_scc_simd.h new file mode 100644 index 000000000..72c15f93b --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_scc_simd.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_FIR_SCC_SIMD_H +#define INCLUDED_GR_FIR_SCC_SIMD_H + +#include <gr_core_api.h> +#include <gr_fir_scc_generic.h> + + +/*! + * \brief common base class for SIMD versions of gr_fir_scc + * \ingroup filter_primitive + * + * This base class handles alignment issues common to SSE and 3DNOW + * subclasses. + */ +class GR_CORE_API gr_fir_scc_simd : public gr_fir_scc_generic +{ +protected: + typedef void (*complex_dotprod_t)(const short *input, + const float *taps, + unsigned n_2_complex_blocks, + float *result); + + /*! + * \p aligned_taps holds 4 copies of the coefficients preshifted + * by 0, 1, 2, or 3 float pairs to meet all possible input data alignments. + * This allows us to always fetch data and taps that are 128-bit aligned. + */ + float *d_aligned_taps[4]; + + complex_dotprod_t d_complex_dotprod; // fast dot product primitive + +public: + + // CREATORS + gr_fir_scc_simd (); + gr_fir_scc_simd (const std::vector<gr_complex> &taps); + ~gr_fir_scc_simd (); + + // MANIPULATORS + virtual void set_taps (const std::vector<gr_complex> &taps); + virtual gr_complex filter (const short input[]); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_scc_x86.cc b/gnuradio-core/src/lib/filter/gr_fir_scc_x86.cc new file mode 100644 index 000000000..ab0668c63 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_scc_x86.cc @@ -0,0 +1,77 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_fir_scc_x86.h> +#include <complex_dotprod_x86.h> + +/* + * --- 3DNow! version --- + */ + +gr_fir_scc_3dnow::gr_fir_scc_3dnow () + : gr_fir_scc_simd () +{ + d_complex_dotprod = complex_dotprod_3dnow; +} + +gr_fir_scc_3dnow::gr_fir_scc_3dnow (const std::vector<gr_complex> &new_taps) + : gr_fir_scc_simd (new_taps) +{ + d_complex_dotprod = complex_dotprod_3dnow; +} + + +/* + * --- 3DNow! Ext version --- + */ + +gr_fir_scc_3dnowext::gr_fir_scc_3dnowext () + : gr_fir_scc_simd () +{ + d_complex_dotprod = complex_dotprod_3dnowext; +} + +gr_fir_scc_3dnowext::gr_fir_scc_3dnowext (const std::vector<gr_complex> &new_taps) + : gr_fir_scc_simd (new_taps) +{ + d_complex_dotprod = complex_dotprod_3dnowext; +} + + +/* + * --- SSE version --- + */ + +gr_fir_scc_sse::gr_fir_scc_sse () + : gr_fir_scc_simd () +{ + d_complex_dotprod = complex_dotprod_sse; +} + +gr_fir_scc_sse::gr_fir_scc_sse (const std::vector<gr_complex> &new_taps) + : gr_fir_scc_simd (new_taps) +{ + d_complex_dotprod = complex_dotprod_sse; +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_scc_x86.h b/gnuradio-core/src/lib/filter/gr_fir_scc_x86.h new file mode 100644 index 000000000..85a63251b --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_scc_x86.h @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_FIR_SCC_X86_H +#define INCLUDED_GR_FIR_SCC_X86_H + +#include <gr_core_api.h> +#include <gr_fir_scc_simd.h> + +/*! + * \brief 3DNow! version of gr_fir_scc + */ +class GR_CORE_API gr_fir_scc_3dnow : public gr_fir_scc_simd +{ +public: + gr_fir_scc_3dnow (); + gr_fir_scc_3dnow (const std::vector<gr_complex> &taps); +}; + +/*! + * \brief 3DNow! Ext version of gr_fir_scc + */ +class GR_CORE_API gr_fir_scc_3dnowext : public gr_fir_scc_simd +{ +public: + gr_fir_scc_3dnowext (); + gr_fir_scc_3dnowext (const std::vector<gr_complex> &taps); +}; + +/*! + * \brief SSE version of gr_fir_scc + */ +class GR_CORE_API gr_fir_scc_sse : public gr_fir_scc_simd +{ +public: + gr_fir_scc_sse (); + gr_fir_scc_sse (const std::vector<gr_complex> &taps); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_sysconfig_armv7_a.cc b/gnuradio-core/src/lib/filter/gr_fir_sysconfig_armv7_a.cc new file mode 100644 index 000000000..70adbc092 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_sysconfig_armv7_a.cc @@ -0,0 +1,337 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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. + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gr_fir_sysconfig_armv7_a.h> +#include <gr_cpu.h> + +#include <gr_fir_ccf.h> +#include <gr_fir_ccf_generic.h> +#include <gr_fir_ccf_armv7_a.h> +#include <gr_fir_fcc.h> +#include <gr_fir_fcc_generic.h> +#include <gr_fir_fff.h> +#include <gr_fir_fff_generic.h> +#include <gr_fir_fff_armv7_a.h> +#include <gr_fir_fsf.h> +#include <gr_fir_fsf_generic.h> +#include <gr_fir_ccc.h> +#include <gr_fir_ccc_generic.h> +#include <gr_fir_scc.h> +#include <gr_fir_scc_generic.h> + +#include <iostream> +using std::cerr; + +///\todo Remove commented out code for altivec and replace with NEON versions. + +/* + * ---------------------------------------------------------------- + * static functions that serve as constructors... + * ---------------------------------------------------------------- + */ + +static gr_fir_ccf * +make_gr_fir_ccf_armv7_a (const std::vector<float> &taps) +{ + return new gr_fir_ccf_armv7_a(taps); +} + +#if 0 +static gr_fir_fcc * +make_gr_fir_fcc_altivec(const std::vector<gr_complex> &taps) +{ + return new gr_fir_fcc_altivec(taps); +} + +static gr_fir_ccc * +make_gr_fir_ccc_altivec (const std::vector<gr_complex> &taps) +{ + return new gr_fir_ccc_altivec (taps); +} +#endif + +static gr_fir_fff * +make_gr_fir_fff_armv7_a (const std::vector<float> &taps) +{ + return new gr_fir_fff_armv7_a (taps); +} + +#if 0 +static gr_fir_fsf * +make_gr_fir_fsf_altivec (const std::vector<float> &taps) +{ + return new gr_fir_fsf_altivec (taps); +} + +static gr_fir_scc * +make_gr_fir_scc_altivec(const std::vector<gr_complex> &taps) +{ + return new gr_fir_scc_altivec(taps); +} +#endif + +/* + * ---------------------------------------------------------------- + * Return instances of the fastest arm versions of these classes. + * + * check CPUID, if has armv7-a, return armv7-a version, + * else return generic version. This will break + * when someone makes an armv7-a without a NEON + * coprocessor. + * ---------------------------------------------------------------- + */ + +gr_fir_ccf * +gr_fir_sysconfig_armv7_a::create_gr_fir_ccf (const std::vector<float> &taps) +{ + static bool first = true; + + if (gr_cpu::has_armv7_a ()){ + if (first){ + cerr << ">>> gr_fir_ccf: using armv7_a\n"; + first = false; + } + return make_gr_fir_ccf_armv7_a (taps); + } + + if (0 && first){ + cerr << ">>> gr_fir_ccf: handing off to parent class\n"; + first = false; + } + return gr_fir_sysconfig_generic::create_gr_fir_ccf (taps); +} + +gr_fir_fcc * +gr_fir_sysconfig_armv7_a::create_gr_fir_fcc (const std::vector<gr_complex> &taps) +{ + static bool first = true; + +#if 0 + if (gr_cpu::has_altivec ()){ + if (first){ + cerr << ">>> gr_fir_fcc: using altivec\n"; + first = false; + } + return make_gr_fir_fcc_altivec (taps); + } +#endif + + if (0 && first){ + cerr << ">>> gr_fir_fcc: handing off to parent class\n"; + first = false; + } + return gr_fir_sysconfig_generic::create_gr_fir_fcc (taps); +} + +gr_fir_ccc * +gr_fir_sysconfig_armv7_a::create_gr_fir_ccc (const std::vector<gr_complex> &taps) +{ + static bool first = true; + +#if 0 + if (gr_cpu::has_altivec ()){ + if (first){ + cerr << ">>> gr_fir_ccc: using altivec\n"; + first = false; + } + return make_gr_fir_ccc_altivec (taps); + } +#endif + + if (0 && first){ + cerr << ">>> gr_fir_ccc: handing off to parent class\n"; + first = false; + } + return gr_fir_sysconfig_generic::create_gr_fir_ccc (taps); +} + +gr_fir_fff * +gr_fir_sysconfig_armv7_a::create_gr_fir_fff (const std::vector<float> &taps) +{ + static bool first = true; + + if (gr_cpu::has_armv7_a ()){ + if (first){ + cerr << ">>> gr_fir_fff: using armv7_a\n"; + first = false; + } + return make_gr_fir_fff_armv7_a (taps); + } + + if (0 && first){ + cerr << ">>> gr_fir_fff: handing off to parent class\n"; + first = false; + } + return gr_fir_sysconfig_generic::create_gr_fir_fff (taps); +} + +gr_fir_fsf * +gr_fir_sysconfig_armv7_a::create_gr_fir_fsf (const std::vector<float> &taps) +{ + static bool first = true; + +#if 0 + if (gr_cpu::has_altivec ()){ + if (first){ + cerr << ">>> gr_fir_fsf: using altivec\n"; + first = false; + } + return make_gr_fir_fsf_altivec (taps); + } +#endif + + if (0 && first){ + cerr << ">>> gr_fir_fsf: handing off to parent class\n"; + first = false; + } + return gr_fir_sysconfig_generic::create_gr_fir_fsf (taps); +} + + +gr_fir_scc * +gr_fir_sysconfig_armv7_a::create_gr_fir_scc (const std::vector<gr_complex> &taps) +{ + static bool first = true; + +#if 0 + if (gr_cpu::has_altivec ()){ + if (first){ + cerr << ">>> gr_fir_scc: using altivec\n"; + first = false; + } + return make_gr_fir_scc_altivec (taps); + } +#endif + + if (0 && first){ + cerr << ">>> gr_fir_scc: handing off to parent class\n"; + first = false; + } + return gr_fir_sysconfig_generic::create_gr_fir_scc (taps); +} + +/* + * ---------------------------------------------------------------- + * Return info about available implementations + * ---------------------------------------------------------------- + */ + +void +gr_fir_sysconfig_armv7_a::get_gr_fir_ccf_info (std::vector<gr_fir_ccf_info> *info) +{ + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_ccf_info (info); + + // add our stuff... + gr_fir_ccf_info t; + if (gr_cpu::has_armv7_a ()){ + t.name = "armv7_a"; + t.create = make_gr_fir_ccf_armv7_a; + (*info).push_back (t); + } +} + +void +gr_fir_sysconfig_armv7_a::get_gr_fir_fcc_info (std::vector<gr_fir_fcc_info> *info) +{ + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_fcc_info (info); + +#if 0 + // add our stuff... + gr_fir_fcc_info t; + if (gr_cpu::has_altivec ()){ + t.name = "altivec"; + t.create = make_gr_fir_fcc_altivec; + (*info).push_back (t); + } +#endif +} + +void +gr_fir_sysconfig_armv7_a::get_gr_fir_ccc_info (std::vector<gr_fir_ccc_info> *info) +{ + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_ccc_info (info); + +#if 0 + // add our stuff... + gr_fir_ccc_info t; + if (gr_cpu::has_altivec ()){ + t.name = "altivec"; + t.create = make_gr_fir_ccc_altivec; + (*info).push_back (t); + } +#endif +} + +void +gr_fir_sysconfig_armv7_a::get_gr_fir_fff_info (std::vector<gr_fir_fff_info> *info) +{ + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_fff_info (info); + + // add our stuff... + gr_fir_fff_info t; + if (gr_cpu::has_armv7_a ()){ + t.name = "armv7_a"; + t.create = make_gr_fir_fff_armv7_a; + (*info).push_back (t); + } +} + +void +gr_fir_sysconfig_armv7_a::get_gr_fir_fsf_info (std::vector<gr_fir_fsf_info> *info) +{ + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_fsf_info (info); + +#if 0 + // add our stuff... + gr_fir_fsf_info t; + if (gr_cpu::has_altivec ()){ + t.name = "altivec"; + t.create = make_gr_fir_fsf_altivec; + (*info).push_back (t); + } +#endif +} + +void +gr_fir_sysconfig_armv7_a::get_gr_fir_scc_info (std::vector<gr_fir_scc_info> *info) +{ + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_scc_info (info); + +#if 0 + // add our stuff... + gr_fir_scc_info t; + if (gr_cpu::has_altivec ()){ + t.name = "altivec"; + t.create = make_gr_fir_scc_altivec; + (*info).push_back (t); + } +#endif +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_sysconfig_armv7_a.h b/gnuradio-core/src/lib/filter/gr_fir_sysconfig_armv7_a.h new file mode 100644 index 000000000..7295475f6 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_sysconfig_armv7_a.h @@ -0,0 +1,47 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2008,2009 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_FIR_SYSCONFIG_ARMV7_A_H +#define INCLUDED_GR_FIR_SYSCONFIG_ARMV7_A_H + +#include <gr_core_api.h> +#include <gr_fir_sysconfig_generic.h> + +class GR_CORE_API gr_fir_sysconfig_armv7_a : public gr_fir_sysconfig_generic { +public: + virtual gr_fir_ccf *create_gr_fir_ccf (const std::vector<float> &taps); + virtual gr_fir_fcc *create_gr_fir_fcc (const std::vector<gr_complex> &taps); + virtual gr_fir_fff *create_gr_fir_fff (const std::vector<float> &taps); + virtual gr_fir_fsf *create_gr_fir_fsf (const std::vector<float> &taps); + virtual gr_fir_scc *create_gr_fir_scc (const std::vector<gr_complex> &taps); + virtual gr_fir_ccc *create_gr_fir_ccc (const std::vector<gr_complex> &taps); +//virtual gr_fir_sss *create_gr_fir_sss (const std::vector<short> &taps); + + virtual void get_gr_fir_ccf_info (std::vector<gr_fir_ccf_info> *info); + virtual void get_gr_fir_fcc_info (std::vector<gr_fir_fcc_info> *info); + virtual void get_gr_fir_fff_info (std::vector<gr_fir_fff_info> *info); + virtual void get_gr_fir_fsf_info (std::vector<gr_fir_fsf_info> *info); + virtual void get_gr_fir_scc_info (std::vector<gr_fir_scc_info> *info); + virtual void get_gr_fir_ccc_info (std::vector<gr_fir_ccc_info> *info); +//virtual void get_gr_fir_sss_info (std::vector<gr_fir_sss_info> *info); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_sysconfig_powerpc.cc b/gnuradio-core/src/lib/filter/gr_fir_sysconfig_powerpc.cc new file mode 100644 index 000000000..f706bd5bf --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_sysconfig_powerpc.cc @@ -0,0 +1,340 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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. + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_fir_sysconfig_powerpc.h> +#include <gr_cpu.h> + +#include <gr_fir_ccf.h> +#include <gr_fir_ccf_generic.h> +//#include <gr_fir_ccf_altivec.h> +#include <gr_fir_fcc.h> +#include <gr_fir_fcc_generic.h> +//#include <gr_fir_fcc_altivec.h> +#include <gr_fir_fff.h> +#include <gr_fir_fff_generic.h> +#include <gr_fir_fff_altivec.h> +#include <gr_fir_fsf.h> +#include <gr_fir_fsf_generic.h> +//#include <gr_fir_fsf_powerpc.h> +#include <gr_fir_ccc.h> +#include <gr_fir_ccc_generic.h> +//#include <gr_fir_ccc_altivec.h> +#include <gr_fir_scc.h> +#include <gr_fir_scc_generic.h> +//#include <gr_fir_scc_altivec.h> + +#include <iostream> +using std::cerr; + +/* + * ---------------------------------------------------------------- + * static functions that serve as constructors... + * ---------------------------------------------------------------- + */ + +#if 0 +static gr_fir_ccf * +make_gr_fir_ccf_altivec(const std::vector<float> &taps) +{ + return new gr_fir_ccf_altivec(taps); +} + +static gr_fir_fcc * +make_gr_fir_fcc_altivec(const std::vector<gr_complex> &taps) +{ + return new gr_fir_fcc_altivec(taps); +} + +static gr_fir_ccc * +make_gr_fir_ccc_altivec (const std::vector<gr_complex> &taps) +{ + return new gr_fir_ccc_altivec (taps); +} +#endif + +static gr_fir_fff * +make_gr_fir_fff_altivec (const std::vector<float> &taps) +{ + return new gr_fir_fff_altivec (taps); +} + +#if 0 +static gr_fir_fsf * +make_gr_fir_fsf_altivec (const std::vector<float> &taps) +{ + return new gr_fir_fsf_altivec (taps); +} + +static gr_fir_scc * +make_gr_fir_scc_altivec(const std::vector<gr_complex> &taps) +{ + return new gr_fir_scc_altivec(taps); +} +#endif + +/* + * ---------------------------------------------------------------- + * Return instances of the fastest powerpc versions of these classes. + * + * check CPUID, if has altivec, return altivec version, + * else return generic version. + * ---------------------------------------------------------------- + */ + +gr_fir_ccf * +gr_fir_sysconfig_powerpc::create_gr_fir_ccf (const std::vector<float> &taps) +{ + static bool first = true; + +#if 0 + if (gr_cpu::has_altivec ()){ + if (first){ + cerr << ">>> gr_fir_ccf: using altivec\n"; + first = false; + } + return make_gr_fir_ccf_altivec (taps); + } +#endif + + if (0 && first){ + cerr << ">>> gr_fir_ccf: handing off to parent class\n"; + first = false; + } + return gr_fir_sysconfig_generic::create_gr_fir_ccf (taps); +} + +gr_fir_fcc * +gr_fir_sysconfig_powerpc::create_gr_fir_fcc (const std::vector<gr_complex> &taps) +{ + static bool first = true; + +#if 0 + if (gr_cpu::has_altivec ()){ + if (first){ + cerr << ">>> gr_fir_fcc: using altivec\n"; + first = false; + } + return make_gr_fir_fcc_altivec (taps); + } +#endif + + if (0 && first){ + cerr << ">>> gr_fir_fcc: handing off to parent class\n"; + first = false; + } + return gr_fir_sysconfig_generic::create_gr_fir_fcc (taps); +} + +gr_fir_ccc * +gr_fir_sysconfig_powerpc::create_gr_fir_ccc (const std::vector<gr_complex> &taps) +{ + static bool first = true; + +#if 0 + if (gr_cpu::has_altivec ()){ + if (first){ + cerr << ">>> gr_fir_ccc: using altivec\n"; + first = false; + } + return make_gr_fir_ccc_altivec (taps); + } +#endif + + if (0 && first){ + cerr << ">>> gr_fir_ccc: handing off to parent class\n"; + first = false; + } + return gr_fir_sysconfig_generic::create_gr_fir_ccc (taps); +} + +gr_fir_fff * +gr_fir_sysconfig_powerpc::create_gr_fir_fff (const std::vector<float> &taps) +{ + static bool first = true; + + if (gr_cpu::has_altivec ()){ + if (first){ + cerr << ">>> gr_fir_fff: using altivec\n"; + first = false; + } + return make_gr_fir_fff_altivec (taps); + } + + if (0 && first){ + cerr << ">>> gr_fir_fff: handing off to parent class\n"; + first = false; + } + return gr_fir_sysconfig_generic::create_gr_fir_fff (taps); +} + +gr_fir_fsf * +gr_fir_sysconfig_powerpc::create_gr_fir_fsf (const std::vector<float> &taps) +{ + static bool first = true; + +#if 0 + if (gr_cpu::has_altivec ()){ + if (first){ + cerr << ">>> gr_fir_fsf: using altivec\n"; + first = false; + } + return make_gr_fir_fsf_altivec (taps); + } +#endif + + if (0 && first){ + cerr << ">>> gr_fir_fsf: handing off to parent class\n"; + first = false; + } + return gr_fir_sysconfig_generic::create_gr_fir_fsf (taps); +} + + +gr_fir_scc * +gr_fir_sysconfig_powerpc::create_gr_fir_scc (const std::vector<gr_complex> &taps) +{ + static bool first = true; + +#if 0 + if (gr_cpu::has_altivec ()){ + if (first){ + cerr << ">>> gr_fir_scc: using altivec\n"; + first = false; + } + return make_gr_fir_scc_altivec (taps); + } +#endif + + if (0 && first){ + cerr << ">>> gr_fir_scc: handing off to parent class\n"; + first = false; + } + return gr_fir_sysconfig_generic::create_gr_fir_scc (taps); +} + +/* + * ---------------------------------------------------------------- + * Return info about available implementations + * ---------------------------------------------------------------- + */ + +void +gr_fir_sysconfig_powerpc::get_gr_fir_ccf_info (std::vector<gr_fir_ccf_info> *info) +{ + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_ccf_info (info); + +#if 0 + // add our stuff... + gr_fir_ccf_info t; + if (gr_cpu::has_altivec ()){ + t.name = "altivec"; + t.create = make_gr_fir_ccf_altivec; + (*info).push_back (t); + } +#endif +} + +void +gr_fir_sysconfig_powerpc::get_gr_fir_fcc_info (std::vector<gr_fir_fcc_info> *info) +{ + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_fcc_info (info); + +#if 0 + // add our stuff... + gr_fir_fcc_info t; + if (gr_cpu::has_altivec ()){ + t.name = "altivec"; + t.create = make_gr_fir_fcc_altivec; + (*info).push_back (t); + } +#endif +} + +void +gr_fir_sysconfig_powerpc::get_gr_fir_ccc_info (std::vector<gr_fir_ccc_info> *info) +{ + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_ccc_info (info); + +#if 0 + // add our stuff... + gr_fir_ccc_info t; + if (gr_cpu::has_altivec ()){ + t.name = "altivec"; + t.create = make_gr_fir_ccc_altivec; + (*info).push_back (t); + } +#endif +} + +void +gr_fir_sysconfig_powerpc::get_gr_fir_fff_info (std::vector<gr_fir_fff_info> *info) +{ + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_fff_info (info); + + // add our stuff... + gr_fir_fff_info t; + if (gr_cpu::has_altivec ()){ + t.name = "altivec"; + t.create = make_gr_fir_fff_altivec; + (*info).push_back (t); + } +} + +void +gr_fir_sysconfig_powerpc::get_gr_fir_fsf_info (std::vector<gr_fir_fsf_info> *info) +{ + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_fsf_info (info); + +#if 0 + // add our stuff... + gr_fir_fsf_info t; + if (gr_cpu::has_altivec ()){ + t.name = "altivec"; + t.create = make_gr_fir_fsf_altivec; + (*info).push_back (t); + } +#endif +} + +void +gr_fir_sysconfig_powerpc::get_gr_fir_scc_info (std::vector<gr_fir_scc_info> *info) +{ + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_scc_info (info); + +#if 0 + // add our stuff... + gr_fir_scc_info t; + if (gr_cpu::has_altivec ()){ + t.name = "altivec"; + t.create = make_gr_fir_scc_altivec; + (*info).push_back (t); + } +#endif +} diff --git a/gnuradio-core/src/lib/filter/gr_fir_sysconfig_powerpc.h b/gnuradio-core/src/lib/filter/gr_fir_sysconfig_powerpc.h new file mode 100644 index 000000000..09a7a0ba0 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_sysconfig_powerpc.h @@ -0,0 +1,47 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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_FIR_SYSCONFIG_POWERPC_H +#define INCLUDED_GR_FIR_SYSCONFIG_POWERPC_H + +#include <gr_core_api.h> +#include <gr_fir_sysconfig_generic.h> + +class GR_CORE_API gr_fir_sysconfig_powerpc : public gr_fir_sysconfig_generic { +public: + virtual gr_fir_ccf *create_gr_fir_ccf (const std::vector<float> &taps); + virtual gr_fir_fcc *create_gr_fir_fcc (const std::vector<gr_complex> &taps); + virtual gr_fir_fff *create_gr_fir_fff (const std::vector<float> &taps); + virtual gr_fir_fsf *create_gr_fir_fsf (const std::vector<float> &taps); + virtual gr_fir_scc *create_gr_fir_scc (const std::vector<gr_complex> &taps); + virtual gr_fir_ccc *create_gr_fir_ccc (const std::vector<gr_complex> &taps); +//virtual gr_fir_sss *create_gr_fir_sss (const std::vector<short> &taps); + + virtual void get_gr_fir_ccf_info (std::vector<gr_fir_ccf_info> *info); + virtual void get_gr_fir_fcc_info (std::vector<gr_fir_fcc_info> *info); + virtual void get_gr_fir_fff_info (std::vector<gr_fir_fff_info> *info); + virtual void get_gr_fir_fsf_info (std::vector<gr_fir_fsf_info> *info); + virtual void get_gr_fir_scc_info (std::vector<gr_fir_scc_info> *info); + virtual void get_gr_fir_ccc_info (std::vector<gr_fir_ccc_info> *info); +//virtual void get_gr_fir_sss_info (std::vector<gr_fir_sss_info> *info); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_sysconfig_x86.cc b/gnuradio-core/src/lib/filter/gr_fir_sysconfig_x86.cc new file mode 100644 index 000000000..97b810699 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_sysconfig_x86.cc @@ -0,0 +1,553 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_fir_sysconfig_x86.h> +#include <gr_cpu.h> + +#include <gr_fir_ccf.h> +#include <gr_fir_ccf_generic.h> +#include <gr_fir_ccf_x86.h> +#include <gr_fir_fcc.h> +#include <gr_fir_fcc_generic.h> +#include <gr_fir_fcc_x86.h> +#include <gr_fir_fff.h> +#include <gr_fir_fff_generic.h> +#include <gr_fir_fff_x86.h> +#include <gr_fir_fsf.h> +#include <gr_fir_fsf_generic.h> +#include <gr_fir_fsf_x86.h> +#include <gr_fir_ccc.h> +#include <gr_fir_ccc_generic.h> +#include <gr_fir_ccc_x86.h> +#include <gr_fir_scc.h> +#include <gr_fir_scc_generic.h> +#include <gr_fir_scc_x86.h> +// #include <gr_fir_sss.h> +// #include <gr_fir_sss_generic.h> +// #include <gr_fir_sss_mmx.h> +// #include <gr_fir_sss_sse2.h> + +#include <iostream> +using std::cerr; + +/* + * ---------------------------------------------------------------- + * static functions that serve as constructors... + * Is it possible to take the address of a normal constructor? + * ---------------------------------------------------------------- + */ + +static gr_fir_ccf * +make_gr_fir_ccf_3dnow(const std::vector<float> &taps) +{ + return new gr_fir_ccf_3dnow(taps); +} + +static gr_fir_ccf * +make_gr_fir_ccf_sse(const std::vector<float> &taps) +{ + return new gr_fir_ccf_sse(taps); +} + +static gr_fir_fcc * +make_gr_fir_fcc_3dnow(const std::vector<gr_complex> &taps) +{ + return new gr_fir_fcc_3dnow(taps); +} + +static gr_fir_fcc * +make_gr_fir_fcc_sse(const std::vector<gr_complex> &taps) +{ + return new gr_fir_fcc_sse(taps); +} + +static gr_fir_ccc * +make_gr_fir_ccc_3dnow (const std::vector<gr_complex> &taps) +{ + return new gr_fir_ccc_3dnow (taps); +} + +static gr_fir_ccc * +make_gr_fir_ccc_3dnowext (const std::vector<gr_complex> &taps) +{ + return new gr_fir_ccc_3dnowext (taps); +} + +static gr_fir_ccc * +make_gr_fir_ccc_sse (const std::vector<gr_complex> &taps) +{ + return new gr_fir_ccc_sse (taps); +} + +static gr_fir_fff * +make_gr_fir_fff_3dnow (const std::vector<float> &taps) +{ + return new gr_fir_fff_3dnow (taps); +} + +static gr_fir_fff * +make_gr_fir_fff_sse (const std::vector<float> &taps) +{ + return new gr_fir_fff_sse (taps); +} + +static gr_fir_fsf * +make_gr_fir_fsf_3dnow (const std::vector<float> &taps) +{ + return new gr_fir_fsf_3dnow (taps); +} + +static gr_fir_fsf * +make_gr_fir_fsf_sse (const std::vector<float> &taps) +{ + return new gr_fir_fsf_sse (taps); +} + +#if 0 +static gr_fir_sss * +make_gr_fir_sss_mmx (const std::vector<short> &taps) +{ + return new gr_fir_sss_mmx (taps); +} + +static gr_fir_sss * +make_gr_fir_sss_sse2 (const std::vector<short> &taps) +{ + return new gr_fir_sss_sse2 (taps); +} +#endif + +static gr_fir_scc * +make_gr_fir_scc_3dnow(const std::vector<gr_complex> &taps) +{ + return new gr_fir_scc_3dnow(taps); +} + +static gr_fir_scc * +make_gr_fir_scc_3dnowext(const std::vector<gr_complex> &taps) +{ + return new gr_fir_scc_3dnowext(taps); +} + +static gr_fir_scc * +make_gr_fir_scc_sse(const std::vector<gr_complex> &taps) +{ + return new gr_fir_scc_sse(taps); +} + +/* + * ---------------------------------------------------------------- + * Return instances of the fastest x86 versions of these classes. + * + * check CPUID, if has 3DNowExt, return 3DNow!Ext version, + * else if 3DNow, return 3DNow! version, + * else if SSE2, return SSE2 version, + * else if SSE, return SSE version, + * else if MMX, return MMX version, + * else return generic version. + * + * FIXME: benchmark, store result, use stored result to + * select the fastest version. + * ---------------------------------------------------------------- + */ + +gr_fir_ccf * +gr_fir_sysconfig_x86::create_gr_fir_ccf (const std::vector<float> &taps) +{ + static bool first = true; + + if (gr_cpu::has_3dnow ()){ + if (first){ + cerr << ">>> gr_fir_ccf: using 3DNow!\n"; + first = false; + } + return make_gr_fir_ccf_3dnow (taps); + } + + if (gr_cpu::has_sse ()){ + if (first){ + cerr << ">>> gr_fir_ccf: using SSE\n"; + first = false; + } + return make_gr_fir_ccf_sse (taps); + } + + if (first){ + cerr << ">>> gr_fir_ccf: handing off to parent class\n"; + first = false; + } + return gr_fir_sysconfig_generic::create_gr_fir_ccf (taps); +} + +gr_fir_fcc * +gr_fir_sysconfig_x86::create_gr_fir_fcc (const std::vector<gr_complex> &taps) +{ + static bool first = true; + + if (gr_cpu::has_3dnow ()){ + if (first){ + cerr << ">>> gr_fir_fcc: using 3DNow!\n"; + first = false; + } + return make_gr_fir_fcc_3dnow (taps); + } + + if (gr_cpu::has_sse ()){ + if (first){ + cerr << ">>> gr_fir_fcc: using SSE\n"; + first = false; + } + return make_gr_fir_fcc_sse (taps); + } + + if (first){ + cerr << ">>> gr_fir_fcc: handing off to parent class\n"; + first = false; + } + return gr_fir_sysconfig_generic::create_gr_fir_fcc (taps); +} + +gr_fir_ccc * +gr_fir_sysconfig_x86::create_gr_fir_ccc (const std::vector<gr_complex> &taps) +{ + static bool first = true; + + if (gr_cpu::has_3dnowext ()){ + if (first) { + cerr << ">>> gr_fir_ccc: using 3DNow!Ext\n"; + first = false; + } + return make_gr_fir_ccc_3dnowext (taps); + } + + if (gr_cpu::has_3dnow ()){ + if (first) { + cerr << ">>> gr_fir_ccc: using 3DNow!\n"; + first = false; + } + return make_gr_fir_ccc_3dnow (taps); + } + + if (gr_cpu::has_sse ()){ + if (first){ + cerr << ">>> gr_fir_ccc: using SSE\n"; + first = false; + } + return make_gr_fir_ccc_sse (taps); + } + + if (first){ + cerr << ">>> gr_fir_ccc: handing off to parent class\n"; + first = false; + } + return gr_fir_sysconfig_generic::create_gr_fir_ccc (taps); +} + +gr_fir_fff * +gr_fir_sysconfig_x86::create_gr_fir_fff (const std::vector<float> &taps) +{ + static bool first = true; + + if (gr_cpu::has_3dnow ()){ + if (first) { + cerr << ">>> gr_fir_fff: using 3DNow!\n"; + first = false; + } + return make_gr_fir_fff_3dnow (taps); + } + + if (gr_cpu::has_sse ()){ + if (first){ + cerr << ">>> gr_fir_fff: using SSE\n"; + first = false; + } + return make_gr_fir_fff_sse (taps); + } + + if (first){ + cerr << ">>> gr_fir_fff: handing off to parent class\n"; + first = false; + } + return gr_fir_sysconfig_generic::create_gr_fir_fff (taps); +} + +gr_fir_fsf * +gr_fir_sysconfig_x86::create_gr_fir_fsf (const std::vector<float> &taps) +{ + static bool first = true; + + if (gr_cpu::has_3dnow ()){ + if (first) { + cerr << ">>> gr_fir_fsf: using 3DNow!\n"; + first = false; + } + return make_gr_fir_fsf_3dnow (taps); + } + + if (gr_cpu::has_sse ()){ + if (first){ + cerr << ">>> gr_fir_fsf: using SSE\n"; + first = false; + } + return make_gr_fir_fsf_sse (taps); + } + + if (first){ + cerr << ">>> gr_fir_fsf: handing off to parent class\n"; + first = false; + } + return gr_fir_sysconfig_generic::create_gr_fir_fsf (taps); +} + +#if 0 +gr_fir_sss * +gr_fir_sysconfig_x86::create_gr_fir_sss (const std::vector<short> &taps) +{ + // FIXME -- probably want to figure out best answer for Athlon and code + // add code to select it here... + + if (gr_cpu::has_sse2 ()){ + cerr << ">>> gr_fir_sss: using SSE2\n"; + return make_gr_fir_sss_sse2 (taps); + } + + if (gr_cpu::has_mmx ()){ + cerr << ">>> gr_fir_sss: using MMX\n"; + return make_gr_fir_sss_mmx (taps); + } + + cerr << ">>> gr_fir_sss: handing off to parent class\n"; + return gr_fir_sysconfig_generic::create_gr_fir_sss (taps); +} +#endif + +gr_fir_scc * +gr_fir_sysconfig_x86::create_gr_fir_scc (const std::vector<gr_complex> &taps) +{ + static bool first = true; + + if (gr_cpu::has_3dnowext ()){ + if (first){ + cerr << ">>> gr_fir_scc: using 3DNow!Ext\n"; + first = false; + } + return make_gr_fir_scc_3dnowext (taps); + } + + if (gr_cpu::has_3dnow ()){ + if (first){ + cerr << ">>> gr_fir_scc: using 3DNow!\n"; + first = false; + } + return make_gr_fir_scc_3dnow (taps); + } + + if (gr_cpu::has_sse ()){ + if (first){ + cerr << ">>> gr_fir_scc: using SSE\n"; + first = false; + } + return make_gr_fir_scc_sse (taps); + } + + if (first){ + cerr << ">>> gr_fir_scc: handing off to parent class\n"; + first = false; + } + return gr_fir_sysconfig_generic::create_gr_fir_scc (taps); +} + +/* + * ---------------------------------------------------------------- + * Return info about available implementations + * ---------------------------------------------------------------- + */ + +void +gr_fir_sysconfig_x86::get_gr_fir_ccf_info (std::vector<gr_fir_ccf_info> *info) +{ + gr_fir_ccf_info t; + + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_ccf_info (info); + + // add our stuff... + if (gr_cpu::has_3dnow ()){ + t.name = "3DNow!"; + t.create = make_gr_fir_ccf_3dnow; + (*info).push_back (t); + } + + if (gr_cpu::has_sse ()){ + t.name = "SSE"; + t.create = make_gr_fir_ccf_sse; + (*info).push_back (t); + } +} + +void +gr_fir_sysconfig_x86::get_gr_fir_fcc_info (std::vector<gr_fir_fcc_info> *info) +{ + gr_fir_fcc_info t; + + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_fcc_info (info); + + // add our stuff... + if (gr_cpu::has_3dnow ()){ + t.name = "3DNow!"; + t.create = make_gr_fir_fcc_3dnow; + (*info).push_back (t); + } + + if (gr_cpu::has_sse ()){ + t.name = "SSE"; + t.create = make_gr_fir_fcc_sse; + (*info).push_back (t); + } +} + +void +gr_fir_sysconfig_x86::get_gr_fir_ccc_info (std::vector<gr_fir_ccc_info> *info) +{ + gr_fir_ccc_info t; + + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_ccc_info (info); + + // add our stuff... + if (gr_cpu::has_3dnowext ()){ + t.name = "3DNow!Ext"; + t.create = make_gr_fir_ccc_3dnowext; + (*info).push_back (t); + } + + if (gr_cpu::has_3dnow ()){ + t.name = "3DNow!"; + t.create = make_gr_fir_ccc_3dnow; + (*info).push_back (t); + } + + if (gr_cpu::has_sse ()){ + t.name = "SSE"; + t.create = make_gr_fir_ccc_sse; + (*info).push_back (t); + } +} + +void +gr_fir_sysconfig_x86::get_gr_fir_fff_info (std::vector<gr_fir_fff_info> *info) +{ + gr_fir_fff_info t; + + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_fff_info (info); + + // add our stuff... + if (gr_cpu::has_3dnow ()){ + t.name = "3DNow!"; + t.create = make_gr_fir_fff_3dnow; + (*info).push_back (t); + } + + if (gr_cpu::has_sse ()){ + t.name = "SSE"; + t.create = make_gr_fir_fff_sse; + (*info).push_back (t); + } +} + +void +gr_fir_sysconfig_x86::get_gr_fir_fsf_info (std::vector<gr_fir_fsf_info> *info) +{ + gr_fir_fsf_info t; + + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_fsf_info (info); + + // add our stuff... + if (gr_cpu::has_3dnow ()){ + t.name = "3DNow!"; + t.create = make_gr_fir_fsf_3dnow; + (*info).push_back (t); + } + + if (gr_cpu::has_sse ()){ + t.name = "SSE"; + t.create = make_gr_fir_fsf_sse; + (*info).push_back (t); + } +} + +void +gr_fir_sysconfig_x86::get_gr_fir_scc_info (std::vector<gr_fir_scc_info> *info) +{ + gr_fir_scc_info t; + + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_scc_info (info); + + // add our stuff... + if (gr_cpu::has_3dnowext ()){ + t.name = "3DNow!Ext"; + t.create = make_gr_fir_scc_3dnowext; + (*info).push_back (t); + } + + if (gr_cpu::has_3dnow ()){ + t.name = "3DNow!"; + t.create = make_gr_fir_scc_3dnow; + (*info).push_back (t); + } + + if (gr_cpu::has_sse ()){ + t.name = "SSE"; + t.create = make_gr_fir_scc_sse; + (*info).push_back (t); + } +} + +#if 0 +void +gr_fir_sysconfig_x86::get_gr_fir_sss_info (std::vector<gr_fir_sss_info> *info) +{ + gr_fir_sss_info t; + + // invoke parent.. + gr_fir_sysconfig_generic::get_gr_fir_sss_info (info); + + // add our stuff... + if (gr_cpu::has_mmx ()){ + t.name = "MMX"; + t.create = make_gr_fir_sss_mmx; + (*info).push_back (t); + } + + if (gr_cpu::has_sse2 ()){ + t.name = "SSE2"; + t.create = make_gr_fir_sss_sse2; + (*info).push_back (t); + } +} +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fir_sysconfig_x86.h b/gnuradio-core/src/lib/filter/gr_fir_sysconfig_x86.h new file mode 100644 index 000000000..ebb399c8b --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_sysconfig_x86.h @@ -0,0 +1,47 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_FIR_SYSCONFIG_X86_H +#define INCLUDED_GR_FIR_SYSCONFIG_X86_H + +#include <gr_core_api.h> +#include <gr_fir_sysconfig_generic.h> + +class GR_CORE_API gr_fir_sysconfig_x86 : public gr_fir_sysconfig_generic { +public: + virtual gr_fir_ccf *create_gr_fir_ccf (const std::vector<float> &taps); + virtual gr_fir_fcc *create_gr_fir_fcc (const std::vector<gr_complex> &taps); + virtual gr_fir_fff *create_gr_fir_fff (const std::vector<float> &taps); + virtual gr_fir_fsf *create_gr_fir_fsf (const std::vector<float> &taps); + virtual gr_fir_scc *create_gr_fir_scc (const std::vector<gr_complex> &taps); + virtual gr_fir_ccc *create_gr_fir_ccc (const std::vector<gr_complex> &taps); +//virtual gr_fir_sss *create_gr_fir_sss (const std::vector<short> &taps); + + virtual void get_gr_fir_ccf_info (std::vector<gr_fir_ccf_info> *info); + virtual void get_gr_fir_fcc_info (std::vector<gr_fir_fcc_info> *info); + virtual void get_gr_fir_fff_info (std::vector<gr_fir_fff_info> *info); + virtual void get_gr_fir_fsf_info (std::vector<gr_fir_fsf_info> *info); + virtual void get_gr_fir_scc_info (std::vector<gr_fir_scc_info> *info); + virtual void get_gr_fir_ccc_info (std::vector<gr_fir_ccc_info> *info); +//virtual void get_gr_fir_sss_info (std::vector<gr_fir_sss_info> *info); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fractional_interpolator_cc.cc b/gnuradio-core/src/lib/filter/gr_fractional_interpolator_cc.cc new file mode 100644 index 000000000..500958e3d --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fractional_interpolator_cc.cc @@ -0,0 +1,93 @@ +/* -*- c++ -*- */ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_io_signature.h> +#include <gr_fractional_interpolator_cc.h> +#include <gri_mmse_fir_interpolator_cc.h> +#include <stdexcept> + +// Public constructor +gr_fractional_interpolator_cc_sptr gr_make_fractional_interpolator_cc(float phase_shift, float interp_ratio) +{ + return gnuradio::get_initial_sptr(new gr_fractional_interpolator_cc(phase_shift, interp_ratio)); +} + +gr_fractional_interpolator_cc::gr_fractional_interpolator_cc(float phase_shift, float interp_ratio) + : gr_block ("fractional_interpolator_cc", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (gr_complex))), + d_mu (phase_shift), d_mu_inc (interp_ratio), d_interp(new gri_mmse_fir_interpolator_cc()) +{ + if (interp_ratio <= 0) + throw std::out_of_range ("interpolation ratio must be > 0"); + if (phase_shift < 0 || phase_shift > 1) + throw std::out_of_range ("phase shift ratio must be > 0 and < 1"); + + set_relative_rate (1.0 / interp_ratio); +} + +gr_fractional_interpolator_cc::~gr_fractional_interpolator_cc() +{ + delete d_interp; +} + +void +gr_fractional_interpolator_cc::forecast(int noutput_items, gr_vector_int &ninput_items_required) +{ + unsigned ninputs = ninput_items_required.size(); + for (unsigned i=0; i < ninputs; i++) + + ninput_items_required[i] = + (int) ceil((noutput_items * d_mu_inc) + d_interp->ntaps()); +} + +int +gr_fractional_interpolator_cc::general_work(int noutput_items, + gr_vector_int &ninput_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]; + + int ii = 0; // input index + int oo = 0; // output index + + while (oo < noutput_items) { + + out[oo++] = d_interp->interpolate(&in[ii], d_mu); + + double s = d_mu + d_mu_inc; + double f = floor (s); + int incr = (int) f; + d_mu = s - f; + ii += incr; + } + + consume_each (ii); + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_fractional_interpolator_cc.h b/gnuradio-core/src/lib/filter/gr_fractional_interpolator_cc.h new file mode 100644 index 000000000..29c67895a --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fractional_interpolator_cc.h @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_FRACTIONAL_INTERPOLATOR_CC_H +#define INCLUDED_GR_FRACTIONAL_INTERPOLATOR_CC_H + +#include <gr_core_api.h> +#include <gr_block.h> + +class gri_mmse_fir_interpolator_cc; + +class gr_fractional_interpolator_cc; +typedef boost::shared_ptr<gr_fractional_interpolator_cc> gr_fractional_interpolator_cc_sptr; + +// public constructor +GR_CORE_API gr_fractional_interpolator_cc_sptr gr_make_fractional_interpolator_cc (float phase_shift, float interp_ratio); + +/*! + * \brief Interpolating mmse filter with gr_complex input, gr_complex output + * \ingroup filter_blk + */ +class GR_CORE_API gr_fractional_interpolator_cc : public gr_block +{ +public: + ~gr_fractional_interpolator_cc (); + 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); + + float mu() const { return d_mu;} + float interp_ratio() const { return d_mu_inc;} + void set_mu (float mu) { d_mu = mu; } + void set_interp_ratio (float interp_ratio) { d_mu_inc = interp_ratio; } + +protected: + gr_fractional_interpolator_cc (float phase_shift, float interp_ratio); + +private: + float d_mu; + float d_mu_inc; + gri_mmse_fir_interpolator_cc *d_interp; + + friend GR_CORE_API gr_fractional_interpolator_cc_sptr + gr_make_fractional_interpolator_cc (float phase_shift, float interp_ratio); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fractional_interpolator_cc.i b/gnuradio-core/src/lib/filter/gr_fractional_interpolator_cc.i new file mode 100644 index 000000000..d7341176a --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fractional_interpolator_cc.i @@ -0,0 +1,37 @@ +/* -*- 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,fractional_interpolator_cc); + +gr_fractional_interpolator_cc_sptr gr_make_fractional_interpolator_cc (float phase_shift, float interp_ratio); + +class gr_fractional_interpolator_cc : public gr_block +{ +private: + gr_fractional_interpolator_cc (float phase_shift, float interp_ratio); + +public: + float mu() const; + float interp_ratio() const; + void set_mu (float mu); + void set_interp_ratio (float interp_ratio); +}; diff --git a/gnuradio-core/src/lib/filter/gr_fractional_interpolator_ff.cc b/gnuradio-core/src/lib/filter/gr_fractional_interpolator_ff.cc new file mode 100644 index 000000000..9cbe31635 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fractional_interpolator_ff.cc @@ -0,0 +1,93 @@ +/* -*- c++ -*- */ +/* + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_io_signature.h> +#include <gr_fractional_interpolator_ff.h> +#include <gri_mmse_fir_interpolator.h> +#include <stdexcept> + +// Public constructor +gr_fractional_interpolator_ff_sptr gr_make_fractional_interpolator_ff(float phase_shift, float interp_ratio) +{ + return gnuradio::get_initial_sptr(new gr_fractional_interpolator_ff(phase_shift, interp_ratio)); +} + +gr_fractional_interpolator_ff::gr_fractional_interpolator_ff(float phase_shift, float interp_ratio) + : gr_block ("fractional_interpolator_ff", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (float))), + d_mu (phase_shift), d_mu_inc (interp_ratio), d_interp(new gri_mmse_fir_interpolator()) +{ + if (interp_ratio <= 0) + throw std::out_of_range ("interpolation ratio must be > 0"); + if (phase_shift < 0 || phase_shift > 1) + throw std::out_of_range ("phase shift ratio must be > 0 and < 1"); + + set_relative_rate (1.0 / interp_ratio); +} + +gr_fractional_interpolator_ff::~gr_fractional_interpolator_ff() +{ + delete d_interp; +} + +void +gr_fractional_interpolator_ff::forecast(int noutput_items, gr_vector_int &ninput_items_required) +{ + unsigned ninputs = ninput_items_required.size(); + for (unsigned i=0; i < ninputs; i++) + + ninput_items_required[i] = + (int) ceil((noutput_items * d_mu_inc) + d_interp->ntaps()); +} + +int +gr_fractional_interpolator_ff::general_work(int noutput_items, + gr_vector_int &ninput_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]; + + int ii = 0; // input index + int oo = 0; // output index + + while (oo < noutput_items) { + + out[oo++] = d_interp->interpolate(&in[ii], d_mu); + + double s = d_mu + d_mu_inc; + double f = floor (s); + int incr = (int) f; + d_mu = s - f; + ii += incr; + } + + consume_each (ii); + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_fractional_interpolator_ff.h b/gnuradio-core/src/lib/filter/gr_fractional_interpolator_ff.h new file mode 100644 index 000000000..7e000a6d1 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fractional_interpolator_ff.h @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_FRACTIONAL_INTERPOLATOR_FF_H +#define INCLUDED_GR_FRACTIONAL_INTERPOLATOR_FF_H + +#include <gr_core_api.h> +#include <gr_block.h> + +class gri_mmse_fir_interpolator; + +class gr_fractional_interpolator_ff; +typedef boost::shared_ptr<gr_fractional_interpolator_ff> gr_fractional_interpolator_ff_sptr; + +// public constructor +GR_CORE_API gr_fractional_interpolator_ff_sptr gr_make_fractional_interpolator_ff (float phase_shift, float interp_ratio); + +/*! + * \brief Interpolating mmse filter with float input, float output + * \ingroup filter_blk + */ +class GR_CORE_API gr_fractional_interpolator_ff : public gr_block +{ +public: + ~gr_fractional_interpolator_ff (); + 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); + + float mu() const { return d_mu;} + float interp_ratio() const { return d_mu_inc;} + void set_mu (float mu) { d_mu = mu; } + void set_interp_ratio (float interp_ratio) { d_mu_inc = interp_ratio; } + +protected: + gr_fractional_interpolator_ff (float phase_shift, float interp_ratio); + +private: + float d_mu; + float d_mu_inc; + gri_mmse_fir_interpolator *d_interp; + + friend GR_CORE_API gr_fractional_interpolator_ff_sptr + gr_make_fractional_interpolator_ff (float phase_shift, float interp_ratio); +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_fractional_interpolator_ff.i b/gnuradio-core/src/lib/filter/gr_fractional_interpolator_ff.i new file mode 100644 index 000000000..4ec7c85cf --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fractional_interpolator_ff.i @@ -0,0 +1,37 @@ +/* -*- 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,fractional_interpolator_ff); + +gr_fractional_interpolator_ff_sptr gr_make_fractional_interpolator_ff (float phase_shift, float interp_ratio); + +class gr_fractional_interpolator_ff : public gr_block +{ +private: + gr_fractional_interpolator_ff (float phase_shift, float interp_ratio); + +public: + float mu() const; + float interp_ratio() const; + void set_mu (float mu); + void set_interp_ratio (float interp_ratio); +}; diff --git a/gnuradio-core/src/lib/filter/gr_freq_xlating_fir_filter_XXX.cc.t b/gnuradio-core/src/lib/filter/gr_freq_xlating_fir_filter_XXX.cc.t new file mode 100644 index 000000000..3d65f872e --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_freq_xlating_fir_filter_XXX.cc.t @@ -0,0 +1,123 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,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: This file is automatically generated by + * generate_gr_freq_xlating_fir_filter_XXX.py + * Any changes made to this file will be overwritten. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <@FIR_TYPE@.h> +#include <gr_fir_util.h> +#include <gr_io_signature.h> + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (int decimation, const std::vector<@TAP_TYPE@> &taps, + double center_freq, double sampling_freq) +{ + return gnuradio::get_initial_sptr (new @NAME@ (decimation, taps, center_freq, sampling_freq)); +} + + +@NAME@::@NAME@ ( + + int decimation, + const std::vector<@TAP_TYPE@> &taps, + double center_freq, + double sampling_freq) + + : gr_sync_decimator ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@)), + decimation), + d_proto_taps (taps), d_center_freq (center_freq), d_sampling_freq (sampling_freq), + d_updated (false) +{ + std::vector<gr_complex> dummy_taps; + d_composite_fir = gr_fir_util::create_@FIR_TYPE@ (dummy_taps); + + set_history (d_proto_taps.size ()); + build_composite_fir (); +} + +@NAME@::~@NAME@ () +{ + delete d_composite_fir; +} + +void +@NAME@::build_composite_fir () +{ + std::vector<gr_complex> ctaps (d_proto_taps.size ()); + + float fwT0 = 2 * M_PI * d_center_freq / d_sampling_freq; + for (unsigned int i = 0; i < d_proto_taps.size (); i++) + ctaps[i] = d_proto_taps[i] * exp (gr_complex (0, i * fwT0)); + + d_composite_fir->set_taps (gr_reverse(ctaps)); + d_r.set_phase_incr (exp (gr_complex (0, fwT0 * decimation ()))); +} + +void +@NAME@::set_center_freq (double center_freq) +{ + d_center_freq = center_freq; + d_updated = true; +} + +void +@NAME@::set_taps (const std::vector<@TAP_TYPE@> &taps) +{ + d_proto_taps = taps; + d_updated = true; +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @I_TYPE@ *in = (@I_TYPE@ *) input_items[0]; + @O_TYPE@ *out = (@O_TYPE@ *) output_items[0]; + + // rebuild composite FIR if the center freq has changed + + if (d_updated){ + set_history (d_proto_taps.size ()); + build_composite_fir (); + d_updated = false; + return 0; // history requirements may have changed. + } + + unsigned j = 0; + for (int i = 0; i < noutput_items; i++){ + out[i] = d_r.rotate (d_composite_fir->filter (&in[j])); + j += decimation (); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_freq_xlating_fir_filter_XXX.h.t b/gnuradio-core/src/lib/filter/gr_freq_xlating_fir_filter_XXX.h.t new file mode 100644 index 000000000..97d20e04f --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_freq_xlating_fir_filter_XXX.h.t @@ -0,0 +1,101 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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: This file is automatically generated by + * generate_gr_freq_xlating_fir_filter_XXX.py Any changes made to this file + * will be overwritten. + */ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_core_api.h> +#include <gr_sync_decimator.h> +#include <gr_rotator.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +/*! + * Construct a FIR filter with the given taps and a composite frequency + * translation that shifts center_freq down to zero Hz. The frequency + * translation logically comes before the filtering operation. + */ +GR_CORE_API @SPTR_NAME@ +gr_make_@BASE_NAME@ (int decimation, const std::vector<@TAP_TYPE@> &taps, + double center_freq, double sampling_freq); + + +class @FIR_TYPE@; + +/*! + * \brief FIR filter combined with frequency translation with @I_TYPE@ input, @O_TYPE@ output and @TAP_TYPE@ taps + * \ingroup filter_blk + * + * This class efficiently combines a frequency translation + * (typically "down conversion") with a FIR filter (typically low-pass) + * and decimation. It is ideally suited for a "channel selection filter" + * and can be efficiently used to select and decimate a narrow band signal + * out of wide bandwidth input. + * + * Uses a single input array to produce a single output array. + * Additional inputs and/or outputs are ignored. + */ +class GR_CORE_API @NAME@ : public gr_sync_decimator +{ + public: + virtual ~@NAME@ (); + + void set_center_freq (double center_freq); + void set_taps (const std::vector<@TAP_TYPE@> &taps); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + private: + friend GR_CORE_API @SPTR_NAME@ + gr_make_@BASE_NAME@ (int decimation, const std::vector<@TAP_TYPE@> &taps, + double center_freq, double sampling_freq); + + protected: + std::vector<@TAP_TYPE@> d_proto_taps; + @FIR_TYPE@ *d_composite_fir; + gr_rotator d_r; + double d_center_freq; + double d_sampling_freq; + bool d_updated; + + virtual void build_composite_fir (); + + /*! + * Construct a FIR filter with the given taps and a composite frequency + * translation that shifts center_freq down to zero Hz. The frequency + * translation logically comes before the filtering operation. + */ + @NAME@ (int decimation, + const std::vector<@TAP_TYPE@> &taps, + double center_freq, double sampling_freq); +}; + +#endif /* _@NAME@_H_ */ diff --git a/gnuradio-core/src/lib/filter/gr_freq_xlating_fir_filter_XXX.i.t b/gnuradio-core/src/lib/filter/gr_freq_xlating_fir_filter_XXX.i.t new file mode 100644 index 000000000..ac6c8c9e1 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_freq_xlating_fir_filter_XXX.i.t @@ -0,0 +1,47 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,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: This file is automatically generated by + * generate_gr_freq_xlating_fir_filter_XXX.py + * Any changes made to this file will be overwritten. + */ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (int decimation, const std::vector<@TAP_TYPE@> &taps, + double center_freq, double sampling_freq); + + +class @NAME@ : public gr_sync_decimator +{ + protected: + @NAME@ (int decimation, const std::vector<@TAP_TYPE@> &taps, + double center_freq, double sampling_freq); + + public: + ~@NAME@ (); + + void set_center_freq (double center_freq); + void set_taps (const std::vector<@TAP_TYPE@> &taps); +}; diff --git a/gnuradio-core/src/lib/filter/gr_goertzel_fc.cc b/gnuradio-core/src/lib/filter/gr_goertzel_fc.cc new file mode 100644 index 000000000..07bed8157 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_goertzel_fc.cc @@ -0,0 +1,76 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_goertzel_fc.h> +#include <gr_io_signature.h> + +// public constructor +gr_goertzel_fc_sptr +gr_make_goertzel_fc(int rate, int len, float freq) +{ + return gnuradio::get_initial_sptr(new gr_goertzel_fc(rate, len, freq)); +} + +gr_goertzel_fc::gr_goertzel_fc(int rate, int len, float freq) + : gr_sync_decimator("goertzel_fc", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (gr_complex)), + len), + d_goertzel(rate, len, freq) +{ + d_len = len; + d_rate = rate; + d_freq = freq; +} + +int gr_goertzel_fc::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float *in = (float *)input_items[0]; + gr_complex *out = (gr_complex *)output_items[0]; + + for (int i = 0; i < noutput_items; i++) { + *out++ = d_goertzel.batch(in); + in += d_len; + } + + return noutput_items; +} + +void +gr_goertzel_fc::set_freq(float freq) +{ + d_freq = freq; + d_goertzel.gri_setparms(d_rate, d_len, d_freq); +} + +void +gr_goertzel_fc::set_rate(int rate) +{ + d_rate = rate; + d_goertzel.gri_setparms(d_rate, d_len, d_freq); +} diff --git a/gnuradio-core/src/lib/filter/gr_goertzel_fc.h b/gnuradio-core/src/lib/filter/gr_goertzel_fc.h new file mode 100644 index 000000000..5fb6e0ee0 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_goertzel_fc.h @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_GOERTZEL_FC_H +#define INCLUDED_GR_GOERTZEL_FC_H + +#include <gr_core_api.h> +#include <gri_goertzel.h> +#include <gr_sync_decimator.h> + +class gr_goertzel_fc; +typedef boost::shared_ptr<gr_goertzel_fc> gr_goertzel_fc_sptr; + +// public constructor +GR_CORE_API gr_goertzel_fc_sptr gr_make_goertzel_fc(int rate, int len, float freq); + +/*! + * \brief Goertzel single-bin DFT calculation. + * \ingroup dft_blk + */ +class GR_CORE_API gr_goertzel_fc : public gr_sync_decimator +{ +private: + friend GR_CORE_API gr_goertzel_fc_sptr gr_make_goertzel_fc (int rate, int len, float freq); + + gr_goertzel_fc(int rate, int len, float freq); + gri_goertzel d_goertzel; + int d_len; + float d_freq; + int d_rate; + +public: + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void set_freq (float freq); + void set_rate (int rate); +}; + +#endif /* INCLUDED_GR_GOERTZEL_FC_H */ + diff --git a/gnuradio-core/src/lib/filter/gr_goertzel_fc.i b/gnuradio-core/src/lib/filter/gr_goertzel_fc.i new file mode 100644 index 000000000..775c78cc8 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_goertzel_fc.i @@ -0,0 +1,35 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,goertzel_fc); + +gr_goertzel_fc_sptr gr_make_goertzel_fc(int rate, int len, float freq); + +class gr_goertzel_fc : public gr_sync_decimator +{ +private: + gr_goertzel_fc(); + +public: + void set_freq (float freq); + void set_rate (int rate); +}; diff --git a/gnuradio-core/src/lib/filter/gr_hilbert_fc.cc b/gnuradio-core/src/lib/filter/gr_hilbert_fc.cc new file mode 100644 index 000000000..385e24ad2 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_hilbert_fc.cc @@ -0,0 +1,67 @@ +/* -*- 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_hilbert_fc.h> +#include <gr_firdes.h> +#include <gr_fir_fff.h> +#include <gr_fir_util.h> + +// public constructor +gr_hilbert_fc_sptr +gr_make_hilbert_fc (unsigned int ntaps) +{ + return gnuradio::get_initial_sptr(new gr_hilbert_fc (ntaps)); +} + +gr_hilbert_fc::gr_hilbert_fc (unsigned int ntaps) + : gr_sync_block ("hilbert_fc", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (gr_complex))), + d_ntaps (ntaps | 0x1), // ensure ntaps is odd + d_hilb (gr_fir_util::create_gr_fir_fff (gr_firdes::hilbert (d_ntaps))) +{ + set_history (d_ntaps); +} + +gr_hilbert_fc::~gr_hilbert_fc () +{ + delete d_hilb; +} + +int +gr_hilbert_fc::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float *in = (float *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + for (int i = 0; i < noutput_items; i++) + out[i] = gr_complex (in[i + d_ntaps/2], + d_hilb->filter (&in[i])); + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_hilbert_fc.h b/gnuradio-core/src/lib/filter/gr_hilbert_fc.h new file mode 100644 index 000000000..2bb5ff9e3 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_hilbert_fc.h @@ -0,0 +1,69 @@ +/* -*- 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_HILBERT_FC_H +#define INCLUDED_GR_HILBERT_FC_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_io_signature.h> +#include <gr_types.h> + +class gr_hilbert_fc; +typedef boost::shared_ptr<gr_hilbert_fc> gr_hilbert_fc_sptr; + +// public constructor +GR_CORE_API gr_hilbert_fc_sptr gr_make_hilbert_fc (unsigned int ntaps); + + +class gr_fir_fff; + +/*! + * \brief Hilbert transformer. + * \ingroup filter_blk + * + * real output is input appropriately delayed. + * imaginary output is hilbert filtered (90 degree phase shift) + * version of input. + */ +class GR_CORE_API gr_hilbert_fc : public gr_sync_block +{ + public: + ~gr_hilbert_fc (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + protected: + gr_hilbert_fc (unsigned int ntaps); + + private: + unsigned int d_ntaps; + gr_fir_fff *d_hilb; + + friend GR_CORE_API gr_hilbert_fc_sptr gr_make_hilbert_fc (unsigned int ntaps); +}; + + + +#endif /* INCLUDED_GR_HILBERT_FC_H */ diff --git a/gnuradio-core/src/lib/filter/gr_hilbert_fc.i b/gnuradio-core/src/lib/filter/gr_hilbert_fc.i new file mode 100644 index 000000000..91d4e23eb --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_hilbert_fc.i @@ -0,0 +1,34 @@ +/* -*- 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,hilbert_fc); + +gr_hilbert_fc_sptr gr_make_hilbert_fc (unsigned int ntaps); + +class gr_hilbert_fc : public gr_sync_block +{ +protected: + gr_hilbert_fc (unsigned int ntaps); + +public: + ~gr_hilbert_fc (); +}; diff --git a/gnuradio-core/src/lib/filter/gr_iir_filter_ffd.cc b/gnuradio-core/src/lib/filter/gr_iir_filter_ffd.cc new file mode 100644 index 000000000..4da2aa310 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_iir_filter_ffd.cc @@ -0,0 +1,82 @@ +/* -*- 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_iir_filter_ffd.h> +#include <gr_io_signature.h> +#include <stdio.h> + + +gr_iir_filter_ffd_sptr +gr_make_iir_filter_ffd (const std::vector<double> &fftaps, + const std::vector<double> &fbtaps) throw (std::invalid_argument) +{ + return gnuradio::get_initial_sptr(new gr_iir_filter_ffd (fftaps, fbtaps)); +} + +gr_iir_filter_ffd::gr_iir_filter_ffd (const std::vector<double> &fftaps, + const std::vector<double> &fbtaps) throw (std::invalid_argument) + + : gr_sync_block ("iir_filter_ffd", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (float))), + d_iir (fftaps, fbtaps), + d_updated (false) +{ + // fprintf (stderr, "gr_iir_filter_ffd::ctor\n"); +} + +gr_iir_filter_ffd::~gr_iir_filter_ffd () +{ + // nop +} + +void +gr_iir_filter_ffd::set_taps (const std::vector<double> &fftaps, + const std::vector<double> &fbtaps) throw (std::invalid_argument) +{ + + d_new_fftaps = fftaps; + d_new_fbtaps = fbtaps; + d_updated = true; +} + +int +gr_iir_filter_ffd::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]; + + + if (d_updated){ + d_iir.set_taps (d_new_fftaps, d_new_fbtaps); + d_updated = false; + } + + d_iir.filter_n (out, in, noutput_items); + return noutput_items; +}; diff --git a/gnuradio-core/src/lib/filter/gr_iir_filter_ffd.h b/gnuradio-core/src/lib/filter/gr_iir_filter_ffd.h new file mode 100644 index 000000000..ab7065e92 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_iir_filter_ffd.h @@ -0,0 +1,99 @@ +/* -*- 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_IIR_FILTER_FFD_H +#define INCLUDED_GR_IIR_FILTER_FFD_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gri_iir.h> +#include <stdexcept> + +class gr_iir_filter_ffd; +typedef boost::shared_ptr<gr_iir_filter_ffd> gr_iir_filter_ffd_sptr; +GR_CORE_API gr_iir_filter_ffd_sptr +gr_make_iir_filter_ffd (const std::vector<double> &fftaps, + const std::vector<double> &fbtaps) throw (std::invalid_argument); + +/*! + * \brief IIR filter with float input, float output and double taps + * \ingroup filter_blk + * + * This filter uses the Direct Form I implementation, where + * \p fftaps contains the feed-forward taps, and \p fbtaps the feedback ones. + * + * + * The input and output satisfy a difference equation of the form + \htmlonly + \f{ + y[n] - \sum_{k=1}^{M} a_k y[n-k] = \sum_{k=0}^{N} b_k x[n-k] + \f} + \endhtmlonly + + \xmlonly + y[n] - \sum_{k=1}^{M} a_k y[n-k] = \sum_{k=0}^{N} b_k x[n-k] + \endxmlonly + + * with the corresponding rational system function + \htmlonly + \f{ + H(z) = \ frac{\sum_{k=0}^{M} b_k z^{-k}}{1 - \sum_{k=1}^{N} a_k z^{-k}} + \f} + \endhtmlonly + + \xmlonly + H(z) = \ frac{\sum_{k=0}^{M} b_k z^{-k}}{1 - \sum_{k=1}^{N} a_k z^{-k}} + \endxmlonly + + * Note that some texts define the system function with a + in the denominator. + * If you're using that convention, you'll need to negate the feedback taps. + */ +class GR_CORE_API gr_iir_filter_ffd : public gr_sync_block +{ + private: + friend GR_CORE_API gr_iir_filter_ffd_sptr + gr_make_iir_filter_ffd (const std::vector<double> &fftaps, + const std::vector<double> &fbtaps) throw (std::invalid_argument); + + gri_iir<float,float,double> d_iir; + std::vector<double> d_new_fftaps; + std::vector<double> d_new_fbtaps; + bool d_updated; + + /*! + * Construct an IIR filter with the given taps + */ + gr_iir_filter_ffd (const std::vector<double> &fftaps, + const std::vector<double> &fbtaps) throw (std::invalid_argument); + + public: + ~gr_iir_filter_ffd (); + + void set_taps (const std::vector<double> &fftaps, + const std::vector<double> &fbtaps) throw (std::invalid_argument); + + 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/filter/gr_iir_filter_ffd.i b/gnuradio-core/src/lib/filter/gr_iir_filter_ffd.i new file mode 100644 index 000000000..0a35ad89e --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_iir_filter_ffd.i @@ -0,0 +1,40 @@ +/* -*- 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,iir_filter_ffd); + +gr_iir_filter_ffd_sptr +gr_make_iir_filter_ffd (const std::vector<double> &fftaps, + const std::vector<double> &fbtaps) throw (std::invalid_argument); + +class gr_iir_filter_ffd : public gr_sync_block +{ + private: + gr_iir_filter_ffd (const std::vector<double> &fftaps, + const std::vector<double> &fbtaps) throw (std::invalid_argument); + + public: + ~gr_iir_filter_ffd (); + + void set_taps (const std::vector<double> &fftaps, + const std::vector<double> &fbtaps) throw (std::invalid_argument); +}; diff --git a/gnuradio-core/src/lib/filter/gr_interp_fir_filter_XXX.cc.t b/gnuradio-core/src/lib/filter/gr_interp_fir_filter_XXX.cc.t new file mode 100644 index 000000000..55297d1eb --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_interp_fir_filter_XXX.cc.t @@ -0,0 +1,146 @@ +/* -*- 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: This file is automatically generated by generate_gr_fir_filter_XXX.py + * Any changes made to this file will be overwritten. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <@FIR_TYPE@.h> +#include <gr_fir_util.h> +#include <gr_io_signature.h> +#include <stdexcept> +#include <iostream> + +@SPTR_NAME@ gr_make_@BASE_NAME@ (unsigned interpolation, const std::vector<@TAP_TYPE@> &taps) +{ + return gnuradio::get_initial_sptr (new @NAME@ (interpolation, taps)); +} + + +@NAME@::@NAME@ (unsigned interpolation, const std::vector<@TAP_TYPE@> &taps) + : gr_sync_interpolator ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@)), + interpolation), + d_updated (false), d_firs (interpolation) +{ + if (interpolation == 0) + throw std::out_of_range ("interpolation must be > 0"); + + std::vector<@TAP_TYPE@> dummy_taps; + + for (unsigned i = 0; i < interpolation; i++) + d_firs[i] = gr_fir_util::create_@FIR_TYPE@ (dummy_taps); + + set_taps (taps); + install_taps(d_new_taps); +} + +@NAME@::~@NAME@ () +{ + int interp = interpolation (); + for (int i = 0; i < interp; i++) + delete d_firs[i]; +} + +void +@NAME@::set_taps (const std::vector<@TAP_TYPE@> &taps) +{ + d_new_taps = taps; + d_updated = true; + + // round up length to a multiple of the interpolation factor + int n = taps.size () % interpolation (); + if (n > 0){ + n = interpolation () - n; + while (n-- > 0) + d_new_taps.insert(d_new_taps.begin(), 0); + } + + assert (d_new_taps.size () % interpolation () == 0); +} + + +void +@NAME@::install_taps (const std::vector<@TAP_TYPE@> &taps) +{ + int nfilters = interpolation (); + int nt = taps.size () / nfilters; + + assert (nt * nfilters == (int) taps.size ()); + + std::vector< std::vector <@TAP_TYPE@> > xtaps (nfilters); + + for (int n = 0; n < nfilters; n++) + xtaps[n].resize (nt); + + for (int i = 0; i < (int) taps.size(); i++) + xtaps[i % nfilters][i / nfilters] = taps[i]; + + for (int n = 0; n < nfilters; n++) + d_firs[n]->set_taps (xtaps[n]); + + set_history (nt); + d_updated = false; + +#if 0 + for (int i = 0; i < nfilters; i++){ + std::cout << "filter[" << i << "] = "; + for (int j = 0; j < nt; j++) + std::cout << xtaps[i][j] << " "; + + std::cout << "\n"; + } +#endif + +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const @I_TYPE@ *in = (const @I_TYPE@ *) input_items[0]; + @O_TYPE@ *out = (@O_TYPE@ *) output_items[0]; + + if (d_updated) { + install_taps (d_new_taps); + return 0; // history requirements may have changed. + } + + int nfilters = interpolation (); + int ni = noutput_items / interpolation (); + + for (int i = 0; i < ni; i++){ + for (int nf = 0; nf < nfilters; nf++) + out[nf] = d_firs[nf]->filter (&in[i]); + out += nfilters; + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_interp_fir_filter_XXX.h.t b/gnuradio-core/src/lib/filter/gr_interp_fir_filter_XXX.h.t new file mode 100644 index 000000000..83904dce2 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_interp_fir_filter_XXX.h.t @@ -0,0 +1,70 @@ +/* -*- 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: This file is automatically generated by generate_gr_fir_filter_XXX.py + * Any changes made to this file will be overwritten. + */ + +#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@ (unsigned interpolation, const std::vector<@TAP_TYPE@> &taps); + +class @FIR_TYPE@; + +/*! + * \brief Interpolating FIR filter with @I_TYPE@ input, @O_TYPE@ output and @TAP_TYPE@ taps + * \ingroup filter_blk + */ +class GR_CORE_API @NAME@ : public gr_sync_interpolator +{ + private: + friend GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (unsigned interpolation, const std::vector<@TAP_TYPE@> &taps); + + std::vector<@TAP_TYPE@> d_new_taps; + bool d_updated; + std::vector<@FIR_TYPE@ *> d_firs; + + /*! + * Construct a FIR filter with the given taps + */ + @NAME@ (unsigned interpolation, const std::vector<@TAP_TYPE@> &taps); + + void install_taps (const std::vector<@TAP_TYPE@> &taps); + + public: + ~@NAME@ (); + + void set_taps (const std::vector<@TAP_TYPE@> &taps); + + 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/filter/gr_interp_fir_filter_XXX.i.t b/gnuradio-core/src/lib/filter/gr_interp_fir_filter_XXX.i.t new file mode 100644 index 000000000..274753001 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_interp_fir_filter_XXX.i.t @@ -0,0 +1,41 @@ +/* -*- 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: This file is automatically generated by generate_GrFIRfilterXXX.py + * Any changes made to this file will be overwritten. + */ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (int interpolation, const std::vector<@TAP_TYPE@> &taps); + +class @NAME@ : public gr_sync_interpolator +{ + private: + @NAME@ (int interpolation, const std::vector<@TAP_TYPE@> &taps); + + public: + ~@NAME@ (); + + void set_taps (const std::vector<@TAP_TYPE@> &taps); +}; diff --git a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc new file mode 100644 index 000000000..ee09fef44 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.cc @@ -0,0 +1,210 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,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_pfb_arb_resampler_ccf.h> +#include <gr_fir_ccf.h> +#include <gr_fir_util.h> +#include <gr_io_signature.h> +#include <cstdio> + +gr_pfb_arb_resampler_ccf_sptr gr_make_pfb_arb_resampler_ccf (float rate, + const std::vector<float> &taps, + unsigned int filter_size) +{ + return gnuradio::get_initial_sptr(new gr_pfb_arb_resampler_ccf (rate, taps, + filter_size)); +} + + +gr_pfb_arb_resampler_ccf::gr_pfb_arb_resampler_ccf (float rate, + const std::vector<float> &taps, + unsigned int filter_size) + : gr_block ("pfb_arb_resampler_ccf", + gr_make_io_signature (1, 1, sizeof(gr_complex)), + gr_make_io_signature (1, 1, sizeof(gr_complex))), + d_updated (false) +{ + d_acc = 0; // start accumulator at 0 + + /* The number of filters is specified by the user as the filter size; + this is also the interpolation rate of the filter. We use it and the + rate provided to determine the decimation rate. This acts as a + rational resampler. The flt_rate is calculated as the residual + between the integer decimation rate and the real decimation rate and + will be used to determine to interpolation point of the resampling + process. + */ + d_int_rate = filter_size; + set_rate(rate); + + // Store the last filter between calls to work + d_last_filter = 0; + + d_start_index = 0; + + d_filters = std::vector<gr_fir_ccf*>(d_int_rate); + d_diff_filters = std::vector<gr_fir_ccf*>(d_int_rate); + + // Create an FIR filter for each channel and zero out the taps + std::vector<float> vtaps(0, d_int_rate); + for(unsigned int i = 0; i < d_int_rate; i++) { + d_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps); + d_diff_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps); + } + + // Now, actually set the filters' taps + std::vector<float> dtaps; + create_diff_taps(taps, dtaps); + create_taps(taps, d_taps, d_filters); + create_taps(dtaps, d_dtaps, d_diff_filters); +} + +gr_pfb_arb_resampler_ccf::~gr_pfb_arb_resampler_ccf () +{ + for(unsigned int i = 0; i < d_int_rate; i++) { + delete d_filters[i]; + delete d_diff_filters[i]; + } +} + +void +gr_pfb_arb_resampler_ccf::create_taps (const std::vector<float> &newtaps, + std::vector< std::vector<float> > &ourtaps, + std::vector<gr_fir_ccf*> &ourfilter) +{ + unsigned int ntaps = newtaps.size(); + d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_int_rate); + + // Create d_numchan vectors to store each channel's taps + ourtaps.resize(d_int_rate); + + // Make a vector of the taps plus fill it out with 0's to fill + // each polyphase filter with exactly d_taps_per_filter + std::vector<float> tmp_taps; + tmp_taps = newtaps; + while((float)(tmp_taps.size()) < d_int_rate*d_taps_per_filter) { + tmp_taps.push_back(0.0); + } + + // Partition the filter + for(unsigned int i = 0; i < d_int_rate; i++) { + // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out + ourtaps[d_int_rate-1-i] = std::vector<float>(d_taps_per_filter, 0); + for(unsigned int j = 0; j < d_taps_per_filter; j++) { + ourtaps[d_int_rate - 1 - i][j] = tmp_taps[i + j*d_int_rate]; + } + + // Build a filter for each channel and add it's taps to it + ourfilter[i]->set_taps(ourtaps[d_int_rate-1-i]); + } + + // Set the history to ensure enough input items for each filter + set_history (d_taps_per_filter + 1); + + d_updated = true; +} + +void +gr_pfb_arb_resampler_ccf::create_diff_taps(const std::vector<float> &newtaps, + std::vector<float> &difftaps) +{ + // Calculate the differential taps (derivative filter) by taking the difference + // between two taps. Duplicate the last one to make both filters the same length. + float tap; + difftaps.clear(); + for(unsigned int i = 0; i < newtaps.size()-1; i++) { + tap = newtaps[i+1] - newtaps[i]; + difftaps.push_back(tap); + } + difftaps.push_back(tap); +} + +void +gr_pfb_arb_resampler_ccf::print_taps() +{ + unsigned int i, j; + for(i = 0; i < d_int_rate; i++) { + printf("filter[%d]: [", i); + for(j = 0; j < d_taps_per_filter; j++) { + printf(" %.4e", d_taps[i][j]); + } + printf("]\n"); + } +} + +int +gr_pfb_arb_resampler_ccf::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gr_complex *in = (gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + if (d_updated) { + d_updated = false; + return 0; // history requirements may have changed. + } + + int i = 0, count = d_start_index; + unsigned int j; + gr_complex o0, o1; + + // Restore the last filter position + j = d_last_filter; + + // produce output as long as we can and there are enough input samples + int max_input = ninput_items[0]-(int)d_taps_per_filter; + while((i < noutput_items) && (count < max_input)) { + // start j by wrapping around mod the number of channels + while((j < d_int_rate) && (i < noutput_items)) { + // Take the current filter and derivative filter output + o0 = d_filters[j]->filter(&in[count]); + o1 = d_diff_filters[j]->filter(&in[count]); + + out[i] = o0 + o1*d_acc; // linearly interpolate between samples + i++; + + // Adjust accumulator and index into filterbank + d_acc += d_flt_rate; + j += d_dec_rate + (int)floor(d_acc); + d_acc = fmodf(d_acc, 1.0); + } + if(i < noutput_items) { // keep state for next entry + float ss = (int)(j / d_int_rate); // number of items to skip ahead by + count += ss; // we have fully consumed another input + j = j % d_int_rate; // roll filter around + } + } + + // Store the current filter position and start of next sample + d_last_filter = j; + d_start_index = std::max(0, count - ninput_items[0]); + + // consume all we've processed but no more than we can + consume_each(std::min(count, ninput_items[0])); + return i; +} diff --git a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h new file mode 100644 index 000000000..d92898a23 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.h @@ -0,0 +1,178 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,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_PFB_ARB_RESAMPLER_CCF_H +#define INCLUDED_GR_PFB_ARB_RESAMPLER_CCF_H + +#include <gr_core_api.h> +#include <gr_block.h> + +class gr_pfb_arb_resampler_ccf; +typedef boost::shared_ptr<gr_pfb_arb_resampler_ccf> gr_pfb_arb_resampler_ccf_sptr; +GR_CORE_API gr_pfb_arb_resampler_ccf_sptr gr_make_pfb_arb_resampler_ccf (float rate, + const std::vector<float> &taps, + unsigned int filter_size=32); + +class gr_fir_ccf; + +/*! + * \class gr_pfb_arb_resampler_ccf + * + * \brief Polyphase filterbank arbitrary resampler with + * gr_complex input, gr_complex output and float taps + * + * \ingroup filter_blk + * \ingroup pfb_blk + * + * This block takes in a signal stream and performs arbitrary + * resampling. The resampling rate can be any real + * number <EM>r</EM>. The resampling is done by constructing + * <EM>N</EM> filters where <EM>N</EM> is the interpolation rate. We + * then calculate <EM>D</EM> where <EM>D = floor(N/r)</EM>. + * + * Using <EM>N</EM> and <EM>D</EM>, we can perform rational resampling + * where <EM>N/D</EM> is a rational number close to the input rate + * <EM>r</EM> where we have <EM>N</EM> filters and we cycle through + * them as a polyphase filterbank with a stride of <EM>D</EM> so that + * <EM>i+1 = (i + D) % N</EM>. + * + * To get the arbitrary rate, we want to interpolate between two + * points. For each value out, we take an output from the current + * filter, <EM>i</EM>, and the next filter <EM>i+1</EM> and then + * linearly interpolate between the two based on the real resampling + * rate we want. + * + * The linear interpolation only provides us with an approximation to + * the real sampling rate specified. The error is a quantization error + * between the two filters we used as our interpolation points. To + * this end, the number of filters, <EM>N</EM>, used determines the + * quantization error; the larger <EM>N</EM>, the smaller the + * noise. You can design for a specified noise floor by setting the + * filter size (parameters <EM>filter_size</EM>). The size defaults to + * 32 filters, which is about as good as most implementations need. + * + * The trick with designing this filter is in how to specify the taps + * of the prototype filter. Like the PFB interpolator, the taps are + * specified using the interpolated filter rate. In this case, that + * rate is the input sample rate multiplied by the number of filters + * in the filterbank, which is also the interpolation rate. All other + * values should be relative to this rate. + * + * For example, for a 32-filter arbitrary resampler and using the + * GNU Radio's firdes utility to build the filter, we build a low-pass + * filter with a sampling rate of <EM>fs</EM>, a 3-dB bandwidth of + * <EM>BW</EM> and a transition bandwidth of <EM>TB</EM>. We can also + * specify the out-of-band attenuation to use, <EM>ATT</EM>, and the + * filter window function (a Blackman-harris window in this case). The + * first input is the gain of the filter, which we specify here as the + * interpolation rate (<EM>32</EM>). + * + * <B><EM>self._taps = gr.firdes.low_pass_2(32, 32*fs, BW, TB, + * attenuation_dB=ATT, window=gr.firdes.WIN_BLACKMAN_hARRIS)</EM></B> + * + * The theory behind this block can be found in Chapter 7.5 of + * the following book. + * + * <B><EM>f. harris, "Multirate Signal Processing for Communication + * Systems", Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B> + */ + +class GR_CORE_API gr_pfb_arb_resampler_ccf : public gr_block +{ + private: + /*! + * Build the polyphase filterbank arbitray resampler. + * \param rate (float) Specifies the resampling rate to use + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps + * should be generated at the filter_size sampling rate. + * \param filter_size (unsigned int) The number of filters in the filter bank. This is directly + related to quantization noise introduced during the resampling. + Defaults to 32 filters. + */ + friend GR_CORE_API gr_pfb_arb_resampler_ccf_sptr gr_make_pfb_arb_resampler_ccf (float rate, + const std::vector<float> &taps, + unsigned int filter_size); + + std::vector<gr_fir_ccf*> d_filters; + std::vector<gr_fir_ccf*> d_diff_filters; + std::vector< std::vector<float> > d_taps; + std::vector< std::vector<float> > d_dtaps; + unsigned int d_int_rate; // the number of filters (interpolation rate) + unsigned int d_dec_rate; // the stride through the filters (decimation rate) + float d_flt_rate; // residual rate for the linear interpolation + float d_acc; + unsigned int d_last_filter; + int d_start_index; + unsigned int d_taps_per_filter; + bool d_updated; + + /*! + * Build the polyphase filterbank arbitray resampler. + * \param rate (float) Specifies the resampling rate to use + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps + * should be generated at the filter_size sampling rate. + * \param filter_size (unsigned int) The number of filters in the filter bank. This is directly + related to quantization noise introduced during the resampling. + Defaults to 32 filters. + */ + gr_pfb_arb_resampler_ccf (float rate, + const std::vector<float> &taps, + unsigned int filter_size); + + void create_diff_taps(const std::vector<float> &newtaps, + std::vector<float> &difftaps); + + /*! + * Resets the filterbank's filter taps with the new prototype filter + * \param newtaps (vector of floats) The prototype filter to populate the filterbank. + * The taps should be generated at the interpolated sampling rate. + * \param ourtaps (vector of floats) Reference to our internal member of holding the taps. + * \param ourfilter (vector of filters) Reference to our internal filter to set the taps for. + */ + void create_taps (const std::vector<float> &newtaps, + std::vector< std::vector<float> > &ourtaps, + std::vector<gr_fir_ccf*> &ourfilter); + + +public: + ~gr_pfb_arb_resampler_ccf (); + + // FIXME: See about a set_taps function during runtime. + + /*! + * Print all of the filterbank taps to screen. + */ + void print_taps(); + void set_rate (float rate) { + d_dec_rate = (unsigned int)floor(d_int_rate/rate); + d_flt_rate = (d_int_rate/rate) - d_dec_rate; + set_relative_rate(rate); + } + + 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 diff --git a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.i b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.i new file mode 100644 index 000000000..da58947e9 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_ccf.i @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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,pfb_arb_resampler_ccf); + +gr_pfb_arb_resampler_ccf_sptr gr_make_pfb_arb_resampler_ccf (float rate, + const std::vector<float> &taps, + unsigned int filter_size=32); + +class gr_pfb_arb_resampler_ccf : public gr_block +{ + private: + gr_pfb_arb_resampler_ccf (float rate, + const std::vector<float> &taps, + unsigned int filter_size); + + public: + ~gr_pfb_arb_resampler_ccf (); + + //void set_taps (const std::vector<float> &taps); + void print_taps(); + void set_rate (float rate); +}; diff --git a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.cc b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.cc new file mode 100644 index 000000000..f01af2e6f --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.cc @@ -0,0 +1,210 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_pfb_arb_resampler_fff.h> +#include <gr_fir_fff.h> +#include <gr_fir_util.h> +#include <gr_io_signature.h> +#include <cstdio> + +gr_pfb_arb_resampler_fff_sptr gr_make_pfb_arb_resampler_fff (float rate, + const std::vector<float> &taps, + unsigned int filter_size) +{ + return gnuradio::get_initial_sptr(new gr_pfb_arb_resampler_fff (rate, taps, + filter_size)); +} + + +gr_pfb_arb_resampler_fff::gr_pfb_arb_resampler_fff (float rate, + const std::vector<float> &taps, + unsigned int filter_size) + : gr_block ("pfb_arb_resampler_fff", + gr_make_io_signature (1, 1, sizeof(float)), + gr_make_io_signature (1, 1, sizeof(float))), + d_updated (false) +{ + d_acc = 0; // start accumulator at 0 + + /* The number of filters is specified by the user as the filter size; + this is also the interpolation rate of the filter. We use it and the + rate provided to determine the decimation rate. This acts as a + rational resampler. The flt_rate is calculated as the residual + between the integer decimation rate and the real decimation rate and + will be used to determine to interpolation point of the resampling + process. + */ + d_int_rate = filter_size; + set_rate(rate); + + // Store the last filter between calls to work + d_last_filter = 0; + + d_start_index = 0; + + d_filters = std::vector<gr_fir_fff*>(d_int_rate); + d_diff_filters = std::vector<gr_fir_fff*>(d_int_rate); + + // Create an FIR filter for each channel and zero out the taps + std::vector<float> vtaps(0, d_int_rate); + for(unsigned int i = 0; i < d_int_rate; i++) { + d_filters[i] = gr_fir_util::create_gr_fir_fff(vtaps); + d_diff_filters[i] = gr_fir_util::create_gr_fir_fff(vtaps); + } + + // Now, actually set the filters' taps + std::vector<float> dtaps; + create_diff_taps(taps, dtaps); + create_taps(taps, d_taps, d_filters); + create_taps(dtaps, d_dtaps, d_diff_filters); +} + +gr_pfb_arb_resampler_fff::~gr_pfb_arb_resampler_fff () +{ + for(unsigned int i = 0; i < d_int_rate; i++) { + delete d_filters[i]; + delete d_diff_filters[i]; + } +} + +void +gr_pfb_arb_resampler_fff::create_taps (const std::vector<float> &newtaps, + std::vector< std::vector<float> > &ourtaps, + std::vector<gr_fir_fff*> &ourfilter) +{ + unsigned int ntaps = newtaps.size(); + d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_int_rate); + + // Create d_numchan vectors to store each channel's taps + ourtaps.resize(d_int_rate); + + // Make a vector of the taps plus fill it out with 0's to fill + // each polyphase filter with exactly d_taps_per_filter + std::vector<float> tmp_taps; + tmp_taps = newtaps; + while((float)(tmp_taps.size()) < d_int_rate*d_taps_per_filter) { + tmp_taps.push_back(0.0); + } + + // Partition the filter + for(unsigned int i = 0; i < d_int_rate; i++) { + // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out + ourtaps[d_int_rate-1-i] = std::vector<float>(d_taps_per_filter, 0); + for(unsigned int j = 0; j < d_taps_per_filter; j++) { + ourtaps[d_int_rate - 1 - i][j] = tmp_taps[i + j*d_int_rate]; + } + + // Build a filter for each channel and add it's taps to it + ourfilter[i]->set_taps(ourtaps[d_int_rate-1-i]); + } + + // Set the history to ensure enough input items for each filter + set_history (d_taps_per_filter + 1); + + d_updated = true; +} + +void +gr_pfb_arb_resampler_fff::create_diff_taps(const std::vector<float> &newtaps, + std::vector<float> &difftaps) +{ + // Calculate the differential taps (derivative filter) by taking the difference + // between two taps. Duplicate the last one to make both filters the same length. + float tap; + difftaps.clear(); + for(unsigned int i = 0; i < newtaps.size()-1; i++) { + tap = newtaps[i+1] - newtaps[i]; + difftaps.push_back(tap); + } + difftaps.push_back(tap); +} + +void +gr_pfb_arb_resampler_fff::print_taps() +{ + unsigned int i, j; + for(i = 0; i < d_int_rate; i++) { + printf("filter[%d]: [", i); + for(j = 0; j < d_taps_per_filter; j++) { + printf(" %.4e", d_taps[i][j]); + } + printf("]\n"); + } +} + +int +gr_pfb_arb_resampler_fff::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float *in = (float *) input_items[0]; + float *out = (float *) output_items[0]; + + if (d_updated) { + d_updated = false; + return 0; // history requirements may have changed. + } + + int i = 0, count = d_start_index; + unsigned int j; + float o0, o1; + + // Restore the last filter position + j = d_last_filter; + + // produce output as long as we can and there are enough input samples + int max_input = ninput_items[0]-(int)d_taps_per_filter; + while((i < noutput_items) && (count < max_input)) { + // start j by wrapping around mod the number of channels + while((j < d_int_rate) && (i < noutput_items)) { + // Take the current filter and derivative filter output + o0 = d_filters[j]->filter(&in[count]); + o1 = d_diff_filters[j]->filter(&in[count]); + + out[i] = o0 + o1*d_acc; // linearly interpolate between samples + i++; + + // Adjust accumulator and index into filterbank + d_acc += d_flt_rate; + j += d_dec_rate + (int)floor(d_acc); + d_acc = fmodf(d_acc, 1.0); + } + if(i < noutput_items) { // keep state for next entry + float ss = (int)(j / d_int_rate); // number of items to skip ahead by + count += ss; // we have fully consumed another input + j = j % d_int_rate; // roll filter around + } + } + + // Store the current filter position and start of next sample + d_last_filter = j; + d_start_index = std::max(0, count - ninput_items[0]); + + // consume all we've processed but no more than we can + consume_each(std::min(count, ninput_items[0])); + return i; +} diff --git a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.h b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.h new file mode 100644 index 000000000..d2e375210 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.h @@ -0,0 +1,178 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_GR_PFB_ARB_RESAMPLER_FFF_H +#define INCLUDED_GR_PFB_ARB_RESAMPLER_FFF_H + +#include <gr_core_api.h> +#include <gr_block.h> + +class gr_pfb_arb_resampler_fff; +typedef boost::shared_ptr<gr_pfb_arb_resampler_fff> gr_pfb_arb_resampler_fff_sptr; +GR_CORE_API gr_pfb_arb_resampler_fff_sptr gr_make_pfb_arb_resampler_fff (float rate, + const std::vector<float> &taps, + unsigned int filter_size=32); + +class gr_fir_fff; + +/*! + * \class gr_pfb_arb_resampler_fff + * + * \brief Polyphase filterbank arbitrary resampler with + * float input, float output and float taps + * + * \ingroup filter_blk + * \ingroup pfb_blk + * + * This block takes in a signal stream and performs arbitrary + * resampling. The resampling rate can be any real + * number <EM>r</EM>. The resampling is done by constructing + * <EM>N</EM> filters where <EM>N</EM> is the interpolation rate. We + * then calculate <EM>D</EM> where <EM>D = floor(N/r)</EM>. + * + * Using <EM>N</EM> and <EM>D</EM>, we can perform rational resampling + * where <EM>N/D</EM> is a rational number close to the input rate + * <EM>r</EM> where we have <EM>N</EM> filters and we cycle through + * them as a polyphase filterbank with a stride of <EM>D</EM> so that + * <EM>i+1 = (i + D) % N</EM>. + * + * To get the arbitrary rate, we want to interpolate between two + * points. For each value out, we take an output from the current + * filter, <EM>i</EM>, and the next filter <EM>i+1</EM> and then + * linearly interpolate between the two based on the real resampling + * rate we want. + * + * The linear interpolation only provides us with an approximation to + * the real sampling rate specified. The error is a quantization error + * between the two filters we used as our interpolation points. To + * this end, the number of filters, <EM>N</EM>, used determines the + * quantization error; the larger <EM>N</EM>, the smaller the + * noise. You can design for a specified noise floor by setting the + * filter size (parameters <EM>filter_size</EM>). The size defaults to + * 32 filters, which is about as good as most implementations need. + * + * The trick with designing this filter is in how to specify the taps + * of the prototype filter. Like the PFB interpolator, the taps are + * specified using the interpolated filter rate. In this case, that + * rate is the input sample rate multiplied by the number of filters + * in the filterbank, which is also the interpolation rate. All other + * values should be relative to this rate. + * + * For example, for a 32-filter arbitrary resampler and using the + * GNU Radio's firdes utility to build the filter, we build a low-pass + * filter with a sampling rate of <EM>fs</EM>, a 3-dB bandwidth of + * <EM>BW</EM> and a transition bandwidth of <EM>TB</EM>. We can also + * specify the out-of-band attenuation to use, <EM>ATT</EM>, and the + * filter window function (a Blackman-harris window in this case). The + * first input is the gain of the filter, which we specify here as the + * interpolation rate (<EM>32</EM>). + * + * <B><EM>self._taps = gr.firdes.low_pass_2(32, 32*fs, BW, TB, + * attenuation_dB=ATT, window=gr.firdes.WIN_BLACKMAN_hARRIS)</EM></B> + * + * The theory behind this block can be found in Chapter 7.5 of + * the following book. + * + * <B><EM>f. harris, "Multirate Signal Processing for Communication + * Systems", Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B> + */ + +class GR_CORE_API gr_pfb_arb_resampler_fff : public gr_block +{ + private: + /*! + * Build the polyphase filterbank arbitray resampler. + * \param rate (float) Specifies the resampling rate to use + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps + * should be generated at the filter_size sampling rate. + * \param filter_size (unsigned int) The number of filters in the filter bank. This is directly + related to quantization noise introduced during the resampling. + Defaults to 32 filters. + */ + friend GR_CORE_API gr_pfb_arb_resampler_fff_sptr gr_make_pfb_arb_resampler_fff (float rate, + const std::vector<float> &taps, + unsigned int filter_size); + + std::vector<gr_fir_fff*> d_filters; + std::vector<gr_fir_fff*> d_diff_filters; + std::vector< std::vector<float> > d_taps; + std::vector< std::vector<float> > d_dtaps; + unsigned int d_int_rate; // the number of filters (interpolation rate) + unsigned int d_dec_rate; // the stride through the filters (decimation rate) + float d_flt_rate; // residual rate for the linear interpolation + float d_acc; + unsigned int d_last_filter; + int d_start_index; + unsigned int d_taps_per_filter; + bool d_updated; + + /*! + * Build the polyphase filterbank arbitray resampler. + * \param rate (float) Specifies the resampling rate to use + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps + * should be generated at the filter_size sampling rate. + * \param filter_size (unsigned int) The number of filters in the filter bank. This is directly + related to quantization noise introduced during the resampling. + Defaults to 32 filters. + */ + gr_pfb_arb_resampler_fff (float rate, + const std::vector<float> &taps, + unsigned int filter_size); + + void create_diff_taps(const std::vector<float> &newtaps, + std::vector<float> &difftaps); + + /*! + * Resets the filterbank's filter taps with the new prototype filter + * \param newtaps (vector of floats) The prototype filter to populate the filterbank. + * The taps should be generated at the interpolated sampling rate. + * \param ourtaps (vector of floats) Reference to our internal member of holding the taps. + * \param ourfilter (vector of filters) Reference to our internal filter to set the taps for. + */ + void create_taps (const std::vector<float> &newtaps, + std::vector< std::vector<float> > &ourtaps, + std::vector<gr_fir_fff*> &ourfilter); + + +public: + ~gr_pfb_arb_resampler_fff (); + + // FIXME: See about a set_taps function during runtime. + + /*! + * Print all of the filterbank taps to screen. + */ + void print_taps(); + void set_rate (float rate) { + d_dec_rate = (unsigned int)floor(d_int_rate/rate); + d_flt_rate = (d_int_rate/rate) - d_dec_rate; + set_relative_rate(rate); + } + + 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 diff --git a/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.i b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.i new file mode 100644 index 000000000..ad0905361 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_arb_resampler_fff.i @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,pfb_arb_resampler_fff); + +gr_pfb_arb_resampler_fff_sptr gr_make_pfb_arb_resampler_fff (float rate, + const std::vector<float> &taps, + unsigned int filter_size=32); + +class gr_pfb_arb_resampler_fff : public gr_block +{ + private: + gr_pfb_arb_resampler_fff (float rate, + const std::vector<float> &taps, + unsigned int filter_size); + + public: + ~gr_pfb_arb_resampler_fff (); + + //void set_taps (const std::vector<float> &taps); + void print_taps(); + void set_rate (float rate); +}; diff --git a/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.cc new file mode 100644 index 000000000..a8cb849e2 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.cc @@ -0,0 +1,240 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,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_pfb_channelizer_ccf.h> +#include <gr_fir_ccf.h> +#include <gr_fir_util.h> +#include <gri_fft.h> +#include <gr_io_signature.h> +#include <cstdio> +#include <cstring> + +gr_pfb_channelizer_ccf_sptr gr_make_pfb_channelizer_ccf (unsigned int numchans, + const std::vector<float> &taps, + float oversample_rate) +{ + return gnuradio::get_initial_sptr(new gr_pfb_channelizer_ccf (numchans, taps, + oversample_rate)); +} + + +gr_pfb_channelizer_ccf::gr_pfb_channelizer_ccf (unsigned int numchans, + const std::vector<float> &taps, + float oversample_rate) + : gr_block ("pfb_channelizer_ccf", + gr_make_io_signature (numchans, numchans, sizeof(gr_complex)), + gr_make_io_signature (1, numchans, sizeof(gr_complex))), + d_updated (false), d_numchans(numchans), d_oversample_rate(oversample_rate) +{ + // The over sampling rate must be rationally related to the number of channels + // in that it must be N/i for i in [1,N], which gives an outputsample rate + // of [fs/N, fs] where fs is the input sample rate. + // This tests the specified input sample rate to see if it conforms to this + // requirement within a few significant figures. + double intp = 0; + double fltp = modf(numchans / oversample_rate, &intp); + if(fltp != 0.0) + throw std::invalid_argument("gr_pfb_channelizer: oversample rate must be N/i for i in [1, N]"); + + set_relative_rate(1.0/intp); + + d_filters = std::vector<gr_fir_ccf*>(d_numchans); + d_channel_map.resize(d_numchans); + + // Create an FIR filter for each channel and zero out the taps + std::vector<float> vtaps(0, d_numchans); + for(unsigned int i = 0; i < d_numchans; i++) { + d_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps); + d_channel_map[i] = i; + } + + // Now, actually set the filters' taps + set_taps(taps); + + // Create the FFT to handle the output de-spinning of the channels + d_fft = new gri_fft_complex (d_numchans, false); + + // Although the filters change, we use this look up table + // to set the index of the FFT input buffer, which equivalently + // performs the FFT shift operation on every other turn. + d_rate_ratio = (int)rintf(d_numchans / d_oversample_rate); + d_idxlut = new int[d_numchans]; + for(unsigned int i = 0; i < d_numchans; i++) { + d_idxlut[i] = d_numchans - ((i + d_rate_ratio) % d_numchans) - 1; + } + + // Calculate the number of filtering rounds to do to evenly + // align the input vectors with the output channels + d_output_multiple = 1; + while((d_output_multiple * d_rate_ratio) % d_numchans != 0) + d_output_multiple++; + set_output_multiple(d_output_multiple); +} + +gr_pfb_channelizer_ccf::~gr_pfb_channelizer_ccf () +{ + delete d_fft; + delete [] d_idxlut; + + for(unsigned int i = 0; i < d_numchans; i++) { + delete d_filters[i]; + } +} + +void +gr_pfb_channelizer_ccf::set_taps (const std::vector<float> &taps) +{ + gruel::scoped_lock guard(d_mutex); + unsigned int i,j; + + unsigned int ntaps = taps.size(); + d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_numchans); + + // Create d_numchan vectors to store each channel's taps + d_taps.resize(d_numchans); + + // Make a vector of the taps plus fill it out with 0's to fill + // each polyphase filter with exactly d_taps_per_filter + std::vector<float> tmp_taps; + tmp_taps = taps; + while((float)(tmp_taps.size()) < d_numchans*d_taps_per_filter) { + tmp_taps.push_back(0.0); + } + + // Partition the filter + for(i = 0; i < d_numchans; i++) { + // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out + d_taps[i] = std::vector<float>(d_taps_per_filter, 0); + for(j = 0; j < d_taps_per_filter; j++) { + d_taps[i][j] = tmp_taps[i + j*d_numchans]; // add taps to channels in reverse order + } + + // Build a filter for each channel and add it's taps to it + d_filters[i]->set_taps(d_taps[i]); + } + + // Set the history to ensure enough input items for each filter + set_history (d_taps_per_filter+1); + + d_updated = true; +} + +void +gr_pfb_channelizer_ccf::print_taps() +{ + unsigned int i, j; + for(i = 0; i < d_numchans; i++) { + printf("filter[%d]: [", i); + for(j = 0; j < d_taps_per_filter; j++) { + printf(" %.4e", d_taps[i][j]); + } + printf("]\n\n"); + } +} + +std::vector< std::vector<float> > +gr_pfb_channelizer_ccf::taps() const +{ + return d_taps; +} + +void +gr_pfb_channelizer_ccf::set_channel_map(const std::vector<int> &map) +{ + gruel::scoped_lock guard(d_mutex); + + if(map.size() > 0) { + unsigned int max = (unsigned int)*std::max_element(map.begin(), map.end()); + unsigned int min = (unsigned int)*std::min_element(map.begin(), map.end()); + if((max >= d_numchans) || (min < 0)) { + throw std::invalid_argument("gr_pfb_channelizer_ccf::set_channel_map: map range out of bounds.\n"); + } + d_channel_map = map; + } +} + +std::vector<int> +gr_pfb_channelizer_ccf::channel_map() const +{ + return d_channel_map; +} + + +int +gr_pfb_channelizer_ccf::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gruel::scoped_lock guard(d_mutex); + + gr_complex *in = (gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + if (d_updated) { + d_updated = false; + return 0; // history requirements may have changed. + } + + size_t noutputs = output_items.size(); + + int n=1, i=-1, j=0, oo=0, last; + int toconsume = (int)rintf(noutput_items/d_oversample_rate); + while(n <= toconsume) { + j = 0; + i = (i + d_rate_ratio) % d_numchans; + last = i; + while(i >= 0) { + in = (gr_complex*)input_items[j]; + d_fft->get_inbuf()[d_idxlut[j]] = d_filters[i]->filter(&in[n]); + j++; + i--; + } + + i = d_numchans-1; + while(i > last) { + in = (gr_complex*)input_items[j]; + d_fft->get_inbuf()[d_idxlut[j]] = d_filters[i]->filter(&in[n-1]); + j++; + i--; + } + + n += (i+d_rate_ratio) >= (int)d_numchans; + + // despin through FFT + d_fft->execute(); + + // Send to output channels + for(unsigned int nn = 0; nn < noutputs; nn++) { + out = (gr_complex*)output_items[nn]; + out[oo] = d_fft->get_outbuf()[d_channel_map[nn]]; + } + oo++; + } + + consume_each(toconsume); + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h new file mode 100644 index 000000000..79ad322f9 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.h @@ -0,0 +1,226 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,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_PFB_CHANNELIZER_CCF_H +#define INCLUDED_GR_PFB_CHANNELIZER_CCF_H + +#include <gr_core_api.h> +#include <gr_block.h> +#include <gruel/thread.h> + +class gr_pfb_channelizer_ccf; +typedef boost::shared_ptr<gr_pfb_channelizer_ccf> gr_pfb_channelizer_ccf_sptr; +GR_CORE_API gr_pfb_channelizer_ccf_sptr gr_make_pfb_channelizer_ccf (unsigned int numchans, + const std::vector<float> &taps, + float oversample_rate=1); + +class gr_fir_ccf; +class gri_fft_complex; + + +/*! + * \class gr_pfb_channelizer_ccf + * + * \brief Polyphase filterbank channelizer with + * gr_complex input, gr_complex output and float taps + * + * \ingroup filter_blk + * \ingroup pfb_blk + * + * This block takes in complex inputs and channelizes it to <EM>M</EM> + * channels of equal bandwidth. Each of the resulting channels is + * decimated to the new rate that is the input sampling rate + * <EM>fs</EM> divided by the number of channels, <EM>M</EM>. + * + * The PFB channelizer code takes the taps generated above and builds + * a set of filters. The set contains <EM>M</EM> number of filters + * and each filter contains ceil(taps.size()/decim) number of taps. + * Each tap from the filter prototype is sequentially inserted into + * the next filter. When all of the input taps are used, the remaining + * filters in the filterbank are filled out with 0's to make sure each + * filter has the same number of taps. + * + * Each filter operates using the gr_fir filter classs of GNU Radio, + * which takes the input stream at <EM>i</EM> and performs the inner + * product calculation to <EM>i+(n-1)</EM> where <EM>n</EM> is the + * number of filter taps. To efficiently handle this in the GNU Radio + * structure, each filter input must come from its own input + * stream. So the channelizer must be provided with <EM>M</EM> streams + * where the input stream has been deinterleaved. This is most easily + * done using the gr_stream_to_streams block. + * + * The output is then produced as a vector, where index <EM>i</EM> in + * the vector is the next sample from the <EM>i</EM>th channel. This + * is most easily handled by sending the output to a + * gr_vector_to_streams block to handle the conversion and passing + * <EM>M</EM> streams out. + * + * The input and output formatting is done using a hier_block2 called + * pfb_channelizer_ccf. This can take in a single stream and outputs + * <EM>M</EM> streams based on the behavior described above. + * + * The filter's taps should be based on the input sampling rate. + * + * For example, using the GNU Radio's firdes utility to building + * filters, we build a low-pass filter with a sampling rate of + * <EM>fs</EM>, a 3-dB bandwidth of <EM>BW</EM> and a transition + * bandwidth of <EM>TB</EM>. We can also specify the out-of-band + * attenuation to use, <EM>ATT</EM>, and the filter window + * function (a Blackman-harris window in this case). The first input + * is the gain of the filter, which we specify here as unity. + * + * <B><EM>self._taps = gr.firdes.low_pass_2(1, fs, BW, TB, + * attenuation_dB=ATT, window=gr.firdes.WIN_BLACKMAN_hARRIS)</EM></B> + * + * The filter output can also be overs ampled. The over sampling rate + * is the ratio of the the actual output sampling rate to the normal + * output sampling rate. It must be rationally related to the number + * of channels as N/i for i in [1,N], which gives an outputsample rate + * of [fs/N, fs] where fs is the input sample rate and N is the number + * of channels. + * + * For example, for 6 channels with fs = 6000 Hz, the normal rate is + * 6000/6 = 1000 Hz. Allowable oversampling rates are 6/6, 6/5, 6/4, + * 6/3, 6/2, and 6/1 where the output sample rate of a 6/1 oversample + * ratio is 6000 Hz, or 6 times the normal 1000 Hz. A rate of 6/5 = 1.2, + * so the output rate would be 1200 Hz. + * + * The theory behind this block can be found in Chapter 6 of + * the following book. + * + * <B><EM>f. harris, "Multirate Signal Processing for Communication + * Systems," Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B> + * + */ + +class GR_CORE_API gr_pfb_channelizer_ccf : public gr_block +{ + private: + /*! + * Build the polyphase filterbank decimator. + * \param numchans (unsigned integer) Specifies the number of channels <EM>M</EM> + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. + * \param oversample_rate (float) The over sampling rate is the ratio of the the actual + * output sampling rate to the normal output sampling rate. + * It must be rationally related to the number of channels + * as N/i for i in [1,N], which gives an outputsample rate + * of [fs/N, fs] where fs is the input sample rate and N is + * the number of channels. + * + * For example, for 6 channels with fs = 6000 Hz, the normal + * rate is 6000/6 = 1000 Hz. Allowable oversampling rates + * are 6/6, 6/5, 6/4, 6/3, 6/2, and 6/1 where the output + * sample rate of a 6/1 oversample ratio is 6000 Hz, or + * 6 times the normal 1000 Hz. + */ + friend GR_CORE_API gr_pfb_channelizer_ccf_sptr gr_make_pfb_channelizer_ccf (unsigned int numchans, + const std::vector<float> &taps, + float oversample_rate); + + bool d_updated; + unsigned int d_numchans; + float d_oversample_rate; + std::vector<gr_fir_ccf*> d_filters; + std::vector< std::vector<float> > d_taps; + unsigned int d_taps_per_filter; + gri_fft_complex *d_fft; + int *d_idxlut; + int d_rate_ratio; + int d_output_multiple; + std::vector<int> d_channel_map; + gruel::mutex d_mutex; // mutex to protect set/work access + + /*! + * Build the polyphase filterbank decimator. + * \param numchans (unsigned integer) Specifies the number of channels <EM>M</EM> + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. + * \param oversample_rate (float) The output over sampling rate. + */ + gr_pfb_channelizer_ccf (unsigned int numchans, + const std::vector<float> &taps, + float oversample_rate); + +public: + ~gr_pfb_channelizer_ccf (); + + /*! + * Resets the filterbank's filter taps with the new prototype filter + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. + */ + void set_taps (const std::vector<float> &taps); + + /*! + * Print all of the filterbank taps to screen. + */ + void print_taps(); + + /*! + * Return a vector<vector<>> of the filterbank taps + */ + std::vector<std::vector<float> > taps() const; + + /*! + * Set the channel map. Channels are numbers as: + * + * N/2+1 | ... | N-1 | 0 | 1 | 2 | ... | N/2 + * <------------------- 0 --------------------> + * freq + * + * So output stream 0 comes from channel 0, etc. Setting a new + * channel map allows the user to specify which channel in frequency + * he/she wants to got to which output stream. + * + * The map should have the same number of elements as the number of + * output connections from the block. The minimum value of the map + * is 0 (for the 0th channel) and the maximum number is N-1 where N + * is the number of channels. + * + * We specify M as the number of output connections made where M <= + * N, so only M out of N channels are driven to an output + * stream. The number of items in the channel map should be at least + * M long. If there are more channels specified, any value in the + * map over M-1 will be ignored. If the size of the map is less than + * M the behavior is unknown (we don't wish to check every entry + * into the work function). + * + * This means that if the channelizer is splitting the signal up + * into N channels but only M channels are specified in the map + * (where M <= N), then M output streams must be connected and the + * map and the channel numbers used must be less than N-1. Output + * channel number can be reused, too. By default, the map is + * [0...M-1] with M = N. + */ + void set_channel_map(const std::vector<int> &map); + + /*! + * Gets the current channel map. + */ + std::vector<int> channel_map() const; + + 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 diff --git a/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.i b/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.i new file mode 100644 index 000000000..1f2b49452 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_channelizer_ccf.i @@ -0,0 +1,45 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,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,pfb_channelizer_ccf); + +gr_pfb_channelizer_ccf_sptr gr_make_pfb_channelizer_ccf (unsigned int numchans, + const std::vector<float> &taps, + float oversample_rate=1); + +class gr_pfb_channelizer_ccf : public gr_block +{ + private: + gr_pfb_channelizer_ccf (unsigned int numchans, + const std::vector<float> &taps, + float oversample_rate); + + public: + ~gr_pfb_channelizer_ccf (); + + void set_taps (const std::vector<float> &taps); + void print_taps(); + std::vector<std::vector<float> > taps() const; + + void set_channel_map(const std::vector<int> &map); + std::vector<int> channel_map() const; +}; diff --git a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc new file mode 100644 index 000000000..efe417918 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.cc @@ -0,0 +1,441 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <cstdio> +#include <cmath> + +#include <gr_pfb_clock_sync_ccf.h> +#include <gr_fir_ccf.h> +#include <gr_fir_util.h> +#include <gr_io_signature.h> +#include <gr_math.h> + +gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (double sps, float loop_bw, + const std::vector<float> &taps, + unsigned int filter_size, + float init_phase, + float max_rate_deviation, + int osps) +{ + return gnuradio::get_initial_sptr(new gr_pfb_clock_sync_ccf (sps, loop_bw, taps, + filter_size, + init_phase, + max_rate_deviation, + osps)); +} + +static int ios[] = {sizeof(gr_complex), sizeof(float), sizeof(float), sizeof(float)}; +static std::vector<int> iosig(ios, ios+sizeof(ios)/sizeof(int)); +gr_pfb_clock_sync_ccf::gr_pfb_clock_sync_ccf (double sps, float loop_bw, + const std::vector<float> &taps, + unsigned int filter_size, + float init_phase, + float max_rate_deviation, + int osps) + : gr_block ("pfb_clock_sync_ccf", + gr_make_io_signature (1, 1, sizeof(gr_complex)), + gr_make_io_signaturev (1, 4, iosig)), + d_updated (false), d_nfilters(filter_size), + d_max_dev(max_rate_deviation), + d_osps(osps), d_error(0), d_out_idx(0) +{ + d_nfilters = filter_size; + d_sps = floor(sps); + + // Set the damping factor for a critically damped system + d_damping = sqrtf(2.0f)/2.0f; + + // Set the bandwidth, which will then call update_gains() + set_loop_bandwidth(loop_bw); + + // Store the last filter between calls to work + // The accumulator keeps track of overflow to increment the stride correctly. + // set it here to the fractional difference based on the initial phaes + d_k = init_phase; + d_rate = (sps-floor(sps))*(double)d_nfilters; + d_rate_i = (int)floor(d_rate); + d_rate_f = d_rate - (float)d_rate_i; + d_filtnum = (int)floor(d_k); + + d_filters = std::vector<gr_fir_ccf*>(d_nfilters); + d_diff_filters = std::vector<gr_fir_ccf*>(d_nfilters); + + // Create an FIR filter for each channel and zero out the taps + std::vector<float> vtaps(0, d_nfilters); + for(int i = 0; i < d_nfilters; i++) { + d_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps); + d_diff_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps); + } + + // Now, actually set the filters' taps + std::vector<float> dtaps; + create_diff_taps(taps, dtaps); + set_taps(taps, d_taps, d_filters); + set_taps(dtaps, d_dtaps, d_diff_filters); +} + +gr_pfb_clock_sync_ccf::~gr_pfb_clock_sync_ccf () +{ + for(int i = 0; i < d_nfilters; i++) { + delete d_filters[i]; + delete d_diff_filters[i]; + } +} + +bool +gr_pfb_clock_sync_ccf::check_topology(int ninputs, int noutputs) +{ + return noutputs == 1 || noutputs == 4; +} + + + +/******************************************************************* + SET FUNCTIONS +*******************************************************************/ + + +void +gr_pfb_clock_sync_ccf::set_loop_bandwidth(float bw) +{ + if(bw < 0) { + throw std::out_of_range ("gr_pfb_clock_sync_cc: invalid bandwidth. Must be >= 0."); + } + + d_loop_bw = bw; + update_gains(); +} + +void +gr_pfb_clock_sync_ccf::set_damping_factor(float df) +{ + if(df < 0 || df > 1.0) { + throw std::out_of_range ("gr_pfb_clock_sync_cc: invalid damping factor. Must be in [0,1]."); + } + + d_damping = df; + update_gains(); +} + +void +gr_pfb_clock_sync_ccf::set_alpha(float alpha) +{ + if(alpha < 0 || alpha > 1.0) { + throw std::out_of_range ("gr_pfb_clock_sync_cc: invalid alpha. Must be in [0,1]."); + } + d_alpha = alpha; +} + +void +gr_pfb_clock_sync_ccf::set_beta(float beta) +{ + if(beta < 0 || beta > 1.0) { + throw std::out_of_range ("gr_pfb_clock_sync_cc: invalid beta. Must be in [0,1]."); + } + d_beta = beta; +} + +/******************************************************************* + GET FUNCTIONS +*******************************************************************/ + + +float +gr_pfb_clock_sync_ccf::get_loop_bandwidth() const +{ + return d_loop_bw; +} + +float +gr_pfb_clock_sync_ccf::get_damping_factor() const +{ + return d_damping; +} + +float +gr_pfb_clock_sync_ccf::get_alpha() const +{ + return d_alpha; +} + +float +gr_pfb_clock_sync_ccf::get_beta() const +{ + return d_beta; +} + +float +gr_pfb_clock_sync_ccf::get_clock_rate() const +{ + return d_rate_f; +} + +/******************************************************************* +*******************************************************************/ + +void +gr_pfb_clock_sync_ccf::update_gains() +{ + float denom = (1.0 + 2.0*d_damping*d_loop_bw + d_loop_bw*d_loop_bw); + d_alpha = (4*d_damping*d_loop_bw) / denom; + d_beta = (4*d_loop_bw*d_loop_bw) / denom; +} + + +void +gr_pfb_clock_sync_ccf::set_taps (const std::vector<float> &newtaps, + std::vector< std::vector<float> > &ourtaps, + std::vector<gr_fir_ccf*> &ourfilter) +{ + int i,j; + + unsigned int ntaps = newtaps.size(); + d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_nfilters); + + // Create d_numchan vectors to store each channel's taps + ourtaps.resize(d_nfilters); + + // Make a vector of the taps plus fill it out with 0's to fill + // each polyphase filter with exactly d_taps_per_filter + std::vector<float> tmp_taps; + tmp_taps = newtaps; + while((float)(tmp_taps.size()) < d_nfilters*d_taps_per_filter) { + tmp_taps.push_back(0.0); + } + + // Partition the filter + for(i = 0; i < d_nfilters; i++) { + // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out + //ourtaps[d_nfilters-1-i] = std::vector<float>(d_taps_per_filter, 0); + ourtaps[i] = std::vector<float>(d_taps_per_filter, 0); + for(j = 0; j < d_taps_per_filter; j++) { + //ourtaps[d_nfilters - 1 - i][j] = tmp_taps[i + j*d_nfilters]; + ourtaps[i][j] = tmp_taps[i + j*d_nfilters]; + } + + // Build a filter for each channel and add it's taps to it + //ourfilter[i]->set_taps(ourtaps[d_nfilters-1-i]); + ourfilter[i]->set_taps(ourtaps[i]); + } + + // Set the history to ensure enough input items for each filter + set_history (d_taps_per_filter + d_sps); + + // Make sure there is enough output space for d_osps outputs/input. + set_output_multiple(d_osps); + + d_updated = true; +} + +void +gr_pfb_clock_sync_ccf::create_diff_taps(const std::vector<float> &newtaps, + std::vector<float> &difftaps) +{ + std::vector<float> diff_filter(3); + diff_filter[0] = -1; + diff_filter[1] = 0; + diff_filter[2] = 1; + + float pwr = 0; + difftaps.push_back(0); + for(unsigned int i = 0; i < newtaps.size()-2; i++) { + float tap = 0; + for(int j = 0; j < 3; j++) { + tap += diff_filter[j]*newtaps[i+j]; + pwr += fabsf(tap); + } + difftaps.push_back(tap); + } + difftaps.push_back(0); + + for(unsigned int i = 0; i < difftaps.size(); i++) { + difftaps[i] *= pwr; + } +} + +std::string +gr_pfb_clock_sync_ccf::get_taps_as_string() +{ + int i, j; + std::stringstream str; + str.precision(4); + str.setf(std::ios::scientific); + + str << "[ "; + for(i = 0; i < d_nfilters; i++) { + str << "[" << d_taps[i][0] << ", "; + for(j = 1; j < d_taps_per_filter-1; j++) { + str << d_taps[i][j] << ", "; + } + str << d_taps[i][j] << "],"; + } + str << " ]" << std::endl; + + return str.str(); +} + +std::string +gr_pfb_clock_sync_ccf::get_diff_taps_as_string() +{ + int i, j; + std::stringstream str; + str.precision(4); + str.setf(std::ios::scientific); + + str << "[ "; + for(i = 0; i < d_nfilters; i++) { + str << "[" << d_dtaps[i][0] << ", "; + for(j = 1; j < d_taps_per_filter-1; j++) { + str << d_dtaps[i][j] << ", "; + } + str << d_dtaps[i][j] << "],"; + } + str << " ]" << std::endl; + + return str.str(); +} + +std::vector< std::vector<float> > +gr_pfb_clock_sync_ccf::get_taps() +{ + return d_taps; +} + +std::vector< std::vector<float> > +gr_pfb_clock_sync_ccf::get_diff_taps() +{ + return d_dtaps; +} + +std::vector<float> +gr_pfb_clock_sync_ccf::get_channel_taps(int channel) +{ + std::vector<float> taps; + for(int i = 0; i < d_taps_per_filter; i++) { + taps.push_back(d_taps[channel][i]); + } + return taps; +} + +std::vector<float> +gr_pfb_clock_sync_ccf::get_diff_channel_taps(int channel) +{ + std::vector<float> taps; + for(int i = 0; i < d_taps_per_filter; i++) { + taps.push_back(d_dtaps[channel][i]); + } + return taps; +} + + +int +gr_pfb_clock_sync_ccf::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gr_complex *in = (gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + float *err = NULL, *outrate = NULL, *outk = NULL; + if(output_items.size() == 4) { + err = (float *) output_items[1]; + outrate = (float*)output_items[2]; + outk = (float*)output_items[3]; + } + + if (d_updated) { + d_updated = false; + return 0; // history requirements may have changed. + } + + // We need this many to process one output + int nrequired = ninput_items[0] - d_taps_per_filter - d_osps; + + int i = 0, count = 0; + float error_r, error_i; + + // produce output as long as we can and there are enough input samples + while((i < noutput_items) && (count < nrequired)) { + while(d_out_idx < d_osps) { + d_filtnum = (int)floor(d_k); + + // Keep the current filter number in [0, d_nfilters] + // If we've run beyond the last filter, wrap around and go to next sample + // If we've go below 0, wrap around and go to previous sample + while(d_filtnum >= d_nfilters) { + d_k -= d_nfilters; + d_filtnum -= d_nfilters; + count += 1; + } + while(d_filtnum < 0) { + d_k += d_nfilters; + d_filtnum += d_nfilters; + count -= 1; + } + + out[i+d_out_idx] = d_filters[d_filtnum]->filter(&in[count+d_out_idx]); + d_k = d_k + d_rate_i + d_rate_f; // update phase + d_out_idx++; + + if(output_items.size() == 4) { + err[i] = d_error; + outrate[i] = d_rate_f; + outk[i] = d_k; + } + + // We've run out of output items we can create; return now. + if(i+d_out_idx >= noutput_items) { + consume_each(count); + return i; + } + } + + // reset here; if we didn't complete a full osps samples last time, + // the early return would take care of it. + d_out_idx = 0; + + // Update the phase and rate estimates for this symbol + gr_complex diff = d_diff_filters[d_filtnum]->filter(&in[count]); + error_r = out[i].real() * diff.real(); + error_i = out[i].imag() * diff.imag(); + d_error = (error_i + error_r) / 2.0; // average error from I&Q channel + + // Run the control loop to update the current phase (k) and + // tracking rate estimates based on the error value + d_rate_f = d_rate_f + d_beta*d_error; + d_k = d_k + d_alpha*d_error; + + // Keep our rate within a good range + d_rate_f = gr_branchless_clip(d_rate_f, d_max_dev); + + i+=d_osps; + count += (int)floor(d_sps); + } + + consume_each(count); + return i; +} diff --git a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h new file mode 100644 index 000000000..8715b4b10 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.h @@ -0,0 +1,375 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,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_PFB_CLOCK_SYNC_CCF_H +#define INCLUDED_GR_PFB_CLOCK_SYNC_CCF_H + +#include <gr_core_api.h> +#include <gr_block.h> + +class gr_pfb_clock_sync_ccf; +typedef boost::shared_ptr<gr_pfb_clock_sync_ccf> gr_pfb_clock_sync_ccf_sptr; +GR_CORE_API gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (double sps, float loop_bw, + const std::vector<float> &taps, + unsigned int filter_size=32, + float init_phase=0, + float max_rate_deviation=1.5, + int osps=1); + +class gr_fir_ccf; + +/*! + * \class gr_pfb_clock_sync_ccf + * + * \brief Timing synchronizer using polyphase filterbanks + * + * \ingroup filter_blk + * \ingroup pfb_blk + * + * This block performs timing synchronization for PAM signals by + * minimizing the derivative of the filtered signal, which in turn + * maximizes the SNR and minimizes ISI. + * + * This approach works by setting up two filterbanks; one filterbank + * contains the signal's pulse shaping matched filter (such as a root + * raised cosine filter), where each branch of the filterbank contains + * a different phase of the filter. The second filterbank contains + * the derivatives of the filters in the first filterbank. Thinking of + * this in the time domain, the first filterbank contains filters that + * have a sinc shape to them. We want to align the output signal to be + * sampled at exactly the peak of the sinc shape. The derivative of + * the sinc contains a zero at the maximum point of the sinc (sinc(0) + * = 1, sinc(0)' = 0). Furthermore, the region around the zero point + * is relatively linear. We make use of this fact to generate the + * error signal. + * + * If the signal out of the derivative filters is d_i[n] for the ith + * filter, and the output of the matched filter is x_i[n], we + * calculate the error as: e[n] = (Re{x_i[n]} * Re{d_i[n]} + + * Im{x_i[n]} * Im{d_i[n]}) / 2.0 This equation averages the error in + * the real and imaginary parts. There are two reasons we multiply by + * the signal itself. First, if the symbol could be positive or + * negative going, but we want the error term to always tell us to go + * in the same direction depending on which side of the zero point we + * are on. The sign of x_i[n] adjusts the error term to do + * this. Second, the magnitude of x_i[n] scales the error term + * depending on the symbol's amplitude, so larger signals give us a + * stronger error term because we have more confidence in that + * symbol's value. Using the magnitude of x_i[n] instead of just the + * sign is especially good for signals with low SNR. + * + * The error signal, e[n], gives us a value proportional to how far + * away from the zero point we are in the derivative signal. We want + * to drive this value to zero, so we set up a second order loop. We + * have two variables for this loop; d_k is the filter number in the + * filterbank we are on and d_rate is the rate which we travel through + * the filters in the steady state. That is, due to the natural clock + * differences between the transmitter and receiver, d_rate represents + * that difference and would traverse the filter phase paths to keep + * the receiver locked. Thinking of this as a second-order PLL, the + * d_rate is the frequency and d_k is the phase. So we update d_rate + * and d_k using the standard loop equations based on two error + * signals, d_alpha and d_beta. We have these two values set based on + * each other for a critically damped system, so in the block + * constructor, we just ask for "gain," which is d_alpha while d_beta + * is equal to (gain^2)/4. + * + * The block's parameters are: + * + * \li \p sps: The clock sync block needs to know the number of samples per + * symbol, because it defaults to return a single point representing + * the symbol. The sps can be any positive real number and does not + * need to be an integer. + * + * \li \p loop_bw: The loop bandwidth is used to set the gain of the + * inner control loop (see: + * http://gnuradio.squarespace.com/blog/2011/8/13/control-loop-gain-values.html). + * This should be set small (a value of around 2pi/100 is suggested in + * that blog post as the step size for the number of radians around + * the unit circle to move relative to the error). + * + * \li \p taps: One of the most important parameters for this block is + * the taps of the filter. One of the benefits of this algorithm is + * that you can put the matched filter in here as the taps, so you get + * both the matched filter and sample timing correction in one go. So + * create your normal matched filter. For a typical digital + * modulation, this is a root raised cosine filter. The number of taps + * of this filter is based on how long you expect the channel to be; + * that is, how many symbols do you want to combine to get the current + * symbols energy back (there's probably a better way of stating + * that). It's usually 5 to 10 or so. That gives you your filter, but + * now we need to think about it as a filter with different phase + * profiles in each filter. So take this number of taps and multiply + * it by the number of filters. This is the number you would use to + * create your prototype filter. When you use this in the PFB + * filerbank, it segments these taps into the filterbanks in such a + * way that each bank now represents the filter at different phases, + * equally spaced at 2pi/N, where N is the number of filters. + * + * \li \p filter_size (default=32): The number of filters can also be + * set and defaults to 32. With 32 filters, you get a good enough + * resolution in the phase to produce very small, almost unnoticeable, + * ISI. Going to 64 filters can reduce this more, but after that + * there is very little gained for the extra complexity. + * + * \li \p init_phase (default=0): The initial phase is another + * settable parameter and refers to the filter path the algorithm + * initially looks at (i.e., d_k starts at init_phase). This value + * defaults to zero, but it might be useful to start at a different + * phase offset, such as the mid-point of the filters. + * + * \li \p max_rate_deviation (default=1.5): The next parameter is the + * max_rate_devitation, which defaults to 1.5. This is how far we + * allow d_rate to swing, positive or negative, from 0. Constraining + * the rate can help keep the algorithm from walking too far away to + * lock during times when there is no signal. + * + * \li \p osps (default=1): The osps is the number of output samples per symbol. By default, + * the algorithm produces 1 sample per symbol, sampled at the exact + * sample value. This osps value was added to better work with + * equalizers, which do a better job of modeling the channel if they + * have 2 samps/sym. + */ + +class GR_CORE_API gr_pfb_clock_sync_ccf : public gr_block +{ + private: + /*! + * Build the polyphase filterbank timing synchronizer. + * \param sps (double) The number of samples per symbol in the incoming signal + * \param loop_bw (float) The bandwidth of the control loop; set's alpha and beta. + * \param taps (vector<int>) The filter taps. + * \param filter_size (uint) The number of filters in the filterbank (default = 32). + * \param init_phase (float) The initial phase to look at, or which filter to start + * with (default = 0). + * \param max_rate_deviation (float) Distance from 0 d_rate can get (default = 1.5). + * \param osps (int) The number of output samples per symbol (default=1). + * + */ + + friend GR_CORE_API gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (double sps, float loop_bw, + const std::vector<float> &taps, + unsigned int filter_size, + float init_phase, + float max_rate_deviation, + int osps); + + bool d_updated; + double d_sps; + double d_sample_num; + float d_loop_bw; + float d_damping; + float d_alpha; + float d_beta; + + int d_nfilters; + int d_taps_per_filter; + std::vector<gr_fir_ccf*> d_filters; + std::vector<gr_fir_ccf*> d_diff_filters; + std::vector< std::vector<float> > d_taps; + std::vector< std::vector<float> > d_dtaps; + + float d_k; + float d_rate; + float d_rate_i; + float d_rate_f; + float d_max_dev; + int d_filtnum; + int d_osps; + float d_error; + int d_out_idx; + + /*! + * Build the polyphase filterbank timing synchronizer. + */ + gr_pfb_clock_sync_ccf (double sps, float loop_bw, + const std::vector<float> &taps, + unsigned int filter_size, + float init_phase, + float max_rate_deviation, + int osps); + + void create_diff_taps(const std::vector<float> &newtaps, + std::vector<float> &difftaps); + +public: + ~gr_pfb_clock_sync_ccf (); + + /*! \brief update the system gains from omega and eta + * + * This function updates the system gains based on the loop + * bandwidth and damping factor of the system. + * These two factors can be set separately through their own + * set functions. + */ + void update_gains(); + + /*! + * Resets the filterbank's filter taps with the new prototype filter + */ + void set_taps (const std::vector<float> &taps, + std::vector< std::vector<float> > &ourtaps, + std::vector<gr_fir_ccf*> &ourfilter); + + /*! + * Returns all of the taps of the matched filter + */ + std::vector< std::vector<float> > get_taps(); + + /*! + * Returns all of the taps of the derivative filter + */ + std::vector< std::vector<float> > get_diff_taps(); + + /*! + * Returns the taps of the matched filter for a particular channel + */ + std::vector<float> get_channel_taps(int channel); + + /*! + * Returns the taps in the derivative filter for a particular channel + */ + std::vector<float> get_diff_channel_taps(int channel); + + /*! + * Return the taps as a formatted string for printing + */ + std::string get_taps_as_string(); + + /*! + * Return the derivative filter taps as a formatted string for printing + */ + std::string get_diff_taps_as_string(); + + + /******************************************************************* + SET FUNCTIONS + *******************************************************************/ + + + /*! + * \brief Set the loop bandwidth + * + * Set the loop filter's bandwidth to \p bw. This should be between + * 2*pi/200 and 2*pi/100 (in rads/samp). It must also be a positive + * number. + * + * When a new damping factor is set, the gains, alpha and beta, of the loop + * are recalculated by a call to update_gains(). + * + * \param bw (float) new bandwidth + * + */ + void set_loop_bandwidth(float bw); + + /*! + * \brief Set the loop damping factor + * + * Set the loop filter's damping factor to \p df. The damping factor + * should be sqrt(2)/2.0 for critically damped systems. + * Set it to anything else only if you know what you are doing. It must + * be a number between 0 and 1. + * + * When a new damping factor is set, the gains, alpha and beta, of the loop + * are recalculated by a call to update_gains(). + * + * \param df (float) new damping factor + * + */ + void set_damping_factor(float df); + + /*! + * \brief Set the loop gain alpha + * + * Set's the loop filter's alpha gain parameter. + * + * This value should really only be set by adjusting the loop bandwidth + * and damping factor. + * + * \param alpha (float) new alpha gain + * + */ + void set_alpha(float alpha); + + /*! + * \brief Set the loop gain beta + * + * Set's the loop filter's beta gain parameter. + * + * This value should really only be set by adjusting the loop bandwidth + * and damping factor. + * + * \param beta (float) new beta gain + * + */ + void set_beta(float beta); + + /*! + * Set the maximum deviation from 0 d_rate can have + */ + void set_max_rate_deviation(float m) + { + d_max_dev = m; + } + + /******************************************************************* + GET FUNCTIONS + *******************************************************************/ + + /*! + * \brief Returns the loop bandwidth + */ + float get_loop_bandwidth() const; + + /*! + * \brief Returns the loop damping factor + */ + float get_damping_factor() const; + + /*! + * \brief Returns the loop gain alpha + */ + float get_alpha() const; + + /*! + * \brief Returns the loop gain beta + */ + float get_beta() const; + + /*! + * \brief Returns the current clock rate + */ + float get_clock_rate() const; + + /******************************************************************* + *******************************************************************/ + + bool check_topology(int ninputs, int noutputs); + + 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 diff --git a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.i b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.i new file mode 100644 index 000000000..85915196f --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_ccf.i @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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,pfb_clock_sync_ccf); + +gr_pfb_clock_sync_ccf_sptr gr_make_pfb_clock_sync_ccf (double sps, float loop_bw, + const std::vector<float> &taps, + unsigned int filter_size=32, + float init_phase=0, + float max_rate_deviation=1.5, + int osps=1); + +class gr_pfb_clock_sync_ccf : public gr_block +{ + private: + gr_pfb_clock_sync_ccf (double sps, float loop_bw, + const std::vector<float> &taps, + unsigned int filter_size, + float init_phase, + float max_rate_deviation, + int osps); + + public: + ~gr_pfb_clock_sync_ccf (); + + void set_taps (const std::vector<float> &taps, + std::vector< std::vector<float> > &ourtaps, + std::vector<gr_fir_ccf*> &ourfilter); + + std::vector< std::vector<float> > get_taps(); + std::vector< std::vector<float> > get_diff_taps(); + std::vector<float> get_channel_taps(int channel); + std::vector<float> get_diff_channel_taps(int channel); + std::string get_taps_as_string(); + std::string get_diff_taps_as_string(); + + void set_loop_bandwidth(float bw); + void set_damping_factor(float df); + void set_alpha(float alpha); + void set_beta(float beta); + void set_max_rate_deviation(float m); + + float get_loop_bandwidth() const; + float get_damping_factor() const; + float get_alpha() const; + float get_beta() const; + float get_clock_rate() const; +}; diff --git a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.cc b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.cc new file mode 100644 index 000000000..886f98913 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.cc @@ -0,0 +1,288 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,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 <cstdio> +#include <cmath> + +#include <gr_pfb_clock_sync_fff.h> +#include <gr_fir_fff.h> +#include <gr_fir_util.h> +#include <gr_io_signature.h> +#include <gr_math.h> + +gr_pfb_clock_sync_fff_sptr gr_make_pfb_clock_sync_fff (double sps, float gain, + const std::vector<float> &taps, + unsigned int filter_size, + float init_phase, + float max_rate_deviation) +{ + return gnuradio::get_initial_sptr(new gr_pfb_clock_sync_fff (sps, gain, taps, + filter_size, + init_phase, + max_rate_deviation)); +} + +static int ios[] = {sizeof(float), sizeof(float), sizeof(float), sizeof(float)}; +static std::vector<int> iosig(ios, ios+sizeof(ios)/sizeof(int)); +gr_pfb_clock_sync_fff::gr_pfb_clock_sync_fff (double sps, float gain, + const std::vector<float> &taps, + unsigned int filter_size, + float init_phase, + float max_rate_deviation) + : gr_block ("pfb_clock_sync_fff", + gr_make_io_signature (1, 1, sizeof(float)), + gr_make_io_signaturev (1, 4, iosig)), + d_updated (false), d_nfilters(filter_size), + d_max_dev(max_rate_deviation) +{ + d_nfilters = filter_size; + d_sps = floor(sps); + + // Store the last filter between calls to work + // The accumulator keeps track of overflow to increment the stride correctly. + // set it here to the fractional difference based on the initial phaes + set_alpha(gain); + set_beta(0.25*gain*gain); + d_k = init_phase; + d_rate = (sps-floor(sps))*(double)d_nfilters; + d_rate_i = (int)floor(d_rate); + d_rate_f = d_rate - (float)d_rate_i; + d_filtnum = (int)floor(d_k); + + d_filters = std::vector<gr_fir_fff*>(d_nfilters); + d_diff_filters = std::vector<gr_fir_fff*>(d_nfilters); + + // Create an FIR filter for each channel and zero out the taps + std::vector<float> vtaps(0, d_nfilters); + for(int i = 0; i < d_nfilters; i++) { + d_filters[i] = gr_fir_util::create_gr_fir_fff(vtaps); + d_diff_filters[i] = gr_fir_util::create_gr_fir_fff(vtaps); + } + + // Now, actually set the filters' taps + std::vector<float> dtaps; + create_diff_taps(taps, dtaps); + set_taps(taps, d_taps, d_filters); + set_taps(dtaps, d_dtaps, d_diff_filters); +} + +gr_pfb_clock_sync_fff::~gr_pfb_clock_sync_fff () +{ + for(int i = 0; i < d_nfilters; i++) { + delete d_filters[i]; + delete d_diff_filters[i]; + } +} + +bool +gr_pfb_clock_sync_fff::check_topology(int ninputs, int noutputs) +{ + return noutputs == 1 || noutputs == 4; +} + +void +gr_pfb_clock_sync_fff::set_taps (const std::vector<float> &newtaps, + std::vector< std::vector<float> > &ourtaps, + std::vector<gr_fir_fff*> &ourfilter) +{ + int i,j; + + unsigned int ntaps = newtaps.size(); + d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_nfilters); + + // Create d_numchan vectors to store each channel's taps + ourtaps.resize(d_nfilters); + + // Make a vector of the taps plus fill it out with 0's to fill + // each polyphase filter with exactly d_taps_per_filter + std::vector<float> tmp_taps; + tmp_taps = newtaps; + while((float)(tmp_taps.size()) < d_nfilters*d_taps_per_filter) { + tmp_taps.push_back(0.0); + } + + // Partition the filter + for(i = 0; i < d_nfilters; i++) { + // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out + ourtaps[d_nfilters-1-i] = std::vector<float>(d_taps_per_filter, 0); + for(j = 0; j < d_taps_per_filter; j++) { + ourtaps[d_nfilters - 1 - i][j] = tmp_taps[i + j*d_nfilters]; + } + + // Build a filter for each channel and add it's taps to it + ourfilter[i]->set_taps(ourtaps[d_nfilters-1-i]); + } + + // Set the history to ensure enough input items for each filter + set_history (d_taps_per_filter + d_sps); + + d_updated = true; +} + +void +gr_pfb_clock_sync_fff::create_diff_taps(const std::vector<float> &newtaps, + std::vector<float> &difftaps) +{ + float maxtap = 1e-20; + difftaps.clear(); + difftaps.push_back(0); //newtaps[0]); + for(unsigned int i = 1; i < newtaps.size()-1; i++) { + float tap = newtaps[i+1] - newtaps[i-1]; + difftaps.push_back(tap); + if(tap > maxtap) { + maxtap = tap; + } + } + difftaps.push_back(0);//-newtaps[newtaps.size()-1]); + + // Scale the differential taps; helps scale error term to better update state + // FIXME: should this be scaled this way or use the same gain as the taps? + for(unsigned int i = 0; i < difftaps.size(); i++) { + difftaps[i] /= maxtap; + } +} + +void +gr_pfb_clock_sync_fff::print_taps() +{ + int i, j; + printf("[ "); + for(i = 0; i < d_nfilters; i++) { + printf("[%.4e, ", d_taps[i][0]); + for(j = 1; j < d_taps_per_filter-1; j++) { + printf("%.4e,", d_taps[i][j]); + } + printf("%.4e],", d_taps[i][j]); + } + printf(" ]\n"); +} + +void +gr_pfb_clock_sync_fff::print_diff_taps() +{ + int i, j; + printf("[ "); + for(i = 0; i < d_nfilters; i++) { + printf("[%.4e, ", d_dtaps[i][0]); + for(j = 1; j < d_taps_per_filter-1; j++) { + printf("%.4e,", d_dtaps[i][j]); + } + printf("%.4e],", d_dtaps[i][j]); + } + printf(" ]\n"); +} + + +std::vector<float> +gr_pfb_clock_sync_fff::channel_taps(int channel) +{ + std::vector<float> taps; + for(int i = 0; i < d_taps_per_filter; i++) { + taps.push_back(d_taps[channel][i]); + } + return taps; +} + +std::vector<float> +gr_pfb_clock_sync_fff::diff_channel_taps(int channel) +{ + std::vector<float> taps; + for(int i = 0; i < d_taps_per_filter; i++) { + taps.push_back(d_dtaps[channel][i]); + } + return taps; +} + + +int +gr_pfb_clock_sync_fff::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float *in = (float *) input_items[0]; + float *out = (float *) output_items[0]; + + float *err = 0, *outrate = 0, *outk = 0; + if(output_items.size() == 4) { + err = (float *) output_items[1]; + outrate = (float*)output_items[2]; + outk = (float*)output_items[3]; + } + + if (d_updated) { + d_updated = false; + return 0; // history requirements may have changed. + } + + // We need this many to process one output + int nrequired = ninput_items[0] - d_taps_per_filter; + + int i = 0, count = 0; + float error; + + // produce output as long as we can and there are enough input samples + while((i < noutput_items) && (count < nrequired)) { + d_filtnum = (int)floor(d_k); + + // Keep the current filter number in [0, d_nfilters] + // If we've run beyond the last filter, wrap around and go to next sample + // If we've go below 0, wrap around and go to previous sample + while(d_filtnum >= d_nfilters) { + d_k -= d_nfilters; + d_filtnum -= d_nfilters; + count += 1; + } + while(d_filtnum < 0) { + d_k += d_nfilters; + d_filtnum += d_nfilters; + count -= 1; + } + + out[i] = d_filters[d_filtnum]->filter(&in[count]); + float diff = d_diff_filters[d_filtnum]->filter(&in[count]); + error = out[i] * diff; + + // Run the control loop to update the current phase (k) and tracking rate + d_k = d_k + d_alpha*error + d_rate_i + d_rate_f; + d_rate_f = d_rate_f + d_beta*error; + + // Keep our rate within a good range + d_rate_f = gr_branchless_clip(d_rate_f, d_max_dev); + + i++; + count += (int)floor(d_sps); + + if(output_items.size() == 4) { + err[i] = error; + outrate[i] = d_rate_f; + outk[i] = d_k; + } + } + consume_each(count); + + return i; +} diff --git a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.h b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.h new file mode 100644 index 000000000..4909d556b --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.h @@ -0,0 +1,266 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,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_PFB_CLOCK_SYNC_FFF_H +#define INCLUDED_GR_PFB_CLOCK_SYNC_FFF_H + +#include <gr_core_api.h> +#include <gr_block.h> + +class gr_pfb_clock_sync_fff; +typedef boost::shared_ptr<gr_pfb_clock_sync_fff> gr_pfb_clock_sync_fff_sptr; +GR_CORE_API gr_pfb_clock_sync_fff_sptr gr_make_pfb_clock_sync_fff (double sps, float gain, + const std::vector<float> &taps, + unsigned int filter_size=32, + float init_phase=0, + float max_rate_deviation=1.5); + +class gr_fir_fff; + +/*! + * \class gr_pfb_clock_sync_fff + * + * \brief Timing synchronizer using polyphase filterbanks + * + * \ingroup filter_blk + * \ingroup pfb_blk + * + * This block performs timing synchronization for PAM signals by + * minimizing the derivative of the filtered signal, which in turn + * maximizes the SNR and minimizes ISI. + * + * This approach works by setting up two filterbanks; one filterbank + * contains the signal's pulse shaping matched filter (such as a root + * raised cosine filter), where each branch of the filterbank contains + * a different phase of the filter. The second filterbank contains + * the derivatives of the filters in the first filterbank. Thinking of + * this in the time domain, the first filterbank contains filters that + * have a sinc shape to them. We want to align the output signal to be + * sampled at exactly the peak of the sinc shape. The derivative of + * the sinc contains a zero at the maximum point of the sinc (sinc(0) + * = 1, sinc(0)' = 0). Furthermore, the region around the zero point + * is relatively linear. We make use of this fact to generate the + * error signal. + * + * If the signal out of the derivative filters is d_i[n] for the ith + * filter, and the output of the matched filter is x_i[n], we + * calculate the error as: e[n] = (Re{x_i[n]} * Re{d_i[n]} + + * Im{x_i[n]} * Im{d_i[n]}) / 2.0 This equation averages the error in + * the real and imaginary parts. There are two reasons we multiply by + * the signal itself. First, if the symbol could be positive or + * negative going, but we want the error term to always tell us to go + * in the same direction depending on which side of the zero point we + * are on. The sign of x_i[n] adjusts the error term to do + * this. Second, the magnitude of x_i[n] scales the error term + * depending on the symbol's amplitude, so larger signals give us a + * stronger error term because we have more confidence in that + * symbol's value. Using the magnitude of x_i[n] instead of just the + * sign is especially good for signals with low SNR. + * + * The error signal, e[n], gives us a value proportional to how far + * away from the zero point we are in the derivative signal. We want + * to drive this value to zero, so we set up a second order loop. We + * have two variables for this loop; d_k is the filter number in the + * filterbank we are on and d_rate is the rate which we travel through + * the filters in the steady state. That is, due to the natural clock + * differences between the transmitter and receiver, d_rate represents + * that difference and would traverse the filter phase paths to keep + * the receiver locked. Thinking of this as a second-order PLL, the + * d_rate is the frequency and d_k is the phase. So we update d_rate + * and d_k using the standard loop equations based on two error + * signals, d_alpha and d_beta. We have these two values set based on + * each other for a critically damped system, so in the block + * constructor, we just ask for "gain," which is d_alpha while d_beta + * is equal to (gain^2)/4. + * + * The block's parameters are: + * + * \li \p sps: The clock sync block needs to know the number of samples per + * symbol, because it defaults to return a single point representing + * the symbol. The sps can be any positive real number and does not + * need to be an integer. + * + * \li \p loop_bw: The loop bandwidth is used to set the gain of the + * inner control loop (see: + * http://gnuradio.squarespace.com/blog/2011/8/13/control-loop-gain-values.html). + * This should be set small (a value of around 2pi/100 is suggested in + * that blog post as the step size for the number of radians around + * the unit circle to move relative to the error). + * + * \li \p taps: One of the most important parameters for this block is + * the taps of the filter. One of the benefits of this algorithm is + * that you can put the matched filter in here as the taps, so you get + * both the matched filter and sample timing correction in one go. So + * create your normal matched filter. For a typical digital + * modulation, this is a root raised cosine filter. The number of taps + * of this filter is based on how long you expect the channel to be; + * that is, how many symbols do you want to combine to get the current + * symbols energy back (there's probably a better way of stating + * that). It's usually 5 to 10 or so. That gives you your filter, but + * now we need to think about it as a filter with different phase + * profiles in each filter. So take this number of taps and multiply + * it by the number of filters. This is the number you would use to + * create your prototype filter. When you use this in the PFB + * filerbank, it segments these taps into the filterbanks in such a + * way that each bank now represents the filter at different phases, + * equally spaced at 2pi/N, where N is the number of filters. + * + * \li \p filter_size (default=32): The number of filters can also be + * set and defaults to 32. With 32 filters, you get a good enough + * resolution in the phase to produce very small, almost unnoticeable, + * ISI. Going to 64 filters can reduce this more, but after that + * there is very little gained for the extra complexity. + * + * \li \p init_phase (default=0): The initial phase is another + * settable parameter and refers to the filter path the algorithm + * initially looks at (i.e., d_k starts at init_phase). This value + * defaults to zero, but it might be useful to start at a different + * phase offset, such as the mid-point of the filters. + * + * \li \p max_rate_deviation (default=1.5): The next parameter is the + * max_rate_devitation, which defaults to 1.5. This is how far we + * allow d_rate to swing, positive or negative, from 0. Constraining + * the rate can help keep the algorithm from walking too far away to + * lock during times when there is no signal. + * + * \li \p osps: note that unlike the ccf version of this algorithm, + * this block does \a not have a setting for the number of output + * samples per symbol. This is mostly because it should not be + * necessary as the reason for having multiple output sps is to + * perform equalization and the equalizers will take in complex + * numbers in order to do magnitude and phase correction. + */ + +class GR_CORE_API gr_pfb_clock_sync_fff : public gr_block +{ + private: + /*! + * Build the polyphase filterbank timing synchronizer. + * \param sps (double) The number of samples per second in the incoming signal + * \param gain (float) The alpha gain of the control loop; beta = (gain^2)/4 by default. + * \param taps (vector<int>) The filter taps. + * \param filter_size (uint) The number of filters in the filterbank (default = 32). + * \param init_phase (float) The initial phase to look at, or which filter to start + * with (default = 0). + * \param max_rate_deviation (float) Distance from 0 d_rate can get (default = 1.5). + * + */ + friend GR_CORE_API gr_pfb_clock_sync_fff_sptr gr_make_pfb_clock_sync_fff (double sps, float gain, + const std::vector<float> &taps, + unsigned int filter_size, + float init_phase, + float max_rate_deviation); + + bool d_updated; + double d_sps; + double d_sample_num; + float d_alpha; + float d_beta; + int d_nfilters; + std::vector<gr_fir_fff*> d_filters; + std::vector<gr_fir_fff*> d_diff_filters; + std::vector< std::vector<float> > d_taps; + std::vector< std::vector<float> > d_dtaps; + float d_k; + float d_rate; + float d_rate_i; + float d_rate_f; + float d_max_dev; + int d_filtnum; + int d_taps_per_filter; + + /*! + * Build the polyphase filterbank timing synchronizer. + */ + gr_pfb_clock_sync_fff (double sps, float gain, + const std::vector<float> &taps, + unsigned int filter_size, + float init_phase, + float max_rate_deviation); + + void create_diff_taps(const std::vector<float> &newtaps, + std::vector<float> &difftaps); + +public: + ~gr_pfb_clock_sync_fff (); + + /*! + * Resets the filterbank's filter taps with the new prototype filter + */ + void set_taps (const std::vector<float> &taps, + std::vector< std::vector<float> > &ourtaps, + std::vector<gr_fir_fff*> &ourfilter); + + /*! + * Returns the taps of the matched filter + */ + std::vector<float> channel_taps(int channel); + + /*! + * Returns the taps in the derivative filter + */ + std::vector<float> diff_channel_taps(int channel); + + /*! + * Print all of the filterbank taps to screen. + */ + void print_taps(); + + /*! + * Print all of the filterbank taps of the derivative filter to screen. + */ + void print_diff_taps(); + + /*! + * Set the gain value alpha for the control loop + */ + void set_alpha(float alpha) + { + d_alpha = alpha; + } + + /*! + * Set the gain value beta for the control loop + */ + void set_beta(float beta) + { + d_beta = beta; + } + + /*! + * Set the maximum deviation from 0 d_rate can have + */ + void set_max_rate_deviation(float m) + { + d_max_dev = m; + } + + bool check_topology(int ninputs, int noutputs); + + 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 diff --git a/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.i b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.i new file mode 100644 index 000000000..754af1a87 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_clock_sync_fff.i @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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,pfb_clock_sync_fff); + +gr_pfb_clock_sync_fff_sptr gr_make_pfb_clock_sync_fff (double sps, float gain, + const std::vector<float> &taps, + unsigned int filter_size=32, + float init_phase=0, + float max_rate_deviation=1.5); + +class gr_pfb_clock_sync_fff : public gr_block +{ + private: + gr_pfb_clock_sync_fff (double sps, float gain, + const std::vector<float> &taps, + unsigned int filter_size, + float init_phase, + float max_rate_deviation); + + public: + ~gr_pfb_clock_sync_fff (); + + void set_taps (const std::vector<float> &taps, + std::vector< std::vector<float> > &ourtaps, + std::vector<gr_fir_fff*> &ourfilter); + + std::vector<float> channel_taps(int channel); + std::vector<float> diff_channel_taps(int channel); + void print_taps(); + void print_diff_taps(); + void set_alpha(float alpha); + void set_beta(float beta); + void set_max_rate_deviation(float m); +}; diff --git a/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.cc new file mode 100644 index 000000000..e563daa51 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.cc @@ -0,0 +1,176 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,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_pfb_decimator_ccf.h> +#include <gr_fir_ccf.h> +#include <gr_fir_util.h> +#include <gri_fft.h> +#include <gr_io_signature.h> +#include <gr_expj.h> +#include <cstdio> + +gr_pfb_decimator_ccf_sptr gr_make_pfb_decimator_ccf (unsigned int decim, + const std::vector<float> &taps, + unsigned int channel) +{ + return gnuradio::get_initial_sptr(new gr_pfb_decimator_ccf (decim, taps, channel)); +} + + +gr_pfb_decimator_ccf::gr_pfb_decimator_ccf (unsigned int decim, + const std::vector<float> &taps, + unsigned int channel) + : gr_sync_block ("pfb_decimator_ccf", + gr_make_io_signature (decim, decim, sizeof(gr_complex)), + gr_make_io_signature (1, 1, sizeof(gr_complex))), + d_updated (false) +{ + d_rate = decim; + d_filters = std::vector<gr_fir_ccf*>(d_rate); + d_chan = channel; + d_rotator = new gr_complex[d_rate]; + + // Create an FIR filter for each channel and zero out the taps + std::vector<float> vtaps(0, d_rate); + for(unsigned int i = 0; i < d_rate; i++) { + d_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps); + d_rotator[i] = gr_expj(i*2*M_PI*d_chan/d_rate); + } + + // Now, actually set the filters' taps + set_taps(taps); + + // Create the FFT to handle the output de-spinning of the channels + d_fft = new gri_fft_complex (d_rate, false); +} + +gr_pfb_decimator_ccf::~gr_pfb_decimator_ccf () +{ + delete d_fft; + for(unsigned int i = 0; i < d_rate; i++) { + delete d_filters[i]; + } +} + +void +gr_pfb_decimator_ccf::set_taps (const std::vector<float> &taps) +{ + unsigned int i,j; + + unsigned int ntaps = taps.size(); + d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_rate); + + // Create d_numchan vectors to store each channel's taps + d_taps.resize(d_rate); + + // Make a vector of the taps plus fill it out with 0's to fill + // each polyphase filter with exactly d_taps_per_filter + std::vector<float> tmp_taps; + tmp_taps = taps; + while((float)(tmp_taps.size()) < d_rate*d_taps_per_filter) { + tmp_taps.push_back(0.0); + } + + // Partition the filter + for(i = 0; i < d_rate; i++) { + // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out + d_taps[i] = std::vector<float>(d_taps_per_filter, 0); + for(j = 0; j < d_taps_per_filter; j++) { + d_taps[i][j] = tmp_taps[i + j*d_rate]; // add taps to channels in reverse order + } + + // Build a filter for each channel and add it's taps to it + d_filters[i]->set_taps(d_taps[i]); + } + + // Set the history to ensure enough input items for each filter + set_history (d_taps_per_filter); + + d_updated = true; +} + +void +gr_pfb_decimator_ccf::print_taps() +{ + unsigned int i, j; + for(i = 0; i < d_rate; i++) { + printf("filter[%d]: [", i); + for(j = 0; j < d_taps_per_filter; j++) { + printf(" %.4e", d_taps[i][j]); + } + printf("]\n\n"); + } +} + +#define ROTATEFFT + +int +gr_pfb_decimator_ccf::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gr_complex *in; + gr_complex *out = (gr_complex *) output_items[0]; + + if (d_updated) { + d_updated = false; + return 0; // history requirements may have changed. + } + + int i; + for(i = 0; i < noutput_items; i++) { + // Move through filters from bottom to top + out[i] = 0; + for(int j = d_rate-1; j >= 0; j--) { + // Take in the items from the first input stream to d_rate + in = (gr_complex*)input_items[d_rate - 1 - j]; + + // Filter current input stream from bottom filter to top + // The rotate them by expj(j*k*2pi/M) where M is the number of filters + // (the decimation rate) and k is the channel number to extract + + // This is the real math that goes on; we abuse the FFT to do this quickly + // for decimation rates > N where N is a small number (~5): + // out[i] += d_filters[j]->filter(&in[i])*gr_expj(j*d_chan*2*M_PI/d_rate); +#ifdef ROTATEFFT + d_fft->get_inbuf()[j] = d_filters[j]->filter(&in[i]); +#else + out[i] += d_filters[j]->filter(&in[i])*d_rotator[i]; +#endif + } + +#ifdef ROTATEFFT + // Perform the FFT to do the complex multiply despinning for all channels + d_fft->execute(); + + // Select only the desired channel out + out[i] = d_fft->get_outbuf()[d_chan]; +#endif + + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h new file mode 100644 index 000000000..a2b347ae2 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.h @@ -0,0 +1,150 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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_PFB_DECIMATOR_CCF_H +#define INCLUDED_GR_PFB_DECIMATOR_CCF_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_pfb_decimator_ccf; +typedef boost::shared_ptr<gr_pfb_decimator_ccf> gr_pfb_decimator_ccf_sptr; +GR_CORE_API gr_pfb_decimator_ccf_sptr gr_make_pfb_decimator_ccf (unsigned int decim, + const std::vector<float> &taps, + unsigned int channel=0); + +class gr_fir_ccf; +class gri_fft_complex; + +/*! + * \class gr_pfb_decimator_ccf + * \brief Polyphase filterbank bandpass decimator with gr_complex + * input, gr_complex output and float taps + * + * \ingroup filter_blk + * \ingroup pfb_blk + * + * This block takes in a signal stream and performs interger down- + * sampling (decimation) with a polyphase filterbank. The first input + * is the integer specifying how much to decimate by. The second + * input is a vector (Python list) of floating-point taps of the + * prototype filter. The third input specifies the channel to extract. + * By default, the zeroth channel is used, which is the baseband + * channel (first Nyquist zone). + * + * The <EM>channel</EM> parameter specifies which channel to use since + * this class is capable of bandpass decimation. Given a complex input + * stream at a sampling rate of <EM>fs</EM> and a decimation rate of + * <EM>decim</EM>, the input frequency domain is split into + * <EM>decim</EM> channels that represent the Nyquist zones. Using the + * polyphase filterbank, we can select any one of these channels to + * decimate. + * + * The output signal will be the basebanded and decimated signal from + * that channel. This concept is very similar to the PFB channelizer + * (see #gr_pfb_channelizer_ccf) where only a single channel is + * extracted at a time. + * + * The filter's taps should be based on the sampling rate before + * decimation. + * + * For example, using the GNU Radio's firdes utility to building + * filters, we build a low-pass filter with a sampling rate of + * <EM>fs</EM>, a 3-dB bandwidth of <EM>BW</EM> and a transition + * bandwidth of <EM>TB</EM>. We can also specify the out-of-band + * attenuation to use, <EM>ATT</EM>, and the filter window + * function (a Blackman-harris window in this case). The first input + * is the gain of the filter, which we specify here as unity. + * + * <B><EM>self._taps = gr.firdes.low_pass_2(1, fs, BW, TB, + * attenuation_dB=ATT, window=gr.firdes.WIN_BLACKMAN_hARRIS)</EM></B> + * + * The PFB decimator code takes the taps generated above and builds a + * set of filters. The set contains <EM>decim</EM> number of filters + * and each filter contains ceil(taps.size()/decim) number of taps. + * Each tap from the filter prototype is sequentially inserted into + * the next filter. When all of the input taps are used, the remaining + * filters in the filterbank are filled out with 0's to make sure each + * filter has the same number of taps. + * + * The theory behind this block can be found in Chapter 6 of + * the following book. + * + * <B><EM>f. harris, "Multirate Signal Processing for Communication + * Systems," Upper Saddle River, NJ: Prentice Hall, Inc. 2004.</EM></B> + */ + +class GR_CORE_API gr_pfb_decimator_ccf : public gr_sync_block +{ + private: + /*! + * Build the polyphase filterbank decimator. + * \param decim (unsigned integer) Specifies the decimation rate to use + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. + * \param channel (unsigned integer) Selects the channel to return [default=0]. + */ + friend GR_CORE_API gr_pfb_decimator_ccf_sptr gr_make_pfb_decimator_ccf (unsigned int decim, + const std::vector<float> &taps, + unsigned int channel); + + std::vector<gr_fir_ccf*> d_filters; + std::vector< std::vector<float> > d_taps; + gri_fft_complex *d_fft; + unsigned int d_rate; + unsigned int d_chan; + unsigned int d_taps_per_filter; + bool d_updated; + gr_complex *d_rotator; + + /*! + * Build the polyphase filterbank decimator. + * \param decim (unsigned integer) Specifies the decimation rate to use + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. + * \param channel (unsigned integer) Selects the channel to return [default=0]. + */ + gr_pfb_decimator_ccf (unsigned int decim, + const std::vector<float> &taps, + unsigned int channel); + +public: + ~gr_pfb_decimator_ccf (); + + /*! + * Resets the filterbank's filter taps with the new prototype filter + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. + */ + void set_taps (const std::vector<float> &taps); + + /*! + * Print all of the filterbank taps to screen. + */ + void print_taps(); + + //void set_channel (unsigned int channel); + + 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/filter/gr_pfb_decimator_ccf.i b/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.i new file mode 100644 index 000000000..e40d00fa9 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_decimator_ccf.i @@ -0,0 +1,41 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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,pfb_decimator_ccf); + +gr_pfb_decimator_ccf_sptr gr_make_pfb_decimator_ccf (unsigned int decim, + const std::vector<float> &taps, + unsigned int channel); + +class gr_pfb_decimator_ccf : public gr_sync_block +{ + private: + gr_pfb_decimator_ccf (unsigned int decim, + const std::vector<float> &taps, + unsigned int channel); + + public: + ~gr_pfb_decimator_ccf (); + + void set_taps (const std::vector<float> &taps); + //void set_channel (unsigned int channel); +}; diff --git a/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.cc new file mode 100644 index 000000000..9c8e734ea --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.cc @@ -0,0 +1,143 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,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_pfb_interpolator_ccf.h> +#include <gr_fir_ccf.h> +#include <gr_fir_util.h> +#include <gr_io_signature.h> +#include <cstdio> + +gr_pfb_interpolator_ccf_sptr gr_make_pfb_interpolator_ccf (unsigned int interp, + const std::vector<float> &taps) +{ + return gnuradio::get_initial_sptr(new gr_pfb_interpolator_ccf (interp, taps)); +} + + +gr_pfb_interpolator_ccf::gr_pfb_interpolator_ccf (unsigned int interp, + const std::vector<float> &taps) + : gr_sync_interpolator ("pfb_interpolator_ccf", + gr_make_io_signature (1, 1, sizeof(gr_complex)), + gr_make_io_signature (1, 1, sizeof(gr_complex)), + interp), + d_updated (false) +{ + d_rate = interp; + d_filters = std::vector<gr_fir_ccf*>(d_rate); + + // Create an FIR filter for each channel and zero out the taps + std::vector<float> vtaps(0, d_rate); + for(unsigned int i = 0; i < d_rate; i++) { + d_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps); + } + + // Now, actually set the filters' taps + set_taps(taps); +} + +gr_pfb_interpolator_ccf::~gr_pfb_interpolator_ccf () +{ + for(unsigned int i = 0; i < d_rate; i++) { + delete d_filters[i]; + } +} + +void +gr_pfb_interpolator_ccf::set_taps (const std::vector<float> &taps) +{ + unsigned int i,j; + + unsigned int ntaps = taps.size(); + d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_rate); + + // Create d_numchan vectors to store each channel's taps + //std::vector< std::vector<float> > vtaps(d_rate); + d_taps.resize(d_rate); + + // Make a vector of the taps plus fill it out with 0's to fill + // each polyphase filter with exactly d_taps_per_filter + std::vector<float> tmp_taps; + tmp_taps = taps; + while((float)(tmp_taps.size()) < d_rate*d_taps_per_filter) { + tmp_taps.push_back(0.0); + } + + // Partition the filter + for(i = 0; i < d_rate; i++) { + // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out + d_taps[i] = std::vector<float>(d_taps_per_filter, 0); + for(j = 0; j < d_taps_per_filter; j++) { + d_taps[i][j] = tmp_taps[i + j*d_rate]; // add taps to channels in reverse order + } + + // Build a filter for each channel and add it's taps to it + d_filters[i]->set_taps(d_taps[i]); + } + + // Set the history to ensure enough input items for each filter + set_history (d_taps_per_filter); + + d_updated = true; +} + +void +gr_pfb_interpolator_ccf::print_taps() +{ + unsigned int i, j; + for(i = 0; i < d_rate; i++) { + printf("filter[%d]: [", i); + for(j = 0; j < d_taps_per_filter; j++) { + printf(" %.4e", d_taps[i][j]); + } + printf("]\n\n"); + } +} + +int +gr_pfb_interpolator_ccf::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gr_complex *in = (gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + if (d_updated) { + d_updated = false; + return 0; // history requirements may have changed. + } + + int i = 0, count = 0; + + while(i < noutput_items) { + for(unsigned int j = 0; j < d_rate; j++) { + out[i] = d_filters[j]->filter(&in[count]); + i++; + } + count++; + } + + return i; +} diff --git a/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h new file mode 100644 index 000000000..aeae86e40 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.h @@ -0,0 +1,131 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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_PFB_INTERPOLATOR_CCF_H +#define INCLUDED_GR_PFB_INTERPOLATOR_CCF_H + +#include <gr_core_api.h> +#include <gr_sync_interpolator.h> + +class gr_pfb_interpolator_ccf; +typedef boost::shared_ptr<gr_pfb_interpolator_ccf> gr_pfb_interpolator_ccf_sptr; +GR_CORE_API gr_pfb_interpolator_ccf_sptr gr_make_pfb_interpolator_ccf (unsigned int interp, + const std::vector<float> &taps); + +class gr_fir_ccf; + +/*! + * \class gr_pfb_interpolator_ccf + * \brief Polyphase filterbank interpolator with gr_complex input, + * gr_complex output and float taps + * + * \ingroup filter_blk + * \ingroup pfb_blk + * + * This block takes in a signal stream and performs interger up- + * sampling (interpolation) with a polyphase filterbank. The first + * input is the integer specifying how much to interpolate by. The + * second input is a vector (Python list) of floating-point taps of + * the prototype filter. + * + * The filter's taps should be based on the interpolation rate + * specified. That is, the bandwidth specified is relative to the + * bandwidth after interpolation. + * + * For example, using the GNU Radio's firdes utility to building + * filters, we build a low-pass filter with a sampling rate of + * <EM>fs</EM>, a 3-dB bandwidth of <EM>BW</EM> and a transition + * bandwidth of <EM>TB</EM>. We can also specify the out-of-band + * attenuation to use, ATT, and the filter window function (a + * Blackman-harris window in this case). The first input is the gain, + * which is also specified as the interpolation rate so that the + * output levels are the same as the input (this creates an overall + * increase in power). + * + * <B><EM>self._taps = gr.firdes.low_pass_2(interp, interp*fs, BW, TB, + * attenuation_dB=ATT, window=gr.firdes.WIN_BLACKMAN_hARRIS)</EM></B> + * + * The PFB interpolator code takes the taps generated above and builds + * a set of filters. The set contains <EM>interp</EM> number of + * filters and each filter contains ceil(taps.size()/interp) number of + * taps. Each tap from the filter prototype is sequentially inserted + * into the next filter. When all of the input taps are used, the + * remaining filters in the filterbank are filled out with 0's to make + * sure each filter has the same number of taps. + * + * The theory behind this block can be found in Chapter 7.1 of the + * following book. + * + * <B><EM>f. harris, "Multirate Signal Processing for Communication + * Systems</EM>," Upper Saddle River, NJ: Prentice Hall, + * Inc. 2004.</EM></B> + */ + +class GR_CORE_API gr_pfb_interpolator_ccf : public gr_sync_interpolator +{ + private: + /*! + * Build the polyphase filterbank interpolator. + * \param interp (unsigned integer) Specifies the interpolation rate to use + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps + * should be generated at the interpolated sampling rate. + */ + friend GR_CORE_API gr_pfb_interpolator_ccf_sptr gr_make_pfb_interpolator_ccf (unsigned int interp, + const std::vector<float> &taps); + + std::vector<gr_fir_ccf*> d_filters; + std::vector< std::vector<float> > d_taps; + unsigned int d_rate; + unsigned int d_taps_per_filter; + bool d_updated; + + /*! + * Construct a Polyphase filterbank interpolator + * \param interp (unsigned integer) Specifies the interpolation rate to use + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps + * should be generated at the interpolated sampling rate. + */ + gr_pfb_interpolator_ccf (unsigned int interp, + const std::vector<float> &taps); + +public: + ~gr_pfb_interpolator_ccf (); + + /*! + * Resets the filterbank's filter taps with the new prototype filter + * \param taps (vector/list of floats) The prototype filter to populate the filterbank. The taps + * should be generated at the interpolated sampling rate. + */ + void set_taps (const std::vector<float> &taps); + + /*! + * Print all of the filterbank taps to screen. + */ + void print_taps(); + + 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/filter/gr_pfb_interpolator_ccf.i b/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.i new file mode 100644 index 000000000..427f1b913 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_interpolator_ccf.i @@ -0,0 +1,39 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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,pfb_interpolator_ccf); + +gr_pfb_interpolator_ccf_sptr gr_make_pfb_interpolator_ccf (unsigned int interp, + const std::vector<float> &taps); + +class gr_pfb_interpolator_ccf : public gr_sync_interpolator +{ + private: + gr_pfb_interpolator_ccf (unsigned int interp, + const std::vector<float> &taps); + + public: + ~gr_pfb_interpolator_ccf (); + + void set_taps (const std::vector<float> &taps); + void print_taps(); +}; diff --git a/gnuradio-core/src/lib/filter/gr_pfb_synthesizer_ccf.cc b/gnuradio-core/src/lib/filter/gr_pfb_synthesizer_ccf.cc new file mode 100644 index 000000000..cd01aaff5 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_synthesizer_ccf.cc @@ -0,0 +1,287 @@ +/* -*- c++ -*- */ +/* + * Copyright 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 <gr_pfb_synthesizer_ccf.h> +#include <gri_fft.h> +#include <gr_io_signature.h> +#include <cstdio> +#include <cstring> + +gr_pfb_synthesizer_ccf_sptr gr_make_pfb_synthesizer_ccf + (unsigned int numchans, const std::vector<float> &taps, bool twox) +{ + return gr_pfb_synthesizer_ccf_sptr + (new gr_pfb_synthesizer_ccf (numchans, taps, twox)); +} + + +gr_pfb_synthesizer_ccf::gr_pfb_synthesizer_ccf + (unsigned int numchans, const std::vector<float> &taps, bool twox) + : gr_sync_interpolator ("pfb_synthesizer_ccf", + gr_make_io_signature (1, numchans, sizeof(gr_complex)), + gr_make_io_signature (1, 1, sizeof(gr_complex)), + numchans), + d_updated (false), d_numchans(numchans), d_state(0) +{ + // set up 2x multiplier; if twox==True, set to 2, otherwise to 1 + d_twox = (twox ? 2 : 1); + if(d_numchans % d_twox != 0) { + throw std::invalid_argument("gr_pfb_synthesizer_ccf: number of channels must be even for 2x oversampling.\n"); + } + + d_filters = std::vector<gri_fir_filter_with_buffer_ccf*>(d_twox*d_numchans); + d_channel_map.resize(d_twox*d_numchans); + + // Create an FIR filter for each channel and zero out the taps + std::vector<float> vtaps(0, d_twox*d_numchans); + for(unsigned int i = 0; i < d_twox*d_numchans; i++) { + d_filters[i] = new gri_fir_filter_with_buffer_ccf(vtaps); + d_channel_map[i] = i; + } + + // Now, actually set the filters' taps + set_taps(taps); + + // Create the IFFT to handle the input channel rotations + d_fft = new gri_fft_complex (d_twox*d_numchans, false); + memset(d_fft->get_inbuf(), 0, d_twox*d_numchans*sizeof(gr_complex)); + + set_output_multiple(d_numchans); +} + +gr_pfb_synthesizer_ccf::~gr_pfb_synthesizer_ccf () +{ + delete d_fft; + for(unsigned int i = 0; i < d_twox*d_numchans; i++) { + delete d_filters[i]; + } +} + +void +gr_pfb_synthesizer_ccf::set_taps(const std::vector<float> &taps) +{ + gruel::scoped_lock guard(d_mutex); + if(d_twox == 1) + set_taps1(taps); + else + set_taps2(taps); +} + +void +gr_pfb_synthesizer_ccf::set_taps1(const std::vector<float> &taps) +{ + unsigned int i,j; + + unsigned int ntaps = taps.size(); + d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_numchans); + + // Create d_numchan vectors to store each channel's taps + d_taps.resize(d_numchans); + + // Make a vector of the taps plus fill it out with 0's to fill + // each polyphase filter with exactly d_taps_per_filter + std::vector<float> tmp_taps; + tmp_taps = taps; + while((float)(tmp_taps.size()) < d_numchans*d_taps_per_filter) { + tmp_taps.push_back(0.0); + } + + // Partition the filter + for(i = 0; i < d_numchans; i++) { + // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out + d_taps[i] = std::vector<float>(d_taps_per_filter, 0); + for(j = 0; j < d_taps_per_filter; j++) { + d_taps[i][j] = tmp_taps[i + j*d_numchans]; // add taps to channels in reverse order + } + + // Build a filter for each channel and add it's taps to it + d_filters[i]->set_taps(d_taps[i]); + } + + // Set the history to ensure enough input items for each filter + set_history (d_taps_per_filter+1); + + d_updated = true; +} + +void +gr_pfb_synthesizer_ccf::set_taps2 (const std::vector<float> &taps) +{ + unsigned int i,j; + int state = 0; + + unsigned int ntaps = taps.size(); + d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_numchans); + + // Create d_numchan vectors to store each channel's taps + d_taps.resize(d_twox*d_numchans); + + // Make a vector of the taps plus fill it out with 0's to fill + // each polyphase filter with exactly d_taps_per_filter + std::vector<float> tmp_taps; + tmp_taps = taps; + while((float)(tmp_taps.size()) < d_numchans*d_taps_per_filter) { + tmp_taps.push_back(0.0); + } + + // Partition the filter + for(i = 0; i < d_numchans; i++) { + // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out + d_taps[i] = std::vector<float>(d_taps_per_filter, 0); + d_taps[d_numchans+i] = std::vector<float>(d_taps_per_filter, 0); + state = 0; + for(j = 0; j < d_taps_per_filter; j++) { + // add taps to channels in reverse order + // Zero out every other tap + if(state == 0) { + d_taps[i][j] = tmp_taps[i + j*d_numchans]; + d_taps[d_numchans + i][j] = 0; + state = 1; + } + else { + d_taps[i][j] = 0; + d_taps[d_numchans + i][j] = tmp_taps[i + j*d_numchans]; + state = 0; + } + } + + // Build a filter for each channel and add it's taps to it + d_filters[i]->set_taps(d_taps[i]); + d_filters[d_numchans + i]->set_taps(d_taps[d_numchans + i]); + } + + // Set the history to ensure enough input items for each filter + set_history (d_taps_per_filter+1); + + d_updated = true; +} + +void +gr_pfb_synthesizer_ccf::print_taps() +{ + unsigned int i, j; + for(i = 0; i < d_twox*d_numchans; i++) { + printf("filter[%d]: [", i); + for(j = 0; j < d_taps_per_filter; j++) { + printf(" %.4e", d_taps[i][j]); + } + printf("]\n\n"); + } +} + + +std::vector< std::vector<float> > +gr_pfb_synthesizer_ccf::taps() const +{ + return d_taps; +} + +void +gr_pfb_synthesizer_ccf::set_channel_map(const std::vector<int> &map) +{ + gruel::scoped_lock guard(d_mutex); + + if(map.size() > 0) { + unsigned int max = (unsigned int)*std::max_element(map.begin(), map.end()); + unsigned int min = (unsigned int)*std::min_element(map.begin(), map.end()); + if((max >= d_twox*d_numchans) || (min < 0)) { + throw std::invalid_argument("gr_pfb_synthesizer_ccf::set_channel_map: map range out of bounds.\n"); + } + d_channel_map = map; + + // Zero out fft buffer so that unused channels are always 0 + memset(d_fft->get_inbuf(), 0,d_twox*d_numchans*sizeof(gr_complex)); + } +} + +std::vector<int> +gr_pfb_synthesizer_ccf::channel_map() const +{ + return d_channel_map; +} + +int +gr_pfb_synthesizer_ccf::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gruel::scoped_lock guard(d_mutex); + + gr_complex *in = (gr_complex*) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + if (d_updated) { + d_updated = false; + return 0; // history requirements may have changed. + } + + unsigned int n, i; + size_t ninputs = input_items.size(); + + // Algoritm for critically sampled channels + if(d_twox == 1) { + for(n = 0; n < noutput_items/d_numchans; n++) { + for(i = 0; i < ninputs; i++) { + in = (gr_complex*)input_items[i]; + d_fft->get_inbuf()[d_channel_map[i]] = in[n]; + } + + // spin through IFFT + d_fft->execute(); + + for(i = 0; i < d_numchans; i++) { + out[i] = d_filters[i]->filter(d_fft->get_outbuf()[i]); + } + out += d_numchans; + } + } + + // Algorithm for oversampling by 2x + else { + for(n = 0; n < noutput_items/d_numchans; n++) { + for(i = 0; i < ninputs; i++) { + in = (gr_complex*)input_items[i]; + d_fft->get_inbuf()[d_channel_map[i]] = in[n]; + } + + // spin through IFFT + d_fft->execute(); + + // Output is sum of two filters, but the input buffer to the filters must be circularly + // shifted by numchans every time through, done by using d_state to determine which IFFT + // buffer position to pull from. + for(i = 0; i < d_numchans; i++) { + out[i] = d_filters[i]->filter(d_fft->get_outbuf()[d_state*d_numchans+i]); + out[i] += d_filters[d_numchans+i]->filter(d_fft->get_outbuf()[(d_state^1)*d_numchans+i]); + } + d_state ^= 1; + + out += d_numchans; + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/filter/gr_pfb_synthesizer_ccf.h b/gnuradio-core/src/lib/filter/gr_pfb_synthesizer_ccf.h new file mode 100644 index 000000000..9e4f85497 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_synthesizer_ccf.h @@ -0,0 +1,147 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + + +#ifndef INCLUDED_GR_PFB_SYNTHESIZER_CCF_H +#define INCLUDED_GR_PFB_SYNTHESIZER_CCF_H + +#include <gr_core_api.h> +#include <gr_sync_interpolator.h> +#include <gri_fir_filter_with_buffer_ccf.h> +#include <gruel/thread.h> + +class gr_pfb_synthesizer_ccf; +typedef boost::shared_ptr<gr_pfb_synthesizer_ccf> gr_pfb_synthesizer_ccf_sptr; +GR_CORE_API gr_pfb_synthesizer_ccf_sptr gr_make_pfb_synthesizer_ccf + (unsigned int numchans, const std::vector<float> &taps, bool twox=false); + +class gri_fft_complex; + + +/*! + * \class gr_pfb_synthesizer_ccf + * + * \brief Polyphase synthesis filterbank with + * gr_complex input, gr_complex output and float taps + * + * \ingroup filter_blk + * \ingroup pfb_blk + */ + +class GR_CORE_API gr_pfb_synthesizer_ccf : public gr_sync_interpolator +{ + private: + /*! + * Build the polyphase synthesis filterbank. + * \param numchans (unsigned integer) Specifies the number of + channels <EM>M</EM> + * \param taps (vector/list of floats) The prototype filter to + populate the filterbank. + * \param twox (bool) use 2x oversampling or not (default is no) + */ + friend GR_CORE_API gr_pfb_synthesizer_ccf_sptr gr_make_pfb_synthesizer_ccf + (unsigned int numchans, const std::vector<float> &taps, bool twox); + + bool d_updated; + unsigned int d_numchans; + unsigned int d_taps_per_filter; + gri_fft_complex *d_fft; + std::vector< gri_fir_filter_with_buffer_ccf*> d_filters; + std::vector< std::vector<float> > d_taps; + int d_state; + std::vector<int> d_channel_map; + unsigned int d_twox; + gruel::mutex d_mutex; // mutex to protect set/work access + + /*! + * \brief Tap setting algorithm for critically sampled channels + */ + void set_taps1(const std::vector<float> &taps); + + /*! + * \brief Tap setting algorithm for 2x over-sampled channels + */ + void set_taps2(const std::vector<float> &taps); + + /*! + * Build the polyphase synthesis filterbank. + * \param numchans (unsigned integer) Specifies the number of + channels <EM>M</EM> + * \param taps (vector/list of floats) The prototype filter + to populate the filterbank. + * \param twox (bool) use 2x oversampling or not (default is no) + */ + gr_pfb_synthesizer_ccf (unsigned int numchans, + const std::vector<float> &taps, + bool twox); + +public: + ~gr_pfb_synthesizer_ccf (); + + /*! + * Resets the filterbank's filter taps with the new prototype filter + * \param taps (vector/list of floats) The prototype filter to + populate the filterbank. + */ + void set_taps (const std::vector<float> &taps); + + /*! + * Print all of the filterbank taps to screen. + */ + void print_taps(); + + /*! + * Return a vector<vector<>> of the filterbank taps + */ + std::vector<std::vector<float> > taps() const; + + /*! + * Set the channel map. Channels are numbers as: + * N/2+1 | ... | N-1 | 0 | 1 | 2 | ... | N/2 + * <------------------- 0 --------------------> + * freq + * + * So input stream 0 goes to channel 0, etc. Setting a new channel + * map allows the user to specify where in frequency he/she wants + * the input stream to go. This is especially useful to avoid + * putting signals into the channels on the edge of the spectrum + * which can either wrap around (in the case of odd number of + * channels) and be affected by filter rolloff in the transmitter. + * + * The map must be at least the number of streams being sent to the + * block. Less and the algorithm will not have enough data to + * properly setup the buffers. Any more channels specified will be + * ignored. + */ + void set_channel_map(const std::vector<int> &map); + + /*! + * Gets the current channel map. + */ + std::vector<int> channel_map() const; + + 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/filter/gr_pfb_synthesizer_ccf.i b/gnuradio-core/src/lib/filter/gr_pfb_synthesizer_ccf.i new file mode 100644 index 000000000..c186ae355 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_pfb_synthesizer_ccf.i @@ -0,0 +1,44 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,pfb_synthesizer_ccf); + +gr_pfb_synthesizer_ccf_sptr gr_make_pfb_synthesizer_ccf + (unsigned int numchans, const std::vector<float> &taps, bool twox=false); + +class gr_pfb_synthesizer_ccf : public gr_sync_interpolator +{ + private: + gr_pfb_synthesizer_ccf (unsigned int numchans, + const std::vector<float> &taps, + bool twox=false); + + public: + ~gr_pfb_synthesizer_ccf (); + + void set_taps (const std::vector<float> &taps); + void print_taps(); + std::vector< std::vector<float> > taps() const; + + void set_channel_map(const std::vector<int> &map); + std::vector<int> channel_map() const; +}; diff --git a/gnuradio-core/src/lib/filter/gr_rational_resampler_base_XXX.cc.t b/gnuradio-core/src/lib/filter/gr_rational_resampler_base_XXX.cc.t new file mode 100644 index 000000000..445834dda --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_rational_resampler_base_XXX.cc.t @@ -0,0 +1,172 @@ +/* -*- 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: This file is automatically generated by + * generate_gr_rational_resampler_base_XXX.py Any changes made to this + * file will be overwritten. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <@FIR_TYPE@.h> +#include <gr_fir_util.h> +#include <gr_io_signature.h> +#include <stdexcept> +#include <iostream> + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (unsigned interpolation, + unsigned decimation, + const std::vector<@TAP_TYPE@> &taps) +{ + return gnuradio::get_initial_sptr (new @NAME@ (interpolation, decimation, taps)); +} + +@NAME@::@NAME@ (unsigned interpolation, unsigned decimation, + const std::vector<@TAP_TYPE@> &taps) + : gr_block ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))), + d_history(1), + d_interpolation(interpolation), d_decimation(decimation), + d_ctr(0), d_updated(false), + d_firs(interpolation) +{ + if (interpolation == 0) + throw std::out_of_range ("interpolation must be > 0"); + if (decimation == 0) + throw std::out_of_range ("decimation must be > 0"); + + set_relative_rate (1.0 * interpolation / decimation); + set_output_multiple (1); + + std::vector<@TAP_TYPE@> dummy_taps; + + for (unsigned i = 0; i < interpolation; i++) + d_firs[i] = gr_fir_util::create_@FIR_TYPE@ (dummy_taps); + + set_taps (taps); + install_taps (d_new_taps); +} + +@NAME@::~@NAME@ () +{ + int interp = interpolation(); + for (int i = 0; i < interp; i++) + delete d_firs[i]; +} + +void +@NAME@::set_taps (const std::vector<@TAP_TYPE@> &taps) +{ + d_new_taps = taps; + d_updated = true; + + // round up length to a multiple of the interpolation factor + int n = taps.size () % interpolation (); + if (n > 0){ + n = interpolation () - n; + while (n-- > 0) + d_new_taps.insert(d_new_taps.begin(), 0); + } + + assert (d_new_taps.size () % interpolation () == 0); +} + + +void +@NAME@::install_taps (const std::vector<@TAP_TYPE@> &taps) +{ + int nfilters = interpolation (); + int nt = taps.size () / nfilters; + + assert (nt * nfilters == (int) taps.size ()); + + std::vector< std::vector <@TAP_TYPE@> > xtaps (nfilters); + + for (int n = 0; n < nfilters; n++) + xtaps[n].resize (nt); + + for (int i = 0; i < (int) taps.size(); i++) + xtaps[i % nfilters][i / nfilters] = taps[i]; + + for (int n = 0; n < nfilters; n++) + d_firs[n]->set_taps (xtaps[n]); + + set_history (nt); + d_updated = false; + +#if 0 + for (int i = 0; i < nfilters; i++){ + std::cout << "filter[" << i << "] = "; + for (int j = 0; j < nt; j++) + std::cout << xtaps[i][j] << " "; + + std::cout << "\n"; + } +#endif + +} + +void +@NAME@::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + int nreqd = std::max((unsigned)1, (int)((double) (noutput_items+1) * decimation() / interpolation()) + history() - 1); + unsigned ninputs = ninput_items_required.size (); + for (unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = nreqd; +} + +int +@NAME@::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const @I_TYPE@ *in = (const @I_TYPE@ *) input_items[0]; + @O_TYPE@ *out = (@O_TYPE@ *) output_items[0]; + + if (d_updated) { + install_taps (d_new_taps); + return 0; // history requirement may have increased. + } + + unsigned int ctr = d_ctr; + + int i = 0; + while (i < noutput_items){ + out[i++] = d_firs[ctr]->filter(in); + ctr += decimation(); + while (ctr >= interpolation()){ + ctr -= interpolation(); + in++; + } + } + + d_ctr = ctr; + consume_each(in - (@I_TYPE@ *) input_items[0]); + return i; +} diff --git a/gnuradio-core/src/lib/filter/gr_rational_resampler_base_XXX.h.t b/gnuradio-core/src/lib/filter/gr_rational_resampler_base_XXX.h.t new file mode 100644 index 000000000..3eb85a979 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_rational_resampler_base_XXX.h.t @@ -0,0 +1,88 @@ +/* -*- 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. + */ + +/* + * WARNING: This file is automatically generated by + * generate_gr_rational_resampler_base_XXX.py Any changes made to this + * file will be overwritten. + */ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_core_api.h> +#include <gr_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; +GR_CORE_API @SPTR_NAME@ +gr_make_@BASE_NAME@ (unsigned interpolation, + unsigned decimation, + const std::vector<@TAP_TYPE@> &taps); + +class @FIR_TYPE@; + +/*! + * \brief Rational Resampling Polyphase FIR filter with @I_TYPE@ input, @O_TYPE@ output and @TAP_TYPE@ taps + * \ingroup filter_blk + */ +class GR_CORE_API @NAME@ : public gr_block +{ + private: + unsigned d_history; + unsigned d_interpolation, d_decimation; + unsigned d_ctr; + std::vector<@TAP_TYPE@> d_new_taps; + bool d_updated; + std::vector<@FIR_TYPE@ *> d_firs; + + friend GR_CORE_API @SPTR_NAME@ + gr_make_@BASE_NAME@ (unsigned interpolation, unsigned decimation, const std::vector<@TAP_TYPE@> &taps); + + + /*! + * Construct a FIR filter with the given taps + */ + @NAME@ (unsigned interpolation, unsigned decimation, + const std::vector<@TAP_TYPE@> &taps); + + void install_taps (const std::vector<@TAP_TYPE@> &taps); + + public: + ~@NAME@ (); + unsigned history () const { return d_history; } + void set_history (unsigned history) { d_history = history; } + + unsigned interpolation() const { return d_interpolation; } + unsigned decimation() const { return d_decimation; } + + void set_taps (const std::vector<@TAP_TYPE@> &taps); + + 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 diff --git a/gnuradio-core/src/lib/filter/gr_rational_resampler_base_XXX.i.t b/gnuradio-core/src/lib/filter/gr_rational_resampler_base_XXX.i.t new file mode 100644 index 000000000..1f789b0a3 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_rational_resampler_base_XXX.i.t @@ -0,0 +1,42 @@ +/* -*- 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. + */ + +/* + * WARNING: This file is automatically generated by + * generate_gr_rational_resampler_base_XXX.py Any changes made to this + * file will be overwritten. + */ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@); + +@SPTR_NAME@ gr_make_@BASE_NAME@ (int interpolation, int decimation, const std::vector<@TAP_TYPE@> &taps); + +class @NAME@ : public gr_block +{ + private: + @NAME@ (int interpolation, int decimation, const std::vector<@TAP_TYPE@> &taps); + + public: + ~@NAME@ (); + + void set_taps (const std::vector<@TAP_TYPE@> &taps); +}; diff --git a/gnuradio-core/src/lib/filter/gr_rotator.h b/gnuradio-core/src/lib/filter/gr_rotator.h new file mode 100644 index 000000000..e31be6ee6 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_rotator.h @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,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 _GR_ROTATOR_H_ +#define _GR_ROTATOR_H_ + +#include <gr_core_api.h> +#include <gr_complex.h> + +class GR_CORE_API gr_rotator { + gr_complex d_phase; + gr_complex d_phase_incr; + unsigned int d_counter; + + public: + gr_rotator () : d_phase (1), d_phase_incr (1), d_counter(0) { } + + void set_phase (gr_complex phase) { d_phase = phase / abs(phase); } + void set_phase_incr (gr_complex incr) { d_phase_incr = incr / abs(incr); } + + gr_complex rotate (gr_complex in){ + d_counter++; + + gr_complex z = in * d_phase; // rotate in by phase + d_phase *= d_phase_incr; // incr our phase (complex mult == add phases) + + if ((d_counter % 512) == 0) + d_phase /= abs(d_phase); // Normalize to ensure multiplication is rotation + + return z; + } + +}; + +#endif /* _GR_ROTATOR_H_ */ diff --git a/gnuradio-core/src/lib/filter/gr_sincos.c b/gnuradio-core/src/lib/filter/gr_sincos.c new file mode 100644 index 000000000..a8d01b0da --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_sincos.c @@ -0,0 +1,83 @@ +/* -*- 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 + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE // ask for GNU extensions if available +#endif + +#include <gr_sincos.h> +#include <math.h> + +// ---------------------------------------------------------------- + +#if defined (HAVE_SINCOS) + +void +gr_sincos (double x, double *sinx, double *cosx) +{ + sincos (x, sinx, cosx); +} + +#else + +void +gr_sincos (double x, double *sinx, double *cosx) +{ + *sinx = sin (x); + *cosx = cos (x); +} + +#endif + +// ---------------------------------------------------------------- + +#if defined (HAVE_SINCOSF) + +void +gr_sincosf (float x, float *sinx, float *cosx) +{ + sincosf (x, sinx, cosx); +} + +#elif defined (HAVE_SINF) && defined (HAVE_COSF) + +void +gr_sincosf (float x, float *sinx, float *cosx) +{ + *sinx = sinf (x); + *cosx = cosf (x); +} + +#else + +void +gr_sincosf (float x, float *sinx, float *cosx) +{ + *sinx = sin (x); + *cosx = cos (x); +} + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_sincos.h b/gnuradio-core/src/lib/filter/gr_sincos.h new file mode 100644 index 000000000..516f43437 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_sincos.h @@ -0,0 +1,41 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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_SINCOS_H +#define INCLUDED_GR_SINCOS_H + +#include <gr_core_api.h> + +#ifdef __cplusplus +extern "C" { +#endif + +// compute sine and cosine at the same time + +GR_CORE_API void gr_sincos (double x, double *sin, double *cos); +GR_CORE_API void gr_sincosf (float x, float *sin, float *cos); + +#ifdef __cplusplus +}; +#endif + +#endif /* INCLUDED_GR_SINCOS_H */ diff --git a/gnuradio-core/src/lib/filter/gr_single_pole_iir.h b/gnuradio-core/src/lib/filter/gr_single_pole_iir.h new file mode 100644 index 000000000..d73ee857d --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_iir.h @@ -0,0 +1,191 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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 _GR_SINGLE_POLE_IIR_H_ +#define _GR_SINGLE_POLE_IIR_H_ + +#include <gr_core_api.h> +#include <stdexcept> +#include <gr_complex.h> +/*! + * \brief class template for single pole IIR filter + */ +template<class o_type, class i_type, class tap_type> +class gr_single_pole_iir { +public: + /*! + * \brief construct new single pole IIR with given alpha + * + * computes y(i) = (1-alpha) * y(i-1) + alpha * x(i) + */ + gr_single_pole_iir (tap_type alpha = 1.0) + { + d_prev_output = 0; + set_taps (alpha); + } + + /*! + * \brief compute a single output value. + * \returns the filtered input value. + */ + o_type filter (const i_type input); + + /*! + * \brief compute an array of N output values. + * \p input must have n valid entries. + */ + void filterN (o_type output[], const i_type input[], unsigned long n); + + /*! + * \brief install \p alpha as the current taps. + */ + void set_taps (tap_type alpha) + { + if (alpha < 0 || alpha > 1) + throw std::out_of_range ("Alpha must be in [0, 1]\n"); + + d_alpha = alpha; + d_one_minus_alpha = 1.0 - alpha; + } + + //! reset state to zero + void reset () + { + d_prev_output = 0; + } + + o_type prev_output () const { return d_prev_output; } + +protected: + tap_type d_alpha; + tap_type d_one_minus_alpha; + o_type d_prev_output; +}; + + +// +// general case. We may want to specialize this +// +template<class o_type, class i_type, class tap_type> +o_type +gr_single_pole_iir<o_type, i_type, tap_type>::filter (const i_type input) +{ + o_type output; + + output = d_alpha * input + d_one_minus_alpha * d_prev_output; + d_prev_output = output; + + return (o_type) output; +} + + +template<class o_type, class i_type, class tap_type> +void +gr_single_pole_iir<o_type, i_type, tap_type>::filterN (o_type output[], + const i_type input[], + unsigned long n) +{ + for (unsigned i = 0; i < n; i++) + output[i] = filter (input[i]); +} + + +// +// Specialized case for gr_complex output and double taps +// We need to have a gr_complexd type for the calculations and prev_output variable (in stead of double) + +template<class i_type> +class gr_single_pole_iir<gr_complex, i_type, double> { +public: + /*! + * \brief construct new single pole IIR with given alpha + * + * computes y(i) = (1-alpha) * y(i-1) + alpha * x(i) + */ + gr_single_pole_iir (double alpha = 1.0) + { + d_prev_output = 0; + set_taps (alpha); + } + + /*! + * \brief compute a single output value. + * \returns the filtered input value. + */ + gr_complex filter (const i_type input); + + /*! + * \brief compute an array of N output values. + * \p input must have n valid entries. + */ + void filterN (gr_complex output[], const i_type input[], unsigned long n); + + /*! + * \brief install \p alpha as the current taps. + */ + void set_taps (double alpha) + { + if (alpha < 0 || alpha > 1) + throw std::out_of_range ("Alpha must be in [0, 1]\n"); + + d_alpha = alpha; + d_one_minus_alpha = 1.0 - alpha; + } + + //! reset state to zero + void reset () + { + d_prev_output = 0; + } + + gr_complexd prev_output () const { return d_prev_output; } + +protected: + double d_alpha; + double d_one_minus_alpha; + gr_complexd d_prev_output; +}; + +template< class i_type> +gr_complex +gr_single_pole_iir<gr_complex, i_type, double>::filter (const i_type input) +{ + gr_complexd output; + + output = d_alpha * (gr_complexd)input + d_one_minus_alpha * d_prev_output; + d_prev_output = output; + + return (gr_complex) output; +} + +//Do we need to specialize this, although it is the same as the general case? + +template<class i_type> +void +gr_single_pole_iir<gr_complex, i_type, double>::filterN (gr_complex output[], + const i_type input[], + unsigned long n) +{ + for (unsigned i = 0; i < n; i++) + output[i] = filter (input[i]); +} + +#endif /* _GR_SINGLE_POLE_IIR_H_ */ diff --git a/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_cc.cc b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_cc.cc new file mode 100644 index 000000000..ae4f654dd --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_cc.cc @@ -0,0 +1,81 @@ +/* -*- 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_single_pole_iir_filter_cc.h> +#include <gr_io_signature.h> +#include <stdio.h> + + +gr_single_pole_iir_filter_cc_sptr +gr_make_single_pole_iir_filter_cc (double alpha, unsigned int vlen) +{ + return gnuradio::get_initial_sptr(new gr_single_pole_iir_filter_cc(alpha, vlen)); +} + +gr_single_pole_iir_filter_cc::gr_single_pole_iir_filter_cc ( + double alpha, unsigned int vlen) + : gr_sync_block ("single_pole_iir_filter_cc", + gr_make_io_signature (1, 1, sizeof (gr_complex) * vlen), + gr_make_io_signature (1, 1, sizeof (gr_complex) * vlen)), + d_vlen(vlen), d_iir(vlen) +{ + set_taps(alpha); +} + +gr_single_pole_iir_filter_cc::~gr_single_pole_iir_filter_cc () +{ + // nop +} + +void +gr_single_pole_iir_filter_cc::set_taps (double alpha) +{ + for (unsigned int i = 0; i < d_vlen; i++) + d_iir[i].set_taps(alpha); +} + +int +gr_single_pole_iir_filter_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]; + unsigned int vlen = d_vlen; + + if (d_vlen == 1){ + for (int i = 0; i < noutput_items; i++) + out[i] = d_iir[0].filter (in[i]); + } + else { + for (int i = 0; i < noutput_items; i++){ + for (unsigned int j = 0; j < vlen; j++){ + *out++ = d_iir[j].filter (*in++); + } + } + } + return noutput_items; +}; diff --git a/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_cc.h b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_cc.h new file mode 100644 index 000000000..13c595826 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_cc.h @@ -0,0 +1,88 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_SINGLE_POLE_IIR_FILTER_CC_H +#define INCLUDED_GR_SINGLE_POLE_IIR_FILTER_CC_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_single_pole_iir.h> +#include <gr_complex.h> +#include <stdexcept> + +class gr_single_pole_iir_filter_cc; +typedef boost::shared_ptr<gr_single_pole_iir_filter_cc> gr_single_pole_iir_filter_cc_sptr; + +GR_CORE_API gr_single_pole_iir_filter_cc_sptr +gr_make_single_pole_iir_filter_cc (double alpha, unsigned int vlen=1); + +/*! + * \brief single pole IIR filter with complex input, complex output + * \ingroup filter_blk + * + * The input and output satisfy a difference equation of the form + \htmlonly + \f{ + y[n] - (1-alpha) y[n-1] = alpha x[n] + \f} + \endhtmlonly + + \xmlonly + y[n] - (1-alpha) y[n-1] = alpha x[n] + \endxmlonly + + * with the corresponding rational system function + \htmlonly + \f{ + H(z) = \frac{alpha}{1 - (1-alpha) z^{-1}} + \f} + \endhtmlonly + + \xmlonly + H(z) = \ frac{alpha}{1 - (1-alpha) z^{-1}} + \endxmlonly + + * Note that some texts define the system function with a + in the denominator. + * If you're using that convention, you'll need to negate the feedback tap. + */ +class GR_CORE_API gr_single_pole_iir_filter_cc : public gr_sync_block +{ + private: + friend GR_CORE_API gr_single_pole_iir_filter_cc_sptr + gr_make_single_pole_iir_filter_cc (double alpha, unsigned int vlen); + + unsigned int d_vlen; + std::vector<gr_single_pole_iir<gr_complex,gr_complex,double> > d_iir; + + gr_single_pole_iir_filter_cc (double alpha, unsigned int vlen); + + public: + ~gr_single_pole_iir_filter_cc (); + + void set_taps (double alpha); + + 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/filter/gr_single_pole_iir_filter_cc.i b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_cc.i new file mode 100644 index 000000000..2f1f285de --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_cc.i @@ -0,0 +1,34 @@ +/* -*- 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,single_pole_iir_filter_cc); + +gr_single_pole_iir_filter_cc_sptr +gr_make_single_pole_iir_filter_cc (double alpha, unsigned int vlen=1); + +class gr_single_pole_iir_filter_cc : public gr_sync_block +{ + public: + ~gr_single_pole_iir_filter_cc (); + + void set_taps (double alpha); +}; diff --git a/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_ff.cc b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_ff.cc new file mode 100644 index 000000000..047b2ba25 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_ff.cc @@ -0,0 +1,81 @@ +/* -*- 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_single_pole_iir_filter_ff.h> +#include <gr_io_signature.h> +#include <stdio.h> + + +gr_single_pole_iir_filter_ff_sptr +gr_make_single_pole_iir_filter_ff (double alpha, unsigned int vlen) +{ + return gnuradio::get_initial_sptr(new gr_single_pole_iir_filter_ff(alpha, vlen)); +} + +gr_single_pole_iir_filter_ff::gr_single_pole_iir_filter_ff ( + double alpha, unsigned int vlen) + : gr_sync_block ("single_pole_iir_filter_ff", + gr_make_io_signature (1, 1, sizeof (float) * vlen), + gr_make_io_signature (1, 1, sizeof (float) * vlen)), + d_vlen(vlen), d_iir(vlen) +{ + set_taps(alpha); +} + +gr_single_pole_iir_filter_ff::~gr_single_pole_iir_filter_ff () +{ + // nop +} + +void +gr_single_pole_iir_filter_ff::set_taps (double alpha) +{ + for (unsigned int i = 0; i < d_vlen; i++) + d_iir[i].set_taps(alpha); +} + +int +gr_single_pole_iir_filter_ff::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]; + unsigned int vlen = d_vlen; + + if (d_vlen == 1){ + for (int i = 0; i < noutput_items; i++) + out[i] = d_iir[0].filter (in[i]); + } + else { + for (int i = 0; i < noutput_items; i++){ + for (unsigned int j = 0; j < vlen; j++){ + *out++ = d_iir[j].filter (*in++); + } + } + } + return noutput_items; +}; diff --git a/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_ff.h b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_ff.h new file mode 100644 index 000000000..8dcdad2c9 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_ff.h @@ -0,0 +1,87 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_SINGLE_POLE_IIR_FILTER_FF_H +#define INCLUDED_GR_SINGLE_POLE_IIR_FILTER_FF_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_single_pole_iir.h> +#include <stdexcept> + +class gr_single_pole_iir_filter_ff; +typedef boost::shared_ptr<gr_single_pole_iir_filter_ff> gr_single_pole_iir_filter_ff_sptr; + +GR_CORE_API gr_single_pole_iir_filter_ff_sptr +gr_make_single_pole_iir_filter_ff (double alpha, unsigned int vlen=1); + +/*! + * \brief single pole IIR filter with float input, float output + * \ingroup filter_blk + * + * The input and output satisfy a difference equation of the form + \htmlonly + \f{ + y[n] - (1-alpha) y[n-1] = alpha x[n] + \f} + \endhtmlonly + + \xmlonly + y[n] - (1-alpha) y[n-1] = alpha x[n] + \endxmlonly + + * with the corresponding rational system function + \htmlonly + \f{ + H(z) = \frac{alpha}{1 - (1-alpha) z^{-1}} + \f} + \endhtmlonly + + \xmlonly +H(z) = \ frac{alpha}{1 - (1-alpha) z^{-1}} + \endxmlonly + + * Note that some texts define the system function with a + in the denominator. + * If you're using that convention, you'll need to negate the feedback tap. + */ +class GR_CORE_API gr_single_pole_iir_filter_ff : public gr_sync_block +{ + private: + friend GR_CORE_API gr_single_pole_iir_filter_ff_sptr + gr_make_single_pole_iir_filter_ff (double alpha, unsigned int vlen); + + unsigned int d_vlen; + std::vector<gr_single_pole_iir<float,float,double> > d_iir; + + gr_single_pole_iir_filter_ff (double alpha, unsigned int vlen); + + public: + ~gr_single_pole_iir_filter_ff (); + + void set_taps (double alpha); + + 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/filter/gr_single_pole_iir_filter_ff.i b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_ff.i new file mode 100644 index 000000000..a835fabb2 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_ff.i @@ -0,0 +1,34 @@ +/* -*- 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,single_pole_iir_filter_ff); + +gr_single_pole_iir_filter_ff_sptr +gr_make_single_pole_iir_filter_ff (double alpha, unsigned int vlen=1); + +class gr_single_pole_iir_filter_ff : public gr_sync_block +{ + public: + ~gr_single_pole_iir_filter_ff (); + + void set_taps (double alpha); +}; diff --git a/gnuradio-core/src/lib/filter/gr_vec_types.h b/gnuradio-core/src/lib/filter/gr_vec_types.h new file mode 100644 index 000000000..2bcec44bf --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_vec_types.h @@ -0,0 +1,54 @@ +/* Cell single token vector types + Copyright (C) 2007 Free Software Foundation, Inc. + + This file is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This file 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 this file; see the file COPYING. If not, write to the Free + Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301, USA. */ + +/* As a special exception, if you include this header file into source files + compiled by GCC, this header file does not by itself cause the resulting + executable to be covered by the GNU General Public License. This exception + does not however invalidate any other reasons why the executable file might be + covered by the GNU General Public License. */ + +/* Single token vector data types for the PowerPC SIMD/Vector Multi-media + eXtension */ + +#ifndef INCLUDED_GR_VEC_TYPES_H +#define INCLUDED_GR_VEC_TYPES_H + +#define qword __vector unsigned char + +#define vec_uchar16 __vector unsigned char +#define vec_char16 __vector signed char +#define vec_bchar16 __vector bool char + +#define vec_ushort8 __vector unsigned short +#define vec_short8 __vector signed short +#define vec_bshort8 __vector bool short + +#define vec_pixel8 __vector pixel + +#define vec_uint4 __vector unsigned int +#define vec_int4 __vector signed int +#define vec_bint4 __vector bool int + +#define vec_float4 __vector float + +#define vec_ullong2 __vector bool char +#define vec_llong2 __vector bool short + +#define vec_double2 __vector bool int + +#endif /* INCLUDED_GR_VEC_TYPES_H */ diff --git a/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.cc b/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.cc new file mode 100644 index 000000000..e958c5061 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.cc @@ -0,0 +1,184 @@ +/* -*- c++ -*- */ +/* + * Copyright 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 <gri_fft_filter_ccc_generic.h> +#include <gri_fft.h> +#include <volk/volk.h> +#include <assert.h> +#include <stdexcept> +#include <cstdio> +#include <cstring> +#include <fftw3.h> + +gri_fft_filter_ccc_generic::gri_fft_filter_ccc_generic (int decimation, + const std::vector<gr_complex> &taps, + int nthreads) + : d_fftsize(-1), d_decimation(decimation), d_fwdfft(0), d_invfft(0), d_nthreads(nthreads) +{ + set_taps(taps); +} + +gri_fft_filter_ccc_generic::~gri_fft_filter_ccc_generic () +{ + delete d_fwdfft; + delete d_invfft; + gri_fft_free(d_xformed_taps); +} + +#if 0 +static void +print_vector_complex(const std::string label, const std::vector<gr_complex> &x) +{ + std::cout << label; + for (unsigned i = 0; i < x.size(); i++) + std::cout << x[i] << " "; + std::cout << "\n"; +} +#endif + + +/* + * determines d_ntaps, d_nsamples, d_fftsize, d_xformed_taps + */ +int +gri_fft_filter_ccc_generic::set_taps (const std::vector<gr_complex> &taps) +{ + int i = 0; + compute_sizes(taps.size()); + + d_tail.resize(tailsize()); + for (i = 0; i < tailsize(); i++) + d_tail[i] = 0; + + gr_complex *in = d_fwdfft->get_inbuf(); + gr_complex *out = d_fwdfft->get_outbuf(); + + float scale = 1.0 / d_fftsize; + + // Compute forward xform of taps. + // Copy taps into first ntaps slots, then pad with zeros + for (i = 0; i < d_ntaps; i++) + in[i] = taps[i] * scale; + + for (; i < d_fftsize; i++) + in[i] = 0; + + d_fwdfft->execute(); // do the xform + + // now copy output to d_xformed_taps + for (i = 0; i < d_fftsize; i++) + d_xformed_taps[i] = out[i]; + + return d_nsamples; +} + +// determine and set d_ntaps, d_nsamples, d_fftsize + +void +gri_fft_filter_ccc_generic::compute_sizes(int ntaps) +{ + int old_fftsize = d_fftsize; + d_ntaps = ntaps; + d_fftsize = (int) (2 * pow(2.0, ceil(log(double(ntaps)) / log(2.0)))); + d_nsamples = d_fftsize - d_ntaps + 1; + + if (0) + fprintf(stderr, "gri_fft_filter_ccc_generic: ntaps = %d, fftsize = %d, nsamples = %d\n", + d_ntaps, d_fftsize, d_nsamples); + + assert(d_fftsize == d_ntaps + d_nsamples -1 ); + + if (d_fftsize != old_fftsize){ // compute new plans + delete d_fwdfft; + delete d_invfft; + d_fwdfft = new gri_fft_complex(d_fftsize, true, d_nthreads); + d_invfft = new gri_fft_complex(d_fftsize, false, d_nthreads); + d_xformed_taps = gri_fft_malloc_complex(d_fftsize); + } +} + +void +gri_fft_filter_ccc_generic::set_nthreads(int n) +{ + d_nthreads = n; + if(d_fwdfft) + d_fwdfft->set_nthreads(n); + if(d_invfft) + d_invfft->set_nthreads(n); +} + +int +gri_fft_filter_ccc_generic::nthreads() const +{ + return d_nthreads; +} + +int +gri_fft_filter_ccc_generic::filter (int nitems, const gr_complex *input, gr_complex *output) +{ + int dec_ctr = 0; + int j = 0; + int ninput_items = nitems * d_decimation; + + for (int i = 0; i < ninput_items; i += d_nsamples){ + + memcpy(d_fwdfft->get_inbuf(), &input[i], d_nsamples * sizeof(gr_complex)); + + for (j = d_nsamples; j < d_fftsize; j++) + d_fwdfft->get_inbuf()[j] = 0; + + d_fwdfft->execute(); // compute fwd xform + + gr_complex *a = d_fwdfft->get_outbuf(); + gr_complex *b = d_xformed_taps; + gr_complex *c = d_invfft->get_inbuf(); + + volk_32fc_x2_multiply_32fc_a(c, a, b, d_fftsize); + + d_invfft->execute(); // compute inv xform + + // add in the overlapping tail + + for (j = 0; j < tailsize(); j++) + d_invfft->get_outbuf()[j] += d_tail[j]; + + // copy nsamples to output + j = dec_ctr; + while (j < d_nsamples) { + *output++ = d_invfft->get_outbuf()[j]; + j += d_decimation; + } + dec_ctr = (j - d_nsamples); + + // stash the tail + memcpy(&d_tail[0], d_invfft->get_outbuf() + d_nsamples, + tailsize() * sizeof(gr_complex)); + } + + assert(dec_ctr == 0); + + return nitems; +} diff --git a/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.h b/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.h new file mode 100644 index 000000000..648c2b8c5 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.h @@ -0,0 +1,96 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_GRI_FFT_FILTER_CCC_GENERIC_H +#define INCLUDED_GRI_FFT_FILTER_CCC_GENERIC_H + +#include <gr_core_api.h> +#include <gr_complex.h> +#include <vector> + +class gri_fft_complex; + +/*! + * \brief Fast FFT filter with gr_complex input, gr_complex output and gr_complex taps + * \ingroup filter_blk + */ +class GR_CORE_API gri_fft_filter_ccc_generic +{ + private: + int d_ntaps; + int d_nsamples; + int d_fftsize; // fftsize = ntaps + nsamples - 1 + int d_decimation; + gri_fft_complex *d_fwdfft; // forward "plan" + gri_fft_complex *d_invfft; // inverse "plan" + int d_nthreads; // number of FFTW threads to use + std::vector<gr_complex> d_tail; // state carried between blocks for overlap-add + std::vector<gr_complex> d_new_taps; + gr_complex *d_xformed_taps; // Fourier xformed taps + + void compute_sizes(int ntaps); + int tailsize() const { return d_ntaps - 1; } + + public: + /*! + * \brief Construct an FFT filter for complex vectors with the given taps and decimation rate. + * + * This is the basic implementation for performing FFT filter for fast convolution + * in other blocks for complex vectors (such as gr_fft_filter_ccc). + * \param decimation The decimation rate of the filter (int) + * \param taps The filter taps (complex) + * \param nthreads The number of threads for the FFT to use (int) + */ + gri_fft_filter_ccc_generic (int decimation, const std::vector<gr_complex> &taps, + int nthreads=1); + ~gri_fft_filter_ccc_generic (); + + /*! + * \brief Set new taps for the filter. + * + * Sets new taps and resets the class properties to handle different sizes + * \param taps The filter taps (complex) + */ + int set_taps (const std::vector<gr_complex> &taps); + + /*! + * \brief Set number of threads to use. + */ + void set_nthreads(int n); + + /*! + * \brief Get number of threads being used. + */ + int nthreads() const; + + /*! + * \brief Perform the filter operation + * + * \param nitems The number of items to produce + * \param input The input vector to be filtered + * \param output The result of the filter operation + */ + int filter (int nitems, const gr_complex *input, gr_complex *output); + +}; + +#endif /* INCLUDED_GRI_FFT_FILTER_CCC_GENERIC_H */ diff --git a/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_sse.cc b/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_sse.cc new file mode 100644 index 000000000..bfc939869 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_sse.cc @@ -0,0 +1,186 @@ +/* -*- c++ -*- */ +/* + * Copyright 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 <gri_fft_filter_ccc_sse.h> +#include <gri_fft.h> +#include <assert.h> +#include <stdexcept> +#include <cstdio> +#include <xmmintrin.h> +#include <fftw3.h> + +gri_fft_filter_ccc_sse::gri_fft_filter_ccc_sse (int decimation, + const std::vector<gr_complex> &taps) + : d_fftsize(-1), d_decimation(decimation), d_fwdfft(0), d_invfft(0) +{ + d_xformed_taps = (gr_complex*)fftwf_malloc(1*sizeof(gr_complex)); + set_taps(taps); +} + +gri_fft_filter_ccc_sse::~gri_fft_filter_ccc_sse () +{ + fftwf_free(d_xformed_taps); + delete d_fwdfft; + delete d_invfft; +} + +#if 0 +static void +print_vector_complex(const std::string label, const std::vector<gr_complex> &x) +{ + std::cout << label; + for (unsigned i = 0; i < x.size(); i++) + std::cout << x[i] << " "; + std::cout << "\n"; +} +#endif + + +/* + * determines d_ntaps, d_nsamples, d_fftsize, d_xformed_taps + */ +int +gri_fft_filter_ccc_sse::set_taps (const std::vector<gr_complex> &taps) +{ + int i = 0; + compute_sizes(taps.size()); + + d_tail.resize(tailsize()); + for (i = 0; i < tailsize(); i++) + d_tail[i] = 0; + + gr_complex *in = d_fwdfft->get_inbuf(); + gr_complex *out = d_fwdfft->get_outbuf(); + + float scale = 1.0 / d_fftsize; + + // Compute forward xform of taps. + // Copy taps into first ntaps slots, then pad with zeros + for (i = 0; i < d_ntaps; i++) + in[i] = taps[i] * scale; + + for (; i < d_fftsize; i++) + in[i] = 0; + + d_fwdfft->execute(); // do the xform + + // now copy output to d_xformed_taps + for (i = 0; i < d_fftsize; i++) + d_xformed_taps[i] = out[i]; + + return d_nsamples; +} + +// determine and set d_ntaps, d_nsamples, d_fftsize + +void +gri_fft_filter_ccc_sse::compute_sizes(int ntaps) +{ + int old_fftsize = d_fftsize; + d_ntaps = ntaps; + d_fftsize = (int) (2 * pow(2.0, ceil(log(ntaps) / log(2)))); + d_nsamples = d_fftsize - d_ntaps + 1; + + if (0) + fprintf(stderr, "gri_fft_filter_ccc_sse: ntaps = %d, fftsize = %d, nsamples = %d\n", + d_ntaps, d_fftsize, d_nsamples); + + assert(d_fftsize == d_ntaps + d_nsamples -1 ); + + if (d_fftsize != old_fftsize){ // compute new plans + delete d_fwdfft; + delete d_invfft; + d_fwdfft = new gri_fft_complex(d_fftsize, true); + d_invfft = new gri_fft_complex(d_fftsize, false); + + fftwf_free(d_xformed_taps); + d_xformed_taps = (gr_complex*)fftwf_malloc((d_fftsize)*sizeof(gr_complex)); + } +} + +int +gri_fft_filter_ccc_sse::filter (int nitems, const gr_complex *input, gr_complex *output) +{ + int dec_ctr = 0; + int j = 0; + int ninput_items = nitems * d_decimation; + + for (int i = 0; i < ninput_items; i += d_nsamples){ + + memcpy(d_fwdfft->get_inbuf(), &input[i], d_nsamples * sizeof(gr_complex)); + + for (j = d_nsamples; j < d_fftsize; j++) + d_fwdfft->get_inbuf()[j] = 0; + + d_fwdfft->execute(); // compute fwd xform + + float *a = (float*)(d_fwdfft->get_outbuf()); + float *b = (float*)(&d_xformed_taps[0]); + float *c = (float*)(d_invfft->get_inbuf()); + + __m128 x0, x1, x2, t0, t1, m; + m = _mm_set_ps(-1, 1, -1, 1); + for (j = 0; j < 2*d_fftsize; j+=4) { // filter in the freq domain + x0 = _mm_load_ps(&a[j]); + t0 = _mm_load_ps(&b[j]); + + t1 = _mm_shuffle_ps(t0, t0, _MM_SHUFFLE(3, 3, 1, 1)); + t0 = _mm_shuffle_ps(t0, t0, _MM_SHUFFLE(2, 2, 0, 0)); + t1 = _mm_mul_ps(t1, m); + + x1 = _mm_mul_ps(x0, t0); + x2 = _mm_mul_ps(x0, t1); + + x2 = _mm_shuffle_ps(x2, x2, _MM_SHUFFLE(2, 3, 0, 1)); + x2 = _mm_add_ps(x1, x2); + + _mm_store_ps(&c[j], x2); + } + + d_invfft->execute(); // compute inv xform + + // add in the overlapping tail + + for (j = 0; j < tailsize(); j++) + d_invfft->get_outbuf()[j] += d_tail[j]; + + // copy nsamples to output + j = dec_ctr; + while (j < d_nsamples) { + *output++ = d_invfft->get_outbuf()[j]; + j += d_decimation; + } + dec_ctr = (j - d_nsamples); + + // stash the tail + memcpy(&d_tail[0], d_invfft->get_outbuf() + d_nsamples, + tailsize() * sizeof(gr_complex)); + } + + assert(dec_ctr == 0); + + return nitems; +} diff --git a/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_sse.h b/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_sse.h new file mode 100644 index 000000000..64b8c0c15 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_sse.h @@ -0,0 +1,83 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_GRI_FFT_FILTER_CCC_SSE_H +#define INCLUDED_GRI_FFT_FILTER_CCC_SSE_H + +#include <gr_core_api.h> +#include <gr_complex.h> +#include <vector> + +class gri_fft_complex; + +/*! + * \brief Fast FFT filter with gr_complex input, gr_complex output and gr_complex taps + * \ingroup filter_blk + */ +class GR_CORE_API gri_fft_filter_ccc_sse +{ + private: + int d_ntaps; + int d_nsamples; + int d_fftsize; // fftsize = ntaps + nsamples - 1 + int d_decimation; + gri_fft_complex *d_fwdfft; // forward "plan" + gri_fft_complex *d_invfft; // inverse "plan" + std::vector<gr_complex> d_tail; // state carried between blocks for overlap-add + gr_complex *d_xformed_taps; + std::vector<gr_complex> d_new_taps; + + void compute_sizes(int ntaps); + int tailsize() const { return d_ntaps - 1; } + + public: + /*! + * \brief Construct an FFT filter for complex vectors with the given taps and decimation rate. + * + * This is the basic implementation for performing FFT filter for fast convolution + * in other blocks for complex vectors (such as gr_fft_filter_ccc). + * \param decimation The decimation rate of the filter (int) + * \param taps The filter taps (complex) + */ + gri_fft_filter_ccc_sse (int decimation, const std::vector<gr_complex> &taps); + ~gri_fft_filter_ccc_sse (); + + /*! + * \brief Set new taps for the filter. + * + * Sets new taps and resets the class properties to handle different sizes + * \param taps The filter taps (complex) + */ + int set_taps (const std::vector<gr_complex> &taps); + + /*! + * \brief Perform the filter operation + * + * \param nitems The number of items to produce + * \param input The input vector to be filtered + * \param output The result of the filter operation + */ + int filter (int nitems, const gr_complex *input, gr_complex *output); + +}; + +#endif /* INCLUDED_GRI_FFT_FILTER_CCC_SSE_H */ diff --git a/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.cc b/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.cc new file mode 100644 index 000000000..c6e923ee1 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.cc @@ -0,0 +1,175 @@ +/* -*- c++ -*- */ +/* + * Copyright 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 <gri_fft_filter_fff_generic.h> +#include <gri_fft.h> +#include <volk/volk.h> +#include <assert.h> +#include <stdexcept> +#include <cstdio> +#include <cstring> + +gri_fft_filter_fff_generic::gri_fft_filter_fff_generic (int decimation, + const std::vector<float> &taps, + int nthreads) + : d_fftsize(-1), d_decimation(decimation), d_fwdfft(0), d_invfft(0), d_nthreads(nthreads) +{ + set_taps(taps); +} + +gri_fft_filter_fff_generic::~gri_fft_filter_fff_generic () +{ + delete d_fwdfft; + delete d_invfft; + gri_fft_free(d_xformed_taps); +} + +/* + * determines d_ntaps, d_nsamples, d_fftsize, d_xformed_taps + */ +int +gri_fft_filter_fff_generic::set_taps (const std::vector<float> &taps) +{ + int i = 0; + compute_sizes(taps.size()); + + d_tail.resize(tailsize()); + for (i = 0; i < tailsize(); i++) + d_tail[i] = 0; + + float *in = d_fwdfft->get_inbuf(); + gr_complex *out = d_fwdfft->get_outbuf(); + + float scale = 1.0 / d_fftsize; + + // Compute forward xform of taps. + // Copy taps into first ntaps slots, then pad with zeros + for (i = 0; i < d_ntaps; i++) + in[i] = taps[i] * scale; + + for (; i < d_fftsize; i++) + in[i] = 0; + + d_fwdfft->execute(); // do the xform + + // now copy output to d_xformed_taps + for (i = 0; i < d_fftsize/2+1; i++) + d_xformed_taps[i] = out[i]; + + return d_nsamples; +} + +// determine and set d_ntaps, d_nsamples, d_fftsize + +void +gri_fft_filter_fff_generic::compute_sizes(int ntaps) +{ + int old_fftsize = d_fftsize; + d_ntaps = ntaps; + d_fftsize = (int) (2 * pow(2.0, ceil(log(double(ntaps)) / log(2.0)))); + d_nsamples = d_fftsize - d_ntaps + 1; + + if (0) + fprintf(stderr, "gri_fft_filter_fff_generic: ntaps = %d, fftsize = %d, nsamples = %d\n", + d_ntaps, d_fftsize, d_nsamples); + + assert(d_fftsize == d_ntaps + d_nsamples -1 ); + + if (d_fftsize != old_fftsize){ // compute new plans + delete d_fwdfft; + delete d_invfft; + d_fwdfft = new gri_fft_real_fwd(d_fftsize); + d_invfft = new gri_fft_real_rev(d_fftsize); + d_xformed_taps = gri_fft_malloc_complex(d_fftsize/2+1); + } +} + +void +gri_fft_filter_fff_generic::set_nthreads(int n) +{ + d_nthreads = n; + if(d_fwdfft) + d_fwdfft->set_nthreads(n); + if(d_invfft) + d_invfft->set_nthreads(n); +} + +int +gri_fft_filter_fff_generic::nthreads() const +{ + return d_nthreads; +} + +int +gri_fft_filter_fff_generic::filter (int nitems, const float *input, float *output) +{ + int dec_ctr = 0; + int j = 0; + int ninput_items = nitems * d_decimation; + + for (int i = 0; i < ninput_items; i += d_nsamples){ + + memcpy(d_fwdfft->get_inbuf(), &input[i], d_nsamples * sizeof(float)); + + for (j = d_nsamples; j < d_fftsize; j++) + d_fwdfft->get_inbuf()[j] = 0; + + d_fwdfft->execute(); // compute fwd xform + + gr_complex *a = d_fwdfft->get_outbuf(); + gr_complex *b = d_xformed_taps; + gr_complex *c = d_invfft->get_inbuf(); + + volk_32fc_x2_multiply_32fc_a(c, a, b, d_fftsize/2+1); + + d_invfft->execute(); // compute inv xform + + // add in the overlapping tail + + for (j = 0; j < tailsize(); j++) + d_invfft->get_outbuf()[j] += d_tail[j]; + + // copy nsamples to output + + //memcpy(out, d_invfft->get_outbuf(), d_nsamples * sizeof(float)); + //out += d_nsamples; + + j = dec_ctr; + while (j < d_nsamples) { + *output++ = d_invfft->get_outbuf()[j]; + j += d_decimation; + } + dec_ctr = (j - d_nsamples); + + // stash the tail + memcpy(&d_tail[0], d_invfft->get_outbuf() + d_nsamples, + tailsize() * sizeof(float)); + } + + assert(dec_ctr == 0); + + return nitems; +} diff --git a/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.h b/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.h new file mode 100644 index 000000000..528bf5dd7 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.h @@ -0,0 +1,94 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_GRI_FFT_FILTER_FFF_GENERIC_H +#define INCLUDED_GRI_FFT_FILTER_FFF_GENERIC_H + +#include <gr_core_api.h> +#include <gr_complex.h> +#include <vector> + +class gri_fft_real_fwd; +class gri_fft_real_rev; + +class GR_CORE_API gri_fft_filter_fff_generic +{ + private: + int d_ntaps; + int d_nsamples; + int d_fftsize; // fftsize = ntaps + nsamples - 1 + int d_decimation; + gri_fft_real_fwd *d_fwdfft; // forward "plan" + gri_fft_real_rev *d_invfft; // inverse "plan" + int d_nthreads; // number of FFTW threads to use + std::vector<float> d_tail; // state carried between blocks for overlap-add + std::vector<float> d_new_taps; + gr_complex *d_xformed_taps; // Fourier xformed taps + + + void compute_sizes(int ntaps); + int tailsize() const { return d_ntaps - 1; } + + public: + /*! + * \brief Construct a FFT filter for float vectors with the given taps and decimation rate. + * + * This is the basic implementation for performing FFT filter for fast convolution + * in other blocks for floating point vectors (such as gr_fft_filter_fff). + * \param decimation The decimation rate of the filter (int) + * \param taps The filter taps (float) + * \param nthreads The number of threads for the FFT to use (int) + */ + gri_fft_filter_fff_generic (int decimation, const std::vector<float> &taps, + int nthreads=1); + ~gri_fft_filter_fff_generic (); + + /*! + * \brief Set new taps for the filter. + * + * Sets new taps and resets the class properties to handle different sizes + * \param taps The filter taps (float) + */ + int set_taps (const std::vector<float> &taps); + + /*! + * \brief Set number of threads to use. + */ + void set_nthreads(int n); + + /*! + * \brief Get number of threads being used. + */ + int nthreads() const; + + /*! + * \brief Perform the filter operation + * + * \param nitems The number of items to produce + * \param input The input vector to be filtered + * \param output The result of the filter operation + */ + int filter (int nitems, const float *input, float *output); + +}; + +#endif /* INCLUDED_GRI_FFT_FILTER_FFF_GENERIC_H */ diff --git a/gnuradio-core/src/lib/filter/gri_fft_filter_fff_sse.cc b/gnuradio-core/src/lib/filter/gri_fft_filter_fff_sse.cc new file mode 100644 index 000000000..84fcfa438 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_fft_filter_fff_sse.cc @@ -0,0 +1,184 @@ +/* -*- c++ -*- */ +/* + * Copyright 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 <gri_fft_filter_fff_sse.h> +#include <gri_fft.h> +#include <assert.h> +#include <stdexcept> +#include <cstdio> +#include <xmmintrin.h> +#include <fftw3.h> + +gri_fft_filter_fff_sse::gri_fft_filter_fff_sse (int decimation, + const std::vector<float> &taps) + : d_fftsize(-1), d_decimation(decimation), d_fwdfft(0), d_invfft(0) +{ + d_xformed_taps = (gr_complex*)fftwf_malloc(1*sizeof(gr_complex)); + set_taps(taps); +} + +gri_fft_filter_fff_sse::~gri_fft_filter_fff_sse () +{ + fftwf_free(d_xformed_taps); + delete d_fwdfft; + delete d_invfft; +} + +/* + * determines d_ntaps, d_nsamples, d_fftsize, d_xformed_taps + */ +int +gri_fft_filter_fff_sse::set_taps (const std::vector<float> &taps) +{ + int i = 0; + compute_sizes(taps.size()); + + d_tail.resize(tailsize()); + for (i = 0; i < tailsize(); i++) + d_tail[i] = 0; + + float *in = d_fwdfft->get_inbuf(); + gr_complex *out = d_fwdfft->get_outbuf(); + + float scale = 1.0 / d_fftsize; + + // Compute forward xform of taps. + // Copy taps into first ntaps slots, then pad with zeros + for (i = 0; i < d_ntaps; i++) + in[i] = taps[i] * scale; + + for (; i < d_fftsize; i++) + in[i] = 0; + + d_fwdfft->execute(); // do the xform + + // now copy output to d_xformed_taps + for (i = 0; i < d_fftsize/2+1; i++) + d_xformed_taps[i] = out[i]; + + return d_nsamples; +} + +// determine and set d_ntaps, d_nsamples, d_fftsize + +void +gri_fft_filter_fff_sse::compute_sizes(int ntaps) +{ + int old_fftsize = d_fftsize; + d_ntaps = ntaps; + d_fftsize = (int) (2 * pow(2.0, ceil(log(ntaps) / log(2)))); + d_nsamples = d_fftsize - d_ntaps + 1; + + if (0) + fprintf(stderr, "gri_fft_filter_fff_sse: ntaps = %d, fftsize = %d, nsamples = %d\n", + d_ntaps, d_fftsize, d_nsamples); + + assert(d_fftsize == d_ntaps + d_nsamples -1 ); + + if (d_fftsize != old_fftsize){ // compute new plans + delete d_fwdfft; + delete d_invfft; + d_fwdfft = new gri_fft_real_fwd(d_fftsize); + d_invfft = new gri_fft_real_rev(d_fftsize); + //d_xformed_taps.resize(d_fftsize/2+1); + + fftwf_free(d_xformed_taps); + d_xformed_taps = (gr_complex*)fftwf_malloc((d_fftsize/2+1)*sizeof(gr_complex)); + } +} + +int +gri_fft_filter_fff_sse::filter (int nitems, const float *input, float *output) +{ + int dec_ctr = 0; + int j = 0; + int ninput_items = nitems * d_decimation; + + for (int i = 0; i < ninput_items; i += d_nsamples){ + + memcpy(d_fwdfft->get_inbuf(), &input[i], d_nsamples * sizeof(float)); + + for (j = d_nsamples; j < d_fftsize; j++) + d_fwdfft->get_inbuf()[j] = 0; + + d_fwdfft->execute(); // compute fwd xform + + float *a = (float*)(d_fwdfft->get_outbuf()); + float *b = (float*)(&d_xformed_taps[0]); + float *c = (float*)(d_invfft->get_inbuf()); + + __m128 x0, x1, x2, t0, t1, m; + m = _mm_set_ps(-1, 1, -1, 1); + for (j = 0; j < d_fftsize; j+=4) { // filter in the freq domain + x0 = _mm_load_ps(&a[j]); + t0 = _mm_load_ps(&b[j]); + + t1 = _mm_shuffle_ps(t0, t0, _MM_SHUFFLE(3, 3, 1, 1)); + t0 = _mm_shuffle_ps(t0, t0, _MM_SHUFFLE(2, 2, 0, 0)); + t1 = _mm_mul_ps(t1, m); + + x1 = _mm_mul_ps(x0, t0); + x2 = _mm_mul_ps(x0, t1); + + x2 = _mm_shuffle_ps(x2, x2, _MM_SHUFFLE(2, 3, 0, 1)); + x2 = _mm_add_ps(x1, x2); + + _mm_store_ps(&c[j], x2); + } + + // Finish off the last one; do the complex multiply as floats + j = d_fftsize/2; + c[j] = (a[j] * b[j]) - (a[j+1] * b[j+1]); + c[j+1] = (a[j] * b[j+1]) + (a[j+1] * b[j]); + + d_invfft->execute(); // compute inv xform + + // add in the overlapping tail + + for (j = 0; j < tailsize(); j++) + d_invfft->get_outbuf()[j] += d_tail[j]; + + // copy nsamples to output + + //memcpy(out, d_invfft->get_outbuf(), d_nsamples * sizeof(float)); + //out += d_nsamples; + + j = dec_ctr; + while (j < d_nsamples) { + *output++ = d_invfft->get_outbuf()[j]; + j += d_decimation; + } + dec_ctr = (j - d_nsamples); + + // stash the tail + memcpy(&d_tail[0], d_invfft->get_outbuf() + d_nsamples, + tailsize() * sizeof(float)); + } + + assert(dec_ctr == 0); + + return nitems; +} diff --git a/gnuradio-core/src/lib/filter/gri_fft_filter_fff_sse.h b/gnuradio-core/src/lib/filter/gri_fft_filter_fff_sse.h new file mode 100644 index 000000000..b6086562d --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_fft_filter_fff_sse.h @@ -0,0 +1,82 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_GRI_FFT_FILTER_FFF_SSE_H +#define INCLUDED_GRI_FFT_FILTER_FFF_SSE_H + +#include <gr_core_api.h> +#include <gr_complex.h> +#include <vector> + +class gri_fft_real_fwd; +class gri_fft_real_rev; + +class GR_CORE_API gri_fft_filter_fff_sse +{ + private: + int d_ntaps; + int d_nsamples; + int d_fftsize; // fftsize = ntaps + nsamples - 1 + int d_decimation; + gri_fft_real_fwd *d_fwdfft; // forward "plan" + gri_fft_real_rev *d_invfft; // inverse "plan" + std::vector<float> d_tail; // state carried between blocks for overlap-add + //std::vector<gr_complex> d_xformed_taps; // Fourier xformed taps + gr_complex *d_xformed_taps; + std::vector<float> d_new_taps; + + + void compute_sizes(int ntaps); + int tailsize() const { return d_ntaps - 1; } + + public: + /*! + * \brief Construct a FFT filter for float vectors with the given taps and decimation rate. + * + * This is the basic implementation for performing FFT filter for fast convolution + * in other blocks for floating point vectors (such as gr_fft_filter_fff). + * \param decimation The decimation rate of the filter (int) + * \param taps The filter taps (float) + */ + gri_fft_filter_fff_sse (int decimation, const std::vector<float> &taps); + ~gri_fft_filter_fff_sse (); + + /*! + * \brief Set new taps for the filter. + * + * Sets new taps and resets the class properties to handle different sizes + * \param taps The filter taps (float) + */ + int set_taps (const std::vector<float> &taps); + + /*! + * \brief Perform the filter operation + * + * \param nitems The number of items to produce + * \param input The input vector to be filtered + * \param output The result of the filter operation + */ + int filter (int nitems, const float *input, float *output); + +}; + +#endif /* INCLUDED_GRI_FFT_FILTER_FFF_SSE_H */ diff --git a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.cc.t b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.cc.t new file mode 100644 index 000000000..0ae644cc6 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.cc.t @@ -0,0 +1,121 @@ +/* -*- c++ -*- */ +/* + * Copyright 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 <@NAME@.h> + +@NAME@::@NAME@(const std::vector<@TAP_TYPE@> &taps) +{ + d_buffer = NULL; + set_taps(taps); +} + +@NAME@::~@NAME@() +{ + if(d_buffer != NULL) + free(d_buffer); +} + +void +@NAME@::set_taps (const std::vector<@TAP_TYPE@> &taps) +{ + d_taps = gr_reverse(taps); + + if(d_buffer != NULL) { + free(d_buffer); + d_buffer = NULL; + } + + // FIXME: memalign this to 16-byte boundaries for SIMD later + size_t t = sizeof(@I_TYPE@) * 2 * d_taps.size(); + d_buffer = (@I_TYPE@*)malloc(t); + memset(d_buffer, 0x00, t); + d_idx = 0; +} + +@O_TYPE@ +@NAME@::filter (@I_TYPE@ input) +{ + unsigned int i; + + d_buffer[d_idx] = input; + d_buffer[d_idx+ntaps()] = input; + + // using the later for the case when ntaps=0; + // profiling shows this doesn't make a difference + //d_idx = (d_idx + 1) % ntaps(); + d_idx++; + if(d_idx >= ntaps()) + d_idx = 0; + + @ACC_TYPE@ out = 0; + for(i = 0; i < ntaps(); i++) { + out += @INPUT_CAST@ d_buffer[d_idx + i] * d_taps[i]; + } + return (@O_TYPE@)out; +} + +@O_TYPE@ +@NAME@::filter (const @I_TYPE@ input[], unsigned long dec) +{ + unsigned int i; + + for(i = 0; i < dec; i++) { + d_buffer[d_idx] = input[i]; + d_buffer[d_idx+ntaps()] = input[i]; + d_idx++; + if(d_idx >= ntaps()) + d_idx = 0; + } + + @ACC_TYPE@ out = 0; + for(i = 0; i < ntaps(); i++) { + out += @INPUT_CAST@ d_buffer[d_idx + i] * d_taps[i]; + } + return (@O_TYPE@)out; +} + +void +@NAME@::filterN (@O_TYPE@ output[], + const @I_TYPE@ input[], + unsigned long n) +{ + for(unsigned long i = 0; i < n; i++) { + output[i] = filter(input[i]); + } +} + +void +@NAME@::filterNdec (@O_TYPE@ output[], + const @I_TYPE@ input[], + unsigned long n, + unsigned long decimate) +{ + unsigned long j = 0; + for(unsigned long i = 0; i < n; i++) { + output[i] = filter(&input[j], decimate); + j += decimate; + } +} diff --git a/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.h.t b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.h.t new file mode 100644 index 000000000..efb314bed --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_fir_filter_with_buffer_XXX.h.t @@ -0,0 +1,132 @@ +/* -*- c++ -*- */ +/* + * Copyright 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: This file is automatically generated by generate_gri_fir_XXX.py + * Any changes made to this file will be overwritten. + */ + + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_core_api.h> +#include <vector> +#include <gr_types.h> +#include <gr_reverse.h> +#include <string.h> +#include <cstdio> + +/*! + * \brief FIR with internal buffer for @I_TYPE@ input, + @O_TYPE@ output and @TAP_TYPE@ taps + * \ingroup filter + * + */ + +class GR_CORE_API @NAME@ { + +protected: + std::vector<@TAP_TYPE@> d_taps; // reversed taps + @I_TYPE@ *d_buffer; + unsigned int d_idx; + +public: + + // CONSTRUCTORS + + /*! + * \brief construct new FIR with given taps. + * + * Note that taps must be in forward order, e.g., coefficient 0 is + * stored in new_taps[0], coefficient 1 is stored in + * new_taps[1], etc. + */ + @NAME@ (const std::vector<@TAP_TYPE@> &taps); + + ~@NAME@ (); + + // MANIPULATORS + + /*! + * \brief compute a single output value. + * + * \p input is a single input value of the filter type + * + * \returns the filtered input value. + */ + @O_TYPE@ filter (@I_TYPE@ input); + + + /*! + * \brief compute a single output value; designed for decimating filters. + * + * \p input is a single input value of the filter type. The value of dec is the + * decimating value of the filter, so input[] must have dec valid values. + * The filter pushes dec number of items onto the circ. buffer before computing + * a single output. + * + * \returns the filtered input value. + */ + @O_TYPE@ filter (const @I_TYPE@ input[], unsigned long dec); + + /*! + * \brief compute an array of N output values. + * + * \p input must have (n - 1 + ntaps()) valid entries. + * input[0] .. input[n - 1 + ntaps() - 1] are referenced to compute the output values. + */ + void filterN (@O_TYPE@ output[], const @I_TYPE@ input[], + unsigned long n); + + /*! + * \brief compute an array of N output values, decimating the input + * + * \p input must have (decimate * (n - 1) + ntaps()) valid entries. + * input[0] .. input[decimate * (n - 1) + ntaps() - 1] are referenced to + * compute the output values. + */ + void filterNdec (@O_TYPE@ output[], const @I_TYPE@ input[], + unsigned long n, unsigned long decimate); + + /*! + * \brief install \p new_taps as the current taps. + */ + void set_taps (const std::vector<@TAP_TYPE@> &taps); + + // ACCESSORS + + /*! + * \return number of taps in filter. + */ + unsigned ntaps () const { return d_taps.size (); } + + /*! + * \return current taps + */ + const std::vector<@TAP_TYPE@> get_taps () const + { + return gr_reverse(d_taps); + } +}; + +#endif /* @GUARD_NAME@ */ diff --git a/gnuradio-core/src/lib/filter/gri_goertzel.cc b/gnuradio-core/src/lib/filter/gri_goertzel.cc new file mode 100644 index 000000000..2fbdd3b13 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_goertzel.cc @@ -0,0 +1,75 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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 <cmath> + +#include <gri_goertzel.h> + +gri_goertzel::gri_goertzel(int rate, int len, float freq) +{ + gri_setparms(rate, len, freq); +} + +void +gri_goertzel::gri_setparms(int rate, int len, float freq) +{ + d_d1 = 0.0; + d_d2 = 0.0; + + float w = 2.0*M_PI*freq/rate; + d_wr = 2.0*std::cos(w); + d_wi = std::sin(w); + d_len = len; + d_processed = 0; + +} + +gr_complex gri_goertzel::batch(float *in) +{ + d_d1 = 0.0; + d_d2 = 0.0; + + for(int i = 0; i < d_len; i++) + input(in[i]); + + return output(); +} + +void gri_goertzel::input(const float &input) +{ + float y = input + d_wr*d_d1 - d_d2; + d_d2 = d_d1; + d_d1 = y; + d_processed++; +} + +gr_complex gri_goertzel::output() +{ + gr_complex out((0.5*d_wr*d_d1-d_d2)/d_len, (d_wi*d_d1)/d_len); + d_d1 = 0.0; + d_d2 = 0.0; + d_processed = 0; + return out; +} diff --git a/gnuradio-core/src/lib/filter/gri_goertzel.h b/gnuradio-core/src/lib/filter/gri_goertzel.h new file mode 100644 index 000000000..e28cb21a8 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_goertzel.h @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_GRI_GOERTZEL_H +#define INCLUDED_GRI_GOERTZEL_H + +#include <gr_core_api.h> +#include <gr_types.h> + +/*! + * \brief Implements Goertzel single-bin DFT calculation + * \ingroup misc + */ +class GR_CORE_API gri_goertzel +{ +public: + gri_goertzel() {} + gri_goertzel(int rate, int len, float freq); + void gri_setparms(int rate, int len, float freq); + + // Process a input array + gr_complex batch(float *in); + + // Process sample by sample + void input(const float &in); + gr_complex output(); + bool ready() const { return d_processed == d_len; } + +private: + float d_d1; + float d_d2; + float d_wr; + float d_wi; + int d_len; + int d_processed; +}; + +#endif /* INCLUDED_GRI_GOERTZEL_H */ diff --git a/gnuradio-core/src/lib/filter/gri_iir.h b/gnuradio-core/src/lib/filter/gri_iir.h new file mode 100644 index 000000000..86345f6c0 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_iir.h @@ -0,0 +1,177 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_IIR_H +#define INCLUDED_GRI_IIR_H + +#include <gr_core_api.h> +#include <vector> +#include <stdexcept> + +/*! + * \brief base class template for Infinite Impulse Response filter (IIR) + */ +template<class i_type, class o_type, class tap_type> +class gri_iir { +public: + /*! + * \brief Construct an IIR with the given taps. + * + * This filter uses the Direct Form I implementation, where + * \p fftaps contains the feed-forward taps, and \p fbtaps the feedback ones. + * + * \p fftaps and \p fbtaps must have equal numbers of taps + * + * The input and output satisfy a difference equation of the form + + \f[ + y[n] - \sum_{k=1}^{M} a_k y[n-k] = \sum_{k=0}^{N} b_k x[n-k] + \f] + + * with the corresponding rational system function + + \f[ + H(z) = \frac{\sum_{k=0}^{N} b_k z^{-k}}{1 - \sum_{k=1}^{M} a_k z^{-k}} + \f] + + * Note that some texts define the system function with a + in the denominator. + * If you're using that convention, you'll need to negate the feedback taps. + */ + gri_iir (const std::vector<tap_type>& fftaps, + const std::vector<tap_type>& fbtaps) throw (std::invalid_argument) + { + set_taps (fftaps, fbtaps); + } + + gri_iir () : d_latest_n(0),d_latest_m(0) { } + + ~gri_iir () {} + + /*! + * \brief compute a single output value. + * \returns the filtered input value. + */ + o_type filter (const i_type input); + + /*! + * \brief compute an array of N output values. + * \p input must have N valid entries. + */ + void filter_n (o_type output[], const i_type input[], long n); + + /*! + * \return number of taps in filter. + */ + unsigned ntaps_ff () const { return d_fftaps.size (); } + unsigned ntaps_fb () const { return d_fbtaps.size (); } + + /*! + * \brief install new taps. + */ + void set_taps (const std::vector<tap_type> &fftaps, + const std::vector<tap_type> &fbtaps) throw (std::invalid_argument) + { + + + d_latest_n = 0; + d_latest_m = 0; + d_fftaps = fftaps; + d_fbtaps = fbtaps; + + int n = fftaps.size (); + int m = fbtaps.size (); + d_prev_input.resize (2 * n); + d_prev_output.resize (2 * m); + + for (int i = 0; i < 2 * n; i++){ + d_prev_input[i] = 0; + } + for (int i = 0; i < 2 * m; i++){ + d_prev_output[i] = 0; + } + } + +protected: + std::vector<tap_type> d_fftaps; + std::vector<tap_type> d_fbtaps; + int d_latest_n; + int d_latest_m; + std::vector<tap_type> d_prev_output; + std::vector<i_type> d_prev_input; +}; + + +// +// general case. We may want to specialize this +// +template<class i_type, class o_type, class tap_type> +o_type +gri_iir<i_type, o_type, tap_type>::filter (const i_type input) +{ + tap_type acc; + unsigned i = 0; + unsigned n = ntaps_ff (); + unsigned m = ntaps_fb (); + + if (n == 0) + return (o_type) 0; + + int latest_n = d_latest_n; + int latest_m = d_latest_m; + + acc = d_fftaps[0] * input; + for (i = 1; i < n; i ++) + acc += (d_fftaps[i] * d_prev_input[latest_n + i]); + for (i = 1; i < m; i ++) + acc += (d_fbtaps[i] * d_prev_output[latest_m + i]); + + // store the values twice to avoid having to handle wrap-around in the loop + d_prev_output[latest_m] = acc; + d_prev_output[latest_m+m] = acc; + d_prev_input[latest_n] = input; + d_prev_input[latest_n+n] = input; + + latest_n--; + latest_m--; + if (latest_n < 0) + latest_n += n; + if (latest_m < 0) + latest_m += m; + + d_latest_m = latest_m; + d_latest_n = latest_n; + return (o_type) acc; +} + + +template<class i_type, class o_type, class tap_type> +void +gri_iir<i_type, o_type, tap_type>::filter_n (o_type output[], + const i_type input[], + long n) +{ + for (int i = 0; i < n; i++) + output[i] = filter (input[i]); +} + +#endif /* INCLUDED_GRI_IIR_H */ + diff --git a/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator.cc b/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator.cc new file mode 100644 index 000000000..52098bf1a --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator.cc @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 <gri_mmse_fir_interpolator.h> +#include <gr_fir_util.h> +#include <gr_fir_fff.h> +#include <assert.h> +#include <cmath> +#include "interpolator_taps.h" + +gri_mmse_fir_interpolator::gri_mmse_fir_interpolator () +{ + filters.resize (NSTEPS + 1); + + for (int i = 0; i < NSTEPS + 1; i++){ + std::vector<float> t (&taps[i][0], &taps[i][NTAPS]); + filters[i] = gr_fir_util::create_gr_fir_fff (t); + } +} + +gri_mmse_fir_interpolator::~gri_mmse_fir_interpolator () +{ + for (int i = 0; i < NSTEPS + 1; i++) + delete filters[i]; +} + +unsigned +gri_mmse_fir_interpolator::ntaps () const +{ + return NTAPS; +} + +unsigned +gri_mmse_fir_interpolator::nsteps () const +{ + return NSTEPS; +} + +float +gri_mmse_fir_interpolator::interpolate (const float input[], float mu) const +{ + int imu = (int) rint (mu * NSTEPS); + + assert (imu >= 0); + assert (imu <= NSTEPS); + + float r = filters[imu]->filter (input); + return r; +} diff --git a/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator.h b/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator.h new file mode 100644 index 000000000..f479169bc --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator.h @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 _GRI_MMSE_FIR_INTERPOLATOR_H_ +#define _GRI_MMSE_FIR_INTERPOLATOR_H_ + +#include <gr_core_api.h> +#include <vector> + +class gr_fir_fff; + +/*! + * \brief Compute intermediate samples between signal samples x(k*Ts) + * \ingroup filter_primitive + * + * This implements a Mininum Mean Squared Error interpolator with 8 taps. + * It is suitable for signals where the bandwidth of interest B = 1/(4*Ts) + * Where Ts is the time between samples. + * + * Although mu, the fractional delay, is specified as a float, it is actually + * quantized. 0.0 <= mu <= 1.0. That is, mu is quantized in the interpolate + * method to 32nd's of a sample. + * + * For more information, in the GNU Radio source code, see: + * \li gnuradio-core/src/gen_interpolator_taps/README + * \li gnuradio-core/src/gen_interpolator_taps/praxis.txt + */ + +class GR_CORE_API gri_mmse_fir_interpolator { +public: + gri_mmse_fir_interpolator (); + ~gri_mmse_fir_interpolator (); + + unsigned ntaps () const; + unsigned nsteps () const; + + /*! + * \brief compute a single interpolated output value. + * \p input must have ntaps() valid entries. + * input[0] .. input[ntaps() - 1] are referenced to compute the output value. + * + * \p mu must be in the range [0, 1] and specifies the fractional delay. + * + * \returns the interpolated input value. + */ + float interpolate (const float input[], float mu) const; + +protected: + std::vector<gr_fir_fff *> filters; +}; + + +#endif /* _GRI_MMSE_FIR_INTERPOLATOR_H_ */ diff --git a/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator_cc.cc b/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator_cc.cc new file mode 100644 index 000000000..174378c22 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator_cc.cc @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 <gri_mmse_fir_interpolator_cc.h> +#include <gr_fir_util.h> +#include <gr_fir_ccf.h> +#include <assert.h> +#include <cmath> +#include "interpolator_taps.h" + +gri_mmse_fir_interpolator_cc::gri_mmse_fir_interpolator_cc () +{ + filters.resize (NSTEPS + 1); + + for (int i = 0; i < NSTEPS + 1; i++){ + std::vector<float> t (&taps[i][0], &taps[i][NTAPS]); + filters[i] = gr_fir_util::create_gr_fir_ccf (t); + } +} + +gri_mmse_fir_interpolator_cc::~gri_mmse_fir_interpolator_cc () +{ + for (int i = 0; i < NSTEPS + 1; i++) + delete filters[i]; +} + +unsigned +gri_mmse_fir_interpolator_cc::ntaps () const +{ + return NTAPS; +} + +unsigned +gri_mmse_fir_interpolator_cc::nsteps () const +{ + return NSTEPS; +} + +gr_complex +gri_mmse_fir_interpolator_cc::interpolate (const gr_complex input[], float mu) +{ + int imu = (int) rint (mu * NSTEPS); + + assert (imu >= 0); + assert (imu <= NSTEPS); + + gr_complex r = filters[imu]->filter (input); + return r; +} diff --git a/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator_cc.h b/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator_cc.h new file mode 100644 index 000000000..bacd9ed92 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator_cc.h @@ -0,0 +1,74 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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 _GRI_MMSE_FIR_INTERPOLATOR_CC_H_ +#define _GRI_MMSE_FIR_INTERPOLATOR_CC_H_ + +#include <gr_core_api.h> +#include <gr_complex.h> +#include <vector> + +class gr_fir_ccf; + +/*! + * \brief Compute intermediate samples between signal samples x(k*Ts) + * \ingroup filter_primitive + * + * This implements a Mininum Mean Squared Error interpolator with 8 taps. + * It is suitable for signals where the bandwidth of interest B = 1/(4*Ts) + * Where Ts is the time between samples. + * + * Although mu, the fractional delay, is specified as a float, it is actually + * quantized. 0.0 <= mu <= 1.0. That is, mu is quantized in the interpolate + * method to 32nd's of a sample. + * + * For more information, in the GNU Radio source code, see: + * \li gnuradio-core/src/gen_interpolator_taps/README + * \li gnuradio-core/src/gen_interpolator_taps/praxis.txt + */ + +class GR_CORE_API gri_mmse_fir_interpolator_cc { +public: + gri_mmse_fir_interpolator_cc (); + ~gri_mmse_fir_interpolator_cc (); + + unsigned ntaps () const; + unsigned nsteps () const; + + /*! + * \brief compute a single interpolated output value. + * + * \p input must have ntaps() valid entries and be 8-byte aligned. + * input[0] .. input[ntaps() - 1] are referenced to compute the output value. + * \throws std::invalid_argument if input is not 8-byte aligned. + * + * \p mu must be in the range [0, 1] and specifies the fractional delay. + * + * \returns the interpolated input value. + */ + gr_complex interpolate (const gr_complex input[], float mu); + +protected: + std::vector<gr_fir_ccf *> filters; +}; + + +#endif /* _GRI_MMSE_FIR_INTERPOLATOR_CC_H_ */ diff --git a/gnuradio-core/src/lib/filter/interpolator_taps.h b/gnuradio-core/src/lib/filter/interpolator_taps.h new file mode 100644 index 000000000..76702b63f --- /dev/null +++ b/gnuradio-core/src/lib/filter/interpolator_taps.h @@ -0,0 +1,141 @@ +/* + * This file was machine generated by gen_interpolator_taps. + * DO NOT EDIT BY HAND. + */ + +static const int NTAPS = 8; +static const int NSTEPS = 128; + +static const float taps[NSTEPS+1][NTAPS] = { + // -4 -3 -2 -1 0 1 2 3 mu + { 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00 }, // 0/128 + { -1.54700e-04, 8.53777e-04, -2.76968e-03, 7.89295e-03, 9.98534e-01, -5.41054e-03, 1.24642e-03, -1.98993e-04 }, // 1/128 + { -3.09412e-04, 1.70888e-03, -5.55134e-03, 1.58840e-02, 9.96891e-01, -1.07209e-02, 2.47942e-03, -3.96391e-04 }, // 2/128 + { -4.64053e-04, 2.56486e-03, -8.34364e-03, 2.39714e-02, 9.95074e-01, -1.59305e-02, 3.69852e-03, -5.92100e-04 }, // 3/128 + { -6.18544e-04, 3.42130e-03, -1.11453e-02, 3.21531e-02, 9.93082e-01, -2.10389e-02, 4.90322e-03, -7.86031e-04 }, // 4/128 + { -7.72802e-04, 4.27773e-03, -1.39548e-02, 4.04274e-02, 9.90917e-01, -2.60456e-02, 6.09305e-03, -9.78093e-04 }, // 5/128 + { -9.26747e-04, 5.13372e-03, -1.67710e-02, 4.87921e-02, 9.88580e-01, -3.09503e-02, 7.26755e-03, -1.16820e-03 }, // 6/128 + { -1.08030e-03, 5.98883e-03, -1.95925e-02, 5.72454e-02, 9.86071e-01, -3.57525e-02, 8.42626e-03, -1.35627e-03 }, // 7/128 + { -1.23337e-03, 6.84261e-03, -2.24178e-02, 6.57852e-02, 9.83392e-01, -4.04519e-02, 9.56876e-03, -1.54221e-03 }, // 8/128 + { -1.38589e-03, 7.69462e-03, -2.52457e-02, 7.44095e-02, 9.80543e-01, -4.50483e-02, 1.06946e-02, -1.72594e-03 }, // 9/128 + { -1.53777e-03, 8.54441e-03, -2.80746e-02, 8.31162e-02, 9.77526e-01, -4.95412e-02, 1.18034e-02, -1.90738e-03 }, // 10/128 + { -1.68894e-03, 9.39154e-03, -3.09033e-02, 9.19033e-02, 9.74342e-01, -5.39305e-02, 1.28947e-02, -2.08645e-03 }, // 11/128 + { -1.83931e-03, 1.02356e-02, -3.37303e-02, 1.00769e-01, 9.70992e-01, -5.82159e-02, 1.39681e-02, -2.26307e-03 }, // 12/128 + { -1.98880e-03, 1.10760e-02, -3.65541e-02, 1.09710e-01, 9.67477e-01, -6.23972e-02, 1.50233e-02, -2.43718e-03 }, // 13/128 + { -2.13733e-03, 1.19125e-02, -3.93735e-02, 1.18725e-01, 9.63798e-01, -6.64743e-02, 1.60599e-02, -2.60868e-03 }, // 14/128 + { -2.28483e-03, 1.27445e-02, -4.21869e-02, 1.27812e-01, 9.59958e-01, -7.04471e-02, 1.70776e-02, -2.77751e-03 }, // 15/128 + { -2.43121e-03, 1.35716e-02, -4.49929e-02, 1.36968e-01, 9.55956e-01, -7.43154e-02, 1.80759e-02, -2.94361e-03 }, // 16/128 + { -2.57640e-03, 1.43934e-02, -4.77900e-02, 1.46192e-01, 9.51795e-01, -7.80792e-02, 1.90545e-02, -3.10689e-03 }, // 17/128 + { -2.72032e-03, 1.52095e-02, -5.05770e-02, 1.55480e-01, 9.47477e-01, -8.17385e-02, 2.00132e-02, -3.26730e-03 }, // 18/128 + { -2.86289e-03, 1.60193e-02, -5.33522e-02, 1.64831e-01, 9.43001e-01, -8.52933e-02, 2.09516e-02, -3.42477e-03 }, // 19/128 + { -3.00403e-03, 1.68225e-02, -5.61142e-02, 1.74242e-01, 9.38371e-01, -8.87435e-02, 2.18695e-02, -3.57923e-03 }, // 20/128 + { -3.14367e-03, 1.76185e-02, -5.88617e-02, 1.83711e-01, 9.33586e-01, -9.20893e-02, 2.27664e-02, -3.73062e-03 }, // 21/128 + { -3.28174e-03, 1.84071e-02, -6.15931e-02, 1.93236e-01, 9.28650e-01, -9.53307e-02, 2.36423e-02, -3.87888e-03 }, // 22/128 + { -3.41815e-03, 1.91877e-02, -6.43069e-02, 2.02814e-01, 9.23564e-01, -9.84679e-02, 2.44967e-02, -4.02397e-03 }, // 23/128 + { -3.55283e-03, 1.99599e-02, -6.70018e-02, 2.12443e-01, 9.18329e-01, -1.01501e-01, 2.53295e-02, -4.16581e-03 }, // 24/128 + { -3.68570e-03, 2.07233e-02, -6.96762e-02, 2.22120e-01, 9.12947e-01, -1.04430e-01, 2.61404e-02, -4.30435e-03 }, // 25/128 + { -3.81671e-03, 2.14774e-02, -7.23286e-02, 2.31843e-01, 9.07420e-01, -1.07256e-01, 2.69293e-02, -4.43955e-03 }, // 26/128 + { -3.94576e-03, 2.22218e-02, -7.49577e-02, 2.41609e-01, 9.01749e-01, -1.09978e-01, 2.76957e-02, -4.57135e-03 }, // 27/128 + { -4.07279e-03, 2.29562e-02, -7.75620e-02, 2.51417e-01, 8.95936e-01, -1.12597e-01, 2.84397e-02, -4.69970e-03 }, // 28/128 + { -4.19774e-03, 2.36801e-02, -8.01399e-02, 2.61263e-01, 8.89984e-01, -1.15113e-01, 2.91609e-02, -4.82456e-03 }, // 29/128 + { -4.32052e-03, 2.43930e-02, -8.26900e-02, 2.71144e-01, 8.83893e-01, -1.17526e-01, 2.98593e-02, -4.94589e-03 }, // 30/128 + { -4.44107e-03, 2.50946e-02, -8.52109e-02, 2.81060e-01, 8.77666e-01, -1.19837e-01, 3.05345e-02, -5.06363e-03 }, // 31/128 + { -4.55932e-03, 2.57844e-02, -8.77011e-02, 2.91006e-01, 8.71305e-01, -1.22047e-01, 3.11866e-02, -5.17776e-03 }, // 32/128 + { -4.67520e-03, 2.64621e-02, -9.01591e-02, 3.00980e-01, 8.64812e-01, -1.24154e-01, 3.18153e-02, -5.28823e-03 }, // 33/128 + { -4.78866e-03, 2.71272e-02, -9.25834e-02, 3.10980e-01, 8.58189e-01, -1.26161e-01, 3.24205e-02, -5.39500e-03 }, // 34/128 + { -4.89961e-03, 2.77794e-02, -9.49727e-02, 3.21004e-01, 8.51437e-01, -1.28068e-01, 3.30021e-02, -5.49804e-03 }, // 35/128 + { -5.00800e-03, 2.84182e-02, -9.73254e-02, 3.31048e-01, 8.44559e-01, -1.29874e-01, 3.35600e-02, -5.59731e-03 }, // 36/128 + { -5.11376e-03, 2.90433e-02, -9.96402e-02, 3.41109e-01, 8.37557e-01, -1.31581e-01, 3.40940e-02, -5.69280e-03 }, // 37/128 + { -5.21683e-03, 2.96543e-02, -1.01915e-01, 3.51186e-01, 8.30432e-01, -1.33189e-01, 3.46042e-02, -5.78446e-03 }, // 38/128 + { -5.31716e-03, 3.02507e-02, -1.04150e-01, 3.61276e-01, 8.23188e-01, -1.34699e-01, 3.50903e-02, -5.87227e-03 }, // 39/128 + { -5.41467e-03, 3.08323e-02, -1.06342e-01, 3.71376e-01, 8.15826e-01, -1.36111e-01, 3.55525e-02, -5.95620e-03 }, // 40/128 + { -5.50931e-03, 3.13987e-02, -1.08490e-01, 3.81484e-01, 8.08348e-01, -1.37426e-01, 3.59905e-02, -6.03624e-03 }, // 41/128 + { -5.60103e-03, 3.19495e-02, -1.10593e-01, 3.91596e-01, 8.00757e-01, -1.38644e-01, 3.64044e-02, -6.11236e-03 }, // 42/128 + { -5.68976e-03, 3.24843e-02, -1.12650e-01, 4.01710e-01, 7.93055e-01, -1.39767e-01, 3.67941e-02, -6.18454e-03 }, // 43/128 + { -5.77544e-03, 3.30027e-02, -1.14659e-01, 4.11823e-01, 7.85244e-01, -1.40794e-01, 3.71596e-02, -6.25277e-03 }, // 44/128 + { -5.85804e-03, 3.35046e-02, -1.16618e-01, 4.21934e-01, 7.77327e-01, -1.41727e-01, 3.75010e-02, -6.31703e-03 }, // 45/128 + { -5.93749e-03, 3.39894e-02, -1.18526e-01, 4.32038e-01, 7.69305e-01, -1.42566e-01, 3.78182e-02, -6.37730e-03 }, // 46/128 + { -6.01374e-03, 3.44568e-02, -1.20382e-01, 4.42134e-01, 7.61181e-01, -1.43313e-01, 3.81111e-02, -6.43358e-03 }, // 47/128 + { -6.08674e-03, 3.49066e-02, -1.22185e-01, 4.52218e-01, 7.52958e-01, -1.43968e-01, 3.83800e-02, -6.48585e-03 }, // 48/128 + { -6.15644e-03, 3.53384e-02, -1.23933e-01, 4.62289e-01, 7.44637e-01, -1.44531e-01, 3.86247e-02, -6.53412e-03 }, // 49/128 + { -6.22280e-03, 3.57519e-02, -1.25624e-01, 4.72342e-01, 7.36222e-01, -1.45004e-01, 3.88454e-02, -6.57836e-03 }, // 50/128 + { -6.28577e-03, 3.61468e-02, -1.27258e-01, 4.82377e-01, 7.27714e-01, -1.45387e-01, 3.90420e-02, -6.61859e-03 }, // 51/128 + { -6.34530e-03, 3.65227e-02, -1.28832e-01, 4.92389e-01, 7.19116e-01, -1.45682e-01, 3.92147e-02, -6.65479e-03 }, // 52/128 + { -6.40135e-03, 3.68795e-02, -1.30347e-01, 5.02377e-01, 7.10431e-01, -1.45889e-01, 3.93636e-02, -6.68698e-03 }, // 53/128 + { -6.45388e-03, 3.72167e-02, -1.31800e-01, 5.12337e-01, 7.01661e-01, -1.46009e-01, 3.94886e-02, -6.71514e-03 }, // 54/128 + { -6.50285e-03, 3.75341e-02, -1.33190e-01, 5.22267e-01, 6.92808e-01, -1.46043e-01, 3.95900e-02, -6.73929e-03 }, // 55/128 + { -6.54823e-03, 3.78315e-02, -1.34515e-01, 5.32164e-01, 6.83875e-01, -1.45993e-01, 3.96678e-02, -6.75943e-03 }, // 56/128 + { -6.58996e-03, 3.81085e-02, -1.35775e-01, 5.42025e-01, 6.74865e-01, -1.45859e-01, 3.97222e-02, -6.77557e-03 }, // 57/128 + { -6.62802e-03, 3.83650e-02, -1.36969e-01, 5.51849e-01, 6.65779e-01, -1.45641e-01, 3.97532e-02, -6.78771e-03 }, // 58/128 + { -6.66238e-03, 3.86006e-02, -1.38094e-01, 5.61631e-01, 6.56621e-01, -1.45343e-01, 3.97610e-02, -6.79588e-03 }, // 59/128 + { -6.69300e-03, 3.88151e-02, -1.39150e-01, 5.71370e-01, 6.47394e-01, -1.44963e-01, 3.97458e-02, -6.80007e-03 }, // 60/128 + { -6.71985e-03, 3.90083e-02, -1.40136e-01, 5.81063e-01, 6.38099e-01, -1.44503e-01, 3.97077e-02, -6.80032e-03 }, // 61/128 + { -6.74291e-03, 3.91800e-02, -1.41050e-01, 5.90706e-01, 6.28739e-01, -1.43965e-01, 3.96469e-02, -6.79662e-03 }, // 62/128 + { -6.76214e-03, 3.93299e-02, -1.41891e-01, 6.00298e-01, 6.19318e-01, -1.43350e-01, 3.95635e-02, -6.78902e-03 }, // 63/128 + { -6.77751e-03, 3.94578e-02, -1.42658e-01, 6.09836e-01, 6.09836e-01, -1.42658e-01, 3.94578e-02, -6.77751e-03 }, // 64/128 + { -6.78902e-03, 3.95635e-02, -1.43350e-01, 6.19318e-01, 6.00298e-01, -1.41891e-01, 3.93299e-02, -6.76214e-03 }, // 65/128 + { -6.79662e-03, 3.96469e-02, -1.43965e-01, 6.28739e-01, 5.90706e-01, -1.41050e-01, 3.91800e-02, -6.74291e-03 }, // 66/128 + { -6.80032e-03, 3.97077e-02, -1.44503e-01, 6.38099e-01, 5.81063e-01, -1.40136e-01, 3.90083e-02, -6.71985e-03 }, // 67/128 + { -6.80007e-03, 3.97458e-02, -1.44963e-01, 6.47394e-01, 5.71370e-01, -1.39150e-01, 3.88151e-02, -6.69300e-03 }, // 68/128 + { -6.79588e-03, 3.97610e-02, -1.45343e-01, 6.56621e-01, 5.61631e-01, -1.38094e-01, 3.86006e-02, -6.66238e-03 }, // 69/128 + { -6.78771e-03, 3.97532e-02, -1.45641e-01, 6.65779e-01, 5.51849e-01, -1.36969e-01, 3.83650e-02, -6.62802e-03 }, // 70/128 + { -6.77557e-03, 3.97222e-02, -1.45859e-01, 6.74865e-01, 5.42025e-01, -1.35775e-01, 3.81085e-02, -6.58996e-03 }, // 71/128 + { -6.75943e-03, 3.96678e-02, -1.45993e-01, 6.83875e-01, 5.32164e-01, -1.34515e-01, 3.78315e-02, -6.54823e-03 }, // 72/128 + { -6.73929e-03, 3.95900e-02, -1.46043e-01, 6.92808e-01, 5.22267e-01, -1.33190e-01, 3.75341e-02, -6.50285e-03 }, // 73/128 + { -6.71514e-03, 3.94886e-02, -1.46009e-01, 7.01661e-01, 5.12337e-01, -1.31800e-01, 3.72167e-02, -6.45388e-03 }, // 74/128 + { -6.68698e-03, 3.93636e-02, -1.45889e-01, 7.10431e-01, 5.02377e-01, -1.30347e-01, 3.68795e-02, -6.40135e-03 }, // 75/128 + { -6.65479e-03, 3.92147e-02, -1.45682e-01, 7.19116e-01, 4.92389e-01, -1.28832e-01, 3.65227e-02, -6.34530e-03 }, // 76/128 + { -6.61859e-03, 3.90420e-02, -1.45387e-01, 7.27714e-01, 4.82377e-01, -1.27258e-01, 3.61468e-02, -6.28577e-03 }, // 77/128 + { -6.57836e-03, 3.88454e-02, -1.45004e-01, 7.36222e-01, 4.72342e-01, -1.25624e-01, 3.57519e-02, -6.22280e-03 }, // 78/128 + { -6.53412e-03, 3.86247e-02, -1.44531e-01, 7.44637e-01, 4.62289e-01, -1.23933e-01, 3.53384e-02, -6.15644e-03 }, // 79/128 + { -6.48585e-03, 3.83800e-02, -1.43968e-01, 7.52958e-01, 4.52218e-01, -1.22185e-01, 3.49066e-02, -6.08674e-03 }, // 80/128 + { -6.43358e-03, 3.81111e-02, -1.43313e-01, 7.61181e-01, 4.42134e-01, -1.20382e-01, 3.44568e-02, -6.01374e-03 }, // 81/128 + { -6.37730e-03, 3.78182e-02, -1.42566e-01, 7.69305e-01, 4.32038e-01, -1.18526e-01, 3.39894e-02, -5.93749e-03 }, // 82/128 + { -6.31703e-03, 3.75010e-02, -1.41727e-01, 7.77327e-01, 4.21934e-01, -1.16618e-01, 3.35046e-02, -5.85804e-03 }, // 83/128 + { -6.25277e-03, 3.71596e-02, -1.40794e-01, 7.85244e-01, 4.11823e-01, -1.14659e-01, 3.30027e-02, -5.77544e-03 }, // 84/128 + { -6.18454e-03, 3.67941e-02, -1.39767e-01, 7.93055e-01, 4.01710e-01, -1.12650e-01, 3.24843e-02, -5.68976e-03 }, // 85/128 + { -6.11236e-03, 3.64044e-02, -1.38644e-01, 8.00757e-01, 3.91596e-01, -1.10593e-01, 3.19495e-02, -5.60103e-03 }, // 86/128 + { -6.03624e-03, 3.59905e-02, -1.37426e-01, 8.08348e-01, 3.81484e-01, -1.08490e-01, 3.13987e-02, -5.50931e-03 }, // 87/128 + { -5.95620e-03, 3.55525e-02, -1.36111e-01, 8.15826e-01, 3.71376e-01, -1.06342e-01, 3.08323e-02, -5.41467e-03 }, // 88/128 + { -5.87227e-03, 3.50903e-02, -1.34699e-01, 8.23188e-01, 3.61276e-01, -1.04150e-01, 3.02507e-02, -5.31716e-03 }, // 89/128 + { -5.78446e-03, 3.46042e-02, -1.33189e-01, 8.30432e-01, 3.51186e-01, -1.01915e-01, 2.96543e-02, -5.21683e-03 }, // 90/128 + { -5.69280e-03, 3.40940e-02, -1.31581e-01, 8.37557e-01, 3.41109e-01, -9.96402e-02, 2.90433e-02, -5.11376e-03 }, // 91/128 + { -5.59731e-03, 3.35600e-02, -1.29874e-01, 8.44559e-01, 3.31048e-01, -9.73254e-02, 2.84182e-02, -5.00800e-03 }, // 92/128 + { -5.49804e-03, 3.30021e-02, -1.28068e-01, 8.51437e-01, 3.21004e-01, -9.49727e-02, 2.77794e-02, -4.89961e-03 }, // 93/128 + { -5.39500e-03, 3.24205e-02, -1.26161e-01, 8.58189e-01, 3.10980e-01, -9.25834e-02, 2.71272e-02, -4.78866e-03 }, // 94/128 + { -5.28823e-03, 3.18153e-02, -1.24154e-01, 8.64812e-01, 3.00980e-01, -9.01591e-02, 2.64621e-02, -4.67520e-03 }, // 95/128 + { -5.17776e-03, 3.11866e-02, -1.22047e-01, 8.71305e-01, 2.91006e-01, -8.77011e-02, 2.57844e-02, -4.55932e-03 }, // 96/128 + { -5.06363e-03, 3.05345e-02, -1.19837e-01, 8.77666e-01, 2.81060e-01, -8.52109e-02, 2.50946e-02, -4.44107e-03 }, // 97/128 + { -4.94589e-03, 2.98593e-02, -1.17526e-01, 8.83893e-01, 2.71144e-01, -8.26900e-02, 2.43930e-02, -4.32052e-03 }, // 98/128 + { -4.82456e-03, 2.91609e-02, -1.15113e-01, 8.89984e-01, 2.61263e-01, -8.01399e-02, 2.36801e-02, -4.19774e-03 }, // 99/128 + { -4.69970e-03, 2.84397e-02, -1.12597e-01, 8.95936e-01, 2.51417e-01, -7.75620e-02, 2.29562e-02, -4.07279e-03 }, // 100/128 + { -4.57135e-03, 2.76957e-02, -1.09978e-01, 9.01749e-01, 2.41609e-01, -7.49577e-02, 2.22218e-02, -3.94576e-03 }, // 101/128 + { -4.43955e-03, 2.69293e-02, -1.07256e-01, 9.07420e-01, 2.31843e-01, -7.23286e-02, 2.14774e-02, -3.81671e-03 }, // 102/128 + { -4.30435e-03, 2.61404e-02, -1.04430e-01, 9.12947e-01, 2.22120e-01, -6.96762e-02, 2.07233e-02, -3.68570e-03 }, // 103/128 + { -4.16581e-03, 2.53295e-02, -1.01501e-01, 9.18329e-01, 2.12443e-01, -6.70018e-02, 1.99599e-02, -3.55283e-03 }, // 104/128 + { -4.02397e-03, 2.44967e-02, -9.84679e-02, 9.23564e-01, 2.02814e-01, -6.43069e-02, 1.91877e-02, -3.41815e-03 }, // 105/128 + { -3.87888e-03, 2.36423e-02, -9.53307e-02, 9.28650e-01, 1.93236e-01, -6.15931e-02, 1.84071e-02, -3.28174e-03 }, // 106/128 + { -3.73062e-03, 2.27664e-02, -9.20893e-02, 9.33586e-01, 1.83711e-01, -5.88617e-02, 1.76185e-02, -3.14367e-03 }, // 107/128 + { -3.57923e-03, 2.18695e-02, -8.87435e-02, 9.38371e-01, 1.74242e-01, -5.61142e-02, 1.68225e-02, -3.00403e-03 }, // 108/128 + { -3.42477e-03, 2.09516e-02, -8.52933e-02, 9.43001e-01, 1.64831e-01, -5.33522e-02, 1.60193e-02, -2.86289e-03 }, // 109/128 + { -3.26730e-03, 2.00132e-02, -8.17385e-02, 9.47477e-01, 1.55480e-01, -5.05770e-02, 1.52095e-02, -2.72032e-03 }, // 110/128 + { -3.10689e-03, 1.90545e-02, -7.80792e-02, 9.51795e-01, 1.46192e-01, -4.77900e-02, 1.43934e-02, -2.57640e-03 }, // 111/128 + { -2.94361e-03, 1.80759e-02, -7.43154e-02, 9.55956e-01, 1.36968e-01, -4.49929e-02, 1.35716e-02, -2.43121e-03 }, // 112/128 + { -2.77751e-03, 1.70776e-02, -7.04471e-02, 9.59958e-01, 1.27812e-01, -4.21869e-02, 1.27445e-02, -2.28483e-03 }, // 113/128 + { -2.60868e-03, 1.60599e-02, -6.64743e-02, 9.63798e-01, 1.18725e-01, -3.93735e-02, 1.19125e-02, -2.13733e-03 }, // 114/128 + { -2.43718e-03, 1.50233e-02, -6.23972e-02, 9.67477e-01, 1.09710e-01, -3.65541e-02, 1.10760e-02, -1.98880e-03 }, // 115/128 + { -2.26307e-03, 1.39681e-02, -5.82159e-02, 9.70992e-01, 1.00769e-01, -3.37303e-02, 1.02356e-02, -1.83931e-03 }, // 116/128 + { -2.08645e-03, 1.28947e-02, -5.39305e-02, 9.74342e-01, 9.19033e-02, -3.09033e-02, 9.39154e-03, -1.68894e-03 }, // 117/128 + { -1.90738e-03, 1.18034e-02, -4.95412e-02, 9.77526e-01, 8.31162e-02, -2.80746e-02, 8.54441e-03, -1.53777e-03 }, // 118/128 + { -1.72594e-03, 1.06946e-02, -4.50483e-02, 9.80543e-01, 7.44095e-02, -2.52457e-02, 7.69462e-03, -1.38589e-03 }, // 119/128 + { -1.54221e-03, 9.56876e-03, -4.04519e-02, 9.83392e-01, 6.57852e-02, -2.24178e-02, 6.84261e-03, -1.23337e-03 }, // 120/128 + { -1.35627e-03, 8.42626e-03, -3.57525e-02, 9.86071e-01, 5.72454e-02, -1.95925e-02, 5.98883e-03, -1.08030e-03 }, // 121/128 + { -1.16820e-03, 7.26755e-03, -3.09503e-02, 9.88580e-01, 4.87921e-02, -1.67710e-02, 5.13372e-03, -9.26747e-04 }, // 122/128 + { -9.78093e-04, 6.09305e-03, -2.60456e-02, 9.90917e-01, 4.04274e-02, -1.39548e-02, 4.27773e-03, -7.72802e-04 }, // 123/128 + { -7.86031e-04, 4.90322e-03, -2.10389e-02, 9.93082e-01, 3.21531e-02, -1.11453e-02, 3.42130e-03, -6.18544e-04 }, // 124/128 + { -5.92100e-04, 3.69852e-03, -1.59305e-02, 9.95074e-01, 2.39714e-02, -8.34364e-03, 2.56486e-03, -4.64053e-04 }, // 125/128 + { -3.96391e-04, 2.47942e-03, -1.07209e-02, 9.96891e-01, 1.58840e-02, -5.55134e-03, 1.70888e-03, -3.09412e-04 }, // 126/128 + { -1.98993e-04, 1.24642e-03, -5.41054e-03, 9.98534e-01, 7.89295e-03, -2.76968e-03, 8.53777e-04, -1.54700e-04 }, // 127/128 + { 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00 }, // 128/128 +}; + diff --git a/gnuradio-core/src/lib/filter/qa_ccomplex_dotprod_x86.cc b/gnuradio-core/src/lib/filter/qa_ccomplex_dotprod_x86.cc new file mode 100644 index 000000000..0d7b878da --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_ccomplex_dotprod_x86.cc @@ -0,0 +1,341 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 <cppunit/TestAssert.h> +#include <qa_ccomplex_dotprod_x86.h> +#include <ccomplex_dotprod_x86.h> +#include <string.h> +#include <iostream> +#include <malloc16.h> +#include <sse_debug.h> +#include <cmath> +#include <gr_cpu.h> +#include <random.h> + +using std::cerr; + +/// Macro for primitive value comparisons +#define assertcomplexEqual(expected0,expected1,actual,delta) \ + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected0, actual[0], delta); \ + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected1, actual[1], delta); + + +#define MAX_BLKS 10 +#define FLOATS_PER_BLK 4 + +#define ERR_DELTA (1e-6) + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_floats (float *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = rint (uniform () * 32767); +} + +static void +zero_floats (float *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = 0.0; +} + +void +ref_ccomplex_dotprod (const float *input, + const float *taps, unsigned n_2_ccomplex_blocks, + float *result) +{ + float sum0[2] = {0,0}; + float sum1[2] = {0,0}; + + do { + + sum0[0] += input[0] * taps[0] - input[1] * taps[1]; + sum0[1] += input[0] * taps[1] + input[1] * taps[0]; + sum1[0] += input[2] * taps[2] - input[3] * taps[3]; + sum1[1] += input[2] * taps[3] + input[3] * taps[2]; + + input += 4; + taps += 4; + + } while (--n_2_ccomplex_blocks != 0); + + + result[0] = sum0[0] + sum1[0]; + result[1] = sum0[1] + sum1[1]; +} + +void +qa_ccomplex_dotprod_x86::setUp () +{ + taps = (float *) calloc16Align (MAX_BLKS, + sizeof (float) * FLOATS_PER_BLK); + + input = (float *) calloc16Align (MAX_BLKS, + sizeof (float) * FLOATS_PER_BLK); + + if (taps == 0 || input == 0) + abort (); +} + +void +qa_ccomplex_dotprod_x86::tearDown () +{ + free16Align (taps); + free16Align (input); + taps = 0; + input = 0; +} + + +void +qa_ccomplex_dotprod_x86::zb () // "zero both" +{ + zero_floats (taps, MAX_BLKS * FLOATS_PER_BLK); + zero_floats (input, MAX_BLKS * FLOATS_PER_BLK); +} + +// +// t1 +// + +void +qa_ccomplex_dotprod_x86::t1_base (ccomplex_dotprod_t ccomplex_dotprod) +{ + float result[2]; + + // cerr << "Testing dump_xmm_regs\n"; + // dump_xmm_regs (); + + // test basic cases, 1 block + + zb (); + ccomplex_dotprod (input, taps, 1, result); + assertcomplexEqual (0.0, 0.0, result, ERR_DELTA); + + // vary each input + + zb (); + input[0] = 1.0; taps[0] = 1.0; taps[1] = -1.0; + ccomplex_dotprod (input, taps, 1, result); + //cerr << result[0] << " " << result[1] << "\n"; + assertcomplexEqual (1.0, -1.0, result, ERR_DELTA); + + zb (); + input[1] = 2.0; taps[0] = 1.0; taps[1] = -1.0; + ccomplex_dotprod (input, taps, 1, result); + assertcomplexEqual (2.0, 2.0, result, ERR_DELTA); + + zb (); + input[2] = 3.0; taps[2] = 1.0; taps[3] = -1.0; + ccomplex_dotprod (input, taps, 1, result); + assertcomplexEqual (3.0, -3.0, result, ERR_DELTA); + + zb (); + input[3] = 4.0; taps[2] = 1.0; taps[3] = -1.0; + ccomplex_dotprod (input, taps, 1, result); + assertcomplexEqual (4.0, 4.0, result, ERR_DELTA); + + // vary each tap + + zb (); + input[0] = 1.0; taps[0] = 0.5; taps[1] = -0.5; + ccomplex_dotprod (input, taps, 1, result); + assertcomplexEqual (0.5, -0.5, result, ERR_DELTA); + + zb (); + input[0] = 1.0; taps[0] = 2.0; taps[1] = -2.0; + ccomplex_dotprod (input, taps, 1, result); + assertcomplexEqual (2.0, -2.0, result, ERR_DELTA); + + zb (); + input[0] = 1.0; taps[0] = 3.0; taps[1] = -3.0; + ccomplex_dotprod (input, taps, 1, result); + assertcomplexEqual (3.0, -3.0, result, ERR_DELTA); + + zb (); + input[0] = 1.0; taps[0] = 4.0; taps[1] = -4.0; + ccomplex_dotprod (input, taps, 1, result); + assertcomplexEqual (4.0, -4.0, result, ERR_DELTA); +} + +// +// t2 +// +void +qa_ccomplex_dotprod_x86::t2_base (ccomplex_dotprod_t ccomplex_dotprod) +{ + float result[2]; + + zb (); + input[0] = 1.0; input[1] = 3.0; taps[0] = 5.0; taps[1] = -2.0; + + //1*5-3*-2 =11, 1*-2+3*5=13 + + ccomplex_dotprod (input, taps, 1, result); + assertcomplexEqual (11.0, 13.0, result, ERR_DELTA); + + //7*5-13*-5 =100, 7*-5+13*5=30 + + input[2] = 7.0; input[3] = 13.0; taps[2] = 5.0; taps[3] = -5.0; + + ccomplex_dotprod (input, taps, 1, result); + assertcomplexEqual (111.0, 43.0, result, ERR_DELTA); + + input[4] = 19; input[5] = -19; taps[4] = 23.0; taps[5] = -23.0; + + //19*23--19*-23 =0, 19*-23+-19*23=-874 + + ccomplex_dotprod (input, taps, 2, result); + assertcomplexEqual (111.0, -831.0, result, ERR_DELTA); + +} + +// +// t3 +// +void +qa_ccomplex_dotprod_x86::t3_base (ccomplex_dotprod_t ccomplex_dotprod) +{ + srandom (0); // we want reproducibility + + for (unsigned int i = 0; i < 10; i++){ + random_floats (input, MAX_BLKS * FLOATS_PER_BLK); + random_floats (taps, MAX_BLKS * FLOATS_PER_BLK); + + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + float ref[2]; + ref_ccomplex_dotprod (input, taps, MAX_BLKS, ref); + float calc[2]; + ccomplex_dotprod (input, taps, MAX_BLKS, calc); + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref[0], + calc[0], + fabs (ref[0]) * 1e-4); + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref[1], + calc[1], + fabs (ref[1]) * 1e-4); + } +} + +void +qa_ccomplex_dotprod_x86::t1_3dnowext () +{ + if (!gr_cpu::has_3dnowext ()){ + cerr << "No 3DNow!Ext support; not tested\n"; + } + else + t1_base (ccomplex_dotprod_3dnowext); +} + +void +qa_ccomplex_dotprod_x86::t2_3dnowext () +{ + if (!gr_cpu::has_3dnowext ()){ + cerr << "No 3DNow!Ext support; not tested\n"; + } + else + t2_base (ccomplex_dotprod_3dnowext); +} + +void +qa_ccomplex_dotprod_x86::t3_3dnowext () +{ + if (!gr_cpu::has_3dnowext ()){ + cerr << "No 3DNow!Ext support; not tested\n"; + } + else + t3_base (ccomplex_dotprod_3dnowext); +} + +void +qa_ccomplex_dotprod_x86::t1_3dnow () +{ + if (!gr_cpu::has_3dnow ()){ + cerr << "No 3DNow! support; not tested\n"; + } + else + t1_base (ccomplex_dotprod_3dnow); +} + +void +qa_ccomplex_dotprod_x86::t2_3dnow () +{ + if (!gr_cpu::has_3dnow ()){ + cerr << "No 3DNow! support; not tested\n"; + } + else + t2_base (ccomplex_dotprod_3dnow); +} + +void +qa_ccomplex_dotprod_x86::t3_3dnow () +{ + if (!gr_cpu::has_3dnow ()){ + cerr << "No 3DNow! support; not tested\n"; + } + else + t3_base (ccomplex_dotprod_3dnow); +} + +void +qa_ccomplex_dotprod_x86::t1_sse () +{ + if (!gr_cpu::has_sse ()){ + cerr << "No SSE support; not tested\n"; + } + else + t1_base (ccomplex_dotprod_sse); +} + +void +qa_ccomplex_dotprod_x86::t2_sse () +{ + if (!gr_cpu::has_sse ()){ + cerr << "No SSE support; not tested\n"; + } + else + t2_base (ccomplex_dotprod_sse); +} + +void +qa_ccomplex_dotprod_x86::t3_sse () +{ + if (!gr_cpu::has_sse ()){ + cerr << "No SSE support; not tested\n"; + } + else + t3_base (ccomplex_dotprod_sse); +} + diff --git a/gnuradio-core/src/lib/filter/qa_ccomplex_dotprod_x86.h b/gnuradio-core/src/lib/filter/qa_ccomplex_dotprod_x86.h new file mode 100644 index 000000000..d24561c72 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_ccomplex_dotprod_x86.h @@ -0,0 +1,74 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_CCOMPLEX_DOTPROD_X86_H_ +#define _QA_CCOMPLEX_DOTPROD_X86_H_ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_ccomplex_dotprod_x86 : public CppUnit::TestCase { + public: + void setUp (); + void tearDown (); + + CPPUNIT_TEST_SUITE (qa_ccomplex_dotprod_x86); + CPPUNIT_TEST (t1_3dnowext); + CPPUNIT_TEST (t2_3dnowext); + CPPUNIT_TEST (t3_3dnowext); + CPPUNIT_TEST (t1_3dnow); + CPPUNIT_TEST (t2_3dnow); + CPPUNIT_TEST (t3_3dnow); + CPPUNIT_TEST (t1_sse); + CPPUNIT_TEST (t2_sse); + CPPUNIT_TEST (t3_sse); + CPPUNIT_TEST_SUITE_END (); + + private: + + void t1_3dnowext (); + void t2_3dnowext (); + void t3_3dnowext (); + void t1_3dnow (); + void t2_3dnow (); + void t3_3dnow (); + void t1_sse (); + void t2_sse (); + void t3_sse (); + + + typedef void (*ccomplex_dotprod_t)(const float *input, + const float *taps, + unsigned n_2_ccomplex_blocks, + float *result); + + void t1_base (ccomplex_dotprod_t); + void t2_base (ccomplex_dotprod_t); + void t3_base (ccomplex_dotprod_t); + + void zb (); + + float *taps; // 16-byte aligned + float *input; // 16-byte aligned +}; + + +#endif /* _QA_CCOMPLEX_DOTPROD_X86_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_complex_dotprod_x86.cc b/gnuradio-core/src/lib/filter/qa_complex_dotprod_x86.cc new file mode 100644 index 000000000..a21b95f63 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_complex_dotprod_x86.cc @@ -0,0 +1,347 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 <cppunit/TestAssert.h> +#include <qa_complex_dotprod_x86.h> +#include <complex_dotprod_x86.h> +#include <string.h> +#include <iostream> +#include <malloc16.h> +#include <sse_debug.h> +#include <cmath> +#include <gr_cpu.h> +#include <random.h> + +using std::cerr; + +/// Macro for primitive value comparisons +#define assertcomplexEqual(expected0,expected1,actual,delta) \ + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected0, actual[0], delta); \ + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected1, actual[1], delta); + + +#define MAX_BLKS 10 +#define FLOATS_PER_BLK 4 +#define SHORTS_PER_BLK 2 + +#define ERR_DELTA (1e-6) + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_floats (float *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = rint (uniform () * 32767); +} + +static void +zero_floats (float *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = 0.0; +} + +static void +random_shorts (short *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = (short) rint (uniform () * 32767); +} + +static void +zero_shorts (short *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = 0; +} + +void +ref_complex_dotprod (const short *input, + const float *taps, unsigned n_2_complex_blocks, + float *result) +{ + float sum0[2] = {0,0}; + float sum1[2] = {0,0}; + + do { + + sum0[0] += input[0] * taps[0]; + sum0[1] += input[0] * taps[1]; + sum1[0] += input[1] * taps[2]; + sum1[1] += input[1] * taps[3]; + + input += 2; + taps += 4; + + } while (--n_2_complex_blocks != 0); + + + result[0] = sum0[0] + sum1[0]; + result[1] = sum0[1] + sum1[1]; +} + +void +qa_complex_dotprod_x86::setUp () +{ + taps = (float *) calloc16Align (MAX_BLKS, + sizeof (float) * FLOATS_PER_BLK); + + input = (short *) calloc16Align (MAX_BLKS, + sizeof (short) * SHORTS_PER_BLK); + + if (taps == 0 || input == 0) + abort (); +} + +void +qa_complex_dotprod_x86::tearDown () +{ + free16Align (taps); + free16Align (input); + taps = 0; + input = 0; +} + + +void +qa_complex_dotprod_x86::zb () // "zero both" +{ + zero_floats (taps, MAX_BLKS * FLOATS_PER_BLK); + zero_shorts (input, MAX_BLKS * SHORTS_PER_BLK); +} + +// +// t1 +// + +void +qa_complex_dotprod_x86::t1_base (complex_dotprod_t complex_dotprod) +{ + float result[2]; + + // cerr << "Testing dump_xmm_regs\n"; + // dump_xmm_regs (); + + // test basic cases, 1 block + + zb (); + complex_dotprod (input, taps, 1, result); + assertcomplexEqual (0.0, 0.0, result, ERR_DELTA); + + // vary each input + + zb (); + input[0] = 1; taps[0] = 1.0; taps[1] = -1.0; + complex_dotprod (input, taps, 1, result); + //cerr << result[0] << " " << result[1] << "\n"; + assertcomplexEqual (1.0, -1.0, result, ERR_DELTA); + + zb (); + input[1] = 2; taps[2] = 1.0; taps[3] = -1.0; + complex_dotprod (input, taps, 1, result); + assertcomplexEqual (2.0, -2.0, result, ERR_DELTA); + + zb (); + input[2] = 3; taps[4] = 1.0; taps[5] = -1.0; + complex_dotprod (input, taps, 2, result); + assertcomplexEqual (3.0, -3.0, result, ERR_DELTA); + + zb (); + input[3] = 4; taps[6] = 1.0; taps[7] = -1.0; + complex_dotprod (input, taps, 2, result); + assertcomplexEqual (4.0, -4.0, result, ERR_DELTA); + + // vary each tap + + zb (); + input[0] = 1; taps[0] = 0.5; taps[1] = -0.5; + complex_dotprod (input, taps, 1, result); + assertcomplexEqual (0.5, -0.5, result, ERR_DELTA); + + zb (); + input[0] = 1; taps[0] = 2.0; taps[1] = -2.0; + complex_dotprod (input, taps, 1, result); + assertcomplexEqual (2.0, -2.0, result, ERR_DELTA); + + zb (); + input[0] = 1; taps[0] = 3.0; taps[1] = -3.0; + complex_dotprod (input, taps, 1, result); + assertcomplexEqual (3.0, -3.0, result, ERR_DELTA); + + zb (); + input[0] = 1; taps[0] = 4.0; taps[1] = -4.0; + complex_dotprod (input, taps, 1, result); + assertcomplexEqual (4.0, -4.0, result, ERR_DELTA); +} + +// +// t2 +// +void +qa_complex_dotprod_x86::t2_base (complex_dotprod_t complex_dotprod) +{ + float result[2]; + + zb (); + input[0] = 1; taps[0] = 2.0; taps[1] = -2.0; + input[1] = 3; taps[2] = 5.0; taps[3] = -5.0; + input[2] = 7; taps[4] = 11.0; taps[5] = -11.0; + input[3] = 13; taps[6] = 17.0; taps[7] = -17.0; + + complex_dotprod (input, taps, 2, result); + assertcomplexEqual (315.0, -315.0, result, ERR_DELTA); + + input[4] = 19; taps[8] = 23.0; taps[9] = -23.0; + complex_dotprod (input, taps, 3, result); + assertcomplexEqual (752.0, -752.0, result, ERR_DELTA); + +} + +// +// t3 +// +void +qa_complex_dotprod_x86::t3_base (complex_dotprod_t complex_dotprod) +{ + srandom (0); // we want reproducibility + + for (unsigned int i = 0; i < 10; i++){ + random_shorts (input, MAX_BLKS * SHORTS_PER_BLK); + random_floats (taps, MAX_BLKS * FLOATS_PER_BLK); + + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + float ref[2]; + ref_complex_dotprod (input, taps, MAX_BLKS, ref); + float calc[2]; + complex_dotprod (input, taps, MAX_BLKS, calc); + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref[0], + calc[0], + fabs (ref[0]) * 1e-4); + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref[1], + calc[1], + fabs (ref[1]) * 1e-4); + } +} + +void +qa_complex_dotprod_x86::t1_3dnowext () +{ + if (!gr_cpu::has_3dnowext ()){ + cerr << "No 3DNow!Ext support; not tested\n"; + } + else + t1_base (complex_dotprod_3dnowext); +} + +void +qa_complex_dotprod_x86::t2_3dnowext () +{ + if (!gr_cpu::has_3dnowext ()){ + cerr << "No 3DNow!Ext support; not tested\n"; + } + else + t2_base (complex_dotprod_3dnowext); +} + +void +qa_complex_dotprod_x86::t3_3dnowext () +{ + if (!gr_cpu::has_3dnowext ()){ + cerr << "No 3DNow!Ext support; not tested\n"; + } + else + t3_base (complex_dotprod_3dnowext); +} + +void +qa_complex_dotprod_x86::t1_3dnow () +{ + if (!gr_cpu::has_3dnow ()){ + cerr << "No 3DNow! support; not tested\n"; + } + else + t1_base (complex_dotprod_3dnow); +} + +void +qa_complex_dotprod_x86::t2_3dnow () +{ + if (!gr_cpu::has_3dnow ()){ + cerr << "No 3DNow! support; not tested\n"; + } + else + t2_base (complex_dotprod_3dnow); +} + +void +qa_complex_dotprod_x86::t3_3dnow () +{ + if (!gr_cpu::has_3dnow ()){ + cerr << "No 3DNow! support; not tested\n"; + } + else + t3_base (complex_dotprod_3dnow); +} + +void +qa_complex_dotprod_x86::t1_sse () +{ + if (!gr_cpu::has_sse ()){ + cerr << "No SSE support; not tested\n"; + } + else + t1_base (complex_dotprod_sse); +} + +void +qa_complex_dotprod_x86::t2_sse () +{ + if (!gr_cpu::has_sse ()){ + cerr << "No SSE support; not tested\n"; + } + else + t2_base (complex_dotprod_sse); +} + +void +qa_complex_dotprod_x86::t3_sse () +{ + if (!gr_cpu::has_sse ()){ + cerr << "No SSE support; not tested\n"; + } + else + t3_base (complex_dotprod_sse); +} + diff --git a/gnuradio-core/src/lib/filter/qa_complex_dotprod_x86.h b/gnuradio-core/src/lib/filter/qa_complex_dotprod_x86.h new file mode 100644 index 000000000..9f9b46039 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_complex_dotprod_x86.h @@ -0,0 +1,74 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_COMPLEX_DOTPROD_X86_H_ +#define _QA_COMPLEX_DOTPROD_X86_H_ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_complex_dotprod_x86 : public CppUnit::TestCase { + public: + void setUp (); + void tearDown (); + + CPPUNIT_TEST_SUITE (qa_complex_dotprod_x86); + CPPUNIT_TEST (t1_3dnowext); + CPPUNIT_TEST (t2_3dnowext); + CPPUNIT_TEST (t3_3dnowext); + CPPUNIT_TEST (t1_3dnow); + CPPUNIT_TEST (t2_3dnow); + CPPUNIT_TEST (t3_3dnow); + CPPUNIT_TEST (t1_sse); + CPPUNIT_TEST (t2_sse); + CPPUNIT_TEST (t3_sse); + CPPUNIT_TEST_SUITE_END (); + + private: + + void t1_3dnowext (); + void t2_3dnowext (); + void t3_3dnowext (); + void t1_3dnow (); + void t2_3dnow (); + void t3_3dnow (); + void t1_sse (); + void t2_sse (); + void t3_sse (); + + + typedef void (*complex_dotprod_t)(const short *input, + const float *taps, + unsigned n_2_complex_blocks, + float *result); + + void t1_base (complex_dotprod_t); + void t2_base (complex_dotprod_t); + void t3_base (complex_dotprod_t); + + void zb (); + + float *taps; // 16-byte aligned + short *input; // 16-byte aligned +}; + + +#endif /* _QA_COMPLEX_DOTPROD_X86_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_dotprod.h b/gnuradio-core/src/lib/filter/qa_dotprod.h new file mode 100644 index 000000000..bd5ba8f3a --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_dotprod.h @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 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_DOTPROD_H_ +#define _QA_DOTPROD_H_ + +#include <cppunit/TestSuite.h> + +CppUnit::TestSuite *qa_dotprod_suite (); + +#endif // _QA_DOTPROD_H_ + diff --git a/gnuradio-core/src/lib/filter/qa_dotprod_armv7_a.cc b/gnuradio-core/src/lib/filter/qa_dotprod_armv7_a.cc new file mode 100644 index 000000000..1e1ded7ea --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_dotprod_armv7_a.cc @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2009 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 "qa_dotprod.h" + +CppUnit::TestSuite * +qa_dotprod_suite () +{ + CppUnit::TestSuite *s = new CppUnit::TestSuite ("dotprod"); + + // empty test suite + + return s; +} diff --git a/gnuradio-core/src/lib/filter/qa_dotprod_generic.cc b/gnuradio-core/src/lib/filter/qa_dotprod_generic.cc new file mode 100644 index 000000000..2c49d1d28 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_dotprod_generic.cc @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 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 "qa_dotprod.h" + +CppUnit::TestSuite * +qa_dotprod_suite () +{ + CppUnit::TestSuite *s = new CppUnit::TestSuite ("dotprod"); + + // empty test suite + + return s; +} diff --git a/gnuradio-core/src/lib/filter/qa_dotprod_powerpc.cc b/gnuradio-core/src/lib/filter/qa_dotprod_powerpc.cc new file mode 100644 index 000000000..2c49d1d28 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_dotprod_powerpc.cc @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 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 "qa_dotprod.h" + +CppUnit::TestSuite * +qa_dotprod_suite () +{ + CppUnit::TestSuite *s = new CppUnit::TestSuite ("dotprod"); + + // empty test suite + + return s; +} diff --git a/gnuradio-core/src/lib/filter/qa_dotprod_x86.cc b/gnuradio-core/src/lib/filter/qa_dotprod_x86.cc new file mode 100644 index 000000000..ec5625f10 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_dotprod_x86.cc @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 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 "qa_dotprod.h" +#include "qa_float_dotprod_x86.h" +#include "qa_complex_dotprod_x86.h" +#include "qa_ccomplex_dotprod_x86.h" + +CppUnit::TestSuite * +qa_dotprod_suite () +{ + CppUnit::TestSuite *s = new CppUnit::TestSuite ("dotprod"); + + s->addTest (qa_float_dotprod_x86::suite ()); + s->addTest (qa_complex_dotprod_x86::suite ()); + s->addTest (qa_ccomplex_dotprod_x86::suite ()); + + return s; +} diff --git a/gnuradio-core/src/lib/filter/qa_filter.cc b/gnuradio-core/src/lib/filter/qa_filter.cc new file mode 100644 index 000000000..629635084 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_filter.cc @@ -0,0 +1,68 @@ +/* + * Copyright 2002,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. + */ + +/* + * This class gathers together all the test cases for the gr + * directory into a single test suite. As you create new test cases, + * add them here. + */ + +#include <qa_filter.h> +#include <qa_gr_fir_ccf.h> +#include <qa_gr_fir_fff.h> +#include <qa_gr_fir_ccc.h> +#include <qa_gr_fir_fcc.h> +#include <qa_gr_fir_scc.h> +#include <qa_gr_firdes.h> +#include <qa_dotprod.h> +#include <qa_gri_mmse_fir_interpolator.h> +#include <qa_gri_mmse_fir_interpolator_cc.h> +#include <qa_gr_rotator.h> +#include <qa_gri_fir_filter_with_buffer_ccf.h> +#include <qa_gri_fir_filter_with_buffer_ccc.h> +#include <qa_gri_fir_filter_with_buffer_fcc.h> +#include <qa_gri_fir_filter_with_buffer_fff.h> +#include <qa_gri_fir_filter_with_buffer_fsf.h> +#include <qa_gri_fir_filter_with_buffer_scc.h> + +CppUnit::TestSuite * +qa_filter::suite () +{ + CppUnit::TestSuite *s = new CppUnit::TestSuite ("filter"); + + s->addTest (qa_dotprod_suite ()); + s->addTest (qa_gr_fir_fff::suite ()); + s->addTest (qa_gr_fir_ccc::suite ()); + s->addTest (qa_gr_fir_fcc::suite ()); + s->addTest (qa_gr_fir_scc::suite ()); + s->addTest (qa_gr_fir_ccf::suite ()); + s->addTest (qa_gri_mmse_fir_interpolator::suite ()); + s->addTest (qa_gri_mmse_fir_interpolator_cc::suite ()); + s->addTest (qa_gr_rotator::suite ()); + s->addTest (qa_gri_fir_filter_with_buffer_ccf::suite ()); + s->addTest (qa_gri_fir_filter_with_buffer_ccc::suite ()); + s->addTest (qa_gri_fir_filter_with_buffer_fcc::suite ()); + s->addTest (qa_gri_fir_filter_with_buffer_fff::suite ()); + s->addTest (qa_gri_fir_filter_with_buffer_fsf::suite ()); + s->addTest (qa_gri_fir_filter_with_buffer_scc::suite ()); + + return s; +} diff --git a/gnuradio-core/src/lib/filter/qa_filter.h b/gnuradio-core/src/lib/filter/qa_filter.h new file mode 100644 index 000000000..740d05ce4 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_filter.h @@ -0,0 +1,38 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_FILTER_H_ +#define _QA_FILTER_H_ + +#include <gruel/attributes.h> +#include <cppunit/TestSuite.h> + +//! collect all the tests for the gr directory + +class __GR_ATTR_EXPORT qa_filter { + public: + //! return suite of tests for all of gr directory + static CppUnit::TestSuite *suite (); +}; + + +#endif /* _QA_FILTER_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_float_dotprod_x86.cc b/gnuradio-core/src/lib/filter/qa_float_dotprod_x86.cc new file mode 100644 index 000000000..f8752d071 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_float_dotprod_x86.cc @@ -0,0 +1,270 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 <cppunit/TestAssert.h> +#include <qa_float_dotprod_x86.h> +#include <float_dotprod_x86.h> +#include <string.h> +#include <iostream> +#include <malloc16.h> +#include <sse_debug.h> +#include <cmath> +#include <gr_cpu.h> +#include <random.h> + +using std::cerr; + + +#define MAX_BLKS 10 +#define FLOATS_PER_BLK 4 + +#define ERR_DELTA (1e-6) + + +static void +random_floats (float *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = random () - RANDOM_MAX/2; +} + +static void +zero_floats (float *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = 0.0; +} + +float +ref_float_dotprod (const float *input, + const float *taps, unsigned n_4_float_blocks) +{ + float sum0 = 0; + float sum1 = 0; + float sum2 = 0; + float sum3 = 0; + + do { + + sum0 += input[0] * taps[0]; + sum1 += input[1] * taps[1]; + sum2 += input[2] * taps[2]; + sum3 += input[3] * taps[3]; + + input += 4; + taps += 4; + + } while (--n_4_float_blocks != 0); + + + return sum0 + sum1 + sum2 + sum3; +} + +void +qa_float_dotprod_x86::setUp () +{ + taps = (float *) calloc16Align (MAX_BLKS, + sizeof (float) * FLOATS_PER_BLK); + + input = (float *) calloc16Align (MAX_BLKS, + sizeof (float) * FLOATS_PER_BLK); + + if (taps == 0 || input == 0) + abort (); +} + +void +qa_float_dotprod_x86::tearDown () +{ + free16Align (taps); + free16Align (input); + taps = 0; + input = 0; +} + + +void +qa_float_dotprod_x86::zb () // "zero both" +{ + zero_floats (taps, MAX_BLKS * FLOATS_PER_BLK); + zero_floats (input, MAX_BLKS * FLOATS_PER_BLK); +} + +// +// t1 +// + +void +qa_float_dotprod_x86::t1_base (float_dotprod_t float_dotprod) +{ + + // cerr << "Testing dump_xmm_regs\n"; + // dump_xmm_regs (); + + // test basic cases, 1 block + + zb (); + CPPUNIT_ASSERT_DOUBLES_EQUAL (0.0, float_dotprod (input, taps, 1), ERR_DELTA); + + // vary each input + + zb (); + input[0] = 0.5; taps[0] = 1.0; + CPPUNIT_ASSERT_DOUBLES_EQUAL (0.5, float_dotprod (input, taps, 1), ERR_DELTA); + + zb (); + input[1] = 2.0; taps[1] = 1.0; + CPPUNIT_ASSERT_DOUBLES_EQUAL (2.0, float_dotprod (input, taps, 1), ERR_DELTA); + + zb (); + input[2] = 3.0; taps[2] = 1.0; + CPPUNIT_ASSERT_DOUBLES_EQUAL (3.0, float_dotprod (input, taps, 1), ERR_DELTA); + + zb (); + input[3] = 4.0; taps[3] = 1.0; + CPPUNIT_ASSERT_DOUBLES_EQUAL (4.0, float_dotprod (input, taps, 1), ERR_DELTA); + + // vary each tap + + zb (); + input[0] = 1.0; taps[0] = 0.5; + CPPUNIT_ASSERT_DOUBLES_EQUAL (0.5, float_dotprod (input, taps, 1), ERR_DELTA); + + zb (); + input[0] = 1.0; taps[0] = 2.0; + CPPUNIT_ASSERT_DOUBLES_EQUAL (2.0, float_dotprod (input, taps, 1), ERR_DELTA); + + zb (); + input[0] = 1.0; taps[0] = 3.0; + CPPUNIT_ASSERT_DOUBLES_EQUAL (3.0, float_dotprod (input, taps, 1), ERR_DELTA); + + zb (); + input[0] = 1.0; taps[0] = 4.0; + CPPUNIT_ASSERT_DOUBLES_EQUAL (4.0, float_dotprod (input, taps, 1), ERR_DELTA); +} + +// +// t2 +// +void +qa_float_dotprod_x86::t2_base (float_dotprod_t float_dotprod) +{ + zb (); + input[0] = 1.0; taps[0] = 2.0; + input[1] = 3.0; taps[1] = 5.0; + input[2] = 7.0; taps[2] = 11.0; + input[3] = 13.0; taps[3] = 17.0; + + CPPUNIT_ASSERT_DOUBLES_EQUAL (315.0, float_dotprod (input, taps, 1), ERR_DELTA); + + input[4] = 19.0; taps[4] = 23.0; + CPPUNIT_ASSERT_DOUBLES_EQUAL (752.0, float_dotprod (input, taps, 2), ERR_DELTA); + +} + +// +// t3 +// +void +qa_float_dotprod_x86::t3_base (float_dotprod_t float_dotprod) +{ + srandom (0); // we want reproducibility + + for (unsigned int i = 0; i < 10; i++){ + random_floats (input, MAX_BLKS * FLOATS_PER_BLK); + random_floats (taps, MAX_BLKS * FLOATS_PER_BLK); + + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + float ref = ref_float_dotprod (input, taps, MAX_BLKS); + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref, + float_dotprod (input, taps, MAX_BLKS), + fabs (ref) * 1e-4); + } +} + +void +qa_float_dotprod_x86::t1_3dnow () +{ + if (!gr_cpu::has_3dnow ()){ + cerr << "No 3DNow! support; not tested\n"; + } + else + t1_base (float_dotprod_3dnow); +} + +void +qa_float_dotprod_x86::t2_3dnow () +{ + if (!gr_cpu::has_3dnow ()){ + cerr << "No 3DNow! support; not tested\n"; + } + else + t2_base (float_dotprod_3dnow); +} + +void +qa_float_dotprod_x86::t3_3dnow () +{ + if (!gr_cpu::has_3dnow ()){ + cerr << "No 3DNow! support; not tested\n"; + } + else + t3_base (float_dotprod_3dnow); +} + +void +qa_float_dotprod_x86::t1_sse () +{ + if (!gr_cpu::has_sse ()){ + cerr << "No SSE support; not tested\n"; + } + else + t1_base (float_dotprod_sse); +} + +void +qa_float_dotprod_x86::t2_sse () +{ + if (!gr_cpu::has_sse ()){ + cerr << "No SSE support; not tested\n"; + } + else + t2_base (float_dotprod_sse); +} + +void +qa_float_dotprod_x86::t3_sse () +{ + if (!gr_cpu::has_sse ()){ + cerr << "No SSE support; not tested\n"; + } + else + t3_base (float_dotprod_sse); +} diff --git a/gnuradio-core/src/lib/filter/qa_float_dotprod_x86.h b/gnuradio-core/src/lib/filter/qa_float_dotprod_x86.h new file mode 100644 index 000000000..38d6104fa --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_float_dotprod_x86.h @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_FLOAT_DOTPROD_X86_H_ +#define _QA_FLOAT_DOTPROD_X86_H_ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_float_dotprod_x86 : public CppUnit::TestCase { + public: + void setUp (); + void tearDown (); + + CPPUNIT_TEST_SUITE (qa_float_dotprod_x86); + CPPUNIT_TEST (t1_3dnow); + CPPUNIT_TEST (t2_3dnow); + CPPUNIT_TEST (t3_3dnow); + CPPUNIT_TEST (t1_sse); + CPPUNIT_TEST (t2_sse); + CPPUNIT_TEST (t3_sse); + CPPUNIT_TEST_SUITE_END (); + + private: + + void t1_3dnow (); + void t2_3dnow (); + void t3_3dnow (); + void t1_sse (); + void t2_sse (); + void t3_sse (); + + + typedef float (*float_dotprod_t)(const float *input, + const float *taps, + unsigned n_4_float_blocks); + + void t1_base (float_dotprod_t); + void t2_base (float_dotprod_t); + void t3_base (float_dotprod_t); + + + void zb (); + + float *taps; // 16-byte aligned + float *input; // 16-byte aligned + +}; + + +#endif /* _QA_FLOAT_DOTPROD_X86_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_gr_fir_ccc.cc b/gnuradio-core/src/lib/filter/qa_gr_fir_ccc.cc new file mode 100644 index 000000000..7474b76e2 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_fir_ccc.cc @@ -0,0 +1,184 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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. + */ + +/* + * FIXME. This code is virtually identical to qa_gr_fir_?CC.cc + * Kludge up some kind of macro to handle the minor differences. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gr_types.h> + +typedef gr_complex i_type; +typedef gr_complex o_type; +typedef gr_complex tap_type; +typedef gr_complex acc_type; + + +#include <qa_gr_fir_ccc.h> +#include <gr_fir_ccc.h> +#include <gr_fir_util.h> +#include <string.h> +#include <iostream> +#include <cmath> +#include <gr_types.h> +#include <cppunit/TestAssert.h> +#include <random.h> +#include <malloc16.h> +#include <string.h> + +using std::vector; + +#define ERR_DELTA (1e-5) + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +// +// typedef for something logically "pointer to constructor". +// there may be a better way, please let me know... +// +typedef gr_fir_ccc* (*fir_maker_t)(const std::vector<tap_type> &taps); + + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_input (i_type *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = (i_type) rint (uniform () * 32767); +} + +static void +random_complex (gr_complex *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++){ + float re = rint (uniform () * 32767); + float im = rint (uniform () * 32767); + buf[i] = gr_complex (re, im); + } +} + +static o_type +ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) +{ + acc_type sum = 0; + for (int i = 0; i < ntaps; i++) + sum += input[i] * taps[ntaps - i - 1]; + + return sum; +} + +// +// Test for ntaps in [0,9], and input lengths in [0,17]. +// This ensures that we are building the shifted taps correctly, +// and exercises all corner cases on input alignment and length. +// + +static void +test_random_io (fir_maker_t maker) +{ + const int MAX_TAPS = 9; + const int OUTPUT_LEN = 17; + const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN; + + // Our SIMD ccc kernel requires that the complex input be 64-bit (8-byte) aligned. + // i_type input[INPUT_LEN]; + i_type *input = (i_type *)malloc16Align(INPUT_LEN * sizeof(i_type)); + o_type expected_output[OUTPUT_LEN]; + o_type actual_output[OUTPUT_LEN]; + tap_type taps[MAX_TAPS]; + + + srandom (0); // we want reproducibility + + for (int n = 0; n <= MAX_TAPS; n++){ + for (int ol = 0; ol <= OUTPUT_LEN; ol++){ + + // cerr << "@@@ n:ol " << n << ":" << ol << endl; + + // build random test case + random_input (input, INPUT_LEN); + random_complex (taps, MAX_TAPS); + + // compute expected output values + for (int o = 0; o < ol; o++){ + expected_output[o] = ref_dotprod (&input[o], taps, n); + } + + // build filter + + vector<tap_type> f1_taps (&taps[0], &taps[n]); + gr_fir_ccc *f1 = maker (f1_taps); + + // zero the output, then do the filtering + memset (actual_output, 0, sizeof (actual_output)); + f1->filterN (actual_output, input, ol); + + // check results + // + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + for (int o = 0; o < ol; o++){ + CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected_output[o], + actual_output[o], + abs (expected_output[o]) * ERR_DELTA); + } + + delete f1; + } + } + free16Align(input); +} + +static void +for_each (void (*f)(fir_maker_t)) +{ + std::vector<gr_fir_ccc_info> info; + gr_fir_util::get_gr_fir_ccc_info (&info); // get all known ccc implementations + + for (std::vector<gr_fir_ccc_info>::iterator p = info.begin (); + p != info.end (); + ++p){ + + std::cerr << " [" << p->name << "]"; + f (p->create); + } + + std::cerr << std::endl; +} + +void +qa_gr_fir_ccc::t1 () +{ + for_each (test_random_io); +} diff --git a/gnuradio-core/src/lib/filter/qa_gr_fir_ccc.h b/gnuradio-core/src/lib/filter/qa_gr_fir_ccc.h new file mode 100644 index 000000000..0535e6652 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_fir_ccc.h @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_GR_FIR_CCC_H_ +#define _QA_GR_FIR_CCC_H_ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_gr_fir_ccc : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_fir_ccc); + CPPUNIT_TEST (t1); + CPPUNIT_TEST_SUITE_END (); + + private: + void t1 (); + +}; + + +#endif /* _QA_GR_FIR_CCC_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_gr_fir_ccf.cc b/gnuradio-core/src/lib/filter/qa_gr_fir_ccf.cc new file mode 100644 index 000000000..84cb924ae --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_fir_ccf.cc @@ -0,0 +1,184 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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. + */ + +/* + * FIXME. This code is virtually identical to qa_gr_fir_?CC.cc + * Kludge up some kind of macro to handle the minor differences. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gr_types.h> + +typedef gr_complex i_type; +typedef gr_complex o_type; +typedef float tap_type; +typedef gr_complex acc_type; + + +#include <qa_gr_fir_ccf.h> +#include <gr_fir_ccf.h> +#include <gr_fir_util.h> +#include <string.h> +#include <iostream> +#include <cmath> +#include <gr_types.h> +#include <cppunit/TestAssert.h> +#include <random.h> +#include <malloc16.h> +#include <string.h> + +using std::vector; + +#define ERR_DELTA (1e-5) + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +// +// typedef for something logically "pointer to constructor". +// there may be a better way, please let me know... +// +typedef gr_fir_ccf* (*fir_maker_t)(const std::vector<tap_type> &taps); + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_floats (float *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = (float) rint (uniform () * 32767); +} + +static void +random_complex (gr_complex *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++){ + float re = rint (uniform () * 32767); + float im = rint (uniform () * 32767); + buf[i] = gr_complex (re, im); + } +} + +static o_type +ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) +{ + acc_type sum = 0; + for (int i = 0; i < ntaps; i++) + sum += input[i] * taps[ntaps - i - 1]; + + return sum; +} + +// +// Test for ntaps in [0,9], and input lengths in [0,17]. +// This ensures that we are building the shifted taps correctly, +// and exercises all corner cases on input alignment and length. +// + +static void +test_random_io (fir_maker_t maker) +{ + const int MAX_TAPS = 9; + const int OUTPUT_LEN = 17; + const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN; + + // Our SIMD ccc kernel requires that the complex input be 64-bit (8-byte) aligned. + //i_type input[INPUT_LEN]; + i_type *input = (i_type *)malloc16Align(INPUT_LEN * sizeof(i_type)); + o_type expected_output[OUTPUT_LEN]; + o_type actual_output[OUTPUT_LEN]; + tap_type taps[MAX_TAPS]; + + + srandom (0); // we want reproducibility + + for (int n = 0; n <= MAX_TAPS; n++){ + for (int ol = 0; ol <= OUTPUT_LEN; ol++){ + + // cerr << "@@@ n:ol " << n << ":" << ol << endl; + + // build random test case + random_complex (input, INPUT_LEN); + random_floats (taps, MAX_TAPS); + + // compute expected output values + for (int o = 0; o < ol; o++){ + expected_output[o] = ref_dotprod (&input[o], taps, n); + } + + // build filter + + vector<tap_type> f1_taps (&taps[0], &taps[n]); + gr_fir_ccf *f1 = maker (f1_taps); + + // zero the output, then do the filtering + memset (actual_output, 0, sizeof (actual_output)); + f1->filterN (actual_output, input, ol); + + // check results + // + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + for (int o = 0; o < ol; o++){ + CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected_output[o], actual_output[o], + abs (expected_output[o]) * ERR_DELTA); + } + + delete f1; + } + } + free16Align(input); +} + + +static void +for_each (void (*f)(fir_maker_t)) +{ + std::vector<gr_fir_ccf_info> info; + gr_fir_util::get_gr_fir_ccf_info (&info); // get all known ccf implementations + + for (std::vector<gr_fir_ccf_info>::iterator p = info.begin (); + p != info.end (); + ++p){ + + std::cerr << " [" << p->name << "]"; + f (p->create); + } + + std::cerr << std::endl; +} + + +void +qa_gr_fir_ccf::t1 () +{ + for_each (test_random_io); +} diff --git a/gnuradio-core/src/lib/filter/qa_gr_fir_ccf.h b/gnuradio-core/src/lib/filter/qa_gr_fir_ccf.h new file mode 100644 index 000000000..bda79cc2f --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_fir_ccf.h @@ -0,0 +1,43 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_GR_FIR_CCF_H_ +#define _QA_GR_FIR_CCF_H_ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_gr_fir_ccf : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_fir_ccf); + CPPUNIT_TEST (t1); + CPPUNIT_TEST_SUITE_END (); + + private: + + void t1 (); + // void t2 (); + // void t3 (); + +}; + + +#endif /* _QA_GR_FIR_CCF_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_gr_fir_fcc.cc b/gnuradio-core/src/lib/filter/qa_gr_fir_fcc.cc new file mode 100644 index 000000000..4c77a5e5c --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_fir_fcc.cc @@ -0,0 +1,181 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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. + */ + +/* + * FIXME. This code is virtually identical to qa_gr_fir_?CC.cc + * Kludge up some kind of macro to handle the minor differences. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gr_types.h> + +typedef float i_type; +typedef gr_complex o_type; +typedef gr_complex tap_type; +typedef gr_complex acc_type; + + +#include <qa_gr_fir_fcc.h> +#include <gr_fir_fcc.h> +#include <gr_fir_util.h> +#include <string.h> +#include <iostream> +#include <cmath> +#include <gr_types.h> +#include <cppunit/TestAssert.h> +#include <random.h> +#include <string.h> + +using std::vector; + +#define ERR_DELTA (1e-5) + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + + +// +// typedef for something logically "pointer to constructor". +// there may be a better way, please let me know... +// +typedef gr_fir_fcc* (*fir_maker_t)(const std::vector<tap_type> &taps); + + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_input (i_type *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = (i_type) rint (uniform () * 32767); +} + +static void +random_complex (gr_complex *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++){ + float re = rint (uniform () * 32767); + float im = rint (uniform () * 32767); + buf[i] = gr_complex (re, im); + } +} + +static o_type +ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) +{ + acc_type sum = 0; + for (int i = 0; i < ntaps; i++) + sum += input[i] * taps[ntaps - i - 1]; + + return sum; +} + +// +// Test for ntaps in [0,9], and input lengths in [0,17]. +// This ensures that we are building the shifted taps correctly, +// and exercises all corner cases on input alignment and length. +// + +static void +test_random_io (fir_maker_t maker) +{ + const int MAX_TAPS = 9; + const int OUTPUT_LEN = 17; + const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN; + + i_type input[INPUT_LEN]; + o_type expected_output[OUTPUT_LEN]; + o_type actual_output[OUTPUT_LEN]; + tap_type taps[MAX_TAPS]; + + + srandom (0); // we want reproducibility + + for (int n = 0; n <= MAX_TAPS; n++){ + for (int ol = 0; ol <= OUTPUT_LEN; ol++){ + + // cerr << "@@@ n:ol " << n << ":" << ol << endl; + + // build random test case + random_input (input, INPUT_LEN); + random_complex (taps, MAX_TAPS); + + // compute expected output values + for (int o = 0; o < ol; o++){ + expected_output[o] = ref_dotprod (&input[o], taps, n); + } + + // build filter + + vector<tap_type> f1_taps (&taps[0], &taps[n]); + gr_fir_fcc *f1 = maker (f1_taps); + + // zero the output, then do the filtering + memset (actual_output, 0, sizeof (actual_output)); + f1->filterN (actual_output, input, ol); + + // check results + // + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + for (int o = 0; o < ol; o++){ + CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected_output[o], + actual_output[o], + abs (expected_output[o]) * ERR_DELTA); + } + + delete f1; + } + } +} + +static void +for_each (void (*f)(fir_maker_t)) +{ + std::vector<gr_fir_fcc_info> info; + gr_fir_util::get_gr_fir_fcc_info (&info); // get all known fcc implementations + + for (std::vector<gr_fir_fcc_info>::iterator p = info.begin (); + p != info.end (); + ++p){ + + std::cerr << " [" << p->name << "]"; + f (p->create); + } + + std::cerr << std::endl; +} + +void +qa_gr_fir_fcc::t1 () +{ + for_each (test_random_io); +} diff --git a/gnuradio-core/src/lib/filter/qa_gr_fir_fcc.h b/gnuradio-core/src/lib/filter/qa_gr_fir_fcc.h new file mode 100644 index 000000000..23706fd9c --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_fir_fcc.h @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_GR_FIR_FCC_H_ +#define _QA_GR_FIR_FCC_H_ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_gr_fir_fcc : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_fir_fcc); + CPPUNIT_TEST (t1); + CPPUNIT_TEST_SUITE_END (); + + private: + + void t1 (); +}; + + +#endif /* _QA_GR_FIR_FCC_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_gr_fir_fff.cc b/gnuradio-core/src/lib/filter/qa_gr_fir_fff.cc new file mode 100644 index 000000000..80ed67465 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_fir_fff.cc @@ -0,0 +1,226 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 <qa_gr_fir_fff.h> +#include <gr_fir_fff.h> +#include <gr_fir_util.h> +#include <string.h> +#include <iostream> +#include <cmath> +#include <cppunit/TestAssert.h> +#include <random.h> +#include <string.h> + +using std::vector; + +typedef float i_type; +typedef float o_type; +typedef float tap_type; +typedef float acc_type; + +#define ERR_DELTA (1e-6) + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + + +// +// typedef for something logically "pointer to constructor". +// there may be a better way, please let me know... +// +typedef gr_fir_fff* (*fir_maker_t)(const std::vector<tap_type> &taps); + + +// ---------------------------------------------------------------- + +const static i_type input_1[] = { + 234, -4, 23, -56, 45, 98, -23, -7 +}; + +const static tap_type taps_1a[] = { + -3 +}; + +const static o_type expected_1a[] = { + -702, 12, -69, 168, -135, -294, 69, 21 +}; + +const static tap_type taps_1b[] = { + -4, 5 +}; + +const static o_type expected_1b[] = { + 1186, -112, 339, -460, -167, 582, -87 +}; + +// ---------------------------------------------------------------- + +static void +test_known_io (fir_maker_t maker) +{ + vector<tap_type> t1a (&taps_1a[0], &taps_1a[NELEM (taps_1a)]); + vector<tap_type> t1b (&taps_1b[0], &taps_1b[NELEM (taps_1b)]); + + gr_fir_fff *f1 = maker (t1a); // create filter + CPPUNIT_ASSERT_EQUAL ((unsigned) 1, f1->ntaps ()); // check ntaps + + // check filter output + int n = NELEM (input_1) - f1->ntaps () + 1; + for (int i = 0; i < n; i++) + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected_1a[i], f1->filter (&input_1[i]), ERR_DELTA); + + f1->set_taps (t1b); // set new taps + CPPUNIT_ASSERT_EQUAL ((unsigned) 2, f1->ntaps ()); // check ntaps + + // check filter output + n = NELEM (input_1) - f1->ntaps () + 1; + for (int i = 0; i < n; i++) + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected_1b[i], f1->filter (&input_1[i]), ERR_DELTA); + + // test filterN interface + + o_type output[NELEM (expected_1b)]; + memset (output, 0, sizeof (output)); + + f1->filterN (output, input_1, n); + for (int i = 0; i < n; i++) + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected_1b[i], output[i], ERR_DELTA); + + delete f1; +} + +// +// Test for ntaps in [0,9], and input lengths in [0,17]. +// This ensures that we are building the shifted taps correctly, +// and exercises all corner cases on input alignment and length. +// + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_floats (float *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = rint (uniform () * 32768); +} + +static o_type +ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) +{ + acc_type sum = 0; + for (int i = 0; i < ntaps; i++) + sum += input[i] * taps[ntaps - i - 1]; + + return sum; +} + +static void +test_random_io (fir_maker_t maker) +{ + const int MAX_TAPS = 32; + const int OUTPUT_LEN = 17; + const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN; + + i_type input[INPUT_LEN]; + o_type expected_output[OUTPUT_LEN]; + o_type actual_output[OUTPUT_LEN]; + tap_type taps[MAX_TAPS]; + + + srandom (0); // we want reproducibility + + for (int n = 0; n <= MAX_TAPS; n++){ + for (int ol = 0; ol <= OUTPUT_LEN; ol++){ + + // cerr << "@@@ n:ol " << n << ":" << ol << endl; + + // build random test case + random_floats (input, INPUT_LEN); + random_floats (taps, MAX_TAPS); + + // compute expected output values + for (int o = 0; o < ol; o++){ + expected_output[o] = ref_dotprod (&input[o], taps, n); + } + + // build filter + + vector<tap_type> f1_taps (&taps[0], &taps[n]); + gr_fir_fff *f1 = maker (f1_taps); + + // zero the output, then do the filtering + memset (actual_output, 0, sizeof (actual_output)); + f1->filterN (actual_output, input, ol); + + // check results + // + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + for (int o = 0; o < ol; o++){ + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected_output[o], actual_output[o], + fabs (expected_output[o]) * 9e-3); + } + + delete f1; + } + } +} + + +static void +for_each (void (*f)(fir_maker_t)) +{ + std::vector<gr_fir_fff_info> info; + gr_fir_util::get_gr_fir_fff_info (&info); // get all known fff implementations + + for (std::vector<gr_fir_fff_info>::iterator p = info.begin (); + p != info.end (); + ++p){ + + std::cerr << " [" << p->name << "]"; + f (p->create); + } + + std::cerr << std::endl; +} + +void +qa_gr_fir_fff::t1 () +{ + for_each (test_known_io); +} + +void +qa_gr_fir_fff::t2 () +{ + for_each (test_random_io); +} diff --git a/gnuradio-core/src/lib/filter/qa_gr_fir_fff.h b/gnuradio-core/src/lib/filter/qa_gr_fir_fff.h new file mode 100644 index 000000000..c89672896 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_fir_fff.h @@ -0,0 +1,43 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_GR_FIR_FFF_H_ +#define _QA_GR_FIR_FFF_H_ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_gr_fir_fff : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_fir_fff); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST_SUITE_END (); + + private: + + void t1 (); + void t2 (); + +}; + + +#endif /* _QA_GR_FIR_FFF_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_gr_fir_scc.cc b/gnuradio-core/src/lib/filter/qa_gr_fir_scc.cc new file mode 100644 index 000000000..3f4a7be2c --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_fir_scc.cc @@ -0,0 +1,179 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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. + */ + +/* + * FIXME. This code is virtually identical to qa_gr_fir_?CC.cc + * Kludge up some kind of macro to handle the minor differences. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gr_types.h> + +typedef short i_type; +typedef gr_complex o_type; +typedef gr_complex tap_type; +typedef gr_complex acc_type; + + +#include <qa_gr_fir_scc.h> +#include <gr_fir_scc.h> +#include <gr_fir_util.h> +#include <string.h> +#include <iostream> +#include <cmath> +#include <gr_types.h> +#include <cppunit/TestAssert.h> +#include <random.h> + +using std::vector; + +#define ERR_DELTA (1e-5) + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +// +// typedef for something logically "pointer to constructor". +// there may be a better way, please let me know... +// +typedef gr_fir_scc* (*fir_maker_t)(const std::vector<tap_type> &taps); + + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_input (i_type *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = (i_type) rint (uniform () * 32767); +} + +static void +random_complex (gr_complex *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++){ + float re = rint (uniform () * 32767); + float im = rint (uniform () * 32767); + buf[i] = gr_complex (re, im); + } +} + +static o_type +ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) +{ + acc_type sum = 0; + for (int i = 0; i < ntaps; i++) + sum += (float) input[i] * taps[ntaps - i - 1]; + + return sum; +} + +// +// Test for ntaps in [0,9], and input lengths in [0,17]. +// This ensures that we are building the shifted taps correctly, +// and exercises all corner cases on input alignment and length. +// + +static void +test_random_io (fir_maker_t maker) +{ + const int MAX_TAPS = 9; + const int OUTPUT_LEN = 17; + const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN; + + i_type input[INPUT_LEN]; + o_type expected_output[OUTPUT_LEN]; + o_type actual_output[OUTPUT_LEN]; + tap_type taps[MAX_TAPS]; + + + srandom (0); // we want reproducibility + + for (int n = 0; n <= MAX_TAPS; n++){ + for (int ol = 0; ol <= OUTPUT_LEN; ol++){ + + // cerr << "@@@ n:ol " << n << ":" << ol << endl; + + // build random test case + random_input (input, INPUT_LEN); + random_complex (taps, MAX_TAPS); + + // compute expected output values + for (int o = 0; o < ol; o++){ + expected_output[o] = ref_dotprod (&input[o], taps, n); + } + + // build filter + + vector<tap_type> f1_taps (&taps[0], &taps[n]); + gr_fir_scc *f1 = maker (f1_taps); + + // zero the output, then do the filtering + memset (actual_output, 0, sizeof (actual_output)); + f1->filterN (actual_output, input, ol); + + // check results + // + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + for (int o = 0; o < ol; o++){ + CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected_output[o], + actual_output[o], + abs (expected_output[o]) * ERR_DELTA); + } + + delete f1; + } + } +} + +static void +for_each (void (*f)(fir_maker_t)) +{ + std::vector<gr_fir_scc_info> info; + gr_fir_util::get_gr_fir_scc_info (&info); // get all known scc implementations + + for (std::vector<gr_fir_scc_info>::iterator p = info.begin (); + p != info.end (); + ++p){ + + std::cerr << " [" << p->name << "]"; + f (p->create); + } + + std::cerr << std::endl; +} + +void +qa_gr_fir_scc::t1 () +{ + for_each (test_random_io); +} diff --git a/gnuradio-core/src/lib/filter/qa_gr_fir_scc.h b/gnuradio-core/src/lib/filter/qa_gr_fir_scc.h new file mode 100644 index 000000000..4b5ffdae3 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_fir_scc.h @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_GR_FIR_SCC_H_ +#define _QA_GR_FIR_SCC_H_ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_gr_fir_scc : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_fir_scc); + CPPUNIT_TEST (t1); + CPPUNIT_TEST_SUITE_END (); + + private: + void t1 (); + +}; + + +#endif /* _QA_GR_FIR_SCC_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_gr_rotator.cc b/gnuradio-core/src/lib/filter/qa_gr_rotator.cc new file mode 100644 index 000000000..b2885a12d --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_rotator.cc @@ -0,0 +1,75 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 <gruel/attributes.h> +#include <cppunit/TestAssert.h> +#include <qa_gr_rotator.h> +#include <gr_rotator.h> +#include <stdio.h> +#include <cmath> +#include <gr_expj.h> + + +// error vector magnitude +__GR_ATTR_UNUSED static float +error_vector_mag(gr_complex a, gr_complex b) +{ + return abs(a-b); +} + +void +qa_gr_rotator::t1 () +{ + static const unsigned int N = 100000; + + gr_rotator r; + + double phase_incr = 2*M_PI / 1003; + double phase = 0; + + // Old code: We increment then return the rotated value, thus we need to start one tick back + // r.set_phase(gr_complex(1,0) * conj(gr_expj(phase_incr))); + + r.set_phase(gr_complex(1,0)); + r.set_phase_incr(gr_expj(phase_incr)); + + for (unsigned i = 0; i < N; i++){ + gr_complex expected = gr_expj(phase); + gr_complex actual = r.rotate(gr_complex(1, 0)); + +#if 0 + float evm = error_vector_mag(expected, actual); + printf("[%6d] expected: (%8.6f, %8.6f) actual: (%8.6f, %8.6f) evm: %8.6f\n", + i, expected.real(), expected.imag(), actual.real(), actual.imag(), evm); +#endif + + CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected, actual, 0.0001); + + phase += phase_incr; + if (phase >= 2*M_PI) + phase -= 2*M_PI; + } +} diff --git a/gnuradio-core/src/lib/filter/qa_gr_rotator.h b/gnuradio-core/src/lib/filter/qa_gr_rotator.h new file mode 100644 index 000000000..739b23f8c --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_rotator.h @@ -0,0 +1,39 @@ +/* -*- 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_GR_ROTATOR_H_ +#define _QA_GR_ROTATOR_H_ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_gr_rotator : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_rotator); + CPPUNIT_TEST (t1); + CPPUNIT_TEST_SUITE_END (); + + private: + void t1 (); + +}; + +#endif /* _QA_GR_ROTATOR_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.cc new file mode 100644 index 000000000..cfdbc53eb --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.cc @@ -0,0 +1,161 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_types.h> +#include <qa_gri_fir_filter_with_buffer_ccc.h> +#include <gri_fir_filter_with_buffer_ccc.h> +#include <string.h> +#include <iostream> +#include <cmath> +#include <cppunit/TestAssert.h> +#include <random.h> +#include <malloc16.h> +#include <string.h> + +typedef gr_complex i_type; +typedef gr_complex o_type; +typedef gr_complex tap_type; +typedef gr_complex acc_type; + +using std::vector; + +#define MAX_DATA (32767) +#define ERR_DELTA (1e-5) + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_complex (gr_complex *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++){ + float re = rint (uniform () * MAX_DATA); + float im = rint (uniform () * MAX_DATA); + buf[i] = gr_complex (re, im); + } +} + +static o_type +ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) +{ + acc_type sum = 0; + for (int i = 0; i < ntaps; i++) { + sum += input[i] * taps[i]; + } + + return sum; +} + +void +qa_gri_fir_filter_with_buffer_ccc::t1 () +{ + test_decimate(1); +} + +void +qa_gri_fir_filter_with_buffer_ccc::t2 () +{ + test_decimate(2); +} + +void +qa_gri_fir_filter_with_buffer_ccc::t3 () +{ + test_decimate(5); +} + +// +// Test for ntaps in [0,9], and input lengths in [0,17]. +// This ensures that we are building the shifted taps correctly, +// and exercises all corner cases on input alignment and length. +// +void +qa_gri_fir_filter_with_buffer_ccc::test_decimate(unsigned int decimate) +{ + const int MAX_TAPS = 9; + const int OUTPUT_LEN = 17; + const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN; + + // Mem aligned buffer not really necessary, but why not? + i_type *input = (i_type *)malloc16Align(INPUT_LEN * sizeof(i_type)); + i_type *dline = (i_type*)malloc16Align(INPUT_LEN * sizeof(i_type)); + o_type expected_output[OUTPUT_LEN]; + o_type actual_output[OUTPUT_LEN]; + tap_type taps[MAX_TAPS]; + + srandom (0); // we want reproducibility + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + + for (int n = 0; n <= MAX_TAPS; n++){ + for (int ol = 0; ol <= OUTPUT_LEN; ol++){ + + // cerr << "@@@ n:ol " << n << ":" << ol << endl; + + // build random test case + random_complex (input, INPUT_LEN); + random_complex (taps, MAX_TAPS); + + // compute expected output values + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + for (int o = 0; o < (int)(ol/decimate); o++){ + // use an actual delay line for this test + for(int dd = 0; dd < (int)decimate; dd++) { + for(int oo = INPUT_LEN-1; oo > 0; oo--) + dline[oo] = dline[oo-1]; + dline[0] = input[decimate*o+dd]; + } + expected_output[o] = ref_dotprod (dline, taps, n); + } + + // build filter + vector<tap_type> f1_taps(&taps[0], &taps[n]); + gri_fir_filter_with_buffer_ccc *f1 = new gri_fir_filter_with_buffer_ccc(f1_taps); + + // zero the output, then do the filtering + memset (actual_output, 0, sizeof (actual_output)); + f1->filterNdec (actual_output, input, ol/decimate, decimate); + + // check results + // + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + for (int o = 0; o < (int)(ol/decimate); o++){ + CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected_output[o], actual_output[o], + sqrt((float)n)*0.25*MAX_DATA*MAX_DATA * ERR_DELTA); + } + delete f1; + } + } + free16Align(input); +} diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.h b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.h new file mode 100644 index 000000000..c1f2df10c --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccc.h @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 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 _QA_GRI_FIR_FILTER_WITH_BUFFER_CCC_H_ +#define _QA_GRI_FIR_FILTER_WITH_BUFFER_CCC_H_ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_gri_fir_filter_with_buffer_ccc : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gri_fir_filter_with_buffer_ccc); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST_SUITE_END (); + + private: + void test_decimate(unsigned int decimate); + + void t1 (); + void t2 (); + void t3 (); + +}; + + +#endif /* _QA_GR_FIR_FILTER_WITH_BUFFER_CCC_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.cc new file mode 100644 index 000000000..9a5be0351 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.cc @@ -0,0 +1,167 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_types.h> +#include <qa_gri_fir_filter_with_buffer_ccf.h> +#include <gri_fir_filter_with_buffer_ccf.h> +#include <string.h> +#include <iostream> +#include <cmath> +#include <cppunit/TestAssert.h> +#include <random.h> +#include <malloc16.h> +#include <string.h> + +typedef gr_complex i_type; +typedef gr_complex o_type; +typedef float tap_type; +typedef gr_complex acc_type; + +using std::vector; + +#define ERR_DELTA (1e-5) + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_floats (float *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = (float) rint (uniform () * 32767); +} + +static void +random_complex (gr_complex *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++){ + float re = rint (uniform () * 32767); + float im = rint (uniform () * 32767); + buf[i] = gr_complex (re, im); + } +} + +static o_type +ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) +{ + acc_type sum = 0; + for (int i = 0; i < ntaps; i++) { + sum += input[i] * taps[i]; + } + + return sum; +} + +void +qa_gri_fir_filter_with_buffer_ccf::t1 () +{ + test_decimate(1); +} + +void +qa_gri_fir_filter_with_buffer_ccf::t2 () +{ + test_decimate(2); +} + +void +qa_gri_fir_filter_with_buffer_ccf::t3 () +{ + test_decimate(5); +} + +// +// Test for ntaps in [0,9], and input lengths in [0,17]. +// This ensures that we are building the shifted taps correctly, +// and exercises all corner cases on input alignment and length. +// +void +qa_gri_fir_filter_with_buffer_ccf::test_decimate (unsigned int decimate) +{ + const int MAX_TAPS = 9; + const int OUTPUT_LEN = 17; + const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN; + + // Mem aligned buffer not really necessary, but why not? + i_type *input = (i_type *)malloc16Align(INPUT_LEN * sizeof(i_type)); + i_type *dline = (i_type*)malloc16Align(INPUT_LEN * sizeof(i_type)); + o_type expected_output[OUTPUT_LEN]; + o_type actual_output[OUTPUT_LEN]; + tap_type taps[MAX_TAPS]; + + srandom (0); // we want reproducibility + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + + for (int n = 0; n <= MAX_TAPS; n++){ + for (int ol = 0; ol <= OUTPUT_LEN; ol++){ + + // cerr << "@@@ n:ol " << n << ":" << ol << endl; + + // build random test case + random_complex (input, INPUT_LEN); + random_floats (taps, MAX_TAPS); + + // compute expected output values + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + for (int o = 0; o < (int)(ol/decimate); o++){ + // use an actual delay line for this test + for(int dd = 0; dd < (int)decimate; dd++) { + for(int oo = INPUT_LEN-1; oo > 0; oo--) + dline[oo] = dline[oo-1]; + dline[0] = input[decimate*o+dd]; + } + expected_output[o] = ref_dotprod (dline, taps, n); + } + + // build filter + vector<tap_type> f1_taps(&taps[0], &taps[n]); + gri_fir_filter_with_buffer_ccf *f1 = new gri_fir_filter_with_buffer_ccf(f1_taps); + + // zero the output, then do the filtering + memset (actual_output, 0, sizeof (actual_output)); + f1->filterNdec (actual_output, input, ol/decimate, decimate); + + // check results + // + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + for (int o = 0; o < (int)(ol/decimate); o++){ + CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected_output[o], actual_output[o], + abs (expected_output[o]) * ERR_DELTA); + } + delete f1; + } + } + free16Align(input); +} diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.h b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.h new file mode 100644 index 000000000..686bc8541 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_ccf.h @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 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 _QA_GRI_FIR_FILTER_WITH_BUFFER_CCF_H_ +#define _QA_GRI_FIR_FILTER_WITH_BUFFER_CCF_H_ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_gri_fir_filter_with_buffer_ccf : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gri_fir_filter_with_buffer_ccf); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST_SUITE_END (); + + private: + void test_decimate(unsigned int decimate); + + void t1 (); + void t2 (); + void t3 (); + +}; + + +#endif /* _QA_GR_FIR_FILTER_WITH_BUFFER_CCF_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.cc new file mode 100644 index 000000000..583697165 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.cc @@ -0,0 +1,168 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_types.h> +#include <qa_gri_fir_filter_with_buffer_fcc.h> +#include <gri_fir_filter_with_buffer_fcc.h> +#include <string.h> +#include <iostream> +#include <cmath> +#include <cppunit/TestAssert.h> +#include <random.h> +#include <malloc16.h> +#include <string.h> + +typedef float i_type; +typedef gr_complex o_type; +typedef gr_complex tap_type; +typedef gr_complex acc_type; + +using std::vector; + +#define ERR_DELTA (1e-5) + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_floats (float *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = (float) rint (uniform () * 32767); +} + +static void +random_complex (gr_complex *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++){ + float re = rint (uniform () * 32767); + float im = rint (uniform () * 32767); + buf[i] = gr_complex (re, im); + } +} + +static o_type +ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) +{ + acc_type sum = 0; + for (int i = 0; i < ntaps; i++) { + sum += input[i] * taps[i]; + } + + return sum; +} + +void +qa_gri_fir_filter_with_buffer_fcc::t1() +{ + test_decimate(1); +} + +void +qa_gri_fir_filter_with_buffer_fcc::t2() +{ + test_decimate(2); +} + +void +qa_gri_fir_filter_with_buffer_fcc::t3() +{ + test_decimate(5); +} + + +// +// Test for ntaps in [0,9], and input lengths in [0,17]. +// This ensures that we are building the shifted taps correctly, +// and exercises all corner cases on input alignment and length. +// +void +qa_gri_fir_filter_with_buffer_fcc::test_decimate(unsigned int decimate) +{ + const int MAX_TAPS = 9; + const int OUTPUT_LEN = 17; + const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN; + + // Mem aligned buffer not really necessary, but why not? + i_type *input = (i_type *)malloc16Align(INPUT_LEN * sizeof(i_type)); + i_type *dline = (i_type*)malloc16Align(INPUT_LEN * sizeof(i_type)); + o_type expected_output[OUTPUT_LEN]; + o_type actual_output[OUTPUT_LEN]; + tap_type taps[MAX_TAPS]; + + srandom (0); // we want reproducibility + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + + for (int n = 0; n <= MAX_TAPS; n++){ + for (int ol = 0; ol <= OUTPUT_LEN; ol++){ + + // cerr << "@@@ n:ol " << n << ":" << ol << endl; + + // build random test case + random_floats (input, INPUT_LEN); + random_complex (taps, MAX_TAPS); + + // compute expected output values + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + for (int o = 0; o < (int)(ol/decimate); o++){ + // use an actual delay line for this test + for(int dd = 0; dd < (int)decimate; dd++) { + for(int oo = INPUT_LEN-1; oo > 0; oo--) + dline[oo] = dline[oo-1]; + dline[0] = input[decimate*o+dd]; + } + expected_output[o] = ref_dotprod (dline, taps, n); + } + + // build filter + vector<tap_type> f1_taps(&taps[0], &taps[n]); + gri_fir_filter_with_buffer_fcc *f1 = new gri_fir_filter_with_buffer_fcc(f1_taps); + + // zero the output, then do the filtering + memset (actual_output, 0, sizeof (actual_output)); + f1->filterNdec (actual_output, input, ol/decimate, decimate); + + // check results + // + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + for (int o = 0; o < (int)(ol/decimate); o++){ + CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected_output[o], actual_output[o], + abs (expected_output[o]) * ERR_DELTA); + } + delete f1; + } + } + free16Align(input); +} diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.h b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.h new file mode 100644 index 000000000..64eed25d3 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fcc.h @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 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 _QA_GRI_FIR_FILTER_WITH_BUFFER_FCC_H_ +#define _QA_GRI_FIR_FILTER_WITH_BUFFER_FCC_H_ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_gri_fir_filter_with_buffer_fcc : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gri_fir_filter_with_buffer_fcc); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST_SUITE_END (); + + private: + void test_decimate(unsigned int decimate); + + void t1 (); + void t2 (); + void t3 (); + +}; + + +#endif /* _QA_GR_FIR_FILTER_WITH_BUFFER_FCC_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.cc new file mode 100644 index 000000000..208ae01db --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.cc @@ -0,0 +1,156 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_types.h> +#include <qa_gri_fir_filter_with_buffer_fff.h> +#include <gri_fir_filter_with_buffer_fff.h> +#include <string.h> +#include <iostream> +#include <cmath> +#include <cppunit/TestAssert.h> +#include <random.h> +#include <malloc16.h> +#include <string.h> + +typedef float i_type; +typedef float o_type; +typedef float tap_type; +typedef float acc_type; + +using std::vector; + +#define ERR_DELTA (1e-5) + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_floats (float *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = (float) rint (uniform () * 32767); +} + +static o_type +ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) +{ + acc_type sum = 0; + for (int i = 0; i < ntaps; i++) { + sum += input[i] * taps[i]; + } + return sum; +} + +void +qa_gri_fir_filter_with_buffer_fff::t1 () +{ + test_decimate(1); +} + +void +qa_gri_fir_filter_with_buffer_fff::t2 () +{ + test_decimate(2); +} + +void +qa_gri_fir_filter_with_buffer_fff::t3 () +{ + test_decimate(5); +} + +// +// Test for ntaps in [0,9], and input lengths in [0,17]. +// This ensures that we are building the shifted taps correctly, +// and exercises all corner cases on input alignment and length. +// +void +qa_gri_fir_filter_with_buffer_fff::test_decimate(unsigned int decimate) +{ + const int MAX_TAPS = 9; + const int OUTPUT_LEN = 17; + const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN; + + // Mem aligned buffer not really necessary, but why not? + i_type *input = (i_type *)malloc16Align(INPUT_LEN * sizeof(i_type)); + i_type *dline = (i_type*)malloc16Align(INPUT_LEN * sizeof(i_type)); + o_type expected_output[OUTPUT_LEN]; + o_type actual_output[OUTPUT_LEN]; + tap_type taps[MAX_TAPS]; + + srandom (0); // we want reproducibility + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + + for (int n = 0; n <= MAX_TAPS; n++){ + for (int ol = 0; ol <= OUTPUT_LEN; ol++){ + + // cerr << "@@@ n:ol " << n << ":" << ol << endl; + + // build random test case + random_floats (input, INPUT_LEN); + random_floats (taps, MAX_TAPS); + + // compute expected output values + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + for (int o = 0; o < (int)(ol/decimate); o++){ + // use an actual delay line for this test + for(int dd = 0; dd < (int)decimate; dd++) { + for(int oo = INPUT_LEN-1; oo > 0; oo--) + dline[oo] = dline[oo-1]; + dline[0] = input[decimate*o+dd]; + } + expected_output[o] = ref_dotprod (dline, taps, n); + } + + // build filter + vector<tap_type> f1_taps(&taps[0], &taps[n]); + gri_fir_filter_with_buffer_fff *f1 = new gri_fir_filter_with_buffer_fff(f1_taps); + + // zero the output, then do the filtering + memset (actual_output, 0, sizeof (actual_output)); + f1->filterNdec (actual_output, input, ol/decimate, decimate); + + // check results + // + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + for (int o = 0; o < (int)(ol/decimate); o++){ + CPPUNIT_ASSERT_DOUBLES_EQUAL(expected_output[o], actual_output[o], + fabsf (expected_output[o]) * ERR_DELTA); + } + delete f1; + } + } + free16Align(input); +} diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.h b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.h new file mode 100644 index 000000000..d219ec72d --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fff.h @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 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 _QA_GRI_FIR_FILTER_WITH_BUFFER_FFF_H_ +#define _QA_GRI_FIR_FILTER_WITH_BUFFER_FFF_H_ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_gri_fir_filter_with_buffer_fff : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gri_fir_filter_with_buffer_fff); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST_SUITE_END (); + + private: + void test_decimate(unsigned int decimate); + + void t1 (); + void t2 (); + void t3 (); + +}; + + +#endif /* _QA_GR_FIR_FILTER_WITH_BUFFER_FFF_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.cc new file mode 100644 index 000000000..e2b6fb04f --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.cc @@ -0,0 +1,147 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_types.h> +#include <qa_gri_fir_filter_with_buffer_fsf.h> +#include <gri_fir_filter_with_buffer_fsf.h> +#include <string.h> +#include <iostream> +#include <cmath> +#include <cppunit/TestAssert.h> +#include <random.h> +#include <malloc16.h> +#include <string.h> + +typedef float i_type; +typedef short o_type; +typedef float tap_type; +typedef float acc_type; + +using std::vector; + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_floats (float *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = (float) rint (uniform () * 128); +} + +static o_type +ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) +{ + acc_type sum = 0; + for (int i = 0; i < ntaps; i++) { + sum += input[i] * taps[i]; + } + return (o_type)sum; +} + +void +qa_gri_fir_filter_with_buffer_fsf::t1 () +{ + test_decimate(1); +} + +void +qa_gri_fir_filter_with_buffer_fsf::t2 () +{ + test_decimate(2); +} + +void +qa_gri_fir_filter_with_buffer_fsf::t3 () +{ + test_decimate(5); +} + +// +// Test for ntaps in [0,9], and input lengths in [0,17]. +// This ensures that we are building the shifted taps correctly, +// and exercises all corner cases on input alignment and length. +// +void +qa_gri_fir_filter_with_buffer_fsf::test_decimate (unsigned int decimate) +{ + const int MAX_TAPS = 9; + const int OUTPUT_LEN = 17; + const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN; + + // Mem aligned buffer not really necessary, but why not? + i_type *input = (i_type *)malloc16Align(INPUT_LEN * sizeof(i_type)); + i_type *dline = (i_type*)malloc16Align(INPUT_LEN * sizeof(i_type)); + o_type expected_output[OUTPUT_LEN]; + o_type actual_output[OUTPUT_LEN]; + tap_type taps[MAX_TAPS]; + + srandom (0); // we want reproducibility + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + + for (int n = 0; n <= MAX_TAPS; n++){ + for (int ol = 0; ol <= OUTPUT_LEN; ol++){ + + // cerr << "@@@ n:ol " << n << ":" << ol << endl; + + // build random test case + random_floats (input, INPUT_LEN); + random_floats (taps, MAX_TAPS); + + // compute expected output values + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + for (int o = 0; o < (int)(ol/decimate); o++){ + // use an actual delay line for this test + for(int dd = 0; dd < (int)decimate; dd++) { + for(int oo = INPUT_LEN-1; oo > 0; oo--) + dline[oo] = dline[oo-1]; + dline[0] = input[decimate*o+dd]; + } + expected_output[o] = ref_dotprod (dline, taps, n); + } + + // build filter + vector<tap_type> f1_taps(&taps[0], &taps[n]); + gri_fir_filter_with_buffer_fsf *f1 = new gri_fir_filter_with_buffer_fsf(f1_taps); + + // zero the output, then do the filtering + memset (actual_output, 0, sizeof (actual_output)); + f1->filterNdec (actual_output, input, ol/decimate, decimate); + + // check results + for (int o = 0; o < (int)(ol/decimate); o++){ + CPPUNIT_ASSERT_EQUAL(expected_output[o], actual_output[o]); + } + delete f1; + } + } + free16Align(input); +} diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.h b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.h new file mode 100644 index 000000000..70030a072 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_fsf.h @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 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 _QA_GRI_FIR_FILTER_WITH_BUFFER_FSF_H_ +#define _QA_GRI_FIR_FILTER_WITH_BUFFER_FSF_H_ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_gri_fir_filter_with_buffer_fsf : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gri_fir_filter_with_buffer_fsf); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST_SUITE_END (); + + private: + void test_decimate(unsigned int decimate); + + void t1 (); + void t2 (); + void t3 (); + +}; + + +#endif /* _QA_GR_FIR_FILTER_WITH_BUFFER_FSF_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.cc b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.cc new file mode 100644 index 000000000..15f8b1f95 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.cc @@ -0,0 +1,167 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_types.h> +#include <qa_gri_fir_filter_with_buffer_scc.h> +#include <gri_fir_filter_with_buffer_scc.h> +#include <string.h> +#include <iostream> +#include <cmath> +#include <cppunit/TestAssert.h> +#include <random.h> +#include <malloc16.h> +#include <string.h> + +typedef short i_type; +typedef gr_complex o_type; +typedef gr_complex tap_type; +typedef gr_complex acc_type; + +using std::vector; + +#define ERR_DELTA (1e-5) + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +static float +uniform () +{ + return 2.0 * ((float) random () / RANDOM_MAX - 0.5); // uniformly (-1, 1) +} + +static void +random_shorts (short *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++) + buf[i] = (short) rint (uniform () * 16384); +} + +static void +random_complex (gr_complex *buf, unsigned n) +{ + for (unsigned i = 0; i < n; i++){ + float re = rint (uniform () * 32767); + float im = rint (uniform () * 32767); + buf[i] = gr_complex (re, im); + } +} + +static o_type +ref_dotprod (const i_type input[], const tap_type taps[], int ntaps) +{ + acc_type sum = 0; + for (int i = 0; i < ntaps; i++) { + sum += (float)input[i] * taps[i]; + } + + return sum; +} + +void +qa_gri_fir_filter_with_buffer_scc::t1 () +{ + test_decimate(1); +} + +void +qa_gri_fir_filter_with_buffer_scc::t2 () +{ + test_decimate(2); +} + +void +qa_gri_fir_filter_with_buffer_scc::t3 () +{ + test_decimate(5); +} + +// +// Test for ntaps in [0,9], and input lengths in [0,17]. +// This ensures that we are building the shifted taps correctly, +// and exercises all corner cases on input alignment and length. +// +void +qa_gri_fir_filter_with_buffer_scc::test_decimate (unsigned int decimate) +{ + const int MAX_TAPS = 9; + const int OUTPUT_LEN = 17; + const int INPUT_LEN = MAX_TAPS + OUTPUT_LEN; + + // Mem aligned buffer not really necessary, but why not? + i_type *input = (i_type *)malloc16Align(INPUT_LEN * sizeof(i_type)); + i_type *dline = (i_type*)malloc16Align(INPUT_LEN * sizeof(i_type)); + o_type expected_output[OUTPUT_LEN]; + o_type actual_output[OUTPUT_LEN]; + tap_type taps[MAX_TAPS]; + + srandom (0); // we want reproducibility + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + + for (int n = 0; n <= MAX_TAPS; n++){ + for (int ol = 0; ol <= OUTPUT_LEN; ol++){ + + // cerr << "@@@ n:ol " << n << ":" << ol << endl; + + // build random test case + random_shorts (input, INPUT_LEN); + random_complex (taps, MAX_TAPS); + + // compute expected output values + memset(dline, 0, INPUT_LEN*sizeof(i_type)); + for (int o = 0; o < (int)(ol/decimate); o++){ + // use an actual delay line for this test + for(int dd = 0; dd < (int)decimate; dd++) { + for(int oo = INPUT_LEN-1; oo > 0; oo--) + dline[oo] = dline[oo-1]; + dline[0] = input[decimate*o+dd]; + } + expected_output[o] = ref_dotprod (dline, taps, n); + } + + // build filter + vector<tap_type> f1_taps(&taps[0], &taps[n]); + gri_fir_filter_with_buffer_scc *f1 = new gri_fir_filter_with_buffer_scc(f1_taps); + + // zero the output, then do the filtering + memset (actual_output, 0, sizeof (actual_output)); + f1->filterNdec (actual_output, input, ol/decimate, decimate); + + // check results + // + // we use a sloppy error margin because on the x86 architecture, + // our reference implementation is using 80 bit floating point + // arithmetic, while the SSE version is using 32 bit float point + // arithmetic. + + for (int o = 0; o < (int)(ol/decimate); o++){ + CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected_output[o], actual_output[o], + abs (expected_output[o]) * ERR_DELTA); + } + delete f1; + } + } + free16Align(input); +} diff --git a/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.h b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.h new file mode 100644 index 000000000..f80056189 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_fir_filter_with_buffer_scc.h @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 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 _QA_GRI_FIR_FILTER_WITH_BUFFER_SCC_H_ +#define _QA_GRI_FIR_FILTER_WITH_BUFFER_SCC_H_ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_gri_fir_filter_with_buffer_scc : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gri_fir_filter_with_buffer_scc); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST_SUITE_END (); + + private: + void test_decimate(unsigned int decimate); + + void t1 (); + void t2 (); + void t3 (); + +}; + + +#endif /* _QA_GR_FIR_FILTER_WITH_BUFFER_SCC_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator.cc b/gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator.cc new file mode 100644 index 000000000..7dca65b9a --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator.cc @@ -0,0 +1,66 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 <cppunit/TestAssert.h> +#include <qa_gri_mmse_fir_interpolator.h> +#include <gri_mmse_fir_interpolator.h> +#include <stdio.h> +#include <cmath> + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + + +static float +test_fcn (double index) +{ + return (2 * sin (index * 0.25 * 2 * M_PI + 0.125 * M_PI) + + 3 * sin (index * 0.077 * 2 * M_PI + 0.3 * M_PI)); +} + + +void +qa_gri_mmse_fir_interpolator::t1 () +{ + static const unsigned N = 100; + float input[N + 10]; + + for (unsigned i = 0; i < NELEM(input); i++) + input[i] = test_fcn ((double) i); + + gri_mmse_fir_interpolator intr; + float inv_nsteps = 1.0 / intr.nsteps (); + + for (unsigned i = 0; i < N; i++){ + for (unsigned imu = 0; imu <= intr.nsteps (); imu += 1){ + float expected = test_fcn ((i + 3) + imu * inv_nsteps); + float actual = intr.interpolate (&input[i], imu * inv_nsteps); + + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected, actual, 0.004); + // printf ("%9.6f %9.6f %9.6f\n", expected, actual, expected - actual); + } + } +} + diff --git a/gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator.h b/gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator.h new file mode 100644 index 000000000..3f4dec7c2 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator.h @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_MMSE_FIR_INTERPOLATOR_H_ +#define _QA_GRI_MMSE_FIR_INTERPOLATOR_H_ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_gri_mmse_fir_interpolator : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gri_mmse_fir_interpolator); + CPPUNIT_TEST (t1); + CPPUNIT_TEST_SUITE_END (); + + private: + void t1 (); + +}; + + +#endif /* _QA_GRI_MMSE_FIR_INTERPOLATOR_H_ */ diff --git a/gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator_cc.cc b/gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator_cc.cc new file mode 100644 index 000000000..1f70d7f42 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator_cc.cc @@ -0,0 +1,124 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gruel/attributes.h> +#include <cppunit/TestAssert.h> +#include <qa_gri_mmse_fir_interpolator_cc.h> +#include <gri_mmse_fir_interpolator_cc.h> +#include <stdio.h> +#include <cmath> +#include <stdexcept> +#include <unistd.h> + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + + +static float +test_fcn_sin(double index) +{ + return (2 * sin (index * 0.25 * 2 * M_PI + 0.125 * M_PI) + + 3 * sin (index * 0.077 * 2 * M_PI + 0.3 * M_PI)); +} + +static float +test_fcn_cos(double index) +{ + return (2 * cos (index * 0.25 * 2 * M_PI + 0.125 * M_PI) + + 3 * cos (index * 0.077 * 2 * M_PI + 0.3 * M_PI)); +} + +static gr_complex +test_fcn(double index) +{ + return gr_complex(test_fcn_cos(index), test_fcn_sin(index)); +} + + +void +qa_gri_mmse_fir_interpolator_cc::t1() +{ + static const unsigned N = 100; + __GR_ATTR_ALIGNED(8) gr_complex input[N + 10]; + + for (unsigned i = 0; i < NELEM(input); i++) + input[i] = test_fcn ((double) i); + + gri_mmse_fir_interpolator_cc intr; + float inv_nsteps = 1.0 / intr.nsteps (); + + for (unsigned i = 0; i < N; i++){ + for (unsigned imu = 0; imu <= intr.nsteps (); imu += 1){ + gr_complex expected = test_fcn ((i + 3) + imu * inv_nsteps); + gr_complex actual = intr.interpolate (&input[i], imu * inv_nsteps); + + CPPUNIT_ASSERT_COMPLEXES_EQUAL (expected, actual, 0.004); + // printf ("%9.6f %9.6f %9.6f\n", expected, actual, expected - actual); + } + } +} + + +/* + * Force bad alignment and confirm that it raises an exception + */ +void +qa_gri_mmse_fir_interpolator_cc::t2_body() +{ + static const unsigned N = 100; + float float_input[2*(N+10) + 1]; + gr_complex *input; + + // We require that gr_complex be aligned on an 8-byte boundary. + // Ensure that we ARE NOT ;) + + if (((intptr_t) float_input & 0x7) == 0) + input = reinterpret_cast<gr_complex *>(&float_input[1]); + else + input = reinterpret_cast<gr_complex *>(&float_input[0]); + + + for (unsigned i = 0; i < (N+10); i++) + input[i] = test_fcn ((double) i); + + gri_mmse_fir_interpolator_cc intr; + float inv_nsteps = 1.0 / intr.nsteps (); + + for (unsigned i = 0; i < N; i++){ + for (unsigned imu = 0; imu <= intr.nsteps (); imu += 1){ + gr_complex expected = test_fcn ((i + 3) + imu * inv_nsteps); + gr_complex actual = intr.interpolate (&input[i], imu * inv_nsteps); + + CPPUNIT_ASSERT_COMPLEXES_EQUAL (expected, actual, 0.004); + // printf ("%9.6f %9.6f %9.6f\n", expected, actual, expected - actual); + } + } +} + +void +qa_gri_mmse_fir_interpolator_cc::t2() +{ + CPPUNIT_ASSERT_THROW(t2_body(), std::invalid_argument); +} diff --git a/gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator_cc.h b/gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator_cc.h new file mode 100644 index 000000000..6be3d9743 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator_cc.h @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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 _QA_GRI_MMSE_FIR_INTERPOLATOR_CC_H_ +#define _QA_GRI_MMSE_FIR_INTERPOLATOR_CC_H_ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_gri_mmse_fir_interpolator_cc : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE(qa_gri_mmse_fir_interpolator_cc); + CPPUNIT_TEST(t1); + // CPPUNIT_TEST(t2); + CPPUNIT_TEST_SUITE_END(); + + private: + void t1(); + void t2(); + void t2_body(); + +}; + +#endif /* _QA_GRI_MMSE_FIR_INTERPOLATOR_CC_H_ */ diff --git a/gnuradio-core/src/lib/filter/short_dotprod_generic.c b/gnuradio-core/src/lib/filter/short_dotprod_generic.c new file mode 100644 index 000000000..49a9c0483 --- /dev/null +++ b/gnuradio-core/src/lib/filter/short_dotprod_generic.c @@ -0,0 +1,49 @@ +/* -*- c -*- */ +/* + * Copyright 2002 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 "short_dotprod_generic.h" + + +int +short_dotprod_generic (const short *input, + const short *taps, unsigned n_4_short_blocks) +{ + int sum0 = 0; + int sum1 = 0; + int sum2 = 0; + int sum3 = 0; + + do { + + sum0 += input[0] * taps[0]; + sum1 += input[1] * taps[1]; + sum2 += input[2] * taps[2]; + sum3 += input[3] * taps[3]; + + input += 4; + taps += 4; + + } while (--n_4_short_blocks != 0); + + + return (sum0 + sum1 + sum2 + sum3); +} diff --git a/gnuradio-core/src/lib/filter/short_dotprod_generic.h b/gnuradio-core/src/lib/filter/short_dotprod_generic.h new file mode 100644 index 000000000..e7d977a00 --- /dev/null +++ b/gnuradio-core/src/lib/filter/short_dotprod_generic.h @@ -0,0 +1,41 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 _SHORT_DOTPROD_GENERIC_H_ +#define _SHORT_DOTPROD_GENERIC_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +int +short_dotprod_generic (const short *input, + const short *taps, unsigned n_4_short_blocks); + + +#ifdef __cplusplus +} +#endif + + + +#endif /* _SHORT_DOTPROD_GENERIC_H_ */ diff --git a/gnuradio-core/src/lib/filter/short_dotprod_mmx.S b/gnuradio-core/src/lib/filter/short_dotprod_mmx.S new file mode 100644 index 000000000..0f6801e4b --- /dev/null +++ b/gnuradio-core/src/lib/filter/short_dotprod_mmx.S @@ -0,0 +1,117 @@ +# +# Copyright 2002 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. +# + +# SIMD MMX dot product +# Equivalent to the following C code: +# long dotprod(signed short *a,signed short *b,int cnt) +# { +# long sum = 0; +# cnt *= 4; +# while(cnt--) +# sum += *a++ + *b++; +# return sum; +# } +# a and b should also be 64-bit aligned, or speed will suffer greatly +# Copyright 1999, Phil Karn KA9Q +# May be used under the terms of the GNU public license + +#include "assembly.h" + + + .file "short_dotprod_mmx.S" +// .version "01.01" +.text + .p2align 3 +.globl GLOB_SYMB(short_dotprod_mmx) + DEF_FUNC_HEAD(short_dotprod_mmx) +GLOB_SYMB(short_dotprod_mmx): + pushl %ebp + movl %esp,%ebp + pushl %esi + pushl %edi + pushl %ecx + pushl %ebx + movl 8(%ebp),%esi # a + movl 12(%ebp),%edi # b + movl 16(%ebp),%ecx # cnt + pxor %mm0,%mm0 # clear running sum (in two 32-bit halves) + +# MMX dot product loop unrolled 4 times, crunching 16 terms per loop + .p2align 4 +.Loop1mmx: subl $4,%ecx + jl .Loop1Done + + movq (%esi),%mm1 # mm1 = a[3],a[2],a[1],a[0] + pmaddwd (%edi),%mm1 # mm1 = b[3]*a[3]+b[2]*a[2],b[1]*a[1]+b[0]*a[0] + paddd %mm1,%mm0 + + movq 8(%esi),%mm1 + pmaddwd 8(%edi),%mm1 + paddd %mm1,%mm0 + + movq 16(%esi),%mm1 + pmaddwd 16(%edi),%mm1 + paddd %mm1,%mm0 + + movq 24(%esi),%mm1 + addl $32,%esi + pmaddwd 24(%edi),%mm1 + addl $32,%edi + paddd %mm1,%mm0 + + jmp .Loop1mmx +.Loop1Done: + + addl $4,%ecx + +# MMX dot product loop, not unrolled, crunching 4 terms per loop +# This could be redone as Duff's Device on the unrolled loop above +.Loop2: subl $1,%ecx + jl .Loop2Done + + movq (%esi),%mm1 + addl $8,%esi + pmaddwd (%edi),%mm1 + addl $8,%edi + paddd %mm1,%mm0 + jmp .Loop2 +.Loop2Done: + + movd %mm0,%ebx # right-hand word to ebx + punpckhdq %mm0,%mm0 # left-hand word to right side of %mm0 + movd %mm0,%eax + addl %ebx,%eax # running sum now in %eax + emms # done with MMX + + popl %ebx + popl %ecx + popl %edi + popl %esi + movl %ebp,%esp + popl %ebp + ret + +FUNC_TAIL(short_dotprod_mmx) + .ident "Hand coded x86 MMX assembly" + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/gnuradio-core/src/lib/filter/short_dotprod_mmx64.S b/gnuradio-core/src/lib/filter/short_dotprod_mmx64.S new file mode 100644 index 000000000..bafd0e04e --- /dev/null +++ b/gnuradio-core/src/lib/filter/short_dotprod_mmx64.S @@ -0,0 +1,105 @@ +# +# Copyright 2002,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. +# + +# SIMD MMX dot product +# Equivalent to the following C code: +# long dotprod(signed short *a,signed short *b,int cnt) +# { +# long sum = 0; +# cnt *= 4; +# while(cnt--) +# sum += *a++ + *b++; +# return sum; +# } +# a and b should also be 64-bit aligned, or speed will suffer greatly +# Copyright 1999, Phil Karn KA9Q +# May be used under the terms of the GNU public license + +#include "assembly.h" + + + .file "short_dotprod_mmx64.S" +// .version "01.01" +.text + .p2align 3 +.globl GLOB_SYMB(short_dotprod_mmx) + DEF_FUNC_HEAD(short_dotprod_mmx) +GLOB_SYMB(short_dotprod_mmx): + + # a: rdi, b: rsi, cnt: rdx + + pxor %mm0,%mm0 # clear running sum (in two 32-bit halves) + +# MMX dot product loop unrolled 4 times, crunching 16 terms per loop + .p2align 4 +.Loop1mmx: sub $4,%rdx + jl .Loop1Done + + movq (%rdi),%mm1 # mm1 = a[3],a[2],a[1],a[0] + pmaddwd (%rsi),%mm1 # mm1 = b[3]*a[3]+b[2]*a[2],b[1]*a[1]+b[0]*a[0] + paddd %mm1,%mm0 + + movq 8(%rdi),%mm1 + pmaddwd 8(%rsi),%mm1 + paddd %mm1,%mm0 + + movq 16(%rdi),%mm1 + pmaddwd 16(%rsi),%mm1 + paddd %mm1,%mm0 + + movq 24(%rdi),%mm1 + add $32,%rdi + pmaddwd 24(%rsi),%mm1 + add $32,%rsi + paddd %mm1,%mm0 + + jmp .Loop1mmx +.Loop1Done: + + add $4,%rdx + +# MMX dot product loop, not unrolled, crunching 4 terms per loop +# This could be redone as Duff's Device on the unrolled loop above +.Loop2: sub $1,%rdx + jl .Loop2Done + + movq (%rdi),%mm1 + add $8,%rdi + pmaddwd (%rsi),%mm1 + add $8,%rsi + paddd %mm1,%mm0 + jmp .Loop2 +.Loop2Done: + + movd %mm0,%edx # right-hand word to edx + punpckhdq %mm0,%mm0 # left-hand word to right side of %mm0 + movd %mm0,%eax + addl %edx,%eax # running sum now in %eax + emms # done with MMX + + retq + +FUNC_TAIL(short_dotprod_mmx) + .ident "Hand coded x86_64 MMX assembly" + +#if defined(__linux__) && defined(__ELF__) +.section .note.GNU-stack,"",%progbits +#endif diff --git a/gnuradio-core/src/lib/filter/short_dotprod_x86.h b/gnuradio-core/src/lib/filter/short_dotprod_x86.h new file mode 100644 index 000000000..13d5ae2a3 --- /dev/null +++ b/gnuradio-core/src/lib/filter/short_dotprod_x86.h @@ -0,0 +1,44 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 _SHORT_DOTPROD_X86_H_ +#define _SHORT_DOTPROD_X86_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +int +short_dotprod_mmx (const short *input, + const short *taps, unsigned n_4_short_blocks); + +int +short_dotprod_sse2 (const short *input, + const short *taps, unsigned n_4_short_blocks); + +#ifdef __cplusplus +} +#endif + + + +#endif /* _SHORT_DOTPROD_X86_H_ */ diff --git a/gnuradio-core/src/lib/filter/sse_debug.c b/gnuradio-core/src/lib/filter/sse_debug.c new file mode 100644 index 000000000..870cc0543 --- /dev/null +++ b/gnuradio-core/src/lib/filter/sse_debug.c @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 <stdio.h> +#include <sse_debug.h> +#include <string.h> + +void +format_xmm_regs (FILE *f, struct xmm_regs *r) +{ + int i; + + for (i = 0; i < 8; i++){ + union xmm_register *x = &r->xmm[i]; + fprintf (f, "xmm%d: %08lx %08lx %08lx %08lx", i, + x->ul[0], x->ul[1], x->ul[2], x->ul[3]); + fprintf (f, " %12g %12g %12g %12g\n", + x->f[0], x->f[1], x->f[2], x->f[3]); + } +} + + +void +get_xmm_regs (struct xmm_regs *x) +{ + asm ("movups %%xmm0,0x00(%0); \n" + "movups %%xmm1,0x10(%0); \n" + "movups %%xmm2,0x20(%0); \n" + "movups %%xmm3,0x30(%0); \n" + "movups %%xmm4,0x40(%0); \n" + "movups %%xmm5,0x50(%0); \n" + "movups %%xmm6,0x60(%0); \n" + "movups %%xmm7,0x70(%0); \n" : : "r" (x)); +} + +void +dump_xmm_regs (void) +{ + struct xmm_regs r; + + get_xmm_regs (&r); + format_xmm_regs (stderr, &r); +} + diff --git a/gnuradio-core/src/lib/filter/sse_debug.h b/gnuradio-core/src/lib/filter/sse_debug.h new file mode 100644 index 000000000..b19b4e646 --- /dev/null +++ b/gnuradio-core/src/lib/filter/sse_debug.h @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 _SSE_DEBUG_H_ +#define _SSE_DEBUG_H_ + +#ifdef __cplusplus +extern "C" { +#endif + + union xmm_register { + unsigned long ul[4]; + float f[4]; + }; + + struct xmm_regs { + union xmm_register xmm[8]; + }; + + // callable from asm, dumps all xmm regs + void dump_xmm_regs (void); + + void get_xmm_regs (struct xmm_regs *x); + +#ifdef __cplusplus +} +#endif + +#endif // _SSE_DEBUG_H_ diff --git a/gnuradio-core/src/lib/filter/sysconfig_armv7_a.cc b/gnuradio-core/src/lib/filter/sysconfig_armv7_a.cc new file mode 100644 index 000000000..2c415863b --- /dev/null +++ b/gnuradio-core/src/lib/filter/sysconfig_armv7_a.cc @@ -0,0 +1,39 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2008,2009 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_fir_sysconfig_armv7_a.h> + +gr_fir_sysconfig * +gr_fir_sysconfig_singleton () +{ + static gr_fir_sysconfig *singleton = 0; + + if (singleton) + return singleton; + + singleton = new gr_fir_sysconfig_armv7_a (); + return singleton; +} diff --git a/gnuradio-core/src/lib/filter/sysconfig_generic.cc b/gnuradio-core/src/lib/filter/sysconfig_generic.cc new file mode 100644 index 000000000..88508f62b --- /dev/null +++ b/gnuradio-core/src/lib/filter/sysconfig_generic.cc @@ -0,0 +1,35 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 <gr_fir_sysconfig_generic.h> + +gr_fir_sysconfig * +gr_fir_sysconfig_singleton () +{ + static gr_fir_sysconfig *singleton = 0; + + if (singleton) + return singleton; + + singleton = new gr_fir_sysconfig_generic (); + return singleton; +} diff --git a/gnuradio-core/src/lib/filter/sysconfig_powerpc.cc b/gnuradio-core/src/lib/filter/sysconfig_powerpc.cc new file mode 100644 index 000000000..911beae2a --- /dev/null +++ b/gnuradio-core/src/lib/filter/sysconfig_powerpc.cc @@ -0,0 +1,38 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_fir_sysconfig_powerpc.h> + +gr_fir_sysconfig * +gr_fir_sysconfig_singleton () +{ + static gr_fir_sysconfig *singleton = 0; + + if (singleton) + return singleton; + + singleton = new gr_fir_sysconfig_powerpc (); + return singleton; +} diff --git a/gnuradio-core/src/lib/filter/sysconfig_x86.cc b/gnuradio-core/src/lib/filter/sysconfig_x86.cc new file mode 100644 index 000000000..582df0ab7 --- /dev/null +++ b/gnuradio-core/src/lib/filter/sysconfig_x86.cc @@ -0,0 +1,38 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_fir_sysconfig_x86.h> + +gr_fir_sysconfig * +gr_fir_sysconfig_singleton () +{ + static gr_fir_sysconfig *singleton = 0; + + if (singleton) + return singleton; + + singleton = new gr_fir_sysconfig_x86 (); + return singleton; +} diff --git a/gnuradio-core/src/lib/general/CMakeLists.txt b/gnuradio-core/src/lib/general/CMakeLists.txt new file mode 100644 index 000000000..ce9a80f37 --- /dev/null +++ b/gnuradio-core/src/lib/general/CMakeLists.txt @@ -0,0 +1,312 @@ +# Copyright 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. + +######################################################################## +# This file included, use CMake directory variables +######################################################################## + +######################################################################## +# Handle the generated sine table +######################################################################## +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/sine_table.h + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/gen_sine_table.py + COMMAND ${PYTHON_EXECUTABLE} + ${CMAKE_CURRENT_SOURCE_DIR}/gen_sine_table.py > + ${CMAKE_CURRENT_BINARY_DIR}/sine_table.h +) + +include(AddFileDependencies) +ADD_FILE_DEPENDENCIES(${CMAKE_CURRENT_SOURCE_DIR}/gr_fxpt.cc + ${CMAKE_CURRENT_BINARY_DIR}/sine_table.h +) + +add_custom_target(general_generated DEPENDS + ${CMAKE_CURRENT_BINARY_DIR}/sine_table.h +) + +######################################################################## +# Handle the generated constants +######################################################################## +execute_process(COMMAND ${PYTHON_EXECUTABLE} -c + "import time;print time.strftime('%a, %d %b %Y %H:%M:%S', time.gmtime())" + OUTPUT_VARIABLE BUILD_DATE OUTPUT_STRIP_TRAILING_WHITESPACE +) +message(STATUS "Loading build date ${BUILD_DATE} into gr_constants...") + +message(STATUS "Loading version ${VERSION} into gr_constants...") + +#double escape for windows backslash path separators +string(REPLACE "\\" "\\\\" prefix ${prefix}) +string(REPLACE "\\" "\\\\" SYSCONFDIR ${SYSCONFDIR}) +string(REPLACE "\\" "\\\\" GR_PREFSDIR ${GR_PREFSDIR}) + +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/gr_constants.cc.in + ${CMAKE_CURRENT_BINARY_DIR}/gr_constants.cc +@ONLY) + +list(APPEND gnuradio_core_sources ${CMAKE_CURRENT_BINARY_DIR}/gr_constants.cc) + +######################################################################## +# Append gnuradio-core library sources +######################################################################## +list(APPEND gnuradio_core_sources + ${CMAKE_CURRENT_SOURCE_DIR}/gr_circular_file.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_count_bits.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fast_atan2f.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fft_vcc_fftw.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fxpt.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_misc.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_random.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_reverse.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gri_add_const_ss_generic.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gri_char_to_float.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gri_control_loop.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gri_debugger_hook.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gri_fft.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gri_float_to_char.cc + ${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 + ${CMAKE_CURRENT_SOURCE_DIR}/gri_uchar_to_float.cc + ${CMAKE_CURRENT_SOURCE_DIR}/malloc16.c +) + +######################################################################## +# Append gnuradio-core test sources +######################################################################## +list(APPEND test_gnuradio_core_sources + ${CMAKE_CURRENT_SOURCE_DIR}/qa_general.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_circular_file.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_cpm.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_firdes.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_fxpt.cc + ${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 +) + +######################################################################## +# Install runtime headers +######################################################################## +install(FILES + ${CMAKE_CURRENT_SOURCE_DIR}/gr_core_api.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_circular_file.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_constants.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_count_bits.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_expj.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fft_vcc_fftw.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fxpt.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fxpt_nco.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_fxpt_vco.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_log2_const.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_math.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_misc.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_nco.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_random.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_reverse.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_simple_framer_sync.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_test_types.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_vco.h + ${CMAKE_CURRENT_SOURCE_DIR}/gri_add_const_ss.h + ${CMAKE_CURRENT_SOURCE_DIR}/gri_agc_cc.h + ${CMAKE_CURRENT_SOURCE_DIR}/gri_agc_ff.h + ${CMAKE_CURRENT_SOURCE_DIR}/gri_agc2_cc.h + ${CMAKE_CURRENT_SOURCE_DIR}/gri_agc2_ff.h + ${CMAKE_CURRENT_SOURCE_DIR}/gri_char_to_float.h + ${CMAKE_CURRENT_SOURCE_DIR}/gri_control_loop.h + ${CMAKE_CURRENT_SOURCE_DIR}/gri_debugger_hook.h + ${CMAKE_CURRENT_SOURCE_DIR}/gri_fft.h + ${CMAKE_CURRENT_SOURCE_DIR}/gri_float_to_char.h + ${CMAKE_CURRENT_SOURCE_DIR}/gri_float_to_int.h + ${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 + ${CMAKE_CURRENT_SOURCE_DIR}/gri_int_to_float.h + ${CMAKE_CURRENT_SOURCE_DIR}/gri_short_to_float.h + ${CMAKE_CURRENT_SOURCE_DIR}/gri_uchar_to_float.h + ${CMAKE_CURRENT_SOURCE_DIR}/malloc16.h + ${CMAKE_CURRENT_SOURCE_DIR}/random.h + DESTINATION ${GR_INCLUDE_DIR}/gnuradio + COMPONENT "core_devel" +) + +######################################################################## +# Install swig headers +######################################################################## +if(ENABLE_PYTHON) +install(FILES + ${CMAKE_CURRENT_SOURCE_DIR}/general.i + ${CMAKE_CURRENT_SOURCE_DIR}/gr_constants.i + ${CMAKE_CURRENT_SOURCE_DIR}/gri_agc_cc.i + ${CMAKE_CURRENT_SOURCE_DIR}/gri_agc_ff.i + ${CMAKE_CURRENT_SOURCE_DIR}/gri_agc2_cc.i + ${CMAKE_CURRENT_SOURCE_DIR}/gri_agc2_ff.i + ${CMAKE_CURRENT_SOURCE_DIR}/gri_control_loop.i + DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig + COMPONENT "core_swig" +) +endif(ENABLE_PYTHON) + +######################################################################## +# Handle triple-threat files that have cc, h, and i +######################################################################## +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_block_gateway + gr_bytes_to_syms + gr_char_to_float + gr_char_to_short + gr_check_counting_s + gr_check_lfsr_32k_s + gr_complex_to_interleaved_short + gr_complex_to_xxx + gr_conjugate_cc + gr_copy + gr_cpfsk_bc + 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 + gr_encode_ccsds_27_bb + gr_endian_swap + gr_fake_channel_coder_pp + gr_feedforward_agc_cc + gr_feval + gr_fft_vcc + gr_fft_vfc + gr_firdes + gr_float_to_char + gr_float_to_complex + gr_float_to_int + gr_float_to_short + 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 + gr_interleaved_short_to_complex + gr_iqcomp_cc + gr_keep_one_in_n + 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 + gr_multiply_const_ff + gr_multiply_conjugate_cc + gr_nlog10_ff + gr_nop + 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 + gr_probe_avg_mag_sqrd_f + gr_pwr_squelch_cc + gr_pwr_squelch_ff + gr_quadrature_demod_cf + gr_random_pdu + gr_rail_ff + gr_regenerate_bb + gr_remez + gr_rms_cf + gr_rms_ff + gr_repeat + gr_short_to_float + gr_short_to_char + gr_simple_correlator + gr_simple_framer + gr_simple_squelch_cc + gr_skiphead + gr_squelch_base_cc + gr_squelch_base_ff + gr_stream_mux + gr_stream_to_streams + gr_stream_to_vector + gr_streams_to_stream + gr_streams_to_vector + gr_stretch_ff + gr_test + gr_threshold_ff + gr_throttle + gr_transcendental + gr_uchar_to_float + gr_vco_f + gr_vector_map + gr_vector_to_stream + 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 + gr_message_strobe +) + +foreach(file_tt ${gr_core_general_triple_threats}) + list(APPEND gnuradio_core_sources ${CMAKE_CURRENT_SOURCE_DIR}/${file_tt}.cc) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${file_tt}.h DESTINATION ${GR_INCLUDE_DIR}/gnuradio COMPONENT "core_devel") + if(ENABLE_PYTHON) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${file_tt}.i DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig COMPONENT "core_swig") + endif(ENABLE_PYTHON) +endforeach(file_tt ${gr_core_general_triple_threats}) diff --git a/gnuradio-core/src/lib/general/README b/gnuradio-core/src/lib/general/README new file mode 100644 index 000000000..5fa18d7f6 --- /dev/null +++ b/gnuradio-core/src/lib/general/README @@ -0,0 +1,98 @@ +Files beginning with Gr* define classes that inherit from VrSigProc. +These are high level signal processing modules that can be glued +together in your signal processing chain. + +All the others are either lower level routines which implement the +functionality of the Gr* modules, but are easier to test (fewer +dependencies), or they are general purpose. + +gr_fir_???.{h,cc}, where ??? are in F, S or C are low level Finite +Impulse Response Filters. These turn out to be where the bulk of the +cycles are burned in many applications. The ??? suffix specifies the +input type, output type and tap type of the arguments. We've +implemented the most frequently used ones. + +[Once upon a time this stuff was done with templates +(gr_fir<iType,oType,tapType>), but this turned out to be a headache. +The code appeared to trigger a bug in GCC where we were getting +multiple definitions of unrelated stuff when we started subclassing +partially specialized templates. It was also not obvious as to to +what combinations of iType, oType and tapType actually worked. We're +now explicit, and the world is a safer place to live...] + +The top level routines for FIR filtering are: + + GrFIRfilterFFF : Float input, Float output, Float taps + -- general purpose + + GrFIRfilterCCF : Complex input, Complex output, Float taps + -- applying real filter to a complex signal + + GrFIRfilterFCC : Float input, Complex output, Complex taps + -- applying complex filter to float input + + GrFIRfilterSCC : Short input, Complex output, Complex taps + -- applying complex filter to short input. Quantizes complex + coefficients to 16 bits and uses MMX or SSE2 as appropriate + + +The combination of down conversion (frequency translation) and channel +selection (filtering) is performed with: + + GrFreqXlatingFIRfilterSFC : Short input, Float taps, Complex baseband output + -- quantizes complex coefficents to 16 bits and uses MMX or + SSE2 (128-bit MMX) as appropriate [optimization to be done]. + + GrFreqXlatingFIRfilterFFC : Float input, Float taps, Complex baseband output + -- 3dnow or SSE as appropriate. + + +[ The stuff described from here down is used to implement the routines + above. This info is only relevant to those who are hacking the internals ] + + +A bit of indirection is involved in selecting the fastest +implementation for any given platform. The lower level classes +gr_fir_FFF.h, gr_fir_CCF, gr_fir_FCC and gr_fir_SCC have i/o +signatures similar to the high level clases above. These +should be considered the abstract base classes that you +work with. Note that they are not actually abstract (they've got a +default implementation; this might be considered a bug), but they +should not be directly instantiated by user code. + +Instead of directly instantiating a gr_fir_FFF, for example, your code +should actually: + + #include <gr_fir_util.h> + + // let the system pick the best implementation for you + gr_fir_FFF *filter = gr_fir_util::create_gr_fir_FFF (my_taps); + +Clear? The same for all the other gr_fir_XXX's. + + + +Performance hacking can be done by subclassing the appropriate +base class. For example, on the x86 platform, there are two +additional classes derived from gr_fir_FFF, gr_fir_FFF_sse and +gr_fir_FFF_3dnow. These classes are then made available to the rest +of the system by virtue of being added to gr_fir_sysconfig_x86.cc, +along with any guards (CPUID checks) needed to ensure that only +compatible code is executed on the current hardware. + + +TO DO +------ + +* Move all the machine specific code to a subdirectory, then have +configure symlink to the right directory. This will allow us to build on +any platform without choking. There is generic code for all routines, +only the machine dependent speedup will be lacking. + +* Add an interface to gr_fir_util that will return a vector of all +valid constructors with descriptive names for each i/o signature. +This will allow the test code and benchmarking code to be blissfully +ignorant of what platform they're running on. The actual building of +the vectors should be done bottom up through the gr_fir_sysconfig +hierarchy. + diff --git a/gnuradio-core/src/lib/general/atsc_rrc1x.dat b/gnuradio-core/src/lib/general/atsc_rrc1x.dat new file mode 100644 index 000000000..3dc87bb0b --- /dev/null +++ b/gnuradio-core/src/lib/general/atsc_rrc1x.dat @@ -0,0 +1,57 @@ +/* + * FILTER SPECIFICATION FILE + * FILTER TYPE:ROOT RAISED COSINE 12H + * PASSBAND RIPPLE IN -dB -.0500 + * STOPBAND RIPPLE IN -dB -50.0000 + * SYMBOL RATE .538112E+07 HERTZ + * ROLLOF FACTOR .115200 + * SAMPLING FREQUENCY .107622E+08 HERTZ + * SAMPLING FREQUENCY .107622E+08 HERTZ + */ + .1821269281208515e-02, + -.9323525242507458e-02, + -.8581001311540604e-02, + .2809949219226837e-02, + .9649330750107765e-03, + -.4944681189954281e-02, + .1624439377337694e-02, + .6519509013742209e-02, + -.4803944379091263e-02, + -.8026130497455597e-02, + .8922342676669359e-02, + .9611152112483978e-02, + -.1463735569268465e-01, + -.1107082655653358e-01, + .2262782817706466e-01, + .1240625558421016e-01, + -.3461387194693089e-01, + -.1348070800304413e-01, + .5474480940029025e-01, + .1432673400267959e-01, + -.9872047463431954e-01, + -.1482593175023794e-01, + .3077511447481811e+00, + .5007477863691747e+00, + .3077511447481811e+00, + -.1482593175023794e-01, + -.9872047463431954e-01, + .1432673400267959e-01, + .5474480940029025e-01, + -.1348070800304413e-01, + -.3461387194693089e-01, + .1240625558421016e-01, + .2262782817706466e-01, + -.1107082655653358e-01, + -.1463735569268465e-01, + .9611152112483978e-02, + .8922342676669359e-02, + -.8026130497455597e-02, + -.4803944379091263e-02, + .6519509013742209e-02, + .1624439377337694e-02, + -.4944681189954281e-02, + .9649330750107765e-03, + .2809949219226837e-02, + -.8581001311540604e-02, + -.9323525242507458e-02, + .1821269281208515e-02 diff --git a/gnuradio-core/src/lib/general/atsc_rrc20.dat b/gnuradio-core/src/lib/general/atsc_rrc20.dat new file mode 100644 index 000000000..94445e96e --- /dev/null +++ b/gnuradio-core/src/lib/general/atsc_rrc20.dat @@ -0,0 +1,101 @@ + -.1141865178942680e-01, + .2192483097314835e-01, + -.6814673542976379e-04, + -.5894266534596682e-02, + -.3580642864108086e-02, + .7064016535878182e-03, + .3225978463888168e-02, + .2832664176821709e-02, + .4997388459742069e-03, + -.1796286087483168e-02, + -.2396093215793371e-02, + -.1009003724902868e-02, + .1184449531137943e-02, + .2406611572951078e-02, + .1609810627996922e-02, + -.6790305487811565e-03, + -.2634476870298386e-02, + -.2524725627154112e-02, + -.1492514275014401e-03, + .2789965830743313e-02, + .3848167601972818e-02, + .1755146309733391e-02, + -.2288600429892540e-02, + -.5209952127188444e-02, + -.4314901307225227e-02, + .3885449841618538e-03, + .5747230723500252e-02, + .7460035849362612e-02, + .3387423232197762e-02, + -.4307936877012253e-02, + -.1007711654528976e-01, + -.8849395904690027e-02, + -.1979861408472061e-03, + .1040456583723426e-01, + .1484309835359454e-01, + .8285604882985354e-02, + -.6346960552036762e-02, + -.1915087224915624e-01, + -.1949162455275655e-01, + -.4145141225308180e-02, + .1850909460335970e-01, + .3220130456611514e-01, + .2337836893275380e-01, + -.7863232865929604e-02, + -.4402747144922614e-01, + -.5751598253846169e-01, + -.2598480274900794e-01, + .5246857088059187e-01, + .1544690094888210e+00, + .2405302016995847e+00, + .2741314689628780e+00, + .2405302016995847e+00, + .1544690094888210e+00, + .5246857088059187e-01, + -.2598480274900794e-01, + -.5751598253846169e-01, + -.4402747144922614e-01, + -.7863232865929604e-02, + .2337836893275380e-01, + .3220130456611514e-01, + .1850909460335970e-01, + -.4145141225308180e-02, + -.1949162455275655e-01, + -.1915087224915624e-01, + -.6346960552036762e-02, + .8285604882985354e-02, + .1484309835359454e-01, + .1040456583723426e-01, + -.1979861408472061e-03, + -.8849395904690027e-02, + -.1007711654528976e-01, + -.4307936877012253e-02, + .3387423232197762e-02, + .7460035849362612e-02, + .5747230723500252e-02, + .3885449841618538e-03, + -.4314901307225227e-02, + -.5209952127188444e-02, + -.2288600429892540e-02, + .1755146309733391e-02, + .3848167601972818e-02, + .2789965830743313e-02, + -.1492514275014401e-03, + -.2524725627154112e-02, + -.2634476870298386e-02, + -.6790305487811565e-03, + .1609810627996922e-02, + .2406611572951078e-02, + .1184449531137943e-02, + -.1009003724902868e-02, + -.2396093215793371e-02, + -.1796286087483168e-02, + .4997388459742069e-03, + .2832664176821709e-02, + .3225978463888168e-02, + .7064016535878182e-03, + -.3580642864108086e-02, + -.5894266534596682e-02, + -.6814673542976379e-04, + .2192483097314835e-01, + -.1141865178942680e-01 diff --git a/gnuradio-core/src/lib/general/atsc_rrc2x.dat b/gnuradio-core/src/lib/general/atsc_rrc2x.dat new file mode 100644 index 000000000..8eae94d77 --- /dev/null +++ b/gnuradio-core/src/lib/general/atsc_rrc2x.dat @@ -0,0 +1,102 @@ +/* + * FILTER SPECIFICATION FILE + * FILTER TYPE:ROOT RAISED COSINE 12H + * PASSBAND RIPPLE IN -dB -.0500 + * STOPBAND RIPPLE IN -dB -50.0000 + * SYMBOL RATE .538112E+07 HERTZ + * ROLLOF FACTOR .115200 + * SAMPLING FREQUENCY .215245E+08 HERTZ +*/ + .8186036720871925E-03, + -.1256920862942934E-02, + -.4844595678150654E-02, + -.6055080797523260E-02, + -.4247304052114487E-02, + -.9502284228801727E-03, + .1615938264876604E-02, + .2120061777532101E-02, + .6354246288537979E-03, + -.1464351080358028E-02, + -.2508673351258040E-02, + -.1573510002344847E-02, + .8145328611135483E-03, + .2996938303112984E-02, + .3244197461754084E-02, + .1038576476275921E-02, + -.2401810139417648E-02, + -.4728596191853285E-02, + -.4019895102828741E-02, + -.2215979620814323E-03, + .4481043666601181E-02, + .6867439020425081E-02, + .4793671425431967E-02, + -.1089230179786682E-02, + -.7325290236622095E-02, + -.9580074809491634E-02, + -.5532339215278626E-02, + .3166179172694683E-02, + .1132524851709604E-01, + .1316944882273674E-01, + .6192639470100403E-02, + -.6509334780275822E-02, + -.1730504119768739E-01, + -.1832502009347081E-01, + -.6741075310856104E-02, + .1229691226035357E-01, + .2738198731094599E-01, + .2702147699892521E-01, + .7156732492148876E-02, + -.2432488137856126E-01, + -.4934547096490860E-01, + -.4763523396104574E-01, + -.7410581223666668E-02, + .6681889295578003E-01, + .1538293845951557E+00, + .2236228249967098E+00, + .2502835178747773E+00, + .2236228249967098E+00, + .1538293845951557E+00, + .6681889295578003E-01, + -.7410581223666668E-02, + -.4763523396104574E-01, + -.4934547096490860E-01, + -.2432488137856126E-01, + .7156732492148876E-02, + .2702147699892521E-01, + .2738198731094599E-01, + .1229691226035357E-01, + -.6741075310856104E-02, + -.1832502009347081E-01, + -.1730504119768739E-01, + -.6509334780275822E-02, + .6192639470100403E-02, + .1316944882273674E-01, + .1132524851709604E-01, + .3166179172694683E-02, + -.5532339215278626E-02, + -.9580074809491634E-02, + -.7325290236622095E-02, + -.1089230179786682E-02, + .4793671425431967E-02, + .6867439020425081E-02, + .4481043666601181E-02, + -.2215979620814323E-03, + -.4019895102828741E-02, + -.4728596191853285E-02, + -.2401810139417648E-02, + .1038576476275921E-02, + .3244197461754084E-02, + .2996938303112984E-02, + .8145328611135483E-03, + -.1573510002344847E-02, + -.2508673351258040E-02, + -.1464351080358028E-02, + .6354246288537979E-03, + .2120061777532101E-02, + .1615938264876604E-02, + -.9502284228801727E-03, + -.4247304052114487E-02, + -.6055080797523260E-02, + -.4844595678150654E-02, + -.1256920862942934E-02, + .8186036720871925E-03 diff --git a/gnuradio-core/src/lib/general/complex_vec_test.cc b/gnuradio-core/src/lib/general/complex_vec_test.cc new file mode 100644 index 000000000..99acc2f35 --- /dev/null +++ b/gnuradio-core/src/lib/general/complex_vec_test.cc @@ -0,0 +1,82 @@ +#include <complex_vec_test.h> +#include <stddef.h> + +std::vector<std::complex<float> > +complex_vec_test0() +{ + std::vector<std::complex<float> > r(5); + + for (size_t i = 0; i < r.size(); i++) + r[i] = std::complex<float>(i, i); + + return r; +} + +std::vector<std::complex<float> > +complex_vec_test1(const std::vector<std::complex<float> > &input) +{ + std::vector<std::complex<float> > r(input.size()); + + for (size_t i = 0; i < input.size(); i++) + r[i] = std::complex<float>(input[i].real()+0.5, input[i].imag()-0.5); + + return r; +} + +std::complex<float> +complex_scalar_test0() +{ + return std::complex<float>(5, 5); +} + +std::complex<float> +complex_scalar_test1(std::complex<float> input) +{ + return std::complex<float>(input.real()+0.5, input.imag()-0.5); +} + + +std::vector<float> +float_vec_test0() +{ + std::vector<float> r(5); + + for (size_t i = 0; i < r.size(); i++) + r[i] = (float) i; + + return r; +} + +std::vector<float> +float_vec_test1(const std::vector<float> &input) +{ + std::vector<float> r(input.size()); + + for (size_t i = 0; i < input.size(); i++) + r[i] = input[i] + 0.5; + + return r; +} + +std::vector<int> +int_vec_test0() +{ + std::vector<int> r(5); + + for (size_t i = 0; i < r.size(); i++) + r[i] = (int) i; + + return r; +} + +std::vector<int> +int_vec_test1(const std::vector<int> &input) +{ + std::vector<int> r(input.size()); + + for (size_t i = 0; i < input.size(); i++) + r[i] = input[i] + 1; + + return r; +} + diff --git a/gnuradio-core/src/lib/general/complex_vec_test.h b/gnuradio-core/src/lib/general/complex_vec_test.h new file mode 100644 index 000000000..be4de41fb --- /dev/null +++ b/gnuradio-core/src/lib/general/complex_vec_test.h @@ -0,0 +1,28 @@ +#include <gr_core_api.h> +#include <vector> +#include <complex> + +GR_CORE_API std::vector<std::complex<float> > +complex_vec_test0(); + +GR_CORE_API std::vector<std::complex<float> > +complex_vec_test1(const std::vector<std::complex<float> > &input); + +GR_CORE_API std::complex<float> +complex_scalar_test0(); + +GR_CORE_API std::complex<float> +complex_scalar_test1(std::complex<float> input); + +GR_CORE_API std::vector<int> +int_vec_test0(); + +GR_CORE_API std::vector<int> +int_vec_test1(const std::vector<int> &input); + +GR_CORE_API std::vector<float> +float_vec_test0(); + +GR_CORE_API std::vector<float> +float_vec_test1(const std::vector<float> &input); + diff --git a/gnuradio-core/src/lib/general/complex_vec_test.i b/gnuradio-core/src/lib/general/complex_vec_test.i new file mode 100644 index 000000000..4b95633be --- /dev/null +++ b/gnuradio-core/src/lib/general/complex_vec_test.i @@ -0,0 +1,25 @@ + +std::vector<std::complex<float> > +complex_vec_test0(); + +std::vector<std::complex<float> > +complex_vec_test1(const std::vector<std::complex<float> > &input); + +std::complex<float> +complex_scalar_test0(); + +std::complex<float> +complex_scalar_test1(std::complex<float> input); + +std::vector<int> +int_vec_test0(); + +std::vector<int> +int_vec_test1(const std::vector<int> &input); + +std::vector<float> +float_vec_test0(); + +std::vector<float> +float_vec_test1(const std::vector<float> &input); + diff --git a/gnuradio-core/src/lib/general/gen_sine_table.py b/gnuradio-core/src/lib/general/gen_sine_table.py new file mode 100755 index 000000000..d7d11eff1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gen_sine_table.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python +# +# 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. +# + +import math +import sys + +def wrap (x): + if x >= 2**31: + return x - 2**32 + return x + +def gen_approx_table (f, nentries, min_x, max_x): + """return a list of nentries containing tuples of the form: + (m, c, abs_error). min_x and max_x specify the domain + of the table. + """ + r = [] + incx = float (max_x - min_x) / nentries + for i in range (nentries): + a = (i * incx) + min_x + b = ((i + 1) * incx) + min_x + m = (f(b)-f(a))/(b-a) + c = (3*a+b)*(f(a)-f(b))/(4*(b-a)) + (f((a+b)/2) + f(a))/2 + abs_error = c+m*a-f(a) + r.append ((m, c, abs_error)) + return r + +def scaled_sine (x): + return math.sin (x * math.pi / 2**31) + +def gen_sine_table (): + nbits = 10 + nentries = 2**nbits + + # min_x = -2**31 + # max_x = 2**31-1 + min_x = 0 + max_x = 2**32-1 + t = gen_approx_table (scaled_sine, nentries, min_x, max_x) + + max_error = 0 + for e in t: + max_error = max (max_error, abs (e[2])) + + # sys.stdout.write ('static const int WORDBITS = 32;\n') + # sys.stdout.write ('static const int NBITS = %d;\n' % (nbits,)) + + sys.stdout.write (' // max_error = %22.15e\n' % (max_error,)) + + # sys.stdout.write ('static const double sine_table[%d][2] = {\n'% (nentries,)) + + for e in t: + sys.stdout.write (' { %22.15e, %22.15e },\n' % (2 * e[0], e[1])) + + # sys.stdout.write ('};\n') + +if __name__ == '__main__': + gen_sine_table () diff --git a/gnuradio-core/src/lib/general/general.i b/gnuradio-core/src/lib/general/general.i new file mode 100644 index 000000000..b727bc8a6 --- /dev/null +++ b/gnuradio-core/src/lib/general/general.i @@ -0,0 +1,273 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004-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 <gri_control_loop.h> +#include <gr_nop.h> +#include <gr_null_sink.h> +#include <gr_null_source.h> +#include <gr_head.h> +#include <gr_skiphead.h> +#include <gr_quadrature_demod_cf.h> +#include <gr_remez.h> +#include <gr_float_to_complex.h> +#include <gr_check_counting_s.h> +#include <gr_lfsr_32k_source_s.h> +#include <gr_check_lfsr_32k_s.h> +#include <gr_stream_to_vector.h> +#include <gr_vector_to_stream.h> +#include <gr_keep_one_in_n.h> +#include <gr_keep_m_in_n.h> +#include <gr_fft_vcc.h> +#include <gr_fft_vfc.h> +#include <gr_float_to_int.h> +#include <gr_float_to_short.h> +#include <gr_float_to_char.h> +#include <gr_float_to_uchar.h> +#include <gr_short_to_float.h> +#include <gr_short_to_char.h> +#include <gr_int_to_float.h> +#include <gr_char_to_float.h> +#include <gr_char_to_short.h> +#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> +#include <gr_interleaved_short_to_complex.h> +//#include <gr_endianness.h> +#include <gr_endian_swap.h> +#include <gr_firdes.h> +#include <gr_interleave.h> +#include <gr_deinterleave.h> +#include <gr_delay.h> +#include <gr_simple_squelch_cc.h> +#include <gr_agc_ff.h> +#include <gr_agc_cc.h> +#include <gr_agc2_ff.h> +#include <gr_agc2_cc.h> +#include <gr_random_pdu.h> +#include <gr_rms_cf.h> +#include <gr_rms_ff.h> +#include <gr_nlog10_ff.h> +#include <gr_fake_channel_coder_pp.h> +#include <gr_throttle.h> +#include <gr_transcendental.h> +#include <gr_stream_mux.h> +#include <gr_stream_to_streams.h> +#include <gr_streams_to_stream.h> +#include <gr_streams_to_vector.h> +#include <gr_vector_to_streams.h> +#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> +#include <gr_regenerate_bb.h> +#include <gr_pa_2x2_phase_combiner.h> +#include <gr_kludge_copy.h> +#include <gr_prefs.h> +#include <gr_constants.h> +#include <gr_test_types.h> +#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> +#include <gr_multiply_const_ff.h> +#include <gr_multiply_conjugate_cc.h> +#include <gr_feval.h> +#include <gr_pwr_squelch_cc.h> +#include <gr_pwr_squelch_ff.h> +#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_tag_debug.h> +#include <gr_message_strobe.h> +%} + +%include "gri_control_loop.i" +%include "gr_nop.i" +%include "gr_null_sink.i" +%include "gr_null_source.i" +%include "gr_head.i" +%include "gr_skiphead.i" +%include "gr_quadrature_demod_cf.i" +%include "gr_remez.i" +%include "gr_float_to_complex.i" +%include "gr_check_counting_s.i" +%include "gr_lfsr_32k_source_s.i" +%include "gr_check_lfsr_32k_s.i" +%include "gr_stream_to_vector.i" +%include "gr_vector_to_stream.i" +%include "gr_keep_one_in_n.i" +%include "gr_keep_m_in_n.i" +%include "gr_fft_vcc.i" +%include "gr_fft_vfc.i" +%include "gr_float_to_int.i" +%include "gr_float_to_short.i" +%include "gr_float_to_char.i" +%include "gr_float_to_uchar.i" +%include "gr_short_to_float.i" +%include "gr_short_to_char.i" +%include "gr_int_to_float.i" +%include "gr_char_to_float.i" +%include "gr_char_to_short.i" +%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" +//%include "gr_endianness.i" +%include "gr_endian_swap.i" +%include "gr_interleaved_short_to_complex.i" +%include "gr_firdes.i" +%include "gr_interleave.i" +%include "gr_deinterleave.i" +%include "gr_delay.i" +%include "gr_simple_squelch_cc.i" +%include "gr_agc_ff.i" +%include "gr_agc_cc.i" +%include "gr_agc2_ff.i" +%include "gr_agc2_cc.i" +%include "gr_random_pdu.i" +%include "gr_rms_cf.i" +%include "gr_rms_ff.i" +%include "gr_nlog10_ff.i" +%include "gr_fake_channel_coder_pp.i" +%include "gr_throttle.i" +%include "gr_transcendental.i" +%include "gr_stream_mux.i" +%include "gr_stream_to_streams.i" +%include "gr_streams_to_stream.i" +%include "gr_streams_to_vector.i" +%include "gr_vector_to_streams.i" +%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" +%include "gr_regenerate_bb.i" +%include "gr_pa_2x2_phase_combiner.i" +%include "gr_kludge_copy.i" +%include "gr_prefs.i" +%include "gr_constants.i" +%include "gr_test_types.h" +%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" +%include "gr_multiply_const_ff.i" +%include "gr_multiply_conjugate_cc.i" +%include "gr_feval.i" +%include "gr_pwr_squelch_cc.i" +%include "gr_pwr_squelch_ff.i" +%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_tag_debug.i" +%include "gr_block_gateway.i" +%include "gr_message_strobe.i" diff --git a/gnuradio-core/src/lib/general/general_generated.i b/gnuradio-core/src/lib/general/general_generated.i new file mode 100644 index 000000000..89b7e1776 --- /dev/null +++ b/gnuradio-core/src/lib/general/general_generated.i @@ -0,0 +1,166 @@ +// +// This file is machine generated. All edits will be overwritten +// +%{ +#include <gr_add_cc.h> +#include <gr_add_const_cc.h> +#include <gr_add_const_ff.h> +#include <gr_add_const_ii.h> +#include <gr_add_const_sf.h> +#include <gr_add_const_ss.h> +#include <gr_add_const_vcc.h> +#include <gr_add_const_vff.h> +#include <gr_add_const_vii.h> +#include <gr_add_const_vss.h> +#include <gr_add_ii.h> +#include <gr_add_ss.h> +#include <gr_add_vcc.h> +#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> +#include <gr_divide_ss.h> +#include <gr_multiply_const_ii.h> +#include <gr_multiply_const_ss.h> +#include <gr_multiply_const_vcc.h> +#include <gr_multiply_const_vff.h> +#include <gr_multiply_const_vii.h> +#include <gr_multiply_const_vss.h> +#include <gr_multiply_ii.h> +#include <gr_multiply_ss.h> +#include <gr_multiply_vcc.h> +#include <gr_multiply_vff.h> +#include <gr_multiply_vii.h> +#include <gr_multiply_vss.h> +#include <gr_mute_cc.h> +#include <gr_mute_ff.h> +#include <gr_mute_ii.h> +#include <gr_mute_ss.h> +#include <gr_noise_source_c.h> +#include <gr_noise_source_f.h> +#include <gr_noise_source_i.h> +#include <gr_noise_source_s.h> +#include <gr_packed_to_unpacked_bb.h> +#include <gr_packed_to_unpacked_ii.h> +#include <gr_packed_to_unpacked_ss.h> +#include <gr_probe_signal_b.h> +#include <gr_probe_signal_s.h> +#include <gr_probe_signal_i.h> +#include <gr_probe_signal_f.h> +#include <gr_probe_signal_c.h> +#include <gr_probe_signal_vb.h> +#include <gr_probe_signal_vs.h> +#include <gr_probe_signal_vi.h> +#include <gr_probe_signal_vf.h> +#include <gr_probe_signal_vc.h> +#include <gr_sig_source_c.h> +#include <gr_sig_source_f.h> +#include <gr_sig_source_i.h> +#include <gr_sig_source_s.h> +#include <gr_sub_cc.h> +#include <gr_sub_ff.h> +#include <gr_sub_ii.h> +#include <gr_sub_ss.h> +#include <gr_unpacked_to_packed_bb.h> +#include <gr_unpacked_to_packed_ii.h> +#include <gr_unpacked_to_packed_ss.h> +#include <gr_vector_sink_b.h> +#include <gr_vector_sink_c.h> +#include <gr_vector_sink_f.h> +#include <gr_vector_sink_i.h> +#include <gr_vector_sink_s.h> +#include <gr_vector_source_b.h> +#include <gr_vector_source_c.h> +#include <gr_vector_source_f.h> +#include <gr_vector_source_i.h> +#include <gr_vector_source_s.h> +%} + +%include <gr_add_cc.i> +%include <gr_add_const_cc.i> +%include <gr_add_const_ff.i> +%include <gr_add_const_ii.i> +%include <gr_add_const_sf.i> +%include <gr_add_const_ss.i> +%include <gr_add_const_vcc.i> +%include <gr_add_const_vff.i> +%include <gr_add_const_vii.i> +%include <gr_add_const_vss.i> +%include <gr_add_ii.i> +%include <gr_add_ss.i> +%include <gr_add_vcc.i> +%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> +%include <gr_divide_ss.i> +%include <gr_multiply_const_ii.i> +%include <gr_multiply_const_ss.i> +%include <gr_multiply_const_vcc.i> +%include <gr_multiply_const_vff.i> +%include <gr_multiply_const_vii.i> +%include <gr_multiply_const_vss.i> +%include <gr_multiply_ii.i> +%include <gr_multiply_ss.i> +%include <gr_multiply_vcc.i> +%include <gr_multiply_vff.i> +%include <gr_multiply_vii.i> +%include <gr_multiply_vss.i> +%include <gr_mute_cc.i> +%include <gr_mute_ff.i> +%include <gr_mute_ii.i> +%include <gr_mute_ss.i> +%include <gr_noise_source_c.i> +%include <gr_noise_source_f.i> +%include <gr_noise_source_i.i> +%include <gr_noise_source_s.i> +%include <gr_packed_to_unpacked_bb.i> +%include <gr_packed_to_unpacked_ii.i> +%include <gr_packed_to_unpacked_ss.i> +%include <gr_probe_signal_b.i> +%include <gr_probe_signal_s.i> +%include <gr_probe_signal_i.i> +%include <gr_probe_signal_f.i> +%include <gr_probe_signal_c.i> +%include <gr_probe_signal_vb.i> +%include <gr_probe_signal_vs.i> +%include <gr_probe_signal_vi.i> +%include <gr_probe_signal_vf.i> +%include <gr_probe_signal_vc.i> +%include <gr_sig_source_c.i> +%include <gr_sig_source_f.i> +%include <gr_sig_source_i.i> +%include <gr_sig_source_s.i> +%include <gr_sub_cc.i> +%include <gr_sub_ff.i> +%include <gr_sub_ii.i> +%include <gr_sub_ss.i> +%include <gr_unpacked_to_packed_bb.i> +%include <gr_unpacked_to_packed_ii.i> +%include <gr_unpacked_to_packed_ss.i> +%include <gr_vector_sink_b.i> +%include <gr_vector_sink_c.i> +%include <gr_vector_sink_f.i> +%include <gr_vector_sink_i.i> +%include <gr_vector_sink_s.i> +%include <gr_vector_source_b.i> +%include <gr_vector_source_c.i> +%include <gr_vector_source_f.i> +%include <gr_vector_source_i.i> +%include <gr_vector_source_s.i> diff --git a/gnuradio-core/src/lib/general/gr_add_ff.cc b/gnuradio-core/src/lib/general/gr_add_ff.cc new file mode 100644 index 000000000..5f6676bb7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_ff.cc @@ -0,0 +1,66 @@ +/* -*- 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 <gr_add_ff.h> +#include <gr_io_signature.h> +#include <volk/volk.h> + +gr_add_ff_sptr +gr_make_add_ff(size_t vlen) +{ + return gnuradio::get_initial_sptr(new gr_add_ff(vlen)); +} + +gr_add_ff::gr_add_ff (size_t vlen) + : gr_sync_block("add_ff", + gr_make_io_signature (1, -1, sizeof(float)*vlen), + gr_make_io_signature (1, 1, sizeof(float)*vlen)), + d_vlen (vlen) +{ + const int alignment_multiple = + volk_get_alignment() / sizeof(float); + set_alignment(std::max(1,alignment_multiple)); +} + +int +gr_add_ff::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float *out = (float *) output_items[0]; + int noi = d_vlen*noutput_items; + + memcpy(out, input_items[0], noi*sizeof(float)); + if(is_unaligned()) { + for(size_t i = 1; i < input_items.size(); i++) + volk_32f_x2_add_32f_u(out, out, (const float*)input_items[i], noi); + } + else { + for(size_t i = 1; i < input_items.size(); i++) + volk_32f_x2_add_32f_a(out, out, (const float*)input_items[i], noi); + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_add_ff.h b/gnuradio-core/src/lib/general/gr_add_ff.h new file mode 100644 index 000000000..ff5604c97 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_ff.h @@ -0,0 +1,56 @@ +/* -*- 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_GR_ADD_FF_H +#define INCLUDED_GR_ADD_FF_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_add_ff; +typedef boost::shared_ptr<gr_add_ff> gr_add_ff_sptr; + +GR_CORE_API gr_add_ff_sptr +gr_make_add_ff (size_t vlen=1); + +/*! + * \brief Add streams of complex values + * \ingroup math_blk + */ + +class GR_CORE_API gr_add_ff : public gr_sync_block +{ + private: + friend GR_CORE_API gr_add_ff_sptr + gr_make_add_ff (size_t vlen); + gr_add_ff (size_t vlen); + + size_t d_vlen; + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_ADD_FF_H */ diff --git a/gnuradio-core/src/lib/general/gr_add_ff.i b/gnuradio-core/src/lib/general/gr_add_ff.i new file mode 100644 index 000000000..75a87651f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_ff.i @@ -0,0 +1,32 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,add_ff) + +gr_add_ff_sptr +gr_make_add_ff (size_t vlen=1); + +class gr_add_ff : public gr_sync_block +{ +public: + +}; diff --git a/gnuradio-core/src/lib/general/gr_additive_scrambler_bb.cc b/gnuradio-core/src/lib/general/gr_additive_scrambler_bb.cc new file mode 100644 index 000000000..35cbb9572 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_additive_scrambler_bb.cc @@ -0,0 +1,65 @@ +/* -*- 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 new file mode 100644 index 000000000..1c336306d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_additive_scrambler_bb.h @@ -0,0 +1,68 @@ +/* -*- 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 new file mode 100644 index 000000000..acf9e8c47 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_additive_scrambler_bb.i @@ -0,0 +1,31 @@ +/* -*- 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_agc2_cc.cc b/gnuradio-core/src/lib/general/gr_agc2_cc.cc new file mode 100644 index 000000000..5097babc9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_agc2_cc.cc @@ -0,0 +1,56 @@ +/* -*- 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_agc2_cc.h> +#include <gr_io_signature.h> +#include <gri_agc2_cc.h> + +gr_agc2_cc_sptr +gr_make_agc2_cc (float attack_rate, float decay_rate, float reference, + float gain, float max_gain) +{ + return gnuradio::get_initial_sptr(new gr_agc2_cc (attack_rate, decay_rate, reference, gain, max_gain)); +} + +gr_agc2_cc::gr_agc2_cc (float attack_rate, float decay_rate, float reference, + float gain, float max_gain) + : gr_sync_block ("gr_agc2_cc", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (gr_complex))), + gri_agc2_cc (attack_rate, decay_rate, reference, gain, max_gain) +{ +} + +int +gr_agc2_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]; + scaleN (out, in, noutput_items); + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_agc2_cc.h b/gnuradio-core/src/lib/general/gr_agc2_cc.h new file mode 100644 index 000000000..54bae1aae --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_agc2_cc.h @@ -0,0 +1,56 @@ +/* -*- 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_AGC2_CC_H +#define INCLUDED_GR_AGC2_CC_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gri_agc2_cc.h> + +class gr_agc2_cc; +typedef boost::shared_ptr<gr_agc2_cc> gr_agc2_cc_sptr; + +GR_CORE_API gr_agc2_cc_sptr +gr_make_agc2_cc (float attack_rate = 1e-1, float decay_rate = 1e-2, float reference = 1.0, + float gain = 1.0, float max_gain = 0.0); +/*! + * \brief high performance Automatic Gain Control class + * \ingroup level_blk + * + * For Power the absolute value of the complex number is used. + */ + +class GR_CORE_API gr_agc2_cc : public gr_sync_block, public gri_agc2_cc +{ + friend GR_CORE_API gr_agc2_cc_sptr gr_make_agc2_cc (float attack_rate, float decay_rate, float reference, + float gain, float max_gain); + gr_agc2_cc (float attack_rate, float decay_rate, float reference, + float gain, float max_gain); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_AGC2_CC_H */ diff --git a/gnuradio-core/src/lib/general/gr_agc2_cc.i b/gnuradio-core/src/lib/general/gr_agc2_cc.i new file mode 100644 index 000000000..6d7b22101 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_agc2_cc.i @@ -0,0 +1,35 @@ +/* -*- 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,agc2_cc) + +%include <gri_agc2_cc.i> + +gr_agc2_cc_sptr +gr_make_agc2_cc (float attack_rate = 1e-1, float decay_rate = 1e-2, float reference = 1.0, + float gain = 1.0, float max_gain = 0.0); + +class gr_agc2_cc : public gr_sync_block , public gri_agc2_cc +{ + gr_agc2_cc (float attack_rate, float decay_rate, float reference, + float gain, float max_gain); +}; diff --git a/gnuradio-core/src/lib/general/gr_agc2_ff.cc b/gnuradio-core/src/lib/general/gr_agc2_ff.cc new file mode 100644 index 000000000..792ee1c6b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_agc2_ff.cc @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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_agc2_ff.h> +#include <gr_io_signature.h> +#include <gri_agc2_ff.h> + +gr_agc2_ff_sptr +gr_make_agc2_ff (float attack_rate, float decay_rate, float reference, + float gain, float max_gain) +{ + return gnuradio::get_initial_sptr(new gr_agc2_ff (attack_rate, decay_rate, reference, + gain, max_gain)); +} + +gr_agc2_ff::gr_agc2_ff (float attack_rate, float decay_rate, float reference, + float gain, float max_gain) + : gr_sync_block ("gr_agc2_ff", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (float))) + , gri_agc2_ff (attack_rate, decay_rate, reference, gain, max_gain) +{ +} + +int +gr_agc2_ff::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]; + scaleN (out, in, noutput_items); + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_agc2_ff.h b/gnuradio-core/src/lib/general/gr_agc2_ff.h new file mode 100644 index 000000000..48529948c --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_agc2_ff.h @@ -0,0 +1,54 @@ +/* -*- 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_AGC2_FF_H +#define INCLUDED_GR_AGC2_FF_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gri_agc2_ff.h> +class gr_agc2_ff; +typedef boost::shared_ptr<gr_agc2_ff> gr_agc2_ff_sptr; + +GR_CORE_API gr_agc2_ff_sptr +gr_make_agc2_ff (float attack_rate = 1e-1, float decay_rate = 1e-2, float reference = 1.0, + float gain = 1.0, float max_gain = 0.0); +/*! + * \brief high performance Automatic Gain Control class + * + * \ingroup level_blk + * Power is approximated by absolute value + */ + +class GR_CORE_API gr_agc2_ff : public gr_sync_block, public gri_agc2_ff +{ + friend GR_CORE_API gr_agc2_ff_sptr gr_make_agc2_ff (float attack_rate, float decay_rate, + float reference, float gain, float max_gain); + gr_agc2_ff (float attack_rate, float decay_rate, float reference, float gain, float max_gain); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_FLOAT_AGC2_FF_H */ diff --git a/gnuradio-core/src/lib/general/gr_agc2_ff.i b/gnuradio-core/src/lib/general/gr_agc2_ff.i new file mode 100644 index 000000000..646391aa7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_agc2_ff.i @@ -0,0 +1,35 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,agc2_ff) + +%include <gri_agc2_ff.i> + +gr_agc2_ff_sptr +gr_make_agc2_ff (float attack_rate = 1e-1, float decay_rate = 1e-2, float reference = 1.0, + float gain = 1.0, float max_gain = 0.0); + +class gr_agc2_ff : public gr_sync_block , public gri_agc2_ff +{ + gr_agc2_ff (float attack_rate, float decay_rate, float reference, + float gain, float max_gain); +}; diff --git a/gnuradio-core/src/lib/general/gr_agc_cc.cc b/gnuradio-core/src/lib/general/gr_agc_cc.cc new file mode 100644 index 000000000..e98f3a303 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_agc_cc.cc @@ -0,0 +1,56 @@ +/* -*- 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_agc_cc.h> +#include <gr_io_signature.h> +#include <gri_agc_cc.h> + +gr_agc_cc_sptr +gr_make_agc_cc (float rate, float reference, + float gain, float max_gain) +{ + return gnuradio::get_initial_sptr(new gr_agc_cc (rate, reference, gain, max_gain)); +} + +gr_agc_cc::gr_agc_cc (float rate, float reference, + float gain, float max_gain) + : gr_sync_block ("gr_agc_cc", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (gr_complex))), + gri_agc_cc (rate, reference, gain, max_gain) +{ +} + +int +gr_agc_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]; + scaleN (out, in, noutput_items); + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_agc_cc.h b/gnuradio-core/src/lib/general/gr_agc_cc.h new file mode 100644 index 000000000..9f35350db --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_agc_cc.h @@ -0,0 +1,55 @@ +/* -*- 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_AGC_CC_H +#define INCLUDED_GR_AGC_CC_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gri_agc_cc.h> +class gr_agc_cc; +typedef boost::shared_ptr<gr_agc_cc> gr_agc_cc_sptr; + +GR_CORE_API gr_agc_cc_sptr +gr_make_agc_cc (float rate = 1e-4, float reference = 1.0, + float gain = 1.0, float max_gain = 0.0); +/*! + * \brief high performance Automatic Gain Control class + * \ingroup level_blk + * + * For Power the absolute value of the complex number is used. + */ + +class GR_CORE_API gr_agc_cc : public gr_sync_block, public gri_agc_cc +{ + friend GR_CORE_API gr_agc_cc_sptr gr_make_agc_cc (float rate, float reference, + float gain, float max_gain); + gr_agc_cc (float rate, float reference, + float gain, float max_gain); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_AGC_CC_H */ diff --git a/gnuradio-core/src/lib/general/gr_agc_cc.i b/gnuradio-core/src/lib/general/gr_agc_cc.i new file mode 100644 index 000000000..f942713b0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_agc_cc.i @@ -0,0 +1,35 @@ +/* -*- 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,agc_cc) + +%include <gri_agc_cc.i> + +gr_agc_cc_sptr +gr_make_agc_cc (float rate = 1e-4, float reference = 1.0, + float gain = 1.0, float max_gain = 0.0); + +class gr_agc_cc : public gr_sync_block , public gri_agc_cc +{ + gr_agc_cc (float rate, float reference, + float gain, float max_gain); +}; diff --git a/gnuradio-core/src/lib/general/gr_agc_ff.cc b/gnuradio-core/src/lib/general/gr_agc_ff.cc new file mode 100644 index 000000000..6050dc7f0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_agc_ff.cc @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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_agc_ff.h> +#include <gr_io_signature.h> +#include <gri_agc_ff.h> + +gr_agc_ff_sptr +gr_make_agc_ff (float rate, float reference, float gain, float max_gain) +{ + return gnuradio::get_initial_sptr(new gr_agc_ff (rate, reference, gain, max_gain)); +} + +gr_agc_ff::gr_agc_ff (float rate, float reference, float gain, float max_gain) + : gr_sync_block ("gr_agc_ff", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (float))) + , gri_agc_ff (rate, reference, gain, max_gain) +{ +} + +int +gr_agc_ff::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]; + scaleN (out, in, noutput_items); + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_agc_ff.h b/gnuradio-core/src/lib/general/gr_agc_ff.h new file mode 100644 index 000000000..dc618213b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_agc_ff.h @@ -0,0 +1,55 @@ +/* -*- 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_AGC_FF_H +#define INCLUDED_GR_AGC_FF_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gri_agc_ff.h> +class gr_agc_ff; +typedef boost::shared_ptr<gr_agc_ff> gr_agc_ff_sptr; + +GR_CORE_API gr_agc_ff_sptr +gr_make_agc_ff (float rate = 1e-4, float reference = 1.0, + float gain = 1.0, float max_gain = 0.0); + +/*! + * \brief high performance Automatic Gain Control class + * \ingroup level_blk + * + * Power is approximated by absolute value + */ + +class GR_CORE_API gr_agc_ff : public gr_sync_block, public gri_agc_ff +{ + friend GR_CORE_API gr_agc_ff_sptr gr_make_agc_ff (float rate, float reference, + float gain, float max_gain); + gr_agc_ff (float rate, float reference, float gain, float max_gain); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_FLOAT_AGC_FF_H */ diff --git a/gnuradio-core/src/lib/general/gr_agc_ff.i b/gnuradio-core/src/lib/general/gr_agc_ff.i new file mode 100644 index 000000000..03c571e1a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_agc_ff.i @@ -0,0 +1,34 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,agc_ff) + +%include <gri_agc_ff.i> + +gr_agc_ff_sptr +gr_make_agc_ff (float rate = 1e-4, float reference = 1.0, + float gain = 1.0, float max_gain = 0.0); + +class gr_agc_ff : public gr_sync_block , public gri_agc_ff +{ + gr_agc_ff (float rate, float reference, float gain, float max_gain); +}; diff --git a/gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.cc b/gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.cc new file mode 100644 index 000000000..472853396 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.cc @@ -0,0 +1,464 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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_align_on_samplenumbers_ss.h> +#include <gr_io_signature.h> +#include <assert.h> +#include <stdexcept> +#include <string.h> +#include <cstdio> + +//define ALIGN_ADVANCED_IMPLEMENTATION to have an alternative implementation of the align algoritm which exactly follows the align_interval spec. +//It is more resource intensive, less tested and probably not needed +//define ALIGN_ADVANCED_IMPLEMENTATION + +//define DEBUG_TOCONSUME to see debug messages about the synchronisation part of this block +//define DEBUG_TOCONSUME +#ifdef DEBUG_TOCONSUME +#define tcPrintf if(dprint) printf +#else +#define tcPrintf //printf +#endif + +#define ePrintf printf + +gr_align_on_samplenumbers_ss_sptr +gr_make_align_on_samplenumbers_ss (int nchan, int align_interval) +{ + return gnuradio::get_initial_sptr(new gr_align_on_samplenumbers_ss (nchan,align_interval)); +} + +gr_align_on_samplenumbers_ss::gr_align_on_samplenumbers_ss (int nchan,int align_interval) + : gr_block ("align_on_samplenumbers_ss", + gr_make_io_signature (2, -1, sizeof (short)), //2, -1 + gr_make_io_signature (2, -1, sizeof (short))), //2,-1 + d_align_interval (align_interval), + d_nchan(nchan), + d_ninputs(0) +{ + if (d_align_interval<0) + set_output_multiple (d_nchan*2); + else + { + set_output_multiple (d_align_interval*d_nchan*2); + } + +} + +gr_align_on_samplenumbers_ss::~gr_align_on_samplenumbers_ss() +{ + +} +void +gr_align_on_samplenumbers_ss::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + //assert (0 == noutput_items % d_align_interval); + unsigned ninputs = ninput_items_required.size(); + for (unsigned int i = 0; i < ninputs; i++) + ninput_items_required[i] = std::max(noutput_items*d_nchan*2+ history() - 1,1024*d_nchan*2+ history() - 1);//TODO include the diffs found in determine input_items_required +} + +bool +gr_align_on_samplenumbers_ss::check_topology (int ninputs, int noutputs) +{ + bool result=true; + if(noutputs!=ninputs) + { + result=false; + ePrintf("gr_align_on_samplenumbers_ss: ERROR noutputs %i != ninputs %i\n",noutputs,ninputs); + } + if(d_nchan<2) + { + result=false; + ePrintf("gr_align_on_samplenumbers_ss: ERROR nchan %i<2 \n",d_nchan); + } + if((int)d_ninputs!=ninputs) + { + //Only resize and reset the status if there really changed something + //Don't reset the status if the user just called stop() and start(), although maybe we should. + d_state.resize(ninputs); + d_ninputs=ninputs; + for(unsigned int i=0;i<d_ninputs;i++) + { + d_state[i].sync_found=false; + d_state[i].sync_end_found=false; + } + d_in_presync=false; + } + return result; +} + +#ifdef ALIGN_ADVANCED_IMPLEMENTATION +int +gr_align_on_samplenumbers_ss::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ +#ifdef DEBUG_TOCONSUME + static int dcount=0; + bool dprint=false; + dcount++; + if(dcount>200) + { + dcount=0; + dprint=true; + } +#endif + const size_t item_size = output_signature()->sizeof_stream_item (0); + const unsigned ninputs = input_items.size(); + const unsigned noutputs = output_items.size(); + + int align_interval=d_align_interval*2*d_nchan; + if(d_align_interval<0) + { + //align once per noutput_items + align_interval=noutput_items; + align_interval=align_interval/(2*d_nchan); + align_interval=align_interval*(2*d_nchan); + } + + int min_ninput_items=noutput_items;//numeric_limits<int>::max(); + int noutput_items_produced=0; + for(unsigned int i=0;i<ninputs;i++) + { + d_state[i].ninput_items=ninput_items[i]; + d_state[i].ninput_items_used=0; + min_ninput_items=std::min(ninput_items[i],min_ninput_items); + } + for(int j=0;j<noutput_items-align_interval+1;j+=align_interval) + { + int common_end; + if(min_ninput_items>=align_interval) + common_end=align_interval; + else + { + common_end=min_ninput_items/(d_nchan*2); + common_end=common_end*(d_nchan*2); + } + if (common_end<=0) break; + + bool all_diffs_zero=true; + //bool sync_found=false; + int diff_comp_end_max=0; + for(unsigned int i=0;i<ninputs;i++) + { + unsigned short * uin=&(((unsigned short*)input_items[i])[d_state[i].ninput_items_used]); + unsigned int x_high16bits = uin[0]; + unsigned int x_low16bits = uin[1]; + d_state[i].ucounter_begin = x_high16bits<<16 | x_low16bits; + d_state[i].diff=d_state[0].ucounter_begin-d_state[i].ucounter_begin;//Result is a signed value,Will wrap around on 32 bit boundary + int common_last=std::max(common_end-d_nchan*2,0); + x_high16bits = uin[d_nchan*2]; + x_low16bits = uin[d_nchan*2+1]; + unsigned int ucounter_begin2 = x_high16bits<<16 | x_low16bits; +#ifdef DEBUG_TOCONSUME + if((d_state[i].ucounter_begin+1)!=(ucounter_begin2)) + if(ucounter_begin2==0) + ePrintf("SYNC counters are 0\n"); + else + ePrintf("Error: counter not continuous.\n ucounter_begin[%i]=%i +1 != ucounter_begin2=%i\n",i,d_state[i].ucounter_begin,ucounter_begin2); +#endif + x_high16bits = uin[common_last]; + x_low16bits = uin[common_last+1]; + d_state[i].ucounter_end = x_high16bits<<16 | x_low16bits; + d_state[i].diff_end=d_state[0].ucounter_end-d_state[i].ucounter_end;//Result is a signed value,Will wrap around on 32 bit boundary + d_state[i].diff_comp_end=d_state[i].ucounter_end-d_state[0].ucounter_end; + diff_comp_end_max=std::max(d_state[i].diff_comp_end,diff_comp_end_max); +#ifdef DEBUG_TOCONSUME + if(d_state[i].diff>256000000 || d_state[i].diff_end>256000000 || d_state[i].diff_comp_end>256000000) + { + tcPrintf("diff[%i]=%i diff_end=%i diff_comp_end=%i\n",i,d_state[i].diff,d_state[i].diff_end,d_state[i].diff_comp_end); + } +#endif + all_diffs_zero=all_diffs_zero && (0==d_state[i].diff_end); + if(d_state[i].ucounter_end<d_state[i].ucounter_begin+(unsigned)(common_last/(d_nchan*2))) //(unsigned)(common_last/(d_nchan*2))) + { + //printf("sync 1 ");// found ucounter_end[%i]=%i ucounter_begin[%i]=%i \n",i,d_state[i].ucounter_end,i,d_state[i].ucounter_begin); + //sync_found=true;//sync_found or 32 bit counter wraparound (0xffffffff -> 0x00000000) + if(!d_in_presync) + { +#ifdef DEBUG_TOCONSUME + printf("presync START with %i\n",i); +#endif + for(unsigned int k=0;k<ninputs;k++) + { + d_state[k].sync_found=false; + d_state[i].sync_end_found=false; + } + d_in_presync=true; + d_state[i].sync_found=true; + } else + { + //d_in_presync=true; +#ifdef DEBUG_TOCONSUME + if(d_state[i].sync_found) + printf("presync CONTINUE with %i\n",i); + else + printf("presync NEXT with %i\n",i); +#endif + d_state[i].sync_found=true; + d_state[i].sync_end_found=false; + } + } else + { + if(d_in_presync && d_state[i].sync_found) + { + d_state[i].sync_end_found=true; + bool all_syncs_found=true; + for(unsigned int k=0;k<ninputs;k++) + all_syncs_found=all_syncs_found && d_state[k].sync_end_found; + d_in_presync=!all_syncs_found; + if(!d_in_presync) + { + for(unsigned int k=0;k<ninputs;k++) + { + d_state[k].sync_found=false; + d_state[i].sync_end_found=false; + } +#ifdef DEBUG_TOCONSUME + printf("presync END\n"); +#endif + } + } + } + } + if(d_in_presync || all_diffs_zero) + { + for(unsigned int i=0;i<ninputs;i++) + { + memcpy(&(((unsigned short*)output_items[i])[j]),&(((const unsigned short*)input_items[i])[d_state[i].ninput_items_used]),common_end*item_size); + //consume(i,common_end); + d_state[i].ninput_items-=common_end; + d_state[i].ninput_items_used+=common_end; + min_ninput_items=std::min(d_state[i].ninput_items,min_ninput_items); +#ifdef DEBUG_TOCONSUME + if(common_end<256) + tcPrintf("common_end %i\n",common_end); +#endif + } + //min_ninput_items-=common_end; + noutput_items_produced+=common_end; + //return common_end; + } else + { + //printf("sync 2"); + for(unsigned int i=0;i<ninputs;i++) + { + int toconsume=std::min((d_state[i].diff_end+diff_comp_end_max)*d_nchan*2,d_state[i].ninput_items); + toconsume=toconsume/(d_nchan*2); + toconsume=toconsume*(d_nchan*2); + d_state[i].ninput_items-=toconsume; + d_state[i].ninput_items_used+=toconsume; + min_ninput_items=std::min(d_state[i].ninput_items,min_ninput_items); +#ifdef DEBUG_TOCONSUME + static int toconsume_counter=0; + toconsume_counter++; + //if(toconsume_counter>10) + { + tcPrintf("toconsume=%i diff_end[%i]*d_nchan*2=%i diff_comp_end_max*d_nchan*2=%i ninput_items[%i]=%i\n",toconsume,i,d_state[i].diff_end*d_nchan*2,diff_comp_end_max*d_nchan*2,i,ninput_items[i]); + toconsume_counter=0; + } +#endif + //printf("toconsume[%i]=%i\n",i,toconsume); + //consume(i,toconsume);//skip the difference in samplenumber items + } + //return 0; + } + } + for(unsigned int i=0;i<ninputs;i++) + consume(i,d_state[i].ninput_items_used); +#ifdef DEBUG_TOCONSUME + if(noutput_items_produced<256) + tcPrintf("noutput_items_produced %i\n",noutput_items_produced); +#endif + return noutput_items_produced; +} + + +#else /*ALIGN_ADVANCED_IMPLEMENTATION*/ +int +gr_align_on_samplenumbers_ss::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ +#ifdef DEBUG_TOCONSUME + static int dcount=0; + bool dprint=false; + dcount++; + if(dcount>2000) + { + dcount=0; + dprint=true; + } +#endif + const size_t item_size = output_signature()->sizeof_stream_item (0); + const unsigned ninputs = input_items.size(); + + int common_end=noutput_items; + //int diff_min=INT_MAX; + //int diff_max=INT_MIN; + for(unsigned int i=0;i<ninputs;i++) + { + unsigned short * uin=(unsigned short*)input_items[i]; + unsigned int x_high16bits = uin[0]; + unsigned int x_low16bits = uin[1]; + d_state[i].ucounter_begin = x_high16bits<<16 | x_low16bits; + d_state[i].diff=d_state[0].ucounter_end-d_state[i].ucounter_end;//Result is a signed value,Will wrap around on 32 bit boundary + x_high16bits = uin[d_nchan*2]; + x_low16bits = uin[d_nchan*2+1]; + unsigned int ucounter_begin2 = x_high16bits<<16 | x_low16bits; + if((d_state[i].ucounter_begin+1)!=(ucounter_begin2)){ + if(ucounter_begin2==0) + { +#ifdef DEBUG_TOCONSUME + ePrintf("SYNC counters are 0\n"); +#endif + } + else + { + ePrintf("Error: counter not continuous.\n ucounter_begin[%i]=%i +1 != ucounter_begin2=%i\n",i,d_state[i].ucounter_begin,ucounter_begin2); + } + } + + //diff_comp[i]=ucounter[i]-ucounter[0]; + //diff_min=std::min(diff[i],diff_min); + //diff_max=std::max(diff[i],diff_max); + common_end=std::max(std::min(ninput_items[i],common_end),0); + } + common_end=common_end/(d_nchan*2); + common_end=common_end*(d_nchan*2); +#ifdef DEBUG_TOCONSUME + if(common_end<d_nchan*2) + { + printf(" common_end %i\n",common_end); + for(int j=0;j<ninputs;j++) + printf("ninput_items[%i]=%i\n",j,ninput_items[j]); + } +#endif + bool all_diffs_zero=true; + bool sync_found=false; + int diff_comp_end_max=0; + for(unsigned int i=0;i<ninputs;i++) + { + unsigned short * uin=(unsigned short*)input_items[i]; + int common_last=common_end-(d_nchan*2); + unsigned int x_high16bits = uin[common_last]; + unsigned int x_low16bits = uin[common_last+1]; + d_state[i].ucounter_end = x_high16bits<<16 | x_low16bits; + d_state[i].diff_end=d_state[0].ucounter_end-d_state[i].ucounter_end;//Result is a signed value,Will wrap around on 32 bit boundary + d_state[i].diff_comp_end=d_state[i].ucounter_end-d_state[0].ucounter_end; + //diff_end_min=std::min(diff_end[i],diff_end_min); + //diff_end_max=std::max(diff_end[i],diff_end_max); + diff_comp_end_max=std::max(d_state[i].diff_comp_end,diff_comp_end_max); +#ifdef DEBUG_TOCONSUME + if(d_state[i].diff_end!=d_state[i].diff) + { + //samples_lost_or_syncstart=true; + printf("Us%i %i %i ",i,d_state[i].diff_end,d_state[i].diff); + } +#endif + all_diffs_zero=all_diffs_zero && (0==d_state[i].diff_end); + if((d_state[i].ucounter_end<d_state[i].ucounter_begin+(unsigned)(common_last/(d_nchan*2))) || (0==d_state[i].ucounter_end) || (0==d_state[i].ucounter_begin)) //(unsigned)(common_last/(d_nchan*2))) + { + sync_found=true;//sync_found or 32 bit counter wraparound (0xffffffff -> 0x00000000) +#ifdef DEBUG_TOCONSUME + tcPrintf("SYNC diff_end[%i]=%i ucounter_end[%i]=%i ucounter_begin[%i]=%i \n",i,d_state[i].diff_end,i,d_state[i].ucounter_end,i,d_state[i].ucounter_begin); + tcPrintf("ucounter_end=%i < %i = ucounter_begin+(unsigned)(common_last/(d_nchan*2) \n",d_state[i].ucounter_end,d_state[i].ucounter_begin+(unsigned)(common_last/(d_nchan*2))); + + printf("ucounter_end[%i]=%i ucounter_begin[%i]=%i\n",i,d_state[i].ucounter_end,i,d_state[i].ucounter_begin); + int expected_sync_position=common_last - d_state[i].ucounter_end*(d_nchan*2); + if(0==uin[expected_sync_position] && 0==uin[expected_sync_position+1]) + { + printf("sync found on input %i at position %i \n",i,expected_sync_position); + //sync_start[i]=expected_sync_position; + } else + { + printf("sync found on input %i position unclear, expected at %i value there %i\n",i,expected_sync_position,uin[expected_sync_position]<<16 | uin[expected_sync_position+1]); + //sync_start[i]=-1; + } + } else + { + tcPrintf("NOsync diff_end[%i]=%i ucounter_end[%i]=%i ucounter_begin[%i]=%i \n",i,d_state[i].diff_end,i,d_state[i].ucounter_end,i,d_state[i].ucounter_begin); +#endif + } + } + bool problem=false; + for(unsigned int i=0;i<ninputs;i++) + if((d_state[i].diff_end+diff_comp_end_max) >0x4000000) + { + problem=true; + ePrintf("Warning: counter diff greater as 64 Million\n"); + ePrintf(" You might want to swap master and slave.\n"); + ePrintf(" i=%i,d_state[i].diff_end+diff_comp_end_max=%i,d_state[i].diff_end=%i,diff_comp_end_max=%i,ucounter[i]=%i,ucounter[0]=%i\n", + i,d_state[i].diff_end+diff_comp_end_max,d_state[i].diff_end,diff_comp_end_max,d_state[i].ucounter_end,d_state[0].ucounter_end); + //ePrintf(" toconsume=%i\n",toconsume); + } + if(sync_found || all_diffs_zero || problem) + { +#ifdef DEBUG_TOCONSUME + if(all_diffs_zero) tcPrintf("ZERO\n"); + if(sync_found) tcPrintf("SYNC\n"); +#endif + for(unsigned int i=0;i<ninputs;i++) + { + memcpy(output_items[i],input_items[i],common_end*item_size); + consume(i,common_end); +#ifdef DEBUG_TOCONSUME + if(common_end<256) + tcPrintf("common_end %i\n",common_end); +#endif + } + return common_end; + } else + { + //int minconsume=0;//common_end/(2*d_nchan*2); + //min_consume=min_consume*d_nchan*2; + for(unsigned int i=0;i<ninputs;i++) + { + int toconsume=std::min((d_state[i].diff_end+diff_comp_end_max)*d_nchan*2,ninput_items[i]); + toconsume=toconsume/(d_nchan*2); + toconsume=toconsume*(d_nchan*2); +#ifdef DEBUG_TOCONSUME + //printf("dcount %i\n",dcount); + static int toconsume_counter=0; + toconsume_counter++; + //if(toconsume_counter>10) + { + tcPrintf("toconsume=%i diff_end[[%i]*d_nchan*2=%i diff_comp_end_max)*d_nchan*2=%i ninput_items[%i]=%i\n", + toconsume,i,d_state[i].diff_end*d_nchan*2,diff_comp_end_max*d_nchan*2,i,ninput_items[i]); + toconsume_counter=0; + } +#endif + consume(i,toconsume);//skip the difference in samplenumber items + //printf("toconsume%i %i diff_comp_end_max %i diff_end[[%i] %i\n",i,toconsume,diff_comp_end_max,i,d_state[i].diff_end); + } + return 0; + } + return -1;//Should never come here +} +#endif /*ALIGN_ADVANCED_IMPLEMENTATION*/ diff --git a/gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.h b/gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.h new file mode 100644 index 000000000..1b71a3f4b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.h @@ -0,0 +1,92 @@ +/* -*- 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_ALIGN_ON_SAMPLE_NUMBERS_SS_H +#define INCLUDED_GR_ALIGN_ON_SAMPLE_NUMBERS_SS_H + +#include <gr_core_api.h> +#include <gr_block.h> + +/*! + * \brief align several complex short (interleaved short) input channels with corresponding unsigned 32 bit sample_counters (provided as interleaved 16 bit values) + * \ingroup misc + * \param number of complex_short input channels (including the 32 bit counting channel) + * \param align_interval is after how much samples (minimally) the sample-alignement is refreshed. Default is 128. + * A bigger value means less processing power but also requests more buffer space, which has a maximum. + * Decrease the align_interval if you get an error like: + * "sched: <gr_block align_on_samplenumbers_ss (0)> is requesting more input data than we can provide. + * ninput_items_required = 32768 + * max_possible_items_available = 16383 + * If this is a filter, consider reducing the number of taps." + * \ingroup block + * Pay attention on how you connect this block. + * It expects a minimum of 2 usrp_source_s with nchan number of channels and FPGA_MODE_COUNTING_32BIT enabled. + * This means that the first complex_short channel on every input is an interleaved 32 bit counter. + * The samples are aligned by dropping samples untill the samplenumbers match. + */ +class gr_align_on_samplenumbers_ss; +typedef boost::shared_ptr<gr_align_on_samplenumbers_ss> gr_align_on_samplenumbers_ss_sptr; + +GR_CORE_API gr_align_on_samplenumbers_ss_sptr gr_make_align_on_samplenumbers_ss (int nchan=2, int align_interval=128); + + + + +class GR_CORE_API gr_align_on_samplenumbers_ss : public gr_block +{ + int d_align_interval; + int d_sample_counter; + int d_nchan; + bool d_in_presync; + unsigned int d_ninputs; + class GR_CORE_API align_state { + public: + unsigned int ucounter_end; + unsigned int ucounter_begin; + int diff; + int diff_comp; + int diff_end; + int diff_comp_end; + bool sync_found; + bool sync_end_found; + int ninput_items; + int ninput_items_used; + }; + std::vector<align_state> d_state; + + friend GR_CORE_API gr_align_on_samplenumbers_ss_sptr gr_make_align_on_samplenumbers_ss (int nchan,int align_interval); + gr_align_on_samplenumbers_ss (int nchan,int align_interval); + + public: + ~gr_align_on_samplenumbers_ss(); + bool check_topology (int ninputs, int noutputs); + 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_ALIGN_ON_SAMPLE_NUMBERS_SS_H */ diff --git a/gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.i b/gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.i new file mode 100644 index 000000000..471f74301 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.i @@ -0,0 +1,34 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,align_on_samplenumbers_ss); + +gr_align_on_samplenumbers_ss_sptr +gr_make_align_on_samplenumbers_ss(int nchan=2, int align_interval=128) throw (std::exception); + +class gr_align_on_samplenumbers_ss : public gr_block +{ + public: + ~gr_align_on_samplenumbers_ss (); + private: + gr_align_on_samplenumbers_ss (int nchan,int align_interval); +}; diff --git a/gnuradio-core/src/lib/general/gr_annotator_1to1.cc b/gnuradio-core/src/lib/general/gr_annotator_1to1.cc new file mode 100644 index 000000000..963af9202 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_annotator_1to1.cc @@ -0,0 +1,107 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_annotator_1to1.h> +#include <gr_io_signature.h> +#include <string.h> +#include <iostream> +#include <iomanip> + +gr_annotator_1to1_sptr +gr_make_annotator_1to1 (int when, size_t sizeof_stream_item) +{ + return gnuradio::get_initial_sptr (new gr_annotator_1to1 + (when, sizeof_stream_item)); +} + +gr_annotator_1to1::gr_annotator_1to1 (int when, size_t sizeof_stream_item) + : gr_sync_block ("annotator_1to1", + gr_make_io_signature (1, -1, sizeof_stream_item), + gr_make_io_signature (1, -1, sizeof_stream_item)), + d_itemsize(sizeof_stream_item), d_when((uint64_t)when) +{ + set_tag_propagation_policy(TPP_ONE_TO_ONE); + + d_tag_counter = 0; + set_relative_rate(1.0); +} + +gr_annotator_1to1::~gr_annotator_1to1 () +{ +} + +int +gr_annotator_1to1::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]; + + std::stringstream str; + str << name() << unique_id(); + + uint64_t abs_N = 0; + int ninputs = input_items.size(); + for(int i = 0; i < ninputs; i++) { + abs_N = nitems_read(i); + + std::vector<gr_tag_t> all_tags; + get_tags_in_range(all_tags, i, abs_N, abs_N + noutput_items); + + std::vector<gr_tag_t>::iterator itr; + for(itr = all_tags.begin(); itr != all_tags.end(); itr++) { + d_stored_tags.push_back(*itr); + } + } + + // Storing the current noutput_items as the value to the "noutput_items" key + pmt::pmt_t srcid = pmt::pmt_string_to_symbol(str.str()); + pmt::pmt_t key = pmt::pmt_string_to_symbol("seq"); + + // Work does nothing to the data stream; just copy all inputs to outputs + // Adds a new tag when the number of items read is a multiple of d_when + abs_N = nitems_read(0); + int noutputs = output_items.size(); + for(int j = 0; j < noutput_items; j++) { + // the min() is a hack to make sure this doesn't segfault if there are a + // different number of ins and outs. This is specifically designed to test + // the 1-to-1 propagation policy. + for(int i = 0; i < std::min(noutputs, ninputs); i++) { + if(abs_N % d_when == 0) { + pmt::pmt_t value = pmt::pmt_from_uint64(d_tag_counter++); + add_item_tag(i, abs_N, key, value, srcid); + } + + in = (const float*)input_items[i]; + out = (float*)output_items[i]; + out[j] = in[j]; + } + abs_N++; + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_annotator_1to1.h b/gnuradio-core/src/lib/general/gr_annotator_1to1.h new file mode 100644 index 000000000..57e572014 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_annotator_1to1.h @@ -0,0 +1,75 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_ANNOTATOR_1TO1_H +#define INCLUDED_GR_ANNOTATOR_1TO1_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_annotator_1to1; +typedef boost::shared_ptr<gr_annotator_1to1> gr_annotator_1to1_sptr; + +// public constructor +GR_CORE_API gr_annotator_1to1_sptr +gr_make_annotator_1to1 (int when, size_t sizeof_stream_item); + +/*! + * \brief 1-to-1 stream annotator testing block. FOR TESTING PURPOSES ONLY. + * + * This block creates tags to be sent downstream every 10,000 items it sees. The + * tags contain the name and ID of the instantiated block, use "seq" as a key, + * and have a counter that increments by 1 for every tag produced that is used + * as the tag's value. The tags are propagated using the 1-to-1 policy. + * + * It also stores a copy of all tags it sees flow past it. These tags can be + * recalled externally with the data() member. + * + * This block is only meant for testing and showing how to use the tags. + */ +class GR_CORE_API gr_annotator_1to1 : public gr_sync_block +{ + public: + ~gr_annotator_1to1 (); + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + std::vector<gr_tag_t> data() const + { + return d_stored_tags; + } + +protected: + gr_annotator_1to1 (int when, size_t sizeof_stream_item); + + private: + size_t d_itemsize; + uint64_t d_when; + uint64_t d_tag_counter; + std::vector<gr_tag_t> d_stored_tags; + + friend GR_CORE_API gr_annotator_1to1_sptr + gr_make_annotator_1to1 (int when, size_t sizeof_stream_item); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_annotator_1to1.i b/gnuradio-core/src/lib/general/gr_annotator_1to1.i new file mode 100644 index 000000000..2637b8d27 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_annotator_1to1.i @@ -0,0 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,annotator_1to1); + +%include <gr_annotator_1to1.h> diff --git a/gnuradio-core/src/lib/general/gr_annotator_alltoall.cc b/gnuradio-core/src/lib/general/gr_annotator_alltoall.cc new file mode 100644 index 000000000..01bdd3064 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_annotator_alltoall.cc @@ -0,0 +1,110 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_annotator_alltoall.h> +#include <gr_io_signature.h> +#include <string.h> +#include <iostream> +#include <iomanip> + +gr_annotator_alltoall_sptr +gr_make_annotator_alltoall (int when, size_t sizeof_stream_item) +{ + return gnuradio::get_initial_sptr (new gr_annotator_alltoall + (when, sizeof_stream_item)); +} + +gr_annotator_alltoall::gr_annotator_alltoall (int when, + size_t sizeof_stream_item) + : gr_sync_block ("annotator_alltoall", + gr_make_io_signature (1, -1, sizeof_stream_item), + gr_make_io_signature (1, -1, sizeof_stream_item)), + d_itemsize(sizeof_stream_item), d_when((uint64_t)when) +{ + set_tag_propagation_policy(TPP_ALL_TO_ALL); + + d_tag_counter = 0; +} + +gr_annotator_alltoall::~gr_annotator_alltoall () +{ +} + +int +gr_annotator_alltoall::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]; + + std::stringstream str; + str << name() << unique_id(); + + uint64_t abs_N = 0, end_N; + int ninputs = input_items.size(); + for(int i = 0; i < ninputs; i++) { + abs_N = nitems_read(i); + end_N = abs_N + (uint64_t)(noutput_items); + + std::vector<gr_tag_t> all_tags; + get_tags_in_range(all_tags, i, abs_N, end_N); + + std::vector<gr_tag_t>::iterator itr; + for(itr = all_tags.begin(); itr != all_tags.end(); itr++) { + d_stored_tags.push_back(*itr); + } + } + + // Source ID and key for any tag that might get applied from this block + pmt::pmt_t srcid = pmt::pmt_string_to_symbol(str.str()); + pmt::pmt_t key = pmt::pmt_string_to_symbol("seq"); + + // Work does nothing to the data stream; just copy all inputs to outputs + // Adds a new tag when the number of items read is a multiple of d_when + abs_N = nitems_written(0); + int noutputs = output_items.size(); + + for(int j = 0; j < noutput_items; j++) { + for(int i = 0; i < noutputs; i++) { + if(abs_N % d_when == 0) { + pmt::pmt_t value = pmt::pmt_from_uint64(d_tag_counter++); + add_item_tag(i, abs_N, key, value, srcid); + } + + // Sum all of the inputs together for each output. Just 'cause. + out = (float*)output_items[i]; + out[j] = 0; + for(int ins = 0; ins < ninputs; ins++) { + in = (const float*)input_items[ins]; + out[j] += in[j]; + } + } + abs_N++; + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_annotator_alltoall.h b/gnuradio-core/src/lib/general/gr_annotator_alltoall.h new file mode 100644 index 000000000..deb5874a4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_annotator_alltoall.h @@ -0,0 +1,76 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_ANNOTATOR_ALLTOALL_H +#define INCLUDED_GR_ANNOTATOR_ALLTOALL_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_annotator_alltoall; +typedef boost::shared_ptr<gr_annotator_alltoall> gr_annotator_alltoall_sptr; + +// public constructor +GR_CORE_API gr_annotator_alltoall_sptr +gr_make_annotator_alltoall (int when, size_t sizeof_stream_item); + +/*! + * \brief All-to-all stream annotator testing block. FOR TESTING PURPOSES ONLY. + * + * This block creates tags to be sent downstream every 10,000 items it sees. The + * tags contain the name and ID of the instantiated block, use "seq" as a key, + * and have a counter that increments by 1 for every tag produced that is used + * as the tag's value. The tags are propagated using the all-to-all policy. + * + * It also stores a copy of all tags it sees flow past it. These tags can be + * recalled externally with the data() member. + * + * This block is only meant for testing and showing how to use the tags. + */ +class GR_CORE_API gr_annotator_alltoall : public gr_sync_block +{ + public: + ~gr_annotator_alltoall (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + std::vector<gr_tag_t> data() const + { + return d_stored_tags; + } + +protected: + gr_annotator_alltoall (int when, size_t sizeof_stream_item); + + private: + size_t d_itemsize; + uint64_t d_when; + uint64_t d_tag_counter; + std::vector<gr_tag_t> d_stored_tags; + + friend GR_CORE_API gr_annotator_alltoall_sptr + gr_make_annotator_alltoall (int when, size_t sizeof_stream_item); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_annotator_alltoall.i b/gnuradio-core/src/lib/general/gr_annotator_alltoall.i new file mode 100644 index 000000000..35190a3d1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_annotator_alltoall.i @@ -0,0 +1,25 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,annotator_alltoall); + +%include <gr_annotator_alltoall.h> diff --git a/gnuradio-core/src/lib/general/gr_annotator_raw.cc b/gnuradio-core/src/lib/general/gr_annotator_raw.cc new file mode 100644 index 000000000..d3dcce73a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_annotator_raw.cc @@ -0,0 +1,106 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_annotator_raw.h> +#include <gr_io_signature.h> +#include <string.h> +#include <iostream> +#include <iomanip> +#include <stdexcept> + +using namespace pmt; + +gr_annotator_raw_sptr +gr_make_annotator_raw(size_t sizeof_stream_item) +{ + return gnuradio::get_initial_sptr(new gr_annotator_raw + (sizeof_stream_item)); +} + +gr_annotator_raw::gr_annotator_raw(size_t sizeof_stream_item) + : gr_sync_block("annotator_raw", + gr_make_io_signature(1, 1, sizeof_stream_item), + gr_make_io_signature(1, 1, sizeof_stream_item)), + d_itemsize(sizeof_stream_item) +{ + set_tag_propagation_policy(TPP_ONE_TO_ONE); + set_relative_rate(1.0); +} + +void gr_annotator_raw::add_tag(uint64_t offset, pmt_t key, pmt_t val) +{ + gruel::scoped_lock l(d_mutex); + + gr_tag_t tag; + tag.srcid = pmt::pmt_intern(name()); + tag.key = key; + tag.value = val; + tag.offset = offset; + + // add our new tag + d_queued_tags.push_back(tag); + // make sure our tags are in offset order + std::sort(d_queued_tags.begin(), d_queued_tags.end(), + gr_tag_t::offset_compare); + // make sure we are not adding an item in the past! + if(tag.offset > nitems_read(0)) { + throw std::runtime_error("gr_annotator_raw::add_tag: item added too far in the past\n."); + } +} + +gr_annotator_raw::~gr_annotator_raw() +{ +} + +int +gr_annotator_raw::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gruel::scoped_lock l(d_mutex); + + const char *in = (const char*)input_items[0]; + char *out = (char*)output_items[0]; + + uint64_t start_N = nitems_read(0); + uint64_t end_N = start_N + (uint64_t)(noutput_items); + + // locate queued tags that fall in this range and insert them when appropriate + std::vector<gr_tag_t>::iterator i = d_queued_tags.begin(); + while( i != d_queued_tags.end() ) { + if( (*i).offset >= start_N && (*i).offset < end_N) { + add_item_tag(0, (*i).offset,(*i).key, (*i).value, (*i).srcid); + i = d_queued_tags.erase(i); + } + else { + break; + } + } + + // copy data across + memcpy(out, in, noutput_items*d_itemsize); + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_annotator_raw.h b/gnuradio-core/src/lib/general/gr_annotator_raw.h new file mode 100644 index 000000000..02d061908 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_annotator_raw.h @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_ANNOTATOR_RAW_H +#define INCLUDED_GR_ANNOTATOR_RAW_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_tags.h> +#include <gruel/thread.h> + +class gr_annotator_raw; +typedef boost::shared_ptr<gr_annotator_raw> gr_annotator_raw_sptr; + +// public constructor +GR_CORE_API gr_annotator_raw_sptr +gr_make_annotator_raw(size_t sizeof_stream_item); + +/*! + * \brief raw stream annotator testing block. + * + * This block creates arbitrary tags to be sent downstream + * blocks to be sent are set manually via accessor methods and are sent only once. + * + * This block is intended for testing of tag related blocks + */ +class GR_CORE_API gr_annotator_raw : public gr_sync_block +{ + public: + ~gr_annotator_raw(); + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + // insert a tag to be added + void add_tag(uint64_t offset, pmt::pmt_t key, pmt::pmt_t val); + +protected: + gr_annotator_raw(size_t sizeof_stream_item); + + private: + size_t d_itemsize; + std::vector<gr_tag_t> d_queued_tags; + gruel::mutex d_mutex; + + friend GR_CORE_API gr_annotator_raw_sptr + gr_make_annotator_raw(size_t sizeof_stream_item); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_annotator_raw.i b/gnuradio-core/src/lib/general/gr_annotator_raw.i new file mode 100644 index 000000000..4a58fe7c7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_annotator_raw.i @@ -0,0 +1,26 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,annotator_raw); + +%include <gr_tags.i> +%include <gr_annotator_raw.h> diff --git a/gnuradio-core/src/lib/general/gr_bin_statistics_f.cc b/gnuradio-core/src/lib/general/gr_bin_statistics_f.cc new file mode 100644 index 000000000..3938f2b48 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_bin_statistics_f.cc @@ -0,0 +1,174 @@ +/* -*- 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_bin_statistics_f.h> +#include <gr_io_signature.h> +#include <string.h> + +gr_bin_statistics_f_sptr +gr_make_bin_statistics_f(unsigned int vlen, + gr_msg_queue_sptr msgq, + gr_feval_dd *tune, + size_t tune_delay, + size_t dwell_delay) +{ + return gnuradio::get_initial_sptr(new gr_bin_statistics_f(vlen, + msgq, + tune, + tune_delay, + dwell_delay)); +} + +gr_bin_statistics_f::gr_bin_statistics_f(unsigned int vlen, + gr_msg_queue_sptr msgq, + gr_feval_dd *tune, + size_t tune_delay, + size_t dwell_delay) + : gr_sync_block("bin_statistics_f", + gr_make_io_signature(1, 1, sizeof(float) * vlen), + gr_make_io_signature(0, 0, 0)), + d_vlen(vlen), d_msgq(msgq), d_tune(tune), + d_tune_delay(tune_delay), d_dwell_delay(dwell_delay), + d_center_freq(0), d_delay(0), + d_max(vlen) +{ + enter_init(); +} + +gr_bin_statistics_f::~gr_bin_statistics_f() +{ + // NOP +} + +void +gr_bin_statistics_f::enter_init() +{ + d_state = ST_INIT; + d_delay = 0; +} + +void +gr_bin_statistics_f::enter_tune_delay() +{ + d_state = ST_TUNE_DELAY; + d_delay = d_tune_delay; + d_center_freq = d_tune->calleval(0); +} + +void +gr_bin_statistics_f::enter_dwell_delay() +{ + d_state = ST_DWELL_DELAY; + d_delay = d_dwell_delay; + reset_stats(); +} + +void +gr_bin_statistics_f::leave_dwell_delay() +{ + send_stats(); +} + +int +gr_bin_statistics_f::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *input = (const float *) input_items[0]; + size_t vlen = d_max.size(); + + int n = 0; + int t; + + while (n < noutput_items){ + switch (d_state){ + + case ST_INIT: + enter_tune_delay(); + break; + + case ST_TUNE_DELAY: + t = std::min(noutput_items - n, int(d_delay)); + n += t; + d_delay -= t; + assert(d_delay >= 0); + if (d_delay == 0) + enter_dwell_delay(); + break; + + case ST_DWELL_DELAY: + t = std::min(noutput_items - n, int(d_delay)); + for (int i = 0; i < t; i++){ + accrue_stats(&input[n * vlen]); + n++; + } + d_delay -= t; + assert(d_delay >= 0); + if (d_delay == 0){ + leave_dwell_delay(); + enter_tune_delay(); + } + break; + + default: + assert(0); + } + } + + return noutput_items; +} + +////////////////////////////////////////////////////////////////////////// +// virtual methods for gathering stats +////////////////////////////////////////////////////////////////////////// + +void +gr_bin_statistics_f::reset_stats() +{ + for (size_t i = 0; i < vlen(); i++){ + d_max[i] = 0; + } +} + +void +gr_bin_statistics_f::accrue_stats(const float *input) +{ + for (size_t i = 0; i < vlen(); i++){ + d_max[i] = std::max(d_max[i], input[i]); // compute per bin maxima + } +} + +void +gr_bin_statistics_f::send_stats() +{ + if (msgq()->full_p()) // if the queue is full, don't block, drop the data... + return; + + // build & send a message + gr_message_sptr msg = gr_make_message(0, center_freq(), vlen(), vlen() * sizeof(float)); + memcpy(msg->msg(), &d_max[0], vlen() * sizeof(float)); + msgq()->insert_tail(msg); +} diff --git a/gnuradio-core/src/lib/general/gr_bin_statistics_f.h b/gnuradio-core/src/lib/general/gr_bin_statistics_f.h new file mode 100644 index 000000000..dd1075909 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_bin_statistics_f.h @@ -0,0 +1,100 @@ +/* -*- 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_BIN_STATISTICS_F_H +#define INCLUDED_GR_BIN_STATISTICS_F_H + + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_feval.h> +#include <gr_message.h> +#include <gr_msg_queue.h> + +class gr_bin_statistics_f; +typedef boost::shared_ptr<gr_bin_statistics_f> gr_bin_statistics_f_sptr; + + +GR_CORE_API gr_bin_statistics_f_sptr +gr_make_bin_statistics_f(unsigned int vlen, // vector length + gr_msg_queue_sptr msgq, + gr_feval_dd *tune, // callback + size_t tune_delay, // samples + size_t dwell_delay); // samples + +/*! + * \brief control scanning and record frequency domain statistics + * \ingroup sink_blk + */ +class GR_CORE_API gr_bin_statistics_f : public gr_sync_block +{ + friend GR_CORE_API gr_bin_statistics_f_sptr + gr_make_bin_statistics_f(unsigned int vlen, // vector length + gr_msg_queue_sptr msgq, + gr_feval_dd *tune, // callback + size_t tune_delay, // samples + size_t dwell_delay); // samples + + enum state_t { ST_INIT, ST_TUNE_DELAY, ST_DWELL_DELAY }; + + size_t d_vlen; + gr_msg_queue_sptr d_msgq; + gr_feval_dd *d_tune; + size_t d_tune_delay; + size_t d_dwell_delay; + double d_center_freq; + + state_t d_state; + size_t d_delay; // nsamples remaining to state transition + + gr_bin_statistics_f(unsigned int vlen, + gr_msg_queue_sptr msgq, + gr_feval_dd *tune, + size_t tune_delay, + size_t dwell_delay); + + void enter_init(); + void enter_tune_delay(); + void enter_dwell_delay(); + void leave_dwell_delay(); + +protected: + std::vector<float> d_max; // per bin maxima + + size_t vlen() const { return d_vlen; } + double center_freq() const { return d_center_freq; } + gr_msg_queue_sptr msgq() const { return d_msgq; } + + virtual void reset_stats(); + virtual void accrue_stats(const float *input); + virtual void send_stats(); + +public: + ~gr_bin_statistics_f(); + + 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_bin_statistics_f.i b/gnuradio-core/src/lib/general/gr_bin_statistics_f.i new file mode 100644 index 000000000..94a3db69a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_bin_statistics_f.i @@ -0,0 +1,47 @@ +/* -*- 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +// Directors are only supported in Python, Java and C#. gr_feval_dd uses directors +#ifdef SWIGPYTHON + +GR_SWIG_BLOCK_MAGIC(gr,bin_statistics_f); + +gr_bin_statistics_f_sptr +gr_make_bin_statistics_f(unsigned int vlen, // vector length + gr_msg_queue_sptr msgq, + gr_feval_dd *tune, // callback + size_t tune_delay, // samples + size_t dwell_delay); // samples + + +class gr_bin_statistics_f : public gr_sync_block +{ +private: + gr_bin_statistics_f(unsigned int vlen, + gr_msg_queue_sptr msgq, + gr_feval_dd *tune, + size_t tune_delay, + size_t dwell_delay); +public: + ~gr_bin_statistics_f(); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_block_gateway.cc b/gnuradio-core/src/lib/general/gr_block_gateway.cc new file mode 100644 index 000000000..79b42803a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_block_gateway.cc @@ -0,0 +1,184 @@ +/* + * 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. + */ + +#include <gr_block_gateway.h> +#include <gr_io_signature.h> +#include <iostream> +#include <boost/bind.hpp> + +/*********************************************************************** + * Helper routines + **********************************************************************/ +template <typename OutType, typename InType> +void copy_pointers(OutType &out, const InType &in){ + out.resize(in.size()); + for (size_t i = 0; i < in.size(); i++){ + out[i] = (void *)(in[i]); + } +} + +/*********************************************************************** + * The gr_block gateway implementation class + **********************************************************************/ +class gr_block_gateway_impl : public gr_block_gateway{ +public: + gr_block_gateway_impl( + gr_feval_ll *handler, + const std::string &name, + gr_io_signature_sptr in_sig, + gr_io_signature_sptr out_sig, + const gr_block_gw_work_type work_type, + const unsigned factor + ): + gr_block(name, in_sig, out_sig), + _handler(handler), + _work_type(work_type) + { + switch(_work_type){ + case GR_BLOCK_GW_WORK_GENERAL: + _decim = 1; //not relevant, but set anyway + _interp = 1; //not relevant, but set anyway + break; + + case GR_BLOCK_GW_WORK_SYNC: + _decim = 1; + _interp = 1; + this->set_fixed_rate(true); + break; + + case GR_BLOCK_GW_WORK_DECIM: + _decim = factor; + _interp = 1; + break; + + case GR_BLOCK_GW_WORK_INTERP: + _decim = 1; + _interp = factor; + this->set_output_multiple(_interp); + break; + } + } + + /******************************************************************* + * Overloads for various scheduler-called functions + ******************************************************************/ + void forecast( + int noutput_items, + gr_vector_int &ninput_items_required + ){ + switch(_work_type){ + case GR_BLOCK_GW_WORK_GENERAL: + _message.action = gr_block_gw_message_type::ACTION_FORECAST; + _message.forecast_args_noutput_items = noutput_items; + _message.forecast_args_ninput_items_required = ninput_items_required; + _handler->calleval(0); + ninput_items_required = _message.forecast_args_ninput_items_required; + return; + + default: + unsigned ninputs = ninput_items_required.size(); + for (unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = fixed_rate_noutput_to_ninput(noutput_items); + return; + } + } + + int general_work( + int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items + ){ + switch(_work_type){ + case GR_BLOCK_GW_WORK_GENERAL: + _message.action = gr_block_gw_message_type::ACTION_GENERAL_WORK; + _message.general_work_args_noutput_items = noutput_items; + _message.general_work_args_ninput_items = ninput_items; + copy_pointers(_message.general_work_args_input_items, input_items); + _message.general_work_args_output_items = output_items; + _handler->calleval(0); + return _message.general_work_args_return_value; + + default: + int r = work (noutput_items, input_items, output_items); + if (r > 0) consume_each(r*_decim/_interp); + return r; + } + } + + int work( + int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items + ){ + _message.action = gr_block_gw_message_type::ACTION_WORK; + _message.work_args_ninput_items = fixed_rate_noutput_to_ninput(noutput_items); + if (_message.work_args_ninput_items == 0) return -1; + _message.work_args_noutput_items = noutput_items; + copy_pointers(_message.work_args_input_items, input_items); + _message.work_args_output_items = output_items; + _handler->calleval(0); + return _message.work_args_return_value; + } + + int fixed_rate_noutput_to_ninput(int noutput_items){ + return (noutput_items*_decim/_interp) + history() - 1; + } + + int fixed_rate_ninput_to_noutput(int ninput_items){ + return std::max(0, ninput_items - (int)history() + 1)*_interp/_decim; + } + + bool start(void){ + _message.action = gr_block_gw_message_type::ACTION_START; + _handler->calleval(0); + return _message.start_args_return_value; + } + + bool stop(void){ + _message.action = gr_block_gw_message_type::ACTION_STOP; + _handler->calleval(0); + return _message.stop_args_return_value; + } + + gr_block_gw_message_type &gr_block_message(void){ + return _message; + } + +private: + gr_feval_ll *_handler; + gr_block_gw_message_type _message; + const gr_block_gw_work_type _work_type; + unsigned _decim, _interp; +}; + +boost::shared_ptr<gr_block_gateway> gr_make_block_gateway( + gr_feval_ll *handler, + const std::string &name, + gr_io_signature_sptr in_sig, + gr_io_signature_sptr out_sig, + const gr_block_gw_work_type work_type, + const unsigned factor +){ + return boost::shared_ptr<gr_block_gateway>( + new gr_block_gateway_impl(handler, name, in_sig, out_sig, work_type, factor) + ); +} diff --git a/gnuradio-core/src/lib/general/gr_block_gateway.h b/gnuradio-core/src/lib/general/gr_block_gateway.h new file mode 100644 index 000000000..2452b1045 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_block_gateway.h @@ -0,0 +1,264 @@ +/* + * 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_GRBLOCK_GATEWAY_H +#define INCLUDED_GRBLOCK_GATEWAY_H + +#include <gr_core_api.h> +#include <gr_block.h> +#include <gr_feval.h> + +/*! + * The work type enum tells the gateway what kind of block to implement. + * The choices are familiar gnuradio block overloads (sync, decim, interp). + */ +enum gr_block_gw_work_type{ + GR_BLOCK_GW_WORK_GENERAL, + GR_BLOCK_GW_WORK_SYNC, + GR_BLOCK_GW_WORK_DECIM, + GR_BLOCK_GW_WORK_INTERP, +}; + +/*! + * Shared message structure between python and gateway. + * Each action type represents a scheduler-called function. + */ +struct gr_block_gw_message_type{ + enum action_type{ + ACTION_GENERAL_WORK, //dispatch work + ACTION_WORK, //dispatch work + ACTION_FORECAST, //dispatch forecast + ACTION_START, //dispatch start + ACTION_STOP, //dispatch stop + }; + + action_type action; + + int general_work_args_noutput_items; + std::vector<int> general_work_args_ninput_items; + std::vector<void *> general_work_args_input_items; //TODO this should be const void*, but swig cant int cast it right + std::vector<void *> general_work_args_output_items; + int general_work_args_return_value; + + int work_args_ninput_items; + int work_args_noutput_items; + std::vector<void *> work_args_input_items; //TODO this should be const void*, but swig cant int cast it right + std::vector<void *> work_args_output_items; + int work_args_return_value; + + int forecast_args_noutput_items; + std::vector<int> forecast_args_ninput_items_required; + + bool start_args_return_value; + + bool stop_args_return_value; +}; + +/*! + * The gateway block which performs all the magic. + * + * The gateway provides access to all the gr_block routines. + * The methods prefixed with gr_block__ are renamed + * to class methods without the prefix in python. + */ +class GR_CORE_API gr_block_gateway : virtual public gr_block{ +public: + //! Provide access to the shared message object + virtual gr_block_gw_message_type &gr_block_message(void) = 0; + + long gr_block__unique_id(void) const{ + return gr_block::unique_id(); + } + + std::string gr_block__name(void) const{ + return gr_block::name(); + } + + unsigned gr_block__history(void) const{ + return gr_block::history(); + } + + void gr_block__set_history(unsigned history){ + return gr_block::set_history(history); + } + + void gr_block__set_fixed_rate(bool fixed_rate){ + return gr_block::set_fixed_rate(fixed_rate); + } + + bool gr_block__fixed_rate(void) const{ + return gr_block::fixed_rate(); + } + + void gr_block__set_output_multiple(int multiple){ + return gr_block::set_output_multiple(multiple); + } + + int gr_block__output_multiple(void) const{ + return gr_block::output_multiple(); + } + + void gr_block__consume(int which_input, int how_many_items){ + return gr_block::consume(which_input, how_many_items); + } + + void gr_block__consume_each(int how_many_items){ + return gr_block::consume_each(how_many_items); + } + + void gr_block__produce(int which_output, int how_many_items){ + return gr_block::produce(which_output, how_many_items); + } + + void gr_block__set_relative_rate(double relative_rate){ + return gr_block::set_relative_rate(relative_rate); + } + + double gr_block__relative_rate(void) const{ + return gr_block::relative_rate(); + } + + uint64_t gr_block__nitems_read(unsigned int which_input){ + return gr_block::nitems_read(which_input); + } + + uint64_t gr_block__nitems_written(unsigned int which_output){ + return gr_block::nitems_written(which_output); + } + + gr_block::tag_propagation_policy_t gr_block__tag_propagation_policy(void){ + return gr_block::tag_propagation_policy(); + } + + void gr_block__set_tag_propagation_policy(gr_block::tag_propagation_policy_t p){ + return gr_block::set_tag_propagation_policy(p); + } + + void gr_block__add_item_tag( + unsigned int which_output, const gr_tag_t &tag + ){ + return gr_block::add_item_tag(which_output, tag); + } + + void gr_block__add_item_tag( + unsigned int which_output, + uint64_t abs_offset, + const pmt::pmt_t &key, + const pmt::pmt_t &value, + const pmt::pmt_t &srcid=pmt::PMT_F + ){ + return gr_block::add_item_tag(which_output, abs_offset, key, value, srcid); + } + + std::vector<gr_tag_t> gr_block__get_tags_in_range( + unsigned int which_input, + uint64_t abs_start, + uint64_t abs_end + ){ + std::vector<gr_tag_t> tags; + gr_block::get_tags_in_range(tags, which_input, abs_start, abs_end); + return tags; + } + + std::vector<gr_tag_t> gr_block__get_tags_in_range( + unsigned int which_input, + uint64_t abs_start, + uint64_t abs_end, + const pmt::pmt_t &key + ){ + std::vector<gr_tag_t> tags; + gr_block::get_tags_in_range(tags, which_input, abs_start, abs_end, key); + return tags; + } + + /* Message passing interface */ + void gr_block__message_port_register_in(pmt::pmt_t port_id){ + gr_block::message_port_register_in(port_id); + } + + void gr_block__message_port_register_out(pmt::pmt_t port_id){ + gr_block::message_port_register_out(port_id); + } + + void gr_block__message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg){ + gr_block::message_port_pub(port_id, msg); + } + + void gr_block__message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target){ + gr_block::message_port_sub(port_id, target); + } + + void gr_block__message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target){ + gr_block::message_port_unsub(port_id, target); + } + + pmt::pmt_t gr_block__message_ports_in(){ + return gr_block::message_ports_in(); + } + + pmt::pmt_t gr_block__message_ports_out(){ + return gr_block::message_ports_out(); + } + + void set_msg_handler_feval(pmt::pmt_t which_port, gr_feval_p *msg_handler) + { + if(msg_queue.find(which_port) == msg_queue.end()){ + throw std::runtime_error("attempt to set_msg_handler_feval() on bad input message port!"); + } + d_msg_handlers_feval[which_port] = msg_handler; + } + +protected: + typedef std::map<pmt::pmt_t, gr_feval_p *, pmt::pmt_comperator> msg_handlers_feval_t; + msg_handlers_feval_t d_msg_handlers_feval; + + void dispatch_msg(pmt::pmt_t which_port, pmt::pmt_t msg){ + // Is there a handler? + if (d_msg_handlers_feval.find(which_port) != d_msg_handlers_feval.end()){ + d_msg_handlers_feval[which_port]->calleval(msg); // Yes, invoke it. + } + else { + // Pass to generic dispatcher if not found + gr_block::dispatch_msg(which_port, msg); + } + } +}; + +/*! + * Make a new gateway block. + * \param handler the swig director object with callback + * \param name the name of the block (Ex: "Shirley") + * \param in_sig the input signature for this block + * \param out_sig the output signature for this block + * \param work_type the type of block overload to implement + * \param factor the decimation or interpolation factor + * \return a new gateway block + */ +GR_CORE_API boost::shared_ptr<gr_block_gateway> gr_make_block_gateway( + gr_feval_ll *handler, + const std::string &name, + gr_io_signature_sptr in_sig, + gr_io_signature_sptr out_sig, + const gr_block_gw_work_type work_type, + const unsigned factor +); + +#endif /* INCLUDED_GRBLOCK_GATEWAY_H */ diff --git a/gnuradio-core/src/lib/general/gr_block_gateway.i b/gnuradio-core/src/lib/general/gr_block_gateway.i new file mode 100644 index 000000000..8adafdfea --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_block_gateway.i @@ -0,0 +1,46 @@ +/* + * 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. + */ + +//////////////////////////////////////////////////////////////////////// +// standard includes +//////////////////////////////////////////////////////////////////////// +%include <gnuradio.i> +%include <gr_tags.i> +%include <gr_feval.i> + +//////////////////////////////////////////////////////////////////////// +// block headers +//////////////////////////////////////////////////////////////////////// +%{ +#include <gr_block_gateway.h> +%} + +//////////////////////////////////////////////////////////////////////// +// data type support +//////////////////////////////////////////////////////////////////////// +%template(int_vector_t) std::vector<int>; +%template(void_star_vector_t) std::vector<void *>; + +//////////////////////////////////////////////////////////////////////// +// block magic +//////////////////////////////////////////////////////////////////////// +GR_SWIG_BLOCK_MAGIC(gr,block_gateway); +%include <gr_block_gateway.h> diff --git a/gnuradio-core/src/lib/general/gr_burst_tagger.cc b/gnuradio-core/src/lib/general/gr_burst_tagger.cc new file mode 100644 index 000000000..83e84bfa0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_burst_tagger.cc @@ -0,0 +1,109 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_burst_tagger.h> +#include <gr_io_signature.h> +#include <string.h> + +gr_burst_tagger_sptr +gr_make_burst_tagger(size_t itemsize) +{ + return gnuradio::get_initial_sptr(new gr_burst_tagger(itemsize)); +} + +gr_burst_tagger::gr_burst_tagger(size_t itemsize) + : gr_sync_block ("burst_tagger", + gr_make_io_signature2 (2, 2, itemsize, sizeof(short)), + gr_make_io_signature (1, 1, itemsize)), + d_itemsize(itemsize), d_state(false) +{ + std::stringstream str; + str << name() << unique_id(); + + d_true_key = pmt::pmt_string_to_symbol("burst"); + d_true_value = pmt::PMT_T; + + d_false_key = pmt::pmt_string_to_symbol("burst"); + d_false_value = pmt::PMT_F; + + d_id = pmt::pmt_string_to_symbol(str.str()); +} + +void +gr_burst_tagger::set_true_tag (const std::string &key, bool value) +{ + d_true_key = pmt::pmt_string_to_symbol(key); + if(value == true) { + d_true_value = pmt::PMT_T; + } + else { + d_true_value = pmt::PMT_F; + } +} + +void +gr_burst_tagger::set_false_tag (const std::string &key, bool value) +{ + d_false_key = pmt::pmt_string_to_symbol(key); + if(value == true) { + d_false_value = pmt::PMT_T; + } + else { + d_false_value = pmt::PMT_F; + } +} + +gr_burst_tagger::~gr_burst_tagger() +{ +} + +int +gr_burst_tagger::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const char *signal = (const char*)input_items[0]; + const short *trigger = (const short*)input_items[1]; + char *out = (char*)output_items[0]; + + memcpy(out, signal, noutput_items * d_itemsize); + + for(int i = 0; i < noutput_items; i++) { + if(trigger[i] > 0) { + if(d_state == false) { + d_state = true; + add_item_tag(0, nitems_written(0)+i, d_true_key, d_true_value, d_id); + } + } + else { + if(d_state == true) { + d_state = false; + add_item_tag(0, nitems_written(0)+i, d_false_key, d_false_value, d_id); + } + } + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_burst_tagger.h b/gnuradio-core/src/lib/general/gr_burst_tagger.h new file mode 100644 index 000000000..9a7898b04 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_burst_tagger.h @@ -0,0 +1,64 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_BURST_TAGGER_H +#define INCLUDED_GR_BURST_TAGGER_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_burst_tagger; +typedef boost::shared_ptr<gr_burst_tagger> gr_burst_tagger_sptr; + +GR_CORE_API gr_burst_tagger_sptr gr_make_burst_tagger(size_t itemsize); + +/*! + * \brief output[i] = input[i] + * \ingroup misc_blk + * + */ +class GR_CORE_API gr_burst_tagger : public gr_sync_block +{ + size_t d_itemsize; + bool d_state; + pmt::pmt_t d_true_key; + pmt::pmt_t d_true_value; + + pmt::pmt_t d_false_key; + pmt::pmt_t d_false_value; + + pmt::pmt_t d_id; + + friend GR_CORE_API gr_burst_tagger_sptr gr_make_burst_tagger(size_t itemsize); + gr_burst_tagger(size_t itemsize); + + public: + ~gr_burst_tagger(); + void set_true_tag (const std::string &key, bool value); + void set_false_tag (const std::string &key, bool value); + + 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_burst_tagger.i b/gnuradio-core/src/lib/general/gr_burst_tagger.i new file mode 100644 index 000000000..a5511e48a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_burst_tagger.i @@ -0,0 +1,35 @@ +/* -*- c++ -*- */ +/* + * Copyright 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,burst_tagger) + +gr_burst_tagger_sptr gr_make_burst_tagger(size_t itemsize); + +class gr_burst_tagger : public gr_sync_block +{ + private: + gr_burst_tagger(size_t itemsize); + + public: + void set_true_tag(const std::string &key, bool value); + void set_false_tag(const std::string &key, bool value); +}; diff --git a/gnuradio-core/src/lib/general/gr_bytes_to_syms.cc b/gnuradio-core/src/lib/general/gr_bytes_to_syms.cc new file mode 100644 index 000000000..7dafa29f9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_bytes_to_syms.cc @@ -0,0 +1,74 @@ +/* -*- 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 new file mode 100644 index 000000000..23e5c6b91 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_bytes_to_syms.h @@ -0,0 +1,61 @@ +/* -*- 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 new file mode 100644 index 000000000..185e7cd29 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_bytes_to_syms.i @@ -0,0 +1,30 @@ +/* -*- 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_char_to_float.cc b/gnuradio-core/src/lib/general/gr_char_to_float.cc new file mode 100644 index 000000000..f63aa5b16 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_char_to_float.cc @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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_char_to_float.h> +#include <gr_io_signature.h> +#include <volk/volk.h> + +gr_char_to_float_sptr +gr_make_char_to_float (size_t vlen, float scale) +{ + return gnuradio::get_initial_sptr(new gr_char_to_float (vlen, scale)); +} + +gr_char_to_float::gr_char_to_float (size_t vlen, float scale) + : gr_sync_block ("gr_char_to_float", + gr_make_io_signature (1, 1, sizeof (char)*vlen), + gr_make_io_signature (1, 1, sizeof (float)*vlen)), + d_vlen(vlen), d_scale(scale) +{ + const int alignment_multiple = + volk_get_alignment() / sizeof(float); + set_alignment(std::max(1,alignment_multiple)); +} + +float +gr_char_to_float::scale() const +{ + return d_scale; +} + +void +gr_char_to_float::set_scale(float scale) +{ + d_scale = scale; +} + +int +gr_char_to_float::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const int8_t *in = (const int8_t *) input_items[0]; + float *out = (float *) output_items[0]; + + // Note: the unaligned benchmarked much faster than the aligned + volk_8i_s32f_convert_32f_u(out, in, d_scale, d_vlen*noutput_items); + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_char_to_float.h b/gnuradio-core/src/lib/general/gr_char_to_float.h new file mode 100644 index 000000000..5170c618c --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_char_to_float.h @@ -0,0 +1,70 @@ +/* -*- 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_CHAR_TO_FLOAT_H +#define INCLUDED_GR_CHAR_TO_FLOAT_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_char_to_float; +typedef boost::shared_ptr<gr_char_to_float> gr_char_to_float_sptr; + +GR_CORE_API gr_char_to_float_sptr +gr_make_char_to_float (size_t vlen=1, float scale=1); + +/*! + * \brief Convert stream of chars to a stream of float + * \ingroup converter_blk + * + * \param vlen vector length of data streams. + * \param scale a scalar divider to change the output signal scale. + */ + +class GR_CORE_API gr_char_to_float : public gr_sync_block +{ + private: + friend GR_CORE_API gr_char_to_float_sptr + gr_make_char_to_float (size_t vlen, float scale); + gr_char_to_float (size_t vlen, float scale); + + size_t d_vlen; + float d_scale; + + public: + /*! + * Get the scalar divider value. + */ + float scale() const; + + /*! + * Set the scalar divider value. + */ + void set_scale(float scale); + + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_CHAR_TO_FLOAT_H */ diff --git a/gnuradio-core/src/lib/general/gr_char_to_float.i b/gnuradio-core/src/lib/general/gr_char_to_float.i new file mode 100644 index 000000000..c0b3d75fe --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_char_to_float.i @@ -0,0 +1,33 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,char_to_float) + +gr_char_to_float_sptr +gr_make_char_to_float (size_t vlen=1, float scale=1); + +class gr_char_to_float : public gr_sync_block +{ +public: + float scale() const; + void set_scale(float scale); +}; diff --git a/gnuradio-core/src/lib/general/gr_char_to_short.cc b/gnuradio-core/src/lib/general/gr_char_to_short.cc new file mode 100644 index 000000000..bb9bd8909 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_char_to_short.cc @@ -0,0 +1,64 @@ +/* -*- 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 <gr_char_to_short.h> +#include <gr_io_signature.h> +#include <volk/volk.h> + +gr_char_to_short_sptr +gr_make_char_to_short (size_t vlen) +{ + return gnuradio::get_initial_sptr(new gr_char_to_short (vlen)); +} + +gr_char_to_short::gr_char_to_short (size_t vlen) + : gr_sync_block ("gr_char_to_short", + gr_make_io_signature (1, 1, sizeof (char)*vlen), + gr_make_io_signature (1, 1, sizeof (short)*vlen)), + d_vlen(vlen) +{ + const int alignment_multiple = + volk_get_alignment() / sizeof(char); + set_alignment(std::max(1,alignment_multiple)); +} + +int +gr_char_to_short::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const int8_t *in = (const int8_t *) input_items[0]; + int16_t *out = (int16_t *) output_items[0]; + + if(is_unaligned()) { + volk_8i_convert_16i_u(out, in, d_vlen*noutput_items); + } + else { + volk_8i_convert_16i_a(out, in, d_vlen*noutput_items); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_char_to_short.h b/gnuradio-core/src/lib/general/gr_char_to_short.h new file mode 100644 index 000000000..7ac5e97b9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_char_to_short.h @@ -0,0 +1,58 @@ +/* -*- 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_GR_CHAR_TO_SHORT_H +#define INCLUDED_GR_CHAR_TO_SHORT_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_char_to_short; +typedef boost::shared_ptr<gr_char_to_short> gr_char_to_short_sptr; + +GR_CORE_API gr_char_to_short_sptr +gr_make_char_to_short (size_t vlen=1); + +/*! + * \brief Convert stream of chars to a stream of float + * \ingroup converter_blk + * + * \param vlen vector length of data streams. + */ + +class GR_CORE_API gr_char_to_short : public gr_sync_block +{ + private: + friend GR_CORE_API gr_char_to_short_sptr + gr_make_char_to_short (size_t vlen); + gr_char_to_short (size_t vlen); + + size_t d_vlen; + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_CHAR_TO_SHORT_H */ diff --git a/gnuradio-core/src/lib/general/gr_char_to_short.i b/gnuradio-core/src/lib/general/gr_char_to_short.i new file mode 100644 index 000000000..a53a0990e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_char_to_short.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,char_to_short) + +gr_char_to_short_sptr gr_make_char_to_short (size_t vlen=1); + +class gr_char_to_short : public gr_sync_block +{ + +}; diff --git a/gnuradio-core/src/lib/general/gr_check_counting_s.cc b/gnuradio-core/src/lib/general/gr_check_counting_s.cc new file mode 100644 index 000000000..c3288f481 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_check_counting_s.cc @@ -0,0 +1,190 @@ +/* -*- 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_check_counting_s.h> +#include <gr_io_signature.h> +#include <stdlib.h> +#include <stdio.h> + +gr_check_counting_s_sptr +gr_make_check_counting_s (bool do_32bit) +{ + return gnuradio::get_initial_sptr(new gr_check_counting_s (do_32bit)); +} + +gr_check_counting_s::gr_check_counting_s (bool do_32bit) + : gr_sync_block ("gr_check_counting", + gr_make_io_signature (1, 1, sizeof (short)), + gr_make_io_signature (0, 0, 0)), + d_state(SEARCHING), d_history (0), d_current_count (0), d_current_count_32bit(0), + d_total_errors (0), d_total_shorts (0), + d_do_32bit(do_32bit) +{ + enter_SEARCHING (); +} + +int +gr_check_counting_s::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + unsigned short *in = (unsigned short *) input_items[0]; + if(d_do_32bit) + return check_32bit(noutput_items,in); + else + return check_16bit(noutput_items,in); +} + +int +gr_check_counting_s::check_16bit (int noutput_items, + unsigned short * in) +{ + for (int i = 0; i < noutput_items; i++){ + unsigned short x = in[i]; + + switch (d_state){ + + case SEARCHING: + if (x == d_current_count){ + right (); + log_error (d_current_count, x); + d_current_count = d_current_count + 1; + if (right_three_times ()) + enter_LOCKED (); + } + else { + wrong (); + log_error (d_current_count, x); + d_current_count = x + 1; + } + break; + + case LOCKED: + if (x == d_current_count){ + right (); + d_current_count = d_current_count + 1; + } + else { + wrong (); + log_error (d_current_count, x); + d_current_count = d_current_count + 1; + if (wrong_three_times ()) + enter_SEARCHING (); + } + break; + + default: + abort (); + } + + d_total_shorts++; + } + + return noutput_items; +} + +int +gr_check_counting_s::check_32bit (int noutput_items, + unsigned short * in) +{ + + for (int i = 0; i < noutput_items-1; i+=2){ + unsigned int x_high16bits = in[i]; + unsigned int x_low16bits = in[i+1]; + unsigned int x = x_high16bits<<16 | x_low16bits; + + switch (d_state){ + + case SEARCHING: + if (x == d_current_count_32bit){ + right (); + log_error_32bit (d_current_count_32bit, x); + d_current_count_32bit = d_current_count_32bit + 1; + if (right_three_times ()) + enter_LOCKED (); + } + else { + wrong (); + log_error_32bit (d_current_count_32bit, x); + d_current_count_32bit = x + 1; + } + break; + + case LOCKED: + if (x == d_current_count_32bit){ + right (); + d_current_count_32bit = d_current_count_32bit + 1; + } + else { + wrong (); + log_error_32bit (d_current_count_32bit, x); + d_current_count_32bit = d_current_count_32bit + 1; + if (wrong_three_times ()) + enter_SEARCHING (); + } + break; + + default: + abort (); + } + + d_total_shorts++; + } + + return noutput_items; +} + +void +gr_check_counting_s::enter_SEARCHING () +{ + d_state = SEARCHING; + fprintf (stdout, "gr_check_counting: enter_SEARCHING at offset %8ld (0x%08lx)\n", + d_total_shorts, d_total_shorts); +} + +void +gr_check_counting_s::enter_LOCKED () +{ + d_state = LOCKED; + fprintf (stdout, "gr_check_counting: enter_LOCKED at offset %8ld (0x%08lx)\n", + d_total_shorts, d_total_shorts); +} + +void +gr_check_counting_s::log_error (unsigned short expected, unsigned short actual) +{ + fprintf (stdout, +"gr_check_counting: expected %5d (0x%04x) got %5d (0x%04x) offset %8ld (0x%08lx)\n", + expected, expected, actual, actual, d_total_shorts, d_total_shorts); +} + +void +gr_check_counting_s::log_error_32bit (unsigned int expected, unsigned int actual) +{ + fprintf (stdout, +"gr_check_counting: expected %10d (0x%08x) got %10d (0x%08x) offset %8ld (0x%08lx)\n", + expected, expected, actual, actual, d_total_shorts, d_total_shorts); +} diff --git a/gnuradio-core/src/lib/general/gr_check_counting_s.h b/gnuradio-core/src/lib/general/gr_check_counting_s.h new file mode 100644 index 000000000..996fa3259 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_check_counting_s.h @@ -0,0 +1,89 @@ +/* -*- 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_CHECK_COUNTING_S_H +#define INCLUDED_GR_CHECK_COUNTING_S_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_check_counting_s; +typedef boost::shared_ptr<gr_check_counting_s> gr_check_counting_s_sptr; + +GR_CORE_API gr_check_counting_s_sptr gr_make_check_counting_s (bool do_32bit=false); + +/*! + * \brief sink that checks if its input stream consists of a counting sequence. + * \param do_32bit expect an interleaved 32 bit counter in stead of 16 bit counter (default false) + * \ingroup sink_blk + * + * This sink is typically used to test the USRP "Counting Mode" or "Counting mode 32 bit". + */ +class GR_CORE_API gr_check_counting_s : public gr_sync_block +{ + friend GR_CORE_API gr_check_counting_s_sptr gr_make_check_counting_s (bool do_32bit); + + enum state { + SEARCHING, // searching for synchronization + LOCKED // is locked + }; + + state d_state; + unsigned int d_history; // bitmask of decisions + unsigned short d_current_count; + unsigned int d_current_count_32bit; + + long d_total_errors; + long d_total_shorts; + bool d_do_32bit; + + gr_check_counting_s (bool do_32bit); + + void enter_SEARCHING (); + void enter_LOCKED (); + + void right (){ + d_history = (d_history << 1) | 0x1; + } + + void wrong (){ + d_history = (d_history << 1) | 0x0; + d_total_errors++; + } + + bool right_three_times () { return (d_history & 0x7) == 0x7; } + bool wrong_three_times () { return (d_history & 0x7) == 0x0; } + + void log_error (unsigned short expected, unsigned short actual); + void log_error_32bit (unsigned int expected, unsigned int actual); + + int check_32bit (int noutput_items, unsigned short * in); + int check_16bit (int noutput_items, unsigned short * in); + + public: + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_CHECK_COUNTING_S_H */ diff --git a/gnuradio-core/src/lib/general/gr_check_counting_s.i b/gnuradio-core/src/lib/general/gr_check_counting_s.i new file mode 100644 index 000000000..0275dad9d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_check_counting_s.i @@ -0,0 +1,31 @@ +/* -*- 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,check_counting_s) + +gr_check_counting_s_sptr gr_make_check_counting_s (bool do_32bit=false); + +class gr_check_counting_s : public gr_sync_block +{ + private: + gr_check_counting_s (bool do_32bit); +}; diff --git a/gnuradio-core/src/lib/general/gr_check_lfsr_32k_s.cc b/gnuradio-core/src/lib/general/gr_check_lfsr_32k_s.cc new file mode 100644 index 000000000..088b8c38a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_check_lfsr_32k_s.cc @@ -0,0 +1,169 @@ +/* -*- 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_check_lfsr_32k_s.h> +#include <gr_io_signature.h> +#include <stdlib.h> +#include <stdio.h> + +gr_check_lfsr_32k_s_sptr +gr_make_check_lfsr_32k_s () +{ + return gnuradio::get_initial_sptr(new gr_check_lfsr_32k_s ()); +} + +gr_check_lfsr_32k_s::gr_check_lfsr_32k_s () + : gr_sync_block ("gr_check_lfsr_32k", + gr_make_io_signature (1, 1, sizeof (short)), + gr_make_io_signature (0, 0, 0)), + d_state(SEARCHING), d_history (0), d_ntotal (0), d_nright (0), + d_runlength (0), d_index(0) +{ + gri_lfsr_32k lfsr; + + for (int i = 0; i < BUFSIZE; i++) + d_buffer[i] = lfsr.next_short (); + + enter_SEARCHING (); +} + +int +gr_check_lfsr_32k_s::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + unsigned short *in = (unsigned short *) input_items[0]; + + for (int i = 0; i < noutput_items; i++){ + unsigned short x = in[i]; + unsigned short expected; + + switch (d_state){ + + case MATCH0: + if (x == d_buffer[0]) + enter_MATCH1 (); + break; + + case MATCH1: + if (x == d_buffer[1]) + enter_MATCH2 (); + else + enter_MATCH0 (); + break; + + case MATCH2: + if (x == d_buffer[2]) + enter_LOCKED (); + else + enter_MATCH0 (); + break; + + case LOCKED: + expected = d_buffer[d_index]; + d_index = d_index + 1; + if (d_index >= BUFSIZE) + d_index = 0; + + if (x == expected) + right (); + else { + wrong (); + log_error (expected, x); + if (wrong_three_times ()) + enter_SEARCHING (); + } + break; + + default: + abort (); + } + + d_ntotal++; + } + + return noutput_items; +} + +void +gr_check_lfsr_32k_s::enter_SEARCHING () +{ + d_state = SEARCHING; + wrong (); // reset history + wrong (); + wrong (); + + d_runlength = 0; + d_index = 0; // reset LFSR to beginning + + if (0) + fprintf (stdout, "gr_check_lfsr_32k: enter_SEARCHING at offset %8ld (0x%08lx)\n", + d_ntotal, d_ntotal); + + enter_MATCH0 (); +} + +void +gr_check_lfsr_32k_s::enter_MATCH0 () +{ + d_state = MATCH0; +} + +void +gr_check_lfsr_32k_s::enter_MATCH1 () +{ + d_state = MATCH1; +} + +void +gr_check_lfsr_32k_s::enter_MATCH2 () +{ + d_state = MATCH2; +} + +void +gr_check_lfsr_32k_s::enter_LOCKED () +{ + d_state = LOCKED; + right (); // setup history + right (); + right (); + + d_index = 3; // already matched first 3 items + + if (0) + fprintf (stdout, "gr_check_lfsr_32k: enter_LOCKED at offset %8ld (0x%08lx)\n", + d_ntotal, d_ntotal); +} + +void +gr_check_lfsr_32k_s::log_error (unsigned short expected, unsigned short actual) +{ + if (0) + fprintf (stdout, + "gr_check_lfsr_32k: expected %5d (0x%04x) got %5d (0x%04x) offset %8ld (0x%08lx)\n", + expected, expected, actual, actual, d_ntotal, d_ntotal); +} diff --git a/gnuradio-core/src/lib/general/gr_check_lfsr_32k_s.h b/gnuradio-core/src/lib/general/gr_check_lfsr_32k_s.h new file mode 100644 index 000000000..2f980b427 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_check_lfsr_32k_s.h @@ -0,0 +1,103 @@ +/* -*- 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_CHECK_LFSR_32K_S_H +#define INCLUDED_GR_CHECK_LFSR_32K_S_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gri_lfsr_32k.h> + + +class gr_check_lfsr_32k_s; +typedef boost::shared_ptr<gr_check_lfsr_32k_s> gr_check_lfsr_32k_s_sptr; + +GR_CORE_API gr_check_lfsr_32k_s_sptr gr_make_check_lfsr_32k_s (); + +/*! + * \brief sink that checks if its input stream consists of a lfsr_32k sequence. + * \ingroup sink_blk + * + * This sink is typically used along with gr_lfsr_32k_source_s to test + * the USRP using its digital loopback mode. + */ +class GR_CORE_API gr_check_lfsr_32k_s : public gr_sync_block +{ + friend GR_CORE_API gr_check_lfsr_32k_s_sptr gr_make_check_lfsr_32k_s (); + + enum state { + SEARCHING, // searching for synchronization + MATCH0, + MATCH1, + MATCH2, + LOCKED // is locked + }; + + state d_state; + unsigned int d_history; // bitmask of decisions + + long d_ntotal; // total number of shorts + long d_nright; // # of correct shorts + long d_runlength; // # of correct shorts in a row + + static const int BUFSIZE = 2048 - 1; // ensure pattern isn't packet aligned + int d_index; + unsigned short d_buffer[BUFSIZE]; + + + gr_check_lfsr_32k_s (); + + void enter_SEARCHING (); + void enter_MATCH0 (); + void enter_MATCH1 (); + void enter_MATCH2 (); + void enter_LOCKED (); + + void right (){ + d_history = (d_history << 1) | 0x1; + d_nright++; + d_runlength++; + } + + void wrong (){ + d_history = (d_history << 1) | 0x0; + d_runlength = 0; + } + + bool right_three_times () { return (d_history & 0x7) == 0x7; } + bool wrong_three_times () { return (d_history & 0x7) == 0x0; } + + void log_error (unsigned short expected, unsigned short actual); + + public: + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + long ntotal () const { return d_ntotal; } + long nright () const { return d_nright; } + long runlength () const { return d_runlength; } + +}; + + +#endif /* INCLUDED_GR_CHECK_LFSR_32K_S_H */ diff --git a/gnuradio-core/src/lib/general/gr_check_lfsr_32k_s.i b/gnuradio-core/src/lib/general/gr_check_lfsr_32k_s.i new file mode 100644 index 000000000..34d4a0b0c --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_check_lfsr_32k_s.i @@ -0,0 +1,36 @@ +/* -*- 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,check_lfsr_32k_s) + +gr_check_lfsr_32k_s_sptr gr_make_check_lfsr_32k_s (); + +class gr_check_lfsr_32k_s : public gr_sync_block +{ + private: + gr_check_lfsr_32k_s (); + +public: + long ntotal () const; + long nright () const; + long runlength () const; +}; diff --git a/gnuradio-core/src/lib/general/gr_circular_file.cc b/gnuradio-core/src/lib/general/gr_circular_file.cc new file mode 100644 index 000000000..6f710c49b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_circular_file.cc @@ -0,0 +1,203 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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_circular_file.h> + +#include <unistd.h> +#ifdef HAVE_SYS_MMAN_H +#include <sys/mman.h> +#endif +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <stdio.h> +#include <assert.h> +#include <stdlib.h> + +#include <algorithm> +#include <stdio.h> +#include <string.h> + +#ifdef HAVE_IO_H +#include <io.h> +#endif + +static const int HEADER_SIZE = 4096; +static const int HEADER_MAGIC = 0xEB021026; + +static const int HD_MAGIC = 0; +static const int HD_HEADER_SIZE = 1; // integer offsets into header +static const int HD_BUFFER_SIZE = 2; +static const int HD_BUFFER_BASE = 3; +static const int HD_BUFFER_CURRENT = 4; + +gr_circular_file::gr_circular_file (const char *filename, + bool writable, int size) + : d_fd (-1), d_header (0), d_buffer (0), d_mapped_size (0), d_bytes_read (0) +{ + int mm_prot; + if (writable){ +#ifdef HAVE_MMAP + mm_prot = PROT_READ | PROT_WRITE; +#endif + d_fd = open (filename, O_CREAT | O_RDWR | O_TRUNC, 0664); + if (d_fd < 0){ + perror (filename); + exit (1); + } +#ifdef HAVE_MMAP /* FIXME */ + if(ftruncate (d_fd, size + HEADER_SIZE) != 0) { + perror (filename); + exit (1); + } +#endif + } + else { +#ifdef HAVE_MMAP + mm_prot = PROT_READ; +#endif + d_fd = open (filename, O_RDONLY); + if (d_fd < 0){ + perror (filename); + exit (1); + } + } + + struct stat statbuf; + if (fstat (d_fd, &statbuf) < 0){ + perror (filename); + exit (1); + } + + if (statbuf.st_size < HEADER_SIZE){ + fprintf (stderr, "%s: file too small to be circular buffer\n", filename); + exit (1); + } + + d_mapped_size = statbuf.st_size; +#ifdef HAVE_MMAP + void *p = mmap (0, d_mapped_size, mm_prot, MAP_SHARED, d_fd, 0); + if (p == MAP_FAILED){ + perror ("gr_circular_file: mmap failed"); + exit (1); + } + + d_header = (int *) p; +#else + perror ("gr_circular_file: mmap unsupported by this system"); + exit (1); +#endif + + if (writable){ // init header + + if (size < 0){ + fprintf (stderr, "gr_circular_buffer: size must be > 0 when writable\n"); + exit (1); + } + + d_header[HD_MAGIC] = HEADER_MAGIC; + d_header[HD_HEADER_SIZE] = HEADER_SIZE; + d_header[HD_BUFFER_SIZE] = size; + d_header[HD_BUFFER_BASE] = HEADER_SIZE; // right after header + d_header[HD_BUFFER_CURRENT] = 0; + } + + // sanity check (the asserts are a bit unforgiving...) + + assert (d_header[HD_MAGIC] == HEADER_MAGIC); + assert (d_header[HD_HEADER_SIZE] == HEADER_SIZE); + assert (d_header[HD_BUFFER_SIZE] > 0); + assert (d_header[HD_BUFFER_BASE] >= d_header[HD_HEADER_SIZE]); + assert (d_header[HD_BUFFER_BASE] + d_header[HD_BUFFER_SIZE] <= d_mapped_size); + assert (d_header[HD_BUFFER_CURRENT] >= 0 && + d_header[HD_BUFFER_CURRENT] < d_header[HD_BUFFER_SIZE]); + + d_bytes_read = 0; + d_buffer = (unsigned char *) d_header + d_header[HD_BUFFER_BASE]; +} + +gr_circular_file::~gr_circular_file () +{ +#ifdef HAVE_MMAP + if (munmap ((char *) d_header, d_mapped_size) < 0){ + perror ("gr_circular_file: munmap"); + exit (1); + } +#endif + close (d_fd); +} + +bool +gr_circular_file::write (void *vdata, int nbytes) +{ + unsigned char *data = (unsigned char *) vdata; + int buffer_size = d_header[HD_BUFFER_SIZE]; + int buffer_current = d_header[HD_BUFFER_CURRENT]; + + while (nbytes > 0){ + int n = std::min (nbytes, buffer_size - buffer_current); + memcpy (d_buffer + buffer_current, data, n); + + buffer_current += n; + if (buffer_current >= buffer_size) + buffer_current = 0; + + data += n; + nbytes -= n; + } + + d_header[HD_BUFFER_CURRENT] = buffer_current; + return true; +} + +int +gr_circular_file::read (void *vdata, int nbytes) +{ + unsigned char *data = (unsigned char *) vdata; + int buffer_current = d_header[HD_BUFFER_CURRENT]; + int buffer_size = d_header[HD_BUFFER_SIZE]; + int total = 0; + + nbytes = std::min (nbytes, buffer_size - d_bytes_read); + + while (nbytes > 0){ + int offset = (buffer_current + d_bytes_read) % buffer_size; + int n = std::min (nbytes, buffer_size - offset); + memcpy (data, d_buffer + offset, n); + data += n; + d_bytes_read += n; + total += n; + nbytes -= n; + } + return total; +} + +void +gr_circular_file::reset_read_pointer () +{ + d_bytes_read = 0; +} diff --git a/gnuradio-core/src/lib/general/gr_circular_file.h b/gnuradio-core/src/lib/general/gr_circular_file.h new file mode 100644 index 000000000..ca1f793f3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_circular_file.h @@ -0,0 +1,60 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 _GR_CIRCULAR_FILE_H_ +#define _GR_CIRCULAR_FILE_H_ + +#include <gr_core_api.h> + +/* + * writes input data into a circular buffer on disk. + * + * the file contains a fixed header: + * 0x0000: int32 magic (0xEB021026) + * 0x0004: int32 size in bytes of header (constant 4096) + * 0x0008: int32 size in bytes of circular buffer (not including header) + * 0x000C: int32 file offset to beginning of circular buffer + * 0x0010: int32 byte offset from beginning of circular buffer to + * current start of data + * + */ +class GR_CORE_API gr_circular_file { + int d_fd; + int *d_header; + unsigned char *d_buffer; + int d_mapped_size; + int d_bytes_read; + +public: + gr_circular_file (const char *filename, bool writable = false, int size = 0); + ~gr_circular_file (); + + bool write (void *data, int nbytes); + + // returns # of bytes actually read or 0 if end of buffer, or -1 on error. + int read (void *data, int nbytes); + + // reset read pointer to beginning of buffer. + void reset_read_pointer (); +}; + +#endif /* _GR_CIRCULAR_FILE_H_ */
\ No newline at end of file diff --git a/gnuradio-core/src/lib/general/gr_complex_to_interleaved_short.cc b/gnuradio-core/src/lib/general/gr_complex_to_interleaved_short.cc new file mode 100644 index 000000000..596c14996 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_complex_to_interleaved_short.cc @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005,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_complex_to_interleaved_short.h> +#include <gr_io_signature.h> +#include <math.h> + +gr_complex_to_interleaved_short_sptr +gr_make_complex_to_interleaved_short () +{ + return gnuradio::get_initial_sptr(new gr_complex_to_interleaved_short ()); +} + +gr_complex_to_interleaved_short::gr_complex_to_interleaved_short () + : gr_sync_interpolator ("gr_complex_to_interleaved_short", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (short)), + 2) +{ +} + +int +gr_complex_to_interleaved_short::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]; + short *out = (short *) output_items[0]; + + for (int i = 0; i < noutput_items/2; i++){ + *out++ = (short) lrintf(in[i].real()); // FIXME saturate? + *out++ = (short) lrintf(in[i].imag()); + } + + return noutput_items; +} + + + diff --git a/gnuradio-core/src/lib/general/gr_complex_to_interleaved_short.h b/gnuradio-core/src/lib/general/gr_complex_to_interleaved_short.h new file mode 100644 index 000000000..66503413f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_complex_to_interleaved_short.h @@ -0,0 +1,52 @@ +/* -*- 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_COMPLEX_TO_INTERLEAVED_SHORT_H +#define INCLUDED_GR_COMPLEX_TO_INTERLEAVED_SHORT_H + +#include <gr_core_api.h> +#include <gr_sync_interpolator.h> + +class gr_complex_to_interleaved_short; +typedef boost::shared_ptr<gr_complex_to_interleaved_short> + gr_complex_to_interleaved_short_sptr; + +GR_CORE_API gr_complex_to_interleaved_short_sptr +gr_make_complex_to_interleaved_short (); + +/*! + * \brief Convert stream of complex to a stream of interleaved shorts + * \ingroup converter_blk + */ + +class GR_CORE_API gr_complex_to_interleaved_short : public gr_sync_interpolator +{ + friend GR_CORE_API gr_complex_to_interleaved_short_sptr gr_make_complex_to_interleaved_short (); + gr_complex_to_interleaved_short (); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_COMPLEX_TO_INTERLEAVED_SHORT_H */ diff --git a/gnuradio-core/src/lib/general/gr_complex_to_interleaved_short.i b/gnuradio-core/src/lib/general/gr_complex_to_interleaved_short.i new file mode 100644 index 000000000..19c01b7c6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_complex_to_interleaved_short.i @@ -0,0 +1,30 @@ +/* -*- 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,complex_to_interleaved_short) + +gr_complex_to_interleaved_short_sptr gr_make_complex_to_interleaved_short (); + +class gr_complex_to_interleaved_short : public gr_sync_interpolator +{ + gr_complex_to_interleaved_short (); +}; diff --git a/gnuradio-core/src/lib/general/gr_complex_to_xxx.cc b/gnuradio-core/src/lib/general/gr_complex_to_xxx.cc new file mode 100644 index 000000000..cdf6d7f3a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_complex_to_xxx.cc @@ -0,0 +1,280 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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 <gr_complex_to_xxx.h> +#include <gr_io_signature.h> +#include <gr_math.h> +#include <volk/volk.h> + +// ---------------------------------------------------------------- + +gr_complex_to_float_sptr +gr_make_complex_to_float (unsigned int vlen) +{ + return gnuradio::get_initial_sptr(new gr_complex_to_float (vlen)); +} + +gr_complex_to_float::gr_complex_to_float (unsigned int vlen) + : gr_sync_block ("complex_to_float", + gr_make_io_signature (1, 1, sizeof (gr_complex) * vlen), + gr_make_io_signature (1, 2, sizeof (float) * vlen)), + d_vlen(vlen) +{ + const int alignment_multiple = + volk_get_alignment() / sizeof(float); + set_alignment(std::max(1,alignment_multiple)); +} + +int +gr_complex_to_float::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]; + float *out0 = (float *) output_items[0]; + float* out1; + int noi = noutput_items * d_vlen; + + switch (output_items.size ()){ + case 1: + if(is_unaligned()) { + for (int i = 0; i < noi; i++){ + out0[i] = in[i].real (); + } + } + else { + volk_32fc_deinterleave_real_32f_a(out0, in, noi); + } + break; + + case 2: + out1 = (float *) output_items[1]; + if(is_unaligned()) { + for (int i = 0; i < noi; i++){ + out0[i] = in[i].real (); + out1[i] = in[i].imag (); + } + } + else { + volk_32fc_deinterleave_32f_x2_a(out0, out1, in, noi); + } + break; + + default: + abort (); + } + + return noutput_items; +} + +// ---------------------------------------------------------------- + +gr_complex_to_real_sptr +gr_make_complex_to_real (unsigned int vlen) +{ + return gnuradio::get_initial_sptr(new gr_complex_to_real (vlen)); +} + +gr_complex_to_real::gr_complex_to_real (unsigned int vlen) + : gr_sync_block ("complex_to_real", + gr_make_io_signature (1, 1, sizeof (gr_complex) * vlen), + gr_make_io_signature (1, 1, sizeof (float) * vlen)), + d_vlen(vlen) +{ + const int alignment_multiple = + volk_get_alignment() / sizeof(float); + set_alignment(std::max(1,alignment_multiple)); +} + +int +gr_complex_to_real::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]; + float *out = (float *) output_items[0]; + int noi = noutput_items * d_vlen; + + if(is_unaligned()) { + for (int i = 0; i < noi; i++){ + out[i] = in[i].real (); + } + } + else { + volk_32fc_deinterleave_real_32f_a(out, in, noi); + } + + return noutput_items; +} + +// ---------------------------------------------------------------- + +gr_complex_to_imag_sptr +gr_make_complex_to_imag (unsigned int vlen) +{ + return gnuradio::get_initial_sptr(new gr_complex_to_imag (vlen)); +} + +gr_complex_to_imag::gr_complex_to_imag (unsigned int vlen) + : gr_sync_block ("complex_to_imag", + gr_make_io_signature (1, 1, sizeof (gr_complex) * vlen), + gr_make_io_signature (1, 1, sizeof (float) * vlen)), + d_vlen(vlen) +{ + const int alignment_multiple = + volk_get_alignment() / sizeof(float); + set_alignment(std::max(1,alignment_multiple)); +} + +int +gr_complex_to_imag::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]; + float *out = (float *) output_items[0]; + int noi = noutput_items * d_vlen; + + if(is_unaligned()) { + for (int i = 0; i < noi; i++){ + out[i] = in[i].imag (); + } + } + else { + volk_32fc_deinterleave_imag_32f_a(out, in, noi); + } + + return noutput_items; +} + +// ---------------------------------------------------------------- + +gr_complex_to_mag_sptr +gr_make_complex_to_mag (unsigned int vlen) +{ + return gnuradio::get_initial_sptr(new gr_complex_to_mag (vlen)); +} + +gr_complex_to_mag::gr_complex_to_mag (unsigned int vlen) + : gr_sync_block ("complex_to_mag", + gr_make_io_signature (1, 1, sizeof (gr_complex) * vlen), + gr_make_io_signature (1, 1, sizeof (float) * vlen)), + d_vlen(vlen) +{ + const int alignment_multiple = + volk_get_alignment() / sizeof(float); + set_alignment(std::max(1,alignment_multiple)); +} + +int +gr_complex_to_mag::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]; + float *out = (float *) output_items[0]; + int noi = noutput_items * d_vlen; + + // turned out to be faster than aligned/unaligned switching + volk_32fc_magnitude_32f_u(out, in, noi); + + return noutput_items; +} + +// ---------------------------------------------------------------- + +gr_complex_to_mag_squared_sptr +gr_make_complex_to_mag_squared (unsigned int vlen) +{ + return gnuradio::get_initial_sptr(new gr_complex_to_mag_squared (vlen)); +} + +gr_complex_to_mag_squared::gr_complex_to_mag_squared (unsigned int vlen) + : gr_sync_block ("complex_to_mag_squared", + gr_make_io_signature (1, 1, sizeof (gr_complex) * vlen), + gr_make_io_signature (1, 1, sizeof (float) * vlen)), + d_vlen(vlen) +{ + const int alignment_multiple = + volk_get_alignment() / sizeof(float); + set_alignment(std::max(1,alignment_multiple)); +} + +int +gr_complex_to_mag_squared::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]; + float *out = (float *) output_items[0]; + int noi = noutput_items * d_vlen; + + if(is_unaligned()) { + volk_32fc_magnitude_squared_32f_u(out, in, noi); + } + else { + volk_32fc_magnitude_squared_32f_a(out, in, noi); + } + + return noutput_items; +} + +// ---------------------------------------------------------------- + +gr_complex_to_arg_sptr +gr_make_complex_to_arg (unsigned int vlen) +{ + return gnuradio::get_initial_sptr(new gr_complex_to_arg (vlen)); +} + +gr_complex_to_arg::gr_complex_to_arg (unsigned int vlen) + : gr_sync_block ("complex_to_arg", + gr_make_io_signature (1, 1, sizeof (gr_complex) * vlen), + gr_make_io_signature (1, 1, sizeof (float) * vlen)), + d_vlen(vlen) +{ + const int alignment_multiple = + volk_get_alignment() / sizeof(float); + set_alignment(std::max(1,alignment_multiple)); +} + +int +gr_complex_to_arg::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]; + float *out = (float *) output_items[0]; + int noi = noutput_items * d_vlen; + + // The fast_atan2f is faster than Volk + for (int i = 0; i < noi; i++){ + // out[i] = std::arg (in[i]); + out[i] = gr_fast_atan2f(in[i]); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_complex_to_xxx.h b/gnuradio-core/src/lib/general/gr_complex_to_xxx.h new file mode 100644 index 000000000..a2f06ea28 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_complex_to_xxx.h @@ -0,0 +1,160 @@ +/* -*- 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_COMPLEX_TO_XXX_H +#define INCLUDED_GR_COMPLEX_TO_XXX_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_complex.h> + +class gr_complex_to_float; +class gr_complex_to_real; +class gr_complex_to_imag; +class gr_complex_to_mag; +class gr_complex_to_mag_squared; +class gr_complex_to_arg; + +typedef boost::shared_ptr<gr_complex_to_float> gr_complex_to_float_sptr; +typedef boost::shared_ptr<gr_complex_to_real> gr_complex_to_real_sptr; +typedef boost::shared_ptr<gr_complex_to_imag> gr_complex_to_imag_sptr; +typedef boost::shared_ptr<gr_complex_to_mag> gr_complex_to_mag_sptr; +typedef boost::shared_ptr<gr_complex_to_mag_squared> gr_complex_to_mag_squared_sptr; +typedef boost::shared_ptr<gr_complex_to_arg> gr_complex_to_arg_sptr; + +GR_CORE_API gr_complex_to_float_sptr gr_make_complex_to_float (unsigned int vlen=1); +GR_CORE_API gr_complex_to_real_sptr gr_make_complex_to_real (unsigned int vlen=1); +GR_CORE_API gr_complex_to_imag_sptr gr_make_complex_to_imag (unsigned int vlen=1); +GR_CORE_API gr_complex_to_mag_sptr gr_make_complex_to_mag (unsigned int vlen=1); +GR_CORE_API gr_complex_to_mag_squared_sptr gr_make_complex_to_mag_squared (unsigned int vlen=1); +GR_CORE_API gr_complex_to_arg_sptr gr_make_complex_to_arg (unsigned int vlen=1); + +/*! + * \brief convert a stream of gr_complex to 1 or 2 streams of float + * \ingroup converter_blk + * \param vlen vector len (default 1) + */ +class GR_CORE_API gr_complex_to_float : public gr_sync_block +{ + friend GR_CORE_API gr_complex_to_float_sptr gr_make_complex_to_float (unsigned int vlen); + gr_complex_to_float (unsigned int vlen); + + unsigned int d_vlen; + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +/*! + * \brief complex in, real out (float) + * \ingroup converter_blk + * \param vlen vector len (default 1) + */ +class GR_CORE_API gr_complex_to_real : public gr_sync_block +{ + friend GR_CORE_API gr_complex_to_real_sptr gr_make_complex_to_real (unsigned int vlen); + gr_complex_to_real (unsigned int vlen); + + unsigned int d_vlen; + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +/*! + * \brief complex in, imaginary out (float) + * \ingroup converter_blk + * \param vlen vector len (default 1) + */ +class GR_CORE_API gr_complex_to_imag : public gr_sync_block +{ + friend GR_CORE_API gr_complex_to_imag_sptr gr_make_complex_to_imag (unsigned int vlen); + gr_complex_to_imag (unsigned int vlen); + + unsigned int d_vlen; + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +/*! + * \brief complex in, magnitude out (float) + * \ingroup converter_blk + * \param vlen vector len (default 1) + */ +class GR_CORE_API gr_complex_to_mag : public gr_sync_block +{ + friend GR_CORE_API gr_complex_to_mag_sptr + gr_make_complex_to_mag (unsigned int vlen); + gr_complex_to_mag (unsigned int vlen); + + unsigned int d_vlen; + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +/*! + * \brief complex in, magnitude squared out (float) + * \ingroup converter_blk + * \param vlen vector len (default 1) + */ +class GR_CORE_API gr_complex_to_mag_squared : public gr_sync_block +{ + friend GR_CORE_API gr_complex_to_mag_squared_sptr gr_make_complex_to_mag_squared (unsigned int vlen); + gr_complex_to_mag_squared (unsigned int vlen); + + unsigned int d_vlen; + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +/*! + * \brief complex in, angle out (float) + * \ingroup converter_blk + * \param vlen vector len (default 1) + */ +class GR_CORE_API gr_complex_to_arg : public gr_sync_block +{ + friend GR_CORE_API gr_complex_to_arg_sptr gr_make_complex_to_arg (unsigned int vlen); + gr_complex_to_arg (unsigned int vlen); + + unsigned int d_vlen; + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_COMPLEX_TO_XXX_H */ diff --git a/gnuradio-core/src/lib/general/gr_complex_to_xxx.i b/gnuradio-core/src/lib/general/gr_complex_to_xxx.i new file mode 100644 index 000000000..372b0e8b5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_complex_to_xxx.i @@ -0,0 +1,64 @@ +/* -*- 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,complex_to_float); +gr_complex_to_float_sptr gr_make_complex_to_float (unsigned int vlen=1); +class gr_complex_to_float : public gr_sync_block +{ + gr_complex_to_float (unsigned int vlen); +}; + +GR_SWIG_BLOCK_MAGIC(gr,complex_to_real); +gr_complex_to_real_sptr gr_make_complex_to_real (unsigned int vlen=1); +class gr_complex_to_real : public gr_sync_block +{ + gr_complex_to_real (unsigned int vlen); +}; + +GR_SWIG_BLOCK_MAGIC(gr,complex_to_imag); +gr_complex_to_imag_sptr gr_make_complex_to_imag (unsigned int vlen=1); +class gr_complex_to_imag : public gr_sync_block +{ + gr_complex_to_imag (unsigned int vlen); +}; + +GR_SWIG_BLOCK_MAGIC(gr,complex_to_mag); +gr_complex_to_mag_sptr gr_make_complex_to_mag (unsigned int vlen=1); +class gr_complex_to_mag : public gr_sync_block +{ + gr_complex_to_mag (unsigned int vlen); +}; + +GR_SWIG_BLOCK_MAGIC(gr,complex_to_mag_squared); +gr_complex_to_mag_squared_sptr gr_make_complex_to_mag_squared (unsigned int vlen=1); +class gr_complex_to_mag_squared : public gr_sync_block +{ + gr_complex_to_mag_squared (unsigned int vlen); +}; + +GR_SWIG_BLOCK_MAGIC(gr,complex_to_arg); +gr_complex_to_arg_sptr gr_make_complex_to_arg (unsigned int vlen=1); +class gr_complex_to_arg : public gr_sync_block +{ + gr_complex_to_arg (unsigned int vlen); +}; + diff --git a/gnuradio-core/src/lib/general/gr_conjugate_cc.cc b/gnuradio-core/src/lib/general/gr_conjugate_cc.cc new file mode 100644 index 000000000..94ac3e162 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_conjugate_cc.cc @@ -0,0 +1,65 @@ +/* -*- 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: this file is machine generated. Edits will be over written + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_conjugate_cc.h> +#include <gr_io_signature.h> +#include <volk/volk.h> + +gr_conjugate_cc_sptr +gr_make_conjugate_cc () +{ + return gnuradio::get_initial_sptr(new gr_conjugate_cc ()); +} + +gr_conjugate_cc::gr_conjugate_cc () + : gr_sync_block ("conjugate_cc", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (gr_complex))) +{ + const int alignment_multiple = + volk_get_alignment() / sizeof(gr_complex); + set_alignment(std::max(1,alignment_multiple)); +} + +int +gr_conjugate_cc::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gr_complex *iptr = (gr_complex *) input_items[0]; + gr_complex *optr = (gr_complex *) output_items[0]; + + if(is_unaligned()) { + volk_32fc_conjugate_32fc_u(optr, iptr, noutput_items); + } + else { + volk_32fc_conjugate_32fc_a(optr, iptr, noutput_items); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_conjugate_cc.h b/gnuradio-core/src/lib/general/gr_conjugate_cc.h new file mode 100644 index 000000000..e0a2af716 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_conjugate_cc.h @@ -0,0 +1,52 @@ +/* -*- 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: this file is machine generated. Edits will be over written + +#ifndef INCLUDED_GR_CONJUGATE_CC_H +#define INCLUDED_GR_CONJUGATE_CC_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_conjugate_cc; +typedef boost::shared_ptr<gr_conjugate_cc> gr_conjugate_cc_sptr; + +GR_CORE_API gr_conjugate_cc_sptr gr_make_conjugate_cc (); + +/*! + * \brief output = complex conjugate of input + * \ingroup math_blk + */ +class GR_CORE_API gr_conjugate_cc : public gr_sync_block +{ + friend GR_CORE_API gr_conjugate_cc_sptr gr_make_conjugate_cc (); + + gr_conjugate_cc (); + + 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_conjugate_cc.i b/gnuradio-core/src/lib/general/gr_conjugate_cc.i new file mode 100644 index 000000000..444ebb1b8 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_conjugate_cc.i @@ -0,0 +1,33 @@ +/* -*- 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: this file is machine generated. Edits will be over written + +GR_SWIG_BLOCK_MAGIC(gr,conjugate_cc) + +gr_conjugate_cc_sptr gr_make_conjugate_cc (); + +class gr_conjugate_cc : public gr_sync_block +{ + private: + gr_conjugate_cc (); +}; diff --git a/gnuradio-core/src/lib/general/gr_constants.cc.in b/gnuradio-core/src/lib/general/gr_constants.cc.in new file mode 100644 index 000000000..b94f254d6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_constants.cc.in @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2009 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. + */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gr_constants.h> + +const std::string +gr_prefix() +{ + return "@prefix@"; +} + +const std::string +gr_sysconfdir() +{ + return "@SYSCONFDIR@"; +} + +const std::string +gr_prefsdir() +{ + return "@GR_PREFSDIR@"; +} + +const std::string +gr_build_date() +{ + return "@BUILD_DATE@"; +} + +const std::string +gr_version() +{ + return "@VERSION@"; +} diff --git a/gnuradio-core/src/lib/general/gr_constants.h b/gnuradio-core/src/lib/general/gr_constants.h new file mode 100644 index 000000000..00ed9463d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_constants.h @@ -0,0 +1,53 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2009 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_CONSTANTS_H +#define INCLUDED_GR_CONSTANTS_H + +#include <gr_core_api.h> +#include <string> + +/*! + * \brief return ./configure --prefix argument. Typically /usr/local + */ +GR_CORE_API const std::string gr_prefix(); + +/*! + * \brief return ./configure --sysconfdir argument. Typically $prefix/etc or /etc + */ +GR_CORE_API const std::string gr_sysconfdir(); + +/*! + * \brief return preferences file directory. Typically $sysconfdir/etc/conf.d + */ +GR_CORE_API const std::string gr_prefsdir(); + +/*! + * \brief return date/time of build, as set when 'bootstrap' is run + */ +GR_CORE_API const std::string gr_build_date(); + +/*! + * \brief return version string defined in configure.ac + */ +GR_CORE_API const std::string gr_version(); + +#endif /* INCLUDED_GR_CONSTANTS_H */ diff --git a/gnuradio-core/src/lib/general/gr_constants.i b/gnuradio-core/src/lib/general/gr_constants.i new file mode 100644 index 000000000..a5aef1492 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_constants.i @@ -0,0 +1,13 @@ +/* -*- c++ -*- */ + +%rename(prefix) gr_prefix; +%rename(sysconfdir) gr_sysconfdir; +%rename(prefsdir) gr_prefsdir; +%rename(build_date) gr_build_date; +%rename(version) gr_version; + +const std::string gr_prefix(); +const std::string gr_sysconfdir(); +const std::string gr_prefsdir(); +const std::string gr_build_date(); +const std::string gr_version(); diff --git a/gnuradio-core/src/lib/general/gr_copy.cc b/gnuradio-core/src/lib/general/gr_copy.cc new file mode 100644 index 000000000..0a6f721f9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_copy.cc @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2009 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_copy.h> +#include <gr_io_signature.h> +#include <string.h> + +gr_copy_sptr +gr_make_copy(size_t itemsize) +{ + return gnuradio::get_initial_sptr(new gr_copy(itemsize)); +} + +gr_copy::gr_copy(size_t itemsize) + : gr_block ("copy", + gr_make_io_signature (1, 1, itemsize), + gr_make_io_signature (1, 1, itemsize)), + d_itemsize(itemsize), + d_enabled(true) +{ +} + +bool +gr_copy::check_topology(int ninputs, int noutputs) +{ + return ninputs == noutputs; +} + +int +gr_copy::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const uint8_t *in = (const uint8_t *) input_items[0]; + uint8_t *out = (uint8_t *) output_items[0]; + + int n = std::min<int>(ninput_items[0], noutput_items); + int j = 0; + + if (d_enabled) { + memcpy(out, in, n*d_itemsize); + j = n; + } + + consume_each(n); + return j; +} diff --git a/gnuradio-core/src/lib/general/gr_copy.h b/gnuradio-core/src/lib/general/gr_copy.h new file mode 100644 index 000000000..b0769fa2b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_copy.h @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2009 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_COPY_H +#define INCLUDED_GR_COPY_H + +#include <gr_core_api.h> +#include <gr_block.h> + +class gr_copy; +typedef boost::shared_ptr<gr_copy> gr_copy_sptr; + +GR_CORE_API gr_copy_sptr gr_make_copy(size_t itemsize); + +/*! + * \brief output[i] = input[i] + * \ingroup misc_blk + * + * When enabled (default), this block copies its input to its output. + * When disabled, this block drops its input on the floor. + * + */ +class GR_CORE_API gr_copy : public gr_block +{ + size_t d_itemsize; + bool d_enabled; + + friend GR_CORE_API gr_copy_sptr gr_make_copy(size_t itemsize); + gr_copy(size_t itemsize); + + public: + + bool check_topology(int ninputs, int noutputs); + + void set_enabled(bool enable) { d_enabled = enable; } + bool enabled() const { return d_enabled;} + + 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 diff --git a/gnuradio-core/src/lib/general/gr_copy.i b/gnuradio-core/src/lib/general/gr_copy.i new file mode 100644 index 000000000..12ddce6aa --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_copy.i @@ -0,0 +1,36 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2009 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,copy) + +gr_copy_sptr gr_make_copy(size_t itemsize); + +class gr_copy : public gr_block +{ + private: + gr_copy(size_t itemsize); + +public: + + void set_enabled(bool enabled); + bool enabled(); +}; diff --git a/gnuradio-core/src/lib/general/gr_core_api.h b/gnuradio-core/src/lib/general/gr_core_api.h new file mode 100644 index 000000000..74c802857 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_core_api.h @@ -0,0 +1,33 @@ +/* + * Copyright 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. + */ + +#ifndef INCLUDED_GR_CORE_API_H +#define INCLUDED_GR_CORE_API_H + +#include <gruel/attributes.h> + +#ifdef gnuradio_core_EXPORTS +# define GR_CORE_API __GR_ATTR_EXPORT +#else +# define GR_CORE_API __GR_ATTR_IMPORT +#endif + +#endif /* INCLUDED_GR_CORE_API_H */ 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 new file mode 100644 index 000000000..73ded3c8b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_correlate_access_code_tag_bb.cc @@ -0,0 +1,129 @@ +/* -*- 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 new file mode 100644 index 000000000..345d3004a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_correlate_access_code_tag_bb.h @@ -0,0 +1,87 @@ +/* -*- 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 new file mode 100644 index 000000000..f7ca4bea7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_correlate_access_code_tag_bb.i @@ -0,0 +1,60 @@ +/* -*- 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_count_bits.cc b/gnuradio-core/src/lib/general/gr_count_bits.cc new file mode 100644 index 000000000..4776fe61a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_count_bits.cc @@ -0,0 +1,93 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 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 <gr_count_bits.h> + +/* + * these are slow and obvious. If you need something faster, fix these + */ + +// return number of set bits in the low 8 bits of x +unsigned int +gr_count_bits8 (unsigned int x) +{ + int count = 0; + + for (int i = 0; i < 8; i++) + if (x & (1 << i)) + count++; + + return count; +} + +// return number of set bits in the low 16 bits of x +unsigned int +gr_count_bits16 (unsigned int x) +{ + int count = 0; + + for (int i = 0; i < 16; i++) + if (x & (1 << i)) + count++; + + return count; + +} + + +#if 0 // slow and obvious + +// return number of set bits in the low 32 bits of x +unsigned int +gr_count_bits32 (unsigned int x) +{ + int count = 0; + + for (int i = 0; i < 32; i++) + if (x & (1 << i)) + count++; + + return count; +} + +#else // fast and not so obvious + +// return number of set bits in the low 32 bits of x +unsigned int +gr_count_bits32 (unsigned int x) +{ + unsigned res = (x & 0x55555555) + ((x >> 1) & 0x55555555); + res = (res & 0x33333333) + ((res >> 2) & 0x33333333); + res = (res & 0x0F0F0F0F) + ((res >> 4) & 0x0F0F0F0F); + res = (res & 0x00FF00FF) + ((res >> 8) & 0x00FF00FF); + return (res & 0x0000FFFF) + ((res >> 16) & 0x0000FFFF); +} + +#endif + + +// return number of set bits in the low 64 bits of x +unsigned int +gr_count_bits64 (unsigned long long x) +{ + return gr_count_bits32((x >> 32) & 0xffffffff) + gr_count_bits32(x & 0xffffffff); +} diff --git a/gnuradio-core/src/lib/general/gr_count_bits.h b/gnuradio-core/src/lib/general/gr_count_bits.h new file mode 100644 index 000000000..76d0173eb --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_count_bits.h @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 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 _GR_COUNT_BITS_H_ +#define _GR_COUNT_BITS_H_ + +#include <gr_core_api.h> + +GR_CORE_API unsigned int gr_count_bits8(unsigned int x); // return number of set bits in the low 8 bits of x +GR_CORE_API unsigned int gr_count_bits16(unsigned int x); // return number of set bits in the low 16 bits of x +GR_CORE_API unsigned int gr_count_bits32(unsigned int x); // return number of set bits in the low 32 bits of x +GR_CORE_API unsigned int gr_count_bits64(unsigned long long int x); + +#endif /* _GR_COUNT_BITS_H_ */ diff --git a/gnuradio-core/src/lib/general/gr_cpfsk_bc.cc b/gnuradio-core/src/lib/general/gr_cpfsk_bc.cc new file mode 100644 index 000000000..24f0edd5c --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_cpfsk_bc.cc @@ -0,0 +1,78 @@ +/* -*- 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_cpfsk_bc.h> +#include <gr_io_signature.h> +#include <gr_expj.h> + +#define M_TWOPI (2*M_PI) + +gr_cpfsk_bc_sptr +gr_make_cpfsk_bc(float k, float ampl, int samples_per_sym) +{ + return gnuradio::get_initial_sptr(new gr_cpfsk_bc(k, ampl, samples_per_sym)); +} + +gr_cpfsk_bc::gr_cpfsk_bc(float k, float ampl, int samples_per_sym) + : gr_sync_interpolator("cpfsk_bc", + gr_make_io_signature(1, 1, sizeof(char)), + gr_make_io_signature(1, 1, sizeof(gr_complex)), + samples_per_sym) +{ + d_samples_per_sym = samples_per_sym; + d_freq = k*M_PI/samples_per_sym; + d_ampl = ampl; + d_phase = 0.0; +} + +gr_cpfsk_bc::~gr_cpfsk_bc() +{ +} + +int +gr_cpfsk_bc::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]; + gr_complex *out = (gr_complex *)output_items[0]; + + for (int i = 0; i < noutput_items/d_samples_per_sym; i++) { + for (int j = 0; j < d_samples_per_sym; j++) { + if (in[i] == 1) + d_phase += d_freq; + else + d_phase -= d_freq; + + while (d_phase > M_TWOPI) + d_phase -= M_TWOPI; + while (d_phase < -M_TWOPI) + d_phase += M_TWOPI; + + *out++ = gr_expj(d_phase)*d_ampl; + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_cpfsk_bc.h b/gnuradio-core/src/lib/general/gr_cpfsk_bc.h new file mode 100644 index 000000000..6ad2774b3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_cpfsk_bc.h @@ -0,0 +1,64 @@ +/* -*- 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_CPFSK_BC_H +#define INCLUDED_GR_CPFSK_BC_H + +#include <gr_core_api.h> +#include <gr_sync_interpolator.h> + +class gr_cpfsk_bc; + +typedef boost::shared_ptr<gr_cpfsk_bc> gr_cpfsk_bc_sptr; + +GR_CORE_API gr_cpfsk_bc_sptr gr_make_cpfsk_bc(float k, float ampl, int samples_per_sym); + +/*! + * \brief Perform continuous phase 2-level frequency shift keying modulation + * on an input stream of unpacked bits. + * \ingroup modulation_blk + * + * \param k modulation index + * \param ampl output amplitude + * \param samples_per_sym number of output samples per input bit + */ + +class GR_CORE_API gr_cpfsk_bc : public gr_sync_interpolator +{ +private: + friend GR_CORE_API gr_cpfsk_bc_sptr gr_make_cpfsk_bc(float k, float ampl, int samples_per_sym); + + gr_cpfsk_bc(float k, float ampl, int samples_per_sym); + + int d_samples_per_sym; // Samples per symbol, square pulse + float d_freq; // Modulation index*pi/samples_per_sym + float d_ampl; // Output amplitude + float d_phase; // Current phase + + public: + ~gr_cpfsk_bc(); + + void set_amplitude(float amplitude) { d_ampl = amplitude; } + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_CPFSK_BC_H */ diff --git a/gnuradio-core/src/lib/general/gr_cpfsk_bc.i b/gnuradio-core/src/lib/general/gr_cpfsk_bc.i new file mode 100644 index 000000000..b86dfb81b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_cpfsk_bc.i @@ -0,0 +1,34 @@ +/* -*- 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,cpfsk_bc); + +gr_cpfsk_bc_sptr gr_make_cpfsk_bc(float k, float ampl, int samples_per_sym); + +class gr_cpfsk_bc : public gr_sync_interpolator +{ +private: + gr_cpfsk_bc(float k, float ampl, int samples_per_sym); + +public: + void set_amplitude(float amplitude); +}; diff --git a/gnuradio-core/src/lib/general/gr_cpm.cc b/gnuradio-core/src/lib/general/gr_cpm.cc new file mode 100644 index 000000000..32ce6502d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_cpm.cc @@ -0,0 +1,218 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + +// Calculate the taps for the CPM phase responses + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <cmath> +#include <cfloat> +#include <gr_cpm.h> + +//gives us erf on compilers without it +#include <boost/math/special_functions/erf.hpp> +namespace bm = boost::math; + +#ifndef M_TWOPI +# define M_TWOPI (2*M_PI) +#endif + +//! Normalised sinc function, sinc(x)=sin(pi*x)/pi*x +inline double +sinc(double x) +{ + if (x == 0) { + return 1.0; + } + + return sin(M_PI * x) / (M_PI * x); +} + + +//! Taps for L-RC CPM (Raised cosine of length L symbols) +std::vector<float> +generate_cpm_lrc_taps(unsigned samples_per_sym, unsigned L) +{ + std::vector<float> taps(samples_per_sym * L, 1.0/L/samples_per_sym); + for (unsigned i = 0; i < samples_per_sym * L; i++) { + taps[i] *= 1 - cos(M_TWOPI * i / L / samples_per_sym); + } + + return taps; +} + + +/*! Taps for L-SRC CPM (Spectral raised cosine of length L symbols). + * + * L-SRC has a time-continuous phase response function of + * + * g(t) = 1/LT * sinc(2t/LT) * cos(beta * 2pi t / LT) / (1 - (4beta / LT * t)^2) + * + * which is the Fourier transform of a cos-rolloff function with rolloff + * beta, and looks like a sinc-function, multiplied with a rolloff term. + * We return the main lobe of the sinc, i.e., everything between the + * zero crossings. + * The time-discrete IR is thus + * + * g(k) = 1/Ls * sinc(2k/Ls) * cos(beta * pi k / Ls) / (1 - (4beta / Ls * k)^2) + * where k = 0...Ls-1 + * and s = samples per symbol. + */ +std::vector<float> +generate_cpm_lsrc_taps(unsigned samples_per_sym, unsigned L, double beta) +{ + double Ls = (double) L * samples_per_sym; + std::vector<double> taps_d(L * samples_per_sym, 0.0); + std::vector<float> taps(L * samples_per_sym, 0.0); + + double sum = 0; + for (unsigned i = 0; i < samples_per_sym * L; i++) { + double k = i - Ls/2; // Causal to acausal + + taps_d[i] = 1.0 / Ls * sinc(2.0 * k / Ls); + + // For k = +/-Ls/4*beta, the rolloff term's cos-function becomes zero + // and the whole thing converges to PI/4 (to prove this, use de + // l'hopital's rule). + if (fabs(fabs(k) - Ls/4/beta) < 2*DBL_EPSILON) { + taps_d[i] *= M_PI_4; + } else { + double tmp = 4.0 * beta * k / Ls; + taps_d[i] *= cos(beta * M_TWOPI * k / Ls) / (1 - tmp * tmp); + } + sum += taps_d[i]; + } + for (unsigned i = 0; i < samples_per_sym * L; i++) { + taps[i] = (float) taps_d[i] / sum; + } + + return taps; +} + + +//! Taps for L-REC CPM (Rectangular pulse shape of length L symbols) +std::vector<float> +generate_cpm_lrec_taps(unsigned samples_per_sym, unsigned L) +{ + return std::vector<float>(samples_per_sym * L, 1.0/L/samples_per_sym); +} + + +//! Helper function for TFM +double tfm_g0(double k, double sps) +{ + if (fabs(k) < 2 * DBL_EPSILON) { + return 1.145393004159143; // 1 + pi^2/48 / sqrt(2) + } + + const double pi2_24 = 0.411233516712057; // pi^2/24 + double f = M_PI * k / sps; + return sinc(k/sps) - pi2_24 * (2 * sin(f) - 2*f*cos(f) - f*f*sin(f)) / (f*f*f); +} + + +//! Taps for TFM CPM (Tamed frequency modulation) +// +// See [2, Chapter 2.7.2]. +// +// [2]: Anderson, Aulin and Sundberg; Digital Phase Modulation +std::vector<float> +generate_cpm_tfm_taps(unsigned sps, unsigned L) +{ + unsigned causal_shift = sps * L / 2; + std::vector<double> taps_d(sps * L, 0.0); + std::vector<float> taps(sps * L, 0.0); + + double sum = 0; + for (unsigned i = 0; i < sps * L; i++) { + double k = (double)(((int)i) - ((int)causal_shift)); // Causal to acausal + + taps_d[i] = tfm_g0(k - sps, sps) + + 2 * tfm_g0(k, sps) + + tfm_g0(k + sps, sps); + sum += taps_d[i]; + } + for (unsigned i = 0; i < sps * L; i++) { + taps[i] = (float) taps_d[i] / sum; + } + + return taps; +} + + +//! Taps for Gaussian CPM. Phase response is truncated after \p L symbols. +// \p bt sets the 3dB-time-bandwidth product. +// +// Note: for h = 0.5, this is the phase response for GMSK. +// +// This C99-compatible formula for the taps is taken straight +// from [1, Chapter 9.2.3]. +// A version in Q-notation can be found in [2, Chapter 2.7.2]. +// +// [1]: Karl-Dirk Kammeyer; Nachrichtenübertragung, 4th Edition. +// [2]: Anderson, Aulin and Sundberg; Digital Phase Modulation +// +std::vector<float> +generate_cpm_gaussian_taps(unsigned samples_per_sym, unsigned L, double bt) +{ + double Ls = (double) L * samples_per_sym; + std::vector<double> taps_d(L * samples_per_sym, 0.0); + std::vector<float> taps(L * samples_per_sym, 0.0); + + // alpha = sqrt(2/ln(2)) * pi * BT + double alpha = 5.336446256636997 * bt; + for (unsigned i = 0; i < samples_per_sym * L; i++) { + double k = i - Ls/2; // Causal to acausal + taps_d[i] = (bm::erf(alpha * (k / samples_per_sym + 0.5)) - + bm::erf(alpha * (k / samples_per_sym - 0.5))) + * 0.5 / samples_per_sym; + taps[i] = (float) taps_d[i]; + } + + return taps; +} + + +std::vector<float> +gr_cpm::phase_response(cpm_type type, unsigned samples_per_sym, unsigned L, double beta) +{ + switch (type) { + case LRC: + return generate_cpm_lrc_taps(samples_per_sym, L); + + case LSRC: + return generate_cpm_lsrc_taps(samples_per_sym, L, beta); + + case LREC: + return generate_cpm_lrec_taps(samples_per_sym, L); + + case TFM: + return generate_cpm_tfm_taps(samples_per_sym, L); + + case GAUSSIAN: + return generate_cpm_gaussian_taps(samples_per_sym, L, beta); + + default: + return generate_cpm_lrec_taps(samples_per_sym, 1); + } +} + diff --git a/gnuradio-core/src/lib/general/gr_cpm.h b/gnuradio-core/src/lib/general/gr_cpm.h new file mode 100644 index 000000000..ef2ff8414 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_cpm.h @@ -0,0 +1,81 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + + +#ifndef INCLUDED_GR_CPM_H +#define INCLUDED_GR_CPM_H + +#include <gr_core_api.h> +#include <vector> + +class GR_CORE_API gr_cpm +{ + public: + enum cpm_type { + LRC, + LSRC, + LREC, + TFM, + GAUSSIAN, + GENERIC = 999 + }; + + /*! \brief Return the taps for an interpolating FIR filter (gr_interp_fir_filter_fff). + * + * These taps represent the phase response \f$g(k)\f$ for use in a CPM modulator, + * see also gr_cpmmod_bc. + * + * \param type The CPM type (Rectangular, Raised Cosine, Spectral Raised Cosine, + * Tamed FM or Gaussian). + * \param samples_per_sym Samples per symbol. + * \param L The length of the phase response in symbols. + * \param beta For Spectral Raised Cosine, this is the rolloff factor. For Gaussian + * phase responses, this the 3dB-time-bandwidth product. For all other + * cases, it is ignored. + * + * Output: returns a vector of length \a K = \p samples_per_sym x \p L. + * This can be used directly in an interpolating FIR filter such as + * gr_interp_fir_filter_fff with interpolation factor \p samples_per_sym. + * + * All phase responses are normalised s.t. \f$ \sum_{k=0}^{K-1} g(k) = 1\f$; this will cause + * a maximum phase change of \f$ h \cdot \pi\f$ between two symbols, where \a h is the + * modulation index. + * + * The following phase responses can be generated: + * - LREC: Rectangular phase response. + * - LRC: Raised cosine phase response, looks like 1 - cos(x). + * - LSRC: Spectral raised cosine. This requires a rolloff factor beta. + * The phase response is the Fourier transform of raised cosine + * function. + * - TFM: Tamed frequency modulation. This scheme minimizes phase change for + * rapidly varying input symbols. + * - GAUSSIAN: A Gaussian phase response. For a modulation index h = 1/2, this + * results in GMSK. + * + * A short description of all these phase responses can be found in [1]. + * + * [1]: Anderson, Aulin and Sundberg; Digital Phase Modulation + */ + static std::vector<float> + phase_response(cpm_type type, unsigned samples_per_sym, unsigned L, double beta=0.3); +}; + +#endif /* INCLUDED_GR_CPM_H */ + diff --git a/gnuradio-core/src/lib/general/gr_cpm.i b/gnuradio-core/src/lib/general/gr_cpm.i new file mode 100644 index 000000000..6c077687d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_cpm.i @@ -0,0 +1,40 @@ +/* -*- C++ -*- */ +/* + * Copyright 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. + */ + +%rename(cpm) gr_cpm; + +class gr_cpm +{ + public: + enum cpm_type { + LRC, + LSRC, + LREC, + TFM, + GAUSSIAN, + GENERIC = 999 + }; + + static std::vector<float> + phase_response(cpm_type type, unsigned samples_per_sym, unsigned L, double beta=0.3); +}; + diff --git a/gnuradio-core/src/lib/general/gr_ctcss_squelch_ff.cc b/gnuradio-core/src/lib/general/gr_ctcss_squelch_ff.cc new file mode 100644 index 000000000..d31763a6b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ctcss_squelch_ff.cc @@ -0,0 +1,112 @@ +/* -*- 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_ctcss_squelch_ff.h> + +static float ctcss_tones[] = { + 67.0, 71.9, 74.4, 77.0, 79.7, 82.5, 85.4, 88.5, 91.5, 94.8, + 97.4, 100.0, 103.5, 107.2, 110.9, 114.8, 118.8, 123.0, 127.3, 131.8, + 136.5, 141.3, 146.2, 151.4, 156.7, 162.2, 167.9, 173.8, 179.9, 186.2, + 192.8, 203.5, 210.7, 218.1, 225.7, 233.6, 241.8, 250.3 +}; + +static int max_tone_index = 37; + +gr_ctcss_squelch_ff_sptr +gr_make_ctcss_squelch_ff(int rate, float freq, float level, int len, int ramp, bool gate) +{ + return gnuradio::get_initial_sptr(new gr_ctcss_squelch_ff(rate, freq, level, len, ramp, gate)); +} + +int gr_ctcss_squelch_ff::find_tone(float freq) +{ + for (int i = 0; i <= max_tone_index; i++) + if (ctcss_tones[i] == freq) // FIXME: make almost equal + return i; + + return -1; +} + +gr_ctcss_squelch_ff::gr_ctcss_squelch_ff(int rate, float freq, float level, int len, int ramp, bool gate) : + gr_squelch_base_ff("ctcss_squelch_ff", ramp, gate) +{ + d_freq = freq; + d_level = level; + + // Default is 100 ms detection time + if (len == 0) + d_len = (int)(rate/10.0); + else + d_len = len; + + int i = find_tone(freq); + + // Non-standard tones or edge tones get 2% guard band, otherwise + // guards are set at adjacent ctcss tone frequencies + float f_l, f_r; + if (i == -1 || i == 0) + f_l = freq*0.98; + else + f_l = ctcss_tones[i-1]; + + if (i == -1 || i == max_tone_index) + f_r = freq*1.02; + else + f_r = ctcss_tones[i+1]; + + d_goertzel_l = gri_goertzel(rate, d_len, f_l); + d_goertzel_c = gri_goertzel(rate, d_len, freq); + d_goertzel_r = gri_goertzel(rate, d_len, f_r); + + d_mute = true; +} + +std::vector<float> gr_ctcss_squelch_ff::squelch_range() const +{ + std::vector<float> r(3); + r[0] = 0.0; + r[1] = 1.0; + r[2] = (r[1]-r[0])/100; // step size + + return r; +} + +void gr_ctcss_squelch_ff::update_state(const float &in) +{ + d_goertzel_l.input(in); + d_goertzel_c.input(in); + d_goertzel_r.input(in); + + float d_out_l, d_out_c, d_out_r; + if (d_goertzel_c.ready()) { + d_out_l = abs(d_goertzel_l.output()); + d_out_c = abs(d_goertzel_c.output()); + d_out_r = abs(d_goertzel_r.output()); + + //printf("d_out_l=%f d_out_c=%f d_out_r=%f\n", d_out_l, d_out_c, d_out_r); + d_mute = (d_out_c < d_level || d_out_c < d_out_l || d_out_c < d_out_r); + } +} diff --git a/gnuradio-core/src/lib/general/gr_ctcss_squelch_ff.h b/gnuradio-core/src/lib/general/gr_ctcss_squelch_ff.h new file mode 100644 index 000000000..ef3d13ba7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ctcss_squelch_ff.h @@ -0,0 +1,68 @@ +/* -*- 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_CTCSS_SQUELCH_FF_H +#define INCLUDED_GR_CTCSS_SQUELCH_FF_H + +#include <gr_core_api.h> +#include <gr_squelch_base_ff.h> +#include <gri_goertzel.h> + +class gr_ctcss_squelch_ff; +typedef boost::shared_ptr<gr_ctcss_squelch_ff> gr_ctcss_squelch_ff_sptr; + +GR_CORE_API gr_ctcss_squelch_ff_sptr +gr_make_ctcss_squelch_ff(int rate, float freq, float level=0.01, int len=0, int ramp=0, bool gate=false); + +/*! + * \brief gate or zero output if ctcss tone not present + * \ingroup level_blk + */ +class GR_CORE_API gr_ctcss_squelch_ff : public gr_squelch_base_ff +{ +private: + float d_freq; + float d_level; + int d_len; + bool d_mute; + + gri_goertzel d_goertzel_l; + gri_goertzel d_goertzel_c; + gri_goertzel d_goertzel_r; + + friend GR_CORE_API gr_ctcss_squelch_ff_sptr gr_make_ctcss_squelch_ff(int rate, float freq, float level, int len, int ramp, bool gate); + gr_ctcss_squelch_ff(int rate, float freq, float level, int len, int ramp, bool gate); + + int find_tone(float freq); + +protected: + virtual void update_state(const float &in); + virtual bool mute() const { return d_mute; } + +public: + std::vector<float> squelch_range() const; + float level() const { return d_level; } + void set_level(float level) { d_level = level; } + int len() const { return d_len; } +}; + +#endif /* INCLUDED_GR_CTCSS_SQUELCH_FF_H */ diff --git a/gnuradio-core/src/lib/general/gr_ctcss_squelch_ff.i b/gnuradio-core/src/lib/general/gr_ctcss_squelch_ff.i new file mode 100644 index 000000000..b160c5dfd --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ctcss_squelch_ff.i @@ -0,0 +1,39 @@ +/* -*- 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,ctcss_squelch_ff); + +%include gr_squelch_base_ff.i + +gr_ctcss_squelch_ff_sptr +gr_make_ctcss_squelch_ff(int rate, float freq, float level=0.01, int len=0, int ramp=0, bool gate=false); + +class gr_ctcss_squelch_ff : public gr_squelch_base_ff +{ + gr_ctcss_squelch_ff(int rate, float freq, float level, int len, int ramp, bool gate); + +public: + std::vector<float> squelch_range() const; + float level() const { return d_level; } + void set_level(float level) { d_level = level; } + int len() const { return d_len; } +}; diff --git a/gnuradio-core/src/lib/general/gr_decode_ccsds_27_fb.cc b/gnuradio-core/src/lib/general/gr_decode_ccsds_27_fb.cc new file mode 100644 index 000000000..319aceeaa --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_decode_ccsds_27_fb.cc @@ -0,0 +1,86 @@ +/* -*- 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_decode_ccsds_27_fb.h> +#include <gr_io_signature.h> + +gr_decode_ccsds_27_fb_sptr +gr_make_decode_ccsds_27_fb() +{ + return gnuradio::get_initial_sptr(new gr_decode_ccsds_27_fb()); +} + +gr_decode_ccsds_27_fb::gr_decode_ccsds_27_fb() + : gr_sync_decimator("decode_ccsds_27_fb", + gr_make_io_signature(1, 1, sizeof(float)), + gr_make_io_signature(1, 1, sizeof(char)), + 2*8) // Rate 1/2 code, unpacked to packed translation +{ + float RATE = 0.5; + float ebn0 = 12.0; + float esn0 = RATE*pow(10.0, ebn0/10.0); + + gen_met(d_mettab, 100, esn0, 0.0, 256); + viterbi_chunks_init(d_state0); +} + +gr_decode_ccsds_27_fb::~gr_decode_ccsds_27_fb() +{ +} + +int +gr_decode_ccsds_27_fb::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]; + unsigned char *out = (unsigned char *)output_items[0]; + + for (int i = 0; i < noutput_items*16; i++) { + // Translate and clip [-1.0..1.0] to [28..228] + float sample = in[i]*100.0+128.0; + if (sample > 255.0) + sample = 255.0; + else if (sample < 0.0) + sample = 0.0; + unsigned char sym = (unsigned char)(floor(sample)); + + d_viterbi_in[d_count % 4] = sym; + if ((d_count % 4) == 3) { + // Every fourth symbol, perform butterfly operation + viterbi_butterfly2(d_viterbi_in, d_mettab, d_state0, d_state1); + + // Every sixteenth symbol, read out a byte + if (d_count % 16 == 11) { + // long metric = + viterbi_get_output(d_state0, out++); + // printf("%li\n", *(out-1), metric); + } + } + + d_count++; + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_decode_ccsds_27_fb.h b/gnuradio-core/src/lib/general/gr_decode_ccsds_27_fb.h new file mode 100644 index 000000000..df8e6f449 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_decode_ccsds_27_fb.h @@ -0,0 +1,78 @@ +/* -*- 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_DECODE_CCSDS_27_FB_H +#define INCLUDED_GR_DECODE_CCSDS_27_FB_H + +#include <gr_core_api.h> +#include <gr_sync_decimator.h> + +extern "C" { +#include <viterbi.h> +} + +class gr_decode_ccsds_27_fb; + +typedef boost::shared_ptr<gr_decode_ccsds_27_fb> gr_decode_ccsds_27_fb_sptr; + +GR_CORE_API gr_decode_ccsds_27_fb_sptr gr_make_decode_ccsds_27_fb(); + +/*! \brief A rate 1/2, k=7 convolutional decoder for the CCSDS standard + * \ingroup ecc + * + * This block performs soft-decision convolutional decoding using the Viterbi + * algorithm. + * + * The input is a stream of (possibly noise corrupted) floating point values + * nominally spanning [-1.0, 1.0], representing the encoded channel symbols + * 0 (-1.0) and 1 (1.0), with erased symbols at 0.0. + * + * The output is MSB first packed bytes of decoded values. + * + * As a rate 1/2 code, there will be one output byte for every 16 input symbols. + * + * This block is designed for continuous data streaming, not packetized data. + * The first 32 bits out will be zeroes, with the output delayed four bytes + * from the corresponding inputs. + */ + +class GR_CORE_API gr_decode_ccsds_27_fb : public gr_sync_decimator +{ +private: + friend GR_CORE_API gr_decode_ccsds_27_fb_sptr gr_make_decode_ccsds_27_fb(); + + gr_decode_ccsds_27_fb(); + + // Viterbi state + int d_mettab[2][256]; + struct viterbi_state d_state0[64]; + struct viterbi_state d_state1[64]; + unsigned char d_viterbi_in[16]; + + int d_count; + +public: + ~gr_decode_ccsds_27_fb(); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_DECODE_CCSDS_27_FB_H */ diff --git a/gnuradio-core/src/lib/general/gr_decode_ccsds_27_fb.i b/gnuradio-core/src/lib/general/gr_decode_ccsds_27_fb.i new file mode 100644 index 000000000..f2e13b593 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_decode_ccsds_27_fb.i @@ -0,0 +1,31 @@ +/* -*- 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,decode_ccsds_27_fb); + +gr_decode_ccsds_27_fb_sptr gr_make_decode_ccsds_27_fb (); + +class gr_decode_ccsds_27_fb : public gr_sync_decimator +{ +private: + gr_decode_ccsds_27_fb(); +}; diff --git a/gnuradio-core/src/lib/general/gr_deinterleave.cc b/gnuradio-core/src/lib/general/gr_deinterleave.cc new file mode 100644 index 000000000..e22db60c1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_deinterleave.cc @@ -0,0 +1,78 @@ +/* -*- 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_deinterleave.h> +#include <gr_io_signature.h> +#include <string.h> + + +gr_deinterleave_sptr +gr_make_deinterleave (size_t itemsize) +{ + return gnuradio::get_initial_sptr(new gr_deinterleave (itemsize)); +} + +gr_deinterleave::gr_deinterleave (size_t itemsize) + : gr_sync_decimator ("deinterleave", + gr_make_io_signature (1, 1, itemsize), + gr_make_io_signature (1, gr_io_signature::IO_INFINITE, itemsize), + 1), + d_itemsize (itemsize) +{ +} + +gr_deinterleave::~gr_deinterleave () +{ + // NOP +} + +bool +gr_deinterleave::check_topology (int ninputs, int noutputs) +{ + set_decimation (noutputs); + return true; +} + +int +gr_deinterleave::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + size_t nchan = output_items.size (); + size_t itemsize = d_itemsize; + const char *in = (const char *) input_items[0]; + char **out = (char **) &output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + for (unsigned int n = 0; n < nchan; n++){ + memcpy (out[n], in, itemsize); + out[n] += itemsize; + in += itemsize; + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_deinterleave.h b/gnuradio-core/src/lib/general/gr_deinterleave.h new file mode 100644 index 000000000..0eecc44d1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_deinterleave.h @@ -0,0 +1,57 @@ +/* -*- 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_DEINTERLEAVE_H +#define INCLUDED_GR_DEINTERLEAVE_H + +#include <gr_core_api.h> +#include <gr_sync_decimator.h> + +class gr_deinterleave; +typedef boost::shared_ptr<gr_deinterleave> gr_deinterleave_sptr; + +GR_CORE_API gr_deinterleave_sptr gr_make_deinterleave (size_t itemsize); + +/*! + * \brief deinterleave a single input into N outputs + * \ingroup slicedice_blk + */ +class GR_CORE_API gr_deinterleave : public gr_sync_decimator +{ + friend GR_CORE_API gr_deinterleave_sptr gr_make_deinterleave (size_t itemsize); + + size_t d_itemsize; + + gr_deinterleave (size_t itemsize); + +public: + ~gr_deinterleave (); + + 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); + +}; + +#endif /* INCLUDED_GR_DEINTERLEAVE_H */ diff --git a/gnuradio-core/src/lib/general/gr_deinterleave.i b/gnuradio-core/src/lib/general/gr_deinterleave.i new file mode 100644 index 000000000..a70ce6c52 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_deinterleave.i @@ -0,0 +1,30 @@ +/* -*- 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,deinterleave) + +gr_deinterleave_sptr gr_make_deinterleave (size_t itemsize); + +class gr_deinterleave : public gr_sync_decimator +{ + gr_deinterleave (size_t itemsize); +}; diff --git a/gnuradio-core/src/lib/general/gr_delay.cc b/gnuradio-core/src/lib/general/gr_delay.cc new file mode 100644 index 000000000..8f728948d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_delay.cc @@ -0,0 +1,129 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,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 <gr_delay.h> +#include <gr_io_signature.h> +#include <string.h> + +gr_delay_sptr +gr_make_delay (size_t itemsize, int delay) +{ + return gnuradio::get_initial_sptr(new gr_delay (itemsize, delay)); +} + +gr_delay::gr_delay (size_t itemsize, int delay) + : gr_block ("delay", + gr_make_io_signature (1, -1, itemsize), + gr_make_io_signature (1, -1, itemsize)), + d_itemsize(itemsize) +{ + set_delay(delay); + d_delta = 0; +} + +void +gr_delay::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + // make sure all inputs have noutput_items available + unsigned ninputs = ninput_items_required.size (); + for (unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = noutput_items; +} + +void +gr_delay::set_delay (int d) +{ + // only set a new delta if there is a change in the delay; this + // protects from quickly-repeated calls to this function that would + // end with d_delta=0. + if(d != delay()) { + gruel::scoped_lock l(d_mutex_delay); + int old = delay(); + set_history(d+1); + d_delta += delay() - old; + } +} + +int +gr_delay::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gruel::scoped_lock l(d_mutex_delay); + assert(input_items.size() == output_items.size()); + + const char *iptr; + char *optr; + int cons, ret; + + // No change in delay; just memcpy ins to outs + if(d_delta == 0) { + for(size_t i = 0; i < input_items.size(); i++) { + iptr = (const char *) input_items[i]; + optr = (char *) output_items[i]; + std::memcpy(optr, iptr, noutput_items*d_itemsize); + } + cons = noutput_items; + ret = noutput_items; + } + + // Skip over d_delta items on the input + else if(d_delta < 0) { + int n_to_copy, n_adj; + int delta = -d_delta; + n_to_copy = std::max(0, noutput_items-delta); + n_adj = std::min(delta, noutput_items); + for(size_t i = 0; i < input_items.size(); i++) { + iptr = (const char *) input_items[i]; + optr = (char *) output_items[i]; + std::memcpy(optr, iptr+delta*d_itemsize, n_to_copy*d_itemsize); + } + cons = noutput_items; + ret = n_to_copy; + delta -= n_adj; + d_delta = -delta; + } + + //produce but not consume (inserts zeros) + else { // d_delta > 0 + int n_from_input, n_padding; + n_from_input = std::max(0, noutput_items-d_delta); + n_padding = std::min(d_delta, noutput_items); + for(size_t i = 0; i < input_items.size(); i++) { + iptr = (const char *) input_items[i]; + optr = (char *) output_items[i]; + std::memset(optr, 0, n_padding*d_itemsize); + std::memcpy(optr, iptr, n_from_input*d_itemsize); + } + cons = n_from_input; + ret = noutput_items; + d_delta -= n_padding; + } + + consume_each(cons); + return ret; +} diff --git a/gnuradio-core/src/lib/general/gr_delay.h b/gnuradio-core/src/lib/general/gr_delay.h new file mode 100644 index 000000000..ed05c47f4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_delay.h @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,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_GR_DELAY_H +#define INCLUDED_GR_DELAY_H + +#include <gr_core_api.h> +#include <gr_block.h> +#include <gruel/thread.h> + +class gr_delay; +typedef boost::shared_ptr<gr_delay> gr_delay_sptr; + +GR_CORE_API gr_delay_sptr gr_make_delay (size_t itemsize, int delay); + +/*! + * \brief delay the input by a certain number of samples + * \ingroup misc_blk + */ +class GR_CORE_API gr_delay : public gr_block +{ + friend GR_CORE_API gr_delay_sptr gr_make_delay (size_t itemsize, int delay); + + gr_delay (size_t itemsize, int delay); + + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + + size_t d_itemsize; + int d_delta; + gruel::mutex d_mutex_delay; + + public: + int delay () const { return history()-1; } + void set_delay (int delay); + + 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 diff --git a/gnuradio-core/src/lib/general/gr_delay.i b/gnuradio-core/src/lib/general/gr_delay.i new file mode 100644 index 000000000..f3d49891d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_delay.i @@ -0,0 +1,35 @@ +/* -*- 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,delay) + + gr_delay_sptr gr_make_delay (size_t itemsize, int delay); + +class gr_delay : public gr_block +{ + private: + gr_delay (size_t itemsize, int delay); + + public: + int delay() const { return history()-1; } + void set_delay (int delay) { set_history(delay+1); } +}; diff --git a/gnuradio-core/src/lib/general/gr_descrambler_bb.cc b/gnuradio-core/src/lib/general/gr_descrambler_bb.cc new file mode 100644 index 000000000..b5ae28fa9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_descrambler_bb.cc @@ -0,0 +1,56 @@ +/* -*- 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 new file mode 100644 index 000000000..333593caa --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_descrambler_bb.h @@ -0,0 +1,60 @@ +/* -*- 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 new file mode 100644 index 000000000..c6cd0a285 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_descrambler_bb.i @@ -0,0 +1,31 @@ +/* -*- 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 new file mode 100644 index 000000000..74324a62e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_diff_decoder_bb.cc @@ -0,0 +1,61 @@ +/* -*- 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 new file mode 100644 index 000000000..c4ebbc476 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_diff_decoder_bb.h @@ -0,0 +1,53 @@ +/* -*- 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 new file mode 100644 index 000000000..3dddb17c3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_diff_decoder_bb.i @@ -0,0 +1,31 @@ +/* -*- 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 new file mode 100644 index 000000000..98492c746 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_diff_encoder_bb.cc @@ -0,0 +1,62 @@ +/* -*- 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 new file mode 100644 index 000000000..e98876b70 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_diff_encoder_bb.h @@ -0,0 +1,54 @@ +/* -*- 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 new file mode 100644 index 000000000..96dadaca5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_diff_encoder_bb.i @@ -0,0 +1,31 @@ +/* -*- 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 new file mode 100644 index 000000000..89fa2041e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_diff_phasor_cc.cc @@ -0,0 +1,61 @@ +/* -*- 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 new file mode 100644 index 000000000..21c4f616d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_diff_phasor_cc.h @@ -0,0 +1,53 @@ +/* -*- 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 new file mode 100644 index 000000000..8aecd5cc7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_diff_phasor_cc.i @@ -0,0 +1,34 @@ +/* -*- 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_dpll_bb.cc b/gnuradio-core/src/lib/general/gr_dpll_bb.cc new file mode 100644 index 000000000..1d5a0d4fd --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_dpll_bb.cc @@ -0,0 +1,84 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2009,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_dpll_bb.h> +#include <gr_io_signature.h> +#include <cstdio> + +gr_dpll_bb_sptr +gr_make_dpll_bb (float period, float gain) +{ + return gnuradio::get_initial_sptr(new gr_dpll_bb (period, gain)); +} + +gr_dpll_bb::gr_dpll_bb (float period, float gain) + : gr_sync_block ("dpll_bb", + gr_make_io_signature (1, 1, sizeof (char)), + gr_make_io_signature (1, 1, sizeof (char))), + d_restart(0),d_pulse_phase(0) +{ + d_pulse_frequency = 1.0/period; + d_gain = gain; + d_decision_threshold = 1.0 - 0.5*d_pulse_frequency; +#if 1 + fprintf(stderr,"frequency = %f period = %f gain = %f threshold = %f\n", + d_pulse_frequency, + period, + d_gain, + d_decision_threshold); +#endif +} + +int +gr_dpll_bb::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const char *iptr = (const char *) input_items[0]; + char *optr = (char *) output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + optr[i]= 0; + if(iptr[i] == 1) { + if (d_restart == 0) { + d_pulse_phase = 1; + } else { + if (d_pulse_phase > 0.5) d_pulse_phase += d_gain*(1.0-d_pulse_phase); + else d_pulse_phase -= d_gain*d_pulse_phase; + } + d_restart = 3; + } + if (d_pulse_phase > d_decision_threshold) { + d_pulse_phase -= 1.0; + if (d_restart > 0) { + d_restart -= 1; + optr[i] = 1; + } + } + d_pulse_phase += d_pulse_frequency; + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_dpll_bb.h b/gnuradio-core/src/lib/general/gr_dpll_bb.h new file mode 100644 index 000000000..a7df974fb --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_dpll_bb.h @@ -0,0 +1,58 @@ +/* -*- 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_DPLL_BB_H +#define INCLUDED_GR_DPLL_BB_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_dpll_bb; +typedef boost::shared_ptr<gr_dpll_bb> gr_dpll_bb_sptr; + +GR_CORE_API gr_dpll_bb_sptr gr_make_dpll_bb (float period, float gain); + +/*! + * \brief Detect the peak of a signal + * \ingroup level_blk + * + * If a peak is detected, this block outputs a 1, + * or it outputs 0's. + */ +class GR_CORE_API gr_dpll_bb : public gr_sync_block +{ + friend GR_CORE_API gr_dpll_bb_sptr gr_make_dpll_bb (float period, float gain); + + gr_dpll_bb (float period, float gain); + + private: + unsigned char d_restart; + float d_pulse_phase, d_pulse_frequency,d_gain,d_decision_threshold; + + 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_dpll_bb.i b/gnuradio-core/src/lib/general/gr_dpll_bb.i new file mode 100644 index 000000000..f31a87374 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_dpll_bb.i @@ -0,0 +1,31 @@ +/* -*- 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,dpll_bb) + + gr_dpll_bb_sptr gr_make_dpll_bb (float period, float gain); + +class gr_dpll_bb : public gr_sync_block +{ + private: + gr_dpll_bb (float period, float gain); +}; diff --git a/gnuradio-core/src/lib/general/gr_encode_ccsds_27_bb.cc b/gnuradio-core/src/lib/general/gr_encode_ccsds_27_bb.cc new file mode 100644 index 000000000..4a92d113a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_encode_ccsds_27_bb.cc @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_encode_ccsds_27_bb.h> +#include <gr_io_signature.h> + +extern "C" { +#include <../viterbi/viterbi.h> +} + +gr_encode_ccsds_27_bb_sptr +gr_make_encode_ccsds_27_bb() +{ + return gnuradio::get_initial_sptr(new gr_encode_ccsds_27_bb()); +} + +gr_encode_ccsds_27_bb::gr_encode_ccsds_27_bb() + : gr_sync_interpolator("encode_ccsds_27_bb", + gr_make_io_signature(1, 1, sizeof(char)), + gr_make_io_signature(1, 1, sizeof(char)), + 16) // Rate 1/2 code, packed to unpacked conversion +{ + d_encstate = 0; +} + +gr_encode_ccsds_27_bb::~gr_encode_ccsds_27_bb() +{ +} + +int +gr_encode_ccsds_27_bb::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + unsigned char *in = (unsigned char *)input_items[0]; + unsigned char *out = (unsigned char *)output_items[0]; + + d_encstate = encode(out, in, noutput_items/16, d_encstate); + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_encode_ccsds_27_bb.h b/gnuradio-core/src/lib/general/gr_encode_ccsds_27_bb.h new file mode 100644 index 000000000..94e9c33f1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_encode_ccsds_27_bb.h @@ -0,0 +1,64 @@ +/* -*- 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_ENCODE_CCSDS_27_BB_H +#define INCLUDED_GR_ENCODE_CCSDS_27_BB_H + +#include <gr_core_api.h> +#include <gr_sync_interpolator.h> + +class gr_encode_ccsds_27_bb; + +typedef boost::shared_ptr<gr_encode_ccsds_27_bb> gr_encode_ccsds_27_bb_sptr; + +GR_CORE_API gr_encode_ccsds_27_bb_sptr gr_make_encode_ccsds_27_bb(); + +/*! \brief A rate 1/2, k=7 convolutional encoder for the CCSDS standard + * \ingroup ecc + * + * This block performs convolutional encoding using the CCSDS standard + * polynomial ("Voyager"). + * + * The input is an MSB first packed stream of bits. + * + * The output is a stream of symbols 0 or 1 representing the encoded data. + * + * As a rate 1/2 code, there will be 16 output symbols for every input byte. + * + * This block is designed for continuous data streaming, not packetized data. + * There is no provision to "flush" the encoder. + */ + +class GR_CORE_API gr_encode_ccsds_27_bb : public gr_sync_interpolator +{ +private: + friend GR_CORE_API gr_encode_ccsds_27_bb_sptr gr_make_encode_ccsds_27_bb(); + + gr_encode_ccsds_27_bb(); + unsigned char d_encstate; + + public: + ~gr_encode_ccsds_27_bb(); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_ENCODE_CCSDS_27_BB_H */ diff --git a/gnuradio-core/src/lib/general/gr_encode_ccsds_27_bb.i b/gnuradio-core/src/lib/general/gr_encode_ccsds_27_bb.i new file mode 100644 index 000000000..e74e9174a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_encode_ccsds_27_bb.i @@ -0,0 +1,31 @@ +/* -*- 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,encode_ccsds_27_bb); + +gr_encode_ccsds_27_bb_sptr gr_make_encode_ccsds_27_bb (); + +class gr_encode_ccsds_27_bb : public gr_sync_interpolator +{ +private: + gr_encode_ccsds_27_bb(); +}; diff --git a/gnuradio-core/src/lib/general/gr_endian_swap.cc b/gnuradio-core/src/lib/general/gr_endian_swap.cc new file mode 100644 index 000000000..8bea0ca30 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_endian_swap.cc @@ -0,0 +1,101 @@ +/* -*- 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 <gr_endian_swap.h> +#include <gr_io_signature.h> +#include <volk/volk.h> + +gr_endian_swap_sptr +gr_make_endian_swap (size_t item_size_bytes) +{ + return gnuradio::get_initial_sptr(new gr_endian_swap (item_size_bytes)); +} + +gr_endian_swap::gr_endian_swap (size_t item_size_bytes) + : gr_sync_block ("gr_endian_swap", + gr_make_io_signature (1, 1, item_size_bytes), + gr_make_io_signature (1, 1, item_size_bytes)) +{ + const int alignment_multiple = volk_get_alignment(); + set_alignment(std::max(1,alignment_multiple)); +} + +int +gr_endian_swap::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]; + char *out = (char *) output_items[0]; + + int nbytes( output_signature()->sizeof_stream_item(0) ); + if(is_unaligned()) { + switch(nbytes){ + case 1: + memcpy(out,in,noutput_items); + break; + case 2: + memcpy(out,in,2*noutput_items); + volk_16u_byteswap_u((uint16_t*)out,noutput_items); + break; + case 4: + memcpy(out,in,4*noutput_items); + volk_32u_byteswap_u((uint32_t*)out,noutput_items); + break; + case 8: + memcpy(out,in,8*noutput_items); + volk_64u_byteswap_u((uint64_t*)out,noutput_items); + break; + default: + throw std::runtime_error("itemsize is not valid for gr_endian_swap!"); + } + } else { + switch(nbytes){ + case 1: + memcpy(out,in,noutput_items); + break; + case 2: + memcpy(out,in,2*noutput_items); + volk_16u_byteswap_a((uint16_t*)out,noutput_items); + break; + case 4: + memcpy(out,in,4*noutput_items); + volk_32u_byteswap_a((uint32_t*)out,noutput_items); + break; + case 8: + memcpy(out,in,8*noutput_items); + volk_64u_byteswap_a((uint64_t*)out,noutput_items); + break; + default: + throw std::runtime_error("itemsize is not valid for gr_endian_swap!"); + } + } + + return noutput_items; +} + + + diff --git a/gnuradio-core/src/lib/general/gr_endian_swap.h b/gnuradio-core/src/lib/general/gr_endian_swap.h new file mode 100644 index 000000000..0baa3f338 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_endian_swap.h @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_GR_ENDIAN_SWAP_H +#define INCLUDED_GR_ENDIAN_SWAP_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_endian_swap; +typedef boost::shared_ptr<gr_endian_swap> gr_endian_swap_sptr; + +GR_CORE_API gr_endian_swap_sptr +gr_make_endian_swap (size_t item_size_bytes=1); + +/*! + * \brief Convert stream of items into thier byte swapped version + * + * \param item_size_bytes number of bytes per item, 1=no-op,2=uint16_t,4=uint32_t,8=uint64_t + */ + +class GR_CORE_API gr_endian_swap : public gr_sync_block +{ + private: + friend GR_CORE_API gr_endian_swap_sptr + gr_make_endian_swap (size_t item_size_bytes); + gr_endian_swap (size_t item_size_bytes); + + size_t item_size_bytes; + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_ENDIAN_SWAP_H */ diff --git a/gnuradio-core/src/lib/general/gr_endian_swap.i b/gnuradio-core/src/lib/general/gr_endian_swap.i new file mode 100644 index 000000000..6058b9de7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_endian_swap.i @@ -0,0 +1,31 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,endian_swap) + +gr_endian_swap_sptr +gr_make_endian_swap (size_t bytes_per_item=1); + +class gr_endian_swap : public gr_sync_block +{ +public: +}; diff --git a/gnuradio-core/src/lib/general/gr_expj.h b/gnuradio-core/src/lib/general/gr_expj.h new file mode 100644 index 000000000..1d8633242 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_expj.h @@ -0,0 +1,38 @@ +/* -*- 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_EXPJ_H +#define INCLUDED_GR_EXPJ_H + +#include <gr_core_api.h> +#include <gr_sincos.h> +#include <gr_types.h> + +static inline gr_complex +gr_expj(float phase) +{ + float t_imag, t_real; + gr_sincosf(phase, &t_imag, &t_real); + return gr_complex(t_real, t_imag); +} + + +#endif /* INCLUDED_GR_EXPJ_H */ diff --git a/gnuradio-core/src/lib/general/gr_fake_channel_coder_pp.cc b/gnuradio-core/src/lib/general/gr_fake_channel_coder_pp.cc new file mode 100644 index 000000000..c1c3883c5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fake_channel_coder_pp.cc @@ -0,0 +1,113 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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_fake_channel_coder_pp.h> +#include <gr_io_signature.h> +#include <string.h> +#include <stdexcept> +#include <string.h> + +static const int PAD_VAL = 0xAA; + +gr_fake_channel_encoder_pp_sptr +gr_make_fake_channel_encoder_pp(int input_vlen, int output_vlen) +{ + return gnuradio::get_initial_sptr(new gr_fake_channel_encoder_pp(input_vlen, + output_vlen)); +} + +gr_fake_channel_encoder_pp::gr_fake_channel_encoder_pp(int input_vlen, int output_vlen) + : gr_sync_block("fake_channel_encoder_pp", + gr_make_io_signature(1, 1, input_vlen * sizeof(unsigned char)), + gr_make_io_signature(1, 1, output_vlen * sizeof(unsigned char))), + d_input_vlen(input_vlen), d_output_vlen(output_vlen) +{ + if (input_vlen <= 0 || output_vlen <= 0 || input_vlen > output_vlen) + throw std::invalid_argument("gr_fake_channel_encoder_pp"); +} + +gr_fake_channel_encoder_pp::~gr_fake_channel_encoder_pp() +{ +} + +int +gr_fake_channel_encoder_pp::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]; + int npad = d_output_vlen - d_input_vlen; + + for (int i = 0; i < noutput_items; i++){ + memcpy(out, in, d_input_vlen); + memset(out + d_input_vlen, PAD_VAL, npad); + in += d_input_vlen; + out += d_output_vlen; + } + + return noutput_items; +} + +// ------------------------------------------------------------------------ + +gr_fake_channel_decoder_pp_sptr +gr_make_fake_channel_decoder_pp(int input_vlen, int output_vlen) +{ + return gnuradio::get_initial_sptr(new gr_fake_channel_decoder_pp(input_vlen, + output_vlen)); +} + +gr_fake_channel_decoder_pp::gr_fake_channel_decoder_pp(int input_vlen, int output_vlen) + : gr_sync_block("fake_channel_decoder_pp", + gr_make_io_signature(1, 1, input_vlen * sizeof(unsigned char)), + gr_make_io_signature(1, 1, output_vlen * sizeof(unsigned char))), + d_input_vlen(input_vlen), d_output_vlen(output_vlen) +{ + if (input_vlen <= 0 || output_vlen <= 0 || output_vlen > input_vlen) + throw std::invalid_argument("gr_fake_channel_decoder_pp"); +} + +gr_fake_channel_decoder_pp::~gr_fake_channel_decoder_pp() +{ +} + +int +gr_fake_channel_decoder_pp::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++){ + memcpy(out, in, d_output_vlen); + in += d_input_vlen; + out += d_output_vlen; + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_fake_channel_coder_pp.h b/gnuradio-core/src/lib/general/gr_fake_channel_coder_pp.h new file mode 100644 index 000000000..45808752d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fake_channel_coder_pp.h @@ -0,0 +1,91 @@ +/* -*- 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_FAKE_CHANNEL_CODER_PP_H +#define INCLUDED_GR_FAKE_CHANNEL_CODER_PP_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_fake_channel_encoder_pp; +typedef boost::shared_ptr<gr_fake_channel_encoder_pp> gr_fake_channel_encoder_pp_sptr; + +GR_CORE_API gr_fake_channel_encoder_pp_sptr +gr_make_fake_channel_encoder_pp(int input_vlen, int output_vlen); + +/*! + * \brief pad packet with alternating 1,0 pattern. + * \ingroup coding_blk + * + * input: stream of byte vectors; output: stream of byte vectors + */ +class GR_CORE_API gr_fake_channel_encoder_pp : public gr_sync_block +{ + int d_input_vlen; + int d_output_vlen; + + gr_fake_channel_encoder_pp(int input_vlen, int output_vlen); + + friend GR_CORE_API gr_fake_channel_encoder_pp_sptr + gr_make_fake_channel_encoder_pp(int input_vlen, int output_vlen); + +public: + ~gr_fake_channel_encoder_pp(); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +// ------------------------------------------------------------------------ + +class gr_fake_channel_decoder_pp; +typedef boost::shared_ptr<gr_fake_channel_decoder_pp> gr_fake_channel_decoder_pp_sptr; + +GR_CORE_API gr_fake_channel_decoder_pp_sptr +gr_make_fake_channel_decoder_pp(int input_vlen, int output_vlen); + +/*! + * \brief remove fake padding from packet + * \ingroup coding_blk + * + * input: stream of byte vectors; output: stream of byte vectors + */ +class GR_CORE_API gr_fake_channel_decoder_pp : public gr_sync_block +{ + int d_input_vlen; + int d_output_vlen; + + gr_fake_channel_decoder_pp(int input_vlen, int output_vlen); + + friend GR_CORE_API gr_fake_channel_decoder_pp_sptr + gr_make_fake_channel_decoder_pp(int input_vlen, int output_vlen); + +public: + ~gr_fake_channel_decoder_pp(); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_FAKE_CHANNEL_CODER_PP_H */ diff --git a/gnuradio-core/src/lib/general/gr_fake_channel_coder_pp.i b/gnuradio-core/src/lib/general/gr_fake_channel_coder_pp.i new file mode 100644 index 000000000..123c84e47 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fake_channel_coder_pp.i @@ -0,0 +1,53 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,fake_channel_encoder_pp) + +gr_fake_channel_encoder_pp_sptr +gr_make_fake_channel_encoder_pp(int input_vlen, + int output_vlen + ) throw(std::invalid_argument); + +class gr_fake_channel_encoder_pp : public gr_sync_block +{ + gr_fake_channel_encoder_pp(int input_vlen, int output_vlen); + +public: + ~gr_fake_channel_encoder_pp(); +}; + +// ------------------------------------------------------------------------ + +GR_SWIG_BLOCK_MAGIC(gr,fake_channel_decoder_pp) + +gr_fake_channel_decoder_pp_sptr +gr_make_fake_channel_decoder_pp(int input_vlen, + int output_vlen + ) throw(std::invalid_argument); + +class gr_fake_channel_decoder_pp : public gr_sync_block +{ + gr_fake_channel_decoder_pp(int input_vlen, int output_vlen); + +public: + ~gr_fake_channel_decoder_pp(); +}; diff --git a/gnuradio-core/src/lib/general/gr_fast_atan2f.cc b/gnuradio-core/src/lib/general/gr_fast_atan2f.cc new file mode 100644 index 000000000..8b7bfea12 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fast_atan2f.cc @@ -0,0 +1,199 @@ +/* -*- 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. + */ + +#include <gr_math.h> // declaration is in here +#include <cmath> + +#define REAL float + +/***************************************************************************/ +/* Constant definitions */ +/***************************************************************************/ + +#define TAN_MAP_RES 0.003921569 /* (smallest non-zero value in table) */ +#define RAD_PER_DEG 0.017453293 +#define TAN_MAP_SIZE 256 + +/* arctangents from 0 to pi/4 radians */ +static REAL +fast_atan_table[257] = { + 0.000000e+00, 3.921549e-03, 7.842976e-03, 1.176416e-02, + 1.568499e-02, 1.960533e-02, 2.352507e-02, 2.744409e-02, + 3.136226e-02, 3.527947e-02, 3.919560e-02, 4.311053e-02, + 4.702413e-02, 5.093629e-02, 5.484690e-02, 5.875582e-02, + 6.266295e-02, 6.656816e-02, 7.047134e-02, 7.437238e-02, + 7.827114e-02, 8.216752e-02, 8.606141e-02, 8.995267e-02, + 9.384121e-02, 9.772691e-02, 1.016096e-01, 1.054893e-01, + 1.093658e-01, 1.132390e-01, 1.171087e-01, 1.209750e-01, + 1.248376e-01, 1.286965e-01, 1.325515e-01, 1.364026e-01, + 1.402496e-01, 1.440924e-01, 1.479310e-01, 1.517652e-01, + 1.555948e-01, 1.594199e-01, 1.632403e-01, 1.670559e-01, + 1.708665e-01, 1.746722e-01, 1.784728e-01, 1.822681e-01, + 1.860582e-01, 1.898428e-01, 1.936220e-01, 1.973956e-01, + 2.011634e-01, 2.049255e-01, 2.086818e-01, 2.124320e-01, + 2.161762e-01, 2.199143e-01, 2.236461e-01, 2.273716e-01, + 2.310907e-01, 2.348033e-01, 2.385093e-01, 2.422086e-01, + 2.459012e-01, 2.495869e-01, 2.532658e-01, 2.569376e-01, + 2.606024e-01, 2.642600e-01, 2.679104e-01, 2.715535e-01, + 2.751892e-01, 2.788175e-01, 2.824383e-01, 2.860514e-01, + 2.896569e-01, 2.932547e-01, 2.968447e-01, 3.004268e-01, + 3.040009e-01, 3.075671e-01, 3.111252e-01, 3.146752e-01, + 3.182170e-01, 3.217506e-01, 3.252758e-01, 3.287927e-01, + 3.323012e-01, 3.358012e-01, 3.392926e-01, 3.427755e-01, + 3.462497e-01, 3.497153e-01, 3.531721e-01, 3.566201e-01, + 3.600593e-01, 3.634896e-01, 3.669110e-01, 3.703234e-01, + 3.737268e-01, 3.771211e-01, 3.805064e-01, 3.838825e-01, + 3.872494e-01, 3.906070e-01, 3.939555e-01, 3.972946e-01, + 4.006244e-01, 4.039448e-01, 4.072558e-01, 4.105574e-01, + 4.138496e-01, 4.171322e-01, 4.204054e-01, 4.236689e-01, + 4.269229e-01, 4.301673e-01, 4.334021e-01, 4.366272e-01, + 4.398426e-01, 4.430483e-01, 4.462443e-01, 4.494306e-01, + 4.526070e-01, 4.557738e-01, 4.589307e-01, 4.620778e-01, + 4.652150e-01, 4.683424e-01, 4.714600e-01, 4.745676e-01, + 4.776654e-01, 4.807532e-01, 4.838312e-01, 4.868992e-01, + 4.899573e-01, 4.930055e-01, 4.960437e-01, 4.990719e-01, + 5.020902e-01, 5.050985e-01, 5.080968e-01, 5.110852e-01, + 5.140636e-01, 5.170320e-01, 5.199904e-01, 5.229388e-01, + 5.258772e-01, 5.288056e-01, 5.317241e-01, 5.346325e-01, + 5.375310e-01, 5.404195e-01, 5.432980e-01, 5.461666e-01, + 5.490251e-01, 5.518738e-01, 5.547124e-01, 5.575411e-01, + 5.603599e-01, 5.631687e-01, 5.659676e-01, 5.687566e-01, + 5.715357e-01, 5.743048e-01, 5.770641e-01, 5.798135e-01, + 5.825531e-01, 5.852828e-01, 5.880026e-01, 5.907126e-01, + 5.934128e-01, 5.961032e-01, 5.987839e-01, 6.014547e-01, + 6.041158e-01, 6.067672e-01, 6.094088e-01, 6.120407e-01, + 6.146630e-01, 6.172755e-01, 6.198784e-01, 6.224717e-01, + 6.250554e-01, 6.276294e-01, 6.301939e-01, 6.327488e-01, + 6.352942e-01, 6.378301e-01, 6.403565e-01, 6.428734e-01, + 6.453808e-01, 6.478788e-01, 6.503674e-01, 6.528466e-01, + 6.553165e-01, 6.577770e-01, 6.602282e-01, 6.626701e-01, + 6.651027e-01, 6.675261e-01, 6.699402e-01, 6.723452e-01, + 6.747409e-01, 6.771276e-01, 6.795051e-01, 6.818735e-01, + 6.842328e-01, 6.865831e-01, 6.889244e-01, 6.912567e-01, + 6.935800e-01, 6.958943e-01, 6.981998e-01, 7.004964e-01, + 7.027841e-01, 7.050630e-01, 7.073330e-01, 7.095943e-01, + 7.118469e-01, 7.140907e-01, 7.163258e-01, 7.185523e-01, + 7.207701e-01, 7.229794e-01, 7.251800e-01, 7.273721e-01, + 7.295557e-01, 7.317307e-01, 7.338974e-01, 7.360555e-01, + 7.382053e-01, 7.403467e-01, 7.424797e-01, 7.446045e-01, + 7.467209e-01, 7.488291e-01, 7.509291e-01, 7.530208e-01, + 7.551044e-01, 7.571798e-01, 7.592472e-01, 7.613064e-01, + 7.633576e-01, 7.654008e-01, 7.674360e-01, 7.694633e-01, + 7.714826e-01, 7.734940e-01, 7.754975e-01, 7.774932e-01, + 7.794811e-01, 7.814612e-01, 7.834335e-01, 7.853983e-01, + 7.853983e-01 + }; + + +/***************************************************************************** +Function: Arc tangent + +Syntax: angle = fast_atan2(y, x); +REAL y y component of input vector +REAL x x component of input vector +REAL angle angle of vector (x, y) in radians + +Description: This function calculates the angle of the vector (x,y) based +on a table lookup and linear interpolation. The table uses +a 256 point table covering -45 to +45 degrees and uses +symetry to determine the final angle value in the range of +-180 to 180 degrees. Note that this function uses the small +angle approximation for values close to zero. This routine +calculates the arc tangent with an average error of ++/- 0.045 degrees. +*****************************************************************************/ + +REAL +gr_fast_atan2f(REAL y, REAL x) +{ + REAL x_abs, y_abs, z; + REAL alpha, angle, base_angle; + int index; + + /* don't divide by zero! */ // FIXME could get hosed with -0.0 + if ((y == 0.0) && (x == 0.0)) + return 0.0; + + /* normalize to +/- 45 degree range */ + y_abs = fabs(y); + x_abs = fabs(x); + //z = (y_abs < x_abs ? y_abs / x_abs : x_abs / y_abs); + if (y_abs < x_abs) + z = y_abs / x_abs; + else + z = x_abs / y_abs; + + /* when ratio approaches the table resolution, the angle is */ + /* best approximated with the argument itself... */ + if (z < TAN_MAP_RES) + base_angle = z; + else { + /* find index and interpolation value */ + alpha = z * (REAL) TAN_MAP_SIZE - .5; + index = (int) alpha; + alpha -= (REAL) index; + /* determine base angle based on quadrant and */ + /* add or subtract table value from base angle based on quadrant */ + base_angle = fast_atan_table[index]; + base_angle += + (fast_atan_table[index + 1] - fast_atan_table[index]) * alpha; + } + + if (x_abs > y_abs) { /* -45 -> 45 or 135 -> 225 */ + if (x >= 0.0) { /* -45 -> 45 */ + if (y >= 0.0) + angle = base_angle; /* 0 -> 45, angle OK */ + else + angle = -base_angle; /* -45 -> 0, angle = -angle */ + } else { /* 135 -> 180 or 180 -> -135 */ + angle = 3.14159265358979323846; + if (y >= 0.0) + angle -= base_angle; /* 135 -> 180, angle = 180 - angle */ + else + angle = base_angle - angle; /* 180 -> -135, angle = angle - 180 */ + } + } else { /* 45 -> 135 or -135 -> -45 */ + if (y >= 0.0) { /* 45 -> 135 */ + angle = 1.57079632679489661923; + if (x >= 0.0) + angle -= base_angle; /* 45 -> 90, angle = 90 - angle */ + else + angle += base_angle; /* 90 -> 135, angle = 90 + angle */ + } else { /* -135 -> -45 */ + angle = -1.57079632679489661923; + if (x >= 0.0) + angle += base_angle; /* -90 -> -45, angle = -90 + angle */ + else + angle -= base_angle; /* -135 -> -90, angle = -90 - angle */ + } + } + +#ifdef ZERO_TO_TWOPI + if (angle < 0) + return (angle + TWOPI); + else + return (angle); +#else + return (angle); +#endif +} + diff --git a/gnuradio-core/src/lib/general/gr_feedforward_agc_cc.cc b/gnuradio-core/src/lib/general/gr_feedforward_agc_cc.cc new file mode 100644 index 000000000..147b64e9b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_feedforward_agc_cc.cc @@ -0,0 +1,91 @@ +/* -*- 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_feedforward_agc_cc.h> +#include <gr_io_signature.h> +#include <stdexcept> + +gr_feedforward_agc_cc_sptr +gr_make_feedforward_agc_cc(int nsamples, float reference) +{ + return gnuradio::get_initial_sptr(new gr_feedforward_agc_cc (nsamples, reference)); +} + +gr_feedforward_agc_cc::gr_feedforward_agc_cc (int nsamples, float reference) + : gr_sync_block ("gr_feedforward_agc_cc", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (gr_complex))), + d_nsamples(nsamples), d_reference(reference) +{ + if (nsamples < 1) + throw std::invalid_argument("gr_feedforward_agc_cc: nsamples must be >= 1"); + + set_history(nsamples); +} + +gr_feedforward_agc_cc::~gr_feedforward_agc_cc() +{ +} + +inline static float +mag_squared(gr_complex x) +{ + return x.real() * x.real() + x.imag() * x.imag(); +} + +// approximate sqrt(x^2 + y^2) +inline static float +envelope(gr_complex x) +{ + float r_abs = std::fabs(x.real()); + float i_abs = std::fabs(x.imag()); + + if (r_abs > i_abs) + return r_abs + 0.4 * i_abs; + else + return i_abs + 0.4 * r_abs; +} + +int +gr_feedforward_agc_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]; + int nsamples = d_nsamples; + float gain; + + for (int i = 0; i < noutput_items; i++){ + //float max_env = 1e-12; // avoid divide by zero + float max_env = 1e-4; // avoid divide by zero, indirectly set max gain + for (int j = 0; j < nsamples; j++) + max_env = std::max(max_env, envelope(in[i+j])); + gain = d_reference / max_env; + out[i] = gain * in[i]; + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_feedforward_agc_cc.h b/gnuradio-core/src/lib/general/gr_feedforward_agc_cc.h new file mode 100644 index 000000000..63e5e4c43 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_feedforward_agc_cc.h @@ -0,0 +1,57 @@ +/* -*- 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_FEEDFORWARD_AGC_CC_H +#define INCLUDED_GR_FEEDFORWARD_AGC_CC_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_feedforward_agc_cc; +typedef boost::shared_ptr<gr_feedforward_agc_cc> gr_feedforward_agc_cc_sptr; + +GR_CORE_API gr_feedforward_agc_cc_sptr +gr_make_feedforward_agc_cc(int nsamples, float reference = 1.0); + +/*! + * \brief Non-causal AGC which computes required gain based on max absolute value over nsamples + * \ingroup level_blk + */ +class GR_CORE_API gr_feedforward_agc_cc : public gr_sync_block +{ + friend GR_CORE_API gr_feedforward_agc_cc_sptr + gr_make_feedforward_agc_cc(int nsamples, float reference); + + int d_nsamples; + float d_reference; + + gr_feedforward_agc_cc(int nsamples, float reference); + + public: + ~gr_feedforward_agc_cc(); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_FEEDFORWARD_AGC_CC_H */ diff --git a/gnuradio-core/src/lib/general/gr_feedforward_agc_cc.i b/gnuradio-core/src/lib/general/gr_feedforward_agc_cc.i new file mode 100644 index 000000000..1fd5a2c26 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_feedforward_agc_cc.i @@ -0,0 +1,34 @@ +/* -*- 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,feedforward_agc_cc); + +gr_feedforward_agc_cc_sptr +gr_make_feedforward_agc_cc(int nsamples, float reference = 1.0); + +class gr_feedforward_agc_cc : public gr_sync_block +{ + gr_feedforward_agc_cc(int nsamples, float reference); + + public: + ~gr_feedforward_agc_cc(); +}; diff --git a/gnuradio-core/src/lib/general/gr_feval.cc b/gnuradio-core/src/lib/general/gr_feval.cc new file mode 100644 index 000000000..89f09984c --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_feval.cc @@ -0,0 +1,132 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gr_feval.h> + +gr_feval_dd::~gr_feval_dd(){} + +double +gr_feval_dd::eval(double x) +{ + return 0; +} + +double +gr_feval_dd::calleval(double x) +{ + return eval(x); +} + +// ---------------------------------------------------------------- + +gr_feval_cc::~gr_feval_cc(){} + +gr_complex +gr_feval_cc::eval(gr_complex x) +{ + return 0; +} + +gr_complex +gr_feval_cc::calleval(gr_complex x) +{ + return eval(x); +} + +// ---------------------------------------------------------------- + +gr_feval_ll::~gr_feval_ll(){} + +long +gr_feval_ll::eval(long x) +{ + return 0; +} + +long +gr_feval_ll::calleval(long x) +{ + return eval(x); +} + +// ---------------------------------------------------------------- + +gr_feval::~gr_feval(){} + +void +gr_feval::eval(void) +{ + // nop +} + +void +gr_feval::calleval(void) +{ + eval(); +} + +// ---------------------------------------------------------------- + +gr_feval_p::~gr_feval_p(){} + +void +gr_feval_p::eval(pmt::pmt_t x) +{ + // nop +} + +void +gr_feval_p::calleval(pmt::pmt_t x) +{ + eval(x); +} + +/* + * Trivial examples showing C++ (transparently) calling Python + */ +double +gr_feval_dd_example(gr_feval_dd *f, double x) +{ + return f->calleval(x); +} + +gr_complex +gr_feval_cc_example(gr_feval_cc *f, gr_complex x) +{ + return f->calleval(x); +} + +long +gr_feval_ll_example(gr_feval_ll *f, long x) +{ + return f->calleval(x); +} + +void +gr_feval_example(gr_feval *f) +{ + f->calleval(); +} diff --git a/gnuradio-core/src/lib/general/gr_feval.h b/gnuradio-core/src/lib/general/gr_feval.h new file mode 100644 index 000000000..a9bccfe51 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_feval.h @@ -0,0 +1,177 @@ +/* -*- 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_FEVAL_H +#define INCLUDED_GR_FEVAL_H + +#include <gr_core_api.h> +#include <gr_complex.h> +#include <gruel/pmt.h> + +/*! + * \brief base class for evaluating a function: double -> double + * \ingroup misc + * + * This class is designed to be subclassed in Python or C++ + * and is callable from both places. It uses SWIG's + * "director" feature to implement the magic. + * It's slow. Don't use it in a performance critical path. + * + * Override eval to define the behavior. + * Use calleval to invoke eval (this kludge is required to allow a + * python specific "shim" to be inserted. + */ +class GR_CORE_API gr_feval_dd +{ +protected: + /*! + * \brief override this to define the function + */ + virtual double eval(double x); + +public: + gr_feval_dd() {} + virtual ~gr_feval_dd(); + + virtual double calleval(double x); // invoke "eval" +}; + +/*! + * \brief base class for evaluating a function: complex -> complex + * \ingroup misc + * + * This class is designed to be subclassed in Python or C++ + * and is callable from both places. It uses SWIG's + * "director" feature to implement the magic. + * It's slow. Don't use it in a performance critical path. + * + * Override eval to define the behavior. + * Use calleval to invoke eval (this kludge is required to allow a + * python specific "shim" to be inserted. + */ +class GR_CORE_API gr_feval_cc +{ +protected: + /*! + * \brief override this to define the function + */ + virtual gr_complex eval(gr_complex x); + +public: + gr_feval_cc() {} + virtual ~gr_feval_cc(); + + virtual gr_complex calleval(gr_complex x); // invoke "eval" +}; + +/*! + * \brief base class for evaluating a function: long -> long + * \ingroup misc + * + * This class is designed to be subclassed in Python or C++ + * and is callable from both places. It uses SWIG's + * "director" feature to implement the magic. + * It's slow. Don't use it in a performance critical path. + * + * Override eval to define the behavior. + * Use calleval to invoke eval (this kludge is required to allow a + * python specific "shim" to be inserted. + */ +class GR_CORE_API gr_feval_ll +{ +protected: + /*! + * \brief override this to define the function + */ + virtual long eval(long x); + +public: + gr_feval_ll() {} + virtual ~gr_feval_ll(); + + virtual long calleval(long x); // invoke "eval" +}; + +/*! + * \brief base class for evaluating a function: void -> void + * \ingroup misc + * + * This class is designed to be subclassed in Python or C++ + * and is callable from both places. It uses SWIG's + * "director" feature to implement the magic. + * It's slow. Don't use it in a performance critical path. + * + * Override eval to define the behavior. + * Use calleval to invoke eval (this kludge is required to allow a + * python specific "shim" to be inserted. + */ +class GR_CORE_API gr_feval +{ +protected: + /*! + * \brief override this to define the function + */ + virtual void eval(); + +public: + gr_feval() {} + virtual ~gr_feval(); + + virtual void calleval(); // invoke "eval" +}; + +/*! + * \brief base class for evaluating a function: pmt -> void + * \ingroup misc + * + * This class is designed to be subclassed in Python or C++ + * and is callable from both places. It uses SWIG's + * "director" feature to implement the magic. + * It's slow. Don't use it in a performance critical path. + * + * Override eval to define the behavior. + * Use calleval to invoke eval (this kludge is required to allow a + * python specific "shim" to be inserted. + */ +class GR_CORE_API gr_feval_p +{ +protected: + /*! + * \brief override this to define the function + */ + virtual void eval(pmt::pmt_t x); + +public: + gr_feval_p() {} + virtual ~gr_feval_p(); + + virtual void calleval(pmt::pmt_t x); // invoke "eval" +}; + +/*! + * \brief trivial examples / test cases showing C++ calling Python code + */ +GR_CORE_API double gr_feval_dd_example(gr_feval_dd *f, double x); +GR_CORE_API gr_complex gr_feval_cc_example(gr_feval_cc *f, gr_complex x); +GR_CORE_API long gr_feval_ll_example(gr_feval_ll *f, long x); +GR_CORE_API void gr_feval_example(gr_feval *f); + +#endif /* INCLUDED_GR_FEVAL_H */ diff --git a/gnuradio-core/src/lib/general/gr_feval.i b/gnuradio-core/src/lib/general/gr_feval.i new file mode 100644 index 000000000..c8b7e54da --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_feval.i @@ -0,0 +1,233 @@ +/* -*- 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. + */ + + +/* + * N.B., this is a _very_ non-standard SWIG .i file + * + * It contains a bunch of magic that is required to ensure that when + * these classes are used as base classes for python code, + * everything works when calling back from C++ into Python. + * + * The gist of the problem is that our C++ code is usually not holding + * the Python Global Interpreter Lock (GIL). Thus if we invoke a + * "director" method from C++, we'll end up in Python not holding the + * GIL. Disaster (SIGSEGV) will result. To avoid this we insert a + * "shim" that grabs and releases the GIL. + * + * If you don't understand SWIG "directors" or the Python GIL, + * don't bother trying to understand what's going on in here. + * + * [We could eliminate a bunch of this hair by requiring SWIG 1.3.29 + * or later and some additional magic declarations, but many systems + * aren't shipping that version yet. Thus we kludge...] + */ + + +// Directors are only supported in Python, Java and C# +#ifdef SWIGPYTHON +%import "pmt_swig.i" +using namespace pmt; + +// Enable SWIG directors for these classes +%feature("director") gr_py_feval_dd; +%feature("director") gr_py_feval_cc; +%feature("director") gr_py_feval_ll; +%feature("director") gr_py_feval; +%feature("director") gr_py_feval_p; + +%feature("nodirector") gr_py_feval_dd::calleval; +%feature("nodirector") gr_py_feval_cc::calleval; +%feature("nodirector") gr_py_feval_ll::calleval; +%feature("nodirector") gr_py_feval::calleval; +%feature("nodirector") gr_py_feval_p::calleval; + + +%rename(feval_dd) gr_py_feval_dd; +%rename(feval_cc) gr_py_feval_cc; +%rename(feval_ll) gr_py_feval_ll; +%rename(feval) gr_py_feval; +%rename(feval_p) gr_py_feval_p; + +//%exception { +// try { $action } +// catch (Swig::DirectorException &e) { std::cerr << e.getMessage(); SWIG_fail; } +//} + +%{ + +// class that ensures we acquire and release the Python GIL + +class ensure_py_gil_state { + PyGILState_STATE d_gstate; +public: + ensure_py_gil_state() { d_gstate = PyGILState_Ensure(); } + ~ensure_py_gil_state() { PyGILState_Release(d_gstate); } +}; + +%} + +/* + * These are the real C++ base classes, however we don't want these exposed. + */ +%ignore gr_feval_dd; +class gr_feval_dd +{ +protected: + virtual double eval(double x); + +public: + gr_feval_dd() {} + virtual ~gr_feval_dd(); + + virtual double calleval(double x); +}; + +%ignore gr_feval_cc; +class gr_feval_cc +{ +protected: + virtual gr_complex eval(gr_complex x); + +public: + gr_feval_cc() {} + virtual ~gr_feval_cc(); + + virtual gr_complex calleval(gr_complex x); +}; + +%ignore gr_feval_ll; +class gr_feval_ll +{ +protected: + virtual long eval(long x); + +public: + gr_feval_ll() {} + virtual ~gr_feval_ll(); + + virtual long calleval(long x); +}; + +%ignore gr_feval; +class gr_feval +{ +protected: + virtual void eval(); + +public: + gr_feval() {} + virtual ~gr_feval(); + + virtual void calleval(); +}; + +%ignore gr_feval_p; +class gr_feval_p +{ +protected: + virtual void eval(pmt_t x); + +public: + gr_feval_p() {} + virtual ~gr_feval_p(); + + virtual void calleval(pmt_t x); +}; + +/* + * These are the ones to derive from in Python. They have the magic shim + * that ensures that we're holding the Python GIL when we enter Python land... + */ + +%inline %{ +#include <gruel/pmt.h> + +class gr_py_feval_dd : public gr_feval_dd +{ + public: + double calleval(double x) + { + ensure_py_gil_state _lock; + return eval(x); + } +}; + +class gr_py_feval_cc : public gr_feval_cc +{ + public: + gr_complex calleval(gr_complex x) + { + ensure_py_gil_state _lock; + return eval(x); + } +}; + +class gr_py_feval_ll : public gr_feval_ll +{ + public: + long calleval(long x) + { + ensure_py_gil_state _lock; + return eval(x); + } +}; + +class gr_py_feval : public gr_feval +{ + public: + void calleval() + { + ensure_py_gil_state _lock; + eval(); + } +}; + +class gr_py_feval_p : public gr_feval_p +{ + public: + void calleval(pmt::pmt_t x) + { + ensure_py_gil_state _lock; + eval(x); + } +}; + +%} + + + +// examples / test cases + +%rename(feval_dd_example) gr_feval_dd_example; +double gr_feval_dd_example(gr_feval_dd *f, double x); + +%rename(feval_cc_example) gr_feval_cc_example; +gr_complex gr_feval_cc_example(gr_feval_cc *f, gr_complex x); + +%rename(feval_ll_example) gr_feval_ll_example; +long gr_feval_ll_example(gr_feval_ll *f, long x); + +%rename(feval_example) gr_feval_example; +void gr_feval_example(gr_feval *f); + +#endif // SWIGPYTHON diff --git a/gnuradio-core/src/lib/general/gr_fft_vcc.cc b/gnuradio-core/src/lib/general/gr_fft_vcc.cc new file mode 100644 index 000000000..addcddb64 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fft_vcc.cc @@ -0,0 +1,80 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2007,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 <gr_fft_vcc.h> // abstract class +#include <gr_fft_vcc_fftw.h> // concrete class +#include <gr_io_signature.h> +#include <gri_fft.h> +#include <math.h> +#include <string.h> + +gr_fft_vcc_sptr +gr_make_fft_vcc (int fft_size, bool forward, + const std::vector<float> &window, + bool shift, int nthreads) +{ + return gr_make_fft_vcc_fftw(fft_size, forward, + window, shift, nthreads); +} + +gr_fft_vcc::gr_fft_vcc (const std::string &name, + int fft_size, bool forward, const std::vector<float> &window, + bool shift) + : gr_sync_block (name, + gr_make_io_signature (1, 1, fft_size * sizeof (gr_complex)), + gr_make_io_signature (1, 1, fft_size * sizeof (gr_complex))), + d_fft_size(fft_size), d_forward(forward), d_shift(shift) +{ + set_window(window); +} + +gr_fft_vcc::~gr_fft_vcc () +{ +} + +bool +gr_fft_vcc::set_window(const std::vector<float> &window) +{ + if(window.size()==0 || window.size()==d_fft_size) { + d_window=window; + return true; + } + else + return false; +} + +void +gr_fft_vcc::set_nthreads(int n) +{ + throw std::runtime_error("gr_fft_vcc::set_nthreads not implemented."); +} + +int +gr_fft_vcc::nthreads() const +{ + throw std::runtime_error("gr_fft_vcc::nthreads not implemented."); + return 0; +} diff --git a/gnuradio-core/src/lib/general/gr_fft_vcc.h b/gnuradio-core/src/lib/general/gr_fft_vcc.h new file mode 100644 index 000000000..db5690d41 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fft_vcc.h @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2007,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. + */ + +#ifndef INCLUDED_GR_FFT_VCC_H +#define INCLUDED_GR_FFT_VCC_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_fft_vcc; +typedef boost::shared_ptr<gr_fft_vcc> gr_fft_vcc_sptr; + +GR_CORE_API gr_fft_vcc_sptr +gr_make_fft_vcc (int fft_size, bool forward, + const std::vector<float> &window, + bool shift=false, int nthreads=1); + +/*! + * \brief Compute forward or reverse FFT. complex vector in / complex vector out. + * \ingroup dft_blk + * + * Abstract base class + */ +class GR_CORE_API gr_fft_vcc : public gr_sync_block +{ +protected: + friend GR_CORE_API gr_fft_vcc_sptr + gr_make_fft_vcc (int fft_size, bool forward, + const std::vector<float> &window, + bool shift); + + unsigned int d_fft_size; + std::vector<float> d_window; + bool d_forward; + bool d_shift; + + gr_fft_vcc (const std::string &name, int fft_size, bool forward, + const std::vector<float> &window, bool shift); + + public: + ~gr_fft_vcc (); + + virtual void set_nthreads(int n); + virtual int nthreads() const; + + bool set_window(const std::vector<float> &window); +}; + +#endif /* INCLUDED_GR_FFT_VCC_H */ diff --git a/gnuradio-core/src/lib/general/gr_fft_vcc.i b/gnuradio-core/src/lib/general/gr_fft_vcc.i new file mode 100644 index 000000000..f9caae7d8 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fft_vcc.i @@ -0,0 +1,41 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2007,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. + */ + +GR_SWIG_BLOCK_MAGIC(gr, fft_vcc) + +gr_fft_vcc_sptr +gr_make_fft_vcc (int fft_size, bool forward, + const std::vector<float> &window, + bool shift=false, int nthreads=1); + +class gr_fft_vcc : public gr_sync_block +{ + protected: + gr_fft_vcc (int fft_size, bool forward, + const std::vector<float> &window, + bool shift); + + public: + bool set_window(const std::vector<float> &window); + void set_nthreads(int n); + int nthreads() const; +}; diff --git a/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.cc b/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.cc new file mode 100644 index 000000000..891173bcd --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.cc @@ -0,0 +1,130 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2007,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_fft_vcc_fftw.h> +#include <gr_io_signature.h> +#include <gri_fft.h> +#include <math.h> +#include <string.h> + +gr_fft_vcc_sptr +gr_make_fft_vcc_fftw (int fft_size, bool forward, + const std::vector<float> &window, + bool shift, int nthreads) +{ + return gnuradio::get_initial_sptr(new gr_fft_vcc_fftw + (fft_size, forward, window, + shift, nthreads)); +} + +gr_fft_vcc_fftw::gr_fft_vcc_fftw (int fft_size, bool forward, + const std::vector<float> &window, + bool shift, int nthreads) + : gr_fft_vcc("fft_vcc_fftw", fft_size, forward, window, shift) +{ + d_fft = new gri_fft_complex (d_fft_size, forward, nthreads); +} + +gr_fft_vcc_fftw::~gr_fft_vcc_fftw () +{ + delete d_fft; +} + +void +gr_fft_vcc_fftw::set_nthreads(int n) +{ + d_fft->set_nthreads(n); +} + +int +gr_fft_vcc_fftw::nthreads() const +{ + return d_fft->nthreads(); +} + +int +gr_fft_vcc_fftw::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]; + + unsigned int input_data_size = input_signature()->sizeof_stream_item (0); + unsigned int output_data_size = output_signature()->sizeof_stream_item (0); + + int count = 0; + + while (count++ < noutput_items){ + + // copy input into optimally aligned buffer + + if (d_window.size()){ + gr_complex *dst = d_fft->get_inbuf(); + if(!d_forward && d_shift){ + unsigned int offset = (!d_forward && d_shift)?(d_fft_size/2):0; + int fft_m_offset = d_fft_size - offset; + for (unsigned int i = 0; i < offset; i++) // apply window + dst[i+fft_m_offset] = in[i] * d_window[i]; + for (unsigned int i = offset; i < d_fft_size; i++) // apply window + dst[i-offset] = in[i] * d_window[i]; + } else { + for (unsigned int i = 0; i < d_fft_size; i++) // apply window + dst[i] = in[i] * d_window[i]; + } + } + else { + if(!d_forward && d_shift) { // apply an ifft shift on the data + gr_complex *dst = d_fft->get_inbuf(); + unsigned int len = (unsigned int)(floor(d_fft_size/2.0)); // half length of complex array + memcpy(&dst[0], &in[len], sizeof(gr_complex)*(d_fft_size - len)); + memcpy(&dst[d_fft_size - len], &in[0], sizeof(gr_complex)*len); + } + else { + memcpy (d_fft->get_inbuf(), in, input_data_size); + } + } + + // compute the fft + d_fft->execute (); + + // copy result to our output + if(d_forward && d_shift) { // apply a fft shift on the data + unsigned int len = (unsigned int)(ceil(d_fft_size/2.0)); + memcpy(&out[0], &d_fft->get_outbuf()[len], sizeof(gr_complex)*(d_fft_size - len)); + memcpy(&out[d_fft_size - len], &d_fft->get_outbuf()[0], sizeof(gr_complex)*len); + } + else { + memcpy (out, d_fft->get_outbuf (), output_data_size); + } + + in += d_fft_size; + out += d_fft_size; + } + + return noutput_items; +} + diff --git a/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.h b/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.h new file mode 100644 index 000000000..967ceaefb --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.h @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2007,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_FFT_VCC_FFTW_H +#define INCLUDED_GR_FFT_VCC_FFTW_H + +#include <gr_core_api.h> +#include <gr_fft_vcc.h> + +class gri_fft_complex; + +GR_CORE_API gr_fft_vcc_sptr +gr_make_fft_vcc_fftw (int fft_size, bool forward, + const std::vector<float> &window, + bool shift=false, int nthreads=1); + +/*! + * \brief Compute forward or reverse FFT. complex vector in / complex vector out. + * \ingroup dft_blk + * + * Concrete class that uses FFTW. + */ +class GR_CORE_API gr_fft_vcc_fftw : public gr_fft_vcc +{ + friend GR_CORE_API gr_fft_vcc_sptr + gr_make_fft_vcc_fftw (int fft_size, bool forward, + const std::vector<float> &window, + bool shift, int nthreads); + + gri_fft_complex *d_fft; + + gr_fft_vcc_fftw (int fft_size, bool forward, + const std::vector<float> &window, + bool shift, int nthreads=1); + + public: + ~gr_fft_vcc_fftw (); + + void set_nthreads(int n); + int nthreads() const; + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_FFT_VCC_FFTW_H */ diff --git a/gnuradio-core/src/lib/general/gr_fft_vfc.cc b/gnuradio-core/src/lib/general/gr_fft_vfc.cc new file mode 100644 index 000000000..2396055b9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fft_vfc.cc @@ -0,0 +1,135 @@ +/* -*- 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 <gr_fft_vfc.h> +#include <gr_io_signature.h> +#include <gri_fft.h> +#include <math.h> +#include <stdexcept> +#include <string.h> +#include <cstdio> + + +// FIXME after this is working, change to use native real to complex fft. +// It should run twice as fast. + + + + +gr_fft_vfc_sptr +gr_make_fft_vfc (int fft_size, bool forward, + const std::vector<float> &window, + int nthreads) +{ + return gnuradio::get_initial_sptr(new gr_fft_vfc (fft_size, forward, + window, nthreads)); +} + +gr_fft_vfc::gr_fft_vfc (int fft_size, bool forward, + const std::vector<float> &window, + int nthreads) + : gr_sync_block ("fft_vfc", + gr_make_io_signature (1, 1, fft_size * sizeof (float)), + gr_make_io_signature (1, 1, fft_size * sizeof (gr_complex))), + d_fft_size(fft_size), d_window() +{ + if (!forward){ + fprintf (stderr, "fft_vfc: forward must == true\n"); + throw std::invalid_argument ("fft_vfc: forward must == true"); + } + + d_fft = new gri_fft_complex (d_fft_size, forward, nthreads); + + set_window(window); +} + +gr_fft_vfc::~gr_fft_vfc () +{ + delete d_fft; +} + +void +gr_fft_vfc::set_nthreads(int n) +{ + d_fft->set_nthreads(n); +} + +int +gr_fft_vfc::nthreads() const +{ + return d_fft->nthreads(); +} + +int +gr_fft_vfc::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]; + gr_complex *out = (gr_complex *) output_items[0]; + + unsigned int output_data_size = output_signature()->sizeof_stream_item (0); + + int count = 0; + + while (count++ < noutput_items){ + + // copy input into optimally aligned buffer + + if (d_window.size()){ + gr_complex *dst = d_fft->get_inbuf(); + for (unsigned int i = 0; i < d_fft_size; i++) // apply window + dst[i] = in[i] * d_window[i]; + } + else { + gr_complex *dst = d_fft->get_inbuf(); + for (unsigned int i = 0; i < d_fft_size; i++) // float to complex conversion + dst[i] = in[i]; + } + + // compute the fft + d_fft->execute (); + + // cpoy result to our output + memcpy (out, d_fft->get_outbuf (), output_data_size); + + in += d_fft_size; + out += d_fft_size; + } + + return noutput_items; +} + +bool +gr_fft_vfc::set_window(const std::vector<float> &window) +{ + if(window.size()==0 || window.size()==d_fft_size) { + d_window=window; + return true; + } + else + return false; +} diff --git a/gnuradio-core/src/lib/general/gr_fft_vfc.h b/gnuradio-core/src/lib/general/gr_fft_vfc.h new file mode 100644 index 000000000..35b95313d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fft_vfc.h @@ -0,0 +1,72 @@ +/* -*- 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. + */ + +#ifndef INCLUDED_GR_FFT_VFC_H +#define INCLUDED_GR_FFT_VFC_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gri_fft_complex; + +class gr_fft_vfc; +typedef boost::shared_ptr<gr_fft_vfc> gr_fft_vfc_sptr; + +GR_CORE_API gr_fft_vfc_sptr +gr_make_fft_vfc (int fft_size, bool forward, + const std::vector<float> &window, + int nthreads=1); + +/*! + * \brief Compute forward FFT. float vector in / complex vector out. + * \ingroup dft_blk + */ + +class GR_CORE_API gr_fft_vfc : public gr_sync_block +{ + friend GR_CORE_API gr_fft_vfc_sptr + gr_make_fft_vfc (int fft_size, bool forward, + const std::vector<float> &window, + int nthreads); + + unsigned int d_fft_size; + std::vector<float> d_window; + gri_fft_complex *d_fft; + + gr_fft_vfc (int fft_size, bool forward, + const std::vector<float> &window, + int nthreads=1); + + public: + ~gr_fft_vfc (); + + void set_nthreads(int n); + int nthreads() const; + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + bool set_window(const std::vector<float> &window); +}; + + +#endif /* INCLUDED_GR_FFT_VFC_H */ diff --git a/gnuradio-core/src/lib/general/gr_fft_vfc.i b/gnuradio-core/src/lib/general/gr_fft_vfc.i new file mode 100644 index 000000000..d387ae155 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fft_vfc.i @@ -0,0 +1,42 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr, fft_vfc) + +gr_fft_vfc_sptr +gr_make_fft_vfc (int fft_size, bool forward, + const std::vector<float> &window, + int nthreads=1) +throw(std::exception); + +class gr_fft_vfc : public gr_sync_block +{ + protected: + gr_fft_vfc (int fft_size, bool forward, + const std::vector<float> &window, + int nthreads=1); + + public: + bool set_window(const std::vector<float> &window); + void set_nthreads(int n); + int nthreads() const; +}; diff --git a/gnuradio-core/src/lib/general/gr_firdes.cc b/gnuradio-core/src/lib/general/gr_firdes.cc new file mode 100644 index 000000000..4c7237141 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_firdes.cc @@ -0,0 +1,840 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2007,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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gr_firdes.h> +#include <stdexcept> + + +using std::vector; + +#define IzeroEPSILON 1E-21 /* Max error acceptable in Izero */ + +static double Izero(double x) +{ + double sum, u, halfx, temp; + int n; + + sum = u = n = 1; + halfx = x/2.0; + do { + temp = halfx/(double)n; + n += 1; + temp *= temp; + u *= temp; + sum += u; + } while (u >= IzeroEPSILON*sum); + return(sum); +} + + +// +// === Low Pass === +// + +vector<float> +gr_firdes::low_pass_2(double gain, + double sampling_freq, // Hz + double cutoff_freq, // Hz BEGINNING of transition band + double transition_width, // Hz width of transition band + double attenuation_dB, // attenuation dB + win_type window_type, + double beta) // used only with Kaiser +{ + sanity_check_1f (sampling_freq, cutoff_freq, transition_width); + + int ntaps = compute_ntaps_windes (sampling_freq, transition_width, + attenuation_dB); + + // construct the truncated ideal impulse response + // [sin(x)/x for the low pass case] + + vector<float> taps(ntaps); + vector<float> w = window (window_type, ntaps, beta); + + int M = (ntaps - 1) / 2; + double fwT0 = 2 * M_PI * cutoff_freq / sampling_freq; + for (int n = -M; n <= M; n++){ + if (n == 0) + taps[n + M] = fwT0 / M_PI * w[n + M]; + else { + // a little algebra gets this into the more familiar sin(x)/x form + taps[n + M] = sin (n * fwT0) / (n * M_PI) * w[n + M]; + } + } + + // find the factor to normalize the gain, fmax. + // For low-pass, gain @ zero freq = 1.0 + + double fmax = taps[0 + M]; + for (int n = 1; n <= M; n++) + fmax += 2 * taps[n + M]; + + gain /= fmax; // normalize + + for (int i = 0; i < ntaps; i++) + taps[i] *= gain; + + + return taps; +} + +vector<float> +gr_firdes::low_pass (double gain, + double sampling_freq, + double cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window_type, + double beta) // used only with Kaiser +{ + sanity_check_1f (sampling_freq, cutoff_freq, transition_width); + + int ntaps = compute_ntaps (sampling_freq, transition_width, + window_type, beta); + + // construct the truncated ideal impulse response + // [sin(x)/x for the low pass case] + + vector<float> taps(ntaps); + vector<float> w = window (window_type, ntaps, beta); + + int M = (ntaps - 1) / 2; + double fwT0 = 2 * M_PI * cutoff_freq / sampling_freq; + + for (int n = -M; n <= M; n++){ + if (n == 0) + taps[n + M] = fwT0 / M_PI * w[n + M]; + else { + // a little algebra gets this into the more familiar sin(x)/x form + taps[n + M] = sin (n * fwT0) / (n * M_PI) * w[n + M]; + } + } + + // find the factor to normalize the gain, fmax. + // For low-pass, gain @ zero freq = 1.0 + + double fmax = taps[0 + M]; + for (int n = 1; n <= M; n++) + fmax += 2 * taps[n + M]; + + gain /= fmax; // normalize + + for (int i = 0; i < ntaps; i++) + taps[i] *= gain; + + return taps; +} + + +// +// === High Pass === +// + +vector<float> +gr_firdes::high_pass_2 (double gain, + double sampling_freq, + double cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + double attenuation_dB, // attenuation dB + win_type window_type, + double beta) // used only with Kaiser +{ + sanity_check_1f (sampling_freq, cutoff_freq, transition_width); + + int ntaps = compute_ntaps_windes (sampling_freq, transition_width, + attenuation_dB); + + // construct the truncated ideal impulse response times the window function + + vector<float> taps(ntaps); + vector<float> w = window (window_type, ntaps, beta); + + int M = (ntaps - 1) / 2; + double fwT0 = 2 * M_PI * cutoff_freq / sampling_freq; + + for (int n = -M; n <= M; n++){ + if (n == 0) + taps[n + M] = (1 - (fwT0 / M_PI)) * w[n + M]; + else { + // a little algebra gets this into the more familiar sin(x)/x form + taps[n + M] = -sin (n * fwT0) / (n * M_PI) * w[n + M]; + } + } + + // find the factor to normalize the gain, fmax. + // For high-pass, gain @ fs/2 freq = 1.0 + + double fmax = taps[0 + M]; + for (int n = 1; n <= M; n++) + fmax += 2 * taps[n + M] * cos (n * M_PI); + + gain /= fmax; // normalize + + for (int i = 0; i < ntaps; i++) + taps[i] *= gain; + + + return taps; +} + + +vector<float> +gr_firdes::high_pass (double gain, + double sampling_freq, + double cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window_type, + double beta) // used only with Kaiser +{ + sanity_check_1f (sampling_freq, cutoff_freq, transition_width); + + int ntaps = compute_ntaps (sampling_freq, transition_width, + window_type, beta); + + // construct the truncated ideal impulse response times the window function + + vector<float> taps(ntaps); + vector<float> w = window (window_type, ntaps, beta); + + int M = (ntaps - 1) / 2; + double fwT0 = 2 * M_PI * cutoff_freq / sampling_freq; + + for (int n = -M; n <= M; n++){ + if (n == 0) + taps[n + M] = (1 - (fwT0 / M_PI)) * w[n + M]; + else { + // a little algebra gets this into the more familiar sin(x)/x form + taps[n + M] = -sin (n * fwT0) / (n * M_PI) * w[n + M]; + } + } + + // find the factor to normalize the gain, fmax. + // For high-pass, gain @ fs/2 freq = 1.0 + + double fmax = taps[0 + M]; + for (int n = 1; n <= M; n++) + fmax += 2 * taps[n + M] * cos (n * M_PI); + + gain /= fmax; // normalize + + for (int i = 0; i < ntaps; i++) + taps[i] *= gain; + + return taps; +} + +// +// === Band Pass === +// + +vector<float> +gr_firdes::band_pass_2 (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + double attenuation_dB, // attenuation dB + win_type window_type, + double beta) // used only with Kaiser +{ + sanity_check_2f (sampling_freq, + low_cutoff_freq, + high_cutoff_freq, transition_width); + + int ntaps = compute_ntaps_windes (sampling_freq, transition_width, + attenuation_dB); + + vector<float> taps(ntaps); + vector<float> w = window (window_type, ntaps, beta); + + int M = (ntaps - 1) / 2; + double fwT0 = 2 * M_PI * low_cutoff_freq / sampling_freq; + double fwT1 = 2 * M_PI * high_cutoff_freq / sampling_freq; + + for (int n = -M; n <= M; n++){ + if (n == 0) + taps[n + M] = (fwT1 - fwT0) / M_PI * w[n + M]; + else { + taps[n + M] = (sin (n * fwT1) - sin (n * fwT0)) / (n * M_PI) * w[n + M]; + } + } + + // find the factor to normalize the gain, fmax. + // For band-pass, gain @ center freq = 1.0 + + double fmax = taps[0 + M]; + for (int n = 1; n <= M; n++) + fmax += 2 * taps[n + M] * cos (n * (fwT0 + fwT1) * 0.5); + + gain /= fmax; // normalize + + for (int i = 0; i < ntaps; i++) + taps[i] *= gain; + + return taps; +} + + +vector<float> +gr_firdes::band_pass (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window_type, + double beta) // used only with Kaiser +{ + sanity_check_2f (sampling_freq, + low_cutoff_freq, + high_cutoff_freq, transition_width); + + int ntaps = compute_ntaps (sampling_freq, transition_width, + window_type, beta); + + // construct the truncated ideal impulse response times the window function + + vector<float> taps(ntaps); + vector<float> w = window (window_type, ntaps, beta); + + int M = (ntaps - 1) / 2; + double fwT0 = 2 * M_PI * low_cutoff_freq / sampling_freq; + double fwT1 = 2 * M_PI * high_cutoff_freq / sampling_freq; + + for (int n = -M; n <= M; n++){ + if (n == 0) + taps[n + M] = (fwT1 - fwT0) / M_PI * w[n + M]; + else { + taps[n + M] = (sin (n * fwT1) - sin (n * fwT0)) / (n * M_PI) * w[n + M]; + } + } + + // find the factor to normalize the gain, fmax. + // For band-pass, gain @ center freq = 1.0 + + double fmax = taps[0 + M]; + for (int n = 1; n <= M; n++) + fmax += 2 * taps[n + M] * cos (n * (fwT0 + fwT1) * 0.5); + + gain /= fmax; // normalize + + for (int i = 0; i < ntaps; i++) + taps[i] *= gain; + + return taps; +} + +// +// === Complex Band Pass === +// + +vector<gr_complex> +gr_firdes::complex_band_pass_2 (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + double attenuation_dB, // attenuation dB + win_type window_type, + double beta) // used only with Kaiser +{ + sanity_check_2f_c (sampling_freq, + low_cutoff_freq, + high_cutoff_freq, transition_width); + + int ntaps = compute_ntaps_windes (sampling_freq, transition_width, + attenuation_dB); + + + + vector<gr_complex> taps(ntaps); + vector<float> lptaps(ntaps); + vector<float> w = window (window_type, ntaps, beta); + + lptaps = low_pass_2(gain,sampling_freq,(high_cutoff_freq - low_cutoff_freq)/2,transition_width,attenuation_dB,window_type,beta); + + gr_complex *optr = &taps[0]; + float *iptr = &lptaps[0]; + float freq = M_PI * (high_cutoff_freq + low_cutoff_freq)/sampling_freq; + float phase=0; + if (lptaps.size() & 01) { + phase = - freq * ( lptaps.size() >> 1 ); + } else phase = - freq/2.0 * ((1 + 2*lptaps.size()) >> 1); + for(unsigned int i=0;i<lptaps.size();i++) { + *optr++ = gr_complex(*iptr * cos(phase),*iptr * sin(phase)); + iptr++, phase += freq; + } + + return taps; +} + + +vector<gr_complex> +gr_firdes::complex_band_pass (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window_type, + double beta) // used only with Kaiser +{ + sanity_check_2f_c (sampling_freq, + low_cutoff_freq, + high_cutoff_freq, transition_width); + + int ntaps = compute_ntaps (sampling_freq, transition_width, + window_type, beta); + + // construct the truncated ideal impulse response times the window function + + vector<gr_complex> taps(ntaps); + vector<float> lptaps(ntaps); + vector<float> w = window (window_type, ntaps, beta); + + lptaps = low_pass(gain,sampling_freq,(high_cutoff_freq - low_cutoff_freq)/2,transition_width,window_type,beta); + + gr_complex *optr = &taps[0]; + float *iptr = &lptaps[0]; + float freq = M_PI * (high_cutoff_freq + low_cutoff_freq)/sampling_freq; + float phase=0; + if (lptaps.size() & 01) { + phase = - freq * ( lptaps.size() >> 1 ); + } else phase = - freq/2.0 * ((1 + 2*lptaps.size()) >> 1); + for(unsigned int i=0;i<lptaps.size();i++) { + *optr++ = gr_complex(*iptr * cos(phase),*iptr * sin(phase)); + iptr++, phase += freq; + } + + return taps; +} + +// +// === Band Reject === +// + +vector<float> +gr_firdes::band_reject_2 (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + double attenuation_dB, // attenuation dB + win_type window_type, + double beta) // used only with Kaiser +{ + sanity_check_2f (sampling_freq, + low_cutoff_freq, + high_cutoff_freq, transition_width); + + int ntaps = compute_ntaps_windes (sampling_freq, transition_width, + attenuation_dB); + + // construct the truncated ideal impulse response times the window function + + vector<float> taps(ntaps); + vector<float> w = window (window_type, ntaps, beta); + + int M = (ntaps - 1) / 2; + double fwT0 = 2 * M_PI * low_cutoff_freq / sampling_freq; + double fwT1 = 2 * M_PI * high_cutoff_freq / sampling_freq; + + for (int n = -M; n <= M; n++){ + if (n == 0) + taps[n + M] = 1.0 + ((fwT0 - fwT1) / M_PI * w[n + M]); + else { + taps[n + M] = (sin (n * fwT0) - sin (n * fwT1)) / (n * M_PI) * w[n + M]; + } + } + + // find the factor to normalize the gain, fmax. + // For band-reject, gain @ zero freq = 1.0 + + double fmax = taps[0 + M]; + for (int n = 1; n <= M; n++) + fmax += 2 * taps[n + M]; + + gain /= fmax; // normalize + + for (int i = 0; i < ntaps; i++) + taps[i] *= gain; + + return taps; +} + +vector<float> +gr_firdes::band_reject (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window_type, + double beta) // used only with Kaiser +{ + sanity_check_2f (sampling_freq, + low_cutoff_freq, + high_cutoff_freq, transition_width); + + int ntaps = compute_ntaps (sampling_freq, transition_width, + window_type, beta); + + // construct the truncated ideal impulse response times the window function + + vector<float> taps(ntaps); + vector<float> w = window (window_type, ntaps, beta); + + int M = (ntaps - 1) / 2; + double fwT0 = 2 * M_PI * low_cutoff_freq / sampling_freq; + double fwT1 = 2 * M_PI * high_cutoff_freq / sampling_freq; + + for (int n = -M; n <= M; n++){ + if (n == 0) + taps[n + M] = 1.0 + ((fwT0 - fwT1) / M_PI * w[n + M]); + else { + taps[n + M] = (sin (n * fwT0) - sin (n * fwT1)) / (n * M_PI) * w[n + M]; + } + } + + // find the factor to normalize the gain, fmax. + // For band-reject, gain @ zero freq = 1.0 + + double fmax = taps[0 + M]; + for (int n = 1; n <= M; n++) + fmax += 2 * taps[n + M]; + + gain /= fmax; // normalize + + for (int i = 0; i < ntaps; i++) + taps[i] *= gain; + + return taps; +} + +// +// Hilbert Transform +// + +vector<float> +gr_firdes::hilbert (unsigned int ntaps, + win_type windowtype, + double beta) +{ + if(!(ntaps & 1)) + throw std::out_of_range("Hilbert: Must have odd number of taps"); + + vector<float> taps(ntaps); + vector<float> w = window (windowtype, ntaps, beta); + unsigned int h = (ntaps-1)/2; + float gain=0; + for (unsigned int i = 1; i <= h; i++) + { + if(i&1) + { + float x = 1/(float)i; + taps[h+i] = x * w[h+i]; + taps[h-i] = -x * w[h-i]; + gain = taps[h+i] - gain; + } + else + taps[h+i] = taps[h-i] = 0; + } + gain = 2 * fabs(gain); + for ( unsigned int i = 0; i < ntaps; i++) + taps[i] /= gain; + return taps; +} + +// +// Gaussian +// + +vector<float> +gr_firdes::gaussian (double gain, + double spb, + double bt, + int ntaps) +{ + + vector<float> taps(ntaps); + double scale = 0; + double dt = 1.0/spb; + double s = 1.0/(sqrt(log(2.0)) / (2*M_PI*bt)); + double t0 = -0.5 * ntaps; + double ts; + for(int i=0;i<ntaps;i++) + { + t0++; + ts = s*dt*t0; + taps[i] = exp(-0.5*ts*ts); + scale += taps[i]; + } + for(int i=0;i<ntaps;i++) + taps[i] = taps[i] / scale * gain; + return taps; +} + + +// +// Root Raised Cosine +// + +vector<float> +gr_firdes::root_raised_cosine (double gain, + double sampling_freq, + double symbol_rate, + double alpha, + int ntaps) +{ + ntaps |= 1; // ensure that ntaps is odd + + double spb = sampling_freq/symbol_rate; // samples per bit/symbol + vector<float> taps(ntaps); + double scale = 0; + for(int i=0;i<ntaps;i++) + { + double x1,x2,x3,num,den; + double xindx = i - ntaps/2; + x1 = M_PI * xindx/spb; + x2 = 4 * alpha * xindx / spb; + x3 = x2*x2 - 1; + if( fabs(x3) >= 0.000001 ) // Avoid Rounding errors... + { + if( i != ntaps/2 ) + num = cos((1+alpha)*x1) + sin((1-alpha)*x1)/(4*alpha*xindx/spb); + else + num = cos((1+alpha)*x1) + (1-alpha) * M_PI / (4*alpha); + den = x3 * M_PI; + } + else + { + if(alpha==1) + { + taps[i] = -1; + continue; + } + x3 = (1-alpha)*x1; + x2 = (1+alpha)*x1; + num = (sin(x2)*(1+alpha)*M_PI + - cos(x3)*((1-alpha)*M_PI*spb)/(4*alpha*xindx) + + sin(x3)*spb*spb/(4*alpha*xindx*xindx)); + den = -32 * M_PI * alpha * alpha * xindx/spb; + } + taps[i] = 4 * alpha * num / den; + scale += taps[i]; + } + + for(int i=0;i<ntaps;i++) + taps[i] = taps[i] * gain / scale; + + return taps; +} + +// +// === Utilities === +// + +// delta_f / width_factor gives number of taps required. +static const float width_factor[5] = { // indexed by win_type + 3.3, // WIN_HAMMING + 3.1, // WIN_HANN + 5.5, // WIN_BLACKMAN + 2.0, // WIN_RECTANGULAR + //5.0 // WIN_KAISER (guesstimate compromise) + //2.0 // WIN_KAISER (guesstimate compromise) + 10.0 // WIN_KAISER +}; + +int +gr_firdes::compute_ntaps_windes(double sampling_freq, + double transition_width, // this is frequency, not relative frequency + double attenuation_dB) +{ + // Based on formula from Multirate Signal Processing for + // Communications Systems, fredric j harris + int ntaps = (int)(attenuation_dB*sampling_freq/(22.0*transition_width)); + if ((ntaps & 1) == 0) // if even... + ntaps++; // ...make odd + return ntaps; +} + +int +gr_firdes::compute_ntaps (double sampling_freq, + double transition_width, + win_type window_type, + double beta) +{ + // normalized transition width + double delta_f = transition_width / sampling_freq; + + // compute number of taps required for given transition width + int ntaps = (int) (width_factor[window_type] / delta_f + 0.5); + if ((ntaps & 1) == 0) // if even... + ntaps++; // ...make odd + + return ntaps; +} + +double gr_firdes::bessi0(double x) +{ + double ax,ans; + double y; + + ax=fabs(x); + if (ax < 3.75) + { + y=x/3.75; + y*=y; + ans=1.0+y*(3.5156229+y*(3.0899424+y*(1.2067492 + +y*(0.2659732+y*(0.360768e-1+y*0.45813e-2))))); + } + else + { + y=3.75/ax; + ans=(exp(ax)/sqrt(ax))*(0.39894228+y*(0.1328592e-1 + +y*(0.225319e-2+y*(-0.157565e-2+y*(0.916281e-2 + +y*(-0.2057706e-1+y*(0.2635537e-1+y*(-0.1647633e-1 + +y*0.392377e-2)))))))); + } + return ans; +} +vector<float> +gr_firdes::window (win_type type, int ntaps, double beta) +{ + vector<float> taps(ntaps); + int M = ntaps - 1; // filter order + + switch (type){ + case WIN_RECTANGULAR: + for (int n = 0; n < ntaps; n++) + taps[n] = 1; + + case WIN_HAMMING: + for (int n = 0; n < ntaps; n++) + taps[n] = 0.54 - 0.46 * cos ((2 * M_PI * n) / M); + break; + + case WIN_HANN: + for (int n = 0; n < ntaps; n++) + taps[n] = 0.5 - 0.5 * cos ((2 * M_PI * n) / M); + break; + + case WIN_BLACKMAN: + for (int n = 0; n < ntaps; n++) + taps[n] = 0.42 - 0.50 * cos ((2*M_PI * n) / (M-1)) - 0.08 * cos ((4*M_PI * n) / (M-1)); + break; + + case WIN_BLACKMAN_hARRIS: + for (int n = -ntaps/2; n < ntaps/2; n++) + taps[n+ntaps/2] = 0.35875 + 0.48829*cos((2*M_PI * n) / (float)M) + + 0.14128*cos((4*M_PI * n) / (float)M) + 0.01168*cos((6*M_PI * n) / (float)M); + break; + +#if 0 + case WIN_KAISER: + for (int n = 0; n < ntaps; n++) + taps[n] = bessi0(beta*sqrt(1.0 - (4.0*n/(M*M))))/bessi0(beta); + break; +#else + + case WIN_KAISER: + { + double IBeta = 1.0/Izero(beta); + double inm1 = 1.0/((double)(ntaps)); + double temp; + //fprintf(stderr, "IBeta = %g; inm1 = %g\n", IBeta, inm1); + + for (int i=0; i<ntaps; i++) { + temp = i * inm1; + //fprintf(stderr, "temp = %g\n", temp); + taps[i] = Izero(beta*sqrt(1.0-temp*temp)) * IBeta; + //fprintf(stderr, "taps[%d] = %g\n", i, taps[i]); + } + } + break; + +#endif + default: + throw std::out_of_range ("gr_firdes:window: type out of range"); + } + + return taps; +} + +void +gr_firdes::sanity_check_1f (double sampling_freq, + double fa, // cutoff freq + double transition_width) +{ + if (sampling_freq <= 0.0) + throw std::out_of_range ("gr_firdes check failed: sampling_freq > 0"); + + if (fa <= 0.0 || fa > sampling_freq / 2) + throw std::out_of_range ("gr_firdes check failed: 0 < fa <= sampling_freq / 2"); + + if (transition_width <= 0) + throw std::out_of_range ("gr_dirdes check failed: transition_width > 0"); +} + +void +gr_firdes::sanity_check_2f (double sampling_freq, + double fa, // first cutoff freq + double fb, // second cutoff freq + double transition_width) +{ + if (sampling_freq <= 0.0) + throw std::out_of_range ("gr_firdes check failed: sampling_freq > 0"); + + if (fa <= 0.0 || fa > sampling_freq / 2) + throw std::out_of_range ("gr_firdes check failed: 0 < fa <= sampling_freq / 2"); + + if (fb <= 0.0 || fb > sampling_freq / 2) + throw std::out_of_range ("gr_firdes check failed: 0 < fb <= sampling_freq / 2"); + + if (fa > fb) + throw std::out_of_range ("gr_firdes check failed: fa <= fb"); + + if (transition_width <= 0) + throw std::out_of_range ("gr_firdes check failed: transition_width > 0"); +} + +void +gr_firdes::sanity_check_2f_c (double sampling_freq, + double fa, // first cutoff freq + double fb, // second cutoff freq + double transition_width) +{ + if (sampling_freq <= 0.0) + throw std::out_of_range ("gr_firdes check failed: sampling_freq > 0"); + + if (fa < -sampling_freq / 2 || fa > sampling_freq / 2) + throw std::out_of_range ("gr_firdes check failed: 0 < fa <= sampling_freq / 2"); + + if (fb < -sampling_freq / 2 || fb > sampling_freq / 2) + throw std::out_of_range ("gr_firdes check failed: 0 < fb <= sampling_freq / 2"); + + if (fa > fb) + throw std::out_of_range ("gr_firdes check failed: fa <= fb"); + + if (transition_width <= 0) + throw std::out_of_range ("gr_firdes check failed: transition_width > 0"); +} diff --git a/gnuradio-core/src/lib/general/gr_firdes.h b/gnuradio-core/src/lib/general/gr_firdes.h new file mode 100644 index 000000000..8d98ebe0a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_firdes.h @@ -0,0 +1,373 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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 _GR_FIRDES_H_ +#define _GR_FIRDES_H_ + +#include <gr_core_api.h> +#include <vector> +#include <cmath> +#include <gr_complex.h> + +/*! + * \brief Finite Impulse Response (FIR) filter design functions. + * \ingroup filter_design + */ + +class GR_CORE_API gr_firdes { + public: + + enum win_type { + WIN_HAMMING = 0, // max attenuation 53 dB + WIN_HANN = 1, // max attenuation 44 dB + WIN_BLACKMAN = 2, // max attenuation 74 dB + WIN_RECTANGULAR = 3, + WIN_KAISER = 4, // max attenuation a function of beta, google it + WIN_BLACKMAN_hARRIS = 5, + WIN_BLACKMAN_HARRIS = 5, // alias for capitalization consistency + }; + + + // ... class methods ... + + /*! + * \brief use "window method" to design a low-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * The normalized width of the transition + * band is what sets the number of taps + * required. Narrow --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + static std::vector<float> + low_pass (double gain, + double sampling_freq, + double cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*! + * \brief use "window method" to design a low-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * \p attenuation_dB required stopband attenuation + * The normalized width of the transition + * band and the required stop band + * attenuation is what sets the number of taps + * required. Narrow --> more taps + * More attenuatin --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector<float> + low_pass_2 (double gain, + double sampling_freq, + double cutoff_freq, // Hz beginning transition band + double transition_width, // Hz width of transition band + double attenuation_dB, // out of band attenuation dB + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*! + * \brief use "window method" to design a high-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * The normalized width of the transition + * band is what sets the number of taps + * required. Narrow --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector<float> + high_pass (double gain, + double sampling_freq, + double cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*! + * \brief use "window method" to design a high-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * \p attenuation_dB out of band attenuation + * The normalized width of the transition + * band and the required stop band + * attenuation is what sets the number of taps + * required. Narrow --> more taps + * More attenuation --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector<float> + high_pass_2 (double gain, + double sampling_freq, + double cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + double attenuation_dB, // out of band attenuation dB + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*! + * \brief use "window method" to design a band-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p low_cutoff_freq: center of transition band (Hz) + * \p high_cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * The normalized width of the transition + * band is what sets the number of taps + * required. Narrow --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + static std::vector<float> + band_pass (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*! + * \brief use "window method" to design a band-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p low_cutoff_freq: center of transition band (Hz) + * \p high_cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * \p attenuation_dB out of band attenuation + * The normalized width of the transition + * band and the required stop band + * attenuation is what sets the number of taps + * required. Narrow --> more taps + * More attenuation --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector<float> + band_pass_2 (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz beginning transition band + double high_cutoff_freq, // Hz beginning transition band + double transition_width, // Hz width of transition band + double attenuation_dB, // out of band attenuation dB + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*! + * \brief use "window method" to design a complex band-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p low_cutoff_freq: center of transition band (Hz) + * \p high_cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * The normalized width of the transition + * band is what sets the number of taps + * required. Narrow --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector<gr_complex> + complex_band_pass (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*! + * \brief use "window method" to design a complex band-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p low_cutoff_freq: center of transition band (Hz) + * \p high_cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * \p attenuation_dB out of band attenuation + * The normalized width of the transition + * band and the required stop band + * attenuation is what sets the number of taps + * required. Narrow --> more taps + * More attenuation --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector<gr_complex> + complex_band_pass_2 (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz beginning transition band + double high_cutoff_freq, // Hz beginning transition band + double transition_width, // Hz width of transition band + double attenuation_dB, // out of band attenuation dB + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*! + * \brief use "window method" to design a band-reject FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p low_cutoff_freq: center of transition band (Hz) + * \p high_cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * The normalized width of the transition + * band is what sets the number of taps + * required. Narrow --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector<float> + band_reject (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*! + * \brief use "window method" to design a band-reject FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p low_cutoff_freq: center of transition band (Hz) + * \p high_cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * \p attenuation_dB out of band attenuation + * The normalized width of the transition + * band and the required stop band + * attenuation is what sets the number of taps + * required. Narrow --> more taps + * More attenuation --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector<float> + band_reject_2 (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz beginning transition band + double high_cutoff_freq, // Hz beginning transition band + double transition_width, // Hz width of transition band + double attenuation_dB, // out of band attenuation dB + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*!\brief design a Hilbert Transform Filter + * + * \p ntaps: Number of taps, must be odd + * \p window_type: What kind of window to use + * \p beta: Only used for Kaiser + */ + static std::vector<float> + hilbert (unsigned int ntaps = 19, + win_type windowtype = WIN_RECTANGULAR, + double beta = 6.76); + + /*! + * \brief design a Root Cosine FIR Filter (do we need a window?) + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p symbol rate: symbol rate, must be a factor of sample rate + * \p alpha: excess bandwidth factor + * \p ntaps: number of taps + */ + static std::vector<float> + root_raised_cosine (double gain, + double sampling_freq, + double symbol_rate, // Symbol rate, NOT bitrate (unless BPSK) + double alpha, // Excess Bandwidth Factor + int ntaps); + + /*! + * \brief design a Gaussian filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p symbols per bit: symbol rate, must be a factor of sample rate + * \p ntaps: number of taps + */ + static std::vector<float> + gaussian (double gain, + double spb, + double bt, // Bandwidth to bitrate ratio + int ntaps); + + // window functions ... + static std::vector<float> window (win_type type, int ntaps, double beta); + +private: + static double bessi0(double x); + static void sanity_check_1f (double sampling_freq, double f1, + double transition_width); + static void sanity_check_2f (double sampling_freq, double f1, double f2, + double transition_width); + static void sanity_check_2f_c (double sampling_freq, double f1, double f2, + double transition_width); + + static int compute_ntaps (double sampling_freq, + double transition_width, + win_type window_type, double beta); + + static int compute_ntaps_windes (double sampling_freq, + double transition_width, + double attenuation_dB); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_firdes.i b/gnuradio-core/src/lib/general/gr_firdes.i new file mode 100644 index 000000000..0493db617 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_firdes.i @@ -0,0 +1,360 @@ +/* -*- C++ -*- */ +/* + * Copyright 2002,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. + */ + +/*! + * \brief Finite Impulse Response (FIR) filter design functions. + */ + +%rename(firdes) gr_firdes; + +class gr_firdes { + public: + + enum win_type { + WIN_HAMMING = 0, // max attenuation 53 dB + WIN_HANN = 1, // max attenuation 44 dB + WIN_BLACKMAN = 2, // max attenuation 74 dB + WIN_RECTANGULAR = 3, + WIN_KAISER = 4, // max attenuation variable with beta, google it + WIN_BLACKMAN_hARRIS = 5, + }; + + // ... class methods ... + + /*! + * \brief use "window method" to design a low-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * The normalized width of the transition + * band is what sets the number of taps + * required. Narrow --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + static std::vector<float> + low_pass (double gain, + double sampling_freq, + double cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window = WIN_HAMMING, + double beta = 6.76 // used only with Kaiser + ) throw(std::out_of_range); + + /*! + * \brief use "window method" to design a low-pass FIR filter + * using alternative design criteria + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * \p attenuation_dB out of band attenuation + * The normalized width of the transition + * band and the required stop band + * attenuation is what sets the number of taps + * required. Narrow --> more taps + * More attenuation --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + static std::vector<float> + low_pass_2 (double gain, + double sampling_freq, + double cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + double attenuation_dB, // out of band attenuation + win_type window = WIN_HAMMING, + double beta = 6.76 // used only with Kaiser + ) throw(std::out_of_range); + + /*! + * \brief use "window method" to design a high-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * The normalized width of the transition + * band is what sets the number of taps + * required. Narrow --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector<float> + high_pass (double gain, + double sampling_freq, + double cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window = WIN_HAMMING, + double beta = 6.76 // used only with Kaiser + ) throw(std::out_of_range); + + /*! + * \brief use "window method" to design a high-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * \p attenuation_dB out of band attenuation + * The normalized width of the transition + * band and the required stop band + * attenuation is what sets the number of taps + * required. Narrow --> more taps + * More attenuation --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector<float> + high_pass_2 (double gain, + double sampling_freq, + double cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + double attenuation_dB, // out of band attenuation dB + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + + /*! + * \brief use "window method" to design a band-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p low_cutoff_freq: center of transition band (Hz) + * \p high_cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * The normalized width of the transition + * band is what sets the number of taps + * required. Narrow --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector<float> + band_pass (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window = WIN_HAMMING, + double beta = 6.76 // used only with Kaiser + ) throw(std::out_of_range); + + + /*! + * \brief use "window method" to design a band-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p low_cutoff_freq: center of transition band (Hz) + * \p high_cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * \p attenuation_dB out of band attenuation + * The normalized width of the transition + * band and the required stop band + * attenuation is what sets the number of taps + * required. Narrow --> more taps + * More attenuation --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector<float> + band_pass_2 (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz beginning transition band + double high_cutoff_freq, // Hz beginning transition band + double transition_width, // Hz width of transition band + double attenuation_dB, // out of band attenuation dB + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*! + * \brief use "window method" to design a band-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p low_cutoff_freq: center of transition band (Hz) + * \p high_cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * The normalized width of the transition + * band is what sets the number of taps + * required. Narrow --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector<gr_complex> + complex_band_pass (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window = WIN_HAMMING, // used only with Kaiser + double beta = 6.76 + ) throw(std::out_of_range); + + + /*! + * \brief use "window method" to design a complex band-pass FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p low_cutoff_freq: center of transition band (Hz) + * \p high_cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * \p attenuation_dB out of band attenuation + * The normalized width of the transition + * band and the required stop band + * attenuation is what sets the number of taps + * required. Narrow --> more taps + * More attenuation --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector<gr_complex> + complex_band_pass_2 (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz beginning transition band + double high_cutoff_freq, // Hz beginning transition band + double transition_width, // Hz width of transition band + double attenuation_dB, // out of band attenuation dB + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*! + * \brief use "window method" to design a band-reject FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p low_cutoff_freq: center of transition band (Hz) + * \p high_cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * The normalized width of the transition + * band is what sets the number of taps + * required. Narrow --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector<float> + band_reject (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz center of transition band + double high_cutoff_freq, // Hz center of transition band + double transition_width, // Hz width of transition band + win_type window = WIN_HAMMING, // used only with Kaiser + double beta = 6.76 + ) throw(std::out_of_range); + + + /*! + * \brief use "window method" to design a band-reject FIR filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p low_cutoff_freq: center of transition band (Hz) + * \p high_cutoff_freq: center of transition band (Hz) + * \p transition_width: width of transition band (Hz). + * \p attenuation_dB out of band attenuation + * The normalized width of the transition + * band and the required stop band + * attenuation is what sets the number of taps + * required. Narrow --> more taps + * More attenuation --> more taps + * \p window_type: What kind of window to use. Determines + * maximum attenuation and passband ripple. + * \p beta: parameter for Kaiser window + */ + + static std::vector<float> + band_reject_2 (double gain, + double sampling_freq, + double low_cutoff_freq, // Hz beginning transition band + double high_cutoff_freq, // Hz beginning transition band + double transition_width, // Hz width of transition band + double attenuation_dB, // out of band attenuation dB + win_type window = WIN_HAMMING, + double beta = 6.76); // used only with Kaiser + + /*!\brief design a Hilbert Transform Filter + * + * \p ntaps: Number of taps, must be odd + * \p window_type: What kind of window to use + * \p beta: Only used for Kaiser + */ + static std::vector<float> + hilbert (unsigned int ntaps = 19, + win_type windowtype = WIN_RECTANGULAR, + double beta = 6.76 + ) throw(std::out_of_range); + + /*! + * \brief design a Root Cosine FIR Filter (do we need a window?) + * + * \p gain: overall gain of filter (typically 1.0) + * \p sampling_freq: sampling freq (Hz) + * \p symbol rate: symbol rate, must be a factor of sample rate + * \p alpha: excess bandwidth factor + * \p ntaps: number of taps + */ + static std::vector<float> + root_raised_cosine (double gain, + double sampling_freq, + double symbol_rate, // Symbol rate, NOT bitrate (unless BPSK) + double alpha, // Excess Bandwidth Factor + int ntaps) throw(std::out_of_range); + + /*! + * \brief design a Gaussian filter + * + * \p gain: overall gain of filter (typically 1.0) + * \p symbols per bit: symbol rate, must be a factor of sample rate + * \p bt: BT bandwidth time product + * \p ntaps: number of taps + */ + static std::vector<float> + gaussian (double gain, + double spb, + double bt, // Bandwidth to bitrate ratio + int ntaps) throw(std::out_of_range); + + /*! + * Return window given type, ntaps and optional beta. + */ + static std::vector<float> gr_firdes::window (win_type type, int ntaps, double beta) + throw(std::runtime_error); +}; diff --git a/gnuradio-core/src/lib/general/gr_float_to_char.cc b/gnuradio-core/src/lib/general/gr_float_to_char.cc new file mode 100644 index 000000000..d67ded3ea --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_char.cc @@ -0,0 +1,79 @@ +/* -*- 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 <gr_float_to_char.h> +#include <gr_io_signature.h> +#include <volk/volk.h> + +gr_float_to_char_sptr +gr_make_float_to_char (size_t vlen, float scale) +{ + return gnuradio::get_initial_sptr(new gr_float_to_char (vlen, scale)); +} + +gr_float_to_char::gr_float_to_char (size_t vlen, float scale) + : gr_sync_block ("gr_float_to_char", + gr_make_io_signature (1, 1, sizeof (float)*vlen), + gr_make_io_signature (1, 1, sizeof (char)*vlen)), + d_vlen(vlen), d_scale(scale) +{ + const int alignment_multiple = + volk_get_alignment() / sizeof(char); + set_alignment(std::max(1,alignment_multiple)); +} + +float +gr_float_to_char::scale() const +{ + return d_scale; +} + +void +gr_float_to_char::set_scale(float scale) +{ + d_scale = scale; +} + +int +gr_float_to_char::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]; + int8_t *out = (int8_t *) output_items[0]; + + if(is_unaligned()) { + volk_32f_s32f_convert_8i_u(out, in, d_scale, d_vlen*noutput_items); + } + else { + volk_32f_s32f_convert_8i_a(out, in, d_scale, d_vlen*noutput_items); + } + + return noutput_items; +} + + + diff --git a/gnuradio-core/src/lib/general/gr_float_to_char.h b/gnuradio-core/src/lib/general/gr_float_to_char.h new file mode 100644 index 000000000..2df50f18d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_char.h @@ -0,0 +1,70 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_GR_FLOAT_TO_CHAR_H +#define INCLUDED_GR_FLOAT_TO_CHAR_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_float_to_char; +typedef boost::shared_ptr<gr_float_to_char> gr_float_to_char_sptr; + +GR_CORE_API gr_float_to_char_sptr +gr_make_float_to_char (size_t vlen=1, float scale=1); + +/*! + * \brief Convert stream of float to a stream of char + * \ingroup converter_blk + * + * \param vlen vector length of data streams. + * \param scale a scalar multiplier to change the output signal scale. + */ + +class GR_CORE_API gr_float_to_char : public gr_sync_block +{ + private: + friend GR_CORE_API gr_float_to_char_sptr gr_make_float_to_char + (size_t vlen, float scale); + gr_float_to_char (size_t vlen, float scale); + + size_t d_vlen; + float d_scale; + + public: + /*! + * Get the scalar multiplier value. + */ + float scale() const; + + /*! + * Set the scalar multiplier value. + */ + void set_scale(float scale); + + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_FLOAT_TO_CHAR_H */ diff --git a/gnuradio-core/src/lib/general/gr_float_to_char.i b/gnuradio-core/src/lib/general/gr_float_to_char.i new file mode 100644 index 000000000..b40389ede --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_char.i @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,float_to_char) + +gr_float_to_char_sptr +gr_make_float_to_char (size_t vlen=1, float scale=1); + +class gr_float_to_char : public gr_sync_block +{ +public: + float scale() const; + void set_scale(float scale); +}; diff --git a/gnuradio-core/src/lib/general/gr_float_to_complex.cc b/gnuradio-core/src/lib/general/gr_float_to_complex.cc new file mode 100644 index 000000000..c68eac8c7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_complex.cc @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004, 2009,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_float_to_complex.h> +#include <gr_io_signature.h> + +gr_float_to_complex_sptr +gr_make_float_to_complex (size_t vlen) +{ + return gnuradio::get_initial_sptr(new gr_float_to_complex (vlen)); +} + +gr_float_to_complex::gr_float_to_complex (size_t vlen) + : gr_sync_block ("gr_float_to_complex", + gr_make_io_signature (1, 2, sizeof (float) * vlen), + gr_make_io_signature (1, 1, sizeof (gr_complex) * vlen)), + d_vlen (vlen) +{ +} + +int +gr_float_to_complex::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float *r = (float *)input_items[0]; + float *i = (float *)input_items[1]; + gr_complex *out = (gr_complex *) output_items[0]; + + switch (input_items.size ()){ + case 1: + for (size_t j = 0; j < noutput_items*d_vlen; j++) + out[j] = gr_complex (r[j], 0); + break; + + case 2: + for (size_t j = 0; j < noutput_items*d_vlen; j++) + out[j] = gr_complex (r[j], i[j]); + break; + + default: + assert (0); + } + + return noutput_items; +} + + + diff --git a/gnuradio-core/src/lib/general/gr_float_to_complex.h b/gnuradio-core/src/lib/general/gr_float_to_complex.h new file mode 100644 index 000000000..628b4a954 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_complex.h @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004, 2009 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_FLOAT_TO_COMPLEX_H +#define INCLUDED_GR_FLOAT_TO_COMPLEX_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_complex.h> + +class gr_float_to_complex; +typedef boost::shared_ptr<gr_float_to_complex> gr_float_to_complex_sptr; + +GR_CORE_API gr_float_to_complex_sptr +gr_make_float_to_complex (size_t vlen = 1); + +/*! + * \brief Convert 1 or 2 streams of float to a stream of gr_complex + * \ingroup converter_blk + */ + +class GR_CORE_API gr_float_to_complex : public gr_sync_block +{ + friend GR_CORE_API gr_float_to_complex_sptr gr_make_float_to_complex (size_t vlen); + gr_float_to_complex (size_t vlen); + + size_t d_vlen; + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_FLOAT_TO_COMPLEX_H */ diff --git a/gnuradio-core/src/lib/general/gr_float_to_complex.i b/gnuradio-core/src/lib/general/gr_float_to_complex.i new file mode 100644 index 000000000..ed5ad128b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_complex.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004, 2009 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,float_to_complex) + +gr_float_to_complex_sptr gr_make_float_to_complex (size_t vlen = 1); + +class gr_float_to_complex : public gr_sync_block +{ + gr_float_to_complex (size_t vlen); +}; diff --git a/gnuradio-core/src/lib/general/gr_float_to_int.cc b/gnuradio-core/src/lib/general/gr_float_to_int.cc new file mode 100644 index 000000000..43b851895 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_int.cc @@ -0,0 +1,89 @@ +/* -*- 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 <gr_float_to_int.h> +#include <gr_io_signature.h> +#include <gri_float_to_int.h> +#include <volk/volk.h> + +gr_float_to_int_sptr +gr_make_float_to_int (size_t vlen, float scale) +{ + return gnuradio::get_initial_sptr(new gr_float_to_int (vlen, scale)); +} + +gr_float_to_int::gr_float_to_int (size_t vlen, float scale) + : gr_sync_block ("gr_float_to_int", + gr_make_io_signature (1, 1, sizeof (float)*vlen), + gr_make_io_signature (1, 1, sizeof (int)*vlen)), + d_vlen(vlen), d_scale(scale) +{ + const int alignment_multiple = + volk_get_alignment() / sizeof(int); + set_alignment(std::max(1,alignment_multiple)); +} + +float +gr_float_to_int::scale() const +{ + return d_scale; +} + +void +gr_float_to_int::set_scale(float scale) +{ + d_scale = scale; +} +int +gr_float_to_int::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + // Disable the Volk for now. There is a problem for large 32-bit ints that + // are not properly represented by the precisions of a single float, which + // can cause wrapping from large, positive numbers to negative. + // In gri_float_to_int, the value is first promoted to a 64-bit + // value, clipped, then converted to a float. +#if 0 + const float *in = (const float *) input_items[0]; + int32_t *out = (int32_t *) output_items[0]; + + if(is_unaligned()) { + volk_32f_s32f_convert_32i_u(out, in, d_scale, d_vlen*noutput_items); + } + else { + volk_32f_s32f_convert_32i_a(out, in, d_scale, d_vlen*noutput_items); + } +#else + const float *in = (const float *) input_items[0]; + int *out = (int *) output_items[0]; + + gri_float_to_int (in, out, d_scale, d_vlen*noutput_items); + +#endif + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_float_to_int.h b/gnuradio-core/src/lib/general/gr_float_to_int.h new file mode 100644 index 000000000..c10ea739d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_int.h @@ -0,0 +1,70 @@ +/* -*- 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_GR_FLOAT_TO_INT_H +#define INCLUDED_GR_FLOAT_TO_INT_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_float_to_int; +typedef boost::shared_ptr<gr_float_to_int> gr_float_to_int_sptr; + +GR_CORE_API gr_float_to_int_sptr +gr_make_float_to_int (size_t vlen=1, float scale=1); + +/*! + * \brief Convert stream of float to a stream of short + * \ingroup converter_blk + * + * \param vlen vector length of data streams. + * \param scale a scalar multiplier to change the output signal scale. + */ + +class GR_CORE_API gr_float_to_int : public gr_sync_block +{ + private: + friend GR_CORE_API + gr_float_to_int_sptr gr_make_float_to_int (size_t vlen, float scale); + gr_float_to_int (size_t vlen, float scale); + + size_t d_vlen; + float d_scale; + + public: + /*! + * Get the scalar multiplier value. + */ + float scale() const; + + /*! + * Set the scalar multiplier value. + */ + void set_scale(float scale); + + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_FLOAT_TO_INT_H */ diff --git a/gnuradio-core/src/lib/general/gr_float_to_int.i b/gnuradio-core/src/lib/general/gr_float_to_int.i new file mode 100644 index 000000000..e2a2c53ce --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_int.i @@ -0,0 +1,33 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,float_to_int) + +gr_float_to_int_sptr +gr_make_float_to_int (size_t vlen=1, float scale=1); + +class gr_float_to_int : public gr_sync_block +{ +public: + float scale() const; + void set_scale(float scale); +}; diff --git a/gnuradio-core/src/lib/general/gr_float_to_short.cc b/gnuradio-core/src/lib/general/gr_float_to_short.cc new file mode 100644 index 000000000..ab720168b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_short.cc @@ -0,0 +1,79 @@ +/* -*- 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 <gr_float_to_short.h> +#include <gr_io_signature.h> +#include <volk/volk.h> + +gr_float_to_short_sptr +gr_make_float_to_short (size_t vlen, float scale) +{ + return gnuradio::get_initial_sptr(new gr_float_to_short (vlen, scale)); +} + +gr_float_to_short::gr_float_to_short (size_t vlen, float scale) + : gr_sync_block ("gr_float_to_short", + gr_make_io_signature (1, 1, sizeof (float)*vlen), + gr_make_io_signature (1, 1, sizeof (short)*vlen)), + d_vlen(vlen), d_scale(scale) +{ + const int alignment_multiple = + volk_get_alignment() / sizeof(short); + set_alignment(std::max(1,alignment_multiple)); +} + +float +gr_float_to_short::scale() const +{ + return d_scale; +} + +void +gr_float_to_short::set_scale(float scale) +{ + d_scale = scale; +} + +int +gr_float_to_short::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]; + short *out = (short *) output_items[0]; + + if(is_unaligned()) { + volk_32f_s32f_convert_16i_u(out, in, d_scale, d_vlen*noutput_items); + } + else { + volk_32f_s32f_convert_16i_a(out, in, d_scale, d_vlen*noutput_items); + } + + return noutput_items; +} + + + diff --git a/gnuradio-core/src/lib/general/gr_float_to_short.h b/gnuradio-core/src/lib/general/gr_float_to_short.h new file mode 100644 index 000000000..9e43804f5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_short.h @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_GR_FLOAT_TO_SHORT_H +#define INCLUDED_GR_FLOAT_TO_SHORT_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_float_to_short; +typedef boost::shared_ptr<gr_float_to_short> gr_float_to_short_sptr; + +GR_CORE_API gr_float_to_short_sptr +gr_make_float_to_short (size_t vlen=1, float scale=1); + +/*! + * \brief Convert stream of float to a stream of short + * \ingroup converter_blk + * + * \param vlen vector length of data streams. + * \param scale a scalar multiplier to change the output signal scale. + */ + +class GR_CORE_API gr_float_to_short : public gr_sync_block +{ + friend GR_CORE_API + gr_float_to_short_sptr gr_make_float_to_short (size_t vlen, float scale); + gr_float_to_short (size_t vlen, float scale); + + size_t d_vlen; + float d_scale; + + public: + /*! + * Get the scalar multiplier value. + */ + float scale() const; + + /*! + * Set the scalar multiplier value. + */ + void set_scale(float scale); + + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_FLOAT_TO_SHORT_H */ diff --git a/gnuradio-core/src/lib/general/gr_float_to_short.i b/gnuradio-core/src/lib/general/gr_float_to_short.i new file mode 100644 index 000000000..ea59a388e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_short.i @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,float_to_short) + +gr_float_to_short_sptr +gr_make_float_to_short (size_t vlen=1, float scale=1); + +class gr_float_to_short : public gr_sync_block +{ +public: + float scale() const; + void set_scale(float scale); +}; diff --git a/gnuradio-core/src/lib/general/gr_float_to_uchar.cc b/gnuradio-core/src/lib/general/gr_float_to_uchar.cc new file mode 100644 index 000000000..5aec73b71 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_uchar.cc @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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_float_to_uchar.h> +#include <gr_io_signature.h> +#include <gri_float_to_uchar.h> + +gr_float_to_uchar_sptr +gr_make_float_to_uchar () +{ + return gnuradio::get_initial_sptr(new gr_float_to_uchar ()); +} + +gr_float_to_uchar::gr_float_to_uchar () + : gr_sync_block ("gr_float_to_uchar", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (unsigned char))) +{ +} + +int +gr_float_to_uchar::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]; + unsigned char *out = (unsigned char *) output_items[0]; + + gri_float_to_uchar (in, out, noutput_items); + + return noutput_items; +} + + + diff --git a/gnuradio-core/src/lib/general/gr_float_to_uchar.h b/gnuradio-core/src/lib/general/gr_float_to_uchar.h new file mode 100644 index 000000000..7fd947048 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_uchar.h @@ -0,0 +1,52 @@ +/* -*- 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_FLOAT_TO_UCHAR_H +#define INCLUDED_GR_FLOAT_TO_UCHAR_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_float_to_uchar; +typedef boost::shared_ptr<gr_float_to_uchar> gr_float_to_uchar_sptr; + +GR_CORE_API gr_float_to_uchar_sptr +gr_make_float_to_uchar (); + +/*! + * \brief Convert stream of float to a stream of unsigned char + * \ingroup converter_blk + */ + +class GR_CORE_API gr_float_to_uchar : public gr_sync_block +{ + friend GR_CORE_API gr_float_to_uchar_sptr gr_make_float_to_uchar (); + gr_float_to_uchar (); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_FLOAT_TO_UCHAR_H */ diff --git a/gnuradio-core/src/lib/general/gr_float_to_uchar.i b/gnuradio-core/src/lib/general/gr_float_to_uchar.i new file mode 100644 index 000000000..b35979213 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_uchar.i @@ -0,0 +1,30 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,float_to_uchar) + +gr_float_to_uchar_sptr gr_make_float_to_uchar (); + +class gr_float_to_uchar : public gr_sync_block +{ + gr_float_to_uchar (); +}; diff --git a/gnuradio-core/src/lib/general/gr_fmdet_cf.cc b/gnuradio-core/src/lib/general/gr_fmdet_cf.cc new file mode 100644 index 000000000..f02036292 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fmdet_cf.cc @@ -0,0 +1,105 @@ +/* -*- 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_fmdet_cf.h> +#include <gr_io_signature.h> +#include <math.h> +#include <gr_math.h> + +#define M_TWOPI (2*M_PI) + +gr_fmdet_cf_sptr +gr_make_fmdet_cf (float samplerate, float freq_low, float freq_high, float scl) +{ + return gnuradio::get_initial_sptr(new gr_fmdet_cf (samplerate, freq_low, freq_high, scl)); +} + +gr_fmdet_cf::gr_fmdet_cf (float samplerate, float freq_low, float freq_high, float scl) + : gr_sync_block ("fmdet_cf", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (float))), + d_S1(0.1),d_S2(0.1), + d_S3(0.1),d_S4(0.1) +{ + const float h[]={0.003118678733, -0.012139843428, 0.027270898036, -0.051318579352, + 0.090406910552, -0.162926865366, 0.361885392563, 0.000000000000, + -0.361885392563, 0.162926865366, -0.090406910552, 0.051318579352, + -0.027270898036, 0.012139843428, -0.003118678733}; + + + + + float delta; + std::vector<float> taps(15); + + d_freqhi = freq_high; + d_freqlo = freq_low; + delta = (d_freqhi - d_freqlo); + d_scl = scl; + d_bias = 0.5*scl*(d_freqhi+d_freqlo)/delta; + for (int i=0;i<15;i++) taps[i] = h[i]; + // d_filter = gr_fir_util::create_gr_fir_ccf(taps); + +} + +int +gr_fmdet_cf::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const gr_complex *iptr = (gr_complex *) input_items[0]; + float *optr = (float *) output_items[0]; + // const gr_complex *scaleiptr = (gr_complex *) input_items[0]; + + int size = noutput_items; + + gr_complex Sdot,S0,S1=d_S1,S2=d_S2,S3=d_S3,S4=d_S4; + float d_8 = 8.0; + + while (size-- > 0) { + S0=*iptr++; + + + Sdot = d_scl * (-S0+d_8*S1-d_8*S1+S4); + + d_freq = (S2.real()*Sdot.imag()-S2.imag()*Sdot.real())/ + (S2.real()*S2.real()+S2.imag()*S2.imag()); + + S4=S3; + S3=S2; + S2=S1; + S1=S0; + + + *optr++ = d_freq-d_bias; + } + d_S1=S1; + d_S2=S2; + d_S3=S3; + d_S4=S4; + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_fmdet_cf.h b/gnuradio-core/src/lib/general/gr_fmdet_cf.h new file mode 100644 index 000000000..f85630f2f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fmdet_cf.h @@ -0,0 +1,63 @@ +/* -*- 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_FMDET_CF_H +#define INCLUDED_GR_FMDET_CF_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_fmdet_cf; +typedef boost::shared_ptr<gr_fmdet_cf> gr_fmdet_cf_sptr; + +GR_CORE_API gr_fmdet_cf_sptr gr_make_fmdet_cf (float samplerate, float freq_low, float freq_high, float scl); + +class gr_fir_ccf; + + +/*! + * \brief Implements an IQ slope detector + * + * + * input: stream of complex; output: stream of floats + * + * This implements a limiting slope detector. The limiter is in the + * normalization by the magnitude of the sample + */ + +class GR_CORE_API gr_fmdet_cf : public gr_sync_block +{ + friend GR_CORE_API gr_fmdet_cf_sptr gr_make_fmdet_cf (float samplerate, float freq_low, + float freq_high, float scl); + + gr_complex d_S1,d_S2,d_S3,d_S4; + float d_freq,d_freqlo,d_freqhi,d_scl,d_bias; + gr_fir_ccf* d_filter; + gr_fmdet_cf (float samplerate, float freq_low, float freq_high, float scl); + + 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_fmdet_cf.i b/gnuradio-core/src/lib/general/gr_fmdet_cf.i new file mode 100644 index 000000000..2db596b7a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fmdet_cf.i @@ -0,0 +1,31 @@ +/* -*- 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,fmdet_cf) + +gr_fmdet_cf_sptr gr_make_fmdet_cf (float samplerate, float freq_low, float freq_high, float scl); + +class gr_fmdet_cf : public gr_sync_block +{ + private: + gr_fmdet_cf (float samplerate, float freq_low, float freq_high, float scl); +}; diff --git a/gnuradio-core/src/lib/general/gr_framer_sink_1.cc b/gnuradio-core/src/lib/general/gr_framer_sink_1.cc new file mode 100644 index 000000000..64a0af6a0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_framer_sink_1.cc @@ -0,0 +1,190 @@ +/* -*- 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 new file mode 100644 index 000000000..93e41745f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_framer_sink_1.h @@ -0,0 +1,107 @@ +/* -*- 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 new file mode 100644 index 000000000..06281b138 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_framer_sink_1.i @@ -0,0 +1,35 @@ +/* -*- 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_frequency_modulator_fc.cc b/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.cc new file mode 100644 index 000000000..5c4daec58 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.cc @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_frequency_modulator_fc.h> +#include <gr_io_signature.h> +#include <gr_fxpt.h> +#include <math.h> +#include <boost/math/special_functions/trunc.hpp> + + +gr_frequency_modulator_fc_sptr gr_make_frequency_modulator_fc (double sensitivity) +{ + return gnuradio::get_initial_sptr(new gr_frequency_modulator_fc (sensitivity)); +} + +gr_frequency_modulator_fc::gr_frequency_modulator_fc (double sensitivity) + : gr_sync_block ("frequency_modulator_fc", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (gr_complex))), + d_sensitivity (sensitivity), d_phase (0) +{ +} + +int +gr_frequency_modulator_fc::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]; + gr_complex *out = (gr_complex *) output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + d_phase = d_phase + d_sensitivity * in[i]; + + while (d_phase > (float)(M_PI)) + d_phase -= (float)(2.0 * M_PI); + while (d_phase < (float)(-M_PI)) + d_phase += (float)(2.0 * M_PI); + + float oi, oq; + + gr_int32 angle = gr_fxpt::float_to_fixed (d_phase); + gr_fxpt::sincos (angle, &oq, &oi); + out[i] = gr_complex (oi, oq); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.h b/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.h new file mode 100644 index 000000000..c680e9648 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.h @@ -0,0 +1,59 @@ +/* -*- 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_FREQUENCY_MODULATOR_FC_H +#define INCLUDED_GR_FREQUENCY_MODULATOR_FC_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_frequency_modulator_fc; +typedef boost::shared_ptr<gr_frequency_modulator_fc> gr_frequency_modulator_fc_sptr; + +GR_CORE_API gr_frequency_modulator_fc_sptr gr_make_frequency_modulator_fc (double sensitivity); + +/*! + * \brief Frequency modulator block + * \ingroup modulation_blk + * + * float input; complex baseband output + */ +class GR_CORE_API gr_frequency_modulator_fc : public gr_sync_block +{ + float d_sensitivity; + float d_phase; + + friend GR_CORE_API gr_frequency_modulator_fc_sptr + gr_make_frequency_modulator_fc (double sensitivity); + + gr_frequency_modulator_fc (double sensitivity); + + public: + void set_sensitivity(float sens) { d_sensitivity = sens; } + float sensitivity() const { return d_sensitivity; } + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_FREQUENCY_MODULATOR_FC_H */ diff --git a/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.i b/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.i new file mode 100644 index 000000000..9a740583b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.i @@ -0,0 +1,34 @@ +/* -*- 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,frequency_modulator_fc) + +gr_frequency_modulator_fc_sptr gr_make_frequency_modulator_fc (double sensitivity); + +class gr_frequency_modulator_fc : public gr_sync_block +{ + private: + gr_frequency_modulator_fc (double sensitivity); +public: + void set_sensitivity(float sens) { d_sensitivity = sens; } + float sensitivity() const { return d_sensitivity; } +}; diff --git a/gnuradio-core/src/lib/general/gr_fxpt.cc b/gnuradio-core/src/lib/general/gr_fxpt.cc new file mode 100644 index 000000000..2ea8520e6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fxpt.cc @@ -0,0 +1,35 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_fxpt.h> + +const float gr_fxpt::s_sine_table[1 << NBITS][2] = { +#include "sine_table.h" +}; + +const float gr_fxpt::PI = 3.14159265358979323846; +const float gr_fxpt::TWO_TO_THE_31 = 2147483648.0; + diff --git a/gnuradio-core/src/lib/general/gr_fxpt.h b/gnuradio-core/src/lib/general/gr_fxpt.h new file mode 100644 index 000000000..9de6c0c18 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fxpt.h @@ -0,0 +1,104 @@ +/* -*- 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_FXPT_H +#define INCLUDED_GR_FXPT_H + +#include <gr_core_api.h> +#include <gr_types.h> + +/*! + * \brief fixed point sine and cosine and friends. + * \ingroup misc + * + * fixed pt radians + * --------- -------- + * -2**31 -pi + * 0 0 + * 2**31-1 pi - epsilon + * + */ +class GR_CORE_API gr_fxpt +{ + static const int WORDBITS = 32; + static const int NBITS = 10; + static const float s_sine_table[1 << NBITS][2]; + static const float PI; + static const float TWO_TO_THE_31; +public: + + static gr_int32 + float_to_fixed (float x) + { + // Fold x into -PI to PI. + int d = (int)floor(x/2/PI+0.5); + x -= d*2*PI; + // And convert to an integer. + return (gr_int32) ((float) x * TWO_TO_THE_31 / PI); + } + + static float + fixed_to_float (gr_int32 x) + { + return x * (PI / TWO_TO_THE_31); + } + + /*! + * \brief Given a fixed point angle x, return float sine (x) + */ + static float + sin (gr_int32 x) + { + gr_uint32 ux = x; + int index = ux >> (WORDBITS - NBITS); + return s_sine_table[index][0] * (ux >> 1) + s_sine_table[index][1]; + } + + /* + * \brief Given a fixed point angle x, return float cosine (x) + */ + static float + cos (gr_int32 x) + { + gr_uint32 ux = x + 0x40000000; + int index = ux >> (WORDBITS - NBITS); + return s_sine_table[index][0] * (ux >> 1) + s_sine_table[index][1]; + } + + /* + * \brief Given a fixedpoint angle x, return float cos(x) and sin (x) + */ + static void sincos(gr_int32 x, float *s, float *c) + { + gr_uint32 ux = x; + int sin_index = ux >> (WORDBITS - NBITS); + *s = s_sine_table[sin_index][0] * (ux >> 1) + s_sine_table[sin_index][1]; + + ux = x + 0x40000000; + int cos_index = ux >> (WORDBITS - NBITS); + *c = s_sine_table[cos_index][0] * (ux >> 1) + s_sine_table[cos_index][1]; + + return; + } + +}; + +#endif /* INCLUDED_GR_FXPT_H */ diff --git a/gnuradio-core/src/lib/general/gr_fxpt_nco.h b/gnuradio-core/src/lib/general/gr_fxpt_nco.h new file mode 100644 index 000000000..9473e6ddb --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fxpt_nco.h @@ -0,0 +1,153 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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_FXPT_NCO_H +#define INCLUDED_GR_FXPT_NCO_H + +#include <gr_core_api.h> +#include <gr_fxpt.h> +#include <gr_complex.h> + +/*! + * \brief Numerically Controlled Oscillator (NCO) + * \ingroup misc + */ +class GR_CORE_API gr_fxpt_nco { + gr_uint32 d_phase; + gr_int32 d_phase_inc; + +public: + gr_fxpt_nco () : d_phase (0), d_phase_inc (0) {} + + ~gr_fxpt_nco () {} + + // radians + void set_phase (float angle) { + d_phase = gr_fxpt::float_to_fixed (angle); + } + + void adjust_phase (float delta_phase) { + d_phase += gr_fxpt::float_to_fixed (delta_phase); + } + + // angle_rate is in radians / step + void set_freq (float angle_rate){ + d_phase_inc = gr_fxpt::float_to_fixed (angle_rate); + } + + // angle_rate is a delta in radians / step + void adjust_freq (float delta_angle_rate) + { + d_phase_inc += gr_fxpt::float_to_fixed (delta_angle_rate); + } + + // increment current phase angle + + void step () + { + d_phase += d_phase_inc; + } + + void step (int n) + { + d_phase += d_phase_inc * n; + } + + // units are radians / step + float get_phase () const { return gr_fxpt::fixed_to_float (d_phase); } + float get_freq () const { return gr_fxpt::fixed_to_float (d_phase_inc); } + + // compute sin and cos for current phase angle + void sincos (float *sinx, float *cosx) const + { + *sinx = gr_fxpt::sin (d_phase); + *cosx = gr_fxpt::cos (d_phase); + } + + // compute cos and sin for a block of phase angles + void sincos (gr_complex *output, int noutput_items, double ampl=1.0) + { + for (int i = 0; i < noutput_items; i++){ + output[i] = gr_complex(gr_fxpt::cos (d_phase) * ampl, gr_fxpt::sin (d_phase) * ampl); + step (); + } + } + + // compute sin for a block of phase angles + void sin (float *output, int noutput_items, double ampl=1.0) + { + for (int i = 0; i < noutput_items; i++){ + output[i] = (float)(gr_fxpt::sin (d_phase) * ampl); + step (); + } + } + + // compute cos for a block of phase angles + void cos (float *output, int noutput_items, double ampl=1.0) + { + for (int i = 0; i < noutput_items; i++){ + output[i] = (float)(gr_fxpt::cos (d_phase) * ampl); + step (); + } + } + + // compute sin for a block of phase angles + void sin (short *output, int noutput_items, double ampl=1.0) + { + for (int i = 0; i < noutput_items; i++){ + output[i] = (short)(gr_fxpt::sin (d_phase) * ampl); + step (); + } + } + + // compute cos for a block of phase angles + void cos (short *output, int noutput_items, double ampl=1.0) + { + for (int i = 0; i < noutput_items; i++){ + output[i] = (short)(gr_fxpt::cos (d_phase) * ampl); + step (); + } + } + + // compute sin for a block of phase angles + void sin (int *output, int noutput_items, double ampl=1.0) + { + for (int i = 0; i < noutput_items; i++){ + output[i] = (int)(gr_fxpt::sin (d_phase) * ampl); + step (); + } + } + + // compute cos for a block of phase angles + void cos (int *output, int noutput_items, double ampl=1.0) + { + for (int i = 0; i < noutput_items; i++){ + output[i] = (int)(gr_fxpt::cos (d_phase) * ampl); + step (); + } + } + + // compute cos or sin for current phase angle + float cos () const { return gr_fxpt::cos (d_phase); } + float sin () const { return gr_fxpt::sin (d_phase); } +}; + +#endif /* INCLUDED_GR_FXPT_NCO_H */ diff --git a/gnuradio-core/src/lib/general/gr_fxpt_vco.h b/gnuradio-core/src/lib/general/gr_fxpt_vco.h new file mode 100644 index 000000000..09c649de7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fxpt_vco.h @@ -0,0 +1,73 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2004,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_FXPT_VCO_H +#define INCLUDED_GR_FXPT_VCO_H + +#include <gr_core_api.h> +#include <gr_fxpt.h> +#include <gr_complex.h> + +/*! + * \brief Voltage Controlled Oscillator (VCO) + * \ingroup misc + */ +class GR_CORE_API gr_fxpt_vco { + gr_int32 d_phase; + +public: + gr_fxpt_vco () : d_phase (0) {} + + ~gr_fxpt_vco () {} + + // radians + void set_phase (float angle) { + d_phase = gr_fxpt::float_to_fixed (angle); + } + + void adjust_phase (float delta_phase) { + d_phase += gr_fxpt::float_to_fixed (delta_phase); + } + + float get_phase () const { return gr_fxpt::fixed_to_float (d_phase); } + + // compute sin and cos for current phase angle + void sincos (float *sinx, float *cosx) const + { + *sinx = gr_fxpt::sin (d_phase); + *cosx = gr_fxpt::cos (d_phase); + } + + // compute a block at a time + void cos (float *output, const float *input, int noutput_items, float k, float ampl = 1.0) + { + for (int i = 0; i < noutput_items; i++){ + output[i] = (float)(gr_fxpt::cos (d_phase) * ampl); + adjust_phase(input[i] * k); + } + } + + // compute cos or sin for current phase angle + float cos () const { return gr_fxpt::cos (d_phase); } + float sin () const { return gr_fxpt::sin (d_phase); } +}; + +#endif /* INCLUDED_GR_FXPT_VCO_H */ diff --git a/gnuradio-core/src/lib/general/gr_glfsr_source_b.cc b/gnuradio-core/src/lib/general/gr_glfsr_source_b.cc new file mode 100644 index 000000000..fcfeb80dc --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_glfsr_source_b.cc @@ -0,0 +1,84 @@ +/* -*- 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 new file mode 100644 index 000000000..7549a76b3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_glfsr_source_b.h @@ -0,0 +1,66 @@ +/* -*- 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 new file mode 100644 index 000000000..ffdd52ddb --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_glfsr_source_b.i @@ -0,0 +1,37 @@ +/* -*- 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 new file mode 100644 index 000000000..a9efc8a70 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_glfsr_source_f.cc @@ -0,0 +1,84 @@ +/* -*- 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 new file mode 100644 index 000000000..3549e3e5d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_glfsr_source_f.h @@ -0,0 +1,66 @@ +/* -*- 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 new file mode 100644 index 000000000..2f84387c2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_glfsr_source_f.i @@ -0,0 +1,37 @@ +/* -*- 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 new file mode 100644 index 000000000..cb07c84dd --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_head.cc @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2009 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_head.h> +#include <gr_io_signature.h> +#include <string.h> + +gr_head::gr_head (size_t sizeof_stream_item, unsigned long long nitems) + : gr_sync_block ("head", + gr_make_io_signature (1, 1, sizeof_stream_item), + gr_make_io_signature (1, 1, sizeof_stream_item)), + d_nitems (nitems), d_ncopied_items (0) +{ +} + +gr_head_sptr +gr_make_head (size_t sizeof_stream_item, unsigned long long nitems) +{ + return gnuradio::get_initial_sptr(new gr_head (sizeof_stream_item, nitems)); +} + +int +gr_head::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + if (d_ncopied_items >= d_nitems) + return -1; // Done! + + unsigned n = std::min (d_nitems - d_ncopied_items, (unsigned long long) noutput_items); + + if (n == 0) + return 0; + + memcpy (output_items[0], input_items[0], n * input_signature()->sizeof_stream_item (0)); + d_ncopied_items += n; + + return n; +} diff --git a/gnuradio-core/src/lib/general/gr_head.h b/gnuradio-core/src/lib/general/gr_head.h new file mode 100644 index 000000000..48415892d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_head.h @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2009,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_GR_HEAD_H +#define INCLUDED_GR_HEAD_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <stddef.h> // size_t + +class gr_head; +typedef boost::shared_ptr<gr_head> gr_head_sptr; + +/*! + * \brief copies the first N items to the output then signals done + * \ingroup slicedice_blk + * + * Useful for building test cases + */ + +class GR_CORE_API gr_head : public gr_sync_block +{ + friend GR_CORE_API gr_head_sptr gr_make_head (size_t sizeof_stream_item, unsigned long long nitems); + gr_head (size_t sizeof_stream_item, unsigned long long nitems); + + unsigned long long d_nitems; + unsigned long long d_ncopied_items; + + public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void reset() { d_ncopied_items = 0; } + void set_length(int nitems) { d_nitems = nitems; } +}; + +GR_CORE_API gr_head_sptr +gr_make_head (size_t sizeof_stream_item, unsigned long long nitems); + + +#endif /* INCLUDED_GR_HEAD_H */ diff --git a/gnuradio-core/src/lib/general/gr_head.i b/gnuradio-core/src/lib/general/gr_head.i new file mode 100644 index 000000000..11f3331d4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_head.i @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2009,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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,head); + +gr_head_sptr gr_make_head(size_t sizeof_stream_item, unsigned long long nitems); + +class gr_head : public gr_block { + gr_head(); +public: + void reset(); + void set_length(int nitems); +}; + diff --git a/gnuradio-core/src/lib/general/gr_int_to_float.cc b/gnuradio-core/src/lib/general/gr_int_to_float.cc new file mode 100644 index 000000000..a7fb24dc6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_int_to_float.cc @@ -0,0 +1,67 @@ +/* -*- 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 <gr_int_to_float.h> +#include <gr_io_signature.h> +#include <volk/volk.h> + +gr_int_to_float_sptr +gr_make_int_to_float (size_t vlen, float scale) +{ + return gnuradio::get_initial_sptr(new gr_int_to_float (vlen, scale)); +} + +gr_int_to_float::gr_int_to_float (size_t vlen, float scale) + : gr_sync_block ("gr_int_to_float", + gr_make_io_signature (1, 1, sizeof (int32_t)*vlen), + gr_make_io_signature (1, 1, sizeof (float)*vlen)), + d_vlen(vlen), d_scale(scale) +{ + const int alignment_multiple = + volk_get_alignment() / sizeof(float); + set_alignment(std::max(1,alignment_multiple)); +} + +int +gr_int_to_float::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const int32_t *in = (const int32_t *) input_items[0]; + float *out = (float *) output_items[0]; + + if(is_unaligned()) { + volk_32i_s32f_convert_32f_u(out, in, d_scale, d_vlen*noutput_items); + } + else { + volk_32i_s32f_convert_32f_a(out, in, d_scale, d_vlen*noutput_items); + } + + return noutput_items; +} + + + diff --git a/gnuradio-core/src/lib/general/gr_int_to_float.h b/gnuradio-core/src/lib/general/gr_int_to_float.h new file mode 100644 index 000000000..6200c5be7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_int_to_float.h @@ -0,0 +1,70 @@ +/* -*- 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_GR_INT_TO_FLOAT_H +#define INCLUDED_GR_INT_TO_FLOAT_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_int_to_float; +typedef boost::shared_ptr<gr_int_to_float> gr_int_to_float_sptr; + +GR_CORE_API gr_int_to_float_sptr +gr_make_int_to_float (size_t vlen=1, float scale=1); + +/*! + * \brief Convert stream of int to a stream of float + * \ingroup converter_blk + * + * \param vlen vector length of data streams. + * \param scale a scalar divider to change the output signal scale. + */ + +class GR_CORE_API gr_int_to_float : public gr_sync_block +{ + private: + friend GR_CORE_API gr_int_to_float_sptr + gr_make_int_to_float (size_t vlen, float scale); + gr_int_to_float (size_t vlen, float scale); + + size_t d_vlen; + float d_scale; + + public: + /*! + * Get the scalar divider value. + */ + float scale() const; + + /*! + * Set the scalar divider value. + */ + void set_scale(float scale); + + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_INT_TO_FLOAT_H */ diff --git a/gnuradio-core/src/lib/general/gr_int_to_float.i b/gnuradio-core/src/lib/general/gr_int_to_float.i new file mode 100644 index 000000000..f3781ac8a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_int_to_float.i @@ -0,0 +1,32 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,int_to_float) + +gr_int_to_float_sptr +gr_make_int_to_float (size_t vlen=1, float scale=1); + +class gr_int_to_float : public gr_sync_block +{ + float scale() const; + void set_scale(float scale); +}; diff --git a/gnuradio-core/src/lib/general/gr_interleave.cc b/gnuradio-core/src/lib/general/gr_interleave.cc new file mode 100644 index 000000000..5d572871e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_interleave.cc @@ -0,0 +1,77 @@ +/* -*- 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_interleave.h> +#include <gr_io_signature.h> +#include <string.h> + + +gr_interleave_sptr +gr_make_interleave (size_t itemsize) +{ + return gnuradio::get_initial_sptr(new gr_interleave (itemsize)); +} + +gr_interleave::gr_interleave (size_t itemsize) + : gr_sync_interpolator ("interleave", + gr_make_io_signature (1, gr_io_signature::IO_INFINITE, itemsize), + gr_make_io_signature (1, 1, itemsize), + 1), + d_itemsize (itemsize) +{ +} + +gr_interleave::~gr_interleave () +{ + // NOP +} + +bool +gr_interleave::check_topology (int ninputs, int noutputs) +{ + set_interpolation (ninputs); + return true; +} + +int +gr_interleave::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + size_t nchan = input_items.size (); + size_t itemsize = d_itemsize; + const char **in = (const char **) &input_items[0]; + char *out = (char *) output_items[0]; + + for (int i = 0; i < noutput_items; i += nchan){ + for (unsigned int n = 0; n < nchan; n++){ + memcpy (out, in[n], itemsize); + out += itemsize; + in[n] += itemsize; + } + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_interleave.h b/gnuradio-core/src/lib/general/gr_interleave.h new file mode 100644 index 000000000..3b0202d00 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_interleave.h @@ -0,0 +1,57 @@ +/* -*- 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_INTERLEAVE_H +#define INCLUDED_GR_INTERLEAVE_H + +#include <gr_core_api.h> +#include <gr_sync_interpolator.h> + +class gr_interleave; +typedef boost::shared_ptr<gr_interleave> gr_interleave_sptr; + +GR_CORE_API gr_interleave_sptr gr_make_interleave (size_t itemsize); + +/*! + * \brief interleave N inputs to a single output + * \ingroup slicedice_blk + */ +class GR_CORE_API gr_interleave : public gr_sync_interpolator +{ + friend GR_CORE_API gr_interleave_sptr gr_make_interleave (size_t itemsize); + + size_t d_itemsize; + + gr_interleave (size_t itemsize); + +public: + ~gr_interleave (); + + 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); + +}; + +#endif /* INCLUDED_GR_INTERLEAVE_H */ diff --git a/gnuradio-core/src/lib/general/gr_interleave.i b/gnuradio-core/src/lib/general/gr_interleave.i new file mode 100644 index 000000000..09a57c886 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_interleave.i @@ -0,0 +1,30 @@ +/* -*- 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,interleave) + +gr_interleave_sptr gr_make_interleave (size_t itemsize); + +class gr_interleave : public gr_sync_interpolator +{ + gr_interleave (size_t itemsize); +}; diff --git a/gnuradio-core/src/lib/general/gr_interleaved_short_to_complex.cc b/gnuradio-core/src/lib/general/gr_interleaved_short_to_complex.cc new file mode 100644 index 000000000..e7d375a35 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_interleaved_short_to_complex.cc @@ -0,0 +1,59 @@ +/* -*- 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_interleaved_short_to_complex.h> +#include <gr_io_signature.h> +#include <gri_interleaved_short_to_complex.h> + +gr_interleaved_short_to_complex_sptr +gr_make_interleaved_short_to_complex () +{ + return gnuradio::get_initial_sptr(new gr_interleaved_short_to_complex ()); +} + +gr_interleaved_short_to_complex::gr_interleaved_short_to_complex () + : gr_sync_decimator ("gr_interleaved_short_to_complex", + gr_make_io_signature (1, 1, sizeof (short)), + gr_make_io_signature (1, 1, sizeof (gr_complex)), + 2) +{ +} + +int +gr_interleaved_short_to_complex::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const short *in = (const short *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + gri_interleaved_short_to_complex (in, out, 2 * noutput_items); + + return noutput_items; +} + + + diff --git a/gnuradio-core/src/lib/general/gr_interleaved_short_to_complex.h b/gnuradio-core/src/lib/general/gr_interleaved_short_to_complex.h new file mode 100644 index 000000000..159d107b3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_interleaved_short_to_complex.h @@ -0,0 +1,52 @@ +/* -*- 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_INTERLEAVED_SHORT_TO_COMPLEX_H +#define INCLUDED_GR_INTERLEAVED_SHORT_TO_COMPLEX_H + +#include <gr_core_api.h> +#include <gr_sync_decimator.h> + +class gr_interleaved_short_to_complex; +typedef boost::shared_ptr<gr_interleaved_short_to_complex> + gr_interleaved_short_to_complex_sptr; + +GR_CORE_API gr_interleaved_short_to_complex_sptr +gr_make_interleaved_short_to_complex (); + +/*! + * \brief Convert stream of interleaved shorts to a stream of complex + * \ingroup converter_blk + */ + +class GR_CORE_API gr_interleaved_short_to_complex : public gr_sync_decimator +{ + friend GR_CORE_API gr_interleaved_short_to_complex_sptr gr_make_interleaved_short_to_complex (); + gr_interleaved_short_to_complex (); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_INTERLEAVED_SHORT_TO_COMPLEX_H */ diff --git a/gnuradio-core/src/lib/general/gr_interleaved_short_to_complex.i b/gnuradio-core/src/lib/general/gr_interleaved_short_to_complex.i new file mode 100644 index 000000000..797710550 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_interleaved_short_to_complex.i @@ -0,0 +1,30 @@ +/* -*- 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,interleaved_short_to_complex) + +gr_interleaved_short_to_complex_sptr gr_make_interleaved_short_to_complex (); + +class gr_interleaved_short_to_complex : public gr_sync_decimator +{ + gr_interleaved_short_to_complex (); +}; diff --git a/gnuradio-core/src/lib/general/gr_iqcomp_cc.cc b/gnuradio-core/src/lib/general/gr_iqcomp_cc.cc new file mode 100644 index 000000000..599b25b72 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_iqcomp_cc.cc @@ -0,0 +1,62 @@ +/* -*- 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_iqcomp_cc.h> +#include <gr_io_signature.h> + +gr_iqcomp_cc_sptr +gr_make_iqcomp_cc (float mu) +{ + return gnuradio::get_initial_sptr(new gr_iqcomp_cc (mu)); +} + +gr_iqcomp_cc::gr_iqcomp_cc (float mu) + : gr_sync_block ("iqcomp_cc", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (gr_complex))), + d_mu (mu) +{ + d_wi=0.0; + d_wq=0.0; +} + +int +gr_iqcomp_cc::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const gr_complex *iptr = (gr_complex *) input_items[0]; + // gr_complex *optr = (gr_complex *) output_items[0]; + + for(int i = 0 ; i < noutput_items ; i++) { + float i_out = iptr[i].real() - iptr[i].imag() * d_wq; + float q_out = iptr[i].imag() - iptr[i].real() * d_wi; + d_wi += d_mu * q_out * iptr[i].real(); + d_wq += d_mu * i_out * iptr[i].imag(); + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_iqcomp_cc.h b/gnuradio-core/src/lib/general/gr_iqcomp_cc.h new file mode 100644 index 000000000..2f5a44ebf --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_iqcomp_cc.h @@ -0,0 +1,55 @@ +/* -*- 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_IQCOMP_CC_H +#define INCLUDED_GR_IQCOMP_CC_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_iqcomp_cc; +typedef boost::shared_ptr<gr_iqcomp_cc> gr_iqcomp_cc_sptr; + +GR_CORE_API gr_iqcomp_cc_sptr gr_make_iqcomp_cc (float mu); + +/*! + * \brief + * \ingroup misc_blk + */ +class GR_CORE_API gr_iqcomp_cc : public gr_sync_block +{ + friend GR_CORE_API gr_iqcomp_cc_sptr gr_make_iqcomp_cc (float mu); + + float d_mu, d_wi, d_wq; + gr_iqcomp_cc (float mu); + + public: + float mu () const { return d_mu; } + void set_mu (float mu) { d_mu = mu; } + + 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_iqcomp_cc.i b/gnuradio-core/src/lib/general/gr_iqcomp_cc.i new file mode 100644 index 000000000..5cca59dd5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_iqcomp_cc.i @@ -0,0 +1,36 @@ +/* -*- 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,iqcomp_cc) + +gr_iqcomp_cc_sptr gr_make_iqcomp_cc (float mu); + +class gr_iqcomp_cc : public gr_sync_block +{ + private: + gr_iqcomp_cc (float mu); + + public: + float mu () const { return d_mu; } + void set_mu (float mu) { d_mu = mu; } +}; diff --git a/gnuradio-core/src/lib/general/gr_keep_m_in_n.cc b/gnuradio-core/src/lib/general/gr_keep_m_in_n.cc new file mode 100644 index 000000000..1becbfa11 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_keep_m_in_n.cc @@ -0,0 +1,98 @@ +/* -*- 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 <gr_keep_m_in_n.h> +#include <gr_io_signature.h> +#include <string.h> +#include <stdio.h> + +gr_keep_m_in_n_sptr +gr_make_keep_m_in_n(size_t item_size, int m, int n, int offset) +{ + return gnuradio::get_initial_sptr(new gr_keep_m_in_n(item_size, m, n, offset)); +} + + +/* +* +* offset = 0, starts with 0th item +* offset = 1, starts with 1st item, etc... +* +* we take m items out of each n +*/ +gr_keep_m_in_n::gr_keep_m_in_n(size_t item_size, int m, int n, int offset) + : gr_block("keep_m_in_n", + gr_make_io_signature(1, 1, item_size), + gr_make_io_signature(1, 1, item_size)), + d_n(n), + d_m(m), + d_offset(offset), + d_itemsize(item_size) +{ + // sanity checking + assert(d_m > 0); + assert(d_n > 0); + assert(d_m <= d_n); + assert(d_offset <= (d_n-d_m)); + + set_output_multiple(m); +} + + +void +gr_keep_m_in_n::forecast(int noutput_items, gr_vector_int &ninput_items_required) +{ + ninput_items_required[0] = d_n*(noutput_items/d_m); +} + +void +gr_keep_m_in_n::set_offset(int offset) +{ + d_offset = offset; +} + +int +gr_keep_m_in_n::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + uint8_t* out = (uint8_t*)output_items[0]; + const uint8_t* in = (const uint8_t*)input_items[0]; + + // iterate over data blocks of size {n, input : m, output} + int blks = std::min(noutput_items/d_m, ninput_items[0]/d_n); + for(int i=0; i<blks; i++) { + // set up copy pointers + const uint8_t* iptr = &in[(i*d_n + d_offset)*d_itemsize]; + uint8_t* optr = &out[i*d_m*d_itemsize]; + // perform copy + memcpy( optr, iptr, d_m*d_itemsize ); + } + + consume_each(d_n); + return d_m; +} diff --git a/gnuradio-core/src/lib/general/gr_keep_m_in_n.h b/gnuradio-core/src/lib/general/gr_keep_m_in_n.h new file mode 100644 index 000000000..c6bf40ecf --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_keep_m_in_n.h @@ -0,0 +1,67 @@ +/* -*- 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_GR_KEEP_M_IN_N_H +#define INCLUDED_GR_KEEP_M_IN_N_H + +#include <gr_core_api.h> +#include <gr_block.h> + +class gr_keep_m_in_n; +typedef boost::shared_ptr<gr_keep_m_in_n> gr_keep_m_in_n_sptr; + +GR_CORE_API gr_keep_m_in_n_sptr +gr_make_keep_m_in_n (size_t item_size, int m, int n, int offset); + + +/*! + * \brief decimate a stream, keeping one item out of every n. + * \ingroup slicedice_blk + */ +class GR_CORE_API gr_keep_m_in_n : public gr_block +{ + friend GR_CORE_API gr_keep_m_in_n_sptr + gr_make_keep_m_in_n (size_t item_size, int m, int n, int offset); + + int d_n; + int d_m; + int d_count; + int d_offset; + int d_itemsize; + + protected: + gr_keep_m_in_n (size_t item_size, int m, int n, int offset); + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + + public: + int general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void set_offset(int offset); + void set_n(int n){ d_n = n; } + void set_m(int m){ d_m = m; } + +}; + +#endif /* INCLUDED_GR_KEEP_M_IN_N_H */ diff --git a/gnuradio-core/src/lib/general/gr_keep_m_in_n.i b/gnuradio-core/src/lib/general/gr_keep_m_in_n.i new file mode 100644 index 000000000..f280c0248 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_keep_m_in_n.i @@ -0,0 +1,35 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,keep_m_in_n) + +gr_keep_m_in_n_sptr +gr_make_keep_m_in_n (size_t itemsize, int m, int n, int offset); + +class gr_keep_m_in_n : public gr_sync_block +{ + protected: + gr_keep_m_in_n (size_t itemsize, int m, int n, int offset); + public: + void set_offset(int offset); + +}; diff --git a/gnuradio-core/src/lib/general/gr_keep_one_in_n.cc b/gnuradio-core/src/lib/general/gr_keep_one_in_n.cc new file mode 100644 index 000000000..fbba9e91c --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_keep_one_in_n.cc @@ -0,0 +1,105 @@ +/* -*- 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_keep_one_in_n.h> +#include <gr_io_signature.h> +#include <string.h> + +gr_keep_one_in_n_sptr +gr_make_keep_one_in_n (size_t item_size, int n) +{ + return gnuradio::get_initial_sptr(new gr_keep_one_in_n (item_size, n)); +} + +gr_keep_one_in_n::gr_keep_one_in_n (size_t item_size, int n) + : gr_block ("keep_one_in_n", + gr_make_io_signature (1, 1, item_size), + gr_make_io_signature (1, 1, item_size)), + d_count(n) +{ + // To avoid bad behavior with using set_relative_rate in this block with + // VERY large values of n, we will keep track of things ourselves. Using + // this to turn off automatic tag propagation, which will be handled + // locally in general_work(). + set_tag_propagation_policy(TPP_DONT); + + set_n(n); +} + +void +gr_keep_one_in_n::set_n(int n) +{ + if (n < 1) + n = 1; + + d_n = n; + d_count = n; + + // keep our internal understanding of the relative rate of this block + // don't set the relative rate, though, and we will handle our own + // tag propagation. + d_decim_rate = 1.0/(float)d_n; +} + +int +gr_keep_one_in_n::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const char *in = (const char *) input_items[0]; + char *out = (char *) output_items[0]; + + size_t item_size = input_signature ()->sizeof_stream_item (0); + int ni = 0; + int no = 0; + + while (ni < ninput_items[0] && no < noutput_items){ + d_count--; + if (d_count <= 0){ + memcpy (out, in, item_size); // copy 1 item + out += item_size; + no++; + d_count = d_n; + } + in += item_size; + ni++; + } + + // Because we have set TPP_DONT, we have to propagate the tags here manually. + // Adjustment of the tag sample value is done using the float d_decim_rate. + std::vector<gr_tag_t> tags; + std::vector<gr_tag_t>::iterator t; + get_tags_in_range(tags, 0, nitems_read(0), nitems_read(0)+ni); + for(t = tags.begin(); t != tags.end(); t++) { + gr_tag_t new_tag = *t; + new_tag.offset *= d_decim_rate; + add_item_tag(0, new_tag); + } + + consume_each (ni); + return no; +} diff --git a/gnuradio-core/src/lib/general/gr_keep_one_in_n.h b/gnuradio-core/src/lib/general/gr_keep_one_in_n.h new file mode 100644 index 000000000..f37475204 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_keep_one_in_n.h @@ -0,0 +1,62 @@ +/* -*- 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_KEEP_ONE_IN_N_H +#define INCLUDED_GR_KEEP_ONE_IN_N_H + +#include <gr_core_api.h> +#include <gr_sync_decimator.h> + +class gr_keep_one_in_n; +typedef boost::shared_ptr<gr_keep_one_in_n> gr_keep_one_in_n_sptr; + +GR_CORE_API gr_keep_one_in_n_sptr +gr_make_keep_one_in_n (size_t item_size, int n); + + +/*! + * \brief decimate a stream, keeping one item out of every n. + * \ingroup slicedice_blk + */ +class GR_CORE_API gr_keep_one_in_n : public gr_block +{ + friend GR_CORE_API gr_keep_one_in_n_sptr + gr_make_keep_one_in_n (size_t item_size, int n); + + int d_n; + int d_count; + float d_decim_rate; + + protected: + gr_keep_one_in_n (size_t item_size, int n); + + public: + int general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void set_n(int n); + +}; + +#endif /* INCLUDED_GR_KEEP_ONE_IN_N_H */ diff --git a/gnuradio-core/src/lib/general/gr_keep_one_in_n.i b/gnuradio-core/src/lib/general/gr_keep_one_in_n.i new file mode 100644 index 000000000..534098cde --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_keep_one_in_n.i @@ -0,0 +1,35 @@ +/* -*- 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,keep_one_in_n) + +gr_keep_one_in_n_sptr +gr_make_keep_one_in_n (size_t itemsize, int n); + +class gr_keep_one_in_n : public gr_block +{ + protected: + gr_keep_one_in_n (size_t itemsize, int n); + + public: + void set_n(int n); +}; diff --git a/gnuradio-core/src/lib/general/gr_kludge_copy.cc b/gnuradio-core/src/lib/general/gr_kludge_copy.cc new file mode 100644 index 000000000..f6a8d8af6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_kludge_copy.cc @@ -0,0 +1,64 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_kludge_copy.h> +#include <gr_io_signature.h> +#include <string.h> + +gr_kludge_copy_sptr +gr_make_kludge_copy(size_t itemsize) +{ + return gnuradio::get_initial_sptr(new gr_kludge_copy(itemsize)); +} + +gr_kludge_copy::gr_kludge_copy(size_t itemsize) + : gr_sync_block ("kludge_copy", + gr_make_io_signature (1, -1, itemsize), + gr_make_io_signature (1, -1, itemsize)), + d_itemsize(itemsize) +{ +} + +bool +gr_kludge_copy::check_topology(int ninputs, int noutputs) +{ + return ninputs == noutputs; +} + +int +gr_kludge_copy::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]; + + int ninputs = input_items.size(); + for (int i = 0; i < ninputs; i++){ + memcpy(out[i], in[i], noutput_items * d_itemsize); + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_kludge_copy.h b/gnuradio-core/src/lib/general/gr_kludge_copy.h new file mode 100644 index 000000000..0bcf14469 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_kludge_copy.h @@ -0,0 +1,56 @@ +/* -*- 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_KLUDGE_COPY_H +#define INCLUDED_GR_KLUDGE_COPY_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_kludge_copy; +typedef boost::shared_ptr<gr_kludge_copy> gr_kludge_copy_sptr; + +GR_CORE_API gr_kludge_copy_sptr gr_make_kludge_copy(size_t itemsize); + +/*! + * \brief output[i] = input[i] + * \ingroup misc_blk + * + * This is a short term kludge to work around a problem with the hierarchical block impl. + */ +class GR_CORE_API gr_kludge_copy : public gr_sync_block +{ + size_t d_itemsize; + + friend GR_CORE_API gr_kludge_copy_sptr gr_make_kludge_copy(size_t itemsize); + gr_kludge_copy(size_t itemsize); + + public: + + bool check_topology(int ninputs, int noutputs); + + 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_kludge_copy.i b/gnuradio-core/src/lib/general/gr_kludge_copy.i new file mode 100644 index 000000000..7ff2b5736 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_kludge_copy.i @@ -0,0 +1,31 @@ +/* -*- 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,kludge_copy) + +gr_kludge_copy_sptr gr_make_kludge_copy(size_t itemsize); + +class gr_kludge_copy : public gr_sync_block +{ + private: + gr_kludge_copy(size_t itemsize); +}; diff --git a/gnuradio-core/src/lib/general/gr_lfsr_32k_source_s.cc b/gnuradio-core/src/lib/general/gr_lfsr_32k_source_s.cc new file mode 100644 index 000000000..c9a874248 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_lfsr_32k_source_s.cc @@ -0,0 +1,70 @@ +/* -*- 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_lfsr_32k_source_s.h> +#include <gr_io_signature.h> +#include <stdexcept> + + +gr_lfsr_32k_source_s_sptr +gr_make_lfsr_32k_source_s () +{ + return gnuradio::get_initial_sptr(new gr_lfsr_32k_source_s ()); +} + + +gr_lfsr_32k_source_s::gr_lfsr_32k_source_s () + : gr_sync_block ("lfsr_32k_source_s", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 1, sizeof (short))), + d_index (0) +{ + gri_lfsr_32k lfsr; + + for (int i = 0; i < BUFSIZE; i++) + d_buffer[i] = lfsr.next_short (); +} + +int +gr_lfsr_32k_source_s::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + short *out = (short *) output_items[0]; + short *buf = d_buffer; + int index = d_index; + + for (int i = 0; i < noutput_items; i++){ + out[i] = buf[index]; + // index = (index + 1) & (BUFSIZE - 1); + index = index + 1; + if (index >= BUFSIZE) + index = 0; + } + + d_index = index; + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_lfsr_32k_source_s.h b/gnuradio-core/src/lib/general/gr_lfsr_32k_source_s.h new file mode 100644 index 000000000..db107652a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_lfsr_32k_source_s.h @@ -0,0 +1,61 @@ +/* -*- 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_LFSR_32K_SOURCE_S_H +#define INCLUDED_GR_LFSR_32K_SOURCE_S_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gri_lfsr_32k.h> + +class gr_lfsr_32k_source_s; +typedef boost::shared_ptr<gr_lfsr_32k_source_s> gr_lfsr_32k_source_s_sptr; + +GR_CORE_API gr_lfsr_32k_source_s_sptr gr_make_lfsr_32k_source_s (); + +/*! + * \brief LFSR pseudo-random source with period of 2^15 bits (2^11 shorts) + * \ingroup source_blk + * + * This source is typically used along with gr_check_lfsr_32k_s to test + * the USRP using its digital loopback mode. + */ +class GR_CORE_API gr_lfsr_32k_source_s : public gr_sync_block +{ + friend GR_CORE_API gr_lfsr_32k_source_s_sptr gr_make_lfsr_32k_source_s (); + + + static const int BUFSIZE = 2048 - 1; // ensure pattern isn't packet aligned + int d_index; + short d_buffer[BUFSIZE]; + + gr_lfsr_32k_source_s (); + + public: + + virtual 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_lfsr_32k_source_s.i b/gnuradio-core/src/lib/general/gr_lfsr_32k_source_s.i new file mode 100644 index 000000000..c2dc1c61b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_lfsr_32k_source_s.i @@ -0,0 +1,31 @@ +/* -*- 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,lfsr_32k_source_s); + +gr_lfsr_32k_source_s_sptr gr_make_lfsr_32k_source_s (); + +class gr_lfsr_32k_source_s : public gr_sync_block +{ + private: + gr_lfsr_32k_source_s (); +}; diff --git a/gnuradio-core/src/lib/general/gr_log2_const.h b/gnuradio-core/src/lib/general/gr_log2_const.h new file mode 100644 index 000000000..40afcf8b8 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_log2_const.h @@ -0,0 +1,47 @@ +/* -*- 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. + */ + + +/* + * a bit of template hackery... + */ +#ifndef INCLUDED_GR_LOG2_CONST_H +#define INCLUDED_GR_LOG2_CONST_H + +#include <gr_core_api.h> +#include <assert.h> + +template<unsigned int k> static inline int gr_log2_const() { assert(0); return 0; } + +template<> inline int gr_log2_const<1>() { return 0; } +template<> inline int gr_log2_const<2>() { return 1; } +template<> inline int gr_log2_const<4>() { return 2; } +template<> inline int gr_log2_const<8>() { return 3; } +template<> inline int gr_log2_const<16>() { return 4; } +template<> inline int gr_log2_const<32>() { return 5; } +template<> inline int gr_log2_const<64>() { return 6; } +template<> inline int gr_log2_const<128>() { return 7; } +template<> inline int gr_log2_const<256>() { return 8; } +template<> inline int gr_log2_const<512>() { return 9; } +template<> inline int gr_log2_const<1024>(){ return 10; } + +#endif /* INCLUDED_GR_LOG2_CONST_H */ diff --git a/gnuradio-core/src/lib/general/gr_map_bb.cc b/gnuradio-core/src/lib/general/gr_map_bb.cc new file mode 100644 index 000000000..7deb8971a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_map_bb.cc @@ -0,0 +1,61 @@ +/* -*- 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 new file mode 100644 index 000000000..0a2f5a45f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_map_bb.h @@ -0,0 +1,52 @@ +/* -*- 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 new file mode 100644 index 000000000..9c8bff644 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_map_bb.i @@ -0,0 +1,32 @@ +/* -*- 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_math.h b/gnuradio-core/src/lib/general/gr_math.h new file mode 100644 index 000000000..b9a802da8 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_math.h @@ -0,0 +1,209 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2005,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. + */ + +/* + * mathematical odds and ends. + */ + +#ifndef _GR_MATH_H_ +#define _GR_MATH_H_ + +#include <gr_core_api.h> +#include <gr_complex.h> + +static inline bool +gr_is_power_of_2(long x) +{ + return x != 0 && (x & (x-1)) == 0; +} + +/*! + * \brief Fast arc tangent using table lookup and linear interpolation + * \ingroup misc + * + * \param y component of input vector + * \param x component of input vector + * \returns float angle angle of vector (x, y) in radians + * + * This function calculates the angle of the vector (x,y) based on a + * table lookup and linear interpolation. The table uses a 256 point + * table covering -45 to +45 degrees and uses symetry to determine the + * final angle value in the range of -180 to 180 degrees. Note that + * this function uses the small angle approximation for values close + * to zero. This routine calculates the arc tangent with an average + * error of +/- 0.045 degrees. + */ +GR_CORE_API float gr_fast_atan2f(float y, float x); + +static inline float gr_fast_atan2f(gr_complex z) +{ + return gr_fast_atan2f(z.imag(), z.real()); +} + +/* This bounds x by +/- clip without a branch */ +static inline float gr_branchless_clip(float x, float clip) +{ + float x1 = fabsf(x+clip); + float x2 = fabsf(x-clip); + x1 -= x2; + return 0.5*x1; +} + +static inline float gr_clip(float x, float clip) +{ + float y = x; + if(x > clip) + y = clip; + else if(x < -clip) + y = -clip; + return y; +} + +// Slicer Functions +static inline unsigned int gr_binary_slicer(float x) +{ + if(x >= 0) + return 1; + else + return 0; +} + +static inline unsigned int gr_quad_45deg_slicer(float r, float i) +{ + unsigned int ret = 0; + if((r >= 0) && (i >= 0)) + ret = 0; + else if((r < 0) && (i >= 0)) + ret = 1; + else if((r < 0) && (i < 0)) + ret = 2; + else + ret = 3; + return ret; +} + +static inline unsigned int gr_quad_0deg_slicer(float r, float i) +{ + unsigned int ret = 0; + if(fabsf(r) > fabsf(i)) { + if(r > 0) + ret = 0; + else + ret = 2; + } + else { + if(i > 0) + ret = 1; + else + ret = 3; + } + + return ret; +} + +static inline unsigned int gr_quad_45deg_slicer(gr_complex x) +{ + return gr_quad_45deg_slicer(x.real(), x.imag()); +} + +static inline unsigned int gr_quad_0deg_slicer(gr_complex x) +{ + return gr_quad_0deg_slicer(x.real(), x.imag()); +} + +// Branchless Slicer Functions +static inline unsigned int gr_branchless_binary_slicer(float x) +{ + return (x >= 0); +} + +static inline unsigned int gr_branchless_quad_0deg_slicer(float r, float i) +{ + unsigned int ret = 0; + ret = (fabsf(r) > fabsf(i)) * (((r < 0) << 0x1)); // either 0 (00) or 2 (10) + ret |= (fabsf(i) > fabsf(r)) * (((i < 0) << 0x1) | 0x1); // either 1 (01) or 3 (11) + + return ret; +} + +static inline unsigned int gr_branchless_quad_0deg_slicer(gr_complex x) +{ + return gr_branchless_quad_0deg_slicer(x.real(), x.imag()); +} + +static inline unsigned int gr_branchless_quad_45deg_slicer(float r, float i) +{ + char ret = (r <= 0); + ret |= ((i <= 0) << 1); + return (ret ^ ((ret & 0x2) >> 0x1)); +} + +static inline unsigned int gr_branchless_quad_45deg_slicer(gr_complex x) +{ + return gr_branchless_quad_45deg_slicer(x.real(), x.imag()); +} + +/*! + * \param x any value + * \param pow2 must be a power of 2 + * \returns \p x rounded down to a multiple of \p pow2. + */ +static inline size_t +gr_p2_round_down(size_t x, size_t pow2) +{ + return x & -pow2; +} + +/*! + * \param x any value + * \param pow2 must be a power of 2 + * \returns \p x rounded up to a multiple of \p pow2. + */ +static inline size_t +gr_p2_round_up(size_t x, size_t pow2) +{ + return gr_p2_round_down(x + pow2 - 1, pow2); +} + +/*! + * \param x any value + * \param pow2 must be a power of 2 + * \returns \p x modulo \p pow2. + */ +static inline size_t +gr_p2_modulo(size_t x, size_t pow2) +{ + return x & (pow2 - 1); +} + +/*! + * \param x any value + * \param pow2 must be a power of 2 + * \returns \p pow2 - (\p x modulo \p pow2). + */ +static inline size_t +gr_p2_modulo_neg(size_t x, size_t pow2) +{ + return pow2 - gr_p2_modulo(x, pow2); +} + +#endif /* _GR_MATH_H_ */ diff --git a/gnuradio-core/src/lib/general/gr_message_strobe.cc b/gnuradio-core/src/lib/general/gr_message_strobe.cc new file mode 100644 index 000000000..6a9f807d1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_message_strobe.cc @@ -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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_message_strobe.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 <string.h> +#include <iostream> + +// public constructor that returns a shared_ptr + +gr_message_strobe_sptr +gr_make_message_strobe (pmt::pmt_t msg, float period_ms) +{ + return gnuradio::get_initial_sptr(new gr_message_strobe(msg, period_ms)); +} + +gr_message_strobe::gr_message_strobe (pmt::pmt_t msg, float period_ms) + : gr_block("message_strobe", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(0, 0, 0)), + d_finished(false), + d_period_ms(period_ms), + d_msg(msg) +{ + message_port_register_out(pmt::mp("strobe")); + d_thread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&gr_message_strobe::run, this))); + + message_port_register_in(pmt::mp("set_msg")); + set_msg_handler(pmt::mp("set_msg"), boost::bind(&gr_message_strobe::set_msg, this, _1)); +} + +gr_message_strobe::~gr_message_strobe() +{ + d_finished = true; + d_thread->interrupt(); + d_thread->join(); +} + +void gr_message_strobe::run(){ + while(!d_finished) { + boost::this_thread::sleep(boost::posix_time::milliseconds(d_period_ms)); + if(d_finished){ return; } + + message_port_pub( pmt::mp("strobe"), d_msg ); + } +} diff --git a/gnuradio-core/src/lib/general/gr_message_strobe.h b/gnuradio-core/src/lib/general/gr_message_strobe.h new file mode 100644 index 000000000..89046ffc0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_message_strobe.h @@ -0,0 +1,62 @@ +/* -*- 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_GR_MESSAGE_STROBE_H +#define INCLUDED_GR_MESSAGE_STROBE_H + +#include <gr_core_api.h> +#include <gr_block.h> +#include <gr_message.h> +#include <gr_msg_queue.h> + +class gr_message_strobe; +typedef boost::shared_ptr<gr_message_strobe> gr_message_strobe_sptr; + +GR_CORE_API gr_message_strobe_sptr gr_make_message_strobe (pmt::pmt_t msg, float period_ms); + +/*! + * \brief Send message at defined interval + * \ingroup msg_blk + */ +class GR_CORE_API gr_message_strobe : public gr_block +{ + private: + friend GR_CORE_API gr_message_strobe_sptr + gr_make_message_strobe(pmt::pmt_t msg, float period_ms); + + boost::shared_ptr<boost::thread> d_thread; + bool d_finished; + float d_period_ms; + pmt::pmt_t d_msg; + + void run(); + + protected: + gr_message_strobe (pmt::pmt_t msg, float period_ms); + + public: + ~gr_message_strobe (); + + void set_msg(pmt::pmt_t msg){ d_msg = msg; } +}; + +#endif /* INCLUDED_GR_MESSAGE_STROBE_H */ diff --git a/gnuradio-core/src/lib/general/gr_message_strobe.i b/gnuradio-core/src/lib/general/gr_message_strobe.i new file mode 100644 index 000000000..490aa8e8a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_message_strobe.i @@ -0,0 +1,30 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,message_strobe); + +%{ +#include <gr_message_strobe.h> +%} + +%include "gr_message_strobe.h" + diff --git a/gnuradio-core/src/lib/general/gr_misc.cc b/gnuradio-core/src/lib/general/gr_misc.cc new file mode 100644 index 000000000..1ed2a03d7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_misc.cc @@ -0,0 +1,65 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include <gr_misc.h> + +unsigned int +gr_rounduppow2(unsigned int n) +{ + int i; + for (i=0;((n-1)>>i) != 0;i++) + ; + return 1<<i; +} + +// ---------------------------------------------------------------- + +void +gr_zero_vector(std::vector<float> &v) +{ + for(unsigned int i=0; i < v.size(); i++) + v[i] = 0; +} + +void +gr_zero_vector(std::vector<double> &v) +{ + for(unsigned int i=0; i < v.size(); i++) + v[i] = 0; +} + +void +gr_zero_vector(std::vector<int> &v) +{ + for(unsigned int i=0; i < v.size(); i++) + v[i] = 0; +} + +void +gr_zero_vector(std::vector<gr_complex> &v) +{ + for(unsigned int i=0; i < v.size(); i++) + v[i] = 0; +} diff --git a/gnuradio-core/src/lib/general/gr_misc.h b/gnuradio-core/src/lib/general/gr_misc.h new file mode 100644 index 000000000..0c790e90c --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_misc.h @@ -0,0 +1,39 @@ +/* -*- 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_MISC_H +#define INCLUDED_GR_MISC_H + +#include <gr_core_api.h> +#include <gr_types.h> + +GR_CORE_API unsigned int +gr_rounduppow2(unsigned int n); + +// FIXME should be template +GR_CORE_API void gr_zero_vector(std::vector<float> &v); +GR_CORE_API void gr_zero_vector(std::vector<double> &v); +GR_CORE_API void gr_zero_vector(std::vector<int> &v); +GR_CORE_API void gr_zero_vector(std::vector<gr_complex> &v); + + +#endif /* INCLUDED_GR_MISC_H */ diff --git a/gnuradio-core/src/lib/general/gr_multiply_cc.cc b/gnuradio-core/src/lib/general/gr_multiply_cc.cc new file mode 100644 index 000000000..4a3751419 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_cc.cc @@ -0,0 +1,69 @@ +/* -*- 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 <gr_multiply_cc.h> +#include <gr_io_signature.h> +#include <volk/volk.h> + +gr_multiply_cc_sptr +gr_make_multiply_cc (size_t vlen) +{ + return gnuradio::get_initial_sptr(new gr_multiply_cc (vlen)); +} + +gr_multiply_cc::gr_multiply_cc (size_t vlen) + : gr_sync_block ("gr_multiply_cc", + gr_make_io_signature (1, -1, sizeof (gr_complex)*vlen), + gr_make_io_signature (1, 1, sizeof (gr_complex)*vlen)), + d_vlen(vlen) +{ + const int alignment_multiple = + volk_get_alignment() / sizeof(gr_complex); + set_alignment(std::max(1,alignment_multiple)); +} + +int +gr_multiply_cc::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gr_complex *out = (gr_complex *) output_items[0]; + int noi = d_vlen*noutput_items; + + memcpy(out, input_items[0], noi*sizeof(gr_complex)); + if(is_unaligned()) { + for(size_t i = 1; i < input_items.size(); i++) + volk_32fc_x2_multiply_32fc_u(out, out, (gr_complex*)input_items[i], noi); + } + else { + for(size_t i = 1; i < input_items.size(); i++) + volk_32fc_x2_multiply_32fc_a(out, out, (gr_complex*)input_items[i], noi); + } + return noutput_items; +} + + + diff --git a/gnuradio-core/src/lib/general/gr_multiply_cc.h b/gnuradio-core/src/lib/general/gr_multiply_cc.h new file mode 100644 index 000000000..d25935b4c --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_cc.h @@ -0,0 +1,56 @@ +/* -*- 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_GR_MULTIPLY_CC_H +#define INCLUDED_GR_MULTIPLY_CC_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_multiply_cc; +typedef boost::shared_ptr<gr_multiply_cc> gr_multiply_cc_sptr; + +GR_CORE_API gr_multiply_cc_sptr +gr_make_multiply_cc (size_t vlen=1); + +/*! + * \brief Multiply streams of complex values + * \ingroup math_blk + */ + +class GR_CORE_API gr_multiply_cc : public gr_sync_block +{ + private: + friend GR_CORE_API gr_multiply_cc_sptr + gr_make_multiply_cc (size_t vlen); + gr_multiply_cc (size_t vlen); + + size_t d_vlen; + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_MULTIPLY_CC_H */ diff --git a/gnuradio-core/src/lib/general/gr_multiply_cc.i b/gnuradio-core/src/lib/general/gr_multiply_cc.i new file mode 100644 index 000000000..f0faa3594 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_cc.i @@ -0,0 +1,32 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,multiply_cc) + +gr_multiply_cc_sptr +gr_make_multiply_cc (size_t vlen=1); + +class gr_multiply_cc : public gr_sync_block +{ +public: + +}; diff --git a/gnuradio-core/src/lib/general/gr_multiply_conjugate_cc.cc b/gnuradio-core/src/lib/general/gr_multiply_conjugate_cc.cc new file mode 100644 index 000000000..0c5fb4a92 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_conjugate_cc.cc @@ -0,0 +1,69 @@ +/* -*- 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 <gr_multiply_conjugate_cc.h> +#include <gr_io_signature.h> +#include <volk/volk.h> + +gr_multiply_conjugate_cc_sptr +gr_make_multiply_conjugate_cc (size_t vlen) +{ + return gnuradio::get_initial_sptr(new gr_multiply_conjugate_cc (vlen)); +} + +gr_multiply_conjugate_cc::gr_multiply_conjugate_cc (size_t vlen) + : gr_sync_block ("gr_multiply_conjugate_cc", + gr_make_io_signature (2, 2, sizeof (gr_complex)*vlen), + gr_make_io_signature (1, 1, sizeof (gr_complex)*vlen)), + d_vlen(vlen) +{ + const int alignment_multiple = + volk_get_alignment() / sizeof(gr_complex); + set_alignment(std::max(1,alignment_multiple)); +} + +int +gr_multiply_conjugate_cc::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gr_complex *in0 = (gr_complex *) input_items[0]; + gr_complex *in1 = (gr_complex *) input_items[1]; + gr_complex *out = (gr_complex *) output_items[0]; + int noi = d_vlen*noutput_items; + + if(is_unaligned()) { + volk_32fc_x2_multiply_conjugate_32fc_u(out, in0, in1, noi); + } + else { + volk_32fc_x2_multiply_conjugate_32fc_a(out, in0, in1, noi); + } + + return noutput_items; +} + + + diff --git a/gnuradio-core/src/lib/general/gr_multiply_conjugate_cc.h b/gnuradio-core/src/lib/general/gr_multiply_conjugate_cc.h new file mode 100644 index 000000000..826e28771 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_conjugate_cc.h @@ -0,0 +1,57 @@ +/* -*- 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_GR_MULTIPLY_CONJUGATE_CC_H +#define INCLUDED_GR_MULTIPLY_CONJUGATE_CC_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_multiply_conjugate_cc; +typedef boost::shared_ptr<gr_multiply_conjugate_cc> +gr_multiply_conjugate_cc_sptr; + +GR_CORE_API gr_multiply_conjugate_cc_sptr +gr_make_multiply_conjugate_cc (size_t vlen=1); + +/*! + * \brief Multiplies a stream by the conjugate of the second stream + * \ingroup math_blk + */ + +class GR_CORE_API gr_multiply_conjugate_cc : public gr_sync_block +{ + private: + friend GR_CORE_API gr_multiply_conjugate_cc_sptr + gr_make_multiply_conjugate_cc (size_t vlen); + gr_multiply_conjugate_cc (size_t vlen); + + size_t d_vlen; + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_MULTIPLY_CONJUGATE_CC_H */ diff --git a/gnuradio-core/src/lib/general/gr_multiply_conjugate_cc.i b/gnuradio-core/src/lib/general/gr_multiply_conjugate_cc.i new file mode 100644 index 000000000..e7979dbcd --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_conjugate_cc.i @@ -0,0 +1,32 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,multiply_conjugate_cc) + +gr_multiply_conjugate_cc_sptr +gr_make_multiply_conjugate_cc (size_t vlen=1); + +class gr_multiply_conjugate_cc : public gr_sync_block +{ +public: + +}; diff --git a/gnuradio-core/src/lib/general/gr_multiply_const_cc.cc b/gnuradio-core/src/lib/general/gr_multiply_const_cc.cc new file mode 100644 index 000000000..bd4511937 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_const_cc.cc @@ -0,0 +1,80 @@ +/* -*- 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 <gr_multiply_const_cc.h> +#include <gr_io_signature.h> +#include <volk/volk.h> + +gr_multiply_const_cc_sptr +gr_make_multiply_const_cc (gr_complex k, size_t vlen) +{ + return gnuradio::get_initial_sptr(new gr_multiply_const_cc (k, vlen)); +} + +gr_multiply_const_cc::gr_multiply_const_cc (gr_complex k, size_t vlen) + : gr_sync_block ("gr_multiply_const_cc", + gr_make_io_signature (1, 1, sizeof (gr_complex)*vlen), + gr_make_io_signature (1, 1, sizeof (gr_complex)*vlen)), + d_k(k), d_vlen(vlen) +{ + const int alignment_multiple = + volk_get_alignment() / sizeof(gr_complex); + set_alignment(std::max(1,alignment_multiple)); +} + +gr_complex +gr_multiply_const_cc::k() const +{ + return d_k; +} + +void +gr_multiply_const_cc::set_k(gr_complex k) +{ + d_k = k; +} + +int +gr_multiply_const_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]; + int noi = d_vlen*noutput_items; + + if(is_unaligned()) { + volk_32fc_s32fc_multiply_32fc_u(out, in, d_k, noi); + } + else { + volk_32fc_s32fc_multiply_32fc_a(out, in, d_k, noi); + } + + return noutput_items; +} + + + diff --git a/gnuradio-core/src/lib/general/gr_multiply_const_cc.h b/gnuradio-core/src/lib/general/gr_multiply_const_cc.h new file mode 100644 index 000000000..97962abc7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_const_cc.h @@ -0,0 +1,60 @@ +/* -*- 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_GR_MULTIPLY_CONST_CC_H +#define INCLUDED_GR_MULTIPLY_CONST_CC_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_multiply_const_cc; +typedef boost::shared_ptr<gr_multiply_const_cc> gr_multiply_const_cc_sptr; + +GR_CORE_API gr_multiply_const_cc_sptr +gr_make_multiply_const_cc (gr_complex k, size_t vlen=1); + +/*! + * \brief Multiply stream of complex values with a constant \p k + * \ingroup math_blk + */ + +class GR_CORE_API gr_multiply_const_cc : public gr_sync_block +{ + private: + friend GR_CORE_API gr_multiply_const_cc_sptr + gr_make_multiply_const_cc (gr_complex k, size_t vlen); + gr_multiply_const_cc (gr_complex k, size_t vlen); + + gr_complex d_k; + size_t d_vlen; + + public: + gr_complex k() const; + void set_k(gr_complex k); + + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_MULTIPLY_CONST_CC_H */ diff --git a/gnuradio-core/src/lib/general/gr_multiply_const_cc.i b/gnuradio-core/src/lib/general/gr_multiply_const_cc.i new file mode 100644 index 000000000..c2f3cbed3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_const_cc.i @@ -0,0 +1,33 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,multiply_const_cc) + +gr_multiply_const_cc_sptr +gr_make_multiply_const_cc (gr_complex k, size_t vlen=1); + +class gr_multiply_const_cc : public gr_sync_block +{ +public: + gr_complex k() const; + void set_k(gr_complex k); +}; diff --git a/gnuradio-core/src/lib/general/gr_multiply_const_ff.cc b/gnuradio-core/src/lib/general/gr_multiply_const_ff.cc new file mode 100644 index 000000000..16ba39df9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_const_ff.cc @@ -0,0 +1,80 @@ +/* -*- 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 <gr_multiply_const_ff.h> +#include <gr_io_signature.h> +#include <volk/volk.h> + +gr_multiply_const_ff_sptr +gr_make_multiply_const_ff (float k, size_t vlen) +{ + return gnuradio::get_initial_sptr(new gr_multiply_const_ff (k, vlen)); +} + +gr_multiply_const_ff::gr_multiply_const_ff (float k, size_t vlen) + : gr_sync_block ("gr_multiply_const_ff", + gr_make_io_signature (1, 1, sizeof (float)*vlen), + gr_make_io_signature (1, 1, sizeof (float)*vlen)), + d_k(k), d_vlen(vlen) +{ + const int alignment_multiple = + volk_get_alignment() / sizeof(float); + set_alignment(std::max(1,alignment_multiple)); +} + +float +gr_multiply_const_ff::k() const +{ + return d_k; +} + +void +gr_multiply_const_ff::set_k(float k) +{ + d_k = k; +} + +int +gr_multiply_const_ff::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]; + int noi = d_vlen*noutput_items; + + if(is_unaligned()) { + volk_32f_s32f_multiply_32f_u(out, in, d_k, noi); + } + else { + volk_32f_s32f_multiply_32f_a(out, in, d_k, noi); + } + + return noutput_items; +} + + + diff --git a/gnuradio-core/src/lib/general/gr_multiply_const_ff.h b/gnuradio-core/src/lib/general/gr_multiply_const_ff.h new file mode 100644 index 000000000..fac73f88a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_const_ff.h @@ -0,0 +1,60 @@ +/* -*- 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_GR_MULTIPLY_CONST_FF_H +#define INCLUDED_GR_MULTIPLY_CONST_FF_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_multiply_const_ff; +typedef boost::shared_ptr<gr_multiply_const_ff> gr_multiply_const_ff_sptr; + +GR_CORE_API gr_multiply_const_ff_sptr +gr_make_multiply_const_ff (float k, size_t vlen=1); + +/*! + * \brief Multiply stream of float values with a constant \p k + * \ingroup math_blk + */ + +class GR_CORE_API gr_multiply_const_ff : public gr_sync_block +{ + private: + friend GR_CORE_API gr_multiply_const_ff_sptr + gr_make_multiply_const_ff (float k, size_t vlen); + gr_multiply_const_ff (float k, size_t vlen); + + float d_k; + size_t d_vlen; + + public: + float k() const; + void set_k(float k); + + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_MULTIPLY_CONST_FF_H */ diff --git a/gnuradio-core/src/lib/general/gr_multiply_const_ff.i b/gnuradio-core/src/lib/general/gr_multiply_const_ff.i new file mode 100644 index 000000000..343f67cd2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_const_ff.i @@ -0,0 +1,33 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,multiply_const_ff) + +gr_multiply_const_ff_sptr +gr_make_multiply_const_ff (float k, size_t vlen=1); + +class gr_multiply_const_ff : public gr_sync_block +{ +public: + float k() const; + void set_k(float k); +}; diff --git a/gnuradio-core/src/lib/general/gr_multiply_ff.cc b/gnuradio-core/src/lib/general/gr_multiply_ff.cc new file mode 100644 index 000000000..bb7bd0755 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_ff.cc @@ -0,0 +1,69 @@ +/* -*- 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 <gr_multiply_ff.h> +#include <gr_io_signature.h> +#include <volk/volk.h> + +gr_multiply_ff_sptr +gr_make_multiply_ff (size_t vlen) +{ + return gnuradio::get_initial_sptr(new gr_multiply_ff (vlen)); +} + +gr_multiply_ff::gr_multiply_ff (size_t vlen) + : gr_sync_block ("gr_multiply_ff", + gr_make_io_signature (1, -1, sizeof (float)*vlen), + gr_make_io_signature (1, 1, sizeof (float)*vlen)), + d_vlen(vlen) +{ + const int alignment_multiple = + volk_get_alignment() / sizeof(float); + set_alignment(std::max(1,alignment_multiple)); +} + +int +gr_multiply_ff::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float *out = (float *) output_items[0]; + int noi = d_vlen*noutput_items; + + memcpy(out, input_items[0], noi*sizeof(float)); + if(is_unaligned()) { + for(size_t i = 1; i < input_items.size(); i++) + volk_32f_x2_multiply_32f_u(out, out, (const float*)input_items[i], noi); + } + else { + for(size_t i = 1; i < input_items.size(); i++) + volk_32f_x2_multiply_32f_a(out, out, (const float*)input_items[i], noi); + } + return noutput_items; +} + + + diff --git a/gnuradio-core/src/lib/general/gr_multiply_ff.h b/gnuradio-core/src/lib/general/gr_multiply_ff.h new file mode 100644 index 000000000..ed628385c --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_ff.h @@ -0,0 +1,56 @@ +/* -*- 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_GR_MULTIPLY_FF_H +#define INCLUDED_GR_MULTIPLY_FF_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_multiply_ff; +typedef boost::shared_ptr<gr_multiply_ff> gr_multiply_ff_sptr; + +GR_CORE_API gr_multiply_ff_sptr +gr_make_multiply_ff (size_t vlen=1); + +/*! + * \brief Multiply streams of complex values + * \ingroup math_blk + */ + +class GR_CORE_API gr_multiply_ff : public gr_sync_block +{ + private: + friend GR_CORE_API gr_multiply_ff_sptr + gr_make_multiply_ff (size_t vlen); + gr_multiply_ff (size_t vlen); + + size_t d_vlen; + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_MULTIPLY_FF_H */ diff --git a/gnuradio-core/src/lib/general/gr_multiply_ff.i b/gnuradio-core/src/lib/general/gr_multiply_ff.i new file mode 100644 index 000000000..e5fdea348 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_ff.i @@ -0,0 +1,32 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,multiply_ff) + +gr_multiply_ff_sptr +gr_make_multiply_ff (size_t vlen=1); + +class gr_multiply_ff : public gr_sync_block +{ +public: + +}; diff --git a/gnuradio-core/src/lib/general/gr_nco.h b/gnuradio-core/src/lib/general/gr_nco.h new file mode 100644 index 000000000..fb51106aa --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_nco.h @@ -0,0 +1,198 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 _GR_NCO_H_ +#define _GR_NCO_H_ + + +#include <vector> +#include <gr_sincos.h> +#include <cmath> +#include <gr_complex.h> + +/*! + * \brief base class template for Numerically Controlled Oscillator (NCO) + * \ingroup misc + */ + + +//FIXME Eventually generalize this to fixed point + +template<class o_type, class i_type> +class gr_nco { +public: + gr_nco () : phase (0), phase_inc(0) {} + + virtual ~gr_nco () {} + + // radians + void set_phase (double angle) { + phase = angle; + } + + void adjust_phase (double delta_phase) { + phase += delta_phase; + } + + + // angle_rate is in radians / step + void set_freq (double angle_rate){ + phase_inc = angle_rate; + } + + // angle_rate is a delta in radians / step + void adjust_freq (double delta_angle_rate) + { + phase_inc += delta_angle_rate; + } + + // increment current phase angle + + void step () + { + phase += phase_inc; + if (fabs (phase) > M_PI){ + + while (phase > M_PI) + phase -= 2*M_PI; + + while (phase < -M_PI) + phase += 2*M_PI; + } + } + + void step (int n) + { + phase += phase_inc * n; + if (fabs (phase) > M_PI){ + + while (phase > M_PI) + phase -= 2*M_PI; + + while (phase < -M_PI) + phase += 2*M_PI; + } + } + + // units are radians / step + double get_phase () const { return phase; } + double get_freq () const { return phase_inc; } + + // compute sin and cos for current phase angle + void sincos (float *sinx, float *cosx) const; + + // compute cos or sin for current phase angle + float cos () const { return std::cos (phase); } + float sin () const { return std::sin (phase); } + + // compute a block at a time + void sin (float *output, int noutput_items, double ampl = 1.0); + void cos (float *output, int noutput_items, double ampl = 1.0); + void sincos (gr_complex *output, int noutput_items, double ampl = 1.0); + void sin (short *output, int noutput_items, double ampl = 1.0); + void cos (short *output, int noutput_items, double ampl = 1.0); + void sin (int *output, int noutput_items, double ampl = 1.0); + void cos (int *output, int noutput_items, double ampl = 1.0); + +protected: + double phase; + double phase_inc; +}; + +template<class o_type, class i_type> +void +gr_nco<o_type,i_type>::sincos (float *sinx, float *cosx) const +{ + gr_sincosf (phase, sinx, cosx); +} + +template<class o_type, class i_type> +void +gr_nco<o_type,i_type>::sin (float *output, int noutput_items, double ampl) +{ + for (int i = 0; i < noutput_items; i++){ + output[i] = (float)(sin () * ampl); + step (); + } +} + +template<class o_type, class i_type> +void +gr_nco<o_type,i_type>::cos (float *output, int noutput_items, double ampl) +{ + for (int i = 0; i < noutput_items; i++){ + output[i] = (float)(cos () * ampl); + step (); + } +} + +template<class o_type, class i_type> +void +gr_nco<o_type,i_type>::sin (short *output, int noutput_items, double ampl) +{ + for (int i = 0; i < noutput_items; i++){ + output[i] = (short)(sin() * ampl); + step (); + } +} + +template<class o_type, class i_type> +void +gr_nco<o_type,i_type>::cos (short *output, int noutput_items, double ampl) +{ + for (int i = 0; i < noutput_items; i++){ + output[i] = (short)(cos () * ampl); + step (); + } +} + +template<class o_type, class i_type> +void +gr_nco<o_type,i_type>::sin (int *output, int noutput_items, double ampl) +{ + for (int i = 0; i < noutput_items; i++){ + output[i] = (int)(sin () * ampl); + step (); + } +} + +template<class o_type, class i_type> +void +gr_nco<o_type,i_type>::cos (int *output, int noutput_items, double ampl) +{ + for (int i = 0; i < noutput_items; i++){ + output[i] = (int)(cos () * ampl); + step (); + } +} + +template<class o_type, class i_type> +void +gr_nco<o_type,i_type>::sincos (gr_complex *output, int noutput_items, double ampl) +{ + for (int i = 0; i < noutput_items; i++){ + float cosx, sinx; + sincos (&sinx, &cosx); + output[i] = gr_complex(cosx * ampl, sinx * ampl); + step (); + } +} +#endif /* _NCO_H_ */ diff --git a/gnuradio-core/src/lib/general/gr_nlog10_ff.cc b/gnuradio-core/src/lib/general/gr_nlog10_ff.cc new file mode 100644 index 000000000..24cfe25fb --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_nlog10_ff.cc @@ -0,0 +1,64 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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_nlog10_ff.h> +#include <gr_io_signature.h> +#include <algorithm> + +gr_nlog10_ff_sptr +gr_make_nlog10_ff (float n, unsigned vlen, float k) +{ + return gnuradio::get_initial_sptr(new gr_nlog10_ff(n, vlen, k)); +} + +gr_nlog10_ff::gr_nlog10_ff(float n, unsigned vlen, float k) + : gr_sync_block("nlog10_ff", + gr_make_io_signature(1, 1, sizeof(float) * vlen), + gr_make_io_signature(1, 1, sizeof(float) * vlen)), + d_vlen(vlen), d_n(n), d_k(k) +{ +} + +gr_nlog10_ff::~gr_nlog10_ff() +{ +} + +int +gr_nlog10_ff::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]; + int noi = noutput_items * d_vlen; + float n = d_n; + float k = d_k; + + for (int i = 0; i < noi; i++) + out[i] = n * log10(std::max(in[i], (float) 1e-18)) + k; + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_nlog10_ff.h b/gnuradio-core/src/lib/general/gr_nlog10_ff.h new file mode 100644 index 000000000..cfeba3fee --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_nlog10_ff.h @@ -0,0 +1,56 @@ +/* -*- 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_NLOG10_FF_H +#define INCLUDED_GR_NLOG10_FF_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_nlog10_ff; +typedef boost::shared_ptr<gr_nlog10_ff> gr_nlog10_ff_sptr; + +GR_CORE_API gr_nlog10_ff_sptr gr_make_nlog10_ff (float n=1.0, unsigned vlen=1, float k=0); + +/*! + * \brief output = n*log10(input) + k + * \ingroup math_blk + */ +class GR_CORE_API gr_nlog10_ff : public gr_sync_block +{ + friend GR_CORE_API gr_nlog10_ff_sptr gr_make_nlog10_ff (float n, unsigned vlen, float k); + + unsigned int d_vlen; + float d_n; + float d_k; + + gr_nlog10_ff (float n, unsigned vlen, float k); + +public: + ~gr_nlog10_ff(); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_NLOG10_FF_H */ diff --git a/gnuradio-core/src/lib/general/gr_nlog10_ff.i b/gnuradio-core/src/lib/general/gr_nlog10_ff.i new file mode 100644 index 000000000..73da59793 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_nlog10_ff.i @@ -0,0 +1,33 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,nlog10_ff); + +gr_nlog10_ff_sptr gr_make_nlog10_ff (float n=1.0, unsigned vlen=1, float k=0); + +class gr_nlog10_ff : public gr_sync_block +{ + gr_nlog10_ff (float n, unsigned vlen, float k); + +public: + ~gr_nlog10_ff(); +}; diff --git a/gnuradio-core/src/lib/general/gr_nop.cc b/gnuradio-core/src/lib/general/gr_nop.cc new file mode 100644 index 000000000..edfe1d76d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_nop.cc @@ -0,0 +1,66 @@ +/* -*- 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_nop.h> +#include <gr_io_signature.h> +#include <boost/bind.hpp> + +gr_nop_sptr +gr_make_nop (size_t sizeof_stream_item) +{ + return gnuradio::get_initial_sptr (new gr_nop (sizeof_stream_item)); +} + +gr_nop::gr_nop (size_t sizeof_stream_item) + : gr_block ("nop", + gr_make_io_signature (0, -1, sizeof_stream_item), + gr_make_io_signature (0, -1, sizeof_stream_item)), + d_nmsgs_recvd(0) +{ + // Arrange to have count_received_msgs called when messages are received. + message_port_register_in(pmt::mp("port")); + set_msg_handler(pmt::mp("port"), boost::bind(&gr_nop::count_received_msgs, this, _1)); +} + +// Trivial message handler that just counts them. +// (N.B., This feature is used in qa_set_msg_handler) +void +gr_nop::count_received_msgs(pmt::pmt_t msg) +{ + d_nmsgs_recvd++; +} + +int +gr_nop::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + // eat any input that's available + for (unsigned i = 0; i < ninput_items.size (); i++) + consume (i, ninput_items[i]); + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_nop.h b/gnuradio-core/src/lib/general/gr_nop.h new file mode 100644 index 000000000..e0d59280f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_nop.h @@ -0,0 +1,61 @@ +/* -*- 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. + */ + +#ifndef INCLUDED_GR_NOP_H +#define INCLUDED_GR_NOP_H + +#include <gr_core_api.h> +#include <gr_block.h> +#include <stddef.h> // size_t + +class gr_nop; +typedef boost::shared_ptr<gr_nop> gr_nop_sptr; + +GR_CORE_API gr_nop_sptr +gr_make_nop (size_t sizeof_stream_item); + +/*! + * \brief Does nothing. Used for testing only. + * \ingroup misc_blk + */ +class GR_CORE_API gr_nop : public gr_block +{ + friend GR_CORE_API gr_nop_sptr gr_make_nop (size_t sizeof_stream_item); + gr_nop (size_t sizeof_stream_item); + +protected: + int d_nmsgs_recvd; + + // Method that just counts any received messages. + void count_received_msgs(pmt::pmt_t msg); + + public: + virtual int general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + int nmsgs_received() const { return d_nmsgs_recvd; } + +}; + +#endif /* INCLUDED_GR_NOP_H */ diff --git a/gnuradio-core/src/lib/general/gr_nop.i b/gnuradio-core/src/lib/general/gr_nop.i new file mode 100644 index 000000000..977a15d18 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_nop.i @@ -0,0 +1,31 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,nop) + +gr_nop_sptr gr_make_nop (size_t sizeof_stream_item); + +class gr_nop : public gr_block { +private: + gr_nop (size_t sizeof_stream_item); +}; + diff --git a/gnuradio-core/src/lib/general/gr_null_sink.cc b/gnuradio-core/src/lib/general/gr_null_sink.cc new file mode 100644 index 000000000..183665502 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_null_sink.cc @@ -0,0 +1,49 @@ +/* -*- 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_null_sink.h> +#include <gr_io_signature.h> + +gr_null_sink::gr_null_sink (size_t sizeof_stream_item) + : gr_sync_block ("null_sink", + gr_make_io_signature (1, 1, sizeof_stream_item), + gr_make_io_signature (0, 0, 0)) +{ +} + +gr_null_sink_sptr +gr_make_null_sink (size_t sizeof_stream_item) +{ + return gnuradio::get_initial_sptr (new gr_null_sink (sizeof_stream_item)); +} + +int +gr_null_sink::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_null_sink.h b/gnuradio-core/src/lib/general/gr_null_sink.h new file mode 100644 index 000000000..737429329 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_null_sink.h @@ -0,0 +1,53 @@ +/* -*- 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. + */ + +#ifndef INCLUDED_GR_NULL_SINK_H +#define INCLUDED_GR_NULL_SINK_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <stddef.h> // size_t + +class gr_null_sink; +typedef boost::shared_ptr<gr_null_sink> gr_null_sink_sptr; + +GR_CORE_API gr_null_sink_sptr +gr_make_null_sink (size_t sizeof_stream_item); + +/*! + * \brief Bit bucket + * \ingroup sink_blk + */ +class GR_CORE_API gr_null_sink : public gr_sync_block +{ + friend GR_CORE_API gr_null_sink_sptr gr_make_null_sink (size_t sizeof_stream_item); + gr_null_sink (size_t sizeof_stream_item); + + public: + + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + +}; + +#endif /* INCLUDED_GR_NULL_SINK_H */ diff --git a/gnuradio-core/src/lib/general/gr_null_sink.i b/gnuradio-core/src/lib/general/gr_null_sink.i new file mode 100644 index 000000000..80411f9b7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_null_sink.i @@ -0,0 +1,31 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,null_sink) + +gr_null_sink_sptr gr_make_null_sink (size_t sizeof_stream_item); + +class gr_null_sink : public gr_sync_block { +private: + gr_null_sink (size_t sizeof_stream_item); +}; + diff --git a/gnuradio-core/src/lib/general/gr_null_source.cc b/gnuradio-core/src/lib/general/gr_null_source.cc new file mode 100644 index 000000000..1ad5c351d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_null_source.cc @@ -0,0 +1,52 @@ +/* -*- 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_null_source.h> +#include <gr_io_signature.h> +#include <string.h> + +gr_null_source::gr_null_source (size_t sizeof_stream_item) + : gr_sync_block ("null_source", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 1, sizeof_stream_item)) +{ +} + +gr_null_source_sptr +gr_make_null_source (size_t sizeof_stream_item) +{ + return gnuradio::get_initial_sptr (new gr_null_source (sizeof_stream_item)); +} + +int +gr_null_source::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + void *optr = (void *) output_items[0]; + memset (optr, 0, noutput_items * output_signature()->sizeof_stream_item (0)); + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_null_source.h b/gnuradio-core/src/lib/general/gr_null_source.h new file mode 100644 index 000000000..1c64e8bd9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_null_source.h @@ -0,0 +1,52 @@ +/* -*- 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. + */ + +#ifndef INCLUDED_GR_NULL_SOURCE_H +#define INCLUDED_GR_NULL_SOURCE_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_null_source; +typedef boost::shared_ptr<gr_null_source> gr_null_source_sptr; + +GR_CORE_API gr_null_source_sptr +gr_make_null_source (size_t sizeof_stream_item); + +/*! + * \brief A source of zeros. + * \ingroup source_blk + */ +class GR_CORE_API gr_null_source : public gr_sync_block +{ + friend GR_CORE_API gr_null_source_sptr gr_make_null_source (size_t sizeof_stream_item); + + gr_null_source (size_t sizeof_stream_item); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + +}; + +#endif /* INCLUDED_GR_NULL_SOURCE_H */ diff --git a/gnuradio-core/src/lib/general/gr_null_source.i b/gnuradio-core/src/lib/general/gr_null_source.i new file mode 100644 index 000000000..120a59999 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_null_source.i @@ -0,0 +1,31 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,null_source) + +gr_null_source_sptr gr_make_null_source (size_t sizeof_stream_item); + +class gr_null_source : public gr_sync_block { +private: + gr_null_source (size_t sizeof_stream_item); +}; + diff --git a/gnuradio-core/src/lib/general/gr_ofdm_bpsk_demapper.cc b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_demapper.cc new file mode 100644 index 000000000..2b718e5ce --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_demapper.cc @@ -0,0 +1,97 @@ +/* -*- 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_ofdm_bpsk_demapper.h> +#include <gr_io_signature.h> + +gr_ofdm_bpsk_demapper_sptr +gr_make_ofdm_bpsk_demapper (unsigned int occupied_carriers) +{ + return gnuradio::get_initial_sptr(new gr_ofdm_bpsk_demapper (occupied_carriers)); +} + +gr_ofdm_bpsk_demapper::gr_ofdm_bpsk_demapper (unsigned occupied_carriers) + : gr_block ("ofdm_bpsk_demapper", + gr_make_io_signature (1, 1, sizeof(gr_complex)*occupied_carriers), + gr_make_io_signature (1, 1, sizeof(unsigned char))), + d_occupied_carriers(occupied_carriers), + d_byte_offset(0), d_partial_byte(0) +{ +} + +gr_ofdm_bpsk_demapper::~gr_ofdm_bpsk_demapper(void) +{ +} + +unsigned char gr_ofdm_bpsk_demapper::slicer(gr_complex x) +{ + return (unsigned char)(x.real() > 0 ? 1 : 0); +} + +void +gr_ofdm_bpsk_demapper::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + unsigned ninputs = ninput_items_required.size (); + for (unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = 1; +} + +int +gr_ofdm_bpsk_demapper::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const gr_complex *in = (const gr_complex *)input_items[0]; + unsigned char *out = (unsigned char *) output_items[0]; + + unsigned int i=0, bytes_produced=0; + + while(i < d_occupied_carriers) { + + while((d_byte_offset < 8) && (i < d_occupied_carriers)) { + //fprintf(stderr, "%f+j%f\n", in[i].real(), in[i].imag()); + d_partial_byte |= slicer(in[i++]) << (d_byte_offset++); + } + + if(d_byte_offset == 8) { + out[bytes_produced++] = d_partial_byte; + d_byte_offset = 0; + d_partial_byte = 0; + } + } + +#if 0 +printf("demod out: "); + for(i = 0; i < bytes_produced; i++) { + printf("%4x", out[i]); + } + printf(" \tlen: %d\n", i); +#endif + + consume_each(1); + return bytes_produced; +} diff --git a/gnuradio-core/src/lib/general/gr_ofdm_bpsk_demapper.h b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_demapper.h new file mode 100644 index 000000000..d69d427ed --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_demapper.h @@ -0,0 +1,69 @@ +/* -*- 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_OFDM_BPSK_DEMAPPER_H +#define INCLUDED_GR_OFDM_BPSK_DEMAPPER_H + + +#include <gr_core_api.h> +#include <gr_block.h> +#include <vector> + +class gr_ofdm_bpsk_demapper; +typedef boost::shared_ptr<gr_ofdm_bpsk_demapper> gr_ofdm_bpsk_demapper_sptr; + +GR_CORE_API gr_ofdm_bpsk_demapper_sptr +gr_make_ofdm_bpsk_demapper (unsigned int occupied_carriers); + + +/*! + * \brief take a vector of complex constellation points in from an FFT + * and demodulate to a stream of bits. Simple BPSK version. + * \ingroup ofdm_blk + */ +class GR_CORE_API gr_ofdm_bpsk_demapper : public gr_block +{ + friend GR_CORE_API gr_ofdm_bpsk_demapper_sptr + gr_make_ofdm_bpsk_demapper (unsigned int occupied_carriers); + + protected: + gr_ofdm_bpsk_demapper (unsigned int occupied_carriers); + + private: + unsigned char slicer(gr_complex x); + + unsigned int d_occupied_carriers; + unsigned int d_byte_offset; + unsigned char d_partial_byte; + + void forecast(int noutput_items, gr_vector_int &ninput_items_required); + + public: + ~gr_ofdm_bpsk_demapper(void); + 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 diff --git a/gnuradio-core/src/lib/general/gr_ofdm_bpsk_demapper.i b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_demapper.i new file mode 100644 index 000000000..e58a4e40c --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_bpsk_demapper.i @@ -0,0 +1,40 @@ +/* -*- 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. + */ + +#include <vector> + +GR_SWIG_BLOCK_MAGIC(gr,ofdm_bpsk_demapper) + +gr_ofdm_bpsk_demapper_sptr +gr_make_ofdm_bpsk_demapper (unsigned int occupied_carriers); + +class gr_ofdm_bpsk_demapper : public gr_sync_decimator +{ + protected: + gr_ofdm_bpsk_demapper (unsigned int occupied_carriers); + + public: + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; diff --git a/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.cc b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.cc new file mode 100644 index 000000000..eb1232756 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.cc @@ -0,0 +1,374 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2008,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_ofdm_frame_sink2.h> +#include <gr_io_signature.h> +#include <gr_expj.h> +#include <gr_math.h> +#include <math.h> +#include <cstdio> +#include <stdexcept> +#include <iostream> +#include <string.h> +#include <gr_constellation.h> + +#define VERBOSE 0 + +inline void +gr_ofdm_frame_sink2::enter_search() +{ + if (VERBOSE) + fprintf(stderr, "@ enter_search\n"); + + d_state = STATE_SYNC_SEARCH; + +} + +inline void +gr_ofdm_frame_sink2::enter_have_sync() +{ + if (VERBOSE) + fprintf(stderr, "@ enter_have_sync\n"); + + d_state = STATE_HAVE_SYNC; + + // clear state of demapper + d_byte_offset = 0; + d_partial_byte = 0; + + d_header = 0; + d_headerbytelen_cnt = 0; + + // Resetting PLL + d_freq = 0.0; + d_phase = 0.0; + fill(d_dfe.begin(), d_dfe.end(), gr_complex(1.0,0.0)); +} + +inline void +gr_ofdm_frame_sink2::enter_have_header() +{ + d_state = STATE_HAVE_HEADER; + + // header consists of two 16-bit shorts in network byte order + // payload length is lower 12 bits + // whitener offset is upper 4 bits + d_packetlen = (d_header >> 16) & 0x0fff; + d_packet_whitener_offset = (d_header >> 28) & 0x000f; + d_packetlen_cnt = 0; + + if (VERBOSE) + fprintf(stderr, "@ enter_have_header (payload_len = %d) (offset = %d)\n", + d_packetlen, d_packet_whitener_offset); +} + + +unsigned int gr_ofdm_frame_sink2::demapper(const gr_complex *in, + unsigned char *out) +{ + unsigned int i=0, bytes_produced=0; + gr_complex carrier; + + carrier=gr_expj(d_phase); + + gr_complex accum_error = 0.0; + //while(i < d_occupied_carriers) { + while(i < d_subcarrier_map.size()) { + if(d_nresid > 0) { + d_partial_byte |= d_resid; + d_byte_offset += d_nresid; + d_nresid = 0; + d_resid = 0; + } + + //while((d_byte_offset < 8) && (i < d_occupied_carriers)) { + while((d_byte_offset < 8) && (i < d_subcarrier_map.size())) { + //gr_complex sigrot = in[i]*carrier*d_dfe[i]; + gr_complex sigrot = in[d_subcarrier_map[i]]*carrier*d_dfe[i]; + + if(d_derotated_output != NULL){ + d_derotated_output[i] = sigrot; + } + + unsigned char bits = d_constell->decision_maker(&sigrot); + + gr_complex closest_sym = d_constell->points()[bits]; + + accum_error += sigrot * conj(closest_sym); + + // FIX THE FOLLOWING STATEMENT + if (norm(sigrot)> 0.001) d_dfe[i] += d_eq_gain*(closest_sym/sigrot-d_dfe[i]); + + i++; + + if((8 - d_byte_offset) >= d_nbits) { + d_partial_byte |= bits << (d_byte_offset); + d_byte_offset += d_nbits; + } + else { + d_nresid = d_nbits-(8-d_byte_offset); + int mask = ((1<<(8-d_byte_offset))-1); + d_partial_byte |= (bits & mask) << d_byte_offset; + d_resid = bits >> (8-d_byte_offset); + d_byte_offset += (d_nbits - d_nresid); + } + //printf("demod symbol: %.4f + j%.4f bits: %x partial_byte: %x byte_offset: %d resid: %x nresid: %d\n", + // in[i-1].real(), in[i-1].imag(), bits, d_partial_byte, d_byte_offset, d_resid, d_nresid); + } + + if(d_byte_offset == 8) { + //printf("demod byte: %x \n\n", d_partial_byte); + out[bytes_produced++] = d_partial_byte; + d_byte_offset = 0; + d_partial_byte = 0; + } + } + //std::cerr << "accum_error " << accum_error << std::endl; + + float angle = arg(accum_error); + + d_freq = d_freq - d_freq_gain*angle; + d_phase = d_phase + d_freq - d_phase_gain*angle; + if (d_phase >= 2*M_PI) d_phase -= 2*M_PI; + if (d_phase <0) d_phase += 2*M_PI; + + //if(VERBOSE) + // std::cerr << angle << "\t" << d_freq << "\t" << d_phase << "\t" << std::endl; + + return bytes_produced; +} + + +gr_ofdm_frame_sink2_sptr +gr_make_ofdm_frame_sink2(gr_constellation_sptr constell, + gr_msg_queue_sptr target_queue, unsigned int occupied_carriers, + float phase_gain, float freq_gain) +{ + return gnuradio::get_initial_sptr(new gr_ofdm_frame_sink2(constell, + target_queue, occupied_carriers, + phase_gain, freq_gain)); +} + + +gr_ofdm_frame_sink2::gr_ofdm_frame_sink2(gr_constellation_sptr constell, + gr_msg_queue_sptr target_queue, unsigned int occupied_carriers, + float phase_gain, float freq_gain) + : gr_sync_block ("ofdm_frame_sink2", + gr_make_io_signature2 (2, 2, sizeof(gr_complex)*occupied_carriers, sizeof(char)), + gr_make_io_signature (1, 1, sizeof(gr_complex)*occupied_carriers)), + d_constell(constell), + d_target_queue(target_queue), d_occupied_carriers(occupied_carriers), + d_byte_offset(0), d_partial_byte(0), + d_resid(0), d_nresid(0),d_phase(0),d_freq(0),d_phase_gain(phase_gain),d_freq_gain(freq_gain), + d_eq_gain(0.05) +{ + if (d_constell->dimensionality() != 1) + throw std::runtime_error ("This receiver only works with constellations of dimension 1."); + + std::string carriers = "FE7F"; + + // A bit hacky to fill out carriers to occupied_carriers length + int diff = (d_occupied_carriers - 4*carriers.length()); + while(diff > 7) { + carriers.insert(0, "f"); + carriers.insert(carriers.length(), "f"); + diff -= 8; + } + + // if there's extras left to be processed + // divide remaining to put on either side of current map + // all of this is done to stick with the concept of a carrier map string that + // can be later passed by the user, even though it'd be cleaner to just do this + // on the carrier map itself + int diff_left=0; + int diff_right=0; + + // dictionary to convert from integers to ascii hex representation + char abc[16] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + if(diff > 0) { + char c[2] = {0,0}; + + diff_left = (int)ceil((float)diff/2.0f); // number of carriers to put on the left side + c[0] = abc[(1 << diff_left) - 1]; // convert to bits and move to ASCI integer + carriers.insert(0, c); + + diff_right = diff - diff_left; // number of carriers to put on the right side + c[0] = abc[0xF^((1 << diff_right) - 1)]; // convert to bits and move to ASCI integer + carriers.insert(carriers.length(), c); + } + + // It seemed like such a good idea at the time... + // because we are only dealing with the occupied_carriers + // at this point, the diff_left in the following compensates + // for any offset from the 0th carrier introduced + unsigned int i,j,k; + for(i = 0; i < (d_occupied_carriers/4)+diff_left; i++) { + char c = carriers[i]; + for(j = 0; j < 4; j++) { + k = (strtol(&c, NULL, 16) >> (3-j)) & 0x1; + if(k) { + d_subcarrier_map.push_back(4*i + j - diff_left); + } + } + } + + // make sure we stay in the limit currently imposed by the occupied_carriers + if(d_subcarrier_map.size() > d_occupied_carriers) { + throw std::invalid_argument("gr_ofdm_mapper_bcv: subcarriers allocated exceeds size of occupied carriers"); + } + + d_bytes_out = new unsigned char[d_occupied_carriers]; + d_dfe.resize(occupied_carriers); + fill(d_dfe.begin(), d_dfe.end(), gr_complex(1.0,0.0)); + + d_nbits = d_constell->bits_per_symbol(); + + enter_search(); +} + +gr_ofdm_frame_sink2::~gr_ofdm_frame_sink2 () +{ + delete [] d_bytes_out; +} + + +int +gr_ofdm_frame_sink2::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]; + const char *sig = (const char *) input_items[1]; + unsigned int j = 0; + unsigned int bytes=0; + + // If the output is connected, send it the derotated symbols + if(output_items.size() >= 1) + d_derotated_output = (gr_complex *)output_items[0]; + else + d_derotated_output = NULL; + + if (VERBOSE) + fprintf(stderr,">>> Entering state machine\n"); + + 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); + + if (sig[0]) { // Found it, set up for header decode + enter_have_sync(); + } + break; + + case STATE_HAVE_SYNC: + // only demod after getting the preamble signal; otherwise, the + // equalizer taps will screw with the PLL performance + bytes = demapper(&in[0], d_bytes_out); + + if (VERBOSE) { + if(sig[0]) + printf("ERROR -- Found SYNC in HAVE_SYNC\n"); + fprintf(stderr,"Header Search bitcnt=%d, header=0x%08x\n", + d_headerbytelen_cnt, d_header); + } + + j = 0; + while(j < bytes) { + d_header = (d_header << 8) | (d_bytes_out[j] & 0xFF); + j++; + + if (++d_headerbytelen_cnt == HEADERBYTELEN) { + + 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()){ + enter_have_header(); + + if (VERBOSE) + printf("\nPacket Length: %d\n", d_packetlen); + + while((j < bytes) && (d_packetlen_cnt < d_packetlen)) { + d_packet[d_packetlen_cnt++] = d_bytes_out[j++]; + } + + if(d_packetlen_cnt == d_packetlen) { + gr_message_sptr msg = + gr_make_message(0, d_packet_whitener_offset, 0, d_packetlen); + memcpy(msg->msg(), d_packet, d_packetlen_cnt); + d_target_queue->insert_tail(msg); // send it + msg.reset(); // free it up + + enter_search(); + } + } + else { + enter_search(); // bad header + } + } + } + break; + + case STATE_HAVE_HEADER: + bytes = demapper(&in[0], d_bytes_out); + + if (VERBOSE) { + if(sig[0]) + printf("ERROR -- Found SYNC in HAVE_HEADER at %d, length of %d\n", d_packetlen_cnt, d_packetlen); + fprintf(stderr,"Packet Build\n"); + } + + j = 0; + while(j < bytes) { + d_packet[d_packetlen_cnt++] = d_bytes_out[j++]; + + 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 + + return 1; +} diff --git a/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.h b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.h new file mode 100644 index 000000000..a743e8c5a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.h @@ -0,0 +1,121 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,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_OFDM_FRAME_SINK2_H +#define INCLUDED_GR_OFDM_FRAME_SINK2_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_msg_queue.h> +#include <gr_constellation.h> + +class gr_ofdm_frame_sink2; +typedef boost::shared_ptr<gr_ofdm_frame_sink2> gr_ofdm_frame_sink2_sptr; + +GR_CORE_API gr_ofdm_frame_sink2_sptr +gr_make_ofdm_frame_sink2 (gr_constellation_sptr constell, + gr_msg_queue_sptr target_queue, unsigned int occupied_tones, + float phase_gain=0.25, float freq_gain=0.25*0.25/4.0); + +/*! + * \brief Takes an OFDM symbol in, demaps it into bits of 0's and 1's, packs + * them into packets, and sends to to a message queue sink. + * \ingroup sink_blk + * \ingroup ofdm_blk + * + * NOTE: The mod input parameter simply chooses a pre-defined demapper/slicer. Eventually, + * we want to be able to pass in a reference to an object to do the demapping and slicing + * for a given modulation type. + */ +class GR_CORE_API gr_ofdm_frame_sink2 : public gr_sync_block +{ + friend GR_CORE_API gr_ofdm_frame_sink2_sptr + gr_make_ofdm_frame_sink2 (gr_constellation_sptr constell, + gr_msg_queue_sptr target_queue, unsigned int occupied_tones, + float phase_gain, float freq_gain); + + private: + enum state_t {STATE_SYNC_SEARCH, STATE_HAVE_SYNC, STATE_HAVE_HEADER}; + + static const int MAX_PKT_LEN = 4096; + static const int HEADERBYTELEN = 4; + + 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_headerbytelen_cnt; // how many so far + + unsigned char *d_bytes_out; // hold the current bytes produced by the demapper + + unsigned int d_occupied_carriers; + unsigned int d_byte_offset; + unsigned int d_partial_byte; + + unsigned char d_packet[MAX_PKT_LEN]; // assembled payload + 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 + + gr_complex * d_derotated_output; // Pointer to output stream to send deroated symbols out + + gr_constellation_sptr d_constell; + std::vector<gr_complex> d_dfe; + unsigned int d_nbits; + + unsigned char d_resid; + unsigned int d_nresid; + float d_phase; + float d_freq; + float d_phase_gain; + float d_freq_gain; + float d_eq_gain; + + std::vector<int> d_subcarrier_map; + + protected: + gr_ofdm_frame_sink2(gr_constellation_sptr constell, + gr_msg_queue_sptr target_queue, unsigned int occupied_tones, + float phase_gain, float freq_gain); + + void enter_search(); + void enter_have_sync(); + void enter_have_header(); + + bool header_ok() + { + // confirm that two copies of header info are identical + return ((d_header >> 16) ^ (d_header & 0xffff)) == 0; + } + + unsigned char slicer(const gr_complex x); + unsigned int demapper(const gr_complex *in, + unsigned char *out); + + public: + ~gr_ofdm_frame_sink2(); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_OFDM_FRAME_SINK2_H */ diff --git a/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.i b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.i new file mode 100644 index 000000000..8c04d1e16 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ofdm_frame_sink2.i @@ -0,0 +1,39 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,ofdm_frame_sink2); + +gr_ofdm_frame_sink2_sptr +gr_make_ofdm_frame_sink2(gr_constellation_sptr constell, + gr_msg_queue_sptr target_queue, unsigned int occupied_tones, + float phase_gain=0.25, float freq_gain=0.25*0.25/4); + +class gr_ofdm_frame_sink2 : public gr_sync_block +{ + protected: + gr_ofdm_frame_sink2(gr_constellation_sptr constell, + gr_msg_queue_sptr target_queue, unsigned int occupied_tones, + float phase_gain, float freq_gain); + + public: + ~gr_ofdm_frame_sink2(); +}; diff --git a/gnuradio-core/src/lib/general/gr_pa_2x2_phase_combiner.cc b/gnuradio-core/src/lib/general/gr_pa_2x2_phase_combiner.cc new file mode 100644 index 000000000..318753672 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pa_2x2_phase_combiner.cc @@ -0,0 +1,74 @@ +/* -*- 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_pa_2x2_phase_combiner.h> +#include <gr_io_signature.h> + +gr_pa_2x2_phase_combiner_sptr +gr_make_pa_2x2_phase_combiner() +{ + return gnuradio::get_initial_sptr(new gr_pa_2x2_phase_combiner()); +} + +gr_pa_2x2_phase_combiner::gr_pa_2x2_phase_combiner () + : gr_sync_block ("pa_2x2_phase_combiner", + gr_make_io_signature (1, 1, NM * sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (float))) +{ + set_theta(0); +} + +void +gr_pa_2x2_phase_combiner::set_theta(float theta) +{ + d_theta = theta; + gr_complex j = gr_complex(0,1); + d_phase[0] = exp(j * (float) (M_PI * (sin(theta) + cos(theta)))); + d_phase[1] = exp(j * (float) (M_PI * cos(theta))); + d_phase[2] = exp(j * (float) (M_PI * sin(theta))); + d_phase[3] = exp(j * (float) 0.0); +} + +int +gr_pa_2x2_phase_combiner::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]; + + for (int i = 0; i < noutput_items; i++){ + gr_complex acc = 0; + acc += in[0] * d_phase[0]; + acc += in[1] * d_phase[1]; + acc += in[2] * d_phase[2]; + acc += in[3] * d_phase[3]; + out[i] = acc; + in += 4; + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_pa_2x2_phase_combiner.h b/gnuradio-core/src/lib/general/gr_pa_2x2_phase_combiner.h new file mode 100644 index 000000000..d430d154f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pa_2x2_phase_combiner.h @@ -0,0 +1,63 @@ +/* -*- 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_PA_2X2_PHASE_COMBINER_H +#define INCLUDED_GR_PA_2X2_PHASE_COMBINER_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_pa_2x2_phase_combiner; +typedef boost::shared_ptr<gr_pa_2x2_phase_combiner> gr_pa_2x2_phase_combiner_sptr; + +GR_CORE_API gr_pa_2x2_phase_combiner_sptr gr_make_pa_2x2_phase_combiner (); + +/*! + * \brief pa_2x2 phase combiner + * \ingroup misc_blk + * + * Anntenas are arranged like this: + * + * 2 3 + * 0 1 + * + * dx and dy are lambda/2. + */ +class GR_CORE_API gr_pa_2x2_phase_combiner : public gr_sync_block +{ + static const int NM = 4; + + float d_theta; + gr_complex d_phase[NM]; + + gr_pa_2x2_phase_combiner (); + friend GR_CORE_API gr_pa_2x2_phase_combiner_sptr gr_make_pa_2x2_phase_combiner(); + + public: + float theta() const { return d_theta; } + void set_theta(float theta); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_PA_2X2_PHASE_COMBINER_H */ diff --git a/gnuradio-core/src/lib/general/gr_pa_2x2_phase_combiner.i b/gnuradio-core/src/lib/general/gr_pa_2x2_phase_combiner.i new file mode 100644 index 000000000..2cd373a5e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pa_2x2_phase_combiner.i @@ -0,0 +1,34 @@ +/* -*- 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,pa_2x2_phase_combiner) + +gr_pa_2x2_phase_combiner_sptr gr_make_pa_2x2_phase_combiner(); + +class gr_pa_2x2_phase_combiner : public gr_sync_block +{ + gr_pa_2x2_phase_combiner(); + + public: + float theta() const; + void set_theta(float theta); +}; diff --git a/gnuradio-core/src/lib/general/gr_pack_k_bits_bb.cc b/gnuradio-core/src/lib/general/gr_pack_k_bits_bb.cc new file mode 100644 index 000000000..0ea0c9e38 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pack_k_bits_bb.cc @@ -0,0 +1,69 @@ +/* -*- 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. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_pack_k_bits_bb.h> +#include <gr_io_signature.h> +#include <stdexcept> +#include <iostream> + +gr_pack_k_bits_bb_sptr gr_make_pack_k_bits_bb(unsigned k) +{ + return gnuradio::get_initial_sptr(new gr_pack_k_bits_bb(k)); +} + + +gr_pack_k_bits_bb::gr_pack_k_bits_bb (unsigned k) + : gr_sync_decimator("pack_k_bits_bb", + gr_make_io_signature (1, 1, sizeof(unsigned char)), + gr_make_io_signature (1, 1, sizeof(unsigned char)), + k), + d_k (k) +{ + if (d_k == 0) + throw std::out_of_range("interpolation must be > 0"); +} + +gr_pack_k_bits_bb::~gr_pack_k_bits_bb() +{ +} + +int +gr_pack_k_bits_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] = 0x00; + for(unsigned int j = 0; j < d_k; j++) { + out[i] |= (0x01 & in[i*d_k+j])<<(d_k-j-1); + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_pack_k_bits_bb.h b/gnuradio-core/src/lib/general/gr_pack_k_bits_bb.h new file mode 100644 index 000000000..8e1508c78 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pack_k_bits_bb.h @@ -0,0 +1,56 @@ +/* -*- 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_GR_PACK_K_BITS_BB_H +#define INCLUDED_GR_PACK_K_BITS_BB_H + +#include <gr_core_api.h> +#include <gr_sync_decimator.h> + +class gr_pack_k_bits_bb; +typedef boost::shared_ptr<gr_pack_k_bits_bb> gr_pack_k_bits_bb_sptr; +GR_CORE_API gr_pack_k_bits_bb_sptr gr_make_pack_k_bits_bb (unsigned k); + +class gr_pack_k_bits_bb; + +/*! + * \brief Converts a stream of bytes with 1 bit in the LSB to a byte with k relevent bits. + * \ingroup converter_blk + */ +class GR_CORE_API gr_pack_k_bits_bb : public gr_sync_decimator +{ + private: + friend GR_CORE_API gr_pack_k_bits_bb_sptr gr_make_pack_k_bits_bb (unsigned k); + + gr_pack_k_bits_bb (unsigned k); + + unsigned d_k; // number of relevent bits to pack from k input bytes + + public: + ~gr_pack_k_bits_bb (); + + 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_pack_k_bits_bb.i b/gnuradio-core/src/lib/general/gr_pack_k_bits_bb.i new file mode 100644 index 000000000..6ae2095ec --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pack_k_bits_bb.i @@ -0,0 +1,34 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,pack_k_bits_bb) + +gr_pack_k_bits_bb_sptr gr_make_pack_k_bits_bb (int k) throw(std::exception); + +class gr_pack_k_bits_bb : public gr_sync_decimator +{ + private: + gr_pack_k_bits_bb (int k); + + public: + ~gr_pack_k_bits_bb (); +}; diff --git a/gnuradio-core/src/lib/general/gr_packet_sink.cc b/gnuradio-core/src/lib/general/gr_packet_sink.cc new file mode 100644 index 000000000..19a8c5fc2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_packet_sink.cc @@ -0,0 +1,207 @@ +/* -*- 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 new file mode 100644 index 000000000..b4cb0b0f6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_packet_sink.h @@ -0,0 +1,112 @@ +/* -*- 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 new file mode 100644 index 000000000..d1290f9d3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_packet_sink.i @@ -0,0 +1,41 @@ +/* -*- 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_peak_detector2_fb.cc b/gnuradio-core/src/lib/general/gr_peak_detector2_fb.cc new file mode 100644 index 000000000..a4179a8c2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_peak_detector2_fb.cc @@ -0,0 +1,107 @@ +/* -*- 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_peak_detector2_fb.h> +#include <gr_io_signature.h> +#include <string.h> + +gr_peak_detector2_fb_sptr +gr_make_peak_detector2_fb (float threshold_factor_rise, + int look_ahead, float alpha) +{ + return gnuradio::get_initial_sptr(new gr_peak_detector2_fb (threshold_factor_rise, + look_ahead, alpha)); +} + +gr_peak_detector2_fb::gr_peak_detector2_fb (float threshold_factor_rise, + int look_ahead, float alpha) + : gr_sync_block ("peak_detector2_fb", + gr_make_io_signature (1, 1, sizeof(float)), + gr_make_io_signature2 (1, 2, sizeof(char), sizeof(float))), + d_threshold_factor_rise(threshold_factor_rise), + d_look_ahead(look_ahead), d_alpha(alpha), d_avg(0.0f), d_found(false) +{ +} + +int +gr_peak_detector2_fb::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) { + float *iptr = (float *) input_items[0]; + char *optr = (char *) output_items[0]; + + assert(noutput_items >= 2); + + memset(optr, 0, noutput_items*sizeof(char)); + + for (int i = 0; i < noutput_items; i++) { + + if (!d_found) { + // Have not yet detected presence of peak + if (iptr[i] > d_avg * (1.0f + d_threshold_factor_rise)) { + d_found = true; + d_look_ahead_remaining = d_look_ahead; + d_peak_val = -(float)INFINITY; + } + else { + d_avg = d_alpha*iptr[i] + (1.0f - d_alpha)*d_avg; + } + } + else { + // Detected presence of peak + if (iptr[i] > d_peak_val) { + d_peak_val = iptr[i]; + d_peak_ind = i; + } + else if (d_look_ahead_remaining <= 0) { + optr[d_peak_ind] = 1; + d_found = false; + d_avg = iptr[i]; + } + + // Have not yet located peak, loop and keep searching. + d_look_ahead_remaining--; + } + + // Every iteration of the loop, write debugging signal out if + // connected: + if (output_items.size() == 2) { + float *sigout = (float *) output_items[1]; + sigout[i] = d_avg; + } + } // loop + + if (!d_found) + return noutput_items; + + // else if detected presence, keep searching during the next call to work. + int tmp = d_peak_ind; + d_peak_ind = 1; + + return tmp - 1; +} + + diff --git a/gnuradio-core/src/lib/general/gr_peak_detector2_fb.h b/gnuradio-core/src/lib/general/gr_peak_detector2_fb.h new file mode 100644 index 000000000..665a6b882 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_peak_detector2_fb.h @@ -0,0 +1,109 @@ +/* -*- 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_peak_detector2_FB_H +#define INCLUDED_gr_peak_detector2_FB_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_peak_detector2_fb; +typedef boost::shared_ptr<gr_peak_detector2_fb> gr_peak_detector2_fb_sptr; + +GR_CORE_API gr_peak_detector2_fb_sptr gr_make_peak_detector2_fb (float threshold_factor_rise = 7, + int look_ahead = 1000, + float alpha = 0.001); + +/*! + * \brief Detect the peak of a signal + * \ingroup level_blk + * + * If a peak is detected, this block outputs a 1, + * or it outputs 0's. A separate debug output may be connected, to + * view the internal EWMA described below. + * + * \param threshold_factor_rise The threshold factor determins when a peak + * is present. An EWMA average of the signal is calculated and when the + * value of the signal goes over threshold_factor_rise*average, we + * call the peak. + * \param look_ahead The look-ahead value is used when the threshold is + * found to locate the peak within this range. + * \param alpha The gain value of a single-pole moving average filter + */ + +class GR_CORE_API gr_peak_detector2_fb : public gr_sync_block +{ + friend GR_CORE_API gr_peak_detector2_fb_sptr + gr_make_peak_detector2_fb (float threshold_factor_rise, int look_ahead, float alpha); + + gr_peak_detector2_fb (float threshold_factor_rise, int look_ahead, float alpha); + +private: + float d_threshold_factor_rise; + int d_look_ahead; + int d_look_ahead_remaining; + int d_peak_ind; + float d_peak_val; + float d_alpha; + float d_avg; + bool d_found; + +public: + + /*! \brief Set the threshold factor value for the rise time + * \param thr new threshold factor + */ + void set_threshold_factor_rise(float thr) { d_threshold_factor_rise = thr; } + + /*! \brief Set the look-ahead factor + * \param look new look-ahead factor + */ + void set_look_ahead(int look) { d_look_ahead = look; } + + /*! \brief Set the running average alpha + * \param alpha new alpha for running average + */ + void set_alpha(int alpha) { d_alpha = alpha; } + + /*! \brief Get the threshold factor value for the rise time + * \return threshold factor + */ + float threshold_factor_rise() { return d_threshold_factor_rise; } + + /*! \brief Get the look-ahead factor value + * \return look-ahead factor + */ + int look_ahead() { return d_look_ahead; } + + /*! \brief Get the alpha value of the running average + * \return alpha + */ + float alpha() { return d_alpha; } + + 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_peak_detector2_fb.i b/gnuradio-core/src/lib/general/gr_peak_detector2_fb.i new file mode 100644 index 000000000..ec7227e69 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_peak_detector2_fb.i @@ -0,0 +1,45 @@ +/* -*- 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,peak_detector2_fb) + + gr_peak_detector2_fb_sptr gr_make_peak_detector2_fb (float threshold_factor_rise = 7, + int look_ahead = 1000, + float alpha=0.001); + +class gr_peak_detector2_fb : public gr_sync_block +{ +private: + gr_peak_detector2_fb (float threshold_factor_rise, int look_ahead, float alpha); + +public: + void set_threshold_factor_rise(float thr) { d_threshold_factor_rise = thr; } + void set_look_ahead(int look) { d_look_ahead = look; } + void set_alpha(int alpha) { d_avg_alpha = alpha; } + + float threshold_factor_rise() { return d_threshold_factor_rise; } + int look_ahead() { return d_look_ahead; } + float alpha() { return d_avg_alpha; } +}; + + diff --git a/gnuradio-core/src/lib/general/gr_phase_modulator_fc.cc b/gnuradio-core/src/lib/general/gr_phase_modulator_fc.cc new file mode 100644 index 000000000..fb05c85a5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_phase_modulator_fc.cc @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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_phase_modulator_fc.h> +#include <gr_io_signature.h> +#include <gr_sincos.h> +#include <math.h> + + +gr_phase_modulator_fc_sptr gr_make_phase_modulator_fc (double sensitivity) +{ + return gnuradio::get_initial_sptr(new gr_phase_modulator_fc (sensitivity)); +} + +gr_phase_modulator_fc::gr_phase_modulator_fc (double sensitivity) + : gr_sync_block ("phase_modulator_fc", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (gr_complex))), + d_sensitivity (sensitivity), d_phase (0) +{ +} + +int +gr_phase_modulator_fc::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]; + gr_complex *out = (gr_complex *) output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + d_phase = d_sensitivity * in[i]; + float oi, oq; + gr_sincosf (d_phase, &oq, &oi); + out[i] = gr_complex (oi, oq); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_phase_modulator_fc.h b/gnuradio-core/src/lib/general/gr_phase_modulator_fc.h new file mode 100644 index 000000000..07f3b82d4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_phase_modulator_fc.h @@ -0,0 +1,56 @@ +/* -*- 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_PHASE_MODULATOR_FC_H +#define INCLUDED_GR_PHASE_MODULATOR_FC_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_phase_modulator_fc; +typedef boost::shared_ptr<gr_phase_modulator_fc> gr_phase_modulator_fc_sptr; + +GR_CORE_API gr_phase_modulator_fc_sptr gr_make_phase_modulator_fc (double sensitivity); + +/*! + * \brief Phase modulator block + * \ingroup modulation_blk + * output=complex(cos(in*sensitivity),sin(in*sensitivity)) + */ +class GR_CORE_API gr_phase_modulator_fc : public gr_sync_block +{ + double d_sensitivity; + double d_phase; + + friend GR_CORE_API gr_phase_modulator_fc_sptr + gr_make_phase_modulator_fc (double sensitivity); + + gr_phase_modulator_fc (double sensitivity); + + public: + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_PHASE_MODULATOR_FC_H */ diff --git a/gnuradio-core/src/lib/general/gr_phase_modulator_fc.i b/gnuradio-core/src/lib/general/gr_phase_modulator_fc.i new file mode 100644 index 000000000..c1816c647 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_phase_modulator_fc.i @@ -0,0 +1,31 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,phase_modulator_fc) + +gr_phase_modulator_fc_sptr gr_make_phase_modulator_fc (double sensitivity); + +class gr_phase_modulator_fc : public gr_sync_block +{ + private: + gr_phase_modulator_fc (double sensitivity); +}; diff --git a/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.cc b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.cc new file mode 100644 index 000000000..b7b1291a3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.cc @@ -0,0 +1,120 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_pll_carriertracking_cc.h> +#include <gr_io_signature.h> +#include <gr_sincos.h> +#include <math.h> +#include <gr_math.h> + +#ifndef M_TWOPI +#define M_TWOPI (2.0f*M_PI) +#endif + +gr_pll_carriertracking_cc_sptr +gr_make_pll_carriertracking_cc (float loop_bw, float max_freq, float min_freq) +{ + return gnuradio::get_initial_sptr(new gr_pll_carriertracking_cc (loop_bw, max_freq, min_freq)); +} + +gr_pll_carriertracking_cc::gr_pll_carriertracking_cc (float loop_bw, + float max_freq, + float min_freq) + : gr_sync_block ("pll_carriertracking_cc", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (gr_complex))), + gri_control_loop(loop_bw, max_freq, min_freq), + d_locksig(0), d_lock_threshold(0), d_squelch_enable(false) +{ +} + +float +gr_pll_carriertracking_cc::mod_2pi (float in) +{ + if(in>M_PI) + return in-M_TWOPI; + else if(in<-M_PI) + return in+M_TWOPI; + else + return in; +} + +float +gr_pll_carriertracking_cc::phase_detector(gr_complex sample,float ref_phase) +{ + float sample_phase; + // sample_phase = atan2(sample.imag(),sample.real()); + sample_phase = gr_fast_atan2f(sample.imag(),sample.real()); + return mod_2pi(sample_phase-ref_phase); +} + +bool +gr_pll_carriertracking_cc::lock_detector(void) +{ + return (fabsf(d_locksig) > d_lock_threshold); +} + +bool +gr_pll_carriertracking_cc::squelch_enable(bool set_squelch) +{ + return d_squelch_enable = set_squelch; +} + +float +gr_pll_carriertracking_cc::set_lock_threshold(float threshold) +{ + return d_lock_threshold = threshold; +} + +int +gr_pll_carriertracking_cc::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const gr_complex *iptr = (gr_complex *) input_items[0]; + gr_complex *optr = (gr_complex *) output_items[0]; + + float error; + float t_imag, t_real; + + for (int i = 0; i < noutput_items; i++){ + gr_sincosf(d_phase, &t_imag, &t_real); + optr[i] = iptr[i] * gr_complex(t_real, -t_imag); + + error = phase_detector(iptr[i],d_phase); + + advance_loop(error); + phase_wrap(); + frequency_limit(); + + d_locksig = d_locksig * (1.0 - d_alpha) + \ + d_alpha*(iptr[i].real() * t_real + iptr[i].imag() * t_imag); + + if ((d_squelch_enable) && !lock_detector()) + optr[i] = 0; + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.h b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.h new file mode 100644 index 000000000..b3bc5ddd0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.h @@ -0,0 +1,74 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_PLL_CARRIERTRACKING_CC_H +#define INCLUDED_GR_PLL_CARRIERTRACKING_CC_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gri_control_loop.h> + +class gr_pll_carriertracking_cc; +typedef boost::shared_ptr<gr_pll_carriertracking_cc> gr_pll_carriertracking_cc_sptr; + +GR_CORE_API gr_pll_carriertracking_cc_sptr gr_make_pll_carriertracking_cc (float loop_bw, + float max_freq, + float min_freq); +/*! + * \brief Implements a PLL which locks to the input frequency and outputs the + * input signal mixed with that carrier. + * \ingroup sync_blk + * + * input: stream of complex; output: stream of complex + * + * This PLL locks onto a [possibly noisy] reference carrier on + * the input and outputs that signal, downconverted to DC + * + * All settings max_freq and min_freq are in terms of radians per sample, + * NOT HERTZ. The loop bandwidth determins the lock range and should be set + * around pi/200 -- 2pi/100. + * \sa gr_pll_freqdet_cf, gr_pll_carriertracking_cc + */ + +class GR_CORE_API gr_pll_carriertracking_cc : public gr_sync_block, public gri_control_loop +{ + friend GR_CORE_API gr_pll_carriertracking_cc_sptr gr_make_pll_carriertracking_cc (float loop_bw, + float max_freq, + float min_freq); + + float d_locksig,d_lock_threshold; + bool d_squelch_enable; + gr_pll_carriertracking_cc (float loop_bw, float max_freq, float min_freq); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +private: + float mod_2pi (float in); + float phase_detector(gr_complex sample,float ref_phase); +public: + bool lock_detector(void); + bool squelch_enable(bool); + float set_lock_threshold(float); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.i b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.i new file mode 100644 index 000000000..a20adf7e2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.i @@ -0,0 +1,39 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,pll_carriertracking_cc); + +gr_pll_carriertracking_cc_sptr +gr_make_pll_carriertracking_cc (float loop_bw, + float max_freq, + float min_freq); + +class gr_pll_carriertracking_cc : public gr_sync_block, public gri_control_loop +{ + private: + gr_pll_carriertracking_cc (float loop_bw, float max_freq, float min_freq); + public: + bool lock_detector(void); + bool squelch_enable(bool); + float set_lock_threshold(float); + +}; diff --git a/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.cc b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.cc new file mode 100644 index 000000000..f80f4ed07 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.cc @@ -0,0 +1,90 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_pll_freqdet_cf.h> +#include <gr_io_signature.h> +#include <math.h> +#include <gr_math.h> + +#ifndef M_TWOPI +#define M_TWOPI (2.0f*M_PI) +#endif + +gr_pll_freqdet_cf_sptr +gr_make_pll_freqdet_cf (float loop_bw, float max_freq, float min_freq) +{ + return gnuradio::get_initial_sptr(new gr_pll_freqdet_cf (loop_bw, max_freq, min_freq)); +} + +gr_pll_freqdet_cf::gr_pll_freqdet_cf (float loop_bw, float max_freq, float min_freq) + : gr_sync_block ("pll_freqdet_cf", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (float))), + gri_control_loop(loop_bw, max_freq, min_freq) +{ +} + +float +gr_pll_freqdet_cf::mod_2pi (float in) +{ + if(in>M_PI) + return in-M_TWOPI; + else if(in<-M_PI) + return in+M_TWOPI; + else + return in; +} + +float +gr_pll_freqdet_cf::phase_detector(gr_complex sample,float ref_phase) +{ + float sample_phase; + sample_phase = gr_fast_atan2f(sample.imag(),sample.real()); + return mod_2pi(sample_phase-ref_phase); +} + +int +gr_pll_freqdet_cf::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const gr_complex *iptr = (gr_complex *) input_items[0]; + float *optr = (float *) output_items[0]; + + float error; + int size = noutput_items; + + while (size-- > 0) { + *optr++ = d_freq; + + error = phase_detector(*iptr++,d_phase); + + advance_loop(error); + phase_wrap(); + frequency_limit(); + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.h b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.h new file mode 100644 index 000000000..3dfc8d709 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.h @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_PLL_FREQDET_CF_H +#define INCLUDED_GR_PLL_FREQDET_CF_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gri_control_loop.h> + +class gr_pll_freqdet_cf; +typedef boost::shared_ptr<gr_pll_freqdet_cf> gr_pll_freqdet_cf_sptr; + +GR_CORE_API gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float loop_bw, + float max_freq, + float min_freq); +/*! + * \brief Implements a PLL which locks to the input frequency and outputs + * an estimate of that frequency. Useful for FM Demod. + * \ingroup sync_blk + * + * input: stream of complex; output: stream of floats + * + * This PLL locks onto a [possibly noisy] reference carrier on + * the input and outputs an estimate of that frequency in radians per sample. + * All settings max_freq and min_freq are in terms of radians per sample, + * NOT HERTZ. The loop bandwidth determins the lock range and should be set + * around pi/200 -- 2pi/100. + * \sa gr_pll_refout_cc, gr_pll_carriertracking_cc + */ + +class GR_CORE_API gr_pll_freqdet_cf : public gr_sync_block, public gri_control_loop +{ + friend GR_CORE_API gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float loop_bw, + float max_freq, + float min_freq); + + float mod_2pi (float in); + gr_pll_freqdet_cf (float loop_bw, float max_freq, float min_freq); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +private: + float phase_detector(gr_complex sample,float ref_phase); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.i b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.i new file mode 100644 index 000000000..87e515adb --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.i @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,pll_freqdet_cf) + + gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float loop_bw, + float max_freq, + float min_freq); + +class gr_pll_freqdet_cf : public gr_sync_block, public gri_control_loop +{ + private: + gr_pll_freqdet_cf (float loop_bw, float max_freq, float min_freq); +}; diff --git a/gnuradio-core/src/lib/general/gr_pll_refout_cc.cc b/gnuradio-core/src/lib/general/gr_pll_refout_cc.cc new file mode 100644 index 000000000..9f95c3f64 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_refout_cc.cc @@ -0,0 +1,93 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_pll_refout_cc.h> +#include <gr_io_signature.h> +#include <gr_sincos.h> +#include <math.h> +#include <gr_math.h> + +#ifndef M_TWOPI +#define M_TWOPI (2.0f*M_PI) +#endif + +gr_pll_refout_cc_sptr +gr_make_pll_refout_cc (float loop_bw, float max_freq, float min_freq) +{ + return gnuradio::get_initial_sptr(new gr_pll_refout_cc (loop_bw, max_freq, min_freq)); +} + +gr_pll_refout_cc::gr_pll_refout_cc (float loop_bw, float max_freq, float min_freq) + : gr_sync_block ("pll_refout_cc", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (gr_complex))), + gri_control_loop(loop_bw, max_freq, min_freq) +{ +} + +float +gr_pll_refout_cc::mod_2pi (float in) +{ + if(in>M_PI) + return in-M_TWOPI; + else if(in<-M_PI) + return in+M_TWOPI; + else + return in; +} + +float +gr_pll_refout_cc::phase_detector(gr_complex sample,float ref_phase) +{ + float sample_phase; + sample_phase = gr_fast_atan2f(sample.imag(),sample.real()); + return mod_2pi(sample_phase-ref_phase); +} + +int +gr_pll_refout_cc::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const gr_complex *iptr = (gr_complex *) input_items[0]; + gr_complex *optr = (gr_complex *) output_items[0]; + + float error; + float t_imag, t_real; + int size = noutput_items; + + while (size-- > 0) { + gr_sincosf(d_phase,&t_imag,&t_real); + *optr++ = gr_complex(t_real,t_imag); + + error = phase_detector(*iptr++,d_phase); + + advance_loop(error); + phase_wrap(); + frequency_limit(); + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_pll_refout_cc.h b/gnuradio-core/src/lib/general/gr_pll_refout_cc.h new file mode 100644 index 000000000..ef5cd31e2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_refout_cc.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_PLL_REFOUT_CC_H +#define INCLUDED_GR_PLL_REFOUT_CC_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gri_control_loop.h> + +class gr_pll_refout_cc; +typedef boost::shared_ptr<gr_pll_refout_cc> gr_pll_refout_cc_sptr; + +GR_CORE_API gr_pll_refout_cc_sptr gr_make_pll_refout_cc (float loop_bw, + float max_freq, float min_freq); +/*! + * \brief Implements a PLL which locks to the input frequency and outputs a carrier + * \ingroup sync_blk + * + * input: stream of complex; output: stream of complex + * + * This PLL locks onto a [possibly noisy] reference carrier on + * the input and outputs a clean version which is phase and frequency + * aligned to it. + * + * All settings max_freq and min_freq are in terms of radians per sample, + * NOT HERTZ. The loop bandwidth determins the lock range and should be set + * around pi/200 -- 2pi/100. + * \sa gr_pll_freqdet_cf, gr_pll_carriertracking_cc + */ +class GR_CORE_API gr_pll_refout_cc : public gr_sync_block, public gri_control_loop +{ + friend GR_CORE_API gr_pll_refout_cc_sptr gr_make_pll_refout_cc (float loop_bw, + float max_freq, float min_freq); + + gr_pll_refout_cc (float loop_bw, float max_freq, float min_freq); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +private: + float mod_2pi (float in); + float phase_detector(gr_complex sample, float ref_phase); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_pll_refout_cc.i b/gnuradio-core/src/lib/general/gr_pll_refout_cc.i new file mode 100644 index 000000000..630c0444f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_refout_cc.i @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2011 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,pll_refout_cc) + +gr_pll_refout_cc_sptr gr_make_pll_refout_cc (float loop_bw, + float max_freq, float min_freq); + +class gr_pll_refout_cc : public gr_sync_block, public gri_control_loop +{ + private: + gr_pll_refout_cc (float loop_bw, float max_freq, float min_freq); +}; diff --git a/gnuradio-core/src/lib/general/gr_pn_correlator_cc.cc b/gnuradio-core/src/lib/general/gr_pn_correlator_cc.cc new file mode 100644 index 000000000..818e48c34 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pn_correlator_cc.cc @@ -0,0 +1,77 @@ +/* -*- 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 new file mode 100644 index 000000000..69bd2c502 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pn_correlator_cc.h @@ -0,0 +1,62 @@ +/* -*- 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 new file mode 100644 index 000000000..e992f33a7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pn_correlator_cc.i @@ -0,0 +1,32 @@ +/* -*- 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_prefs.cc b/gnuradio-core/src/lib/general/gr_prefs.cc new file mode 100644 index 000000000..9705eed4f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_prefs.cc @@ -0,0 +1,229 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gr_prefs.h> +#include <gr_sys_paths.h> +#include <gr_constants.h> +#include <algorithm> + +#include <boost/filesystem/operations.hpp> +#include <boost/filesystem/path.hpp> +#include <boost/filesystem/fstream.hpp> +namespace fs = boost::filesystem; + +/* + * Stub implementations + */ + +static gr_prefs s_default_singleton; +static gr_prefs *s_singleton = &s_default_singleton; + +gr_prefs * +gr_prefs::singleton() +{ + return s_singleton; +} + +void +gr_prefs::set_singleton(gr_prefs *p) +{ + s_singleton = p; +} + +gr_prefs::gr_prefs() +{ + _read_files(); +} + +gr_prefs::~gr_prefs() +{ + // nop +} + +std::vector<std::string> +gr_prefs::_sys_prefs_filenames() +{ + std::vector<std::string> fnames; + + fs::path dir = gr_prefsdir(); + if(!fs::is_directory(dir)) + return fnames; + + fs::directory_iterator diritr(dir); + while(diritr != fs::directory_iterator()) { + fs::path p = *diritr++; + fnames.push_back(p.string()); + } + std::sort(fnames.begin(), fnames.end()); + + // Find if there is a ~/.gnuradio/config file and add this to the + // beginning of the file list to override any preferences in the + // installed path config files. + fs::path homedir = fs::path(gr_appdata_path()); + homedir = homedir/".gnuradio/config.conf"; + if(fs::exists(homedir)) { + fnames.insert(fnames.begin(), homedir.string()); + } + + return fnames; +} + +void +gr_prefs::_read_files() +{ + std::vector<std::string> filenames = _sys_prefs_filenames(); + std::vector<std::string>::iterator sitr; + char tmp[1024]; + for(sitr = filenames.begin(); sitr != filenames.end(); sitr++) { + fs::ifstream fin(*sitr); + while(!fin.eof()) { + fin.getline(tmp, 1024); + std::string t(tmp); + // ignore empty lines or lines of just comments + if((t.size() > 0) && (t[0] != '#')) { + // remove any comments in the line + size_t hash = t.find("#"); + + // Use hash marks at the end of each segment as a delimiter + d_configs += t.substr(0, hash) + '#'; + } + } + fin.close(); + } + + // Remove all whitespace + d_configs.erase(std::remove_if(d_configs.begin(), d_configs.end(), ::isspace), d_configs.end()); +} + +bool +gr_prefs::has_section(const std::string §ion) +{ + size_t t = d_configs.find("[" + section + "]#"); + return t != std::string::npos; +} + +bool +gr_prefs::has_option(const std::string §ion, const std::string &option) +{ + if(has_section(section)) { + size_t sec = d_configs.find("[" + section + "]#"); + size_t opt = d_configs.find("#" + option + "=", sec); + return opt != std::string::npos; + } + else { + return false; + } +} + +const std::string +gr_prefs::get_string(const std::string §ion, const std::string &option, + const std::string &default_val) +{ + std::stringstream envname; + std::string secname=section, optname=option; + + std::transform(section.begin(), section.end(), secname.begin(), ::toupper); + std::transform(option.begin(), option.end(), optname.begin(), ::toupper); + envname << "GR_CONF_" << secname << "_" << optname; + + char *v = getenv(envname.str().c_str()); + if(v) { + return std::string(v); + } + + if(has_option(section, option)) { + std::string optname = "#" + option + "="; + size_t sec = d_configs.find("[" + section + "]#"); + size_t opt = d_configs.find(optname, sec); + + size_t start = opt + optname.size(); + size_t end = d_configs.find("#", start); + size_t len = end - start; + + return d_configs.substr(start, len); + } + else { + return default_val; + } +} + +bool +gr_prefs::get_bool(const std::string §ion, const std::string &option, bool default_val) +{ + if(has_option(section, option)) { + std::string str = get_string(section, option, ""); + if(str == "") { + return default_val; + } + std::transform(str.begin(), str.end(), str.begin(), ::tolower); + if((str == "true") || (str == "on") || (str == "1")) + return true; + else if((str == "false") || (str == "off") || (str == "0")) + return false; + else + return default_val; + } + else { + return default_val; + } +} + +long +gr_prefs::get_long(const std::string §ion, const std::string &option, long default_val) +{ + if(has_option(section, option)) { + std::string str = get_string(section, option, ""); + if(str == "") { + return default_val; + } + std::stringstream sstr(str); + long n; + sstr >> n; + return n; + } + else { + return default_val; + } +} + +double +gr_prefs::get_double(const std::string §ion, const std::string &option, double default_val) +{ + if(has_option(section, option)) { + std::string str = get_string(section, option, ""); + if(str == "") { + return default_val; + } + std::stringstream sstr(str); + double n; + sstr >> n; + return n; + } + else { + return default_val; + } +} + diff --git a/gnuradio-core/src/lib/general/gr_prefs.h b/gnuradio-core/src/lib/general/gr_prefs.h new file mode 100644 index 000000000..dc2745d16 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_prefs.h @@ -0,0 +1,94 @@ +/* -*- 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_PREFS_H +#define INCLUDED_GR_PREFS_H + +#include <gr_core_api.h> +#include <string> +#include <gruel/thread.h> + +/*! + * \brief Base class for representing user preferences a la windows INI files. + * \ingroup misc + * + * The real implementation is in Python, and is accessable from C++ + * via the magic of SWIG directors. + */ + +class GR_CORE_API gr_prefs +{ +public: + static gr_prefs *singleton(); + static void set_singleton(gr_prefs *p); + + gr_prefs(); + virtual ~gr_prefs(); + + /*! + * \brief Does \p section exist? + */ + virtual bool has_section(const std::string §ion); + + /*! + * \brief Does \p option exist? + */ + virtual bool has_option(const std::string §ion, const std::string &option); + + /*! + * \brief If option exists return associated value; else default_val. + */ + virtual const std::string get_string(const std::string §ion, + const std::string &option, + const std::string &default_val); + + /*! + * \brief If option exists and value can be converted to bool, return it; else default_val. + */ + virtual bool get_bool(const std::string §ion, + const std::string &option, + bool default_val); + + /*! + * \brief If option exists and value can be converted to long, return it; else default_val. + */ + virtual long get_long(const std::string §ion, + const std::string &option, + long default_val); + + /*! + * \brief If option exists and value can be converted to double, return it; else default_val. + */ + virtual double get_double(const std::string §ion, + const std::string &option, + double default_val); + + protected: + virtual std::vector<std::string> _sys_prefs_filenames(); + virtual void _read_files(); + + private: + gruel::mutex d_mutex; + std::string d_configs; +}; + + +#endif /* INCLUDED_GR_PREFS_H */ diff --git a/gnuradio-core/src/lib/general/gr_prefs.i b/gnuradio-core/src/lib/general/gr_prefs.i new file mode 100644 index 000000000..b21d47f3b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_prefs.i @@ -0,0 +1,69 @@ +/* -*- 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. + */ + +class gr_prefs +{ +public: + static gr_prefs *singleton(); + static void set_singleton(gr_prefs *p); + + virtual ~gr_prefs(); + + /*! + * \brief Does \p section exist? + */ + virtual bool has_section(const std::string §ion); + + /*! + * \brief Does \p option exist? + */ + virtual bool has_option(const std::string §ion, const std::string &option); + + /*! + * \brief If option exists return associated value; else default_val. + */ + virtual const std::string get_string(const std::string §ion, + const std::string &option, + const std::string &default_val); + + /*! + * \brief If option exists and value can be converted to bool, return it; else default_val. + */ + virtual bool get_bool(const std::string §ion, + const std::string &option, + bool default_val); + + /*! + * \brief If option exists and value can be converted to long, return it; else default_val. + */ + virtual long get_long(const std::string §ion, + const std::string &option, + long default_val); + + /*! + * \brief If option exists and value can be converted to double, return it; else default_val. + */ + virtual double get_double(const std::string §ion, + const std::string &option, + double default_val); +}; + diff --git a/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_c.cc b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_c.cc new file mode 100644 index 000000000..6430d2753 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_c.cc @@ -0,0 +1,84 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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_probe_avg_mag_sqrd_c.h> +#include <gr_io_signature.h> +#include <cmath> + +gr_probe_avg_mag_sqrd_c_sptr +gr_make_probe_avg_mag_sqrd_c(double threshold_db, double alpha) +{ + return gnuradio::get_initial_sptr(new gr_probe_avg_mag_sqrd_c(threshold_db, alpha)); +} + +gr_probe_avg_mag_sqrd_c::gr_probe_avg_mag_sqrd_c (double threshold_db, double alpha) + : gr_sync_block ("probe_avg_mag_sqrd_c", + gr_make_io_signature(1, 1, sizeof(gr_complex)), + gr_make_io_signature(0, 0, 0)), + d_iir(alpha), d_unmuted(false), d_level(0) +{ + set_threshold (threshold_db); +} + +gr_probe_avg_mag_sqrd_c::~gr_probe_avg_mag_sqrd_c() +{ +} + + +int +gr_probe_avg_mag_sqrd_c::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const gr_complex *in = (const gr_complex *) input_items[0]; + + for (int i = 0; i < noutput_items; i++){ + double mag_sqrd = in[i].real()*in[i].real() + in[i].imag()*in[i].imag(); + d_iir.filter(mag_sqrd); // computed for side effect: prev_output() + } + + d_unmuted = d_iir.prev_output() >= d_threshold; + d_level = d_iir.prev_output(); + return noutput_items; +} + +double +gr_probe_avg_mag_sqrd_c::threshold() const +{ + return 10 * std::log10(d_threshold); +} + +void +gr_probe_avg_mag_sqrd_c::set_threshold(double decibels) +{ + // convert to absolute threshold (mag squared) + d_threshold = std::pow(10.0, decibels/10); +} + +void +gr_probe_avg_mag_sqrd_c::set_alpha(double alpha) +{ + d_iir.set_taps(alpha); +} diff --git a/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_c.h b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_c.h new file mode 100644 index 000000000..2811677cf --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_c.h @@ -0,0 +1,75 @@ +/* -*- 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_PROBE_AVG_MAG_SQRD_C_H +#define INCLUDED_GR_PROBE_AVG_MAG_SQRD_C_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_single_pole_iir.h> + +class gr_probe_avg_mag_sqrd_c; +typedef boost::shared_ptr<gr_probe_avg_mag_sqrd_c> gr_probe_avg_mag_sqrd_c_sptr; + +GR_CORE_API gr_probe_avg_mag_sqrd_c_sptr +gr_make_probe_avg_mag_sqrd_c (double threshold_db, double alpha = 0.0001); + +/*! + * \brief compute avg magnitude squared. + * \ingroup sink_blk + * + * input: gr_complex + * + * Compute a running average of the magnitude squared of the the input. + * The level and indication as to whether the level exceeds threshold + * can be retrieved with the level and unmuted accessors. + */ +class GR_CORE_API gr_probe_avg_mag_sqrd_c : public gr_sync_block +{ + double d_threshold; + gr_single_pole_iir<double,double,double> d_iir; + bool d_unmuted; + double d_level; + + friend GR_CORE_API gr_probe_avg_mag_sqrd_c_sptr + gr_make_probe_avg_mag_sqrd_c (double threshold_db, double alpha); + + gr_probe_avg_mag_sqrd_c (double threshold_db, double alpha); + +public: + ~gr_probe_avg_mag_sqrd_c (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + // ACCESSORS + bool unmuted () const { return d_unmuted; } + double level () const { return d_level; } + + double threshold() const; + + // SETTERS + void set_alpha (double alpha); + void set_threshold (double decibels); +}; + +#endif /* INCLUDED_GR_PROBE_AVG_MAG_SQRD_C_H */ diff --git a/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_c.i b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_c.i new file mode 100644 index 000000000..bce244c12 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_c.i @@ -0,0 +1,36 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,probe_avg_mag_sqrd_c); + +gr_probe_avg_mag_sqrd_c_sptr +gr_make_probe_avg_mag_sqrd_c (double threshold_db, double alpha = 0.0001); + +class gr_probe_avg_mag_sqrd_c : public gr_sync_block +{ +public: + bool unmuted () const { return d_unmuted; } + double level () const { return d_level; } + void set_alpha (double alpha); + void set_threshold (double decibels); + double threshold(); +}; diff --git a/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_cf.cc b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_cf.cc new file mode 100644 index 000000000..b5946283b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_cf.cc @@ -0,0 +1,86 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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_probe_avg_mag_sqrd_cf.h> +#include <gr_io_signature.h> +#include <cmath> + +gr_probe_avg_mag_sqrd_cf_sptr +gr_make_probe_avg_mag_sqrd_cf(double threshold_db, double alpha) +{ + return gnuradio::get_initial_sptr(new gr_probe_avg_mag_sqrd_cf(threshold_db, alpha)); +} + +gr_probe_avg_mag_sqrd_cf::gr_probe_avg_mag_sqrd_cf (double threshold_db, double alpha) + : gr_sync_block ("probe_avg_mag_sqrd_cf", + gr_make_io_signature(1, 1, sizeof(gr_complex)), + gr_make_io_signature(1, 1, sizeof(float))), + d_iir(alpha), d_unmuted(false), d_level(0) +{ + set_threshold (threshold_db); +} + +gr_probe_avg_mag_sqrd_cf::~gr_probe_avg_mag_sqrd_cf() +{ +} + + +int +gr_probe_avg_mag_sqrd_cf::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]; + float *out = (float *) output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + out[i] = d_iir.prev_output(); + double mag_sqrd = in[i].real()*in[i].real() + in[i].imag()*in[i].imag(); + d_iir.filter(mag_sqrd); // computed for side effect: prev_output() + } + + d_unmuted = d_iir.prev_output() >= d_threshold; + d_level = d_iir.prev_output(); + return noutput_items; +} + +double +gr_probe_avg_mag_sqrd_cf::threshold() const +{ + return 10 * std::log10(d_threshold); +} + +void +gr_probe_avg_mag_sqrd_cf::set_threshold(double decibels) +{ + // convert to absolute threshold (mag squared) + d_threshold = std::pow(10.0, decibels/10); +} + +void +gr_probe_avg_mag_sqrd_cf::set_alpha(double alpha) +{ + d_iir.set_taps(alpha); +} diff --git a/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_cf.h b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_cf.h new file mode 100644 index 000000000..bb5d1ebf9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_cf.h @@ -0,0 +1,77 @@ +/* -*- 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_PROBE_AVG_MAG_SQRD_CF_H +#define INCLUDED_GR_PROBE_AVG_MAG_SQRD_CF_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_single_pole_iir.h> + +class gr_probe_avg_mag_sqrd_cf; +typedef boost::shared_ptr<gr_probe_avg_mag_sqrd_cf> gr_probe_avg_mag_sqrd_cf_sptr; + +GR_CORE_API gr_probe_avg_mag_sqrd_cf_sptr +gr_make_probe_avg_mag_sqrd_cf (double threshold_db, double alpha = 0.0001); + +/*! + * \brief compute avg magnitude squared. + * \ingroup sink_blk + * + * input: gr_complex + * output: gr_float + * + * Compute a running average of the magnitude squared of the the input. + * The level and indication as to whether the level exceeds threshold + * can be retrieved with the level and unmuted accessors. + * + */ +class GR_CORE_API gr_probe_avg_mag_sqrd_cf : public gr_sync_block +{ + double d_threshold; + gr_single_pole_iir<double,double,double> d_iir; + bool d_unmuted; + double d_level; + + friend GR_CORE_API gr_probe_avg_mag_sqrd_cf_sptr + gr_make_probe_avg_mag_sqrd_cf (double threshold_db, double alpha); + + gr_probe_avg_mag_sqrd_cf (double threshold_db, double alpha); + +public: + ~gr_probe_avg_mag_sqrd_cf (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + // ACCESSORS + bool unmuted () const { return d_unmuted; } + double level () const { return d_level; } + + double threshold() const; + + // SETTERS + void set_alpha (double alpha); + void set_threshold (double decibels); +}; + +#endif /* INCLUDED_GR_PROBE_AVG_MAG_SQRD_CF_H */ diff --git a/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_cf.i b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_cf.i new file mode 100644 index 000000000..bf76d973b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_cf.i @@ -0,0 +1,36 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,probe_avg_mag_sqrd_cf); + +gr_probe_avg_mag_sqrd_cf_sptr +gr_make_probe_avg_mag_sqrd_cf (double threshold_db, double alpha = 0.0001); + +class gr_probe_avg_mag_sqrd_cf : public gr_sync_block +{ +public: + bool unmuted () const { return d_unmuted; } + double level () const { return d_level; } + void set_alpha (double alpha); + void set_threshold (double decibels); + double threshold(); +}; diff --git a/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_f.cc b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_f.cc new file mode 100644 index 000000000..4ed40743f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_f.cc @@ -0,0 +1,84 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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_probe_avg_mag_sqrd_f.h> +#include <gr_io_signature.h> +#include <cmath> + +gr_probe_avg_mag_sqrd_f_sptr +gr_make_probe_avg_mag_sqrd_f(double threshold_db, double alpha) +{ + return gnuradio::get_initial_sptr(new gr_probe_avg_mag_sqrd_f(threshold_db, alpha)); +} + +gr_probe_avg_mag_sqrd_f::gr_probe_avg_mag_sqrd_f (double threshold_db, double alpha) + : gr_sync_block ("probe_avg_mag_sqrd_f", + gr_make_io_signature(1, 1, sizeof(float)), + gr_make_io_signature(0, 0, 0)), + d_iir(alpha), d_unmuted(false), d_level(0) +{ + set_threshold (threshold_db); +} + +gr_probe_avg_mag_sqrd_f::~gr_probe_avg_mag_sqrd_f() +{ +} + + +int +gr_probe_avg_mag_sqrd_f::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]; + + for (int i = 0; i < noutput_items; i++){ + double mag_sqrd = in[i]*in[i]; + d_iir.filter(mag_sqrd); // computed for side effect: prev_output() + } + + d_unmuted = d_iir.prev_output() >= d_threshold; + d_level = d_iir.prev_output(); + return noutput_items; +} + +double +gr_probe_avg_mag_sqrd_f::threshold() const +{ + return 10 * std::log10(d_threshold); +} + +void +gr_probe_avg_mag_sqrd_f::set_threshold(double decibels) +{ + // convert to absolute threshold (mag sqrd) + d_threshold = std::pow(10.0, decibels/10); +} + +void +gr_probe_avg_mag_sqrd_f::set_alpha(double alpha) +{ + d_iir.set_taps(alpha); +} diff --git a/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_f.h b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_f.h new file mode 100644 index 000000000..b2efcc64e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_f.h @@ -0,0 +1,75 @@ +/* -*- 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_PROBE_AVG_MAG_SQRD_F_H +#define INCLUDED_GR_PROBE_AVG_MAG_SQRD_F_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_single_pole_iir.h> + +class gr_probe_avg_mag_sqrd_f; +typedef boost::shared_ptr<gr_probe_avg_mag_sqrd_f> gr_probe_avg_mag_sqrd_f_sptr; + +GR_CORE_API gr_probe_avg_mag_sqrd_f_sptr +gr_make_probe_avg_mag_sqrd_f (double threshold_db, double alpha = 0.0001); + +/*! + * \brief compute avg magnitude squared. + * \ingroup sink_blk + * + * input: float + * + * Compute a running average of the magnitude squared of the the input. + * The level and indication as to whether the level exceeds threshold + * can be retrieved with the level and unmuted accessors. + */ +class GR_CORE_API gr_probe_avg_mag_sqrd_f : public gr_sync_block +{ + double d_threshold; + gr_single_pole_iir<double,double,double> d_iir; + bool d_unmuted; + double d_level; + + friend GR_CORE_API gr_probe_avg_mag_sqrd_f_sptr + gr_make_probe_avg_mag_sqrd_f (double threshold_db, double alpha); + + gr_probe_avg_mag_sqrd_f (double threshold_db, double alpha); + +public: + ~gr_probe_avg_mag_sqrd_f (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + // ACCESSORS + bool unmuted () const { return d_unmuted; } + double level () const { return d_level; } + + double threshold() const; + + // SETTERS + void set_alpha (double alpha); + void set_threshold (double decibels); +}; + +#endif /* INCLUDED_GR_PROBE_AVG_MAG_SQRD_F_H */ diff --git a/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_f.i b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_f.i new file mode 100644 index 000000000..1c63ae8e9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_f.i @@ -0,0 +1,36 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,probe_avg_mag_sqrd_f); + +gr_probe_avg_mag_sqrd_f_sptr +gr_make_probe_avg_mag_sqrd_f (double threshold_db, double alpha = 0.0001); + +class gr_probe_avg_mag_sqrd_f : public gr_sync_block +{ +public: + bool unmuted () const { return d_unmuted; } + double level () const { return d_level; } + double threshold() const; + void set_alpha (double alpha); + void set_threshold (double decibels); +}; diff --git a/gnuradio-core/src/lib/general/gr_probe_density_b.cc b/gnuradio-core/src/lib/general/gr_probe_density_b.cc new file mode 100644 index 000000000..31661780a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_density_b.cc @@ -0,0 +1,68 @@ +/* -*- 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 new file mode 100644 index 000000000..ab84a63a9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_density_b.h @@ -0,0 +1,73 @@ +/* -*- 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_probe_density_b.i b/gnuradio-core/src/lib/general/gr_probe_density_b.i new file mode 100644 index 000000000..ca65708af --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_density_b.i @@ -0,0 +1,36 @@ +/* -*- 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,probe_density_b); + +gr_probe_density_b_sptr gr_make_probe_density_b(double alpha); + +class gr_probe_density_b : public gr_sync_block +{ +public: + double density() const; + + void set_alpha(double alpha); + +private: + gr_probe_density_b(); +}; diff --git a/gnuradio-core/src/lib/general/gr_pwr_squelch_cc.cc b/gnuradio-core/src/lib/general/gr_pwr_squelch_cc.cc new file mode 100644 index 000000000..90eab13eb --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pwr_squelch_cc.cc @@ -0,0 +1,55 @@ +/* -*- 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_pwr_squelch_cc.h> + +gr_pwr_squelch_cc_sptr +gr_make_pwr_squelch_cc(double threshold, double alpha, int ramp, bool gate) +{ + return gnuradio::get_initial_sptr(new gr_pwr_squelch_cc(threshold, alpha, ramp, gate)); +} + +gr_pwr_squelch_cc::gr_pwr_squelch_cc(double threshold, double alpha, int ramp, bool gate) : + gr_squelch_base_cc("pwr_squelch_cc", ramp, gate), + d_iir(alpha) +{ + set_threshold(threshold); +} + +std::vector<float> gr_pwr_squelch_cc::squelch_range() const +{ + std::vector<float> r(3); + r[0] = -50.0; // min FIXME + r[1] = +50.0; // max FIXME + r[2] = (r[1] - r[0]) / 100; // step size + + return r; +} + +void gr_pwr_squelch_cc::update_state(const gr_complex &in) +{ + d_pwr = d_iir.filter(in.real()*in.real()+in.imag()*in.imag()); +} diff --git a/gnuradio-core/src/lib/general/gr_pwr_squelch_cc.h b/gnuradio-core/src/lib/general/gr_pwr_squelch_cc.h new file mode 100644 index 000000000..b2b4624f5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pwr_squelch_cc.h @@ -0,0 +1,63 @@ +/* -*- 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_PWR_SQUELCH_CC_H +#define INCLUDED_GR_PWR_SQUELCH_CC_H + +#include <gr_core_api.h> +#include <cmath> +#include <gr_squelch_base_cc.h> +#include <gr_single_pole_iir.h> + +class gr_pwr_squelch_cc; +typedef boost::shared_ptr<gr_pwr_squelch_cc> gr_pwr_squelch_cc_sptr; + +GR_CORE_API gr_pwr_squelch_cc_sptr +gr_make_pwr_squelch_cc(double db, double alpha = 0.0001, int ramp=0, bool gate=false); + +/*! + * \brief gate or zero output when input power below threshold + * \ingroup level_blk + */ +class GR_CORE_API gr_pwr_squelch_cc : public gr_squelch_base_cc +{ +private: + double d_threshold; + double d_pwr; + gr_single_pole_iir<double,double,double> d_iir; + + friend GR_CORE_API gr_pwr_squelch_cc_sptr gr_make_pwr_squelch_cc(double db, double alpha, int ramp, bool gate); + gr_pwr_squelch_cc(double db, double alpha, int ramp, bool gate); + +protected: + virtual void update_state(const gr_complex &in); + virtual bool mute() const { return d_pwr < d_threshold; } + +public: + std::vector<float> squelch_range() const; + + double threshold() const { return 10*log10(d_threshold); } + void set_threshold(double db) { d_threshold = std::pow(10.0, db/10); } + void set_alpha(double alpha) { d_iir.set_taps(alpha); } +}; + +#endif /* INCLUDED_GR_PWR_SQUELCH_CC_H */ diff --git a/gnuradio-core/src/lib/general/gr_pwr_squelch_cc.i b/gnuradio-core/src/lib/general/gr_pwr_squelch_cc.i new file mode 100644 index 000000000..c8cafd7aa --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pwr_squelch_cc.i @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2009 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,pwr_squelch_cc); + +// retrieve info on the base class, without generating wrappers since +// the base class has a pure virual method. +%import "gr_squelch_base_cc.i" + +gr_pwr_squelch_cc_sptr +gr_make_pwr_squelch_cc(double db, double alpha=0.0001, int ramp=0, bool gate=false); + +class gr_pwr_squelch_cc : public gr_squelch_base_cc +{ +private: + gr_pwr_squelch_cc(double db, double alpha, int ramp, bool gate); + +public: + double threshold() const { return 10*log10(d_threshold); } + void set_threshold(double db) { d_threshold = std::pow(10.0, db/10); } + void set_alpha(double alpha) { d_iir.set_taps(alpha); } + std::vector<float> squelch_range() const; +}; diff --git a/gnuradio-core/src/lib/general/gr_pwr_squelch_ff.cc b/gnuradio-core/src/lib/general/gr_pwr_squelch_ff.cc new file mode 100644 index 000000000..cfa867243 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pwr_squelch_ff.cc @@ -0,0 +1,55 @@ +/* -*- 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_pwr_squelch_ff.h> + +gr_pwr_squelch_ff_sptr +gr_make_pwr_squelch_ff(double threshold, double alpha, int ramp, bool gate) +{ + return gnuradio::get_initial_sptr(new gr_pwr_squelch_ff(threshold, alpha, ramp, gate)); +} + +gr_pwr_squelch_ff::gr_pwr_squelch_ff(double threshold, double alpha, int ramp, bool gate) : + gr_squelch_base_ff("pwr_squelch_ff", ramp, gate), + d_iir(alpha) +{ + set_threshold(threshold); +} + +std::vector<float> gr_pwr_squelch_ff::squelch_range() const +{ + std::vector<float> r(3); + r[0] = -50.0; // min FIXME + r[1] = +50.0; // max FIXME + r[2] = (r[1] - r[0]) / 100; // step size + + return r; +} + +void gr_pwr_squelch_ff::update_state(const float &in) +{ + d_pwr = d_iir.filter(in*in); +} diff --git a/gnuradio-core/src/lib/general/gr_pwr_squelch_ff.h b/gnuradio-core/src/lib/general/gr_pwr_squelch_ff.h new file mode 100644 index 000000000..d5148c409 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pwr_squelch_ff.h @@ -0,0 +1,63 @@ +/* -*- 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_PWR_SQUELCH_FF_H +#define INCLUDED_GR_PWR_SQUELCH_FF_H + +#include <gr_core_api.h> +#include <cmath> +#include <gr_squelch_base_ff.h> +#include <gr_single_pole_iir.h> + +class gr_pwr_squelch_ff; +typedef boost::shared_ptr<gr_pwr_squelch_ff> gr_pwr_squelch_ff_sptr; + +GR_CORE_API gr_pwr_squelch_ff_sptr +gr_make_pwr_squelch_ff(double db, double alpha = 0.0001, int ramp=0, bool gate=false); + +/*! + * \brief gate or zero output when input power below threshold + * \ingroup level_blk + */ +class GR_CORE_API gr_pwr_squelch_ff : public gr_squelch_base_ff +{ +private: + double d_threshold; + double d_pwr; + gr_single_pole_iir<double,double,double> d_iir; + + friend GR_CORE_API gr_pwr_squelch_ff_sptr gr_make_pwr_squelch_ff(double db, double alpha, int ramp, bool gate); + gr_pwr_squelch_ff(double db, double alpha, int ramp, bool gate); + +protected: + virtual void update_state(const float &in); + virtual bool mute() const { return d_pwr < d_threshold; } + +public: + std::vector<float> squelch_range() const; + + double threshold() const { return 10*log10(d_threshold); } + void set_threshold(double db) { d_threshold = std::pow(10.0, db/10); } + void set_alpha(double alpha) { d_iir.set_taps(alpha); } +}; + +#endif /* INCLUDED_GR_PWR_SQUELCH_FF_H */ diff --git a/gnuradio-core/src/lib/general/gr_pwr_squelch_ff.i b/gnuradio-core/src/lib/general/gr_pwr_squelch_ff.i new file mode 100644 index 000000000..2682f2758 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pwr_squelch_ff.i @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2009 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,pwr_squelch_ff); + +// retrieve info on the base class, without generating wrappers since +// the base class has a pure virual method. +%import "gr_squelch_base_ff.i" + +gr_pwr_squelch_ff_sptr +gr_make_pwr_squelch_ff(double db, double alpha=0.0001, int ramp=0, bool gate=false); + +class gr_pwr_squelch_ff : public gr_squelch_base_ff +{ +private: + gr_pwr_squelch_ff(double db, double alpha, int ramp, bool gate); + +public: + double threshold() const { return 10*log10(d_threshold); } + void set_threshold(double db) { d_threshold = std::pow(10.0, db/10); } + void set_alpha(double alpha) { d_iir.set_taps(alpha); } + std::vector<float> squelch_range() const; +}; diff --git a/gnuradio-core/src/lib/general/gr_quadrature_demod_cf.cc b/gnuradio-core/src/lib/general/gr_quadrature_demod_cf.cc new file mode 100644 index 000000000..fa0958276 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_quadrature_demod_cf.cc @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005,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_quadrature_demod_cf.h> +#include <gr_io_signature.h> +#include <gr_math.h> + +gr_quadrature_demod_cf::gr_quadrature_demod_cf (float gain) + : gr_sync_block ("quadrature_demod_cf", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (float))), + d_gain (gain) +{ + set_history (2); // we need to look at the previous value +} + +gr_quadrature_demod_cf_sptr +gr_make_quadrature_demod_cf (float gain) +{ + return gnuradio::get_initial_sptr(new gr_quadrature_demod_cf (gain)); +} + +int +gr_quadrature_demod_cf::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gr_complex *in = (gr_complex *) input_items[0]; + float *out = (float *) output_items[0]; + in++; // ensure that in[-1] is valid + + for (int i = 0; i < noutput_items; i++){ + gr_complex product = in[i] * conj (in[i-1]); + // out[i] = d_gain * arg (product); + out[i] = d_gain * gr_fast_atan2f(imag(product), real(product)); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_quadrature_demod_cf.h b/gnuradio-core/src/lib/general/gr_quadrature_demod_cf.h new file mode 100644 index 000000000..9f5976c97 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_quadrature_demod_cf.h @@ -0,0 +1,56 @@ +/* -*- 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_QUADRATURE_DEMOD_CF_H +#define INCLUDED_GR_QUADRATURE_DEMOD_CF_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_quadrature_demod_cf; +typedef boost::shared_ptr<gr_quadrature_demod_cf> gr_quadrature_demod_cf_sptr; +GR_CORE_API gr_quadrature_demod_cf_sptr gr_make_quadrature_demod_cf (float gain); + +/*! + * \brief quadrature demodulator: complex in, float out + * \ingroup demodulation_blk + * + * This can be used to demod FM, FSK, GMSK, etc. + * The input is complex baseband. + */ +class GR_CORE_API gr_quadrature_demod_cf : public gr_sync_block +{ + friend GR_CORE_API gr_quadrature_demod_cf_sptr gr_make_quadrature_demod_cf (float gain); + gr_quadrature_demod_cf (float gain); + + float d_gain; + + public: + void set_gain(float gain) { d_gain = gain; } + float gain() const { return d_gain; } + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_QUADRATURE_DEMOD_CF_H */ diff --git a/gnuradio-core/src/lib/general/gr_quadrature_demod_cf.i b/gnuradio-core/src/lib/general/gr_quadrature_demod_cf.i new file mode 100644 index 000000000..4c9168e64 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_quadrature_demod_cf.i @@ -0,0 +1,34 @@ +/* -*- 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, quadrature_demod_cf) + +gr_quadrature_demod_cf_sptr gr_make_quadrature_demod_cf (float gain); + +class gr_quadrature_demod_cf : public gr_sync_block +{ + gr_quadrature_demod_cf (float gain); + +public: + void set_gain(float gain) { d_gain = gain; } + float gain() const { return d_gain; } +}; diff --git a/gnuradio-core/src/lib/general/gr_rail_ff.cc b/gnuradio-core/src/lib/general/gr_rail_ff.cc new file mode 100644 index 000000000..cd33c10d3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_rail_ff.cc @@ -0,0 +1,62 @@ +/* -*- 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_rail_ff.h> +#include <gr_io_signature.h> + +gr_rail_ff_sptr +gr_make_rail_ff(float lo, float hi) +{ + return gnuradio::get_initial_sptr(new gr_rail_ff(lo, hi)); +} + +gr_rail_ff::gr_rail_ff(float lo, float hi) + : gr_sync_block("rail_ff", + gr_make_io_signature(1, 1, sizeof(float)), + gr_make_io_signature(1, 1, sizeof(float))), + d_lo(lo), d_hi(hi) +{ +} + +int +gr_rail_ff::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 i = 0; i < noutput_items; i++) { + if (in[i] < d_lo) + out[i] = d_lo; + else if (in[i] > d_hi) + out[i] = d_hi; + else + out[i] = in[i]; + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_rail_ff.h b/gnuradio-core/src/lib/general/gr_rail_ff.h new file mode 100644 index 000000000..29db5b1fa --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_rail_ff.h @@ -0,0 +1,57 @@ +/* -*- 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_RAIL_FF_H_ +# define INCLUDED_GR_RAIL_FF_H_ + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +/*! + * \brief clips input values to min, max + * \ingroup misc + */ + +class gr_rail_ff; +typedef boost::shared_ptr<gr_rail_ff> gr_rail_ff_sptr; + +GR_CORE_API gr_rail_ff_sptr gr_make_rail_ff(float lo, float hi); + +class GR_CORE_API gr_rail_ff : public gr_sync_block +{ + friend GR_CORE_API gr_rail_ff_sptr gr_make_rail_ff (float lo, float hi); + + float d_lo, d_hi; // the constant + gr_rail_ff(float lo, float hi); + + public: + float lo() const { return d_lo; } + void set_lo(float lo) { d_lo = lo; } + float hi() const { return d_hi; } + void set_hi(float hi) { d_hi = hi; } + + 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_rail_ff.i b/gnuradio-core/src/lib/general/gr_rail_ff.i new file mode 100644 index 000000000..bdc453516 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_rail_ff.i @@ -0,0 +1,30 @@ +/* -*- 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,rail_ff); + +gr_rail_ff_sptr gr_make_rail_ff(float lo, float hi); + +class gr_rail_ff : public gr_sync_block +{ +private: + gr_rail_ff(float lo, float hi); +}; diff --git a/gnuradio-core/src/lib/general/gr_random.cc b/gnuradio-core/src/lib/general/gr_random.cc new file mode 100644 index 000000000..323839acc --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_random.cc @@ -0,0 +1,183 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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. + */ + +/* + * Copyright 1997 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of M.I.T. not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. M.I.T. makes no representations about the + * suitability of this software for any purpose. It is provided "as is" + * without express or implied warranty. + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <math.h> +#include <gr_random.h> + +#define IA 16807 +#define IM 2147483647 +#define AM (1.0/IM) +#define IQ 127773 +#define IR 2836 +#define NDIV (1+(IM-1)/NTAB) +#define EPS 1.2e-7 +#define RNMX (1.0-EPS) + + +gr_random::gr_random (long seed) +{ + reseed (seed); +} + +void +gr_random::reseed (long seed) +{ + d_seed = seed; + d_iy = 0; + for (int i = 0; i < NTAB; i++) + d_iv[i] = 0; + d_iset = 0; + d_gset = 0; +} + +/* + * This looks like it returns a uniform random deviate between 0.0 and 1.0 + * It looks similar to code from "Numerical Recipes in C". + */ +float gr_random::ran1() +{ + int j; + long k; + float temp; + + if (d_seed <= 0 || !d_iy) { + if (-d_seed < 1) + d_seed=1; + else + d_seed = -d_seed; + for (j=NTAB+7;j>=0;j--) { + k=d_seed/IQ; + d_seed=IA*(d_seed-k*IQ)-IR*k; + if (d_seed < 0) + d_seed += IM; + if (j < NTAB) + d_iv[j] = d_seed; + } + d_iy=d_iv[0]; + } + k=(d_seed)/IQ; + d_seed=IA*(d_seed-k*IQ)-IR*k; + if (d_seed < 0) + d_seed += IM; + j=d_iy/NDIV; + d_iy=d_iv[j]; + d_iv[j] = d_seed; + temp=AM * d_iy; + if (temp > RNMX) + temp = RNMX; + return temp; +} + +/* + * Returns a normally distributed deviate with zero mean and variance 1. + * Also looks like it's from "Numerical Recipes in C". + */ +float gr_random::gasdev() +{ + float fac,rsq,v1,v2; + d_iset = 1 - d_iset; + if (d_iset) { + do { + v1=2.0*ran1()-1.0; + v2=2.0*ran1()-1.0; + rsq=v1*v1+v2*v2; + } while (rsq >= 1.0 || rsq == 0.0); + fac= sqrt(-2.0*log(rsq)/rsq); + d_gset=v1*fac; + return v2*fac; + } + return d_gset; +} + +/* + * Copied from The KC7WW / OH2BNS Channel Simulator + * FIXME Need to check how good this is at some point + */ + +float gr_random::laplacian() +{ + float z = ran1(); + if (z < 0.5) + return log(2.0 * z) / M_SQRT2; + else + return -log(2.0 * (1.0 - z)) / M_SQRT2; +} + +/* + * Copied from The KC7WW / OH2BNS Channel Simulator + * FIXME Need to check how good this is at some point + */ + + // 5 => scratchy, 8 => Geiger + +float gr_random::impulse(float factor = 5) +{ + float z = -M_SQRT2 * log(ran1()); + if (fabsf(z) <= factor) + return 0.0; + else + return z; +} + +/* + * Complex rayleigh is really gaussian I and gaussian Q + * It can also be generated by real rayleigh magnitude and + * uniform random angle + * Adapted from The KC7WW / OH2BNS Channel Simulator + * FIXME Need to check how good this is at some point + */ + +gr_complex gr_random::rayleigh_complex() +{ + return gr_complex(gasdev(),gasdev()); +} + +/* Other option + mag = rayleigh(); + ang = 2.0 * M_PI * RNG(); + *Rx = rxx * cos(z); + *Iy = rxx * sin(z); +*/ + + +float gr_random::rayleigh() +{ + return sqrt(-2.0 * log(ran1())); +} diff --git a/gnuradio-core/src/lib/general/gr_random.h b/gnuradio-core/src/lib/general/gr_random.h new file mode 100644 index 000000000..96a8f4418 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_random.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_RANDOM_H +#define INCLUDED_GR_RANDOM_H + +#include <gr_core_api.h> +#include <gr_complex.h> + +/*! + * \brief pseudo random number generator + * \ingroup math_blk + */ +class GR_CORE_API gr_random { +protected: + static const int NTAB = 32; + long d_seed; + long d_iy; + long d_iv[NTAB]; + int d_iset; + float d_gset; + + +public: + gr_random (long seed=3021); + + void reseed (long seed); + + /*! + * \brief uniform random deviate in the range [0.0, 1.0) + */ + float ran1 (); + + /*! + * \brief normally distributed deviate with zero mean and variance 1 + */ + float gasdev (); + + float laplacian (); + float impulse (float factor); + float rayleigh (); + gr_complex rayleigh_complex (); +}; + +#endif /* INCLUDED_GR_RANDOM_H */ + diff --git a/gnuradio-core/src/lib/general/gr_random_pdu.cc b/gnuradio-core/src/lib/general/gr_random_pdu.cc new file mode 100644 index 000000000..6d8c13614 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_random_pdu.cc @@ -0,0 +1,84 @@ +/* -*- 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 <gr_random_pdu.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 <string.h> +#include <iostream> +#include <vector> + +// public constructor that returns a shared_ptr + +gr_random_pdu_sptr +gr_make_random_pdu (int items_min, int items_max) +{ + return gnuradio::get_initial_sptr(new gr_random_pdu(items_min, items_max)); +} + +gr_random_pdu::gr_random_pdu (int items_min, int items_max) + : gr_block("random_pdu", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(0, 0, 0)), + urange(items_min, items_max), + brange(0, 255), + rvar(rng, urange), + bvar(rng, brange) +{ + message_port_register_out(pmt::mp("pdus")); + message_port_register_in(pmt::mp("generate")); + set_msg_handler(pmt::mp("generate"), boost::bind(&gr_random_pdu::generate_pdu, this, _1)); +} + +bool gr_random_pdu::start(){ + output_random(); + return true; +} + +void gr_random_pdu::output_random(){ + + // pick a random vector length + int len = rvar(); + + // fill it with random bytes + std::vector<unsigned char> vec; + for(int i=0; i<len; i++){ + vec.push_back((unsigned char) bvar()); + } + + // send the vector + pmt::pmt_t vecpmt( pmt::pmt_make_blob( &vec[0], len ) ); + pmt::pmt_t pdu( pmt::pmt_cons( pmt::PMT_NIL, vecpmt ) ); + message_port_pub( pmt::mp("pdus"), pdu ); + + std::cout << "sending new random vector of length " << len << "\n"; +} + diff --git a/gnuradio-core/src/lib/general/gr_random_pdu.h b/gnuradio-core/src/lib/general/gr_random_pdu.h new file mode 100644 index 000000000..e6457d21b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_random_pdu.h @@ -0,0 +1,64 @@ +/* -*- 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_GR_RANDOM_PDU_H +#define INCLUDED_GR_RANDOM_PDU_H + +#include <gr_core_api.h> +#include <gr_block.h> +#include <gr_message.h> +#include <gr_msg_queue.h> + +#include <boost/random.hpp> +#include <boost/generator_iterator.hpp> + +class gr_random_pdu; +typedef boost::shared_ptr<gr_random_pdu> gr_random_pdu_sptr; + +GR_CORE_API gr_random_pdu_sptr gr_make_random_pdu (int mintime, int maxtime); + +/*! + * \brief Send message at defined interval + * \ingroup msg_blk + */ +class GR_CORE_API gr_random_pdu : public gr_block +{ + private: + friend GR_CORE_API gr_random_pdu_sptr + gr_make_random_pdu(int mintime, int maxtime); + + void output_random(); + + boost::mt19937 rng; + boost::uniform_int<> urange; + boost::uniform_int<> brange; + boost::variate_generator< boost::mt19937, boost::uniform_int<> > rvar; // pdu length + boost::variate_generator< boost::mt19937, boost::uniform_int<> > bvar; // pdu contents + + public: + gr_random_pdu (int, int); + bool start(); + void generate_pdu(pmt::pmt_t msg){ output_random(); } + void generate_pdu(){ output_random(); } +}; + +#endif /* INCLUDED_GR_RANDOM_PDU_H */ diff --git a/gnuradio-core/src/lib/general/gr_random_pdu.i b/gnuradio-core/src/lib/general/gr_random_pdu.i new file mode 100644 index 000000000..045a33060 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_random_pdu.i @@ -0,0 +1,30 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,random_pdu); + +%{ +#include <gr_random_pdu.h> +%} + +%include "gr_random_pdu.h" + diff --git a/gnuradio-core/src/lib/general/gr_regenerate_bb.cc b/gnuradio-core/src/lib/general/gr_regenerate_bb.cc new file mode 100644 index 000000000..c96cf247d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_regenerate_bb.cc @@ -0,0 +1,90 @@ +/* -*- 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_regenerate_bb.h> +#include <gr_io_signature.h> + +gr_regenerate_bb_sptr +gr_make_regenerate_bb (int period, unsigned int max_regen) +{ + return gnuradio::get_initial_sptr(new gr_regenerate_bb (period, max_regen)); +} + +gr_regenerate_bb::gr_regenerate_bb (int period, unsigned int max_regen) + : gr_sync_block ("regenerate_bb", + gr_make_io_signature (1, 1, sizeof (char)), + gr_make_io_signature (1, 1, sizeof (char))), + d_period(period), + d_countdown(0), + d_max_regen(max_regen), + d_regen_count(max_regen) +{ +} + +void gr_regenerate_bb::set_max_regen(unsigned int regen) +{ + d_max_regen = regen; + d_countdown = 0; + d_regen_count = d_max_regen; +} + +void gr_regenerate_bb::set_period(int period) +{ + d_period = period; + d_countdown = 0; + d_regen_count = d_max_regen; +} + +int +gr_regenerate_bb::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const char *iptr = (const char *) input_items[0]; + char *optr = (char *) output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + optr[i] = 0; + + if(d_regen_count < d_max_regen) { + d_countdown--; + + if(d_countdown == 0) { + optr[i] = 1; + d_countdown = d_period; + d_regen_count++; + } + } + + if(iptr[i] == 1) { + d_countdown = d_period; + optr[i] = 1; + d_regen_count = 0; + } + + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_regenerate_bb.h b/gnuradio-core/src/lib/general/gr_regenerate_bb.h new file mode 100644 index 000000000..e820db69e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_regenerate_bb.h @@ -0,0 +1,76 @@ +/* -*- 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_REGENERATE_BB_H +#define INCLUDED_GR_REGENERATE_BB_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_regenerate_bb; +typedef boost::shared_ptr<gr_regenerate_bb> gr_regenerate_bb_sptr; + +GR_CORE_API gr_regenerate_bb_sptr gr_make_regenerate_bb (int period, unsigned int max_regen=500); + +/*! + * \brief Detect the peak of a signal and repeat every period samples + * \ingroup level_blk + * + * If a peak is detected, this block outputs a 1 repeated every period samples + * until reset by detection of another 1 on the input or stopped after max_regen + * regenerations have occurred. + * + * Note that if max_regen=(-1)/ULONG_MAX then the regeneration will run forever. + */ +class GR_CORE_API gr_regenerate_bb : public gr_sync_block +{ + /*! + * \brief Make a regenerate block + * \param period The number of samples between regenerations + * \param max_regen The maximum number of regenerations to perform; if set to + * ULONG_MAX, it will regenerate continuously. + */ + friend GR_CORE_API gr_regenerate_bb_sptr gr_make_regenerate_bb (int period, unsigned int max_regen); + + gr_regenerate_bb (int period, unsigned int max_regen); + + private: + int d_period; + int d_countdown; + unsigned int d_max_regen; + unsigned int d_regen_count; + + public: + /*! \brief Reset the maximum regeneration count; this will reset the current regen. + */ + void set_max_regen(unsigned int regen); + + /*! \brief Reset the period of regenerations; this will reset the current regen. + */ + void set_period(int period); + + 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_regenerate_bb.i b/gnuradio-core/src/lib/general/gr_regenerate_bb.i new file mode 100644 index 000000000..064b0a278 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_regenerate_bb.i @@ -0,0 +1,38 @@ +/* -*- 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,regenerate_bb) + +gr_regenerate_bb_sptr gr_make_regenerate_bb (int period, unsigned int max_regen=500); + +class gr_regenerate_bb : public gr_sync_block +{ + private: + gr_regenerate_bb (int period, unsigned int max_regen); + +public: + void set_max_regen(unsigned int regen); + + /*! \brief Reset the period of regenerations; this will reset the current regen. + */ + void set_period(int period); +}; diff --git a/gnuradio-core/src/lib/general/gr_remez.cc b/gnuradio-core/src/lib/general/gr_remez.cc new file mode 100644 index 000000000..db4789e43 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_remez.cc @@ -0,0 +1,1033 @@ +/************************************************************************** + * Parks-McClellan algorithm for FIR filter design (C version) + *------------------------------------------------- + * Copyright (c) 1995,1998 Jake Janovetz (janovetz@uiuc.edu) + * Copyright (c) 2004 Free Software Foundation, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301 USA + * + * + * Sep 1999 - Paul Kienzle (pkienzle@cs.indiana.edu) + * Modified for use in octave as a replacement for the matlab function + * remez.mex. In particular, magnitude responses are required for all + * band edges rather than one per band, griddensity is a parameter, + * and errors are returned rather than printed directly. + * Mar 2000 - Kai Habel (kahacjde@linux.zrz.tu-berlin.de) + * Change: ColumnVector x=arg(i).vector_value(); + * to: ColumnVector x(arg(i).vector_value()); + * There appear to be some problems with the routine Search. See comments + * therein [search for PAK:]. I haven't looked closely at the rest + * of the code---it may also have some problems. + *************************************************************************/ + +/* + * This code was extracted from octave.sf.net, and wrapped with + * GNU Radio glue. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include <gr_remez.h> +#include <cmath> +#include <assert.h> +#include <iostream> + + +#ifndef LOCAL_BUFFER +#include <vector> +#define LOCAL_BUFFER(T, buf, size) \ + std::vector<T> buf ## _vector (size); \ + T *buf = &(buf ## _vector[0]) +#endif + + +#define CONST const +#define BANDPASS 1 +#define DIFFERENTIATOR 2 +#define HILBERT 3 + +#define NEGATIVE 0 +#define POSITIVE 1 + +#define Pi 3.14159265358979323846 +#define Pi2 (2*Pi) + +#define GRIDDENSITY 16 +#define MAXITERATIONS 40 + +/******************* + * CreateDenseGrid + *================= + * Creates the dense grid of frequencies from the specified bands. + * Also creates the Desired Frequency Response function (D[]) and + * the Weight function (W[]) on that dense grid + * + * + * INPUT: + * ------ + * int r - 1/2 the number of filter coefficients + * int numtaps - Number of taps in the resulting filter + * int numband - Number of bands in user specification + * double bands[] - User-specified band edges [2*numband] + * double des[] - Desired response per band [2*numband] + * double weight[] - Weight per band [numband] + * int symmetry - Symmetry of filter - used for grid check + * int griddensity + * + * OUTPUT: + * ------- + * int gridsize - Number of elements in the dense frequency grid + * double Grid[] - Frequencies (0 to 0.5) on the dense grid [gridsize] + * double D[] - Desired response on the dense grid [gridsize] + * double W[] - Weight function on the dense grid [gridsize] + *******************/ + +static void +CreateDenseGrid (int r, int numtaps, int numband, const double bands[], + const double des[], const double weight[], int gridsize, + double Grid[], double D[], double W[], + int symmetry, int griddensity) +{ + int i, j, k, band; + double delf, lowf, highf, grid0; + + delf = 0.5/(griddensity*r); + +/* + * For differentiator, hilbert, + * symmetry is odd and Grid[0] = max(delf, bands[0]) + */ + grid0 = (symmetry == NEGATIVE) && (delf > bands[0]) ? delf : bands[0]; + + j=0; + for (band=0; band < numband; band++) + { + lowf = (band==0 ? grid0 : bands[2*band]); + highf = bands[2*band + 1]; + k = (int)((highf - lowf)/delf + 0.5); /* .5 for rounding */ + for (i=0; i<k; i++) + { + D[j] = des[2*band] + i*(des[2*band+1]-des[2*band])/(k-1); + W[j] = weight[band]; + Grid[j] = lowf; + lowf += delf; + j++; + } + Grid[j-1] = highf; + } + +/* + * Similar to above, if odd symmetry, last grid point can't be .5 + * - but, if there are even taps, leave the last grid point at .5 + */ + if ((symmetry == NEGATIVE) && + (Grid[gridsize-1] > (0.5 - delf)) && + (numtaps % 2)) + { + Grid[gridsize-1] = 0.5-delf; + } +} + + +/******************** + * InitialGuess + *============== + * Places Extremal Frequencies evenly throughout the dense grid. + * + * + * INPUT: + * ------ + * int r - 1/2 the number of filter coefficients + * int gridsize - Number of elements in the dense frequency grid + * + * OUTPUT: + * ------- + * int Ext[] - Extremal indexes to dense frequency grid [r+1] + ********************/ + +static void +InitialGuess (int r, int Ext[], int gridsize) +{ + int i; + + for (i=0; i<=r; i++) + Ext[i] = i * (gridsize-1) / r; +} + + +/*********************** + * CalcParms + *=========== + * + * + * INPUT: + * ------ + * int r - 1/2 the number of filter coefficients + * int Ext[] - Extremal indexes to dense frequency grid [r+1] + * double Grid[] - Frequencies (0 to 0.5) on the dense grid [gridsize] + * double D[] - Desired response on the dense grid [gridsize] + * double W[] - Weight function on the dense grid [gridsize] + * + * OUTPUT: + * ------- + * double ad[] - 'b' in Oppenheim & Schafer [r+1] + * double x[] - [r+1] + * double y[] - 'C' in Oppenheim & Schafer [r+1] + ***********************/ + +static void +CalcParms (int r, int Ext[], double Grid[], double D[], double W[], + double ad[], double x[], double y[]) +{ + int i, j, k, ld; + double sign, xi, delta, denom, numer; + +/* + * Find x[] + */ + for (i=0; i<=r; i++) + x[i] = cos(Pi2 * Grid[Ext[i]]); + +/* + * Calculate ad[] - Oppenheim & Schafer eq 7.132 + */ + ld = (r-1)/15 + 1; /* Skips around to avoid round errors */ + for (i=0; i<=r; i++) + { + denom = 1.0; + xi = x[i]; + for (j=0; j<ld; j++) + { + for (k=j; k<=r; k+=ld) + if (k != i) + denom *= 2.0*(xi - x[k]); + } + if (fabs(denom)<0.00001) + denom = 0.00001; + ad[i] = 1.0/denom; + } + +/* + * Calculate delta - Oppenheim & Schafer eq 7.131 + */ + numer = denom = 0; + sign = 1; + for (i=0; i<=r; i++) + { + numer += ad[i] * D[Ext[i]]; + denom += sign * ad[i]/W[Ext[i]]; + sign = -sign; + } + delta = numer/denom; + sign = 1; + +/* + * Calculate y[] - Oppenheim & Schafer eq 7.133b + */ + for (i=0; i<=r; i++) + { + y[i] = D[Ext[i]] - sign * delta/W[Ext[i]]; + sign = -sign; + } +} + + +/********************* + * ComputeA + *========== + * Using values calculated in CalcParms, ComputeA calculates the + * actual filter response at a given frequency (freq). Uses + * eq 7.133a from Oppenheim & Schafer. + * + * + * INPUT: + * ------ + * double freq - Frequency (0 to 0.5) at which to calculate A + * int r - 1/2 the number of filter coefficients + * double ad[] - 'b' in Oppenheim & Schafer [r+1] + * double x[] - [r+1] + * double y[] - 'C' in Oppenheim & Schafer [r+1] + * + * OUTPUT: + * ------- + * Returns double value of A[freq] + *********************/ + +static double +ComputeA (double freq, int r, double ad[], double x[], double y[]) +{ + int i; + double xc, c, denom, numer; + + denom = numer = 0; + xc = cos(Pi2 * freq); + for (i=0; i<=r; i++) + { + c = xc - x[i]; + if (fabs(c) < 1.0e-7) + { + numer = y[i]; + denom = 1; + break; + } + c = ad[i]/c; + denom += c; + numer += c*y[i]; + } + return numer/denom; +} + + +/************************ + * CalcError + *=========== + * Calculates the Error function from the desired frequency response + * on the dense grid (D[]), the weight function on the dense grid (W[]), + * and the present response calculation (A[]) + * + * + * INPUT: + * ------ + * int r - 1/2 the number of filter coefficients + * double ad[] - [r+1] + * double x[] - [r+1] + * double y[] - [r+1] + * int gridsize - Number of elements in the dense frequency grid + * double Grid[] - Frequencies on the dense grid [gridsize] + * double D[] - Desired response on the dense grid [gridsize] + * double W[] - Weight function on the desnse grid [gridsize] + * + * OUTPUT: + * ------- + * double E[] - Error function on dense grid [gridsize] + ************************/ + +static void +CalcError (int r, double ad[], double x[], double y[], + int gridsize, double Grid[], + double D[], double W[], double E[]) +{ + int i; + double A; + + for (i=0; i<gridsize; i++) + { + A = ComputeA(Grid[i], r, ad, x, y); + E[i] = W[i] * (D[i] - A); + } +} + +/************************ + * Search + *======== + * Searches for the maxima/minima of the error curve. If more than + * r+1 extrema are found, it uses the following heuristic (thanks + * Chris Hanson): + * 1) Adjacent non-alternating extrema deleted first. + * 2) If there are more than one excess extrema, delete the + * one with the smallest error. This will create a non-alternation + * condition that is fixed by 1). + * 3) If there is exactly one excess extremum, delete the smaller + * of the first/last extremum + * + * + * INPUT: + * ------ + * int r - 1/2 the number of filter coefficients + * int Ext[] - Indexes to Grid[] of extremal frequencies [r+1] + * int gridsize - Number of elements in the dense frequency grid + * double E[] - Array of error values. [gridsize] + * OUTPUT: + * ------- + * int Ext[] - New indexes to extremal frequencies [r+1] + ************************/ +static int +Search (int r, int Ext[], + int gridsize, double E[]) +{ + int i, j, k, l, extra; /* Counters */ + int up, alt; + int *foundExt; /* Array of found extremals */ + +/* + * Allocate enough space for found extremals. + */ + foundExt = (int *)malloc((2*r) * sizeof(int)); + k = 0; + +/* + * Check for extremum at 0. + */ + if (((E[0]>0.0) && (E[0]>E[1])) || + ((E[0]<0.0) && (E[0]<E[1]))) + foundExt[k++] = 0; + +/* + * Check for extrema inside dense grid + */ + for (i=1; i<gridsize-1; i++) + { + if (((E[i]>=E[i-1]) && (E[i]>E[i+1]) && (E[i]>0.0)) || + ((E[i]<=E[i-1]) && (E[i]<E[i+1]) && (E[i]<0.0))) { + // PAK: we sometimes get too many extremal frequencies + if (k >= 2*r) return -3; + foundExt[k++] = i; + } + } + +/* + * Check for extremum at 0.5 + */ + j = gridsize-1; + if (((E[j]>0.0) && (E[j]>E[j-1])) || + ((E[j]<0.0) && (E[j]<E[j-1]))) { + if (k >= 2*r) return -3; + foundExt[k++] = j; + } + + // PAK: we sometimes get not enough extremal frequencies + if (k < r+1) return -2; + + +/* + * Remove extra extremals + */ + extra = k - (r+1); + assert(extra >= 0); + + while (extra > 0) + { + if (E[foundExt[0]] > 0.0) + up = 1; /* first one is a maxima */ + else + up = 0; /* first one is a minima */ + + l=0; + alt = 1; + for (j=1; j<k; j++) + { + if (fabs(E[foundExt[j]]) < fabs(E[foundExt[l]])) + l = j; /* new smallest error. */ + if ((up) && (E[foundExt[j]] < 0.0)) + up = 0; /* switch to a minima */ + else if ((!up) && (E[foundExt[j]] > 0.0)) + up = 1; /* switch to a maxima */ + else + { + alt = 0; + // PAK: break now and you will delete the smallest overall + // extremal. If you want to delete the smallest of the + // pair of non-alternating extremals, then you must do: + // + // if (fabs(E[foundExt[j]]) < fabs(E[foundExt[j-1]])) l=j; + // else l=j-1; + break; /* Ooops, found two non-alternating */ + } /* extrema. Delete smallest of them */ + } /* if the loop finishes, all extrema are alternating */ + +/* + * If there's only one extremal and all are alternating, + * delete the smallest of the first/last extremals. + */ + if ((alt) && (extra == 1)) + { + if (fabs(E[foundExt[k-1]]) < fabs(E[foundExt[0]])) + /* Delete last extremal */ + l = k-1; + // PAK: changed from l = foundExt[k-1]; + else + /* Delete first extremal */ + l = 0; + // PAK: changed from l = foundExt[0]; + } + + for (j=l; j<k-1; j++) /* Loop that does the deletion */ + { + foundExt[j] = foundExt[j+1]; + assert(foundExt[j]<gridsize); + } + k--; + extra--; + } + + for (i=0; i<=r; i++) + { + assert(foundExt[i]<gridsize); + Ext[i] = foundExt[i]; /* Copy found extremals to Ext[] */ + } + + free(foundExt); + return 0; +} + + +/********************* + * FreqSample + *============ + * Simple frequency sampling algorithm to determine the impulse + * response h[] from A's found in ComputeA + * + * + * INPUT: + * ------ + * int N - Number of filter coefficients + * double A[] - Sample points of desired response [N/2] + * int symmetry - Symmetry of desired filter + * + * OUTPUT: + * ------- + * double h[] - Impulse Response of final filter [N] + *********************/ +static void +FreqSample (int N, double A[], double h[], int symm) +{ + int n, k; + double x, val, M; + + M = (N-1.0)/2.0; + if (symm == POSITIVE) + { + if (N%2) + { + for (n=0; n<N; n++) + { + val = A[0]; + x = Pi2 * (n - M)/N; + for (k=1; k<=M; k++) + val += 2.0 * A[k] * cos(x*k); + h[n] = val/N; + } + } + else + { + for (n=0; n<N; n++) + { + val = A[0]; + x = Pi2 * (n - M)/N; + for (k=1; k<=(N/2-1); k++) + val += 2.0 * A[k] * cos(x*k); + h[n] = val/N; + } + } + } + else + { + if (N%2) + { + for (n=0; n<N; n++) + { + val = 0; + x = Pi2 * (n - M)/N; + for (k=1; k<=M; k++) + val += 2.0 * A[k] * sin(x*k); + h[n] = val/N; + } + } + else + { + for (n=0; n<N; n++) + { + val = A[N/2] * sin(Pi * (n - M)); + x = Pi2 * (n - M)/N; + for (k=1; k<=(N/2-1); k++) + val += 2.0 * A[k] * sin(x*k); + h[n] = val/N; + } + } + } +} + +/******************* + * isDone + *======== + * Checks to see if the error function is small enough to consider + * the result to have converged. + * + * INPUT: + * ------ + * int r - 1/2 the number of filter coeffiecients + * int Ext[] - Indexes to extremal frequencies [r+1] + * double E[] - Error function on the dense grid [gridsize] + * + * OUTPUT: + * ------- + * Returns 1 if the result converged + * Returns 0 if the result has not converged + ********************/ + +static bool +isDone (int r, int Ext[], double E[]) +{ + int i; + double min, max, current; + + min = max = fabs(E[Ext[0]]); + for (i=1; i<=r; i++) + { + current = fabs(E[Ext[i]]); + if (current < min) + min = current; + if (current > max) + max = current; + } + return (((max-min)/max) < 0.0001); +} + +/******************** + * remez + *======= + * Calculates the optimal (in the Chebyshev/minimax sense) + * FIR filter impulse response given a set of band edges, + * the desired reponse on those bands, and the weight given to + * the error in those bands. + * + * INPUT: + * ------ + * int numtaps - Number of filter coefficients + * int numband - Number of bands in filter specification + * double bands[] - User-specified band edges [2 * numband] + * double des[] - User-specified band responses [2 * numband] + * double weight[] - User-specified error weights [numband] + * int type - Type of filter + * + * OUTPUT: + * ------- + * double h[] - Impulse response of final filter [numtaps] + * returns - true on success, false on failure to converge + ********************/ + +static int +remez (double h[], int numtaps, + int numband, const double bands[], + const double des[], const double weight[], + int type, int griddensity) +{ + double *Grid, *W, *D, *E; + int i, iter, gridsize, r, *Ext; + double *taps, c; + double *x, *y, *ad; + int symmetry; + + if (type == BANDPASS) + symmetry = POSITIVE; + else + symmetry = NEGATIVE; + + r = numtaps/2; /* number of extrema */ + if ((numtaps%2) && (symmetry == POSITIVE)) + r++; + +/* + * Predict dense grid size in advance for memory allocation + * .5 is so we round up, not truncate + */ + gridsize = 0; + for (i=0; i<numband; i++) + { + gridsize += (int)(2*r*griddensity*(bands[2*i+1] - bands[2*i]) + .5); + } + if (symmetry == NEGATIVE) + { + gridsize--; + } + +/* + * Dynamically allocate memory for arrays with proper sizes + */ + Grid = (double *)malloc(gridsize * sizeof(double)); + D = (double *)malloc(gridsize * sizeof(double)); + W = (double *)malloc(gridsize * sizeof(double)); + E = (double *)malloc(gridsize * sizeof(double)); + Ext = (int *)malloc((r+1) * sizeof(int)); + taps = (double *)malloc((r+1) * sizeof(double)); + x = (double *)malloc((r+1) * sizeof(double)); + y = (double *)malloc((r+1) * sizeof(double)); + ad = (double *)malloc((r+1) * sizeof(double)); + +/* + * Create dense frequency grid + */ + CreateDenseGrid(r, numtaps, numband, bands, des, weight, + gridsize, Grid, D, W, symmetry, griddensity); + InitialGuess(r, Ext, gridsize); + +/* + * For Differentiator: (fix grid) + */ + if (type == DIFFERENTIATOR) + { + for (i=0; i<gridsize; i++) + { +/* D[i] = D[i]*Grid[i]; */ + if (D[i] > 0.0001) + W[i] = W[i]/Grid[i]; + } + } + +/* + * For odd or Negative symmetry filters, alter the + * D[] and W[] according to Parks McClellan + */ + if (symmetry == POSITIVE) + { + if (numtaps % 2 == 0) + { + for (i=0; i<gridsize; i++) + { + c = cos(Pi * Grid[i]); + D[i] /= c; + W[i] *= c; + } + } + } + else + { + if (numtaps % 2) + { + for (i=0; i<gridsize; i++) + { + c = sin(Pi2 * Grid[i]); + D[i] /= c; + W[i] *= c; + } + } + else + { + for (i=0; i<gridsize; i++) + { + c = sin(Pi * Grid[i]); + D[i] /= c; + W[i] *= c; + } + } + } + +/* + * Perform the Remez Exchange algorithm + */ + for (iter=0; iter<MAXITERATIONS; iter++) + { + CalcParms(r, Ext, Grid, D, W, ad, x, y); + CalcError(r, ad, x, y, gridsize, Grid, D, W, E); + int err = Search(r, Ext, gridsize, E); + if (err) return err; + for(int i=0; i <= r; i++) assert(Ext[i]<gridsize); + if (isDone(r, Ext, E)) + break; + } + + CalcParms(r, Ext, Grid, D, W, ad, x, y); + +/* + * Find the 'taps' of the filter for use with Frequency + * Sampling. If odd or Negative symmetry, fix the taps + * according to Parks McClellan + */ + for (i=0; i<=numtaps/2; i++) + { + if (symmetry == POSITIVE) + { + if (numtaps%2) + c = 1; + else + c = cos(Pi * (double)i/numtaps); + } + else + { + if (numtaps%2) + c = sin(Pi2 * (double)i/numtaps); + else + c = sin(Pi * (double)i/numtaps); + } + taps[i] = ComputeA((double)i/numtaps, r, ad, x, y)*c; + } + +/* + * Frequency sampling design with calculated taps + */ + FreqSample(numtaps, taps, h, symmetry); + +/* + * Delete allocated memory + */ + free(Grid); + free(W); + free(D); + free(E); + free(Ext); + free(x); + free(y); + free(ad); + return iter<MAXITERATIONS?0:-1; +} + +////////////////////////////////////////////////////////////////////////////// +// +// GNU Radio interface +// +////////////////////////////////////////////////////////////////////////////// + + +static void +punt (const std::string msg) +{ + std::cerr << msg << '\n'; + throw std::runtime_error (msg); +} + +std::vector<double> +gr_remez (int order, + const std::vector<double> &arg_bands, + const std::vector<double> &arg_response, + const std::vector<double> &arg_weight, + const std::string filter_type, + int grid_density + ) throw (std::runtime_error) +{ + int numtaps = order + 1; + if (numtaps < 4) + punt ("gr_remez: number of taps must be >= 3"); + + int numbands = arg_bands.size () / 2; + LOCAL_BUFFER (double, bands, numbands * 2); + if (numbands < 1 || arg_bands.size () % 2 == 1) + punt ("gr_remez: must have an even number of band edges"); + + for (unsigned int i = 1; i < arg_bands.size (); i++){ + if (arg_bands[i] < arg_bands[i-1]) + punt ("gr_remez: band edges must be nondecreasing"); + } + + if (arg_bands[0] < 0 || arg_bands[arg_bands.size () - 1] > 1) + punt ("gr_remez: band edges must be in the range [0,1]"); + + // Divide by 2 to fit with the implementation that uses a + // sample rate of [0, 0.5] instead of [0, 1.0] + for (int i = 0; i < 2 * numbands; i++) + bands[i] = arg_bands[i] / 2; + + LOCAL_BUFFER (double, response, numbands * 2); + if (arg_response.size () != arg_bands.size ()) + punt ("gr_remez: must have one response magnitude for each band edge"); + + for (int i = 0; i < 2 * numbands; i++) + response[i] = arg_response[i]; + + LOCAL_BUFFER (double, weight, numbands); + for (int i = 0; i < numbands; i++) + weight[i] = 1.0; + + if (arg_weight.size () != 0){ + if ((int) arg_weight.size () != numbands) + punt ("gr_remez: need one weight for each band [=length(band)/2]"); + for (int i = 0; i < numbands; i++) + weight[i] = arg_weight [i]; + } + + int itype = 0; + if (filter_type == "bandpass") + itype = BANDPASS; + else if (filter_type == "differentiator") + itype = DIFFERENTIATOR; + else if (filter_type == "hilbert") + itype = HILBERT; + else + punt ("gr_remez: unknown ftype '" + filter_type + "'"); + + if (grid_density < 16) + punt ("gr_remez: grid_density is too low; must be >= 16"); + + LOCAL_BUFFER (double, coeff, numtaps + 5); // FIXME why + 5? + int err = remez (coeff, numtaps, numbands, + bands, response, weight, itype, grid_density); + + if (err == -1) + punt ("gr_remez: failed to converge"); + + if (err == -2) + punt ("gr_remez: insufficient extremals -- cannot continue"); + + if (err == -3) + punt ("gr_remez: too many extremals -- cannot continue"); + + return std::vector<double> (&coeff[0], &coeff[numtaps]); +} + + + +#if 0 +/* == Octave interface starts here ====================================== */ + +DEFUN_DLD (remez, args, , + "b = remez(n, f, a [, w] [, ftype] [, griddensity])\n\ +Parks-McClellan optimal FIR filter design.\n\ +n gives the number of taps in the returned filter\n\ +f gives frequency at the band edges [ b1 e1 b2 e2 b3 e3 ...]\n\ +a gives amplitude at the band edges [ a(b1) a(e1) a(b2) a(e2) ...]\n\ +w gives weighting applied to each band\n\ +ftype is 'bandpass', 'hilbert' or 'differentiator'\n\ +griddensity determines how accurately the filter will be\n\ + constructed. The minimum value is 16, but higher numbers are\n\ + slower to compute.\n\ +\n\ +Frequency is in the range (0, 1), with 1 being the nyquist frequency") +{ + octave_value_list retval; + int i; + + int nargin = args.length(); + if (nargin < 3 || nargin > 6) { + print_usage("remez"); + return retval; + } + + int numtaps = NINT (args(0).double_value()) + 1; // #coeff = filter order+1 + if (numtaps < 4) { + error("remez: number of taps must be an integer greater than 3"); + return retval; + } + + ColumnVector o_bands(args(1).vector_value()); + int numbands = o_bands.length()/2; + OCTAVE_LOCAL_BUFFER(double, bands, numbands*2); + if (numbands < 1 || o_bands.length()%2 == 1) { + error("remez: must have an even number of band edges"); + return retval; + } + for (i=1; i < o_bands.length(); i++) { + if (o_bands(i)<o_bands(i-1)) { + error("band edges must be nondecreasing"); + return retval; + } + } + if (o_bands(0) < 0 || o_bands(1) > 1) { + error("band edges must be in the range [0,1]"); + return retval; + } + for(i=0; i < 2*numbands; i++) bands[i] = o_bands(i)/2.0; + + ColumnVector o_response(args(2).vector_value()); + OCTAVE_LOCAL_BUFFER (double, response, numbands*2); + if (o_response.length() != o_bands.length()) { + error("remez: must have one response magnitude for each band edge"); + return retval; + } + for(i=0; i < 2*numbands; i++) response[i] = o_response(i); + + std::string stype = std::string("bandpass"); + int density = 16; + OCTAVE_LOCAL_BUFFER (double, weight, numbands); + for (i=0; i < numbands; i++) weight[i] = 1.0; + if (nargin > 3) { + if (args(3).is_real_matrix()) { + ColumnVector o_weight(args(3).vector_value()); + if (o_weight.length() != numbands) { + error("remez: need one weight for each band [=length(band)/2]"); + return retval; + } + for (i=0; i < numbands; i++) weight[i] = o_weight(i); + } + else if (args(3).is_string()) + stype = args(3).string_value(); + else if (args(3).is_real_scalar()) + density = NINT(args(3).double_value()); + else { + error("remez: incorrect argument list"); + return retval; + } + } + if (nargin > 4) { + if (args(4).is_string() && !args(3).is_string()) + stype = args(4).string_value(); + else if (args(4).is_real_scalar() && !args(3).is_real_scalar()) + density = NINT(args(4).double_value()); + else { + error("remez: incorrect argument list"); + return retval; + } + } + if (nargin > 5) { + if (args(5).is_real_scalar() + && !args(4).is_real_scalar() + && !args(3).is_real_scalar()) + density = NINT(args(4).double_value()); + else { + error("remez: incorrect argument list"); + return retval; + } + } + + int itype; + if (stype == "bandpass") + itype = BANDPASS; + else if (stype == "differentiator") + itype = DIFFERENTIATOR; + else if (stype == "hilbert") + itype = HILBERT; + else { + error("remez: unknown ftype '%s'", stype.data()); + return retval; + } + + if (density < 16) { + error("remez: griddensity is too low; must be greater than 16"); + return retval; + } + + OCTAVE_LOCAL_BUFFER (double, coeff, numtaps+5); + int err = remez(coeff,numtaps,numbands,bands,response,weight,itype,density); + + if (err == -1) + warning("remez: -- failed to converge -- returned filter may be bad."); + else if (err == -2) { + error("remez: insufficient extremals--cannot continue"); + return retval; + } + else if (err == -3) { + error("remez: too many extremals--cannot continue"); + return retval; + } + + ColumnVector h(numtaps); + while(numtaps--) h(numtaps) = coeff[numtaps]; + + return octave_value(h); +} + +/* +%!test +%! b = [ +%! 0.0415131831103279 +%! 0.0581639884202646 +%! -0.0281579212691008 +%! -0.0535575358002337 +%! -0.0617245915143180 +%! 0.0507753178978075 +%! 0.2079018331396460 +%! 0.3327160895375440 +%! 0.3327160895375440 +%! 0.2079018331396460 +%! 0.0507753178978075 +%! -0.0617245915143180 +%! -0.0535575358002337 +%! -0.0281579212691008 +%! 0.0581639884202646 +%! 0.0415131831103279]; +%! assert(remez(15,[0,0.3,0.4,1],[1,1,0,0]),b,1e-14); + + */ + +#endif diff --git a/gnuradio-core/src/lib/general/gr_remez.h b/gnuradio-core/src/lib/general/gr_remez.h new file mode 100644 index 000000000..d875b8822 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_remez.h @@ -0,0 +1,65 @@ +/* -*- 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_REMEZ_H +#define INCLUDED_GR_REMEZ_H + +#include <gr_core_api.h> +#include <gr_types.h> +#include <string> +#include <stdexcept> + +/*! + * \brief Parks-McClellan FIR filter design. + * + * \ingroup filter_design + * + * Calculates the optimal (in the Chebyshev/minimax sense) FIR filter + * inpulse reponse given a set of band edges, the desired reponse on + * those bands, and the weight given to the error in those bands. + * + * \param order filter order (number of taps in the returned filter - 1) + * \param bands frequency at the band edges [ b1 e1 b2 e2 b3 e3 ...] + * \param ampl desired amplitude at the band edges [ a(b1) a(e1) a(b2) a(e2) ...] + * \param error_weight weighting applied to each band (usually 1) + * \param filter_type one of "bandpass", "hilbert" or "differentiator" + * \param grid_density determines how accurately the filter will be constructed. \ + * The minimum value is 16; higher values are slower to compute. + * + * Frequency is in the range [0, 1], with 1 being the Nyquist frequency (Fs/2) + * + * \returns vector of computed taps + * + * \throws std::runtime_error if args are invalid or calculation fails to converge. + */ + +GR_CORE_API std::vector<double> +gr_remez (int order, + const std::vector<double> &bands, + const std::vector<double> &l, + const std::vector<double> &error_weight, + const std::string filter_type = "bandpass", + int grid_density = 16 + ) throw (std::runtime_error); + + +#endif /* INCLUDED_GR_REMEZ_H */ diff --git a/gnuradio-core/src/lib/general/gr_remez.i b/gnuradio-core/src/lib/general/gr_remez.i new file mode 100644 index 000000000..fe3eea20d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_remez.i @@ -0,0 +1,32 @@ +/* -*- 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. + */ + +%rename(remez) gr_remez; + +std::vector<double> +gr_remez (int order, + const std::vector<double> &bands, + const std::vector<double> &l, + const std::vector<double> &error_weight, + const std::string filter_type = "bandpass", + int grid_density = 16 + ) throw (std::runtime_error); diff --git a/gnuradio-core/src/lib/general/gr_repeat.cc b/gnuradio-core/src/lib/general/gr_repeat.cc new file mode 100644 index 000000000..2fa82cd94 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_repeat.cc @@ -0,0 +1,69 @@ +/* -*- 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_repeat.h> +#include <gr_io_signature.h> +#include <string.h> + +gr_repeat_sptr +gr_make_repeat(size_t itemsize, int interp) +{ + return gnuradio::get_initial_sptr(new gr_repeat(itemsize, interp)); +} + +gr_repeat::gr_repeat(size_t itemsize, int interp) + : gr_sync_interpolator("extend", + gr_make_io_signature(1, 1, itemsize), + gr_make_io_signature(1, 1, itemsize), + interp), + d_interp(interp), + d_itemsize(itemsize) +{ +} + +gr_repeat::~gr_repeat() +{ +} + +int +gr_repeat::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]; + char *out = (char *)output_items[0]; + + for (int i = 0; i < noutput_items/d_interp; i++) { + for (int j = 0; j < d_interp; j++) { + memcpy(out, in, d_itemsize); + out += d_itemsize; + } + + in += d_itemsize; + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_repeat.h b/gnuradio-core/src/lib/general/gr_repeat.h new file mode 100644 index 000000000..548ca79f4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_repeat.h @@ -0,0 +1,57 @@ +/* -*- 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_REPEAT_H +#define INCLUDED_GR_REPEAT_H + +#include <gr_core_api.h> +#include <gr_sync_interpolator.h> + +class gr_repeat; + +typedef boost::shared_ptr<gr_repeat> gr_repeat_sptr; + +GR_CORE_API gr_repeat_sptr gr_make_repeat(size_t itemsize, int interp); + +/*! + * \brief Repeat a sample 'interp' times in output stream + * \ingroup misc_blk + */ + +class GR_CORE_API gr_repeat : public gr_sync_interpolator +{ +private: + friend GR_CORE_API gr_repeat_sptr gr_make_repeat(size_t itemsize, int interp); + + gr_repeat(size_t itemsize, int interp); + + int d_interp; + int d_itemsize; + + public: + ~gr_repeat(); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_REPEAT_H */ diff --git a/gnuradio-core/src/lib/general/gr_repeat.i b/gnuradio-core/src/lib/general/gr_repeat.i new file mode 100644 index 000000000..c657a4906 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_repeat.i @@ -0,0 +1,11 @@ +/* -*- c++ -*- */ + +GR_SWIG_BLOCK_MAGIC(gr,repeat); + +gr_repeat_sptr gr_make_repeat(size_t itemsize, int interp); + +class gr_repeat : public gr_sync_interpolator +{ +private: + gr_repeat(); +}; diff --git a/gnuradio-core/src/lib/general/gr_reverse.cc b/gnuradio-core/src/lib/general/gr_reverse.cc new file mode 100644 index 000000000..08c588cb5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_reverse.cc @@ -0,0 +1,60 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_reverse.h> + + +std::vector<float> +gr_reverse (const std::vector<float> &taps) +{ + int size = taps.size (); + std::vector<float> new_taps(size); + + if (size == 0) + return new_taps; + + for (int i = 0; i < size; i++) + new_taps[i] = taps[size - i - 1]; + + return new_taps; +} + + +std::vector<gr_complex> +gr_reverse (const std::vector<gr_complex> &taps) +{ + int size = taps.size (); + std::vector<gr_complex> new_taps(size); + + if (size == 0) + return new_taps; + + for (int i = 0; i < size; i++) + new_taps[i] = taps[size - i - 1]; + + return new_taps; +} + diff --git a/gnuradio-core/src/lib/general/gr_reverse.h b/gnuradio-core/src/lib/general/gr_reverse.h new file mode 100644 index 000000000..15bf3cb73 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_reverse.h @@ -0,0 +1,34 @@ +/* -*- 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_REVERSE_H +#define INCLUDED_GR_REVERSE_H + +#include <gr_core_api.h> +#include <vector> +#include <gr_complex.h> + +// reverse the order of taps +std::vector<float> gr_reverse (const std::vector<float> &taps); +std::vector<gr_complex> gr_reverse (const std::vector<gr_complex> &taps); + + +#endif /* INCLUDED_GR_REVERSE_H */ diff --git a/gnuradio-core/src/lib/general/gr_rms_cf.cc b/gnuradio-core/src/lib/general/gr_rms_cf.cc new file mode 100644 index 000000000..44eb2221e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_rms_cf.cc @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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_rms_cf.h> +#include <gr_io_signature.h> +#include <cmath> + +gr_rms_cf_sptr +gr_make_rms_cf(double alpha) +{ + return gnuradio::get_initial_sptr(new gr_rms_cf(alpha)); +} + +gr_rms_cf::gr_rms_cf (double alpha) + : gr_sync_block ("rms_cf", + gr_make_io_signature(1, 1, sizeof(gr_complex)), + gr_make_io_signature(1, 1, sizeof(float))), + d_iir(alpha) +{ + +} + +gr_rms_cf::~gr_rms_cf() +{ +} + + +int +gr_rms_cf::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]; + float *out = (float *) output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + double mag_sqrd = in[i].real()*in[i].real() + in[i].imag()*in[i].imag(); + double f = d_iir.filter(mag_sqrd); + out[i] = sqrt(f); + } + + return noutput_items; +} + +void +gr_rms_cf::set_alpha(double alpha) +{ + d_iir.set_taps(alpha); +} diff --git a/gnuradio-core/src/lib/general/gr_rms_cf.h b/gnuradio-core/src/lib/general/gr_rms_cf.h new file mode 100644 index 000000000..9e701aa6a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_rms_cf.h @@ -0,0 +1,61 @@ +/* -*- 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_RMS_CF_H +#define INCLUDED_GR_RMS_CF_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_single_pole_iir.h> + +class gr_rms_cf; +typedef boost::shared_ptr<gr_rms_cf> gr_rms_cf_sptr; + +GR_CORE_API gr_rms_cf_sptr +gr_make_rms_cf (double alpha = 0.0001); + +/*! + * \brief RMS average power + * \ingroup math_blk + */ +class GR_CORE_API gr_rms_cf : public gr_sync_block +{ + gr_single_pole_iir<double,double,double> d_iir; + bool d_unmuted; + + friend GR_CORE_API gr_rms_cf_sptr + gr_make_rms_cf (double alpha); + + gr_rms_cf (double alpha); + +public: + ~gr_rms_cf (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + bool unmuted () const { return d_unmuted; } + + void set_alpha (double alpha); +}; + +#endif /* INCLUDED_GR_RMS_CF_H */ diff --git a/gnuradio-core/src/lib/general/gr_rms_cf.i b/gnuradio-core/src/lib/general/gr_rms_cf.i new file mode 100644 index 000000000..a668200ee --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_rms_cf.i @@ -0,0 +1,33 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,rms_cf); + +gr_rms_cf_sptr +gr_make_rms_cf (double alpha = 0.0001); + +class gr_rms_cf : public gr_sync_block +{ +public: + bool unmuted () const { return d_unmuted; } + void set_alpha (double alpha); +}; diff --git a/gnuradio-core/src/lib/general/gr_rms_ff.cc b/gnuradio-core/src/lib/general/gr_rms_ff.cc new file mode 100644 index 000000000..233f419cd --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_rms_ff.cc @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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_rms_ff.h> +#include <gr_io_signature.h> +#include <cmath> + +gr_rms_ff_sptr +gr_make_rms_ff(double alpha) +{ + return gnuradio::get_initial_sptr(new gr_rms_ff(alpha)); +} + +gr_rms_ff::gr_rms_ff (double alpha) + : gr_sync_block ("rms_ff", + gr_make_io_signature(1, 1, sizeof(float)), + gr_make_io_signature(1, 1, sizeof(float))), + d_iir(alpha) +{ + +} + +gr_rms_ff::~gr_rms_ff() +{ +} + + +int +gr_rms_ff::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 i = 0; i < noutput_items; i++){ + double mag_sqrd = in[i]*in[i]; + double f = d_iir.filter(mag_sqrd); + out[i] = sqrt(f); + } + + return noutput_items; +} + +void +gr_rms_ff::set_alpha(double alpha) +{ + d_iir.set_taps(alpha); +} diff --git a/gnuradio-core/src/lib/general/gr_rms_ff.h b/gnuradio-core/src/lib/general/gr_rms_ff.h new file mode 100644 index 000000000..30cf7f9d9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_rms_ff.h @@ -0,0 +1,61 @@ +/* -*- 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_RMS_FF_H +#define INCLUDED_GR_RMS_FF_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_single_pole_iir.h> + +class gr_rms_ff; +typedef boost::shared_ptr<gr_rms_ff> gr_rms_ff_sptr; + +GR_CORE_API gr_rms_ff_sptr +gr_make_rms_ff (double alpha = 0.0001); + +/*! + * \brief RMS average power + * \ingroup math_blk + */ +class GR_CORE_API gr_rms_ff : public gr_sync_block +{ + gr_single_pole_iir<double,double,double> d_iir; + bool d_unmuted; + + friend GR_CORE_API gr_rms_ff_sptr + gr_make_rms_ff (double alpha); + + gr_rms_ff (double alpha); + +public: + ~gr_rms_ff (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + bool unmuted () const { return d_unmuted; } + + void set_alpha (double alpha); +}; + +#endif /* INCLUDED_GR_RMS_FF_H */ diff --git a/gnuradio-core/src/lib/general/gr_rms_ff.i b/gnuradio-core/src/lib/general/gr_rms_ff.i new file mode 100644 index 000000000..00b03f5d4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_rms_ff.i @@ -0,0 +1,33 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,rms_ff); + +gr_rms_ff_sptr +gr_make_rms_ff (double alpha = 0.0001); + +class gr_rms_ff : public gr_sync_block +{ +public: + bool unmuted () const { return d_unmuted; } + void set_alpha (double alpha); +}; diff --git a/gnuradio-core/src/lib/general/gr_scrambler_bb.cc b/gnuradio-core/src/lib/general/gr_scrambler_bb.cc new file mode 100644 index 000000000..31eb19207 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_scrambler_bb.cc @@ -0,0 +1,56 @@ +/* -*- 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 new file mode 100644 index 000000000..edb429e0a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_scrambler_bb.h @@ -0,0 +1,60 @@ +/* -*- 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 new file mode 100644 index 000000000..a7ef7b364 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_scrambler_bb.i @@ -0,0 +1,31 @@ +/* -*- 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_short_to_char.cc b/gnuradio-core/src/lib/general/gr_short_to_char.cc new file mode 100644 index 000000000..8c146a351 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_short_to_char.cc @@ -0,0 +1,67 @@ +/* -*- 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 <gr_short_to_char.h> +#include <gr_io_signature.h> +#include <volk/volk.h> + +gr_short_to_char_sptr +gr_make_short_to_char (size_t vlen) +{ + return gnuradio::get_initial_sptr(new gr_short_to_char (vlen)); +} + +gr_short_to_char::gr_short_to_char (size_t vlen) + : gr_sync_block ("gr_short_to_char", + gr_make_io_signature (1, 1, sizeof (short)*vlen), + gr_make_io_signature (1, 1, sizeof (char)*vlen)), + d_vlen(vlen) +{ + const int alignment_multiple = + volk_get_alignment() / sizeof(char); + set_alignment(std::max(1,alignment_multiple)); +} + +int +gr_short_to_char::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const int16_t *in = (const int16_t *) input_items[0]; + int8_t *out = (int8_t *) output_items[0]; + + if(is_unaligned()) { + volk_16i_convert_8i_u(out, in, d_vlen*noutput_items); + } + else { + volk_16i_convert_8i_a(out, in, d_vlen*noutput_items); + } + + return noutput_items; +} + + + diff --git a/gnuradio-core/src/lib/general/gr_short_to_char.h b/gnuradio-core/src/lib/general/gr_short_to_char.h new file mode 100644 index 000000000..bf96211c7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_short_to_char.h @@ -0,0 +1,58 @@ +/* -*- 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_GR_SHORT_TO_CHAR_H +#define INCLUDED_GR_SHORT_TO_CHAR_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_short_to_char; +typedef boost::shared_ptr<gr_short_to_char> gr_short_to_char_sptr; + +GR_CORE_API gr_short_to_char_sptr +gr_make_short_to_char (size_t vlen=1); + +/*! + * \brief Convert stream of short to a stream of float + * \ingroup converter_blk + * + * \param vlen vector length of data streams. + */ + +class GR_CORE_API gr_short_to_char : public gr_sync_block +{ + private: + friend GR_CORE_API gr_short_to_char_sptr + gr_make_short_to_char (size_t vlen); + gr_short_to_char (size_t vlen); + + size_t d_vlen; + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_SHORT_TO_CHAR_H */ diff --git a/gnuradio-core/src/lib/general/gr_short_to_char.i b/gnuradio-core/src/lib/general/gr_short_to_char.i new file mode 100644 index 000000000..7389ed10b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_short_to_char.i @@ -0,0 +1,31 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,short_to_char) + +gr_short_to_char_sptr +gr_make_short_to_char (size_t vlen=1); + +class gr_short_to_char : public gr_sync_block +{ + +}; diff --git a/gnuradio-core/src/lib/general/gr_short_to_float.cc b/gnuradio-core/src/lib/general/gr_short_to_float.cc new file mode 100644 index 000000000..093d6024f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_short_to_float.cc @@ -0,0 +1,78 @@ +/* -*- 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 <gr_short_to_float.h> +#include <gr_io_signature.h> +#include <volk/volk.h> + +gr_short_to_float_sptr +gr_make_short_to_float (size_t vlen, float scale) +{ + return gnuradio::get_initial_sptr(new gr_short_to_float (vlen, scale)); +} + +gr_short_to_float::gr_short_to_float (size_t vlen, float scale) + : gr_sync_block ("gr_short_to_float", + gr_make_io_signature (1, 1, sizeof (short)*vlen), + gr_make_io_signature (1, 1, sizeof (float)*vlen)), + d_vlen(vlen), d_scale(scale) +{ + const int alignment_multiple = + volk_get_alignment() / sizeof(float); + set_alignment(std::max(1,alignment_multiple)); +} + +float +gr_short_to_float::scale() const +{ + return d_scale; +} + +void +gr_short_to_float::set_scale(float scale) +{ + d_scale = scale; +} + +int +gr_short_to_float::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const short *in = (const short *) input_items[0]; + float *out = (float *) output_items[0]; + + if(is_unaligned()) { + volk_16i_s32f_convert_32f_u(out, in, d_scale, d_vlen*noutput_items); + } + else { + volk_16i_s32f_convert_32f_a(out, in, d_scale, d_vlen*noutput_items); + } + return noutput_items; +} + + + diff --git a/gnuradio-core/src/lib/general/gr_short_to_float.h b/gnuradio-core/src/lib/general/gr_short_to_float.h new file mode 100644 index 000000000..362549e70 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_short_to_float.h @@ -0,0 +1,70 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_GR_SHORT_TO_FLOAT_H +#define INCLUDED_GR_SHORT_TO_FLOAT_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_short_to_float; +typedef boost::shared_ptr<gr_short_to_float> gr_short_to_float_sptr; + +GR_CORE_API gr_short_to_float_sptr +gr_make_short_to_float (size_t vlen=1, float scale=1); + +/*! + * \brief Convert stream of short to a stream of float + * \ingroup converter_blk + * + * \param vlen vector length of data streams. + * \param scale a scalar divider to change the output signal scale. + */ + +class GR_CORE_API gr_short_to_float : public gr_sync_block +{ + private: + friend GR_CORE_API gr_short_to_float_sptr + gr_make_short_to_float (size_t vlen, float scale); + gr_short_to_float (size_t vlen, float scale); + + size_t d_vlen; + float d_scale; + + public: + /*! + * Get the scalar divider value. + */ + float scale() const; + + /*! + * Set the scalar divider value. + */ + void set_scale(float scale); + + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_SHORT_TO_FLOAT_H */ diff --git a/gnuradio-core/src/lib/general/gr_short_to_float.i b/gnuradio-core/src/lib/general/gr_short_to_float.i new file mode 100644 index 000000000..e781e292c --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_short_to_float.i @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,short_to_float) + +gr_short_to_float_sptr +gr_make_short_to_float (size_t vlen=1, float scale=1); + +class gr_short_to_float : public gr_sync_block +{ +public: + float scale() const; + void set_scale(float scale); +}; diff --git a/gnuradio-core/src/lib/general/gr_simple_correlator.cc b/gnuradio-core/src/lib/general/gr_simple_correlator.cc new file mode 100644 index 000000000..b9209e74f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_correlator.cc @@ -0,0 +1,237 @@ +/* -*- 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_correlator.h> +#include <gr_simple_framer_sync.h> +#include <gr_io_signature.h> +#include <assert.h> +#include <stdexcept> +#include <gr_count_bits.h> +#include <string.h> +#include <cstdio> + + +static const int THRESHOLD = 3; + +gr_simple_correlator_sptr +gr_make_simple_correlator (int payload_bytesize) +{ + return gnuradio::get_initial_sptr(new gr_simple_correlator (payload_bytesize)); +} + +gr_simple_correlator::gr_simple_correlator (int payload_bytesize) + : gr_block ("simple_correlator", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (unsigned char))), + d_payload_bytesize (payload_bytesize), + d_state (ST_LOOKING), d_osi (0), + d_bblen ((payload_bytesize + GRSF_PAYLOAD_OVERHEAD) * GRSF_BITS_PER_BYTE), + d_bitbuf (new unsigned char [d_bblen]), + d_pktbuf (new unsigned char [d_bblen/GRSF_BITS_PER_BYTE]), + d_bbi (0) +{ + d_avbi = 0; + d_accum = 0.0; + d_avg = 0.0; + for (int i = 0; i < AVG_PERIOD; i++) + d_avgbuf[i] = 0.0; + +#ifdef DEBUG_SIMPLE_CORRELATOR + d_debug_fp = fopen("corr.log", "w"); +#endif + enter_looking (); + +} + +gr_simple_correlator::~gr_simple_correlator () +{ +#ifdef DEBUG_SIMPLE_CORRELATOR + fclose(d_debug_fp); +#endif + delete [] d_bitbuf; + delete [] d_pktbuf; +} + + +void +gr_simple_correlator::enter_looking () +{ + fflush (stdout); + // fprintf (stderr, ">>> enter_looking\n"); + d_state = ST_LOOKING; + for (int i = 0; i < OVERSAMPLE; i++) + d_shift_reg[i] = 0; + d_osi = 0; + + d_avbi = 0; + d_avg = d_avg * 0.5; + d_accum = 0; + for (int i = 0; i < AVG_PERIOD; i++) + d_avgbuf[i] = 0.0; +} + +void +gr_simple_correlator::enter_under_threshold () +{ + fflush (stdout); + // fprintf (stderr, ">>> enter_under_threshold\n"); + d_state = ST_UNDER_THRESHOLD; + d_transition_osi = d_osi; +} + +void +gr_simple_correlator::enter_locked () +{ + d_state = ST_LOCKED; + int delta = sub_index (d_osi, d_transition_osi); + d_center_osi = add_index (d_transition_osi, delta/2); + d_center_osi = add_index (d_center_osi, 3); // FIXME + d_bbi = 0; + fflush (stdout); + // fprintf (stderr, ">>> enter_locked d_center_osi = %d\n", d_center_osi); + + d_avg = std::max(-1.0, std::min(1.0, d_accum * (1.0/AVG_PERIOD))); + // fprintf(stderr, ">>> enter_locked d_avg = %g\n", d_avg); +} + +static void +packit (unsigned char *pktbuf, const unsigned char *bitbuf, int bitcount) +{ + for (int i = 0; i < bitcount; i += 8){ + int t = bitbuf[i+0] & 0x1; + t = (t << 1) | (bitbuf[i+1] & 0x1); + t = (t << 1) | (bitbuf[i+2] & 0x1); + t = (t << 1) | (bitbuf[i+3] & 0x1); + t = (t << 1) | (bitbuf[i+4] & 0x1); + t = (t << 1) | (bitbuf[i+5] & 0x1); + t = (t << 1) | (bitbuf[i+6] & 0x1); + t = (t << 1) | (bitbuf[i+7] & 0x1); + *pktbuf++ = t; + } +} + +void +gr_simple_correlator::update_avg(float x) +{ + d_accum -= d_avgbuf[d_avbi]; + d_avgbuf[d_avbi] = x; + d_accum += x; + d_avbi = (d_avbi + 1) & (AVG_PERIOD-1); +} + + +int +gr_simple_correlator::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *in = (const float *) input_items[0]; + unsigned char *out = (unsigned char *) output_items[0]; + + + int n = 0; + int nin = ninput_items[0]; + int decision; + int hamming_dist; + +#ifdef DEBUG_SIMPLE_CORRELATOR + struct debug_data { + float raw_data; + float sampled; + float enter_locked; + } debug_data; +#endif + + while (n < nin){ + +#ifdef DEBUG_SIMPLE_CORRELATOR + debug_data.raw_data = in[n]; + debug_data.sampled = 0.0; + debug_data.enter_locked = 0.0; +#endif + + switch (d_state){ + + case ST_LOCKED: + if (d_osi == d_center_osi){ + +#ifdef DEBUG_SIMPLE_CORRELATOR + debug_data.sampled = 1.0; +#endif + decision = slice (in[n]); + + d_bitbuf[d_bbi] = decision; + d_bbi++; + if (d_bbi >= d_bblen){ + // printf ("got whole packet\n"); + packit (d_pktbuf, d_bitbuf, d_bbi); + printf ("seqno %3d\n", d_pktbuf[0]); + memcpy (out, &d_pktbuf[GRSF_PAYLOAD_OVERHEAD], d_payload_bytesize); + enter_looking (); + consume_each (n + 1); + return d_payload_bytesize; + } + } + break; + + case ST_LOOKING: + case ST_UNDER_THRESHOLD: + update_avg(in[n]); + decision = slice (in[n]); + d_shift_reg[d_osi] = (d_shift_reg[d_osi] << 1) | decision; + + hamming_dist = gr_count_bits64 (d_shift_reg[d_osi] ^ GRSF_SYNC); + // printf ("%2d %d\n", hamming_dist, d_osi); + + if (d_state == ST_LOOKING && hamming_dist <= THRESHOLD){ + // We're seeing a good PN code, remember location + enter_under_threshold (); + } + else if (d_state == ST_UNDER_THRESHOLD && hamming_dist > THRESHOLD){ + // no longer seeing good PN code, compute center of goodness + enter_locked (); +#ifdef DEBUG_SIMPLE_CORRELATOR + debug_data.enter_locked = 1.0; +#endif + } + break; + + default: + assert (0); + } + +#ifdef DEBUG_SIMPLE_CORRELATOR + fwrite(&debug_data, sizeof (debug_data), 1, d_debug_fp); +#endif + + d_osi = add_index (d_osi, 1); + n++; + } + + consume_each (n); + return 0; +} diff --git a/gnuradio-core/src/lib/general/gr_simple_correlator.h b/gnuradio-core/src/lib/general/gr_simple_correlator.h new file mode 100644 index 000000000..37d00c125 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_correlator.h @@ -0,0 +1,111 @@ +/* -*- 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_CORRELATOR_H +#define INCLUDED_GR_SIMPLE_CORRELATOR_H + +#include <gr_core_api.h> +#include <gr_block.h> +#include <assert.h> + +//#define DEBUG_SIMPLE_CORRELATOR + +class gr_simple_correlator; +typedef boost::shared_ptr<gr_simple_correlator> gr_simple_correlator_sptr; + +GR_CORE_API gr_simple_correlator_sptr gr_make_simple_correlator (int payload_bytesize); + +/*! + * \brief inverse of gr_simple_framer (more or less) + * \ingroup sync_blk + */ +class GR_CORE_API gr_simple_correlator : public gr_block +{ + static const int OVERSAMPLE = 8; + enum state_t { ST_LOOKING, ST_UNDER_THRESHOLD, ST_LOCKED }; + + int d_payload_bytesize; + state_t d_state; + unsigned int d_osi; // over sample index [0,OVERSAMPLE-1] + unsigned int d_transition_osi; // first index where Hamming dist < thresh + unsigned int d_center_osi; // center of bit + unsigned long long int d_shift_reg[OVERSAMPLE]; + int d_bblen; // length of bitbuf + unsigned char *d_bitbuf; // demodulated bits + unsigned char *d_pktbuf; // temp packet buf + int d_bbi; // bitbuf index + + static const int AVG_PERIOD = 512; // must be power of 2 (for freq offset correction) + int d_avbi; + float d_avgbuf[AVG_PERIOD]; + float d_avg; + float d_accum; + +#ifdef DEBUG_SIMPLE_CORRELATOR + FILE *d_debug_fp; // binary log file +#endif + + friend GR_CORE_API gr_simple_correlator_sptr gr_make_simple_correlator (int payload_bytesize); + gr_simple_correlator (int payload_bytesize); + + + inline int slice (float x) + { + return x >= d_avg ? 1 : 0; + } + + void update_avg(float x); + + void enter_locked (); + void enter_under_threshold (); + void enter_looking (); + + static int add_index (int a, int b) + { + int t = a + b; + if (t >= OVERSAMPLE) + t -= OVERSAMPLE; + assert (t >= 0 && t < OVERSAMPLE); + return t; + } + + static int sub_index (int a, int b) + { + int t = a - b; + if (t < 0) + t += OVERSAMPLE; + assert (t >= 0 && t < OVERSAMPLE); + return t; + } + + + public: + ~gr_simple_correlator (); + + 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_CORRELATOR_H */ diff --git a/gnuradio-core/src/lib/general/gr_simple_correlator.i b/gnuradio-core/src/lib/general/gr_simple_correlator.i new file mode 100644 index 000000000..24d133072 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_correlator.i @@ -0,0 +1,31 @@ +/* -*- 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_correlator); + +gr_simple_correlator_sptr gr_make_simple_correlator (int payload_bytesize); + +class gr_simple_correlator : public gr_block +{ + private: + gr_simple_correlator (int payload_bytesize); +}; diff --git a/gnuradio-core/src/lib/general/gr_simple_framer.cc b/gnuradio-core/src/lib/general/gr_simple_framer.cc new file mode 100644 index 000000000..506603bb7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_framer.cc @@ -0,0 +1,101 @@ +/* -*- 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 new file mode 100644 index 000000000..76a4b7bab --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_framer.h @@ -0,0 +1,59 @@ +/* -*- 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 new file mode 100644 index 000000000..c13ead87b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_framer.i @@ -0,0 +1,31 @@ +/* -*- 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_simple_framer_sync.h b/gnuradio-core/src/lib/general/gr_simple_framer_sync.h new file mode 100644 index 000000000..66173be42 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_framer_sync.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_SIMPLE_FRAMER_SYNC_H +#define INCLUDED_GR_SIMPLE_FRAMER_SYNC_H + +/*! + * \brief Here are a couple of maximum length sequences (m-sequences) that were generated by the + * the "mseq" matlab/octave code downloaded from: + * <a href="http://www.mathworks.com/matlabcentral/fileexchange/990">http://www.mathworks.com/matlabcentral/fileexchange/990</a> + * + * <pre> + * 31-bit m-sequence: + * 0110100100001010111011000111110 + * 0x690AEC76 (padded on right with a zero) + * + * 63-bit m-sequence: + * 101011001101110110100100111000101111001010001100001000001111110 + * 0xACDDA4E2F28C20FC (padded on right with a zero) + * </pre> + */ + +static const unsigned long long GRSF_SYNC = 0xacdda4e2f28c20fcULL; + +static const int GRSF_BITS_PER_BYTE = 8; +static const int GRSF_SYNC_OVERHEAD = sizeof(GRSF_SYNC); +static const int GRSF_PAYLOAD_OVERHEAD = 1; // 1 byte seqno +static const int GRSF_TAIL_PAD = 1; // one byte trailing padding +static const int GRSF_OVERHEAD = GRSF_SYNC_OVERHEAD + GRSF_PAYLOAD_OVERHEAD + GRSF_TAIL_PAD; + + +#endif /* INCLUDED_GR_SIMPLE_FRAMER_SYNC_H */ diff --git a/gnuradio-core/src/lib/general/gr_simple_squelch_cc.cc b/gnuradio-core/src/lib/general/gr_simple_squelch_cc.cc new file mode 100644 index 000000000..5d90a3da4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_squelch_cc.cc @@ -0,0 +1,99 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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_squelch_cc.h> +#include <gr_io_signature.h> +#include <cmath> + +gr_simple_squelch_cc_sptr +gr_make_simple_squelch_cc(double threshold_db, double alpha) +{ + return gnuradio::get_initial_sptr(new gr_simple_squelch_cc(threshold_db, alpha)); +} + +gr_simple_squelch_cc::gr_simple_squelch_cc (double threshold_db, double alpha) + : gr_sync_block ("simple_squelch_cc", + gr_make_io_signature(1, 1, sizeof(gr_complex)), + gr_make_io_signature(1, 1, sizeof(gr_complex))), + d_iir(alpha), d_unmuted(false) +{ + set_threshold (threshold_db); +} + +gr_simple_squelch_cc::~gr_simple_squelch_cc() +{ +} + + +int +gr_simple_squelch_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]; + + for (int i = 0; i < noutput_items; i++){ + double mag_sqrd = in[i].real()*in[i].real() + in[i].imag()*in[i].imag(); + double f = d_iir.filter(mag_sqrd); + if (f >= d_threshold) + out[i] = in[i]; + else + out[i] = 0; + } + + d_unmuted = d_iir.prev_output() >= d_threshold; + return noutput_items; +} + +void +gr_simple_squelch_cc::set_threshold(double decibels) +{ + // convert to absolute threshold (mag squared) + d_threshold = std::pow(10.0, decibels/10); +} + +double +gr_simple_squelch_cc::threshold() const +{ + return 10 * log10(d_threshold); +} + +void +gr_simple_squelch_cc::set_alpha(double alpha) +{ + d_iir.set_taps(alpha); +} + +std::vector<float> +gr_simple_squelch_cc::squelch_range() const +{ + std::vector<float> r(3); + r[0] = -50.0; // min FIXME + r[1] = +50.0; // max FIXME + r[2] = (r[1] - r[0]) / 100; // step size + + return r; +} diff --git a/gnuradio-core/src/lib/general/gr_simple_squelch_cc.h b/gnuradio-core/src/lib/general/gr_simple_squelch_cc.h new file mode 100644 index 000000000..4bf62c7ec --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_squelch_cc.h @@ -0,0 +1,67 @@ +/* -*- 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_SIMPLE_SQUELCH_CC_H +#define INCLUDED_GR_SIMPLE_SQUELCH_CC_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_single_pole_iir.h> + +class gr_simple_squelch_cc; +typedef boost::shared_ptr<gr_simple_squelch_cc> gr_simple_squelch_cc_sptr; + +GR_CORE_API gr_simple_squelch_cc_sptr +gr_make_simple_squelch_cc (double threshold_db, double alpha = 0.0001); + +/*! + * \brief simple squelch block based on average signal power and threshold in dB. + * \ingroup level_blk + */ +class GR_CORE_API gr_simple_squelch_cc : public gr_sync_block +{ + double d_threshold; + gr_single_pole_iir<double,double,double> d_iir; + bool d_unmuted; + + friend GR_CORE_API gr_simple_squelch_cc_sptr + gr_make_simple_squelch_cc (double threshold_db, double alpha); + + gr_simple_squelch_cc (double threshold_db, double alpha); + +public: + ~gr_simple_squelch_cc (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + bool unmuted () const { return d_unmuted; } + + void set_alpha (double alpha); + void set_threshold (double decibels); + + double threshold() const; + std::vector<float> squelch_range() const; + +}; + +#endif /* INCLUDED_GR_SIMPLE_SQUELCH_CC_H */ diff --git a/gnuradio-core/src/lib/general/gr_simple_squelch_cc.i b/gnuradio-core/src/lib/general/gr_simple_squelch_cc.i new file mode 100644 index 000000000..17b469e15 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_squelch_cc.i @@ -0,0 +1,37 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,simple_squelch_cc); + +gr_simple_squelch_cc_sptr +gr_make_simple_squelch_cc (double threshold_db, double alpha = 0.0001); + +class gr_simple_squelch_cc : public gr_sync_block +{ +public: + bool unmuted () const { return d_unmuted; } + void set_alpha (double alpha); + void set_threshold (double decibels); + + double threshold() const; + std::vector<float> squelch_range() const; +}; diff --git a/gnuradio-core/src/lib/general/gr_skiphead.cc b/gnuradio-core/src/lib/general/gr_skiphead.cc new file mode 100644 index 000000000..7b441bea9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_skiphead.cc @@ -0,0 +1,83 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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_skiphead.h> +#include <gr_io_signature.h> +#include <string.h> + +gr_skiphead::gr_skiphead (size_t itemsize, uint64_t nitems_to_skip) + : gr_block ("skiphead", + gr_make_io_signature(1, 1, itemsize), + gr_make_io_signature(1, 1, itemsize)), + d_nitems_to_skip(nitems_to_skip), d_nitems(0) +{ +} + +gr_skiphead_sptr +gr_make_skiphead (size_t itemsize, uint64_t nitems_to_skip) +{ + return gnuradio::get_initial_sptr(new gr_skiphead (itemsize, nitems_to_skip)); +} + +int +gr_skiphead::general_work(int noutput_items, + gr_vector_int &ninput_items_, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const char *in = (const char *) input_items[0]; + char *out = (char *) output_items[0]; + + int ninput_items = std::min(ninput_items_[0], noutput_items); + int ii = 0; // input index + + while (ii < ninput_items){ + + uint64_t ni_total = ii + d_nitems; // total items processed so far + if (ni_total < d_nitems_to_skip){ // need to skip some more + + int n_to_skip = (int) std::min(d_nitems_to_skip - ni_total, + (uint64_t)(ninput_items - ii)); + ii += n_to_skip; + } + + else { // nothing left to skip. copy away + + int n_to_copy = ninput_items - ii; + if (n_to_copy > 0){ + size_t itemsize = output_signature()->sizeof_stream_item(0); + memcpy(out, in + (ii*itemsize), n_to_copy*itemsize); + } + + d_nitems += ninput_items; + consume_each(ninput_items); + return n_to_copy; + } + } + + d_nitems += ninput_items; + consume_each(ninput_items); + return 0; +} diff --git a/gnuradio-core/src/lib/general/gr_skiphead.h b/gnuradio-core/src/lib/general/gr_skiphead.h new file mode 100644 index 000000000..899b40f27 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_skiphead.h @@ -0,0 +1,60 @@ +/* -*- 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_SKIPHEAD_H +#define INCLUDED_GR_SKIPHEAD_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <stddef.h> // size_t + +class gr_skiphead; +typedef boost::shared_ptr<gr_skiphead> gr_skiphead_sptr; + +GR_CORE_API gr_skiphead_sptr +gr_make_skiphead (size_t itemsize, uint64_t nitems_to_skip); + + +/*! + * \brief skips the first N items, from then on copies items to the output + * \ingroup slicedice_blk + * + * Useful for building test cases and sources which have metadata or junk at the start + */ + +class GR_CORE_API gr_skiphead : public gr_block +{ + friend GR_CORE_API gr_skiphead_sptr gr_make_skiphead (size_t itemsize, uint64_t nitems_to_skip); + gr_skiphead (size_t itemsize, uint64_t nitems_to_skip); + + uint64_t d_nitems_to_skip; + uint64_t d_nitems; // total items seen + + public: + + 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_SKIPHEAD_H */ diff --git a/gnuradio-core/src/lib/general/gr_skiphead.i b/gnuradio-core/src/lib/general/gr_skiphead.i new file mode 100644 index 000000000..3246db970 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_skiphead.i @@ -0,0 +1,30 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,skiphead); + +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); +}; diff --git a/gnuradio-core/src/lib/general/gr_squelch_base_cc.cc b/gnuradio-core/src/lib/general/gr_squelch_base_cc.cc new file mode 100644 index 000000000..b32a0a695 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_squelch_base_cc.cc @@ -0,0 +1,93 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_squelch_base_cc.h> +#include <gr_io_signature.h> + +gr_squelch_base_cc::gr_squelch_base_cc(const char *name, int ramp, bool gate) : + gr_block(name, + gr_make_io_signature(1, 1, sizeof(gr_complex)), + gr_make_io_signature(1, 1, sizeof(gr_complex))) +{ + set_ramp(ramp); + set_gate(gate); + d_state = ST_MUTED; + d_envelope = d_ramp ? 0.0 : 1.0; + d_ramped = 0; +} + +int gr_squelch_base_cc::general_work(int noutput_items, + gr_vector_int &ninput_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]; + + int j = 0; + + for (int i = 0; i < noutput_items; i++) { + update_state(in[i]); + + // Adjust envelope based on current state + switch(d_state) { + case ST_MUTED: + if (!mute()) + d_state = d_ramp ? ST_ATTACK : ST_UNMUTED; // If not ramping, go straight to unmuted + break; + + case ST_UNMUTED: + if (mute()) + d_state = d_ramp ? ST_DECAY : ST_MUTED; // If not ramping, go straight to muted + break; + + case ST_ATTACK: + d_envelope = 0.5-std::cos(M_PI*(++d_ramped)/d_ramp)/2.0; // FIXME: precalculate window for speed + if (d_ramped >= d_ramp) { // use >= in case d_ramp is set to lower value elsewhere + d_state = ST_UNMUTED; + d_envelope = 1.0; + } + break; + + case ST_DECAY: + d_envelope = 0.5-std::cos(M_PI*(--d_ramped)/d_ramp)/2.0; // FIXME: precalculate window for speed + if (d_ramped == 0.0) + d_state = ST_MUTED; + break; + }; + + // If unmuted, copy input times envelope to output + // Otherwise, if not gating, copy zero to output + if (d_state != ST_MUTED) + out[j++] = in[i]*gr_complex(d_envelope, 0.0); + else + if (!d_gate) + out[j++] = 0.0; + } + + consume_each(noutput_items); // Use all the inputs + return j; // But only report outputs copied +} diff --git a/gnuradio-core/src/lib/general/gr_squelch_base_cc.h b/gnuradio-core/src/lib/general/gr_squelch_base_cc.h new file mode 100644 index 000000000..f1814473f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_squelch_base_cc.h @@ -0,0 +1,59 @@ +/* -*- 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_SQUELCH_BASE_CC_H +#define INCLUDED_GR_SQUELCH_BASE_CC_H + +#include <gr_core_api.h> +#include <gr_block.h> + +class GR_CORE_API gr_squelch_base_cc : public gr_block +{ +private: + int d_ramp; + int d_ramped; + bool d_gate; + double d_envelope; + enum { ST_MUTED, ST_ATTACK, ST_UNMUTED, ST_DECAY } d_state; + +protected: + virtual void update_state(const gr_complex &sample) {}; + virtual bool mute() const { return false; }; + +public: + gr_squelch_base_cc(const char *name, int ramp, bool gate); + + int ramp() const { return d_ramp; } + void set_ramp(int ramp) { d_ramp = ramp; } + bool gate() const { return d_gate; } + void set_gate(bool gate) { d_gate = gate; } + bool unmuted() const { return (d_state == ST_UNMUTED || d_state == ST_ATTACK); } + + virtual std::vector<float> squelch_range() const = 0; + + 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_SQUELCH_BASE_CC_H */ diff --git a/gnuradio-core/src/lib/general/gr_squelch_base_cc.i b/gnuradio-core/src/lib/general/gr_squelch_base_cc.i new file mode 100644 index 000000000..6501b7d2b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_squelch_base_cc.i @@ -0,0 +1,40 @@ +/* -*- 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. + */ + +#include <gr_block.h> + +class gr_squelch_base_cc : public gr_block +{ +private: + enum { ST_MUTED, ST_ATTACK, ST_UNMUTED, ST_DECAY } d_state; + +public: + gr_squelch_base_cc(const char *name, int ramp, bool gate); + + int ramp() const { return d_ramp; } + void set_ramp(int ramp) { d_ramp = ramp; } + bool gate() const { return d_gate; } + void set_gate(bool gate) { d_gate = gate; } + bool unmuted() const { return (d_state == ST_UNMUTED || d_state == ST_ATTACK); } + + virtual std::vector<float> squelch_range() const = 0; +}; diff --git a/gnuradio-core/src/lib/general/gr_squelch_base_ff.cc b/gnuradio-core/src/lib/general/gr_squelch_base_ff.cc new file mode 100644 index 000000000..4bf8cff97 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_squelch_base_ff.cc @@ -0,0 +1,93 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_squelch_base_ff.h> +#include <gr_io_signature.h> + +gr_squelch_base_ff::gr_squelch_base_ff(const char *name, int ramp, bool gate) : + gr_block(name, + gr_make_io_signature(1, 1, sizeof(float)), + gr_make_io_signature(1, 1, sizeof(float))) +{ + set_ramp(ramp); + set_gate(gate); + d_state = ST_MUTED; + d_envelope = d_ramp ? 0.0 : 1.0; + d_ramped = 0; +} + +int gr_squelch_base_ff::general_work(int noutput_items, + gr_vector_int &ninput_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]; + + int j = 0; + + for (int i = 0; i < noutput_items; i++) { + update_state(in[i]); + + // Adjust envelope based on current state + switch(d_state) { + case ST_MUTED: + if (!mute()) + d_state = d_ramp ? ST_ATTACK : ST_UNMUTED; // If not ramping, go straight to unmuted + break; + + case ST_UNMUTED: + if (mute()) + d_state = d_ramp ? ST_DECAY : ST_MUTED; // If not ramping, go straight to muted + break; + + case ST_ATTACK: + d_envelope = 0.5-std::cos(M_PI*(++d_ramped)/d_ramp)/2.0; // FIXME: precalculate window for speed + if (d_ramped >= d_ramp) { // use >= in case d_ramp is set to lower value elsewhere + d_state = ST_UNMUTED; + d_envelope = 1.0; + } + break; + + case ST_DECAY: + d_envelope = 0.5-std::cos(M_PI*(--d_ramped)/d_ramp)/2.0; // FIXME: precalculate window for speed + if (d_ramped == 0.0) + d_state = ST_MUTED; + break; + }; + + // If unmuted, copy input times envelope to output + // Otherwise, if not gating, copy zero to output + if (d_state != ST_MUTED) + out[j++] = in[i]*d_envelope; + else + if (!d_gate) + out[j++] = 0.0; + } + + consume_each(noutput_items); // Use all the inputs + return j; // But only report outputs copied +} diff --git a/gnuradio-core/src/lib/general/gr_squelch_base_ff.h b/gnuradio-core/src/lib/general/gr_squelch_base_ff.h new file mode 100644 index 000000000..eb52635b4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_squelch_base_ff.h @@ -0,0 +1,59 @@ +/* -*- 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_SQUELCH_BASE_FF_H +#define INCLUDED_GR_SQUELCH_BASE_FF_H + +#include <gr_core_api.h> +#include <gr_block.h> + +class GR_CORE_API gr_squelch_base_ff : public gr_block +{ +private: + int d_ramp; + int d_ramped; + bool d_gate; + double d_envelope; + enum { ST_MUTED, ST_ATTACK, ST_UNMUTED, ST_DECAY } d_state; + +protected: + virtual void update_state(const float &sample) {}; + virtual bool mute() const { return false; }; + +public: + gr_squelch_base_ff(const char *name, int ramp, bool gate); + + int ramp() const { return d_ramp; } + void set_ramp(int ramp) { d_ramp = ramp; } + bool gate() const { return d_gate; } + void set_gate(bool gate) { d_gate = gate; } + bool unmuted() const { return (d_state == ST_UNMUTED || d_state == ST_ATTACK); } + + virtual std::vector<float> squelch_range() const = 0; + + 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_SQUELCH_BASE_FF_H */ diff --git a/gnuradio-core/src/lib/general/gr_squelch_base_ff.i b/gnuradio-core/src/lib/general/gr_squelch_base_ff.i new file mode 100644 index 000000000..a4e5c7115 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_squelch_base_ff.i @@ -0,0 +1,40 @@ +/* -*- 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. + */ + +#include <gr_block.h> + +class gr_squelch_base_ff : public gr_block +{ +private: + enum { ST_MUTED, ST_ATTACK, ST_UNMUTED, ST_DECAY } d_state; + +public: + gr_squelch_base_ff(const char *name, int ramp, bool gate); + + int ramp() const { return d_ramp; } + void set_ramp(int ramp) { d_ramp = ramp; } + bool gate() const { return d_gate; } + void set_gate(bool gate) { d_gate = gate; } + bool unmuted() const { return (d_state == ST_UNMUTED || d_state == ST_ATTACK); } + + virtual std::vector<float> squelch_range() const = 0; +}; diff --git a/gnuradio-core/src/lib/general/gr_stream_mux.cc b/gnuradio-core/src/lib/general/gr_stream_mux.cc new file mode 100644 index 000000000..978d960b2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_stream_mux.cc @@ -0,0 +1,124 @@ +/* -*- 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_stream_mux.h> +#include <gr_io_signature.h> +#include <string.h> +#include <cstdio> + +#define VERBOSE 0 + +gr_stream_mux_sptr +gr_make_stream_mux (size_t itemsize, const std::vector<int> &lengths) +{ + return gnuradio::get_initial_sptr(new gr_stream_mux (itemsize, lengths)); +} + +gr_stream_mux::gr_stream_mux (size_t itemsize, const std::vector<int> &lengths) + : gr_block ("stream_mux", + gr_make_io_signature (1, -1, itemsize), + gr_make_io_signature (1, 1, itemsize)), + d_itemsize(itemsize), + d_stream(0), + d_residual(0), + d_lengths(lengths) +{ + if(d_lengths[d_stream] == 0) { + increment_stream(); + } + d_residual = d_lengths[d_stream]; +} + +gr_stream_mux::~gr_stream_mux(void) +{ +} + +void +gr_stream_mux::forecast (int noutput_items, gr_vector_int &ninput_items_required) +{ + unsigned ninputs = ninput_items_required.size (); + for (unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = (d_lengths[i] == 0 ? 0 : 1); +} + +void gr_stream_mux::increment_stream() +{ + do { + d_stream = (d_stream+1) % d_lengths.size(); + } while(d_lengths[d_stream] == 0); + + d_residual = d_lengths[d_stream]; +} + +int +gr_stream_mux::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + char *out = (char *) output_items[0]; + const char *in; + int out_index = 0; + std::vector<int> input_index(d_lengths.size(), 0); + + if(VERBOSE) { + printf("mux: nouput_items: %d d_stream: %d\n", noutput_items, d_stream); + for(size_t i = 0; i < d_lengths.size(); i++) + printf("\tninput_items[%zu]: %d\n", i, ninput_items[i]); + } + + while (1) { + int r = std::min(noutput_items - out_index, + std::min(d_residual, + ninput_items[d_stream] - input_index[d_stream])); + if(VERBOSE) { + printf("mux: r=%d\n", r); + printf("\tnoutput_items - out_index: %d\n", + noutput_items - out_index); + printf("\td_residual: %d\n", + d_residual); + printf("\tninput_items[d_stream] - input_index[d_stream]: %d\n", + ninput_items[d_stream] - input_index[d_stream]); + } + + if(r <= 0) { + return out_index; + } + + in = (const char *) input_items[d_stream] + input_index[d_stream]*d_itemsize; + + memcpy(&out[out_index*d_itemsize], in, r*d_itemsize); + out_index += r; + input_index[d_stream] += r; + d_residual -= r; + + consume(d_stream, r); + + if(d_residual == 0) { + increment_stream(); + } + } +} diff --git a/gnuradio-core/src/lib/general/gr_stream_mux.h b/gnuradio-core/src/lib/general/gr_stream_mux.h new file mode 100644 index 000000000..742bf082d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_stream_mux.h @@ -0,0 +1,93 @@ +/* -*- 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_STREAM_MUX_H +#define INCLUDED_GR_STREAM_MUX_H + + +#include <gr_core_api.h> +#include <gr_block.h> +#include <vector> + +/*! + * \brief Creates a stream muxing block to multiplex many streams into + * one with a specified format. + * \ingroup converter_blk + * + * \param itemsize the item size of the stream + * \param length a vector (list/tuple) specifying the number of + * items from each stream the mux together. + * Warning: this requires that at least as many items + * per stream are available or the system will wait + * indefinitely for the items. + * + */ +class gr_stream_mux; +typedef boost::shared_ptr<gr_stream_mux> gr_stream_mux_sptr; + + + +GR_CORE_API gr_stream_mux_sptr +gr_make_stream_mux (size_t itemsize, const std::vector<int> &lengths); + + +/*! + * \brief Stream muxing block to multiplex many streams into + * one with a specified format. + * + * Muxes N streams together producing an output stream that + * contains N0 items from the first stream, N1 items from the second, + * etc. and repeats: + * + * [N0, N1, N2, ..., Nm, N0, N1, ...] + */ + +class GR_CORE_API gr_stream_mux : public gr_block +{ + friend GR_CORE_API gr_stream_mux_sptr + gr_make_stream_mux (size_t itemsize, const std::vector<int> &lengths); + + protected: + gr_stream_mux (size_t itemsize, const std::vector<int> &lengths); + + private: + size_t d_itemsize; + unsigned int d_stream; // index of currently selected stream + int d_residual; // number if items left to put into current stream + gr_vector_int d_lengths; // number if items to pack per stream + + void increment_stream(); + + public: + ~gr_stream_mux(void); + + 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 diff --git a/gnuradio-core/src/lib/general/gr_stream_mux.i b/gnuradio-core/src/lib/general/gr_stream_mux.i new file mode 100644 index 000000000..7cc116a23 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_stream_mux.i @@ -0,0 +1,42 @@ +/* -*- 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. + */ + +#include <vector> + +GR_SWIG_BLOCK_MAGIC(gr,stream_mux) + +gr_stream_mux_sptr +gr_make_stream_mux (size_t itemsize, + const std::vector<int> &lengths); + +class gr_stream_mux : public gr_block +{ + protected: + gr_make_stream_mux (size_t itemsize, + const std::vector<int> &lengths); + + public: + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; diff --git a/gnuradio-core/src/lib/general/gr_stream_to_streams.cc b/gnuradio-core/src/lib/general/gr_stream_to_streams.cc new file mode 100644 index 000000000..de72adb1d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_stream_to_streams.cc @@ -0,0 +1,66 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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_stream_to_streams.h> +#include <gr_io_signature.h> +#include <string.h> + +gr_stream_to_streams_sptr +gr_make_stream_to_streams (size_t item_size, size_t nstreams) +{ + return gnuradio::get_initial_sptr(new gr_stream_to_streams (item_size, nstreams)); +} + +gr_stream_to_streams::gr_stream_to_streams (size_t item_size, size_t nstreams) + : gr_sync_decimator ("stream_to_streams", + gr_make_io_signature (1, 1, item_size), + gr_make_io_signature (nstreams, + nstreams, item_size), + nstreams) +{ +} + +int +gr_stream_to_streams::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + size_t item_size = output_signature()->sizeof_stream_item (0); + + const char *in = (const char *) input_items[0]; + char **outv = (char **) &output_items[0]; + int nstreams = output_items.size(); + + for (int i = 0; i < noutput_items; i++){ + for (int j = 0; j < nstreams; j++){ + memcpy(outv[j], in, item_size); + outv[j] += item_size; + in += item_size; + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_stream_to_streams.h b/gnuradio-core/src/lib/general/gr_stream_to_streams.h new file mode 100644 index 000000000..117f57bf5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_stream_to_streams.h @@ -0,0 +1,56 @@ +/* -*- 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_STREAM_TO_STREAMS_H +#define INCLUDED_GR_STREAM_TO_STREAMS_H + +#include <gr_core_api.h> +#include <gr_sync_decimator.h> + +class gr_stream_to_streams; +typedef boost::shared_ptr<gr_stream_to_streams> gr_stream_to_streams_sptr; + +GR_CORE_API gr_stream_to_streams_sptr +gr_make_stream_to_streams (size_t item_size, size_t nstreams); + + +/*! + * \brief convert a stream of items into a N streams of items + * \ingroup slicedice_blk + * + * Converts a stream of N items into N streams of 1 item. + * Repeat ad infinitum. + */ +class GR_CORE_API gr_stream_to_streams : public gr_sync_decimator +{ + friend GR_CORE_API gr_stream_to_streams_sptr + gr_make_stream_to_streams (size_t item_size, size_t nstreams); + + protected: + gr_stream_to_streams (size_t item_size, size_t nstreams); + + public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_STREAM_TO_STREAMS_H */ diff --git a/gnuradio-core/src/lib/general/gr_stream_to_streams.i b/gnuradio-core/src/lib/general/gr_stream_to_streams.i new file mode 100644 index 000000000..4d324372e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_stream_to_streams.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,stream_to_streams) + +gr_stream_to_streams_sptr +gr_make_stream_to_streams (size_t itemsize, size_t nstreams); + +class gr_stream_to_streams : public gr_sync_decimator +{ + protected: + gr_stream_to_streams (size_t itemsize, size_t nstreams); + + public: +}; diff --git a/gnuradio-core/src/lib/general/gr_stream_to_vector.cc b/gnuradio-core/src/lib/general/gr_stream_to_vector.cc new file mode 100644 index 000000000..d38cdd434 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_stream_to_vector.cc @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005,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_stream_to_vector.h> +#include <gr_io_signature.h> +#include <string.h> + +gr_stream_to_vector_sptr +gr_make_stream_to_vector (size_t item_size, size_t nitems_per_block) +{ + return gnuradio::get_initial_sptr(new gr_stream_to_vector (item_size, nitems_per_block)); +} + +gr_stream_to_vector::gr_stream_to_vector (size_t item_size, size_t nitems_per_block) + : gr_sync_decimator ("stream_to_vector", + gr_make_io_signature (1, 1, item_size), + gr_make_io_signature (1, 1, item_size * nitems_per_block), + nitems_per_block) +{ +} + +int +gr_stream_to_vector::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + size_t block_size = output_signature()->sizeof_stream_item (0); + + const char *in = (const char *) input_items[0]; + char *out = (char *) output_items[0]; + + memcpy (out, in, noutput_items * block_size); + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_stream_to_vector.h b/gnuradio-core/src/lib/general/gr_stream_to_vector.h new file mode 100644 index 000000000..362349965 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_stream_to_vector.h @@ -0,0 +1,55 @@ +/* -*- 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. + */ + +#ifndef INCLUDED_GR_STREAM_TO_VECTOR_H +#define INCLUDED_GR_STREAM_TO_VECTOR_H + +#include <gr_core_api.h> +#include <gr_sync_decimator.h> + +class gr_stream_to_vector; +typedef boost::shared_ptr<gr_stream_to_vector> gr_stream_to_vector_sptr; + +GR_CORE_API gr_stream_to_vector_sptr +gr_make_stream_to_vector (size_t item_size, size_t nitems_per_block); + + +/*! + * \brief convert a stream of items into a stream of blocks containing nitems_per_block + * \ingroup slicedice_blk + */ +class GR_CORE_API gr_stream_to_vector : public gr_sync_decimator +{ + friend GR_CORE_API gr_stream_to_vector_sptr + gr_make_stream_to_vector (size_t item_size, size_t nitems_per_block); + + protected: + gr_stream_to_vector (size_t item_size, size_t nitems_per_block); + + public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_STREAM_TO_VECTOR_H */ diff --git a/gnuradio-core/src/lib/general/gr_stream_to_vector.i b/gnuradio-core/src/lib/general/gr_stream_to_vector.i new file mode 100644 index 000000000..ef867012a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_stream_to_vector.i @@ -0,0 +1,34 @@ +/* -*- 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,stream_to_vector) + +gr_stream_to_vector_sptr +gr_make_stream_to_vector (size_t itemsize, size_t nitems_per_block); + +class gr_stream_to_vector : public gr_sync_decimator +{ + protected: + gr_stream_to_vector (size_t itemsize, size_t nitems_per_block); + + public: +}; diff --git a/gnuradio-core/src/lib/general/gr_streams_to_stream.cc b/gnuradio-core/src/lib/general/gr_streams_to_stream.cc new file mode 100644 index 000000000..8bce74722 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_streams_to_stream.cc @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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_streams_to_stream.h> +#include <gr_io_signature.h> +#include <string.h> + +gr_streams_to_stream_sptr +gr_make_streams_to_stream (size_t item_size, size_t nstreams) +{ + return gnuradio::get_initial_sptr(new gr_streams_to_stream (item_size, nstreams)); +} + +gr_streams_to_stream::gr_streams_to_stream (size_t item_size, size_t nstreams) + : gr_sync_interpolator ("streams_to_stream", + gr_make_io_signature (nstreams, nstreams, item_size), + gr_make_io_signature (1, 1, item_size), + nstreams) +{ +} + +int +gr_streams_to_stream::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + size_t item_size = output_signature()->sizeof_stream_item (0); + + const char **inv = (const char **) &input_items[0]; + char *out = (char *) output_items[0]; + int nstreams = input_items.size(); + + assert (noutput_items % nstreams == 0); + int ni = noutput_items / nstreams; + + for (int i = 0; i < ni; i++){ + for (int j = 0; j < nstreams; j++){ + memcpy(out, inv[j], item_size); + out += item_size; + inv[j] += item_size; + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_streams_to_stream.h b/gnuradio-core/src/lib/general/gr_streams_to_stream.h new file mode 100644 index 000000000..f63683767 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_streams_to_stream.h @@ -0,0 +1,56 @@ +/* -*- 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_STREAMS_TO_STREAM_H +#define INCLUDED_GR_STREAMS_TO_STREAM_H + +#include <gr_core_api.h> +#include <gr_sync_interpolator.h> + +class gr_streams_to_stream; +typedef boost::shared_ptr<gr_streams_to_stream> gr_streams_to_stream_sptr; + +GR_CORE_API gr_streams_to_stream_sptr +gr_make_streams_to_stream (size_t item_size, size_t nstreams); + + +/*! + * \brief Convert N streams of 1 item into a 1 stream of N items + * \ingroup slicedice_blk + * + * Convert N streams of 1 item into 1 stream of N items. + * Repeat ad infinitum. + */ +class GR_CORE_API gr_streams_to_stream : public gr_sync_interpolator +{ + friend GR_CORE_API gr_streams_to_stream_sptr + gr_make_streams_to_stream (size_t item_size, size_t nstreams); + + protected: + gr_streams_to_stream (size_t item_size, size_t nstreams); + + public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_STREAMS_TO_STREAM_H */ diff --git a/gnuradio-core/src/lib/general/gr_streams_to_stream.i b/gnuradio-core/src/lib/general/gr_streams_to_stream.i new file mode 100644 index 000000000..a09ded071 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_streams_to_stream.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,streams_to_stream) + +gr_streams_to_stream_sptr +gr_make_streams_to_stream (size_t itemsize, size_t nstreams); + +class gr_streams_to_stream : public gr_sync_interpolator +{ + protected: + gr_streams_to_stream (size_t itemsize, size_t nstreams); + + public: +}; diff --git a/gnuradio-core/src/lib/general/gr_streams_to_vector.cc b/gnuradio-core/src/lib/general/gr_streams_to_vector.cc new file mode 100644 index 000000000..cf862ca95 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_streams_to_vector.cc @@ -0,0 +1,64 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005,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_streams_to_vector.h> +#include <gr_io_signature.h> +#include <string.h> + +gr_streams_to_vector_sptr +gr_make_streams_to_vector (size_t item_size, size_t nstreams) +{ + return gnuradio::get_initial_sptr(new gr_streams_to_vector (item_size, nstreams)); +} + +gr_streams_to_vector::gr_streams_to_vector (size_t item_size, size_t nstreams) + : gr_sync_block ("streams_to_vector", + gr_make_io_signature (nstreams, nstreams, item_size), + gr_make_io_signature (1, 1, nstreams * item_size)) +{ +} + +int +gr_streams_to_vector::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + size_t item_size = input_signature()->sizeof_stream_item(0); + int nstreams = input_items.size(); + + const char **inv = (const char **) &input_items[0]; + char *out = (char *) output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + for (int j = 0; j < nstreams; j++){ + memcpy(out, inv[j], item_size); + inv[j] += item_size; + out += item_size; + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_streams_to_vector.h b/gnuradio-core/src/lib/general/gr_streams_to_vector.h new file mode 100644 index 000000000..1df289099 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_streams_to_vector.h @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_STREAMS_TO_VECTOR_H +#define INCLUDED_GR_STREAMS_TO_VECTOR_H + +#include <gr_core_api.h> +#include <gr_sync_interpolator.h> + +class gr_streams_to_vector; +typedef boost::shared_ptr<gr_streams_to_vector> gr_streams_to_vector_sptr; + +GR_CORE_API gr_streams_to_vector_sptr +gr_make_streams_to_vector (size_t item_size, size_t nstreams); + + +/*! + * \brief convert N streams of items to 1 stream of vector length N + * \ingroup slicedice_blk + */ +class GR_CORE_API gr_streams_to_vector : public gr_sync_block +{ + friend GR_CORE_API gr_streams_to_vector_sptr + gr_make_streams_to_vector (size_t item_size, size_t nstreams); + + protected: + gr_streams_to_vector (size_t item_size, size_t nstreams); + + public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_STREAMS_TO_VECTOR_H */ diff --git a/gnuradio-core/src/lib/general/gr_streams_to_vector.i b/gnuradio-core/src/lib/general/gr_streams_to_vector.i new file mode 100644 index 000000000..4d5eca45e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_streams_to_vector.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,streams_to_vector) + +gr_streams_to_vector_sptr +gr_make_streams_to_vector (size_t itemsize, size_t nstreams); + +class gr_streams_to_vector : public gr_sync_block +{ + protected: + gr_streams_to_vector (size_t itemsize, size_t nstreams); + + public: +}; diff --git a/gnuradio-core/src/lib/general/gr_stretch_ff.cc b/gnuradio-core/src/lib/general/gr_stretch_ff.cc new file mode 100644 index 000000000..e89eadf8b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_stretch_ff.cc @@ -0,0 +1,74 @@ +/* -*- 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_stretch_ff.h> +#include <gr_io_signature.h> + +gr_stretch_ff_sptr +gr_make_stretch_ff(float lo, size_t vlen) +{ + return gnuradio::get_initial_sptr(new gr_stretch_ff(lo, vlen)); +} + +gr_stretch_ff::gr_stretch_ff(float lo, size_t vlen) + : gr_sync_block("stretch_ff", + gr_make_io_signature(1, 1, vlen * sizeof(float)), + gr_make_io_signature(1, 1, vlen * sizeof(float))), + d_lo(lo), d_vlen(vlen) +{ +} + +int +gr_stretch_ff::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++) { + float vmax = in[0] - d_lo; + + for (unsigned int i = 1; i < d_vlen; i++) { + float vtmp = in[i] - d_lo; + if (vtmp > vmax) + vmax = vtmp; + } + + if (vmax != 0.0) + for (unsigned int i = 0; i < d_vlen; i++) + out[i] = d_lo * (1.0 - (in[i] - d_lo) / vmax); + else + for (unsigned int i = 0; i < d_vlen; i++) + out[i] = in[i]; + + in += d_vlen; + out += d_vlen; + } + + return noutput_items; +} + diff --git a/gnuradio-core/src/lib/general/gr_stretch_ff.h b/gnuradio-core/src/lib/general/gr_stretch_ff.h new file mode 100644 index 000000000..f592c94a7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_stretch_ff.h @@ -0,0 +1,60 @@ +/* -*- 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_STRETCH_FF_H_ +# define INCLUDED_GR_STRETCH_FF_H_ + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +/*! + * \brief adjust y-range of an input vector by mapping to range + * (max-of-input, stipulated-min). Primarily for spectral signature + * matching by normalizing spectrum dynamic ranges. + * \ingroup misc_blk + */ + + +class gr_stretch_ff; +typedef boost::shared_ptr<gr_stretch_ff> gr_stretch_ff_sptr; + +GR_CORE_API gr_stretch_ff_sptr gr_make_stretch_ff(float lo, size_t vlen); + +class GR_CORE_API gr_stretch_ff : public gr_sync_block +{ + friend GR_CORE_API gr_stretch_ff_sptr gr_make_stretch_ff(float lo, size_t vlen); + + float d_lo; // the constant + size_t d_vlen; + gr_stretch_ff(float lo, size_t vlen); + + public: + float lo() const { return d_lo; } + void set_lo(float lo) { d_lo = lo; } + size_t vlen() const { return d_vlen; } + + 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_stretch_ff.i b/gnuradio-core/src/lib/general/gr_stretch_ff.i new file mode 100644 index 000000000..81366655e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_stretch_ff.i @@ -0,0 +1,31 @@ +/* -*- 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,stretch_ff); + +gr_stretch_ff_sptr gr_make_stretch_ff(float lo, size_t vlen); + +class gr_stretch_ff : public gr_sync_block +{ +private: + gr_stretch_ff(float lo, size_t vlen); +}; + diff --git a/gnuradio-core/src/lib/general/gr_tag_debug.cc b/gnuradio-core/src/lib/general/gr_tag_debug.cc new file mode 100644 index 000000000..ecf1b65e1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_tag_debug.cc @@ -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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_tag_debug.h> +#include <gr_io_signature.h> +#include <iostream> +#include <iomanip> + +gr_tag_debug_sptr +gr_make_tag_debug(size_t sizeof_stream_item, const std::string &name) +{ + return gnuradio::get_initial_sptr + (new gr_tag_debug(sizeof_stream_item, name)); +} + +gr_tag_debug::gr_tag_debug(size_t sizeof_stream_item, const std::string &name) + : gr_sync_block("tag_debug", + gr_make_io_signature(1, -1, sizeof_stream_item), + gr_make_io_signature(0, 0, 0)), + d_name(name), d_display(true) +{ +} + +std::vector<gr_tag_t> +gr_tag_debug::current_tags() +{ + gruel::scoped_lock l(d_mutex); + return d_tags; +} + +void +gr_tag_debug::set_display(bool d) +{ + gruel::scoped_lock l(d_mutex); + d_display = d; +} + +int +gr_tag_debug::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gruel::scoped_lock l(d_mutex); + + std::stringstream sout; + if(d_display) { + sout << std::endl + << "----------------------------------------------------------------------"; + sout << std::endl << "Tag Debug: " << d_name << std::endl; + } + + uint64_t abs_N, end_N; + for(size_t i = 0; i < input_items.size(); i++) { + abs_N = nitems_read(i); + end_N = abs_N + (uint64_t)(noutput_items); + + d_tags.clear(); + get_tags_in_range(d_tags, i, abs_N, end_N); + + if(d_display) { + sout << "Input Stream: " << std::setw(2) << std::setfill('0') << i << std::setfill(' ') << std::endl; + for(d_tags_itr = d_tags.begin(); d_tags_itr != d_tags.end(); d_tags_itr++) { + sout << std::setw(10) << "Offset: " << d_tags_itr->offset + << std::setw(10) << "Source: " << (pmt::pmt_is_symbol(d_tags_itr->srcid) ? pmt::pmt_symbol_to_string(d_tags_itr->srcid) : "n/a") + << std::setw(10) << "Key: " << pmt::pmt_symbol_to_string(d_tags_itr->key) + << std::setw(10) << "Value: "; + sout << d_tags_itr->value << std::endl; + } + } + } + + if(d_display) { + sout << "----------------------------------------------------------------------"; + sout << std::endl; + + if(d_tags.size() > 0) + std::cout << sout.str(); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_tag_debug.h b/gnuradio-core/src/lib/general/gr_tag_debug.h new file mode 100644 index 000000000..57578884a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_tag_debug.h @@ -0,0 +1,85 @@ +/* -*- 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_GR_TAG_DEBUG_H +#define INCLUDED_GR_TAG_DEBUG_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gruel/thread.h> +#include <stddef.h> + +class gr_tag_debug; +typedef boost::shared_ptr<gr_tag_debug> gr_tag_debug_sptr; + +GR_CORE_API gr_tag_debug_sptr +gr_make_tag_debug(size_t sizeof_stream_item, const std::string &name); + +/*! + * \brief Bit bucket that prints out any tag received. + * \ingroup sink_blk + * + * This block collects all tags sent to it on all input ports and + * displays them to stdout in a formatted way. The \p name parameter + * is used to identify which debug sink generated the tag, so when + * connecting a block to this debug sink, an appropriate name is + * something that identifies the input block. + * + * This block otherwise acts as a NULL sink in that items from the + * input stream are ignored. It is designed to be able to attach to + * any block and watch all tags streaming out of that block for + * debugging purposes. + * + * The tags from the last call to this work function are stored and + * can be retrieved using the function 'current_tags'. + */ +class GR_CORE_API gr_tag_debug : public gr_sync_block +{ + private: + friend GR_CORE_API gr_tag_debug_sptr + gr_make_tag_debug(size_t sizeof_stream_item, const std::string &name); + gr_tag_debug(size_t sizeof_stream_item, const std::string &name); + + std::string d_name; + std::vector<gr_tag_t> d_tags; + std::vector<gr_tag_t>::iterator d_tags_itr; + bool d_display; + gruel::mutex d_mutex; + + public: + /*! + * \brief Returns a vector of gr_tag_t items as of the last call to + * work. + */ + std::vector<gr_tag_t> current_tags(); + + /*! + * \brief Set the display of tags to stdout on/off. + */ + void set_display(bool d); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_TAG_DEBUG_H */ diff --git a/gnuradio-core/src/lib/general/gr_tag_debug.i b/gnuradio-core/src/lib/general/gr_tag_debug.i new file mode 100644 index 000000000..3af1bdcfe --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_tag_debug.i @@ -0,0 +1,35 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,tag_debug) + +%include <gr_tags.i> + +gr_tag_debug_sptr +gr_make_tag_debug(size_t sizeof_stream_item, const std::string &name); + +class gr_tag_debug : public gr_sync_block +{ +public: + std::vector<gr_tag_t> current_tags(); + void set_display(bool d); +}; diff --git a/gnuradio-core/src/lib/general/gr_test.cc b/gnuradio-core/src/lib/general/gr_test.cc new file mode 100644 index 000000000..cd5ef8361 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_test.cc @@ -0,0 +1,177 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,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_test.h> +#include <gr_io_signature.h> +#include <stdexcept> +#include <iostream> +#include <string.h> + +gr_test_sptr gr_make_test (const std::string &name, + int min_inputs, int max_inputs, unsigned int sizeof_input_item, + int min_outputs, int max_outputs, unsigned int sizeof_output_item, + unsigned int history,unsigned int output_multiple,double relative_rate, + bool fixed_rate,gr_consume_type_t cons_type, gr_produce_type_t prod_type) +{ + return gnuradio::get_initial_sptr(new gr_test (name, min_inputs,max_inputs,sizeof_input_item, + min_outputs,max_outputs,sizeof_output_item, + history,output_multiple,relative_rate,fixed_rate,cons_type, prod_type)); +} + + gr_test::gr_test (const std::string &name,int min_inputs, int max_inputs, unsigned int sizeof_input_item, + int min_outputs, int max_outputs, unsigned int sizeof_output_item, + unsigned int history,unsigned int output_multiple,double relative_rate, + bool fixed_rate,gr_consume_type_t cons_type, gr_produce_type_t prod_type): gr_block (name, + gr_make_io_signature (min_inputs, max_inputs, sizeof_input_item), + gr_make_io_signature (min_outputs, max_outputs, sizeof_output_item)), + d_sizeof_input_item(sizeof_input_item), + d_sizeof_output_item(sizeof_output_item), + d_check_topology(true), + d_consume_type(cons_type), + d_min_consume(0), + d_max_consume(0), + d_produce_type(prod_type), + d_min_produce(0), + d_max_produce(0) + { + set_history(history); + set_output_multiple(output_multiple); + set_relative_rate(relative_rate); + set_fixed_rate(fixed_rate); + } + +int +gr_test::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + //touch all inputs and outputs to detect segfaults + unsigned ninputs = input_items.size (); + unsigned noutputs= output_items.size(); + for (unsigned i = 0; i < ninputs; i++) + { + char * in=(char *)input_items[i]; + if (ninput_items[i]< (int)(noutput_items+history())) + { + std::cerr << "ERROR: ninput_items[" << i << "] < noutput_items+history()" << std::endl; + std::cerr << "ninput_items[" << i << "] = " << ninput_items[i] << std::endl; + std::cerr << "noutput_items+history() = " << noutput_items+history() << std::endl; + std::cerr << "noutput_items = " << noutput_items << std::endl; + std::cerr << "history() = " << history() << std::endl; + throw std::runtime_error ("gr_test"); + } else + { + for (int j=0;j<ninput_items[i];j++) + { + //Touch every available input_item + //We use a class variable to avoid the compiler to optimize this away + for(unsigned int k=0;k<d_sizeof_input_item;k++) + d_temp= in[j*d_sizeof_input_item+k]; + } + switch (d_consume_type) + { + case CONSUME_NOUTPUT_ITEMS: + consume(i,noutput_items); + break; + case CONSUME_NOUTPUT_ITEMS_LIMIT_MAX: + consume(i,std::min(noutput_items,d_max_consume)); + break; + case CONSUME_NOUTPUT_ITEMS_LIMIT_MIN: + consume(i,std::min(std::max(noutput_items,d_min_consume),ninput_items[i])); + break; + case CONSUME_ALL_AVAILABLE: + consume(i,ninput_items[i]); + break; + case CONSUME_ALL_AVAILABLE_LIMIT_MAX: + consume(i,std::min(ninput_items[i],d_max_consume)); + break; +/* //This could result in segfault, uncomment if you want to test this + case CONSUME_ALL_AVAILABLE_LIMIT_MIN: + consume(i,std::max(ninput_items[i],d_max_consume)); + break;*/ + case CONSUME_ZERO: + consume(i,0); + break; + case CONSUME_ONE: + consume(i,1); + break; + case CONSUME_MINUS_ONE: + consume(i,-1); + break; + default: + consume(i,noutput_items); + } + } + } + for (unsigned i = 0; i < noutputs; i++) + { + char * out=(char *)output_items[i]; + { + for (int j=0;j<noutput_items;j++) + { + //Touch every available output_item + for(unsigned int k=0;k<d_sizeof_output_item;k++) + out[j*d_sizeof_input_item+k]=0; + } + } + } + //Now copy input to output until max ninputs or max noutputs is reached + int common_nports=std::min(ninputs,noutputs); + if(d_sizeof_output_item==d_sizeof_input_item) + for (int i = 0; i < common_nports; i++) + { + memcpy(output_items[i],input_items[i],noutput_items*d_sizeof_input_item); + } + int noutput_items_produced=0; + switch (d_produce_type){ + case PRODUCE_NOUTPUT_ITEMS: + noutput_items_produced=noutput_items; + break; + case PRODUCE_NOUTPUT_ITEMS_LIMIT_MAX: + noutput_items_produced=std::min(noutput_items,d_max_produce); + break; +/* //This could result in segfault, uncomment if you want to test this + case PRODUCE_NOUTPUT_ITEMS_LIMIT_MIN: + noutput_items_produced=std::max(noutput_items,d_min_produce); + break;*/ + case PRODUCE_ZERO: + noutput_items_produced=0; + break; + case PRODUCE_ONE: + noutput_items_produced=1; + break; + case PRODUCE_MINUS_ONE: + noutput_items_produced=-1; + break; + default: + noutput_items_produced=noutput_items; + } + return noutput_items_produced; + } + + + diff --git a/gnuradio-core/src/lib/general/gr_test.h b/gnuradio-core/src/lib/general/gr_test.h new file mode 100644 index 000000000..caeba4c51 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_test.h @@ -0,0 +1,195 @@ +/* -*- 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_TEST_H +#define INCLUDED_GR_TEST_H + +#include <gr_core_api.h> +#include <gr_block.h> +#include <string> +#include "gr_test_types.h" + +class gr_test; +typedef boost::shared_ptr<gr_test> gr_test_sptr; + +// public constructor +GR_CORE_API gr_test_sptr gr_make_test (const std::string &name=std::string("gr_test"), + int min_inputs=1, int max_inputs=1, unsigned int sizeof_input_item=1, + int min_outputs=1, int max_outputs=1, unsigned int sizeof_output_item=1, + unsigned int history=1,unsigned int output_multiple=1,double relative_rate=1.0, + bool fixed_rate=true,gr_consume_type_t cons_type=CONSUME_NOUTPUT_ITEMS, gr_produce_type_t prod_type=PRODUCE_NOUTPUT_ITEMS); + +/*! + * \brief Test class for testing runtime system (setting up buffers and such.) + * \ingroup misc + * + * This block does not do any usefull actual data processing. + * It just exposes setting all standard block parameters using the contructor or public methods. + * + * This block can be usefull when testing the runtime system. + * You can force this block to have a large history, decimation + * factor and/or large output_multiple. + * The runtime system should detect this and create large enough buffers + * all through the signal chain. + */ +class GR_CORE_API gr_test : public gr_block { + + public: + + ~gr_test (){} + +int general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + // ---------------------------------------------------------------- + // override these to define your behavior + // ---------------------------------------------------------------- + + /*! + * \brief Estimate input requirements given output request + * + * \param noutput_items number of output items to produce + * \param ninput_items_required number of input items required on each input stream + * + * Given a request to product \p noutput_items, estimate the number of + * data items required on each input stream. The estimate doesn't have + * to be exact, but should be close. + */ + void forecast (int noutput_items, + gr_vector_int &ninput_items_required) + { + unsigned ninputs = ninput_items_required.size (); + for (unsigned i = 0; i < ninputs; i++) + ninput_items_required[i] = (int)((double)noutput_items / relative_rate()) + (int)history(); + } + + + /*! + * \brief Force check topology to return true or false. + * + * \param check_topology value to return when check_topology is called (true or false) + * default check_topology returns true + * + */ + void set_check_topology (bool check_topology){ d_check_topology=check_topology;} + + /*! + * \brief Confirm that ninputs and noutputs is an acceptable combination. + * + * \param ninputs number of input streams connected + * \param noutputs number of output streams connected + * + * \returns true if this is a valid configuration for this block. + * + * This function is called by the runtime system whenever the + * topology changes. Most classes do not need to override this. + * This check is in addition to the constraints specified by the input + * and output gr_io_signatures. + */ + bool check_topology (int ninputs, int noutputs) { return d_check_topology;} + + // ---------------------------------------------------------------- + /* + * The following two methods provide special case info to the + * scheduler in the event that a block has a fixed input to output + * ratio. gr_sync_block, gr_sync_decimator and gr_sync_interpolator + * override these. If you're fixed rate, subclass one of those. + */ + /*! + * \brief Given ninput samples, return number of output samples that will be produced. + * N.B. this is only defined if fixed_rate returns true. + * Generally speaking, you don't need to override this. + */ + int fixed_rate_ninput_to_noutput(int ninput) { return (int)((double)ninput/relative_rate()); } + + /*! + * \brief Given noutput samples, return number of input samples required to produce noutput. + * N.B. this is only defined if fixed_rate returns true. + */ + int fixed_rate_noutput_to_ninput(int noutput) { return (int)((double)noutput*relative_rate()); } + + /*! + * \brief Set if fixed rate should return true. + * N.B. This is normally a private method but we make it available here as public. + */ + void set_fixed_rate_public(bool fixed_rate){ set_fixed_rate(fixed_rate);} + + /*! + * \brief Set the consume pattern. + * + * \param cons_type which consume pattern to use + */ + void set_consume_type (gr_consume_type_t cons_type) { d_consume_type=cons_type;} + + /*! + * \brief Set the consume limit. + * + * \param limit min or maximum items to consume (depending on consume_type) + */ + void set_consume_limit (unsigned int limit) { d_min_consume=limit; d_max_consume=limit;} + + /*! + * \brief Set the produce pattern. + * + * \param prod_type which produce pattern to use + */ + void set_produce_type (gr_produce_type_t prod_type) { d_produce_type=prod_type;} + + /*! + * \brief Set the produce limit. + * + * \param limit min or maximum items to produce (depending on produce_type) + */ + void set_produce_limit (unsigned int limit) { d_min_produce=limit; d_max_produce=limit;} + + // ---------------------------------------------------------------------------- + + + + protected: + unsigned int d_sizeof_input_item; + unsigned int d_sizeof_output_item; + bool d_check_topology; + char d_temp; + gr_consume_type_t d_consume_type; + int d_min_consume; + int d_max_consume; + gr_produce_type_t d_produce_type; + int d_min_produce; + int d_max_produce; + gr_test (const std::string &name,int min_inputs, int max_inputs, unsigned int sizeof_input_item, + int min_outputs, int max_outputs, unsigned int sizeof_output_item, + unsigned int history,unsigned int output_multiple,double relative_rate, + bool fixed_rate,gr_consume_type_t cons_type, gr_produce_type_t prod_type); + + + + friend GR_CORE_API gr_test_sptr gr_make_test (const std::string &name,int min_inputs, int max_inputs, unsigned int sizeof_input_item, + int min_outputs, int max_outputs, unsigned int sizeof_output_item, + unsigned int history,unsigned int output_multiple,double relative_rate, + bool fixed_rate,gr_consume_type_t cons_type, gr_produce_type_t prod_type); +}; + + + +#endif /* INCLUDED_GR_TEST_H */ diff --git a/gnuradio-core/src/lib/general/gr_test.i b/gnuradio-core/src/lib/general/gr_test.i new file mode 100644 index 000000000..d81025011 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_test.i @@ -0,0 +1,64 @@ +/* -*- 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,test); + + +class gr_test; +typedef boost::shared_ptr<gr_test> gr_test_sptr; + + +// public constructor +gr_test_sptr gr_make_test (const std::string &name=std::string("gr_test"), + int min_inputs=1, int max_inputs=1, unsigned int sizeof_input_item=1, + int min_outputs=1, int max_outputs=1, unsigned int sizeof_output_item=1, + unsigned int history=1,unsigned int output_multiple=1,double relative_rate=1.0, + bool fixed_rate=true,gr_consume_type_t cons_type=CONSUME_NOUTPUT_ITEMS, gr_produce_type_t prod_type=PRODUCE_NOUTPUT_ITEMS); + + +class gr_test : public gr_block { + + public: + + ~gr_test (); + void forecast (int noutput_items, + gr_vector_int &ninput_items_required); + void set_check_topology (bool check_topology); + bool check_topology (int ninputs, int noutputs); + int fixed_rate_ninput_to_noutput(int ninput); + int fixed_rate_noutput_to_ninput(int noutput); + void set_fixed_rate_public(bool fixed_rate); + void set_consume_type (gr_consume_type_t cons_type); + void set_consume_limit (unsigned int limit); + void set_produce_type (gr_produce_type_t prod_type); + void set_produce_limit (unsigned int limit); + + protected: + gr_test (const std::string &name,int min_inputs, int max_inputs, unsigned int sizeof_input_item, + int min_outputs, int max_outputs, unsigned int sizeof_output_item, + unsigned int history,unsigned int output_multiple,double relative_rate, + bool fixed_rate,gr_consume_type_t cons_type, gr_produce_type_t prod_type); + +}; + + + diff --git a/gnuradio-core/src/lib/general/gr_test_types.h b/gnuradio-core/src/lib/general/gr_test_types.h new file mode 100644 index 000000000..04f38f7b2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_test_types.h @@ -0,0 +1,46 @@ +/* -*- 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_TEST_TYPES_H +#define INCLUDED_GR_TEST_TYPES_H + +typedef enum { + CONSUME_NOUTPUT_ITEMS=0, + CONSUME_NOUTPUT_ITEMS_LIMIT_MAX=1, + CONSUME_NOUTPUT_ITEMS_LIMIT_MIN=2, + CONSUME_ALL_AVAILABLE=3, + CONSUME_ALL_AVAILABLE_LIMIT_MAX=4, + /*CONSUME_ALL_AVAILABLE_LIMIT_MIN=5,*/ + CONSUME_ZERO=6, + CONSUME_ONE=7, + CONSUME_MINUS_ONE=8 + } gr_consume_type_t; + +typedef enum { + PRODUCE_NOUTPUT_ITEMS=0, + PRODUCE_NOUTPUT_ITEMS_LIMIT_MAX=1, + /*PRODUCE_NOUTPUT_ITEMS_LIMIT_MIN=2,*/ + PRODUCE_ZERO=6, + PRODUCE_ONE=7, + PRODUCE_MINUS_ONE=8 + } gr_produce_type_t; + +#endif /* INCLUDED_GR_TEST_TYPES_H */ diff --git a/gnuradio-core/src/lib/general/gr_threshold_ff.cc b/gnuradio-core/src/lib/general/gr_threshold_ff.cc new file mode 100644 index 000000000..952613151 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_threshold_ff.cc @@ -0,0 +1,67 @@ +/* -*- 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: this file is machine generated. Edits will be over written + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_threshold_ff.h> +#include <gr_io_signature.h> + +gr_threshold_ff_sptr +gr_make_threshold_ff (float lo, float hi, float initial_state) +{ + return gnuradio::get_initial_sptr(new gr_threshold_ff (lo, hi, initial_state)); +} + +gr_threshold_ff::gr_threshold_ff (float lo, float hi, float initial_state) + : gr_sync_block ("threshold_ff", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (float))), + d_lo (lo), d_hi (hi), d_last_state (initial_state) +{ +} + +int +gr_threshold_ff::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 i=0; i<noutput_items; i++) { + if (in[i] > d_hi) { + out[i] = 1.0; + d_last_state = 1.0; + } else if (in[i] < d_lo) { + out[i] = 0.0; + d_last_state = 0.0; + } else + out[i] = d_last_state; + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_threshold_ff.h b/gnuradio-core/src/lib/general/gr_threshold_ff.h new file mode 100644 index 000000000..678f8b1d2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_threshold_ff.h @@ -0,0 +1,59 @@ +/* -*- 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_THRESHOLD_FF_H +#define INCLUDED_GR_THRESHOLD_FF_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_threshold_ff; +typedef boost::shared_ptr<gr_threshold_ff> gr_threshold_ff_sptr; + +GR_CORE_API gr_threshold_ff_sptr gr_make_threshold_ff (float lo, float hi, float initial_state=0); + +/*! + * \brief Please fix my documentation + * \ingroup misc_blk + */ +class GR_CORE_API gr_threshold_ff : public gr_sync_block +{ + friend GR_CORE_API gr_threshold_ff_sptr gr_make_threshold_ff (float lo, float hi, float initial_state); + + float d_lo,d_hi; // the constant + float d_last_state; + gr_threshold_ff (float lo, float hi, float initial_state); + + public: + float lo () const { return d_lo; } + void set_lo (float lo) { d_lo = lo; } + float hi () const { return d_hi; } + void set_hi (float hi) { d_hi = hi; } + float last_state () const { return d_last_state; } + void set_last_state (float last_state) { d_last_state = last_state; } + + 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_threshold_ff.i b/gnuradio-core/src/lib/general/gr_threshold_ff.i new file mode 100644 index 000000000..7584feea8 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_threshold_ff.i @@ -0,0 +1,39 @@ +/* -*- 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,threshold_ff); + +gr_threshold_ff_sptr gr_make_threshold_ff (float lo, float hi, float initial_state=0); + +class gr_threshold_ff : public gr_sync_block +{ + private: + gr_threshold_ff (float lo, float hi, float initial_state); + + public: + float lo () const { return d_lo; } + void set_lo (float lo) { d_lo = lo; } + float hi () const { return d_hi; } + void set_hi (float hi) { d_hi = hi; } + float last_state () const { return d_last_state; } + void set_last_state (float last_state) { d_last_state = last_state; } +}; diff --git a/gnuradio-core/src/lib/general/gr_throttle.cc b/gnuradio-core/src/lib/general/gr_throttle.cc new file mode 100644 index 000000000..040ab5220 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_throttle.cc @@ -0,0 +1,89 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005-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_throttle.h> +#include <gr_io_signature.h> +#include <cstring> +#include <boost/thread/thread.hpp> + +class gr_throttle_impl : public gr_throttle{ +public: + gr_throttle_impl(size_t itemsize): + gr_sync_block("throttle", + gr_make_io_signature(1, 1, itemsize), + gr_make_io_signature(1, 1, itemsize)), + d_itemsize(itemsize) + { + /* NOP */ + } + + void set_sample_rate(double rate){ + //changing the sample rate performs a reset of state params + d_start = boost::get_system_time(); + d_total_samples = 0; + d_samps_per_tick = rate/boost::posix_time::time_duration::ticks_per_second(); + d_samps_per_us = rate/1e6; + } + + int work ( + int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items + ){ + //calculate the expected number of samples to have passed through + boost::system_time now = boost::get_system_time(); + boost::int64_t ticks = (now - d_start).ticks(); + uint64_t expected_samps = uint64_t(d_samps_per_tick*ticks); + + //if the expected samples was less, we need to throttle back + if (d_total_samples > expected_samps){ + boost::this_thread::sleep(boost::posix_time::microseconds( + long((d_total_samples - expected_samps)/d_samps_per_us) + )); + } + + //copy all samples output[i] <= input[i] + const char *in = (const char *) input_items[0]; + char *out = (char *) output_items[0]; + std::memcpy(out, in, noutput_items * d_itemsize); + d_total_samples += noutput_items; + return noutput_items; + } + +private: + boost::system_time d_start; + size_t d_itemsize; + uint64_t d_total_samples; + double d_samps_per_tick, d_samps_per_us; +}; + +gr_throttle::sptr +gr_make_throttle(size_t itemsize, double samples_per_sec) +{ + gr_throttle::sptr throttle(new gr_throttle_impl(itemsize)); + throttle->set_sample_rate(samples_per_sec); + return throttle; +} diff --git a/gnuradio-core/src/lib/general/gr_throttle.h b/gnuradio-core/src/lib/general/gr_throttle.h new file mode 100644 index 000000000..876d6d826 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_throttle.h @@ -0,0 +1,50 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005-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_THROTTLE_H +#define INCLUDED_GR_THROTTLE_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +/*! + * \brief throttle flow of samples such that the average rate does not exceed samples_per_sec. + * \ingroup misc_blk + * + * input: one stream of itemsize; output: one stream of itemsize + * + * N.B. this should only be used in GUI apps where there is no other + * rate limiting block. It is not intended nor effective at precisely + * controlling the rate of samples. That should be controlled by a + * source or sink tied to sample clock. E.g., a USRP or audio card. + */ +class GR_CORE_API gr_throttle : virtual public gr_sync_block +{ +public: + typedef boost::shared_ptr<gr_throttle> sptr; + + //! Sets the sample rate in samples per second + virtual void set_sample_rate(double rate) = 0; +}; + +GR_CORE_API gr_throttle::sptr gr_make_throttle(size_t itemsize, double samples_per_sec); + +#endif /* INCLUDED_GR_THROTTLE_H */ diff --git a/gnuradio-core/src/lib/general/gr_throttle.i b/gnuradio-core/src/lib/general/gr_throttle.i new file mode 100644 index 000000000..5ba32de6e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_throttle.i @@ -0,0 +1,29 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005-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 <gr_throttle.h> +%} + +GR_SWIG_BLOCK_MAGIC(gr,throttle); + +%include <gr_throttle.h> diff --git a/gnuradio-core/src/lib/general/gr_transcendental.cc b/gnuradio-core/src/lib/general/gr_transcendental.cc new file mode 100644 index 000000000..c1482491b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_transcendental.cc @@ -0,0 +1,153 @@ +/* + * 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 <gr_transcendental.h> +#include <gr_io_signature.h> +#include <stdexcept> +#include <complex> //complex math +#include <cmath> //real math +#include <map> + +/*********************************************************************** + * work function creation and registration + **********************************************************************/ +typedef int(*work_fcn_type)(int, gr_vector_const_void_star &, gr_vector_void_star &); +struct map_val_type{ + work_fcn_type work_fcn; + size_t io_size; +}; +typedef std::map<std::string, map_val_type> map_type; + +//construct map on first use idiom +static map_type &get_map(void){ + static map_type map; + return map; +} + +//static initialization of this object registers a function +struct gr_transcendental_registrant{ + gr_transcendental_registrant( + const std::string &key, + const work_fcn_type &work_fcn, + const size_t io_size + ){ + map_val_type val; + val.work_fcn = work_fcn; + val.io_size = io_size; + get_map()[key] = val; + } +}; + +//macro to create a work function and register it +#define REGISTER_FUNCTION(__fcn__, __type__, __key__) \ + static int __key__ ## _work( \ + int noutput_items, \ + gr_vector_const_void_star &input_items, \ + gr_vector_void_star &output_items \ + ){ \ + const __type__ *in = (const __type__ *) input_items[0]; \ + __type__ *out = (__type__ *) output_items[0]; \ + for (size_t i = 0; i < size_t(noutput_items); i++){ \ + out[i] = std::__fcn__(in[i]); \ + } \ + return noutput_items; \ + } \ + gr_transcendental_registrant __key__ ## _registrant(#__key__, &__key__ ## _work, sizeof(__type__)); + +//register work functions for real types +#define REGISTER_REAL_FUNCTIONS(__fcn__) \ + REGISTER_FUNCTION(__fcn__, float, __fcn__ ## _float) \ + REGISTER_FUNCTION(__fcn__, double, __fcn__ ## _double) + +//register work functions for complex types +#define REGISTER_COMPLEX_FUNCTIONS(__fcn__) \ + REGISTER_FUNCTION(__fcn__, std::complex<float>, __fcn__ ## _complex_float) \ + REGISTER_FUNCTION(__fcn__, std::complex<double>, __fcn__ ## _complex_double) + +//register both complex and real +#define REGISTER_FUNCTIONS(__fcn__) \ + REGISTER_REAL_FUNCTIONS(__fcn__) \ + REGISTER_COMPLEX_FUNCTIONS(__fcn__) + +//create and register transcendental work functions +REGISTER_FUNCTIONS(cos) +REGISTER_FUNCTIONS(sin) +REGISTER_FUNCTIONS(tan) +REGISTER_REAL_FUNCTIONS(acos) +REGISTER_REAL_FUNCTIONS(asin) +REGISTER_REAL_FUNCTIONS(atan) +REGISTER_FUNCTIONS(cosh) +REGISTER_FUNCTIONS(sinh) +REGISTER_FUNCTIONS(tanh) +REGISTER_FUNCTIONS(exp) +REGISTER_FUNCTIONS(log) +REGISTER_FUNCTIONS(log10) +REGISTER_FUNCTIONS(sqrt) + +/*********************************************************************** + * implementation block simply calls into the function pointer + **********************************************************************/ +class gr_transcendental_impl : public gr_transcendental{ +public: + gr_transcendental_impl( + const work_fcn_type &work_fcn, const size_t io_size + ): + gr_sync_block( + "transcendental", + gr_make_io_signature(1, 1, io_size), + gr_make_io_signature(1, 1, io_size) + ), + _work_fcn(work_fcn) + { + // NOP + } + + int work( + int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items + ){ + return _work_fcn(noutput_items, input_items, output_items); + } + +private: + const work_fcn_type &_work_fcn; +}; + +/*********************************************************************** + * factory function to make transcendental block + **********************************************************************/ +gr_transcendental::sptr gr_make_transcendental( + const std::string &name, + const std::string &type +){ + //search for an entry in the map + const std::string key = name + "_" + type; + const bool has_key = get_map().count(key) != 0; + if (!has_key) throw std::runtime_error( + "could not find transcendental function for " + key + ); + + //make a new block with found work function + return gr_transcendental::sptr(new gr_transcendental_impl( + get_map()[key].work_fcn, get_map()[key].io_size + )); +} diff --git a/gnuradio-core/src/lib/general/gr_transcendental.h b/gnuradio-core/src/lib/general/gr_transcendental.h new file mode 100644 index 000000000..9841a53e9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_transcendental.h @@ -0,0 +1,49 @@ +/* + * 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_GR_TRANSCENDENTAL_H +#define INCLUDED_GR_TRANSCENDENTAL_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <string> + +/*! + * \brief A block that performs various transcendental math operations. + * + * Possible function names can be found in the cmath library. + * IO may be either complex or real, double or single precision. + * + * Possible type strings: float, double, complex_float, complex_double + * + * output[i] = trans_fcn(input[i]) + */ +class GR_CORE_API gr_transcendental : virtual public gr_sync_block{ +public: + typedef boost::shared_ptr<gr_transcendental> sptr; +}; + +GR_CORE_API gr_transcendental::sptr gr_make_transcendental( + const std::string &name, + const std::string &type = "float" +); + +#endif /* INCLUDED_GR_TRANSCENDENTAL_H */ diff --git a/gnuradio-core/src/lib/general/gr_transcendental.i b/gnuradio-core/src/lib/general/gr_transcendental.i new file mode 100644 index 000000000..6acdb10b7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_transcendental.i @@ -0,0 +1,33 @@ +/* + * 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. + */ + +//////////////////////////////////////////////////////////////////////// +// block headers +//////////////////////////////////////////////////////////////////////// +%{ +#include <gr_transcendental.h> +%} + +//////////////////////////////////////////////////////////////////////// +// block magic +//////////////////////////////////////////////////////////////////////// +GR_SWIG_BLOCK_MAGIC(gr,transcendental) +%include <gr_transcendental.h> diff --git a/gnuradio-core/src/lib/general/gr_uchar_to_float.cc b/gnuradio-core/src/lib/general/gr_uchar_to_float.cc new file mode 100644 index 000000000..981a93440 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_uchar_to_float.cc @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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_uchar_to_float.h> +#include <gr_io_signature.h> +#include <gri_uchar_to_float.h> + +gr_uchar_to_float_sptr +gr_make_uchar_to_float () +{ + return gnuradio::get_initial_sptr(new gr_uchar_to_float ()); +} + +gr_uchar_to_float::gr_uchar_to_float () + : gr_sync_block ("gr_uchar_to_float", + gr_make_io_signature (1, 1, sizeof (unsigned char)), + gr_make_io_signature (1, 1, sizeof (float))) +{ +} + +int +gr_uchar_to_float::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]; + float *out = (float *) output_items[0]; + + gri_uchar_to_float (in, out, noutput_items); + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_uchar_to_float.h b/gnuradio-core/src/lib/general/gr_uchar_to_float.h new file mode 100644 index 000000000..c02601cca --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_uchar_to_float.h @@ -0,0 +1,52 @@ +/* -*- 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_UCHAR_TO_FLOAT_H +#define INCLUDED_GR_UCHAR_TO_FLOAT_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_uchar_to_float; +typedef boost::shared_ptr<gr_uchar_to_float> gr_uchar_to_float_sptr; + +GR_CORE_API gr_uchar_to_float_sptr +gr_make_uchar_to_float (); + +/*! + * \brief Convert stream of unsigned chars to a stream of float + * \ingroup converter_blk + */ + +class GR_CORE_API gr_uchar_to_float : public gr_sync_block +{ + friend GR_CORE_API gr_uchar_to_float_sptr gr_make_uchar_to_float (); + gr_uchar_to_float (); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_UCHAR_TO_FLOAT_H */ diff --git a/gnuradio-core/src/lib/general/gr_uchar_to_float.i b/gnuradio-core/src/lib/general/gr_uchar_to_float.i new file mode 100644 index 000000000..b6cc35329 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_uchar_to_float.i @@ -0,0 +1,30 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,uchar_to_float) + +gr_uchar_to_float_sptr gr_make_uchar_to_float (); + +class gr_uchar_to_float : public gr_sync_block +{ + gr_uchar_to_float (); +}; diff --git a/gnuradio-core/src/lib/general/gr_unpack_k_bits_bb.cc b/gnuradio-core/src/lib/general/gr_unpack_k_bits_bb.cc new file mode 100644 index 000000000..00b88e972 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_unpack_k_bits_bb.cc @@ -0,0 +1,70 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_unpack_k_bits_bb.h> +#include <gr_io_signature.h> +#include <stdexcept> +#include <iostream> + +gr_unpack_k_bits_bb_sptr gr_make_unpack_k_bits_bb (unsigned k) +{ + return gnuradio::get_initial_sptr(new gr_unpack_k_bits_bb (k)); +} + + +gr_unpack_k_bits_bb::gr_unpack_k_bits_bb (unsigned k) + : gr_sync_interpolator ("unpack_k_bits_bb", + gr_make_io_signature (1, 1, sizeof (unsigned char)), + gr_make_io_signature (1, 1, sizeof (unsigned char)), + k), + d_k (k) +{ + if (d_k == 0) + throw std::out_of_range ("interpolation must be > 0"); +} + +gr_unpack_k_bits_bb::~gr_unpack_k_bits_bb () +{ +} + +int +gr_unpack_k_bits_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]; + + int n = 0; + for (unsigned int i = 0; i < noutput_items/d_k; i++){ + unsigned int t = in[i]; + for (int j = d_k - 1; j >= 0; j--) + out[n++] = (t >> j) & 0x01; + } + + assert(n == noutput_items); + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_unpack_k_bits_bb.h b/gnuradio-core/src/lib/general/gr_unpack_k_bits_bb.h new file mode 100644 index 000000000..c3ea28d3f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_unpack_k_bits_bb.h @@ -0,0 +1,56 @@ +/* -*- 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_UNPACK_K_BITS_BB_H +#define INCLUDED_GR_UNPACK_K_BITS_BB_H + +#include <gr_core_api.h> +#include <gr_sync_interpolator.h> + +class gr_unpack_k_bits_bb; +typedef boost::shared_ptr<gr_unpack_k_bits_bb> gr_unpack_k_bits_bb_sptr; +GR_CORE_API gr_unpack_k_bits_bb_sptr gr_make_unpack_k_bits_bb (unsigned k); + +class gr_unpack_k_bits_bb; + +/*! + * \brief Converts a byte with k relevent bits to k output bytes with 1 bit in the LSB. + * \ingroup converter_blk + */ +class GR_CORE_API gr_unpack_k_bits_bb : public gr_sync_interpolator +{ + private: + friend GR_CORE_API gr_unpack_k_bits_bb_sptr gr_make_unpack_k_bits_bb (unsigned k); + + gr_unpack_k_bits_bb (unsigned k); + + unsigned d_k; // number of relevent bits to unpack into k output bytes + + public: + ~gr_unpack_k_bits_bb (); + + 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_unpack_k_bits_bb.i b/gnuradio-core/src/lib/general/gr_unpack_k_bits_bb.i new file mode 100644 index 000000000..de0f4b33e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_unpack_k_bits_bb.i @@ -0,0 +1,34 @@ +/* -*- 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,unpack_k_bits_bb) + +gr_unpack_k_bits_bb_sptr gr_make_unpack_k_bits_bb (int k) throw(std::exception); + +class gr_unpack_k_bits_bb : public gr_sync_interpolator +{ + private: + gr_unpack_k_bits_bb (int k); + + public: + ~gr_unpack_k_bits_bb (); +}; diff --git a/gnuradio-core/src/lib/general/gr_vco.h b/gnuradio-core/src/lib/general/gr_vco.h new file mode 100644 index 000000000..3ceaf15dd --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vco.h @@ -0,0 +1,94 @@ +/* -*- 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 _GR_VCO_H_ +#define _GR_VCO_H_ + + +#include <vector> +#include <gr_sincos.h> +#include <cmath> +#include <gr_complex.h> + +/*! + * \brief base class template for Voltage Controlled Oscillator (VCO) + * \ingroup misc + */ + +//FIXME Eventually generalize this to fixed point + +template<class o_type, class i_type> +class gr_vco { +public: + gr_vco () : d_phase (0) {} + + virtual ~gr_vco () {} + + // radians + void set_phase (double angle) { + d_phase = angle; + } + + void adjust_phase (double delta_phase) { + d_phase += delta_phase; + if (fabs (d_phase) > M_PI){ + + while (d_phase > M_PI) + d_phase -= 2*M_PI; + + while (d_phase < -M_PI) + d_phase += 2*M_PI; + } + } + + double get_phase () const { return d_phase; } + + // compute sin and cos for current phase angle + void sincos (float *sinx, float *cosx) const; + + // compute cos or sin for current phase angle + float cos () const { return std::cos (d_phase); } + float sin () const { return std::sin (d_phase); } + + // compute a block at a time + void cos (float *output, const float *input, int noutput_items, double k, double ampl = 1.0); + +protected: + double d_phase; +}; + +template<class o_type, class i_type> +void +gr_vco<o_type,i_type>::sincos (float *sinx, float *cosx) const +{ + gr_sincosf (d_phase, sinx, cosx); +} + +template<class o_type, class i_type> +void +gr_vco<o_type,i_type>::cos (float *output, const float *input, int noutput_items, double k, double ampl) +{ + for (int i = 0; i < noutput_items; i++){ + output[i] = cos() * ampl; + adjust_phase(input[i] * k); + } +} +#endif /* _GR_VCO_H_ */ diff --git a/gnuradio-core/src/lib/general/gr_vco_f.cc b/gnuradio-core/src/lib/general/gr_vco_f.cc new file mode 100644 index 000000000..0899bc77e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vco_f.cc @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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_vco_f.h> +#include <gr_io_signature.h> +#include <math.h> + +gr_vco_f_sptr +gr_make_vco_f(double sampling_rate, double sensitivity, double amplitude) +{ + return gnuradio::get_initial_sptr(new gr_vco_f(sampling_rate, sensitivity, amplitude)); +} + + +gr_vco_f::gr_vco_f(double sampling_rate, double sensitivity, double amplitude) + : gr_sync_block("vco_f", + gr_make_io_signature(1, 1, sizeof(float)), + gr_make_io_signature(1, 1, sizeof(float))), + d_sampling_rate(sampling_rate), d_sensitivity(sensitivity), d_amplitude(amplitude), + d_k(d_sensitivity/d_sampling_rate) +{ +} + +int +gr_vco_f::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *input = (const float *)input_items[0]; + float *output = (float *)output_items[0]; + + d_vco.cos(output, input, noutput_items, d_k, d_amplitude); + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_vco_f.h b/gnuradio-core/src/lib/general/gr_vco_f.h new file mode 100644 index 000000000..83f6a9773 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vco_f.h @@ -0,0 +1,75 @@ +/* -*- 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_VCO_F_H +#define INCLUDED_GR_VCO_F_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_fxpt_vco.h> + +/*! + * \brief VCO - Voltage controlled oscillator + * \ingroup misc + * + * \param sampling_rate sampling rate (Hz) + * \param sensitivity units are radians/sec/volt + * \param amplitude output amplitude + */ +class gr_vco_f; +typedef boost::shared_ptr<gr_vco_f> gr_vco_f_sptr; + + +GR_CORE_API gr_vco_f_sptr gr_make_vco_f(double sampling_rate, double sensitivity, double amplitude); + +/*! + * \brief VCO - Voltage controlled oscillator + * \ingroup modulator_blk + * + * input: float stream of control voltages; output: float oscillator output + */ +class GR_CORE_API gr_vco_f : public gr_sync_block +{ + friend GR_CORE_API gr_vco_f_sptr gr_make_vco_f(double sampling_rate, double sensitivity, double amplitude); + + /*! + * \brief VCO - Voltage controlled oscillator + * + * \param sampling_rate sampling rate (Hz) + * \param sensitivity units are radians/sec/volt + * \param amplitude output amplitude + */ + gr_vco_f(double sampling_rate, double sensitivity, double amplitude); + + double d_sampling_rate; + double d_sensitivity; + double d_amplitude; + double d_k; + gr_fxpt_vco d_vco; + +public: + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_VCO_F_H */ diff --git a/gnuradio-core/src/lib/general/gr_vco_f.i b/gnuradio-core/src/lib/general/gr_vco_f.i new file mode 100644 index 000000000..8ecf31411 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vco_f.i @@ -0,0 +1,38 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,vco_f); + +/*! + * \brief VCO - Voltage controlled oscillator + * + * \param sampling_rate sampling rate (Hz) + * \param sensitivity units are radians/sec/volt + * \param amplitude output amplitude + */ +gr_vco_f_sptr gr_make_vco_f(double sampling_rate, double sensitivity, double amplitude); + + +class gr_vco_f : public gr_sync_block { + private: + gr_vco_f(double sampling_rate, double sensitivity, double amplitude); +}; diff --git a/gnuradio-core/src/lib/general/gr_vector_map.cc b/gnuradio-core/src/lib/general/gr_vector_map.cc new file mode 100644 index 000000000..2a13efb06 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_map.cc @@ -0,0 +1,117 @@ +/* -*- 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 <gr_vector_map.h> +#include <gr_io_signature.h> +#include <string.h> + +std::vector<int> +get_in_sizeofs(size_t item_size, std::vector<size_t> in_vlens) +{ + std::vector<int> in_sizeofs; + for(unsigned int i = 0; i < in_vlens.size(); i++) { + in_sizeofs.push_back(in_vlens[i]*item_size); + } + return in_sizeofs; +} + +std::vector<int> +get_out_sizeofs(size_t item_size, + std::vector< std::vector< std::vector<size_t> > > mapping) +{ + std::vector<int> out_sizeofs; + for(unsigned int i = 0; i < mapping.size(); i++) { + out_sizeofs.push_back(mapping[i].size()*item_size); + } + return out_sizeofs; +} + +gr_vector_map_sptr +gr_make_vector_map (size_t item_size, std::vector<size_t> in_vlens, + std::vector< std::vector< std::vector<size_t> > > mapping) +{ + return gnuradio::get_initial_sptr(new gr_vector_map(item_size, + in_vlens, + mapping)); +} + +gr_vector_map::gr_vector_map(size_t item_size, std::vector<size_t> in_vlens, + std::vector< std::vector< std::vector<size_t> > > mapping) + : gr_sync_block("vector_map", + gr_make_io_signaturev(in_vlens.size(), in_vlens.size(), + get_in_sizeofs(item_size, in_vlens)), + gr_make_io_signaturev(mapping.size(), mapping.size(), + get_out_sizeofs(item_size, mapping))), + d_item_size(item_size), d_in_vlens(in_vlens) +{ + set_mapping(mapping); +} + +void +gr_vector_map::set_mapping(std::vector< std::vector< std::vector<size_t> > > mapping) { + // Make sure the contents of the mapping vectors are possible. + for(unsigned int i=0; i<mapping.size(); i++) { + for(unsigned int j=0; j<mapping[i].size(); j++) { + if(mapping[i][j].size() != 2) { + throw std::runtime_error("Mapping must be of the form (out_mapping_stream1, out_mapping_stream2, ...), where out_mapping_stream1 is of the form (mapping_element1, mapping_element2, ...), where mapping_element1 is of the form (input_stream, input_element). This error is raised because a mapping_element vector does not contain exactly 2 items."); + } + unsigned int s = mapping[i][j][0]; + unsigned int index = mapping[i][j][1]; + if(s >= d_in_vlens.size()) { + throw std::runtime_error("Stream numbers in mapping must be less than the number of input streams."); + } + if((index < 0) || (index >= d_in_vlens[s])) { + throw std::runtime_error ("Indices in mapping must be greater than 0 and less than the input vector lengths."); + } + } + } + gruel::scoped_lock guard(d_mutex); + d_mapping = mapping; +} + +int +gr_vector_map::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const char **inv = (const char **) &input_items[0]; + char **outv = (char **) &output_items[0]; + + for(unsigned int n = 0; n < (unsigned int)(noutput_items); n++) { + for(unsigned int i = 0; i < d_mapping.size(); i++) { + unsigned int out_vlen = d_mapping[i].size(); + for(unsigned int j = 0; j < out_vlen; j++) { + unsigned int s = d_mapping[i][j][0]; + unsigned int k = d_mapping[i][j][1]; + memcpy(outv[i] + out_vlen*d_item_size*n + + d_item_size*j, inv[s] + d_in_vlens[s]*d_item_size*n + + k*d_item_size, d_item_size); + } + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_vector_map.h b/gnuradio-core/src/lib/general/gr_vector_map.h new file mode 100644 index 000000000..f5492b1e3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_map.h @@ -0,0 +1,83 @@ +/* -*- 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_GR_VECTOR_MAP_H +#define INCLUDED_GR_VECTOR_MAP_H + +#include <vector> +#include <gr_core_api.h> +#include <gr_sync_interpolator.h> +#include <gruel/thread.h> + +class gr_vector_map; +typedef boost::shared_ptr<gr_vector_map> gr_vector_map_sptr; + +GR_CORE_API gr_vector_map_sptr +gr_make_vector_map (size_t item_size, std::vector<size_t> in_vlens, + std::vector< std::vector< std::vector<size_t> > > mapping); + +/*! + * \brief Maps elements from a set of input vectors to a set of output vectors. + * + * If in[i] is the input vector in the i'th stream then the output + * vector in the j'th stream is: + * + * out[j][k] = in[mapping[j][k][0]][mapping[j][k][1]] + * + * That is mapping is of the form (out_stream1_mapping, + * out_stream2_mapping, ...) and out_stream1_mapping is of the form + * (element1_mapping, element2_mapping, ...) and element1_mapping is + * of the form (in_stream, in_element). + * + * \param item_size (integer) size of vector elements + * + * \param in_vlens (vector of integers) number of elements in each + * input vector + * + * \param mapping (vector of vectors of vectors of integers) how to + * map elements from input to output vectors + * + * \ingroup slicedice_blk + */ +class GR_CORE_API gr_vector_map : public gr_sync_block +{ + friend GR_CORE_API gr_vector_map_sptr + gr_make_vector_map(size_t item_size, std::vector<size_t> in_vlens, + std::vector< std::vector< std::vector<size_t> > > mapping); + size_t d_item_size; + std::vector<size_t> d_in_vlens; + std::vector< std::vector< std::vector<size_t> > > d_mapping; + gruel::mutex d_mutex; // mutex to protect set/work access + + protected: + gr_vector_map(size_t item_size, std::vector<size_t> in_vlens, + std::vector< std::vector< std::vector<size_t> > > mapping); + + public: + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void set_mapping(std::vector< std::vector< std::vector<size_t> > > mapping); +}; + +#endif /* INCLUDED_GR_VECTOR_MAP_H */ diff --git a/gnuradio-core/src/lib/general/gr_vector_map.i b/gnuradio-core/src/lib/general/gr_vector_map.i new file mode 100644 index 000000000..e9fa3f27e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_map.i @@ -0,0 +1,28 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr, vector_map); + +%template() std::vector<size_t>; +%template() std::vector< std::vector< std::vector<size_t> > >; + +%include "gr_vector_map.h" diff --git a/gnuradio-core/src/lib/general/gr_vector_to_stream.cc b/gnuradio-core/src/lib/general/gr_vector_to_stream.cc new file mode 100644 index 000000000..621b7ec58 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_to_stream.cc @@ -0,0 +1,58 @@ +/* -*- 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_vector_to_stream.h> +#include <gr_io_signature.h> +#include <string.h> + +gr_vector_to_stream_sptr +gr_make_vector_to_stream (size_t item_size, size_t nitems_per_block) +{ + return gnuradio::get_initial_sptr(new gr_vector_to_stream (item_size, nitems_per_block)); +} + +gr_vector_to_stream::gr_vector_to_stream (size_t item_size, size_t nitems_per_block) + : gr_sync_interpolator ("vector_to_stream", + gr_make_io_signature (1, 1, item_size * nitems_per_block), + gr_make_io_signature (1, 1, item_size), + nitems_per_block) +{ +} + +int +gr_vector_to_stream::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + size_t block_size = output_signature()->sizeof_stream_item (0); + + const char *in = (const char *) input_items[0]; + char *out = (char *) output_items[0]; + + memcpy (out, in, noutput_items * block_size); + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_vector_to_stream.h b/gnuradio-core/src/lib/general/gr_vector_to_stream.h new file mode 100644 index 000000000..9fc8030f5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_to_stream.h @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_VECTOR_TO_STREAM_H +#define INCLUDED_GR_VECTOR_TO_STREAM_H + +#include <gr_core_api.h> +#include <gr_sync_interpolator.h> + +class gr_vector_to_stream; +typedef boost::shared_ptr<gr_vector_to_stream> gr_vector_to_stream_sptr; + +GR_CORE_API gr_vector_to_stream_sptr +gr_make_vector_to_stream (size_t item_size, size_t nitems_per_block); + + +/*! + * \brief convert a stream of blocks of nitems_per_block items into a stream of items + * \ingroup slicedice_blk + */ +class GR_CORE_API gr_vector_to_stream : public gr_sync_interpolator +{ + friend GR_CORE_API gr_vector_to_stream_sptr + gr_make_vector_to_stream (size_t item_size, size_t nitems_per_block); + + protected: + gr_vector_to_stream (size_t item_size, size_t nitems_per_block); + + public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_VECTOR_TO_STREAM_H */ diff --git a/gnuradio-core/src/lib/general/gr_vector_to_stream.i b/gnuradio-core/src/lib/general/gr_vector_to_stream.i new file mode 100644 index 000000000..99776eeb8 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_to_stream.i @@ -0,0 +1,34 @@ +/* -*- 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,vector_to_stream) + +gr_vector_to_stream_sptr +gr_make_vector_to_stream (size_t itemsize, size_t nitems_per_block); + +class gr_vector_to_stream : public gr_sync_decimator +{ + protected: + gr_vector_to_stream (size_t itemsize, size_t nitems_per_block); + + public: +}; diff --git a/gnuradio-core/src/lib/general/gr_vector_to_streams.cc b/gnuradio-core/src/lib/general/gr_vector_to_streams.cc new file mode 100644 index 000000000..7ab352a4f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_to_streams.cc @@ -0,0 +1,64 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005,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_vector_to_streams.h> +#include <gr_io_signature.h> +#include <string.h> + +gr_vector_to_streams_sptr +gr_make_vector_to_streams (size_t item_size, size_t nstreams) +{ + return gnuradio::get_initial_sptr(new gr_vector_to_streams (item_size, nstreams)); +} + +gr_vector_to_streams::gr_vector_to_streams (size_t item_size, size_t nstreams) + : gr_sync_block ("vector_to_streams", + gr_make_io_signature (1, 1, nstreams * item_size), + gr_make_io_signature (nstreams, nstreams, item_size)) +{ +} + +int +gr_vector_to_streams::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + size_t item_size = output_signature()->sizeof_stream_item(0); + int nstreams = output_items.size(); + + const char *in = (const char *) input_items[0]; + char **outv = (char **) &output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + for (int j = 0; j < nstreams; j++){ + memcpy(outv[j], in, item_size); + outv[j] += item_size; + in += item_size; + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_vector_to_streams.h b/gnuradio-core/src/lib/general/gr_vector_to_streams.h new file mode 100644 index 000000000..8db423053 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_to_streams.h @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_VECTOR_TO_STREAMS_H +#define INCLUDED_GR_VECTOR_TO_STREAMS_H + +#include <gr_core_api.h> +#include <gr_sync_interpolator.h> + +class gr_vector_to_streams; +typedef boost::shared_ptr<gr_vector_to_streams> gr_vector_to_streams_sptr; + +GR_CORE_API gr_vector_to_streams_sptr +gr_make_vector_to_streams (size_t item_size, size_t nstreams); + + +/*! + * \brief Convert 1 stream of vectors of length N to N streams of items + * \ingroup slicedice_blk + */ +class GR_CORE_API gr_vector_to_streams : public gr_sync_block +{ + friend GR_CORE_API gr_vector_to_streams_sptr + gr_make_vector_to_streams (size_t item_size, size_t nstreams); + + protected: + gr_vector_to_streams (size_t item_size, size_t nstreams); + + public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_VECTOR_TO_STREAMS_H */ diff --git a/gnuradio-core/src/lib/general/gr_vector_to_streams.i b/gnuradio-core/src/lib/general/gr_vector_to_streams.i new file mode 100644 index 000000000..d4123135b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_to_streams.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,vector_to_streams) + +gr_vector_to_streams_sptr +gr_make_vector_to_streams (size_t itemsize, size_t nstreams); + +class gr_vector_to_streams : public gr_sync_block +{ + protected: + gr_vector_to_streams (size_t itemsize, size_t nstreams); + + public: +}; diff --git a/gnuradio-core/src/lib/general/gri_add_const_ss.h b/gnuradio-core/src/lib/general/gri_add_const_ss.h new file mode 100644 index 000000000..7433ee41b --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_add_const_ss.h @@ -0,0 +1,36 @@ +/* -*- 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_GRI_ADD_CONST_SS_H +#define INCLUDED_GRI_ADD_CONST_SS_H + +/*! + * \brief Low-level, high-speed add_const_ss primitive + * + * copy src to dst adding konst + */ + +void +gri_add_const_ss (short *dst, const short *src, int nshorts, short konst); + + +#endif /* _INCLUDED_GRI_ADD_CONST_SS_H_ */ diff --git a/gnuradio-core/src/lib/general/gri_add_const_ss_generic.cc b/gnuradio-core/src/lib/general/gri_add_const_ss_generic.cc new file mode 100644 index 000000000..3b5ee1824 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_add_const_ss_generic.cc @@ -0,0 +1,49 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gri_add_const_ss.h> + +void +gri_add_const_ss (short *dst, const short *src, int nshorts, short konst) +{ + static const int STRIDE = 8; + + int i; + + for (i = 0; i < nshorts - (STRIDE - 1); i += STRIDE){ + dst[i + 0] = src[i + 0] + konst; + dst[i + 1] = src[i + 1] + konst; + dst[i + 2] = src[i + 2] + konst; + dst[i + 3] = src[i + 3] + konst; + dst[i + 4] = src[i + 4] + konst; + dst[i + 5] = src[i + 5] + konst; + dst[i + 6] = src[i + 6] + konst; + dst[i + 7] = src[i + 7] + konst; + } + + for (; i < nshorts; i++) + dst[i] = src[i] + konst; +} diff --git a/gnuradio-core/src/lib/general/gri_agc2_cc.h b/gnuradio-core/src/lib/general/gri_agc2_cc.h new file mode 100644 index 000000000..55aa19b9a --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_agc2_cc.h @@ -0,0 +1,91 @@ +/* -*- 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 _GRI_AGC2_CC_H_ +#define _GRI_AGC2_CC_H_ + +#include <gr_core_api.h> +#include <math.h> + +/*! + * \brief high performance Automatic Gain Control class + * + * For Power the absolute value of the complex number is used. + */ +class GR_CORE_API gri_agc2_cc { + + public: + gri_agc2_cc (float attack_rate = 1e-1, float decay_rate = 1e-2, float reference = 1.0, + float gain = 1.0, float max_gain = 0.0) + : _attack_rate(attack_rate), _decay_rate(decay_rate), _reference(reference), + _gain(gain), _max_gain(max_gain) {}; + + float decay_rate () const { return _decay_rate; } + float attack_rate () const { return _attack_rate; } + float reference () const { return _reference; } + float gain () const { return _gain; } + float max_gain() const { return _max_gain; } + + void set_decay_rate (float rate) { _decay_rate = rate; } + void set_attack_rate (float rate) { _attack_rate = rate; } + void set_reference (float reference) { _reference = reference; } + void set_gain (float gain) { _gain = gain; } + void set_max_gain(float max_gain) { _max_gain = max_gain; } + + gr_complex scale (gr_complex input){ + gr_complex output = input * _gain; + + float tmp = -_reference + sqrt(output.real()*output.real() + + output.imag()*output.imag()); + float rate = _decay_rate; + if((tmp) > _gain) + rate = _attack_rate; + _gain -= tmp*rate; + +#if 0 + fprintf(stdout, "rate = %f\ttmp = %f\t gain = %f\n", rate, tmp, _gain); +#endif + + // Not sure about this; will blow up if _gain < 0 (happens when rates are too high), + // but is this the solution? + if (_gain < 0.0) + _gain = 10e-5; + + if (_max_gain > 0.0 && _gain > _max_gain) + _gain = _max_gain; + return output; + } + + void scaleN (gr_complex output[], const gr_complex input[], unsigned n){ + for (unsigned i = 0; i < n; i++) + output[i] = scale (input[i]); + } + + protected: + float _attack_rate; // attack rate for fast changing signals + float _decay_rate; // decay rate for slow changing signals + float _reference; // reference value + float _gain; // current gain + float _max_gain; // max allowable gain +}; + +#endif /* _GRI_AGC2_CC_H_ */ diff --git a/gnuradio-core/src/lib/general/gri_agc2_cc.i b/gnuradio-core/src/lib/general/gri_agc2_cc.i new file mode 100644 index 000000000..08716c6ed --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_agc2_cc.i @@ -0,0 +1,47 @@ +/* -*- 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. + */ + +#include <math.h> + +/*! + * \brief high performance Automatic Gain Control class with attack and decay rates + * + * For Power the absolute value of the complex number is used. + */ + + +class gri_agc2_cc { + + public: + gri_agc2_cc (float attack_rate = 1e-1, float decay_rate = 1e-2, float reference = 1.0, + float gain = 1.0, float max_gain = 0.0); + float decay_rate (); + float attack_rate (); + float reference (); + float gain (); + float max_gain (); + void set_decay_rate (float rate); + void set_attack_rate (float rate); + void set_reference (float reference); + void set_gain (float gain); + void set_max_gain(float max_gain); + }; diff --git a/gnuradio-core/src/lib/general/gri_agc2_ff.h b/gnuradio-core/src/lib/general/gri_agc2_ff.h new file mode 100644 index 000000000..a8b46bec5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_agc2_ff.h @@ -0,0 +1,90 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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 _GRI_AGC2_FF_H_ +#define _GRI_AGC2_FF_H_ + +#include <gr_core_api.h> +#include <math.h> + +/*! + * \brief high performance Automatic Gain Control class with attack and decay rate + * + * Power is approximated by absolute value + */ + +class GR_CORE_API gri_agc2_ff { + + public: + gri_agc2_ff (float attack_rate = 1e-1, float decay_rate = 1e-2, float reference = 1.0, + float gain = 1.0, float max_gain = 0.0) + : _attack_rate(attack_rate), _decay_rate(decay_rate), _reference(reference), + _gain(gain), _max_gain(max_gain) {}; + + float attack_rate () const { return _attack_rate; } + float decay_rate () const { return _decay_rate; } + float reference () const { return _reference; } + float gain () const { return _gain; } + float max_gain () const { return _max_gain; } + + void set_attack_rate (float rate) { _attack_rate = rate; } + void set_decay_rate (float rate) { _decay_rate = rate; } + void set_reference (float reference) { _reference = reference; } + void set_gain (float gain) { _gain = gain; } + void set_max_gain (float max_gain) { _max_gain = max_gain; } + + float scale (float input){ + float output = input * _gain; + + float tmp = (fabsf(output)) - _reference; + float rate = _decay_rate; + if(fabsf(tmp) > _gain) + rate = _attack_rate; + _gain -= tmp*rate; + +#if 0 + fprintf(stdout, "rate = %f\ttmp = %f\t gain = %f\n", rate, tmp, _gain); +#endif + + // Not sure about this + if (_gain < 0.0) + _gain = 10e-5; + + if (_max_gain > 0.0 && _gain > _max_gain) + _gain = _max_gain; + return output; + } + + void scaleN (float output[], const float input[], unsigned n){ + for (unsigned i = 0; i < n; i++) + output[i] = scale (input[i]); + } + + protected: + float _attack_rate; // attack_rate for fast changing signals + float _decay_rate; // decay rate for slow changing signals + float _reference; // reference value + float _gain; // current gain + float _max_gain; // maximum gain +}; + +#endif /* _GRI_AGC2_FF_H_ */ diff --git a/gnuradio-core/src/lib/general/gri_agc2_ff.i b/gnuradio-core/src/lib/general/gri_agc2_ff.i new file mode 100644 index 000000000..9f97d8f0d --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_agc2_ff.i @@ -0,0 +1,47 @@ +/* -*- 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. + */ + +#include <math.h> + +/*! + * \brief high performance Automatic Gain Control class + * + * Power is approximated by absolute value + */ + + +class gri_agc2_ff { + + public: + gri_agc2_ff (float attack_rate = 1e-1, float decay_rate = 1e-2, + float reference = 1.0, float gain = 1.0, float max_gain = 0.0); + float attack_rate (); + float decay_rate (); + float reference (); + float gain (); + float max_gain (); + void set_attack_rate (float rate); + void set_decay_rate (float rate); + void set_reference (float reference); + void set_gain (float gain); + void set_max_gain (float max_gain); + }; diff --git a/gnuradio-core/src/lib/general/gri_agc_cc.h b/gnuradio-core/src/lib/general/gri_agc_cc.h new file mode 100644 index 000000000..90edc5dcd --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_agc_cc.h @@ -0,0 +1,75 @@ +/* -*- 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_GRI_AGC_CC_H +#define INCLUDED_GRI_AGC_CC_H + +#include <gr_core_api.h> +#include <math.h> + +/*! + * \brief high performance Automatic Gain Control class + * + * For Power the absolute value of the complex number is used. + */ + +class GR_CORE_API gri_agc_cc { + + public: + gri_agc_cc (float rate = 1e-4, float reference = 1.0, + float gain = 1.0, float max_gain = 0.0) + : _rate(rate), _reference(reference), + _gain(gain), _max_gain(max_gain) {}; + + float rate () const { return _rate; } + float reference () const { return _reference; } + float gain () const { return _gain; } + float max_gain() const { return _max_gain; } + + void set_rate (float rate) { _rate = rate; } + void set_reference (float reference) { _reference = reference; } + void set_gain (float gain) { _gain = gain; } + void set_max_gain(float max_gain) { _max_gain = max_gain; } + + gr_complex scale (gr_complex input){ + gr_complex output = input * _gain; + + _gain += _rate * (_reference - sqrt(output.real()*output.real() + + output.imag()*output.imag())); + if (_max_gain > 0.0 && _gain > _max_gain) + _gain = _max_gain; + return output; + } + + void scaleN (gr_complex output[], const gr_complex input[], unsigned n){ + for (unsigned i = 0; i < n; i++) + output[i] = scale (input[i]); + } + + protected: + float _rate; // adjustment rate + float _reference; // reference value + float _gain; // current gain + float _max_gain; // max allowable gain +}; + +#endif /* INCLUDED_GRI_AGC_CC_H */ diff --git a/gnuradio-core/src/lib/general/gri_agc_cc.i b/gnuradio-core/src/lib/general/gri_agc_cc.i new file mode 100644 index 000000000..d3dd9b61b --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_agc_cc.i @@ -0,0 +1,41 @@ +/* -*- 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. + */ + +#include <math.h> + +/*! + * \brief high performance Automatic Gain Control class + * + * For Power the absolute value of the complex number is used. + */ + + +class gri_agc_cc { + + public: + gri_agc_cc (float rate = 1e-4, float reference = 1.0, + float gain = 1.0, float max_gain = 0.0); + float rate (); + float reference (); + float gain (); + float max_gain (); + }; diff --git a/gnuradio-core/src/lib/general/gri_agc_ff.h b/gnuradio-core/src/lib/general/gri_agc_ff.h new file mode 100644 index 000000000..1c233c746 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_agc_ff.h @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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_GRI_AGC_FF_H +#define INCLUDED_GRI_AGC_FF_H + +#include <gr_core_api.h> +#include <math.h> + +/*! + * \brief high performance Automatic Gain Control class + * + * Power is approximated by absolute value + */ +class GR_CORE_API gri_agc_ff { + + public: + gri_agc_ff (float rate = 1e-4, float reference = 1.0, + float gain = 1.0, float max_gain = 0.0) + : _rate(rate), _reference(reference), _gain(gain), _max_gain(max_gain) {}; + + float rate () const { return _rate; } + float reference () const { return _reference; } + float gain () const { return _gain; } + float max_gain () const { return _max_gain; } + + void set_rate (float rate) { _rate = rate; } + void set_reference (float reference) { _reference = reference; } + void set_gain (float gain) { _gain = gain; } + void set_max_gain (float max_gain) { _max_gain = max_gain; } + + float scale (float input){ + float output = input * _gain; + _gain += (_reference - fabsf (output)) * _rate; + if (_max_gain > 0.0 && _gain > _max_gain) + _gain = _max_gain; + return output; + } + + void scaleN (float output[], const float input[], unsigned n){ + for (unsigned i = 0; i < n; i++) + output[i] = scale (input[i]); + } + + protected: + float _rate; // adjustment rate + float _reference; // reference value + float _gain; // current gain + float _max_gain; // maximum gain +}; + +#endif /* INCLUDED_GRI_AGC_FF_H */ + diff --git a/gnuradio-core/src/lib/general/gri_agc_ff.i b/gnuradio-core/src/lib/general/gri_agc_ff.i new file mode 100644 index 000000000..df4acf7af --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_agc_ff.i @@ -0,0 +1,36 @@ +/* -*- 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. + */ + +#include <math.h> + +/*! + * \brief high performance Automatic Gain Control class + * + * Power is approximated by absolute value + */ + +class gri_agc_ff { + + public: + gri_agc_ff (float rate = 1e-4, float reference = 1.0, + float gain = 1.0, float max_gain = 0.0); +}; diff --git a/gnuradio-core/src/lib/general/gri_char_to_float.cc b/gnuradio-core/src/lib/general/gri_char_to_float.cc new file mode 100644 index 000000000..fd9a6636a --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_char_to_float.cc @@ -0,0 +1,40 @@ +/* -*- 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. + */ + +#include <gri_char_to_float.h> + +void +gri_char_to_float (const char *in, float *out, int nsamples) +{ + while (nsamples >= 4){ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; + out += 4; + in += 4; + nsamples -= 4; + } + + while (nsamples-- > 0) + *out++ = *in++; +} diff --git a/gnuradio-core/src/lib/general/gri_char_to_float.h b/gnuradio-core/src/lib/general/gri_char_to_float.h new file mode 100644 index 000000000..8bd3bfde7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_char_to_float.h @@ -0,0 +1,34 @@ +/* -*- 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_GRI_CHAR_TO_FLOAT_H +#define INCLUDED_GRI_CHAR_TO_FLOAT_H + +#include <gr_core_api.h> + +/* + * convert array of chars to floats + */ +GR_CORE_API void gri_char_to_float (const char *in, float *out, int nsamples); + + +#endif /* INCLUDED_GRI_CHAR_TO_FLOAT_H */
\ No newline at end of file diff --git a/gnuradio-core/src/lib/general/gri_control_loop.cc b/gnuradio-core/src/lib/general/gri_control_loop.cc new file mode 100644 index 000000000..bb3c4a326 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_control_loop.cc @@ -0,0 +1,210 @@ +/* -*- 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 <gri_control_loop.h> +#include <gr_math.h> +#include <stdexcept> + +#define M_TWOPI (2.0f*M_PI) + +gri_control_loop::gri_control_loop(float loop_bw, + float max_freq, float min_freq) + : d_phase(0), d_freq(0), d_max_freq(max_freq), d_min_freq(min_freq) +{ + // Set the damping factor for a critically damped system + d_damping = sqrtf(2.0f)/2.0f; + + // Set the bandwidth, which will then call update_gains() + set_loop_bandwidth(loop_bw); +} + +gri_control_loop::~gri_control_loop() +{ +} + +void +gri_control_loop::update_gains() +{ + float denom = (1.0 + 2.0*d_damping*d_loop_bw + d_loop_bw*d_loop_bw); + d_alpha = (4*d_damping*d_loop_bw) / denom; + d_beta = (4*d_loop_bw*d_loop_bw) / denom; +} + +void +gri_control_loop::advance_loop(float error) +{ + d_freq = d_freq + d_beta * error; + d_phase = d_phase + d_freq + d_alpha * error; +} + + +void +gri_control_loop::phase_wrap() +{ + while(d_phase>M_TWOPI) + d_phase -= M_TWOPI; + while(d_phase<-M_TWOPI) + d_phase += M_TWOPI; +} + +void +gri_control_loop::frequency_limit() +{ + if (d_freq > d_max_freq) + d_freq = d_max_freq; + else if (d_freq < d_min_freq) + d_freq = d_min_freq; +} + +/******************************************************************* + SET FUNCTIONS +*******************************************************************/ + +void +gri_control_loop::set_loop_bandwidth(float bw) +{ + if(bw < 0) { + throw std::out_of_range ("gri_control_loop: invalid bandwidth. Must be >= 0."); + } + + d_loop_bw = bw; + update_gains(); +} + +void +gri_control_loop::set_damping_factor(float df) +{ + if(df < 0 || df > 1.0) { + throw std::out_of_range ("gri_control_loop: invalid damping factor. Must be in [0,1]."); + } + + d_damping = df; + update_gains(); +} + +void +gri_control_loop::set_alpha(float alpha) +{ + if(alpha < 0 || alpha > 1.0) { + throw std::out_of_range ("gri_control_loop: invalid alpha. Must be in [0,1]."); + } + d_alpha = alpha; +} + +void +gri_control_loop::set_beta(float beta) +{ + if(beta < 0 || beta > 1.0) { + throw std::out_of_range ("gri_control_loop: invalid beta. Must be in [0,1]."); + } + d_beta = beta; +} + +void +gri_control_loop::set_frequency(float freq) +{ + if(freq > d_max_freq) + d_freq = d_min_freq; + else if(freq < d_min_freq) + d_freq = d_max_freq; + else + d_freq = freq; +} + +void +gri_control_loop::set_phase(float phase) +{ + d_phase = phase; + while(d_phase>M_TWOPI) + d_phase -= M_TWOPI; + while(d_phase<-M_TWOPI) + d_phase += M_TWOPI; +} + +void +gri_control_loop::set_max_freq(float freq) +{ + d_max_freq = freq; +} + +void +gri_control_loop::set_min_freq(float freq) +{ + d_min_freq = freq; +} + +/******************************************************************* + GET FUNCTIONS +*******************************************************************/ + + +float +gri_control_loop::get_loop_bandwidth() const +{ + return d_loop_bw; +} + +float +gri_control_loop::get_damping_factor() const +{ + return d_damping; +} + +float +gri_control_loop::get_alpha() const +{ + return d_alpha; +} + +float +gri_control_loop::get_beta() const +{ + return d_beta; +} + +float +gri_control_loop::get_frequency() const +{ + return d_freq; +} + +float +gri_control_loop::get_phase() const +{ + return d_phase; +} + +float +gri_control_loop::get_max_freq() const +{ + return d_max_freq; +} + +float +gri_control_loop::get_min_freq() const +{ + return d_min_freq; +} diff --git a/gnuradio-core/src/lib/general/gri_control_loop.h b/gnuradio-core/src/lib/general/gri_control_loop.h new file mode 100644 index 000000000..304857ac7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_control_loop.h @@ -0,0 +1,230 @@ +/* -*- 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 GRI_CONTROL_LOOP +#define GRI_CONTROL_LOOP + +#include <gr_core_api.h> + +class GR_CORE_API gri_control_loop +{ + protected: + float d_phase, d_freq; + float d_max_freq, d_min_freq; + float d_damping, d_loop_bw; + float d_alpha, d_beta; + + public: + gri_control_loop(float loop_bw, float max_freq, float min_freq); + virtual ~gri_control_loop(); + + /*! \brief update the system gains from the loop bandwidth and damping factor + * + * This function updates the system gains based on the loop + * bandwidth and damping factor of the system. + * These two factors can be set separately through their own + * set functions. + */ + void update_gains(); + + /*! \brief update the system gains from the loop bandwidth and damping factor + * + * This function updates the system gains based on the loop + * bandwidth and damping factor of the system. + * These two factors can be set separately through their own + * set functions. + */ + void advance_loop(float error); + + /*! \brief Keep the phase between -2pi and 2pi + * + * This function keeps the phase between -2pi and 2pi. If the phase + * is greater than 2pi by d, it wraps around to be -2pi+d; similarly if + * it is less than -2pi by d, it wraps around to 2pi-d. + * + * This function should be called after advance_loop to keep the phase + * in a good operating region. It is set as a separate method in case + * another way is desired as this is fairly heavy-handed. + */ + void phase_wrap(); + + /*! \brief Keep the frequency between d_min_freq and d_max_freq + * + * This function keeps the frequency between d_min_freq and d_max_freq. + * If the frequency is greater than d_max_freq, it is set to d_max_freq. + * If the frequency is less than d_min_freq, it is set to d_min_freq. + * + * This function should be called after advance_loop to keep the frequency + * in the specified region. It is set as a separate method in case + * another way is desired as this is fairly heavy-handed. + */ + void frequency_limit(); + + /******************************************************************* + SET FUNCTIONS + *******************************************************************/ + + /*! + * \brief Set the loop bandwidth + * + * Set the loop filter's bandwidth to \p bw. This should be between + * 2*pi/200 and 2*pi/100 (in rads/samp). It must also be a positive + * number. + * + * When a new damping factor is set, the gains, alpha and beta, of the loop + * are recalculated by a call to update_gains(). + * + * \param bw (float) new bandwidth + * + */ + void set_loop_bandwidth(float bw); + + /*! + * \brief Set the loop damping factor + * + * Set the loop filter's damping factor to \p df. The damping factor + * should be sqrt(2)/2.0 for critically damped systems. + * Set it to anything else only if you know what you are doing. It must + * be a number between 0 and 1. + * + * When a new damping factor is set, the gains, alpha and beta, of the loop + * are recalculated by a call to update_gains(). + * + * \param df (float) new damping factor + * + */ + void set_damping_factor(float df); + + /*! + * \brief Set the loop gain alpha + * + * Set's the loop filter's alpha gain parameter. + * + * This value should really only be set by adjusting the loop bandwidth + * and damping factor. + * + * \param alpha (float) new alpha gain + * + */ + void set_alpha(float alpha); + + /*! + * \brief Set the loop gain beta + * + * Set's the loop filter's beta gain parameter. + * + * This value should really only be set by adjusting the loop bandwidth + * and damping factor. + * + * \param beta (float) new beta gain + * + */ + void set_beta(float beta); + + /*! + * \brief Set the control loop's frequency. + * + * Set's the control loop's frequency. While this is normally updated by the + * inner loop of the algorithm, it could be useful to manually initialize, + * set, or reset this under certain circumstances. + * + * \param freq (float) new frequency + * + */ + void set_frequency(float freq); + + /*! + * \brief Set the control loop's phase. + * + * Set's the control loop's phase. While this is normally updated by the + * inner loop of the algorithm, it could be useful to manually initialize, + * set, or reset this under certain circumstances. + * + * \param phase (float) new phase + * + */ + void set_phase(float phase); + + /*! + * \brief Set the control loop's maximum frequency. + * + * Set the maximum frequency the control loop can track. + * + * \param freq (float) new max frequency + */ + void set_max_freq(float freq); + + /*! + * \brief Set the control loop's minimum frequency. + * + * Set the minimum frequency the control loop can track. + * + * \param freq (float) new min frequency + */ + void set_min_freq(float freq); + + /******************************************************************* + GET FUNCTIONS + *******************************************************************/ + + /*! + * \brief Returns the loop bandwidth + */ + float get_loop_bandwidth() const; + + /*! + * \brief Returns the loop damping factor + */ + float get_damping_factor() const; + + /*! + * \brief Returns the loop gain alpha + */ + float get_alpha() const; + + /*! + * \brief Returns the loop gain beta + */ + float get_beta() const; + + /*! + * \brief Get the control loop's frequency estimate + */ + float get_frequency() const; + + /*! + * \brief Get the control loop's phase estimate + */ + float get_phase() const; + + /*! + * \brief Get the control loop's maximum frequency. + */ + float get_max_freq() const; + + /*! + * \brief Get the control loop's minimum frequency. + */ + float get_min_freq() const; +}; + +#endif /* GRI_CONTROL_LOOP */ diff --git a/gnuradio-core/src/lib/general/gri_control_loop.i b/gnuradio-core/src/lib/general/gri_control_loop.i new file mode 100644 index 000000000..8a23207e5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_control_loop.i @@ -0,0 +1,57 @@ +/* -*- 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. + */ + + +class gri_control_loop +{ + public: + gri_control_loop(float loop_bw, float max_freq, float min_freq); + virtual ~gri_control_loop(); + + void update_gains(); + void advance_loop(float error); + void phase_wrap(); + void frequency_limit(); + + /******************************************************************* + SET FUNCTIONS + *******************************************************************/ + + void set_loop_bandwidth(float bw); + void set_damping_factor(float df); + void set_alpha(float alpha); + void set_beta(float beta); + void set_frequency(float freq); + void set_phase(float phase); + + + /******************************************************************* + GET FUNCTIONS + *******************************************************************/ + + float get_loop_bandwidth() const; + float get_damping_factor() const; + float get_alpha() const; + float get_beta() const; + float get_frequency() const; + float get_phase() const; +}; diff --git a/gnuradio-core/src/lib/general/gri_debugger_hook.cc b/gnuradio-core/src/lib/general/gri_debugger_hook.cc new file mode 100644 index 000000000..d9270c435 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_debugger_hook.cc @@ -0,0 +1,29 @@ +/* -*- 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. + */ + +#include <gri_debugger_hook.h> + +void +gri_debugger_hook () +{ + // nop. set a breakpoint here +} diff --git a/gnuradio-core/src/lib/general/gri_debugger_hook.h b/gnuradio-core/src/lib/general/gri_debugger_hook.h new file mode 100644 index 000000000..c871c7bf6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_debugger_hook.h @@ -0,0 +1,30 @@ +/* -*- 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_GRI_DEBUGGER_HOOK_H +#define INCLUDED_GRI_DEBUGGER_HOOK_H + +#include <gr_core_api.h> + +GR_CORE_API void gri_debugger_hook (); + +#endif /* INCLUDED_GRI_DEBUGGER_HOOK_H */
\ No newline at end of file diff --git a/gnuradio-core/src/lib/general/gri_fft.cc b/gnuradio-core/src/lib/general/gri_fft.cc new file mode 100644 index 000000000..68e7e6951 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_fft.cc @@ -0,0 +1,330 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2008,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 <gri_fft.h> +#include <gr_sys_paths.h> +#include <fftw3.h> + +#ifdef _MSC_VER //http://www.fftw.org/install/windows.html#DLLwisdom +static void my_fftw_write_char(char c, void *f) { fputc(c, (FILE *) f); } +#define fftw_export_wisdom_to_file(f) fftw_export_wisdom(my_fftw_write_char, (void*) (f)) +#define fftwf_export_wisdom_to_file(f) fftwf_export_wisdom(my_fftw_write_char, (void*) (f)) +#define fftwl_export_wisdom_to_file(f) fftwl_export_wisdom(my_fftw_write_char, (void*) (f)) + +static int my_fftw_read_char(void *f) { return fgetc((FILE *) f); } +#define fftw_import_wisdom_from_file(f) fftw_import_wisdom(my_fftw_read_char, (void*) (f)) +#define fftwf_import_wisdom_from_file(f) fftwf_import_wisdom(my_fftw_read_char, (void*) (f)) +#define fftwl_import_wisdom_from_file(f) fftwl_import_wisdom(my_fftw_read_char, (void*) (f)) +#endif //_MSC_VER + +#include <gr_complex.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <cassert> +#include <stdexcept> + +#include <boost/filesystem/operations.hpp> +#include <boost/filesystem/path.hpp> +namespace fs = boost::filesystem; + +gr_complex * +gri_fft_malloc_complex(int size) +{ + return (gr_complex*)fftwf_malloc(sizeof(gr_complex)*size); +} + +float * +gri_fft_malloc_float(int size) +{ + return (float*)fftwf_malloc(sizeof(float)*size); +} + +void +gri_fft_free(void *b) +{ + fftwf_free(b); +} + +boost::mutex & +gri_fft_planner::mutex() +{ + static boost::mutex s_planning_mutex; + + return s_planning_mutex; +} + +static const char * +wisdom_filename () +{ + static fs::path path; + path = fs::path(gr_appdata_path()) / ".gr_fftw_wisdom"; + return path.string().c_str(); +} + +static void +gri_fftw_import_wisdom () +{ + const char *filename = wisdom_filename (); + FILE *fp = fopen (filename, "r"); + if (fp != 0){ + int r = fftwf_import_wisdom_from_file (fp); + fclose (fp); + if (!r){ + fprintf (stderr, "gri_fftw: can't import wisdom from %s\n", filename); + } + } +} + +static void +gri_fftw_config_threading (int nthreads) +{ + static int fftw_threads_inited = 0; + +#ifdef FFTW3F_THREADS + if (fftw_threads_inited == 0) + { + fftw_threads_inited = 1; + fftwf_init_threads(); + } + + fftwf_plan_with_nthreads(nthreads); +#endif +} + +static void +gri_fftw_export_wisdom () +{ + const char *filename = wisdom_filename (); + FILE *fp = fopen (filename, "w"); + if (fp != 0){ + fftwf_export_wisdom_to_file (fp); + fclose (fp); + } + else { + fprintf (stderr, "gri_fftw: "); + perror (filename); + } +} + +// ---------------------------------------------------------------- + +gri_fft_complex::gri_fft_complex (int fft_size, bool forward, int nthreads) +{ + // Hold global mutex during plan construction and destruction. + gri_fft_planner::scoped_lock lock(gri_fft_planner::mutex()); + + assert (sizeof (fftwf_complex) == sizeof (gr_complex)); + + if (fft_size <= 0) + throw std::out_of_range ("gri_fftw: invalid fft_size"); + + d_fft_size = fft_size; + d_inbuf = (gr_complex *) fftwf_malloc (sizeof (gr_complex) * inbuf_length ()); + if (d_inbuf == 0) + throw std::runtime_error ("fftwf_malloc"); + + d_outbuf = (gr_complex *) fftwf_malloc (sizeof (gr_complex) * outbuf_length ()); + if (d_outbuf == 0){ + fftwf_free (d_inbuf); + throw std::runtime_error ("fftwf_malloc"); + } + + d_nthreads = nthreads; + gri_fftw_config_threading (nthreads); + gri_fftw_import_wisdom (); // load prior wisdom from disk + + d_plan = fftwf_plan_dft_1d (fft_size, + reinterpret_cast<fftwf_complex *>(d_inbuf), + reinterpret_cast<fftwf_complex *>(d_outbuf), + forward ? FFTW_FORWARD : FFTW_BACKWARD, + FFTW_MEASURE); + + if (d_plan == NULL) { + fprintf(stderr, "gri_fft_complex: error creating plan\n"); + throw std::runtime_error ("fftwf_plan_dft_1d failed"); + } + gri_fftw_export_wisdom (); // store new wisdom to disk +} + +gri_fft_complex::~gri_fft_complex () +{ + // Hold global mutex during plan construction and destruction. + gri_fft_planner::scoped_lock lock(gri_fft_planner::mutex()); + + fftwf_destroy_plan ((fftwf_plan) d_plan); + fftwf_free (d_inbuf); + fftwf_free (d_outbuf); +} + +void +gri_fft_complex::set_nthreads(int n) +{ + if (n <= 0) + throw std::out_of_range ("gri_fftw: invalid number of threads"); + d_nthreads = n; + +#ifdef FFTW3F_THREADS + fftwf_plan_with_nthreads(d_nthreads); +#endif +} + +void +gri_fft_complex::execute () +{ + fftwf_execute ((fftwf_plan) d_plan); +} + +// ---------------------------------------------------------------- + +gri_fft_real_fwd::gri_fft_real_fwd (int fft_size, int nthreads) +{ + // Hold global mutex during plan construction and destruction. + gri_fft_planner::scoped_lock lock(gri_fft_planner::mutex()); + + assert (sizeof (fftwf_complex) == sizeof (gr_complex)); + + if (fft_size <= 0) + throw std::out_of_range ("gri_fftw: invalid fft_size"); + + d_fft_size = fft_size; + d_inbuf = (float *) fftwf_malloc (sizeof (float) * inbuf_length ()); + if (d_inbuf == 0) + throw std::runtime_error ("fftwf_malloc"); + + d_outbuf = (gr_complex *) fftwf_malloc (sizeof (gr_complex) * outbuf_length ()); + if (d_outbuf == 0){ + fftwf_free (d_inbuf); + throw std::runtime_error ("fftwf_malloc"); + } + + d_nthreads = nthreads; + gri_fftw_config_threading (nthreads); + gri_fftw_import_wisdom (); // load prior wisdom from disk + + d_plan = fftwf_plan_dft_r2c_1d (fft_size, + d_inbuf, + reinterpret_cast<fftwf_complex *>(d_outbuf), + FFTW_MEASURE); + + if (d_plan == NULL) { + fprintf(stderr, "gri_fft_real_fwd: error creating plan\n"); + throw std::runtime_error ("fftwf_plan_dft_r2c_1d failed"); + } + gri_fftw_export_wisdom (); // store new wisdom to disk +} + +gri_fft_real_fwd::~gri_fft_real_fwd () +{ + // Hold global mutex during plan construction and destruction. + gri_fft_planner::scoped_lock lock(gri_fft_planner::mutex()); + + fftwf_destroy_plan ((fftwf_plan) d_plan); + fftwf_free (d_inbuf); + fftwf_free (d_outbuf); +} + +void +gri_fft_real_fwd::set_nthreads(int n) +{ + if (n <= 0) + throw std::out_of_range ("gri_fftw: invalid number of threads"); + d_nthreads = n; + +#ifdef FFTW3F_THREADS + fftwf_plan_with_nthreads(d_nthreads); +#endif +} + +void +gri_fft_real_fwd::execute () +{ + fftwf_execute ((fftwf_plan) d_plan); +} + +// ---------------------------------------------------------------- + +gri_fft_real_rev::gri_fft_real_rev (int fft_size, int nthreads) +{ + // Hold global mutex during plan construction and destruction. + gri_fft_planner::scoped_lock lock(gri_fft_planner::mutex()); + + assert (sizeof (fftwf_complex) == sizeof (gr_complex)); + + if (fft_size <= 0) + throw std::out_of_range ("gri_fftw: invalid fft_size"); + + d_fft_size = fft_size; + d_inbuf = (gr_complex *) fftwf_malloc (sizeof (gr_complex) * inbuf_length ()); + if (d_inbuf == 0) + throw std::runtime_error ("fftwf_malloc"); + + d_outbuf = (float *) fftwf_malloc (sizeof (float) * outbuf_length ()); + if (d_outbuf == 0){ + fftwf_free (d_inbuf); + throw std::runtime_error ("fftwf_malloc"); + } + + d_nthreads = nthreads; + gri_fftw_config_threading (nthreads); + gri_fftw_import_wisdom (); // load prior wisdom from disk + + // FIXME If there's ever a chance that the planning functions + // will be called in multiple threads, we've got to ensure single + // threaded access. They are not thread-safe. + d_plan = fftwf_plan_dft_c2r_1d (fft_size, + reinterpret_cast<fftwf_complex *>(d_inbuf), + d_outbuf, + FFTW_MEASURE); + + if (d_plan == NULL) { + fprintf(stderr, "gri_fft_real_rev: error creating plan\n"); + throw std::runtime_error ("fftwf_plan_dft_c2r_1d failed"); + } + gri_fftw_export_wisdom (); // store new wisdom to disk +} + +gri_fft_real_rev::~gri_fft_real_rev () +{ + fftwf_destroy_plan ((fftwf_plan) d_plan); + fftwf_free (d_inbuf); + fftwf_free (d_outbuf); +} + +void +gri_fft_real_rev::set_nthreads(int n) +{ + if (n <= 0) + throw std::out_of_range ("gri_fftw: invalid number of threads"); + d_nthreads = n; + +#ifdef FFTW3F_THREADS + fftwf_plan_with_nthreads(d_nthreads); +#endif +} + +void +gri_fft_real_rev::execute () +{ + fftwf_execute ((fftwf_plan) d_plan); +} + diff --git a/gnuradio-core/src/lib/general/gri_fft.h b/gnuradio-core/src/lib/general/gri_fft.h new file mode 100644 index 000000000..65e9d046e --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_fft.h @@ -0,0 +1,185 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,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 _GRI_FFT_H_ +#define _GRI_FFT_H_ + +/* + * Wrappers for FFTW single precision 1d dft + */ + +#include <gr_core_api.h> +#include <gr_complex.h> +#include <boost/thread.hpp> + +/*! \brief Helper function for allocating complex fft buffers + */ +gr_complex* gri_fft_malloc_complex(int size); + +/*! \brief Helper function for allocating float fft buffers + */ +float* gri_fft_malloc_float(int size); + +/*! \brief Helper function for freeing fft buffers + */ +void gri_fft_free(void *b); + + +/*! + * \brief Export reference to planner mutex for those apps that + * want to use FFTW w/o using the gri_fftw* classes. + */ +class GR_CORE_API gri_fft_planner { +public: + typedef boost::mutex::scoped_lock scoped_lock; + /*! + * Return reference to planner mutex + */ + static boost::mutex &mutex(); +}; + +/*! + * \brief FFT: complex in, complex out + * \ingroup misc + */ +class GR_CORE_API gri_fft_complex { + int d_fft_size; + int d_nthreads; + gr_complex *d_inbuf; + gr_complex *d_outbuf; + void *d_plan; + +public: + gri_fft_complex (int fft_size, bool forward = true, int nthreads=1); + virtual ~gri_fft_complex (); + + /* + * These return pointers to buffers owned by gri_fft_complex into which + * input and output take place. It's done this way in order to + * ensure optimal alignment for SIMD instructions. + */ + gr_complex *get_inbuf () const { return d_inbuf; } + gr_complex *get_outbuf () const { return d_outbuf; } + + int inbuf_length () const { return d_fft_size; } + int outbuf_length () const { return d_fft_size; } + + /*! + * Set the number of threads to use for caclulation. + */ + void set_nthreads(int n); + + /*! + * Get the number of threads being used by FFTW + */ + int nthreads() const { return d_nthreads; } + + /*! + * compute FFT. The input comes from inbuf, the output is placed in outbuf. + */ + void execute (); +}; + +/*! + * \brief FFT: real in, complex out + * \ingroup misc + */ +class GR_CORE_API gri_fft_real_fwd { + int d_fft_size; + int d_nthreads; + float *d_inbuf; + gr_complex *d_outbuf; + void *d_plan; + +public: + gri_fft_real_fwd (int fft_size, int nthreads=1); + virtual ~gri_fft_real_fwd (); + + /* + * These return pointers to buffers owned by gri_fft_real_fwd into + * which input and output take place. It's done this way in order + * to ensure optimal alignment for SIMD instructions. + */ + float *get_inbuf () const { return d_inbuf; } + gr_complex *get_outbuf () const { return d_outbuf; } + + int inbuf_length () const { return d_fft_size; } + int outbuf_length () const { return d_fft_size / 2 + 1; } + + /*! + * Set the number of threads to use for caclulation. + */ + void set_nthreads(int n); + + /*! + * Get the number of threads being used by FFTW + */ + int nthreads() const { return d_nthreads; } + + /*! + * compute FFT. The input comes from inbuf, the output is placed in outbuf. + */ + void execute (); +}; + +/*! + * \brief FFT: complex in, float out + * \ingroup misc + */ +class GR_CORE_API gri_fft_real_rev { + int d_fft_size; + int d_nthreads; + gr_complex *d_inbuf; + float *d_outbuf; + void *d_plan; + +public: + gri_fft_real_rev (int fft_size, int nthreads=1); + virtual ~gri_fft_real_rev (); + + /* + * These return pointers to buffers owned by gri_fft_real_rev into + * which input and output take place. It's done this way in order + * to ensure optimal alignment for SIMD instructions. + */ + gr_complex *get_inbuf () const { return d_inbuf; } + float *get_outbuf () const { return d_outbuf; } + + int inbuf_length () const { return d_fft_size / 2 + 1; } + int outbuf_length () const { return d_fft_size; } + + /*! + * Set the number of threads to use for caclulation. + */ + void set_nthreads(int n); + + /*! + * Get the number of threads being used by FFTW + */ + int nthreads() const { return d_nthreads; } + + /*! + * compute FFT. The input comes from inbuf, the output is placed in outbuf. + */ + void execute (); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gri_float_to_char.cc b/gnuradio-core/src/lib/general/gri_float_to_char.cc new file mode 100644 index 000000000..3e779b0e7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_float_to_char.cc @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 + +#define _ISOC9X_SOURCE +#include <gri_float_to_char.h> +#include <math.h> + +static const int MIN_CHAR = -128; +static const int MAX_CHAR = 127; + + +void +gri_float_to_char (const float *in, char *out, int nsamples) +{ + for (int i = 0; i < nsamples; i++){ + long int r = (long int) rint (in[i]); + if (r < MIN_CHAR) + r = MIN_CHAR; + else if (r > MAX_CHAR) + r = MAX_CHAR; + out[i] = r; + } +} diff --git a/gnuradio-core/src/lib/general/gri_float_to_char.h b/gnuradio-core/src/lib/general/gri_float_to_char.h new file mode 100644 index 000000000..172a7da65 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_float_to_char.h @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_FLOAT_TO_CHAR_H +#define INCLUDED_GRI_FLOAT_TO_CHAR_H + +#include <gr_core_api.h> + +/*! + * convert array of floats to chars with rounding and saturation. + */ +GR_CORE_API void gri_float_to_char (const float *in, char *out, int nsamples); + +#endif /* INCLUDED_GRI_FLOAT_TO_CHAR_H */ diff --git a/gnuradio-core/src/lib/general/gri_float_to_int.cc b/gnuradio-core/src/lib/general/gri_float_to_int.cc new file mode 100644 index 000000000..525ea675d --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_float_to_int.cc @@ -0,0 +1,47 @@ +/* -*- 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 + +#define _ISOC9X_SOURCE +#include <gri_float_to_int.h> +#include <math.h> +#include <stdint.h> + +static const int64_t MAX_INT = 2147483647; // (2^31)-1 +static const int64_t MIN_INT = -2147483647; // -(2^31)-1 + + +void +gri_float_to_int (const float *in, int *out, float scale, int nsamples) +{ + for (int i = 0; i < nsamples; i++){ + int64_t r = llrintf(scale * in[i]); + if (r < MIN_INT) + r = MIN_INT; + else if (r > MAX_INT) + r = MAX_INT; + out[i] = static_cast<int>(r); + } +} diff --git a/gnuradio-core/src/lib/general/gri_float_to_int.h b/gnuradio-core/src/lib/general/gri_float_to_int.h new file mode 100644 index 000000000..84f72a420 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_float_to_int.h @@ -0,0 +1,33 @@ +/* -*- 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_GRI_FLOAT_TO_INT_H +#define INCLUDED_GRI_FLOAT_TO_INT_H + +#include <gr_core_api.h> + +/*! + * convert array of floats to int with rounding and saturation. + */ +GR_CORE_API void gri_float_to_int (const float *in, int *out, float scale, int nsamples); + +#endif /* INCLUDED_GRI_FLOAT_TO_INT_H */ diff --git a/gnuradio-core/src/lib/general/gri_float_to_short.cc b/gnuradio-core/src/lib/general/gri_float_to_short.cc new file mode 100644 index 000000000..4508e37a7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_float_to_short.cc @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 + +#define _ISOC9X_SOURCE +#include <gri_float_to_short.h> +#include <math.h> + +static const int MIN_SHORT = -32768; +static const int MAX_SHORT = 32767; + + +void +gri_float_to_short (const float *in, short *out, int nsamples) +{ + for (int i = 0; i < nsamples; i++){ + long int r = (long int) rint (in[i]); + if (r < MIN_SHORT) + r = MIN_SHORT; + else if (r > MAX_SHORT) + r = MAX_SHORT; + out[i] = r; + } +} diff --git a/gnuradio-core/src/lib/general/gri_float_to_short.h b/gnuradio-core/src/lib/general/gri_float_to_short.h new file mode 100644 index 000000000..b9cdf685b --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_float_to_short.h @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_FLOAT_TO_SHORT_H +#define INCLUDED_GRI_FLOAT_TO_SHORT_H + +#include <gr_core_api.h> + +/*! + * convert array of floats to shorts with rounding and saturation. + */ +GR_CORE_API void gri_float_to_short (const float *in, short *out, int nsamples); + +#endif /* INCLUDED_GRI_FLOAT_TO_SHORT_H */ diff --git a/gnuradio-core/src/lib/general/gri_float_to_uchar.cc b/gnuradio-core/src/lib/general/gri_float_to_uchar.cc new file mode 100644 index 000000000..9ea42a31b --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_float_to_uchar.cc @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 + +#define _ISOC9X_SOURCE +#include <gri_float_to_uchar.h> +#include <math.h> + +static const int MIN_UCHAR = 0; +static const int MAX_UCHAR = 255; + + +void +gri_float_to_uchar (const float *in, unsigned char *out, int nsamples) +{ + for (int i = 0; i < nsamples; i++){ + long int r = (long int) rint (in[i]); + if (r < MIN_UCHAR) + r = MIN_UCHAR; + else if (r > MAX_UCHAR) + r = MAX_UCHAR; + out[i] = r; + } +} diff --git a/gnuradio-core/src/lib/general/gri_float_to_uchar.h b/gnuradio-core/src/lib/general/gri_float_to_uchar.h new file mode 100644 index 000000000..e24b1973f --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_float_to_uchar.h @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_FLOAT_TO_UCHAR_H +#define INCLUDED_GRI_FLOAT_TO_UCHAR_H + +#include <gr_core_api.h> + +/*! + * convert array of floats to unsigned chars with rounding and saturation. + */ +GR_CORE_API void gri_float_to_uchar (const float *in, unsigned char *out, int nsamples); + +#endif /* INCLUDED_GRI_FLOAT_TO_UCHAR_H */ diff --git a/gnuradio-core/src/lib/general/gri_glfsr.cc b/gnuradio-core/src/lib/general/gri_glfsr.cc new file mode 100644 index 000000000..ba6951882 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_glfsr.cc @@ -0,0 +1,67 @@ +/* -*- 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 new file mode 100644 index 000000000..9aae2d9f1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_glfsr.h @@ -0,0 +1,57 @@ +/* -*- 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/gri_int_to_float.cc b/gnuradio-core/src/lib/general/gri_int_to_float.cc new file mode 100644 index 000000000..91da08897 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_int_to_float.cc @@ -0,0 +1,37 @@ +/* -*- 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 + +#define _ISOC9X_SOURCE +#include <gri_int_to_float.h> +#include <math.h> + +void +gri_int_to_float (const int *in, float *out, int nsamples) +{ + for (int i = 0; i < nsamples; i++){ + out[i] = static_cast<float>(in[i]); + } +} diff --git a/gnuradio-core/src/lib/general/gri_int_to_float.h b/gnuradio-core/src/lib/general/gri_int_to_float.h new file mode 100644 index 000000000..4b08b7c6b --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_int_to_float.h @@ -0,0 +1,34 @@ +/* -*- 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_GRI_INT_TO_FLOAT_H +#define INCLUDED_GRI_INT_TO_FLOAT_H + +#include <gr_core_api.h> + +/* + * convert array of ints to floats + */ +GR_CORE_API void gri_int_to_float (const int *in, float *out, int nsamples); + + +#endif /* INCLUDED_GRI_INT_TO_FLOAT_H */ diff --git a/gnuradio-core/src/lib/general/gri_interleaved_short_to_complex.cc b/gnuradio-core/src/lib/general/gri_interleaved_short_to_complex.cc new file mode 100644 index 000000000..7d0af0fc7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_interleaved_short_to_complex.cc @@ -0,0 +1,39 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 <gri_interleaved_short_to_complex.h> +#include <assert.h> + +void +gri_interleaved_short_to_complex (const short *in, + gr_complex *out, int nsamples) +{ + assert (nsamples % 2 == 0); + + for (int i = 0; i < nsamples/2; i++){ + out[i] = gr_complex (in[i*2 + 0], in[i*2 + 1]); + } +} diff --git a/gnuradio-core/src/lib/general/gri_interleaved_short_to_complex.h b/gnuradio-core/src/lib/general/gri_interleaved_short_to_complex.h new file mode 100644 index 000000000..8d8a0d16e --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_interleaved_short_to_complex.h @@ -0,0 +1,38 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_INTERLEAVED_SHORT_TO_COMPLEX_H +#define INCLUDED_GRI_INTERLEAVED_SHORT_TO_COMPLEX_H + +#include <gr_core_api.h> +#include <gr_complex.h> + +/* + * convert array of interleaved shorts to complex. + * the shorts contains real, imaginary, real, imaginary... + * nsamples is the number of shorts; it must be even. + */ +GR_CORE_API void gri_interleaved_short_to_complex (const short *in, gr_complex *out, int nsamples); + +#endif /* INCLUDED_GRI_INTERLEAVED_SHORT_TO_COMPLEX_H */ + + diff --git a/gnuradio-core/src/lib/general/gri_lfsr.h b/gnuradio-core/src/lib/general/gri_lfsr.h new file mode 100644 index 000000000..420236077 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_lfsr.h @@ -0,0 +1,152 @@ +/* -*- 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_GRI_LFSR_H +#define INCLUDED_GRI_LFSR_H + +#include <gr_core_api.h> +#include <stdexcept> +#include <stdint.h> + +/*! + * \brief Fibonacci Linear Feedback Shift Register using specified polynomial mask + * \ingroup misc + * + * Generates a maximal length pseudo-random sequence of length 2^degree-1 + * + * Constructor: gri_lfsr(int mask, int seed, int reg_len); + * + * mask - polynomial coefficients representing the locations + * of feedback taps from a shift register which are xor'ed + * together to form the new high order bit. + * + * Some common masks might be: + * x^4 + x^3 + x^0 = 0x19 + * x^5 + x^3 + x^0 = 0x29 + * x^6 + x^5 + x^0 = 0x61 + * + * seed - the initialization vector placed into the register + * durring initialization. Low order bit corresponds + * to x^0 coefficient -- the first to be shifted as output. + * + * reg_len - specifies the length of the feedback shift register + * to be used. Durring each iteration, the register + * is rightshifted one and the new bit is placed in bit reg_len. + * reg_len should generally be at least order(mask) + 1 + * + * + * see http://en.wikipedia.org/wiki/Linear_feedback_shift_register + * for more explanation. + * + * + * + * next_bit() - Standard LFSR operation + * + * Perform one cycle of the LFSR. The output bit is taken from + * the shift register LSB. The shift register MSB is assigned from + * the modulo 2 sum of the masked shift register. + * + * next_bit_scramble(unsigned char input) - Scramble an input stream + * + * Perform one cycle of the LFSR. The output bit is taken from + * the shift register LSB. The shift register MSB is assigned from + * the modulo 2 sum of the masked shift register and the input LSB. + * + * next_bit_descramble(unsigned char input) - Descramble an input stream + * + * Perform one cycle of the LFSR. The output bit is taken from + * the modulo 2 sum of the masked shift register and the input LSB. + * The shift register MSB is assigned from the LSB of the input. + * + * See http://en.wikipedia.org/wiki/Scrambler for operation of these + * last two functions (see multiplicative scrambler.) + * + */ + +class GR_CORE_API gri_lfsr +{ + private: + uint32_t d_shift_register; + uint32_t d_mask; + uint32_t d_seed; + uint32_t d_shift_register_length; // less than 32 + + static uint32_t + popCount(uint32_t x) + { + uint32_t r = x - ((x >> 1) & 033333333333) + - ((x >> 2) & 011111111111); + return ((r + (r >> 3)) & 030707070707) % 63; + } + + public: + + gri_lfsr(uint32_t mask, uint32_t seed, uint32_t reg_len) + : d_shift_register(seed), + d_mask(mask), + d_seed(seed), + d_shift_register_length(reg_len) + { + if (reg_len > 31) + throw std::invalid_argument("reg_len must be <= 31"); + } + + unsigned char next_bit() { + unsigned char output = d_shift_register & 1; + unsigned char newbit = popCount( d_shift_register & d_mask )%2; + d_shift_register = ((d_shift_register>>1) | (newbit<<d_shift_register_length)); + return output; + } + + unsigned char next_bit_scramble(unsigned char input) { + unsigned char output = d_shift_register & 1; + unsigned char newbit = (popCount( d_shift_register & d_mask )%2)^(input & 1); + d_shift_register = ((d_shift_register>>1) | (newbit<<d_shift_register_length)); + return output; + } + + unsigned char next_bit_descramble(unsigned char input) { + unsigned char output = (popCount( d_shift_register & d_mask )%2)^(input & 1); + unsigned char newbit = input & 1; + d_shift_register = ((d_shift_register>>1) | (newbit<<d_shift_register_length)); + return output; + } + + /*! + * Reset shift register to initial seed value + */ + void reset() { d_shift_register = d_seed; } + + /*! + * Rotate the register through x number of bits + * where we are just throwing away the results to get queued up correctly + */ + void pre_shift(int num){ + for(int i=0; i<num; i++){ + next_bit(); + } + } + + int mask() const { return d_mask; } +}; + +#endif /* INCLUDED_GRI_LFSR_H */ diff --git a/gnuradio-core/src/lib/general/gri_lfsr_15_1_0.h b/gnuradio-core/src/lib/general/gri_lfsr_15_1_0.h new file mode 100644 index 000000000..578739f7e --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_lfsr_15_1_0.h @@ -0,0 +1,60 @@ +/* -*- 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_GRI_LFSR_15_1_0_H +#define INCLUDED_GRI_LFSR_15_1_0_H + +#include <gr_core_api.h> + +/*! + * \brief Linear Feedback Shift Register using primitive polynomial x^15 + x + 1 + * \ingroup misc + * + * Generates a maximal length pseudo-random sequence of length 2^15 - 1 bits. + */ + +class GR_CORE_API gri_lfsr_15_1_0 { + unsigned long d_sr; // shift register + + public: + + gri_lfsr_15_1_0 () { reset (); } + + void reset () { d_sr = 0x7fff; } + + int next_bit (){ + d_sr = ((((d_sr >> 1) ^ d_sr) & 0x1) << 14) | (d_sr >> 1); + return d_sr & 0x1; + } + + int next_byte (){ + int v = 0; + for (int i = 0; i < 8; i++){ + v >>= 1; + if (next_bit ()) + v |= 0x80; + } + return v; + } +}; + +#endif /* INCLUDED_GRI_LFSR_15_1_0_H */
\ No newline at end of file diff --git a/gnuradio-core/src/lib/general/gri_lfsr_32k.h b/gnuradio-core/src/lib/general/gri_lfsr_32k.h new file mode 100644 index 000000000..e84512b9a --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_lfsr_32k.h @@ -0,0 +1,80 @@ +/* -*- 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_GRI_LFSR_32k_H +#define INCLUDED_GRI_LFSR_32k_H + +#include <gr_core_api.h> +#include <gri_lfsr_15_1_0.h> + +/*! + * \brief generate pseudo-random sequence of length 32768 bits. + * \ingroup misc + * + * This is based on gri_lfsr_15_1_0 with an extra 0 added at the end + * of the sequence. + */ + +class GR_CORE_API gri_lfsr_32k { + gri_lfsr_15_1_0 d_lfsr; + unsigned int d_count; + + public: + gri_lfsr_32k () { reset (); } + + void reset (){ + d_lfsr.reset (); + d_count = 0; + } + + int next_bit (){ + if (d_count == 32767){ + d_count = 0; + return 0; + } + d_count++; + return d_lfsr.next_bit (); + } + + int next_byte (){ + int v = 0; + for (int i = 0; i < 8; i++){ + v >>= 1; + if (next_bit ()) + v |= 0x80; + } + return v; + } + + int next_short (){ + int v = 0; + for (int i = 0; i < 16; i++){ + v >>= 1; + if (next_bit ()) + v |= 0x8000; + } + return v; + } + +}; + +#endif /* INCLUDED_GRI_LFSR_32k_H */ diff --git a/gnuradio-core/src/lib/general/gri_short_to_float.cc b/gnuradio-core/src/lib/general/gri_short_to_float.cc new file mode 100644 index 000000000..d5d0e786e --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_short_to_float.cc @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_short_to_float.h> + +void +gri_short_to_float (const short *in, float *out, int nsamples) +{ + while (nsamples >= 4){ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; + out += 4; + in += 4; + nsamples -= 4; + } + + while (nsamples-- > 0) + *out++ = *in++; +} diff --git a/gnuradio-core/src/lib/general/gri_short_to_float.h b/gnuradio-core/src/lib/general/gri_short_to_float.h new file mode 100644 index 000000000..2ffdbb45b --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_short_to_float.h @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_SHORT_TO_FLOAT_H +#define INCLUDED_GRI_SHORT_TO_FLOAT_H + +#include <gr_core_api.h> + +/* + * convert array of shorts to floats + */ +GR_CORE_API void gri_short_to_float (const short *in, float *out, int nsamples); + + +#endif /* INCLUDED_GRI_SHORT_TO_FLOAT_H */
\ No newline at end of file diff --git a/gnuradio-core/src/lib/general/gri_uchar_to_float.cc b/gnuradio-core/src/lib/general/gri_uchar_to_float.cc new file mode 100644 index 000000000..91f3e7336 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_uchar_to_float.cc @@ -0,0 +1,40 @@ +/* -*- 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. + */ + +#include <gri_uchar_to_float.h> + +void +gri_uchar_to_float (const unsigned char *in, float *out, int nsamples) +{ + while (nsamples >= 4){ + out[0] = in[0]; + out[1] = in[1]; + out[2] = in[2]; + out[3] = in[3]; + out += 4; + in += 4; + nsamples -= 4; + } + + while (nsamples-- > 0) + *out++ = *in++; +} diff --git a/gnuradio-core/src/lib/general/gri_uchar_to_float.h b/gnuradio-core/src/lib/general/gri_uchar_to_float.h new file mode 100644 index 000000000..633c5d4ce --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_uchar_to_float.h @@ -0,0 +1,34 @@ +/* -*- 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_GRI_UCHAR_TO_FLOAT_H +#define INCLUDED_GRI_UCHAR_TO_FLOAT_H + +#include <gr_core_api.h> + +/* + * convert array of unsigned chars to floats + */ +GR_CORE_API void gri_uchar_to_float (const unsigned char *in, float *out, int nsamples); + + +#endif /* INCLUDED_GRI_UCHAR_TO_FLOAT_H */
\ No newline at end of file diff --git a/gnuradio-core/src/lib/general/malloc16.c b/gnuradio-core/src/lib/general/malloc16.c new file mode 100644 index 000000000..2cc6135e7 --- /dev/null +++ b/gnuradio-core/src/lib/general/malloc16.c @@ -0,0 +1,46 @@ +/* Wrapper functions for malloc/free that force 16-byte alignment + * See http://perso.club-internet.fr/matmac/sourcesc.htm + + * Copyright 2001 Phil Karn, KA9Q + * May be used under the terms of the GNU Public License (GPL) + */ + +#include "malloc16.h" +#include <string.h> + +void *malloc16Align(int size){ + void *p; + void **p1; + + if((p = malloc(size+31)) == NULL) + return NULL; + + /* Round up to next 16-byte boundary */ + p1 = (void **)(((long)p + 31) & (~15)); + + /* Stash actual start of block just before ptr we return */ + p1[-1] = p; + + /* Return 16-byte aligned address */ + return (void *)p1; +} + +void *calloc16Align(size_t nmemb,size_t size){ + int nbytes; + void *p; + + nbytes = nmemb*size; + if((p = malloc16Align(nbytes)) == NULL) + return NULL; + + memset(p,0,nbytes); + return p; +} + +void free16Align(void *p){ + + if(p != NULL){ + /* Retrieve pointer to actual start of block and free it */ + free(((void **)p)[-1]); + } +} diff --git a/gnuradio-core/src/lib/general/malloc16.h b/gnuradio-core/src/lib/general/malloc16.h new file mode 100644 index 000000000..eaa32c625 --- /dev/null +++ b/gnuradio-core/src/lib/general/malloc16.h @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 <gr_core_api.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> + +GR_CORE_API void *malloc16Align(int size); +GR_CORE_API void *calloc16Align(size_t nmemb,size_t size); +GR_CORE_API void free16Align(void *p); + +#ifdef __cplusplus +} +#endif diff --git a/gnuradio-core/src/lib/general/qa_general.cc b/gnuradio-core/src/lib/general/qa_general.cc new file mode 100644 index 000000000..26b21983e --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_general.cc @@ -0,0 +1,53 @@ +/* + * Copyright 2002 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. + */ + +/* + * This class gathers together all the test cases for the gr + * directory into a single test suite. As you create new test cases, + * add them here. + */ + +#include <qa_general.h> +#include <qa_gr_firdes.h> +#include <qa_gr_circular_file.h> +#include <qa_gr_cpm.h> +#include <qa_gr_fxpt.h> +#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 () +{ + CppUnit::TestSuite *s = new CppUnit::TestSuite ("general"); + + s->addTest (qa_gr_firdes::suite ()); + s->addTest (qa_gr_circular_file::suite ()); + s->addTest (qa_gr_cpm::suite ()); + s->addTest (qa_gr_fxpt::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_general.h b/gnuradio-core/src/lib/general/qa_general.h new file mode 100644 index 000000000..bf52cddc1 --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_general.h @@ -0,0 +1,38 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_GENERAL_H_ +#define _QA_GENERAL_H_ + +#include <gruel/attributes.h> +#include <cppunit/TestSuite.h> + +//! collect all the tests for the gr directory + +class __GR_ATTR_EXPORT qa_general { + public: + //! return suite of tests for all of gr directory + static CppUnit::TestSuite *suite (); +}; + + +#endif /* _QA_GENERAL_H_ */ diff --git a/gnuradio-core/src/lib/general/qa_gr_circular_file.cc b/gnuradio-core/src/lib/general/qa_gr_circular_file.cc new file mode 100644 index 000000000..243e44784 --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_circular_file.cc @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 <qa_gr_circular_file.h> +#include <gr_circular_file.h> +#include <cppunit/TestAssert.h> +#include <iostream> +#include <stdio.h> +#include <unistd.h> + +static const char *test_file = "qa_gr_circular_file.data"; +static const int BUFFER_SIZE = 8192; +static const int NWRITE = 8192 * 9 / 8; + +void +qa_gr_circular_file::t1 () +{ +#ifdef HAVE_MMAP + gr_circular_file *cf_writer; + gr_circular_file *cf_reader; + + // write the data... + + cf_writer = new gr_circular_file (test_file, true, BUFFER_SIZE * sizeof (short)); + + short sd; + for (int i = 0; i < NWRITE; i++){ + sd = i; + cf_writer->write (&sd, sizeof (sd)); + } + + delete cf_writer; + + // now read it back... + + cf_reader = new gr_circular_file (test_file); + for (int i = 0; i < BUFFER_SIZE; i++){ + int n = cf_reader->read (&sd, sizeof (sd)); + CPPUNIT_ASSERT_EQUAL ((int) sizeof (sd), n); + CPPUNIT_ASSERT_EQUAL (NWRITE - BUFFER_SIZE + i, (int) sd); + } + + int n = cf_reader->read (&sd, sizeof (sd)); + CPPUNIT_ASSERT_EQUAL (0, n); + + delete cf_reader; + unlink (test_file); +#endif // HAVE_MMAP +} + diff --git a/gnuradio-core/src/lib/general/qa_gr_circular_file.h b/gnuradio-core/src/lib/general/qa_gr_circular_file.h new file mode 100644 index 000000000..df35ab077 --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_circular_file.h @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_GR_CIRCULAR_FILE_H_ +#define _QA_GR_CIRCULAR_FILE_H_ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_gr_circular_file : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_circular_file); + CPPUNIT_TEST (t1); + CPPUNIT_TEST_SUITE_END (); + + private: + void t1 (); + +}; + + +#endif /* _QA_GR_CIRCULAR_FILE_H_ */ diff --git a/gnuradio-core/src/lib/general/qa_gr_cpm.cc b/gnuradio-core/src/lib/general/qa_gr_cpm.cc new file mode 100644 index 000000000..ee3e2bdea --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_cpm.cc @@ -0,0 +1,140 @@ +/* -*- c++ -*- */ +/* + * Copyright 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. + */ + +#include <qa_gr_cpm.h> +#include <gr_cpm.h> +#include <cppunit/TestAssert.h> + +const double DELTA = 1e-5; +const int L = 5; +const int samples_per_sym = 4; +const float taps_lrc[20] = { + 0, 0.002447174185242, 0.009549150281253, 0.020610737385376, + 0.034549150281253, 0.050000000000000, 0.065450849718747, 0.079389262614624, + 0.090450849718747, 0.097552825814758, 0.100000000000000, 0.097552825814758, + 0.090450849718747, 0.079389262614624, 0.065450849718747, 0.050000000000000, + 0.034549150281253, 0.020610737385376, 0.009549150281253, 0.002447174185242 +}; + + +const float taps_lsrc[20] = { // beta = 0.2 + 0.000000000000000, 0.009062686687436, 0.019517618142920, 0.030875041875917, + 0.042552315421249, 0.053912556756416, 0.064308860403517, 0.073130584159352, + 0.079847961304114, 0.084051371489937, 0.085482007518284, 0.084051371489937, + 0.079847961304114, 0.073130584159352, 0.064308860403517, 0.053912556756416, + 0.042552315421249, 0.030875041875917, 0.019517618142920, 0.009062686687436 +}; + + +const float taps_tfm[20] = { + -0.003946522220317, -0.005147757690530, -0.003171631690177, 0.003959659609805, + 0.017498721302356, 0.037346982678383, 0.062251889790391, 0.087364237065604, + 0.110049050955117, 0.125677762224511, 0.132288693729399, 0.125677762224511, + 0.110049050955117, 0.087364237065604, 0.062251889790391, 0.037346982678383, + 0.017498721302356, 0.003959659609805, -0.003171631690177, -0.005147757690530 +}; + + +const float taps_gaussian[20] = { // BT = 0.3 + 0.000000743866524, 0.000009286258371, 0.000085441834550, 0.000581664421923, + 0.002945540765422, 0.011178079812344, 0.032117220937421, 0.070841188736816, + 0.122053715366673, 0.167389736919915, 0.185594670675172, 0.167389736919915, + 0.122053715366673, 0.070841188736816, 0.032117220937421, 0.011178079812344, + 0.002945540765422, 0.000581664421923, 0.000085441834550, 0.000009286258371 +}; + + +// Check LREC phase response +void +qa_gr_cpm::t1 () +{ + std::vector<float> taps(gr_cpm::phase_response(gr_cpm::LREC, samples_per_sym, L)); + + for (int i = 0; i < L * samples_per_sym; i++) { + CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[i], 0.05, DELTA); + } +} + + +// Check LRC phase response +void +qa_gr_cpm::t2 () +{ + std::vector<float> taps(gr_cpm::phase_response(gr_cpm::LRC, samples_per_sym, L)); + float sum = 0; + + for (int i = 0; i < L * samples_per_sym; i++) { + CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[i], taps_lrc[i], DELTA); + sum += taps[i]; + } + + CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0, DELTA); +} + + +// Check LSRC phase response +void +qa_gr_cpm::t3 () +{ + std::vector<float> taps(gr_cpm::phase_response(gr_cpm::LSRC, samples_per_sym, L, 0.2)); + float sum = 0; + + for (int i = 0; i < L * samples_per_sym; i++) { + CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[i], taps_lsrc[i], DELTA); + sum += taps[i]; + } + + CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0, DELTA); +} + + +// Check the TFM phase response +void +qa_gr_cpm::t4 () +{ + std::vector<float> taps(gr_cpm::phase_response(gr_cpm::TFM, samples_per_sym, L)); + float sum = 0; + + for (int i = 0; i < L * samples_per_sym; i++) { + CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[i], taps_tfm[i], DELTA); + sum += taps[i]; + } + + CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0, DELTA); +} + + +// Check the Gaussian phase response +void +qa_gr_cpm::t5 () +{ + std::vector<float> taps(gr_cpm::phase_response(gr_cpm::GAUSSIAN, samples_per_sym, L, 0.3)); + float sum = 0; + + for (int i = 0; i < L * samples_per_sym; i++) { + CPPUNIT_ASSERT_DOUBLES_EQUAL(taps[i], taps_gaussian[i], DELTA); + sum += taps[i]; + } + + CPPUNIT_ASSERT_DOUBLES_EQUAL(sum, 1.0, DELTA); +} + diff --git a/gnuradio-core/src/lib/general/qa_gr_cpm.h b/gnuradio-core/src/lib/general/qa_gr_cpm.h new file mode 100644 index 000000000..2f46b42a7 --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_cpm.h @@ -0,0 +1,49 @@ +/* -*- c++ -*- */ +/* + * Copyright 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 _QA_GR_CPM_H +#define _QA_GR_CPM_H + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_gr_cpm : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_cpm); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST (t4); + CPPUNIT_TEST (t5); + CPPUNIT_TEST_SUITE_END (); + + private: + void t1 (); + void t2 (); + void t3 (); + void t4 (); + void t5 (); + +}; + + +#endif /* _QA_GR_CPM_H */ + diff --git a/gnuradio-core/src/lib/general/qa_gr_firdes.cc b/gnuradio-core/src/lib/general/qa_gr_firdes.cc new file mode 100644 index 000000000..877b4bd56 --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_firdes.cc @@ -0,0 +1,618 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 <qa_gr_firdes.h> +#include <gr_firdes.h> +#include <cppunit/TestAssert.h> +#include <gr_complex.h> +#include <string.h> +#include <iostream> +#include <iomanip> +#include <stdio.h> + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +using std::vector; + +#if 0 +static void +print_taps (std::ostream &s, vector<float> &v) +{ + + for (unsigned int i = 0; i < v.size (); i++){ + printf ("tap[%2d] = %16.7e\n", i, v[i]); + } +} +#endif + +static void +check_symmetry (vector<float> &v) +{ + int n = v.size (); + int m = n / 2; + + for (int i = 0; i < m; i++) + CPPUNIT_ASSERT_DOUBLES_EQUAL (v[i], v[n - i - 1], 1e-9); +} + +const static float t1_exp[53] = { + -9.0525491e-04, + 2.0713841e-04, + 1.2388536e-03, + 2.9683491e-04, + -1.7744775e-03, + -1.3599906e-03, + 2.2031884e-03, + 3.2744040e-03, + -1.8868084e-03, + -5.9935520e-03, + 6.4301129e-18, + 8.9516686e-03, + 4.2178580e-03, + -1.0998557e-02, + -1.1173409e-02, + 1.0455756e-02, + 2.0686293e-02, + -5.2032238e-03, + -3.1896964e-02, + -7.4998410e-03, + 4.3362070e-02, + 3.2502845e-02, + -5.3328082e-02, + -8.5621715e-02, + 6.0117975e-02, + 3.1128189e-01, + 4.3769023e-01, + 3.1128189e-01, + 6.0117975e-02, + -8.5621715e-02, + -5.3328082e-02, + 3.2502845e-02, + 4.3362070e-02, + -7.4998410e-03, + -3.1896964e-02, + -5.2032238e-03, + 2.0686293e-02, + 1.0455756e-02, + -1.1173409e-02, + -1.0998557e-02, + 4.2178580e-03, + 8.9516686e-03, + 6.4301129e-18, + -5.9935520e-03, + -1.8868084e-03, + 3.2744040e-03, + 2.2031884e-03, + -1.3599906e-03, + -1.7744775e-03, + 2.9683491e-04, + 1.2388536e-03, + 2.0713841e-04, + -9.0525491e-04 +}; + +const static float t2_exp[53] = { + 9.0380036e-04, + -2.0680559e-04, + -1.2368630e-03, + -2.9635796e-04, + 1.7716263e-03, + 1.3578053e-03, + -2.1996482e-03, + -3.2691427e-03, + 1.8837767e-03, + 5.9839217e-03, + -6.4197810e-18, + -8.9372853e-03, + -4.2110807e-03, + 1.0980885e-02, + 1.1155456e-02, + -1.0438956e-02, + -2.0653054e-02, + 5.1948633e-03, + 3.1845711e-02, + 7.4877902e-03, + -4.3292396e-02, + -3.2450620e-02, + 5.3242393e-02, + 8.5484132e-02, + -6.0021374e-02, + -3.1078172e-01, + 5.6184036e-01, + -3.1078172e-01, + -6.0021374e-02, + 8.5484132e-02, + 5.3242393e-02, + -3.2450620e-02, + -4.3292396e-02, + 7.4877902e-03, + 3.1845711e-02, + 5.1948633e-03, + -2.0653054e-02, + -1.0438956e-02, + 1.1155456e-02, + 1.0980885e-02, + -4.2110807e-03, + -8.9372853e-03, + -6.4197810e-18, + 5.9839217e-03, + 1.8837767e-03, + -3.2691427e-03, + -2.1996482e-03, + 1.3578053e-03, + 1.7716263e-03, + -2.9635796e-04, + -1.2368630e-03, + -2.0680559e-04, + 9.0380036e-04 +}; + +const static float t3_exp[107] = { + -1.8970841e-06, + -7.1057165e-04, + 5.4005696e-04, + 4.6233178e-04, + 2.0572044e-04, + 3.5209916e-04, + -1.4098573e-03, + 1.1279077e-04, + -6.2994129e-04, + 1.1450432e-03, + 1.3637283e-03, + -6.4360141e-04, + 3.6509900e-04, + -3.2864159e-03, + 7.0192874e-04, + 3.7524730e-04, + 2.0256115e-03, + 3.0641893e-03, + -3.6618244e-03, + 7.5592739e-05, + -5.5586505e-03, + 2.3849572e-03, + 4.0114378e-03, + 1.6636450e-03, + 4.7835698e-03, + -1.0191196e-02, + -3.8158931e-04, + -5.5551580e-03, + 5.3901658e-03, + 1.1366769e-02, + -3.0000482e-03, + 4.9341680e-03, + -2.0093076e-02, + 5.5752542e-17, + 1.2093617e-03, + 8.6089745e-03, + 2.2382140e-02, + -1.6854567e-02, + 1.6913920e-03, + -3.1222520e-02, + 3.2711059e-03, + 2.2604836e-02, + 8.1451107e-03, + 3.7583180e-02, + -5.2293688e-02, + -8.0551542e-03, + -4.0092729e-02, + 1.5582236e-02, + 9.7452506e-02, + -1.6183170e-02, + 8.3281815e-02, + -2.8196752e-01, + -1.0965768e-01, + 5.2867508e-01, + -1.0965768e-01, + -2.8196752e-01, + 8.3281815e-02, + -1.6183170e-02, + 9.7452506e-02, + 1.5582236e-02, + -4.0092729e-02, + -8.0551542e-03, + -5.2293688e-02, + 3.7583180e-02, + 8.1451107e-03, + 2.2604836e-02, + 3.2711059e-03, + -3.1222520e-02, + 1.6913920e-03, + -1.6854567e-02, + 2.2382140e-02, + 8.6089745e-03, + 1.2093617e-03, + 5.5752542e-17, + -2.0093076e-02, + 4.9341680e-03, + -3.0000482e-03, + 1.1366769e-02, + 5.3901658e-03, + -5.5551580e-03, + -3.8158931e-04, + -1.0191196e-02, + 4.7835698e-03, + 1.6636450e-03, + 4.0114378e-03, + 2.3849572e-03, + -5.5586505e-03, + 7.5592739e-05, + -3.6618244e-03, + 3.0641893e-03, + 2.0256115e-03, + 3.7524730e-04, + 7.0192874e-04, + -3.2864159e-03, + 3.6509900e-04, + -6.4360141e-04, + 1.3637283e-03, + 1.1450432e-03, + -6.2994129e-04, + 1.1279077e-04, + -1.4098573e-03, + 3.5209916e-04, + 2.0572044e-04, + 4.6233178e-04, + 5.4005696e-04, + -7.1057165e-04, + -1.8970841e-06 +}; + + +const static float t4_exp[] = { // low pass + 0.001059958362, +0.0002263929928, +-0.001277606934, +-0.0009675776237, + 0.001592264394, + 0.00243603508, +-0.001451682881, +-0.004769335967, +5.281541594e-18, + 0.007567512803, + 0.003658855334, +-0.009761494584, + -0.01011830103, + 0.009636915289, + 0.0193619132, +-0.004935568199, + -0.03060629964, +-0.007267376408, + 0.04236677289, + 0.03197422624, + -0.05274848267, + -0.0850463286, + 0.05989059806, + 0.31065014, + 0.4370569289, + 0.31065014, + 0.05989059806, + -0.0850463286, + -0.05274848267, + 0.03197422624, + 0.04236677289, +-0.007267376408, + -0.03060629964, +-0.004935568199, + 0.0193619132, + 0.009636915289, + -0.01011830103, +-0.009761494584, + 0.003658855334, + 0.007567512803, +5.281541594e-18, +-0.004769335967, +-0.001451682881, + 0.00243603508, + 0.001592264394, +-0.0009675776237, +-0.001277606934, +0.0002263929928, + 0.001059958362, +}; + + +const static float t5_exp[] = { //high pass +-0.001062123571, +-0.0002268554381, + 0.001280216733, + 0.000969554123, +-0.001595516922, +-0.002441011136, + 0.001454648213, + 0.004779078532, +-5.292330097e-18, +-0.007582970895, + -0.00366632943, + 0.009781434201, + 0.01013896987, +-0.009656600654, + -0.01940146461, + 0.004945650231, + 0.03066881932, + 0.00728222169, + -0.04245331511, + -0.03203954175, + 0.05285623297, + 0.08522006124, + -0.06001294032, + -0.3112847209, + 0.5630782247, + -0.3112847209, + -0.06001294032, + 0.08522006124, + 0.05285623297, + -0.03203954175, + -0.04245331511, + 0.00728222169, + 0.03066881932, + 0.004945650231, + -0.01940146461, +-0.009656600654, + 0.01013896987, + 0.009781434201, + -0.00366632943, +-0.007582970895, +-5.292330097e-18, + 0.004779078532, + 0.001454648213, +-0.002441011136, +-0.001595516922, + 0.000969554123, + 0.001280216733, +-0.0002268554381, +-0.001062123571, +}; + +const static float t6_exp[] = { // bandpass +0.0002809273137, +-0.001047327649, +7.936541806e-05, +-0.0004270860809, +0.0007595835486, +0.0008966081077, +-0.0004236323002, +0.0002423936094, +-0.002212299034, +0.0004807534278, +0.0002620361629, + 0.001443728455, + 0.002229931997, +-0.002720607212, +5.731141573e-05, +-0.004297634587, + 0.001878833398, + 0.003217151389, + 0.001357055153, + 0.003965090029, +-0.008576190099, +-0.0003257228818, +-0.004805727862, + 0.004721920472, + 0.01007549558, +-0.002688719891, + 0.004467967432, + -0.01837076992, +5.119658377e-17, + 0.001125075156, + 0.008071650751, + 0.02113764361, + -0.01602453552, + 0.001618095324, + -0.03004053794, + 0.003163811285, + 0.0219683405, + 0.007950295694, + 0.03682873398, + -0.05142467469, + -0.00794606097, + -0.03965795785, + 0.01544955093, + 0.09681399167, + -0.01610304788, + 0.08297294378, + -0.2811714709, + -0.1094062924, + 0.5275565982, + -0.1094062924, + -0.2811714709, + 0.08297294378, + -0.01610304788, + 0.09681399167, + 0.01544955093, + -0.03965795785, + -0.00794606097, + -0.05142467469, + 0.03682873398, + 0.007950295694, + 0.0219683405, + 0.003163811285, + -0.03004053794, + 0.001618095324, + -0.01602453552, + 0.02113764361, + 0.008071650751, + 0.001125075156, +5.119658377e-17, + -0.01837076992, + 0.004467967432, +-0.002688719891, + 0.01007549558, + 0.004721920472, +-0.004805727862, +-0.0003257228818, +-0.008576190099, + 0.003965090029, + 0.001357055153, + 0.003217151389, + 0.001878833398, +-0.004297634587, +5.731141573e-05, +-0.002720607212, + 0.002229931997, + 0.001443728455, +0.0002620361629, +0.0004807534278, +-0.002212299034, +0.0002423936094, +-0.0004236323002, +0.0008966081077, +0.0007595835486, +-0.0004270860809, +7.936541806e-05, +-0.001047327649, +0.0002809273137, +}; + +void +qa_gr_firdes::t1 () +{ + vector<float> taps = + gr_firdes::low_pass ( 1.0, + 8000, + 1750, + 500, + gr_firdes::WIN_HAMMING); + + // cout << "ntaps: " << taps.size () << endl; + // print_taps (cout, taps); + + CPPUNIT_ASSERT_EQUAL (NELEM (t1_exp), taps.size ()); + for (unsigned int i = 0; i < taps.size (); i++) + CPPUNIT_ASSERT_DOUBLES_EQUAL (t1_exp[i], taps[i], 1e-9); + + check_symmetry (taps); +} + +void +qa_gr_firdes::t2 () +{ + vector<float> taps = + gr_firdes::high_pass ( 1.0, + 8000, + 1750, + 500, + gr_firdes::WIN_HAMMING); + + // cout << "ntaps: " << taps.size () << endl; + // print_taps (cout, taps); + + CPPUNIT_ASSERT_EQUAL (NELEM (t2_exp), taps.size ()); + + for (unsigned int i = 0; i < taps.size (); i++) + CPPUNIT_ASSERT_DOUBLES_EQUAL (t2_exp[i], taps[i], 1e-9); + + check_symmetry (taps); +} + +void +qa_gr_firdes::t3 () +{ + vector<float> taps = + gr_firdes::band_pass ( 1.0, + 20e6, + 5.75e6 - (5.28e6/2), + 5.75e6 + (5.28e6/2), + 0.62e6, + gr_firdes::WIN_HAMMING); + + // cout << "ntaps: " << taps.size () << endl; + // print_taps (cout, taps); + + CPPUNIT_ASSERT_EQUAL (NELEM (t3_exp), taps.size ()); + + for (unsigned int i = 0; i < taps.size (); i++) + CPPUNIT_ASSERT_DOUBLES_EQUAL (t3_exp[i], taps[i], 1e-7); + + check_symmetry (taps); +} + +void +qa_gr_firdes::t4 () +{ + vector<float> taps = + gr_firdes::low_pass_2 ( 1.0, + 8000, + 1750, + 500, + 66, + gr_firdes::WIN_HAMMING); + + // std::cout << "ntaps: " << taps.size () << std::endl; + // print_taps (std::cout, taps); + + CPPUNIT_ASSERT_EQUAL (NELEM (t4_exp), taps.size ()); + for (unsigned int i = 0; i < taps.size (); i++) + CPPUNIT_ASSERT_DOUBLES_EQUAL (t4_exp[i], taps[i], 1e-9); + + + check_symmetry (taps); +} + +void +qa_gr_firdes::t5 () +{ + vector<float> taps = + gr_firdes::high_pass_2 ( 1.0, + 8000, + 1750, + 500, + 66, + gr_firdes::WIN_HAMMING); + + // std::cout << "ntaps: " << taps.size () << std::endl; + // print_taps (std::cout, taps); + + CPPUNIT_ASSERT_EQUAL (NELEM (t5_exp), taps.size ()); + + for (unsigned int i = 0; i < taps.size (); i++) + CPPUNIT_ASSERT_DOUBLES_EQUAL (t5_exp[i], taps[i], 1e-9); + + check_symmetry (taps); +} + +void +qa_gr_firdes::t6 () +{ + vector<float> taps = + gr_firdes::band_pass_2 ( 1.0, + 20e6, + 5.75e6 - (5.28e6/2), + 5.75e6 + (5.28e6/2), + 0.62e6, + 66, + gr_firdes::WIN_HAMMING); + + // std::cout << "ntaps: " << taps.size () << std::endl; + // print_taps (std::cout, taps); + + CPPUNIT_ASSERT_EQUAL (NELEM (t6_exp), taps.size ()); + + for (unsigned int i = 0; i < taps.size (); i++) + CPPUNIT_ASSERT_DOUBLES_EQUAL (t6_exp[i], taps[i], 1e-7); + + check_symmetry (taps); +} + +void +qa_gr_firdes::t7 () +{ +} diff --git a/gnuradio-core/src/lib/general/qa_gr_firdes.h b/gnuradio-core/src/lib/general/qa_gr_firdes.h new file mode 100644 index 000000000..98cee99b9 --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_firdes.h @@ -0,0 +1,52 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_GR_FIRDES_H_ +#define _QA_GR_FIRDES_H_ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_gr_firdes : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_firdes); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST (t4); + CPPUNIT_TEST (t5); + CPPUNIT_TEST (t6); + CPPUNIT_TEST (t7); + CPPUNIT_TEST_SUITE_END (); + + private: + void t1 (); + void t2 (); + void t3 (); + void t4 (); + void t5 (); + void t6 (); + void t7 (); + +}; + + +#endif /* _QA_GR_FIRDES_H_ */ diff --git a/gnuradio-core/src/lib/general/qa_gr_fxpt.cc b/gnuradio-core/src/lib/general/qa_gr_fxpt.cc new file mode 100644 index 000000000..7eac0d896 --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_fxpt.cc @@ -0,0 +1,103 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <qa_gr_fxpt.h> +#include <gr_fxpt.h> +#include <cppunit/TestAssert.h> +#include <iostream> +#include <stdio.h> +#include <unistd.h> +#include <math.h> + +static const float SIN_COS_TOLERANCE = 1e-5; + +void +qa_gr_fxpt::t0 () +{ + CPPUNIT_ASSERT_DOUBLES_EQUAL (M_PI/2, gr_fxpt::fixed_to_float (0x40000000), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL (0.0, gr_fxpt::fixed_to_float (0x00000000), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL (-M_PI, gr_fxpt::fixed_to_float (0x80000000), SIN_COS_TOLERANCE); + + if (0){ + /* + * These are disabled because of some precision issues. + * + * Different compilers seem to have different opinions on whether + * the calulations are done single or double (or extended) + * precision. Any of the answers are fine for our real purpose, but + * sometimes the answer is off by a few bits at the bottom. + * Hence, the disabled check. + */ + CPPUNIT_ASSERT_EQUAL ((gr_int32) 0x40000000, gr_fxpt::float_to_fixed (M_PI/2)); + CPPUNIT_ASSERT_EQUAL ((gr_int32) 0, gr_fxpt::float_to_fixed (0)); + CPPUNIT_ASSERT_EQUAL ((gr_int32) 0x80000000, gr_fxpt::float_to_fixed (-M_PI)); + } +} + +void +qa_gr_fxpt::t1 () +{ + + CPPUNIT_ASSERT_DOUBLES_EQUAL ( 0, gr_fxpt::sin (0x00000000), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL ( 0.707106781, gr_fxpt::sin (0x20000000), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL ( 1, gr_fxpt::sin (0x40000000), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL ( 0.707106781, gr_fxpt::sin (0x60000000), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL ( 0, gr_fxpt::sin (0x7fffffff), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL ( 0, gr_fxpt::sin (0x80000000), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL ( 0, gr_fxpt::sin (0x80000001), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL (-1, gr_fxpt::sin (-0x40000000), SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL (-0.707106781, gr_fxpt::sin (-0x20000000), SIN_COS_TOLERANCE); + + + for (float p = -M_PI; p < M_PI; p += 2 * M_PI / 3600){ + float expected = sin (p); + float actual = gr_fxpt::sin (gr_fxpt::float_to_fixed (p)); + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected, actual, SIN_COS_TOLERANCE); + } +} + +void +qa_gr_fxpt::t2 () +{ + for (float p = -M_PI; p < M_PI; p += 2 * M_PI / 3600){ + float expected = cos (p); + float actual = gr_fxpt::cos (gr_fxpt::float_to_fixed (p)); + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected, actual, SIN_COS_TOLERANCE); + } +} + +void +qa_gr_fxpt::t3 () +{ + for (float p = -M_PI; p < M_PI; p += 2 * M_PI / 3600){ + float expected_sin = sin (p); + float expected_cos = cos (p); + float actual_sin; + float actual_cos; + gr_fxpt::sincos (gr_fxpt::float_to_fixed (p), &actual_sin, &actual_cos); + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected_sin, actual_sin, SIN_COS_TOLERANCE); + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected_cos, actual_cos, SIN_COS_TOLERANCE); + } +} diff --git a/gnuradio-core/src/lib/general/qa_gr_fxpt.h b/gnuradio-core/src/lib/general/qa_gr_fxpt.h new file mode 100644 index 000000000..72211563e --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_fxpt.h @@ -0,0 +1,48 @@ +/* -*- 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_QA_GR_FXPT_H +#define INCLUDED_QA_GR_FXPT_H + + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_gr_fxpt : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_fxpt); + CPPUNIT_TEST (t0); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST_SUITE_END (); + + private: + void t0 (); + void t1 (); + void t2 (); + void t3 (); + +}; + +#endif /* INCLUDED_QA_GR_FXPT_H */ + + diff --git a/gnuradio-core/src/lib/general/qa_gr_fxpt_nco.cc b/gnuradio-core/src/lib/general/qa_gr_fxpt_nco.cc new file mode 100644 index 000000000..6f208eac8 --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_fxpt_nco.cc @@ -0,0 +1,119 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <qa_gr_fxpt_nco.h> +#include <gr_fxpt_nco.h> +#include <gr_nco.h> +#include <cppunit/TestAssert.h> +#include <iostream> +#include <stdio.h> +#include <unistd.h> +#include <math.h> + +static const float SIN_COS_TOLERANCE = 1e-5; + +//static const float SIN_COS_FREQ = 5003; +static const float SIN_COS_FREQ = 4096; + +static const int SIN_COS_BLOCK_SIZE = 100000; + +static double max_d(double a, double b) +{ + return fabs(a) > fabs(b) ? a : b; +} + +void +qa_gr_fxpt_nco::t0 () +{ + gr_nco<float,float> ref_nco; + gr_fxpt_nco new_nco; + double max_error = 0, max_phase_error = 0; + + ref_nco.set_freq ((float)(2 * M_PI / SIN_COS_FREQ)); + new_nco.set_freq ((float)(2 * M_PI / SIN_COS_FREQ)); + + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_nco.get_freq(), new_nco.get_freq(), SIN_COS_TOLERANCE); + + for (int i = 0; i < SIN_COS_BLOCK_SIZE; i++){ + float ref_sin = ref_nco.sin (); + float new_sin = new_nco.sin (); + //printf ("i = %6d\n", i); + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_sin, new_sin, SIN_COS_TOLERANCE); + + max_error = max_d (max_error, ref_sin-new_sin); + + float ref_cos = ref_nco.cos (); + float new_cos = new_nco.cos (); + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_cos, new_cos, SIN_COS_TOLERANCE); + + max_error = max_d (max_error, ref_cos-new_cos); + + ref_nco.step (); + new_nco.step (); + + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_nco.get_phase(), new_nco.get_phase(), SIN_COS_TOLERANCE); + + max_phase_error = max_d (max_phase_error, ref_nco.get_phase()-new_nco.get_phase()); + } + // printf ("Fxpt max error %.9f, max phase error %.9f\n", max_error, max_phase_error); +} + +void +qa_gr_fxpt_nco::t1 () +{ + gr_nco<float,float> ref_nco; + gr_fxpt_nco new_nco; + gr_complex ref_block[SIN_COS_BLOCK_SIZE]; + gr_complex new_block[SIN_COS_BLOCK_SIZE]; + double max_error = 0; + + ref_nco.set_freq ((float)(2 * M_PI / SIN_COS_FREQ)); + new_nco.set_freq ((float)(2 * M_PI / SIN_COS_FREQ)); + + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_nco.get_freq(), new_nco.get_freq(), SIN_COS_TOLERANCE); + + ref_nco.sincos ((gr_complex*)ref_block, SIN_COS_BLOCK_SIZE); + new_nco.sincos ((gr_complex*)new_block, SIN_COS_BLOCK_SIZE); + + for (int i = 0; i < SIN_COS_BLOCK_SIZE; i++){ + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_block[i].real(), new_block[i].real(), SIN_COS_TOLERANCE); + max_error = max_d (max_error, ref_block[i].real()-new_block[i].real()); + + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_block[i].imag(), new_block[i].imag(), SIN_COS_TOLERANCE); + max_error = max_d (max_error, ref_block[i].imag()-new_block[i].imag()); + } + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_nco.get_phase(), new_nco.get_phase(), SIN_COS_TOLERANCE); + // printf ("Fxpt max error %.9f, max phase error %.9f\n", max_error, max_phase_error); +} + +void +qa_gr_fxpt_nco::t2 () +{ +} + +void +qa_gr_fxpt_nco::t3 () +{ +} diff --git a/gnuradio-core/src/lib/general/qa_gr_fxpt_nco.h b/gnuradio-core/src/lib/general/qa_gr_fxpt_nco.h new file mode 100644 index 000000000..8998922bb --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_fxpt_nco.h @@ -0,0 +1,48 @@ +/* -*- 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_QA_GR_FXPT_NCO_H +#define INCLUDED_QA_GR_FXPT_NCO_H + + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_gr_fxpt_nco : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_fxpt_nco); + CPPUNIT_TEST (t0); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST_SUITE_END (); + + private: + void t0 (); + void t1 (); + void t2 (); + void t3 (); + +}; + +#endif /* INCLUDED_QA_GR_FXPT_NCO_H */ + + diff --git a/gnuradio-core/src/lib/general/qa_gr_fxpt_vco.cc b/gnuradio-core/src/lib/general/qa_gr_fxpt_vco.cc new file mode 100644 index 000000000..5b6993a30 --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_fxpt_vco.cc @@ -0,0 +1,110 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <qa_gr_fxpt_vco.h> +#include <gr_fxpt_vco.h> +#include <gr_vco.h> +#include <cppunit/TestAssert.h> +#include <iostream> +#include <stdio.h> +#include <unistd.h> +#include <math.h> + +static const float SIN_COS_TOLERANCE = 1e-5; + +static const float SIN_COS_K = 0.42; +static const float SIN_COS_AMPL = 0.8; + +static const int SIN_COS_BLOCK_SIZE = 100000; + +static double max_d(double a, double b) +{ + return fabs(a) > fabs(b) ? a : b; +} + +void +qa_gr_fxpt_vco::t0 () +{ + gr_vco<float,float> ref_vco; + gr_fxpt_vco new_vco; + double max_error = 0, max_phase_error = 0; + float input[SIN_COS_BLOCK_SIZE]; + + for (int i = 0; i < SIN_COS_BLOCK_SIZE; i++){ + input[i] = sin(double(i)); + } + + for (int i = 0; i < SIN_COS_BLOCK_SIZE; i++){ + float ref_cos = ref_vco.cos (); + float new_cos = new_vco.cos (); + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_cos, new_cos, SIN_COS_TOLERANCE); + + max_error = max_d (max_error, ref_cos-new_cos); + + ref_vco.adjust_phase (input[i]); + new_vco.adjust_phase (input[i]); + + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_vco.get_phase(), new_vco.get_phase(), SIN_COS_TOLERANCE); + + max_phase_error = max_d (max_phase_error, ref_vco.get_phase()-new_vco.get_phase()); + } + // printf ("Fxpt max error %.9f, max phase error %.9f\n", max_error, max_phase_error); +} + + +void +qa_gr_fxpt_vco::t1 () +{ + gr_vco<float,float> ref_vco; + gr_fxpt_vco new_vco; + float ref_block[SIN_COS_BLOCK_SIZE]; + float new_block[SIN_COS_BLOCK_SIZE]; + float input[SIN_COS_BLOCK_SIZE]; + double max_error = 0; + + for (int i = 0; i < SIN_COS_BLOCK_SIZE; i++){ + input[i] = sin(double(i)); + } + + ref_vco.cos (ref_block, input, SIN_COS_BLOCK_SIZE, SIN_COS_K, SIN_COS_AMPL); + new_vco.cos (new_block, input, SIN_COS_BLOCK_SIZE, SIN_COS_K, SIN_COS_AMPL); + + for (int i = 0; i < SIN_COS_BLOCK_SIZE; i++){ + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_block[i], new_block[i], SIN_COS_TOLERANCE); + max_error = max_d (max_error, ref_block[i]-new_block[i]); + } + CPPUNIT_ASSERT_DOUBLES_EQUAL (ref_vco.get_phase(), new_vco.get_phase(), SIN_COS_TOLERANCE); + // printf ("Fxpt max error %.9f, max phase error %.9f\n", max_error, ref_vco.get_phase()-new_vco.get_phase()); +} + +void +qa_gr_fxpt_vco::t2 () +{ +} + +void +qa_gr_fxpt_vco::t3 () +{ +} diff --git a/gnuradio-core/src/lib/general/qa_gr_fxpt_vco.h b/gnuradio-core/src/lib/general/qa_gr_fxpt_vco.h new file mode 100644 index 000000000..fab8022e3 --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_fxpt_vco.h @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_QA_GR_FXPT_VCO_H +#define INCLUDED_QA_GR_FXPT_VCO_H + + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_gr_fxpt_vco : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_fxpt_vco); + CPPUNIT_TEST (t0); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST_SUITE_END (); + + private: + void t0 (); + void t1 (); + void t2 (); + void t3 (); + +}; + +#endif /* INCLUDED_QA_GR_FXPT_VCO_H */ + + diff --git a/gnuradio-core/src/lib/general/qa_gr_math.cc b/gnuradio-core/src/lib/general/qa_gr_math.cc new file mode 100644 index 000000000..74d51b536 --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_math.cc @@ -0,0 +1,105 @@ +/* + * 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 <gr_math.h> +#include <qa_gr_math.h> +#include <cppunit/TestAssert.h> +#include <stdio.h> + +void +qa_gr_math::test_binary_slicer1 () +{ + float x[5] = {-1, -0.5, 0, 0.5, 1.0}; + unsigned int z[5] = {0, 0, 1, 1, 1}; + unsigned int y; + + //printf("\nBinary\n"); + for (unsigned int i = 0; i < 5; i++) { + y = gr_binary_slicer(x[i]); + //printf("in: %f out: %d desired: %d\n", x[i], y, z[i]); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(y, z[i], 1e-9); + } + + //printf("\nBranchless Binary\n"); + for (unsigned int i = 0; i < 5; i++) { + y = gr_branchless_binary_slicer(x[i]); + //printf("in: %f out: %d desired: %d\n", x[i], y, z[i]); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(y, z[i], 1e-9); + } +} + +void +qa_gr_math::test_quad_0deg_slicer1 () +{ + gr_complex x[4] = {gr_complex(1, 0), + gr_complex(0, 1), + gr_complex(-1, 0), + gr_complex(0, -1)}; + + unsigned int z[4] = {0, 1, 2, 3}; + unsigned int y; + + //printf("\nQuad0\n"); + for (unsigned int i = 0; i < 4; i++) { + y = gr_quad_0deg_slicer(x[i]); + //printf("in: %.4f+j%.4f out: %d desired: %d\n", x[i].real(), x[i].imag(), y, z[i]); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(y, z[i], 1e-9); + } + + //printf("\nBranchless Quad0\n"); + for (unsigned int i = 0; i < 4; i++) { + y = gr_branchless_quad_0deg_slicer(x[i]); + //printf("in: %.4f+j%.4f out: %d desired: %d\n", x[i].real(), x[i].imag(), y, z[i]); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(y, z[i], 1e-9); + } +} + +void +qa_gr_math::test_quad_45deg_slicer1 () +{ + gr_complex x[4] = {gr_complex(0.707, 0.707), + gr_complex(-0.707, 0.707), + gr_complex(-0.707, -0.707), + gr_complex(0.707, -0.707)}; + + unsigned int z[4] = {0, 1, 2, 3}; + unsigned int y; + + //printf("\nQuad45\n"); + for (unsigned int i = 0; i < 4; i++) { + y = gr_quad_45deg_slicer(x[i]); + //printf("in: %.4f+j%.4f out: %d desired: %d\n", x[i].real(), x[i].imag(), y, z[i]); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(y, z[i], 1e-9); + } + + //printf("\nBranchless Quad45\n"); + for (unsigned int i = 0; i < 4; i++) { + y = gr_branchless_quad_45deg_slicer(x[i]); + //printf("in: %.4f+j%.4f out: %d desired: %d\n", x[i].real(), x[i].imag(), y, z[i]); + + CPPUNIT_ASSERT_DOUBLES_EQUAL(y, z[i], 1e-9); + } +} diff --git a/gnuradio-core/src/lib/general/qa_gr_math.h b/gnuradio-core/src/lib/general/qa_gr_math.h new file mode 100644 index 000000000..86858c03d --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_math.h @@ -0,0 +1,42 @@ +/* -*- 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_GR_MATH_H_ +#define _QA_GR_MATH_H_ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_gr_math : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE(qa_gr_math); + CPPUNIT_TEST(test_binary_slicer1); + CPPUNIT_TEST(test_quad_0deg_slicer1); + CPPUNIT_TEST(test_quad_45deg_slicer1); + CPPUNIT_TEST_SUITE_END(); + + private: + void test_binary_slicer1(); + void test_quad_0deg_slicer1(); + void test_quad_45deg_slicer1(); +}; + +#endif /* _QA_GR_MATH_H_ */ diff --git a/gnuradio-core/src/lib/general/qa_gri_lfsr.cc b/gnuradio-core/src/lib/general/qa_gri_lfsr.cc new file mode 100644 index 000000000..87d610df6 --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gri_lfsr.cc @@ -0,0 +1,142 @@ +/* + * 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 new file mode 100644 index 000000000..e91843bbb --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gri_lfsr.h @@ -0,0 +1,42 @@ +/* -*- 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/general/random.h b/gnuradio-core/src/lib/general/random.h new file mode 100644 index 000000000..c643c3e42 --- /dev/null +++ b/gnuradio-core/src/lib/general/random.h @@ -0,0 +1,38 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003, 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 _RANDOM_H_ +#define _RANDOM_H_ + +// While rand(3) specifies RAND_MAX, random(3) says that the output +// ranges from 0 to 2^31-1 but does not specify a macro to denote +// this. We define RANDOM_MAX for cleanliness. We must omit the +// definition for systems that have made the same choice. (Note that +// random(3) is from 4.2BSD, and not specified by POSIX.) + +#ifndef RANDOM_MAX +static const int RANDOM_MAX = 2147483647; // 2^31-1 +#endif /* RANDOM_MAX */ + +#include <stdlib.h> + +#endif // _RANDOM_H_ diff --git a/gnuradio-core/src/lib/general/sine_table.h b/gnuradio-core/src/lib/general/sine_table.h new file mode 100644 index 000000000..69834943b --- /dev/null +++ b/gnuradio-core/src/lib/general/sine_table.h @@ -0,0 +1,1025 @@ + // max_error = 2.353084136763606e-06 + { 2.925817799165007e-09, 7.219194364267018e-09 }, + { 2.925707643778599e-09, 2.526699001579799e-07 }, + { 2.925487337153070e-09, 1.191140162167675e-06 }, + { 2.925156887582842e-09, 3.284585035595589e-06 }, + { 2.924716307509151e-09, 6.994872605695784e-06 }, + { 2.924165613519592e-09, 1.278374920658798e-05 }, + { 2.923504826347475e-09, 2.111280464718590e-05 }, + { 2.922733970871080e-09, 3.244343744537165e-05 }, + { 2.921853076112655e-09, 4.723682007436170e-05 }, + { 2.920862175237416e-09, 6.595386421935634e-05 }, + { 2.919761305552202e-09, 8.905518605213658e-05 }, + { 2.918550508504146e-09, 1.170010715193098e-04 }, + { 2.917229829679050e-09, 1.502514416517192e-04 }, + { 2.915799318799769e-09, 1.892658178912071e-04 }, + { 2.914259029724184e-09, 2.345032874456615e-04 }, + { 2.912609020443340e-09, 2.864224686607020e-04 }, + { 2.910849353079123e-09, 3.454814764261432e-04 }, + { 2.908980093882049e-09, 4.121378876027343e-04 }, + { 2.907001313228646e-09, 4.868487064877691e-04 }, + { 2.904913085618902e-09, 5.700703303049837e-04 }, + { 2.902715489673383e-09, 6.622585147355725e-04 }, + { 2.900408608130373e-09, 7.638683394782519e-04 }, + { 2.897992527842612e-09, 8.753541738578119e-04 }, + { 2.895467339774186e-09, 9.971696424604937e-04 }, + { 2.892833138996999e-09, 1.129767590823255e-03 }, + { 2.890090024687216e-09, 1.273600051161478e-03 }, + { 2.887238100121550e-09, 1.429118208142094e-03 }, + { 2.884277472673313e-09, 1.596772364709564e-03 }, + { 2.881208253808507e-09, 1.777011907950626e-03 }, + { 2.878030559081432e-09, 1.970285275029487e-03 }, + { 2.874744508130554e-09, 2.177039919152579e-03 }, + { 2.871350224673798e-09, 2.397722275614272e-03 }, + { 2.867847836504030e-09, 2.632777727878843e-03 }, + { 2.864237475484149e-09, 2.882650573737405e-03 }, + { 2.860519277542297e-09, 3.147783991507308e-03 }, + { 2.856693382666432e-09, 3.428620006328931e-03 }, + { 2.852759934899389e-09, 3.725599456482154e-03 }, + { 2.848719082333207e-09, 4.039161959812243e-03 }, + { 2.844570977103752e-09, 4.369745880190706e-03 }, + { 2.840315775384800e-09, 4.717788294077374e-03 }, + { 2.835953637382310e-09, 5.083724957128360e-03 }, + { 2.831484727328322e-09, 5.467990270896617e-03 }, + { 2.826909213474759e-09, 5.871017249604038e-03 }, + { 2.822227268087134e-09, 6.293237486988512e-03 }, + { 2.817439067438018e-09, 6.735081123237729e-03 }, + { 2.812544791800534e-09, 7.196976811989608e-03 }, + { 2.807544625441273e-09, 7.679351687456759e-03 }, + { 2.802438756613836e-09, 8.182631331563162e-03 }, + { 2.797227377551135e-09, 8.707239741274575e-03 }, + { 2.791910684458716e-09, 9.253599295902304e-03 }, + { 2.786488877507140e-09, 9.822130724578715e-03 }, + { 2.780962160824228e-09, 1.041325307382490e-02 }, + { 2.775330742487884e-09, 1.102738367513773e-02 }, + { 2.769594834517682e-09, 1.166493811278924e-02 }, + { 2.763754652867477e-09, 1.232633019159818e-02 }, + { 2.757810417416620e-09, 1.301197190494069e-02 }, + { 2.751762351962413e-09, 1.372227340270610e-02 }, + { 2.745610684210923e-09, 1.445764295952962e-02 }, + { 2.739355645769094e-09, 1.521848694296229e-02 }, + { 2.732997472135539e-09, 1.600520978188769e-02 }, + { 2.726536402691907e-09, 1.681821393496225e-02 }, + { 2.719972680693777e-09, 1.765789985920713e-02 }, + { 2.713306553261610e-09, 1.852466597868779e-02 }, + { 2.706538271371373e-09, 1.941890865333146e-02 }, + { 2.699668089844909e-09, 2.034102214787814e-02 }, + { 2.692696267340880e-09, 2.129139860085272e-02 }, + { 2.685623066344263e-09, 2.227042799383416e-02 }, + { 2.678448753157212e-09, 2.327849812064098e-02 }, + { 2.671173597888530e-09, 2.431599455681316e-02 }, + { 2.663797874443630e-09, 2.538330062913108e-02 }, + { 2.656321860514457e-09, 2.648079738524795e-02 }, + { 2.648745837568575e-09, 2.760886356354952e-02 }, + { 2.641070090839117e-09, 2.876787556300114e-02 }, + { 2.633294909313421e-09, 2.995820741329835e-02 }, + { 2.625420585722845e-09, 3.118023074495535e-02 }, + { 2.617447416531143e-09, 3.243431475972608e-02 }, + { 2.609375701923643e-09, 3.372082620101990e-02 }, + { 2.601205745795833e-09, 3.504012932452527e-02 }, + { 2.592937855741933e-09, 3.639258586895711e-02 }, + { 2.584572343043400e-09, 3.777855502693250e-02 }, + { 2.576109522656942e-09, 3.919839341605197e-02 }, + { 2.567549713203028e-09, 4.065245505002102e-02 }, + { 2.558893236953688e-09, 4.214109131001403e-02 }, + { 2.550140419820252e-09, 4.366465091617666e-02 }, + { 2.541291591341445e-09, 4.522347989919473e-02 }, + { 2.532347084670572e-09, 4.681792157215026e-02 }, + { 2.523307236563343e-09, 4.844831650239501e-02 }, + { 2.514172387364900e-09, 5.011500248369893e-02 }, + { 2.504942880997064e-09, 5.181831450849345e-02 }, + { 2.495619064945627e-09, 5.355858474024022e-02 }, + { 2.486201290246928e-09, 5.533614248606705e-02 }, + { 2.476689911475047e-09, 5.715131416942842e-02 }, + { 2.467085286727668e-09, 5.900442330315692e-02 }, + { 2.457387777613798e-09, 6.089579046229943e-02 }, + { 2.447597749239101e-09, 6.282573325755320e-02 }, + { 2.437715570192557e-09, 6.479456630859221e-02 }, + { 2.427741612532542e-09, 6.680260121764925e-02 }, + { 2.417676251773166e-09, 6.885014654319160e-02 }, + { 2.407519866869294e-09, 7.093750777401114e-02 }, + { 2.397272840203310e-09, 7.306498730310884e-02 }, + { 2.386935557569868e-09, 7.523288440214027e-02 }, + { 2.376508408161815e-09, 7.744149519577415e-02 }, + { 2.365991784555363e-09, 7.969111263635709e-02 }, + { 2.355386082695641e-09, 8.198202647865405e-02 }, + { 2.344691701881232e-09, 8.431452325495814e-02 }, + { 2.333909044749407e-09, 8.668888625021409e-02 }, + { 2.323038517261246e-09, 8.910539547731611e-02 }, + { 2.312080528685971e-09, 9.156432765274414e-02 }, + { 2.301035491585642e-09, 9.406595617227698e-02 }, + { 2.289903821799651e-09, 9.661055108691619e-02 }, + { 2.278685938428940e-09, 9.919837907903295e-02 }, + { 2.267382263820762e-09, 1.018297034385580e-01 }, + { 2.255993223551837e-09, 1.045047840397028e-01 }, + { 2.244519246413220e-09, 1.072238773174577e-01 }, + { 2.232960764393620e-09, 1.099872362446146e-01 }, + { 2.221318212663309e-09, 1.127951103088245e-01 }, + { 2.209592029557811e-09, 1.156477454898748e-01 }, + { 2.197782656561395e-09, 1.185453842371912e-01 }, + { 2.185890538290176e-09, 1.214882654476019e-01 }, + { 2.173916122475606e-09, 1.244766244431883e-01 }, + { 2.161859859947797e-09, 1.275106929493488e-01 }, + { 2.149722204618256e-09, 1.305906990731841e-01 }, + { 2.137503613462743e-09, 1.337168672820376e-01 }, + { 2.125204546504321e-09, 1.368894183821595e-01 }, + { 2.112825466795944e-09, 1.401085694976751e-01 }, + { 2.100366840402933e-09, 1.433745340497602e-01 }, + { 2.087829136385612e-09, 1.466875217359607e-01 }, + { 2.075212826781308e-09, 1.500477385098620e-01 }, + { 2.062518386587093e-09, 1.534553865607503e-01 }, + { 2.049746293741359e-09, 1.569106642937665e-01 }, + { 2.036897029106193e-09, 1.604137663100403e-01 }, + { 2.023971076449323e-09, 1.639648833871233e-01 }, + { 2.010968922425217e-09, 1.675642024598467e-01 }, + { 1.997891056557933e-09, 1.712119066008896e-01 }, + { 1.984737971221581e-09, 1.749081750021970e-01 }, + { 1.971510161622434e-09, 1.786531829561379e-01 }, + { 1.958208125780130e-09, 1.824471018371070e-01 }, + { 1.944832364508511e-09, 1.862900990834311e-01 }, + { 1.931383381397782e-09, 1.901823381790926e-01 }, + { 1.917861682794392e-09, 1.941239786363039e-01 }, + { 1.904267777782611e-09, 1.981151759777950e-01 }, + { 1.890602178165317e-09, 2.021560817195309e-01 }, + { 1.876865398444616e-09, 2.062468433536743e-01 }, + { 1.863057955802572e-09, 2.103876043317229e-01 }, + { 1.849180370081465e-09, 2.145785040479915e-01 }, + { 1.835233163764673e-09, 2.188196778231083e-01 }, + { 1.821216861956509e-09, 2.231112568880342e-01 }, + { 1.807131992362945e-09, 2.274533683680190e-01 }, + { 1.792979085271234e-09, 2.318461352671018e-01 }, + { 1.778758673530482e-09, 2.362896764525300e-01 }, + { 1.764471292530943e-09, 2.407841066397789e-01 }, + { 1.750117480184598e-09, 2.453295363773890e-01 }, + { 1.735697776904342e-09, 2.499260720324433e-01 }, + { 1.721212725583874e-09, 2.545738157760434e-01 }, + { 1.706662871577097e-09, 2.592728655691494e-01 }, + { 1.692048762677849e-09, 2.640233151485341e-01 }, + { 1.677370949099090e-09, 2.688252540131204e-01 }, + { 1.662629983452104e-09, 2.736787674105404e-01 }, + { 1.647826420726167e-09, 2.785839363237506e-01 }, + { 1.632960818266680e-09, 2.835408374583758e-01 }, + { 1.618033735755429e-09, 2.885495432295704e-01 }, + { 1.603045735188609e-09, 2.936101217498361e-01 }, + { 1.587997380855918e-09, 2.987226368167127e-01 }, + { 1.572889239319430e-09, 3.038871479007593e-01 }, + { 1.557721879392051e-09, 3.091037101339017e-01 }, + { 1.542495872116447e-09, 3.143723742978435e-01 }, + { 1.527211790743024e-09, 3.196931868130269e-01 }, + { 1.511870210708909e-09, 3.250661897274744e-01 }, + { 1.496471709615926e-09, 3.304914207062036e-01 }, + { 1.481016867208896e-09, 3.359689130207621e-01 }, + { 1.465506265353924e-09, 3.414986955389885e-01 }, + { 1.449940488016384e-09, 3.470807927151147e-01 }, + { 1.434320121238994e-09, 3.527152245800635e-01 }, + { 1.418645753119802e-09, 3.584020067320109e-01 }, + { 1.402917973789838e-09, 3.641411503272979e-01 }, + { 1.387137375391042e-09, 3.699326620714776e-01 }, + { 1.371304552054134e-09, 3.757765442106153e-01 }, + { 1.355420099875958e-09, 3.816727945230153e-01 }, + { 1.339484616897137e-09, 3.876214063110671e-01 }, + { 1.323498703079580e-09, 3.936223683933865e-01 }, + { 1.307462960283922e-09, 3.996756650972121e-01 }, + { 1.291377992246768e-09, 4.057812762511174e-01 }, + { 1.275244404558188e-09, 4.119391771778626e-01 }, + { 1.259062804638585e-09, 4.181493386877248e-01 }, + { 1.242833801715929e-09, 4.244117270719281e-01 }, + { 1.226558006803155e-09, 4.307263040962509e-01 }, + { 1.210236032674760e-09, 4.370930269951803e-01 }, + { 1.193868493843725e-09, 4.435118484661861e-01 }, + { 1.177456006538695e-09, 4.499827166641340e-01 }, + { 1.160999188680582e-09, 4.565055751961679e-01 }, + { 1.144498659859216e-09, 4.630803631168164e-01 }, + { 1.127955041310214e-09, 4.697070149232604e-01 }, + { 1.111368955891417e-09, 4.763854605510119e-01 }, + { 1.094741028059551e-09, 4.831156253697562e-01 }, + { 1.078071883846871e-09, 4.898974301794375e-01 }, + { 1.061362150836978e-09, 4.967307912069362e-01 }, + { 1.044612458142151e-09, 5.036156201023686e-01 }, + { 1.027823436378632e-09, 5.105518239364775e-01 }, + { 1.010995717643647e-09, 5.175393051975563e-01 }, + { 9.941299354913699e-10, 5.245779617890562e-01 }, + { 9.772267249089968e-10, 5.316676870274011e-01 }, + { 9.602867222926046e-10, 5.388083696401416e-01 }, + { 9.433105654240147e-10, 5.459998937639375e-01 }, + { 9.262988934458084e-10, 5.532421389435711e-01 }, + { 9.092523468378193e-10, 5.605349801305876e-01 }, + { 8.921715673928355e-10, 5.678782876825250e-01 }, + { 8.750571981926701e-10, 5.752719273622372e-01 }, + { 8.579098835836508e-10, 5.827157603377209e-01 }, + { 8.407302691522673e-10, 5.902096431821322e-01 }, + { 8.235190017016133e-10, 5.977534278737073e-01 }, + { 8.062767292259225e-10, 6.053469617967722e-01 }, + { 7.890041008871165e-10, 6.129900877421282e-01 }, + { 7.717017669898175e-10, 6.206826439083659e-01 }, + { 7.543703789572603e-10, 6.284244639030392e-01 }, + { 7.370105893063053e-10, 6.362153767444958e-01 }, + { 7.196230516231919e-10, 6.440552068636356e-01 }, + { 7.022084205389746e-10, 6.519437741060674e-01 }, + { 6.847673517046416e-10, 6.598808937346672e-01 }, + { 6.673005017664976e-10, 6.678663764322770e-01 }, + { 6.498085283416530e-10, 6.759000283046127e-01 }, + { 6.322920899929834e-10, 6.839816508836737e-01 }, + { 6.147518462045659e-10, 6.921110411311926e-01 }, + { 5.971884573565851e-10, 7.002879914425926e-01 }, + { 5.796025847007168e-10, 7.085122896509806e-01 }, + { 5.619948903351406e-10, 7.167837190315758e-01 }, + { 5.443660371796048e-10, 7.251020583063744e-01 }, + { 5.267166889504394e-10, 7.334670816491009e-01 }, + { 5.090475101356742e-10, 7.418785586903696e-01 }, + { 4.913591659698399e-10, 7.503362545232619e-01 }, + { 4.736523224091392e-10, 7.588399297089872e-01 }, + { 4.559276461062478e-10, 7.673893402829834e-01 }, + { 4.381858043851147e-10, 7.759842377612828e-01 }, + { 4.204274652161870e-10, 7.846243691469355e-01 }, + { 4.026532971908398e-10, 7.933094769370790e-01 }, + { 3.848639694963359e-10, 8.020392991300200e-01 }, + { 3.670601518910503e-10, 8.108135692324444e-01 }, + { 3.492425146784233e-10, 8.196320162675177e-01 }, + { 3.314117286825031e-10, 8.284943647824689e-01 }, + { 3.135684652223755e-10, 8.374003348569865e-01 }, + { 2.957133960867535e-10, 8.463496421118015e-01 }, + { 2.778471935089361e-10, 8.553419977173513e-01 }, + { 2.599705301412391e-10, 8.643771084029740e-01 }, + { 2.420840790301135e-10, 8.734546764660205e-01 }, + { 2.241885135902046e-10, 8.825743997817682e-01 }, + { 2.062845075795238e-10, 8.917359718130367e-01 }, + { 1.883727350736140e-10, 9.009390816205823e-01 }, + { 1.704538704408269e-10, 9.101834138731877e-01 }, + { 1.525285883160648e-10, 9.194686488588080e-01 }, + { 1.345975635762696e-10, 9.287944624950824e-01 }, + { 1.166614713141648e-10, 9.381605263410157e-01 }, + { 9.872098681369190e-11, 9.475665076080466e-01 }, + { 8.077678552380464e-11, 9.570120691722380e-01 }, + { 6.282954303364090e-11, 9.664968695860140e-01 }, + { 4.487993504668797e-11, 9.760205630906909e-01 }, + { 2.692863735553042e-11, 9.855827996289697e-01 }, + { 8.976325816439114e-12, 9.951832248577780e-01 }, + { -8.976323676304494e-12, 1.004821480161519e+00 }, + { -2.692863521550168e-11, 1.014497202665280e+00 }, + { -4.487993290681805e-11, 1.024210025248670e+00 }, + { -6.282954089398273e-11, 1.033959576559617e+00 }, + { -8.077678338451706e-11, 1.043745481028715e+00 }, + { -9.872098467477489e-11, 1.053567358883467e+00 }, + { -1.166614691757772e-10, 1.063424826163223e+00 }, + { -1.345975614383584e-10, 1.073317494734013e+00 }, + { -1.525285861788948e-10, 1.083244972303963e+00 }, + { -1.704538683042922e-10, 1.093206862438572e+00 }, + { -1.883727329379793e-10, 1.103202764576806e+00 }, + { -2.062845054446831e-10, 1.113232274046796e+00 }, + { -2.241885114563697e-10, 1.123294982082432e+00 }, + { -2.420840768973375e-10, 1.133390475839767e+00 }, + { -2.599705280096278e-10, 1.143518338413855e+00 }, + { -2.778471913784365e-10, 1.153678148855860e+00 }, + { -2.957133939575774e-10, 1.163869482190458e+00 }, + { -3.135684630945758e-10, 1.174091909433296e+00 }, + { -3.314117265561857e-10, 1.184344997608959e+00 }, + { -3.492425125535882e-10, 1.194628309769018e+00 }, + { -3.670601497678034e-10, 1.204941405010466e+00 }, + { -3.848639673748360e-10, 1.215283838494269e+00 }, + { -4.026532950710339e-10, 1.225655161464298e+00 }, + { -4.204274630982869e-10, 1.236054921266445e+00 }, + { -4.381858022691734e-10, 1.246482661367958e+00 }, + { -4.559276439922654e-10, 1.256937921377146e+00 }, + { -4.736523202972214e-10, 1.267420237063216e+00 }, + { -4.913591638600925e-10, 1.277929140376502e+00 }, + { -5.090475080282032e-10, 1.288464159468706e+00 }, + { -5.267166868452449e-10, 1.299024818713528e+00 }, + { -5.443660350768455e-10, 1.309610638727845e+00 }, + { -5.619948882348695e-10, 1.320221136392390e+00 }, + { -5.796025826029868e-10, 1.330855824873457e+00 }, + { -5.971884552615020e-10, 1.341514213644420e+00 }, + { -6.147518441122357e-10, 1.352195808507556e+00 }, + { -6.322920879034590e-10, 1.362900111616144e+00 }, + { -6.498085262549874e-10, 1.373626621496939e+00 }, + { -6.673004996827436e-10, 1.384374833072571e+00 }, + { -6.847673496239581e-10, 1.395144237684605e+00 }, + { -7.022084184613616e-10, 1.405934323116231e+00 }, + { -7.196230495488082e-10, 1.416744573616104e+00 }, + { -7.370105872352039e-10, 1.427574469921397e+00 }, + { -7.543703768894941e-10, 1.438423489281758e+00 }, + { -7.717017649255453e-10, 1.449291105483472e+00 }, + { -7.890040988262324e-10, 1.460176788873383e+00 }, + { -8.062767271686383e-10, 1.471080006383765e+00 }, + { -8.235189996479819e-10, 1.482000221556656e+00 }, + { -8.407302671024475e-10, 1.492936894569018e+00 }, + { -8.579098815375368e-10, 1.503889482257845e+00 }, + { -8.750571961505266e-10, 1.514857438145604e+00 }, + { -8.921715653546624e-10, 1.525840212465756e+00 }, + { -9.092523448036167e-10, 1.536837252188703e+00 }, + { -9.262988914157881e-10, 1.547848001047890e+00 }, + { -9.433105633981766e-10, 1.558871899565883e+00 }, + { -9.602867202711075e-10, 1.569908385081254e+00 }, + { -9.772267228916820e-10, 1.580956891774897e+00 }, + { -9.941299334786078e-10, 1.592016850697478e+00 }, + { -1.010995715635332e-09, 1.603087689796053e+00 }, + { -1.027823434374870e-09, 1.614168833942028e+00 }, + { -1.044612456143047e-09, 1.625259704958335e+00 }, + { -1.061362148842745e-09, 1.636359721647526e+00 }, + { -1.078071881857297e-09, 1.647468299819543e+00 }, + { -1.094741026074900e-09, 1.658584852320419e+00 }, + { -1.111368953911690e-09, 1.669708789060341e+00 }, + { -1.127955039335462e-09, 1.680839517042381e+00 }, + { -1.144498657889600e-09, 1.691976440391624e+00 }, + { -1.160999186716154e-09, 1.703118960383971e+00 }, + { -1.177456004579561e-09, 1.714266475475616e+00 }, + { -1.193868491889832e-09, 1.725418381332405e+00 }, + { -1.210236030726319e-09, 1.736574070859850e+00 }, + { -1.226558004860220e-09, 1.747732934232508e+00 }, + { -1.242833799778447e-09, 1.758894358924547e+00 }, + { -1.259062802706714e-09, 1.770057729740021e+00 }, + { -1.275244402631982e-09, 1.781222428842935e+00 }, + { -1.291377990326492e-09, 1.792387835788660e+00 }, + { -1.307462958369363e-09, 1.803553327553897e+00 }, + { -1.323498701170897e-09, 1.814718278568759e+00 }, + { -1.339484614994490e-09, 1.825882060747428e+00 }, + { -1.355420097979292e-09, 1.837044043519582e+00 }, + { -1.371304550163662e-09, 1.848203593862598e+00 }, + { -1.387137373506711e-09, 1.859360076332671e+00 }, + { -1.402917971911754e-09, 1.870512853097495e+00 }, + { -1.418645751248018e-09, 1.881661283967967e+00 }, + { -1.434320119373722e-09, 1.892804726431080e+00 }, + { -1.449940486157623e-09, 1.903942535681972e+00 }, + { -1.465506263501516e-09, 1.915074064656886e+00 }, + { -1.481016865363264e-09, 1.926198664066737e+00 }, + { -1.496471707776859e-09, 1.937315682428795e+00 }, + { -1.511870208876724e-09, 1.948424466101625e+00 }, + { -1.527211788917509e-09, 1.959524359317042e+00 }, + { -1.542495870297867e-09, 1.970614704215133e+00 }, + { -1.557721877580406e-09, 1.981694840876775e+00 }, + { -1.572889237514880e-09, 1.992764107358707e+00 }, + { -1.587997379058514e-09, 2.003821839726753e+00 }, + { -1.603045733398246e-09, 2.014867372090665e+00 }, + { -1.618033733972424e-09, 2.025900036638798e+00 }, + { -1.632960816490822e-09, 2.036919163671778e+00 }, + { -1.647826418957721e-09, 2.047924081638631e+00 }, + { -1.662629981691070e-09, 2.058914117170269e+00 }, + { -1.677370947345626e-09, 2.069888595116115e+00 }, + { -1.692048760931849e-09, 2.080846838577820e+00 }, + { -1.706662869838827e-09, 2.091788168946183e+00 }, + { -1.721212723853279e-09, 2.102711905935372e+00 }, + { -1.735697775181424e-09, 2.113617367619504e+00 }, + { -1.750117478469621e-09, 2.124503870468520e+00 }, + { -1.764471290823748e-09, 2.135370729383332e+00 }, + { -1.778758671831281e-09, 2.146217257733207e+00 }, + { -1.792979083579974e-09, 2.157042767390815e+00 }, + { -1.807131990679890e-09, 2.167846568770014e+00 }, + { -1.821216860281448e-09, 2.178627970860822e+00 }, + { -1.835233162097977e-09, 2.189386281268046e+00 }, + { -1.849180368423027e-09, 2.200120806246095e+00 }, + { -1.863057954152340e-09, 2.210830850737588e+00 }, + { -1.876865396802907e-09, 2.221515718409926e+00 }, + { -1.890602176531920e-09, 2.232174711691990e+00 }, + { -1.904267776157843e-09, 2.242807131812679e+00 }, + { -1.917861681178094e-09, 2.253412278837029e+00 }, + { -1.931383379790273e-09, 2.263989451705295e+00 }, + { -1.944832362909578e-09, 2.274537948269257e+00 }, + { -1.958208124189984e-09, 2.285057065331676e+00 }, + { -1.971510160041235e-09, 2.295546098682665e+00 }, + { -1.984737969649064e-09, 2.306004343138794e+00 }, + { -1.997891054994522e-09, 2.316431092581699e+00 }, + { -2.010968920870647e-09, 2.326825639994779e+00 }, + { -2.023971074903858e-09, 2.337187277503834e+00 }, + { -2.036897027569834e-09, 2.347515296413520e+00 }, + { -2.049746292214264e-09, 2.357808987247877e+00 }, + { -2.062518385069210e-09, 2.368067639787542e+00 }, + { -2.075212825272584e-09, 2.378290543109652e+00 }, + { -2.087829134886364e-09, 2.388476985626922e+00 }, + { -2.100366838912949e-09, 2.398626255125417e+00 }, + { -2.112825465315542e-09, 2.408737638805759e+00 }, + { -2.125204545033289e-09, 2.418810423320288e+00 }, + { -2.137503612001452e-09, 2.428843894814472e+00 }, + { -2.149722203166389e-09, 2.438837338964302e+00 }, + { -2.161859858505829e-09, 2.448790041018174e+00 }, + { -2.173916121043380e-09, 2.458701285834241e+00 }, + { -2.185890536867478e-09, 2.468570357921585e+00 }, + { -2.197782655148702e-09, 2.478396541480230e+00 }, + { -2.209592028154913e-09, 2.488179120439544e+00 }, + { -2.221318211270522e-09, 2.497917378500214e+00 }, + { -2.232960763010574e-09, 2.507610599172123e+00 }, + { -2.244519245040444e-09, 2.517258065817044e+00 }, + { -2.255993222189014e-09, 2.526859061686102e+00 }, + { -2.267382262468209e-09, 2.536412869962689e+00 }, + { -2.278685937086658e-09, 2.545918773800664e+00 }, + { -2.289903820467374e-09, 2.555376056366064e+00 }, + { -2.301035490263848e-09, 2.564784000877677e+00 }, + { -2.312080527374447e-09, 2.574141890646339e+00 }, + { -2.323038515960257e-09, 2.583449009117307e+00 }, + { -2.333909043458635e-09, 2.592704639909166e+00 }, + { -2.344691700601153e-09, 2.601908066856634e+00 }, + { -2.355386081425938e-09, 2.611058574048749e+00 }, + { -2.365991783296513e-09, 2.620155445872768e+00 }, + { -2.376508406913500e-09, 2.629197967052127e+00 }, + { -2.386935556332088e-09, 2.638185422689490e+00 }, + { -2.397272838976436e-09, 2.647117098307332e+00 }, + { -2.407519865653114e-09, 2.655992279887846e+00 }, + { -2.417676250567891e-09, 2.664810253915885e+00 }, + { -2.427741611338014e-09, 2.673570307418169e+00 }, + { -2.437715569009093e-09, 2.682271728006635e+00 }, + { -2.447597748066437e-09, 2.690913803917100e+00 }, + { -2.457387776452357e-09, 2.699495824053297e+00 }, + { -2.467085285577292e-09, 2.708017078025636e+00 }, + { -2.476689910335470e-09, 2.716476856194105e+00 }, + { -2.486201289118733e-09, 2.724874449709689e+00 }, + { -2.495619063828443e-09, 2.733209150554255e+00 }, + { -2.504942879891263e-09, 2.741480251583985e+00 }, + { -2.514172386270163e-09, 2.749687046568741e+00 }, + { -2.523307235480146e-09, 2.757828830235740e+00 }, + { -2.532347083598520e-09, 2.765904898308531e+00 }, + { -2.541291590280960e-09, 2.773914547551261e+00 }, + { -2.550140418771202e-09, 2.781857075807392e+00 }, + { -2.558893235915887e-09, 2.789731782043156e+00 }, + { -2.567549712176927e-09, 2.797537966388929e+00 }, + { -2.576109521642196e-09, 2.805274930179221e+00 }, + { -2.584572342040407e-09, 2.812941975996573e+00 }, + { -2.592937854750428e-09, 2.820538407710556e+00 }, + { -2.601205744816134e-09, 2.828063530521908e+00 }, + { -2.609375700955458e-09, 2.835516651001539e+00 }, + { -2.617447415574869e-09, 2.842897077134583e+00 }, + { -2.625420584778350e-09, 2.850204118359573e+00 }, + { -2.633294908380520e-09, 2.857437085611509e+00 }, + { -2.641070089918234e-09, 2.864595291363663e+00 }, + { -2.648745836659391e-09, 2.871678049666939e+00 }, + { -2.656321859617343e-09, 2.878684676194483e+00 }, + { -2.663797873558322e-09, 2.885614488280000e+00 }, + { -2.671173597015318e-09, 2.892466804962122e+00 }, + { -2.678448752295859e-09, 2.899240947023252e+00 }, + { -2.685623065495139e-09, 2.905936237033475e+00 }, + { -2.692696266503800e-09, 2.912551999389617e+00 }, + { -2.699668089019767e-09, 2.919087560358171e+00 }, + { -2.706538270558513e-09, 2.925542248116882e+00 }, + { -2.713306552460767e-09, 2.931915392794031e+00 }, + { -2.719972679905295e-09, 2.938206326512581e+00 }, + { -2.726536401915442e-09, 2.944414383428562e+00 }, + { -2.732997471371516e-09, 2.950538899775061e+00 }, + { -2.739355645017194e-09, 2.956579213900666e+00 }, + { -2.745610683471516e-09, 2.962534666313284e+00 }, + { -2.751762351235315e-09, 2.968404599718795e+00 }, + { -2.757810416701751e-09, 2.974188359063684e+00 }, + { -2.763754652165128e-09, 2.979885291576143e+00 }, + { -2.769594833827588e-09, 2.985494746805227e+00 }, + { -2.775330741810390e-09, 2.991016076664491e+00 }, + { -2.780962160159068e-09, 2.996448635469842e+00 }, + { -2.786488876854607e-09, 3.001791779983262e+00 }, + { -2.791910683818570e-09, 3.007044869450794e+00 }, + { -2.797227376923695e-09, 3.012207265645876e+00 }, + { -2.802438755998943e-09, 3.017278332907412e+00 }, + { -2.807544624838820e-09, 3.022257438182037e+00 }, + { -2.812544791210840e-09, 3.027143951064684e+00 }, + { -2.817439066860792e-09, 3.031937243837070e+00 }, + { -2.822227267522746e-09, 3.036636691510884e+00 }, + { -2.826909212922864e-09, 3.041241671864994e+00 }, + { -2.831484726789317e-09, 3.045751565488710e+00 }, + { -2.835953636855826e-09, 3.050165755818853e+00 }, + { -2.840315774871260e-09, 3.054483629182857e+00 }, + { -2.844570976602957e-09, 3.058704574835744e+00 }, + { -2.848719081844986e-09, 3.062827985002047e+00 }, + { -2.852759934424164e-09, 3.066853254915581e+00 }, + { -2.856693382203833e-09, 3.070779782857041e+00 }, + { -2.860519277092708e-09, 3.074606970196721e+00 }, + { -2.864237475047239e-09, 3.078334221430809e+00 }, + { -2.867847836080156e-09, 3.081960944223928e+00 }, + { -2.871350224262603e-09, 3.085486549445314e+00 }, + { -2.874744507732462e-09, 3.088910451211251e+00 }, + { -2.878030558696270e-09, 3.092232066921130e+00 }, + { -2.881208253436038e-09, 3.095450817298478e+00 }, + { -2.884277472313999e-09, 3.098566126429974e+00 }, + { -2.887238099774968e-09, 3.101577421802070e+00 }, + { -2.890090024353816e-09, 3.104484134342861e+00 }, + { -2.892833138676371e-09, 3.107285698457308e+00 }, + { -2.895467339466766e-09, 3.109981552069083e+00 }, + { -2.897992527547963e-09, 3.112571136655481e+00 }, + { -2.900408607848946e-09, 3.115053897289195e+00 }, + { -2.902715489404992e-09, 3.117429282673042e+00 }, + { -2.904913085363323e-09, 3.119696745180238e+00 }, + { -2.907001312986328e-09, 3.121855740892224e+00 }, + { -2.908980093652563e-09, 3.123905729634218e+00 }, + { -2.910849352862924e-09, 3.125846175016163e+00 }, + { -2.912609020239985e-09, 3.127676544466606e+00 }, + { -2.914259029534118e-09, 3.129396309273659e+00 }, + { -2.915799318622574e-09, 3.131004944618667e+00 }, + { -2.917229829515169e-09, 3.132501929616775e+00 }, + { -2.918550508353347e-09, 3.133886747350606e+00 }, + { -2.919761305414294e-09, 3.135158884909254e+00 }, + { -2.920862175112829e-09, 3.136317833424958e+00 }, + { -2.921853076000972e-09, 3.137363088107359e+00 }, + { -2.922733970772719e-09, 3.138294148283254e+00 }, + { -2.923504826262027e-09, 3.139110517429204e+00 }, + { -2.924165613447473e-09, 3.139811703211207e+00 }, + { -2.924716307449950e-09, 3.140397217517018e+00 }, + { -2.925156887536978e-09, 3.140866576495489e+00 }, + { -2.925487337120335e-09, 3.141219300588825e+00 }, + { -2.925707643758784e-09, 3.141454914570261e+00 }, + { -2.925817799158535e-09, 3.141572947579352e+00 }, + { -2.925817799171455e-09, 3.141572933154836e+00 }, + { -2.925707643798390e-09, 3.141454409272987e+00 }, + { -2.925487337185779e-09, 3.141216918378770e+00 }, + { -2.925156887628892e-09, 3.140860007424112e+00 }, + { -2.924716307568119e-09, 3.140383227898687e+00 }, + { -2.924165613591896e-09, 3.139786135867868e+00 }, + { -2.923504826432903e-09, 3.139068292003385e+00 }, + { -2.922733970969412e-09, 3.138229261619561e+00 }, + { -2.921853076224321e-09, 3.137268614707029e+00 }, + { -2.920862175361976e-09, 3.136185925964038e+00 }, + { -2.919761305690083e-09, 3.134980774833275e+00 }, + { -2.918550508654911e-09, 3.133652745531368e+00 }, + { -2.917229829843137e-09, 3.132201427085629e+00 }, + { -2.915799318976726e-09, 3.130626413363146e+00 }, + { -2.914259029914435e-09, 3.128927303107136e+00 }, + { -2.912609020646661e-09, 3.127103699965947e+00 }, + { -2.910849353295315e-09, 3.125155212527586e+00 }, + { -2.908980094111509e-09, 3.123081454351802e+00 }, + { -2.907001313470937e-09, 3.120882043999591e+00 }, + { -2.904913085874448e-09, 3.118556605068443e+00 }, + { -2.902715489941767e-09, 3.116104766219928e+00 }, + { -2.900408608411958e-09, 3.113526161214776e+00 }, + { -2.897992528137022e-09, 3.110820428940251e+00 }, + { -2.895467340081818e-09, 3.107987213444579e+00 }, + { -2.892833139317615e-09, 3.105026163964191e+00 }, + { -2.890090025020589e-09, 3.101936934956479e+00 }, + { -2.887238100468092e-09, 3.098719186130021e+00 }, + { -2.884277473032614e-09, 3.095372582472161e+00 }, + { -2.881208254180937e-09, 3.091896794282404e+00 }, + { -2.878030559466594e-09, 3.088291497198199e+00 }, + { -2.874744508528832e-09, 3.084556372228054e+00 }, + { -2.871350225084755e-09, 3.080691105776848e+00 }, + { -2.867847836928063e-09, 3.076695389678615e+00 }, + { -2.864237475921086e-09, 3.072568921221621e+00 }, + { -2.860519277991847e-09, 3.068311403179147e+00 }, + { -2.856693383129018e-09, 3.063922543837792e+00 }, + { -2.852759935374575e-09, 3.059402057023109e+00 }, + { -2.848719082821403e-09, 3.054749662130841e+00 }, + { -2.844570977604520e-09, 3.049965084150782e+00 }, + { -2.840315775898525e-09, 3.045048053697736e+00 }, + { -2.835953637908582e-09, 3.039998307034967e+00 }, + { -2.831484727867511e-09, 3.034815586104635e+00 }, + { -2.826909214026628e-09, 3.029499638550941e+00 }, + { -2.822227268651470e-09, 3.024050217748861e+00 }, + { -2.817439068015245e-09, 3.018467082830179e+00 }, + { -2.812544792390175e-09, 3.012749998707001e+00 }, + { -2.807544626043751e-09, 3.006898736100911e+00 }, + { -2.802438757228650e-09, 3.000913071564665e+00 }, + { -2.797227378178760e-09, 2.994792787510961e+00 }, + { -2.791910685098702e-09, 2.988537672233504e+00 }, + { -2.786488878159805e-09, 2.982147519935565e+00 }, + { -2.780962161489413e-09, 2.975622130750641e+00 }, + { -2.775330743165298e-09, 2.968961310769028e+00 }, + { -2.769594835207775e-09, 2.962164872061613e+00 }, + { -2.763754653569747e-09, 2.955232632701135e+00 }, + { -2.757810418131543e-09, 2.948164416789036e+00 }, + { -2.751762352689432e-09, 2.940960054474719e+00 }, + { -2.745610684950541e-09, 2.933619381982341e+00 }, + { -2.739355646520809e-09, 2.926142241629213e+00 }, + { -2.732997472899722e-09, 2.918528481852205e+00 }, + { -2.726536403468318e-09, 2.910777957226018e+00 }, + { -2.719972681482232e-09, 2.902890528487386e+00 }, + { -2.713306554062453e-09, 2.894866062556452e+00 }, + { -2.706538272184154e-09, 2.886704432555728e+00 }, + { -2.699668090670078e-09, 2.878405517834426e+00 }, + { -2.692696268177908e-09, 2.869969203985464e+00 }, + { -2.685623067193599e-09, 2.861395382869544e+00 }, + { -2.678448754018380e-09, 2.852683952631486e+00 }, + { -2.671173598761847e-09, 2.843834817723832e+00 }, + { -2.663797875328991e-09, 2.834847888922988e+00 }, + { -2.656321861411517e-09, 2.825723083350459e+00 }, + { -2.648745838477759e-09, 2.816460324492298e+00 }, + { -2.641070091759922e-09, 2.807059542215146e+00 }, + { -2.633294910246296e-09, 2.797520672788269e+00 }, + { -2.625420586667340e-09, 2.787843658897949e+00 }, + { -2.617447417487602e-09, 2.778028449668942e+00 }, + { -2.609375702891616e-09, 2.768075000678399e+00 }, + { -2.601205746775692e-09, 2.757983273976943e+00 }, + { -2.592937856733464e-09, 2.747753238101915e+00 }, + { -2.584572344046340e-09, 2.737384868096553e+00 }, + { -2.576109523671634e-09, 2.726878145526201e+00 }, + { -2.567549714229129e-09, 2.716233058492422e+00 }, + { -2.558893237991435e-09, 2.705449601651722e+00 }, + { -2.550140420869302e-09, 2.694527776227857e+00 }, + { -2.541291592402089e-09, 2.683467590030445e+00 }, + { -2.532347085742440e-09, 2.672269057466213e+00 }, + { -2.523307237646751e-09, 2.660932199557362e+00 }, + { -2.514172388459584e-09, 2.649457043952206e+00 }, + { -2.504942882102813e-09, 2.637843624941622e+00 }, + { -2.495619066062810e-09, 2.626091983472908e+00 }, + { -2.486201291375123e-09, 2.614202167160335e+00 }, + { -2.476689912614465e-09, 2.602174230302269e+00 }, + { -2.467085287878098e-09, 2.590008233889805e+00 }, + { -2.457387778775451e-09, 2.577704245623143e+00 }, + { -2.447597750411553e-09, 2.565262339920002e+00 }, + { -2.437715571376127e-09, 2.552682597931055e+00 }, + { -2.427741613727123e-09, 2.539965107548168e+00 }, + { -2.417676252978335e-09, 2.527109963417675e+00 }, + { -2.407519868085581e-09, 2.514117266951687e+00 }, + { -2.397272841430131e-09, 2.500987126335739e+00 }, + { -2.386935558807595e-09, 2.487719656543254e+00 }, + { -2.376508409410024e-09, 2.474314979341178e+00 }, + { -2.365991785814531e-09, 2.460773223303822e+00 }, + { -2.355386083965131e-09, 2.447094523817833e+00 }, + { -2.344691703161363e-09, 2.433279023095734e+00 }, + { -2.333909046040126e-09, 2.419326870180582e+00 }, + { -2.323038518562289e-09, 2.405238220956597e+00 }, + { -2.312080529997549e-09, 2.391013238157397e+00 }, + { -2.301035492907384e-09, 2.376652091371587e+00 }, + { -2.289903823131822e-09, 2.362154957053137e+00 }, + { -2.278685939771276e-09, 2.347522018525197e+00 }, + { -2.267382265173420e-09, 2.332753465990296e+00 }, + { -2.255993224914501e-09, 2.317849496533128e+00 }, + { -2.244519247786155e-09, 2.302810314130351e+00 }, + { -2.232960765776561e-09, 2.287636129652823e+00 }, + { -2.221318214056095e-09, 2.272327160873552e+00 }, + { -2.209592030960763e-09, 2.256883632472565e+00 }, + { -2.197782657974034e-09, 2.241305776039511e+00 }, + { -2.185890539712767e-09, 2.225593830081461e+00 }, + { -2.173916123907886e-09, 2.209748040023618e+00 }, + { -2.161859861389976e-09, 2.193768658216360e+00 }, + { -2.149722206070124e-09, 2.177655943935795e+00 }, + { -2.137503614923981e-09, 2.161410163388424e+00 }, + { -2.125204547975352e-09, 2.145031589714984e+00 }, + { -2.112825468276292e-09, 2.128520502989477e+00 }, + { -2.100366841892917e-09, 2.111877190225612e+00 }, + { -2.087829137884807e-09, 2.095101945374541e+00 }, + { -2.075212828290086e-09, 2.078195069329960e+00 }, + { -2.062518388104923e-09, 2.061156869925600e+00 }, + { -2.049746295268559e-09, 2.043987661939897e+00 }, + { -2.036897030642658e-09, 2.026687767092888e+00 }, + { -2.023971077994576e-09, 2.009257514048162e+00 }, + { -2.010968923979840e-09, 1.991697238413571e+00 }, + { -1.997891058121344e-09, 1.974007282737320e+00 }, + { -1.984737972794098e-09, 1.956187996511354e+00 }, + { -1.971510163203686e-09, 1.938239736166060e+00 }, + { -1.958208127370276e-09, 1.920162865072273e+00 }, + { -1.944832366107339e-09, 1.901957753535934e+00 }, + { -1.931383383005451e-09, 1.883624778799427e+00 }, + { -1.917861684410531e-09, 1.865164325035177e+00 }, + { -1.904267779407432e-09, 1.846576783346324e+00 }, + { -1.890602179798714e-09, 1.827862551760622e+00 }, + { -1.876865400086483e-09, 1.809022035228338e+00 }, + { -1.863057957452539e-09, 1.790055645617624e+00 }, + { -1.849180371740008e-09, 1.770963801711725e+00 }, + { -1.835233165431475e-09, 1.751746929201178e+00 }, + { -1.821216863631569e-09, 1.732405460681919e+00 }, + { -1.807131994045840e-09, 1.712939835648088e+00 }, + { -1.792979086962494e-09, 1.693350500488565e+00 }, + { -1.778758675229683e-09, 1.673637908477153e+00 }, + { -1.764471294238191e-09, 1.653802519770021e+00 }, + { -1.750117481899733e-09, 1.633844801396848e+00 }, + { -1.735697778626995e-09, 1.613765227254186e+00 }, + { -1.721212727314574e-09, 1.593564278099856e+00 }, + { -1.706662873315474e-09, 1.573242441540939e+00 }, + { -1.692048764423848e-09, 1.552800212030258e+00 }, + { -1.677370950852395e-09, 1.532238090855187e+00 }, + { -1.662629985213192e-09, 1.511556586131055e+00 }, + { -1.647826422494560e-09, 1.490756212788764e+00 }, + { -1.632960820042537e-09, 1.469837492568651e+00 }, + { -1.618033737538645e-09, 1.448800954008929e+00 }, + { -1.603045736978760e-09, 1.427647132435469e+00 }, + { -1.587997382653428e-09, 1.406376569953373e+00 }, + { -1.572889241124034e-09, 1.384989815432507e+00 }, + { -1.557721881203696e-09, 1.363487424499449e+00 }, + { -1.542495873934815e-09, 1.341869959524515e+00 }, + { -1.527211792568486e-09, 1.320137989611176e+00 }, + { -1.511870212541253e-09, 1.298292090581491e+00 }, + { -1.496471711454994e-09, 1.276332844965754e+00 }, + { -1.481016869054634e-09, 1.254260841988828e+00 }, + { -1.465506267206068e-09, 1.232076677556547e+00 }, + { -1.449940489875303e-09, 1.209780954243628e+00 }, + { -1.434320123104372e-09, 1.187374281276747e+00 }, + { -1.418645754991533e-09, 1.164857274523495e+00 }, + { -1.402917975667710e-09, 1.142230556475749e+00 }, + { -1.387137377275425e-09, 1.119494756236361e+00 }, + { -1.371304553944712e-09, 1.096650509501278e+00 }, + { -1.355420101772623e-09, 1.073698458546610e+00 }, + { -1.339484618799891e-09, 1.050639252211352e+00 }, + { -1.323498704988051e-09, 1.027473545880543e+00 }, + { -1.307462962198534e-09, 1.004202001471034e+00 }, + { -1.291377994167204e-09, 9.808252874104182e-01 }, + { -1.275244406484394e-09, 9.573440786237052e-01 }, + { -1.259062806570190e-09, 9.337590565128454e-01 }, + { -1.242833803653464e-09, 9.100709089414796e-01 }, + { -1.226558008746195e-09, 8.862803302125812e-01 }, + { -1.210236034623253e-09, 8.623880210538113e-01 }, + { -1.193868495797618e-09, 8.383946885959868e-01 }, + { -1.177456008497777e-09, 8.143010463544786e-01 }, + { -1.160999190645010e-09, 7.901078142102129e-01 }, + { -1.144498661828833e-09, 7.658157183877095e-01 }, + { -1.127955043284965e-09, 7.414254914366063e-01 }, + { -1.111368957870986e-09, 7.169378722095157e-01 }, + { -1.094741030044308e-09, 6.923536058430697e-01 }, + { -1.078071885836393e-09, 6.676734437331688e-01 }, + { -1.061362152831423e-09, 6.428981435165511e-01 }, + { -1.044612460141255e-09, 6.180284690466404e-01 }, + { -1.027823438382183e-09, 5.930651903718045e-01 }, + { -1.010995719652015e-09, 5.680090837138436e-01 }, + { -9.941299375042378e-10, 5.428609314418970e-01 }, + { -9.772267269262058e-10, 5.176215220520872e-01 }, + { -9.602867243141016e-10, 4.922916501421032e-01 }, + { -9.433105674499058e-10, 4.668721163885412e-01 }, + { -9.262988954758817e-10, 4.413637275202624e-01 }, + { -9.092523488719689e-10, 4.157672962958654e-01 }, + { -8.921715694311144e-10, 3.900836414778084e-01 }, + { -8.750572002347607e-10, 3.643135878065193e-01 }, + { -8.579098856296589e-10, 3.384579659762392e-01 }, + { -8.407302712022458e-10, 3.125176126069478e-01 }, + { -8.235190037551917e-10, 2.864933702193017e-01 }, + { -8.062767312831008e-10, 2.603860872080448e-01 }, + { -7.890041029479477e-10, 2.341966178147619e-01 }, + { -7.717017690542486e-10, 2.079258220999725e-01 }, + { -7.543703810250266e-10, 1.815745659161734e-01 }, + { -7.370105913774597e-10, 1.551437208801425e-01 }, + { -7.196230536974697e-10, 1.286341643433767e-01 }, + { -7.022084226165876e-10, 1.020467793657360e-01 }, + { -6.847673537853251e-10, 7.538245468350446e-02 }, + { -6.673005038502516e-10, 4.864208468284503e-02 }, + { -6.498085304282128e-10, 2.182656936863137e-02 }, + { -6.322920920826137e-10, -5.063185663820913e-03 }, + { -6.147518482969490e-10, -3.202626926150343e-02 }, + { -5.971884594516681e-10, -5.906176474160862e-02 }, + { -5.796025867984469e-10, -8.616874992366363e-02 }, + { -5.619948924353588e-10, -1.133462971605448e-01 }, + { -5.443660392823640e-10, -1.405934733692621e-01 }, + { -5.267166910556339e-10, -1.679093400638023e-01 }, + { -5.090475122431451e-10, -1.952929533862739e-01 }, + { -4.913591680795342e-10, -2.227433641394564e-01 }, + { -4.736523245210571e-10, -2.502596178194491e-01 }, + { -4.559276482202303e-10, -2.778407546490776e-01 }, + { -4.381858065011618e-10, -3.054858096104932e-01 }, + { -4.204274673340870e-10, -3.331938124792702e-01 }, + { -4.026532993105397e-10, -3.609637878577768e-01 }, + { -3.848639716178888e-10, -3.887947552098022e-01 }, + { -3.670601540142443e-10, -4.166857288948674e-01 }, + { -3.492425168032583e-10, -4.446357182029681e-01 }, + { -3.314117308088734e-10, -4.726437273896633e-01 }, + { -3.135684673501752e-10, -5.007087557112619e-01 }, + { -2.957133982159296e-10, -5.288297974607742e-01 }, + { -2.778471956393828e-10, -5.570058420037128e-01 }, + { -2.599705322729564e-10, -5.852358738143247e-01 }, + { -2.420840811628366e-10, -6.135188725122560e-01 }, + { -2.241885157240923e-10, -6.418538128986450e-01 }, + { -2.062845097142585e-10, -6.702396649949099e-01 }, + { -1.883727372093546e-10, -6.986753940779493e-01 }, + { -1.704538725773087e-10, -7.271599607197149e-01 }, + { -1.525285904532877e-10, -7.556923208240308e-01 }, + { -1.345975657140748e-10, -7.842714256651911e-01 }, + { -1.166614734526054e-10, -8.128962219265712e-01 }, + { -9.872098895260891e-11, -8.415656517393372e-01 }, + { -8.077678766314517e-11, -8.702786527215916e-01 }, + { -6.282954517324612e-11, -8.990341580176152e-01 }, + { -4.487993718655790e-11, -9.278310963373758e-01 }, + { -2.692863949561210e-11, -9.566683919968972e-01 }, + { -8.976327956520795e-12, -9.855449649582175e-01 }, + { 8.976321536169872e-12, -1.014459730869357e+00 }, + { 2.692863307547294e-11, -1.043411601105914e+00 }, + { 4.487993076694813e-11, -1.072399482811314e+00 }, + { 6.282953875437751e-11, -1.101422278938424e+00 }, + { 8.077678124517653e-11, -1.130478888291020e+00 }, + { 9.872098253591082e-11, -1.159568205565684e+00 }, + { 1.166614670373367e-10, -1.188689121393192e+00 }, + { 1.345975593005002e-10, -1.217840522381901e+00 }, + { 1.525285840416718e-10, -1.247021291159495e+00 }, + { 1.704538661678104e-10, -1.276230306415868e+00 }, + { 1.883727308022916e-10, -1.305466442946703e+00 }, + { 2.062845033098954e-10, -1.334728571696106e+00 }, + { 2.241885093225349e-10, -1.364015559800721e+00 }, + { 2.420840747645085e-10, -1.393326270633325e+00 }, + { 2.599705258779635e-10, -1.422659563847049e+00 }, + { 2.778471892479898e-10, -1.452014295419243e+00 }, + { 2.957133918284542e-10, -1.481389317696831e+00 }, + { 3.135684609667761e-10, -1.510783479440191e+00 }, + { 3.314117244297624e-10, -1.540195625869043e+00 }, + { 3.492425104288060e-10, -1.569624598707558e+00 }, + { 3.670601476445565e-10, -1.599069236228850e+00 }, + { 3.848639652533361e-10, -1.628528373302631e+00 }, + { 4.026532929512281e-10, -1.658000841439269e+00 }, + { 4.204274609803869e-10, -1.687485468837799e+00 }, + { 4.381858001531792e-10, -1.716981080430596e+00 }, + { 4.559276418782829e-10, -1.746486497931567e+00 }, + { 4.736523181853565e-10, -1.776000539882225e+00 }, + { 4.913591617503452e-10, -1.805522021699094e+00 }, + { 5.090475059206794e-10, -1.835049755721194e+00 }, + { 5.267166847401562e-10, -1.864582551257262e+00 }, + { 5.443660329740862e-10, -1.894119214633676e+00 }, + { 5.619948861345454e-10, -1.923658549242818e+00 }, + { 5.796025805053097e-10, -1.953199355591180e+00 }, + { 5.971884531664190e-10, -1.982740431347091e+00 }, + { 6.147518420199055e-10, -2.012280571390674e+00 }, + { 6.322920858139346e-10, -2.041818567861395e+00 }, + { 6.498085241682158e-10, -2.071353210208005e+00 }, + { 6.673004975990425e-10, -2.100883285238127e+00 }, + { 6.847673475432746e-10, -2.130407577166309e+00 }, + { 7.022084163838545e-10, -2.159924867664933e+00 }, + { 7.196230474743716e-10, -2.189433935913779e+00 }, + { 7.370105851640495e-10, -2.218933558650552e+00 }, + { 7.543703748217808e-10, -2.248422510220072e+00 }, + { 7.717017628611672e-10, -2.277899562625407e+00 }, + { 7.890040967654542e-10, -2.307363485579104e+00 }, + { 8.062767251113011e-10, -2.336813046552684e+00 }, + { 8.235189975944034e-10, -2.366247010829556e+00 }, + { 8.407302650525749e-10, -2.395664141553858e+00 }, + { 8.579098794915287e-10, -2.425063199784153e+00 }, + { 8.750571941082773e-10, -2.454442944543319e+00 }, + { 8.921715633164894e-10, -2.483802132872044e+00 }, + { 9.092523427695200e-10, -2.513139519878584e+00 }, + { 9.262988893857148e-10, -2.542453858792682e+00 }, + { 9.433105613723914e-10, -2.571743901017465e+00 }, + { 9.602867182493987e-10, -2.601008396180870e+00 }, + { 9.772267208744730e-10, -2.630246092190425e+00 }, + { 9.941299314658458e-10, -2.659455735283526e+00 }, + { 1.010995713627070e-09, -2.688636070081818e+00 }, + { 1.027823432371055e-09, -2.717785839644439e+00 }, + { 1.044612454143997e-09, -2.746903785521352e+00 }, + { 1.061362146848353e-09, -2.775988647805256e+00 }, + { 1.078071879867828e-09, -2.805039165187255e+00 }, + { 1.094741024090249e-09, -2.834054075009077e+00 }, + { 1.111368951931856e-09, -2.863032113318052e+00 }, + { 1.127955037360817e-09, -2.891972014920939e+00 }, + { 1.144498655920037e-09, -2.920872513436805e+00 }, + { 1.160999184751779e-09, -2.949732341353290e+00 }, + { 1.177456002620215e-09, -2.978550230079517e+00 }, + { 1.193868489936097e-09, -3.007324910002949e+00 }, + { 1.210236028777826e-09, -3.036055110540183e+00 }, + { 1.226558002917232e-09, -3.064739560196251e+00 }, + { 1.242833797841123e-09, -3.093376986616735e+00 }, + { 1.259062800774685e-09, -3.121966116643377e+00 }, + { 1.275244400705935e-09, -3.150505676371791e+00 }, + { 1.291377988406056e-09, -3.178994391202159e+00 }, + { 1.307462956454857e-09, -3.207430985899192e+00 }, + { 1.323498699262108e-09, -3.235814184645077e+00 }, + { 1.339484613091842e-09, -3.264142711097884e+00 }, + { 1.355420096082785e-09, -3.292415288443373e+00 }, + { 1.371304548273191e-09, -3.320630639454825e+00 }, + { 1.387137371622433e-09, -3.348787486547389e+00 }, + { 1.402917970033511e-09, -3.376884551834256e+00 }, + { 1.418645749376393e-09, -3.404920557184582e+00 }, + { 1.434320117508396e-09, -3.432894224276359e+00 }, + { 1.449940484298756e-09, -3.460804274656981e+00 }, + { 1.465506261649108e-09, -3.488649429796768e+00 }, + { 1.481016863517580e-09, -3.516428411149154e+00 }, + { 1.496471705937951e-09, -3.544139940202303e+00 }, + { 1.511870207044433e-09, -3.571782738540999e+00 }, + { 1.527211787092206e-09, -3.599355527901174e+00 }, + { 1.542495868479076e-09, -3.626857030226671e+00 }, + { 1.557721875768920e-09, -3.654285967729458e+00 }, + { 1.572889235710329e-09, -3.681641062941412e+00 }, + { 1.587997377261005e-09, -3.708921038776707e+00 }, + { 1.603045731607830e-09, -3.736124618586623e+00 }, + { 1.618033732189314e-09, -3.763250526218862e+00 }, + { 1.632960814715177e-09, -3.790297486071938e+00 }, + { 1.647826417189275e-09, -3.817264223155802e+00 }, + { 1.662629979930247e-09, -3.844149463148589e+00 }, + { 1.677370945591844e-09, -3.870951932452996e+00 }, + { 1.692048759186008e-09, -3.897670358257890e+00 }, + { 1.706662868100504e-09, -3.924303468590212e+00 }, + { 1.721212722122685e-09, -3.950849992378278e+00 }, + { 1.735697773458400e-09, -3.977308659506432e+00 }, + { 1.750117476754591e-09, -4.003678200876669e+00 }, + { 1.764471289116712e-09, -4.029957348461003e+00 }, + { 1.778758670132079e-09, -4.056144835364877e+00 }, + { 1.792979081888926e-09, -4.082239395882965e+00 }, + { 1.807131988996465e-09, -4.108239765556996e+00 }, + { 1.821216858606652e-09, -4.134144681236933e+00 }, + { 1.835233160431175e-09, -4.159952881133585e+00 }, + { 1.849180366764537e-09, -4.185663104882633e+00 }, + { 1.863057952502055e-09, -4.211274093599509e+00 }, + { 1.876865395161145e-09, -4.236784589940537e+00 }, + { 1.890602174898734e-09, -4.262193338157148e+00 }, + { 1.904267774533022e-09, -4.287499084158302e+00 }, + { 1.917861679562008e-09, -4.312700575567174e+00 }, + { 1.931383378182392e-09, -4.337796561778708e+00 }, + { 1.944832361310856e-09, -4.362785794021793e+00 }, + { 1.958208122599839e-09, -4.387667025411434e+00 }, + { 1.971510158459931e-09, -4.412439011013396e+00 }, + { 1.984737968076495e-09, -4.437100507898339e+00 }, + { 1.997891053431005e-09, -4.461650275204912e+00 }, + { 2.010968919316289e-09, -4.486087074191693e+00 }, + { 2.023971073358447e-09, -4.510409668301784e+00 }, + { 2.036897026033634e-09, -4.534616823217992e+00 }, + { 2.049746290686799e-09, -4.558707306921882e+00 }, + { 2.062518383551274e-09, -4.582679889754607e+00 }, + { 2.075212823764071e-09, -4.606533344469879e+00 }, + { 2.087829133387063e-09, -4.630266446298172e+00 }, + { 2.100366837422912e-09, -4.653877973001258e+00 }, + { 2.112825463835087e-09, -4.677366704934605e+00 }, + { 2.125204543562522e-09, -4.700731425099899e+00 }, + { 2.137503610540056e-09, -4.723970919208608e+00 }, + { 2.149722201714786e-09, -4.747083975738060e+00 }, + { 2.161859857063438e-09, -4.770069385989595e+00 }, + { 2.173916119610994e-09, -4.792925944149308e+00 }, + { 2.185890535445098e-09, -4.815652447340950e+00 }, + { 2.197782653735957e-09, -4.838247695689436e+00 }, + { 2.209592026751962e-09, -4.860710492376411e+00 }, + { 2.221318209877576e-09, -4.883039643700314e+00 }, + { 2.232960761627846e-09, -4.905233959130168e+00 }, + { 2.244519243667616e-09, -4.927292251368517e+00 }, + { 2.255993220826402e-09, -4.949213336406265e+00 }, + { 2.267382261115285e-09, -4.970996033581527e+00 }, + { 2.278685935744269e-09, -4.992639165639563e+00 }, + { 2.289903819135414e-09, -5.014141558784778e+00 }, + { 2.301035488942000e-09, -5.035502042744443e+00 }, + { 2.312080526062763e-09, -5.056719450823151e+00 }, + { 2.323038514659161e-09, -5.077792619963239e+00 }, + { 2.333909042168180e-09, -5.098720390796817e+00 }, + { 2.344691699320969e-09, -5.119501607709159e+00 }, + { 2.355386080156553e-09, -5.140135118892792e+00 }, + { 2.365991782037187e-09, -5.160619776404897e+00 }, + { 2.376508405665132e-09, -5.180954436227641e+00 }, + { 2.386935555094626e-09, -5.201137958319343e+00 }, + { 2.397272837749508e-09, -5.221169206676762e+00 }, + { 2.407519864436774e-09, -5.241047049389645e+00 }, + { 2.417676249362563e-09, -5.260770358700167e+00 }, + { 2.427741610143750e-09, -5.280338011053974e+00 }, + { 2.437715567825576e-09, -5.299748887163106e+00 }, + { 2.447597746894037e-09, -5.319001872058887e+00 }, + { 2.457387775290440e-09, -5.338095855149190e+00 }, + { 2.467085284426756e-09, -5.357029730277389e+00 }, + { 2.476689909196263e-09, -5.375802395772283e+00 }, + { 2.486201287990485e-09, -5.394412754510426e+00 }, + { 2.495619062711154e-09, -5.412859713968929e+00 }, + { 2.504942878785408e-09, -5.431142186284682e+00 }, + { 2.514172385175743e-09, -5.449259088303476e+00 }, + { 2.523307234396791e-09, -5.467209341642627e+00 }, + { 2.532347082526785e-09, -5.484991872743321e+00 }, + { 2.541291589219998e-09, -5.502605612925014e+00 }, + { 2.550140417722072e-09, -5.520049498445633e+00 }, + { 2.558893234878378e-09, -5.537322470548212e+00 }, + { 2.567549711150773e-09, -5.554423475524196e+00 }, + { 2.576109520627371e-09, -5.571351464763084e+00 }, + { 2.584572341037361e-09, -5.588105394812198e+00 }, + { 2.592937853759161e-09, -5.604684227423386e+00 }, + { 2.601205743836355e-09, -5.621086929615246e+00 }, + { 2.609375699987564e-09, -5.637312473723475e+00 }, + { 2.617447414618146e-09, -5.653359837454964e+00 }, + { 2.625420583833750e-09, -5.669228003945694e+00 }, + { 2.633294907447937e-09, -5.684915961806963e+00 }, + { 2.641070088997271e-09, -5.700422705186584e+00 }, + { 2.648745835750128e-09, -5.715747233817712e+00 }, + { 2.656321858720176e-09, -5.730888553077074e+00 }, + { 2.663797872673252e-09, -5.745845674030161e+00 }, + { 2.671173596142054e-09, -5.760617613492118e+00 }, + { 2.678448751434797e-09, -5.775203394076705e+00 }, + { 2.685623064645538e-09, -5.789602044248679e+00 }, + { 2.692696265666640e-09, -5.803812598380606e+00 }, + { 2.699668088194915e-09, -5.817834096797069e+00 }, + { 2.706538269745573e-09, -5.831665585834668e+00 }, + { 2.713306551659817e-09, -5.845306117889361e+00 }, + { 2.719972679116734e-09, -5.858754751472542e+00 }, + { 2.726536401139295e-09, -5.872010551255358e+00 }, + { 2.732997470607439e-09, -5.885072588127400e+00 }, + { 2.739355644265558e-09, -5.897939939244211e+00 }, + { 2.745610682731633e-09, -5.910611688078208e+00 }, + { 2.751762350508137e-09, -5.923086924473290e+00 }, + { 2.757810415987146e-09, -5.935364744687794e+00 }, + { 2.763754651462700e-09, -5.947444251452243e+00 }, + { 2.769594833137415e-09, -5.959324554015538e+00 }, + { 2.775330741132843e-09, -5.971004768198829e+00 }, + { 2.780962159494174e-09, -5.982484016437981e+00 }, + { 2.786488876202047e-09, -5.993761427840588e+00 }, + { 2.791910683178690e-09, -6.004836138231525e+00 }, + { 2.797227376295779e-09, -6.015707290202086e+00 }, + { 2.802438755383971e-09, -6.026374033162623e+00 }, + { 2.807544624236659e-09, -6.036835523383457e+00 }, + { 2.812544790621093e-09, -6.047090924050914e+00 }, + { 2.817439066283459e-09, -6.057139405311101e+00 }, + { 2.822227266958278e-09, -6.066980144322601e+00 }, + { 2.826909212371261e-09, -6.076612325295799e+00 }, + { 2.831484726250221e-09, -6.086035139548830e+00 }, + { 2.835953636329660e-09, -6.095247785550617e+00 }, + { 2.840315774357203e-09, -6.104249468967751e+00 }, + { 2.844570976102082e-09, -6.113039402715685e+00 }, + { 2.848719081357095e-09, -6.121616806996519e+00 }, + { 2.852759933948860e-09, -6.129980909353977e+00 }, + { 2.856693381741114e-09, -6.138130944714082e+00 }, + { 2.860519276643053e-09, -6.146066155436312e+00 }, + { 2.864237474610633e-09, -6.153785791350256e+00 }, + { 2.867847835656203e-09, -6.161289109809551e+00 }, + { 2.871350223851726e-09, -6.168575375732642e+00 }, + { 2.874744507333867e-09, -6.175643861647406e+00 }, + { 2.878030558310989e-09, -6.182493847739853e+00 }, + { 2.881208253063899e-09, -6.189124621889823e+00 }, + { 2.884277471954592e-09, -6.195535479723423e+00 }, + { 2.887238099428306e-09, -6.201725724651554e+00 }, + { 2.890090024020323e-09, -6.207694667918394e+00 }, + { 2.892833138356060e-09, -6.213441628635915e+00 }, + { 2.895467339159240e-09, -6.218965933835304e+00 }, + { 2.897992527253659e-09, -6.224266918505075e+00 }, + { 2.900408607567016e-09, -6.229343925633495e+00 }, + { 2.902715489136496e-09, -6.234196306254763e+00 }, + { 2.904913085108075e-09, -6.238823419482017e+00 }, + { 2.907001312743911e-09, -6.243224632557377e+00 }, + { 2.908980093422997e-09, -6.247399320887848e+00 }, + { 2.910849352646620e-09, -6.251346868091392e+00 }, + { 2.912609020036956e-09, -6.255066666028537e+00 }, + { 2.914259029343965e-09, -6.258558114851525e+00 }, + { 2.915799318445710e-09, -6.261820623039620e+00 }, + { 2.917229829350759e-09, -6.264853607438842e+00 }, + { 2.918550508202463e-09, -6.267656493305673e+00 }, + { 2.919761305276718e-09, -6.270228714337005e+00 }, + { 2.920862174988150e-09, -6.272569712717951e+00 }, + { 2.921853075889193e-09, -6.274678939154603e+00 }, + { 2.922733970674264e-09, -6.276555852917634e+00 }, + { 2.923504826176907e-09, -6.278199921870962e+00 }, + { 2.924165613375264e-09, -6.279610622518139e+00 }, + { 2.924716307391075e-09, -6.280787440034993e+00 }, + { 2.925156887490598e-09, -6.281729868306345e+00 }, + { 2.925487337087508e-09, -6.282437409966992e+00 }, + { 2.925707643739298e-09, -6.282909576428774e+00 }, + { 2.925817799151970e-09, -6.283145887925411e+00 }, diff --git a/gnuradio-core/src/lib/gengen/CMakeLists.txt b/gnuradio-core/src/lib/gengen/CMakeLists.txt new file mode 100644 index 000000000..db3103a26 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/CMakeLists.txt @@ -0,0 +1,175 @@ +# Copyright 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. + +######################################################################## +# This file included, use CMake directory variables +######################################################################## +include(GrPython) + +######################################################################## +# generate the python helper script which calls into the build utils +######################################################################## +file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py " +#!${PYTHON_EXECUTABLE} + +import sys, os, re +sys.path.append('${GR_CORE_PYTHONPATH}') +os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}' +os.chdir('${CMAKE_CURRENT_BINARY_DIR}') + +if __name__ == '__main__': + import build_utils + root, inp = sys.argv[1:3] + for sig in sys.argv[3:]: + name = re.sub ('X+', sig, root) + d = build_utils.standard_dict(name, sig) + build_utils.expand_template(d, inp) + +") + +######################################################################## +# generation helper macro to generate various files from template +######################################################################## +macro(expand_h_cc_i root) + + foreach(ext h cc i) + #make a list of all the generated files + unset(expanded_files_${ext}) + foreach(sig ${ARGN}) + string(REGEX REPLACE "X+" ${sig} name ${root}) + list(APPEND expanded_files_${ext} ${CMAKE_CURRENT_BINARY_DIR}/${name}.${ext}) + endforeach(sig) + + #create a command to generate the files + add_custom_command( + OUTPUT ${expanded_files_${ext}} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.${ext}.t + COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py + ${root} ${root}.${ext}.t ${ARGN} + ) + endforeach(ext) + + #make source files depends on headers to force generation + set_source_files_properties(${expanded_files_cc} + PROPERTIES OBJECT_DEPENDS "${expanded_files_h}" + ) + + #install rules for the generated cc, h, and i files + list(APPEND generated_gengen_sources ${expanded_files_cc}) + list(APPEND generated_gengen_includes ${expanded_files_h}) + list(APPEND generated_gengen_swigs ${expanded_files_i}) + +endmacro(expand_h_cc_i) + +######################################################################## +# Invoke macro to generate various sources +######################################################################## +expand_h_cc_i(gr_vector_source_X b s i f c) +expand_h_cc_i(gr_vector_insert_X b) +expand_h_cc_i(gr_vector_sink_X b s i f c) +expand_h_cc_i(gr_noise_source_X s i f c) +expand_h_cc_i(gr_fastnoise_source_X s i f c) +expand_h_cc_i(gr_sig_source_X s i f c) +expand_h_cc_i(gr_probe_signal_X b s i f c) +expand_h_cc_i(gr_probe_signal_vX b s i f c) + +expand_h_cc_i(gr_add_const_XX bb ss ii ff cc sf) +expand_h_cc_i(gr_multiply_const_XX ss ii) +expand_h_cc_i(gr_add_XX ss ii cc) +expand_h_cc_i(gr_sub_XX ss ii ff cc) +expand_h_cc_i(gr_multiply_XX ss ii) +expand_h_cc_i(gr_divide_XX ss ii ff cc) +expand_h_cc_i(gr_mute_XX ss ii ff cc) +expand_h_cc_i(gr_add_const_vXX ss ii ff cc) +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) +expand_h_cc_i(gr_and_XX bb ss ii) +expand_h_cc_i(gr_and_const_XX bb ss ii) +expand_h_cc_i(gr_or_XX bb ss ii) +expand_h_cc_i(gr_not_XX bb ss ii) +expand_h_cc_i(gr_sample_and_hold_XX bb ss ii ff) +expand_h_cc_i(gr_argmax_XX fs is ss) +expand_h_cc_i(gr_max_XX ff ii ss) +expand_h_cc_i(gr_peak_detector_XX fb ib sb) + +add_custom_target(gengen_generated DEPENDS + ${generated_gengen_includes} + ${generated_gengen_swigs} +) + +######################################################################## +# Create the master gengen swig include files +######################################################################## +set(generated_index ${CMAKE_CURRENT_BINARY_DIR}/gengen_generated.i.in) +file(WRITE ${generated_index} " +// +// This file is machine generated. All edits will be overwritten +// +") + +file(APPEND ${generated_index} "%{\n") +foreach(swig_file ${generated_gengen_swigs}) + get_filename_component(name ${swig_file} NAME_WE) + file(APPEND ${generated_index} "#include<${name}.h>\n") +endforeach(swig_file) +file(APPEND ${generated_index} "%}\n") + +foreach(swig_file ${generated_gengen_swigs}) + get_filename_component(name ${swig_file} NAME) + file(APPEND ${generated_index} "%include<${name}>\n") +endforeach(swig_file) + +execute_process( + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${generated_index} ${CMAKE_CURRENT_BINARY_DIR}/gengen_generated.i +) + +######################################################################## +# Handle the generated sources + a few non-generated ones +######################################################################## +list(APPEND gnuradio_core_sources + ${generated_gengen_sources} +) + +install(FILES + ${generated_gengen_includes} + ${CMAKE_CURRENT_SOURCE_DIR}/gr_endianness.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_noise_type.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_sig_source_waveform.h + DESTINATION ${GR_INCLUDE_DIR}/gnuradio + COMPONENT "core_devel" +) + +if(ENABLE_PYTHON) + install(FILES + ${generated_gengen_swigs} + ${CMAKE_CURRENT_SOURCE_DIR}/gr_endianness.i + ${CMAKE_CURRENT_SOURCE_DIR}/gengen.i + ${CMAKE_CURRENT_BINARY_DIR}/gengen_generated.i + DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig + COMPONENT "core_swig" + ) +endif(ENABLE_PYTHON) diff --git a/gnuradio-core/src/lib/gengen/generate_all.py b/gnuradio-core/src/lib/gengen/generate_all.py new file mode 100755 index 000000000..6b0f20f05 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/generate_all.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python +# +# 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. +# + +from build_utils import output_glue + +import generate_common + +def generate_all (): + generate_common.generate () + output_glue ('gengen') + + +if __name__ == '__main__': + generate_all () diff --git a/gnuradio-core/src/lib/gengen/generate_common.py b/gnuradio-core/src/lib/gengen/generate_common.py new file mode 100755 index 000000000..13d01b0f9 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/generate_common.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python +# +# Copyright 2004,2006,2007,2008,2009 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 build_utils import expand_template, standard_dict +from build_utils_codes import * + +import re + + +# sources and sinks +ss_signatures = ['s', 'i', 'f', 'c'] + +ss_roots = [ + 'gr_vector_source_X', + 'gr_vector_sink_X', + 'gr_noise_source_X', + 'gr_sig_source_X', + 'gr_probe_signal_X', + 'gr_probe_signal_vX' + ] + +# regular blocks +reg_signatures = ['ss', 'ii', 'ff', 'cc'] + +reg_roots = [ + 'gr_add_const_XX', + 'gr_sub_XX', + 'gr_divide_XX', + 'gr_mute_XX', + 'gr_add_const_vXX', + 'gr_multiply_const_vXX', + 'gr_integrate_XX', + 'gr_moving_average_XX', + ] + +# 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')), + ('gr_and_XX', ('bb','ss','ii')), + ('gr_and_const_XX', ('bb','ss','ii')), + ('gr_or_XX', ('bb','ss','ii')), + ('gr_not_XX', ('bb','ss','ii')), + ('gr_sample_and_hold_XX', ('bb','ss','ii','ff')), + ('gr_argmax_XX', ('fs','is','ss')), + ('gr_max_XX', ('ff','ii','ss')), + ('gr_peak_detector_XX', ('fb','ib','sb')), + ('gr_multiply_XX', ('ss','ii')), + ('gr_multiply_const_XX', ('ss','ii')), + ('gr_add_XX', ('ss','cc','ii')) + ) + + +def expand_h_cc_i (root, sig): + # root looks like 'gr_vector_sink_X' + name = re.sub ('X+', sig, root) + d = standard_dict (name, sig) + expand_template (d, root + '.h.t') + expand_template (d, root + '.cc.t') + expand_template (d, root + '.i.t') + + +def generate (): + expand_h_cc_i ('gr_add_const_XX', 'sf') # for MC4020 + expand_h_cc_i ('gr_vector_sink_X', 'b') + expand_h_cc_i ('gr_vector_source_X', 'b') + expand_h_cc_i ('gr_probe_signal_X', 'b') + expand_h_cc_i ('gr_probe_signal_vX', 'b') + for r in ss_roots: + for s in ss_signatures: + expand_h_cc_i (r, s) + for r in reg_roots : + for s in reg_signatures: + expand_h_cc_i (r, s) + + for root, sigs in others: + for s in sigs: + expand_h_cc_i (root, s) + + + +if __name__ == '__main__': + generate () + + diff --git a/gnuradio-core/src/lib/gengen/gengen.i b/gnuradio-core/src/lib/gengen/gengen.i new file mode 100644 index 000000000..d1895bfa8 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gengen.i @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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 "gr_endianness.h" +#include "gr_sig_source_waveform.h" +#include "gr_noise_type.h" +%} + +%include "gr_endianness.i" +%include "gr_sig_source_waveform.h" +%include "gr_noise_type.h" + +%include "gengen_generated.i" diff --git a/gnuradio-core/src/lib/gengen/gr_add_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_add_XX.cc.t new file mode 100644 index 000000000..5a888125b --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_add_XX.cc.t @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004, 2009,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> + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (size_t vlen) +{ + return gnuradio::get_initial_sptr (new @NAME@ (vlen)); +} + +@NAME@::@NAME@ (size_t vlen) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, -1, sizeof (@I_TYPE@)*vlen), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@)*vlen)), + d_vlen (vlen) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + + int ninputs = input_items.size (); + + for (size_t i = 0; i < noutput_items*d_vlen; i++){ + @I_TYPE@ acc = ((@I_TYPE@ *) input_items[0])[i]; + for (int j = 1; j < ninputs; j++) + acc += ((@I_TYPE@ *) input_items[j])[i]; + + *optr++ = (@O_TYPE@) acc; + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/gengen/gr_add_XX.h.t b/gnuradio-core/src/lib/gengen/gr_add_XX.h.t new file mode 100644 index 000000000..cd6d80cd9 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_add_XX.h.t @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004, 2009 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_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (size_t vlen = 1); + +/*! + * \brief output = sum (input_0, input_1, ...) + * \ingroup math_blk + * + * Add across all input streams. + */ +class GR_CORE_API @NAME@ : public gr_sync_block +{ + friend GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (size_t vlen); + + @NAME@ (size_t vlen); + + size_t d_vlen; + + 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/gengen/gr_add_XX.i.t b/gnuradio-core/src/lib/gengen/gr_add_XX.i.t new file mode 100644 index 000000000..b2c510610 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_add_XX.i.t @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004, 2009 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@ (size_t vlen = 1); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (size_t vlen); +}; diff --git a/gnuradio-core/src/lib/gengen/gr_add_const_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_add_const_XX.cc.t new file mode 100644 index 000000000..3dccc86b8 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_add_const_XX.cc.t @@ -0,0 +1,72 @@ +/* -*- 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> + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (@O_TYPE@ k) +{ + return gnuradio::get_initial_sptr (new @NAME@ (k)); +} + +@NAME@::@NAME@ (@O_TYPE@ k) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))), + d_k (k) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @I_TYPE@ *iptr = (@I_TYPE@ *) input_items[0]; + @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + + int size = noutput_items; + + while (size >= 8){ + *optr++ = *iptr++ + d_k; + *optr++ = *iptr++ + d_k; + *optr++ = *iptr++ + d_k; + *optr++ = *iptr++ + d_k; + *optr++ = *iptr++ + d_k; + *optr++ = *iptr++ + d_k; + *optr++ = *iptr++ + d_k; + *optr++ = *iptr++ + d_k; + size -= 8; + } + + while (size-- > 0) + *optr++ = *iptr++ + d_k; + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/gengen/gr_add_const_XX.h.t b/gnuradio-core/src/lib/gengen/gr_add_const_XX.h.t new file mode 100644 index 000000000..00d2c9b58 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_add_const_XX.h.t @@ -0,0 +1,56 @@ +/* -*- 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_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (@O_TYPE@ k); + +/*! + * \brief output = input + constant + * \ingroup math_blk + */ +class GR_CORE_API @NAME@ : public gr_sync_block +{ + friend GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (@O_TYPE@ k); + + @O_TYPE@ d_k; // the constant + @NAME@ (@O_TYPE@ k); + + public: + @O_TYPE@ k () const { return d_k; } + void set_k (@O_TYPE@ k) { d_k = k; } + + 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/gengen/gr_add_const_XX.i.t b/gnuradio-core/src/lib/gengen/gr_add_const_XX.i.t new file mode 100644 index 000000000..b7921554e --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_add_const_XX.i.t @@ -0,0 +1,37 @@ +/* -*- 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@ (@TYPE@ k); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (@TYPE@ k); + + public: + @TYPE@ k () const { return d_k; } + void set_k (@TYPE@ k) { d_k = k; } +}; diff --git a/gnuradio-core/src/lib/gengen/gr_add_const_vXX.cc.t b/gnuradio-core/src/lib/gengen/gr_add_const_vXX.cc.t new file mode 100755 index 000000000..b29f3014d --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_add_const_vXX.cc.t @@ -0,0 +1,61 @@ +/* -*- 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. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <gr_io_signature.h> + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (const std::vector<@I_TYPE@> &k) +{ + return gnuradio::get_initial_sptr (new @NAME@ (k)); +} + +@NAME@::@NAME@ (const std::vector<@I_TYPE@> &k) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof(@I_TYPE@)*k.size()), + gr_make_io_signature (1, 1, sizeof(@O_TYPE@)*k.size())) +{ + d_k = k; +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @I_TYPE@ *iptr = (@O_TYPE@ *)input_items[0]; + @O_TYPE@ *optr = (@O_TYPE@ *)output_items[0]; + + int nitems_per_block = output_signature()->sizeof_stream_item(0)/sizeof(@I_TYPE@); + + for (int i = 0; i < noutput_items; i++) + for (int j = 0; j < nitems_per_block; j++) + *optr++ = *iptr++ + d_k[j]; + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/gengen/gr_add_const_vXX.h.t b/gnuradio-core/src/lib/gengen/gr_add_const_vXX.h.t new file mode 100644 index 000000000..438a84bfd --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_add_const_vXX.h.t @@ -0,0 +1,56 @@ +/* -*- 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. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (const std::vector<@I_TYPE@> &k); + +/*! + * \brief output vector = input vector + constant vector + * \ingroup math_blk + */ +class GR_CORE_API @NAME@ : public gr_sync_block +{ + friend GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (const std::vector<@I_TYPE@> &k); + + std::vector<@I_TYPE@> d_k; // the constant + @NAME@ (const std::vector<@I_TYPE@> &k); + + public: + const std::vector<@I_TYPE@> k () const { return d_k; } + void set_k (const std::vector<@I_TYPE@> &k) { d_k = k; } + + 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/gengen/gr_add_const_vXX.i.t b/gnuradio-core/src/lib/gengen/gr_add_const_vXX.i.t new file mode 100755 index 000000000..e0e6ae905 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_add_const_vXX.i.t @@ -0,0 +1,37 @@ +/* -*- 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. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (const std::vector<@I_TYPE@> &k); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (const std::vector<@I_TYPE@> &k); + + public: + std::vector<@I_TYPE@> k () const { return d_k; } + void set_k (const std::vector<@I_TYPE@> &k) { d_k = k; } +}; diff --git a/gnuradio-core/src/lib/gengen/gr_and_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_and_XX.cc.t new file mode 100644 index 000000000..9d60e092a --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_and_XX.cc.t @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <gr_io_signature.h> + +@SPTR_NAME@ +gr_make_@BASE_NAME@ () +{ + return gnuradio::get_initial_sptr (new @NAME@ ()); +} + +@NAME@::@NAME@ () + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, -1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + + int ninputs = input_items.size (); + + for (int i = 0; i < noutput_items; i++) { + @I_TYPE@ acc = ((@I_TYPE@ *) input_items[0])[i]; + for (int j = 1; j < ninputs; j++) + acc = acc & ((@I_TYPE@ *) input_items[j])[i]; + + *optr++ = (@O_TYPE@) acc; + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/gengen/gr_and_XX.h.t b/gnuradio-core/src/lib/gengen/gr_and_XX.h.t new file mode 100644 index 000000000..224778096 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_and_XX.h.t @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (); + +/*! + * \brief output = input_0 & input_1 & , ... & input_N) + * \ingroup math_blk + * + * bitwise boolean and across all input streams. + */ +class GR_CORE_API @NAME@ : public gr_sync_block +{ + friend GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (); + + @NAME@ (); + + 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/gengen/gr_and_XX.i.t b/gnuradio-core/src/lib/gengen/gr_and_XX.i.t new file mode 100644 index 000000000..06db5ca59 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_and_XX.i.t @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (); +}; diff --git a/gnuradio-core/src/lib/gengen/gr_and_const_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_and_const_XX.cc.t new file mode 100644 index 000000000..d4f9a4b61 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_and_const_XX.cc.t @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,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> + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (@I_TYPE@ k) +{ + return gnuradio::get_initial_sptr (new @NAME@ (k)); +}; + +@NAME@::@NAME@ (@I_TYPE@ k) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))), + d_k (k) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @I_TYPE@ *iptr = (@I_TYPE@ *) input_items[0]; + @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + + int size = noutput_items; + + while (size >= 8) { + *optr++ = *iptr++ & d_k; + *optr++ = *iptr++ & d_k; + *optr++ = *iptr++ & d_k; + *optr++ = *iptr++ & d_k; + *optr++ = *iptr++ & d_k; + *optr++ = *iptr++ & d_k; + *optr++ = *iptr++ & d_k; + *optr++ = *iptr++ & d_k; + size -= 8; + } + + while (size-- > 0) + *optr++ = *iptr++ & d_k; + + return (noutput_items); +} diff --git a/gnuradio-core/src/lib/gengen/gr_and_const_XX.h.t b/gnuradio-core/src/lib/gengen/gr_and_const_XX.h.t new file mode 100644 index 000000000..b331f33cc --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_and_const_XX.h.t @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (@O_TYPE@ k); + +/*! + * \brief output_N = input_N & value + * \ingroup math_blk + * + * bitwise boolean and of const to the data stream. + */ +class GR_CORE_API @NAME@ : public gr_sync_block +{ + friend GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (@O_TYPE@ k); + + @O_TYPE@ d_k; // the constant + @NAME@ (@O_TYPE@ k); + + public: + @O_TYPE@ k () const { return d_k; } + void set_k (@O_TYPE@ k) { d_k = k; } + + 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/gengen/gr_and_const_XX.i.t b/gnuradio-core/src/lib/gengen/gr_and_const_XX.i.t new file mode 100644 index 000000000..c797c45eb --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_and_const_XX.i.t @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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@ (@O_TYPE@ k); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (@O_TYPE@ k); + + public: + @O_TYPE@ k () const { return d_k; } + void set_k (@O_TYPE@ k) { d_k = k; } +}; diff --git a/gnuradio-core/src/lib/gengen/gr_argmax_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_argmax_XX.cc.t new file mode 100644 index 000000000..f780bd811 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_argmax_XX.cc.t @@ -0,0 +1,79 @@ +/* -*- 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. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <gr_io_signature.h> + +@SPTR_NAME@ +gr_make_@BASE_NAME@ ( size_t vlen ) +{ + return @SPTR_NAME@ ( new @NAME@(vlen)); +} + +@NAME@::@NAME@( size_t vlen) + : gr_sync_block ( "@BASE_NAME@", + gr_make_io_signature (1, -1, vlen*sizeof (@I_TYPE@)), + gr_make_io_signature (2, 2, sizeof (@O_TYPE@))), + d_vlen(vlen) +{ +} + + +int +@NAME@::work( int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + + int ninputs = input_items.size (); + + @O_TYPE@ *x_optr = (@O_TYPE@ *) output_items[0]; + @O_TYPE@ *y_optr = (@O_TYPE@ *) output_items[1]; + + for (int i=0; i<noutput_items; i++) { + + @I_TYPE@ max = ((@I_TYPE@ *) input_items[0])[i*d_vlen]; + int x = 0; + int y = 0; + + for (int j=0; j < (int) d_vlen; j++ ) { + for (int k=0; k<ninputs; k++) { + if ( ((@I_TYPE@ *) input_items[k])[i*d_vlen + j] > max) { + max = ((@I_TYPE@ *) input_items[k])[i*d_vlen + j]; + x = j; + y = k; + } + } + } + + *x_optr++ = (@O_TYPE@) x; + *y_optr++ = (@O_TYPE@) y; + } + return noutput_items; +} + diff --git a/gnuradio-core/src/lib/gengen/gr_argmax_XX.h.t b/gnuradio-core/src/lib/gengen/gr_argmax_XX.h.t new file mode 100644 index 000000000..a706221fb --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_argmax_XX.h.t @@ -0,0 +1,52 @@ +/* -*- 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. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (size_t vlen); + + +class GR_CORE_API @NAME@ : public gr_sync_block +{ + friend GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (size_t vlen); + + @NAME@ (size_t vlen); + size_t d_vlen; + + 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/gengen/gr_argmax_XX.i.t b/gnuradio-core/src/lib/gengen/gr_argmax_XX.i.t new file mode 100644 index 000000000..233551ad9 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_argmax_XX.i.t @@ -0,0 +1,34 @@ +/* -*- 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. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (size_t vlen); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (size_t vlen); + size_t d_vlen; +}; 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 new file mode 100644 index 000000000..4a642c13e --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_chunks_to_symbols_XX.cc.t @@ -0,0 +1,74 @@ +/* -*- 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 new file mode 100644 index 000000000..17d5688b8 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_chunks_to_symbols_XX.h.t @@ -0,0 +1,73 @@ +/* -*- 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 new file mode 100644 index 000000000..14c8be486 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_chunks_to_symbols_XX.i.t @@ -0,0 +1,37 @@ +/* -*- 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/gengen/gr_divide_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_divide_XX.cc.t new file mode 100644 index 000000000..63450cb3d --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_divide_XX.cc.t @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004, 2009,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> + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (size_t vlen) +{ + return gnuradio::get_initial_sptr (new @NAME@ (vlen)); +} + +@NAME@::@NAME@ (size_t vlen) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, -1, sizeof (@I_TYPE@)*vlen), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@)*vlen)), + d_vlen (vlen) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + + int ninputs = input_items.size (); + + if (ninputs == 1){ // compute reciprocal + for (size_t i = 0; i < noutput_items*d_vlen; i++) + *optr++ = (@O_TYPE@) ((@O_TYPE@) 1 / + ((@I_TYPE@ *) input_items[0])[i]); + } + + else { + for (size_t i = 0; i < noutput_items*d_vlen; i++){ + @I_TYPE@ acc = ((@I_TYPE@ *) input_items[0])[i]; + for (int j = 1; j < ninputs; j++) + acc /= ((@I_TYPE@ *) input_items[j])[i]; + + *optr++ = (@O_TYPE@) acc; + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/gengen/gr_divide_XX.h.t b/gnuradio-core/src/lib/gengen/gr_divide_XX.h.t new file mode 100644 index 000000000..40ee27a51 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_divide_XX.h.t @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004, 2009 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_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (size_t vlen = 1); + +/*! + * \brief output = input_0 / input_1 / input_x ...) + * \ingroup math_blk + * + * Divide across all input streams. + */ +class GR_CORE_API @NAME@ : public gr_sync_block +{ + friend GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (size_t vlen); + + @NAME@ (size_t vlen); + + size_t d_vlen; + + 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/gengen/gr_divide_XX.i.t b/gnuradio-core/src/lib/gengen/gr_divide_XX.i.t new file mode 100644 index 000000000..b2c510610 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_divide_XX.i.t @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004, 2009 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@ (size_t vlen = 1); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (size_t vlen); +}; diff --git a/gnuradio-core/src/lib/gengen/gr_endianness.h b/gnuradio-core/src/lib/gengen/gr_endianness.h new file mode 100644 index 000000000..c4ecb1383 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_endianness.h @@ -0,0 +1,27 @@ +/* -*- 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_ENDIANNESS_H +#define INCLUDED_GR_ENDIANNESS_H + +typedef enum {GR_MSB_FIRST, GR_LSB_FIRST} gr_endianness_t; + +#endif /* INCLUDED_GR_ENDIANNESS_H */ diff --git a/gnuradio-core/src/lib/gengen/gr_endianness.i b/gnuradio-core/src/lib/gengen/gr_endianness.i new file mode 100644 index 000000000..572b7a42f --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_endianness.i @@ -0,0 +1,23 @@ +/* -*- 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. + */ + +%include <gr_endianness.h> diff --git a/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.cc.t b/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.cc.t new file mode 100644 index 000000000..7be7bdde8 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.cc.t @@ -0,0 +1,116 @@ +/* -*- 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 <stdexcept> + + +@NAME@_sptr +gr_make_@BASE_NAME@ (gr_noise_type_t type, float ampl, long seed, long samples) +{ + return gnuradio::get_initial_sptr(new @NAME@ (type, ampl, seed, samples)); +} + + +@NAME@::@NAME@ (gr_noise_type_t type, float ampl, long seed, long samples) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 1, sizeof (@TYPE@))), + d_type (type), + d_ampl (ampl), + d_rng (seed) +{ + d_samples.resize(samples); + generate(); +} + +void +@NAME@::generate() +{ + int noutput_items = d_samples.size(); + switch (d_type){ +#if @IS_COMPLEX@ // complex? + + case GR_UNIFORM: + for (int i = 0; i < noutput_items; i++) + d_samples[i] = gr_complex (d_ampl * ((d_rng.ran1 () * 2.0) - 1.0), + d_ampl * ((d_rng.ran1 () * 2.0) - 1.0)); + break; + + case GR_GAUSSIAN: + for (int i = 0; i < noutput_items; i++) + d_samples[i] = d_ampl * d_rng.rayleigh_complex (); + break; + +#else // nope... + + case GR_UNIFORM: + for (int i = 0; i < noutput_items; i++) + d_samples[i] = (@TYPE@)(d_ampl * ((d_rng.ran1 () * 2.0) - 1.0)); + break; + + case GR_GAUSSIAN: + for (int i = 0; i < noutput_items; i++) + d_samples[i] = (@TYPE@)(d_ampl * d_rng.gasdev ()); + break; + + case GR_LAPLACIAN: + for (int i = 0; i < noutput_items; i++) + d_samples[i] = (@TYPE@)(d_ampl * d_rng.laplacian ()); + break; + + case GR_IMPULSE: // FIXME changeable impulse settings + for (int i = 0; i < noutput_items; i++) + d_samples[i] = (@TYPE@)(d_ampl * d_rng.impulse (9)); + break; +#endif + + default: + throw std::runtime_error ("invalid type"); + } + +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @TYPE@ *out = (@TYPE@ *) output_items[0]; + + for(int i=0; i<noutput_items; i++){ +#ifdef __USE_GNU + size_t idx = lrand48() % d_samples.size(); +#else + size_t idx = rand() % d_samples.size(); +#endif + out[i] = d_samples[idx]; + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.h.t b/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.h.t new file mode 100644 index 000000000..007e44975 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.h.t @@ -0,0 +1,87 @@ +/* -*- 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_block.h> +#include <gr_noise_type.h> +#include <gr_random.h> + + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @NAME@_sptr; + +/*! \brief Make a noise source + * \param type the random distribution to use (see gr_noise_type.h) + * \param ampl a scaling factor for the output + * \param seed seed for random generators. Note that for uniform and + * Gaussian distributions, this should be a negative number. + * \param samples number of samples to pre-generate. + */ +GR_CORE_API @NAME@_sptr +gr_make_@BASE_NAME@ (gr_noise_type_t type, float ampl, long seed = 0, long samples=1024*16); + +/*! + * \brief Random number source + * \ingroup source_blk + * + * \details + * Generate random values from different distributions. + * Currently, only Gaussian and uniform are enabled. + * + * \param type the random distribution to use (see gr_noise_type.h) + * \param ampl a scaling factor for the output + * \param seed seed for random generators. Note that for uniform and + * Gaussian distributions, this should be a negative number. + * \param samples number of samples to pre-generate. + */ +class GR_CORE_API @NAME@ : public gr_sync_block { + friend GR_CORE_API @NAME@_sptr + + gr_make_@BASE_NAME@ (gr_noise_type_t type, float ampl, long seed, long samples); + + gr_noise_type_t d_type; + float d_ampl; + gr_random d_rng; + std::vector<@TYPE@> d_samples; + + @NAME@ (gr_noise_type_t type, float ampl, long seed = 0, long samples=1024*16); + + public: + void set_type (gr_noise_type_t type) { d_type = type; generate(); } + void set_amplitude (float ampl) { d_ampl = ampl; generate(); } + void generate(); + + gr_noise_type_t type () const { return d_type; } + float amplitude () const { return d_ampl; } + + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif diff --git a/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.i.t b/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.i.t new file mode 100644 index 000000000..e1f7c775b --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_fastnoise_source_X.i.t @@ -0,0 +1,40 @@ +/* -*- 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@); + +@NAME@_sptr +gr_make_@BASE_NAME@ (gr_noise_type_t type, float ampl, long seed = 0, long samples = 1024*16); + +class @NAME@ : public gr_block { + private: + @NAME@ (gr_noise_type_t type, float ampl, long seed = 0, long samples = 1024*16); + + public: + void set_type (gr_noise_type_t type) { d_type = type; } + void set_amplitude (float ampl) { d_ampl = ampl; } + + gr_noise_type_t type () const { return d_type; } + float amplitude () const { return d_ampl; } +}; diff --git a/gnuradio-core/src/lib/gengen/gr_integrate_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_integrate_XX.cc.t new file mode 100644 index 000000000..1dbee49db --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_integrate_XX.cc.t @@ -0,0 +1,67 @@ +/* -*- 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. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <gr_io_signature.h> + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (int decim) +{ + return gnuradio::get_initial_sptr (new @NAME@ (decim)); +} + +@NAME@::@NAME@ (int decim) + : gr_sync_decimator ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@)), + decim), + d_decim(decim), + d_count(0) +{ +} + +@NAME@::~@NAME@ () +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const @I_TYPE@ *in = (const @I_TYPE@ *) input_items[0]; + @O_TYPE@ *out = (@O_TYPE@ *) output_items[0]; + + for (int i = 0; i < noutput_items; i++) { + out[i] = (@O_TYPE@)0; + for (int j = 0; j < d_decim; j++) + out[i] += in[i*d_decim+j]; + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/gengen/gr_integrate_XX.h.t b/gnuradio-core/src/lib/gengen/gr_integrate_XX.h.t new file mode 100644 index 000000000..abb13ea90 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_integrate_XX.h.t @@ -0,0 +1,61 @@ +/* -*- 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. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_core_api.h> +#include <gr_sync_decimator.h> + +class @NAME@; + +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (int decim); + +/*! + * \brief output = sum(input[0]...input[n]) + * \ingroup math_blk + * + * Integrate successive samples in input stream and decimate + */ +class GR_CORE_API @NAME@ : public gr_sync_decimator +{ +private: + friend GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@(int decim); + + @NAME@ (int decim); + + int d_decim; + int d_count; + +public: + ~@NAME@ (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* @GUARD_NAME@ */ diff --git a/gnuradio-core/src/lib/gengen/gr_integrate_XX.i.t b/gnuradio-core/src/lib/gengen/gr_integrate_XX.i.t new file mode 100644 index 000000000..a96e5fd29 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_integrate_XX.i.t @@ -0,0 +1,33 @@ +/* -*- 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. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@); + +@SPTR_NAME@ gr_make_@BASE_NAME@ (int decim); + +class @NAME@ : public gr_sync_decimator +{ +private: + @NAME@ (); +}; diff --git a/gnuradio-core/src/lib/gengen/gr_max_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_max_XX.cc.t new file mode 100644 index 000000000..c53820cd6 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_max_XX.cc.t @@ -0,0 +1,71 @@ +/* -*- 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. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <gr_io_signature.h> + +@SPTR_NAME@ +gr_make_@BASE_NAME@ ( size_t vlen ) +{ + return @SPTR_NAME@ ( new @NAME@(vlen)); +} + +@NAME@::@NAME@( size_t vlen) + : gr_sync_block ( "@BASE_NAME@", + gr_make_io_signature (1, -1, vlen*sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))), + d_vlen(vlen) +{ +} + +int +@NAME@::work( int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + + int ninputs = input_items.size (); + + for (int i=0; i<noutput_items; i++) { + + @I_TYPE@ max = ((@I_TYPE@ *) input_items[0])[i*d_vlen]; + + for (int j=0; j < (int) d_vlen; j++ ) { + for (int k=0; k<ninputs; k++) { + if ( ((@I_TYPE@ *) input_items[k])[i*d_vlen + j] > max) { + max = ((@I_TYPE@*) input_items[k])[i*d_vlen + j]; + } + } + } + + *optr++ = (@O_TYPE@) max; + } + return noutput_items; +} + diff --git a/gnuradio-core/src/lib/gengen/gr_max_XX.h.t b/gnuradio-core/src/lib/gengen/gr_max_XX.h.t new file mode 100644 index 000000000..a706221fb --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_max_XX.h.t @@ -0,0 +1,52 @@ +/* -*- 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. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (size_t vlen); + + +class GR_CORE_API @NAME@ : public gr_sync_block +{ + friend GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (size_t vlen); + + @NAME@ (size_t vlen); + size_t d_vlen; + + 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/gengen/gr_max_XX.i.t b/gnuradio-core/src/lib/gengen/gr_max_XX.i.t new file mode 100644 index 000000000..233551ad9 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_max_XX.i.t @@ -0,0 +1,34 @@ +/* -*- 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. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (size_t vlen); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (size_t vlen); + size_t d_vlen; +}; diff --git a/gnuradio-core/src/lib/gengen/gr_moving_average_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_moving_average_XX.cc.t new file mode 100644 index 000000000..ddee30bd7 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_moving_average_XX.cc.t @@ -0,0 +1,93 @@ +/* -*- 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. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <gr_io_signature.h> + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (int length, @O_TYPE@ scale, int max_iter) +{ + return gnuradio::get_initial_sptr (new @NAME@ (length, scale, max_iter)); +} + +@NAME@::@NAME@ (int length, @O_TYPE@ scale, int max_iter) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))), + d_length(length), + d_scale(scale), + d_max_iter(max_iter), + d_new_length(length), + d_new_scale(scale), + d_updated(false) +{ + set_history(length); +} + +@NAME@::~@NAME@ () +{ +} + +void +@NAME@::set_length_and_scale(int length, @O_TYPE@ scale) +{ + d_new_length = length; + d_new_scale = scale; + d_updated = true; +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + if (d_updated) { + d_length = d_new_length; + d_scale = d_new_scale; + set_history(d_length); + d_updated = false; + return 0; // history requirements might have changed + } + + const @I_TYPE@ *in = (const @I_TYPE@ *) input_items[0]; + @O_TYPE@ *out = (@O_TYPE@ *) output_items[0]; + + @I_TYPE@ sum = 0; + int num_iter = (noutput_items>d_max_iter) ? d_max_iter : noutput_items; + for (int i = 0; i < d_length-1 ; i++) { + sum += in[i]; + } + + for (int i = 0; i < num_iter; i++) { + sum += in[i+d_length-1]; + out[i] = sum * d_scale; + sum -= in[i]; + } + + return num_iter; +} diff --git a/gnuradio-core/src/lib/gengen/gr_moving_average_XX.h.t b/gnuradio-core/src/lib/gengen/gr_moving_average_XX.h.t new file mode 100644 index 000000000..37678abe1 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_moving_average_XX.h.t @@ -0,0 +1,72 @@ +/* -*- 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. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class @NAME@; + +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (int length, @O_TYPE@ scale, int max_iter = 4096); + +/*! + * \brief output is the moving sum of the last N samples, scaled by the scale factor + * \ingroup filter_blk + * + * max_iter limits how long we go without flushing the accumulator + * This is necessary to avoid numerical instability for float and complex. + */ +class GR_CORE_API @NAME@ : public gr_sync_block +{ +private: + friend GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@(int length, @O_TYPE@ scale, int max_iter); + + @NAME@ (int length, @O_TYPE@ scale, int max_iter = 4096); + + int d_length; + @O_TYPE@ d_scale; + int d_max_iter; + + int d_new_length; + @O_TYPE@ d_new_scale; + bool d_updated; + +public: + ~@NAME@ (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + int length() const { return d_new_length; } + @O_TYPE@ scale() const { return d_new_scale; } + + void set_length_and_scale(int length, @O_TYPE@ scale); +}; + +#endif /* @GUARD_NAME@ */ diff --git a/gnuradio-core/src/lib/gengen/gr_moving_average_XX.i.t b/gnuradio-core/src/lib/gengen/gr_moving_average_XX.i.t new file mode 100644 index 000000000..6e3b9ca9b --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_moving_average_XX.i.t @@ -0,0 +1,38 @@ +/* -*- 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. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@); + +@SPTR_NAME@ gr_make_@BASE_NAME@ (int length, @O_TYPE@ scale, int max_iter=4096); + +class @NAME@ : public gr_sync_block +{ +private: + @NAME@ (); + + public: + int length() const; + @O_TYPE@ scale() const; + void set_length_and_scale(int length, @O_TYPE@ scale); +}; diff --git a/gnuradio-core/src/lib/gengen/gr_multiply_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_multiply_XX.cc.t new file mode 100644 index 000000000..a60118e14 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_multiply_XX.cc.t @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004, 2009,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> + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (size_t vlen) +{ + return gnuradio::get_initial_sptr (new @NAME@ (vlen)); +} + +@NAME@::@NAME@ (size_t vlen) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, -1, sizeof (@I_TYPE@)*vlen), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@)*vlen)), + d_vlen (vlen) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + + int ninputs = input_items.size (); + + for (size_t i = 0; i < noutput_items*d_vlen; i++){ + @I_TYPE@ acc = ((@I_TYPE@ *) input_items[0])[i]; + for (int j = 1; j < ninputs; j++) + acc *= ((@I_TYPE@ *) input_items[j])[i]; + + *optr++ = (@O_TYPE@) acc; + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/gengen/gr_multiply_XX.h.t b/gnuradio-core/src/lib/gengen/gr_multiply_XX.h.t new file mode 100644 index 000000000..18ec6d0be --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_multiply_XX.h.t @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004, 2009 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_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (size_t vlen = 1); + +/*! + * \brief output = prod (input_0, input_1, ...) + * \ingroup math_blk + * + * Multiply across all input streams. + */ +class GR_CORE_API @NAME@ : public gr_sync_block +{ + friend GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (size_t vlen); + + @NAME@ (size_t vlen); + + size_t d_vlen; + + 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/gengen/gr_multiply_XX.i.t b/gnuradio-core/src/lib/gengen/gr_multiply_XX.i.t new file mode 100644 index 000000000..b2c510610 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_multiply_XX.i.t @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004, 2009 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@ (size_t vlen = 1); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (size_t vlen); +}; diff --git a/gnuradio-core/src/lib/gengen/gr_multiply_const_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_multiply_const_XX.cc.t new file mode 100644 index 000000000..424b62412 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_multiply_const_XX.cc.t @@ -0,0 +1,72 @@ +/* -*- 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> + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (@O_TYPE@ k) +{ + return gnuradio::get_initial_sptr (new @NAME@ (k)); +} + +@NAME@::@NAME@ (@O_TYPE@ k) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))), + d_k (k) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @I_TYPE@ *iptr = (@I_TYPE@ *) input_items[0]; + @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + + int size = noutput_items; + + while (size >= 8){ + *optr++ = *iptr++ * d_k; + *optr++ = *iptr++ * d_k; + *optr++ = *iptr++ * d_k; + *optr++ = *iptr++ * d_k; + *optr++ = *iptr++ * d_k; + *optr++ = *iptr++ * d_k; + *optr++ = *iptr++ * d_k; + *optr++ = *iptr++ * d_k; + size -= 8; + } + + while (size-- > 0) + *optr++ = *iptr++ * d_k; + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/gengen/gr_multiply_const_XX.h.t b/gnuradio-core/src/lib/gengen/gr_multiply_const_XX.h.t new file mode 100644 index 000000000..274fc3b99 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_multiply_const_XX.h.t @@ -0,0 +1,56 @@ +/* -*- 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_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (@O_TYPE@ k); + +/*! + * \brief output = input * constant + * \ingroup math_blk + */ +class GR_CORE_API @NAME@ : public gr_sync_block +{ + friend GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (@O_TYPE@ k); + + @O_TYPE@ d_k; // the constant + @NAME@ (@O_TYPE@ k); + + public: + @O_TYPE@ k () const { return d_k; } + void set_k (@O_TYPE@ k) { d_k = k; } + + 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/gengen/gr_multiply_const_XX.i.t b/gnuradio-core/src/lib/gengen/gr_multiply_const_XX.i.t new file mode 100644 index 000000000..b7921554e --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_multiply_const_XX.i.t @@ -0,0 +1,37 @@ +/* -*- 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@ (@TYPE@ k); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (@TYPE@ k); + + public: + @TYPE@ k () const { return d_k; } + void set_k (@TYPE@ k) { d_k = k; } +}; diff --git a/gnuradio-core/src/lib/gengen/gr_multiply_const_vXX.cc.t b/gnuradio-core/src/lib/gengen/gr_multiply_const_vXX.cc.t new file mode 100755 index 000000000..eb896dee5 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_multiply_const_vXX.cc.t @@ -0,0 +1,61 @@ +/* -*- 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. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <gr_io_signature.h> + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (const std::vector<@I_TYPE@> &k) +{ + return gnuradio::get_initial_sptr (new @NAME@ (k)); +} + +@NAME@::@NAME@ (const std::vector<@I_TYPE@> &k) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof(@I_TYPE@)*k.size()), + gr_make_io_signature (1, 1, sizeof(@O_TYPE@)*k.size())) +{ + d_k = k; +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @I_TYPE@ *iptr = (@O_TYPE@ *)input_items[0]; + @O_TYPE@ *optr = (@O_TYPE@ *)output_items[0]; + + int nitems_per_block = output_signature()->sizeof_stream_item(0)/sizeof(@I_TYPE@); + + for (int i = 0; i < noutput_items; i++) + for (int j = 0; j < nitems_per_block; j++) + *optr++ = *iptr++ * d_k[j]; + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/gengen/gr_multiply_const_vXX.h.t b/gnuradio-core/src/lib/gengen/gr_multiply_const_vXX.h.t new file mode 100644 index 000000000..2c6edd364 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_multiply_const_vXX.h.t @@ -0,0 +1,56 @@ +/* -*- 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. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (const std::vector<@I_TYPE@> &k); + +/*! + * \brief output vector = input vector * constant vector (element-wise) + * \ingroup math_blk + */ +class GR_CORE_API @NAME@ : public gr_sync_block +{ + friend GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (const std::vector<@I_TYPE@> &k); + + std::vector<@I_TYPE@> d_k; // the constant + @NAME@ (const std::vector<@I_TYPE@> &k); + + public: + const std::vector<@I_TYPE@> k () const { return d_k; } + void set_k (const std::vector<@I_TYPE@> &k) { d_k = k; } + + 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/gengen/gr_multiply_const_vXX.i.t b/gnuradio-core/src/lib/gengen/gr_multiply_const_vXX.i.t new file mode 100755 index 000000000..e0e6ae905 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_multiply_const_vXX.i.t @@ -0,0 +1,37 @@ +/* -*- 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. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (const std::vector<@I_TYPE@> &k); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (const std::vector<@I_TYPE@> &k); + + public: + std::vector<@I_TYPE@> k () const { return d_k; } + void set_k (const std::vector<@I_TYPE@> &k) { d_k = k; } +}; diff --git a/gnuradio-core/src/lib/gengen/gr_mute_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_mute_XX.cc.t new file mode 100644 index 000000000..4b8ff8415 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_mute_XX.cc.t @@ -0,0 +1,79 @@ +/* -*- 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 <string.h> + + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (bool mute) +{ + return gnuradio::get_initial_sptr (new @NAME@ (mute)); +} + +@NAME@::@NAME@ (bool mute) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))), + d_mute (mute) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @I_TYPE@ *iptr = (@I_TYPE@ *) input_items[0]; + @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + + int size = noutput_items; + + if (d_mute){ + memset (optr, 0, noutput_items * sizeof(@O_TYPE@)); + } + else { + while (size >= 8){ + *optr++ = *iptr++; + *optr++ = *iptr++; + *optr++ = *iptr++; + *optr++ = *iptr++; + *optr++ = *iptr++; + *optr++ = *iptr++; + *optr++ = *iptr++; + *optr++ = *iptr++; + size -= 8; + } + + while (size-- > 0) + *optr++ = *iptr++; + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/gengen/gr_mute_XX.h.t b/gnuradio-core/src/lib/gengen/gr_mute_XX.h.t new file mode 100644 index 000000000..ca23904e9 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_mute_XX.h.t @@ -0,0 +1,56 @@ +/* -*- 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_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (bool mute=false); + +/*! + * \brief output = input or zero if muted. + * \ingroup level_blk + */ +class GR_CORE_API @NAME@ : public gr_sync_block +{ + friend GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (bool mute); + + bool d_mute; + @NAME@ (bool mute); + + public: + bool mute () const { return d_mute; } + void set_mute (bool mute) { d_mute = mute; } + + 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/gengen/gr_mute_XX.i.t b/gnuradio-core/src/lib/gengen/gr_mute_XX.i.t new file mode 100644 index 000000000..ffcfac8a6 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_mute_XX.i.t @@ -0,0 +1,37 @@ +/* -*- 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@(bool mute=false); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (bool mute); + + public: + bool mute () const { return d_mute; } + void set_mute (bool mute) { d_mute = mute; } +}; diff --git a/gnuradio-core/src/lib/gengen/gr_noise_source_X.cc.t b/gnuradio-core/src/lib/gengen/gr_noise_source_X.cc.t new file mode 100644 index 000000000..3078f6366 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_noise_source_X.cc.t @@ -0,0 +1,99 @@ +/* -*- 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 <stdexcept> + + +@NAME@_sptr +gr_make_@BASE_NAME@ (gr_noise_type_t type, float ampl, long seed) +{ + return gnuradio::get_initial_sptr(new @NAME@ (type, ampl, seed)); +} + + +@NAME@::@NAME@ (gr_noise_type_t type, float ampl, long seed) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 1, sizeof (@TYPE@))), + d_type (type), + d_ampl (ampl), + d_rng (seed) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @TYPE@ *out = (@TYPE@ *) output_items[0]; + + switch (d_type){ +#if @IS_COMPLEX@ // complex? + + case GR_UNIFORM: + for (int i = 0; i < noutput_items; i++) + out[i] = gr_complex (d_ampl * ((d_rng.ran1 () * 2.0) - 1.0), + d_ampl * ((d_rng.ran1 () * 2.0) - 1.0)); + break; + + case GR_GAUSSIAN: + for (int i = 0; i < noutput_items; i++) + out[i] = d_ampl * d_rng.rayleigh_complex (); + break; + +#else // nope... + + case GR_UNIFORM: + for (int i = 0; i < noutput_items; i++) + out[i] = (@TYPE@)(d_ampl * ((d_rng.ran1 () * 2.0) - 1.0)); + break; + + case GR_GAUSSIAN: + for (int i = 0; i < noutput_items; i++) + out[i] = (@TYPE@)(d_ampl * d_rng.gasdev ()); + break; + + case GR_LAPLACIAN: + for (int i = 0; i < noutput_items; i++) + out[i] = (@TYPE@)(d_ampl * d_rng.laplacian ()); + break; + + case GR_IMPULSE: // FIXME changeable impulse settings + for (int i = 0; i < noutput_items; i++) + out[i] = (@TYPE@)(d_ampl * d_rng.impulse (9)); + break; +#endif + + default: + throw std::runtime_error ("invalid type"); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/gengen/gr_noise_source_X.h.t b/gnuradio-core/src/lib/gengen/gr_noise_source_X.h.t new file mode 100644 index 000000000..31ffb2b16 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_noise_source_X.h.t @@ -0,0 +1,83 @@ +/* -*- 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_block.h> +#include <gr_noise_type.h> +#include <gr_random.h> + + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @NAME@_sptr; + +/*! \brief Make a noise source + * \param type the random distribution to use (see gr_noise_type.h) + * \param ampl a scaling factor for the output + * \param seed seed for random generators. Note that for uniform and + * Gaussian distributions, this should be a negative number. + */ +GR_CORE_API @NAME@_sptr +gr_make_@BASE_NAME@ (gr_noise_type_t type, float ampl, long seed = 0); + +/*! + * \brief Random number source + * \ingroup source_blk + * + * \details + * Generate random values from different distributions. + * Currently, only Gaussian and uniform are enabled. + * + * \param type the random distribution to use (see gr_noise_type.h) + * \param ampl a scaling factor for the output + * \param seed seed for random generators. Note that for uniform and + * Gaussian distributions, this should be a negative number. + */ +class GR_CORE_API @NAME@ : public gr_sync_block { + friend GR_CORE_API @NAME@_sptr + + gr_make_@BASE_NAME@ (gr_noise_type_t type, float ampl, long seed); + + gr_noise_type_t d_type; + float d_ampl; + gr_random d_rng; + + @NAME@ (gr_noise_type_t type, float ampl, long seed = 0); + + public: + void set_type (gr_noise_type_t type) { d_type = type; } + void set_amplitude (float ampl) { d_ampl = ampl; } + + gr_noise_type_t type () const { return d_type; } + float amplitude () const { return d_ampl; } + + virtual 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/gengen/gr_noise_source_X.i.t b/gnuradio-core/src/lib/gengen/gr_noise_source_X.i.t new file mode 100644 index 000000000..df27ab79b --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_noise_source_X.i.t @@ -0,0 +1,40 @@ +/* -*- 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@); + +@NAME@_sptr +gr_make_@BASE_NAME@ (gr_noise_type_t type, float ampl, long seed = 0); + +class @NAME@ : public gr_block { + private: + @NAME@ (gr_noise_type_t type, float ampl, long seed = 0); + + public: + void set_type (gr_noise_type_t type) { d_type = type; } + void set_amplitude (float ampl) { d_ampl = ampl; } + + gr_noise_type_t type () const { return d_type; } + float amplitude () const { return d_ampl; } +}; diff --git a/gnuradio-core/src/lib/gengen/gr_noise_type.h b/gnuradio-core/src/lib/gengen/gr_noise_type.h new file mode 100644 index 000000000..d2aba9b0c --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_noise_type.h @@ -0,0 +1,30 @@ +/* -*- 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_NOISE_TYPE_H +#define INCLUDED_GR_NOISE_TYPE_H + +typedef enum { + GR_UNIFORM = 200, GR_GAUSSIAN, GR_LAPLACIAN, GR_IMPULSE +} gr_noise_type_t; + +#endif /* INCLUDED_GR_NOISE_TYPE_H */ diff --git a/gnuradio-core/src/lib/gengen/gr_not_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_not_XX.cc.t new file mode 100644 index 000000000..4806b142f --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_not_XX.cc.t @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <gr_io_signature.h> + +@SPTR_NAME@ +gr_make_@BASE_NAME@ () +{ + return gnuradio::get_initial_sptr (new @NAME@ ()); +} + +@NAME@::@NAME@ () + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + const @I_TYPE@ *inptr = (const @I_TYPE@ *) input_items[0]; + + + for (int i = 0; i < noutput_items; i++) { + *optr++ = ~(inptr[i]); + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/gengen/gr_not_XX.h.t b/gnuradio-core/src/lib/gengen/gr_not_XX.h.t new file mode 100644 index 000000000..aff421109 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_not_XX.h.t @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (); + +/*! + * \brief output = ~input_0 + * \ingroup math_blk + * + * bitwise boolean not across input stream. + */ +class GR_CORE_API @NAME@ : public gr_sync_block +{ + friend GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (); + + @NAME@ (); + + 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/gengen/gr_not_XX.i.t b/gnuradio-core/src/lib/gengen/gr_not_XX.i.t new file mode 100644 index 000000000..06db5ca59 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_not_XX.i.t @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (); +}; diff --git a/gnuradio-core/src/lib/gengen/gr_or_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_or_XX.cc.t new file mode 100644 index 000000000..ee55eedda --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_or_XX.cc.t @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <gr_io_signature.h> + +@SPTR_NAME@ +gr_make_@BASE_NAME@ () +{ + return gnuradio::get_initial_sptr (new @NAME@ ()); +} + +@NAME@::@NAME@ () + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, -1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + + int ninputs = input_items.size (); + + for (int i = 0; i < noutput_items; i++) { + @I_TYPE@ acc = ((@I_TYPE@ *) input_items[0])[i]; + for (int j = 1; j < ninputs; j++) + acc = acc | ((@I_TYPE@ *) input_items[j])[i]; + + *optr++ = (@O_TYPE@) acc; + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/gengen/gr_or_XX.h.t b/gnuradio-core/src/lib/gengen/gr_or_XX.h.t new file mode 100644 index 000000000..8860eedd5 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_or_XX.h.t @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (); + +/*! + * \brief output = input_0 | input_1 | , ... | input_N) + * \ingroup math_blk + * + * bitwise boolean or across all input streams. + */ +class GR_CORE_API @NAME@ : public gr_sync_block +{ + friend GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (); + + @NAME@ (); + + 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/gengen/gr_or_XX.i.t b/gnuradio-core/src/lib/gengen/gr_or_XX.i.t new file mode 100644 index 000000000..06db5ca59 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_or_XX.i.t @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (); +}; diff --git a/gnuradio-core/src/lib/gengen/gr_packed_to_unpacked_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_packed_to_unpacked_XX.cc.t new file mode 100644 index 000000000..75e53c4ca --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_packed_to_unpacked_XX.cc.t @@ -0,0 +1,137 @@ +/* -*- 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@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <gr_io_signature.h> +#include <assert.h> +#include <gr_log2_const.h> + +static const unsigned int BITS_PER_TYPE = sizeof(@I_TYPE@) * 8; +static const unsigned int LOG2_L_TYPE = gr_log2_const<sizeof(@I_TYPE@) * 8>(); + + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (unsigned int bits_per_chunk, gr_endianness_t endianness) +{ + return @SPTR_NAME@ + (new @NAME@ (bits_per_chunk,endianness)); +} + +@NAME@::@NAME@ (unsigned int bits_per_chunk, + gr_endianness_t endianness) + : gr_block ("@BASE_NAME@", + gr_make_io_signature (1, -1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, -1, sizeof (@O_TYPE@))), + d_bits_per_chunk(bits_per_chunk),d_endianness(endianness),d_index(0) +{ + assert (bits_per_chunk <= BITS_PER_TYPE); + assert (bits_per_chunk > 0); + + set_relative_rate ((1.0 * BITS_PER_TYPE) / bits_per_chunk); +} + +void +@NAME@::forecast(int noutput_items, gr_vector_int &ninput_items_required) +{ + + int input_required = (int) ceil((d_index + noutput_items * d_bits_per_chunk) / (1.0 * BITS_PER_TYPE)); + unsigned ninputs = ninput_items_required.size(); + for (unsigned int i = 0; i < ninputs; i++) { + ninput_items_required[i] = input_required; + //printf("Forecast wants %d needs %d\n",noutput_items,ninput_items_required[i]); + } +} + +unsigned int +get_bit_le (const @I_TYPE@ *in_vector,unsigned int bit_addr) +{ + @I_TYPE@ x = in_vector[bit_addr>>LOG2_L_TYPE]; + return (x>>(bit_addr&(BITS_PER_TYPE-1)))&1; +} + +unsigned int +get_bit_be (const @I_TYPE@ *in_vector,unsigned int bit_addr) +{ + @I_TYPE@ x = in_vector[bit_addr>>LOG2_L_TYPE]; + return (x>>((BITS_PER_TYPE-1)-(bit_addr&(BITS_PER_TYPE-1))))&1; +} + +int +@NAME@::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + unsigned int index_tmp = d_index; + + 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]; + index_tmp = d_index; + + // per stream processing + + switch (d_endianness){ + + case GR_MSB_FIRST: + for (int i = 0; i < noutput_items; i++){ + //printf("here msb %d\n",i); + @O_TYPE@ x = 0; + for(unsigned int j=0; j<d_bits_per_chunk; j++, index_tmp++) + x = (x<<1) | get_bit_be(in, index_tmp); + out[i] = x; + } + break; + + case GR_LSB_FIRST: + for (int i = 0; i < noutput_items; i++){ + //printf("here lsb %d\n",i); + @O_TYPE@ x = 0; + for(unsigned int j=0; j<d_bits_per_chunk; j++, index_tmp++) + x = (x<<1) | get_bit_le(in, index_tmp); + out[i] = x; + } + break; + + default: + assert(0); + } + + //printf("almost got to end\n"); + assert(ninput_items[m] >= (int) ((d_index+(BITS_PER_TYPE-1))>>LOG2_L_TYPE)); + } + + d_index = index_tmp; + consume_each (d_index >> LOG2_L_TYPE); + d_index = d_index & (BITS_PER_TYPE-1); + //printf("got to end\n"); + return noutput_items; +} diff --git a/gnuradio-core/src/lib/gengen/gr_packed_to_unpacked_XX.h.t b/gnuradio-core/src/lib/gengen/gr_packed_to_unpacked_XX.h.t new file mode 100644 index 000000000..e95771b37 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_packed_to_unpacked_XX.h.t @@ -0,0 +1,85 @@ +/* -*- 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. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_core_api.h> +#include <gr_block.h> +#include <gr_endianness.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +GR_CORE_API @SPTR_NAME@ +gr_make_@BASE_NAME@ (unsigned int bits_per_chunk, gr_endianness_t endianness); + +/*! + * \brief Convert a stream of packed bytes or shorts to stream of unpacked bytes or shorts. + * \ingroup converter_blk + * + * input: stream of @I_TYPE@; output: stream of @O_TYPE@ + * + * This is the inverse of gr_unpacked_to_packed_XX. + * + * The bits in the bytes or shorts input stream are grouped into chunks of + * \p bits_per_chunk bits and each resulting chunk is written right- + * justified to the output stream of bytes or shorts. + * All b or 16 bits of the each input bytes or short are processed. + * The right thing is done if bits_per_chunk is not a power of two. + * + * The combination of gr_packed_to_unpacked_XX_ followed by + * gr_chunks_to_symbols_Xf or gr_chunks_to_symbols_Xc 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_block +{ + friend GR_CORE_API @SPTR_NAME@ + gr_make_@BASE_NAME@ (unsigned int bits_per_chunk, gr_endianness_t endianness); + + @NAME@ (unsigned int bits_per_chunk, gr_endianness_t endianness); + + unsigned int d_bits_per_chunk; + gr_endianness_t d_endianness; + unsigned int d_index; + + 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); + + bool check_topology(int ninputs, int noutputs) { return ninputs == noutputs; } + +}; + +#endif diff --git a/gnuradio-core/src/lib/gengen/gr_packed_to_unpacked_XX.i.t b/gnuradio-core/src/lib/gengen/gr_packed_to_unpacked_XX.i.t new file mode 100644 index 000000000..1e978956a --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_packed_to_unpacked_XX.i.t @@ -0,0 +1,33 @@ +/* -*- 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@ (unsigned int bits_per_chunk, gr_endianness_t endianness); + +class @NAME@ : public gr_block +{ + @NAME@ (unsigned int bits_per_chunk, gr_endianness_t endianness); +}; diff --git a/gnuradio-core/src/lib/gengen/gr_peak_detector_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_peak_detector_XX.cc.t new file mode 100644 index 000000000..54af3c0cd --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_peak_detector_XX.cc.t @@ -0,0 +1,111 @@ +/* -*- 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. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <gr_io_signature.h> +#include <string.h> + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (float threshold_factor_rise, + float threshold_factor_fall, + int look_ahead, float alpha) +{ + return gnuradio::get_initial_sptr (new @NAME@ (threshold_factor_rise, + threshold_factor_fall, + look_ahead, alpha)); +} + +@NAME@::@NAME@ (float threshold_factor_rise, + float threshold_factor_fall, + int look_ahead, float alpha) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (char))), + d_threshold_factor_rise(threshold_factor_rise), + d_threshold_factor_fall(threshold_factor_fall), + d_look_ahead(look_ahead), d_avg_alpha(alpha), d_avg(0), d_found(0) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @I_TYPE@ *iptr = (@I_TYPE@ *) input_items[0]; + char *optr = (char *) output_items[0]; + + memset(optr, 0, noutput_items*sizeof(char)); + + @I_TYPE@ peak_val = -(@I_TYPE@)INFINITY; + int peak_ind = 0; + unsigned char state = 0; + int i = 0; + + //printf("noutput_items %d\n",noutput_items); + while(i < noutput_items) { + if(state == 0) { // below threshold + if(iptr[i] > d_avg*d_threshold_factor_rise) { + state = 1; + } + else { + d_avg = (d_avg_alpha)*iptr[i] + (1-d_avg_alpha)*d_avg; + i++; + } + } + else if(state == 1) { // above threshold, have not found peak + //printf("Entered State 1: %f i: %d noutput_items: %d\n", iptr[i], i, noutput_items); + if(iptr[i] > peak_val) { + peak_val = iptr[i]; + peak_ind = i; + d_avg = (d_avg_alpha)*iptr[i] + (1-d_avg_alpha)*d_avg; + i++; + } + else if (iptr[i] > d_avg*d_threshold_factor_fall) { + d_avg = (d_avg_alpha)*iptr[i] + (1-d_avg_alpha)*d_avg; + i++; + } + else { + optr[peak_ind] = 1; + state = 0; + peak_val = -(@I_TYPE@)INFINITY; + //printf("Leaving State 1: Peak: %f Peak Ind: %d i: %d noutput_items: %d\n", + //peak_val, peak_ind, i, noutput_items); + } + } + } + + if(state == 0) { + //printf("Leave in State 0, produced %d\n",noutput_items); + return noutput_items; + } + else { // only return up to passing the threshold + //printf("Leave in State 1, only produced %d of %d\n",peak_ind,noutput_items); + return peak_ind+1; + } +} diff --git a/gnuradio-core/src/lib/gengen/gr_peak_detector_XX.h.t b/gnuradio-core/src/lib/gengen/gr_peak_detector_XX.h.t new file mode 100644 index 000000000..3e05594fb --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_peak_detector_XX.h.t @@ -0,0 +1,126 @@ +/* -*- 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. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (float threshold_factor_rise = 0.25, + float threshold_factor_fall = 0.40, + int look_ahead = 10, + float alpha = 0.001); + +/*! + * \brief Detect the peak of a signal + * \ingroup level_blk + * + * If a peak is detected, this block outputs a 1, + * or it outputs 0's. + * + * \param threshold_factor_rise The threshold factor determins when a peak + * has started. An average of the signal is calculated and when the + * value of the signal goes over threshold_factor_rise*average, we + * start looking for a peak. + * \param threshold_factor_fall The threshold factor determins when a peak + * has ended. An average of the signal is calculated and when the + * value of the signal goes bellow threshold_factor_fall*average, we + * stop looking for a peak. + * \param look_ahead The look-ahead value is used when the threshold is + * found to look if there another peak within this step range. + * If there is a larger value, we set that as the peak and look ahead + * again. This is continued until the highest point is found with + * This look-ahead range. + * \param alpha The gain value of a moving average filter + */ +class GR_CORE_API @NAME@ : public gr_sync_block +{ + friend GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (float threshold_factor_rise, + float threshold_factor_fall, + int look_ahead, float alpha); + + @NAME@ (float threshold_factor_rise, + float threshold_factor_fall, + int look_ahead, float alpha); + + private: + float d_threshold_factor_rise; + float d_threshold_factor_fall; + int d_look_ahead; + float d_avg_alpha; + float d_avg; + unsigned char d_found; + + public: + + /*! \brief Set the threshold factor value for the rise time + * \param thr new threshold factor + */ + void set_threshold_factor_rise(float thr) { d_threshold_factor_rise = thr; } + + /*! \brief Set the threshold factor value for the fall time + * \param thr new threshold factor + */ + void set_threshold_factor_fall(float thr) { d_threshold_factor_fall = thr; } + + /*! \brief Set the look-ahead factor + * \param look new look-ahead factor + */ + void set_look_ahead(int look) { d_look_ahead = look; } + + /*! \brief Set the running average alpha + * \param alpha new alpha for running average + */ + void set_alpha(int alpha) { d_avg_alpha = alpha; } + + /*! \brief Get the threshold factor value for the rise time + * \return threshold factor + */ + float threshold_factor_rise() { return d_threshold_factor_rise; } + + /*! \brief Get the threshold factor value for the fall time + * \return threshold factor + */ + float threshold_factor_fall() { return d_threshold_factor_fall; } + + /*! \brief Get the look-ahead factor value + * \return look-ahead factor + */ + int look_ahead() { return d_look_ahead; } + + /*! \brief Get the alpha value of the running average + * \return alpha + */ + float alpha() { return d_avg_alpha; } + + 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/gengen/gr_peak_detector_XX.i.t b/gnuradio-core/src/lib/gengen/gr_peak_detector_XX.i.t new file mode 100644 index 000000000..212ce0c94 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_peak_detector_XX.i.t @@ -0,0 +1,49 @@ +/* -*- 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. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (float threshold_factor_rise = 0.25, + float threshold_factor_fall = 0.40, + int look_ahead = 10, + float alpha=0.001); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (float threshold_factor_rise, + float threshold_factor_fall, + int look_ahead, float alpha); + + public: + void set_threshold_factor_rise(float thr) { d_threshold_factor_rise = thr; } + void set_threshold_factor_fall(float thr) { d_threshold_factor_fall = thr; } + void set_look_ahead(int look) { d_look_ahead = look; } + void set_alpha(int alpha) { d_avg_alpha = alpha; } + + float threshold_factor_rise() { return d_threshold_factor_rise; } + float threshold_factor_fall() { return d_threshold_factor_fall; } + int look_ahead() { return d_look_ahead; } + float alpha() { return d_avg_alpha; } +}; diff --git a/gnuradio-core/src/lib/gengen/gr_probe_signal_X.cc.t b/gnuradio-core/src/lib/gengen/gr_probe_signal_X.cc.t new file mode 100644 index 000000000..9a10bab59 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_probe_signal_X.cc.t @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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 <@NAME@.h> +#include <gr_io_signature.h> + +@NAME@_sptr +gr_make_@BASE_NAME@() +{ + return gnuradio::get_initial_sptr(new @NAME@()); +} + +@NAME@::@NAME@ () +: gr_sync_block ("@BASE_NAME@", + gr_make_io_signature(1, 1, sizeof(@TYPE@)), + gr_make_io_signature(0, 0, 0)), + d_level(0) +{ +} + +@NAME@::~@NAME@() +{ +} + + +int +@NAME@::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const @TYPE@ *in = (const @TYPE@ *) input_items[0]; + + if (noutput_items > 0) + d_level = in[noutput_items-1]; + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/gengen/gr_probe_signal_X.h.t b/gnuradio-core/src/lib/gengen/gr_probe_signal_X.h.t new file mode 100644 index 000000000..936f437f1 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_probe_signal_X.h.t @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005, 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 @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @NAME@_sptr; + +GR_CORE_API @NAME@_sptr +gr_make_@BASE_NAME@ (); + +/*! + * \brief Sink that allows a sample to be grabbed from Python. + * \ingroup sink_blk + */ +class GR_CORE_API @NAME@ : public gr_sync_block +{ + @TYPE@ d_level; + + friend GR_CORE_API @NAME@_sptr + gr_make_@BASE_NAME@(); + + @NAME@(); + +public: + ~@NAME@(); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + @TYPE@ level() const { return d_level; } + +}; + +#endif /* @GUARD_NAME@ */ diff --git a/gnuradio-core/src/lib/gengen/gr_probe_signal_X.i.t b/gnuradio-core/src/lib/gengen/gr_probe_signal_X.i.t new file mode 100644 index 000000000..ec9643686 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_probe_signal_X.i.t @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005, 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@); + +@NAME@_sptr +gr_make_@BASE_NAME@ (); + +class @NAME@ : public gr_sync_block +{ +public: + @TYPE@ level (); +}; diff --git a/gnuradio-core/src/lib/gengen/gr_probe_signal_vX.cc.t b/gnuradio-core/src/lib/gengen/gr_probe_signal_vX.cc.t new file mode 100644 index 000000000..1aedca4ec --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_probe_signal_vX.cc.t @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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 <@NAME@.h> +#include <gr_io_signature.h> +#include <iostream> + +@NAME@_sptr +gr_make_@BASE_NAME@(size_t size) +{ + return gnuradio::get_initial_sptr(new @NAME@(size)); +} + +@NAME@::@NAME@ (size_t size) +: gr_sync_block ("@BASE_NAME@", + gr_make_io_signature(1, 1, size*sizeof(@TYPE@)), + gr_make_io_signature(0, 0, 0)), + d_level(size, 0), d_size(size) +{ +} + +@NAME@::~@NAME@() +{ +} + +int +@NAME@::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const @TYPE@ *in = (const @TYPE@ *) input_items[0]; + + for (size_t i=0; i<d_size; i++) + d_level[i] = in[(noutput_items-1)*d_size+i]; + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/gengen/gr_probe_signal_vX.h.t b/gnuradio-core/src/lib/gengen/gr_probe_signal_vX.h.t new file mode 100644 index 000000000..ee673c14a --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_probe_signal_vX.h.t @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005, 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 @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <vector> + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @NAME@_sptr; + +GR_CORE_API @NAME@_sptr +gr_make_@BASE_NAME@ (size_t size); + +/*! + * \brief Sink that allows a sample to be grabbed from Python. + * \ingroup sink_blk + */ +class GR_CORE_API @NAME@ : public gr_sync_block +{ + std::vector<@TYPE@> d_level; + + friend GR_CORE_API @NAME@_sptr + gr_make_@BASE_NAME@(size_t size); + + @NAME@(size_t size); + + size_t d_size; + +public: + ~@NAME@(); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + std::vector<@TYPE@> level() const { return d_level; } + +}; + +#endif /* @GUARD_NAME@ */ diff --git a/gnuradio-core/src/lib/gengen/gr_probe_signal_vX.i.t b/gnuradio-core/src/lib/gengen/gr_probe_signal_vX.i.t new file mode 100644 index 000000000..b7de09125 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_probe_signal_vX.i.t @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005, 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@); + +@NAME@_sptr +gr_make_@BASE_NAME@ (size_t size); + +class @NAME@ : public gr_sync_block +{ +public: + std::vector<@TYPE@> level (); +}; diff --git a/gnuradio-core/src/lib/gengen/gr_sample_and_hold_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_sample_and_hold_XX.cc.t new file mode 100644 index 000000000..68f4d544e --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_sample_and_hold_XX.cc.t @@ -0,0 +1,62 @@ +/* -*- 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. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <gr_io_signature.h> + +@SPTR_NAME@ +gr_make_@BASE_NAME@ () +{ + return gnuradio::get_initial_sptr (new @NAME@ ()); +} + +@NAME@::@NAME@ () + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature2 (2, 2, sizeof (@I_TYPE@), sizeof(char)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))), + d_data(0) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @I_TYPE@ *iptr = (@I_TYPE@ *) input_items[0]; + const char *ctrl = (const char *) input_items[1]; + @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + + for (int i = 0; i < noutput_items; i++){ + if(ctrl[i]) { + d_data = iptr[i]; + } + optr[i] = d_data; + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/gengen/gr_sample_and_hold_XX.h.t b/gnuradio-core/src/lib/gengen/gr_sample_and_hold_XX.h.t new file mode 100644 index 000000000..0364941cb --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_sample_and_hold_XX.h.t @@ -0,0 +1,58 @@ +/* -*- 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. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (); + +/*! + * \brief sample and hold circuit + * \ingroup level_blk + * + * Samples the data stream (input stream 0) and holds the value + * if the control signal is 1 (intput stream 1). + */ +class GR_CORE_API @NAME@ : public gr_sync_block +{ + friend GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (); + + @NAME@ (); + + private: + @O_TYPE@ d_data; + + 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/gengen/gr_sample_and_hold_XX.i.t b/gnuradio-core/src/lib/gengen/gr_sample_and_hold_XX.i.t new file mode 100644 index 000000000..4620b0f2c --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_sample_and_hold_XX.i.t @@ -0,0 +1,33 @@ +/* -*- 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. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (); +}; diff --git a/gnuradio-core/src/lib/gengen/gr_sig_source_X.cc.t b/gnuradio-core/src/lib/gengen/gr_sig_source_X.cc.t new file mode 100644 index 000000000..6959eac82 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_sig_source_X.cc.t @@ -0,0 +1,241 @@ +/* -*- 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 <algorithm> +#include <gr_io_signature.h> +#include <stdexcept> +#include <algorithm> +#include <gr_complex.h> + + +@NAME@::@NAME@ (double sampling_freq, gr_waveform_t waveform, + double frequency, double ampl, @TYPE@ offset) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 1, sizeof (@TYPE@))), + d_sampling_freq (sampling_freq), d_waveform (waveform), d_frequency (frequency), + d_ampl (ampl), d_offset (offset) +{ + d_nco.set_freq (2 * M_PI * d_frequency / d_sampling_freq); +} + +@NAME@_sptr +gr_make_@BASE_NAME@ (double sampling_freq, gr_waveform_t waveform, + double frequency, double ampl, @TYPE@ offset) +{ + return gnuradio::get_initial_sptr(new @NAME@ (sampling_freq, waveform, frequency, ampl, offset)); +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @TYPE@ *optr = (@TYPE@ *) output_items[0]; + @TYPE@ t; + + switch (d_waveform){ + +#if @IS_COMPLEX@ // complex? + + case GR_CONST_WAVE: + t = (gr_complex) d_ampl + d_offset; + std::fill_n(optr, noutput_items, t); + break; + + case GR_SIN_WAVE: + case GR_COS_WAVE: + d_nco.sincos (optr, noutput_items, d_ampl); + if (d_offset == gr_complex(0,0)) + break; + + for (int i = 0; i < noutput_items; i++){ + optr[i] += d_offset; + } + break; + + /* Implements a real square wave high from -PI to 0. + * The imaginary square wave leads by 90 deg. + */ + case GR_SQR_WAVE: + for (int i = 0; i < noutput_items; i++){ + if (d_nco.get_phase() < -1*M_PI/2) + optr[i] = gr_complex(d_ampl, 0)+d_offset; + else if (d_nco.get_phase() < 0) + optr[i] = gr_complex(d_ampl, d_ampl)+d_offset; + else if (d_nco.get_phase() < M_PI/2) + optr[i] = gr_complex(0, d_ampl)+d_offset; + else + optr[i] = d_offset; + d_nco.step(); + } + break; + + /* Implements a real triangle wave rising from -PI to 0 and + * falling from 0 to PI. The imaginary triangle wave leads by 90 deg. + */ + case GR_TRI_WAVE: + for (int i = 0; i < noutput_items; i++){ + if (d_nco.get_phase() < -1*M_PI/2){ + optr[i] = gr_complex(d_ampl*d_nco.get_phase()/M_PI + d_ampl, + -1*d_ampl*d_nco.get_phase()/M_PI - d_ampl/2)+d_offset; + } + else if (d_nco.get_phase() < 0){ + optr[i] = gr_complex(d_ampl*d_nco.get_phase()/M_PI + d_ampl, + d_ampl*d_nco.get_phase()/M_PI + d_ampl/2)+d_offset; + } + else if (d_nco.get_phase() < M_PI/2){ + optr[i] = gr_complex(-1*d_ampl*d_nco.get_phase()/M_PI + d_ampl, + d_ampl*d_nco.get_phase()/M_PI + d_ampl/2)+d_offset; + } + else{ + optr[i] = gr_complex(-1*d_ampl*d_nco.get_phase()/M_PI + d_ampl, + -1*d_ampl*d_nco.get_phase()/M_PI + 3*d_ampl/2)+d_offset; + } + d_nco.step(); + } + break; + + /* Implements a real saw tooth wave rising from -PI to PI. + * The imaginary saw tooth wave leads by 90 deg. + */ + case GR_SAW_WAVE: + for (int i = 0; i < noutput_items; i++){ + if (d_nco.get_phase() < -1*M_PI/2){ + optr[i] = gr_complex(d_ampl*d_nco.get_phase()/(2*M_PI) + d_ampl/2, + d_ampl*d_nco.get_phase()/(2*M_PI) + 5*d_ampl/4)+d_offset; + } + else{ + optr[i] = gr_complex(d_ampl*d_nco.get_phase()/(2*M_PI) + d_ampl/2, + d_ampl*d_nco.get_phase()/(2*M_PI) + d_ampl/4)+d_offset; + } + d_nco.step(); + } + break; + +#else // nope... + + case GR_CONST_WAVE: + t = (@TYPE@) d_ampl + d_offset; + std::fill_n(optr, noutput_items, t); + break; + + case GR_SIN_WAVE: + d_nco.sin (optr, noutput_items, d_ampl); + if (d_offset == 0) + break; + + for (int i = 0; i < noutput_items; i++){ + optr[i] += d_offset; + } + break; + + case GR_COS_WAVE: + d_nco.cos (optr, noutput_items, d_ampl); + if (d_offset == 0) + break; + + for (int i = 0; i < noutput_items; i++){ + optr[i] += d_offset; + } + break; + + /* The square wave is high from -PI to 0. */ + case GR_SQR_WAVE: + t = (@TYPE@) d_ampl + d_offset; + for (int i = 0; i < noutput_items; i++){ + if (d_nco.get_phase() < 0) + optr[i] = t; + else + optr[i] = d_offset; + d_nco.step(); + } + break; + + /* The triangle wave rises from -PI to 0 and falls from 0 to PI. */ + case GR_TRI_WAVE: + for (int i = 0; i < noutput_items; i++){ + double t = d_ampl*d_nco.get_phase()/M_PI; + if (d_nco.get_phase() < 0) + optr[i] = static_cast<@TYPE@>(t + d_ampl + d_offset); + else + optr[i] = static_cast<@TYPE@>(-1*t + d_ampl + d_offset); + d_nco.step(); + } + break; + + /* The saw tooth wave rises from -PI to PI. */ + case GR_SAW_WAVE: + for (int i = 0; i < noutput_items; i++){ + t = static_cast<@TYPE@>(d_ampl*d_nco.get_phase()/(2*M_PI) + d_ampl/2 + d_offset); + optr[i] = t; + d_nco.step(); + } + break; + +#endif + + default: + throw std::runtime_error ("gr_sig_source: invalid waveform"); + } + + return noutput_items; +} + +void +@NAME@::set_sampling_freq (double sampling_freq) +{ + d_sampling_freq = sampling_freq; + d_nco.set_freq (2 * M_PI * d_frequency / d_sampling_freq); +} + +void +@NAME@::set_waveform (gr_waveform_t waveform) +{ + d_waveform = waveform; +} + +void +@NAME@::set_frequency (double frequency) +{ + d_frequency = frequency; + d_nco.set_freq (2 * M_PI * d_frequency / d_sampling_freq); +} + +void +@NAME@::set_amplitude (double ampl) +{ + d_ampl = ampl; +} + +void +@NAME@::set_offset (@TYPE@ offset) +{ + d_offset = offset; +} + diff --git a/gnuradio-core/src/lib/gengen/gr_sig_source_X.h.t b/gnuradio-core/src/lib/gengen/gr_sig_source_X.h.t new file mode 100644 index 000000000..baa82dbe2 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_sig_source_X.h.t @@ -0,0 +1,82 @@ +/* -*- 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_block.h> +#include <gr_sig_source_waveform.h> +#include <gr_fxpt_nco.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @NAME@_sptr; + +/*! + * \brief signal generator with @TYPE@ output. + * \ingroup source_blk + */ + +class GR_CORE_API @NAME@ : public gr_sync_block { + friend GR_CORE_API @NAME@_sptr + gr_make_@BASE_NAME@ (double sampling_freq, gr_waveform_t waveform, + double frequency, double ampl, @TYPE@ offset); + + double d_sampling_freq; + gr_waveform_t d_waveform; + double d_frequency; + double d_ampl; + @TYPE@ d_offset; + gr_fxpt_nco d_nco; + + + @NAME@ (double sampling_freq, gr_waveform_t waveform, + double wave_freq, double ampl, @TYPE@ offset); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + // ACCESSORS + double sampling_freq () const { return d_sampling_freq; } + gr_waveform_t waveform () const { return d_waveform; } + double frequency () const { return d_frequency; } + double amplitude () const { return d_ampl; } + @TYPE@ offset () const { return d_offset; } + + // MANIPULATORS + void set_sampling_freq (double sampling_freq); + void set_waveform (gr_waveform_t waveform); + void set_frequency (double frequency); + void set_amplitude (double ampl); + void set_offset (@TYPE@ offset); +}; + +GR_CORE_API @NAME@_sptr +gr_make_@BASE_NAME@ (double sampling_freq, gr_waveform_t waveform, + double wave_freq, double ampl, @TYPE@ offset = 0); + + +#endif diff --git a/gnuradio-core/src/lib/gengen/gr_sig_source_X.i.t b/gnuradio-core/src/lib/gengen/gr_sig_source_X.i.t new file mode 100644 index 000000000..7bd85fcb8 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_sig_source_X.i.t @@ -0,0 +1,52 @@ +/* -*- 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@); + +@NAME@_sptr +gr_make_@BASE_NAME@ (double sampling_freq, gr_waveform_t waveform, + double wave_freq, double ampl, @TYPE@ offset = 0); + + +class @NAME@ : public gr_sync_block { + private: + @NAME@ (double sampling_freq, gr_waveform_t waveform, + double wave_freq, double ampl, @TYPE@ offset); + + public: + + // ACCESSORS + double sampling_freq () const { return d_sampling_freq; } + gr_waveform_t waveform () const { return d_waveform; } + double frequency () const { return d_frequency; } + double amplitude () const { return d_ampl; } + @TYPE@ offset () const { return d_offset; } + + // MANIPULATORS + void set_sampling_freq (double sampling_freq); + void set_waveform (gr_waveform_t waveform); + void set_frequency (double frequency); + void set_amplitude (double ampl); + void set_offset (@TYPE@ offset); +}; diff --git a/gnuradio-core/src/lib/gengen/gr_sig_source_waveform.h b/gnuradio-core/src/lib/gengen/gr_sig_source_waveform.h new file mode 100644 index 000000000..9fe233ba4 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_sig_source_waveform.h @@ -0,0 +1,29 @@ +/* -*- 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_SIG_SOURCE_WAVEFORM_H +#define INCLUDED_GR_SIG_SOURCE_WAVEFORM_H + +typedef enum { + GR_CONST_WAVE = 100, GR_SIN_WAVE, GR_COS_WAVE, GR_SQR_WAVE, GR_TRI_WAVE, GR_SAW_WAVE +} gr_waveform_t; + +#endif /* INCLUDED_GR_SIG_SOURCE_WAVEFORM_H */ diff --git a/gnuradio-core/src/lib/gengen/gr_sub_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_sub_XX.cc.t new file mode 100644 index 000000000..11eb7440e --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_sub_XX.cc.t @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004, 2009,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> + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (size_t vlen) +{ + return gnuradio::get_initial_sptr (new @NAME@ (vlen)); +} + +@NAME@::@NAME@ (size_t vlen) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, -1, sizeof (@I_TYPE@)*vlen), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@)*vlen)), + d_vlen (vlen) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + + int ninputs = input_items.size (); + + if (ninputs == 1){ // negate + for (size_t i = 0; i < noutput_items*d_vlen; i++) + *optr++ = (@O_TYPE@) -((@I_TYPE@ *) input_items[0])[i]; + } + + else { + for (size_t i = 0; i < noutput_items*d_vlen; i++){ + @I_TYPE@ acc = ((@I_TYPE@ *) input_items[0])[i]; + for (int j = 1; j < ninputs; j++) + acc -= ((@I_TYPE@ *) input_items[j])[i]; + + *optr++ = (@O_TYPE@) acc; + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/gengen/gr_sub_XX.h.t b/gnuradio-core/src/lib/gengen/gr_sub_XX.h.t new file mode 100644 index 000000000..f96c93484 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_sub_XX.h.t @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004, 2009 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_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (size_t vlen = 1); + +/*! + * \brief output = input_0 - input_1 - ...) + * \ingroup math_blk + * + * Subtract across all input streams. + */ +class GR_CORE_API @NAME@ : public gr_sync_block +{ + friend GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (size_t vlen); + + @NAME@ (size_t vlen); + + size_t d_vlen; + + 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/gengen/gr_sub_XX.i.t b/gnuradio-core/src/lib/gengen/gr_sub_XX.i.t new file mode 100644 index 000000000..b2c510610 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_sub_XX.i.t @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004, 2009 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@ (size_t vlen = 1); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (size_t vlen); +}; diff --git a/gnuradio-core/src/lib/gengen/gr_unpacked_to_packed_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_unpacked_to_packed_XX.cc.t new file mode 100644 index 000000000..ed2b713db --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_unpacked_to_packed_XX.cc.t @@ -0,0 +1,129 @@ +/* -*- 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. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <gr_io_signature.h> +#include <assert.h> + +static const unsigned int BITS_PER_TYPE = sizeof(@O_TYPE@) * 8; + + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (unsigned int bits_per_chunk, gr_endianness_t endianness) +{ + return @SPTR_NAME@ + (new @NAME@ (bits_per_chunk,endianness)); +} + +@NAME@::@NAME@ (unsigned int bits_per_chunk, + gr_endianness_t endianness) + : gr_block ("@BASE_NAME@", + gr_make_io_signature (1, -1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, -1, sizeof (@O_TYPE@))), + d_bits_per_chunk(bits_per_chunk),d_endianness(endianness),d_index(0) +{ + assert (bits_per_chunk <= BITS_PER_TYPE); + assert (bits_per_chunk > 0); + + set_relative_rate (bits_per_chunk/(1.0 * BITS_PER_TYPE)); +} + +void +@NAME@::forecast(int noutput_items, gr_vector_int &ninput_items_required) +{ + int input_required = (int) ceil( (d_index+noutput_items * 1.0 * BITS_PER_TYPE)/d_bits_per_chunk); + unsigned ninputs = ninput_items_required.size(); + for (unsigned int i = 0; i < ninputs; i++) { + ninput_items_required[i] = input_required; + } +} + +unsigned int +get_bit_be1 (const @I_TYPE@ *in_vector,unsigned int bit_addr, unsigned int bits_per_chunk) { + unsigned int byte_addr = (int)bit_addr/bits_per_chunk; + @I_TYPE@ x = in_vector[byte_addr]; + unsigned int residue = bit_addr - byte_addr * bits_per_chunk; + //printf("Bit addr %d byte addr %d residue %d val %d\n",bit_addr,byte_addr,residue,(x>>(bits_per_chunk-1-residue))&1); + return (x >> (bits_per_chunk-1-residue))&1; +} + +int +@NAME@::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + unsigned int index_tmp = d_index; + + 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]; + index_tmp=d_index; + + // per stream processing + + //assert((ninput_items[m]-d_index)*d_bits_per_chunk >= noutput_items*BITS_PER_TYPE); + + switch(d_endianness){ + + case GR_MSB_FIRST: + for(int i=0;i<noutput_items;i++) { + @O_TYPE@ tmp=0; + for(unsigned int j=0; j<BITS_PER_TYPE; j++) { + tmp = (tmp<<1) | get_bit_be1(in,index_tmp,d_bits_per_chunk); + index_tmp++; + } + out[i] = tmp; + } + break; + + case GR_LSB_FIRST: + for(int i=0;i<noutput_items;i++) { + unsigned long tmp=0; + for(unsigned int j=0; j<BITS_PER_TYPE; j++) { + tmp = (tmp>>1)| (get_bit_be1(in,index_tmp,d_bits_per_chunk)<<(BITS_PER_TYPE-1)); + index_tmp++; + } + out[i] = tmp; + } + break; + + default: + assert(0); + } + } + + d_index = index_tmp; + consume_each ((int)(d_index/d_bits_per_chunk)); + d_index = d_index%d_bits_per_chunk; + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/gengen/gr_unpacked_to_packed_XX.h.t b/gnuradio-core/src/lib/gengen/gr_unpacked_to_packed_XX.h.t new file mode 100644 index 000000000..a7b7b54df --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_unpacked_to_packed_XX.h.t @@ -0,0 +1,82 @@ +/* -*- 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. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_core_api.h> +#include <gr_block.h> +#include <gr_endianness.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @NAME@_sptr; + +GR_CORE_API @SPTR_NAME@ +gr_make_@BASE_NAME@ (unsigned int bits_per_chunk, gr_endianness_t endianness); + +/*! + * \brief Convert a stream of unpacked bytes or shorts into a stream of packed bytes or shorts. + * \ingroup converter_blk + * + * input: stream of @I_TYPE@; output: stream of @O_TYPE@ + * + * This is the inverse of gr_packed_to_unpacked_XX. + * + * The low \p bits_per_chunk bits are extracted from each input byte or short. + * These bits are then packed densely into the output bytes or shorts, such that + * all 8 or 16 bits of the output bytes or shorts are filled with valid input bits. + * The right thing is done if bits_per_chunk is not a power of two. + * + * The combination of gr_packed_to_unpacked_XX followed by + * gr_chunks_to_symbols_Xf or gr_chunks_to_symbols_Xc 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_block +{ + friend GR_CORE_API @SPTR_NAME@ + gr_make_@BASE_NAME@ (unsigned int bits_per_chunk, gr_endianness_t endianness); + + @NAME@ (unsigned int bits_per_chunk, gr_endianness_t endianness); + + unsigned int d_bits_per_chunk; + gr_endianness_t d_endianness; + unsigned int d_index; + + 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); + + bool check_topology(int ninputs, int noutputs) { return ninputs == noutputs; } +}; + +#endif diff --git a/gnuradio-core/src/lib/gengen/gr_unpacked_to_packed_XX.i.t b/gnuradio-core/src/lib/gengen/gr_unpacked_to_packed_XX.i.t new file mode 100644 index 000000000..1e978956a --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_unpacked_to_packed_XX.i.t @@ -0,0 +1,33 @@ +/* -*- 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@ (unsigned int bits_per_chunk, gr_endianness_t endianness); + +class @NAME@ : public gr_block +{ + @NAME@ (unsigned int bits_per_chunk, gr_endianness_t endianness); +}; diff --git a/gnuradio-core/src/lib/gengen/gr_vector_insert_X.cc.t b/gnuradio-core/src/lib/gengen/gr_vector_insert_X.cc.t new file mode 100644 index 000000000..20968afe2 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_vector_insert_X.cc.t @@ -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. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <@NAME@.h> +#include <algorithm> +#include <gr_io_signature.h> +#include <stdexcept> + +#include <stdio.h> + +@NAME@::@NAME@(const std::vector<@TYPE@> &data, int periodicity, int offset) + : gr_block("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof(@TYPE@)), + gr_make_io_signature (1, 1, sizeof(@TYPE@))), + d_data(data), + d_offset(offset), + d_periodicity(periodicity) +{ + //printf("INITIAL: periodicity = %d, offset = %d\n", periodicity, offset); + // some sanity checks + assert(offset < periodicity); + assert(offset >= 0); + assert((size_t)periodicity > data.size()); +} + +int +@NAME@::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @TYPE@ *out = (@TYPE@ *)output_items[0]; + const @TYPE@ *in = (const @TYPE@ *)input_items[0]; + + int ii(0), oo(0); + + while((oo < noutput_items) && (ii < ninput_items[0])) { + + //printf("oo = %d, ii = %d, d_offset = %d, noutput_items = %d, ninput_items[0] = %d", oo, ii, d_offset, noutput_items, ninput_items[0]); + //printf(", d_periodicity = %d\n", d_periodicity); + + if(d_offset >= ((int)d_data.size())) { // if we are in the copy region + int max_copy = std::min( std::min( noutput_items - oo, ninput_items[0] - ii ), d_periodicity - d_offset ); + //printf("copy %d from input\n", max_copy); + memcpy( &out[oo], &in[ii], sizeof(@TYPE@)*max_copy ); + //printf(" * memcpy returned.\n"); + ii += max_copy; + oo += max_copy; + d_offset = (d_offset + max_copy)%d_periodicity; + + } + else { // if we are in the insertion region + int max_copy = std::min( noutput_items - oo, ((int)d_data.size()) - d_offset ); + //printf("copy %d from d_data[%d] to out[%d]\n", max_copy, d_offset, oo); + memcpy( &out[oo], &d_data[d_offset], sizeof(@TYPE@)*max_copy ); + //printf(" * memcpy returned.\n"); + oo += max_copy; + d_offset = (d_offset + max_copy)%d_periodicity; + //printf(" ## (inelse) oo = %d, d_offset = %d\n", oo, d_offset); + } + + //printf(" # exit else, on to next loop.\n"); + } + //printf(" # got out of loop\n"); + + //printf("consume = %d, produce = %d\n", ii, oo); + consume_each(ii); + return oo; +} + +@NAME@_sptr +gr_make_@BASE_NAME@ (const std::vector<@TYPE@> &data, int periodicity, int offset) +{ + return gnuradio::get_initial_sptr(new @NAME@ (data, periodicity, offset)); +} + diff --git a/gnuradio-core/src/lib/gengen/gr_vector_insert_X.h.t b/gnuradio-core/src/lib/gengen/gr_vector_insert_X.h.t new file mode 100644 index 000000000..26f851700 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_vector_insert_X.h.t @@ -0,0 +1,61 @@ +/* -*- 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. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_core_api.h> +#include <gr_block.h> + +class GR_CORE_API @NAME@; +typedef boost::shared_ptr<@NAME@> @NAME@_sptr; + +/*! + * \brief source of @TYPE@'s that gets its data from a vector + * \ingroup source_blk + */ + +class @NAME@ : public gr_block { + friend GR_CORE_API @NAME@_sptr + gr_make_@BASE_NAME@(const std::vector<@TYPE@> &data, int periodicity, int offset); + + std::vector<@TYPE@> d_data; + int d_offset; + int d_periodicity; + + @NAME@(const std::vector<@TYPE@> &data, int periodicity, int offset); + + public: + void rewind() {d_offset=0;} + virtual int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + void set_data(const std::vector<@TYPE@> &data){ d_data = data; rewind(); } +}; + +GR_CORE_API @NAME@_sptr +gr_make_@BASE_NAME@(const std::vector<@TYPE@> &data, int periodicity, int offset=0); + +#endif diff --git a/gnuradio-core/src/lib/gengen/gr_vector_insert_X.i.t b/gnuradio-core/src/lib/gengen/gr_vector_insert_X.i.t new file mode 100644 index 000000000..f3341eec4 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_vector_insert_X.i.t @@ -0,0 +1,37 @@ +/* -*- 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. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@); + +@NAME@_sptr +gr_make_@BASE_NAME@ (const std::vector<@TYPE@> &data, int periodicity, int offset = 0) + throw(std::invalid_argument); + +class @NAME@ : public gr_block { + public: + void rewind(); + void set_data(const std::vector<@TYPE@> &data); + private: + @NAME@ (const std::vector<@TYPE@> &data, int periodicity, int offset = 0); +}; diff --git a/gnuradio-core/src/lib/gengen/gr_vector_sink_X.cc.t b/gnuradio-core/src/lib/gengen/gr_vector_sink_X.cc.t new file mode 100644 index 000000000..a9e3a0a3e --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_vector_sink_X.cc.t @@ -0,0 +1,64 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <@NAME@.h> +#include <algorithm> +#include <gr_io_signature.h> + + +@NAME@::@NAME@ (int vlen) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@TYPE@) * vlen), + gr_make_io_signature (0, 0, 0)), + d_vlen(vlen) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @TYPE@ *iptr = (@TYPE@ *) input_items[0]; + for (int i = 0; i < noutput_items * d_vlen; i++) + d_data.push_back (iptr[i]); + + return noutput_items; +} + + +@NAME@_sptr +gr_make_@BASE_NAME@ (int vlen) +{ + return gnuradio::get_initial_sptr(new @NAME@ (vlen)); +} + +std::vector<@TYPE@> +@NAME@::data () const +{ + return d_data; +} diff --git a/gnuradio-core/src/lib/gengen/gr_vector_sink_X.h.t b/gnuradio-core/src/lib/gengen/gr_vector_sink_X.h.t new file mode 100644 index 000000000..b9126dc7b --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_vector_sink_X.h.t @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2008,2009 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_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @NAME@_sptr; + +GR_CORE_API @NAME@_sptr +gr_make_@BASE_NAME@ (int vlen = 1); + + +/*! + * \brief @TYPE@ sink that writes to a vector + * \ingroup sink_blk + */ + +class GR_CORE_API @NAME@ : public gr_sync_block { + friend GR_CORE_API @NAME@_sptr gr_make_@BASE_NAME@ (int vlen); + std::vector<@TYPE@> d_data; + int d_vlen; + @NAME@ (int vlen); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void reset() {d_data.clear();} + void clear() {reset(); } // deprecated + std::vector<@TYPE@> data () const; +}; + +#endif diff --git a/gnuradio-core/src/lib/gengen/gr_vector_sink_X.i.t b/gnuradio-core/src/lib/gengen/gr_vector_sink_X.i.t new file mode 100644 index 000000000..d4a940911 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_vector_sink_X.i.t @@ -0,0 +1,39 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2008,2009 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@ (int vlen = 1); + +class @NAME@ : public gr_sync_block { + private: + @NAME@ (int vlen); + + public: + void clear(); // deprecated + void reset(); + std::vector<@TYPE@> data () const; +}; + diff --git a/gnuradio-core/src/lib/gengen/gr_vector_source_X.cc.t b/gnuradio-core/src/lib/gengen/gr_vector_source_X.cc.t new file mode 100644 index 000000000..9f68f9cf1 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_vector_source_X.cc.t @@ -0,0 +1,89 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <@NAME@.h> +#include <algorithm> +#include <gr_io_signature.h> +#include <stdexcept> + + +@NAME@::@NAME@ (const std::vector<@TYPE@> &data, bool repeat, int vlen) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 1, sizeof (@TYPE@) * vlen)), + d_data (data), + d_repeat (repeat), + d_offset (0), + d_vlen (vlen) +{ + if ((data.size() % vlen) != 0) + throw std::invalid_argument("data length must be a multiple of vlen"); +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @TYPE@ *optr = (@TYPE@ *) output_items[0]; + + if (d_repeat){ + unsigned int size = d_data.size (); + unsigned int offset = d_offset; + + if (size == 0) + return -1; + + for (int i = 0; i < noutput_items*d_vlen; i++){ + optr[i] = d_data[offset++]; + if (offset >= size) + offset = 0; + } + d_offset = offset; + return noutput_items; + } + + else { + if (d_offset >= d_data.size ()) + return -1; // Done! + + unsigned n = std::min ((unsigned) d_data.size () - d_offset, + (unsigned) noutput_items*d_vlen); + for (unsigned i = 0; i < n; i++) + optr[i] = d_data[d_offset + i]; + + d_offset += n; + return n/d_vlen; + } +} + +@NAME@_sptr +gr_make_@BASE_NAME@ (const std::vector<@TYPE@> &data, bool repeat, int vlen) +{ + return gnuradio::get_initial_sptr(new @NAME@ (data, repeat, vlen)); +} + diff --git a/gnuradio-core/src/lib/gengen/gr_vector_source_X.h.t b/gnuradio-core/src/lib/gengen/gr_vector_source_X.h.t new file mode 100644 index 000000000..fe02c1346 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_vector_source_X.h.t @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class GR_CORE_API @NAME@; +typedef boost::shared_ptr<@NAME@> @NAME@_sptr; + +/*! + * \brief source of @TYPE@'s that gets its data from a vector + * \ingroup source_blk + */ + +class @NAME@ : public gr_sync_block { + friend GR_CORE_API @NAME@_sptr + gr_make_@BASE_NAME@ (const std::vector<@TYPE@> &data, bool repeat, int vlen); + + std::vector<@TYPE@> d_data; + bool d_repeat; + unsigned int d_offset; + int d_vlen; + + @NAME@ (const std::vector<@TYPE@> &data, bool repeat, int vlen); + + public: + void rewind() {d_offset=0;} + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + void set_data(const std::vector<@TYPE@> &data){ d_data = data; rewind(); } +}; + +GR_CORE_API @NAME@_sptr +gr_make_@BASE_NAME@ (const std::vector<@TYPE@> &data, bool repeat = false, int vlen = 1); + +#endif diff --git a/gnuradio-core/src/lib/gengen/gr_vector_source_X.i.t b/gnuradio-core/src/lib/gengen/gr_vector_source_X.i.t new file mode 100644 index 000000000..4986c68a3 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_vector_source_X.i.t @@ -0,0 +1,37 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@); + +@NAME@_sptr +gr_make_@BASE_NAME@ (const std::vector<@TYPE@> &data, bool repeat = false, int vlen = 1) + throw(std::invalid_argument); + +class @NAME@ : public gr_sync_block { + public: + void rewind(); + void set_data(const std::vector<@TYPE@> &data); + private: + @NAME@ (const std::vector<@TYPE@> &data, int vlen); +}; diff --git a/gnuradio-core/src/lib/gengen/gr_xor_XX.cc.t b/gnuradio-core/src/lib/gengen/gr_xor_XX.cc.t new file mode 100644 index 000000000..d6990aa4f --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_xor_XX.cc.t @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <gr_io_signature.h> + +@SPTR_NAME@ +gr_make_@BASE_NAME@ () +{ + return gnuradio::get_initial_sptr (new @NAME@ ()); +} + +@NAME@::@NAME@ () + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, -1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@))) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + @O_TYPE@ *optr = (@O_TYPE@ *) output_items[0]; + + int ninputs = input_items.size (); + + for (int i = 0; i < noutput_items; i++) { + @I_TYPE@ acc = ((@I_TYPE@ *) input_items[0])[i]; + for (int j = 1; j < ninputs; j++) + acc = acc ^ ((@I_TYPE@ *) input_items[j])[i]; + + *optr++ = (@O_TYPE@) acc; + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/gengen/gr_xor_XX.h.t b/gnuradio-core/src/lib/gengen/gr_xor_XX.h.t new file mode 100644 index 000000000..8fe47d9e0 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_xor_XX.h.t @@ -0,0 +1,55 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (); + +/*! + * \brief output = input_0 ^ input_1 ^ , ... ^ input_N) + * \ingroup math_blk + * + * bitwise boolean xor across all input streams. + */ +class GR_CORE_API @NAME@ : public gr_sync_block +{ + friend GR_CORE_API @SPTR_NAME@ gr_make_@BASE_NAME@ (); + + @NAME@ (); + + 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/gengen/gr_xor_XX.i.t b/gnuradio-core/src/lib/gengen/gr_xor_XX.i.t new file mode 100644 index 000000000..06db5ca59 --- /dev/null +++ b/gnuradio-core/src/lib/gengen/gr_xor_XX.i.t @@ -0,0 +1,33 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (); +}; diff --git a/gnuradio-core/src/lib/gnuradio-config-info.cc b/gnuradio-core/src/lib/gnuradio-config-info.cc new file mode 100644 index 000000000..d3e6454fd --- /dev/null +++ b/gnuradio-core/src/lib/gnuradio-config-info.cc @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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. + */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gr_constants.h> +#include <boost/program_options.hpp> +#include <iostream> + +namespace po = boost::program_options; + +int +main(int argc, char **argv) +{ + po::options_description desc("Program options: gnuradio [options]"); + po::variables_map vm; + + desc.add_options() + ("help,h", "print help message") + ("prefix", "print gnuradio installation prefix") + ("sysconfdir", "print gnuradio system configuration directory") + ("prefsdir", "print gnuradio preferences directory") + ("builddate", "print gnuradio build date (RFC2822 format)") + ("version,v", "print gnuradio version") + ; + + po::store(po::parse_command_line(argc, argv, desc), vm); + po::notify(vm); + + if (vm.size() == 0 || vm.count("help")) { + std::cout << desc << std::endl; + return 1; + } + + if (vm.count("prefix")) + std::cout << gr_prefix() << std::endl; + + if (vm.count("sysconfdir")) + std::cout << gr_sysconfdir() << std::endl; + + if (vm.count("prefsdir")) + std::cout << gr_prefsdir() << std::endl; + + if (vm.count("builddate")) + std::cout << gr_build_date() << std::endl; + + if (vm.count("version")) + std::cout << gr_version() << std::endl; + + return 0; +} diff --git a/gnuradio-core/src/lib/hier/CMakeLists.txt b/gnuradio-core/src/lib/hier/CMakeLists.txt new file mode 100644 index 000000000..192dd5939 --- /dev/null +++ b/gnuradio-core/src/lib/hier/CMakeLists.txt @@ -0,0 +1,42 @@ +# Copyright 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. + +######################################################################## +# This file included, use CMake directory variables +######################################################################## +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) + +list(APPEND gnuradio_core_sources + ${CMAKE_CURRENT_SOURCE_DIR}/gr_channel_model.cc +) + +install(FILES + ${CMAKE_CURRENT_SOURCE_DIR}/gr_channel_model.h + DESTINATION ${GR_INCLUDE_DIR}/gnuradio + COMPONENT "core_devel" +) + +if(ENABLE_PYTHON) + install(FILES + ${CMAKE_CURRENT_SOURCE_DIR}/hier.i + ${CMAKE_CURRENT_SOURCE_DIR}/gr_channel_model.i + DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig + COMPONENT "core_swig" + ) +endif(ENABLE_PYTHON) diff --git a/gnuradio-core/src/lib/hier/gr_channel_model.cc b/gnuradio-core/src/lib/hier/gr_channel_model.cc new file mode 100644 index 000000000..7da357809 --- /dev/null +++ b/gnuradio-core/src/lib/hier/gr_channel_model.cc @@ -0,0 +1,126 @@ +/* + * Copyright 2009 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 <gr_channel_model.h> +#include <gr_io_signature.h> +#include <gr_sig_source_f.h> +#include <iostream> + +// Shared pointer constructor +gr_channel_model_sptr +gr_make_channel_model(double noise_voltage, + double frequency_offset, + double epsilon, + const std::vector<gr_complex> &taps, + double noise_seed) +{ + return gnuradio::get_initial_sptr(new gr_channel_model(noise_voltage, + frequency_offset, + epsilon, + taps, + noise_seed)); +} + +// Hierarchical block constructor +gr_channel_model::gr_channel_model(double noise_voltage, + double frequency_offset, + double epsilon, + const std::vector<gr_complex> &taps, + double noise_seed) + : gr_hier_block2("gr_channel_model", + gr_make_io_signature(1, 1, sizeof(gr_complex)), + gr_make_io_signature(1, 1, sizeof(gr_complex))) +{ + d_taps = taps; + while(d_taps.size() < 2) { + d_taps.push_back(0); + } + + d_timing_offset = gr_make_fractional_interpolator_cc(0, epsilon); + + d_multipath = gr_make_fir_filter_ccc(1, d_taps); + + d_noise_adder = gr_make_add_cc(); + d_noise = gr_make_fastnoise_source_c(GR_GAUSSIAN, noise_voltage, noise_seed, 1024*8); + d_freq_offset = gr_make_sig_source_c(1, GR_SIN_WAVE, frequency_offset, 1.0, 0.0); + d_mixer_offset = gr_make_multiply_cc(); + + connect(self(), 0, d_timing_offset, 0); + connect(d_timing_offset, 0, d_multipath, 0); + connect(d_multipath, 0, d_mixer_offset, 0); + connect(d_freq_offset, 0, d_mixer_offset, 1); + connect(d_mixer_offset, 0, d_noise_adder, 1); + connect(d_noise, 0, d_noise_adder, 0); + connect(d_noise_adder, 0, self(), 0); +} + +void +gr_channel_model::set_noise_voltage(double noise_voltage) +{ + d_noise->set_amplitude(noise_voltage); +} + +void +gr_channel_model::set_frequency_offset(double frequency_offset) +{ + d_freq_offset->set_frequency(frequency_offset); +} + +void +gr_channel_model::set_taps(const std::vector<gr_complex> &taps) +{ + d_taps = taps; + while(d_taps.size() < 2) { + d_taps.push_back(0); + } + d_multipath->set_taps(d_taps); +} + +void +gr_channel_model::set_timing_offset(double epsilon) +{ + d_timing_offset->set_interp_ratio(epsilon); +} + + +double +gr_channel_model::noise_voltage() const +{ + return d_noise->amplitude(); +} + +double +gr_channel_model::frequency_offset() const +{ + return d_freq_offset->frequency(); +} + +std::vector<gr_complex> +gr_channel_model::taps() const +{ + return d_multipath->taps(); +} + +double +gr_channel_model::timing_offset() const +{ + return d_timing_offset->interp_ratio(); +} diff --git a/gnuradio-core/src/lib/hier/gr_channel_model.h b/gnuradio-core/src/lib/hier/gr_channel_model.h new file mode 100644 index 000000000..5796a6db2 --- /dev/null +++ b/gnuradio-core/src/lib/hier/gr_channel_model.h @@ -0,0 +1,79 @@ +/* + * Copyright 2009 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 <gr_core_api.h> +#include <gr_top_block.h> +#include <gr_fractional_interpolator_cc.h> +#include <gr_sig_source_c.h> +#include <gr_fir_filter_ccc.h> +#include <gr_add_cc.h> +#include <gr_fastnoise_source_c.h> +#include <gr_multiply_cc.h> + +class gr_channel_model; +typedef boost::shared_ptr<gr_channel_model> gr_channel_model_sptr; + + +GR_CORE_API gr_channel_model_sptr gr_make_channel_model(double noise_voltage=0.0, + double frequency_offset=0.0, + double epsilon=1.0, + const std::vector<gr_complex> &taps=std::vector<gr_complex>(1, 1), + double noise_seed=0); + +/*! + * \brief channel simulator + * \ingroup misc_blk + */ +class GR_CORE_API gr_channel_model : public gr_hier_block2 +{ + private: + gr_channel_model(double noise_voltage, + double frequency_offset, + double epsilon, + const std::vector<gr_complex> &taps, + double noise_seed); + + friend GR_CORE_API gr_channel_model_sptr gr_make_channel_model(double noise_voltage, + double frequency_offset, + double epsilon, + const std::vector<gr_complex> &taps, + double noise_seed); + + gr_fractional_interpolator_cc_sptr d_timing_offset; + gr_sig_source_c_sptr d_freq_offset; + gr_fir_filter_ccc_sptr d_multipath; + gr_add_cc_sptr d_noise_adder; + gr_fastnoise_source_c_sptr d_noise; + gr_multiply_cc_sptr d_mixer_offset; + + std::vector<gr_complex> d_taps; + + public: + void set_noise_voltage(double noise_voltage); + void set_frequency_offset(double frequency_offset); + void set_taps(const std::vector<gr_complex> &taps); + void set_timing_offset(double epsilon); + + double noise_voltage() const; + double frequency_offset() const; + std::vector<gr_complex> taps() const; + double timing_offset() const; +}; diff --git a/gnuradio-core/src/lib/hier/gr_channel_model.i b/gnuradio-core/src/lib/hier/gr_channel_model.i new file mode 100644 index 000000000..9aa6ebf5b --- /dev/null +++ b/gnuradio-core/src/lib/hier/gr_channel_model.i @@ -0,0 +1,50 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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,channel_model) + +gr_channel_model_sptr gr_make_channel_model(double noise_voltage=0.0, + double frequency_offset=0.0, + double epsilon=1.0, + const std::vector<gr_complex> &taps=std::vector<gr_complex>(1, 1), + double noise_seed=0); + +class gr_channel_model : public gr_hier_block2 +{ + private: + gr_channel_model(double noise_voltage, + double frequency_offset, + double epsilon, + const std::vector<gr_complex> &taps, + double noise_seed); + + public: + void set_noise_voltage(double noise_voltage); + void set_frequency_offset(double frequency_offset); + void set_taps(const std::vector<gr_complex> &taps); + void set_timing_offset(double epsilon); + + double noise_voltage() const; + double frequency_offset() const; + std::vector<gr_complex> taps() const; + double timing_offset() const; +}; diff --git a/gnuradio-core/src/lib/hier/hier.i b/gnuradio-core/src/lib/hier/hier.i new file mode 100644 index 000000000..82044415e --- /dev/null +++ b/gnuradio-core/src/lib/hier/hier.i @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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_channel_model.h> +%} + +%include "gr_channel_model.i" + diff --git a/gnuradio-core/src/lib/io/CMakeLists.txt b/gnuradio-core/src/lib/io/CMakeLists.txt new file mode 100644 index 000000000..59ca06b5a --- /dev/null +++ b/gnuradio-core/src/lib/io/CMakeLists.txt @@ -0,0 +1,118 @@ +# Copyright 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. + +######################################################################## +# This file included, use CMake directory variables +######################################################################## + +######################################################################## +# Append gnuradio-core library sources +######################################################################## +list(APPEND gnuradio_core_sources + ${CMAKE_CURRENT_SOURCE_DIR}/gr_histo_sink_f.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_oscope_guts.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_oscope_sink_f.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_oscope_sink_x.cc + ${CMAKE_CURRENT_SOURCE_DIR}/i2c.cc + ${CMAKE_CURRENT_SOURCE_DIR}/i2c_bitbang.cc + ${CMAKE_CURRENT_SOURCE_DIR}/i2c_bbio.cc + ${CMAKE_CURRENT_SOURCE_DIR}/i2c_bbio_pp.cc + ${CMAKE_CURRENT_SOURCE_DIR}/microtune_4702.cc + ${CMAKE_CURRENT_SOURCE_DIR}/microtune_4937.cc + ${CMAKE_CURRENT_SOURCE_DIR}/microtune_xxxx.cc + ${CMAKE_CURRENT_SOURCE_DIR}/ppio_ppdev.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gri_wavfile.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_pdu.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_stream_pdu_base.cc +) + +######################################################################## +# Install runtime headers +######################################################################## +install(FILES + ${CMAKE_CURRENT_SOURCE_DIR}/gr_histo_sink_f.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_oscope_guts.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_oscope_sink_f.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_oscope_sink_x.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_trigger_mode.h + ${CMAKE_CURRENT_SOURCE_DIR}/i2c.h + ${CMAKE_CURRENT_SOURCE_DIR}/i2c_bitbang.h + ${CMAKE_CURRENT_SOURCE_DIR}/i2c_bbio.h + ${CMAKE_CURRENT_SOURCE_DIR}/i2c_bbio_pp.h + ${CMAKE_CURRENT_SOURCE_DIR}/microtune_4702.h + ${CMAKE_CURRENT_SOURCE_DIR}/microtune_4937.h + ${CMAKE_CURRENT_SOURCE_DIR}/microtune_eval_board_defs.h + ${CMAKE_CURRENT_SOURCE_DIR}/microtune_xxxx.h + ${CMAKE_CURRENT_SOURCE_DIR}/ppio_ppdev.h + ${CMAKE_CURRENT_SOURCE_DIR}/gri_wavfile.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_pdu.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_stream_pdu_base.h + DESTINATION ${GR_INCLUDE_DIR}/gnuradio + COMPONENT "core_devel" +) + +######################################################################## +# Install swig headers +######################################################################## +if(ENABLE_PYTHON) +install(FILES + ${CMAKE_CURRENT_SOURCE_DIR}/io.i + ${CMAKE_CURRENT_SOURCE_DIR}/gr_histo_sink.i + ${CMAKE_CURRENT_SOURCE_DIR}/gr_oscope_sink.i + DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig + COMPONENT "core_swig" +) +endif(ENABLE_PYTHON) + +######################################################################## +# Handle triple-threat files that have cc, h, and i +######################################################################## +set(gr_core_io_triple_threats + gr_file_sink + gr_file_sink_base + gr_file_source + gr_file_descriptor_sink + gr_file_descriptor_source + gr_message_debug + gr_message_sink + gr_message_source + gr_message_burst_source + gr_pdu_to_tagged_stream + microtune_xxxx_eval_board + microtune_4702_eval_board + microtune_4937_eval_board + ppio + sdr_1000 + gr_udp_sink + gr_udp_source + gr_wavfile_source + gr_wavfile_sink + gr_tagged_file_sink + gr_tagged_stream_to_pdu + gr_tuntap_pdu + gr_socket_pdu +) + +foreach(file_tt ${gr_core_io_triple_threats}) + list(APPEND gnuradio_core_sources ${CMAKE_CURRENT_SOURCE_DIR}/${file_tt}.cc) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${file_tt}.h DESTINATION ${GR_INCLUDE_DIR}/gnuradio COMPONENT "core_devel") + if(ENABLE_PYTHON) + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/${file_tt}.i DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig COMPONENT "core_swig") + endif(ENABLE_PYTHON) +endforeach(file_tt ${gr_core_io_triple_threats}) diff --git a/gnuradio-core/src/lib/io/gr_file_descriptor_sink.cc b/gnuradio-core/src/lib/io/gr_file_descriptor_sink.cc new file mode 100644 index 000000000..099d46dbd --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_descriptor_sink.cc @@ -0,0 +1,87 @@ +/* -*- 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_file_descriptor_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 <stdio.h> + +#ifdef HAVE_IO_H +#include <io.h> +#endif + +gr_file_descriptor_sink::gr_file_descriptor_sink (size_t itemsize, int fd) + : gr_sync_block ("file_descriptor_sink", + gr_make_io_signature (1, 1, itemsize), + gr_make_io_signature (0, 0, 0)), + d_itemsize (itemsize), d_fd (fd) +{ +} + +gr_file_descriptor_sink_sptr +gr_make_file_descriptor_sink (size_t itemsize, int fd) +{ + return gnuradio::get_initial_sptr(new gr_file_descriptor_sink (itemsize, fd)); +} + +gr_file_descriptor_sink::~gr_file_descriptor_sink () +{ + close (d_fd); +} + +int +gr_file_descriptor_sink::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + char *inbuf = (char *) input_items[0]; + unsigned long byte_size = noutput_items * d_itemsize; + + while (byte_size > 0){ + ssize_t r; + + r = write (d_fd, inbuf, byte_size); + if (r == -1){ + if (errno == EINTR) + continue; + else { + perror ("gr_file_descriptor_sink"); + return -1; // indicate we're done + } + } + else { + byte_size -= r; + inbuf += r; + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/io/gr_file_descriptor_sink.h b/gnuradio-core/src/lib/io/gr_file_descriptor_sink.h new file mode 100644 index 000000000..3b1c1167f --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_descriptor_sink.h @@ -0,0 +1,59 @@ +/* -*- 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_FILE_DESCRIPTOR_SINK_H +#define INCLUDED_GR_FILE_DESCRIPTOR_SINK_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_file_descriptor_sink; +typedef boost::shared_ptr<gr_file_descriptor_sink> gr_file_descriptor_sink_sptr; + +GR_CORE_API gr_file_descriptor_sink_sptr gr_make_file_descriptor_sink (size_t itemsize, int fd); + +/*! + * \brief Write stream to file descriptor. + * \ingroup sink_blk + */ + +class GR_CORE_API gr_file_descriptor_sink : public gr_sync_block +{ + friend GR_CORE_API gr_file_descriptor_sink_sptr gr_make_file_descriptor_sink (size_t itemsize, int fd); + + private: + size_t d_itemsize; + int d_fd; + + protected: + gr_file_descriptor_sink (size_t itemsize, int fd); + + public: + ~gr_file_descriptor_sink (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_FILE_DESCRIPTOR_SINK_H */ diff --git a/gnuradio-core/src/lib/io/gr_file_descriptor_sink.i b/gnuradio-core/src/lib/io/gr_file_descriptor_sink.i new file mode 100644 index 000000000..2c256e44d --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_descriptor_sink.i @@ -0,0 +1,35 @@ +/* -*- 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,file_descriptor_sink) + +gr_file_descriptor_sink_sptr +gr_make_file_descriptor_sink (size_t itemsize, int fd); + +class gr_file_descriptor_sink : public gr_sync_block +{ + protected: + gr_file_descriptor_sink (size_t itemsize, int fd); + + public: + ~gr_file_descriptor_sink (); +}; diff --git a/gnuradio-core/src/lib/io/gr_file_descriptor_source.cc b/gnuradio-core/src/lib/io/gr_file_descriptor_source.cc new file mode 100644 index 000000000..a63abf96b --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_descriptor_source.cc @@ -0,0 +1,151 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_file_descriptor_source.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 <stdio.h> +#include <string.h> + +#ifdef HAVE_IO_H +#include <io.h> +#endif + +gr_file_descriptor_source::gr_file_descriptor_source (size_t itemsize, + int fd, + bool repeat) + : gr_sync_block ("file_descriptor_source", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 1, itemsize)), + d_itemsize (itemsize), d_fd (fd), d_repeat (repeat), + d_residue (new unsigned char[itemsize]), d_residue_len (0) +{ +} + +// public constructor that returns a shared_ptr + +gr_file_descriptor_source_sptr +gr_make_file_descriptor_source (size_t itemsize, int fd, bool repeat) +{ + return gr_file_descriptor_source_sptr ( + new gr_file_descriptor_source (itemsize, fd, repeat)); +} + +gr_file_descriptor_source::~gr_file_descriptor_source () +{ + close (d_fd); + delete [] d_residue; +} + +int +gr_file_descriptor_source::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + assert (noutput_items > 0); + + char *o = (char *) output_items[0]; + int nread = 0; + + while (1){ + int r = read_items (o, noutput_items - nread); + if (r == -1){ + if (errno == EINTR) + continue; + else { + perror ("file_descriptor_source[read]"); + return -1; + } + } + else if (r == 0){ // end of file + if (!d_repeat) + break; + else { + flush_residue (); + if (lseek (d_fd, 0, SEEK_SET) == -1){ + perror ("file_descriptor_source[lseek]"); + return -1; + } + } + } + else { + o += r * d_itemsize; + nread += r; + break; + } + } + + if (nread == 0) // EOF + return -1; + + return nread; +} + +int +gr_file_descriptor_source::read_items (char *buf, int nitems) +{ + assert (nitems > 0); + assert (d_residue_len < d_itemsize); + + int nbytes_read = 0; + + if (d_residue_len > 0){ + memcpy (buf, d_residue, d_residue_len); + nbytes_read = d_residue_len; + d_residue_len = 0; + } + + int r = read (d_fd, buf + nbytes_read, nitems * d_itemsize - nbytes_read); + if (r <= 0){ + handle_residue (buf, nbytes_read); + return r; + } + + r = handle_residue (buf, r + nbytes_read); + + if (r == 0) // block until we get something + return read_items (buf, nitems); + + return r; +} + +int +gr_file_descriptor_source::handle_residue (char *buf, int nbytes_read) +{ + assert (nbytes_read >= 0); + int nitems_read = nbytes_read / d_itemsize; + d_residue_len = nbytes_read % d_itemsize; + if (d_residue_len > 0){ + // fprintf (stderr, "handle_residue: %d\n", d_residue_len); + memcpy (d_residue, buf + nbytes_read - d_residue_len, d_residue_len); + } + return nitems_read; +} diff --git a/gnuradio-core/src/lib/io/gr_file_descriptor_source.h b/gnuradio-core/src/lib/io/gr_file_descriptor_source.h new file mode 100644 index 000000000..ebabd81ed --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_descriptor_source.h @@ -0,0 +1,68 @@ +/* -*- 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_FILE_DESCRIPTOR_SOURCE_H +#define INCLUDED_GR_FILE_DESCRIPTOR_SOURCE_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> + +class gr_file_descriptor_source; +typedef boost::shared_ptr<gr_file_descriptor_source> gr_file_descriptor_source_sptr; + +GR_CORE_API gr_file_descriptor_source_sptr +gr_make_file_descriptor_source (size_t itemsize, int fd, bool repeat = false); + +/*! + * \brief Read stream from file descriptor. + * \ingroup source_blk + */ + +class GR_CORE_API gr_file_descriptor_source : public gr_sync_block +{ + friend GR_CORE_API gr_file_descriptor_source_sptr + gr_make_file_descriptor_source (size_t itemsize, int fd, bool repeat); + private: + size_t d_itemsize; + int d_fd; + bool d_repeat; + + unsigned char *d_residue; + unsigned long d_residue_len; + + protected: + gr_file_descriptor_source (size_t itemsize, int fd, bool repeat); + + int read_items (char *buf, int nitems); + int handle_residue (char *buf, int nbytes_read); + void flush_residue () { d_residue_len = 0; } + + + public: + ~gr_file_descriptor_source (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_FILE_DESCRIPTOR_SOURCE_H */ diff --git a/gnuradio-core/src/lib/io/gr_file_descriptor_source.i b/gnuradio-core/src/lib/io/gr_file_descriptor_source.i new file mode 100644 index 000000000..3ca082522 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_descriptor_source.i @@ -0,0 +1,35 @@ +/* -*- 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,file_descriptor_source) + +gr_file_descriptor_source_sptr +gr_make_file_descriptor_source (size_t itemsize, int fd, bool repeat=false); + +class gr_file_descriptor_source : public gr_sync_block +{ + protected: + gr_file_descriptor_source (size_t itemsize, int fd, bool repeat); + + public: + ~gr_file_descriptor_source (); +}; diff --git a/gnuradio-core/src/lib/io/gr_file_sink.cc b/gnuradio-core/src/lib/io/gr_file_sink.cc new file mode 100644 index 000000000..10c8360cb --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_sink.cc @@ -0,0 +1,84 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_file_sink.h> +#include <gr_io_signature.h> +#include <stdexcept> + + +gr_file_sink_sptr +gr_make_file_sink (size_t itemsize, const char *filename) +{ + return gnuradio::get_initial_sptr(new gr_file_sink (itemsize, filename)); +} + +gr_file_sink::gr_file_sink(size_t itemsize, const char *filename) + : gr_sync_block ("file_sink", + gr_make_io_signature(1, 1, itemsize), + gr_make_io_signature(0, 0, 0)), + gr_file_sink_base(filename, true), + d_itemsize(itemsize) +{ +} + +gr_file_sink::~gr_file_sink () +{ +} + +int +gr_file_sink::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + char *inbuf = (char*)input_items[0]; + int nwritten = 0; + + do_update(); // update d_fp is reqd + + if(!d_fp) + return noutput_items; // drop output on the floor + + while(nwritten < noutput_items) { + int count = fwrite(inbuf, d_itemsize, noutput_items - nwritten, d_fp); + if(count == 0) { + if(ferror(d_fp)) { + std::stringstream s; + s << "file_sink write failed with error " << fileno(d_fp) << std::endl; + throw std::runtime_error(s.str()); + } + else { // is EOF + break; + } + } + nwritten += count; + inbuf += count * d_itemsize; + } + + if(d_unbuffered) + fflush (d_fp); + + return nwritten; +} diff --git a/gnuradio-core/src/lib/io/gr_file_sink.h b/gnuradio-core/src/lib/io/gr_file_sink.h new file mode 100644 index 000000000..e40ec9ab8 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_sink.h @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_FILE_SINK_H +#define INCLUDED_GR_FILE_SINK_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_file_sink_base.h> + +class gr_file_sink; +typedef boost::shared_ptr<gr_file_sink> gr_file_sink_sptr; + +GR_CORE_API gr_file_sink_sptr gr_make_file_sink(size_t itemsize, const char *filename); + +/*! + * \brief Write stream to file. + * \ingroup sink_blk + */ + +class GR_CORE_API gr_file_sink : public gr_sync_block, public gr_file_sink_base +{ + friend GR_CORE_API gr_file_sink_sptr gr_make_file_sink(size_t itemsize, const char *filename); + + private: + size_t d_itemsize; + + protected: + gr_file_sink(size_t itemsize, const char *filename); + + public: + ~gr_file_sink(); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_FILE_SINK_H */ diff --git a/gnuradio-core/src/lib/io/gr_file_sink.i b/gnuradio-core/src/lib/io/gr_file_sink.i new file mode 100644 index 000000000..47ab9e964 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_sink.i @@ -0,0 +1,45 @@ +/* -*- 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,file_sink) + +gr_file_sink_sptr +gr_make_file_sink (size_t itemsize, const char *filename); + +class gr_file_sink : public gr_sync_block, public gr_file_sink_base +{ + protected: + gr_file_sink (size_t itemsize, const char *filename); + + public: + ~gr_file_sink (); + + /*! + * \brief open filename and begin output to it. + */ + bool open(const char *filename); + + /*! + * \brief close current output file. + */ + void close(); +}; diff --git a/gnuradio-core/src/lib/io/gr_file_sink_base.cc b/gnuradio-core/src/lib/io/gr_file_sink_base.cc new file mode 100644 index 000000000..d0aca418e --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_sink_base.cc @@ -0,0 +1,125 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006,2007,2009 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_file_sink_base.h> +#include <cstdio> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdexcept> +#include <stdio.h> +#include <gruel/thread.h> + +// win32 (mingw/msvc) specific +#ifdef HAVE_IO_H +#include <io.h> +#endif +#ifdef O_BINARY +#define OUR_O_BINARY O_BINARY +#else +#define OUR_O_BINARY 0 +#endif + +// should be handled via configure +#ifdef O_LARGEFILE +#define OUR_O_LARGEFILE O_LARGEFILE +#else +#define OUR_O_LARGEFILE 0 +#endif + +gr_file_sink_base::gr_file_sink_base(const char *filename, bool is_binary) + : d_fp(0), d_new_fp(0), d_updated(false), d_is_binary(is_binary) +{ + if (!open(filename)) + throw std::runtime_error ("can't open file"); +} + +gr_file_sink_base::~gr_file_sink_base () +{ + close(); + if (d_fp){ + fclose(d_fp); + d_fp = 0; + } +} + +bool +gr_file_sink_base::open(const char *filename) +{ + gruel::scoped_lock guard(d_mutex); // hold mutex for duration of this function + + // we use the open system call to get access to the O_LARGEFILE flag. + int fd; + if ((fd = ::open (filename, + O_WRONLY|O_CREAT|O_TRUNC|OUR_O_LARGEFILE|OUR_O_BINARY, + 0664)) < 0){ + perror (filename); + return false; + } + if (d_new_fp){ // if we've already got a new one open, close it + fclose(d_new_fp); + d_new_fp = 0; + } + + if ((d_new_fp = fdopen (fd, d_is_binary ? "wb" : "w")) == NULL){ + perror (filename); + ::close(fd); // don't leak file descriptor if fdopen fails. + } + + d_updated = true; + return d_new_fp != 0; +} + +void +gr_file_sink_base::close() +{ + gruel::scoped_lock guard(d_mutex); // hold mutex for duration of this function + + if (d_new_fp){ + fclose(d_new_fp); + d_new_fp = 0; + } + d_updated = true; +} + +void +gr_file_sink_base::do_update() +{ + if (d_updated){ + gruel::scoped_lock guard(d_mutex); // hold mutex for duration of this block + if (d_fp) + fclose(d_fp); + d_fp = d_new_fp; // install new file pointer + d_new_fp = 0; + d_updated = false; + } +} + +void +gr_file_sink_base::set_unbuffered(bool unbuffered) +{ + d_unbuffered = unbuffered; +} diff --git a/gnuradio-core/src/lib/io/gr_file_sink_base.h b/gnuradio-core/src/lib/io/gr_file_sink_base.h new file mode 100644 index 000000000..8a70cee76 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_sink_base.h @@ -0,0 +1,75 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2007,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_FILE_SINK_BASE_H +#define INCLUDED_GR_FILE_SINK_BASE_H + +#include <gr_core_api.h> +#include <boost/thread.hpp> +#include <cstdio> + +/*! + * \brief Common base class for file sinks + */ +class GR_CORE_API gr_file_sink_base +{ + protected: + FILE *d_fp; // current FILE pointer + FILE *d_new_fp; // new FILE pointer + bool d_updated; // is there a new FILE pointer? + bool d_is_binary; + boost::mutex d_mutex; + bool d_unbuffered; + + protected: + gr_file_sink_base(const char *filename, bool is_binary); + + public: + ~gr_file_sink_base(); + + /*! + * \brief Open filename and begin output to it. + */ + bool open(const char *filename); + + /*! + * \brief Close current output file. + * + * Closes current output file and ignores any output until + * open is called to connect to another file. + */ + void close(); + + /*! + * \brief if we've had an update, do it now. + */ + void do_update(); + + + /*! + * \brief turn on unbuffered writes for slower outputs + */ + void set_unbuffered(bool unbuffered); +}; + + +#endif /* INCLUDED_GR_FILE_SINK_BASE_H */ diff --git a/gnuradio-core/src/lib/io/gr_file_sink_base.i b/gnuradio-core/src/lib/io/gr_file_sink_base.i new file mode 100644 index 000000000..993dba277 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_sink_base.i @@ -0,0 +1,51 @@ +/* -*- 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +class gr_file_sink_base +{ + protected: + gr_file_sink_base(const char *filename, bool is_binary); + + public: + ~gr_file_sink_base(); + + /*! + * \brief Open filename and begin output to it. + */ + bool open(const char *filename); + + /*! + * \brief Close current output file. + * + * Closes current output file and ignores any output until + * open is called to connect to another file. + */ + void close(); + + /*! + * \brief if we've had an update, do it now. + */ + void do_update(); + + /*! + *\brief turn on unbuffered mode for slow outputs + */ + void set_unbuffered(bool unbuffered); +}; diff --git a/gnuradio-core/src/lib/io/gr_file_source.cc b/gnuradio-core/src/lib/io/gr_file_source.cc new file mode 100644 index 000000000..6da7abac2 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_source.cc @@ -0,0 +1,192 @@ +/* -*- 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 <gruel/thread.h> +#include <gr_file_source.h> +#include <gr_io_signature.h> +#include <cstdio> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdexcept> +#include <stdio.h> + +// win32 (mingw/msvc) specific +#ifdef HAVE_IO_H +#include <io.h> +#endif +#ifdef O_BINARY +#define OUR_O_BINARY O_BINARY +#else +#define OUR_O_BINARY 0 +#endif +// should be handled via configure +#ifdef O_LARGEFILE +#define OUR_O_LARGEFILE O_LARGEFILE +#else +#define OUR_O_LARGEFILE 0 +#endif + +gr_file_source::gr_file_source(size_t itemsize, const char *filename, bool repeat) + : gr_sync_block("file_source", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 1, itemsize)), + d_itemsize(itemsize), d_fp(0), d_new_fp (0), d_repeat(repeat), + d_updated(false) +{ + open(filename, repeat); +} + +// public constructor that returns a shared_ptr + +gr_file_source_sptr +gr_make_file_source (size_t itemsize, const char *filename, bool repeat) +{ + return gnuradio::get_initial_sptr(new gr_file_source (itemsize, filename, repeat)); +} + +gr_file_source::~gr_file_source () +{ + close(); + if(d_fp) { + fclose(d_fp); + d_fp = 0; + } +} + +int +gr_file_source::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + char *o = (char *) output_items[0]; + int i; + int size = noutput_items; + + do_update(); // update d_fp is reqd + if(d_fp == NULL) + throw std::runtime_error("work with file not open"); + + gruel::scoped_lock lock(fp_mutex); // hold for the rest of this function + while (size) { + i = fread(o, d_itemsize, size, (FILE *) d_fp); + + size -= i; + o += i * d_itemsize; + + if (size == 0) // done + break; + + if (i > 0) // short read, try again + continue; + + // We got a zero from fread. This is either EOF or error. In + // any event, if we're in repeat mode, seek back to the beginning + // of the file and try again, else break + + if (!d_repeat) + break; + + if (fseek ((FILE *) d_fp, 0, SEEK_SET) == -1) { + std::stringstream s; + s << "[" << __FILE__ << "]" << " fseek failed" << std::endl; + throw std::runtime_error(s.str()); + } + } + + if (size > 0){ // EOF or error + if (size == noutput_items) // we didn't read anything; say we're done + return -1; + return noutput_items - size; // else return partial result + } + + return noutput_items; +} + +bool +gr_file_source::seek (long seek_point, int whence) +{ + // obtain exclusive access for duration of this function + gruel::scoped_lock lock(fp_mutex); + return fseek((FILE *) d_fp, seek_point * d_itemsize, whence) == 0; +} + +void +gr_file_source::open(const char *filename, bool repeat) +{ + // obtain exclusive access for duration of this function + gruel::scoped_lock lock(fp_mutex); + + int fd; + + // we use "open" to use to the O_LARGEFILE flag + if((fd = ::open(filename, O_RDONLY | OUR_O_LARGEFILE | OUR_O_BINARY)) < 0) { + perror(filename); + throw std::runtime_error("can't open file"); + } + + if(d_new_fp) { + fclose(d_new_fp); + d_new_fp = 0; + } + + if((d_new_fp = fdopen (fd, "rb")) == NULL) { + perror(filename); + ::close(fd); // don't leak file descriptor if fdopen fails + throw std::runtime_error("can't open file"); + } + + d_updated = true; + d_repeat = repeat; +} + +void +gr_file_source::close() +{ + // obtain exclusive access for duration of this function + gruel::scoped_lock lock(fp_mutex); + + if(d_new_fp != NULL) { + fclose(d_new_fp); + d_new_fp = NULL; + } + d_updated = true; +} + +void +gr_file_source::do_update() +{ + if(d_updated) { + gruel::scoped_lock lock(fp_mutex); // hold while in scope + + if(d_fp) + fclose(d_fp); + + d_fp = d_new_fp; // install new file pointer + d_new_fp = 0; + d_updated = false; + } +} diff --git a/gnuradio-core/src/lib/io/gr_file_source.h b/gnuradio-core/src/lib/io/gr_file_source.h new file mode 100644 index 000000000..0478fba04 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_source.h @@ -0,0 +1,107 @@ +/* -*- 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_FILE_SOURCE_H +#define INCLUDED_GR_FILE_SOURCE_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <boost/thread/mutex.hpp> + +class gr_file_source; +typedef boost::shared_ptr<gr_file_source> gr_file_source_sptr; + +GR_CORE_API gr_file_source_sptr +gr_make_file_source (size_t itemsize, const char *filename, bool repeat = false); + +/*! + * \brief Read stream from file + * \ingroup source_blk + */ + +class GR_CORE_API gr_file_source : public gr_sync_block +{ + private: + size_t d_itemsize; + FILE *d_fp; + FILE *d_new_fp; + bool d_repeat; + bool d_updated; + + protected: + gr_file_source(size_t itemsize, const char *filename, bool repeat); + + void do_update(); + + boost::mutex fp_mutex; + + public: + /*! + * \brief Create a file source. + * + * Opens \p filename as a source of items into a flowgraph. The data + * is expected to be in binary format, item after item. The \p + * itemsize of the block determines the conversion from bits to + * items. + * + * If \p repeat is turned on, the file will repeat the file after + * it's reached the end. + * + * \param itemsize the size of each item in the file, in bytes + * \param filename name of the file to source from + * \param repeat repeat file from start + */ + friend GR_CORE_API gr_file_source_sptr + gr_make_file_source(size_t itemsize, + const char *filename, + bool repeat); + + ~gr_file_source(); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + /*! + * \brief Seek file to \p seek_point relative to \p whence + * + * \param seek_point sample offset in file + * \param whence one of SEEK_SET, SEEK_CUR, SEEK_END (man fseek) + */ + bool seek(long seek_point, int whence); + + /*! + * \brief Opens a new file. + * + * \param filename name of the file to source from + * \param repeat repeat file from start + */ + void open(const char *filename, bool repeat); + + /*! + * \brief Close the file handle. + */ + void close(); + +}; + +#endif /* INCLUDED_GR_FILE_SOURCE_H */ diff --git a/gnuradio-core/src/lib/io/gr_file_source.i b/gnuradio-core/src/lib/io/gr_file_source.i new file mode 100644 index 000000000..e71cef0d1 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_source.i @@ -0,0 +1,45 @@ +/* -*- 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. + */ + + +%constant int SEEK_SET = 0; /* Seek from beginning of file. */ +%constant int SEEK_CUR = 1; /* Seek from current position. */ +%constant int SEEK_END = 2; /* Seek from end of file. */ + + +GR_SWIG_BLOCK_MAGIC(gr,file_source) + +gr_file_source_sptr +gr_make_file_source (size_t itemsize, const char *filename, bool repeat=false); + +class gr_file_source : public gr_sync_block +{ + protected: + gr_file_source (size_t itemsize, const char *filename, bool repeat); + + public: + ~gr_file_source (); + + bool seek (long seek_point, int whence); + void open (const char *filename, bool repeat); + void close(); +}; diff --git a/gnuradio-core/src/lib/io/gr_histo_sink.i b/gnuradio-core/src/lib/io/gr_histo_sink.i new file mode 100644 index 000000000..14079e190 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_histo_sink.i @@ -0,0 +1,39 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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,histo_sink_f) + +gr_histo_sink_f_sptr gr_make_histo_sink_f (gr_msg_queue_sptr msgq); + +class gr_histo_sink_f : public gr_sync_block +{ +public: + ~gr_histo_sink_f (void); + + unsigned int get_frame_size(void); + unsigned int get_num_bins(void); + + void set_frame_size(unsigned int frame_size); + void set_num_bins(unsigned int num_bins); + +}; diff --git a/gnuradio-core/src/lib/io/gr_histo_sink_f.cc b/gnuradio-core/src/lib/io/gr_histo_sink_f.cc new file mode 100644 index 000000000..fc0c12ce6 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_histo_sink_f.cc @@ -0,0 +1,165 @@ +/* -*- c++ -*- */ +/* + * Copyright 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 <gr_histo_sink_f.h> +#include <gr_io_signature.h> +#include <boost/math/special_functions/round.hpp> + +static float get_clean_num(float num){ + if (num == 0) return 0; + /* extract sign and exponent from num */ + int sign = (num < 0) ? -1 : 1; num = fabs(num); + float exponent = floor(log10(num)); + /* search for closest number with base 1, 2, 5, 10 */ + float closest_num = 10*pow(10, exponent); + if (fabs(num - 1*pow(10, exponent)) < fabs(num - closest_num)) + closest_num = 1*pow(10, exponent); + if (fabs(num - 2*pow(10, exponent)) < fabs(num - closest_num)) + closest_num = 2*pow(10, exponent); + if (fabs(num - 5*pow(10, exponent)) < fabs(num - closest_num)) + closest_num = 5*pow(10, exponent); + return sign*closest_num; +} + +gr_histo_sink_f_sptr +gr_make_histo_sink_f (gr_msg_queue_sptr msgq) +{ + return gnuradio::get_initial_sptr(new gr_histo_sink_f (msgq)); +} + +gr_histo_sink_f::gr_histo_sink_f (gr_msg_queue_sptr msgq) + : gr_sync_block ("histo_sink_f", gr_make_io_signature (1, 1, sizeof (float)), gr_make_io_signature (0, 0, 0)), + d_msgq (msgq), d_num_bins(11), d_frame_size(1000), d_sample_count(0), d_bins(NULL), d_samps(NULL) +{ + //allocate arrays and clear + set_num_bins(d_num_bins); + set_frame_size(d_frame_size); +} + +gr_histo_sink_f::~gr_histo_sink_f (void) +{ + delete [] d_samps; + delete [] d_bins; +} + +int +gr_histo_sink_f::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]; + gruel::scoped_lock guard(d_mutex); // hold mutex for duration of this function + for (unsigned int i = 0; i < (unsigned int)noutput_items; i++){ + d_samps[d_sample_count] = in[i]; + d_sample_count++; + /* processed a frame? */ + if (d_sample_count == d_frame_size){ + send_frame(); + clear(); + } + } + return noutput_items; +} + +void +gr_histo_sink_f::send_frame(void){ + /* output queue full, drop the data */ + if (d_msgq->full_p()) return; + /* find the minimum and maximum */ + float minimum = d_samps[0]; + float maximum = d_samps[0]; + for (unsigned int i = 0; i < d_frame_size; i++){ + if (d_samps[i] < minimum) minimum = d_samps[i]; + if (d_samps[i] > maximum) maximum = d_samps[i]; + } + minimum = get_clean_num(minimum); + maximum = get_clean_num(maximum); + if (minimum == maximum || minimum > maximum) return; //useless data or screw up? + /* load the bins */ + int index; + float bin_width = (maximum - minimum)/(d_num_bins-1); + for (unsigned int i = 0; i < d_sample_count; i++){ + index = boost::math::iround((d_samps[i] - minimum)/bin_width); + /* ensure the index range in case a small floating point error is involed */ + if (index < 0) index = 0; + if (index >= (int)d_num_bins) index = d_num_bins-1; + d_bins[index]++; + } + /* Build a message to hold the output records */ + gr_message_sptr msg = gr_make_message(0, minimum, maximum, d_num_bins*sizeof(float)); + float *out = (float *)msg->msg(); // get pointer to raw message buffer + /* normalize the bins and put into message */ + for (unsigned int i = 0; i < d_num_bins; i++){ + out[i] = ((float)d_bins[i])/d_frame_size; + } + /* send the message */ + d_msgq->handle(msg); +} + +void +gr_histo_sink_f::clear(void){ + d_sample_count = 0; + /* zero the bins */ + for (unsigned int i = 0; i < d_num_bins; i++){ + d_bins[i] = 0; + } +} + +/************************************************** + * Getters + **************************************************/ +unsigned int +gr_histo_sink_f::get_frame_size(void){ + return d_frame_size; +} + +unsigned int +gr_histo_sink_f::get_num_bins(void){ + return d_num_bins; +} + +/************************************************** + * Setters + **************************************************/ +void +gr_histo_sink_f::set_frame_size(unsigned int frame_size){ + gruel::scoped_lock guard(d_mutex); // hold mutex for duration of this function + d_frame_size = frame_size; + /* allocate a new sample array */ + delete [] d_samps; + d_samps = new float[d_frame_size]; + clear(); +} + +void +gr_histo_sink_f::set_num_bins(unsigned int num_bins){ + gruel::scoped_lock guard(d_mutex); // hold mutex for duration of this function + d_num_bins = num_bins; + /* allocate a new bin array */ + delete [] d_bins; + d_bins = new unsigned int[d_num_bins]; + clear(); +} diff --git a/gnuradio-core/src/lib/io/gr_histo_sink_f.h b/gnuradio-core/src/lib/io/gr_histo_sink_f.h new file mode 100644 index 000000000..934066ba2 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_histo_sink_f.h @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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_HISTO_SINK_F_H +#define INCLUDED_GR_HISTO_SINK_F_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_msg_queue.h> +#include <gruel/thread.h> + +class gr_histo_sink_f; +typedef boost::shared_ptr<gr_histo_sink_f> gr_histo_sink_f_sptr; + +GR_CORE_API gr_histo_sink_f_sptr gr_make_histo_sink_f (gr_msg_queue_sptr msgq); + +/*! + * \brief Histogram module. + * \ingroup sink_blk + */ +class GR_CORE_API gr_histo_sink_f : public gr_sync_block +{ +private: + gr_msg_queue_sptr d_msgq; + unsigned int d_num_bins; + unsigned int d_frame_size; + unsigned int d_sample_count; + unsigned int *d_bins; + float *d_samps; + gruel::mutex d_mutex; + + friend GR_CORE_API gr_histo_sink_f_sptr gr_make_histo_sink_f (gr_msg_queue_sptr msgq); + gr_histo_sink_f (gr_msg_queue_sptr msgq); + void send_frame(void); + void clear(void); + +public: + ~gr_histo_sink_f (void); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + unsigned int get_frame_size(void); + unsigned int get_num_bins(void); + + void set_frame_size(unsigned int frame_size); + void set_num_bins(unsigned int num_bins); + +}; + +#endif /* INCLUDED_GR_HISTO_SINK_F_H */ diff --git a/gnuradio-core/src/lib/io/gr_message_burst_source.cc b/gnuradio-core/src/lib/io/gr_message_burst_source.cc new file mode 100644 index 000000000..e9e2dfd4d --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_burst_source.cc @@ -0,0 +1,144 @@ +/* -*- 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 <gr_message_burst_source.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 <string.h> +#include <gr_tags.h> + +// public constructor that returns a shared_ptr + +gr_message_burst_source_sptr +gr_make_message_burst_source(size_t itemsize, int msgq_limit) +{ + return gnuradio::get_initial_sptr(new gr_message_burst_source(itemsize, msgq_limit)); +} + +// public constructor that takes existing message queue +gr_message_burst_source_sptr +gr_make_message_burst_source(size_t itemsize, gr_msg_queue_sptr msgq) +{ + return gnuradio::get_initial_sptr(new gr_message_burst_source(itemsize, msgq)); +} + +gr_message_burst_source::gr_message_burst_source (size_t itemsize, int msgq_limit) + : gr_sync_block("message_burst_source", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(1, 1, itemsize)), + d_itemsize(itemsize), d_msgq(gr_make_msg_queue(msgq_limit)), d_msg_offset(0), d_eof(false) +{ + std::stringstream id; + id << name() << unique_id(); + d_me = pmt::pmt_string_to_symbol(id.str()); +} + +gr_message_burst_source::gr_message_burst_source (size_t itemsize, gr_msg_queue_sptr msgq) + : gr_sync_block("message_burst_source", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(1, 1, itemsize)), + d_itemsize(itemsize), d_msgq(msgq), d_msg_offset(0), d_eof(false) +{ + std::stringstream id; + id << name() << unique_id(); + d_me = pmt::pmt_string_to_symbol(id.str()); +} + +gr_message_burst_source::~gr_message_burst_source() +{ +} + +int +gr_message_burst_source::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + char *out = (char *) output_items[0]; + int nn = 0; + + uint64_t abs_sample_count = nitems_written(0); + + while (nn < noutput_items){ + if (d_msg){ + // + // Consume whatever we can from the current message + // + + int mm = std::min(noutput_items - nn, (int)((d_msg->length() - d_msg_offset) / d_itemsize)); + memcpy (out, &(d_msg->msg()[d_msg_offset]), mm * d_itemsize); + + nn += mm; + out += mm * d_itemsize; + d_msg_offset += mm * d_itemsize; + assert(d_msg_offset <= d_msg->length()); + + if (d_msg_offset == d_msg->length()){ + if (d_msg->type() == 1) // type == 1 sets EOF + d_eof = true; + d_msg.reset(); + //tag end of burst + add_item_tag(0, //stream ID + abs_sample_count+nn-1, //sample number + pmt::pmt_string_to_symbol("tx_eob"), + pmt::pmt_from_bool(1), + d_me //block src id + ); + } + } + else { + // + // No current message + // + if (d_msgq->empty_p() && nn > 0){ // no more messages in the queue, return what we've got + break; + } + + if (d_eof) + return -1; + + d_msg = d_msgq->delete_head(); // block, waiting for a message + d_msg_offset = 0; + //tag start of burst + add_item_tag(0, //stream ID + abs_sample_count+nn, //sample number + pmt::pmt_string_to_symbol("tx_sob"), + pmt::pmt_from_bool(1), + d_me //block src id + ); + + + if ((d_msg->length() % d_itemsize) != 0) + throw std::runtime_error("msg length is not a multiple of d_itemsize"); + } + } + + return nn; +} diff --git a/gnuradio-core/src/lib/io/gr_message_burst_source.h b/gnuradio-core/src/lib/io/gr_message_burst_source.h new file mode 100644 index 000000000..63e220113 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_burst_source.h @@ -0,0 +1,71 @@ +/* -*- 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_GR_MESSAGE_BURST_SOURCE_H +#define INCLUDED_GR_MESSAGE_BURST_SOURCE_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_message.h> +#include <gr_msg_queue.h> + +class gr_message_burst_source; +typedef boost::shared_ptr<gr_message_burst_source> gr_message_burst_source_sptr; + +GR_CORE_API gr_message_burst_source_sptr gr_make_message_burst_source (size_t itemsize, int msgq_limit=0); +GR_CORE_API gr_message_burst_source_sptr gr_make_message_burst_source (size_t itemsize, gr_msg_queue_sptr msgq); + +/*! + * \brief Turn received messages into a stream and tag them for UHD to send. + * \ingroup source_blk + */ +class GR_CORE_API gr_message_burst_source : public gr_sync_block +{ + private: + size_t d_itemsize; + gr_msg_queue_sptr d_msgq; + gr_message_sptr d_msg; + unsigned d_msg_offset; + bool d_eof; + + pmt::pmt_t d_me; + + friend GR_CORE_API gr_message_burst_source_sptr + gr_make_message_burst_source(size_t itemsize, int msgq_limit); + friend GR_CORE_API gr_message_burst_source_sptr + gr_make_message_burst_source(size_t itemsize, gr_msg_queue_sptr msgq); + + protected: + gr_message_burst_source (size_t itemsize, int msgq_limit); + gr_message_burst_source (size_t itemsize, gr_msg_queue_sptr msgq); + + public: + ~gr_message_burst_source (); + + gr_msg_queue_sptr msgq() const { return d_msgq; } + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_gr_message_burst_source_H */ diff --git a/gnuradio-core/src/lib/io/gr_message_burst_source.i b/gnuradio-core/src/lib/io/gr_message_burst_source.i new file mode 100644 index 000000000..f7ad840c2 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_burst_source.i @@ -0,0 +1,38 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,message_burst_source); + +gr_message_burst_source_sptr gr_make_message_burst_source (size_t itemsize, int msgq_limit=0); +gr_message_burst_source_sptr gr_make_message_burst_source (size_t itemsize, gr_msg_queue_sptr msgq); + +class gr_message_burst_source : public gr_sync_block +{ + protected: + gr_message_burst_source (size_t itemsize, int msgq_limit); + gr_message_burst_source (size_t itemsize, gr_msg_queue_sptr msgq); + + public: + ~gr_message_burst_source (); + + gr_msg_queue_sptr msgq() const; +}; diff --git a/gnuradio-core/src/lib/io/gr_message_debug.cc b/gnuradio-core/src/lib/io/gr_message_debug.cc new file mode 100644 index 000000000..9eb1bb639 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_debug.cc @@ -0,0 +1,120 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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 <gr_message_debug.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 <string.h> +#include <iostream> + +// public constructor that returns a shared_ptr + +gr_message_debug_sptr +gr_make_message_debug () +{ + return gnuradio::get_initial_sptr(new gr_message_debug()); +} + +void +gr_message_debug::print(pmt::pmt_t msg) +{ + std::cout << "******* MESSAGE DEBUG PRINT ********\n"; + pmt::pmt_print(msg); + std::cout << "************************************\n"; +} + +void +gr_message_debug::store(pmt::pmt_t msg) +{ + gruel::scoped_lock guard(d_mutex); + d_messages.push_back(msg); +} + +void +gr_message_debug::print_pdu(pmt::pmt_t pdu) +{ + pmt::pmt_t meta = pmt::pmt_car(pdu); + pmt::pmt_t vector = pmt::pmt_cdr(pdu); + std::cout << "* MESSAGE DEBUG PRINT PDU VERBOSE *\n"; + pmt::pmt_print(meta); + size_t len = pmt::pmt_length(vector); + std::cout << "pdu_length = " << len << std::endl; + std::cout << "contents = " << std::endl; + size_t offset(0); + const uint8_t* d = (const uint8_t*) pmt_uniform_vector_elements(vector, offset); + for(size_t i=0; i<len; i+=16){ + printf("%04x: ", ((unsigned int)i)); + for(size_t j=i; j<std::min(i+16,len); j++){ + printf("%02x ",d[j] ); + } + + std::cout << std::endl; + } + + std::cout << "***********************************\n"; +} + +int +gr_message_debug::num_messages() +{ + return (int)d_messages.size(); +} + +pmt::pmt_t +gr_message_debug::get_message(int i) +{ + gruel::scoped_lock guard(d_mutex); + + if((size_t)i >= d_messages.size()) { + throw std::runtime_error("gr_message_debug: index for message out of bounds.\n"); + } + + return d_messages[i]; +} + +gr_message_debug::gr_message_debug() + : gr_block("message_debug", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(0, 0, 0)) +{ + message_port_register_in(pmt::mp("print")); + set_msg_handler(pmt::mp("print"), boost::bind(&gr_message_debug::print, this, _1)); + + message_port_register_in(pmt::mp("store")); + set_msg_handler(pmt::mp("store"), boost::bind(&gr_message_debug::store, this, _1)); + + message_port_register_in(pmt::mp("print_pdu")); + set_msg_handler(pmt::mp("print_pdu"), boost::bind(&gr_message_debug::print_pdu, this, _1)); +} + +gr_message_debug::~gr_message_debug() +{ +} diff --git a/gnuradio-core/src/lib/io/gr_message_debug.h b/gnuradio-core/src/lib/io/gr_message_debug.h new file mode 100644 index 000000000..f1374e806 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_debug.h @@ -0,0 +1,114 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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_GR_MESSAGE_DEBUG_H +#define INCLUDED_GR_MESSAGE_DEBUG_H + +#include <gr_core_api.h> +#include <gr_block.h> +#include <gr_message.h> +#include <gr_msg_queue.h> +#include <gruel/thread.h> + +class gr_message_debug; +typedef boost::shared_ptr<gr_message_debug> gr_message_debug_sptr; + +GR_CORE_API gr_message_debug_sptr gr_make_message_debug(); + +/*! + * \brief Print received messages to stdout + * \ingroup sink_blk + */ +class GR_CORE_API gr_message_debug : public gr_block +{ + private: + friend GR_CORE_API gr_message_debug_sptr + gr_make_message_debug(); + + /*! + * \brief Messages received in this port are printed to stdout. + * + * This port receives messages from the scheduler's message handling + * mechanism and prints it to stdout. This message handler function + * is only meant to be used by the scheduler to handle messages + * posted to port 'print'. + * + * \param msg A pmt message passed from the scheduler's message handling. + */ + void print(pmt::pmt_t msg); + + /*! + * \brief PDU formatted messages received in this port are printed to stdout. + * + * This port receives messages from the scheduler's message handling + * mechanism and prints it to stdout. This message handler function + * is only meant to be used by the scheduler to handle messages + * posted to port 'print'. + * + * \param pdu A PDU message passed from the scheduler's message handling. + */ + void print_pdu(pmt::pmt_t pdu); + + /*! + * \brief Messages received in this port are stored in a vector. + * + * This port receives messages from the scheduler's message handling + * mechanism and stores it in a vector. Messages can be retrieved + * later using the 'get_message' function. This message handler + * function is only meant to be used by the scheduler to handle + * messages posted to port 'store'. + * + * \param msg A pmt message passed from the scheduler's message handling. + */ + void store(pmt::pmt_t msg); + + gruel::mutex d_mutex; + std::vector<pmt::pmt_t> d_messages; + + protected: + gr_message_debug (); + + public: + ~gr_message_debug (); + + /*! + * \brief Reports the number of messages received by this block. + */ + int num_messages(); + + /*! + * \brief Get a message (as a PMT) from the message vector at index \p i. + * + * Messages passed to the 'store' port will be stored in a + * vector. This function retrieves those messages by index. They are + * index in order of when they were received (all messages are just + * pushed onto the back of a vector). This is mostly useful in + * debugging message passing graphs and in QA code. + * + * \param i The index in the vector for the message to retrieve. + * + * \return a message at index \p i as a pmt_t. + */ + pmt::pmt_t get_message(int i); +}; + +#endif /* INCLUDED_GR_MESSAGE_DEBUG_H */ diff --git a/gnuradio-core/src/lib/io/gr_message_debug.i b/gnuradio-core/src/lib/io/gr_message_debug.i new file mode 100644 index 000000000..65d3bfc4a --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_debug.i @@ -0,0 +1,30 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,message_debug); + +%{ +#include <gr_message_debug.h> +%} + +%include "gr_message_debug.h" + diff --git a/gnuradio-core/src/lib/io/gr_message_sink.cc b/gnuradio-core/src/lib/io/gr_message_sink.cc new file mode 100644 index 000000000..ae0b5c764 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_sink.cc @@ -0,0 +1,79 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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_message_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 <string.h> + + +// public constructor that returns a shared_ptr + +gr_message_sink_sptr +gr_make_message_sink (size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block) +{ + return gnuradio::get_initial_sptr(new gr_message_sink(itemsize, msgq, dont_block)); +} + +gr_message_sink::gr_message_sink (size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block) + : gr_sync_block("message_sink", + gr_make_io_signature(1, 1, itemsize), + gr_make_io_signature(0, 0, 0)), + d_itemsize(itemsize), d_msgq(msgq), d_dont_block(dont_block) +{ +} + +gr_message_sink::~gr_message_sink() +{ +} + +int +gr_message_sink::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]; + + // if we'd block, drop the data on the floor and say everything is OK + if (d_dont_block && d_msgq->full_p()) + return noutput_items; + + // build a message to hold whatever we've got + gr_message_sptr msg = gr_make_message(0, // msg type + d_itemsize, // arg1 for other end + noutput_items, // arg2 for other end (redundant) + noutput_items * d_itemsize); // len of msg + memcpy(msg->msg(), in, noutput_items * d_itemsize); + + d_msgq->handle(msg); // send it + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/io/gr_message_sink.h b/gnuradio-core/src/lib/io/gr_message_sink.h new file mode 100644 index 000000000..84005694a --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_sink.h @@ -0,0 +1,63 @@ +/* -*- 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_MESSAGE_SINK_H +#define INCLUDED_GR_MESSAGE_SINK_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_message.h> +#include <gr_msg_queue.h> + +class gr_message_sink; +typedef boost::shared_ptr<gr_message_sink> gr_message_sink_sptr; + +GR_CORE_API gr_message_sink_sptr gr_make_message_sink (size_t itemsize, + gr_msg_queue_sptr msgq, + bool dont_block); + +/*! + * \brief Gather received items into messages and insert into msgq + * \ingroup sink_blk + */ +class GR_CORE_API gr_message_sink : public gr_sync_block +{ + private: + size_t d_itemsize; + gr_msg_queue_sptr d_msgq; + bool d_dont_block; + + friend GR_CORE_API gr_message_sink_sptr + gr_make_message_sink(size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block); + + protected: + gr_message_sink (size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block); + + public: + ~gr_message_sink (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_MESSAGE_SINK_H */ diff --git a/gnuradio-core/src/lib/io/gr_message_sink.i b/gnuradio-core/src/lib/io/gr_message_sink.i new file mode 100644 index 000000000..8415cbd66 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_sink.i @@ -0,0 +1,36 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,message_sink); + +gr_message_sink_sptr gr_make_message_sink (size_t itemsize, + gr_msg_queue_sptr msgq, + bool dont_block); + +class gr_message_sink : public gr_sync_block +{ + protected: + gr_message_sink (size_t itemsize, gr_msg_queue_sptr msgq, bool dont_block); + + public: + ~gr_message_sink (); +}; diff --git a/gnuradio-core/src/lib/io/gr_message_source.cc b/gnuradio-core/src/lib/io/gr_message_source.cc new file mode 100644 index 000000000..fb3da89a8 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_source.cc @@ -0,0 +1,120 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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_message_source.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 <string.h> + + +// public constructor that returns a shared_ptr + +gr_message_source_sptr +gr_make_message_source(size_t itemsize, int msgq_limit) +{ + return gnuradio::get_initial_sptr(new gr_message_source(itemsize, msgq_limit)); +} + +// public constructor that takes existing message queue +gr_message_source_sptr +gr_make_message_source(size_t itemsize, gr_msg_queue_sptr msgq) +{ + return gnuradio::get_initial_sptr(new gr_message_source(itemsize, msgq)); +} + +gr_message_source::gr_message_source (size_t itemsize, int msgq_limit) + : gr_sync_block("message_source", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(1, 1, itemsize)), + d_itemsize(itemsize), d_msgq(gr_make_msg_queue(msgq_limit)), d_msg_offset(0), d_eof(false) +{ +} + +gr_message_source::gr_message_source (size_t itemsize, gr_msg_queue_sptr msgq) + : gr_sync_block("message_source", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(1, 1, itemsize)), + d_itemsize(itemsize), d_msgq(msgq), d_msg_offset(0), d_eof(false) +{ +} + +gr_message_source::~gr_message_source() +{ +} + +int +gr_message_source::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + char *out = (char *) output_items[0]; + int nn = 0; + + while (nn < noutput_items){ + if (d_msg){ + // + // Consume whatever we can from the current message + // + int mm = std::min(noutput_items - nn, (int)((d_msg->length() - d_msg_offset) / d_itemsize)); + memcpy (out, &(d_msg->msg()[d_msg_offset]), mm * d_itemsize); + + nn += mm; + out += mm * d_itemsize; + d_msg_offset += mm * d_itemsize; + assert(d_msg_offset <= d_msg->length()); + + if (d_msg_offset == d_msg->length()){ + if (d_msg->type() == 1) // type == 1 sets EOF + d_eof = true; + d_msg.reset(); + } + } + else { + // + // No current message + // + if (d_msgq->empty_p() && nn > 0){ // no more messages in the queue, return what we've got + break; + } + + if (d_eof) + return -1; + + d_msg = d_msgq->delete_head(); // block, waiting for a message + d_msg_offset = 0; + + if ((d_msg->length() % d_itemsize) != 0) + throw std::runtime_error("msg length is not a multiple of d_itemsize"); + } + } + + return nn; +} diff --git a/gnuradio-core/src/lib/io/gr_message_source.h b/gnuradio-core/src/lib/io/gr_message_source.h new file mode 100644 index 000000000..c510d1775 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_source.h @@ -0,0 +1,69 @@ +/* -*- 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_MESSAGE_SOURCE_H +#define INCLUDED_GR_MESSAGE_SOURCE_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_message.h> +#include <gr_msg_queue.h> + +class gr_message_source; +typedef boost::shared_ptr<gr_message_source> gr_message_source_sptr; + +GR_CORE_API gr_message_source_sptr gr_make_message_source (size_t itemsize, int msgq_limit=0); +GR_CORE_API gr_message_source_sptr gr_make_message_source (size_t itemsize, gr_msg_queue_sptr msgq); + +/*! + * \brief Turn received messages into a stream + * \ingroup source_blk + */ +class GR_CORE_API gr_message_source : public gr_sync_block +{ + private: + size_t d_itemsize; + gr_msg_queue_sptr d_msgq; + gr_message_sptr d_msg; + unsigned d_msg_offset; + bool d_eof; + + friend GR_CORE_API gr_message_source_sptr + gr_make_message_source(size_t itemsize, int msgq_limit); + friend GR_CORE_API gr_message_source_sptr + gr_make_message_source(size_t itemsize, gr_msg_queue_sptr msgq); + + protected: + gr_message_source (size_t itemsize, int msgq_limit); + gr_message_source (size_t itemsize, gr_msg_queue_sptr msgq); + + public: + ~gr_message_source (); + + gr_msg_queue_sptr msgq() const { return d_msgq; } + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_MESSAGE_SOURCE_H */ diff --git a/gnuradio-core/src/lib/io/gr_message_source.i b/gnuradio-core/src/lib/io/gr_message_source.i new file mode 100644 index 000000000..9ee9157e8 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_source.i @@ -0,0 +1,38 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,message_source); + +gr_message_source_sptr gr_make_message_source (size_t itemsize, int msgq_limit=0); +gr_message_source_sptr gr_make_message_source (size_t itemsize, gr_msg_queue_sptr msgq); + +class gr_message_source : public gr_sync_block +{ + protected: + gr_message_source (size_t itemsize, int msgq_limit); + gr_message_source (size_t itemsize, gr_msg_queue_sptr msgq); + + public: + ~gr_message_source (); + + gr_msg_queue_sptr msgq() const; +}; diff --git a/gnuradio-core/src/lib/io/gr_oscope_guts.cc b/gnuradio-core/src/lib/io/gr_oscope_guts.cc new file mode 100644 index 000000000..a5ea3002a --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_guts.cc @@ -0,0 +1,437 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_oscope_guts.h> +#include <stdexcept> +#include <stdio.h> +#include <algorithm> +#include <unistd.h> +#include <math.h> +#include <assert.h> + +/* + * Bad performance if it's large, and flaky triggering if it's too small + */ +static const int OUTPUT_RECORD_SIZE = 1024; // Must be power of 2 + +/* + * For (slow-updated) STRIPCHART triggering, we make the record size larger, since we + * potentially want to be able to "see" hours of data. This works as long as the + * update rates to a STRIPCHART are low, which they generally are--that's rather what + * a stripchart is all about! + */ +static const int SCHART_MULT = 8; + + +static inline int +wrap_bi (int buffer_index, int mx) // wrap buffer index +{ + return buffer_index & (mx - 1); +} + +static inline int +incr_bi (int buffer_index, int mx) // increment buffer index +{ + return wrap_bi (buffer_index + 1, mx); +} + +static inline int +decr_bi (int buffer_index, int mx) // decrement buffer index +{ + return wrap_bi (buffer_index - 1, mx); +} + +gr_oscope_guts::gr_oscope_guts (double sample_rate, gr_msg_queue_sptr msgq) + : d_nchannels (1), + d_msgq (msgq), + d_trigger_mode (gr_TRIG_MODE_AUTO), + d_trigger_slope (gr_TRIG_SLOPE_POS), + d_trigger_channel (0), + d_sample_rate (sample_rate), + d_update_rate (20), + d_trigger_level (0), + d_obi (0), + d_state (HOLD_OFF), + d_decimator_count (0), + d_decimator_count_init (1), + d_hold_off_count (0), + d_hold_off_count_init (OUTPUT_RECORD_SIZE/2-1), + d_pre_trigger_count (0), + d_post_trigger_count (0), + d_post_trigger_count_init (OUTPUT_RECORD_SIZE/2) +{ + for (int i = 0; i < MAX_CHANNELS; i++) + d_buffer[i] = 0; + + for (int i = 0; i < MAX_CHANNELS; i++){ + d_buffer[i] = new float [OUTPUT_RECORD_SIZE*SCHART_MULT]; + for (int j = 0; j < OUTPUT_RECORD_SIZE*SCHART_MULT; j++) + d_buffer[i][j] = 0.0; + } + + // be sure buffer is full before first write + enter_hold_off (); + update_rate_or_decimation_changed (); +} + +gr_oscope_guts::~gr_oscope_guts () +{ + for (int i = 0; i < MAX_CHANNELS; i++) + delete [] d_buffer[i]; +} + +// MANIPULATORS + +// \p channel_data points to nchannels float values. These are the values +// for each channel at this sample time. + +void +gr_oscope_guts::process_sample (const float *channel_data) +{ + d_decimator_count--; + if (d_decimator_count > 0) + return; + + d_decimator_count = d_decimator_count_init; + + if (d_trigger_mode != gr_TRIG_MODE_STRIPCHART) + { + for (int i = 0; i < d_nchannels; i++) + d_buffer[i][d_obi] = channel_data[i]; // copy data into buffer + + switch (d_state){ + case HOLD_OFF: + d_hold_off_count--; + if (d_hold_off_count <= 0) + enter_look_for_trigger (); + break; + + case LOOK_FOR_TRIGGER: + if (found_trigger ()) + enter_post_trigger (); + break; + + case POST_TRIGGER: + d_post_trigger_count--; + if (d_post_trigger_count <= 0){ + write_output_records (); + enter_hold_off (); + } + break; + + default: + assert (0); + } + + d_obi = incr_bi (d_obi, OUTPUT_RECORD_SIZE); + } + else + { + for (int i = 0; i < d_nchannels; i++) + { + for (int j = (OUTPUT_RECORD_SIZE*SCHART_MULT)-1; j > 0; j--) + { + d_buffer[i][j] = d_buffer[i][j-1]; + } + d_buffer[i][0] = channel_data[i]; + } + d_trigger_off = 0; + write_output_records(); + } +} + +/* + * Functions called on state entry + */ + +void +gr_oscope_guts::enter_hold_off () +{ + d_state = HOLD_OFF; + d_hold_off_count = d_hold_off_count_init; +} + +void +gr_oscope_guts::enter_look_for_trigger () +{ + d_pre_trigger_count = 0; + d_state = LOOK_FOR_TRIGGER; +} + +void +gr_oscope_guts::enter_post_trigger () +{ + d_state = POST_TRIGGER; + d_post_trigger_count = d_post_trigger_count_init; + //ensure that the trigger offset is no more than than half a sample + if (d_trigger_off > .5) d_trigger_off -= 1; + else d_post_trigger_count--; +} + +// ---------------------------------------------------------------- +// returns true if trigger found + +bool +gr_oscope_guts::found_trigger () +{ + int mx = d_trigger_mode == gr_TRIG_MODE_STRIPCHART ? OUTPUT_RECORD_SIZE*SCHART_MULT : + OUTPUT_RECORD_SIZE; + + float prev_sample = d_buffer[d_trigger_channel][decr_bi(d_obi, mx)]; + float new_sample = d_buffer[d_trigger_channel][d_obi]; + + switch (d_trigger_mode){ + + case gr_TRIG_MODE_AUTO: //too many samples without a trigger + d_pre_trigger_count++; + if (d_pre_trigger_count > OUTPUT_RECORD_SIZE/2) return true; + + case gr_TRIG_MODE_NORM: //look for trigger + switch (d_trigger_slope){ + + case gr_TRIG_SLOPE_POS: //trigger point in pos slope? + if (new_sample < d_trigger_level || prev_sample >= d_trigger_level) return false; + break; + + case gr_TRIG_SLOPE_NEG: //trigger point in neg slope? + if (new_sample > d_trigger_level || prev_sample <= d_trigger_level) return false; + break; + } + + //calculate the trigger offset in % sample + d_trigger_off = (d_trigger_level - prev_sample)/(new_sample - prev_sample); + return true; + + case gr_TRIG_MODE_FREE: //free run mode, always trigger + d_trigger_off = 0; + return true; + + default: + assert (0); + return false; + } +} + +// ---------------------------------------------------------------- +// write output records (duh!) + +void +gr_oscope_guts::write_output_records () +{ + int mx; + + mx = d_trigger_mode == gr_TRIG_MODE_STRIPCHART ? + OUTPUT_RECORD_SIZE*SCHART_MULT : OUTPUT_RECORD_SIZE; + + // if the output queue if full, drop the data like its hot. + if (d_msgq->full_p()) + return; + // Build a message to hold the output records + gr_message_sptr msg = + gr_make_message(0, // msg type + d_nchannels, // arg1 for other side + mx, // arg2 for other side + ((d_nchannels * mx) + 1) * sizeof(float)); // sizeof payload + + float *out = (float *)msg->msg(); // get pointer to raw message buffer + + for (int ch = 0; ch < d_nchannels; ch++){ + // note that d_obi + 1 points at the oldest sample in the buffer + for (int i = 0; i < mx; i++){ + out[i] = d_buffer[ch][wrap_bi(d_obi + 1 + i, mx)]; + } + out += mx; + } + //Set the last sample as the trigger offset: + // The non gl scope sink will not look at this last sample. + // The gl scope sink will use this last sample as an offset. + out[0] = d_trigger_off; + d_msgq->handle(msg); // send the msg +} + +// ---------------------------------------------------------------- + +bool +gr_oscope_guts::set_update_rate (double update_rate) +{ + d_update_rate = std::min (std::max (1./10., update_rate), d_sample_rate); + update_rate_or_decimation_changed (); + return true; +} + +bool +gr_oscope_guts::set_decimation_count (int decimator_count) +{ + decimator_count = std::max (1, decimator_count); + d_decimator_count_init = decimator_count; + update_rate_or_decimation_changed (); + return true; +} + +bool +gr_oscope_guts::set_sample_rate(double sample_rate) +{ + d_sample_rate = sample_rate; + return set_update_rate(update_rate()); +} + + +void +gr_oscope_guts::update_rate_or_decimation_changed () +{ + d_hold_off_count_init = + (int) rint (d_sample_rate / d_update_rate / d_decimator_count_init); +} + +bool +gr_oscope_guts::set_trigger_channel (int channel) +{ + if (channel >= 0 && channel < d_nchannels){ + d_trigger_channel = channel; + trigger_changed (); + return true; + } + + return false; +} + +bool +gr_oscope_guts::set_trigger_mode (gr_trigger_mode mode) +{ + d_trigger_mode = mode; + trigger_changed (); + return true; +} + +bool +gr_oscope_guts::set_trigger_slope (gr_trigger_slope slope) +{ + d_trigger_slope = slope; + trigger_changed (); + return true; +} + +bool +gr_oscope_guts::set_trigger_level (double trigger_level) +{ + d_trigger_level = trigger_level; + trigger_changed (); + return true; +} + +bool +gr_oscope_guts::set_trigger_level_auto () +{ + // find the level 1/2 way between the min and the max + + float min_v = d_buffer[d_trigger_channel][0]; + float max_v = d_buffer[d_trigger_channel][0]; + + for (int i = 1; i < OUTPUT_RECORD_SIZE; i++){ + min_v = std::min (min_v, d_buffer[d_trigger_channel][i]); + max_v = std::max (max_v, d_buffer[d_trigger_channel][i]); + } + return set_trigger_level((min_v + max_v) * 0.5); +} + +bool +gr_oscope_guts::set_num_channels(int nchannels) +{ + if (nchannels > 0 && nchannels <= MAX_CHANNELS){ + d_nchannels = nchannels; + return true; + } + return false; +} + + +void +gr_oscope_guts::trigger_changed () +{ + enter_look_for_trigger (); +} + +// ACCESSORS + +int +gr_oscope_guts::num_channels () const +{ + return d_nchannels; +} + +double +gr_oscope_guts::sample_rate () const +{ + return d_sample_rate; +} + +double +gr_oscope_guts::update_rate () const +{ + return d_update_rate; +} + +int +gr_oscope_guts::get_decimation_count () const +{ + return d_decimator_count_init; +} + +int +gr_oscope_guts::get_trigger_channel () const +{ + return d_trigger_channel; +} + +gr_trigger_mode +gr_oscope_guts::get_trigger_mode () const +{ + return d_trigger_mode; +} + +gr_trigger_slope +gr_oscope_guts::get_trigger_slope () const +{ + return d_trigger_slope; +} + +double +gr_oscope_guts::get_trigger_level () const +{ + return d_trigger_level; +} + +int +gr_oscope_guts::get_samples_per_output_record () const +{ + int mx; + + mx = OUTPUT_RECORD_SIZE; + if (d_trigger_mode == gr_TRIG_MODE_STRIPCHART) + { + mx = OUTPUT_RECORD_SIZE*SCHART_MULT; + } + return mx; +} diff --git a/gnuradio-core/src/lib/io/gr_oscope_guts.h b/gnuradio-core/src/lib/io/gr_oscope_guts.h new file mode 100644 index 000000000..bc9513c7e --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_guts.h @@ -0,0 +1,123 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,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_OSCOPE_GUTS_H +#define INCLUDED_GR_OSCOPE_GUTS_H + +#include <gr_core_api.h> +#include <gr_trigger_mode.h> +#include <gr_msg_queue.h> + +/*! + * \brief guts of oscilloscope trigger and buffer module + * + * This module processes sets of samples provided the \p process_sample + * method. When appropriate given the updateRate, sampleRate and + * trigger conditions, process_sample will periodically write output + * records of captured data to output_fd. For each trigger event, + * nchannels records will be written. Each record consists of + * get_samples_per_output_record binary floats. The trigger instant + * occurs at the 1/2 way point in the buffer. Thus, output records + * consist of 50% pre-trigger data and 50% post-trigger data. + */ + +class GR_CORE_API gr_oscope_guts { +public: + static const int MAX_CHANNELS = 8; +private: + enum scope_state { HOLD_OFF, LOOK_FOR_TRIGGER, POST_TRIGGER }; + + int d_nchannels; // how many channels + gr_msg_queue_sptr d_msgq; // message queue we stuff output records into + gr_trigger_mode d_trigger_mode; + gr_trigger_slope d_trigger_slope; + int d_trigger_channel; // which channel to watch for trigger condition + double d_sample_rate; // input sample rate in Hz + double d_update_rate; // approx freq to produce an output record (Hz) + double d_trigger_level; + + int d_obi; // output buffer index + float *d_buffer[MAX_CHANNELS]; + + scope_state d_state; + int d_decimator_count; + int d_decimator_count_init; + int d_hold_off_count; + int d_hold_off_count_init; + int d_pre_trigger_count; + int d_post_trigger_count; + int d_post_trigger_count_init; + float d_trigger_off; //%sample trigger is off + + // NOT IMPLEMENTED + gr_oscope_guts (const gr_oscope_guts &rhs); // no copy constructor + gr_oscope_guts &operator= (const gr_oscope_guts &rhs); // no assignment operator + + void trigger_changed (); + void update_rate_or_decimation_changed (); + bool found_trigger (); // returns true if found + void write_output_records (); + + void enter_hold_off (); // called on state entry + void enter_look_for_trigger (); + void enter_post_trigger (); + +public: + // CREATORS + gr_oscope_guts (double sample_rate, gr_msg_queue_sptr msgq); + ~gr_oscope_guts (); + + // MANIPULATORS + + /*! + * \p channel_data points to nchannels float values. These are the values + * for each channel at this sample time. + */ + void process_sample (const float *channel_data); + + bool set_update_rate (double update_rate); + bool set_decimation_count (int decimation_count); + bool set_trigger_channel (int channel); + bool set_trigger_mode (gr_trigger_mode mode); + bool set_trigger_slope (gr_trigger_slope slope); + bool set_trigger_level (double trigger_level); + bool set_trigger_level_auto (); // set to 50% level + bool set_sample_rate(double sample_rate); + bool set_num_channels(int nchannels); + + + // ACCESSORS + int num_channels () const; + double sample_rate () const; + double update_rate () const; + int get_decimation_count () const; + int get_trigger_channel () const; + gr_trigger_mode get_trigger_mode () const; + gr_trigger_slope get_trigger_slope () const; + double get_trigger_level () const; + + // # of samples written to each output record. + int get_samples_per_output_record () const; +}; + +#endif /* INCLUDED_GR_OSCOPE_GUTS_H */ diff --git a/gnuradio-core/src/lib/io/gr_oscope_sink.i b/gnuradio-core/src/lib/io/gr_oscope_sink.i new file mode 100644 index 000000000..3d7072ed4 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_sink.i @@ -0,0 +1,77 @@ +/* -*- 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. + */ + +%include gr_trigger_mode.h + +// GR_SWIG_BLOCK_MAGIC(gr,oscope_sink_x) + +%ignore gr_oscope_sink_x; +class gr_oscope_sink_x : public gr_sync_block +{ + protected: + gr_oscope_sink_x (const std::string name, + gr_io_signature_sptr input_sig, + double sample_rate); + + public: + ~gr_oscope_sink_x (); + + bool set_update_rate (double update_rate); + bool set_decimation_count (int decimation_count); + bool set_trigger_channel (int channel); + bool set_trigger_mode (gr_trigger_mode mode); + bool set_trigger_slope (gr_trigger_slope slope); + bool set_trigger_level (double trigger_level); + bool set_trigger_level_auto (); // set to 50% level + bool set_sample_rate(double sample_rate); + + // ACCESSORS + int num_channels () const; + double sample_rate () const; + double update_rate () const; + int get_decimation_count () const; + int get_trigger_channel () const; + gr_trigger_mode get_trigger_mode () const; + gr_trigger_slope get_trigger_slope () const; + double get_trigger_level () const; + + // # of samples written to each output record. + int get_samples_per_output_record () const; +}; + +// ---------------------------------------------------------------- + +GR_SWIG_BLOCK_MAGIC(gr,oscope_sink_f) + +gr_oscope_sink_f_sptr +gr_make_oscope_sink_f (double sample_rate, gr_msg_queue_sptr msgq); + +class gr_oscope_sink_f : public gr_oscope_sink_x +{ +private: + gr_oscope_sink_f (double sample_rate, gr_msg_queue_sptr msgq); + +public: + ~gr_oscope_sink_f (); +}; + +// ---------------------------------------------------------------- diff --git a/gnuradio-core/src/lib/io/gr_oscope_sink_f.cc b/gnuradio-core/src/lib/io/gr_oscope_sink_f.cc new file mode 100644 index 000000000..493a25e81 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_sink_f.cc @@ -0,0 +1,78 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2004,2005,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_oscope_sink_f.h> +#include <gr_io_signature.h> +#include <gr_oscope_guts.h> + + +gr_oscope_sink_f_sptr +gr_make_oscope_sink_f (double sampling_rate, gr_msg_queue_sptr msgq) +{ + return gnuradio::get_initial_sptr(new gr_oscope_sink_f (sampling_rate, msgq)); +} + + +gr_oscope_sink_f::gr_oscope_sink_f (double sampling_rate, gr_msg_queue_sptr msgq) + : gr_oscope_sink_x ("oscope_sink_f", + gr_make_io_signature (1, gr_oscope_guts::MAX_CHANNELS, sizeof (float)), + sampling_rate), + d_msgq(msgq) +{ + d_guts = new gr_oscope_guts (d_sampling_rate, d_msgq); +} + + +bool +gr_oscope_sink_f::check_topology (int ninputs, int noutputs) +{ + return d_guts->set_num_channels(ninputs); +} + + +gr_oscope_sink_f::~gr_oscope_sink_f () +{ +} + +int +gr_oscope_sink_f::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + int ni = input_items.size (); + float tmp[gr_oscope_guts::MAX_CHANNELS]; + + for (int i = 0; i < noutput_items; i++){ + + // FIXME for now, copy the data. Fix later if reqd + for (int ch = 0; ch < ni; ch++) + tmp[ch] = ((const float *) input_items[ch])[i]; + + d_guts->process_sample (tmp); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/io/gr_oscope_sink_f.h b/gnuradio-core/src/lib/io/gr_oscope_sink_f.h new file mode 100644 index 000000000..8d434d2bc --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_sink_f.h @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2004,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_OSCOPE_SINK_F_H +#define INCLUDED_GR_OSCOPE_SINK_F_H + +#include <gr_core_api.h> +#include <gr_oscope_sink_x.h> +#include <gr_msg_queue.h> + +class gr_oscope_sink_f; +typedef boost::shared_ptr<gr_oscope_sink_x> gr_oscope_sink_f_sptr; + +GR_CORE_API gr_oscope_sink_f_sptr gr_make_oscope_sink_f (double sampling_rate, gr_msg_queue_sptr msgq); + + +/*! + * \brief Building block for python oscilloscope module. + * \ingroup sink_blk + * + * Accepts multiple float streams. + */ +class GR_CORE_API gr_oscope_sink_f : public gr_oscope_sink_x +{ +private: + friend GR_CORE_API gr_oscope_sink_f_sptr + gr_make_oscope_sink_f (double sampling_rate, gr_msg_queue_sptr msgq); + + gr_oscope_sink_f (double sampling_rate, gr_msg_queue_sptr msgq); + + gr_msg_queue_sptr d_msgq; + + public: + ~gr_oscope_sink_f (); + + 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); +}; + +#endif /* INCLUDED_GR_OSCOPE_SINK_F_H */ + diff --git a/gnuradio-core/src/lib/io/gr_oscope_sink_x.cc b/gnuradio-core/src/lib/io/gr_oscope_sink_x.cc new file mode 100644 index 000000000..9580dbf6a --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_sink_x.cc @@ -0,0 +1,156 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_oscope_sink_x.h> +#include <gr_io_signature.h> +#include <gr_oscope_guts.h> + + +gr_oscope_sink_x::gr_oscope_sink_x (const std::string name, + gr_io_signature_sptr input_sig, + double sampling_rate) + : gr_sync_block (name, input_sig, gr_make_io_signature (0, 0, 0)), + d_sampling_rate (sampling_rate), d_guts (0) +{ +} + +gr_oscope_sink_x::~gr_oscope_sink_x () +{ + delete d_guts; +} + +// ---------------------------------------------------------------- + +bool +gr_oscope_sink_x::set_update_rate (double update_rate) +{ + return d_guts->set_update_rate (update_rate); +} + +bool +gr_oscope_sink_x::set_decimation_count (int decimation_count) +{ + return d_guts->set_decimation_count (decimation_count); +} + +bool +gr_oscope_sink_x::set_trigger_channel (int channel) +{ + return d_guts->set_trigger_channel (channel); +} + +bool +gr_oscope_sink_x::set_trigger_mode (gr_trigger_mode mode) +{ + return d_guts->set_trigger_mode (mode); +} + +bool +gr_oscope_sink_x::set_trigger_slope (gr_trigger_slope slope) +{ + return d_guts->set_trigger_slope (slope); +} + +bool +gr_oscope_sink_x::set_trigger_level (double trigger_level) +{ + return d_guts->set_trigger_level (trigger_level); +} + + +bool +gr_oscope_sink_x::set_trigger_level_auto () +{ + return d_guts->set_trigger_level_auto (); +} + +bool +gr_oscope_sink_x::set_sample_rate (double sample_rate) +{ + return d_guts->set_sample_rate (sample_rate); +} + +bool +gr_oscope_sink_x::set_num_channels (int nchannels) +{ + return d_guts->set_num_channels (nchannels); +} + +// ACCESSORS + +int +gr_oscope_sink_x::num_channels () const +{ + return d_guts->num_channels (); +} + +double +gr_oscope_sink_x::sample_rate () const +{ + return d_guts->sample_rate (); +} + +double +gr_oscope_sink_x::update_rate () const +{ + return d_guts->update_rate (); +} + +int +gr_oscope_sink_x::get_decimation_count () const +{ + return d_guts->get_decimation_count (); +} + +int +gr_oscope_sink_x::get_trigger_channel () const +{ + return d_guts->get_trigger_channel (); +} + +gr_trigger_mode +gr_oscope_sink_x::get_trigger_mode () const +{ + return d_guts->get_trigger_mode (); +} + +gr_trigger_slope +gr_oscope_sink_x::get_trigger_slope () const +{ + return d_guts->get_trigger_slope (); +} + +double +gr_oscope_sink_x::get_trigger_level () const +{ + return d_guts->get_trigger_level (); +} + +int +gr_oscope_sink_x::get_samples_per_output_record () const +{ + return d_guts->get_samples_per_output_record (); +} diff --git a/gnuradio-core/src/lib/io/gr_oscope_sink_x.h b/gnuradio-core/src/lib/io/gr_oscope_sink_x.h new file mode 100644 index 000000000..153d0937a --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_sink_x.h @@ -0,0 +1,77 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,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_OSCOPE_SINK_X_H +#define INCLUDED_GR_OSCOPE_SINK_X_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_trigger_mode.h> + +class gr_oscope_guts; + +/*! + * \brief Abstract class for python oscilloscope module. + * \ingroup sink_blk + * + * Don't instantiate this. Use gr_oscope_sink_f or gr_oscope_sink_c instead. + */ +class GR_CORE_API gr_oscope_sink_x : public gr_sync_block +{ +protected: + double d_sampling_rate; + gr_oscope_guts *d_guts; + + gr_oscope_sink_x (const std::string name, + gr_io_signature_sptr input_sig, + double sampling_rate); + +public: + ~gr_oscope_sink_x (); + + bool set_update_rate (double update_rate); + bool set_decimation_count (int decimation_count); + bool set_trigger_channel (int channel); + bool set_trigger_mode (gr_trigger_mode mode); + bool set_trigger_slope (gr_trigger_slope slope); + bool set_trigger_level (double trigger_level); + bool set_trigger_level_auto (); // set to 50% level + bool set_sample_rate(double sample_rate); + bool set_num_channels (int nchannels); + + + // ACCESSORS + int num_channels () const; + double sample_rate () const; + double update_rate () const; + int get_decimation_count () const; + int get_trigger_channel () const; + gr_trigger_mode get_trigger_mode () const; + gr_trigger_slope get_trigger_slope () const; + double get_trigger_level () const; + + // # of samples written to each output record. + int get_samples_per_output_record () const; + +}; + +#endif /* INCLUDED_GR_OSCOPE_SINK_X_H */ diff --git a/gnuradio-core/src/lib/io/gr_pdu.cc b/gnuradio-core/src/lib/io/gr_pdu.cc new file mode 100644 index 000000000..302fd7b9b --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_pdu.cc @@ -0,0 +1,79 @@ +/* -*- 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 <gr_pdu.h> + +size_t +gr_pdu_itemsize(gr_pdu_vector_type type){ + switch(type){ + case pdu_byte: + return 1; + case pdu_float: + return sizeof(float); + case pdu_complex: + return sizeof(gr_complex); + default: + throw std::runtime_error("bad type!"); + } +} + +bool +gr_pdu_type_matches(gr_pdu_vector_type type, pmt::pmt_t v){ + switch(type){ + case pdu_byte: + return pmt::pmt_is_u8vector(v); + case pdu_float: + return pmt::pmt_is_f32vector(v); + case pdu_complex: + return pmt::pmt_is_c32vector(v); + default: + throw std::runtime_error("bad type!"); + } +} + +pmt::pmt_t +gr_pdu_make_vector(gr_pdu_vector_type type, const uint8_t* buf, size_t items){ + switch(type){ + case pdu_byte: + return pmt::pmt_init_u8vector(items, buf); + case pdu_float: + return pmt::pmt_init_f32vector(items, (const float*)buf); + case pdu_complex: + return pmt::pmt_init_c32vector(items, (const gr_complex*)buf); + default: + throw std::runtime_error("bad type!"); + } +} + +gr_pdu_vector_type type_from_pmt(pmt::pmt_t vector){ + if(pmt_is_u8vector(vector)) + return pdu_byte; + if(pmt_is_f32vector(vector)) + return pdu_float; + if(pmt_is_c32vector(vector)) + return pdu_complex; + throw std::runtime_error("bad type!"); +} diff --git a/gnuradio-core/src/lib/io/gr_pdu.h b/gnuradio-core/src/lib/io/gr_pdu.h new file mode 100644 index 000000000..a5ae87db7 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_pdu.h @@ -0,0 +1,39 @@ +/* -*- 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 GR_PDU_H +#define GR_PDU_H + +#include <gr_complex.h> +#include <gruel/pmt.h> + +#define pdu_port_id pmt::mp("pdus") +#define pdu_length_tag pmt::mp("pdu_length") + +enum gr_pdu_vector_type { pdu_byte, pdu_float, pdu_complex }; + +size_t gr_pdu_itemsize(gr_pdu_vector_type type); +bool gr_pdu_type_matches(gr_pdu_vector_type type, pmt::pmt_t v); +pmt::pmt_t gr_pdu_make_vector(gr_pdu_vector_type type, const uint8_t* buf, size_t items); +gr_pdu_vector_type type_from_pmt(pmt::pmt_t vector); + +#endif diff --git a/gnuradio-core/src/lib/io/gr_pdu.i b/gnuradio-core/src/lib/io/gr_pdu.i new file mode 100644 index 000000000..ada3a63a7 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_pdu.i @@ -0,0 +1,30 @@ +/* -*- 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.
+ */
+
+%{
+#include <gr_pdu.h>
+%}
+
+enum gr_pdu_vector_type { pdu_byte, pdu_float, pdu_complex };
+
+
+
diff --git a/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc new file mode 100644 index 000000000..5c319dc39 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.cc @@ -0,0 +1,132 @@ +/* -*- 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 <gr_pdu_to_tagged_stream.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 <string.h> + + +// public constructor that returns a shared_ptr + +gr_pdu_to_tagged_stream_sptr +gr_make_pdu_to_tagged_stream(gr_pdu_vector_type t) +{ + return gnuradio::get_initial_sptr(new gr_pdu_to_tagged_stream(t)); +} + +gr_pdu_to_tagged_stream::gr_pdu_to_tagged_stream (gr_pdu_vector_type t) + : gr_sync_block("pdu_to_tagged_stream", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(1, 1, gr_pdu_itemsize(t))), + d_vectortype(t), d_itemsize(gr_pdu_itemsize(t)) +{ + message_port_register_in(pdu_port_id); +} + +gr_pdu_to_tagged_stream::~gr_pdu_to_tagged_stream() +{ +} + +int +gr_pdu_to_tagged_stream::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + char *out = (char *) output_items[0]; + int nout = 0; + + // if we have remaining output, send it + if(d_remain.size() > 0){ + nout = std::min((size_t)d_remain.size()/d_itemsize, (size_t)noutput_items); + memcpy(out, &d_remain[0], nout*d_itemsize); + d_remain.erase( d_remain.begin(), d_remain.begin()+nout); + noutput_items -= nout; + out += nout*d_itemsize; + } + + // if we have space for at least one item output as much as we can + if(noutput_items > 0){ + + // grab a message if one exists + //pmt::pmt_t msg( delete_head_nowait( pdu_port_id ) ); + pmt::pmt_t msg( delete_head_blocking( pdu_port_id ) ); + if(msg.get() == NULL ){ + return nout; + } + + // make sure type is valid + if(!pmt::pmt_is_pair(msg)){ + throw std::runtime_error("received a malformed pdu message!"); + } + +// printf("got a msg\n"); +// pmt::pmt_print(msg); + + // grab the components of the pdu message + pmt::pmt_t meta(pmt::pmt_car(msg)); // make sure this is NIL || Dict ? + pmt::pmt_t vect(pmt::pmt_cdr(msg)); // make sure this is a vector? + + // compute offset for output tag + uint64_t offset = nitems_written(0) + nout; + + // add a tag for pdu length + add_item_tag(0, offset, pdu_length_tag, pmt::pmt_from_long( pmt::pmt_length(vect) ), pmt::mp(alias())); + + // if we recieved metadata add it as tags + if( !pmt_eq(meta, pmt::PMT_NIL) ){ + pmt::pmt_t pair(pmt::pmt_dict_keys( meta )); + while( !pmt_eq(pair, pmt::PMT_NIL) ){ + pmt::pmt_t k(pmt::pmt_cdr(pair)); + pmt::pmt_t v(pmt::pmt_dict_ref(meta, k, pmt::PMT_NIL)); + add_item_tag(0, offset, k, v, pmt::mp(alias())); + } + } + + // copy vector output + size_t ncopy = std::min((size_t)noutput_items, (size_t)pmt::pmt_length(vect)); + size_t nsave = pmt::pmt_length(vect) - ncopy; + + // copy output + size_t io(0); + nout += ncopy; + memcpy(out, pmt_uniform_vector_elements(vect,io), ncopy*d_itemsize); + + // save leftover items if needed for next work call + if(nsave > 0){ + d_remain.resize(nsave*d_itemsize, 0); + memcpy(&d_remain[0], pmt_uniform_vector_elements(vect,ncopy), nsave*d_itemsize); + } + + } + + return nout; +} diff --git a/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.h b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.h new file mode 100644 index 000000000..3105a3d38 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.h @@ -0,0 +1,63 @@ +/* -*- 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_GR_PDU_TO_TAGGED_STREAM_H +#define INCLUDED_GR_PDU_TO_TAGGED_STREAM_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_message.h> +#include <gr_msg_queue.h> +#include <gr_pdu.h> + +class gr_pdu_to_tagged_stream; +typedef boost::shared_ptr<gr_pdu_to_tagged_stream> gr_pdu_to_tagged_stream_sptr; + +GR_CORE_API gr_pdu_to_tagged_stream_sptr gr_make_pdu_to_tagged_stream (gr_pdu_vector_type t); + +/*! + * \brief Turn received messages into a stream + * \ingroup source_blk + */ +class GR_CORE_API gr_pdu_to_tagged_stream : public gr_sync_block +{ + private: + gr_pdu_vector_type d_vectortype; + size_t d_itemsize; + std::vector<uint8_t> d_remain; + + friend GR_CORE_API gr_pdu_to_tagged_stream_sptr + gr_make_pdu_to_tagged_stream(gr_pdu_vector_type t); + + protected: + gr_pdu_to_tagged_stream (gr_pdu_vector_type t); + + public: + ~gr_pdu_to_tagged_stream (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + +}; + +#endif /* INCLUDED_GR_PDU_TO_TAGGED_SOURCE_H */ diff --git a/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.i b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.i new file mode 100644 index 000000000..ec760b309 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_pdu_to_tagged_stream.i @@ -0,0 +1,31 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,pdu_to_tagged_stream); + +%{ +#include <gr_pdu_to_tagged_stream.h> +%} + +%include <gr_pdu_to_tagged_stream.h> + + diff --git a/gnuradio-core/src/lib/io/gr_socket_pdu.cc b/gnuradio-core/src/lib/io/gr_socket_pdu.cc new file mode 100644 index 000000000..bb374b300 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_socket_pdu.cc @@ -0,0 +1,157 @@ +/* -*- 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 <gr_socket_pdu.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 <string.h> +#include <iostream> +#include <gr_pdu.h> +#include <boost/format.hpp> + +// public constructor that returns a shared_ptr +gr_socket_pdu_sptr +gr_make_socket_pdu (std::string type, std::string addr, std::string port, int MTU) +{ + return gnuradio::get_initial_sptr(new gr_socket_pdu(type,addr,port,MTU)); +} + +gr_socket_pdu::gr_socket_pdu (std::string type, std::string addr, std::string port, int MTU) + : gr_stream_pdu_base(MTU) +{ + + if( (type == "TCP_SERVER") || (type == "TCP_CLIENT")){ + boost::asio::ip::tcp::resolver resolver(_io_service); + boost::asio::ip::tcp::resolver::query query(boost::asio::ip::tcp::v4(), addr, port); + _tcp_endpoint = *resolver.resolve(query); + } + if( (type == "UDP_SERVER") || (type == "UDP_CLIENT")){ + boost::asio::ip::udp::resolver resolver(_io_service); + boost::asio::ip::udp::resolver::query query(boost::asio::ip::udp::v4(), addr, port); + if( (type == "UDP_SERVER") ){ + _udp_endpoint = *resolver.resolve(query); + } else { + _udp_endpoint_other = *resolver.resolve(query); + } + } + + // register ports + message_port_register_out(pmt::mp("pdus")); + message_port_register_in(pmt::mp("pdus")); + + // set up socketry + if (type == "TCP_SERVER"){ + _acceptor_tcp.reset(new boost::asio::ip::tcp::acceptor(_io_service, _tcp_endpoint)); + _acceptor_tcp->set_option(boost::asio::ip::tcp::acceptor::reuse_address(true)); + start_tcp_accept(); + // bind tcp server send handler + set_msg_handler(pmt::mp("pdus"), boost::bind(&gr_socket_pdu::tcp_server_send, this, _1)); + } else if(type =="TCP_CLIENT"){ + boost::system::error_code error = boost::asio::error::host_not_found; + _tcp_socket.reset(new boost::asio::ip::tcp::socket(_io_service)); + _tcp_socket->connect(_tcp_endpoint, error); + if(error){ + throw boost::system::system_error(error); + } + set_msg_handler(pmt::mp("pdus"), boost::bind(&gr_socket_pdu::tcp_client_send, this, _1)); + _tcp_socket->async_read_some( + boost::asio::buffer(rxbuf), + boost::bind(&gr_socket_pdu::handle_tcp_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); + + } else if(type =="UDP_SERVER"){ + _udp_socket.reset(new boost::asio::ip::udp::socket(_io_service, _udp_endpoint)); + _udp_socket->async_receive_from( boost::asio::buffer(rxbuf), _udp_endpoint_other, + boost::bind(&gr_socket_pdu::handle_udp_read, this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + set_msg_handler(pmt::mp("pdus"), boost::bind(&gr_socket_pdu::udp_send, this, _1)); + } else if(type =="UDP_CLIENT"){ + _udp_socket.reset(new boost::asio::ip::udp::socket(_io_service, _udp_endpoint)); + _udp_socket->async_receive_from( boost::asio::buffer(rxbuf), _udp_endpoint_other, + boost::bind(&gr_socket_pdu::handle_udp_read, this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + set_msg_handler(pmt::mp("pdus"), boost::bind(&gr_socket_pdu::udp_send, this, _1)); + } else { + throw std::runtime_error("unknown socket type!"); + } + + // start thread for io_service + d_thread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&gr_socket_pdu::run_io_service, this))); + d_started = true; +} + +void tcp_connection::handle_read(const boost::system::error_code& error/*error*/, size_t bytes_transferred) + { + if(!error) + { + pmt::pmt_t vector = pmt::pmt_init_u8vector(bytes_transferred, (const uint8_t*)&buf[0]); + pmt::pmt_t pdu = pmt::pmt_cons( pmt::PMT_NIL, vector); + + d_block->message_port_pub( pmt::mp("pdus"), pdu ); + + socket_.async_read_some( + boost::asio::buffer(buf), + boost::bind(&tcp_connection::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); + + } else { + std::cout << "error occurred\n"; + } + + } + + +void gr_socket_pdu::tcp_server_send(pmt::pmt_t msg){ + pmt::pmt_t vector = pmt::pmt_cdr(msg); + for(size_t i=0; i<d_tcp_connections.size(); i++){ + d_tcp_connections[i]->send(vector); + } +} + +void gr_socket_pdu::tcp_client_send(pmt::pmt_t msg){ + pmt::pmt_t vector = pmt::pmt_cdr(msg); + size_t len = pmt::pmt_length(vector); + size_t offset(0); + boost::array<char, 10000> txbuf; + memcpy(&txbuf[0], pmt::pmt_uniform_vector_elements(vector, offset), len); + _tcp_socket->send(boost::asio::buffer(txbuf,len)); +} + +void gr_socket_pdu::udp_send(pmt::pmt_t msg){ + pmt::pmt_t vector = pmt::pmt_cdr(msg); + size_t len = pmt::pmt_length(vector); + size_t offset(0); + boost::array<char, 10000> txbuf; + memcpy(&txbuf[0], pmt::pmt_uniform_vector_elements(vector, offset), len); + if(_udp_endpoint_other.address().to_string() != "0.0.0.0") + _udp_socket->send_to(boost::asio::buffer(txbuf,len), _udp_endpoint_other); +} diff --git a/gnuradio-core/src/lib/io/gr_socket_pdu.h b/gnuradio-core/src/lib/io/gr_socket_pdu.h new file mode 100644 index 000000000..2fedb317d --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_socket_pdu.h @@ -0,0 +1,203 @@ +/* -*- 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_GR_SOCKET_PDU_H +#define INCLUDED_GR_SOCKET_PDU_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_message.h> +#include <gr_msg_queue.h> +#include <gr_stream_pdu_base.h> +#include <boost/array.hpp> +#include <boost/asio.hpp> +#include <iostream> + +class gr_socket_pdu; +typedef boost::shared_ptr<gr_socket_pdu> gr_socket_pdu_sptr; + +GR_CORE_API gr_socket_pdu_sptr gr_make_socket_pdu (std::string type, std::string addr, std::string port, int MTU=10000); + +class tcp_connection + : public boost::enable_shared_from_this<tcp_connection> +{ +public: + typedef boost::shared_ptr<tcp_connection> pointer; + gr_socket_pdu *d_block; + boost::array<char, 10000> buf; + + static pointer create(boost::asio::io_service& io_service) + { + return pointer(new tcp_connection(io_service)); + } + + boost::asio::ip::tcp::socket& socket() + { + return socket_; + } + + void start(gr_socket_pdu* parent) + { + d_block = parent; +// message_ = "connected to gr_socket_pdu\n"; +// boost::asio::async_write(socket_, boost::asio::buffer(message_), +// boost::bind(&tcp_connection::handle_write, shared_from_this(), +// boost::asio::placeholders::error, +// boost::asio::placeholders::bytes_transferred)); + + socket_.async_read_some( + boost::asio::buffer(buf), + boost::bind(&tcp_connection::handle_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); + } + void send(pmt::pmt_t vector){ + size_t len = pmt::pmt_length(vector); + size_t offset(0); + boost::array<char, 10000> txbuf; + memcpy(&txbuf[0], pmt::pmt_uniform_vector_elements(vector, offset), len); + boost::asio::async_write(socket_, boost::asio::buffer(txbuf, len), + boost::bind(&tcp_connection::handle_write, shared_from_this(), + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + } + + ~tcp_connection(){ +// std::cout << "tcp_connection destroyed\n"; + } + +private: + tcp_connection(boost::asio::io_service& io_service) + : socket_(io_service) + { + } + + void handle_read(const boost::system::error_code& error/*error*/, size_t bytes_transferred); + + void handle_write(const boost::system::error_code& /*error*/, + size_t /*bytes_transferred*/) + { + } + + boost::asio::ip::tcp::socket socket_; + std::string message_; +}; + + +/*! + * \brief Gather received items into messages and insert into msgq + * \ingroup sink_blk + */ +class GR_CORE_API gr_socket_pdu : public gr_stream_pdu_base +{ + private: + friend GR_CORE_API gr_socket_pdu_sptr + gr_make_socket_pdu(std::string type, std::string addr, std::string port, int MTU); + + boost::asio::io_service _io_service; + + boost::array<char, 10000> rxbuf; + + // tcp specific + boost::asio::ip::tcp::endpoint _tcp_endpoint; + + // specific to tcp server + boost::shared_ptr<boost::asio::ip::tcp::acceptor> _acceptor_tcp; + std::vector<tcp_connection::pointer> d_tcp_connections; + void tcp_server_send(pmt::pmt_t msg); + void tcp_client_send(pmt::pmt_t msg); + void udp_send(pmt::pmt_t msg); + + // specific to tcp client + boost::shared_ptr<boost::asio::ip::tcp::socket> _tcp_socket; + + // specific to udp client/server + boost::asio::ip::udp::endpoint _udp_endpoint; + boost::asio::ip::udp::endpoint _udp_endpoint_other; + boost::shared_ptr<boost::asio::ip::udp::socket> _udp_socket; + + void handle_receive(const boost::system::error_code& error, std::size_t ){ + } + + void start_tcp_accept(){ + tcp_connection::pointer new_connection = + tcp_connection::create(_acceptor_tcp->get_io_service()); + + _acceptor_tcp->async_accept(new_connection->socket(), + boost::bind(&gr_socket_pdu::handle_tcp_accept, this, new_connection, + boost::asio::placeholders::error)); + } + + void handle_tcp_accept(tcp_connection::pointer new_connection, const boost::system::error_code& error){ + if (!error) + { + new_connection->start(this); + d_tcp_connections.push_back(new_connection); + start_tcp_accept(); + } else { + std::cout << error << std::endl; + } + } + + void run_io_service(){ + _io_service.run(); + } + + void handle_udp_read(const boost::system::error_code& error/*error*/, size_t bytes_transferred){ + if(!error){ + pmt::pmt_t vector = pmt::pmt_init_u8vector(bytes_transferred, (const uint8_t*)&rxbuf[0]); + pmt::pmt_t pdu = pmt::pmt_cons( pmt::PMT_NIL, vector); + + message_port_pub( pmt::mp("pdus"), pdu ); + + _udp_socket->async_receive_from( boost::asio::buffer(rxbuf), _udp_endpoint_other, + boost::bind(&gr_socket_pdu::handle_udp_read, this, + boost::asio::placeholders::error, + boost::asio::placeholders::bytes_transferred)); + } else { + throw boost::system::system_error(error); +// std::cout << "error occurred\n"; + } + } + void handle_tcp_read(const boost::system::error_code& error/*error*/, size_t bytes_transferred){ + if(!error) + { + pmt::pmt_t vector = pmt::pmt_init_u8vector(bytes_transferred, (const uint8_t*)&rxbuf[0]); + pmt::pmt_t pdu = pmt::pmt_cons( pmt::PMT_NIL, vector); + + message_port_pub( pmt::mp("pdus"), pdu ); + + _tcp_socket->async_read_some( + boost::asio::buffer(rxbuf), + boost::bind(&gr_socket_pdu::handle_tcp_read, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); + + } else { + //std::cout << "error occurred\n"; + throw boost::system::system_error(error); + } + } + + protected: + gr_socket_pdu (std::string type, std::string addr, std::string port, int MTU=10000); + public: + ~gr_socket_pdu () {} +}; + +#endif /* INCLUDED_GR_TUNTAP_PDU_H */ diff --git a/gnuradio-core/src/lib/io/gr_socket_pdu.i b/gnuradio-core/src/lib/io/gr_socket_pdu.i new file mode 100644 index 000000000..3e20b63e2 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_socket_pdu.i @@ -0,0 +1,33 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,socket_pdu); + +%ignore tcp_connection; + +%{ +#include <gr_socket_pdu.h> +%} + +%include "gr_stream_pdu_base.h" +%include "gr_socket_pdu.h" + diff --git a/gnuradio-core/src/lib/io/gr_stream_pdu_base.cc b/gnuradio-core/src/lib/io/gr_stream_pdu_base.cc new file mode 100644 index 000000000..7250c33e5 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_stream_pdu_base.cc @@ -0,0 +1,123 @@ +/* -*- 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 <ciso646> +#include <gr_stream_pdu_base.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 <string.h> +#include <iostream> +#include <gr_pdu.h> +#include <boost/asio.hpp> +#include <boost/format.hpp> + +#ifdef HAVE_IO_H +#include <io.h> +#endif + +static const long timeout_us = 100*1000; //100ms + +gr_stream_pdu_base::gr_stream_pdu_base (int MTU) + : gr_sync_block("stream_pdu_base", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(0, 0, 0)), + d_finished(false), d_started(false), d_fd(-1) +{ + // reserve space for rx buffer + d_rxbuf.resize(MTU,0); +} + +gr_stream_pdu_base::~gr_stream_pdu_base() +{ + stop_rxthread(); +} + +void gr_stream_pdu_base::stop_rxthread(){ + d_finished = true; + if(d_started){ + d_thread->interrupt(); + d_thread->join(); + } + } + +void gr_stream_pdu_base::start_rxthread(pmt::pmt_t _rxport){ + rxport = _rxport; + d_thread = boost::shared_ptr<boost::thread>(new boost::thread(boost::bind(&gr_stream_pdu_base::run, this))); + d_started = true; + } + +void gr_stream_pdu_base::run(){ + while(!d_finished) { + if(not wait_ready()){ continue; } + const int result = read( d_fd, &d_rxbuf[0], d_rxbuf.size() ); + if(result <= 0){ throw std::runtime_error("gr_stream_pdu_base, bad socket read!"); } + pmt::pmt_t vector = pmt::pmt_init_u8vector(result, &d_rxbuf[0]); + pmt::pmt_t pdu = pmt::pmt_cons( pmt::PMT_NIL, vector); + message_port_pub(rxport, pdu); + } +} + +void gr_stream_pdu_base::send(pmt::pmt_t msg){ + pmt::pmt_t vector = pmt::pmt_cdr(msg); + size_t offset(0); + size_t itemsize(gr_pdu_itemsize(type_from_pmt(vector))); + int len( pmt::pmt_length(vector)*itemsize ); + + const int rv = write(d_fd, pmt::pmt_uniform_vector_elements(vector, offset), len); + if(rv != len){ + std::cerr << boost::format("WARNING: gr_stream_pdu_base::send(pdu) write failed! (d_fd=%d, len=%d, rv=%d)") + % d_fd % len % rv << std::endl; + } +} + +int +gr_stream_pdu_base::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + throw std::runtime_error("should not be called.\n"); + return 0; +} + +bool gr_stream_pdu_base::wait_ready(){ + //setup timeval for timeout + timeval tv; + tv.tv_sec = 0; + tv.tv_usec = timeout_us; + + //setup rset for timeout + fd_set rset; + FD_ZERO(&rset); + FD_SET(d_fd, &rset); + + //call select with timeout on receive socket + return ::select(d_fd+1, &rset, NULL, NULL, &tv) > 0; +} diff --git a/gnuradio-core/src/lib/io/gr_stream_pdu_base.h b/gnuradio-core/src/lib/io/gr_stream_pdu_base.h new file mode 100644 index 000000000..35bacf523 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_stream_pdu_base.h @@ -0,0 +1,59 @@ +/* -*- 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_GR_STREAM_PDU_BASE_H +#define INCLUDED_GR_STREAM_PDU_BASE_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_message.h> +#include <gr_msg_queue.h> + +/*! + * \brief Gather received items into messages and insert into msgq + * \ingroup sink_blk + */ +class GR_CORE_API gr_stream_pdu_base : public gr_sync_block +{ + public: + boost::shared_ptr<boost::thread> d_thread; + bool d_finished; + bool d_started; + std::vector<uint8_t> d_rxbuf; + void run(); + int d_fd; + gr_stream_pdu_base (int MTU=10000); + ~gr_stream_pdu_base (); + void send(pmt::pmt_t msg); + bool wait_ready(); + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + void start_rxthread(pmt::pmt_t _rxport); + void stop_rxthread(); + private: + pmt::pmt_t rxport; +}; + +typedef boost::shared_ptr<gr_stream_pdu_base> gr_stream_pdu_base_sptr; + +#endif /* INCLUDED_GR_TUNTAP_PDU_H */ diff --git a/gnuradio-core/src/lib/io/gr_tagged_file_sink.cc b/gnuradio-core/src/lib/io/gr_tagged_file_sink.cc new file mode 100644 index 000000000..6d642088e --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_tagged_file_sink.cc @@ -0,0 +1,216 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_tagged_file_sink.h> +#include <gr_io_signature.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdexcept> +#include <iostream> + +#ifdef HAVE_IO_H +#include <io.h> +#endif + +#ifdef O_BINARY +#define OUR_O_BINARY O_BINARY +#else +#define OUR_O_BINARY 0 +#endif + +// should be handled via configure +#ifdef O_LARGEFILE +#define OUR_O_LARGEFILE O_LARGEFILE +#else +#define OUR_O_LARGEFILE 0 +#endif + + +gr_tagged_file_sink::gr_tagged_file_sink (size_t itemsize, double samp_rate) + : gr_sync_block ("tagged_file_sink", + gr_make_io_signature (1, 1, itemsize), + gr_make_io_signature (0, 0, 0)), + d_itemsize (itemsize), d_n(0), d_sample_rate(samp_rate) +{ + d_state = NOT_IN_BURST; + d_last_N = 0; + d_timeval = 0; +} + +gr_tagged_file_sink_sptr +gr_make_tagged_file_sink (size_t itemsize, double samp_rate) +{ + return gnuradio::get_initial_sptr(new gr_tagged_file_sink (itemsize, samp_rate)); +} + +gr_tagged_file_sink::~gr_tagged_file_sink () +{ +} + +int +gr_tagged_file_sink::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + char *inbuf = (char *) input_items[0]; + + 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 + + std::vector<gr_tag_t> all_tags; + get_tags_in_range(all_tags, 0, start_N, end_N); + + std::sort(all_tags.begin(), all_tags.end(), gr_tag_t::offset_compare); + + std::vector<gr_tag_t>::iterator vitr = all_tags.begin(); + + int idx = 0, idx_stop = 0; + while(idx < noutput_items) { + if(d_state == NOT_IN_BURST) { + while(vitr != all_tags.end()) { + if((pmt::pmt_eqv((*vitr).key, bkey)) && + pmt::pmt_is_true((*vitr).value)) { + + uint64_t N = (*vitr).offset; + idx = (int)(N - start_N); + + //std::cout << std::endl << "Found start of burst: " + // << idx << ", " << N << std::endl; + + // Find time burst occurred by getting latest time tag and extrapolating + // 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")); + if(time_tags.size() > 0) { + const gr_tag_t tag = time_tags[time_tags.size()-1]; + + uint64_t time_nitems = tag.offset; + + // 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)); + double tfrac = pmt::pmt_to_double(pmt::pmt_tuple_ref(time, 1)); + + // Get new time from last time tag + difference in time to when + // burst tag occured based on the sample rate + double delta = (double)(N - time_nitems) / d_sample_rate; + d_timeval = (double)tsecs + tfrac + delta; + + //std::cout.setf(std::ios::fixed, std::ios::floatfield); + //std::cout.precision(8); + //std::cout << "Time found: " << (double)tsecs + tfrac << std::endl; + //std::cout << " time: " << d_timeval << std::endl; + //std::cout << " time at N = " << time_nitems << " burst N = " << N << std::endl; + } + else { + // if no time tag, use last seen tag and update time based on + // sample rate of the block + d_timeval += (double)(N - d_last_N) / d_sample_rate; + //std::cout << "Time not found" << std::endl; + //std::cout << " time: " << d_timeval << std::endl; + } + d_last_N = N; + + std::stringstream filename; + filename.setf(std::ios::fixed, std::ios::floatfield); + filename.precision(8); + filename << "file" << unique_id() << "_" << d_n << "_" << d_timeval << ".dat"; + d_n++; + + int fd; + if ((fd = ::open (filename.str().c_str(), + O_WRONLY|O_CREAT|O_TRUNC|OUR_O_LARGEFILE|OUR_O_BINARY, + 0664)) < 0){ + perror (filename.str().c_str()); + return -1; + } + + // FIXME: + //if ((d_handle = fdopen (fd, d_is_binary ? "wb" : "w")) == NULL){ + if ((d_handle = fdopen (fd, "wb")) == NULL){ + perror (filename.str().c_str()); + ::close(fd); // don't leak file descriptor if fdopen fails. + } + + //std::cout << "Created new file: " << filename.str() << std::endl; + + d_state = IN_BURST; + break; + } + + vitr++; + } + if(d_state == NOT_IN_BURST) + return noutput_items; + } + else { // In burst + while(vitr != all_tags.end()) { + if((pmt::pmt_eqv((*vitr).key, bkey)) && + pmt::pmt_is_false((*vitr).value)) { + uint64_t N = (*vitr).offset; + idx_stop = (int)N - start_N; + + //std::cout << "Found end of burst: " + // << idx_stop << ", " << N << std::endl; + + int count = fwrite (&inbuf[d_itemsize*idx], d_itemsize, + idx_stop-idx, d_handle); + if (count == 0) { + if(ferror(d_handle)) { + perror("gr_tagged_file_sink: error writing file"); + } + } + idx = idx_stop; + d_state = NOT_IN_BURST; + vitr++; + fclose(d_handle); + break; + } + else { + vitr++; + } + } + if(d_state == IN_BURST) { + int count = fwrite (&inbuf[d_itemsize*idx], d_itemsize, + noutput_items-idx, d_handle); + if (count == 0) { + if(ferror(d_handle)) { + perror("gr_tagged_file_sink: error writing file"); + } + } + idx = noutput_items; + } + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/io/gr_tagged_file_sink.h b/gnuradio-core/src/lib/io/gr_tagged_file_sink.h new file mode 100644 index 000000000..d6f931a67 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_tagged_file_sink.h @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_TAGGED_FILE_SINK_H +#define INCLUDED_GR_TAGGED_FILE_SINK_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <cstdio> // for FILE + +class gr_tagged_file_sink; +typedef boost::shared_ptr<gr_tagged_file_sink> gr_tagged_file_sink_sptr; + +GR_CORE_API gr_tagged_file_sink_sptr gr_make_tagged_file_sink (size_t itemsize, + double samp_rate); + +/*! + * \brief Write stream to file descriptor. + * \ingroup sink_blk + */ + +class GR_CORE_API gr_tagged_file_sink : public gr_sync_block +{ + friend GR_CORE_API gr_tagged_file_sink_sptr gr_make_tagged_file_sink (size_t itemsize, + double samp_rate); + + private: + enum { + NOT_IN_BURST = 0, + IN_BURST + }; + + size_t d_itemsize; + int d_state; + FILE *d_handle; + int d_n; + double d_sample_rate; + uint64_t d_last_N; + double d_timeval; + + protected: + gr_tagged_file_sink (size_t itemsize, double samp_rate); + + public: + ~gr_tagged_file_sink (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_TAGGED_FILE_SINK_H */ diff --git a/gnuradio-core/src/lib/io/gr_tagged_file_sink.i b/gnuradio-core/src/lib/io/gr_tagged_file_sink.i new file mode 100644 index 000000000..2f2596e12 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_tagged_file_sink.i @@ -0,0 +1,35 @@ +/* -*- c++ -*- */ +/* + * Copyright 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,tagged_file_sink) + +gr_tagged_file_sink_sptr +gr_make_tagged_file_sink (size_t itemsize, double samp_rate); + +class gr_tagged_file_sink : public gr_sync_block +{ + protected: + gr_tagged_file_sink (size_t itemsize, double samp_rate); + + public: + ~gr_tagged_file_sink (); +}; diff --git a/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.cc b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.cc new file mode 100644 index 000000000..8211b7672 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.cc @@ -0,0 +1,137 @@ +/* -*- 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 <gr_tagged_stream_to_pdu.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 <string.h> + +// public constructor that returns a shared_ptr + +gr_tagged_stream_to_pdu_sptr +gr_make_tagged_stream_to_pdu(gr_pdu_vector_type t) +{ + return gnuradio::get_initial_sptr(new gr_tagged_stream_to_pdu(t)); +} + +gr_tagged_stream_to_pdu::gr_tagged_stream_to_pdu (gr_pdu_vector_type t) + : gr_sync_block("tagged_stream_to_pdu", + gr_make_io_signature(1, 1, gr_pdu_itemsize(t)), + gr_make_io_signature(0, 0, 0)), + d_vectortype(t), d_itemsize(gr_pdu_itemsize(t)), d_inpdu(false), + d_pdu_meta(pmt::PMT_NIL), d_pdu_vector(pmt::PMT_NIL) +{ + message_port_register_out(pdu_port_id); +} + +gr_tagged_stream_to_pdu::~gr_tagged_stream_to_pdu() +{ + printf("destructor running\n"); +} + +int +gr_tagged_stream_to_pdu::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const uint8_t *in = (const uint8_t*) input_items[0]; + uint64_t abs_N = nitems_read(0); + + // if we are not in a pdu already, start a new one + if(!d_inpdu){ + get_tags_in_range(d_tags, 0, abs_N, abs_N+1); + bool found_length_tag(false); + for(d_tags_itr = d_tags.begin(); (d_tags_itr != d_tags.end()) && (!found_length_tag); d_tags_itr++){ + if( pmt::pmt_equal( (*d_tags_itr).key, pdu_length_tag ) ){ + if( (*d_tags_itr).offset != abs_N ){ + throw std::runtime_error("expected next pdu length tag on a different item..."); + } + found_length_tag = true; + d_pdu_length = pmt::pmt_to_long( (*d_tags_itr).value ); + d_pdu_remain = d_pdu_length; + d_pdu_meta = pmt::pmt_make_dict(); + break; + } // if have length tag + } // iter over tags + if(!found_length_tag){ + throw std::runtime_error("tagged stream does not contain a pdu_length tag!"); + } + } + + size_t ncopy = std::min((size_t)noutput_items, d_pdu_remain); + + // copy any tags in this range into our meta object + get_tags_in_range(d_tags, 0, abs_N, abs_N+ncopy); + for(d_tags_itr = d_tags.begin(); d_tags_itr != d_tags.end(); d_tags_itr++){ + if( ! pmt_equal( (*d_tags_itr).key, pdu_length_tag ) ){ + d_pdu_meta = pmt_dict_add(d_pdu_meta, (*d_tags_itr).key, (*d_tags_itr).value); + } + } + + // copy samples for this vector into either a pmt or our save buffer + if(ncopy == d_pdu_remain){ // we will send this pdu + if(d_save.size() == 0){ + d_pdu_vector = gr_pdu_make_vector(d_vectortype, in, ncopy); + send_message(); + } else { + size_t oldsize = d_save.size(); + d_save.resize((oldsize + ncopy)*d_itemsize, 0); + memcpy( &d_save[oldsize*d_itemsize], in, ncopy*d_itemsize ); + d_pdu_vector = gr_pdu_make_vector(d_vectortype, &d_save[0], d_pdu_length); + send_message(); + d_save.clear(); + } + } else { + d_inpdu = true; + size_t oldsize = d_save.size(); + d_save.resize( (oldsize+ncopy)*d_itemsize ); + memcpy( &d_save[oldsize*d_itemsize], in, ncopy*d_itemsize ); + d_pdu_remain -= ncopy; + } + + return ncopy; +} + +void gr_tagged_stream_to_pdu::send_message(){ + + if(pmt::pmt_length(d_pdu_vector) != d_pdu_length){ + throw std::runtime_error("msg length not correct"); + } + + pmt::pmt_t msg = pmt::pmt_cons( d_pdu_meta, d_pdu_vector ); + message_port_pub( pdu_port_id, msg ); + + d_pdu_meta = pmt::PMT_NIL; + d_pdu_vector = pmt::PMT_NIL; + d_pdu_length = 0; + d_pdu_remain = 0; + d_inpdu = false; +} diff --git a/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.h b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.h new file mode 100644 index 000000000..c3fff3581 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.h @@ -0,0 +1,76 @@ +/* -*- 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_GR_TAGGED_STREAM_TO_PDU_H +#define INCLUDED_GR_TAGGED_STREAM_TO_PDU_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_message.h> +#include <gr_msg_queue.h> +#include <gr_pdu.h> + +class gr_tagged_stream_to_pdu; +typedef boost::shared_ptr<gr_tagged_stream_to_pdu> gr_tagged_stream_to_pdu_sptr; + +GR_CORE_API gr_tagged_stream_to_pdu_sptr gr_make_tagged_stream_to_pdu (gr_pdu_vector_type t); + +/*! + * \brief Turn received messages into a stream + * \ingroup source_blk + */ +class GR_CORE_API gr_tagged_stream_to_pdu : public gr_sync_block +{ + private: + gr_pdu_vector_type d_vectortype; + size_t d_itemsize; + + std::vector<uint8_t> d_save; + + std::vector<gr_tag_t> d_tags; + std::vector<gr_tag_t>::iterator d_tags_itr; + + bool d_inpdu; + + size_t d_pdu_length; + size_t d_pdu_remain; + pmt::pmt_t d_pdu_meta; + pmt::pmt_t d_pdu_vector; + + friend GR_CORE_API gr_tagged_stream_to_pdu_sptr + gr_make_tagged_stream_to_pdu(gr_pdu_vector_type t); + + protected: + gr_tagged_stream_to_pdu (gr_pdu_vector_type t); + + public: + ~gr_tagged_stream_to_pdu (); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + void send_message(); + +}; + +#endif /* INCLUDED_GR_PDU_TO_TAGGED_SOURCE_H */ diff --git a/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.i b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.i new file mode 100644 index 000000000..f12987b74 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_tagged_stream_to_pdu.i @@ -0,0 +1,31 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,tagged_stream_to_pdu); + +%{ +#include <gr_tagged_stream_to_pdu.h> +%} + +%include <gr_tagged_stream_to_pdu.h> + + diff --git a/gnuradio-core/src/lib/io/gr_trigger_mode.h b/gnuradio-core/src/lib/io/gr_trigger_mode.h new file mode 100644 index 000000000..be131686b --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_trigger_mode.h @@ -0,0 +1,38 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,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_TRIGGER_MODE_H +#define INCLUDED_GR_TRIGGER_MODE_H + +enum gr_trigger_mode { + gr_TRIG_MODE_FREE, + gr_TRIG_MODE_AUTO, + gr_TRIG_MODE_NORM, + gr_TRIG_MODE_STRIPCHART, +}; + +enum gr_trigger_slope { + gr_TRIG_SLOPE_POS, + gr_TRIG_SLOPE_NEG, +}; + +#endif /* INCLUDED_GR_TRIGGER_MODE_H */ diff --git a/gnuradio-core/src/lib/io/gr_tuntap_pdu.cc b/gnuradio-core/src/lib/io/gr_tuntap_pdu.cc new file mode 100644 index 000000000..8dd4b18a1 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_tuntap_pdu.cc @@ -0,0 +1,145 @@ +/* -*- 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 <gr_tuntap_pdu.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 <string.h> +#include <iostream> +#include <gr_pdu.h> +#include <boost/format.hpp> + +#if (defined(linux) || defined(__linux) || defined(__linux__)) + +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include <arpa/inet.h> +#include <linux/if.h> + + +// public constructor that returns a shared_ptr + +gr_tuntap_pdu_sptr +gr_make_tuntap_pdu (std::string dev, int MTU) +{ + return gnuradio::get_initial_sptr(new gr_tuntap_pdu(dev, MTU)); +} + +gr_tuntap_pdu::gr_tuntap_pdu (std::string dev, int MTU) + : gr_stream_pdu_base(MTU) +{ + + // make the tuntap + char dev_cstr[1024]; + memset(dev_cstr, 0x00, 1024); + strncpy(dev_cstr, dev.c_str(), std::min(sizeof(dev_cstr), dev.size())); + d_fd = tun_alloc(dev_cstr); + if(d_fd <= 0){ + throw std::runtime_error("TunTap make: tun_alloc failed (are you running as root?)"); + } + + std::cout << boost::format( + "Allocated virtual ethernet interface: %s\n" + "You must now use ifconfig to set its IP address. E.g.,\n" + " $ sudo ifconfig %s 192.168.200.1\n" + "Be sure to use a different address in the same subnet for each machine.\n" + ) % dev % dev << std::endl; + + // set up output message port + message_port_register_out(pmt::mp("pdus")); + start_rxthread(pmt::mp("pdus")); + + // set up input message port + message_port_register_in(pmt::mp("pdus")); + set_msg_handler(pmt::mp("pdus"), boost::bind(&gr_tuntap_pdu::send, this, _1)); +} + + +int gr_tuntap_pdu::tun_alloc(char *dev, int flags) { + struct ifreq ifr; + int fd, err; + const char *clonedev = "/dev/net/tun"; + + /* Arguments taken by the function: + * + * char *dev: the name of an interface (or '\0'). MUST have enough + * space to hold the interface name if '\0' is passed + * int flags: interface flags (eg, IFF_TUN etc.) + */ + + /* open the clone device */ + if( (fd = open(clonedev, O_RDWR)) < 0 ) { + return fd; + } + + /* preparation of the struct ifr, of type "struct ifreq" */ + memset(&ifr, 0, sizeof(ifr)); + + ifr.ifr_flags = flags; /* IFF_TUN or IFF_TAP, plus maybe IFF_NO_PI */ + + if (*dev) { + /* if a device name was specified, put it in the structure; otherwise, + * the kernel will try to allocate the "next" device of the + * specified type */ + strncpy(ifr.ifr_name, dev, IFNAMSIZ); + } + + /* try to create the device */ + if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ) { + close(fd); + return err; + } + + /* if the operation was successful, write back the name of the + * interface to the variable "dev", so the caller can know + * it. Note that the caller MUST reserve space in *dev (see calling + * code below) */ + strcpy(dev, ifr.ifr_name); + + /* this is the special file descriptor that the caller will use to talk + * with the virtual interface */ + return fd; +} + +#else //if not linux + +gr_block_sptr +gr_make_tuntap_pdu(std::string dev, int MTU) +{ + gr_block_sptr rv; + throw std::runtime_error("tuntap only implemented on linux"); + return rv; +} + +#endif diff --git a/gnuradio-core/src/lib/io/gr_tuntap_pdu.h b/gnuradio-core/src/lib/io/gr_tuntap_pdu.h new file mode 100644 index 000000000..18c83f42b --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_tuntap_pdu.h @@ -0,0 +1,74 @@ +/* -*- 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_GR_TUNTAP_PDU_H +#define INCLUDED_GR_TUNTAP_PDU_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_message.h> +#include <gr_msg_queue.h> +#include <gr_stream_pdu_base.h> + +#if (defined(linux) || defined(__linux) || defined(__linux__)) + +#include <linux/if_tun.h> + +class gr_tuntap_pdu; +typedef boost::shared_ptr<gr_tuntap_pdu> gr_tuntap_pdu_sptr; + +GR_CORE_API gr_tuntap_pdu_sptr gr_make_tuntap_pdu (std::string dev, int MTU=10000); + +/*! + * \brief Gather received items into messages and insert into msgq + * \ingroup sink_blk + */ +class GR_CORE_API gr_tuntap_pdu : public gr_stream_pdu_base +{ + private: + friend GR_CORE_API gr_tuntap_pdu_sptr + gr_make_tuntap_pdu(std::string dev, int MTU); + int tun_alloc(char* dev, int flags = IFF_TAP | IFF_NO_PI); + std::string d_dev; + protected: + gr_tuntap_pdu (std::string dev, int MTU=10000); + + public: + ~gr_tuntap_pdu () {} + +}; + +#else // if not linux + +class gr_tuntap_pdu +{ +private: + gr_tuntap_pdu() {}; +public: + ~gr_tuntap_pdu() {}; +}; + +GR_CORE_API gr_block_sptr gr_make_tuntap_pdu (std::string dev, int MTU=0); + +#endif + +#endif /* INCLUDED_GR_TUNTAP_PDU_H */ diff --git a/gnuradio-core/src/lib/io/gr_tuntap_pdu.i b/gnuradio-core/src/lib/io/gr_tuntap_pdu.i new file mode 100644 index 000000000..589bbc385 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_tuntap_pdu.i @@ -0,0 +1,30 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,tuntap_pdu); + +%{ +#include <gr_tuntap_pdu.h> +%} + +%include "gr_tuntap_pdu.h" + diff --git a/gnuradio-core/src/lib/io/gr_udp_sink.cc b/gnuradio-core/src/lib/io/gr_udp_sink.cc new file mode 100644 index 000000000..6b1d34ef7 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_udp_sink.cc @@ -0,0 +1,304 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2008,2009,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. + */ + +#include <boost/asio.hpp> + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include <gr_udp_sink.h> +#include <gr_io_signature.h> +#include <stdexcept> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#if defined(HAVE_NETDB_H) +#include <netdb.h> +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> //usually included by <netdb.h>? +#endif +typedef void* optval_t; +#elif defined(HAVE_WINDOWS_H) +// if not posix, assume winsock +#define USING_WINSOCK +#include <winsock2.h> +#include <ws2tcpip.h> +#define SHUT_RDWR 2 +typedef char* optval_t; +#endif + +#include <gruel/thread.h> + +#define SNK_VERBOSE 0 + +static int is_error( int perr ) +{ + // Compare error to posix error code; return nonzero if match. +#if defined(USING_WINSOCK) +#define ENOPROTOOPT 109 +#define ECONNREFUSED 111 + // All codes to be checked for must be defined below + int werr = WSAGetLastError(); + switch( werr ) { + case WSAETIMEDOUT: + return( perr == EAGAIN ); + case WSAENOPROTOOPT: + return( perr == ENOPROTOOPT ); + case WSAECONNREFUSED: + return( perr == ECONNREFUSED ); + default: + fprintf(stderr,"gr_udp_source/is_error: unknown error %d\n", perr ); + throw std::runtime_error("internal error"); + } + return 0; +#else + return( perr == errno ); +#endif +} + +static void report_error( const char *msg1, const char *msg2 ) +{ + // Deal with errors, both posix and winsock +#if defined(USING_WINSOCK) + int werr = WSAGetLastError(); + fprintf(stderr, "%s: winsock error %d\n", msg1, werr ); +#else + perror(msg1); +#endif + if( msg2 != NULL ) + throw std::runtime_error(msg2); + return; +} + +gr_udp_sink::gr_udp_sink (size_t itemsize, + const char *host, unsigned short port, + int payload_size, bool eof) + : gr_sync_block ("udp_sink", + gr_make_io_signature (1, 1, itemsize), + gr_make_io_signature (0, 0, 0)), + d_itemsize (itemsize), d_payload_size(payload_size), d_eof(eof), + d_socket(-1), d_connected(false) +{ +#if defined(USING_WINSOCK) // for Windows (with MinGW) + // initialize winsock DLL + WSADATA wsaData; + int iResult = WSAStartup( MAKEWORD(2,2), &wsaData ); + if( iResult != NO_ERROR ) { + report_error( "gr_udp_source WSAStartup", "can't open socket" ); + } +#endif + + // create socket + d_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if(d_socket == -1) { + report_error("socket open","can't open socket"); + } + + // Don't wait when shutting down + linger lngr; + lngr.l_onoff = 1; + lngr.l_linger = 0; + if(setsockopt(d_socket, SOL_SOCKET, SO_LINGER, (optval_t)&lngr, sizeof(linger)) == -1) { + if( !is_error(ENOPROTOOPT) ) { // no SO_LINGER for SOCK_DGRAM on Windows + report_error("SO_LINGER","can't set socket option SO_LINGER"); + } + } + + // Get the destination address + connect(host, port); +} + +// public constructor that returns a shared_ptr + +gr_udp_sink_sptr +gr_make_udp_sink (size_t itemsize, + const char *host, unsigned short port, + int payload_size, bool eof) +{ + return gnuradio::get_initial_sptr(new gr_udp_sink (itemsize, + host, port, + payload_size, eof)); +} + +gr_udp_sink::~gr_udp_sink () +{ + if (d_connected) + disconnect(); + + if (d_socket != -1){ + shutdown(d_socket, SHUT_RDWR); +#if defined(USING_WINSOCK) + closesocket(d_socket); +#else + ::close(d_socket); +#endif + d_socket = -1; + } + +#if defined(USING_WINSOCK) // for Windows (with MinGW) + // free winsock resources + WSACleanup(); +#endif +} + +int +gr_udp_sink::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]; + ssize_t r=0, bytes_sent=0, bytes_to_send=0; + ssize_t total_size = noutput_items*d_itemsize; + + #if SNK_VERBOSE + printf("Entered udp_sink\n"); + #endif + + gruel::scoped_lock guard(d_mutex); // protect d_socket + + while(bytes_sent < total_size) { + bytes_to_send = std::min((ssize_t)d_payload_size, (total_size-bytes_sent)); + + if(d_connected) { + r = send(d_socket, (in+bytes_sent), bytes_to_send, 0); + if(r == -1) { // error on send command + if( is_error(ECONNREFUSED) ) + r = bytes_to_send; // discard data until receiver is started + else { + report_error("udp_sink",NULL); // there should be no error case where + return -1; // this function should not exit immediately + } + } + } + else + r = bytes_to_send; // discarded for lack of connection + bytes_sent += r; + + #if SNK_VERBOSE + printf("\tbyte sent: %d bytes\n", r); + #endif + } + + #if SNK_VERBOSE + printf("Sent: %d bytes (noutput_items: %d)\n", bytes_sent, noutput_items); + #endif + + return noutput_items; +} + +void gr_udp_sink::connect( const char *host, unsigned short port ) +{ + if(d_connected) + disconnect(); + + if(host != NULL ) { + // Get the destination address + struct addrinfo *ip_dst; + struct addrinfo hints; + memset( (void*)&hints, 0, sizeof(hints) ); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + char port_str[12]; + sprintf( port_str, "%d", port ); + + // FIXME leaks if report_error throws below + int ret = getaddrinfo( host, port_str, &hints, &ip_dst ); + if( ret != 0 ) + report_error("gr_udp_source/getaddrinfo", + "can't initialize destination socket" ); + + // don't need d_mutex lock when !d_connected + if(::connect(d_socket, ip_dst->ai_addr, ip_dst->ai_addrlen) == -1) { + report_error("socket connect","can't connect to socket"); + } + d_connected = true; + + freeaddrinfo(ip_dst); + } + + return; +} + +void gr_udp_sink::disconnect() +{ + if(!d_connected) + return; + + #if SNK_VERBOSE + printf("gr_udp_sink disconnecting\n"); + #endif + + gruel::scoped_lock guard(d_mutex); // protect d_socket from work() + + // Send a few zero-length packets to signal receiver we are done + if(d_eof) { + int i; + for( i = 0; i < 3; i++ ) + (void) send( d_socket, NULL, 0, 0 ); // ignore errors + } + + // Sending EOF can produce ERRCONNREFUSED errors that won't show up + // until the next send or recv, which might confuse us if it happens + // on a new connection. The following does a nonblocking recv to + // clear any such errors. + timeval timeout; + timeout.tv_sec = 0; // zero time for immediate return + timeout.tv_usec = 0; + fd_set readfds; + FD_ZERO(&readfds); + FD_SET(d_socket, &readfds); + int r = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout); + if(r < 0) { + #if SNK_VERBOSE + report_error("udp_sink/select",NULL); + #endif + } + else if(r > 0) { // call recv() to get error return + r = recv(d_socket, (char*)&readfds, sizeof(readfds), 0); + if(r < 0) { + #if SNK_VERBOSE + report_error("udp_sink/recv",NULL); + #endif + } + } + + // Since I can't find any way to disconnect a datagram socket in Cygwin, + // we just leave it connected but disable sending. +#if 0 + // zeroed address structure should reset connection + struct sockaddr addr; + memset( (void*)&addr, 0, sizeof(addr) ); + // addr.sa_family = AF_UNSPEC; // doesn't work on Cygwin + // addr.sa_family = AF_INET; // doesn't work on Cygwin + + if(::connect(d_socket, &addr, sizeof(addr)) == -1) + report_error("socket connect","can't connect to socket"); +#endif + + d_connected = false; + + return; +} diff --git a/gnuradio-core/src/lib/io/gr_udp_sink.h b/gnuradio-core/src/lib/io/gr_udp_sink.h new file mode 100644 index 000000000..bf042a6d1 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_udp_sink.h @@ -0,0 +1,112 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2008,2009,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_UDP_SINK_H +#define INCLUDED_GR_UDP_SINK_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gruel/thread.h> + +class gr_udp_sink; +typedef boost::shared_ptr<gr_udp_sink> gr_udp_sink_sptr; + +GR_CORE_API gr_udp_sink_sptr +gr_make_udp_sink (size_t itemsize, + const char *host, unsigned short port, + int payload_size=1472, bool eof=true); + +/*! + * \brief Write stream to an UDP socket. + * \ingroup sink_blk + * + * \param itemsize The size (in bytes) of the item datatype + * \param host The name or IP address of the receiving host; use + * NULL or None for no connection + * \param port Destination port to connect to on receiving host + * \param payload_size UDP payload size by default set to 1472 = + * (1500 MTU - (8 byte UDP header) - (20 byte IP header)) + * \param eof Send zero-length packet on disconnect + */ + +class GR_CORE_API gr_udp_sink : public gr_sync_block +{ + friend GR_CORE_API gr_udp_sink_sptr gr_make_udp_sink (size_t itemsize, + const char *host, + unsigned short port, + int payload_size, bool eof); + private: + size_t d_itemsize; + + int d_payload_size; // maximum transmission unit (packet length) + bool d_eof; // send zero-length packet on disconnect + int d_socket; // handle to socket + bool d_connected; // are we connected? + gruel::mutex d_mutex; // protects d_socket and d_connected + + protected: + /*! + * \brief UDP Sink Constructor + * + * \param itemsize The size (in bytes) of the item datatype + * \param host The name or IP address of the receiving host; use + * NULL or None for no connection + * \param port Destination port to connect to on receiving host + * \param payload_size UDP payload size by default set to + * 1472 = (1500 MTU - (8 byte UDP header) - (20 byte IP header)) + * \param eof Send zero-length packet on disconnect + */ + gr_udp_sink (size_t itemsize, + const char *host, unsigned short port, + int payload_size, bool eof); + + public: + ~gr_udp_sink (); + + /*! \brief return the PAYLOAD_SIZE of the socket */ + int payload_size() { return d_payload_size; } + + /*! \brief Change the connection to a new destination + * + * \param host The name or IP address of the receiving host; use + * NULL or None to break the connection without closing + * \param port Destination port to connect to on receiving host + * + * Calls disconnect() to terminate any current connection first. + */ + void connect( const char *host, unsigned short port ); + + /*! \brief Send zero-length packet (if eof is requested) then stop sending + * + * Zero-byte packets can be interpreted as EOF by gr_udp_source. Note that + * disconnect occurs automatically when the sink is destroyed, but not when + * its top_block stops.*/ + void disconnect(); + + // should we export anything else? + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#endif /* INCLUDED_GR_UDP_SINK_H */ diff --git a/gnuradio-core/src/lib/io/gr_udp_sink.i b/gnuradio-core/src/lib/io/gr_udp_sink.i new file mode 100644 index 000000000..ba7043937 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_udp_sink.i @@ -0,0 +1,46 @@ +/* -*- 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. + */ + + +GR_SWIG_BLOCK_MAGIC(gr,udp_sink) + +gr_udp_sink_sptr +gr_make_udp_sink (size_t itemsize, + const char *host, unsigned short port, + int payload_size=1472, bool eof=true) throw (std::runtime_error); + +class gr_udp_sink : public gr_sync_block +{ + protected: + gr_udp_sink (size_t itemsize, + const char *host, unsigned short port, + int payload_size, bool eof) + throw (std::runtime_error); + + public: + ~gr_udp_sink (); + + int payload_size() { return d_payload_size; } + void connect( const char *host, unsigned short port ); + void disconnect(); + +}; diff --git a/gnuradio-core/src/lib/io/gr_udp_source.cc b/gnuradio-core/src/lib/io/gr_udp_source.cc new file mode 100644 index 000000000..eca8e89d0 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_udp_source.cc @@ -0,0 +1,374 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2008,2009,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_udp_source.h> +#include <gr_io_signature.h> +#include <stdexcept> +#include <errno.h> +#include <stdio.h> +#include <string.h> + +#if defined(HAVE_NETDB_H) +#include <netdb.h> +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_SOCKET_H +#include <sys/socket.h> +#endif +typedef void* optval_t; + +// ntohs() on FreeBSD may require both netinet/in.h and arpa/inet.h, in order +#if defined(HAVE_NETINET_IN_H) +#include <netinet/in.h> +#endif +#if defined(HAVE_ARPA_INET_H) +#include <arpa/inet.h> +#endif + +#elif defined(HAVE_WINDOWS_H) +// if not posix, assume winsock +#define USING_WINSOCK +#include <winsock2.h> +#include <ws2tcpip.h> +#define SHUT_RDWR 2 +typedef char* optval_t; +#endif + +#define USE_SELECT 1 // non-blocking receive on all platforms +#define USE_RCV_TIMEO 0 // non-blocking receive on all but Cygwin +#define SRC_VERBOSE 0 + +static int is_error( int perr ) +{ + // Compare error to posix error code; return nonzero if match. +#if defined(USING_WINSOCK) +#define ENOPROTOOPT 109 + // All codes to be checked for must be defined below + int werr = WSAGetLastError(); + switch( werr ) { + case WSAETIMEDOUT: + return( perr == EAGAIN ); + case WSAENOPROTOOPT: + return( perr == ENOPROTOOPT ); + default: + fprintf(stderr,"gr_udp_source/is_error: unknown error %d\n", perr ); + throw std::runtime_error("internal error"); + } + return 0; +#else + return( perr == errno ); +#endif +} + +static void report_error( const char *msg1, const char *msg2 ) +{ + // Deal with errors, both posix and winsock +#if defined(USING_WINSOCK) + int werr = WSAGetLastError(); + fprintf(stderr, "%s: winsock error %d\n", msg1, werr ); +#else + perror(msg1); +#endif + if( msg2 != NULL ) + throw std::runtime_error(msg2); + return; +} + +gr_udp_source::gr_udp_source(size_t itemsize, const char *host, + unsigned short port, int payload_size, + bool eof, bool wait) + : gr_sync_block ("udp_source", + gr_make_io_signature(0, 0, 0), + gr_make_io_signature(1, 1, itemsize)), + d_itemsize(itemsize), d_payload_size(payload_size), + d_eof(eof), d_wait(wait), d_socket(-1), d_residual(0), d_temp_offset(0) +{ + int ret = 0; + +#if defined(USING_WINSOCK) // for Windows (with MinGW) + // initialize winsock DLL + WSADATA wsaData; + int iResult = WSAStartup( MAKEWORD(2,2), &wsaData ); + if( iResult != NO_ERROR ) { + report_error( "gr_udp_source WSAStartup", "can't open socket" ); + } +#endif + + // Set up the address stucture for the source address and port numbers + // Get the source IP address from the host name + struct addrinfo *ip_src; // store the source IP address to use + struct addrinfo hints; + memset( (void*)&hints, 0, sizeof(hints) ); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + hints.ai_flags = AI_PASSIVE; + char port_str[12]; + sprintf( port_str, "%d", port ); + + // FIXME leaks if report_error throws below + ret = getaddrinfo( host, port_str, &hints, &ip_src ); + if( ret != 0 ) + report_error("gr_udp_source/getaddrinfo", + "can't initialize source socket" ); + + // FIXME leaks if report_error throws below + d_temp_buff = new char[d_payload_size]; // allow it to hold up to payload_size bytes + + // create socket + d_socket = socket(ip_src->ai_family, ip_src->ai_socktype, + ip_src->ai_protocol); + if(d_socket == -1) { + report_error("socket open","can't open socket"); + } + + // Turn on reuse address + int opt_val = 1; + if(setsockopt(d_socket, SOL_SOCKET, SO_REUSEADDR, (optval_t)&opt_val, sizeof(int)) == -1) { + report_error("SO_REUSEADDR","can't set socket option SO_REUSEADDR"); + } + + // Don't wait when shutting down + linger lngr; + lngr.l_onoff = 1; + lngr.l_linger = 0; + if(setsockopt(d_socket, SOL_SOCKET, SO_LINGER, (optval_t)&lngr, sizeof(linger)) == -1) { + if( !is_error(ENOPROTOOPT) ) { // no SO_LINGER for SOCK_DGRAM on Windows + report_error("SO_LINGER","can't set socket option SO_LINGER"); + } + } + +#if USE_RCV_TIMEO + // Set a timeout on the receive function to not block indefinitely + // This value can (and probably should) be changed + // Ignored on Cygwin +#if defined(USING_WINSOCK) + DWORD timeout = 1000; // milliseconds +#else + timeval timeout; + timeout.tv_sec = 1; + timeout.tv_usec = 0; +#endif + if(setsockopt(d_socket, SOL_SOCKET, SO_RCVTIMEO, (optval_t)&timeout, sizeof(timeout)) == -1) { + report_error("SO_RCVTIMEO","can't set socket option SO_RCVTIMEO"); + } +#endif // USE_RCV_TIMEO + + // bind socket to an address and port number to listen on + if(bind (d_socket, ip_src->ai_addr, ip_src->ai_addrlen) == -1) { + report_error("socket bind","can't bind socket"); + } + freeaddrinfo(ip_src); + +} + +gr_udp_source_sptr +gr_make_udp_source (size_t itemsize, const char *ipaddr, + unsigned short port, int payload_size, bool eof, bool wait) +{ + return gnuradio::get_initial_sptr(new gr_udp_source (itemsize, ipaddr, + port, payload_size, eof, wait)); +} + +gr_udp_source::~gr_udp_source () +{ + delete [] d_temp_buff; + + if (d_socket != -1){ + shutdown(d_socket, SHUT_RDWR); +#if defined(USING_WINSOCK) + closesocket(d_socket); +#else + ::close(d_socket); +#endif + d_socket = -1; + } + +#if defined(USING_WINSOCK) // for Windows (with MinGW) + // free winsock resources + WSACleanup(); +#endif +} + +int +gr_udp_source::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + char *out = (char *) output_items[0]; + ssize_t r=0, nbytes=0, bytes_received=0; + ssize_t total_bytes = (ssize_t)(d_itemsize*noutput_items); + + #if SRC_VERBOSE + printf("\nEntered udp_source\n"); + #endif + + // Remove items from temp buffer if they are in there + if(d_residual) { + nbytes = std::min(d_residual, total_bytes); + memcpy(out, d_temp_buff+d_temp_offset, nbytes); + bytes_received = nbytes; + + #if SRC_VERBOSE + printf("\tTemp buff size: %d offset: %d (bytes_received: %d) (noutput_items: %d)\n", + d_residual, d_temp_offset, bytes_received, noutput_items); + #endif + + // Increment pointer + out += bytes_received; + + // Update indexing of amount of bytes left in the buffer + d_residual -= nbytes; + d_temp_offset += nbytes; + + // Return now with what we've got. + assert(nbytes % d_itemsize == 0); + return nbytes/d_itemsize; + } + + while(1) { + // get the data into our output buffer and record the number of bytes + +#if USE_SELECT + // RCV_TIMEO doesn't work on all systems (e.g., Cygwin) + // use select() instead of, or in addition to RCV_TIMEO + fd_set readfds; + timeval timeout; + timeout.tv_sec = 1; // Init timeout each iteration. Select can modify it. + timeout.tv_usec = 0; + FD_ZERO(&readfds); + FD_SET(d_socket, &readfds); + r = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout); + if(r < 0) { + report_error("udp_source/select",NULL); + return -1; + } + else if(r == 0 ) { // timed out + if( d_wait ) { + // Allow boost thread interrupt, then try again + //boost::this_thread::interruption_point(); + //continue; + return 0; + } + else + return -1; + } +#endif // USE_SELECT + + // This is a non-blocking call with a timeout set in the constructor + r = recv(d_socket, d_temp_buff, d_payload_size, 0); // get the entire payload or the what's available + + // If r > 0, round it down to a multiple of d_itemsize + // (If sender is broken, don't propagate problem) + if (r > 0) + r = (r/d_itemsize) * d_itemsize; + + // Check if there was a problem; forget it if the operation just timed out + if(r == -1) { + if( is_error(EAGAIN) ) { // handle non-blocking call timeout + #if SRC_VERBOSE + printf("UDP receive timed out\n"); + #endif + + if( d_wait ) { + // Allow boost thread interrupt, then try again + //boost::this_thread::interruption_point(); + //continue; + return 0; + } + else + return -1; + } + else { + report_error("udp_source/recv",NULL); + return -1; + } + } + else if(r==0) { + if(d_eof) { + // zero-length packet interpreted as EOF + + #if SNK_VERBOSE + printf("\tzero-length packet received; returning EOF\n"); + #endif + + return -1; + } + else{ + // do we need to allow boost thread interrupt? + boost::this_thread::interruption_point(); + continue; + } + } + else { + // Calculate the number of bytes we can take from the buffer in this call + nbytes = std::min(r, total_bytes-bytes_received); + + // adjust the total number of bytes we have to round down to nearest integer of an itemsize + nbytes -= ((bytes_received+nbytes) % d_itemsize); + + // copy the number of bytes we want to look at here + memcpy(out, d_temp_buff, nbytes); + + d_residual = r - nbytes; // save the number of bytes stored + d_temp_offset=nbytes; // reset buffer index + + // keep track of the total number of bytes received + bytes_received += nbytes; + + // increment the pointer + out += nbytes; + + // Immediately return when data comes in + break; + } + + #if SNK_VERBOSE + printf("\tbytes received: %d bytes (nbytes: %d)\n", bytes, nbytes); + #endif + } + + #if SRC_VERBOSE + printf("Total Bytes Received: %d (bytes_received / noutput_items = %d / %d)\n", + bytes_received, bytes_received, noutput_items); + #endif + + // bytes_received is already set to some integer multiple of itemsize + return bytes_received/d_itemsize; +} + +// Return port number of d_socket +int gr_udp_source::get_port(void) +{ + sockaddr_in name; + socklen_t len = sizeof(name); + int ret = getsockname( d_socket, (sockaddr*)&name, &len ); + if( ret ) { + report_error("gr_udp_source/getsockname",NULL); + return -1; + } + return ntohs(name.sin_port); +} diff --git a/gnuradio-core/src/lib/io/gr_udp_source.h b/gnuradio-core/src/lib/io/gr_udp_source.h new file mode 100644 index 000000000..56dcb3c0a --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_udp_source.h @@ -0,0 +1,110 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2008,2009,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_UDP_SOURCE_H +#define INCLUDED_GR_UDP_SOURCE_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gruel/thread.h> + +class gr_udp_source; +typedef boost::shared_ptr<gr_udp_source> gr_udp_source_sptr; + +GR_CORE_API gr_udp_source_sptr gr_make_udp_source(size_t itemsize, const char *host, + unsigned short port, + int payload_size=1472, + bool eof=true, bool wait=true); + +/*! + * \brief Read stream from an UDP socket. + * \ingroup source_blk + * + * \param itemsize The size (in bytes) of the item datatype + * \param host The name or IP address of the receiving host; can be + * NULL, None, or "0.0.0.0" to allow reading from any + * interface on the host + * \param port The port number on which to receive data; use 0 to + * have the system assign an unused port number + * \param payload_size UDP payload size by default set to 1472 = + * (1500 MTU - (8 byte UDP header) - (20 byte IP header)) + * \param eof Interpret zero-length packet as EOF (default: true) + * \param wait Wait for data if not immediately available + * (default: true) + * +*/ + +class GR_CORE_API gr_udp_source : public gr_sync_block +{ + friend GR_CORE_API gr_udp_source_sptr gr_make_udp_source(size_t itemsize, + const char *host, + unsigned short port, + int payload_size, + bool eof, bool wait); + + private: + size_t d_itemsize; + int d_payload_size; // maximum transmission unit (packet length) + bool d_eof; // zero-length packet is EOF + bool d_wait; // wait if data if not immediately available + int d_socket; // handle to socket + char *d_temp_buff; // hold buffer between calls + ssize_t d_residual; // hold information about number of bytes stored in the temp buffer + size_t d_temp_offset; // point to temp buffer location offset + + protected: + /*! + * \brief UDP Source Constructor + * + * \param itemsize The size (in bytes) of the item datatype + * \param host The name or IP address of the receiving host; can be + * NULL, None, or "0.0.0.0" to allow reading from any + * interface on the host + * \param port The port number on which to receive data; use 0 to + * have the system assign an unused port number + * \param payload_size UDP payload size by default set to 1472 = + * (1500 MTU - (8 byte UDP header) - (20 byte IP header)) + * \param eof Interpret zero-length packet as EOF (default: true) + * \param wait Wait for data if not immediately available + * (default: true) + */ + gr_udp_source(size_t itemsize, const char *host, unsigned short port, + int payload_size, bool eof, bool wait); + + public: + ~gr_udp_source(); + + /*! \brief return the PAYLOAD_SIZE of the socket */ + int payload_size() { return d_payload_size; } + + /*! \brief return the port number of the socket */ + int get_port(); + + // should we export anything else? + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#endif /* INCLUDED_GR_UDP_SOURCE_H */ diff --git a/gnuradio-core/src/lib/io/gr_udp_source.i b/gnuradio-core/src/lib/io/gr_udp_source.i new file mode 100644 index 000000000..18823a356 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_udp_source.i @@ -0,0 +1,41 @@ +/* -*- 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. + */ + +GR_SWIG_BLOCK_MAGIC(gr,udp_source) + +gr_udp_source_sptr +gr_make_udp_source (size_t itemsize, const char *host, + unsigned short port, int payload_size=1472, + bool eof=true, bool wait=true) throw (std::runtime_error); + +class gr_udp_source : public gr_sync_block +{ + protected: + gr_udp_source (size_t itemsize, const char *host, + unsigned short port, int payload_size, bool eof, bool wait) throw (std::runtime_error); + + public: + ~gr_udp_source (); + + int payload_size() { return d_payload_size; } + int get_port(); +}; diff --git a/gnuradio-core/src/lib/io/gr_wavfile_sink.cc b/gnuradio-core/src/lib/io/gr_wavfile_sink.cc new file mode 100644 index 000000000..8526032f6 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_wavfile_sink.cc @@ -0,0 +1,280 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006,2007,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 <gr_wavfile_sink.h> +#include <gr_io_signature.h> +#include <gri_wavfile.h> +#include <stdexcept> +#include <climits> +#include <cstring> +#include <cmath> +#include <fcntl.h> +#include <gruel/thread.h> +#include <boost/math/special_functions/round.hpp> + +// win32 (mingw/msvc) specific +#ifdef HAVE_IO_H +#include <io.h> +#endif +#ifdef O_BINARY +#define OUR_O_BINARY O_BINARY +#else +#define OUR_O_BINARY 0 +#endif + +// should be handled via configure +#ifdef O_LARGEFILE +#define OUR_O_LARGEFILE O_LARGEFILE +#else +#define OUR_O_LARGEFILE 0 +#endif + + +gr_wavfile_sink_sptr +gr_make_wavfile_sink(const char *filename, + int n_channels, + unsigned int sample_rate, + int bits_per_sample) +{ + return gnuradio::get_initial_sptr(new gr_wavfile_sink (filename, + n_channels, + sample_rate, + bits_per_sample)); +} + +gr_wavfile_sink::gr_wavfile_sink(const char *filename, + int n_channels, + unsigned int sample_rate, + int bits_per_sample) + : gr_sync_block ("wavfile_sink", + gr_make_io_signature(1, n_channels, sizeof(float)), + gr_make_io_signature(0, 0, 0)), + d_sample_rate(sample_rate), d_nchans(n_channels), + d_fp(0), d_new_fp(0), d_updated(false) +{ + if (bits_per_sample != 8 && bits_per_sample != 16) { + throw std::runtime_error("Invalid bits per sample (supports 8 and 16)"); + } + d_bytes_per_sample = bits_per_sample / 8; + d_bytes_per_sample_new = d_bytes_per_sample; + + if (!open(filename)) { + throw std::runtime_error ("can't open file"); + } + + if (bits_per_sample == 8) { + d_max_sample_val = 0xFF; + d_min_sample_val = 0; + d_normalize_fac = d_max_sample_val/2; + d_normalize_shift = 1; + } else { + d_max_sample_val = 0x7FFF; + d_min_sample_val = -0x7FFF; + d_normalize_fac = d_max_sample_val; + d_normalize_shift = 0; + if (bits_per_sample != 16) { + fprintf(stderr, "Invalid bits per sample value requested, using 16"); + } + } +} + + +bool +gr_wavfile_sink::open(const char* filename) +{ + gruel::scoped_lock guard(d_mutex); + + // we use the open system call to get access to the O_LARGEFILE flag. + int fd; + if ((fd = ::open (filename, + O_WRONLY|O_CREAT|O_TRUNC|OUR_O_LARGEFILE|OUR_O_BINARY, + 0664)) < 0){ + perror (filename); + return false; + } + + if (d_new_fp) { // if we've already got a new one open, close it + fclose(d_new_fp); + d_new_fp = 0; + } + + if ((d_new_fp = fdopen (fd, "wb")) == NULL) { + perror (filename); + ::close(fd); // don't leak file descriptor if fdopen fails. + return false; + } + d_updated = true; + + if (!gri_wavheader_write(d_new_fp, + d_sample_rate, + d_nchans, + d_bytes_per_sample_new)) { + fprintf(stderr, "[%s] could not write to WAV file\n", __FILE__); + exit(-1); + } + + return true; +} + + +void +gr_wavfile_sink::close() +{ + gruel::scoped_lock guard(d_mutex); + + if (!d_fp) + return; + + close_wav(); +} + +void gr_wavfile_sink::close_wav() +{ + unsigned int byte_count = d_sample_count * d_bytes_per_sample; + + gri_wavheader_complete(d_fp, byte_count); + + fclose(d_fp); + d_fp = NULL; +} + + +gr_wavfile_sink::~gr_wavfile_sink () +{ + if (d_new_fp) { + fclose(d_new_fp); + } + + close(); +} + + +int +gr_wavfile_sink::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float **in = (float **) &input_items[0]; + int n_in_chans = input_items.size(); + + short int sample_buf_s; + + int nwritten; + + gruel::scoped_lock guard(d_mutex); // hold mutex for duration of this block + do_update(); // update: d_fp is reqd + if (!d_fp) // drop output on the floor + return noutput_items; + + for (nwritten = 0; nwritten < noutput_items; nwritten++) { + for (int chan = 0; chan < d_nchans; chan++) { + // Write zeros to channels which are in the WAV file + // but don't have any inputs here + if (chan < n_in_chans) { + sample_buf_s = + convert_to_short(in[chan][nwritten]); + } else { + sample_buf_s = 0; + } + + gri_wav_write_sample(d_fp, sample_buf_s, d_bytes_per_sample); + + if (feof(d_fp) || ferror(d_fp)) { + fprintf(stderr, "[%s] file i/o error\n", __FILE__); + close(); + exit(-1); + } + d_sample_count++; + } + } + + return nwritten; +} + + +short int +gr_wavfile_sink::convert_to_short(float sample) +{ + sample += d_normalize_shift; + sample *= d_normalize_fac; + if (sample > d_max_sample_val) { + sample = d_max_sample_val; + } else if (sample < d_min_sample_val) { + sample = d_min_sample_val; + } + + return (short int) boost::math::iround(sample); +} + + +void +gr_wavfile_sink::set_bits_per_sample(int bits_per_sample) +{ + gruel::scoped_lock guard(d_mutex); + if (bits_per_sample == 8 || bits_per_sample == 16) { + d_bytes_per_sample_new = bits_per_sample / 8; + } +} + + +void +gr_wavfile_sink::set_sample_rate(unsigned int sample_rate) +{ + gruel::scoped_lock guard(d_mutex); + d_sample_rate = sample_rate; +} + + +void +gr_wavfile_sink::do_update() +{ + if (!d_updated) { + return; + } + + if (d_fp) { + close_wav(); + } + + d_fp = d_new_fp; // install new file pointer + d_new_fp = 0; + d_sample_count = 0; + d_bytes_per_sample = d_bytes_per_sample_new; + + if (d_bytes_per_sample == 1) { + d_max_sample_val = UCHAR_MAX; + d_min_sample_val = 0; + d_normalize_fac = d_max_sample_val/2; + d_normalize_shift = 1; + } else if (d_bytes_per_sample == 2) { + d_max_sample_val = SHRT_MAX; + d_min_sample_val = SHRT_MIN; + d_normalize_fac = d_max_sample_val; + d_normalize_shift = 0; + } + + d_updated = false; +} diff --git a/gnuradio-core/src/lib/io/gr_wavfile_sink.h b/gnuradio-core/src/lib/io/gr_wavfile_sink.h new file mode 100644 index 000000000..162151b7a --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_wavfile_sink.h @@ -0,0 +1,138 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009 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_WAVFILE_SINK_H +#define INCLUDED_GR_WAVFILE_SINK_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <gr_file_sink_base.h> +#include <boost/thread.hpp> + +class gr_wavfile_sink; +typedef boost::shared_ptr<gr_wavfile_sink> gr_wavfile_sink_sptr; + +/* + * \p filename The .wav file to be opened + * \p n_channels Number of channels (2 = stereo or I/Q output) + * \p sample_rate Sample rate [S/s] + * \p bits_per_sample 16 or 8 bit, default is 16 + */ +GR_CORE_API gr_wavfile_sink_sptr +gr_make_wavfile_sink (const char *filename, + int n_channels, + unsigned int sample_rate, + int bits_per_sample = 16); + +/*! + * \brief Write stream to a Microsoft PCM (.wav) file. + * + * Values must be floats within [-1;1]. + * Check gr_make_wavfile_sink() for extra info. + * + * \ingroup sink_blk + */ +class GR_CORE_API gr_wavfile_sink : public gr_sync_block +{ +private: + friend GR_CORE_API gr_wavfile_sink_sptr gr_make_wavfile_sink (const char *filename, + int n_channels, + unsigned int sample_rate, + int bits_per_sample); + + gr_wavfile_sink(const char *filename, + int n_channels, + unsigned int sample_rate, + int bits_per_sample); + + unsigned d_sample_rate; + int d_nchans; + unsigned d_sample_count; + int d_bytes_per_sample; + int d_bytes_per_sample_new; + int d_max_sample_val; + int d_min_sample_val; + int d_normalize_shift; + int d_normalize_fac; + + FILE *d_fp; + FILE *d_new_fp; + bool d_updated; + boost::mutex d_mutex; + + /*! + * \brief Convert a sample value within [-1;+1] to a corresponding + * short integer value + */ + short convert_to_short(float sample); + + /*! + * \brief If any file changes have occurred, update now. This is called + * internally by work() and thus doesn't usually need to be called by + * hand. + */ + void do_update(); + + /*! + * \brief Writes information to the WAV header which is not available + * a-priori (chunk size etc.) and closes the file. Not thread-safe and + * assumes d_fp is a valid file pointer, should thus only be called by + * other methods. + */ + void close_wav(); + +public: + ~gr_wavfile_sink (); + + /*! + * \brief Opens a new file and writes a WAV header. Thread-safe. + */ + bool open(const char* filename); + + /*! + * \brief Closes the currently active file and completes the WAV + * header. Thread-safe. + */ + void close(); + + /*! + * \brief Set the sample rate. This will not affect the WAV file + * currently opened. Any following open() calls will use this new + * sample rate. + */ + void set_sample_rate(unsigned int sample_rate); + + /*! + * \brief Set bits per sample. This will not affect the WAV file + * currently opened (see set_sample_rate()). If the value is neither + * 8 nor 16, the call is ignored and the current value is kept. + */ + void set_bits_per_sample(int bits_per_sample); + + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + +}; + +#endif /* INCLUDED_GR_WAVFILE_SINK_H */ diff --git a/gnuradio-core/src/lib/io/gr_wavfile_sink.i b/gnuradio-core/src/lib/io/gr_wavfile_sink.i new file mode 100644 index 000000000..48d1130bd --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_wavfile_sink.i @@ -0,0 +1,47 @@ +/* -*- 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,wavfile_sink); + +gr_wavfile_sink_sptr +gr_make_wavfile_sink (const char *filename, + int n_channels, + unsigned int sample_rate, + int bits_per_sample = 16) throw (std::runtime_error); + +class gr_wavfile_sink : public gr_sync_block +{ +protected: + gr_wavfile_sink(const char *filename, + int n_channels, + unsigned int sample_rate, + int bits_per_sample) throw (std::runtime_error); + +public: + ~gr_wavfile_sink (); + bool open(const char* filename); + void close(); + void set_sample_rate(unsigned int sample_rate); + void set_bits_per_sample(int bits_per_sample); +}; + diff --git a/gnuradio-core/src/lib/io/gr_wavfile_source.cc b/gnuradio-core/src/lib/io/gr_wavfile_source.cc new file mode 100644 index 000000000..c8372868b --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_wavfile_source.cc @@ -0,0 +1,171 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_wavfile_source.h> +#include <gr_io_signature.h> +#include <gri_wavfile.h> +#include <sys/types.h> +#include <fcntl.h> +#include <stdexcept> + +// win32 (mingw/msvc) specific +#ifdef HAVE_IO_H +#include <io.h> +#endif +#ifdef O_BINARY +#define OUR_O_BINARY O_BINARY +#else +#define OUR_O_BINARY 0 +#endif +// should be handled via configure +#ifdef O_LARGEFILE +#define OUR_O_LARGEFILE O_LARGEFILE +#else +#define OUR_O_LARGEFILE 0 +#endif + + +gr_wavfile_source_sptr +gr_make_wavfile_source (const char *filename, bool repeat) +{ + return gnuradio::get_initial_sptr(new gr_wavfile_source (filename, repeat)); +} + + +gr_wavfile_source::gr_wavfile_source (const char *filename, bool repeat) + : gr_sync_block ("wavfile_source", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 2, sizeof(float))), + d_fp(NULL), d_repeat(repeat), + d_sample_rate(1), d_nchans(1), d_bytes_per_sample(2), d_first_sample_pos(0), + d_samples_per_chan(0), d_sample_idx(0) +{ + // we use "open" to use to the O_LARGEFILE flag + + int fd; + if ((fd = open (filename, O_RDONLY | OUR_O_LARGEFILE | OUR_O_BINARY)) < 0) { + perror (filename); + throw std::runtime_error ("can't open file"); + } + + if ((d_fp = fdopen (fd, "rb")) == NULL) { + perror (filename); + throw std::runtime_error ("can't open file"); + } + + // Scan headers, check file validity + if (!gri_wavheader_parse(d_fp, + d_sample_rate, + d_nchans, + d_bytes_per_sample, + d_first_sample_pos, + d_samples_per_chan)) { + throw std::runtime_error("is not a valid wav file"); + } + + if (d_samples_per_chan == 0) { + throw std::runtime_error("WAV file does not contain any samples"); + } + + if (d_bytes_per_sample == 1) { + d_normalize_fac = 128; + d_normalize_shift = 1; + } else { + d_normalize_fac = 0x7FFF; + d_normalize_shift = 0; + } + + // Re-set the output signature + set_output_signature(gr_make_io_signature(1, d_nchans, sizeof(float))); +} + + +gr_wavfile_source::~gr_wavfile_source () +{ + fclose(d_fp); +} + + +int +gr_wavfile_source::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float **out = (float **) &output_items[0]; + int n_out_chans = output_items.size(); + + int i; + short sample; + + for (i = 0; i < noutput_items; i++) { + if (d_sample_idx >= d_samples_per_chan) { + if (!d_repeat) { + // if nothing was read at all, say we're done. + return i ? i : -1; + } + + if (fseek (d_fp, d_first_sample_pos, SEEK_SET) == -1) { + fprintf(stderr, "[%s] fseek failed\n", __FILE__); + exit(-1); + } + + d_sample_idx = 0; + } + + for (int chan = 0; chan < d_nchans; chan++) { + sample = gri_wav_read_sample(d_fp, d_bytes_per_sample); + + if (chan < n_out_chans) { + out[chan][i] = convert_to_float(sample); + } + } + + d_sample_idx++; + + // OK, EOF is not necessarily an error. But we're not going to + // deal with handling corrupt wav files, so if they give us any + // trouble they won't be processed. Serves them bloody right. + if (feof(d_fp) || ferror(d_fp)) { + if (i == 0) { + fprintf(stderr, "[%s] WAV file has corrupted header or i/o error\n", __FILE__); + return -1; + } + return i; + } + } + + return noutput_items; +} + + +float +gr_wavfile_source::convert_to_float(short int sample) +{ + float sample_out = (float) sample; + sample_out /= d_normalize_fac; + sample_out -= d_normalize_shift; + return sample_out; +} diff --git a/gnuradio-core/src/lib/io/gr_wavfile_source.h b/gnuradio-core/src/lib/io/gr_wavfile_source.h new file mode 100644 index 000000000..02e6e3678 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_wavfile_source.h @@ -0,0 +1,95 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_WAVFILE_SOURCE_H +#define INCLUDED_GR_WAVFILE_SOURCE_H + +#include <gr_core_api.h> +#include <gr_sync_block.h> +#include <cstdio> // for FILE + +class gr_wavfile_source; +typedef boost::shared_ptr<gr_wavfile_source> gr_wavfile_source_sptr; + +GR_CORE_API gr_wavfile_source_sptr +gr_make_wavfile_source (const char *filename, bool repeat = false); + +/*! + * \brief Read stream from a Microsoft PCM (.wav) file, output floats + * + * Unless otherwise called, values are within [-1;1]. + * Check gr_make_wavfile_source() for extra info. + * + * \ingroup source_blk + */ + +class GR_CORE_API gr_wavfile_source : public gr_sync_block +{ +private: + friend GR_CORE_API gr_wavfile_source_sptr gr_make_wavfile_source (const char *filename, + bool repeat); + gr_wavfile_source(const char *filename, bool repeat); + + FILE *d_fp; + bool d_repeat; + + unsigned d_sample_rate; + int d_nchans; + int d_bytes_per_sample; + int d_first_sample_pos; + unsigned d_samples_per_chan; + unsigned d_sample_idx; + int d_normalize_shift; + int d_normalize_fac; + + /*! + * \brief Convert an integer sample value to a float value within [-1;1] + */ + float convert_to_float(short int sample); + +public: + ~gr_wavfile_source (); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + /*! + * \brief Read the sample rate as specified in the wav file header + */ + unsigned int sample_rate() const { return d_sample_rate; }; + + /*! + * \brief Return the number of bits per sample as specified in the wav + * file header. Only 8 or 16 bit are supported here. + */ + int bits_per_sample() const { return d_bytes_per_sample * 8; }; + + /*! + * \brief Return the number of channels in the wav file as specified in + * the wav file header. This is also the max number of outputs you can + * have. + */ + int channels() const { return d_nchans; }; +}; + +#endif /* INCLUDED_GR_WAVFILE_SOURCE_H */ diff --git a/gnuradio-core/src/lib/io/gr_wavfile_source.i b/gnuradio-core/src/lib/io/gr_wavfile_source.i new file mode 100644 index 000000000..5af2224f1 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_wavfile_source.i @@ -0,0 +1,42 @@ +/* -*- 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,wavfile_source); + +gr_wavfile_source_sptr +gr_make_wavfile_source (const char *filename, + bool repeat = false) throw (std::runtime_error); + +class gr_wavfile_source : public gr_sync_block +{ +private: + gr_wavfile_source(const char *filename, + bool repeat) throw (std::runtime_error); + +public: + ~gr_wavfile_source(); + + unsigned int sample_rate(); + int bits_per_sample(); + int channels(); +}; + diff --git a/gnuradio-core/src/lib/io/gri_wavfile.cc b/gnuradio-core/src/lib/io/gri_wavfile.cc new file mode 100644 index 000000000..277e6b7b0 --- /dev/null +++ b/gnuradio-core/src/lib/io/gri_wavfile.cc @@ -0,0 +1,251 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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 <gri_wavfile.h> +#include <cstring> +#include <stdint.h> +#include <boost/detail/endian.hpp> //BOOST_BIG_ENDIAN + +# define VALID_COMPRESSION_TYPE 0x0001 + +// Basically, this is the opposite of htonx() and ntohx() +// Define host to/from worknet (little endian) short and long +#ifdef BOOST_BIG_ENDIAN + + static inline uint16_t __gri_wav_bs16(uint16_t x) + { + return (x>>8) | (x<<8); + } + + static inline uint32_t __gri_wav_bs32(uint32_t x) + { + return (uint32_t(__gri_wav_bs16(uint16_t(x&0xfffful)))<<16) | (__gri_wav_bs16(uint16_t(x>>16))); + } + + #define htowl(x) __gri_wav_bs32(x) + #define wtohl(x) __gri_wav_bs32(x) + #define htows(x) __gri_wav_bs16(x) + #define wtohs(x) __gri_wav_bs16(x) + +#else + + #define htowl(x) uint32_t(x) + #define wtohl(x) uint32_t(x) + #define htows(x) uint16_t(x) + #define wtohs(x) uint16_t(x) + +#endif // BOOST_BIG_ENDIAN + +// WAV files are always little-endian, so we need some byte switching macros +static inline uint32_t host_to_wav(uint32_t x) { return htowl(x); } +static inline uint16_t host_to_wav(uint16_t x) { return htows(x); } +static inline int16_t host_to_wav(int16_t x) { return htows(x); } +static inline uint32_t wav_to_host(uint32_t x) { return wtohl(x); } +static inline uint16_t wav_to_host(uint16_t x) { return wtohs(x); } +static inline int16_t wav_to_host(int16_t x) { return wtohs(x); } + +bool +gri_wavheader_parse(FILE *fp, + unsigned int &sample_rate_o, + int &nchans_o, + int &bytes_per_sample_o, + int &first_sample_pos_o, + unsigned int &samples_per_chan_o) +{ + // _o variables take return values + char str_buf[8] = {0}; + + uint32_t file_size; + uint32_t fmt_hdr_skip; + uint16_t compression_type; + uint16_t nchans; + uint32_t sample_rate; + uint32_t avg_bytes_per_sec; + uint16_t block_align; + uint16_t bits_per_sample; + uint32_t chunk_size; + + size_t fresult; + + fresult = fread(str_buf, 1, 4, fp); + if (fresult != 4 || strncmp(str_buf, "RIFF", 4) || feof(fp)) { + return false; + } + + fresult = fread(&file_size, 1, 4, fp); + + fresult = fread(str_buf, 1, 8, fp); + if (fresult != 8 || strncmp(str_buf, "WAVEfmt ", 8) || feof(fp)) { + return false; + } + + fresult = fread(&fmt_hdr_skip, 1, 4, fp); + + fresult = fread(&compression_type, 1, 2, fp); + if (wav_to_host(compression_type) != VALID_COMPRESSION_TYPE) { + return false; + } + + fresult = fread(&nchans, 1, 2, fp); + fresult = fread(&sample_rate, 1, 4, fp); + fresult = fread(&avg_bytes_per_sec, 1, 4, fp); + fresult = fread(&block_align, 1, 2, fp); + fresult = fread(&bits_per_sample, 1, 2, fp); + + if (ferror(fp)) { + return false; + } + + fmt_hdr_skip = wav_to_host(fmt_hdr_skip); + nchans = wav_to_host(nchans); + sample_rate = wav_to_host(sample_rate); + bits_per_sample = wav_to_host(bits_per_sample); + + if (bits_per_sample != 8 && bits_per_sample != 16) { + return false; + } + + fmt_hdr_skip -= 16; + if (fmt_hdr_skip) { + fseek(fp, fmt_hdr_skip, SEEK_CUR); + } + + // data chunk + fresult = fread(str_buf, 1, 4, fp); + if (strncmp(str_buf, "data", 4)) { + return false; + } + + fresult = fread(&chunk_size, 1, 4, fp); + if (ferror(fp)) { + return false; + } + + // More byte swapping + chunk_size = wav_to_host(chunk_size); + + // Output values + sample_rate_o = (unsigned) sample_rate; + nchans_o = (int) nchans; + bytes_per_sample_o = (int) (bits_per_sample / 8); + first_sample_pos_o = (int) ftell(fp); + samples_per_chan_o = (unsigned) (chunk_size / (bytes_per_sample_o * nchans)); + return true; +} + + +short int +gri_wav_read_sample(FILE *fp, int bytes_per_sample) +{ + int16_t buf_16bit; + + if(!fread(&buf_16bit, bytes_per_sample, 1, fp)) { + return 0; + } + if(bytes_per_sample == 1) { + return (short) buf_16bit; + } + return (short)wav_to_host(buf_16bit); +} + + +bool +gri_wavheader_write(FILE *fp, + unsigned int sample_rate, + int nchans, + int bytes_per_sample) +{ + const int header_len = 44; + char wav_hdr[header_len] = "RIFF\0\0\0\0WAVEfmt \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0data\0\0\0"; + uint16_t nchans_f = (uint16_t) nchans; + uint32_t sample_rate_f = (uint32_t) sample_rate; + uint16_t block_align = bytes_per_sample * nchans; + uint32_t avg_bytes = sample_rate * block_align; + uint16_t bits_per_sample = bytes_per_sample * 8; + + nchans_f = host_to_wav(nchans_f); + sample_rate_f = host_to_wav(sample_rate_f); + block_align = host_to_wav(block_align); + avg_bytes = host_to_wav(avg_bytes); + bits_per_sample = host_to_wav(bits_per_sample); + + wav_hdr[16] = 0x10; // no extra bytes + wav_hdr[20] = 0x01; // no compression + memcpy((void *) (wav_hdr + 22), (void *) &nchans_f, 2); + memcpy((void *) (wav_hdr + 24), (void *) &sample_rate_f, 4); + memcpy((void *) (wav_hdr + 28), (void *) &avg_bytes, 4); + memcpy((void *) (wav_hdr + 32), (void *) &block_align, 2); + memcpy((void *) (wav_hdr + 34), (void *) &bits_per_sample, 2); + + fwrite(&wav_hdr, 1, header_len, fp); + if (ferror(fp)) { + return false; + } + + return true; +} + + +void +gri_wav_write_sample(FILE *fp, short int sample, int bytes_per_sample) +{ + void *data_ptr; + unsigned char buf_8bit; + int16_t buf_16bit; + + if (bytes_per_sample == 1) { + buf_8bit = (unsigned char) sample; + data_ptr = (void *) &buf_8bit; + } else { + buf_16bit = host_to_wav((int16_t) sample); + data_ptr = (void *) &buf_16bit; + } + + fwrite(data_ptr, 1, bytes_per_sample, fp); +} + + +bool +gri_wavheader_complete(FILE *fp, unsigned int byte_count) +{ + uint32_t chunk_size = (uint32_t) byte_count; + chunk_size = host_to_wav(chunk_size); + + fseek(fp, 40, SEEK_SET); + fwrite(&chunk_size, 1, 4, fp); + + chunk_size = (uint32_t) byte_count + 36; // fmt chunk and data header + chunk_size = host_to_wav(chunk_size); + fseek(fp, 4, SEEK_SET); + + fwrite(&chunk_size, 1, 4, fp); + + if (ferror(fp)) { + return false; + } + + return true; +} diff --git a/gnuradio-core/src/lib/io/gri_wavfile.h b/gnuradio-core/src/lib/io/gri_wavfile.h new file mode 100644 index 000000000..16280e34a --- /dev/null +++ b/gnuradio-core/src/lib/io/gri_wavfile.h @@ -0,0 +1,96 @@ +/* -*- 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. + */ + +// This file stores all the RIFF file type knowledge for the gr_wavfile_* +// blocks. + +#include <gr_core_api.h> +#include <cstdio> + +/*! + * \brief Read signal information from a given WAV file. + * + * \param[in] fp File pointer to an opened, empty file. + * \param[out] sample_rate Stores the sample rate [S/s] + * \param[out] nchans Number of channels + * \param[out] bytes_per_sample Bytes per sample, can either be 1 or 2 (corresponding o + * 8 or 16 bit samples, respectively) + * \param[out] first_sample_pos Number of the first byte containing a sample. Use this + * with fseek() to jump from the end of the file to the + * first sample when in repeat mode. + * \param[out] samples_per_chan Number of samples per channel + * \return True on a successful read, false if the file could not be read or is + * not a valid WAV file. + */ +bool +gri_wavheader_parse(FILE *fp, + unsigned int &sample_rate, + int &nchans, + int &bytes_per_sample, + int &first_sample_pos, + unsigned int &samples_per_chan); + + +/*! + * \brief Read one sample from an open WAV file at the current position. + * + * Takes care of endianness. + */ +short int +gri_wav_read_sample(FILE *fp, int bytes_per_sample); + + +/*! + * \brief Write a valid RIFF file header + * + * Note: Some header values are kept blank because they're usually not known + * a-priori (file and chunk lengths). Use gri_wavheader_complete() to fill + * these in. + */ +bool +gri_wavheader_write(FILE *fp, + unsigned int sample_rate, + int nchans, + int bytes_per_sample); + +/*! + * \brief Write one sample to an open WAV file at the current position. + * + * Takes care of endianness. + */ +void +gri_wav_write_sample(FILE *fp, short int sample, int bytes_per_sample); + + +/*! + * \brief Complete a WAV header + * + * Note: The stream position is changed during this function. If anything + * needs to be written to the WAV file after calling this function (which + * shouldn't happen), you need to fseek() to the end of the file (or + * whereever). + * + * \param[in] fp File pointer to an open WAV file with a blank header + * \param[in] byte_count Length of all samples written to the file in bytes. + */ +bool +gri_wavheader_complete(FILE *fp, unsigned int byte_count); diff --git a/gnuradio-core/src/lib/io/i2c.cc b/gnuradio-core/src/lib/io/i2c.cc new file mode 100644 index 000000000..02dd47b53 --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c.cc @@ -0,0 +1,28 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,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. + */ + +#include "i2c.h" + +i2c::~i2c () +{ + // NOP +} diff --git a/gnuradio-core/src/lib/io/i2c.h b/gnuradio-core/src/lib/io/i2c.h new file mode 100644 index 000000000..6b7f25a29 --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c.h @@ -0,0 +1,49 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,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_I2C_H +#define INCLUDED_I2C_H + +#include <gr_core_api.h> +#include <boost/shared_ptr.hpp> + +class i2c; +typedef boost::shared_ptr<i2c> i2c_sptr; + +/*! + * \brief abstract class for controlling i2c bus + */ +class GR_CORE_API i2c { + public: + + i2c () {} + virtual ~i2c (); + + //! \returns true iff successful + virtual bool write (int addr, const unsigned char *buf, int nbytes) = 0; + + //! \returns number of bytes read or -1 if error + virtual int read (int addr, unsigned char *buf, int max_bytes) = 0; +}; + +#endif /* INCLUDED_I2C_H */ + diff --git a/gnuradio-core/src/lib/io/i2c_bbio.cc b/gnuradio-core/src/lib/io/i2c_bbio.cc new file mode 100644 index 000000000..ddd00290d --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c_bbio.cc @@ -0,0 +1,29 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,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. + */ + +#include "i2c_bbio.h" + +i2c_bbio::~i2c_bbio () +{ + // NOP +} + diff --git a/gnuradio-core/src/lib/io/i2c_bbio.h b/gnuradio-core/src/lib/io/i2c_bbio.h new file mode 100644 index 000000000..6bf47b9cd --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c_bbio.h @@ -0,0 +1,51 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,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_I2C_BBIO_H +#define INCLUDED_I2C_BBIO_H + +#include <gr_core_api.h> +#include <boost/shared_ptr.hpp> + +class i2c_bbio; +typedef boost::shared_ptr<i2c_bbio> i2c_bbio_sptr; + + +/*! + * \brief abstract class that implements bit banging i/o for i2c bus. + * \ingroup base + */ +class GR_CORE_API i2c_bbio { + public: + + i2c_bbio () {} + virtual ~i2c_bbio (); + + virtual void set_scl (bool state) = 0; + virtual void set_sda (bool state) = 0; + virtual bool get_sda () = 0; + + virtual void lock () = 0; + virtual void unlock () = 0; +}; + +#endif /* INCLUDED_I2C_BBIO_H */ diff --git a/gnuradio-core/src/lib/io/i2c_bbio_pp.cc b/gnuradio-core/src/lib/io/i2c_bbio_pp.cc new file mode 100644 index 000000000..382bb6b37 --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c_bbio_pp.cc @@ -0,0 +1,87 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,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. + */ + +#include "i2c_bbio_pp.h" +#include "microtune_eval_board_defs.h" + +i2c_bbio_pp::i2c_bbio_pp (ppio_sptr pp) +{ + d_pp = pp; + d_pp->lock (); + d_pp->write_control (d_pp->read_control () & ~UT_CP_MUST_BE_ZERO); // output, no interrupts + d_pp->unlock (); +} + +i2c_bbio_sptr +make_i2c_bbio_pp (ppio_sptr pp) +{ + return i2c_bbio_sptr (new i2c_bbio_pp (pp)); +} + +void +i2c_bbio_pp::set_scl (bool state) +{ + int r = d_pp->read_control(); + + if (!state){ // active low + d_pp->write_control (r | UT_CP_TUNER_SCL); + } + else { + d_pp->write_control (r & ~UT_CP_TUNER_SCL); + } + d_pp->read_control (); // use for 1us delay + d_pp->read_control (); // use for 1us delay +} + +void +i2c_bbio_pp::set_sda (bool state) +{ + int r = d_pp->read_data (); + + if (!state){ // active low + d_pp->write_data (r | UT_DP_TUNER_SDA_OUT); + } + else { + d_pp->write_data (r & ~UT_DP_TUNER_SDA_OUT); + } + d_pp->read_data (); // use for 1us delay + d_pp->read_data (); // use for 1us delay +} + +bool +i2c_bbio_pp::get_sda () +{ + int r = d_pp->read_status (); + return (r & UT_SP_TUNER_SDA_IN) == 0; // eval board has an inverter on it +} + +void +i2c_bbio_pp::lock () +{ + d_pp->lock (); +} + +void +i2c_bbio_pp::unlock () +{ + d_pp->unlock (); +} diff --git a/gnuradio-core/src/lib/io/i2c_bbio_pp.h b/gnuradio-core/src/lib/io/i2c_bbio_pp.h new file mode 100644 index 000000000..2391bc1fc --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c_bbio_pp.h @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,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_I2C_BBIO_PP_H +#define INCLUDED_I2C_BBIO_PP_H + +#include <gr_core_api.h> +#include "i2c_bbio.h" +#include "ppio.h" + +/*! + * \brief concrete class that bit bangs eval board i2c bus using parallel port + * + * \ingroup base + * This class talks to the i2c bus on the microtune eval board using + * the parallel port. This works for both the 4937 and 4702 boards. + */ +class GR_CORE_API i2c_bbio_pp : public i2c_bbio { + friend GR_CORE_API i2c_bbio_sptr make_i2c_bbio_pp (ppio_sptr pp); + i2c_bbio_pp (ppio_sptr pp); + + public: + + virtual void set_scl (bool state); + virtual void set_sda (bool state); + virtual bool get_sda (); + + virtual void lock (); + virtual void unlock (); + + private: + ppio_sptr d_pp; +}; + +GR_CORE_API i2c_bbio_sptr make_i2c_bbio_pp (ppio_sptr pp); + + +#endif /* INCLUDED_I2C_BBIO_PP_H */ diff --git a/gnuradio-core/src/lib/io/i2c_bitbang.cc b/gnuradio-core/src/lib/io/i2c_bitbang.cc new file mode 100644 index 000000000..eb801c68f --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c_bitbang.cc @@ -0,0 +1,144 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,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. + */ + +#include "i2c_bitbang.h" + +i2c_bitbang::i2c_bitbang (i2c_bbio_sptr io) +{ + d_io = io; + d_io->lock (); + + stop (); // get bus in known state + + d_io->unlock (); +} + +i2c_sptr +make_i2c_bitbang (i2c_bbio_sptr io) +{ + return i2c_sptr (new i2c_bitbang (io)); +} + + +// start: +// entry: SCL = 1, SDA = 1 +// exit: SCL = 0, SDA = 0 + +void +i2c_bitbang::start () +{ + set_sda (1); + set_scl (1); + set_sda (0); // SDA high -> low while SCL high + set_scl (0); +} + + +// stop: +// entry: SCL = X, SDA = X +// exit: SCL = 1, SDA = 1 + +void +i2c_bitbang::stop () +{ + set_scl (0); + set_sda (0); + set_scl (1); + set_sda (1); // SDA low -> high while SCL high +} + + +// write_bit: +// entry: SCL = 0, SDA = X +// exit: SCL = 0, SDA = X + +void +i2c_bitbang::write_bit (bool bit) +{ + set_sda (bit); + set_scl (1); + set_scl (0); +} + + +// write_byte: +// entry: SCL = 0, SDA = X +// exit: SCL = 0, SDA = 1 + +bool +i2c_bitbang::write_byte (char t) +{ + int i; + bool ack_bit; + + for (i = 0; i < 8; i++){ + write_bit (t & 0x80); + t <<= 1; + } + + // clock #9. This is the ACK bit. + + set_sda (1); // tristate SDA + set_scl (1); + ack_bit = get_sda (); // slave should pull SDA line low + set_scl (0); + + return ack_bit == 0; +} + + +// write: the high level entry point... +// entry: SCL = 1, SDA = 1 +// exit: SCL = 1, SDA = 1 + +bool +i2c_bitbang::write (int addr, const unsigned char *buf, int nbytes) +{ + bool ok = true; + + d_io->lock (); + start (); + ok = write_byte ((addr << 1) | 0); // addr plus "read opcode" + + for (int i = 0; i < nbytes; i++) + ok &= write_byte (buf[i]); + + stop (); + d_io->unlock (); + return ok; +} + + +// read: the high level entry point... +// entry: SCL = 1, SDA = 1 +// exit: SCL = 1, SDA = 1 + +int +i2c_bitbang::read (int addr, unsigned char *buf, int max_bytes) +{ + d_io->lock (); + + // FIXME + + d_io->unlock (); + return -1; +} diff --git a/gnuradio-core/src/lib/io/i2c_bitbang.h b/gnuradio-core/src/lib/io/i2c_bitbang.h new file mode 100644 index 000000000..1d6fe5044 --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c_bitbang.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,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_I2C_BITBANG_H +#define INCLUDED_I2C_BITBANG_H + +#include <gr_core_api.h> +#include <i2c.h> +#include <i2c_bbio.h> + +/*! + * \brief class for controlling i2c bus + * \ingroup base + */ +class GR_CORE_API i2c_bitbang : public i2c { + friend GR_CORE_API i2c_sptr make_i2c_bitbang (i2c_bbio_sptr io); + i2c_bitbang (i2c_bbio_sptr io); + + public: + ~i2c_bitbang () {} + + //! \returns true iff successful + bool write (int addr, const unsigned char *buf, int nbytes); + + //! \returns number of bytes read or -1 if error + int read (int addr, unsigned char *buf, int max_bytes); + + +private: + void start (); + void stop (); + void write_bit (bool bit); + bool write_byte (char byte); + + void set_sda (bool bit) { d_io->set_sda (bit); } + void set_scl (bool bit) { d_io->set_scl (bit); } + bool get_sda () { return d_io->get_sda (); } + + i2c_bbio_sptr d_io; +}; + +GR_CORE_API i2c_sptr make_i2c_bitbang (i2c_bbio_sptr io); + +#endif /* INCLUDED_I2C_BITBANG_H */ + + diff --git a/gnuradio-core/src/lib/io/io.i b/gnuradio-core/src/lib/io/io.i new file mode 100644 index 000000000..e2de4eb97 --- /dev/null +++ b/gnuradio-core/src/lib/io/io.i @@ -0,0 +1,83 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +%{ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_file_sink.h> +#include <gr_file_source.h> +#include <gr_file_descriptor_sink.h> +#include <gr_file_descriptor_source.h> +#include <gr_histo_sink_f.h> +#include <microtune_4702_eval_board.h> +#include <microtune_4937_eval_board.h> +#include <sdr_1000.h> +#include <gr_oscope_sink_x.h> +#include <gr_oscope_sink_f.h> +#include <ppio.h> +#include <gr_message_source.h> +#include <gr_message_burst_source.h> +#include <gr_message_sink.h> +#include <gr_udp_sink.h> +#include <gr_udp_source.h> +#include <gr_wavfile_sink.h> +#include <gr_wavfile_source.h> +#include <gr_tagged_file_sink.h> +#include <gr_pdu_to_tagged_stream.h> +#include <gr_tagged_stream_to_pdu.h> +#include <gr_message_debug.h> +#include <gr_pdu.h> +#include <gr_tuntap_pdu.h> +#include <gr_socket_pdu.h> +%} + +%include "gr_file_sink_base.i" +%include "gr_file_sink.i" +%include "gr_file_source.i" +%include "gr_file_descriptor_sink.i" +%include "gr_file_descriptor_source.i" +%include "gr_histo_sink.i" +%include "microtune_xxxx_eval_board.i" +%include "microtune_4702_eval_board.i" +%include "microtune_4937_eval_board.i" +%include "sdr_1000.i" +%include "gr_oscope_sink.i" +%include "ppio.i" +%include "gr_message_source.i" +%include "gr_message_burst_source.i" +%include "gr_message_sink.i" +%include "gr_udp_sink.i" +%include "gr_udp_source.i" +%include "gr_wavfile_sink.i" +%include "gr_wavfile_source.i" +%include "gr_tagged_file_sink.i" +%include "gr_pdu_to_tagged_stream.i" +%include "gr_tagged_stream_to_pdu.i" +%include "gr_message_debug.i" +%include "gr_pdu.i" +%include "gr_tuntap_pdu.i" +%include "gr_socket_pdu.i" + + diff --git a/gnuradio-core/src/lib/io/microtune_4702.cc b/gnuradio-core/src/lib/io/microtune_4702.cc new file mode 100644 index 000000000..3ec072d51 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4702.cc @@ -0,0 +1,183 @@ +/* -*- c++-*- */ +/* + * Copyright 2001,2003,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. + */ + +#include "microtune_4702.h" +#include <stdlib.h> +#include <stdio.h> +#include "i2c.h" + +static const double FIRST_IF = 36.00e6; + +// The tuner internally has 3 bands: VHF Low, VHF High & UHF. +// These are the recommened boundaries +static const double VHF_High_takeover = 174e6; +static const double UHF_takeover = 470e6; + +static int PLL_I2C_ADDR = 0x60; + +static unsigned char +control_byte_1 (bool prescaler, int reference_divisor) +{ + int c = 0x80; + //Note: Last two divider bits (bits 2 and 3 of this byte) determined later + if (prescaler) + c |= 0x10; + + switch (reference_divisor){ + case 2: + c |= 0x00; break; + case 4: + c |= 0x01; break; + case 8: + c |= 0x02; break; + case 16: + c |= 0x03; break; + case 32: + c |= 0x04; break; + case 64: + c |= 0x05; break; + case 128: + c |= 0x06; break; + case 256: + c |= 0x07; break; + case 24: + c |= 0x08; break; + case 5: + c |= 0x09; break; + case 10: + c |= 0x0A; break; + case 20: + c |= 0x0B; break; + case 40: + c |= 0x0C; break; + case 80: + c |= 0x0D; break; + case 160: + c |= 0x0E; break; + case 320: + c |= 0x0F; break; + default: + abort (); + } + return c; +} + +static unsigned char +control_byte_2 (double target_freq) +{ + int c; + + if (target_freq < VHF_High_takeover) // VHF low + c = 0x8E; + + else if (target_freq < UHF_takeover){ // VHF high + c = 0x05; + if (target_freq < 390e6) + c |= 0x40; + else + c |= 0x80; + } + else { // UHF + c = 0x03; + if (target_freq < 750e6) + c |= 0x80; + else + c |= 0xC0; + } + + return c; +} + + +microtune_4702::microtune_4702 (i2c_sptr i2c, int i2c_addr) +{ + d_i2c = i2c; + d_i2c_addr = i2c_addr; + d_reference_divider = 320; + d_prescaler = false; +} + +microtune_4702::~microtune_4702 () +{ + // nop +} + +/*! + * \brief select RF frequency to be tuned to output frequency. + * \p target_freq is the requested frequency in Hz, \p actual_freq + * is set to the actual frequency tuned. It takes about 100 ms + * for the PLL to settle. + * + * \returns true iff sucessful. + */ +bool +microtune_4702::set_RF_freq (double target_freq, double *p_actual_freq) +{ + unsigned char buf[4]; + + double target_f_osc = target_freq + FIRST_IF; + + double f_ref = 4e6 / d_reference_divider; + + //int divisor = (int) ((target_f_osc + (f_ref * 4)) / (f_ref * 8)); + + long int divisor = (long int) (target_f_osc / f_ref); + double actual_freq = (f_ref * divisor) - FIRST_IF; + if (p_actual_freq != 0) + *p_actual_freq = actual_freq; + + if ((divisor & ~0x1ffff) != 0) // >17 bit divisor + return false; + + buf[0] = ((divisor & 0x07f00) >> 8) & 0xff; // DB1 + buf[1] = divisor & 0xff; // DB2 + buf[2] = control_byte_1 (d_prescaler, d_reference_divider); + buf[2] = buf[2] | (((divisor & 0x18000) >> 10) & 0xff); + buf[3] = control_byte_2 (target_freq); + + printf ("%x\n", PLL_I2C_ADDR); +//#if 0 + printf ("set_RF_freq: target: %g MHz actual: %g MHz %02x %02x %02x %02x\n", + target_freq/1e6, actual_freq/1e6, buf[0], buf[1], buf[2], buf[3]); +//#endif + + return d_i2c->write (d_i2c_addr, buf, sizeof (buf)); +} + +/*! + * \returns true iff PLL is locked + */ +bool +microtune_4702::pll_locked_p () +{ + // FIXME + return true; +} + +/*! + * \returns the output frequency of the tuner in Hz. + */ +double +microtune_4702::get_output_freq () +{ + return FIRST_IF; +} diff --git a/gnuradio-core/src/lib/io/microtune_4702.h b/gnuradio-core/src/lib/io/microtune_4702.h new file mode 100644 index 000000000..ccc66db71 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4702.h @@ -0,0 +1,71 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2003 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_MICROTUNE_4702_H +#define INCLUDED_MICROTUNE_4702_H + +#include <gr_core_api.h> +#include <microtune_xxxx.h> + +/*! + * \brief class for controlling microtune 4702 tuner module + * \ingroup hardware + */ + +class GR_CORE_API microtune_4702 : public microtune_xxxx { +public: + microtune_4702 (i2c_sptr i2c, int i2c_addr); + + virtual ~microtune_4702 (); + + /*! + * \brief select RF frequency to be tuned to output frequency. + * \p freq is the requested frequency in Hz, \p actual_freq + * is set to the actual frequency tuned. It takes about 100 ms + * for the PLL to settle. + * + * \returns true iff sucessful. + */ + bool set_RF_freq (double freq, double *actual_freq); + + /*! + * \returns true iff PLL is locked + */ + bool pll_locked_p (); + + /*! + * \returns the output frequency of the tuner in Hz. + */ + double get_output_freq (); + + private: + + i2c_sptr d_i2c; + int d_i2c_addr; + int d_reference_divider; + bool d_prescaler; /* if set, higher charge pump current: + faster tuning, worse phase noise + for distance < 10kHz to the carrier */ +}; + +#endif /* INCLUDED_MICROTUNE_4702_H */ + diff --git a/gnuradio-core/src/lib/io/microtune_4702_eval_board.cc b/gnuradio-core/src/lib/io/microtune_4702_eval_board.cc new file mode 100644 index 000000000..f6c68726b --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4702_eval_board.cc @@ -0,0 +1,88 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,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. + */ + +#include "microtune_4702_eval_board.h" +#include "microtune_eval_board_defs.h" +#include "ppio.h" +#include "microtune_4702.h" + +static const int TUNER_I2C_ADDR = 0x60; + +microtune_4702_eval_board::microtune_4702_eval_board (int which_pp) + : microtune_xxxx_eval_board (which_pp) +{ + d_tuner = new microtune_4702 (d_i2c, TUNER_I2C_ADDR); +} + +microtune_4702_eval_board::~microtune_4702_eval_board () +{ + // default is OK +} + +static const float RF_MIN_V = 1.0; // RF AGC control voltages +static const float RF_MAX_V = 4.0; +static const float IF_MIN_V = 2.0; // IF AGC control voltages +static const float IF_MAX_V = 4.0; + +static const float MIN_AGC = 0; // bottom of synthetic range +static const float MAX_AGC = 1000; // top of synthetic range + +static const float CUTOVER_POINT = 667; + + +// linear is in the range MIN_AGC to MAX_AGC + +static float +linear_to_RF_AGC_voltage (float linear) +{ + if (linear >= CUTOVER_POINT) + return RF_MAX_V; + + float slope = (RF_MAX_V - RF_MIN_V) / CUTOVER_POINT; + return RF_MIN_V + linear * slope; +} + +static float +linear_to_IF_AGC_voltage (float linear) +{ + if (linear < CUTOVER_POINT) + return IF_MIN_V; + + float slope = (IF_MAX_V - IF_MIN_V) / (MAX_AGC - CUTOVER_POINT); + return IF_MIN_V + (linear - CUTOVER_POINT) * slope; +} + +void +microtune_4702_eval_board::set_AGC (float v) +{ + if (v < MIN_AGC) + v = MIN_AGC; + + if (v > MAX_AGC) + v = MAX_AGC; + + float rf_agc_voltage = linear_to_RF_AGC_voltage (v); + float if_agc_voltage = linear_to_IF_AGC_voltage (v); + + set_RF_AGC_voltage (rf_agc_voltage); + set_IF_AGC_voltage (if_agc_voltage); +} diff --git a/gnuradio-core/src/lib/io/microtune_4702_eval_board.h b/gnuradio-core/src/lib/io/microtune_4702_eval_board.h new file mode 100644 index 000000000..d866a4b94 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4702_eval_board.h @@ -0,0 +1,49 @@ +/* -*- C++ -*- */ +/* + * Copyright 2001,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_MICROTUNE_4702_EVAL_BOARD_H +#define INCLUDED_MICROTUNE_4702_EVAL_BOARD_H + +#include <gr_core_api.h> +#include "microtune_xxxx_eval_board.h" + +/*! + * \brief control microtune 4702 eval board + * \ingroup hardware + */ + +class GR_CORE_API microtune_4702_eval_board : public microtune_xxxx_eval_board { +public: + microtune_4702_eval_board (int which_pp = 0); + ~microtune_4702_eval_board (); + + /*! + * \brief set RF and IF AGC levels together (scale [0, 1000]) + * + * This provides a simple linear interface for adjusting both + * the RF and IF gain in consort. This is the easy to use interface. + * 0 corresponds to minimum gain. 1000 corresponds to maximum gain. + */ + virtual void set_AGC (float value_0_1000); +}; + +#endif /* INCLUDED_MICROTUNE_4702_EVAL_BOARD_H */ diff --git a/gnuradio-core/src/lib/io/microtune_4702_eval_board.i b/gnuradio-core/src/lib/io/microtune_4702_eval_board.i new file mode 100644 index 000000000..fc085a975 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4702_eval_board.i @@ -0,0 +1,36 @@ +/* -*- C++ -*- */ +/* + * Copyright 2001,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. + */ + +class microtune_4702_eval_board : public microtune_xxxx_eval_board { +public: + microtune_4702_eval_board (int which_pp = 0); + ~microtune_4702_eval_board (); + + /*! + * \brief set RF and IF AGC levels together (scale [0, 1000]) + * + * This provides a simple linear interface for adjusting both + * the RF and IF gain in consort. This is the easy to use interface. + * 0 corresponds to minimum gain. 1000 corresponds to maximum gain. + */ + virtual void set_AGC (float value_0_1000); +}; diff --git a/gnuradio-core/src/lib/io/microtune_4937.cc b/gnuradio-core/src/lib/io/microtune_4937.cc new file mode 100644 index 000000000..72ddd4bb6 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4937.cc @@ -0,0 +1,146 @@ +/* -*- c++-*- */ +/* + * Copyright 2001,2003 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 "microtune_4937.h" +#include <stdlib.h> +#include <stdio.h> +#include <i2c.h> + +static const double first_IF = 43.75e6; + +// The tuner internally has 3 bands: VHF Low, VHF High & UHF. +// These are the recommened boundaries +static const double VHF_High_takeover = 158e6; +static const double UHF_takeover = 464e6; + + +static unsigned char +control_byte_1 (bool fast_tuning_p, int reference_divisor) +{ + int c = 0x88; + + if (fast_tuning_p) + c |= 0x40; + + switch (reference_divisor){ + case 512: + c |= 0x3 << 1; break; + case 640: + c |= 0x0 << 1; break; + case 1024: + c |= 0x1 << 1; break; + default: + abort (); + } + return c; +} + +static unsigned char +control_byte_2 (double target_freq, bool shutdown_tx_PGA) +{ + int c; + + if (target_freq < VHF_High_takeover) // VHF low + c = 0xa0; + else if (target_freq < UHF_takeover) // VHF high + c = 0x90; + else // UHF + c = 0x30; + + if (shutdown_tx_PGA) + c |= 0x08; + + return c; +} + +microtune_4937::microtune_4937 (i2c_sptr i2c, int i2c_addr) +{ + d_i2c = i2c; + d_i2c_addr = i2c_addr; + d_reference_divider = 640; + d_fast_tuning_p = false; +} + +microtune_4937::~microtune_4937 () +{ + // nop +} + +/*! + * \brief select RF frequency to be tuned to output frequency. + * \p target_freq is the requested frequency in Hz, \p actual_freq + * is set to the actual frequency tuned. It takes about 100 ms + * for the PLL to settle. + * + * \returns true iff sucessful. + */ +bool +microtune_4937::set_RF_freq (double target_freq, double *p_actual_freq) +{ + unsigned char buf[4]; + + double target_f_osc = target_freq + first_IF; + + double f_ref = 4e6 / d_reference_divider; + + // f_osc = f_ref * 8 * divisor + // divisor = f_osc / (f_ref * 8) + + int divisor = (int) ((target_f_osc + (f_ref * 4)) / (f_ref * 8)); + double actual_freq = (f_ref * 8 * divisor) - first_IF; + if (p_actual_freq != 0) + *p_actual_freq = actual_freq; + + if ((divisor & ~0x7fff) != 0) // 15 bit divisor + return false; + + buf[0] = (divisor >> 8) & 0xff; // DB1 + buf[1] = divisor & 0xff; // DB2 + buf[2] = control_byte_1 (d_fast_tuning_p, d_reference_divider); + buf[3] = control_byte_2 (target_freq, true); + +#if 0 + printf ("set_RF_freq: target: %g MHz actual: %g MHz %02x %02x %02x %02x\n", + target_freq/1e6, actual_freq/1e6, buf[0], buf[1], buf[2], buf[3]); +#endif + + return d_i2c->write (d_i2c_addr, buf, 4); +} + +/*! + * \returns true iff PLL is locked + */ +bool +microtune_4937::pll_locked_p () +{ + // FIXME + return true; +} + +/*! + * \returns the output frequency of the tuner in Hz. + */ +double +microtune_4937::get_output_freq () +{ + return 5.75e6; // 3x7702 +} diff --git a/gnuradio-core/src/lib/io/microtune_4937.h b/gnuradio-core/src/lib/io/microtune_4937.h new file mode 100644 index 000000000..be8657c95 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4937.h @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2003 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_MICROTUNE_4937_H +#define INCLUDED_MICROTUNE_4937_H + +#include <gr_core_api.h> +#include <microtune_xxxx.h> + +/*! + * \brief class for controlling microtune 4937 tuner module + * \ingroup hardware + */ +class GR_CORE_API microtune_4937 : public microtune_xxxx { +public: + microtune_4937 (i2c_sptr i2c, int i2c_addr = 0x61); + virtual ~microtune_4937 (); + + /*! + * \brief select RF frequency to be tuned to output frequency. + * \p freq is the requested frequency in Hz, \p actual_freq + * is set to the actual frequency tuned. It takes about 100 ms + * for the PLL to settle. + * + * \returns true iff sucessful. + */ + bool set_RF_freq (double freq, double *actual_freq); + + /*! + * \returns true iff PLL is locked + */ + bool pll_locked_p (); + + /*! + * \returns the output frequency (IF center freq) of the tuner in Hz. + */ + double get_output_freq (); + + private: + + i2c_sptr d_i2c; + int d_i2c_addr; + int d_reference_divider; + bool d_fast_tuning_p; /* if set, higher charge pump current: + faster tuning, worse phase noise + for distance < 10kHz to the carrier */ +}; + +#endif /* INCLUDED_MICROTUNE_4937_H */ diff --git a/gnuradio-core/src/lib/io/microtune_4937_eval_board.cc b/gnuradio-core/src/lib/io/microtune_4937_eval_board.cc new file mode 100644 index 000000000..a25b8addf --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4937_eval_board.cc @@ -0,0 +1,97 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,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. + */ + +#include "microtune_4937_eval_board.h" +#include "microtune_eval_board_defs.h" +#include "ppio.h" +#include "microtune_4937.h" + +static const int TUNER_I2C_ADDR = 0x61; + +microtune_4937_eval_board::microtune_4937_eval_board (int which_pp) + : microtune_xxxx_eval_board (which_pp) +{ + d_tuner = new microtune_4937 (d_i2c, TUNER_I2C_ADDR); + + // disable upstream amplifier + d_ppio->lock (); + int t = d_ppio->read_data (); + t &= ~(UT_DP_TX_ENABLE | UT_DP_TX_SDA | UT_DP_TX_SCL); + t |= UT_DP_TX_AS; + d_ppio->write_data (t); + d_ppio->unlock (); +} + +microtune_4937_eval_board::~microtune_4937_eval_board () +{ + // Default action is OK +} + + +static const float RF_MIN_V = 1.5; // RF AGC control voltages +static const float RF_MAX_V = 4.0; +static const float IF_MIN_V = 2.0; // IF AGC control voltages +static const float IF_MAX_V = 4.0; + +static const float MIN_AGC = 0; // bottom of synthetic range +static const float MAX_AGC = 1000; // top of synthetic range + +static const float CUTOVER_POINT = 667; + + +// linear is in the range MIN_AGC to MAX_AGC + +static float +linear_to_RF_AGC_voltage (float linear) +{ + if (linear >= CUTOVER_POINT) + return RF_MAX_V; + + float slope = (RF_MAX_V - RF_MIN_V) / CUTOVER_POINT; + return RF_MIN_V + linear * slope; +} + +static float +linear_to_IF_AGC_voltage (float linear) +{ + if (linear < CUTOVER_POINT) + return IF_MIN_V; + + float slope = (IF_MAX_V - IF_MIN_V) / (MAX_AGC - CUTOVER_POINT); + return IF_MIN_V + (linear - CUTOVER_POINT) * slope; +} + +void +microtune_4937_eval_board::set_AGC (float v) +{ + if (v < MIN_AGC) + v = MIN_AGC; + + if (v > MAX_AGC) + v = MAX_AGC; + + float rf_agc_voltage = linear_to_RF_AGC_voltage (v); + float if_agc_voltage = linear_to_IF_AGC_voltage (v); + + set_RF_AGC_voltage (rf_agc_voltage); + set_IF_AGC_voltage (if_agc_voltage); +} diff --git a/gnuradio-core/src/lib/io/microtune_4937_eval_board.h b/gnuradio-core/src/lib/io/microtune_4937_eval_board.h new file mode 100644 index 000000000..3abd9084e --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4937_eval_board.h @@ -0,0 +1,50 @@ +/* -*- C++ -*- */ +/* + * Copyright 2001,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_MICROTUNE_4937_EVAL_BOARD_H +#define INCLUDED_MICROTUNE_4937_EVAL_BOARD_H + +#include <gr_core_api.h> +#include "microtune_xxxx_eval_board.h" + +/*! + * \brief control microtune 4937 eval board + * \ingroup hardware + */ + +class GR_CORE_API microtune_4937_eval_board : public microtune_xxxx_eval_board { +public: + microtune_4937_eval_board (int which_pp = 0); + ~microtune_4937_eval_board (); + + /*! + * \brief set RF and IF AGC levels together (scale [0, 1000]) + * + * This provides a simple linear interface for adjusting both + * the RF and IF gain in consort. This is the easy to use interface. + * 0 corresponds to minimum gain. 1000 corresponds to maximum gain. + */ + virtual void set_AGC (float value_0_1000); +}; + + +#endif /* INCLUDED_MICROTUNE_4937_EVAL_BOARD_H */ diff --git a/gnuradio-core/src/lib/io/microtune_4937_eval_board.i b/gnuradio-core/src/lib/io/microtune_4937_eval_board.i new file mode 100644 index 000000000..e261416f7 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4937_eval_board.i @@ -0,0 +1,36 @@ +/* -*- C++ -*- */ +/* + * Copyright 2001,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. + */ + +class microtune_4937_eval_board : public microtune_xxxx_eval_board { +public: + microtune_4937_eval_board (int which_pp = 0); + ~microtune_4937_eval_board (); + + /*! + * \brief set RF and IF AGC levels together (scale [0, 1000]) + * + * This provides a simple linear interface for adjusting both + * the RF and IF gain in consort. This is the easy to use interface. + * 0 corresponds to minimum gain. 1000 corresponds to maximum gain. + */ + virtual void set_AGC (float value_0_1000); +}; diff --git a/gnuradio-core/src/lib/io/microtune_eval_board.i b/gnuradio-core/src/lib/io/microtune_eval_board.i new file mode 100644 index 000000000..f77ef47b4 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_eval_board.i @@ -0,0 +1,95 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 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. + */ + +/* + * SWIG interface defs for Microtune 4937 and eval board with Eric's daughterboard + */ + +/*! + * \brief abstract class for controlling microtune 4937 tuner module + */ +class microtune_4937 { +public: + microtune_4937 (); + + virtual ~microtune_4937 (); + + // returns actual freq or 0 if error (easier interface for SWIG) + double set_RF_freq (double freq); + + /*! + * \returns true iff PLL is locked + */ + bool pll_locked_p (); + + /*! + * \returns the output frequency (IF center freq) of the tuner in Hz. + */ + double get_output_freq (); + + + private: + //! \returns true iff successful + virtual bool i2c_write (int addr, const unsigned char *buf, int nbytes) = 0; + + //! \returns number of bytes read or -1 if error + virtual int i2c_read (int addr, unsigned char *buf, int max_bytes) = 0; + + int d_reference_divider; + bool d_fast_tuning_p; /* if set, higher charge pump current: + faster tuning, worse phase noise + for distance < 10kHz to the carrier */ +}; + +/*! + * \brief concrete class for controlling microtune 4937 eval board attached to parallel port + */ +class microtune_eval_board : public microtune_4937 { +public: + microtune_eval_board (int which_pp = 0); + ~microtune_eval_board (); + + //! is the eval board present? + bool board_present_p (); + + /*! + * \brief set RF and IF AGC control voltages ([0, 5] volts) + */ + void set_RF_AGC_voltage (float volts); + void set_IF_AGC_voltage (float volts); + + /*! + * \brief set RF and IF AGC levels together (scale [0, 1000]) + * + * This provides a simple linear interface for adjusting both + * the RF and IF gain in consort. This is the easy to use interface. + * 0 corresponds to minimum gain. 1000 corresponds to maximum gain. + */ + void set_AGC (float value_0_1000); + +private: + //! \returns true iff successful + virtual bool i2c_write (int addr, const unsigned char *buf, int nbytes); + + //! \returns number of bytes read or -1 if error + virtual int i2c_read (int addr, unsigned char *buf, int max_bytes); +}; diff --git a/gnuradio-core/src/lib/io/microtune_eval_board_defs.h b/gnuradio-core/src/lib/io/microtune_eval_board_defs.h new file mode 100644 index 000000000..61c52364f --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_eval_board_defs.h @@ -0,0 +1,71 @@ +/* -*-C-*- +******************************************************************************* +* +* File: microtune_eval_board_defs.h +* Description: defines for parallel port control of eval board +* +******************************************************************************* +*/ + +/* + * Copyright 2001 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 _MICROTUNE_EVAL_BOARD_DEFS_H_ +#define _MICROTUNE_EVAL_BOARD_DEFS_H_ + +/* + * The Microtune 4937DI5 cable modem tuner eval board is controlled + * by bit banging the PC parallel port. This file defines the relevant + * bits. + * + * The parallel port has an 8 bit data port (output), + * an 8 bit control port (output) and + * an 8 bit status port (input). + * + * Not all bits of the control and status ports may be arbitrarily used. + */ + + +// parallel port data port constants (output) + +static const int UT_DP_TX_SDA = 0x01; // upstream control bus +static const int UT_DP_TX_SCL = 0x02; // upstream control bus +static const int UT_DP_TX_AS = 0x04; // upstream control bus +static const int UT_DP_TX_ENABLE = 0x08; // upstream h/w enable +// bits 4,5,6 not used +static const int UT_DP_TUNER_SDA_OUT = 0x80; // tuner i2c bus data + +// parallel port control port constants (output) + +static const int UT_CP_TUNER_SCL = 0x08; // tuner i2c bus clock +static const int UT_CP_MUST_BE_ZERO = 0xf0; // must be zero + +// parallel port status port constants (input) + +// bits 0,1,2 not used +static const int UT_SP_TUNER_SCL_LOOP_BACK= 0x08; // inverted SCL loop back +static const int UT_SP_SHOULD_BE_ZERO = 0x10; // reads as zero +static const int UT_SP_SHOULD_BE_ONE = 0x20; // reads as one +// bit 6 not used +static const int UT_SP_TUNER_SDA_IN = 0x80; + + +#endif /* _MICROTUNE_EVAL_BOARD_DEFS_H_ */ diff --git a/gnuradio-core/src/lib/io/microtune_xxxx.cc b/gnuradio-core/src/lib/io/microtune_xxxx.cc new file mode 100644 index 000000000..3d55f534a --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_xxxx.cc @@ -0,0 +1,41 @@ +/* -*- c++-*- */ +/* + * Copyright 2001,2003,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. + */ + +#include "microtune_xxxx.h" + +microtune_xxxx::~microtune_xxxx () +{ + // nop +} + +double +microtune_xxxx::set_RF_freq (double target_freq) +{ + double actual_freq = 0.0; + + if (set_RF_freq (target_freq, &actual_freq)) + return actual_freq; + + return 0.0; +} + + diff --git a/gnuradio-core/src/lib/io/microtune_xxxx.h b/gnuradio-core/src/lib/io/microtune_xxxx.h new file mode 100644 index 000000000..b2646d39f --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_xxxx.h @@ -0,0 +1,66 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2003,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_MICROTUNE_XXXX_H +#define INCLUDED_MICROTUNE_XXXX_H + +#include <gr_core_api.h> +#include <boost/shared_ptr.hpp> + +class i2c; +typedef boost::shared_ptr<i2c> i2c_sptr; + +/*! + * \brief abstract class for controlling microtune {4937,4702} tuner modules + * \ingroup base + */ +class GR_CORE_API microtune_xxxx { +public: + microtune_xxxx () {} + virtual ~microtune_xxxx (); + + /*! + * \brief select RF frequency to be tuned to output frequency. + * \p freq is the requested frequency in Hz, \p actual_freq + * is set to the actual frequency tuned. It takes about 100 ms + * for the PLL to settle. + * + * \returns true iff sucessful. + */ + virtual bool set_RF_freq (double freq, double *actual_freq) = 0; + + // returns actual freq or 0 if error (easier interface for SWIG) + double set_RF_freq (double freq); + + /*! + * \returns true iff PLL is locked + */ + virtual bool pll_locked_p () = 0; + + /*! + * \returns the output frequency (IF center freq) of the tuner in Hz. + */ + virtual double get_output_freq () = 0; + +}; + +#endif /* INCLUDED_MICROTUNE_XXXX_H */ diff --git a/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.cc b/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.cc new file mode 100644 index 000000000..35600ff06 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.cc @@ -0,0 +1,144 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "microtune_xxxx_eval_board.h" +#include "microtune_eval_board_defs.h" +#include "microtune_xxxx.h" +#include "ppio.h" +#include "i2c_bitbang.h" +#include "i2c_bbio_pp.h" +#include <cmath> + +static int AGC_DAC_I2C_ADDR = 0x2C; + +microtune_xxxx_eval_board::microtune_xxxx_eval_board (int which_pp) +{ + d_ppio = make_ppio (which_pp); + d_i2c = make_i2c_bitbang (make_i2c_bbio_pp (d_ppio)); + d_tuner = 0; +} + +microtune_xxxx_eval_board::~microtune_xxxx_eval_board () +{ + delete d_tuner; + d_tuner = 0; +} + + +//! is the eval board present? +bool +microtune_xxxx_eval_board::board_present_p () +{ + bool result = true; + d_ppio->lock (); + + int t = d_ppio->read_status (); + if ((t & UT_SP_SHOULD_BE_ZERO) != 0 + || (t & UT_SP_SHOULD_BE_ONE) != UT_SP_SHOULD_BE_ONE) + result = false; + + // could also see if SCL is looped back or not, but that seems like overkill + + d_ppio->unlock (); + return result; +} + +/* + * ---------------------------------------------------------------- + * AGC stuff + * + * We're using a MAX518 8-bit 5V dual dac for setting the AGC's + * ---------------------------------------------------------------- + */ +void +microtune_xxxx_eval_board::write_dac (int which, int value) +{ + unsigned char cmd[2]; + cmd[0] = which & 1; + cmd[1] = value; + d_i2c->write (AGC_DAC_I2C_ADDR, cmd, sizeof (cmd)); +} + +void +microtune_xxxx_eval_board::write_both_dacs (int value0, int value1) +{ + unsigned char cmd[4]; + cmd[0] = 0; + cmd[1] = value0; + cmd[2] = 1; + cmd[3] = value1; + d_i2c->write (AGC_DAC_I2C_ADDR, cmd, sizeof (cmd)); +} + +static int scale_volts (float volts) +{ + int n; + n = (int) rint (volts * (256 / 5.0)); + if (n < 0) + n = 0; + if (n > 255) + n = 255; + + return n; +} + +void +microtune_xxxx_eval_board::set_RF_AGC_voltage (float volts) +{ + write_dac (0, scale_volts (volts)); +} + +void +microtune_xxxx_eval_board::set_IF_AGC_voltage (float volts) +{ + write_dac (1, scale_volts (volts)); +} + +// delegate to tuner + +bool +microtune_xxxx_eval_board::set_RF_freq (double freq, double *actual_freq) +{ + return d_tuner->set_RF_freq (freq, actual_freq); +} + +double +microtune_xxxx_eval_board::set_RF_freq (double freq) +{ + return d_tuner->set_RF_freq (freq); +} + +bool +microtune_xxxx_eval_board::pll_locked_p () +{ + return d_tuner->pll_locked_p (); +} + +double +microtune_xxxx_eval_board::get_output_freq () +{ + return d_tuner->get_output_freq (); +} diff --git a/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.h b/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.h new file mode 100644 index 000000000..7fd784ade --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.h @@ -0,0 +1,98 @@ +/* -*- C++ -*- */ +/* + * Copyright 2001,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_MICROTUNE_XXXX_EVAL_BOARD_H +#define INCLUDED_MICROTUNE_XXXX_EVAL_BOARD_H + +#include <gr_core_api.h> +#include <boost/shared_ptr.hpp> + +class microtune_xxxx; + +class ppio; +typedef boost::shared_ptr<ppio> ppio_sptr; + +class i2c; +typedef boost::shared_ptr<i2c> i2c_sptr; + +/*! + * \brief abstract class for controlling microtune xxxx eval board + * \ingroup hardware + */ +class GR_CORE_API microtune_xxxx_eval_board { +public: + microtune_xxxx_eval_board (int which_pp = 0); + virtual ~microtune_xxxx_eval_board (); + + //! is the eval board present? + bool board_present_p (); + + /*! + * \brief set RF and IF AGC control voltages ([0, 5] volts) + */ + void set_RF_AGC_voltage (float volts); + void set_IF_AGC_voltage (float volts); + + /*! + * \brief set RF and IF AGC levels together (scale [0, 1000]) + * + * This provides a simple linear interface for adjusting both + * the RF and IF gain in consort. This is the easy to use interface. + * 0 corresponds to minimum gain. 1000 corresponds to maximum gain. + */ + virtual void set_AGC (float value_0_1000) = 0; + + /*! + * \brief select RF frequency to be tuned to output frequency. + * \p freq is the requested frequency in Hz, \p actual_freq + * is set to the actual frequency tuned. It takes about 100 ms + * for the PLL to settle. + * + * \returns true iff sucessful. + */ + bool set_RF_freq (double freq, double *actual_freq); + + // returns actual freq or 0 if error (easier interface for SWIG) + double set_RF_freq (double freq); + + /*! + * \returns true iff PLL is locked + */ + bool pll_locked_p (); + + /*! + * \returns the output frequency (IF center freq) of the tuner in Hz. + */ + double get_output_freq (); + + +private: + void write_dac (int which, int value); + void write_both_dacs (int val0, int val1); + +protected: + ppio_sptr d_ppio; + i2c_sptr d_i2c; + microtune_xxxx *d_tuner; +}; + +#endif /* INCLUDED_MICROTUNE_XXXX_EVAL_BOARD_H */ diff --git a/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.i b/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.i new file mode 100644 index 000000000..8a8a59742 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.i @@ -0,0 +1,58 @@ +/* -*- 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. + */ + +class microtune_xxxx_eval_board { +public: + microtune_xxxx_eval_board (int which_pp = 0); + virtual ~microtune_xxxx_eval_board (); + + //! is the eval board present? + bool board_present_p (); + + /*! + * \brief set RF and IF AGC control voltages ([0, 5] volts) + */ + void set_RF_AGC_voltage (float volts); + void set_IF_AGC_voltage (float volts); + + /*! + * \brief set RF and IF AGC levels together (scale [0, 1000]) + * + * This provides a simple linear interface for adjusting both + * the RF and IF gain in consort. This is the easy to use interface. + * 0 corresponds to minimum gain. 1000 corresponds to maximum gain. + */ + virtual void set_AGC (float value_0_1000) = 0; + + // returns actual freq or 0 if error (easier interface for SWIG) + double set_RF_freq (double freq); + + /*! + * \returns true iff PLL is locked + */ + bool pll_locked_p (); + + /*! + * \returns the output frequency (IF center freq) of the tuner in Hz. + */ + double get_output_freq (); +}; diff --git a/gnuradio-core/src/lib/io/ppio.cc b/gnuradio-core/src/lib/io/ppio.cc new file mode 100644 index 000000000..a5edc539c --- /dev/null +++ b/gnuradio-core/src/lib/io/ppio.cc @@ -0,0 +1,39 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 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 <ppio.h> +#include <ppio_ppdev.h> + +ppio::~ppio () +{ +} + +// Factory method. +// +// Right now, we've only got one subclass we like. If there were more, +// we'd instantiate the "right one" here. + +ppio_sptr +make_ppio (int which_pp) +{ + return make_ppio_ppdev (which_pp); +} diff --git a/gnuradio-core/src/lib/io/ppio.h b/gnuradio-core/src/lib/io/ppio.h new file mode 100644 index 000000000..d99f7bf79 --- /dev/null +++ b/gnuradio-core/src/lib/io/ppio.h @@ -0,0 +1,63 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2003 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_PPIO_H +#define INCLUDED_PPIO_H + +#include <gr_core_api.h> +#include <boost/shared_ptr.hpp> + +class ppio; +typedef boost::shared_ptr<ppio> ppio_sptr; + + +/*! + * \brief abstract class that provides low level access to parallel port bits + * \ingroup hardware + */ + +class GR_CORE_API ppio { + public: + ppio () {} + virtual ~ppio (); + + virtual void write_data (unsigned char v) = 0; + virtual unsigned char read_data () = 0; + virtual void write_control (unsigned char v) = 0; + virtual unsigned char read_control () = 0; + virtual unsigned char read_status () = 0; + + virtual void lock () = 0; + virtual void unlock () = 0; +}; + +/*! + * \brief Factory method. + * + * Split out from class to make life easier for SWIG + */ + +GR_CORE_API ppio_sptr make_ppio (int which_pp); + + +#endif /* INCLUDED_PPIO_H */ + diff --git a/gnuradio-core/src/lib/io/ppio.i b/gnuradio-core/src/lib/io/ppio.i new file mode 100644 index 000000000..6b95dcf88 --- /dev/null +++ b/gnuradio-core/src/lib/io/ppio.i @@ -0,0 +1,48 @@ +/* -*- 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. + */ + +class ppio; +typedef boost::shared_ptr<ppio> ppio_sptr; + +%template(ppio_sptr) boost::shared_ptr<ppio>; + +/*! + * \brief abstract class that provides low level access to parallel port bits + */ + +class ppio { + public: + ppio () {} + virtual ~ppio (); + + virtual void write_data (unsigned char v) = 0; + virtual unsigned char read_data () = 0; + virtual void write_control (unsigned char v) = 0; + virtual unsigned char read_control () = 0; + virtual unsigned char read_status () = 0; + + virtual void lock () = 0; + virtual void unlock () = 0; +}; + + +ppio_sptr make_ppio (int which_pp); diff --git a/gnuradio-core/src/lib/io/ppio_ppdev.cc b/gnuradio-core/src/lib/io/ppio_ppdev.cc new file mode 100644 index 000000000..f52845958 --- /dev/null +++ b/gnuradio-core/src/lib/io/ppio_ppdev.cc @@ -0,0 +1,321 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2003,2004,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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <ppio_ppdev.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdlib.h> +#include <iostream> +#include <errno.h> +#include <stdio.h> +#include <stdexcept> +#if defined(HAVE_LINUX_PPDEV_H) +#include <sys/ioctl.h> +#include <linux/ppdev.h> +#include <linux/parport.h> +#include <sstream> +#elif defined(HAVE_DEV_PPBUS_PPI_H) +#include <sys/ioctl.h> +#include <dev/ppbus/ppi.h> +#include <dev/ppbus/ppbconf.h> +#include <sstream> +#else +// #warn "ppio_ppdev is not functional on this platform" +#endif + +// These control port bits are active low. +// We toggle them so that this weirdness doesn't get get propagated +// through our interface. + +static int CP_ACTIVE_LOW_BITS = 0x0B; + +// These status port bits are active low. +// We toggle them so that this weirdness doesn't get get propagated +// through our interface. + +static int SP_ACTIVE_LOW_BITS = 0x80; + +#if defined(HAVE_LINUX_PPDEV_H) + +// The real Linux code... + +ppio_ppdev::ppio_ppdev (int which) +{ + std::ostringstream filename; + filename << "/dev/parport" << which; + const char *c_filename = filename.str().c_str(); + + if ((d_fd = open (c_filename, O_RDWR)) < 0){ + int my_errno = errno; + perror (c_filename); + if (my_errno == ENOENT){ + std::cerr << "Does the device file " << c_filename << " exist?\n"; + std::cerr << "If not, as root execute: \n"; + std::cerr << " # mknod " << c_filename << " c 99 0\n"; + std::cerr << " # chmod 666 " << c_filename << std::endl; + } + throw std::runtime_error ("open"); + } + + int mode = IEEE1284_MODE_COMPAT; + if (ioctl (d_fd, PPSETMODE, &mode) != 0){ + perror ("ppio_ppdev: PPSETMODE"); + close (d_fd); + throw std::runtime_error ("PPSETMODE"); + } +} + +ppio_ppdev::~ppio_ppdev () +{ + close (d_fd); +} + + +void +ppio_ppdev::write_data (unsigned char v) +{ + if (ioctl (d_fd, PPWDATA, &v) != 0){ + perror ("ppio_ppdev: PPWDATA"); + throw std::runtime_error ("PPWDATA"); + } +} + +unsigned char +ppio_ppdev::read_data () +{ + unsigned char v; + + if (ioctl (d_fd, PPRDATA, &v) != 0){ + perror ("ppio_ppdev: PPRDATA"); + throw std::runtime_error ("PPRDATA"); + } + return v; +} + +void +ppio_ppdev::write_control (unsigned char v) +{ + unsigned char ctrl = v ^ CP_ACTIVE_LOW_BITS; + if (ioctl (d_fd, PPWCONTROL, &ctrl) != 0){ + perror ("ppio_ppdev: PPWCONTROL"); + throw std::runtime_error ("PPWCONTROL"); + } +} + +unsigned char +ppio_ppdev::read_control () +{ + unsigned char ctrl; + if (ioctl (d_fd, PPRCONTROL, &ctrl) != 0){ + perror ("ppio_ppdev: PPRCONTROL"); + throw std::runtime_error ("PPRCONTROL"); + } + + return ctrl ^ CP_ACTIVE_LOW_BITS; +} + +unsigned char +ppio_ppdev::read_status () +{ + unsigned char status; + if (ioctl (d_fd, PPRSTATUS, &status) != 0){ + perror ("ppio_ppdev: PPRSTATUS"); + throw std::runtime_error ("PPRSTATUS"); + } + + return status ^ SP_ACTIVE_LOW_BITS; +} + +void +ppio_ppdev::lock () +{ + if (ioctl (d_fd, PPCLAIM) != 0){ + perror ("ppio_ppdev: PPCLAIM"); + throw std::runtime_error ("PPCLAIM"); + } +} + +void +ppio_ppdev::unlock () +{ + if (ioctl (d_fd, PPRELEASE) != 0){ + perror ("ppio_ppdev: PPRELEASE"); + throw std::runtime_error ("PPRELEASE"); + } +} + +#elif defined(HAVE_DEV_PPBUS_PPI_H) + +// The real FreeBSD code... (Could work on other BSDs as well) + +ppio_ppdev::ppio_ppdev (int which) +{ + std::ostringstream filename; + filename << "/dev/ppi" << which; + const char *c_filename = filename.str().c_str(); + if ((d_fd = open (c_filename, O_RDWR)) < 0){ + int my_errno = errno; + perror (c_filename); + throw std::runtime_error ("open"); + } + +#if 0 + int mode = IEEE1284_MODE_COMPAT; + if (ioctl (d_fd, PPSETMODE, &mode) != 0){ + perror ("ppio_ppdev: PPSETMODE"); + close (d_fd); + throw std::runtime_error ("PPSETMODE"); + } +#endif +} + +ppio_ppdev::~ppio_ppdev () +{ + close (d_fd); +} + + +void +ppio_ppdev::write_data (unsigned char v) +{ + if (ioctl (d_fd, PPISDATA, &v) != 0){ + perror ("ppio_ppdev: PPISDATA"); + throw std::runtime_error ("PPISDATA"); + } +} + +unsigned char +ppio_ppdev::read_data () +{ + unsigned char v; + + if (ioctl (d_fd, PPIGDATA, &v) != 0){ + perror ("ppio_ppdev: PPIGDATA"); + throw std::runtime_error ("PPIGDATA"); + } + return v; +} + +void +ppio_ppdev::write_control (unsigned char v) +{ + unsigned char ctrl = v ^ CP_ACTIVE_LOW_BITS; + if (ioctl (d_fd, PPISCTRL, &ctrl) != 0){ + perror ("ppio_ppdev: PPISCTRL"); + throw std::runtime_error ("PPISCTRL"); + } +} + +unsigned char +ppio_ppdev::read_control () +{ + unsigned char ctrl; + if (ioctl (d_fd, PPIGCTRL, &ctrl) != 0){ + perror ("ppio_ppdev: PPIGCTRL"); + throw std::runtime_error ("PPIGCTRL"); + } + + return ctrl ^ CP_ACTIVE_LOW_BITS; +} + +unsigned char +ppio_ppdev::read_status () +{ + unsigned char status; + if (ioctl (d_fd, PPIGSTATUS, &status) != 0){ + perror ("ppio_ppdev: PPIGSTATUS"); + throw std::runtime_error ("PPIGSTATUS"); + } + return status ^ SP_ACTIVE_LOW_BITS; +} + +void +ppio_ppdev::lock () +{ +} + +void +ppio_ppdev::unlock () +{ +} +#else +/* Apparently, non real code */ + +ppio_ppdev::ppio_ppdev (int which) +{ + std::cerr << "ppio_ppdev: Not implemented on this platform\n"; + throw std::runtime_error ("not implmeneted"); +} + +ppio_ppdev::~ppio_ppdev () +{ +} + +void +ppio_ppdev::write_data (unsigned char v) +{ +} + +unsigned char +ppio_ppdev::read_data () +{ + return 0; +} + +void +ppio_ppdev::write_control (unsigned char v) +{ +} + +unsigned char +ppio_ppdev::read_control () +{ + return 0; +} + +unsigned char +ppio_ppdev::read_status () +{ + return 0; +} + +void +ppio_ppdev::lock () +{ +} + +void +ppio_ppdev::unlock () +{ +} + +#endif + +ppio_ppdev_sptr +make_ppio_ppdev (int which) +{ + return ppio_ppdev_sptr (new ppio_ppdev (which)); +} diff --git a/gnuradio-core/src/lib/io/ppio_ppdev.h b/gnuradio-core/src/lib/io/ppio_ppdev.h new file mode 100644 index 000000000..1f86d7e04 --- /dev/null +++ b/gnuradio-core/src/lib/io/ppio_ppdev.h @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2001,2003 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_PPIO_PPDEV_H +#define INCLUDED_PPIO_PPDEV_H + +#include <gr_core_api.h> +#include <ppio.h> + +class ppio_ppdev; +typedef boost::shared_ptr<ppio_ppdev> ppio_ppdev_sptr; + +/*! + * \brief access to parallel port bits using the linux ppdev interface + * \ingroup hardware + */ + +class GR_CORE_API ppio_ppdev : public ppio { + friend GR_CORE_API ppio_ppdev_sptr make_ppio_ppdev (int which = 0); + ppio_ppdev (int which = 0); + + public: + virtual ~ppio_ppdev (); + + virtual void write_data (unsigned char v); + virtual unsigned char read_data (); + virtual void write_control (unsigned char v); + virtual unsigned char read_control (); + virtual unsigned char read_status (); + + virtual void lock (); + virtual void unlock (); + + private: + int d_fd; +}; + +ppio_ppdev_sptr +make_ppio_ppdev (int which); + + +#endif /* INCLUDED_PPIO_PPDEV_H */ + diff --git a/gnuradio-core/src/lib/io/sdr_1000.cc b/gnuradio-core/src/lib/io/sdr_1000.cc new file mode 100644 index 000000000..a8c2555e0 --- /dev/null +++ b/gnuradio-core/src/lib/io/sdr_1000.cc @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 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 <sdr_1000.h> +#include <ppio.h> + +sdr_1000_base::sdr_1000_base (int which_pp) +{ + d_ppio = make_ppio (which_pp); + d_shadow[0] = 0; + d_shadow[1] = 0; + d_shadow[2] = 0; + d_shadow[3] = 0; + reset (); +} + +sdr_1000_base::~sdr_1000_base () +{ +} + +void +sdr_1000_base::reset () +{ + d_ppio->lock (); + d_ppio->write_control (0x0F); + d_ppio->unlock (); + write_latch (L_EXT, 0x00, 0xff); + write_latch (L_BAND, 0x00, 0xff); + write_latch (L_DDS0, 0x80, 0xff); // hold DDS in reset + write_latch (L_DDS1, 0x00, 0xff); +} + + +void +sdr_1000_base::write_latch (int which, int value, int mask) +{ + if (!(0 <= which && which <= 3)) + return; + + d_ppio->lock (); + d_shadow[which] = (d_shadow[which] & ~mask) | (value & mask); + d_ppio->write_data (d_shadow[which]); + d_ppio->write_control (0x0F ^ (1 << which)); + d_ppio->write_control (0x0F); + d_ppio->unlock (); +} diff --git a/gnuradio-core/src/lib/io/sdr_1000.h b/gnuradio-core/src/lib/io/sdr_1000.h new file mode 100644 index 000000000..c00608a3a --- /dev/null +++ b/gnuradio-core/src/lib/io/sdr_1000.h @@ -0,0 +1,53 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,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_SDR_1000_H +#define INCLUDED_SDR_1000_H + +#include <gr_core_api.h> +#include <boost/shared_ptr.hpp> + +class ppio; +typedef boost::shared_ptr<ppio> ppio_sptr; + + +enum { L_EXT = 0, L_BAND = 1, L_DDS0 = 2, L_DDS1 = 3 }; + +/*! + * \brief Very low level interface to SDR 1000 xcvr hardware + * \sa sdr_1000.py for a higher level interface. + * \ingroup hardware + */ +class GR_CORE_API sdr_1000_base { + ppio_sptr d_ppio; + int d_shadow[4]; // shadow latches + +public: + + sdr_1000_base (int which_pp); + ~sdr_1000_base (); + + void reset (); + void write_latch (int which, int value, int mask); +}; + +#endif /* INCLUDED_SDR_1000_H */ diff --git a/gnuradio-core/src/lib/io/sdr_1000.i b/gnuradio-core/src/lib/io/sdr_1000.i new file mode 100644 index 000000000..c9b1ef560 --- /dev/null +++ b/gnuradio-core/src/lib/io/sdr_1000.i @@ -0,0 +1,36 @@ +/* -*- 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. + */ + +const int L_EXT = 0; +const int L_BAND = 1; +const int L_DDS0 = 2; +const int L_DDS1 = 3; + +class sdr_1000_base { +public: + + sdr_1000_base (int which_pp); + ~sdr_1000_base (); + + void reset (); + void write_latch (int which, int value, int mask); +}; diff --git a/gnuradio-core/src/lib/missing/CMakeLists.txt b/gnuradio-core/src/lib/missing/CMakeLists.txt new file mode 100644 index 000000000..85267ee48 --- /dev/null +++ b/gnuradio-core/src/lib/missing/CMakeLists.txt @@ -0,0 +1,32 @@ +# Copyright 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. + +######################################################################## +# This file included, use CMake directory variables +######################################################################## + +list(APPEND gnuradio_core_sources + ${CMAKE_CURRENT_SOURCE_DIR}/bug_work_around_8.cc +) + +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)") + list(APPEND gnuradio_core_sources + ${CMAKE_CURRENT_SOURCE_DIR}/posix_memalign.cc + ) +endif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(powerpc|ppc)") diff --git a/gnuradio-core/src/lib/missing/bug_work_around_8.cc b/gnuradio-core/src/lib/missing/bug_work_around_8.cc new file mode 100644 index 000000000..5e431a210 --- /dev/null +++ b/gnuradio-core/src/lib/missing/bug_work_around_8.cc @@ -0,0 +1,3 @@ +// if libmisc has no sources, it doesn't get built correctly +#include <gruel/attributes.h> +static int gr_bug_work_around_8 __GR_ATTR_UNUSED; diff --git a/gnuradio-core/src/lib/missing/getopt.c b/gnuradio-core/src/lib/missing/getopt.c new file mode 100644 index 000000000..69c7c16f7 --- /dev/null +++ b/gnuradio-core/src/lib/missing/getopt.c @@ -0,0 +1,733 @@ +/* Getopt for GNU. + NOTE: getopt is now part of the C library, so if you don't know what + "Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu + before changing it! + + Copyright (C) 1987, 88, 89, 90, 91, 92, 1993 + Free Software Foundation, Inc. + + This program 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. + + This program 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 this program; if not, write to the Free Software + Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +/* NOTE!!! AIX requires this to be the first thing in the file. + Do not put ANYTHING before it! */ +#if !defined (__GNUC__) && defined (_AIX) + #pragma alloca +#endif + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not __GNUC__ */ +#if defined (HAVE_ALLOCA_H) || (defined(sparc) && (defined(sun) || (!defined(USG) && !defined(SVR4) && !defined(__svr4__)))) +#include <alloca.h> +#else +#ifndef _AIX +char *alloca (); +#endif +#endif /* alloca.h */ +#endif /* not __GNUC__ */ + +#if !__STDC__ && !defined(const) && IN_GCC +#define const +#endif + +/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>. */ +#ifndef _NO_PROTO +#define _NO_PROTO +#endif + +#include <stdio.h> + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +#if defined (_LIBC) || !defined (__GNU_LIBRARY__) + + +/* This needs to come after some library #include + to get __GNU_LIBRARY__ defined. */ +#ifdef __GNU_LIBRARY__ +#undef alloca +/* Don't include stdlib.h for non-GNU C libraries because some of them + contain conflicting prototypes for getopt. */ +#include <stdlib.h> +#else /* Not GNU C library. */ +#define __alloca alloca +#endif /* GNU C library. */ + +/* If GETOPT_COMPAT is defined, `+' as well as `--' can introduce a + long-named option. Because this is not POSIX.2 compliant, it is + being phased out. */ +/* #define GETOPT_COMPAT */ + +/* This version of `getopt' appears to the caller like standard Unix `getopt' + but it behaves differently for the user, since it allows the user + to intersperse the options with the other arguments. + + As `getopt' works, it permutes the elements of ARGV so that, + when it is done, all the options precede everything else. Thus + all application programs are extended to handle flexible argument order. + + Setting the environment variable POSIXLY_CORRECT disables permutation. + Then the behavior is completely standard. + + GNU application programs can use a third alternative mode in which + they can distinguish the relative order of options and other arguments. */ + +#include "getopt.h" + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +char *optarg = 0; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +/* XXX 1003.2 says this must be 1 before any call. */ +int optind = 0; + +/* The next char to be scanned in the option-element + in which the last option character we returned was found. + This allows us to pick up the scan where we left off. + + If this is zero, or a null string, it means resume the scan + by advancing to the next ARGV-element. */ + +static char *nextchar; + +/* Callers store zero here to inhibit the error message + for unrecognized options. */ + +int opterr = 1; + +/* Set to an option character which was unrecognized. + This must be initialized on some systems to avoid linking in the + system's own getopt implementation. */ + +int optopt = '?'; + +/* Describe how to deal with options that follow non-option ARGV-elements. + + If the caller did not specify anything, + the default is REQUIRE_ORDER if the environment variable + POSIXLY_CORRECT is defined, PERMUTE otherwise. + + REQUIRE_ORDER means don't recognize them as options; + stop option processing when the first non-option is seen. + This is what Unix does. + This mode of operation is selected by either setting the environment + variable POSIXLY_CORRECT, or using `+' as the first character + of the list of option characters. + + PERMUTE is the default. We permute the contents of ARGV as we scan, + so that eventually all the non-options are at the end. This allows options + to be given in any order, even with programs that were not written to + expect this. + + RETURN_IN_ORDER is an option available to programs that were written + to expect options and other ARGV-elements in any order and that care about + the ordering of the two. We describe each non-option ARGV-element + as if it were the argument of an option with character code 1. + Using `-' as the first character of the list of option characters + selects this mode of operation. + + The special argument `--' forces an end of option-scanning regardless + of the value of `ordering'. In the case of RETURN_IN_ORDER, only + `--' can cause `getopt' to return EOF with `optind' != ARGC. */ + +static enum +{ + REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER +} ordering; + +#ifdef __GNU_LIBRARY__ +/* We want to avoid inclusion of string.h with non-GNU libraries + because there are many ways it can cause trouble. + On some systems, it contains special magic macros that don't work + in GCC. */ +#include <string.h> +#define my_index strchr +#define my_bcopy(src, dst, n) memcpy ((dst), (src), (n)) +#else + +/* Avoid depending on library functions or files + whose names are inconsistent. */ + +char *getenv (); + +static char * +my_index (str, chr) + const char *str; + int chr; +{ + while (*str) + { + if (*str == chr) + return (char *) str; + str++; + } + return 0; +} + +static void +my_bcopy (from, to, size) + const char *from; + char *to; + int size; +{ + int i; + for (i = 0; i < size; i++) + to[i] = from[i]; +} +#endif /* GNU C library. */ + +/* Handle permutation of arguments. */ + +/* Describe the part of ARGV that contains non-options that have + been skipped. `first_nonopt' is the index in ARGV of the first of them; + `last_nonopt' is the index after the last of them. */ + +static int first_nonopt; +static int last_nonopt; + +/* Exchange two adjacent subsequences of ARGV. + One subsequence is elements [first_nonopt,last_nonopt) + which contains all the non-options that have been skipped so far. + The other is elements [last_nonopt,optind), which contains all + the options processed since those non-options were skipped. + + `first_nonopt' and `last_nonopt' are relocated so that they describe + the new indices of the non-options in ARGV after they are moved. */ + +static void +exchange (argv) + char **argv; +{ + int nonopts_size = (last_nonopt - first_nonopt) * sizeof (char *); + char **temp = (char **) __alloca (nonopts_size); + + /* Interchange the two blocks of data in ARGV. */ + + my_bcopy ((char *) &argv[first_nonopt], (char *) temp, nonopts_size); + my_bcopy ((char *) &argv[last_nonopt], (char *) &argv[first_nonopt], + (optind - last_nonopt) * sizeof (char *)); + my_bcopy ((char *) temp, + (char *) &argv[first_nonopt + optind - last_nonopt], + nonopts_size); + + /* Update records for the slots the non-options now occupy. */ + + first_nonopt += (optind - last_nonopt); + last_nonopt = optind; +} + +/* Scan elements of ARGV (whose length is ARGC) for option characters + given in OPTSTRING. + + If an element of ARGV starts with '-', and is not exactly "-" or "--", + then it is an option element. The characters of this element + (aside from the initial '-') are option characters. If `getopt' + is called repeatedly, it returns successively each of the option characters + from each of the option elements. + + If `getopt' finds another option character, it returns that character, + updating `optind' and `nextchar' so that the next call to `getopt' can + resume the scan with the following option character or ARGV-element. + + If there are no more option characters, `getopt' returns `EOF'. + Then `optind' is the index in ARGV of the first ARGV-element + that is not an option. (The ARGV-elements have been permuted + so that those that are not options now come last.) + + OPTSTRING is a string containing the legitimate option characters. + If an option character is seen that is not listed in OPTSTRING, + return '?' after printing an error message. If you set `opterr' to + zero, the error message is suppressed but we still return '?'. + + If a char in OPTSTRING is followed by a colon, that means it wants an arg, + so the following text in the same ARGV-element, or the text of the following + ARGV-element, is returned in `optarg'. Two colons mean an option that + wants an optional arg; if there is text in the current ARGV-element, + it is returned in `optarg', otherwise `optarg' is set to zero. + + If OPTSTRING starts with `-' or `+', it requests different methods of + handling the non-option ARGV-elements. + See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above. + + Long-named options begin with `--' instead of `-'. + Their names may be abbreviated as long as the abbreviation is unique + or is an exact match for some defined option. If they have an + argument, it follows the option name in the same ARGV-element, separated + from the option name by a `=', or else the in next ARGV-element. + When `getopt' finds a long-named option, it returns 0 if that option's + `flag' field is nonzero, the value of the option's `val' field + if the `flag' field is zero. + + The elements of ARGV aren't really const, because we permute them. + But we pretend they're const in the prototype to be compatible + with other systems. + + LONGOPTS is a vector of `struct option' terminated by an + element containing a name which is zero. + + LONGIND returns the index in LONGOPT of the long-named option found. + It is only valid when a long-named option has been found by the most + recent call. + + If LONG_ONLY is nonzero, '-' as well as '--' can introduce + long-named options. */ + +int +_getopt_internal (argc, argv, optstring, longopts, longind, long_only) + int argc; + char *const *argv; + const char *optstring; + const struct option *longopts; + int *longind; + int long_only; +{ + int option_index; + + optarg = 0; + + /* Initialize the internal data when the first call is made. + Start processing options with ARGV-element 1 (since ARGV-element 0 + is the program name); the sequence of previously skipped + non-option ARGV-elements is empty. */ + + if (optind == 0) + { + first_nonopt = last_nonopt = optind = 1; + + nextchar = NULL; + + /* Determine how to handle the ordering of options and nonoptions. */ + + if (optstring[0] == '-') + { + ordering = RETURN_IN_ORDER; + ++optstring; + } + else if (optstring[0] == '+') + { + ordering = REQUIRE_ORDER; + ++optstring; + } + else if (getenv ("POSIXLY_CORRECT") != NULL) + ordering = REQUIRE_ORDER; + else + ordering = PERMUTE; + } + + if (nextchar == NULL || *nextchar == '\0') + { + if (ordering == PERMUTE) + { + /* If we have just processed some options following some non-options, + exchange them so that the options come first. */ + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (last_nonopt != optind) + first_nonopt = optind; + + /* Now skip any additional non-options + and extend the range of non-options previously skipped. */ + + while (optind < argc + && (argv[optind][0] != '-' || argv[optind][1] == '\0') +#ifdef GETOPT_COMPAT + && (longopts == NULL + || argv[optind][0] != '+' || argv[optind][1] == '\0') +#endif /* GETOPT_COMPAT */ + ) + optind++; + last_nonopt = optind; + } + + /* Special ARGV-element `--' means premature end of options. + Skip it like a null option, + then exchange with previous non-options as if it were an option, + then skip everything else like a non-option. */ + + if (optind != argc && !strcmp (argv[optind], "--")) + { + optind++; + + if (first_nonopt != last_nonopt && last_nonopt != optind) + exchange ((char **) argv); + else if (first_nonopt == last_nonopt) + first_nonopt = optind; + last_nonopt = argc; + + optind = argc; + } + + /* If we have done all the ARGV-elements, stop the scan + and back over any non-options that we skipped and permuted. */ + + if (optind == argc) + { + /* Set the next-arg-index to point at the non-options + that we previously skipped, so the caller will digest them. */ + if (first_nonopt != last_nonopt) + optind = first_nonopt; + return EOF; + } + + /* If we have come to a non-option and did not permute it, + either stop the scan or describe it to the caller and pass it by. */ + + if ((argv[optind][0] != '-' || argv[optind][1] == '\0') +#ifdef GETOPT_COMPAT + && (longopts == NULL + || argv[optind][0] != '+' || argv[optind][1] == '\0') +#endif /* GETOPT_COMPAT */ + ) + { + if (ordering == REQUIRE_ORDER) + return EOF; + optarg = argv[optind++]; + return 1; + } + + /* We have found another option-ARGV-element. + Start decoding its characters. */ + + nextchar = (argv[optind] + 1 + + (longopts != NULL && argv[optind][1] == '-')); + } + + if (longopts != NULL + && ((argv[optind][0] == '-' + && (argv[optind][1] == '-' || long_only)) +#ifdef GETOPT_COMPAT + || argv[optind][0] == '+' +#endif /* GETOPT_COMPAT */ + )) + { + const struct option *p; + char *s = nextchar; + int exact = 0; + int ambig = 0; + const struct option *pfound = NULL; + int indfound; + + while (*s && *s != '=') + s++; + + /* Test all options for either exact match or abbreviated matches. */ + for (p = longopts, option_index = 0; p->name; + p++, option_index++) + if (!strncmp (p->name, nextchar, s - nextchar)) + { + if (s - nextchar == strlen (p->name)) + { + /* Exact match found. */ + pfound = p; + indfound = option_index; + exact = 1; + break; + } + else if (pfound == NULL) + { + /* First nonexact match found. */ + pfound = p; + indfound = option_index; + } + else + /* Second nonexact match found. */ + ambig = 1; + } + + if (ambig && !exact) + { + if (opterr) + fprintf (stderr, "%s: option `%s' is ambiguous\n", + argv[0], argv[optind]); + nextchar += strlen (nextchar); + optind++; + return '?'; + } + + if (pfound != NULL) + { + option_index = indfound; + optind++; + if (*s) + { + /* Don't test has_arg with >, because some C compilers don't + allow it to be used on enums. */ + if (pfound->has_arg) + optarg = s + 1; + else + { + if (opterr) + { + if (argv[optind - 1][1] == '-') + /* --option */ + fprintf (stderr, + "%s: option `--%s' doesn't allow an argument\n", + argv[0], pfound->name); + else + /* +option or -option */ + fprintf (stderr, + "%s: option `%c%s' doesn't allow an argument\n", + argv[0], argv[optind - 1][0], pfound->name); + } + nextchar += strlen (nextchar); + return '?'; + } + } + else if (pfound->has_arg == 1) + { + if (optind < argc) + optarg = argv[optind++]; + else + { + if (opterr) + fprintf (stderr, "%s: option `%s' requires an argument\n", + argv[0], argv[optind - 1]); + nextchar += strlen (nextchar); + return optstring[0] == ':' ? ':' : '?'; + } + } + nextchar += strlen (nextchar); + if (longind != NULL) + *longind = option_index; + if (pfound->flag) + { + *(pfound->flag) = pfound->val; + return 0; + } + return pfound->val; + } + /* Can't find it as a long option. If this is not getopt_long_only, + or the option starts with '--' or is not a valid short + option, then it's an error. + Otherwise interpret it as a short option. */ + if (!long_only || argv[optind][1] == '-' +#ifdef GETOPT_COMPAT + || argv[optind][0] == '+' +#endif /* GETOPT_COMPAT */ + || my_index (optstring, *nextchar) == NULL) + { + if (opterr) + { + if (argv[optind][1] == '-') + /* --option */ + fprintf (stderr, "%s: unrecognized option `--%s'\n", + argv[0], nextchar); + else + /* +option or -option */ + fprintf (stderr, "%s: unrecognized option `%c%s'\n", + argv[0], argv[optind][0], nextchar); + } + nextchar = (char *) ""; + optind++; + return '?'; + } + } + + /* Look at and handle the next option-character. */ + + { + char c = *nextchar++; + char *temp = my_index (optstring, c); + + /* Increment `optind' when we start to process its last character. */ + if (*nextchar == '\0') + ++optind; + + if (temp == NULL || c == ':') + { + if (opterr) + { +#if 0 + if (c < 040 || c >= 0177) + fprintf (stderr, "%s: unrecognized option, character code 0%o\n", + argv[0], c); + else + fprintf (stderr, "%s: unrecognized option `-%c'\n", argv[0], c); +#else + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c); +#endif + } + optopt = c; + return '?'; + } + if (temp[1] == ':') + { + if (temp[2] == ':') + { + /* This is an option that accepts an argument optionally. */ + if (*nextchar != '\0') + { + optarg = nextchar; + optind++; + } + else + optarg = 0; + nextchar = NULL; + } + else + { + /* This is an option that requires an argument. */ + if (*nextchar != '\0') + { + optarg = nextchar; + /* If we end this ARGV-element by taking the rest as an arg, + we must advance to the next element now. */ + optind++; + } + else if (optind == argc) + { + if (opterr) + { +#if 0 + fprintf (stderr, "%s: option `-%c' requires an argument\n", + argv[0], c); +#else + /* 1003.2 specifies the format of this message. */ + fprintf (stderr, "%s: option requires an argument -- %c\n", + argv[0], c); +#endif + } + optopt = c; + if (optstring[0] == ':') + c = ':'; + else + c = '?'; + } + else + /* We already incremented `optind' once; + increment it again when taking next ARGV-elt as argument. */ + optarg = argv[optind++]; + nextchar = NULL; + } + } + return c; + } +} + +#ifdef GETOPT +int +getopt (argc, argv, optstring) + int argc; + char *const *argv; + const char *optstring; +{ + return _getopt_internal (argc, argv, optstring, + (const struct option *) 0, + (int *) 0, + 0); +} +#endif + +#endif /* _LIBC or not __GNU_LIBRARY__. */ + +#ifdef TEST + +/* Compile with -DTEST to make an executable for use in testing + the above definition of `getopt'. */ + +int +main (argc, argv) + int argc; + char **argv; +{ + int c; + int digit_optind = 0; + + while (1) + { + int this_option_optind = optind ? optind : 1; + + c = getopt (argc, argv, "abc:d:0123456789"); + if (c == EOF) + break; + + switch (c) + { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + if (digit_optind != 0 && digit_optind != this_option_optind) + printf ("digits occur in two different argv-elements.\n"); + digit_optind = this_option_optind; + printf ("option %c\n", c); + break; + + case 'a': + printf ("option a\n"); + break; + + case 'b': + printf ("option b\n"); + break; + + case 'c': + printf ("option c with value `%s'\n", optarg); + break; + + case '?': + break; + + default: + printf ("?? getopt returned character code 0%o ??\n", c); + } + } + + if (optind < argc) + { + printf ("non-option ARGV-elements: "); + while (optind < argc) + printf ("%s ", argv[optind++]); + printf ("\n"); + } + + exit (0); +} + +#endif /* TEST */ diff --git a/gnuradio-core/src/lib/missing/getopt.h b/gnuradio-core/src/lib/missing/getopt.h new file mode 100644 index 000000000..067908147 --- /dev/null +++ b/gnuradio-core/src/lib/missing/getopt.h @@ -0,0 +1,129 @@ +/* Declarations for getopt. + Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc. + + This program 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. + + This program 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 this program; if not, write to the Free Software + Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#ifndef _GETOPT_H +#define _GETOPT_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* For communication from `getopt' to the caller. + When `getopt' finds an option that takes an argument, + the argument value is returned here. + Also, when `ordering' is RETURN_IN_ORDER, + each non-option ARGV-element is returned here. */ + +extern char *optarg; + +/* Index in ARGV of the next element to be scanned. + This is used for communication to and from the caller + and for communication between successive calls to `getopt'. + + On entry to `getopt', zero means this is the first call; initialize. + + When `getopt' returns EOF, this is the index of the first of the + non-option elements that the caller should itself scan. + + Otherwise, `optind' communicates from one call to the next + how much of ARGV has been scanned so far. */ + +extern int optind; + +/* Callers store zero here to inhibit the error message `getopt' prints + for unrecognized options. */ + +extern int opterr; + +/* Set to an option character which was unrecognized. */ + +extern int optopt; + +/* Describe the long-named options requested by the application. + The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector + of `struct option' terminated by an element containing a name which is + zero. + + The field `has_arg' is: + no_argument (or 0) if the option does not take an argument, + required_argument (or 1) if the option requires an argument, + optional_argument (or 2) if the option takes an optional argument. + + If the field `flag' is not NULL, it points to a variable that is set + to the value given in the field `val' when the option is found, but + left unchanged if the option is not found. + + To have a long-named option do something other than set an `int' to + a compiled-in constant, such as set a value from `optarg', set the + option's `flag' field to zero and its `val' field to a nonzero + value (the equivalent single-letter option character, if there is + one). For long options that have a zero `flag' field, `getopt' + returns the contents of the `val' field. */ + +struct option +{ +#if __STDC__ + const char *name; +#else + char *name; +#endif + /* has_arg can't be an enum because some compilers complain about + type mismatches in all the code that assumes it is an int. */ + int has_arg; + int *flag; + int val; +}; + +/* Names for the values of the `has_arg' field of `struct option'. */ + +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +#if __STDC__ +#if defined(__GNU_LIBRARY__) +/* Many other libraries have conflicting prototypes for getopt, with + differences in the consts, in stdlib.h. To avoid compilation + errors, only prototype getopt for the GNU C library. */ +extern int getopt (int argc, char *const *argv, const char *shortopts); +#else /* not __GNU_LIBRARY__ */ +extern int getopt (); +#endif /* not __GNU_LIBRARY__ */ +extern int getopt_long (int argc, char *const *argv, const char *shortopts, + const struct option *longopts, int *longind); +extern int getopt_long_only (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind); + +/* Internal only. Users should not call this directly. */ +extern int _getopt_internal (int argc, char *const *argv, + const char *shortopts, + const struct option *longopts, int *longind, + int long_only); +#else /* not __STDC__ */ +extern int getopt (); +extern int getopt_long (); +extern int getopt_long_only (); + +extern int _getopt_internal (); +#endif /* not __STDC__ */ + +#ifdef __cplusplus +} +#endif + +#endif /* _GETOPT_H */ diff --git a/gnuradio-core/src/lib/missing/gettimeofday.c b/gnuradio-core/src/lib/missing/gettimeofday.c new file mode 100644 index 000000000..a53e47ed9 --- /dev/null +++ b/gnuradio-core/src/lib/missing/gettimeofday.c @@ -0,0 +1,50 @@ +/* + * Copyright 2003 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 <config.h> + +#ifdef HAVE_WINDOWS_H +#include <windows.h> +#endif +#ifdef HAVE_WINBASE_H +# include <winbase.h> +#endif + +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +/* + * broken implementation for WIN32. + * FIXME: usec precision + */ +int gettimeofday(struct timeval *tv, struct timezone *tz) +{ + if (tv) { + time_t tm; + + time(&tm); + tv->tv_sec = tm; + tv->tv_usec = 0; + } + return 0; +} + diff --git a/gnuradio-core/src/lib/missing/posix_memalign.cc b/gnuradio-core/src/lib/missing/posix_memalign.cc new file mode 100644 index 000000000..aaeff7804 --- /dev/null +++ b/gnuradio-core/src/lib/missing/posix_memalign.cc @@ -0,0 +1,114 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009 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 "posix_memalign.h" + +#ifdef HAVE_MALLOC_H +// for Cygwin valloc () prototype +#include <malloc.h> +#endif + +#ifndef HAVE_POSIX_MEMALIGN + +/* emulate posix_memalign functionality, to some degree */ + +#include <errno.h> +#include "gr_pagesize.h" + +int posix_memalign +(void **memptr, size_t alignment, size_t size) +{ + /* emulate posix_memalign functionality, to some degree */ + + /* make sure the return handle is valid; return "bad address" if not valid */ + if (memptr == 0) + return (EFAULT); + *memptr = (void*) 0; + + /* make sure 'alignment' is a power of 2 + * and multiple of sizeof (void*) + */ + + /* make sure 'alignment' is a multiple of sizeof (void*) */ + if ((alignment % sizeof (void*)) != 0) + return (EINVAL); + + /* make sure 'alignment' is a power of 2 */ + if ((alignment & (alignment - 1)) != 0) + return (EINVAL); + + /* good alignment */ + +#if (ALIGNED_MALLOC != 0) + + /* if 'malloc' is known to be aligned, and the desired 'alignment' + * matches is <= that provided by 'malloc', then use 'malloc'. This + * works on, e.g., Darwin 8 & 9: for which malloc is 16-byte aligned. + */ + size_t am = (size_t) ALIGNED_MALLOC; + if (alignment <= am) { + /* make sure ALIGNED_MALLOC is a power of 2, to guarantee that the + * alignment is correct (since 'alignment' must be a power of 2). + */ + if ((am & (am - 1)) != 0) + return (EINVAL); + /* good malloc alignment */ + *memptr = malloc (size); + } + +#endif /* (ALIGNED_MALLOC != 0) */ +#ifdef HAVE_VALLOC + + if (*memptr == (void*) 0) { + /* try valloc if it exists */ + /* cheap and easy way to make sure alignment is met, so long as it + * is <= pagesize () */ + if (alignment <= (size_t) gr_pagesize ()) { + *memptr = valloc (size); + } + } + +#endif /* HAVE_VALLOC */ + +#if (ALIGNED_MALLOC == 0) && !defined (HAVE_VALLOC) + /* no posix_memalign, valloc, and malloc isn't known to be aligned + * (enough for the input arguments); no idea what to do. + */ + +#error gnuradio-core/src/libmissing/posix_memalign.cc: Cannot find a way to alloc aligned memory. + +#endif + + /* if the pointer wasn't allocated properly, return that there was + * not enough memory to allocate; otherwise, return OK (0). + */ + if (*memptr == (void*) 0) + return (ENOMEM); + else + return (0); +}; + +#endif /* ! HAVE_POSIX_MEMALIGN */ diff --git a/gnuradio-core/src/lib/missing/posix_memalign.h b/gnuradio-core/src/lib/missing/posix_memalign.h new file mode 100644 index 000000000..ea79ced2e --- /dev/null +++ b/gnuradio-core/src/lib/missing/posix_memalign.h @@ -0,0 +1,42 @@ +/* -*- 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 _POSIX_MEMALIGN_H_ +#define _POSIX_MEMALIGN_H_ + +#include <stdlib.h> + +#ifndef HAVE_POSIX_MEMALIGN + +#ifdef __cplusplus +extern "C" { +#endif + +extern int posix_memalign (void** memptr, size_t alignment, size_t size); + +#ifdef __cplusplus +}; +#endif + +#endif /* ! HAVE_POSIX_MEMALIGN */ + +#endif /* _POSIX_MEMALIGN_H_ */ diff --git a/gnuradio-core/src/lib/missing/usleep.c b/gnuradio-core/src/lib/missing/usleep.c new file mode 100644 index 000000000..b1d7dad47 --- /dev/null +++ b/gnuradio-core/src/lib/missing/usleep.c @@ -0,0 +1,67 @@ +/* Copyright (C) 1992 Free Software Foundation, Inc. +This file is part of the GNU C Library. + +The GNU C Library is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public License as +published by the Free Software Foundation; either version 3 of the +License, or (at your option) any later version. + +The GNU C Library 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 +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with the GNU C Library; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 675 Mass Ave, +Cambridge, MA 02139, USA. */ + +#include <config.h> + +#ifndef HAVE_USLEEP + +#include <sys/types.h> +#include <sys/time.h> + +#ifdef HAVE_SYS_SELECT_H +# include <sys/select.h> +#endif + +#ifdef HAVE_WINDOWS_H +#include <windows.h> +#endif +#ifdef HAVE_WINBASE_H +# include <winbase.h> +#endif + +#ifdef apollo +# include <apollo/base.h> +# include <apollo/time.h> + static time_$clock_t DomainTime100mS = + { + 0, 100000/4 + }; + static status_$t DomainStatus; +#endif + +/* Sleep USECONDS microseconds, or until a previously set timer goes off. */ +int +usleep (unsigned long useconds) +{ +#ifdef apollo + /* The usleep function does not work under the SYS5.3 environment. + Use the Domain/OS time_$wait call instead. */ + time_$wait (time_$relative, DomainTime100mS, &DomainStatus); +#elif defined(HAVE_SSLEEP) /* Win32 */ + Sleep( useconds/1000 ); +#else + struct timeval delay; + + delay.tv_sec = 0; + delay.tv_usec = useconds; + select (0, 0, 0, 0, &delay); +#endif + return 0; +} + +#endif /* !HAVE_USLEEP */ diff --git a/gnuradio-core/src/lib/reed-solomon/CMakeLists.txt b/gnuradio-core/src/lib/reed-solomon/CMakeLists.txt new file mode 100644 index 000000000..f073249f6 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/CMakeLists.txt @@ -0,0 +1,62 @@ +# Copyright 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. + +######################################################################## +# This file included, use CMake directory variables +######################################################################## +#MSVC workaround: we cant have dynamically sized arrays. +#So ifdef a max array bounds that is larger than NN and NROOTS +#Its a bit of a hack, but if you look at the code, its so full of ifdefs, +#and lacks optimization where it should be pre-allocating these arrays. +if(MSVC) + set_source_files_properties( + ${CMAKE_CURRENT_SOURCE_DIR}/exercise.c + ${CMAKE_CURRENT_SOURCE_DIR}/decode_rs.c + PROPERTIES COMPILE_DEFINITIONS "MAX_ARRAY=256;" + ) +endif(MSVC) + +set(gr_core_rs_sources + ${CMAKE_CURRENT_SOURCE_DIR}/encode_rs.c + ${CMAKE_CURRENT_SOURCE_DIR}/decode_rs.c + ${CMAKE_CURRENT_SOURCE_DIR}/init_rs.c +) + +######################################################################## +# Setup sources and includes +######################################################################## +list(APPEND gnuradio_core_sources ${gr_core_rs_sources}) + +install( + FILES ${CMAKE_CURRENT_SOURCE_DIR}/rs.h + DESTINATION ${GR_INCLUDE_DIR}/gnuradio + COMPONENT "core_devel" +) + +######################################################################## +# Register unit tests +######################################################################## +if(ENABLE_TESTING) +add_executable(gr_core_rstest + ${gr_core_rs_sources} + ${CMAKE_CURRENT_SOURCE_DIR}/rstest.c + ${CMAKE_CURRENT_SOURCE_DIR}/exercise.c +) +add_test(gr-core-reed-solomon-test gr_core_rstest) +endif(ENABLE_TESTING) diff --git a/gnuradio-core/src/lib/reed-solomon/Makefile.in.karn b/gnuradio-core/src/lib/reed-solomon/Makefile.in.karn new file mode 100644 index 000000000..8550b4158 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/Makefile.in.karn @@ -0,0 +1,99 @@ +# Copyright 2002 Phil Karn, KA9Q +# May be used under the terms of the GNU General Public License (GPL) +# @configure_input@ +srcdir = @srcdir@ +prefix = @prefix@ +exec_prefix=@exec_prefix@ +VPATH = @srcdir@ +CC=@CC@ + +CFLAGS=@CFLAGS@ @ARCH_OPTION@ -Wall + +LIB= encode_rs_char.o encode_rs_int.o encode_rs_8.o \ + decode_rs_char.o decode_rs_int.o decode_rs_8.o \ + init_rs_char.o init_rs_int.o ccsds_tab.o \ + encode_rs_ccsds.o decode_rs_ccsds.o ccsds_tal.o + +all: librs.a librs.so.@SO_VERSION@ + +test: rstest + ./rstest + +rstest: rstest.o exercise_int.o exercise_char.o exercise_8.o exercise_ccsds.o \ + librs.a + gcc -g -o $@ $^ + +install: all + install -D -m 644 -p librs.a librs.so.@SO_VERSION@ @libdir@ + (cd @libdir@;ln -f -s librs.so.@SO_VERSION@ librs.so) + ldconfig + install -m 644 -p rs.h @includedir@ + install -m 644 rs.3 @mandir@/man3 + +librs.a: $(LIB) + ar rv $@ $^ + +librs.so.@SO_VERSION@: librs.a + gcc -shared -Xlinker -soname=librs.so.@SO_NAME@ -o $@ -Wl,-whole-archive $^ -Wl,-no-whole-archive -lc + +encode_rs_char.o: encode_rs.c + gcc $(CFLAGS) -c -o $@ $^ + +encode_rs_int.o: encode_rs.c + gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^ + +encode_rs_8.o: encode_rs.c + gcc -DFIXED=1 $(CFLAGS) -c -o $@ $^ + +decode_rs_char.o: decode_rs.c + gcc $(CFLAGS) -c -o $@ $^ + +decode_rs_int.o: decode_rs.c + gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^ + +decode_rs_8.o: decode_rs.c + gcc -DFIXED=1 $(CFLAGS) -c -o $@ $^ + +init_rs_char.o: init_rs.c + gcc $(CFLAGS) -c -o $@ $^ + +init_rs_int.o: init_rs.c + gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^ + +ccsds_tab.o: ccsds_tab.c + +ccsds_tab.c: gen_ccsds + ./gen_ccsds > ccsds_tab.c + +gen_ccsds: gen_ccsds.o init_rs_char.o + gcc -o $@ $^ + +gen_ccsds.o: gen_ccsds.c + gcc $(CFLAGS) -c -o $@ $^ + +ccsds_tal.o: ccsds_tal.c + +ccsds_tal.c: gen_ccsds_tal + ./gen_ccsds_tal > ccsds_tal.c + +exercise_char.o: exercise.c + gcc $(CFLAGS) -c -o $@ $^ + +exercise_int.o: exercise.c + gcc -DBIGSYM=1 $(CFLAGS) -c -o $@ $^ + +exercise_8.o: exercise.c + gcc -DFIXED=1 $(CFLAGS) -c -o $@ $^ + +exercise_ccsds.o: exercise.c + gcc -DCCSDS=1 $(CFLAGS) -c -o $@ $^ + + +clean: + rm -f *.o *.a ccsds_tab.c ccsds_tal.c gen_ccsds gen_ccsds_tal \ + rstest librs.so.@SO_VERSION@ + +distclean: clean + rm -f config.log config.cache config.status config.h makefile + + diff --git a/gnuradio-core/src/lib/reed-solomon/README b/gnuradio-core/src/lib/reed-solomon/README new file mode 100644 index 000000000..341832dbd --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/README @@ -0,0 +1,5 @@ +This code is from http://people.qualcomm.com/karn/code/fec +It is based on reed-soloman-3.1.1 (1 Jan 2002). + +I has been converted to use automake, to better integrate with GNU +Radio's build strategy. diff --git a/gnuradio-core/src/lib/reed-solomon/README.karn b/gnuradio-core/src/lib/reed-solomon/README.karn new file mode 100644 index 000000000..f30644ffe --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/README.karn @@ -0,0 +1,22 @@ +This package implements a general purpose Reed-Solomon encoding and decoding +facility. See the rs.3 man page for details. + +To install, simply do the following after extracting this tarball into +an empty directory: + +./configure +make +make install + +The command "make test" runs a battery of encode/decode tests using a +variety of RS codes using random data and random errors. Each test +should pass with an "OK"; if any fail, please let me know so I can +track down the problem. + +Phil Karn (karn@ka9q.net) 1 Jan 2002 + +Copyright 2002, Phil Karn, KA9Q +This software may be used under the terms of the GNU General Public License (GPL). + + + diff --git a/gnuradio-core/src/lib/reed-solomon/ccsds.h b/gnuradio-core/src/lib/reed-solomon/ccsds.h new file mode 100644 index 000000000..0f2bde618 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/ccsds.h @@ -0,0 +1 @@ +extern unsigned char Taltab[],Tal1tab[]; diff --git a/gnuradio-core/src/lib/reed-solomon/char.h b/gnuradio-core/src/lib/reed-solomon/char.h new file mode 100644 index 000000000..7b2030a0b --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/char.h @@ -0,0 +1,57 @@ +/* Include file to configure the RS codec for character symbols + * + * Copyright 2002, Phil Karn, KA9Q + * May be used under the terms of the GNU General Public License (GPL) + */ + +#define DTYPE unsigned char + +#include <gr_core_api.h> + +/* Reed-Solomon codec control block */ +struct rs { + unsigned int mm; /* Bits per symbol */ + unsigned int nn; /* Symbols per block (= (1<<mm)-1) */ + unsigned char *alpha_to; /* log lookup table */ + unsigned char *index_of; /* Antilog lookup table */ + unsigned char *genpoly; /* Generator polynomial */ + unsigned int nroots; /* Number of generator roots = number of parity symbols */ + unsigned char fcr; /* First consecutive root, index form */ + unsigned char prim; /* Primitive element, index form */ + unsigned char iprim; /* prim-th root of 1, index form */ +}; + +static inline unsigned int modnn(struct rs *rs, unsigned int x){ + while (x >= rs->nn) { + x -= rs->nn; + x = (x >> rs->mm) + (x & rs->nn); + } + return x; +} +#define MODNN(x) modnn(rs,x) + +#define MM (rs->mm) +#define NN (rs->nn) +#define ALPHA_TO (rs->alpha_to) +#define INDEX_OF (rs->index_of) +#define GENPOLY (rs->genpoly) +#define NROOTS (rs->nroots) +#define FCR (rs->fcr) +#define PRIM (rs->prim) +#define IPRIM (rs->iprim) +#define A0 (NN) + +#define ENCODE_RS encode_rs_char +#define DECODE_RS decode_rs_char +#define INIT_RS init_rs_char +#define FREE_RS free_rs_char + +GR_CORE_API void ENCODE_RS(void *p,DTYPE *data,DTYPE *parity); +GR_CORE_API int DECODE_RS(void *p,DTYPE *data,int *eras_pos,int no_eras); +GR_CORE_API void *INIT_RS(unsigned int symsize,unsigned int gfpoly,unsigned int fcr, + unsigned int prim,unsigned int nroots); +GR_CORE_API void FREE_RS(void *p); + + + + diff --git a/gnuradio-core/src/lib/reed-solomon/decode_rs.c b/gnuradio-core/src/lib/reed-solomon/decode_rs.c new file mode 100644 index 000000000..f9438cf26 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/decode_rs.c @@ -0,0 +1,270 @@ +/* Reed-Solomon decoder + * Copyright 2002 Phil Karn, KA9Q + * May be used under the terms of the GNU General Public License (GPL) + */ + +#ifdef DEBUG +#include <stdio.h> +#endif + +#include <string.h> + +#define NULL ((void *)0) +#define min(a,b) ((a) < (b) ? (a) : (b)) + +#ifdef FIXED +#include "fixed.h" +#elif defined(BIGSYM) +#include "int.h" +#else +#include "char.h" +#endif + +int DECODE_RS( +#ifndef FIXED +void *p, +#endif +DTYPE *data, int *eras_pos, int no_eras){ + +#ifndef FIXED + struct rs *rs = (struct rs *)p; +#endif + int deg_lambda, el, deg_omega; + int i, j, r, k; +#ifdef MAX_ARRAY + DTYPE u,q,tmp,num1,num2,den,discr_r; + DTYPE lambda[MAX_ARRAY], s[MAX_ARRAY]; /* Err+Eras Locator poly + * and syndrome poly */ + DTYPE b[MAX_ARRAY], t[MAX_ARRAY], omega[MAX_ARRAY]; + DTYPE root[MAX_ARRAY], reg[MAX_ARRAY], loc[MAX_ARRAY]; +#else + DTYPE u,q,tmp,num1,num2,den,discr_r; + DTYPE lambda[NROOTS+1], s[NROOTS]; /* Err+Eras Locator poly + * and syndrome poly */ + DTYPE b[NROOTS+1], t[NROOTS+1], omega[NROOTS+1]; + DTYPE root[NROOTS], reg[NROOTS+1], loc[NROOTS]; +#endif + int syn_error, count; + + /* form the syndromes; i.e., evaluate data(x) at roots of g(x) */ + for(i=0;(unsigned int)i<NROOTS;i++) + s[i] = data[0]; + + for(j=1;(unsigned int)j<NN;j++){ + for(i=0;(unsigned int)i<NROOTS;i++){ + if(s[i] == 0){ + s[i] = data[j]; + } else { + s[i] = data[j] ^ ALPHA_TO[MODNN(INDEX_OF[s[i]] + (FCR+i)*PRIM)]; + } + } + } + + /* Convert syndromes to index form, checking for nonzero condition */ + syn_error = 0; + for(i=0;(unsigned int)i<NROOTS;i++){ + syn_error |= s[i]; + s[i] = INDEX_OF[s[i]]; + } + + if (!syn_error) { + /* if syndrome is zero, data[] is a codeword and there are no + * errors to correct. So return data[] unmodified + */ + count = 0; + goto finish; + } + memset(&lambda[1],0,NROOTS*sizeof(lambda[0])); + lambda[0] = 1; + + if (no_eras > 0) { + /* Init lambda to be the erasure locator polynomial */ + lambda[1] = ALPHA_TO[MODNN(PRIM*(NN-1-eras_pos[0]))]; + for (i = 1; i < no_eras; i++) { + u = MODNN(PRIM*(NN-1-eras_pos[i])); + for (j = i+1; j > 0; j--) { + tmp = INDEX_OF[lambda[j - 1]]; + if(tmp != A0) + lambda[j] ^= ALPHA_TO[MODNN(u + tmp)]; + } + } + +#if DEBUG >= 1 + /* Test code that verifies the erasure locator polynomial just constructed + Needed only for decoder debugging. */ + + /* find roots of the erasure location polynomial */ + for(i=1;i<=no_eras;i++) + reg[i] = INDEX_OF[lambda[i]]; + + count = 0; + for (i = 1,k=IPRIM-1; i <= NN; i++,k = MODNN(k+IPRIM)) { + q = 1; + for (j = 1; j <= no_eras; j++) + if (reg[j] != A0) { + reg[j] = MODNN(reg[j] + j); + q ^= ALPHA_TO[reg[j]]; + } + if (q != 0) + continue; + /* store root and error location number indices */ + root[count] = i; + loc[count] = k; + count++; + } + if (count != no_eras) { + printf("count = %d no_eras = %d\n lambda(x) is WRONG\n",count,no_eras); + count = -1; + goto finish; + } +#if DEBUG >= 2 + printf("\n Erasure positions as determined by roots of Eras Loc Poly:\n"); + for (i = 0; i < count; i++) + printf("%d ", loc[i]); + printf("\n"); +#endif +#endif + } + for(i=0;(unsigned int)i<NROOTS+1;i++) + b[i] = INDEX_OF[lambda[i]]; + + /* + * Begin Berlekamp-Massey algorithm to determine error+erasure + * locator polynomial + */ + r = no_eras; + el = no_eras; + while ((unsigned int)(++r) <= NROOTS) { /* r is the step number */ + /* Compute discrepancy at the r-th step in poly-form */ + discr_r = 0; + for (i = 0; i < r; i++){ + if ((lambda[i] != 0) && (s[r-i-1] != A0)) { + discr_r ^= ALPHA_TO[MODNN(INDEX_OF[lambda[i]] + s[r-i-1])]; + } + } + discr_r = INDEX_OF[discr_r]; /* Index form */ + if (discr_r == A0) { + /* 2 lines below: B(x) <-- x*B(x) */ + memmove(&b[1],b,NROOTS*sizeof(b[0])); + b[0] = A0; + } else { + /* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */ + t[0] = lambda[0]; + for (i = 0 ; (unsigned int)i < NROOTS; i++) { + if(b[i] != A0) + t[i+1] = lambda[i+1] ^ ALPHA_TO[MODNN(discr_r + b[i])]; + else + t[i+1] = lambda[i+1]; + } + if (2 * el <= r + no_eras - 1) { + el = r + no_eras - el; + /* + * 2 lines below: B(x) <-- inv(discr_r) * + * lambda(x) + */ + for (i = 0; (unsigned int)i <= NROOTS; i++) + b[i] = (lambda[i] == 0) ? A0 : MODNN(INDEX_OF[lambda[i]] - discr_r + NN); + } else { + /* 2 lines below: B(x) <-- x*B(x) */ + memmove(&b[1],b,NROOTS*sizeof(b[0])); + b[0] = A0; + } + memcpy(lambda,t,(NROOTS+1)*sizeof(t[0])); + } + } + + /* Convert lambda to index form and compute deg(lambda(x)) */ + deg_lambda = 0; + for(i=0;(unsigned int)i<NROOTS+1;i++){ + lambda[i] = INDEX_OF[lambda[i]]; + if(lambda[i] != A0) + deg_lambda = i; + } + /* Find roots of the error+erasure locator polynomial by Chien search */ + memcpy(®[1],&lambda[1],NROOTS*sizeof(reg[0])); + count = 0; /* Number of roots of lambda(x) */ + for (i = 1,k=IPRIM-1; (unsigned int)i <= NN; i++,k = MODNN(k+IPRIM)) { + q = 1; /* lambda[0] is always 0 */ + for (j = deg_lambda; j > 0; j--){ + if (reg[j] != A0) { + reg[j] = MODNN(reg[j] + j); + q ^= ALPHA_TO[reg[j]]; + } + } + if (q != 0) + continue; /* Not a root */ + /* store root (index-form) and error location number */ +#if DEBUG>=2 + printf("count %d root %d loc %d\n",count,i,k); +#endif + root[count] = i; + loc[count] = k; + /* If we've already found max possible roots, + * abort the search to save time + */ + if(++count == deg_lambda) + break; + } + if (deg_lambda != count) { + /* + * deg(lambda) unequal to number of roots => uncorrectable + * error detected + */ + count = -1; + goto finish; + } + /* + * Compute err+eras evaluator poly omega(x) = s(x)*lambda(x) (modulo + * x**NROOTS). in index form. Also find deg(omega). + */ + deg_omega = 0; + for (i = 0; (unsigned int)i < NROOTS;i++){ + tmp = 0; + j = (deg_lambda < i) ? deg_lambda : i; + for(;j >= 0; j--){ + if ((s[i - j] != A0) && (lambda[j] != A0)) + tmp ^= ALPHA_TO[MODNN(s[i - j] + lambda[j])]; + } + if(tmp != 0) + deg_omega = i; + omega[i] = INDEX_OF[tmp]; + } + omega[NROOTS] = A0; + + /* + * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 = + * inv(X(l))**(FCR-1) and den = lambda_pr(inv(X(l))) all in poly-form + */ + for (j = count-1; j >=0; j--) { + num1 = 0; + for (i = deg_omega; i >= 0; i--) { + if (omega[i] != A0) + num1 ^= ALPHA_TO[MODNN(omega[i] + i * root[j])]; + } + num2 = ALPHA_TO[MODNN(root[j] * (FCR - 1) + NN)]; + den = 0; + + /* lambda[i+1] for i even is the formal derivative lambda_pr of lambda[i] */ + for (i = (int)min((unsigned int)deg_lambda,NROOTS-1) & ~1; i >= 0; i -=2) { + if(lambda[i+1] != A0) + den ^= ALPHA_TO[MODNN(lambda[i+1] + i * root[j])]; + } + if (den == 0) { +#if DEBUG >= 1 + printf("\n ERROR: denominator = 0\n"); +#endif + count = -1; + goto finish; + } + /* Apply error to data */ + if (num1 != 0) { + data[loc[j]] ^= ALPHA_TO[MODNN(INDEX_OF[num1] + INDEX_OF[num2] + NN - INDEX_OF[den])]; + } + } + finish: + if(eras_pos != NULL){ + for(i=0;i<count;i++) + eras_pos[i] = loc[i]; + } + return count; +} diff --git a/gnuradio-core/src/lib/reed-solomon/decode_rs_ccsds.c b/gnuradio-core/src/lib/reed-solomon/decode_rs_ccsds.c new file mode 100644 index 000000000..2543d3a64 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/decode_rs_ccsds.c @@ -0,0 +1,27 @@ +/* This function wraps around the fixed 8-bit decoder, performing the + * basis transformations necessary to meet the CCSDS standard + * + * Copyright 2002, Phil Karn, KA9Q + * May be used under the terms of the GNU General Public License (GPL) + */ +#define FIXED 1 +#include "fixed.h" +#include "ccsds.h" + +int decode_rs_ccsds(unsigned char *data,int *eras_pos,int no_eras){ + int i,r; + unsigned char cdata[NN]; + + /* Convert data from dual basis to conventional */ + for(i=0;i<NN;i++) + cdata[i] = Tal1tab[data[i]]; + + r = decode_rs_8(cdata,eras_pos,no_eras); + + if(r > 0){ + /* Convert from conventional to dual basis */ + for(i=0;i<NN;i++) + data[i] = Taltab[cdata[i]]; + } + return r; +} diff --git a/gnuradio-core/src/lib/reed-solomon/encode_rs.c b/gnuradio-core/src/lib/reed-solomon/encode_rs.c new file mode 100644 index 000000000..cd31f32c6 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/encode_rs.c @@ -0,0 +1,47 @@ +/* Reed-Solomon encoder + * Copyright 2002, Phil Karn, KA9Q + * May be used under the terms of the GNU General Public License (GPL) + */ +#include <string.h> + +#ifdef FIXED +#include "fixed.h" +#elif defined(BIGSYM) +#include "int.h" +#else +#include "char.h" +#endif + +void ENCODE_RS( +#ifndef FIXED +void *p, +#endif +DTYPE *data, DTYPE *bb){ +#ifndef FIXED + struct rs *rs = (struct rs *)p; +#endif + unsigned int i, j; + DTYPE feedback; + + memset(bb,0,NROOTS*sizeof(DTYPE)); + + for(i=0;i<NN-NROOTS;i++){ + feedback = INDEX_OF[data[i] ^ bb[0]]; + if(feedback != A0){ /* feedback term is non-zero */ +#ifdef UNNORMALIZED + /* This line is unnecessary when GENPOLY[NROOTS] is unity, as it must + * always be for the polynomials constructed by init_rs() + */ + feedback = MODNN(NN - GENPOLY[NROOTS] + feedback); +#endif + for(j=1;j<NROOTS;j++) + bb[j] ^= ALPHA_TO[MODNN(feedback + GENPOLY[NROOTS-j])]; + } + /* Shift */ + memmove(&bb[0],&bb[1],sizeof(DTYPE)*(NROOTS-1)); + if(feedback != A0) + bb[NROOTS-1] = ALPHA_TO[MODNN(feedback + GENPOLY[0])]; + else + bb[NROOTS-1] = 0; + } +} diff --git a/gnuradio-core/src/lib/reed-solomon/encode_rs_ccsds.c b/gnuradio-core/src/lib/reed-solomon/encode_rs_ccsds.c new file mode 100644 index 000000000..a748b3468 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/encode_rs_ccsds.c @@ -0,0 +1,24 @@ +/* This function wraps around the fixed 8-bit encoder, performing the + * basis transformations necessary to meet the CCSDS standard + * + * Copyright 2002, Phil Karn, KA9Q + * May be used under the terms of the GNU General Public License (GPL) + */ +#define FIXED +#include "fixed.h" +#include "ccsds.h" + +void encode_rs_ccsds(unsigned char *data,unsigned char *parity){ + int i; + unsigned char cdata[NN-NROOTS]; + + /* Convert data from dual basis to conventional */ + for(i=0;i<NN-NROOTS;i++) + cdata[i] = Tal1tab[data[i]]; + + encode_rs_8(cdata,parity); + + /* Convert parity from conventional to dual basis */ + for(i=0;i<NN-NROOTS;i++) + parity[i] = Taltab[parity[i]]; +} diff --git a/gnuradio-core/src/lib/reed-solomon/exercise.c b/gnuradio-core/src/lib/reed-solomon/exercise.c new file mode 100644 index 000000000..de33a6bff --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/exercise.c @@ -0,0 +1,134 @@ +/* Exercise an RS codec a specified number of times using random + * data and error patterns + * + * Copyright 2002 Phil Karn, KA9Q + * May be used under the terms of the GNU General Public License (GPL) + */ +#define FLAG_ERASURE 1 /* Randomly flag 50% of errors as erasures */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifdef FIXED +#include "fixed.h" +#define EXERCISE exercise_8 +#elif defined(CCSDS) +#include "fixed.h" +#include "ccsds.h" +#define EXERCISE exercise_ccsds +#elif defined(BIGSYM) +#include "int.h" +#define EXERCISE exercise_int +#else +#include "char.h" +#define EXERCISE exercise_char +#endif + +#ifdef FIXED +#define PRINTPARM printf("(255,223):"); +#elif defined(CCSDS) +#define PRINTPARM printf("CCSDS (255,223):"); +#else +#define PRINTPARM printf("(%d,%d):",rs->nn,rs->nn-rs->nroots); +#endif + +/* Exercise the RS codec passed as an argument */ +int EXERCISE( +#if !defined(CCSDS) && !defined(FIXED) +void *p, +#endif +int trials){ +#if !defined(CCSDS) && !defined(FIXED) + struct rs *rs = (struct rs *)p; +#endif +#if MAX_ARRAY + DTYPE block[MAX_ARRAY],tblock[MAX_ARRAY]; + unsigned int i; + int errors; + int errlocs[MAX_ARRAY]; + int derrlocs[MAX_ARRAY]; +#else + DTYPE block[NN],tblock[NN]; + unsigned int i; + int errors; + int errlocs[NN]; + int derrlocs[NROOTS]; +#endif + int derrors; + int errval,errloc; + int erasures; + int decoder_errors = 0; + + while(trials-- != 0){ + /* Test up to the error correction capacity of the code */ + for(errors=0;(unsigned int)errors <= NROOTS/2;errors++){ + + /* Load block with random data and encode */ + for(i=0;i<NN-NROOTS;i++) + block[i] = random() & NN; + +#if defined(CCSDS) || defined(FIXED) + ENCODE_RS(&block[0],&block[NN-NROOTS]); +#else + ENCODE_RS(rs,&block[0],&block[NN-NROOTS]); +#endif + + /* Make temp copy, seed with errors */ + memcpy(tblock,block,sizeof(tblock)); + memset(errlocs,0,sizeof(errlocs)); + memset(derrlocs,0,sizeof(derrlocs)); + erasures=0; + for(i=0;i<(unsigned int)errors;i++){ + do { + errval = random() & NN; + } while(errval == 0); /* Error value must be nonzero */ + + do { + errloc = random() % NN; + } while(errlocs[errloc] != 0); /* Must not choose the same location twice */ + + errlocs[errloc] = 1; + +#if FLAG_ERASURE + if(random() & 1) /* 50-50 chance */ + derrlocs[erasures++] = errloc; +#endif + tblock[errloc] ^= errval; + } + + /* Decode the errored block */ +#if defined(CCSDS) || defined(FIXED) + derrors = DECODE_RS(tblock,derrlocs,erasures); +#else + derrors = DECODE_RS(rs,tblock,derrlocs,erasures); +#endif + + if(derrors != errors){ + PRINTPARM + printf(" decoder says %d errors, true number is %d\n",derrors,errors); + decoder_errors++; + } + for(i=0;i<(unsigned int)derrors;i++){ + if(errlocs[derrlocs[i]] == 0){ + PRINTPARM + printf(" decoder indicates error in location %d without error\n",i); + decoder_errors++; + } + } + if(memcmp(tblock,block,sizeof(tblock)) != 0){ + PRINTPARM + printf(" uncorrected errors! output ^ input:"); + decoder_errors++; + for(i=0;i<NN;i++) + printf(" %02x",tblock[i] ^ block[i]); + printf("\n"); + } + } + } + return decoder_errors; +} diff --git a/gnuradio-core/src/lib/reed-solomon/fixed.h b/gnuradio-core/src/lib/reed-solomon/fixed.h new file mode 100644 index 000000000..30091e7bf --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/fixed.h @@ -0,0 +1,40 @@ +/* Configure the RS codec with fixed parameters for CCSDS standard + * (255,223) code over GF(256). Note: the conventional basis is still + * used; the dual-basis mappings are performed in [en|de]code_rs_ccsds.c + * + * Copyright 2002 Phil Karn, KA9Q + * May be used under the terms of the GNU General Public License (GPL) + */ +#define DTYPE unsigned char + +#include <gr_core_api.h> + +static inline int mod255(int x){ + while (x >= 255) { + x -= 255; + x = (x >> 8) + (x & 255); + } + return x; +} +#define MODNN(x) mod255(x) + +extern unsigned char CCSDS_alpha_to[]; +extern unsigned char CCSDS_index_of[]; +extern unsigned char CCSDS_poly[]; + +#define MM 8 +#define NN 255 +#define ALPHA_TO CCSDS_alpha_to +#define INDEX_OF CCSDS_index_of +#define GENPOLY CCSDS_poly +#define NROOTS 32 +#define FCR 112 +#define PRIM 11 +#define IPRIM 116 +#define A0 (NN) + +#define ENCODE_RS encode_rs_8 +#define DECODE_RS decode_rs_8 + +GR_CORE_API void ENCODE_RS(DTYPE *data,DTYPE *parity); +GR_CORE_API int DECODE_RS(DTYPE *data, int *eras_pos, int no_eras);
\ No newline at end of file diff --git a/gnuradio-core/src/lib/reed-solomon/gen_ccsds.c b/gnuradio-core/src/lib/reed-solomon/gen_ccsds.c new file mode 100644 index 000000000..1e4e4f536 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/gen_ccsds.c @@ -0,0 +1,34 @@ +/* Generate tables for CCSDS code + * Copyright 2002 Phil Karn, KA9Q + * May be used under the terms of the GNU General Public License (GPL) + */ +#include <stdio.h> +#include "char.h" + +int main(){ + struct rs *rs; + int i; + + rs = init_rs_char(8,0x187,112,11,32); /* CCSDS standard */ + printf("unsigned char CCSDS_alpha_to[] = {"); + for(i=0;i<256;i++){ + if((i % 16) == 0) + printf("\n"); + printf("0x%02x,",rs->alpha_to[i]); + } + printf("\n};\n\nunsigned char CCSDS_index_of[] = {"); + for(i=0;i<256;i++){ + if((i % 16) == 0) + printf("\n"); + printf("%3d,",rs->index_of[i]); + } + printf("\n};\n\nunsigned char CCSDS_poly[] = {"); + for(i=0;i<33;i++){ + if((i % 16) == 0) + printf("\n"); + + printf("%3d,",rs->genpoly[i]); + } + printf("\n};\n"); + exit(0); +} diff --git a/gnuradio-core/src/lib/reed-solomon/gen_ccsds_tal.c b/gnuradio-core/src/lib/reed-solomon/gen_ccsds_tal.c new file mode 100644 index 000000000..9dde18917 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/gen_ccsds_tal.c @@ -0,0 +1,50 @@ +/* Conversion lookup tables from conventional alpha to Berlekamp's + * dual-basis representation. Used in the CCSDS version only. + * taltab[] -- convert conventional to dual basis + * tal1tab[] -- convert dual basis to conventional + + * Note: the actual RS encoder/decoder works with the conventional basis. + * So data is converted from dual to conventional basis before either + * encoding or decoding and then converted back. + * + * Copyright 2002 Phil Karn, KA9Q + * May be used under the terms of the GNU General Public License (GPL) + */ +#include <stdio.h> +unsigned char Taltab[256],Tal1tab[256]; + +static unsigned char tal[] = { 0x8d, 0xef, 0xec, 0x86, 0xfa, 0x99, 0xaf, 0x7b }; + +/* Generate conversion lookup tables between conventional alpha representation + * (@**7, @**6, ...@**0) + * and Berlekamp's dual basis representation + * (l0, l1, ...l7) + */ +int main(){ + int i,j,k; + + for(i=0;i<256;i++){/* For each value of input */ + Taltab[i] = 0; + for(j=0;j<8;j++) /* for each column of matrix */ + for(k=0;k<8;k++){ /* for each row of matrix */ + if(i & (1<<k)) + Taltab[i] ^= tal[7-k] & (1<<j); + } + Tal1tab[Taltab[i]] = i; + } + printf("unsigned char Taltab[] = {\n"); + for(i=0;i<256;i++){ + if((i % 16) == 0) + printf("\n"); + printf("0x%02x,",Taltab[i]); + } + printf("\n};\n\nunsigned char Tal1tab[] = {"); + for(i=0;i<256;i++){ + if((i % 16) == 0) + printf("\n"); + printf("0x%02x,",Tal1tab[i]); + } + printf("\n};\n"); + exit(0); +} + diff --git a/gnuradio-core/src/lib/reed-solomon/init_rs.c b/gnuradio-core/src/lib/reed-solomon/init_rs.c new file mode 100644 index 000000000..4ec77cd72 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/init_rs.c @@ -0,0 +1,129 @@ +/* Initialize a RS codec + * + * Copyright 2002 Phil Karn, KA9Q + * May be used under the terms of the GNU General Public License (GPL) + */ +#include <stdlib.h> + +#ifdef CCSDS +#include "ccsds.h" +#elif defined(BIGSYM) +#include "int.h" +#else +#include "char.h" +#endif + +#define NULL ((void *)0) + +void FREE_RS(void *p){ + struct rs *rs = (struct rs *)p; + + free(rs->alpha_to); + free(rs->index_of); + free(rs->genpoly); + free(rs); +} + +/* Initialize a Reed-Solomon codec + * symsize = symbol size, bits (1-8) + * gfpoly = Field generator polynomial coefficients + * fcr = first root of RS code generator polynomial, index form + * prim = primitive element to generate polynomial roots + * nroots = RS code generator polynomial degree (number of roots) + */ +void *INIT_RS(unsigned int symsize,unsigned int gfpoly,unsigned fcr,unsigned prim, + unsigned int nroots){ + struct rs *rs; + int sr,root,iprim; + unsigned int i, j; + + if(symsize > 8*sizeof(DTYPE)) + return NULL; /* Need version with ints rather than chars */ + + if(fcr >= (1u<<symsize)) + return NULL; + if(prim == 0 || prim >= (1u<<symsize)) + return NULL; + if(nroots >= (1u<<symsize)) + return NULL; /* Can't have more roots than symbol values! */ + + rs = (struct rs *)calloc(1,sizeof(struct rs)); + rs->mm = symsize; + rs->nn = (1<<symsize)-1; + + rs->alpha_to = (DTYPE *)malloc(sizeof(DTYPE)*(rs->nn+1)); + if(rs->alpha_to == NULL){ + free(rs); + return NULL; + } + rs->index_of = (DTYPE *)malloc(sizeof(DTYPE)*(rs->nn+1)); + if(rs->index_of == NULL){ + free(rs->alpha_to); + free(rs); + return NULL; + } + + /* Generate Galois field lookup tables */ + rs->index_of[0] = A0; /* log(zero) = -inf */ + rs->alpha_to[A0] = 0; /* alpha**-inf = 0 */ + sr = 1; + for(i=0;i<rs->nn;i++){ + rs->index_of[sr] = i; + rs->alpha_to[i] = sr; + sr <<= 1; + if(sr & (1<<symsize)) + sr ^= gfpoly; + sr &= rs->nn; + } + if(sr != 1){ + /* field generator polynomial is not primitive! */ + free(rs->alpha_to); + free(rs->index_of); + free(rs); + return NULL; + } + + /* Form RS code generator polynomial from its roots */ + rs->genpoly = (DTYPE *)malloc(sizeof(DTYPE)*(nroots+1)); + if(rs->genpoly == NULL){ + free(rs->alpha_to); + free(rs->index_of); + free(rs); + return NULL; + } + rs->fcr = fcr; + rs->prim = prim; + rs->nroots = nroots; + + /* Find prim-th root of 1, used in decoding */ + for(iprim=1;(iprim % prim) != 0;iprim += rs->nn) + ; + rs->iprim = iprim / prim; + + rs->genpoly[0] = 1; + for (i = 0,root=fcr*prim; i < nroots; i++,root += prim) { + rs->genpoly[i+1] = 1; + + /* Multiply rs->genpoly[] by @**(root + x) */ + for (j = i; j > 0; j--){ + if (rs->genpoly[j] != 0) + rs->genpoly[j] = rs->genpoly[j-1] ^ rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[j]] + root)]; + else + rs->genpoly[j] = rs->genpoly[j-1]; + } + /* rs->genpoly[0] can never be zero */ + rs->genpoly[0] = rs->alpha_to[modnn(rs,rs->index_of[rs->genpoly[0]] + root)]; + } + /* convert rs->genpoly[] to index form for quicker encoding */ + for (i = 0; i <= nroots; i++) + rs->genpoly[i] = rs->index_of[rs->genpoly[i]]; + +#if 0 + printf ("genpoly:\n"); + for (i = nroots; i >= 0; i--){ + printf (" %3d*X^%d\n", rs->alpha_to[rs->genpoly[i]], i); + } +#endif + + return rs; +} diff --git a/gnuradio-core/src/lib/reed-solomon/int.h b/gnuradio-core/src/lib/reed-solomon/int.h new file mode 100644 index 000000000..403d68757 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/int.h @@ -0,0 +1,55 @@ +/* Include file to configure the RS codec for integer symbols + * + * Copyright 2002, Phil Karn, KA9Q + * May be used under the terms of the GNU General Public License (GPL) + */ +#define DTYPE int + +#include <gr_core_api.h> + +/* Reed-Solomon codec control block */ +struct GR_CORE_API rs { + unsigned int mm; /* Bits per symbol */ + unsigned int nn; /* Symbols per block (= (1<<mm)-1) */ + int *alpha_to; /* log lookup table */ + int *index_of; /* Antilog lookup table */ + int *genpoly; /* Generator polynomial */ + unsigned int nroots; /* Number of generator roots = number of parity symbols */ + unsigned int fcr; /* First consecutive root, index form */ + unsigned int prim; /* Primitive element, index form */ + unsigned int iprim; /* prim-th root of 1, index form */ +}; + +static inline int modnn(struct rs *rs,int x){ + while (x >= rs->nn) { + x -= rs->nn; + x = (x >> rs->mm) + (x & rs->nn); + } + return x; +} +#define MODNN(x) modnn(rs,x) + +#define MM (rs->mm) +#define NN (rs->nn) +#define ALPHA_TO (rs->alpha_to) +#define INDEX_OF (rs->index_of) +#define GENPOLY (rs->genpoly) +#define NROOTS (rs->nroots) +#define FCR (rs->fcr) +#define PRIM (rs->prim) +#define IPRIM (rs->iprim) +#define A0 (NN) + +#define ENCODE_RS encode_rs_int +#define DECODE_RS decode_rs_int +#define INIT_RS init_rs_int +#define FREE_RS free_rs_int + +GR_CORE_API void ENCODE_RS(void *p,DTYPE *data,DTYPE *parity); +GR_CORE_API int DECODE_RS(void *p,DTYPE *data,int *eras_pos,int no_eras); +void *INIT_RS(unsigned int symsize,unsigned int gfpoly,unsigned int fcr, + unsigned int prim,unsigned int nroots); +GR_CORE_API void FREE_RS(void *p); + + + diff --git a/gnuradio-core/src/lib/reed-solomon/rs.3 b/gnuradio-core/src/lib/reed-solomon/rs.3 new file mode 100644 index 000000000..c3953ce57 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/rs.3 @@ -0,0 +1,170 @@ +.TH REED-SOLOMON 3 +.SH NAME +init_rs_int, encode_rs_int, decode_rs_int, free_rs_int, +init_rs_char, encode_rs_char, decode_rs_char, free_rs_char, +encode_rs_8, decode_rs_8, encode_rs_ccsds, decode_rs_ccsds +.SH SYNOPSIS +.nf +.ft B +#include "rs.h" + +void *init_rs_int(unsigned int symsize,unsigned int gfpoly,unsigned fcr, +unsigned prim,unsigned int nroots); +void encode_rs_int(void *rs,int *data,int *parity); +int decode_rs_int(void *rs,int *data,int *eras_pos,int no_eras); +void free_rs_int(void *rs); + +void *init_rs_char(unsigned int symsize,unsigned int gfpoly,unsigned fcr, +unsigned prim,unsigned int nroots); +void encode_rs_char(void *rs,unsigned char *data,unsigned char *parity); +int decode_rs_char(void *rs,unsigned char *data,int *eras_pos,int no_eras); +void free_rs_char(void *rs); + +void encode_rs_8(unsigned char *data,unsigned char *parity); +int decode_rs_8(unsigned char *data,int *eras_pos,int no_eras); + +void encode_rs_ccsds(unsigned char *data,unsigned char *parity); +int decode_rs_ccsds(unsigned char *data,int *eras_pos,int no_eras); + +unsigned char Taltab[256]; +unsigned char Tal1tab[256]; + +.fi + +.SH DESCRIPTION +These functions implement Reed-Solomon error control encoding and +decoding. For optimal performance in a variety of applications, three +sets of functions are supplied. To access these functions, add "-lrs" +to your linker command line. + +The functions with names ending in "_int" handle data in integer arrays, +permitting arbitrarily large codewords limited only by machine +resources. + +The functions with names ending in "_char" take unsigned char arrays and can +handle codes with symbols of 8 bits or less (i.e., with codewords of +255 symbols or less). + +\fBencode_rs_8\fR and \fBdecode_rs_8\fR implement a specific +(255,223) code with 8-bit symbols specified by the CCSDS: +a field generator of 1 + X + X^2 + X^7 + X^8 and a code +generator with first consecutive root = 112 and a primitive element of +11. These functions use the conventional +polynomial form, \fBnot\fR the dual-basis specified in +the CCSDS standard, to represent symbols. + +For full CCSDS compatibility, \fBencode_rs_ccsds\fR and +\fBdecode_rs_ccsds\fR are provided. These functions use two lookup +tables, \fBTaltab\fR to convert from conventional to dual-basis, and +\fBTal1tab\fR to perform the inverse mapping from dual-basis to +conventional form, before and after calls to \fBencode_rs_8\fR +and \fBdecode_rs_8\fR. + +The _8 and _ccsds functions do not require initialization. +To use the general purpose RS encoder or decoder (i.e., +the _char or _int versions), the user must first +call \fBinit_rs_int\fR or \fBinit_rs_char\fR as appropriate. The +arguments are as follows: + +\fBsymsize\fR gives the symbol size in bits, up to 8 for \fBinit_rs_char\fR +or 32 for \fBinit_rs_int\fR on a machine with 32-bit ints (though such a +huge code would exhaust memory limits on a 32-bit machine). The resulting +Reed-Solomon code word will have 2^\fBsymsize\fR - 1 symbols, +each containing \fBsymsize\fR bits. + +\fBgfpoly\fR gives the extended Galois field generator polynomial coefficients, +with the 0th coefficient in the low order bit. The polynomial +\fImust\fR be primitive; if not, the call will fail and NULL will be +returned. + +\fBfcr\fR gives, in index form, the first consecutive root of the +Reed Solomon code generator polynomial. + +\fBprim\fR gives, in index form, the primitive element in the Galois field +used to generate the Reed Solomon code generator polynomial. + +\fBnroots\fR gives the number of roots in the Reed Solomon code +generator polynomial. This equals the number of parity symbols +per code block. + +The resulting Reed-Solomon code has parameters (N,K), where +N = 2^\fBsymsize\fR-1 and K = N-\fBnroots\fR. + +The \fBencode_rs_char\fR and \fBencode_rs_int\fR functions accept +the pointer returned by \fBinit_rs_char\fR or +\fBinit_rs_int\fR, respectively, to +encode a block of data using the specified code. +The input data array is expected to +contain K symbols (of \fBsymsize\fR bits each, right justified +in each char or int) and \fBnroots\fR parity symbols will be placed +into the \fBparity\fR array, right justified. + +The \fBdecode_rs_char\fR and \fBdecode_rs_int\fR functions correct +the errors in a Reed-Solomon codeword up to the capability of the code. +An optional list of "erased" symbol indices may be given in the \fBeras_pos\fR +array to assist the decoder; this parameter may be NULL if no erasures +are given. The number of erased symbols must be given in the \fBno_eras\fR +parameter. + +To maximize performance, the encode and decode functions perform no +"sanity checking" of their inputs. Decoder failure may result if +\fBeras_pos\fR contains duplicate entries, and both encoder and +decoder will fail if an input symbol exceeds its allowable range. +(Symbol range overflow cannot occur with the _8 or _ccsds functions, +or with the _char functions when 8-bit symbols are specified.) + +The decoder corrects the symbols "in place", returning the number +of symbols in error. If the codeword is uncorrectable, -1 is returned +and the data block is unchanged. If \fBeras_pos\fR is non-null, it is +used to return a list of corrected symbol positions, in no particular +order. This means that the +array passed through this parameter \fImust\fR have at least \fBnroots\fR +elements to prevent a possible buffer overflow. + +The \fBfree_rs_int\fR and \fBfree_rs_char\fR functions free the internal +space allocated by the \fBinit_rs_int\fR and \fBinit_rs_char\fR functions, +respecitively. + +The functions \fBencode_rs_8\fR and \fBdecode_rs_8\fR do not have +corresponding \fBinit\fR and \fBfree\fR, nor do they take the +\fBrs\fR argument accepted by the other functions as their parameters +are statically compiled. These functions implement a code +equivalent to calling + +\fBinit_rs_char\fR(8,0x187,112,11,32); + +and using the resulting pointer with \fBencode_rs_char\fR and +\fBdecode_rs_char\fR. + +.SH RETURN VALUES +\fBinit_rs_int\fR and \fBinit_rs_char\fR return a pointer to an internal +control structure that must be passed to the corresponding encode, decode +and free functions. These functions return NULL on error. + +The decode functions return a count of corrected +symbols, or -1 if the block was uncorrectible. + +.SH AUTHOR +Phil Karn, KA9Q (karn@ka9q.net), based heavily on earlier work by Robert +Morelos-Zaragoza (rober@spectra.eng.hawaii.edu) and Hari Thirumoorthy +(harit@spectra.eng.hawaii.edu). + +.SH COPYRIGHT +Copyright 2002, Phil Karn, KA9Q. May be used under the terms of the +GNU General Public License (GPL). + +.SH SEE ALSO +CCSDS 101.0-B-5: Telemetry Channel Coding. +http://www.ccsds.org/documents/pdf/CCSDS-101.0-B-5.pdf + +.SH NOTE +CCSDS chose the "dual basis" symbol representation because it +simplified the implementation of a Reed-Solomon encoder in dedicated +hardware. However, this approach holds no advantages for a software +implementation on a general purpose computer, so use of the dual basis +is recommended only if compatibility with the CCSDS standard is needed, +e.g., to decode data from an existing spacecraft using the CCSDS +standard. If you just want a fast (255,223) RS codec without needing +to interoperate with a CCSDS standard code, use \fBencode_rs_8\fR +and \fBdecode_rs_8\fR. + diff --git a/gnuradio-core/src/lib/reed-solomon/rs.h b/gnuradio-core/src/lib/reed-solomon/rs.h new file mode 100644 index 000000000..97e78769e --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/rs.h @@ -0,0 +1,31 @@ +#include <gr_core_api.h> +/* User include file for the Reed-Solomon codec + * Copyright 2002, Phil Karn KA9Q + * May be used under the terms of the GNU General Public License (GPL) + */ + +/* General purpose RS codec, 8-bit symbols */ +GR_CORE_API void encode_rs_char(void *rs,unsigned char *data,unsigned char *parity); +GR_CORE_API int decode_rs_char(void *rs,unsigned char *data,int *eras_pos, + int no_eras); +GR_CORE_API void *init_rs_char(unsigned int symsize,unsigned int gfpoly, + unsigned int fcr,unsigned int prim,unsigned int nroots); +GR_CORE_API void free_rs_char(void *rs); + +/* General purpose RS codec, integer symbols */ +GR_CORE_API void encode_rs_int(void *rs,int *data,int *parity); +GR_CORE_API int decode_rs_int(void *rs,int *data,int *eras_pos,int no_eras); +GR_CORE_API void *init_rs_int(unsigned int symsize,unsigned int gfpoly,unsigned int fcr, + unsigned int prim,unsigned int nroots); +GR_CORE_API void free_rs_int(void *rs); + +/* CCSDS standard (255,223) RS codec with conventional (*not* dual-basis) + * symbol representation + */ +GR_CORE_API void encode_rs_8(unsigned char *data,unsigned char *parity); +GR_CORE_API int decode_rs_8(unsigned char *data,int *eras_pos,int no_eras); + +/* Tables to map from conventional->dual (Taltab) and + * dual->conventional (Tal1tab) bases + */ +extern unsigned char Taltab[],Tal1tab[]; diff --git a/gnuradio-core/src/lib/reed-solomon/rstest.c b/gnuradio-core/src/lib/reed-solomon/rstest.c new file mode 100644 index 000000000..d8fc5448a --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/rstest.c @@ -0,0 +1,117 @@ +/* Test the Reed-Solomon codecs + * for various block sizes and with random data and random error patterns + * + * Copyright 2002 Phil Karn, KA9Q + * May be used under the terms of the GNU General Public License (GPL) + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include "rs.h" + +int exercise_char(void *,int); + +#ifdef ALL_VERSIONS +int exercise_int(void *,int); +int exercise_8(int); +int exercise_ccsds(int); +#endif + +struct { + int symsize; + int genpoly; + int fcs; + int prim; + int nroots; + int ntrials; +} Tab[] = { + {2, 0x7, 1, 1, 1, 10 }, + {3, 0xb, 1, 1, 2, 10 }, + {4, 0x13, 1, 1, 4, 10 }, + {5, 0x25, 1, 1, 6, 10 }, + {6, 0x43, 1, 1, 8, 10 }, + {7, 0x89, 1, 1, 10, 10 }, + {8, 0x11d, 1, 1, 32, 10 }, + {8, 0x187, 112,11, 32, 10 }, /* Duplicates CCSDS codec */ +#ifdef ALL_VESIONS + {9, 0x211, 1, 1, 32, 10 }, + {10,0x409, 1, 1, 32, 10 }, + {11,0x805, 1, 1, 32, 10 }, + {12,0x1053, 1, 1, 32, 5 }, + {13,0x201b, 1, 1, 32, 2 }, + {14,0x4443, 1, 1, 32, 1 }, + {15,0x8003, 1, 1, 32, 1 }, + {16,0x1100b, 1, 1, 32, 1 }, +#endif + {0, 0, 0, 0, 0}, +}; + +int main(){ + void *handle; + int errs,terrs; + int i; + + terrs = 0; + srandom(time(NULL)); + +#ifdef ALL_VERSIONS + printf("Testing fixed (255,223) RS codec..."); + fflush(stdout); + errs = exercise_8(10); + terrs += errs; + if(errs == 0){ + printf("OK\n"); + } + printf("Testing CCSDS standard (255,223) RS codec..."); + fflush(stdout); + errs = exercise_ccsds(10); + terrs += errs; + if(errs == 0){ + printf("OK\n"); + } +#endif + + for(i=0;Tab[i].symsize != 0;i++){ + int nn,kk; + + nn = (1<<Tab[i].symsize) - 1; + kk = nn - Tab[i].nroots; + printf("Testing (%d,%d) RS codec...",nn,kk); + fflush(stdout); + if(Tab[i].symsize <= 8){ + if((handle = init_rs_char(Tab[i].symsize,Tab[i].genpoly,Tab[i].fcs,Tab[i].prim,Tab[i].nroots)) == NULL){ + printf("init_rs_char failed!\n"); + continue; + } + errs = exercise_char(handle,Tab[i].ntrials); + } else { +#ifdef ALL_VERSIONS + if((handle = init_rs_int(Tab[i].symsize,Tab[i].genpoly,Tab[i].fcs,Tab[i].prim,Tab[i].nroots)) == NULL){ + printf("init_rs_int failed!\n"); + continue; + } + errs = exercise_int(handle,Tab[i].ntrials); +#else + printf ("init_rs_init support is not enabled\n"); + exit (1); +#endif + + } + terrs += errs; + if(errs == 0){ + printf("OK\n"); + } + free_rs_char(handle); + } + if(terrs == 0) + printf("All codec tests passed!\n"); + + exit(0); +} + + diff --git a/gnuradio-core/src/lib/runtime/CMakeLists.txt b/gnuradio-core/src/lib/runtime/CMakeLists.txt new file mode 100644 index 000000000..5f2c317c4 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/CMakeLists.txt @@ -0,0 +1,187 @@ +# Copyright 2010-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. + +######################################################################## +# This file included, use CMake directory variables +######################################################################## + +######################################################################## +# Control availability of vmcircbuf methods. +# For now, only allows disabling of shm methods, which cause uncatchable +# segmentation faults on Cygwin with gcc 4.x (x <= 5) +# Usage: +# GR_VMCIRCBUF() +# +# Will set TRY_SHM_VMCIRCBUF to 1 by default except on Windows machines. +# Can manually set with -DTRY_SHM_VMCIRCBUF=0|1 +######################################################################## + + if(WIN32) + OPTION(TRY_SHM_VMCIRCBUF "Try SHM VMCIRCBUF" OFF) + else(WIN32) + OPTION(TRY_SHM_VMCIRCBUF "Try SHM VMCIRCBUF" ON) + endif(WIN32) + + message(STATUS "TRY_SHM_VMCIRCBUF set to ${TRY_SHM_VMCIRCBUF}.") + + if(TRY_SHM_VMCIRCBUF) + add_definitions( -DTRY_SHM_VMCIRCBUF ) + endif(TRY_SHM_VMCIRCBUF) + +######################################################################## +# Append gnuradio-core library sources +######################################################################## +list(APPEND gnuradio_core_sources + #${CMAKE_CURRENT_SOURCE_DIR}/gr_basic_block.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_flowgraph.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_flat_flowgraph.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_block.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_block_detail.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_block_executor.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_block_registry.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_hier_block2.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_hier_block2_detail.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_buffer.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_dispatcher.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_error_handler.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_io_signature.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_local_sighandler.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_message.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_msg_accepter.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_msg_handler.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_msg_queue.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_pagesize.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_preferences.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_realtime.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_scheduler.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_scheduler_sts.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_scheduler_tpb.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_single_threaded_scheduler.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_sptr_magic.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_sync_block.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_sync_decimator.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_sync_interpolator.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_sys_paths.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_top_block.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_top_block_impl.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_tpb_detail.cc + #${CMAKE_CURRENT_SOURCE_DIR}/gr_tpb_thread_body.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_vmcircbuf.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_vmcircbuf_mmap_shm_open.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_vmcircbuf_mmap_tmpfile.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_vmcircbuf_createfilemapping.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_vmcircbuf_sysv_shm.cc + ${CMAKE_CURRENT_SOURCE_DIR}/gr_select_handler.cc +) + +######################################################################## +# Append gnuradio-core test sources +######################################################################## +list(APPEND test_gnuradio_core_sources + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_block.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_hier_block2.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_hier_block2_derived.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_buffer.cc + #${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_flowgraph.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_top_block.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_io_signature.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_gr_vmcircbuf.cc + #${CMAKE_CURRENT_SOURCE_DIR}/qa_block_tags.cc + ${CMAKE_CURRENT_SOURCE_DIR}/qa_runtime.cc + #${CMAKE_CURRENT_SOURCE_DIR}/qa_set_msg_handler.cc +) + +######################################################################## +# Install runtime headers +######################################################################## +install(FILES + ${CMAKE_CURRENT_SOURCE_DIR}/gr_basic_block.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_flowgraph.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_flat_flowgraph.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_block.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_block_detail.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_block_executor.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_block_registry.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_hier_block2.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_hier_block2_detail.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_buffer.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_complex.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_dispatcher.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_error_handler.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_io_signature.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_local_sighandler.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_message.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_msg_accepter.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_msg_handler.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_msg_queue.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_pagesize.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_preferences.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_realtime.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_runtime_types.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_scheduler.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_scheduler_sts.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_scheduler_tpb.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_select_handler.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_single_threaded_scheduler.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_sptr_magic.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_sync_block.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_sync_decimator.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_sync_interpolator.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_top_block.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_top_block_impl.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_tpb_detail.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_tpb_thread_body.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_timer.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_sys_paths.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_types.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_unittests.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_vmcircbuf.h + ${CMAKE_CURRENT_SOURCE_DIR}/gr_tags.h + DESTINATION ${GR_INCLUDE_DIR}/gnuradio + COMPONENT "core_devel" +) + +######################################################################## +# Install swig headers +######################################################################## +if(ENABLE_PYTHON) +install(FILES + ${CMAKE_CURRENT_SOURCE_DIR}/gr_basic_block.i + ${CMAKE_CURRENT_SOURCE_DIR}/gr_block.i + ${CMAKE_CURRENT_SOURCE_DIR}/gr_block_detail.i + ${CMAKE_CURRENT_SOURCE_DIR}/gr_hier_block2.i + ${CMAKE_CURRENT_SOURCE_DIR}/gr_buffer.i + ${CMAKE_CURRENT_SOURCE_DIR}/gr_dispatcher.i + ${CMAKE_CURRENT_SOURCE_DIR}/gr_error_handler.i + ${CMAKE_CURRENT_SOURCE_DIR}/gr_io_signature.i + ${CMAKE_CURRENT_SOURCE_DIR}/gr_message.i + ${CMAKE_CURRENT_SOURCE_DIR}/gr_msg_handler.i + ${CMAKE_CURRENT_SOURCE_DIR}/gr_msg_queue.i + ${CMAKE_CURRENT_SOURCE_DIR}/gr_realtime.i + ${CMAKE_CURRENT_SOURCE_DIR}/gr_single_threaded_scheduler.i + ${CMAKE_CURRENT_SOURCE_DIR}/gr_sync_block.i + ${CMAKE_CURRENT_SOURCE_DIR}/gr_sync_decimator.i + ${CMAKE_CURRENT_SOURCE_DIR}/gr_sync_interpolator.i + ${CMAKE_CURRENT_SOURCE_DIR}/gr_tags.i + ${CMAKE_CURRENT_SOURCE_DIR}/gr_top_block.i + ${CMAKE_CURRENT_SOURCE_DIR}/runtime.i + DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig + COMPONENT "core_swig" +) +endif(ENABLE_PYTHON) diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.cc b/gnuradio-core/src/lib/runtime/gr_basic_block.cc new file mode 100644 index 000000000..6ff57a1d6 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.cc @@ -0,0 +1,227 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,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 <gr_basic_block.h> +#include <gr_block_registry.h> +#include <stdexcept> +#include <sstream> +#include <iostream> + +using namespace pmt; + +static long s_next_id = 0; +static long s_ncurrently_allocated = 0; + +long +gr_basic_block_ncurrently_allocated() +{ + return s_ncurrently_allocated; +} + +gr_basic_block::gr_basic_block(const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature) + : d_name(name), + d_input_signature(input_signature), + d_output_signature(output_signature), + d_unique_id(s_next_id++), + d_symbolic_id(global_block_registry.block_register(this)), + d_symbol_name(global_block_registry.register_symbolic_name(this)), + d_color(WHITE), + message_subscribers(pmt::pmt_make_dict()) +{ + s_ncurrently_allocated++; +} + +gr_basic_block::~gr_basic_block() +{ + s_ncurrently_allocated--; + global_block_registry.block_unregister(this); +} + +gr_basic_block_sptr +gr_basic_block::to_basic_block() +{ + return shared_from_this(); +} + +void +gr_basic_block::set_block_alias(std::string name) +{ + global_block_registry.register_symbolic_name(this, name); +} + +// ** Message passing interface ** + +// - register a new input message port +void +gr_basic_block::message_port_register_in(pmt::pmt_t port_id) +{ + if(!pmt::pmt_is_symbol(port_id)) { + throw std::runtime_error("message_port_register_in: bad port id"); + } + msg_queue[port_id] = msg_queue_t(); + msg_queue_ready[port_id] = boost::shared_ptr<boost::condition_variable>(new boost::condition_variable()); +} + +pmt::pmt_t +gr_basic_block::message_ports_in() +{ + pmt::pmt_t port_names = pmt::pmt_make_vector(msg_queue.size(), pmt::PMT_NIL); + msg_queue_map_itr itr = msg_queue.begin(); + for(size_t i = 0; i < msg_queue.size(); i++) { + pmt::pmt_vector_set(port_names, i, (*itr).first); + itr++; + } + return port_names; +} + +// - register a new output message port +void +gr_basic_block::message_port_register_out(pmt::pmt_t port_id) +{ + if(!pmt::pmt_is_symbol(port_id)) { + throw std::runtime_error("message_port_register_out: bad port id"); + } + if(pmt::pmt_dict_has_key(message_subscribers, port_id)) { + throw std::runtime_error("message_port_register_out: port already in use"); + } + message_subscribers = pmt::pmt_dict_add(message_subscribers, port_id, pmt::PMT_NIL); +} + +pmt::pmt_t +gr_basic_block::message_ports_out() +{ + size_t len = pmt::pmt_length(message_subscribers); + pmt::pmt_t port_names = pmt::pmt_make_vector(len, pmt::PMT_NIL); + pmt::pmt_t keys = pmt::pmt_dict_keys(message_subscribers); + for(size_t i = 0; i < len; i++) { + pmt::pmt_vector_set(port_names, i, pmt::pmt_nth(i, keys)); + } + return port_names; +} + +// - publish a message on a message port +void gr_basic_block::message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg) +{ + if(!pmt::pmt_dict_has_key(message_subscribers, port_id)) { + throw std::runtime_error("port does not exist"); + } + + pmt::pmt_t currlist = pmt::pmt_dict_ref(message_subscribers, port_id, pmt::PMT_NIL); + // iterate through subscribers on port + while(pmt::pmt_is_pair(currlist)) { + pmt::pmt_t target = pmt::pmt_car(currlist); + + pmt::pmt_t block = pmt::pmt_car(target); + pmt::pmt_t port = pmt::pmt_cdr(target); + + currlist = pmt::pmt_cdr(currlist); + gr_basic_block_sptr blk = global_block_registry.block_lookup(block); + //blk->post(msg); + blk->post(port, msg); + } +} + +// - subscribe to a message port +void +gr_basic_block::message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target){ + if(!pmt::pmt_dict_has_key(message_subscribers, port_id)){ + std::stringstream ss; + ss << "Port does not exist: \"" << pmt::pmt_write_string(port_id) << "\" on block: " << pmt::pmt_write_string(target) << std::endl; + throw std::runtime_error(ss.str()); + } + pmt::pmt_t currlist = pmt::pmt_dict_ref(message_subscribers,port_id,pmt::PMT_NIL); + + // ignore re-adds of the same target + if(!pmt::pmt_list_has(currlist, target)) + message_subscribers = pmt::pmt_dict_add(message_subscribers,port_id,pmt::pmt_list_add(currlist,target)); +} + +void +gr_basic_block::message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target){ + if(!pmt::pmt_dict_has_key(message_subscribers, port_id)){ + std::stringstream ss; + ss << "Port does not exist: \"" << pmt::pmt_write_string(port_id) << "\" on block: " << pmt::pmt_write_string(target) << std::endl; + throw std::runtime_error(ss.str()); + } + + // ignore unsubs of unknown targets + pmt::pmt_t currlist = pmt::pmt_dict_ref(message_subscribers,port_id,pmt::PMT_NIL); + message_subscribers = pmt::pmt_dict_add(message_subscribers,port_id,pmt::pmt_list_rm(currlist,target)); +} + +void +gr_basic_block::_post(pmt_t which_port, pmt_t msg) +{ + insert_tail(which_port, msg); +} + +void +gr_basic_block::insert_tail(pmt::pmt_t which_port, pmt::pmt_t msg) +{ + gruel::scoped_lock guard(mutex); + + if( (msg_queue.find(which_port) == msg_queue.end()) || (msg_queue_ready.find(which_port) == msg_queue_ready.end())){ + std::cout << "target port = " << pmt::pmt_symbol_to_string(which_port) << std::endl; + throw std::runtime_error("attempted to insert_tail on invalid queue!"); + } + + msg_queue[which_port].push_back(msg); + msg_queue_ready[which_port]->notify_one(); + + // wake up thread if BLKD_IN or BLKD_OUT + global_block_registry.notify_blk(alias()); +} + +pmt_t +gr_basic_block::delete_head_nowait(pmt::pmt_t which_port) +{ + gruel::scoped_lock guard(mutex); + + if (empty_p(which_port)){ + return pmt::pmt_t(); + } + + pmt_t m(msg_queue[which_port].front()); + msg_queue[which_port].pop_front(); + + return m; +} + +pmt_t +gr_basic_block::delete_head_blocking(pmt::pmt_t which_port) +{ + gruel::scoped_lock guard(mutex); + + while (empty_p(which_port)){ + msg_queue_ready[which_port]->wait(guard); + } + + pmt_t m(msg_queue[which_port].front()); + msg_queue[which_port].pop_front(); + return m; +} diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.h b/gnuradio-core/src/lib/runtime/gr_basic_block.h new file mode 100644 index 000000000..024159c4c --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.h @@ -0,0 +1,299 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,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_GR_BASIC_BLOCK_H +#define INCLUDED_GR_BASIC_BLOCK_H + +#include <gr_core_api.h> +#include <gr_runtime_types.h> +#include <gr_sptr_magic.h> +#include <boost/enable_shared_from_this.hpp> +#include <boost/function.hpp> +#include <gr_msg_accepter.h> +#include <string> +#include <deque> +#include <map> +#include <gr_io_signature.h> +#include <gruel/thread.h> +#include <boost/foreach.hpp> +#include <boost/thread/condition_variable.hpp> +#include <iostream> + +/*! + * \brief The abstract base class for all signal processing blocks. + * \ingroup internal + * + * Basic blocks are the bare abstraction of an entity that has a name, + * a set of inputs and outputs, and a message queue. These are never instantiated + * directly; rather, this is the abstract parent class of both gr_hier_block, + * which is a recursive container, and gr_block, which implements actual + * signal processing functions. + */ + +class GR_CORE_API gr_basic_block : public gr_msg_accepter, public boost::enable_shared_from_this<gr_basic_block> +{ + typedef boost::function<void(pmt::pmt_t)> msg_handler_t; + + private: + + //msg_handler_t d_msg_handler; + typedef std::map<pmt::pmt_t , msg_handler_t, pmt::pmt_comperator> d_msg_handlers_t; + d_msg_handlers_t d_msg_handlers; + + typedef std::deque<pmt::pmt_t> msg_queue_t; + typedef std::map<pmt::pmt_t, msg_queue_t, pmt::pmt_comperator> msg_queue_map_t; + typedef std::map<pmt::pmt_t, msg_queue_t, pmt::pmt_comperator>::iterator msg_queue_map_itr; + std::map<pmt::pmt_t, boost::shared_ptr<boost::condition_variable>, pmt::pmt_comperator> msg_queue_ready; + + gruel::mutex mutex; //< protects all vars + + protected: + friend class gr_flowgraph; + friend class gr_flat_flowgraph; // TODO: will be redundant + friend class gr_tpb_thread_body; + + enum vcolor { WHITE, GREY, BLACK }; + + std::string d_name; + gr_io_signature_sptr d_input_signature; + gr_io_signature_sptr d_output_signature; + long d_unique_id; + long d_symbolic_id; + std::string d_symbol_name; + std::string d_symbol_alias; + vcolor d_color; + msg_queue_map_t msg_queue; + + gr_basic_block(void){} //allows pure virtual interface sub-classes + + //! Protected constructor prevents instantiation by non-derived classes + gr_basic_block(const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); + + //! may only be called during constructor + void set_input_signature(gr_io_signature_sptr iosig) { + d_input_signature = iosig; + } + + //! may only be called during constructor + void set_output_signature(gr_io_signature_sptr iosig) { + d_output_signature = iosig; + } + + /*! + * \brief Allow the flowgraph to set for sorting and partitioning + */ + void set_color(vcolor color) { d_color = color; } + vcolor color() const { return d_color; } + + /*! + * \brief Tests if there is a handler attached to port \p which_port + */ + bool has_msg_handler(pmt::pmt_t which_port) { + return (d_msg_handlers.find(which_port) != d_msg_handlers.end()); + } + + /* + * This function is called by the runtime system to dispatch messages. + * + * The thread-safety guarantees mentioned in set_msg_handler are implemented + * by the callers of this method. + */ + virtual void dispatch_msg(pmt::pmt_t which_port, pmt::pmt_t msg) + { + // AA Update this + if(has_msg_handler(which_port)) { // Is there a handler? + d_msg_handlers[which_port](msg); // Yes, invoke it. + } + } + + // Message passing interface + pmt::pmt_t message_subscribers; + + public: + virtual ~gr_basic_block(); + long unique_id() const { return d_unique_id; } + long symbolic_id() const { return d_symbolic_id; } + std::string name() const { return d_name; } + std::string symbol_name() const { return d_symbol_name; } + gr_io_signature_sptr input_signature() const { return d_input_signature; } + gr_io_signature_sptr output_signature() const { return d_output_signature; } + gr_basic_block_sptr to_basic_block(); // Needed for Python type coercion + bool alias_set() { return !d_symbol_alias.empty(); } + std::string alias(){ return alias_set()?d_symbol_alias:symbol_name(); } + pmt::pmt_t alias_pmt(){ return pmt::pmt_intern(alias()); } + void set_block_alias(std::string name); + + // ** Message passing interface ** + void message_port_register_in(pmt::pmt_t port_id); + void message_port_register_out(pmt::pmt_t port_id); + void message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg); + void message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target); + void message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target); + + virtual bool message_port_is_hier(pmt::pmt_t port_id) { (void) port_id; std::cout << "is_hier\n"; return false; } + virtual bool message_port_is_hier_in(pmt::pmt_t port_id) { (void) port_id; std::cout << "is_hier_in\n"; return false; } + virtual bool message_port_is_hier_out(pmt::pmt_t port_id) { (void) port_id; std::cout << "is_hier_out\n"; return false; } + + /*! + * \brief Get input message port names. + * + * Returns the available input message ports for a block. The + * return object is a PMT vector that is filled with PMT symbols. + */ + pmt::pmt_t message_ports_in(); + + /*! + * \brief Get output message port names. + * + * Returns the available output message ports for a block. The + * return object is a PMT vector that is filled with PMT symbols. + */ + pmt::pmt_t message_ports_out(); + + /*! + * Accept msg, place in queue, arrange for thread to be awakened if it's not already. + */ + void _post(pmt::pmt_t which_port, pmt::pmt_t msg); + + //! is the queue empty? + //bool empty_p(const pmt::pmt_t &which_port) const { return msg_queue[which_port].empty(); } + bool empty_p(pmt::pmt_t which_port) { + if(msg_queue.find(which_port) == msg_queue.end()) + throw std::runtime_error("port does not exist!"); + return msg_queue[which_port].empty(); + } + bool empty_p() { + bool rv = true; + BOOST_FOREACH(msg_queue_map_t::value_type &i, msg_queue) { + rv &= msg_queue[i.first].empty(); + } + return rv; + } + + //! How many messages in the queue? + size_t nmsgs(pmt::pmt_t which_port) { + if(msg_queue.find(which_port) == msg_queue.end()) + throw std::runtime_error("port does not exist!"); + return msg_queue[which_port].size(); + } + + //| Acquires and release the mutex + void insert_tail( pmt::pmt_t which_port, pmt::pmt_t msg); + /*! + * \returns returns pmt at head of queue or pmt_t() if empty. + */ + pmt::pmt_t delete_head_nowait( pmt::pmt_t which_port); + + /*! + * \returns returns pmt at head of queue or pmt_t() if empty. + */ + pmt::pmt_t delete_head_blocking( pmt::pmt_t which_port); + + msg_queue_t::iterator get_iterator(pmt::pmt_t which_port){ + return msg_queue[which_port].begin(); + } + + void erase_msg(pmt::pmt_t which_port, msg_queue_t::iterator it){ + msg_queue[which_port].erase(it); + } + + virtual bool has_msg_port(pmt::pmt_t which_port){ + if(msg_queue.find(which_port) != msg_queue.end()){ + return true; + } + if(pmt::pmt_dict_has_key(message_subscribers, which_port)){ + return true; + } + return false; + } + + + /*! + * \brief Confirm that ninputs and noutputs is an acceptable combination. + * + * \param ninputs number of input streams connected + * \param noutputs number of output streams connected + * + * \returns true if this is a valid configuration for this block. + * + * This function is called by the runtime system whenever the + * topology changes. Most classes do not need to override this. + * This check is in addition to the constraints specified by the input + * and output gr_io_signatures. + */ + virtual bool check_topology(int ninputs, int noutputs) { (void) ninputs; (void) noutputs; return true; } + + /*! + * \brief Set the callback that is fired when messages are available. + * + * \p msg_handler can be any kind of function pointer or function object + * that has the signature: + * <pre> + * void msg_handler(pmt::pmt msg); + * </pre> + * + * (You may want to use boost::bind to massage your callable into the + * correct form. See gr_nop.{h,cc} for an example that sets up a class + * method as the callback.) + * + * Blocks that desire to handle messages must call this method in their + * constructors to register the handler that will be invoked when messages + * are available. + * + * If the block inherits from gr_block, the runtime system will ensure that + * msg_handler is called in a thread-safe manner, such that work and + * msg_handler will never be called concurrently. This allows msg_handler + * to update state variables without having to worry about thread-safety + * issues with work, general_work or another invocation of msg_handler. + * + * If the block inherits from gr_hier_block2, the runtime system will + * ensure that no reentrant calls are made to msg_handler. + */ + //template <typename T> void set_msg_handler(T msg_handler){ + // d_msg_handler = msg_handler_t(msg_handler); + //} + template <typename T> void set_msg_handler(pmt::pmt_t which_port, T msg_handler){ + if(msg_queue.find(which_port) == msg_queue.end()){ + throw std::runtime_error("attempt to set_msg_handler() on bad input message port!"); } + d_msg_handlers[which_port] = msg_handler_t(msg_handler); + } +}; + +inline bool operator<(gr_basic_block_sptr lhs, gr_basic_block_sptr rhs) +{ + return lhs->unique_id() < rhs->unique_id(); +} + +typedef std::vector<gr_basic_block_sptr> gr_basic_block_vector_t; +typedef std::vector<gr_basic_block_sptr>::iterator gr_basic_block_viter_t; + +GR_CORE_API long gr_basic_block_ncurrently_allocated(); + +inline std::ostream &operator << (std::ostream &os, gr_basic_block_sptr basic_block) +{ + os << basic_block->name() << "(" << basic_block->unique_id() << ")"; + return os; +} + +#endif /* INCLUDED_GR_BASIC_BLOCK_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_basic_block.i b/gnuradio-core/src/lib/runtime/gr_basic_block.i new file mode 100644 index 000000000..91f3d2cfc --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_basic_block.i @@ -0,0 +1,62 @@ +/* -*- 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. + */ + +class gr_basic_block; +typedef boost::shared_ptr<gr_basic_block> gr_basic_block_sptr; +%template(gr_basic_block_sptr) boost::shared_ptr<gr_basic_block>; +%import "pmt_swig.i" +using namespace pmt; + +// support vectors of these... +namespace std { + %template(x_vector_gr_basic_block_sptr) vector<gr_basic_block_sptr>; +}; + +class gr_basic_block +{ +protected: + gr_basic_block(); + +public: + virtual ~gr_basic_block(); + std::string name() const; + std::string symbol_name() const; + gr_io_signature_sptr input_signature() const; + gr_io_signature_sptr output_signature() const; + long unique_id() const; + gr_basic_block_sptr to_basic_block(); + bool check_topology (int ninputs, int noutputs); + std::string alias(); + void set_block_alias(std::string name); + void _post(pmt_t which_port, pmt_t msg); + pmt_t message_ports_in(); + pmt_t message_ports_out(); +}; + +%rename(block_ncurrently_allocated) gr_basic_block_ncurrently_allocated; +long gr_basic_block_ncurrently_allocated(); + +#ifdef SWIGPYTHON +%pythoncode %{ +gr_basic_block_sptr.__repr__ = lambda self: "<gr_basic_block %s (%d)>" % (self.name(), self.unique_id ()) +%} +#endif diff --git a/gnuradio-core/src/lib/runtime/gr_block.cc b/gnuradio-core/src/lib/runtime/gr_block.cc new file mode 100644 index 000000000..443ac8f64 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_block.cc @@ -0,0 +1,459 @@ +/* + * Copyright 2012-2013 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 "pmx_helper.hpp" +#include <gr_block.h> +#include <boost/foreach.hpp> +#include <iostream> +#include <boost/detail/atomic_count.hpp> + +static boost::detail::atomic_count unique_id_pool(0); + +gr_block::gr_block(void) +{ + //NOP +} + +gr_block::gr_block( + const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature +): + gras::Block(name), + _unique_id(++unique_id_pool), + _name(name) +{ + //this initializes private vars, order matters + this->set_fixed_rate(false); + this->set_output_multiple(1); + this->set_history(1); + this->set_relative_rate(1.0); + this->set_decimation(1); + this->set_interpolation(1); + this->set_tag_propagation_policy(TPP_ALL_TO_ALL); + this->set_input_signature(input_signature); + this->set_output_signature(output_signature); +} + +gr_io_signature_sptr gr_block::input_signature(void) const +{ + return _in_sig; +} + +gr_io_signature_sptr gr_block::output_signature(void) const +{ + return _out_sig; +} + +void gr_block::set_input_signature(gr_io_signature_sptr sig) +{ + for (size_t i = 0; i < sig->sizeof_stream_items().size(); i++) + { + this->input_config(i).item_size = sig->sizeof_stream_items().at(i); + } + _in_sig = sig; +} + +void gr_block::set_output_signature(gr_io_signature_sptr sig) +{ + for (size_t i = 0; i < sig->sizeof_stream_items().size(); i++) + { + this->output_config(i).item_size = sig->sizeof_stream_items().at(i); + } + _out_sig = sig; +} + +gr_block::~gr_block(void) +{ + //NOP +} + +void gr_block::notify_active(void) +{ + this->start(); +} + +bool gr_block::start(void) +{ + return true; +} + +void gr_block::notify_inactive(void) +{ + this->stop(); +} + +bool gr_block::stop(void) +{ + return true; +} + +void gr_block::notify_topology(const size_t num_inputs, const size_t num_outputs) +{ + _num_outputs = num_outputs; + _fcast_ninput_items.resize(num_inputs); + _work_ninput_items.resize(num_inputs); + this->check_topology(num_inputs, num_outputs); +} + +bool gr_block::check_topology(int, int) +{ + return true; +} + +void gr_block::work( + const InputItems &input_items, + const OutputItems &output_items +){ + _work_io_ptr_mask = 0; + #define REALLY_BIG size_t(1 << 30) + const size_t num_inputs = input_items.size(); + const size_t num_outputs = output_items.size(); + + //------------------------------------------------------------------ + //-- initialize input buffers before work + //------------------------------------------------------------------ + size_t num_input_items = input_items.min(); + if (_enable_fixed_rate) num_input_items -= _input_history_items; + for (size_t i = 0; i < num_inputs; i++) + { + _work_ninput_items[i] = input_items[i].size(); + _work_io_ptr_mask |= ptrdiff_t(input_items.vec()[i]); + if GRAS_UNLIKELY(_enable_fixed_rate and input_items[i].size() <= _input_history_items) + { + return this->mark_input_fail(i); + } + } + + //------------------------------------------------------------------ + //-- initialize output buffers before work + //------------------------------------------------------------------ + size_t num_output_items = output_items.min(); + num_output_items /= _output_multiple_items; + num_output_items *= _output_multiple_items; + for (size_t i = 0; i < num_outputs; i++) + { + _work_io_ptr_mask |= ptrdiff_t(output_items.vec()[i]); + } + + //------------------------------------------------------------------ + //-- calculate the work_noutput_items given: + //-- min of num_input_items + //-- min of num_output_items + //-- relative rate and output multiple items + //------------------------------------------------------------------ + size_t work_noutput_items = num_output_items; + if (num_inputs and (_enable_fixed_rate or not num_outputs)) + { + size_t calc_output_items = size_t(num_input_items*_relative_rate); + calc_output_items += _output_multiple_items-1; + calc_output_items /= _output_multiple_items; + calc_output_items *= _output_multiple_items; + if (calc_output_items and calc_output_items < work_noutput_items) + work_noutput_items = calc_output_items; + } + + //------------------------------------------------------------------ + //-- forecast + //------------------------------------------------------------------ + if (num_inputs or num_outputs) + { + forecast_again_you_jerk: + _fcast_ninput_items = _work_ninput_items; //init for NOP case + this->forecast(work_noutput_items, _fcast_ninput_items); + for (size_t i = 0; i < input_items.size(); i++) + { + if GRAS_LIKELY(_fcast_ninput_items[i] <= _work_ninput_items[i]) continue; + + //handle the case of forecast failing + if GRAS_UNLIKELY(work_noutput_items <= _output_multiple_items) + { + return this->mark_input_fail(i); + } + + work_noutput_items = work_noutput_items/2; //backoff regime + work_noutput_items += _output_multiple_items-1; + work_noutput_items /= _output_multiple_items; + work_noutput_items *= _output_multiple_items; + goto forecast_again_you_jerk; + } + } + + const int work_ret = this->general_work( + work_noutput_items, + _work_ninput_items, + const_cast<InputItems &>(input_items).vec(), + const_cast<OutputItems &>(output_items).vec() + ); + + if GRAS_LIKELY(work_ret > 0) for (size_t i = 0; i < num_outputs; i++) + { + this->produce(i, work_ret); + } + + if GRAS_UNLIKELY(work_ret == -1) this->mark_done(); +} + +static inline unsigned long long myullround(const double x) +{ + return (unsigned long long)(x + 0.5); +} + +void gr_block::propagate_tags(const size_t which_input, const gras::TagIter &iter) +{ + switch (_tag_prop_policy) + { + case TPP_DONT: break; //well that was ez + case TPP_ALL_TO_ALL: + for (size_t out_i = 0; out_i < _num_outputs; out_i++) + { + BOOST_FOREACH(gras::Tag t, iter) + { + t.offset = myullround(t.offset * _relative_rate); + this->post_output_tag(out_i, t); + } + } + break; + case TPP_ONE_TO_ONE: + if (which_input < _num_outputs) + { + BOOST_FOREACH(gras::Tag t, iter) + { + t.offset = myullround(t.offset * _relative_rate); + this->post_output_tag(which_input, t); + } + } + break; + }; +} + +void gr_block::forecast(int noutput_items, std::vector<int> &ninputs_req) +{ + for (size_t i = 0; i < ninputs_req.size(); i++) + { + ninputs_req[i] = fixed_rate_noutput_to_ninput(noutput_items); + } +} + +int gr_block::general_work( + int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items +){ + throw std::runtime_error("gr_block subclasses must overload general_work!"); +} + +void gr_block::set_alignment(const size_t) +{ + //TODO + //probably dont need this since buffers always start aligned + //and therefore alignment is always re-acheived +} + +size_t gr_block::fixed_rate_noutput_to_ninput(const size_t noutput_items) +{ + return ((decimation()*noutput_items)/interpolation()) + _input_history_items; +} + +void gr_block::set_interpolation(const size_t interp) +{ + _interp = interp; + this->set_relative_rate(1.0*interp); + this->set_output_multiple(interp); +} + +void gr_block::set_decimation(const size_t decim) +{ + _decim = decim; + this->set_relative_rate(1.0/decim); +} + +unsigned gr_block::history(void) const +{ + //implement off-by-one history compat + return _input_history_items+1; +} + +void gr_block::set_history(unsigned history) +{ + //implement off-by-one history compat + if (history == 0) history++; + _input_history_items = history-1; + this->input_config(0).preload_items = _input_history_items; + this->commit_config(); +} + +void gr_block::set_fixed_rate(const bool fixed_rate) +{ + _enable_fixed_rate = fixed_rate; +} + +bool gr_block::fixed_rate(void) const +{ + return _enable_fixed_rate; +} + +void gr_block::_update_input_reserve(void) +{ + /*! + * Set an input reserve for fixed rate blocks. + * + * FIXME: Also do this when output multiple is large, + * This makes gr-trellis pass under conditions where not fixed rate set, + * but the output multiple is so large that default input isnt sufficient. + */ + if (_enable_fixed_rate or _output_multiple_items > 1024) + { + const size_t reserve = size_t(0.5 + _output_multiple_items/_relative_rate); + if (reserve) this->input_config(0).reserve_items = reserve; + } +} + +void gr_block::set_output_multiple(const size_t multiple) +{ + _output_multiple_items = multiple; + this->output_config(0).reserve_items = multiple; + this->_update_input_reserve(); +} + +size_t gr_block::output_multiple(void) const +{ + return _output_multiple_items; +} + +void gr_block::set_relative_rate(double relative_rate) +{ + _relative_rate = relative_rate; + this->_update_input_reserve(); +} + +double gr_block::relative_rate(void) const +{ + return _relative_rate; +} + +int gr_block::max_noutput_items(void) const +{ + return this->output_config(0).maximum_items; +} + +void gr_block::set_max_noutput_items(int max_items) +{ + this->output_config(0).maximum_items = max_items; +} + +void gr_block::unset_max_noutput_items(void) +{ + this->set_max_noutput_items(0); +} + +bool gr_block::is_set_max_noutput_items(void) const +{ + return this->max_noutput_items() != 0; +} + +static gr_tag_t Tag2gr_tag(const gras::Tag &tag) +{ + gr_tag_t t; + t.offset = tag.offset; + const gras::StreamTag &st = tag.object.as<gras::StreamTag>(); + t.key = pmt::pmc_to_pmt(st.key); + t.value = pmt::pmc_to_pmt(st.val); + t.srcid = pmt::pmc_to_pmt(st.src); + return t; +} + +static gras::Tag gr_tag2Tag(const gr_tag_t &tag) +{ + return gras::Tag + ( + tag.offset, + PMC_M(gras::StreamTag( + pmt::pmt_to_pmc(tag.key), + pmt::pmt_to_pmc(tag.value), + pmt::pmt_to_pmc(tag.srcid) + )) + ); +} + +void gr_block::add_item_tag( + const size_t which_output, const gr_tag_t &tag +){ + this->post_output_tag(which_output, gr_tag2Tag(tag)); +} + +void gr_block::add_item_tag( + const size_t which_output, + uint64_t abs_offset, + const pmt::pmt_t &key, + const pmt::pmt_t &value, + const pmt::pmt_t &srcid +){ + gr_tag_t t; + t.offset = abs_offset; + t.key = key; + t.value = value; + t.srcid = srcid; + this->add_item_tag(which_output, t); +} + +void gr_block::get_tags_in_range( + std::vector<gr_tag_t> &tags, + const size_t which_input, + uint64_t abs_start, + uint64_t abs_end, + const pmt::pmt_t &key +){ + tags.clear(); + BOOST_FOREACH(const gras::Tag &tag, this->get_input_tags(which_input)) + { + if (tag.offset >= abs_start and tag.offset <= abs_end) + { + gr_tag_t t = Tag2gr_tag(tag); + if (not key or pmt::pmt_equal(t.key, key)) tags.push_back(t); + } + } +} + +gr_block::tag_propagation_policy_t gr_block::tag_propagation_policy(void) +{ + return _tag_prop_policy; +} + +void gr_block::set_tag_propagation_policy(gr_block::tag_propagation_policy_t p) +{ + _tag_prop_policy = p; +} + +gras::BufferQueueSptr gr_block::input_buffer_allocator(const size_t, const gras::SBufferConfig &config) +{ + if (_input_history_items) + { + return gras::BufferQueue::make_circ(config, 32/*many*/); + } + return gras::BufferQueueSptr(); +} + +gras::BufferQueueSptr gr_block::output_buffer_allocator(const size_t which, const gras::SBufferConfig &config) +{ + return gras::Block::output_buffer_allocator(which, config); +} diff --git a/gnuradio-core/src/lib/runtime/gr_block.h b/gnuradio-core/src/lib/runtime/gr_block.h new file mode 100644 index 000000000..bd085100b --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_block.h @@ -0,0 +1,437 @@ +/* + * Copyright 2012-2013 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_GNURADIO_GR_BLOCK_H +#define INCLUDED_GNURADIO_GR_BLOCK_H + +#include <gr_core_api.h> +#include <gras/block.hpp> +#include <gr_io_signature.h> +#include <gr_types.h> +#include <gr_tags.h> +#include <string> +#include <deque> +#include <map> +#include <boost/foreach.hpp> +#include <gruel/thread.h> +#include <gr_sptr_magic.h> + +struct GR_CORE_API gr_block : gras::Block +{ + + gr_block(void); + + gr_block( + const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature + ); + + long unique_id(void) const{return _unique_id;} + std::string name(void) const{return _name;} + long _unique_id; + std::string _name; + + virtual ~gr_block(void); + + gr_io_signature_sptr input_signature(void) const; + gr_io_signature_sptr output_signature(void) const; + + void set_input_signature(gr_io_signature_sptr sig); + void set_output_signature(gr_io_signature_sptr sig); + + virtual bool check_topology(int ninputs, int noutputs); + + //! Overload me! I am the forecast + virtual void forecast(int, std::vector<int> &); + + //! Return options for the work call + enum + { + WORK_CALLED_PRODUCE = -2, + WORK_DONE = -1 + }; + + /*! + * \brief compute output items from input items + * + * \param noutput_items number of output items to write on each output stream + * \param ninput_items number of input items available on each input stream + * \param input_items vector of pointers to the input items, one entry per input stream + * \param output_items vector of pointers to the output items, one entry per output stream + * + * \returns number of items actually written to each output stream, or -1 on EOF. + * It is OK to return a value less than noutput_items. -1 <= return value <= noutput_items + * + * general_work must call consume or consume_each to indicate how many items + * were consumed on each input stream. + */ + virtual int general_work( + int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items + ); + + virtual bool start(void); + virtual bool stop(void); + + //! Call during work to consume items + void consume_each(const int how_many_items); + + void consume(const size_t i, const int how_many_items); + + void produce(const size_t o, const int how_many_items); + + //! Get absolute count of all items consumed on the given input port + uint64_t nitems_read(const size_t which_input = 0); + + //! Get absolute count of all items produced on the given output port + uint64_t nitems_written(const size_t which_output = 0); + + void add_item_tag( + const size_t which_output, const gr_tag_t &tag + ); + + void add_item_tag( + const size_t which_output, + uint64_t abs_offset, + const pmt::pmt_t &key, + const pmt::pmt_t &value, + const pmt::pmt_t &srcid=pmt::PMT_F + ); + + void get_tags_in_range( + std::vector<gr_tag_t> &tags, + const size_t which_input, + uint64_t abs_start, + uint64_t abs_end, + const pmt::pmt_t &key = pmt::pmt_t() + ); + + void set_alignment(const size_t alignment); + + bool is_unaligned(void); + + size_t fixed_rate_noutput_to_ninput(const size_t noutput_items); + + size_t interpolation(void) const; + + void set_interpolation(const size_t); + + size_t decimation(void) const; + + void set_decimation(const size_t); + + int max_noutput_items(void) const; + + void set_max_noutput_items(int); + + void unset_max_noutput_items(void); + + bool is_set_max_noutput_items(void) const; + + /******************************************************************* + * Deal with input and output port configuration + ******************************************************************/ + + unsigned history(void) const; + + void set_history(unsigned history); + + /*! + * Enable fixed rate logic. + * When enabled, relative rate is assumed to be set, + * and forecast is automatically called. + * Also, consume will be called automatically. + */ + void set_fixed_rate(const bool fixed_rate); + + //! Get the fixed rate setting + bool fixed_rate(void) const; + + /*! + * The relative rate can be thought of as interpolation/decimation. + * In other words, relative rate is the ratio of output items to input items. + */ + void set_relative_rate(const double relative_rate); + + //! Get the relative rate setting + double relative_rate(void) const; + + /*! + * The output multiple setting controls work output buffer sizes. + * Buffers will be number of items modulo rounted to the multiple. + */ + void set_output_multiple(const size_t multiple); + + //! Get the output multiple setting + size_t output_multiple(void) const; + + /******************************************************************* + * Deal with tag handling and tag configuration + ******************************************************************/ + + enum tag_propagation_policy_t + { + TPP_DONT = 0, + TPP_ALL_TO_ALL = 1, + TPP_ONE_TO_ONE = 2 + }; + + tag_propagation_policy_t tag_propagation_policy(void); + + void set_tag_propagation_policy(tag_propagation_policy_t p); + + ///////////// TODO ////////////////////// + void set_max_output_buffer(long){} + void set_max_output_buffer(int, long){} + long max_output_buffer(size_t){return 0;} + void set_min_output_buffer(long){} + void set_min_output_buffer(int, long){} + long min_output_buffer(size_t){return 0;} + + ///////////// ALIAS stuff - is it used? ////////////////////// + std::string d_symbol_alias; + std::string d_symbol_name; + std::string symbol_name() const { return d_symbol_name; } + bool alias_set() { return !d_symbol_alias.empty(); } + std::string alias(){ return alias_set()?d_symbol_alias:symbol_name(); } + pmt::pmt_t alias_pmt(){ return pmt::pmt_intern(alias()); } + void set_block_alias(std::string name){d_symbol_alias = name;} + + ///////////// MSG stuff not implemented ////////////////////// + typedef std::deque<pmt::pmt_t> msg_queue_t; + typedef std::map<pmt::pmt_t, msg_queue_t, pmt::pmt_comperator> msg_queue_map_t; + typedef std::map<pmt::pmt_t, msg_queue_t, pmt::pmt_comperator>::iterator msg_queue_map_itr; + msg_queue_map_t msg_queue; + pmt::pmt_t message_subscribers; + + typedef boost::function<void(pmt::pmt_t)> msg_handler_t; + typedef std::map<pmt::pmt_t , msg_handler_t, pmt::pmt_comperator> d_msg_handlers_t; + d_msg_handlers_t d_msg_handlers; + + template <typename T> void set_msg_handler(pmt::pmt_t which_port, T msg_handler){} + + void message_port_register_in(pmt::pmt_t /*port_id*/){} + void message_port_register_out(pmt::pmt_t /*port_id*/){} + void message_port_pub(pmt::pmt_t /*port_id*/, pmt::pmt_t /*msg*/){} + void message_port_sub(pmt::pmt_t /*port_id*/, pmt::pmt_t /*target*/){} + void message_port_unsub(pmt::pmt_t /*port_id*/, pmt::pmt_t /*target*/){} + + virtual bool message_port_is_hier(pmt::pmt_t port_id) { (void) port_id; /*std::cout << "is_hier\n";*/ return false; } + virtual bool message_port_is_hier_in(pmt::pmt_t port_id) { (void) port_id; /*std::cout << "is_hier_in\n";*/ return false; } + virtual bool message_port_is_hier_out(pmt::pmt_t port_id) { (void) port_id; /*std::cout << "is_hier_out\n";*/ return false; } + + /*! + * \brief Get input message port names. + * + * Returns the available input message ports for a block. The + * return object is a PMT vector that is filled with PMT symbols. + */ + pmt::pmt_t message_ports_in(){return pmt::PMT_NIL;} + + /*! + * \brief Get output message port names. + * + * Returns the available output message ports for a block. The + * return object is a PMT vector that is filled with PMT symbols. + */ + pmt::pmt_t message_ports_out(){return pmt::PMT_NIL;} + + //! is the queue empty? + bool empty_p(pmt::pmt_t which_port) { + if(msg_queue.find(which_port) == msg_queue.end()) + throw std::runtime_error("port does not exist!"); + return msg_queue[which_port].empty(); + } + bool empty_p() { + bool rv = true; + BOOST_FOREACH(msg_queue_map_t::value_type &i, msg_queue){ rv &= msg_queue[i.first].empty(); } + return rv; + } + + //| Acquires and release the mutex + void insert_tail( pmt::pmt_t /*which_port*/, pmt::pmt_t /*msg*/){} + /*! + * \returns returns pmt at head of queue or pmt_t() if empty. + */ + pmt::pmt_t delete_head_nowait( pmt::pmt_t /*which_port*/){return pmt::PMT_NIL;} + + /*! + * \returns returns pmt at head of queue or pmt_t() if empty. + */ + pmt::pmt_t delete_head_blocking( pmt::pmt_t /*which_port*/){return pmt::PMT_NIL;} + + msg_queue_t::iterator get_iterator(pmt::pmt_t which_port){ + return msg_queue[which_port].begin(); + } + + void erase_msg(pmt::pmt_t which_port, msg_queue_t::iterator it){ + msg_queue[which_port].erase(it); + } + + virtual bool has_msg_port(pmt::pmt_t which_port){ + if(msg_queue.find(which_port) != msg_queue.end()){ + return true; + } + if(pmt::pmt_dict_has_key(message_subscribers, which_port)){ + return true; + } + return false; + } + + /*! + * \brief Tests if there is a handler attached to port \p which_port + */ + bool has_msg_handler(pmt::pmt_t which_port) { + return (d_msg_handlers.find(which_port) != d_msg_handlers.end()); + } + + /* + * This function is called by the runtime system to dispatch messages. + * + * The thread-safety guarantees mentioned in set_msg_handler are implemented + * by the callers of this method. + */ + virtual void dispatch_msg(pmt::pmt_t which_port, pmt::pmt_t msg) + { + // AA Update this + if(has_msg_handler(which_port)) { // Is there a handler? + d_msg_handlers[which_port](msg); // Yes, invoke it. + } + } + + /*! Used by block's setters and work functions to make + * setting/resetting of parameters thread-safe. + * + * Used by calling gruel::scoped_lock l(d_setlock); + */ + gruel::mutex d_setlock; + + // ---------------------------------------------------------------------------- + // Functions to handle thread affinity + std::vector<int> d_affinity; // thread affinity proc. mask + + /*! + * \brief Set the thread's affinity to processor core \p n. + * + * \param mask a vector of unsigned ints of the core numbers available to this block. + */ + void set_processor_affinity(const std::vector<int> &mask){d_affinity=mask;} + + /*! + * \brief Remove processor affinity to a specific core. + */ + void unset_processor_affinity(){} + + /*! + * \brief Get the current processor affinity. + */ + std::vector<int> processor_affinity() { return d_affinity; } + + ///////////////// private vars ////////////////////// + + gr_vector_int _work_ninput_items; + gr_vector_int _fcast_ninput_items; + size_t _num_outputs; + ptrdiff_t _work_io_ptr_mask; + size_t _output_multiple_items; + double _relative_rate; + bool _enable_fixed_rate; + size_t _input_history_items; + tag_propagation_policy_t _tag_prop_policy; + size_t _interp, _decim; + gr_io_signature_sptr _in_sig, _out_sig; + + ///////////////// the Block overloads ////////////////////// + + //! implements work -> calls general work + void work(const InputItems &, const OutputItems &); + + //! notifications of new topological commits + void notify_topology(const size_t, const size_t); + + //! start notification + void notify_active(void); + + //! stop notification + void notify_inactive(void); + + //! implements tag_propagation_policy() + virtual void propagate_tags(const size_t, const gras::TagIter &); + + void _update_input_reserve(void); + + gras::BufferQueueSptr input_buffer_allocator(const size_t, const gras::SBufferConfig &); + gras::BufferQueueSptr output_buffer_allocator(const size_t, const gras::SBufferConfig &); + +}; + +typedef boost::shared_ptr<gr_block> gr_block_sptr; + +GRAS_FORCE_INLINE void gr_block::consume_each(const int how_many_items) +{ + if GRAS_UNLIKELY(how_many_items < 0) return; + gras::Block::consume(size_t(how_many_items)); +} + +GRAS_FORCE_INLINE void gr_block::consume(const size_t i, const int how_many_items) +{ + if GRAS_UNLIKELY(how_many_items < 0) return; + gras::Block::consume(i, size_t(how_many_items)); +} + +GRAS_FORCE_INLINE void gr_block::produce(const size_t o, const int how_many_items) +{ + if GRAS_UNLIKELY(how_many_items < 0) return; + gras::Block::produce(o, size_t(how_many_items)); +} + +GRAS_FORCE_INLINE uint64_t gr_block::nitems_read(const size_t which_input) +{ + return Block::get_consumed(which_input); +} + +GRAS_FORCE_INLINE uint64_t gr_block::nitems_written(const size_t which_output) +{ + return Block::get_produced(which_output); +} + +GRAS_FORCE_INLINE size_t gr_block::interpolation(void) const +{ + return _interp; +} + +GRAS_FORCE_INLINE size_t gr_block::decimation(void) const +{ + return _decim; +} + +GRAS_FORCE_INLINE bool gr_block::is_unaligned(void) +{ + //TODO + //probably dont need this since volk dispatcher checks alignment + //32 byte aligned is good enough for you + return (_work_io_ptr_mask & ptrdiff_t(GRAS_MAX_ALIGNMENT-1)) != 0; +} + +#endif /*INCLUDED_GNURADIO_GR_BLOCK_H*/ diff --git a/gnuradio-core/src/lib/runtime/gr_block.i b/gnuradio-core/src/lib/runtime/gr_block.i new file mode 100644 index 000000000..a53489f9a --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_block.i @@ -0,0 +1,93 @@ +/* -*- 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. + */ + +%include <gr_basic_block.i> + +class gr_block; +typedef boost::shared_ptr<gr_block> gr_block_sptr; +%template(gr_block_sptr) boost::shared_ptr<gr_block>; + +// support vectors of these... +namespace std { + %template(x_vector_gr_block_sptr) vector<gr_block_sptr>; +}; + +class gr_block : public gr_basic_block { + protected: + gr_block (const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); + + public: + + virtual ~gr_block (); + + unsigned history () const; + + int output_multiple () const; + double relative_rate () const; + + bool start(); + bool stop(); + + uint64_t nitems_read(unsigned int which_input); + uint64_t nitems_written(unsigned int which_output); + + // Methods to manage the block's max_noutput_items size. + int max_noutput_items(); + void set_max_noutput_items(int m); + void unset_max_noutput_items(); + bool is_set_max_noutput_items(); + + // Methods to manage block's min/max buffer sizes. + long max_output_buffer(int i); + void set_max_output_buffer(long max_output_buffer); + void set_max_output_buffer(int port, long max_output_buffer); + long min_output_buffer(int i); + void set_min_output_buffer(long min_output_buffer); + void set_min_output_buffer(int port, long min_output_buffer); + + // Methods to access performance counters + float pc_noutput_items(); + float pc_noutput_items_var(); + float pc_nproduced(); + float pc_nproduced_var(); + float pc_input_buffers_full(int which); + float pc_input_buffers_full_var(int which); + std::vector<float> pc_input_buffers_full(); + std::vector<float> pc_input_buffers_full_var(); + float pc_output_buffers_full(int which); + float pc_output_buffers_full_var(int which); + std::vector<float> pc_output_buffers_full(); + std::vector<float> pc_output_buffers_full_var(); + float pc_work_time(); + float pc_work_time_var(); + + // Methods to manage processor affinity. + void set_processor_affinity(const std::vector<int> &mask); + void unset_processor_affinity(); + std::vector<int> processor_affinity(); + + // internal use + gr_block_detail_sptr detail () const { return d_detail; } + void set_detail (gr_block_detail_sptr detail) { d_detail = detail; } +}; diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.cc b/gnuradio-core/src/lib/runtime/gr_block_detail.cc new file mode 100644 index 000000000..4922ea083 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_block_detail.cc @@ -0,0 +1,414 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2009,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_block_detail.h> +#include <gr_buffer.h> +#include <iostream> + +using namespace pmt; + +static long s_ncurrently_allocated = 0; + +long +gr_block_detail_ncurrently_allocated () +{ + return s_ncurrently_allocated; +} + +gr_block_detail::gr_block_detail (unsigned int ninputs, unsigned int noutputs) + : d_produce_or(0), + d_ninputs (ninputs), d_noutputs (noutputs), + d_input (ninputs), d_output (noutputs), + d_done (false), + d_avg_noutput_items(0), + d_var_noutput_items(0), + d_avg_nproduced(0), + d_var_nproduced(0), + d_avg_input_buffers_full(ninputs, 0), + d_var_input_buffers_full(ninputs, 0), + d_avg_output_buffers_full(noutputs, 0), + d_var_output_buffers_full(noutputs, 0), + d_avg_work_time(0), + d_var_work_time(0), + d_pc_counter(0) +{ + s_ncurrently_allocated++; +} + +gr_block_detail::~gr_block_detail () +{ + // should take care of itself + s_ncurrently_allocated--; +} + +void +gr_block_detail::set_input (unsigned int which, gr_buffer_reader_sptr reader) +{ + if (which >= d_ninputs) + throw std::invalid_argument ("gr_block_detail::set_input"); + + d_input[which] = reader; +} + +void +gr_block_detail::set_output (unsigned int which, gr_buffer_sptr buffer) +{ + if (which >= d_noutputs) + throw std::invalid_argument ("gr_block_detail::set_output"); + + d_output[which] = buffer; +} + +gr_block_detail_sptr +gr_make_block_detail (unsigned int ninputs, unsigned int noutputs) +{ + return gr_block_detail_sptr (new gr_block_detail (ninputs, noutputs)); +} + +void +gr_block_detail::set_done (bool done) +{ + d_done = done; + for (unsigned int i = 0; i < d_noutputs; i++) + d_output[i]->set_done (done); + + for (unsigned int i = 0; i < d_ninputs; i++) + d_input[i]->set_done (done); +} + +void +gr_block_detail::consume (int which_input, int how_many_items) +{ + if (how_many_items > 0) { + input (which_input)->update_read_pointer (how_many_items); + } +} + + +void +gr_block_detail::consume_each (int how_many_items) +{ + if (how_many_items > 0) { + for (int i = 0; i < ninputs (); i++) { + d_input[i]->update_read_pointer (how_many_items); + } + } +} + +void +gr_block_detail::produce (int which_output, int how_many_items) +{ + if (how_many_items > 0){ + d_output[which_output]->update_write_pointer (how_many_items); + d_produce_or |= how_many_items; + } +} + +void +gr_block_detail::produce_each (int how_many_items) +{ + if (how_many_items > 0) { + for (int i = 0; i < noutputs (); i++) { + d_output[i]->update_write_pointer (how_many_items); + } + d_produce_or |= how_many_items; + } +} + + +uint64_t +gr_block_detail::nitems_read(unsigned int which_input) +{ + if(which_input >= d_ninputs) + throw std::invalid_argument ("gr_block_detail::n_input_items"); + return d_input[which_input]->nitems_read(); +} + +uint64_t +gr_block_detail::nitems_written(unsigned int which_output) +{ + if(which_output >= d_noutputs) + throw std::invalid_argument ("gr_block_detail::n_output_items"); + return d_output[which_output]->nitems_written(); +} + +void +gr_block_detail::add_item_tag(unsigned int which_output, const gr_tag_t &tag) +{ + if(!pmt_is_symbol(tag.key)) { + throw pmt_wrong_type("gr_block_detail::add_item_tag key", tag.key); + } + else { + // Add tag to gr_buffer's deque tags + d_output[which_output]->add_item_tag(tag); + } +} + +void +gr_block_detail::remove_item_tag(unsigned int which_input, const gr_tag_t &tag) +{ + if(!pmt_is_symbol(tag.key)) { + throw pmt_wrong_type("gr_block_detail::add_item_tag key", tag.key); + } + else { + // Add tag to gr_buffer's deque tags + d_input[which_input]->buffer()->remove_item_tag(tag); + } +} + +void +gr_block_detail::get_tags_in_range(std::vector<gr_tag_t> &v, + unsigned int which_input, + uint64_t abs_start, + uint64_t abs_end) +{ + // get from gr_buffer_reader's deque of tags + d_input[which_input]->get_tags_in_range(v, abs_start, abs_end); +} + +void +gr_block_detail::get_tags_in_range(std::vector<gr_tag_t> &v, + unsigned int which_input, + uint64_t abs_start, + uint64_t abs_end, + const pmt_t &key) +{ + std::vector<gr_tag_t> found_items; + + v.resize(0); + + // get from gr_buffer_reader's deque of tags + d_input[which_input]->get_tags_in_range(found_items, abs_start, abs_end); + + // Filter further by key name + pmt_t itemkey; + std::vector<gr_tag_t>::iterator itr; + for(itr = found_items.begin(); itr != found_items.end(); itr++) { + itemkey = (*itr).key; + if(pmt_eqv(key, itemkey)) { + v.push_back(*itr); + } + } +} + +void +gr_block_detail::set_processor_affinity(const std::vector<int> &mask) +{ + if(threaded) { + try { + gruel::thread_bind_to_processor(thread, mask); + } + catch (std::runtime_error e) { + std::cerr << "set_processor_affinity: invalid mask." << std::endl;; + } + } +} + +void +gr_block_detail::unset_processor_affinity() +{ + if(threaded) { + gruel::thread_unbind(thread); + } +} + +void +gr_block_detail::start_perf_counters() +{ + d_start_of_work = gruel::high_res_timer_now(); +} + +void +gr_block_detail::stop_perf_counters(int noutput_items, int nproduced) +{ + d_end_of_work = gruel::high_res_timer_now(); + gruel::high_res_timer_type diff = d_end_of_work - d_start_of_work; + + if(d_pc_counter == 0) { + d_avg_work_time = diff; + d_var_work_time = 0; + d_avg_nproduced = nproduced; + d_var_nproduced = 0; + d_avg_noutput_items = noutput_items; + d_var_noutput_items = 0; + for(size_t i=0; i < d_input.size(); i++) { + float pfull = static_cast<float>(d_input[i]->items_available()) / + static_cast<float>(d_input[i]->max_possible_items_available()); + d_avg_input_buffers_full[i] = pfull; + d_var_input_buffers_full[i] = 0; + } + for(size_t i=0; i < d_output.size(); i++) { + gruel::scoped_lock guard(*d_output[i]->mutex()); + float pfull = 1.0f - static_cast<float>(d_output[i]->space_available()) / + static_cast<float>(d_output[i]->bufsize()); + d_avg_output_buffers_full[i] = pfull; + d_var_output_buffers_full[i] = 0; + } + } + else { + float d = diff - d_avg_work_time; + d_avg_work_time = d_avg_work_time + d/d_pc_counter; + d_var_work_time = d_var_work_time + d*d; + + d = nproduced - d_avg_nproduced; + d_avg_nproduced = d_avg_nproduced + d/d_pc_counter; + d_var_nproduced = d_var_nproduced + d*d; + + d = noutput_items - d_avg_noutput_items; + d_avg_noutput_items = d_avg_noutput_items + d/d_pc_counter; + d_var_noutput_items = d_var_noutput_items + d*d; + + for(size_t i=0; i < d_input.size(); i++) { + float pfull = static_cast<float>(d_input[i]->items_available()) / + static_cast<float>(d_input[i]->max_possible_items_available()); + + d = pfull - d_avg_input_buffers_full[i]; + d_avg_input_buffers_full[i] = d_avg_input_buffers_full[i] + d/d_pc_counter; + d_var_input_buffers_full[i] = d_var_input_buffers_full[i] + d*d; + } + + for(size_t i=0; i < d_output.size(); i++) { + gruel::scoped_lock guard(*d_output[i]->mutex()); + float pfull = 1.0f - static_cast<float>(d_output[i]->space_available()) / + static_cast<float>(d_output[i]->bufsize()); + + d = pfull - d_avg_output_buffers_full[i]; + d_avg_output_buffers_full[i] = d_avg_output_buffers_full[i] + d/d_pc_counter; + d_var_output_buffers_full[i] = d_var_output_buffers_full[i] + d*d; + } + } + + d_pc_counter++; +} + +void +gr_block_detail::reset_perf_counters() +{ + d_pc_counter = 0; +} + +float +gr_block_detail::pc_noutput_items() +{ + return d_avg_noutput_items; +} + +float +gr_block_detail::pc_nproduced() +{ + return d_avg_nproduced; +} + +float +gr_block_detail::pc_input_buffers_full(size_t which) +{ + if(which < d_avg_input_buffers_full.size()) + return d_avg_input_buffers_full[which]; + else + return 0; +} + +std::vector<float> +gr_block_detail::pc_input_buffers_full() +{ + return d_avg_input_buffers_full; +} + +float +gr_block_detail::pc_output_buffers_full(size_t which) +{ + if(which < d_avg_output_buffers_full.size()) + return d_avg_output_buffers_full[which]; + else + return 0; +} + +std::vector<float> +gr_block_detail::pc_output_buffers_full() +{ + return d_avg_output_buffers_full; +} + +float +gr_block_detail::pc_work_time() +{ + return d_avg_work_time; +} + + +float +gr_block_detail::pc_noutput_items_var() +{ + return d_var_noutput_items/(d_pc_counter-1); +} + +float +gr_block_detail::pc_nproduced_var() +{ + return d_var_nproduced/(d_pc_counter-1); +} + +float +gr_block_detail::pc_input_buffers_full_var(size_t which) +{ + if(which < d_avg_input_buffers_full.size()) + return d_var_input_buffers_full[which]/(d_pc_counter-1); + else + return 0; +} + +std::vector<float> +gr_block_detail::pc_input_buffers_full_var() +{ + std::vector<float> var(d_avg_input_buffers_full.size(), 0); + for(size_t i = 0; i < d_avg_input_buffers_full.size(); i++) + var[i] = d_avg_input_buffers_full[i]/(d_pc_counter-1); + return var; +} + +float +gr_block_detail::pc_output_buffers_full_var(size_t which) +{ + if(which < d_avg_output_buffers_full.size()) + return d_var_output_buffers_full[which]/(d_pc_counter-1); + else + return 0; +} + +std::vector<float> +gr_block_detail::pc_output_buffers_full_var() +{ + std::vector<float> var(d_avg_output_buffers_full.size(), 0); + for(size_t i = 0; i < d_avg_output_buffers_full.size(); i++) + var[i] = d_avg_output_buffers_full[i]/(d_pc_counter-1); + return var; +} + +float +gr_block_detail::pc_work_time_var() +{ + return d_var_work_time/(d_pc_counter-1); +} diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.h b/gnuradio-core/src/lib/runtime/gr_block_detail.h new file mode 100644 index 000000000..15d85135a --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_block_detail.h @@ -0,0 +1,235 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2009,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 detail. + * + * 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_BLOCK_DETAIL_H +#define INCLUDED_GR_BLOCK_DETAIL_H + +#include <gr_core_api.h> +#include <gr_runtime_types.h> +#include <gr_tpb_detail.h> +#include <gr_tags.h> +#include <gruel/high_res_timer.h> +#include <stdexcept> + +/*! + * \brief Implementation details to support the signal processing abstraction + * \ingroup internal + * + * This class contains implementation detail that should be "out of sight" + * of almost all users of GNU Radio. This decoupling also means that + * we can make changes to the guts without having to recompile everything. + */ +class GR_CORE_API gr_block_detail { + public: + ~gr_block_detail (); + + int ninputs () const { return d_ninputs; } + int noutputs () const { return d_noutputs; } + bool sink_p () const { return d_noutputs == 0; } + bool source_p () const { return d_ninputs == 0; } + + void set_done (bool done); + bool done () const { return d_done; } + + void set_input (unsigned int which, gr_buffer_reader_sptr reader); + gr_buffer_reader_sptr input (unsigned int which) + { + if (which >= d_ninputs) + throw std::invalid_argument ("gr_block_detail::input"); + return d_input[which]; + } + + void set_output (unsigned int which, gr_buffer_sptr buffer); + gr_buffer_sptr output (unsigned int which) + { + if (which >= d_noutputs) + throw std::invalid_argument ("gr_block_detail::output"); + return d_output[which]; + } + + /*! + * \brief Tell the scheduler \p how_many_items of input stream \p which_input were consumed. + */ + void consume (int which_input, int how_many_items); + + /*! + * \brief Tell the scheduler \p how_many_items were consumed on each input stream. + */ + void consume_each (int how_many_items); + + /*! + * \brief Tell the scheduler \p how_many_items were produced on output stream \p which_output. + */ + void produce (int which_output, int how_many_items); + + /*! + * \brief Tell the scheduler \p how_many_items were produced on each output stream. + */ + void produce_each (int how_many_items); + + // Return the number of items read on input stream which_input + uint64_t nitems_read(unsigned int which_input); + + // Return the number of items written on output stream which_output + uint64_t nitems_written(unsigned int which_output); + + + /*! + * \brief Adds a new tag to the given output stream. + * + * Calls gr_buffer::add_item_tag(), + * which appends the tag onto its deque. + * + * \param which_output an integer of which output stream to attach the tag + * \param tag the tag object to add + */ + void add_item_tag(unsigned int which_output, const gr_tag_t &tag); + + /*! + * \brief Removes a tag from the given input stream. + * + * Calls gr_buffer::remove_item_tag(), which removes the tag from its deque. + * + * \param which_input an integer of which input stream to remove the tag from + * \param tag the tag object to add + */ + void remove_item_tag(unsigned int which_input, const gr_tag_t &tag); + + /*! + * \brief Given a [start,end), returns a vector of all tags in the range. + * + * Pass-through function to gr_buffer_reader to get a vector of tags + * in given range. Range of counts is from start to end-1. + * + * Tags are tuples of: + * (item count, source id, key, value) + * + * \param v a vector reference to return tags into + * \param which_input an integer of which input stream to pull from + * \param abs_start a uint64 count of the start of the range of interest + * \param abs_end a uint64 count of the end of the range of interest + */ + void get_tags_in_range(std::vector<gr_tag_t> &v, + unsigned int which_input, + uint64_t abs_start, + uint64_t abs_end); + + /*! + * \brief Given a [start,end), returns a vector of all tags in the range + * with a given key. + * + * Calls get_tags_in_range(which_input, abs_start, abs_end) to get a vector of + * tags from the buffers. This function then provides a secondary filter to + * the tags to extract only tags with the given 'key'. + * + * Tags are tuples of: + * (item count, source id, key, value) + * + * \param v a vector reference to return tags into + * \param which_input an integer of which input stream to pull from + * \param abs_start a uint64 count of the start of the range of interest + * \param abs_end a uint64 count of the end of the range of interest + * \param key a PMT symbol to select only tags of this key + */ + void get_tags_in_range(std::vector<gr_tag_t> &v, + unsigned int which_input, + uint64_t abs_start, + uint64_t abs_end, + const pmt::pmt_t &key); + + /*! + * \brief Set core affinity of block to the cores in the vector mask. + * + * \param mask a vector of ints of the core numbers available to this block. + */ + void set_processor_affinity(const std::vector<int> &mask); + + /*! + * \brief Unset core affinity. + */ + void unset_processor_affinity(); + + bool threaded; // set if thread is currently running. + gruel::gr_thread_t thread; // portable thread handle + + void start_perf_counters(); + void stop_perf_counters(int noutput_items, int nproduced); + void reset_perf_counters(); + + // Calls to get performance counter items + float pc_noutput_items(); + float pc_nproduced(); + float pc_input_buffers_full(size_t which); + std::vector<float> pc_input_buffers_full(); + float pc_output_buffers_full(size_t which); + std::vector<float> pc_output_buffers_full(); + float pc_work_time(); + + float pc_noutput_items_var(); + float pc_nproduced_var(); + float pc_input_buffers_full_var(size_t which); + std::vector<float> pc_input_buffers_full_var(); + float pc_output_buffers_full_var(size_t which); + std::vector<float> pc_output_buffers_full_var(); + float pc_work_time_var(); + + gr_tpb_detail d_tpb; // used by thread-per-block scheduler + int d_produce_or; + + // ---------------------------------------------------------------------------- + + private: + unsigned int d_ninputs; + unsigned int d_noutputs; + std::vector<gr_buffer_reader_sptr> d_input; + std::vector<gr_buffer_sptr> d_output; + bool d_done; + + // Performance counters + float d_avg_noutput_items; + float d_var_noutput_items; + float d_avg_nproduced; + float d_var_nproduced; + std::vector<float> d_avg_input_buffers_full; + std::vector<float> d_var_input_buffers_full; + std::vector<float> d_avg_output_buffers_full; + std::vector<float> d_var_output_buffers_full; + gruel::high_res_timer_type d_start_of_work, d_end_of_work; + float d_avg_work_time; + float d_var_work_time; + float d_pc_counter; + + gr_block_detail (unsigned int ninputs, unsigned int noutputs); + + friend struct gr_tpb_detail; + + friend GR_CORE_API gr_block_detail_sptr + gr_make_block_detail (unsigned int ninputs, unsigned int noutputs); +}; + +GR_CORE_API gr_block_detail_sptr +gr_make_block_detail (unsigned int ninputs, unsigned int noutputs); + +GR_CORE_API long +gr_block_detail_ncurrently_allocated (); + +#endif /* INCLUDED_GR_BLOCK_DETAIL_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_block_detail.i b/gnuradio-core/src/lib/runtime/gr_block_detail.i new file mode 100644 index 000000000..74ff46360 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_block_detail.i @@ -0,0 +1,66 @@ +/* -*- 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. + */ + +class gr_block_detail; +typedef boost::shared_ptr<gr_block_detail> gr_block_detail_sptr; +%template(gr_block_detail_sptr) boost::shared_ptr<gr_block_detail>; +%rename(block_detail) gr_make_block_detail; +%ignore gr_block_detail; + +gr_block_detail_sptr gr_make_block_detail (unsigned int ninputs, unsigned int noutputs); + +class gr_block_detail { + public: + + ~gr_block_detail (); + + int ninputs () const { return d_ninputs; } + int noutputs () const { return d_noutputs; } + bool sink_p () const { return d_noutputs == 0; } + bool source_p () const { return d_ninputs == 0; } + + void set_input (unsigned int which, gr_buffer_reader_sptr reader); + gr_buffer_reader_sptr input (unsigned int which) + { + if (which >= d_ninputs) + throw std::invalid_argument ("gr_block_detail::input"); + return d_input[which]; + } + + void set_output (unsigned int which, gr_buffer_sptr buffer); + gr_buffer_sptr output (unsigned int which) + { + if (which >= d_noutputs) + throw std::invalid_argument ("gr_block_detail::output"); + return d_output[which]; + } + + // ---------------------------------------------------------------------------- + + private: + gr_block_detail (unsigned int ninputs, unsigned int noutputs); + +}; + + +%rename(block_detail_ncurrently_allocated) gr_block_detail_ncurrently_allocated; +long gr_block_detail_ncurrently_allocated (); diff --git a/gnuradio-core/src/lib/runtime/gr_block_executor.cc b/gnuradio-core/src/lib/runtime/gr_block_executor.cc new file mode 100644 index 000000000..e070f3c50 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_block_executor.cc @@ -0,0 +1,487 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2008,2009,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_block_executor.h> +#include <gr_block.h> +#include <gr_block_detail.h> +#include <gr_buffer.h> +#include <gr_prefs.h> +#include <boost/thread.hpp> +#include <boost/format.hpp> +#include <iostream> +#include <limits> +#include <assert.h> +#include <stdio.h> + +// must be defined to either 0 or 1 +#define ENABLE_LOGGING 0 + +#if (ENABLE_LOGGING) +#define LOG(x) do { x; } while(0) +#else +#define LOG(x) do {;} while(0) +#endif + +static int which_scheduler = 0; + +inline static unsigned int +round_up (unsigned int n, unsigned int multiple) +{ + return ((n + multiple - 1) / multiple) * multiple; +} + +inline static unsigned int +round_down (unsigned int n, unsigned int multiple) +{ + return (n / multiple) * multiple; +} + +// +// Return minimum available write space in all our downstream buffers +// or -1 if we're output blocked and the output we're blocked +// on is done. +// +static int +min_available_space (gr_block_detail *d, int output_multiple, int min_noutput_items) +{ + int min_space = std::numeric_limits<int>::max(); + if (min_noutput_items == 0) + min_noutput_items = 1; + for (int i = 0; i < d->noutputs (); i++){ + gruel::scoped_lock guard(*d->output(i)->mutex()); + int avail_n = round_down(d->output(i)->space_available(), output_multiple); + int best_n = round_down(d->output(i)->bufsize()/2, output_multiple); + if (best_n < min_noutput_items) + throw std::runtime_error("Buffer too small for min_noutput_items"); + int n = std::min(avail_n, best_n); + if (n < min_noutput_items){ // We're blocked on output. + if (d->output(i)->done()){ // Downstream is done, therefore we're done. + return -1; + } + return 0; + } + min_space = std::min (min_space, n); + } + return min_space; +} + +static bool +propagate_tags(gr_block::tag_propagation_policy_t policy, gr_block_detail *d, + const std::vector<uint64_t> &start_nitems_read, double rrate, + std::vector<gr_tag_t> &rtags) +{ + // Move tags downstream + // if a sink, we don't need to move downstream + if(d->sink_p()) { + return true; + } + + switch(policy) { + case gr_block::TPP_DONT: + return true; + break; + case gr_block::TPP_ALL_TO_ALL: + // every tag on every input propogates to everyone downstream + for(int i = 0; i < d->ninputs(); i++) { + d->get_tags_in_range(rtags, i, start_nitems_read[i], + d->nitems_read(i)); + + std::vector<gr_tag_t>::iterator t; + if(rrate == 1.0) { + for(t = rtags.begin(); t != rtags.end(); t++) { + for(int o = 0; o < d->noutputs(); o++) + d->output(o)->add_item_tag(*t); + } + } + else { + for(t = rtags.begin(); t != rtags.end(); t++) { + gr_tag_t new_tag = *t; + new_tag.offset *= rrate; + for(int o = 0; o < d->noutputs(); o++) + d->output(o)->add_item_tag(new_tag); + } + } + } + break; + case gr_block::TPP_ONE_TO_ONE: + // tags from input i only go to output i + // this requires d->ninputs() == d->noutputs; this is checked when this + // type of tag-propagation system is selected in gr_block_detail + if(d->ninputs() == d->noutputs()) { + for(int i = 0; i < d->ninputs(); i++) { + d->get_tags_in_range(rtags, i, start_nitems_read[i], + d->nitems_read(i)); + + std::vector<gr_tag_t>::iterator t; + for(t = rtags.begin(); t != rtags.end(); t++) { + gr_tag_t new_tag = *t; + new_tag.offset *= rrate; + d->output(i)->add_item_tag(new_tag); + } + } + } + else { + std::cerr << "Error: gr_block_executor: propagation_policy 'ONE-TO-ONE' requires ninputs == noutputs" << std::endl; + return false; + } + + break; + default: + return true; + } + return true; +} + +gr_block_executor::gr_block_executor (gr_block_sptr block, int max_noutput_items) + : d_block(block), d_log(0), d_max_noutput_items(max_noutput_items) +{ + if (ENABLE_LOGGING){ + std::string name = str(boost::format("sst-%03d.log") % which_scheduler++); + d_log = new std::ofstream(name.c_str()); + std::unitbuf(*d_log); // make it unbuffered... + *d_log << "gr_block_executor: " + << d_block << std::endl; + } + +#ifdef GR_PERFORMANCE_COUNTERS + gr_prefs *prefs = gr_prefs::singleton(); + d_use_pc = prefs->get_bool("PerfCounters", "on", false); +#endif /* GR_PERFORMANCE_COUNTERS */ + + d_block->start(); // enable any drivers, etc. +} + +gr_block_executor::~gr_block_executor () +{ + if (ENABLE_LOGGING) + delete d_log; + + d_block->stop(); // stop any drivers, etc. +} + +gr_block_executor::state +gr_block_executor::run_one_iteration() +{ + int noutput_items; + int max_items_avail; + int max_noutput_items = d_max_noutput_items; + int new_alignment=0; + int alignment_state=-1; + + gr_block *m = d_block.get(); + gr_block_detail *d = m->detail().get(); + + LOG(*d_log << std::endl << m); + + if (d->done()){ + assert(0); + return DONE; + } + + if (d->source_p ()){ + d_ninput_items_required.resize (0); + d_ninput_items.resize (0); + d_input_items.resize (0); + d_input_done.resize(0); + d_output_items.resize (d->noutputs ()); + d_start_nitems_read.resize(0); + + // determine the minimum available output space + noutput_items = min_available_space (d, m->output_multiple (), m->min_noutput_items ()); + noutput_items = std::min(noutput_items, max_noutput_items); + LOG(*d_log << " source\n noutput_items = " << noutput_items << std::endl); + if (noutput_items == -1) // we're done + goto were_done; + + if (noutput_items == 0){ // we're output blocked + LOG(*d_log << " BLKD_OUT\n"); + return BLKD_OUT; + } + + goto setup_call_to_work; // jump to common code + } + + else if (d->sink_p ()){ + d_ninput_items_required.resize (d->ninputs ()); + d_ninput_items.resize (d->ninputs ()); + d_input_items.resize (d->ninputs ()); + d_input_done.resize(d->ninputs()); + d_output_items.resize (0); + d_start_nitems_read.resize(d->ninputs()); + LOG(*d_log << " sink\n"); + + max_items_avail = 0; + for (int i = 0; i < d->ninputs (); i++){ + { + /* + * Acquire the mutex and grab local copies of items_available and done. + */ + gruel::scoped_lock guard(*d->input(i)->mutex()); + d_ninput_items[i] = d->input(i)->items_available(); + d_input_done[i] = d->input(i)->done(); + } + + LOG(*d_log << " d_ninput_items[" << i << "] = " << d_ninput_items[i] << std::endl); + LOG(*d_log << " d_input_done[" << i << "] = " << d_input_done[i] << std::endl); + + if (d_ninput_items[i] < m->output_multiple() && d_input_done[i]) + goto were_done; + + max_items_avail = std::max (max_items_avail, d_ninput_items[i]); + } + + // take a swag at how much output we can sink + noutput_items = (int) (max_items_avail * m->relative_rate ()); + noutput_items = round_down (noutput_items, m->output_multiple ()); + noutput_items = std::min(noutput_items, max_noutput_items); + LOG(*d_log << " max_items_avail = " << max_items_avail << std::endl); + LOG(*d_log << " noutput_items = " << noutput_items << std::endl); + + if (noutput_items == 0){ // we're blocked on input + LOG(*d_log << " BLKD_IN\n"); + return BLKD_IN; + } + + goto try_again; // Jump to code shared with regular case. + } + + else { + // do the regular thing + d_ninput_items_required.resize (d->ninputs ()); + d_ninput_items.resize (d->ninputs ()); + d_input_items.resize (d->ninputs ()); + d_input_done.resize(d->ninputs()); + d_output_items.resize (d->noutputs ()); + d_start_nitems_read.resize(d->ninputs()); + + max_items_avail = 0; + for (int i = 0; i < d->ninputs (); i++){ + { + /* + * Acquire the mutex and grab local copies of items_available and done. + */ + gruel::scoped_lock guard(*d->input(i)->mutex()); + d_ninput_items[i] = d->input(i)->items_available (); + d_input_done[i] = d->input(i)->done(); + } + max_items_avail = std::max (max_items_avail, d_ninput_items[i]); + } + + // determine the minimum available output space + noutput_items = min_available_space (d, m->output_multiple (), m->min_noutput_items ()); + if (ENABLE_LOGGING){ + *d_log << " regular "; + if (m->relative_rate() >= 1.0) + *d_log << "1:" << m->relative_rate() << std::endl; + else + *d_log << 1.0/m->relative_rate() << ":1\n"; + *d_log << " max_items_avail = " << max_items_avail << std::endl; + *d_log << " noutput_items = " << noutput_items << std::endl; + } + if (noutput_items == -1) // we're done + goto were_done; + + if (noutput_items == 0){ // we're output blocked + LOG(*d_log << " BLKD_OUT\n"); + return BLKD_OUT; + } + + try_again: + if (m->fixed_rate()){ + // try to work it forward starting with max_items_avail. + // We want to try to consume all the input we've got. + int reqd_noutput_items = m->fixed_rate_ninput_to_noutput(max_items_avail); + + // only test this if we specifically set the output_multiple + if(m->output_multiple_set()) + reqd_noutput_items = round_down(reqd_noutput_items, m->output_multiple()); + + if (reqd_noutput_items > 0 && reqd_noutput_items <= noutput_items) + noutput_items = reqd_noutput_items; + + // if we need this many outputs, overrule the max_noutput_items setting + max_noutput_items = std::max(m->output_multiple(), max_noutput_items); + } + noutput_items = std::min(noutput_items, max_noutput_items); + + // Check if we're still unaligned; use up items until we're + // aligned again. Otherwise, make sure we set the alignment + // requirement. + if(!m->output_multiple_set()) { + if(m->is_unaligned()) { + // When unaligned, don't just set noutput_items to the remaining + // samples to meet alignment; this causes too much overhead in + // requiring a premature call back here. Set the maximum amount + // of samples to handle unalignment and get us back aligned. + if(noutput_items >= m->unaligned()) { + noutput_items = round_up(noutput_items, m->alignment()) \ + - (m->alignment() - m->unaligned()); + new_alignment = 0; + } + else { + new_alignment = m->unaligned() - noutput_items; + } + alignment_state = 0; + } + else if(noutput_items < m->alignment()) { + // if we don't have enough for an aligned call, keep track of + // misalignment, set unaligned flag, and proceed. + new_alignment = m->alignment() - noutput_items; + m->set_unaligned(new_alignment); + m->set_is_unaligned(true); + alignment_state = 1; + } + else { + // enough to round down to the nearest alignment and process. + noutput_items = round_down(noutput_items, m->alignment()); + m->set_is_unaligned(false); + alignment_state = 2; + } + } + + // ask the block how much input they need to produce noutput_items + m->forecast (noutput_items, d_ninput_items_required); + + // See if we've got sufficient input available + + int i; + for (i = 0; i < d->ninputs (); i++) + if (d_ninput_items_required[i] > d_ninput_items[i]) // not enough + break; + + if (i < d->ninputs ()){ // not enough input on input[i] + // if we can, try reducing the size of our output request + if (noutput_items > m->output_multiple ()){ + noutput_items /= 2; + noutput_items = round_up (noutput_items, m->output_multiple ()); + goto try_again; + } + + // We're blocked on input + LOG(*d_log << " BLKD_IN\n"); + if (d_input_done[i]) // If the upstream block is done, we're done + goto were_done; + + // Is it possible to ever fulfill this request? + if (d_ninput_items_required[i] > d->input(i)->max_possible_items_available ()){ + // Nope, never going to happen... + std::cerr << "\nsched: <gr_block " << m->name() + << " (" << m->unique_id() << ")>" + << " is requesting more input data\n" + << " than we can provide.\n" + << " ninput_items_required = " + << d_ninput_items_required[i] << "\n" + << " max_possible_items_available = " + << d->input(i)->max_possible_items_available() << "\n" + << " If this is a filter, consider reducing the number of taps.\n"; + goto were_done; + } + + // If we were made unaligned in this round but return here without + // processing; reset the unalignment claim before next entry. + if(alignment_state == 1) { + m->set_unaligned(0); + m->set_is_unaligned(false); + } + return BLKD_IN; + } + + // We've got enough data on each input to produce noutput_items. + // Finish setting up the call to work. + + for (int i = 0; i < d->ninputs (); i++) + d_input_items[i] = d->input(i)->read_pointer(); + + setup_call_to_work: + + d->d_produce_or = 0; + for (int i = 0; i < d->noutputs (); i++) + d_output_items[i] = d->output(i)->write_pointer(); + + // determine where to start looking for new tags + for (int i = 0; i < d->ninputs(); i++) + d_start_nitems_read[i] = d->nitems_read(i); + +#ifdef GR_PERFORMANCE_COUNTERS + if(d_use_pc) + d->start_perf_counters(); +#endif /* GR_PERFORMANCE_COUNTERS */ + + // Do the actual work of the block + int n = m->general_work (noutput_items, d_ninput_items, + d_input_items, d_output_items); + +#ifdef GR_PERFORMANCE_COUNTERS + if(d_use_pc) + d->stop_perf_counters(noutput_items, n); +#endif /* GR_PERFORMANCE_COUNTERS */ + + LOG(*d_log << " general_work: noutput_items = " << noutput_items + << " result = " << n << std::endl); + + // Adjust number of unaligned items left to process + if(m->is_unaligned()) { + m->set_unaligned(new_alignment); + m->set_is_unaligned(m->unaligned() != 0); + } + + if(!propagate_tags(m->tag_propagation_policy(), d, + d_start_nitems_read, m->relative_rate(), + d_returned_tags)) + goto were_done; + + if (n == gr_block::WORK_DONE) + goto were_done; + + if (n != gr_block::WORK_CALLED_PRODUCE) + d->produce_each (n); // advance write pointers + + if (d->d_produce_or > 0) // block produced something + return READY; + + // We didn't produce any output even though we called general_work. + // We have (most likely) consumed some input. + + /* + // If this is a source, it's broken. + if (d->source_p()){ + std::cerr << "gr_block_executor: source " << m + << " produced no output. We're marking it DONE.\n"; + // FIXME maybe we ought to raise an exception... + goto were_done; + } + */ + + // Have the caller try again... + return READY_NO_OUTPUT; + } + assert (0); + + were_done: + LOG(*d_log << " were_done\n"); + d->set_done (true); + return DONE; +} diff --git a/gnuradio-core/src/lib/runtime/gr_block_executor.h b/gnuradio-core/src/lib/runtime/gr_block_executor.h new file mode 100644 index 000000000..fb7f9c269 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_block_executor.h @@ -0,0 +1,78 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_BLOCK_EXECUTOR_H +#define INCLUDED_GR_BLOCK_EXECUTOR_H + +#include <gr_core_api.h> +#include <gr_runtime_types.h> +#include <fstream> +#include <gr_tags.h> + +//class gr_block_executor; +//typedef boost::shared_ptr<gr_block_executor> gr_block_executor_sptr; + + +/*! + * \brief Manage the execution of a single block. + * \ingroup internal + */ + +class GR_CORE_API gr_block_executor { +protected: + gr_block_sptr d_block; // The block we're trying to run + std::ofstream *d_log; + + // These are allocated here so we don't have to on each iteration + + gr_vector_int d_ninput_items_required; + gr_vector_int d_ninput_items; + gr_vector_const_void_star d_input_items; + std::vector<bool> d_input_done; + gr_vector_void_star d_output_items; + std::vector<uint64_t> d_start_nitems_read; //stores where tag counts are before work + std::vector<gr_tag_t> d_returned_tags; + int d_max_noutput_items; + +#ifdef GR_PERFORMANCE_COUNTERS + bool d_use_pc; +#endif /* GR_PERFORMANCE_COUNTERS */ + + public: + gr_block_executor(gr_block_sptr block, int max_noutput_items=100000); + ~gr_block_executor (); + + enum state { + READY, // We made progress; everything's cool. + READY_NO_OUTPUT, // We consumed some input, but produced no output. + BLKD_IN, // no progress; we're blocked waiting for input data. + BLKD_OUT, // no progress; we're blocked waiting for output buffer space. + DONE, // we're done; don't call me again. + }; + + /* + * \brief Run one iteration. + */ + state run_one_iteration(); +}; + +#endif /* INCLUDED_GR_BLOCK_EXECUTOR_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_block_registry.cc b/gnuradio-core/src/lib/runtime/gr_block_registry.cc new file mode 100644 index 000000000..ff23d97eb --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_block_registry.cc @@ -0,0 +1,76 @@ +#include <gr_basic_block.h> +#include <gr_block_registry.h> +#include <gr_tpb_detail.h> +#include <gr_block_detail.h> +#include <gr_block.h> +#include <stdio.h> + +gr_block_registry global_block_registry; + +gr_block_registry::gr_block_registry(){ + d_ref_map = pmt::pmt_make_dict(); +} + +long gr_block_registry::block_register(gr_basic_block* block){ + if(d_map.find(block->name()) == d_map.end()){ + d_map[block->name()] = blocksubmap_t(); + d_map[block->name()][0] = block; + return 0; + } else { + for(size_t i=0; i<=d_map[block->name()].size(); i++){ + if(d_map[block->name()].find(i) == d_map[block->name()].end()){ + d_map[block->name()][i] = block; + return i; + } + } + } + throw std::runtime_error("should not reach this"); +} + +void gr_block_registry::block_unregister(gr_basic_block* block){ + d_map[block->name()].erase( d_map[block->name()].find(block->symbolic_id())); + d_ref_map = pmt::pmt_dict_delete(d_ref_map, pmt::pmt_intern(block->symbol_name())); + if(block->alias_set()){ + d_ref_map = pmt::pmt_dict_delete(d_ref_map, pmt::pmt_intern(block->alias())); + } +} + +std::string gr_block_registry::register_symbolic_name(gr_basic_block* block){ + std::stringstream ss; + ss << block->name() << block->symbolic_id(); + //std::cout << "register_symbolic_name: " << ss.str() << std::endl; + register_symbolic_name(block, ss.str()); + return ss.str(); +} + +void gr_block_registry::register_symbolic_name(gr_basic_block* block, std::string name){ + if(pmt_dict_has_key(d_ref_map, pmt::pmt_intern(name))){ + throw std::runtime_error("symbol already exists, can not re-use!"); + } + d_ref_map = pmt_dict_add(d_ref_map, pmt::pmt_intern(name), pmt::pmt_make_any(block)); +} + +gr_basic_block_sptr gr_block_registry::block_lookup(pmt::pmt_t symbol){ + pmt::pmt_t ref = pmt_dict_ref(d_ref_map, symbol, pmt::PMT_NIL); + if(pmt::pmt_eq(ref, pmt::PMT_NIL)){ + throw std::runtime_error("block lookup failed! block not found!"); + } + gr_basic_block* blk = boost::any_cast<gr_basic_block*>( pmt::pmt_any_ref(ref) ); + return blk->shared_from_this(); +} + + +void gr_block_registry::register_primitive(std::string blk, gr_block* ref){ + primitive_map[blk] = ref; +} + +void gr_block_registry::unregister_primitive(std::string blk){ + primitive_map.erase(primitive_map.find(blk)); +} + +void gr_block_registry::notify_blk(std::string blk){ + if(primitive_map.find(blk) == primitive_map.end()){ return; } + if(primitive_map[blk]->detail().get()) + primitive_map[blk]->detail()->d_tpb.notify_msg(); +} + diff --git a/gnuradio-core/src/lib/runtime/gr_block_registry.h b/gnuradio-core/src/lib/runtime/gr_block_registry.h new file mode 100644 index 000000000..3a9d9868f --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_block_registry.h @@ -0,0 +1,43 @@ +#ifndef GR_BLOCK_REGISTRY_H +#define GR_BLOCK_REGISTRY_H + +#include <map> +#include <gr_basic_block.h> + +#ifndef GR_BASIC_BLOCK_H +class gr_basic_block; +class gr_block; +#endif + +class gr_block_registry { + public: + gr_block_registry(); + + long block_register(gr_basic_block* block); + void block_unregister(gr_basic_block* block); + + std::string register_symbolic_name(gr_basic_block* block); + void register_symbolic_name(gr_basic_block* block, std::string name); + + gr_basic_block_sptr block_lookup(pmt::pmt_t symbol); + + void register_primitive(std::string blk, gr_block* ref); + void unregister_primitive(std::string blk); + void notify_blk(std::string blk); + + private: + + //typedef std::map< long, gr_basic_block_sptr > blocksubmap_t; + typedef std::map< long, gr_basic_block* > blocksubmap_t; + typedef std::map< std::string, blocksubmap_t > blockmap_t; + + blockmap_t d_map; + pmt::pmt_t d_ref_map; + std::map< std::string, gr_block*> primitive_map; + +}; + +extern gr_block_registry global_block_registry; + +#endif + diff --git a/gnuradio-core/src/lib/runtime/gr_buffer.cc b/gnuradio-core/src/lib/runtime/gr_buffer.cc new file mode 100644 index 000000000..369959d65 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_buffer.cc @@ -0,0 +1,347 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2009,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_buffer.h> +#include <gr_vmcircbuf.h> +#include <gr_math.h> +#include <stdexcept> +#include <iostream> +#include <assert.h> +#include <algorithm> +#include <boost/math/common_factor_rt.hpp> + +static long s_buffer_count = 0; // counts for debugging storage mgmt +static long s_buffer_reader_count = 0; + +// ---------------------------------------------------------------------------- +// Notes on storage management +// +// Pretty much all the fundamental classes are now using the +// shared_ptr stuff for automatic reference counting. To ensure that +// no mistakes are made, we make the constructors for classes private, +// and then provide a free factory function that returns a smart +// pointer to the desired class. +// +// gr_buffer and gr_buffer_reader are no exceptions. However, they +// both want pointers to each other, and unless we do something, we'll +// never delete any of them because of the circular structure. +// They'll always have a reference count of at least one. We could +// use boost::weak_ptr's from gr_buffer to gr_buffer_reader but that +// introduces it's own problems. (gr_buffer_reader's destructor needs +// to call gr_buffer::drop_reader, but has no easy way to get a +// shared_ptr to itself.) +// +// Instead, we solve this problem by having gr_buffer hold a raw +// pointer to gr_buffer_reader in its d_reader vector. +// gr_buffer_reader's destructor calls gr_buffer::drop_reader, so +// we're never left with an dangling pointer. gr_buffer_reader still +// has a shared_ptr to the buffer ensuring that the buffer doesn't go +// away under it. However, when the reference count of a +// gr_buffer_reader goes to zero, we can successfully reclaim it. +// ---------------------------------------------------------------------------- + + +/* + * Compute the minimum number of buffer items that work (i.e., + * address space wrap-around works). To work is to satisfy this + * contraint for integer buffer_size and k: + * + * type_size * nitems == k * page_size + */ +static long +minimum_buffer_items (long type_size, long page_size) +{ + return page_size / boost::math::gcd (type_size, page_size); +} + + +gr_buffer::gr_buffer (int nitems, size_t sizeof_item, gr_block_sptr link) + : d_base (0), d_bufsize (0), d_vmcircbuf (0), + d_sizeof_item (sizeof_item), d_link(link), + d_write_index (0), d_abs_write_offset(0), d_done (false), + d_last_min_items_read(0) +{ + if (!allocate_buffer (nitems, sizeof_item)) + throw std::bad_alloc (); + + s_buffer_count++; +} + +gr_buffer_sptr +gr_make_buffer (int nitems, size_t sizeof_item, gr_block_sptr link) +{ + return gr_buffer_sptr (new gr_buffer (nitems, sizeof_item, link)); +} + +gr_buffer::~gr_buffer () +{ + delete d_vmcircbuf; + assert (d_readers.size() == 0); + s_buffer_count--; +} + +/*! + * sets d_vmcircbuf, d_base, d_bufsize. + * returns true iff successful. + */ +bool +gr_buffer::allocate_buffer (int nitems, size_t sizeof_item) +{ + int orig_nitems = nitems; + + // Any buffersize we come up with must be a multiple of min_nitems. + + int granularity = gr_vmcircbuf_sysconfig::granularity (); + int min_nitems = minimum_buffer_items (sizeof_item, granularity); + + // Round-up nitems to a multiple of min_nitems. + + if (nitems % min_nitems != 0) + nitems = ((nitems / min_nitems) + 1) * min_nitems; + + // If we rounded-up a whole bunch, give the user a heads up. + // This only happens if sizeof_item is not a power of two. + + if (nitems > 2 * orig_nitems && nitems * (int) sizeof_item > granularity){ + std::cerr << "gr_buffer::allocate_buffer: warning: tried to allocate\n" + << " " << orig_nitems << " items of size " + << sizeof_item << ". Due to alignment requirements\n" + << " " << nitems << " were allocated. If this isn't OK, consider padding\n" + << " your structure to a power-of-two bytes.\n" + << " On this platform, our allocation granularity is " << granularity << " bytes.\n"; + } + + d_bufsize = nitems; + d_vmcircbuf = gr_vmcircbuf_sysconfig::make (d_bufsize * d_sizeof_item); + if (d_vmcircbuf == 0){ + std::cerr << "gr_buffer::allocate_buffer: failed to allocate buffer of size " + << d_bufsize * d_sizeof_item / 1024 << " KB\n"; + return false; + } + + d_base = (char *) d_vmcircbuf->pointer_to_first_copy (); + return true; +} + + +int +gr_buffer::space_available () +{ + if (d_readers.empty ()) + return d_bufsize - 1; // See comment below + + else { + + // Find out the maximum amount of data available to our readers + + int most_data = d_readers[0]->items_available (); + uint64_t min_items_read = d_readers[0]->nitems_read(); + for (size_t i = 1; i < d_readers.size (); i++) { + most_data = std::max (most_data, d_readers[i]->items_available ()); + min_items_read = std::min(min_items_read, d_readers[i]->nitems_read()); + } + + if(min_items_read != d_last_min_items_read) { + prune_tags(d_last_min_items_read); + d_last_min_items_read = min_items_read; + } + + // The -1 ensures that the case d_write_index == d_read_index is + // unambiguous. It indicates that there is no data for the reader + + return d_bufsize - most_data - 1; + } +} + +void * +gr_buffer::write_pointer () +{ + return &d_base[d_write_index * d_sizeof_item]; +} + +void +gr_buffer::update_write_pointer (int nitems) +{ + gruel::scoped_lock guard(*mutex()); + d_write_index = index_add (d_write_index, nitems); + d_abs_write_offset += nitems; +} + +void +gr_buffer::set_done (bool done) +{ + gruel::scoped_lock guard(*mutex()); + d_done = done; +} + +gr_buffer_reader_sptr +gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload, gr_block_sptr link) +{ + if (nzero_preload < 0) + throw std::invalid_argument("gr_buffer_add_reader: nzero_preload must be >= 0"); + + gr_buffer_reader_sptr r (new gr_buffer_reader (buf, + buf->index_sub(buf->d_write_index, + nzero_preload), + link)); + buf->d_readers.push_back (r.get ()); + + return r; +} + +void +gr_buffer::drop_reader (gr_buffer_reader *reader) +{ + // isn't C++ beautiful... GAG! + + std::vector<gr_buffer_reader *>::iterator result = + std::find (d_readers.begin (), d_readers.end (), reader); + + if (result == d_readers.end ()) + throw std::invalid_argument ("gr_buffer::drop_reader"); // we didn't find it... + + d_readers.erase (result); +} + +void +gr_buffer::add_item_tag(const gr_tag_t &tag) +{ + gruel::scoped_lock guard(*mutex()); + d_item_tags.push_back(tag); +} + +void +gr_buffer::remove_item_tag(const gr_tag_t &tag) +{ + gruel::scoped_lock guard(*mutex()); + for (std::deque<gr_tag_t>::iterator it = d_item_tags.begin(); it != d_item_tags.end(); ++it) { + if (*it == tag) { + d_item_tags.erase(it); + break; + } + } +} + +void +gr_buffer::prune_tags(uint64_t max_time) +{ + /* NOTE: this function _should_ lock the mutex before editing + d_item_tags. In practice, this function is only called at + runtime by min_available_space in gr_block_executor.cc, + which locks the mutex itself. + + If this function is used elsewhere, remember to lock the + buffer's mutex al la the scoped_lock line below. + */ + //gruel::scoped_lock guard(*mutex()); + std::deque<gr_tag_t>::iterator itr = d_item_tags.begin(); + + uint64_t item_time; + + // Since tags are not guarenteed to be in any particular order, + // we need to erase here instead of pop_front. An erase in the + // middle invalidates all iterators; so this resets the iterator + // to find more. Mostly, we wil be erasing from the front and + // therefore lose little time this way. + while(itr != d_item_tags.end()) { + item_time = (*itr).offset; + if(item_time < max_time) { + d_item_tags.erase(itr); + itr = d_item_tags.begin(); + } + else + itr++; + } +} + +long +gr_buffer_ncurrently_allocated () +{ + return s_buffer_count; +} + +// ---------------------------------------------------------------------------- + +gr_buffer_reader::gr_buffer_reader(gr_buffer_sptr buffer, unsigned int read_index, + gr_block_sptr link) + : d_buffer(buffer), d_read_index(read_index), d_abs_read_offset(0), d_link(link) +{ + s_buffer_reader_count++; +} + +gr_buffer_reader::~gr_buffer_reader () +{ + d_buffer->drop_reader(this); + s_buffer_reader_count--; +} + +int +gr_buffer_reader::items_available () const +{ + return d_buffer->index_sub (d_buffer->d_write_index, d_read_index); +} + +const void * +gr_buffer_reader::read_pointer () +{ + return &d_buffer->d_base[d_read_index * d_buffer->d_sizeof_item]; +} + +void +gr_buffer_reader::update_read_pointer (int nitems) +{ + gruel::scoped_lock guard(*mutex()); + d_read_index = d_buffer->index_add (d_read_index, nitems); + d_abs_read_offset += nitems; +} + +void +gr_buffer_reader::get_tags_in_range(std::vector<gr_tag_t> &v, + uint64_t abs_start, + uint64_t abs_end) +{ + gruel::scoped_lock guard(*mutex()); + + v.resize(0); + std::deque<gr_tag_t>::iterator itr = d_buffer->get_tags_begin(); + + uint64_t item_time; + while(itr != d_buffer->get_tags_end()) { + item_time = (*itr).offset; + + if((item_time >= abs_start) && (item_time < abs_end)) { + v.push_back(*itr); + } + + itr++; + } +} + +long +gr_buffer_reader_ncurrently_allocated () +{ + return s_buffer_reader_count; +} diff --git a/gnuradio-core/src/lib/runtime/gr_buffer.h b/gnuradio-core/src/lib/runtime/gr_buffer.h new file mode 100644 index 000000000..28ea97726 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_buffer.h @@ -0,0 +1,309 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +#ifndef INCLUDED_GR_BUFFER_H +#define INCLUDED_GR_BUFFER_H + +#include <gr_core_api.h> +#include <gr_runtime_types.h> +#include <boost/weak_ptr.hpp> +#include <gruel/thread.h> +#include <gr_tags.h> +#include <deque> + +class gr_vmcircbuf; + +/*! + * \brief Allocate a buffer that holds at least \p nitems of size \p sizeof_item. + * + * The total size of the buffer will be rounded up to a system + * dependent boundary. This is typically the system page size, but + * under MS windows is 64KB. + * + * \param nitems is the minimum number of items the buffer will hold. + * \param sizeof_item is the size of an item in bytes. + * \param link is the block that writes to this buffer. + */ +GR_CORE_API gr_buffer_sptr gr_make_buffer (int nitems, size_t sizeof_item, gr_block_sptr link=gr_block_sptr()); + + +/*! + * \brief Single writer, multiple reader fifo. + * \ingroup internal + */ +class GR_CORE_API gr_buffer { + public: + + virtual ~gr_buffer (); + + /*! + * \brief return number of items worth of space available for writing + */ + int space_available (); + + /*! + * \brief return size of this buffer in items + */ + int bufsize() const { return d_bufsize; } + + /*! + * \brief return pointer to write buffer. + * + * The return value points at space that can hold at least + * space_available() items. + */ + void *write_pointer (); + + /*! + * \brief tell buffer that we wrote \p nitems into it + */ + void update_write_pointer (int nitems); + + void set_done (bool done); + bool done () const { return d_done; } + + /*! + * \brief Return the block that writes to this buffer. + */ + gr_block_sptr link() { return gr_block_sptr(d_link); } + + size_t nreaders() const { return d_readers.size(); } + gr_buffer_reader* reader(size_t index) { return d_readers[index]; } + + gruel::mutex *mutex() { return &d_mutex; } + + uint64_t nitems_written() { return d_abs_write_offset; } + + size_t get_sizeof_item() { return d_sizeof_item; } + + /*! + * \brief Adds a new tag to the buffer. + * + * \param tag the new tag + */ + void add_item_tag(const gr_tag_t &tag); + + /*! + * \brief Removes an existing tag from the buffer. + * + * If no such tag is found, does nothing. + * + * \param tag the tag that needs to be removed + */ + void remove_item_tag(const gr_tag_t &tag); + + /*! + * \brief Removes all tags before \p max_time from buffer + * + * \param max_time the time (item number) to trim up until. + */ + void prune_tags(uint64_t max_time); + + std::deque<gr_tag_t>::iterator get_tags_begin() { return d_item_tags.begin(); } + std::deque<gr_tag_t>::iterator get_tags_end() { return d_item_tags.end(); } + + // ------------------------------------------------------------------------- + + private: + + friend class gr_buffer_reader; + friend GR_CORE_API gr_buffer_sptr gr_make_buffer (int nitems, size_t sizeof_item, gr_block_sptr link); + friend GR_CORE_API gr_buffer_reader_sptr gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload, gr_block_sptr link); + + protected: + char *d_base; // base address of buffer + unsigned int d_bufsize; // in items + private: + gr_vmcircbuf *d_vmcircbuf; + size_t d_sizeof_item; // in bytes + std::vector<gr_buffer_reader *> d_readers; + boost::weak_ptr<gr_block> d_link; // block that writes to this buffer + + // + // The mutex protects d_write_index, d_abs_write_offset, d_done, d_item_tags + // and the d_read_index's and d_abs_read_offset's in the buffer readers. + // + gruel::mutex d_mutex; + unsigned int d_write_index; // in items [0,d_bufsize) + uint64_t d_abs_write_offset; // num items written since the start + bool d_done; + std::deque<gr_tag_t> d_item_tags; + uint64_t d_last_min_items_read; + + unsigned + index_add (unsigned a, unsigned b) + { + unsigned s = a + b; + + if (s >= d_bufsize) + s -= d_bufsize; + + assert (s < d_bufsize); + return s; + } + + unsigned + index_sub (unsigned a, unsigned b) + { + int s = a - b; + + if (s < 0) + s += d_bufsize; + + assert ((unsigned) s < d_bufsize); + return s; + } + + virtual bool allocate_buffer (int nitems, size_t sizeof_item); + + /*! + * \brief constructor is private. Use gr_make_buffer to create instances. + * + * Allocate a buffer that holds at least \p nitems of size \p sizeof_item. + * + * \param nitems is the minimum number of items the buffer will hold. + * \param sizeof_item is the size of an item in bytes. + * \param link is the block that writes to this buffer. + * + * The total size of the buffer will be rounded up to a system + * dependent boundary. This is typically the system page size, but + * under MS windows is 64KB. + */ + gr_buffer (int nitems, size_t sizeof_item, gr_block_sptr link); + + /*! + * \brief disassociate \p reader from this buffer + */ + void drop_reader (gr_buffer_reader *reader); + +}; + +/*! + * \brief Create a new gr_buffer_reader and attach it to buffer \p buf + * \param buf is the buffer the \p gr_buffer_reader reads from. + * \param nzero_preload -- number of zero items to "preload" into buffer. + * \param link is the block that reads from the buffer using this gr_buffer_reader. + */ +GR_CORE_API gr_buffer_reader_sptr +gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload, gr_block_sptr link=gr_block_sptr()); + +//! returns # of gr_buffers currently allocated +GR_CORE_API long gr_buffer_ncurrently_allocated (); + + +// --------------------------------------------------------------------------- + +/*! + * \brief How we keep track of the readers of a gr_buffer. + * \ingroup internal + */ + +class GR_CORE_API gr_buffer_reader { + public: + + ~gr_buffer_reader (); + + /*! + * \brief Return number of items available for reading. + */ + int items_available () const; + + /*! + * \brief Return buffer this reader reads from. + */ + gr_buffer_sptr buffer () const { return d_buffer; } + + + /*! + * \brief Return maximum number of items that could ever be available for reading. + * This is used as a sanity check in the scheduler to avoid looping forever. + */ + int max_possible_items_available () const { return d_buffer->d_bufsize - 1; } + + /*! + * \brief return pointer to read buffer. + * + * The return value points to items_available() number of items + */ + const void *read_pointer (); + + /* + * \brief tell buffer we read \p items from it + */ + void update_read_pointer (int nitems); + + void set_done (bool done) { d_buffer->set_done (done); } + bool done () const { return d_buffer->done (); } + + gruel::mutex *mutex() { return d_buffer->mutex(); } + + + uint64_t nitems_read() { return d_abs_read_offset; } + + size_t get_sizeof_item() { return d_buffer->get_sizeof_item(); } + + /*! + * \brief Return the block that reads via this reader. + * + */ + gr_block_sptr link() { return gr_block_sptr(d_link); } + + + /*! + * \brief Given a [start,end), returns a vector all tags in the range. + * + * Get a vector of tags in given range. Range of counts is from start to end-1. + * + * Tags are tuples of: + * (item count, source id, key, value) + * + * \param v a vector reference to return tags into + * \param abs_start a uint64 count of the start of the range of interest + * \param abs_end a uint64 count of the end of the range of interest + */ + void get_tags_in_range(std::vector<gr_tag_t> &v, + uint64_t abs_start, + uint64_t abs_end); + + // ------------------------------------------------------------------------- + + private: + + friend class gr_buffer; + friend GR_CORE_API gr_buffer_reader_sptr + gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload, gr_block_sptr link); + + + gr_buffer_sptr d_buffer; + unsigned int d_read_index; // in items [0,d->buffer.d_bufsize) + uint64_t d_abs_read_offset; // num items seen since the start + boost::weak_ptr<gr_block> d_link; // block that reads via this buffer reader + + //! constructor is private. Use gr_buffer::add_reader to create instances + gr_buffer_reader (gr_buffer_sptr buffer, unsigned int read_index, gr_block_sptr link); +}; + +//! returns # of gr_buffer_readers currently allocated +GR_CORE_API long gr_buffer_reader_ncurrently_allocated (); + + +#endif /* INCLUDED_GR_BUFFER_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_buffer.i b/gnuradio-core/src/lib/runtime/gr_buffer.i new file mode 100644 index 000000000..390a94e05 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_buffer.i @@ -0,0 +1,63 @@ +/* -*- 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. + */ + +class gr_buffer; +typedef boost::shared_ptr<gr_buffer> gr_buffer_sptr; +%template(gr_buffer_sptr) boost::shared_ptr<gr_buffer>; +%rename(buffer) gr_make_buffer; +%ignore gr_buffer; + +gr_buffer_sptr gr_make_buffer (int nitems, size_t sizeof_item, gr_block_sptr link); + +class gr_buffer { + public: + ~gr_buffer (); + + private: + gr_buffer (int nitems, size_t sizeof_item, gr_block_sptr link); +}; + + +class gr_buffer_reader; +typedef boost::shared_ptr<gr_buffer_reader> gr_buffer_reader_sptr; +%template(gr_buffer_reader_sptr) boost::shared_ptr<gr_buffer_reader>; +%ignore gr_buffer_reader; + +%rename(buffer_add_reader) gr_buffer_add_reader; +gr_buffer_reader_sptr gr_buffer_add_reader (gr_buffer_sptr buf, int nzero_preload, gr_block_sptr link); + +class gr_buffer_reader { + public: + ~gr_buffer_reader (); + + private: + friend class gr_buffer; + gr_buffer_reader (gr_buffer_sptr buffer, unsigned int read_index, gr_block_sptr link); +}; + + +%rename(buffer_ncurrently_allocated) gr_buffer_ncurrently_allocated; +long gr_buffer_ncurrently_allocated (); + +%rename(buffer_reader_ncurrently_allocated) gr_buffer_reader_ncurrently_allocated; +long gr_buffer_reader_ncurrently_allocated (); + diff --git a/gnuradio-core/src/lib/runtime/gr_complex.h b/gnuradio-core/src/lib/runtime/gr_complex.h new file mode 100644 index 000000000..58d1525b4 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_complex.h @@ -0,0 +1,46 @@ +/* -*- 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_COMPLEX_H +#define INCLUDED_GR_COMPLEX_H + +#include <complex> +typedef std::complex<float> gr_complex; +typedef std::complex<double> gr_complexd; + + +inline bool is_complex (gr_complex x) { (void) x; return true;} +inline bool is_complex (gr_complexd x) { (void) x; return true;} +inline bool is_complex (float x) { (void) x; return false;} +inline bool is_complex (double x) { (void) x; return false;} +inline bool is_complex (int x) { (void) x; return false;} +inline bool is_complex (char x) { (void) x; return false;} +inline bool is_complex (short x) { (void) x; return false;} + + +// this doesn't really belong here, but there are worse places for it... + +#define CPPUNIT_ASSERT_COMPLEXES_EQUAL(expected,actual,delta) \ + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected.real(), actual.real(), delta); \ + CPPUNIT_ASSERT_DOUBLES_EQUAL (expected.imag(), actual.imag(), delta); + +#endif /* INCLUDED_GR_COMPLEX_H */ + diff --git a/gnuradio-core/src/lib/runtime/gr_dispatcher.cc b/gnuradio-core/src/lib/runtime/gr_dispatcher.cc new file mode 100644 index 000000000..96ebe9ad8 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_dispatcher.cc @@ -0,0 +1,193 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_dispatcher.h> +#include <math.h> +#include <errno.h> +#include <stdio.h> + +#ifdef HAVE_SELECT +# ifdef HAVE_SYS_SELECT_H +# include <sys/select.h> +# else +# ifdef HAVE_SYS_TIME_H +# include <sys/time.h> +# endif +# ifdef HAVE_SYS_TYPES_H +# include <sys/types.h> +# endif +# ifdef HAVE_UNISTD_H +# include <unistd.h> +# endif +# endif +#endif + + +static gr_dispatcher_sptr s_singleton; + +gr_dispatcher_sptr +gr_make_dispatcher() +{ + return gr_dispatcher_sptr(new gr_dispatcher()); +} + +gr_dispatcher_sptr +gr_dispatcher_singleton() +{ + if (s_singleton) + return s_singleton; + + s_singleton = gr_make_dispatcher(); + return s_singleton; +} + +#if !defined(HAVE_SELECT) // Stub it out + +gr_dispatcher::gr_dispatcher() +{ +} + +gr_dispatcher::~gr_dispatcher() +{ +} + +bool +gr_dispatcher::add_handler(gr_select_handler_sptr handler) +{ + return true; +} + +bool +gr_dispatcher::del_handler(gr_select_handler_sptr handler) +{ + return true; +} + +bool +gr_dispatcher::del_handler(gr_select_handler *handler) +{ + return true; +} + +void +gr_dispatcher::loop(double timeout) +{ +} + +#else // defined(HAVE_SELECT) + +gr_dispatcher::gr_dispatcher() + : d_handler(FD_SETSIZE), d_max_index(-1) +{ +} + +gr_dispatcher::~gr_dispatcher() +{ +} + +bool +gr_dispatcher::add_handler(gr_select_handler_sptr handler) +{ + int fd = handler->fd(); + if (fd < 0 || fd >= FD_SETSIZE) + return false; + + d_max_index = std::max(d_max_index, fd); + d_handler[fd] = handler; + return true; +} + +bool +gr_dispatcher::del_handler(gr_select_handler_sptr handler) +{ + return del_handler(handler.get()); +} + +bool +gr_dispatcher::del_handler(gr_select_handler *handler) +{ + int fd = handler->fd(); + if (fd < 0 || fd >= FD_SETSIZE) + return false; + + d_handler[fd].reset(); + + if (fd == d_max_index){ + int i; + for (i = fd - 1; i >= 0 && !d_handler[i]; i--) + ; + d_max_index = i; + } + return true; +} + + +void +gr_dispatcher::loop(double timeout) +{ + struct timeval master; + struct timeval tmp; + fd_set rd_set; + fd_set wr_set; + + double secs = floor (timeout); + master.tv_sec = (long) secs; + master.tv_usec = (long) ((timeout - secs) * 1e6); + + while (d_max_index >= 0){ + FD_ZERO(&rd_set); + FD_ZERO(&wr_set); + + for (int i = 0; i <= d_max_index; i++){ + if (d_handler[i] && d_handler[i]->readable()) + FD_SET(i, &rd_set); + if (d_handler[i] && d_handler[i]->writable()) + FD_SET(i, &wr_set); + } + + tmp = master; + int retval = select(d_max_index+1, &rd_set, &wr_set, 0, &tmp); + if (retval == 0) // timed out with nothing ready + continue; + if (retval < 0){ + if (errno == EINTR) + continue; + perror ("gr_dispatcher/select"); + return; + } + + for (int i = 0; i <= d_max_index; i++){ + if (FD_ISSET(i, &rd_set)) + if (d_handler[i]) + d_handler[i]->handle_read(); + if (FD_ISSET(i, &wr_set)) + if (d_handler[i]) + d_handler[i]->handle_write(); + } + } +} + +#endif diff --git a/gnuradio-core/src/lib/runtime/gr_dispatcher.h b/gnuradio-core/src/lib/runtime/gr_dispatcher.h new file mode 100644 index 000000000..72a0b0176 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_dispatcher.h @@ -0,0 +1,69 @@ +/* -*- 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_DISPATCHER_H +#define INCLUDED_GR_DISPATCHER_H + +#include <gr_core_api.h> +#include <gr_select_handler.h> +#include <vector> + +class gr_dispatcher; +typedef boost::shared_ptr<gr_dispatcher> gr_dispatcher_sptr; + +GR_CORE_API gr_dispatcher_sptr gr_dispatcher_singleton(); +GR_CORE_API gr_dispatcher_sptr gr_make_dispatcher(); + +/*! + * \brief invoke callbacks based on select. + * \ingroup internal + * + * \sa gr_select_handler + */ +class GR_CORE_API gr_dispatcher +{ + gr_dispatcher(); + friend GR_CORE_API gr_dispatcher_sptr gr_make_dispatcher(); + + std::vector<gr_select_handler_sptr> d_handler; + int d_max_index; + +public: + ~gr_dispatcher(); + + bool add_handler(gr_select_handler_sptr handler); + bool del_handler(gr_select_handler_sptr handler); + bool del_handler(gr_select_handler *handler); + + /*! + * \brief Event dispatching loop. + * + * Enter a polling loop that only terminates after all gr_select_handlers + * have been removed. \p timeout sets the timeout parameter to the select() + * call, measured in seconds. + * + * \param timeout maximum number of seconds to block in select. + */ + void loop(double timeout=10); +}; + +#endif /* INCLUDED_GR_DISPATCHER_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_dispatcher.i b/gnuradio-core/src/lib/runtime/gr_dispatcher.i new file mode 100644 index 000000000..28737cd31 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_dispatcher.i @@ -0,0 +1,55 @@ +/* -*- 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. + */ + +class gr_dispatcher; +typedef boost::shared_ptr<gr_dispatcher> gr_dispatcher_sptr; +%template(gr_dispatcher_sptr) boost::shared_ptr<gr_dispatcher>; + +%rename(dispatcher) gr_make_dispatcher; +gr_dispatcher_sptr gr_make_dispatcher(); + +%rename(dispatcher_singleton) gr_dispatcher_singleton; +gr_dispatcher_sptr gr_dispatcher_singleton(); + +/*! + * \brief invoke callbacks based on select. + * + * \sa gr_select_handler + */ +class gr_dispatcher +{ + gr_dispatcher(); + +public: + ~gr_dispatcher(); + + /*! + * \brief Event dispatching loop. + * + * Enter a polling loop that only terminates after all gr_select_handlers + * have been removed. \p timeout sets the timeout parameter to the select() + * call, measured in seconds. + * + * \param timeout maximum number of seconds to block in select. + */ + void loop(double timeout=10); +}; diff --git a/gnuradio-core/src/lib/runtime/gr_error_handler.cc b/gnuradio-core/src/lib/runtime/gr_error_handler.cc new file mode 100644 index 000000000..448682966 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_error_handler.cc @@ -0,0 +1,244 @@ +/* -*- 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. + */ +/* + * This code is based on error.cc from the "Click Modular Router". + * Original copyright follows: + */ +/* + * error.{cc,hh} -- flexible classes for error reporting + * Eddie Kohler + * + * Copyright (c) 1999-2000 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, subject to the conditions + * listed in the Click LICENSE file. These conditions include: you must + * preserve this copyright notice, and you cannot mention the copyright + * holders in advertising related to the Software without their permission. + * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This + * notice is a summary of the Click LICENSE file; the license in that file is + * legally binding. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_error_handler.h> +#include <assert.h> +#include <stdexcept> +#include <unistd.h> + +#ifdef HAVE_IO_H +#include <io.h> +#endif + +static gr_error_handler *s_default_handler = 0; +static gr_error_handler *s_silent_handler = 0; + +bool +gr_error_handler::has_default_handler() +{ + return s_default_handler != 0; +} + +void +gr_error_handler::set_default_handler(gr_error_handler *errh) +{ + s_default_handler = errh; +} + +gr_error_handler * +gr_error_handler::default_handler() +{ + assert (s_default_handler != 0); + return s_default_handler; +} + +gr_error_handler * +gr_error_handler::silent_handler() +{ + assert (s_silent_handler != 0); + return s_silent_handler; +} + +// ---------------------------------------------------------------- + +gr_error_handler::~gr_error_handler() +{ + // nop +} + +void +gr_error_handler::debug(const char *format, ...) +{ + va_list val; + va_start(val, format); + verror(ERR_DEBUG, format, val); + va_end(val); +} + +void +gr_error_handler::message(const char *format, ...) +{ + va_list val; + va_start(val, format); + verror(ERR_MESSAGE, format, val); + va_end(val); +} + +void +gr_error_handler::warning(const char *format, ...) +{ + va_list val; + va_start(val, format); + verror(ERR_WARNING, format, val); + va_end(val); +} + +void +gr_error_handler::error(const char *format, ...) +{ + va_list val; + va_start(val, format); + verror(ERR_ERROR, format, val); + va_end(val); +} + +void +gr_error_handler::fatal(const char *format, ...) +{ + va_list val; + va_start(val, format); + verror(ERR_FATAL, format, val); + va_end(val); +} + +void +gr_error_handler::verror(seriousness s, const char *format, va_list val) +{ + std::string text = make_text(s, format, val); + handle_text(s, text); + count_error(s); +} + +void +gr_error_handler::verror_text(seriousness s, const std::string &text) +{ + // text is already made + handle_text(s, text); + count_error(s); +} + +std::string +gr_error_handler::make_text(seriousness s, const char *format, va_list val) +{ + char text_buf[4096]; + vsnprintf(text_buf, sizeof(text_buf), format, val); + text_buf[sizeof(text_buf)-1] = 0; + return text_buf; +} + +// ---------------------------------------------------------------- + +void +gr_base_error_handler::count_error(seriousness s) +{ + if (s < ERR_WARNING) + /* do nothing */; + else if (s < ERR_ERROR) + d_nwarnings++; + else + d_nerrors++; +} + +// ---------------------------------------------------------------- + +gr_file_error_handler::gr_file_error_handler(FILE *file) + : d_file(file), d_fd(-1) +{ +} + +gr_file_error_handler::gr_file_error_handler(int file_descriptor) +{ + d_fd = dup(file_descriptor); // so we can fclose it + if (d_fd == -1){ + perror("gr_file_error_handler:dup"); + throw std::invalid_argument("gr_file_error_handler:dup"); + } + d_file = fdopen(d_fd, "w"); + if (d_file == 0){ + perror("gr_file_error_handler:fdopen"); + throw std::invalid_argument("gr_file_error_handler:fdopen"); + } +} + +gr_file_error_handler::~gr_file_error_handler() +{ + if (d_fd != -1){ + fclose(d_file); + } +} + +void +gr_file_error_handler::handle_text(seriousness s, const std::string &text) +{ + if (text.length() <= 0) + return; + + fwrite(text.data(), 1, text.length(), d_file); + if (text[text.length()-1] != '\n') + fwrite("\n", 1, 1, d_file); + + if (d_fd != -1) + fflush(d_file); // keep synced with any other users of fd +} + + +// ---------------------------------------------------------------- +// static error handlers +// + +class gr_silent_error_handler : public gr_base_error_handler +{ +public: + gr_silent_error_handler() {} + void handle_text(seriousness s, const std::string &str); +}; + +void +gr_silent_error_handler::handle_text(seriousness s, const std::string &str) +{ + // nop +} + +class force_init { +public: + force_init() + { + s_default_handler = new gr_file_error_handler(stdout); + s_silent_handler = new gr_silent_error_handler(); + } +}; + +static force_init kludge; diff --git a/gnuradio-core/src/lib/runtime/gr_error_handler.h b/gnuradio-core/src/lib/runtime/gr_error_handler.h new file mode 100644 index 000000000..569c01c45 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_error_handler.h @@ -0,0 +1,117 @@ +/* -*- 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. + */ +/* + * This code is based on error.hh from the "Click Modular Router". + * Original copyright follows: + */ +/* + * error.{cc,hh} -- flexible classes for error reporting + * Eddie Kohler + * + * Copyright (c) 1999-2000 Massachusetts Institute of Technology + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, subject to the conditions + * listed in the Click LICENSE file. These conditions include: you must + * preserve this copyright notice, and you cannot mention the copyright + * holders in advertising related to the Software without their permission. + * The Software is provided WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED. This + * notice is a summary of the Click LICENSE file; the license in that file is + * legally binding. + */ + +#ifndef INCLUDED_GR_ERROR_HANDLER_H +#define INCLUDED_GR_ERROR_HANDLER_H + +#include <gr_core_api.h> +#include <stdarg.h> +#include <string> +#include <cstdio> // for FILE + +/*! + * \brief abstract error handler + * \ingroup base + */ +class GR_CORE_API gr_error_handler { +public: + enum seriousness { + ERR_DEBUG = 0x00000000, + ERR_MESSAGE = 0x00010000, + ERR_WARNING = 0x00020000, + ERR_ERROR = 0x00030000, + ERR_FATAL = 0x00040000 + }; + + gr_error_handler() {} + virtual ~gr_error_handler(); + + static gr_error_handler *default_handler(); + static gr_error_handler *silent_handler(); + + static bool has_default_handler(); + static void set_default_handler(gr_error_handler *errh); + + void debug(const char *format, ...); + void message(const char *format, ...); + void warning(const char *format, ...); + void error(const char *format, ...); + void fatal(const char *format, ...); + + virtual int nwarnings() const = 0; + virtual int nerrors() const = 0; + virtual void reset_counts() = 0; + + void verror(seriousness s, const char *format, va_list); + void verror_text(seriousness s, const std::string &text); + +protected: + virtual void count_error(seriousness s) = 0; + virtual void handle_text(seriousness s, const std::string &str) = 0; + std::string make_text(seriousness s, const char *format, va_list); +}; + + +class GR_CORE_API gr_base_error_handler : public gr_error_handler { + int d_nwarnings; + int d_nerrors; + +public: + gr_base_error_handler() : d_nwarnings(0), d_nerrors(0) {} + int nwarnings() const { return d_nwarnings; } + int nerrors() const { return d_nerrors; } + void reset_counts() { d_nwarnings = d_nerrors = 0; } + void count_error(seriousness s); +}; + +class GR_CORE_API gr_file_error_handler : public gr_base_error_handler { + FILE *d_file; + int d_fd; +public: + gr_file_error_handler(FILE *file); + gr_file_error_handler(int file_descriptor); + ~gr_file_error_handler(); + + void handle_text(seriousness s, const std::string &str); +}; + +#endif /* INCLUDED_GR_ERROR_HANDLER_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_error_handler.i b/gnuradio-core/src/lib/runtime/gr_error_handler.i new file mode 100644 index 000000000..072394a72 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_error_handler.i @@ -0,0 +1,69 @@ +/* -*- 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. + */ + +%rename(error_handler) gr_error_handler; +%rename(file_error_handler) gr_file_error_handler; + +class gr_error_handler { +public: + enum seriousness { + ERR_DEBUG = 0x00000000, + ERR_MESSAGE = 0x00010000, + ERR_WARNING = 0x00020000, + ERR_ERROR = 0x00030000, + ERR_FATAL = 0x00040000 + }; + + gr_error_handler() {} + virtual ~gr_error_handler(); + + static gr_error_handler *default_handler(); + static gr_error_handler *silent_handler(); + + static bool has_default_handler(); + static void set_default_handler(gr_error_handler *errh); + + virtual int nwarnings() const = 0; + virtual int nerrors() const = 0; + virtual void reset_counts() = 0; + + void verror_text(seriousness s, const std::string &text); +}; + +%ignore gr_base_error_handler; +class gr_base_error_handler : public gr_error_handler { + int d_nwarnings; + int d_nerrors; + +public: + gr_base_error_handler() : d_nwarnings(0), d_nerrors(0) {} + int nwarnings() const { return d_nwarnings; } + int nerrors() const { return d_nerrors; } + void reset_counts() { d_nwarnings = d_nerrors = 0; } + void count_error(seriousness s); +}; + +class gr_file_error_handler : public gr_base_error_handler { +public: + gr_file_error_handler(int file_descriptor); + ~gr_file_error_handler(); +}; diff --git a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc new file mode 100644 index 000000000..9294a5dca --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.cc @@ -0,0 +1,403 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_flat_flowgraph.h> +#include <gr_block_detail.h> +#include <gr_io_signature.h> +#include <gr_buffer.h> +#include <volk/volk.h> +#include <iostream> +#include <map> +#include <boost/format.hpp> + +#define GR_FLAT_FLOWGRAPH_DEBUG 0 + +// 32Kbyte buffer size between blocks +#define GR_FIXED_BUFFER_SIZE (32*(1L<<10)) + +static const unsigned int s_fixed_buffer_size = GR_FIXED_BUFFER_SIZE; + +gr_flat_flowgraph_sptr +gr_make_flat_flowgraph() +{ + return gr_flat_flowgraph_sptr(new gr_flat_flowgraph()); +} + +gr_flat_flowgraph::gr_flat_flowgraph() +{ +} + +gr_flat_flowgraph::~gr_flat_flowgraph() +{ +} + +void +gr_flat_flowgraph::setup_connections() +{ + gr_basic_block_vector_t blocks = calc_used_blocks(); + + // Assign block details to blocks + for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) + cast_to_block_sptr(*p)->set_detail(allocate_block_detail(*p)); + + // Connect inputs to outputs for each block + for(gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { + connect_block_inputs(*p); + + gr_block_sptr block = cast_to_block_sptr(*p); + block->set_unaligned(0); + block->set_is_unaligned(false); + } + + // Connect message ports connetions + for(gr_msg_edge_viter_t i = d_msg_edges.begin(); i != d_msg_edges.end(); i++){ + if(GR_FLAT_FLOWGRAPH_DEBUG) + std::cout << boost::format("flat_fg connecting msg primitives: (%s, %s)->(%s, %s)\n") % + i->src().block() % i->src().port() % + i->dst().block() % i->dst().port(); + i->src().block()->message_port_sub( i->src().port(), pmt::pmt_cons(i->dst().block()->alias_pmt(), i->dst().port()) ); + } + +} + +gr_block_detail_sptr +gr_flat_flowgraph::allocate_block_detail(gr_basic_block_sptr block) +{ + int ninputs = calc_used_ports(block, true).size(); + int noutputs = calc_used_ports(block, false).size(); + gr_block_detail_sptr detail = gr_make_block_detail(ninputs, noutputs); + + gr_block_sptr grblock = cast_to_block_sptr(block); + if(!grblock) + throw std::runtime_error("allocate_block_detail found non-gr_block"); + + if (GR_FLAT_FLOWGRAPH_DEBUG) + std::cout << "Creating block detail for " << block << std::endl; + + for (int i = 0; i < noutputs; i++) { + grblock->expand_minmax_buffer(i); + + gr_buffer_sptr buffer = allocate_buffer(block, i); + if (GR_FLAT_FLOWGRAPH_DEBUG) + std::cout << "Allocated buffer for output " << block << ":" << i << std::endl; + detail->set_output(i, buffer); + + // Update the block's max_output_buffer based on what was actually allocated. + grblock->set_max_output_buffer(i, buffer->bufsize()); + } + + return detail; +} + +gr_buffer_sptr +gr_flat_flowgraph::allocate_buffer(gr_basic_block_sptr block, int port) +{ + gr_block_sptr grblock = cast_to_block_sptr(block); + if (!grblock) + throw std::runtime_error("allocate_buffer found non-gr_block"); + int item_size = block->output_signature()->sizeof_stream_item(port); + + // *2 because we're now only filling them 1/2 way in order to + // increase the available parallelism when using the TPB scheduler. + // (We're double buffering, where we used to single buffer) + int nitems = s_fixed_buffer_size * 2 / item_size; + + // Make sure there are at least twice the output_multiple no. of items + if (nitems < 2*grblock->output_multiple()) // Note: this means output_multiple() + nitems = 2*grblock->output_multiple(); // can't be changed by block dynamically + + // If any downstream blocks are decimators and/or have a large output_multiple, + // ensure we have a buffer at least twice their decimation factor*output_multiple + gr_basic_block_vector_t blocks = calc_downstream_blocks(block, port); + + // limit buffer size if indicated + if(grblock->max_output_buffer(port) > 0) { +// std::cout << "constraining output items to " << block->max_output_buffer(port) << "\n"; + nitems = std::min((long)nitems, (long)grblock->max_output_buffer(port)); + nitems -= nitems%grblock->output_multiple(); + if( nitems < 1 ) + throw std::runtime_error("problems allocating a buffer with the given max output buffer constraint!"); + } + else if(grblock->min_output_buffer(port) > 0) { + nitems = std::max((long)nitems, (long)grblock->min_output_buffer(port)); + nitems -= nitems%grblock->output_multiple(); + if( nitems < 1 ) + throw std::runtime_error("problems allocating a buffer with the given min output buffer constraint!"); + } + + for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { + gr_block_sptr dgrblock = cast_to_block_sptr(*p); + if (!dgrblock) + throw std::runtime_error("allocate_buffer found non-gr_block"); + + double decimation = (1.0/dgrblock->relative_rate()); + int multiple = dgrblock->output_multiple(); + int history = dgrblock->history(); + nitems = std::max(nitems, static_cast<int>(2*(decimation*multiple+history))); + } + +// std::cout << "gr_make_buffer(" << nitems << ", " << item_size << ", " << grblock << "\n"; + return gr_make_buffer(nitems, item_size, grblock); +} + +void +gr_flat_flowgraph::connect_block_inputs(gr_basic_block_sptr block) +{ + gr_block_sptr grblock = cast_to_block_sptr(block); + if (!grblock) + throw std::runtime_error("connect_block_inputs found non-gr_block"); + + // Get its detail and edges that feed into it + gr_block_detail_sptr detail = grblock->detail(); + gr_edge_vector_t in_edges = calc_upstream_edges(block); + + // For each edge that feeds into it + for (gr_edge_viter_t e = in_edges.begin(); e != in_edges.end(); e++) { + // Set the buffer reader on the destination port to the output + // buffer on the source port + int dst_port = e->dst().port(); + int src_port = e->src().port(); + gr_basic_block_sptr src_block = e->src().block(); + gr_block_sptr src_grblock = cast_to_block_sptr(src_block); + if (!src_grblock) + throw std::runtime_error("connect_block_inputs found non-gr_block"); + gr_buffer_sptr src_buffer = src_grblock->detail()->output(src_port); + + if (GR_FLAT_FLOWGRAPH_DEBUG) + std::cout << "Setting input " << dst_port << " from edge " << (*e) << std::endl; + + detail->set_input(dst_port, gr_buffer_add_reader(src_buffer, grblock->history()-1, grblock)); + } +} + +void +gr_flat_flowgraph::merge_connections(gr_flat_flowgraph_sptr old_ffg) +{ + // Allocate block details if needed. Only new blocks that aren't pruned out + // by flattening will need one; existing blocks still in the new flowgraph will + // already have one. + for (gr_basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) { + gr_block_sptr block = cast_to_block_sptr(*p); + + if (!block->detail()) { + if (GR_FLAT_FLOWGRAPH_DEBUG) + std::cout << "merge: allocating new detail for block " << (*p) << std::endl; + block->set_detail(allocate_block_detail(block)); + } + else + if (GR_FLAT_FLOWGRAPH_DEBUG) + std::cout << "merge: reusing original detail for block " << (*p) << std::endl; + } + + // Calculate the old edges that will be going away, and clear the buffer readers + // on the RHS. + for (gr_edge_viter_t old_edge = old_ffg->d_edges.begin(); old_edge != old_ffg->d_edges.end(); old_edge++) { + if (GR_FLAT_FLOWGRAPH_DEBUG) + std::cout << "merge: testing old edge " << (*old_edge) << "..."; + + gr_edge_viter_t new_edge; + for (new_edge = d_edges.begin(); new_edge != d_edges.end(); new_edge++) + if (new_edge->src() == old_edge->src() && + new_edge->dst() == old_edge->dst()) + break; + + if (new_edge == d_edges.end()) { // not found in new edge list + if (GR_FLAT_FLOWGRAPH_DEBUG) + std::cout << "not in new edge list" << std::endl; + // zero the buffer reader on RHS of old edge + gr_block_sptr block(cast_to_block_sptr(old_edge->dst().block())); + int port = old_edge->dst().port(); + block->detail()->set_input(port, gr_buffer_reader_sptr()); + } + else { + if (GR_FLAT_FLOWGRAPH_DEBUG) + std::cout << "found in new edge list" << std::endl; + } + } + + // Now connect inputs to outputs, reusing old buffer readers if they exist + for (gr_basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) { + gr_block_sptr block = cast_to_block_sptr(*p); + + if (GR_FLAT_FLOWGRAPH_DEBUG) + std::cout << "merge: merging " << (*p) << "..."; + + if (old_ffg->has_block_p(*p)) { + // Block exists in old flow graph + if (GR_FLAT_FLOWGRAPH_DEBUG) + std::cout << "used in old flow graph" << std::endl; + gr_block_detail_sptr detail = block->detail(); + + // Iterate through the inputs and see what needs to be done + int ninputs = calc_used_ports(block, true).size(); // Might be different now + for (int i = 0; i < ninputs; i++) { + if (GR_FLAT_FLOWGRAPH_DEBUG) + std::cout << "Checking input " << block << ":" << i << "..."; + gr_edge edge = calc_upstream_edge(*p, i); + + // Fish out old buffer reader and see if it matches correct buffer from edge list + gr_block_sptr src_block = cast_to_block_sptr(edge.src().block()); + gr_block_detail_sptr src_detail = src_block->detail(); + gr_buffer_sptr src_buffer = src_detail->output(edge.src().port()); + gr_buffer_reader_sptr old_reader; + if (i < detail->ninputs()) // Don't exceed what the original detail has + old_reader = detail->input(i); + + // If there's a match, use it + if (old_reader && (src_buffer == old_reader->buffer())) { + if (GR_FLAT_FLOWGRAPH_DEBUG) + std::cout << "matched, reusing" << std::endl; + } + else { + if (GR_FLAT_FLOWGRAPH_DEBUG) + std::cout << "needs a new reader" << std::endl; + + // Create new buffer reader and assign + detail->set_input(i, gr_buffer_add_reader(src_buffer, block->history()-1, block)); + } + } + } + else { + // Block is new, it just needs buffer readers at this point + if (GR_FLAT_FLOWGRAPH_DEBUG) + std::cout << "new block" << std::endl; + connect_block_inputs(block); + + // Make sure all buffers are aligned + setup_buffer_alignment(block); + } + + // Now deal with the fact that the block details might have changed numbers of + // inputs and outputs vs. in the old flowgraph. + } +} + +void +gr_flat_flowgraph::setup_buffer_alignment(gr_block_sptr block) +{ + const int alignment = volk_get_alignment(); + for(int i = 0; i < block->detail()->ninputs(); i++) { + void *r = (void*)block->detail()->input(i)->read_pointer(); + unsigned long int ri = (unsigned long int)r % alignment; + //std::cerr << "reader: " << r << " alignment: " << ri << std::endl; + if(ri != 0) { + size_t itemsize = block->detail()->input(i)->get_sizeof_item(); + block->detail()->input(i)->update_read_pointer(alignment-ri/itemsize); + } + block->set_unaligned(0); + block->set_is_unaligned(false); + } + + for(int i = 0; i < block->detail()->noutputs(); i++) { + void *w = (void*)block->detail()->output(i)->write_pointer(); + unsigned long int wi = (unsigned long int)w % alignment; + //std::cerr << "writer: " << w << " alignment: " << wi << std::endl; + if(wi != 0) { + size_t itemsize = block->detail()->output(i)->get_sizeof_item(); + block->detail()->output(i)->update_write_pointer(alignment-wi/itemsize); + } + block->set_unaligned(0); + block->set_is_unaligned(false); + } +} + +void gr_flat_flowgraph::dump() +{ + for (gr_edge_viter_t e = d_edges.begin(); e != d_edges.end(); e++) + std::cout << " edge: " << (*e) << std::endl; + + for (gr_basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) { + std::cout << " block: " << (*p) << std::endl; + gr_block_detail_sptr detail = cast_to_block_sptr(*p)->detail(); + std::cout << " detail @" << detail << ":" << std::endl; + + int ni = detail->ninputs(); + int no = detail->noutputs(); + for (int i = 0; i < no; i++) { + gr_buffer_sptr buffer = detail->output(i); + std::cout << " output " << i << ": " << buffer << std::endl; + } + + for (int i = 0; i < ni; i++) { + gr_buffer_reader_sptr reader = detail->input(i); + std::cout << " reader " << i << ": " << reader + << " reading from buffer=" << reader->buffer() << std::endl; + } + } + +} + +gr_block_vector_t +gr_flat_flowgraph::make_block_vector(gr_basic_block_vector_t &blocks) +{ + gr_block_vector_t result; + for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { + result.push_back(cast_to_block_sptr(*p)); + } + + return result; +} + + +void gr_flat_flowgraph::clear_endpoint(const gr_msg_endpoint &e, bool is_src){ + for(size_t i=0; i<d_msg_edges.size(); i++){ + if(is_src){ + if(d_msg_edges[i].src() == e){ + d_msg_edges.erase(d_msg_edges.begin() + i); + i--; + } + } else { + if(d_msg_edges[i].dst() == e){ + d_msg_edges.erase(d_msg_edges.begin() + i); + i--; + } + } + } +} + +void gr_flat_flowgraph::replace_endpoint(const gr_msg_endpoint &e, const gr_msg_endpoint &r, bool is_src){ + size_t n_replr(0); + if(GR_FLAT_FLOWGRAPH_DEBUG) + std::cout << boost::format("gr_flat_flowgraph::replace_endpoint( %s, %s, %d )\n") % e.block()% r.block()% is_src; + for(size_t i=0; i<d_msg_edges.size(); i++){ + if(is_src){ + if(d_msg_edges[i].src() == e){ + if(GR_FLAT_FLOWGRAPH_DEBUG) + std::cout << boost::format("gr_flat_flowgraph::replace_endpoint() flattening to ( %s, %s )\n") % r.block()% d_msg_edges[i].dst().block(); + d_msg_edges.push_back( gr_msg_edge(r, d_msg_edges[i].dst() ) ); + n_replr++; + } + } else { + if(d_msg_edges[i].dst() == e){ + if(GR_FLAT_FLOWGRAPH_DEBUG) + std::cout << boost::format("gr_flat_flowgraph::replace_endpoint() flattening to ( %s, %s )\n") % r.block()% d_msg_edges[i].dst().block(); + d_msg_edges.push_back( gr_msg_edge(d_msg_edges[i].src(), r ) ); + n_replr++; + } + } + } +} + diff --git a/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.h b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.h new file mode 100644 index 000000000..5c8268d7d --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_flat_flowgraph.h @@ -0,0 +1,80 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,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_FLAT_FLOWGRAPH_H +#define INCLUDED_GR_FLAT_FLOWGRAPH_H + +#include <gr_core_api.h> +#include <gr_flowgraph.h> +#include <gr_block.h> + +// Create a shared pointer to a heap allocated gr_flat_flowgraph +// (types defined in gr_runtime_types.h) +GR_CORE_API gr_flat_flowgraph_sptr gr_make_flat_flowgraph(); + +/*! + *\brief Class specializing gr_flat_flowgraph that has all nodes + * as gr_blocks, with no hierarchy + * \ingroup internal + */ +class GR_CORE_API gr_flat_flowgraph : public gr_flowgraph +{ +public: + friend GR_CORE_API gr_flat_flowgraph_sptr gr_make_flat_flowgraph(); + + // Destruct an arbitrary gr_flat_flowgraph + ~gr_flat_flowgraph(); + + // Wire gr_blocks together in new flat_flowgraph + void setup_connections(); + + // Merge applicable connections from existing flat flowgraph + void merge_connections(gr_flat_flowgraph_sptr sfg); + + void dump(); + + /*! + * Make a vector of gr_block from a vector of gr_basic_block + */ + static gr_block_vector_t make_block_vector(gr_basic_block_vector_t &blocks); + + void replace_endpoint(const gr_msg_endpoint &e, const gr_msg_endpoint &r, bool is_src); + void clear_endpoint(const gr_msg_endpoint &e, bool is_src); + +private: + gr_flat_flowgraph(); + + gr_block_detail_sptr allocate_block_detail(gr_basic_block_sptr block); + gr_buffer_sptr allocate_buffer(gr_basic_block_sptr block, int port); + void connect_block_inputs(gr_basic_block_sptr block); + + /* When reusing a flowgraph's blocks, this call makes sure all of the + * buffer's are aligned at the machine's alignment boundary and tells + * the blocks that they are aligned. + * + * Called from both setup_connections and merge_connections for + * start and restarts. + */ + void setup_buffer_alignment(gr_block_sptr block); +}; + +#endif /* INCLUDED_GR_FLAT_FLOWGRAPH_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_flowgraph.cc b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc new file mode 100644 index 000000000..63a208480 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_flowgraph.cc @@ -0,0 +1,515 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,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_flowgraph.h> +#include <gr_io_signature.h> +#include <stdexcept> +#include <sstream> +#include <iterator> + +#define GR_FLOWGRAPH_DEBUG 0 + +gr_edge::~gr_edge() +{ +} + +gr_flowgraph_sptr gr_make_flowgraph() +{ + return gr_flowgraph_sptr(new gr_flowgraph()); +} + +gr_flowgraph::gr_flowgraph() +{ +} + +gr_flowgraph::~gr_flowgraph() +{ +} + +// FIXME: move to libgruel as a utility function +template<class T> +static +std::vector<T> +unique_vector(std::vector<T> v) +{ + std::vector<T> result; + std::insert_iterator<std::vector<T> > inserter(result, result.begin()); + + sort(v.begin(), v.end()); + unique_copy(v.begin(), v.end(), inserter); + return result; +} + +void +gr_flowgraph::connect(const gr_endpoint &src, const gr_endpoint &dst) +{ + check_valid_port(src.block()->output_signature(), src.port()); + check_valid_port(dst.block()->input_signature(), dst.port()); + check_dst_not_used(dst); + check_type_match(src, dst); + + // All ist klar, Herr Kommisar + d_edges.push_back(gr_edge(src,dst)); +} + +void +gr_flowgraph::disconnect(const gr_endpoint &src, const gr_endpoint &dst) +{ + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { + if (src == p->src() && dst == p->dst()) { + d_edges.erase(p); + return; + } + } + + std::stringstream msg; + msg << "cannot disconnect edge " << gr_edge(src, dst) << ", not found"; + throw std::invalid_argument(msg.str()); +} + +void +gr_flowgraph::validate() +{ + d_blocks = calc_used_blocks(); + + for (gr_basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) { + std::vector<int> used_ports; + int ninputs, noutputs; + + if (GR_FLOWGRAPH_DEBUG) + std::cout << "Validating block: " << (*p) << std::endl; + + used_ports = calc_used_ports(*p, true); // inputs + ninputs = used_ports.size(); + check_contiguity(*p, used_ports, true); // inputs + + used_ports = calc_used_ports(*p, false); // outputs + noutputs = used_ports.size(); + check_contiguity(*p, used_ports, false); // outputs + + if (!((*p)->check_topology(ninputs, noutputs))) { + std::stringstream msg; + msg << "check topology failed on " << (*p) + << " using ninputs=" << ninputs + << ", noutputs=" << noutputs; + throw std::runtime_error(msg.str()); + } + } +} + +void +gr_flowgraph::clear() +{ + // Boost shared pointers will deallocate as needed + d_blocks.clear(); + d_edges.clear(); +} + +void +gr_flowgraph::check_valid_port(gr_io_signature_sptr sig, int port) +{ + std::stringstream msg; + + if (port < 0) { + msg << "negative port number " << port << " is invalid"; + throw std::invalid_argument(msg.str()); + } + + int max = sig->max_streams(); + if (max != gr_io_signature::IO_INFINITE && port >= max) { + msg << "port number " << port << " exceeds max of "; + if (max == 0) + msg << "(none)"; + else + msg << max-1; + throw std::invalid_argument(msg.str()); + } +} + +void +gr_flowgraph::check_valid_port(const gr_msg_endpoint &e) +{ + if (GR_FLOWGRAPH_DEBUG) + std::cout << "check_valid_port( " << e.block() << ", " << e.port() << ")\n"; + + if(!e.block()->has_msg_port(e.port())) + throw std::invalid_argument("invalid msg port in connect() or disconnect()"); +} + +void +gr_flowgraph::check_dst_not_used(const gr_endpoint &dst) +{ + // A destination is in use if it is already on the edge list + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) + if (p->dst() == dst) { + std::stringstream msg; + msg << "destination already in use by edge " << (*p); + throw std::invalid_argument(msg.str()); + } +} + +void +gr_flowgraph::check_type_match(const gr_endpoint &src, const gr_endpoint &dst) +{ + int src_size = src.block()->output_signature()->sizeof_stream_item(src.port()); + int dst_size = dst.block()->input_signature()->sizeof_stream_item(dst.port()); + + if (src_size != dst_size) { + std::stringstream msg; + msg << "itemsize mismatch: " << src << " using " << src_size + << ", " << dst << " using " << dst_size; + throw std::invalid_argument(msg.str()); + } +} + +gr_basic_block_vector_t +gr_flowgraph::calc_used_blocks() +{ + gr_basic_block_vector_t tmp; + + // make sure free standing message blocks are included + for (gr_msg_edge_viter_t p = d_msg_edges.begin(); p != d_msg_edges.end(); p++) { +// for now only blocks receiving messages get a thread context - uncomment to allow senders to also obtain one +// tmp.push_back(p->src().block()); + tmp.push_back(p->dst().block()); + } + + // Collect all blocks in the edge list + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { + tmp.push_back(p->src().block()); + tmp.push_back(p->dst().block()); + } + + return unique_vector<gr_basic_block_sptr>(tmp); +} + +std::vector<int> +gr_flowgraph::calc_used_ports(gr_basic_block_sptr block, bool check_inputs) +{ + std::vector<int> tmp; + + // Collect all seen ports + gr_edge_vector_t edges = calc_connections(block, check_inputs); + for (gr_edge_viter_t p = edges.begin(); p != edges.end(); p++) { + if (check_inputs == true) + tmp.push_back(p->dst().port()); + else + tmp.push_back(p->src().port()); + } + + return unique_vector<int>(tmp); +} + +gr_edge_vector_t +gr_flowgraph::calc_connections(gr_basic_block_sptr block, bool check_inputs) +{ + gr_edge_vector_t result; + + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { + if (check_inputs) { + if (p->dst().block() == block) + result.push_back(*p); + } + else { + if (p->src().block() == block) + result.push_back(*p); + } + } + + return result; // assumes no duplicates +} + +void +gr_flowgraph::check_contiguity(gr_basic_block_sptr block, + const std::vector<int> &used_ports, + bool check_inputs) +{ + std::stringstream msg; + + gr_io_signature_sptr sig = + check_inputs ? block->input_signature() : block->output_signature(); + + int nports = used_ports.size(); + int min_ports = sig->min_streams(); + int max_ports = sig->max_streams(); + + if (nports == 0 && min_ports == 0) + return; + + if (nports < min_ports) { + msg << block << ": insufficient connected " + << (check_inputs ? "input ports " : "output ports ") + << "(" << min_ports << " needed, " << nports << " connected)"; + throw std::runtime_error(msg.str()); + } + + if (nports > max_ports && max_ports != gr_io_signature::IO_INFINITE) { + msg << block << ": too many connected " + << (check_inputs ? "input ports " : "output ports ") + << "(" << max_ports << " allowed, " << nports << " connected)"; + throw std::runtime_error(msg.str()); + } + + if (used_ports[nports-1]+1 != nports) { + for (int i = 0; i < nports; i++) { + if (used_ports[i] != i) { + msg << block << ": missing connection " + << (check_inputs ? "to input port " : "from output port ") + << i; + throw std::runtime_error(msg.str()); + } + } + } +} + +gr_basic_block_vector_t +gr_flowgraph::calc_downstream_blocks(gr_basic_block_sptr block, int port) +{ + gr_basic_block_vector_t tmp; + + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) + if (p->src() == gr_endpoint(block, port)) + tmp.push_back(p->dst().block()); + + return unique_vector<gr_basic_block_sptr>(tmp); +} + +gr_basic_block_vector_t +gr_flowgraph::calc_downstream_blocks(gr_basic_block_sptr block) +{ + gr_basic_block_vector_t tmp; + + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) + if (p->src().block() == block) + tmp.push_back(p->dst().block()); + + return unique_vector<gr_basic_block_sptr>(tmp); +} + +gr_edge_vector_t +gr_flowgraph::calc_upstream_edges(gr_basic_block_sptr block) +{ + gr_edge_vector_t result; + + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) + if (p->dst().block() == block) + result.push_back(*p); + + return result; // Assume no duplicates +} + +bool +gr_flowgraph::has_block_p(gr_basic_block_sptr block) +{ + gr_basic_block_viter_t result; + result = std::find(d_blocks.begin(), d_blocks.end(), block); + return (result != d_blocks.end()); +} + +gr_edge +gr_flowgraph::calc_upstream_edge(gr_basic_block_sptr block, int port) +{ + gr_edge result; + + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { + if (p->dst() == gr_endpoint(block, port)) { + result = (*p); + break; + } + } + + return result; +} + +std::vector<gr_basic_block_vector_t> +gr_flowgraph::partition() +{ + std::vector<gr_basic_block_vector_t> result; + gr_basic_block_vector_t blocks = calc_used_blocks(); + gr_basic_block_vector_t graph; + + while (blocks.size() > 0) { + graph = calc_reachable_blocks(blocks[0], blocks); + assert(graph.size()); + result.push_back(topological_sort(graph)); + + for (gr_basic_block_viter_t p = graph.begin(); p != graph.end(); p++) + blocks.erase(find(blocks.begin(), blocks.end(), *p)); + } + + return result; +} + +gr_basic_block_vector_t +gr_flowgraph::calc_reachable_blocks(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks) +{ + gr_basic_block_vector_t result; + + // Mark all blocks as unvisited + for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) + (*p)->set_color(gr_basic_block::WHITE); + + // Recursively mark all reachable blocks + reachable_dfs_visit(block, blocks); + + // Collect all the blocks that have been visited + for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) + if ((*p)->color() == gr_basic_block::BLACK) + result.push_back(*p); + + return result; +} + +// Recursively mark all reachable blocks from given block and block list +void +gr_flowgraph::reachable_dfs_visit(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks) +{ + // Mark the current one as visited + block->set_color(gr_basic_block::BLACK); + + // Recurse into adjacent vertices + gr_basic_block_vector_t adjacent = calc_adjacent_blocks(block, blocks); + + for (gr_basic_block_viter_t p = adjacent.begin(); p != adjacent.end(); p++) + if ((*p)->color() == gr_basic_block::WHITE) + reachable_dfs_visit(*p, blocks); +} + +// Return a list of block adjacent to a given block along any edge +gr_basic_block_vector_t +gr_flowgraph::calc_adjacent_blocks(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks) +{ + gr_basic_block_vector_t tmp; + + // Find any blocks that are inputs or outputs + for (gr_edge_viter_t p = d_edges.begin(); p != d_edges.end(); p++) { + if (p->src().block() == block) + tmp.push_back(p->dst().block()); + if (p->dst().block() == block) + tmp.push_back(p->src().block()); + } + + return unique_vector<gr_basic_block_sptr>(tmp); +} + +gr_basic_block_vector_t +gr_flowgraph::topological_sort(gr_basic_block_vector_t &blocks) +{ + gr_basic_block_vector_t tmp; + gr_basic_block_vector_t result; + tmp = sort_sources_first(blocks); + + // Start 'em all white + for (gr_basic_block_viter_t p = tmp.begin(); p != tmp.end(); p++) + (*p)->set_color(gr_basic_block::WHITE); + + for (gr_basic_block_viter_t p = tmp.begin(); p != tmp.end(); p++) { + if ((*p)->color() == gr_basic_block::WHITE) + topological_dfs_visit(*p, result); + } + + reverse(result.begin(), result.end()); + return result; +} + +gr_basic_block_vector_t +gr_flowgraph::sort_sources_first(gr_basic_block_vector_t &blocks) +{ + gr_basic_block_vector_t sources, nonsources, result; + + for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { + if (source_p(*p)) + sources.push_back(*p); + else + nonsources.push_back(*p); + } + + for (gr_basic_block_viter_t p = sources.begin(); p != sources.end(); p++) + result.push_back(*p); + + for (gr_basic_block_viter_t p = nonsources.begin(); p != nonsources.end(); p++) + result.push_back(*p); + + return result; +} + +bool +gr_flowgraph::source_p(gr_basic_block_sptr block) +{ + return (calc_upstream_edges(block).size() == 0); +} + +void +gr_flowgraph::topological_dfs_visit(gr_basic_block_sptr block, gr_basic_block_vector_t &output) +{ + block->set_color(gr_basic_block::GREY); + gr_basic_block_vector_t blocks(calc_downstream_blocks(block)); + + for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { + switch ((*p)->color()) { + case gr_basic_block::WHITE: + topological_dfs_visit(*p, output); + break; + + case gr_basic_block::GREY: + throw std::runtime_error("flow graph has loops!"); + + case gr_basic_block::BLACK: + continue; + + default: + throw std::runtime_error("invalid color on block!"); + } + } + + block->set_color(gr_basic_block::BLACK); + output.push_back(block); +} + +void gr_flowgraph::connect(const gr_msg_endpoint &src, const gr_msg_endpoint &dst){ + check_valid_port(src); + check_valid_port(dst); + for (gr_msg_edge_viter_t p = d_msg_edges.begin(); p != d_msg_edges.end(); p++) { + if(p->src() == src && p->dst() == dst){ + throw std::runtime_error("connect called on already connected edge!"); + } + } + d_msg_edges.push_back(gr_msg_edge(src,dst)); +} + +void gr_flowgraph::disconnect(const gr_msg_endpoint &src, const gr_msg_endpoint &dst){ + check_valid_port(src); + check_valid_port(dst); + for (gr_msg_edge_viter_t p = d_msg_edges.begin(); p != d_msg_edges.end(); p++) { + if(p->src() == src && p->dst() == dst){ + d_msg_edges.erase(p); + return; + } + } + throw std::runtime_error("disconnect called on non-connected edge!"); +} + + diff --git a/gnuradio-core/src/lib/runtime/gr_flowgraph.h b/gnuradio-core/src/lib/runtime/gr_flowgraph.h new file mode 100644 index 000000000..bef70f626 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_flowgraph.h @@ -0,0 +1,251 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,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_FLOWGRAPH_H +#define INCLUDED_GR_FLOWGRAPH_H + +#include <gr_core_api.h> +#include <gr_basic_block.h> +#include <iostream> + +/*! + * \brief Class representing a specific input or output graph endpoint + * \ingroup internal + */ +class GR_CORE_API gr_endpoint +{ +private: + gr_basic_block_sptr d_basic_block; + int d_port; + +public: + gr_endpoint() : d_basic_block(), d_port(0) { } + gr_endpoint(gr_basic_block_sptr block, int port) { d_basic_block = block; d_port = port; } + gr_basic_block_sptr block() const { return d_basic_block; } + int port() const { return d_port; } + + bool operator==(const gr_endpoint &other) const; +}; + +inline bool gr_endpoint::operator==(const gr_endpoint &other) const +{ + return (d_basic_block == other.d_basic_block && + d_port == other.d_port); +} + +class GR_CORE_API gr_msg_endpoint +{ +private: + gr_basic_block_sptr d_basic_block; + pmt::pmt_t d_port; + bool d_is_hier; +public: + gr_msg_endpoint() : d_basic_block(), d_port(pmt::PMT_NIL) { } + gr_msg_endpoint(gr_basic_block_sptr block, pmt::pmt_t port, bool is_hier=false){ d_basic_block = block; d_port = port; d_is_hier = is_hier;} + gr_basic_block_sptr block() const { return d_basic_block; } + pmt::pmt_t port() const { return d_port; } + bool is_hier() const { return d_is_hier; } + void set_hier(bool h) { d_is_hier = h; } + + bool operator==(const gr_msg_endpoint &other) const; + +}; + +inline bool gr_msg_endpoint::operator==(const gr_msg_endpoint &other) const +{ + return (d_basic_block == other.d_basic_block && + pmt::pmt_equal(d_port, other.d_port)); +} + + +// Hold vectors of gr_endpoint objects +typedef std::vector<gr_endpoint> gr_endpoint_vector_t; +typedef std::vector<gr_endpoint>::iterator gr_endpoint_viter_t; + +/*! + *\brief Class representing a connection between to graph endpoints + * + */ +class GR_CORE_API gr_edge +{ +public: + gr_edge() : d_src(), d_dst() { }; + gr_edge(const gr_endpoint &src, const gr_endpoint &dst) : d_src(src), d_dst(dst) { } + ~gr_edge(); + + const gr_endpoint &src() const { return d_src; } + const gr_endpoint &dst() const { return d_dst; } + +private: + gr_endpoint d_src; + gr_endpoint d_dst; +}; + + +// Hold vectors of gr_edge objects +typedef std::vector<gr_edge> gr_edge_vector_t; +typedef std::vector<gr_edge>::iterator gr_edge_viter_t; + + +/*! + *\brief Class representing a msg connection between to graph msg endpoints + * + */ +class GR_CORE_API gr_msg_edge +{ +public: + gr_msg_edge() : d_src(), d_dst() { }; + gr_msg_edge(const gr_msg_endpoint &src, const gr_msg_endpoint &dst) : d_src(src), d_dst(dst) { } + ~gr_msg_edge() {} + + const gr_msg_endpoint &src() const { return d_src; } + const gr_msg_endpoint &dst() const { return d_dst; } + +private: + gr_msg_endpoint d_src; + gr_msg_endpoint d_dst; +}; + +// Hold vectors of gr_edge objects +typedef std::vector<gr_msg_edge> gr_msg_edge_vector_t; +typedef std::vector<gr_msg_edge>::iterator gr_msg_edge_viter_t; + +// Create a shared pointer to a heap allocated flowgraph +// (types defined in gr_runtime_types.h) +GR_CORE_API gr_flowgraph_sptr gr_make_flowgraph(); + +/*! + * \brief Class representing a directed, acyclic graph of basic blocks + * \ingroup internal + */ +class GR_CORE_API gr_flowgraph +{ +public: + friend GR_CORE_API gr_flowgraph_sptr gr_make_flowgraph(); + + // Destruct an arbitrary flowgraph + ~gr_flowgraph(); + + // Connect two endpoints + void connect(const gr_endpoint &src, const gr_endpoint &dst); + + // Disconnect two endpoints + void disconnect(const gr_endpoint &src, const gr_endpoint &dst); + + // Connect an output port to an input port (convenience) + void connect(gr_basic_block_sptr src_block, int src_port, + gr_basic_block_sptr dst_block, int dst_port); + + // Disconnect an input port from an output port (convenience) + void disconnect(gr_basic_block_sptr src_block, int src_port, + gr_basic_block_sptr dst_block, int dst_port); + + // Connect two msg endpoints + void connect(const gr_msg_endpoint &src, const gr_msg_endpoint &dst); + + // Disconnect two msg endpoints + void disconnect(const gr_msg_endpoint &src, const gr_msg_endpoint &dst); + + // Validate connectivity, raise exception if invalid + void validate(); + + // Clear existing flowgraph + void clear(); + + // Return vector of edges + const gr_edge_vector_t &edges() const { return d_edges; } + + // Return vector of msg edges + const gr_msg_edge_vector_t &msg_edges() const { return d_msg_edges; } + + // Return vector of connected blocks + gr_basic_block_vector_t calc_used_blocks(); + + // Return toplogically sorted vector of blocks. All the sources come first. + gr_basic_block_vector_t topological_sort(gr_basic_block_vector_t &blocks); + + // Return vector of vectors of disjointly connected blocks, topologically + // sorted. + std::vector<gr_basic_block_vector_t> partition(); + +protected: + gr_basic_block_vector_t d_blocks; + gr_edge_vector_t d_edges; + gr_msg_edge_vector_t d_msg_edges; + + gr_flowgraph(); + std::vector<int> calc_used_ports(gr_basic_block_sptr block, bool check_inputs); + gr_basic_block_vector_t calc_downstream_blocks(gr_basic_block_sptr block, int port); + gr_edge_vector_t calc_upstream_edges(gr_basic_block_sptr block); + bool has_block_p(gr_basic_block_sptr block); + gr_edge calc_upstream_edge(gr_basic_block_sptr block, int port); + +private: + + void check_valid_port(gr_io_signature_sptr sig, int port); + void check_valid_port(const gr_msg_endpoint &e); + void check_dst_not_used(const gr_endpoint &dst); + void check_type_match(const gr_endpoint &src, const gr_endpoint &dst); + gr_edge_vector_t calc_connections(gr_basic_block_sptr block, bool check_inputs); // false=use outputs + void check_contiguity(gr_basic_block_sptr block, const std::vector<int> &used_ports, bool check_inputs); + + gr_basic_block_vector_t calc_downstream_blocks(gr_basic_block_sptr block); + gr_basic_block_vector_t calc_reachable_blocks(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks); + void reachable_dfs_visit(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks); + gr_basic_block_vector_t calc_adjacent_blocks(gr_basic_block_sptr block, gr_basic_block_vector_t &blocks); + gr_basic_block_vector_t sort_sources_first(gr_basic_block_vector_t &blocks); + bool source_p(gr_basic_block_sptr block); + void topological_dfs_visit(gr_basic_block_sptr block, gr_basic_block_vector_t &output); +}; + +// Convenience functions +inline +void gr_flowgraph::connect(gr_basic_block_sptr src_block, int src_port, + gr_basic_block_sptr dst_block, int dst_port) +{ + connect(gr_endpoint(src_block, src_port), + gr_endpoint(dst_block, dst_port)); +} + +inline +void gr_flowgraph::disconnect(gr_basic_block_sptr src_block, int src_port, + gr_basic_block_sptr dst_block, int dst_port) +{ + disconnect(gr_endpoint(src_block, src_port), + gr_endpoint(dst_block, dst_port)); +} + +inline std::ostream& +operator <<(std::ostream &os, const gr_endpoint endp) +{ + os << endp.block() << ":" << endp.port(); + return os; +} + +inline std::ostream& +operator <<(std::ostream &os, const gr_edge edge) +{ + os << edge.src() << "->" << edge.dst(); + return os; +} + +#endif /* INCLUDED_GR_FLOWGRAPH_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.cc b/gnuradio-core/src/lib/runtime/gr_hier_block2.cc new file mode 100644 index 000000000..04eb60fc6 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.cc @@ -0,0 +1,77 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2007,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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_hier_block2.h> +#include <boost/detail/atomic_count.hpp> + +static boost::detail::atomic_count unique_id_pool(0); + + +gr_hier_block2::gr_hier_block2(void) +{ + //NOP +} + +gr_hier_block2::gr_hier_block2( + const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature +): + gras::HierBlock(name), + _unique_id(++unique_id_pool), + _name(name) +{ + this->set_input_signature(input_signature); + this->set_output_signature(output_signature); +} + +gr_hier_block2_sptr gr_make_hier_block2( + const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature +){ + return gr_hier_block2_sptr(new gr_hier_block2(name, input_signature, output_signature)); +} + +gr_io_signature_sptr gr_hier_block2::input_signature(void) const +{ + return _in_sig; +} + +gr_io_signature_sptr gr_hier_block2::output_signature(void) const +{ + return _out_sig; +} + +void gr_hier_block2::set_input_signature(gr_io_signature_sptr sig) +{ + _in_sig = sig; +} + +void gr_hier_block2::set_output_signature(gr_io_signature_sptr sig) +{ + _out_sig = sig; +} diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.h b/gnuradio-core/src/lib/runtime/gr_hier_block2.h new file mode 100644 index 000000000..d393c42cb --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.h @@ -0,0 +1,71 @@ +/* + * Copyright 2012-2013 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_GNURADIO_GR_HIER_BLOCK2_H +#define INCLUDED_GNURADIO_GR_HIER_BLOCK2_H + +#include <gr_core_api.h> +#include <gras/hier_block.hpp> +#include <gr_io_signature.h> + +struct GR_CORE_API gr_hier_block2 : gras::HierBlock +{ + + gr_hier_block2(void); + + gr_hier_block2( + const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature + ); + + long unique_id(void) const{return _unique_id;} + std::string name(void) const{return _name;} + long _unique_id; + std::string _name; + + const gr_hier_block2 &self(void) const + { + return *this; + } + + gr_io_signature_sptr input_signature(void) const; + gr_io_signature_sptr output_signature(void) const; + + void set_input_signature(gr_io_signature_sptr sig); + void set_output_signature(gr_io_signature_sptr sig); + + inline void lock(void){} + + inline void unlock(void){this->commit();} + + gr_io_signature_sptr _in_sig, _out_sig; +}; + +typedef boost::shared_ptr<gr_hier_block2> gr_hier_block2_sptr; + +GR_CORE_API gr_hier_block2_sptr gr_make_hier_block2( + const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature +); + +#endif /*INCLUDED_GNURADIO_GR_HIER_BLOCK2_H*/ diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2.i b/gnuradio-core/src/lib/runtime/gr_hier_block2.i new file mode 100644 index 000000000..a857394ca --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2.i @@ -0,0 +1,88 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2006,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 <gr_basic_block.i> + +class gr_hier_block2; +typedef boost::shared_ptr<gr_hier_block2> gr_hier_block2_sptr; +%template(gr_hier_block2_sptr) boost::shared_ptr<gr_hier_block2>; + +// Hack to have a Python shim implementation of gr.hier_block2 +// that instantiates one of these and passes through calls +%rename(hier_block2_swig) gr_make_hier_block2; +gr_hier_block2_sptr gr_make_hier_block2(const std::string name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature) + throw (std::runtime_error); + +// Rename connect and disconnect so that we can more easily build a +// better interface in scripting land. +%rename(primitive_connect) gr_hier_block2::connect; +%rename(primitive_disconnect) gr_hier_block2::disconnect; +%rename(primitive_msg_connect) gr_hier_block2::msg_connect; +%rename(primitive_msg_disconnect) gr_hier_block2::msg_disconnect; +%rename(primitive_message_port_register_hier_in) gr_hier_block2::message_port_register_hier_in; +%rename(primitive_message_port_register_hier_out) gr_hier_block2::message_port_register_hier_out; + +class gr_hier_block2 : public gr_basic_block +{ +private: + gr_hier_block2(const std::string name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); + +public: + ~gr_hier_block2 (); + + void connect(gr_basic_block_sptr block) + throw (std::invalid_argument); + void connect(gr_basic_block_sptr src, int src_port, + gr_basic_block_sptr dst, int dst_port) + throw (std::invalid_argument); + void msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport, + gr_basic_block_sptr dst, pmt::pmt_t dstport) + throw (std::runtime_error); + void msg_connect(gr_basic_block_sptr src, std::string srcport, + gr_basic_block_sptr dst, std::string dstport) + throw (std::runtime_error); + void msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport, + gr_basic_block_sptr dst, pmt::pmt_t dstport) + throw (std::runtime_error); + void msg_disconnect(gr_basic_block_sptr src, std::string srcport, + gr_basic_block_sptr dst, std::string dstport) + throw (std::runtime_error); + + void disconnect(gr_basic_block_sptr block) + throw (std::invalid_argument); + void disconnect(gr_basic_block_sptr src, int src_port, + gr_basic_block_sptr dst, int dst_port) + throw (std::invalid_argument); + void disconnect_all(); + void lock(); + void unlock(); + + void message_port_register_hier_in(pmt::pmt_t port_id); + void message_port_register_hier_out(pmt::pmt_t port_id); + + + gr_hier_block2_sptr to_hier_block2(); // Needed for Python type coercion +}; diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc new file mode 100644 index 000000000..add6da024 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.cc @@ -0,0 +1,615 @@ +/* + * Copyright 2006,2007,2009 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_hier_block2_detail.h> +#include <gr_io_signature.h> +#include <stdexcept> +#include <sstream> +#include <boost/format.hpp> + +#define GR_HIER_BLOCK2_DETAIL_DEBUG 0 + +gr_hier_block2_detail::gr_hier_block2_detail(gr_hier_block2 *owner) : + d_owner(owner), + d_parent_detail(0), + d_fg(gr_make_flowgraph()) +{ + int min_inputs = owner->input_signature()->min_streams(); + int max_inputs = owner->input_signature()->max_streams(); + int min_outputs = owner->output_signature()->min_streams(); + int max_outputs = owner->output_signature()->max_streams(); + + if (max_inputs == gr_io_signature::IO_INFINITE || + max_outputs == gr_io_signature::IO_INFINITE || + (min_inputs != max_inputs) ||(min_outputs != max_outputs) ) { + std::stringstream msg; + msg << "Hierarchical blocks do not yet support arbitrary or" + << " variable numbers of inputs or outputs (" << d_owner->name() << ")"; + throw std::runtime_error(msg.str()); + } + + d_inputs = std::vector<gr_endpoint_vector_t>(max_inputs); + d_outputs = gr_endpoint_vector_t(max_outputs); +} + + +gr_hier_block2_detail::~gr_hier_block2_detail() +{ + d_owner = 0; // Don't use delete, we didn't allocate +} + +void +gr_hier_block2_detail::connect(gr_basic_block_sptr block) +{ + std::stringstream msg; + + // Check if duplicate + if (std::find(d_blocks.begin(), d_blocks.end(), block) != d_blocks.end()) { + msg << "Block " << block << " already connected."; + throw std::invalid_argument(msg.str()); + } + + // Check if has inputs or outputs + if (block->input_signature()->max_streams() != 0 || + block->output_signature()->max_streams() != 0) { + msg << "Block " << block << " must not have any input or output ports"; + throw std::invalid_argument(msg.str()); + } + + gr_hier_block2_sptr hblock(cast_to_hier_block2_sptr(block)); + + if (hblock && hblock.get() != d_owner) { + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "connect: block is hierarchical, setting parent to " << this << std::endl; + hblock->d_detail->d_parent_detail = this; + } + + d_blocks.push_back(block); +} + +void +gr_hier_block2_detail::connect(gr_basic_block_sptr src, int src_port, + gr_basic_block_sptr dst, int dst_port) +{ + std::stringstream msg; + + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "connecting: " << gr_endpoint(src, src_port) + << " -> " << gr_endpoint(dst, dst_port) << std::endl; + + if (src.get() == dst.get()) + throw std::invalid_argument("connect: src and destination blocks cannot be the same"); + + gr_hier_block2_sptr src_block(cast_to_hier_block2_sptr(src)); + gr_hier_block2_sptr dst_block(cast_to_hier_block2_sptr(dst)); + + if (src_block && src.get() != d_owner) { + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "connect: src is hierarchical, setting parent to " << this << std::endl; + src_block->d_detail->d_parent_detail = this; + } + + if (dst_block && dst.get() != d_owner) { + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "connect: dst is hierarchical, setting parent to " << this << std::endl; + dst_block->d_detail->d_parent_detail = this; + } + + // Connections to block inputs or outputs + int max_port; + if (src.get() == d_owner) { + max_port = src->input_signature()->max_streams(); + if ((max_port != -1 && (src_port >= max_port)) || src_port < 0) { + msg << "source port " << src_port << " out of range for " << src; + throw std::invalid_argument(msg.str()); + } + + return connect_input(src_port, dst_port, dst); + } + + if (dst.get() == d_owner) { + max_port = dst->output_signature()->max_streams(); + if ((max_port != -1 && (dst_port >= max_port)) || dst_port < 0) { + msg << "destination port " << dst_port << " out of range for " << dst; + throw std::invalid_argument(msg.str()); + } + + return connect_output(dst_port, src_port, src); + } + + // Internal connections + d_fg->connect(src, src_port, dst, dst_port); + + // TODO: connects to NC +} + +void +gr_hier_block2_detail::msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport, + gr_basic_block_sptr dst, pmt::pmt_t dstport) +{ + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "connecting message port..." << std::endl; + + // register the subscription +// this is done later... +// src->message_port_sub(srcport, pmt::pmt_cons(dst->alias_pmt(), dstport)); + + // add block uniquely to list to internal blocks + if (std::find(d_blocks.begin(), d_blocks.end(), dst) == d_blocks.end()){ + d_blocks.push_back(src); + d_blocks.push_back(dst); + } + + bool hier_out = (d_owner == src.get()) && src->message_port_is_hier_out(srcport);; + bool hier_in = (d_owner == dst.get()) && dst->message_port_is_hier_in(dstport); + + gr_hier_block2_sptr src_block(cast_to_hier_block2_sptr(src)); + gr_hier_block2_sptr dst_block(cast_to_hier_block2_sptr(dst)); + + if (src_block && src.get() != d_owner) { + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "connect: src is hierarchical, setting parent to " << this << std::endl; + src_block->d_detail->d_parent_detail = this; + } + + if (dst_block && dst.get() != d_owner) { + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "connect: dst is hierarchical, setting parent to " << this << std::endl; + dst_block->d_detail->d_parent_detail = this; + } + + // add edge for this message connection + if(GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << boost::format("connect( (%s, %s, %d), (%s, %s, %d) )\n") % + src % srcport % hier_out % + dst % dstport % hier_in; + d_fg->connect( gr_msg_endpoint(src, srcport, hier_out), gr_msg_endpoint(dst, dstport, hier_in)); +} + +void +gr_hier_block2_detail::msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport, + gr_basic_block_sptr dst, pmt::pmt_t dstport) +{ + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "disconnecting message port..." << std::endl; + + // unregister the subscription - if already subscribed + src->message_port_unsub(srcport, pmt::pmt_cons(dst->alias_pmt(), dstport)); + + // remove edge for this message connection + bool hier_out = (d_owner == src.get()) && src->message_port_is_hier_out(srcport);; + bool hier_in = (d_owner == dst.get()) && dst->message_port_is_hier_in(dstport); + d_fg->disconnect( gr_msg_endpoint(src, srcport, hier_out), gr_msg_endpoint(dst, dstport, hier_in)); +} + +void +gr_hier_block2_detail::disconnect(gr_basic_block_sptr block) +{ + // Check on singleton list + for (gr_basic_block_viter_t p = d_blocks.begin(); p != d_blocks.end(); p++) { + if (*p == block) { + d_blocks.erase(p); + + gr_hier_block2_sptr hblock(cast_to_hier_block2_sptr(block)); + if (block && block.get() != d_owner) { + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "disconnect: block is hierarchical, clearing parent" << std::endl; + hblock->d_detail->d_parent_detail = 0; + } + + return; + } + } + + // Otherwise find all edges containing block + gr_edge_vector_t edges, tmp = d_fg->edges(); + gr_edge_vector_t::iterator p; + for (p = tmp.begin(); p != tmp.end(); p++) { + if ((*p).src().block() == block || (*p).dst().block() == block) { + edges.push_back(*p); + + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "disconnect: block found in edge " << (*p) << std::endl; + } + } + + if (edges.size() == 0) { + std::stringstream msg; + msg << "cannot disconnect block " << block << ", not found"; + throw std::invalid_argument(msg.str()); + } + + for (p = edges.begin(); p != edges.end(); p++) { + disconnect((*p).src().block(), (*p).src().port(), + (*p).dst().block(), (*p).dst().port()); + } +} + +void +gr_hier_block2_detail::disconnect(gr_basic_block_sptr src, int src_port, + gr_basic_block_sptr dst, int dst_port) +{ + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "disconnecting: " << gr_endpoint(src, src_port) + << " -> " << gr_endpoint(dst, dst_port) << std::endl; + + if (src.get() == dst.get()) + throw std::invalid_argument("disconnect: source and destination blocks cannot be the same"); + + gr_hier_block2_sptr src_block(cast_to_hier_block2_sptr(src)); + gr_hier_block2_sptr dst_block(cast_to_hier_block2_sptr(dst)); + + if (src_block && src.get() != d_owner) { + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "disconnect: src is hierarchical, clearing parent" << std::endl; + src_block->d_detail->d_parent_detail = 0; + } + + if (dst_block && dst.get() != d_owner) { + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "disconnect: dst is hierarchical, clearing parent" << std::endl; + dst_block->d_detail->d_parent_detail = 0; + } + + if (src.get() == d_owner) + return disconnect_input(src_port, dst_port, dst); + + if (dst.get() == d_owner) + return disconnect_output(dst_port, src_port, src); + + // Internal connections + d_fg->disconnect(src, src_port, dst, dst_port); +} + +void +gr_hier_block2_detail::connect_input(int my_port, int port, gr_basic_block_sptr block) +{ + std::stringstream msg; + + if (my_port < 0 || my_port >= (signed)d_inputs.size()) { + msg << "input port " << my_port << " out of range for " << block; + throw std::invalid_argument(msg.str()); + } + + gr_endpoint_vector_t &endps = d_inputs[my_port]; + gr_endpoint endp(block, port); + + gr_endpoint_viter_t p = std::find(endps.begin(), endps.end(), endp); + if (p != endps.end()) { + msg << "external input port " << my_port << " already wired to " << endp; + throw std::invalid_argument(msg.str()); + } + + endps.push_back(endp); +} + +void +gr_hier_block2_detail::connect_output(int my_port, int port, gr_basic_block_sptr block) +{ + std::stringstream msg; + + if (my_port < 0 || my_port >= (signed)d_outputs.size()) { + msg << "output port " << my_port << " out of range for " << block; + throw std::invalid_argument(msg.str()); + } + + if (d_outputs[my_port].block()) { + msg << "external output port " << my_port << " already connected from " + << d_outputs[my_port]; + throw std::invalid_argument(msg.str()); + } + + d_outputs[my_port] = gr_endpoint(block, port); +} + +void +gr_hier_block2_detail::disconnect_input(int my_port, int port, gr_basic_block_sptr block) +{ + std::stringstream msg; + + if (my_port < 0 || my_port >= (signed)d_inputs.size()) { + msg << "input port number " << my_port << " out of range for " << block; + throw std::invalid_argument(msg.str()); + } + + gr_endpoint_vector_t &endps = d_inputs[my_port]; + gr_endpoint endp(block, port); + + gr_endpoint_viter_t p = std::find(endps.begin(), endps.end(), endp); + if (p == endps.end()) { + msg << "external input port " << my_port << " not connected to " << endp; + throw std::invalid_argument(msg.str()); + } + + endps.erase(p); +} + +void +gr_hier_block2_detail::disconnect_output(int my_port, int port, gr_basic_block_sptr block) +{ + std::stringstream msg; + + if (my_port < 0 || my_port >= (signed)d_outputs.size()) { + msg << "output port number " << my_port << " out of range for " << block; + throw std::invalid_argument(msg.str()); + } + + if (d_outputs[my_port].block() != block) { + msg << "block " << block << " not assigned to output " + << my_port << ", can't disconnect"; + throw std::invalid_argument(msg.str()); + } + + d_outputs[my_port] = gr_endpoint(); +} + +gr_endpoint_vector_t +gr_hier_block2_detail::resolve_port(int port, bool is_input) +{ + std::stringstream msg; + + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "Resolving port " << port << " as an " + << (is_input ? "input" : "output") + << " of " << d_owner->name() << std::endl; + + gr_endpoint_vector_t result; + + if (is_input) { + if (port < 0 || port >= (signed)d_inputs.size()) { + msg << "resolve_port: hierarchical block '" << d_owner->name() + << "': input " << port << " is out of range"; + throw std::runtime_error(msg.str()); + } + + if (d_inputs[port].empty()) { + msg << "resolve_port: hierarchical block '" << d_owner->name() + << "': input " << port << " is not connected internally"; + throw std::runtime_error(msg.str()); + } + + gr_endpoint_vector_t &endps = d_inputs[port]; + gr_endpoint_viter_t p; + for (p = endps.begin(); p != endps.end(); p++) { + gr_endpoint_vector_t tmp = resolve_endpoint(*p, true); + std::copy(tmp.begin(), tmp.end(), back_inserter(result)); + } + } + else { + if (port < 0 || port >= (signed)d_outputs.size()) { + msg << "resolve_port: hierarchical block '" << d_owner->name() + << "': output " << port << " is out of range"; + throw std::runtime_error(msg.str()); + } + + if (d_outputs[port] == gr_endpoint()) { + msg << "resolve_port: hierarchical block '" << d_owner->name() + << "': output " << port << " is not connected internally"; + throw std::runtime_error(msg.str()); + } + + result = resolve_endpoint(d_outputs[port], false); + } + + if (result.empty()) { + msg << "resolve_port: hierarchical block '" << d_owner->name() + << "': unable to resolve " + << (is_input ? "input port " : "output port ") + << port; + throw std::runtime_error(msg.str()); + } + + return result; +} + +void +gr_hier_block2_detail::disconnect_all() +{ + d_fg->clear(); + d_blocks.clear(); + d_inputs.clear(); + d_outputs.clear(); +} + +gr_endpoint_vector_t +gr_hier_block2_detail::resolve_endpoint(const gr_endpoint &endp, bool is_input) const +{ + std::stringstream msg; + gr_endpoint_vector_t result; + + // Check if endpoint is a leaf node + if (cast_to_block_sptr(endp.block())) { + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "Block " << endp.block() << " is a leaf node, returning." << std::endl; + result.push_back(endp); + return result; + } + + // Check if endpoint is a hierarchical block + gr_hier_block2_sptr hier_block2(cast_to_hier_block2_sptr(endp.block())); + if (hier_block2) { + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "Resolving endpoint " << endp << " as an " + << (is_input ? "input" : "output") + << ", recursing" << std::endl; + return hier_block2->d_detail->resolve_port(endp.port(), is_input); + } + + msg << "unable to resolve" << (is_input ? " input " : " output ") + << "endpoint " << endp; + throw std::runtime_error(msg.str()); +} + +void +gr_hier_block2_detail::flatten_aux(gr_flat_flowgraph_sptr sfg) const +{ + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << " ** Flattening " << d_owner->name() << std::endl; + + // Add my edges to the flow graph, resolving references to actual endpoints + gr_edge_vector_t edges = d_fg->edges(); + gr_msg_edge_vector_t msg_edges = d_fg->msg_edges(); + gr_edge_viter_t p; + gr_msg_edge_viter_t q,u; + + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "Flattening stream connections: " << std::endl; + + for (p = edges.begin(); p != edges.end(); p++) { + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "Flattening edge " << (*p) << std::endl; + + gr_endpoint_vector_t src_endps = resolve_endpoint(p->src(), false); + gr_endpoint_vector_t dst_endps = resolve_endpoint(p->dst(), true); + + gr_endpoint_viter_t s, d; + for (s = src_endps.begin(); s != src_endps.end(); s++) { + for (d = dst_endps.begin(); d != dst_endps.end(); d++) { + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << (*s) << "->" << (*d) << std::endl; + sfg->connect(*s, *d); + } + } + } + + // loop through flattening hierarchical connections + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "Flattening msg connections: " << std::endl; + + + std::vector<std::pair<gr_msg_endpoint, bool> > resolved_endpoints; + for(q = msg_edges.begin(); q != msg_edges.end(); q++) { + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << boost::format(" flattening edge ( %s, %s, %d) -> ( %s, %s, %d)\n") % q->src().block() % q->src().port() % q->src().is_hier() % q->dst().block() % q->dst().port() % q->dst().is_hier(); + + bool normal_connection = true; + + // resolve existing connections to hier ports + if(q->dst().is_hier()){ + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << boost::format(" resolve hier output (%s, %s)") % q->dst().block() % q->dst().port() << std::endl; + sfg->replace_endpoint( q->dst(), q->src(), true ); + resolved_endpoints.push_back(std::pair<gr_msg_endpoint, bool>(q->dst(),true)); + normal_connection = false; + } + + if(q->src().is_hier()){ + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << boost::format(" resolve hier input (%s, %s)") % q->src().block() % q->src().port() << std::endl; + sfg->replace_endpoint( q->src(), q->dst(), false ); + resolved_endpoints.push_back(std::pair<gr_msg_endpoint, bool>(q->src(),false)); + normal_connection = false; + } + + // propogate non hier connections through + if(normal_connection){ + sfg->connect( q->src(), q->dst() ); + } + } + for(std::vector<std::pair<gr_msg_endpoint, bool> >::iterator it = resolved_endpoints.begin(); it != resolved_endpoints.end(); it++){ + sfg->clear_endpoint( (*it).first, (*it).second ); + } + +/* // connect primitive edges in the new fg + for(q = msg_edges.begin(); q != msg_edges.end(); q++) { + if( (!q->src().is_hier()) && (!q->dst().is_hier()) ){ + sfg->connect( q->src(), q->dst() ); + } else { + std::cout << "not connecting hier connection!" << std::endl; + } + }*/ + + // Construct unique list of blocks used either in edges, inputs, + // outputs, or by themselves. I still hate STL. + gr_basic_block_vector_t blocks; // unique list of used blocks + gr_basic_block_vector_t tmp = d_fg->calc_used_blocks(); + + // First add the list of singleton blocks + std::vector<gr_basic_block_sptr>::const_iterator b; // Because flatten_aux is const + for (b = d_blocks.begin(); b != d_blocks.end(); b++) + tmp.push_back(*b); + + // Now add the list of connected input blocks + std::stringstream msg; + for (unsigned int i = 0; i < d_inputs.size(); i++) { + if (d_inputs[i].size() == 0) { + msg << "In hierarchical block " << d_owner->name() << ", input " << i + << " is not connected internally"; + throw std::runtime_error(msg.str()); + } + + for (unsigned int j = 0; j < d_inputs[i].size(); j++) + tmp.push_back(d_inputs[i][j].block()); + } + + for (unsigned int i = 0; i < d_outputs.size(); i++) { + gr_basic_block_sptr blk = d_outputs[i].block(); + if (!blk) { + msg << "In hierarchical block " << d_owner->name() << ", output " << i + << " is not connected internally"; + throw std::runtime_error(msg.str()); + } + tmp.push_back(blk); + } + sort(tmp.begin(), tmp.end()); + + std::insert_iterator<gr_basic_block_vector_t> inserter(blocks, blocks.begin()); + unique_copy(tmp.begin(), tmp.end(), inserter); + + // Recurse hierarchical children + for (gr_basic_block_viter_t p = blocks.begin(); p != blocks.end(); p++) { + gr_hier_block2_sptr hier_block2(cast_to_hier_block2_sptr(*p)); + if (hier_block2 && (hier_block2.get() != d_owner)) { + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "flatten_aux: recursing into hierarchical block " << hier_block2 << std::endl; + hier_block2->d_detail->flatten_aux(sfg); + } + } +} + +void +gr_hier_block2_detail::lock() +{ + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "lock: entered in " << this << std::endl; + + if (d_parent_detail) + d_parent_detail->lock(); + else + d_owner->lock(); +} + +void +gr_hier_block2_detail::unlock() +{ + if (GR_HIER_BLOCK2_DETAIL_DEBUG) + std::cout << "unlock: entered in " << this << std::endl; + + if (d_parent_detail) + d_parent_detail->unlock(); + else + d_owner->unlock(); +} + diff --git a/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h new file mode 100644 index 000000000..b38dae301 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_hier_block2_detail.h @@ -0,0 +1,74 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2007,2009 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_HIER_BLOCK2_DETAIL_H +#define INCLUDED_GR_HIER_BLOCK2_DETAIL_H + +#include <gr_core_api.h> +#include <gr_hier_block2.h> +#include <gr_flat_flowgraph.h> +#include <boost/utility.hpp> + +/*! + * \ingroup internal + */ +class GR_CORE_API gr_hier_block2_detail : boost::noncopyable +{ +public: + gr_hier_block2_detail(gr_hier_block2 *owner); + ~gr_hier_block2_detail(); + + void connect(gr_basic_block_sptr block); + void connect(gr_basic_block_sptr src, int src_port, + gr_basic_block_sptr dst, int dst_port); + void msg_connect(gr_basic_block_sptr src, pmt::pmt_t srcport, + gr_basic_block_sptr dst, pmt::pmt_t dstport); + void msg_disconnect(gr_basic_block_sptr src, pmt::pmt_t srcport, + gr_basic_block_sptr dst, pmt::pmt_t dstport); + void disconnect(gr_basic_block_sptr block); + void disconnect(gr_basic_block_sptr, int src_port, + gr_basic_block_sptr, int dst_port); + void disconnect_all(); + void lock(); + void unlock(); + void flatten_aux(gr_flat_flowgraph_sptr sfg) const; + +private: + + // Private implementation data + gr_hier_block2 *d_owner; + gr_hier_block2_detail *d_parent_detail; + gr_flowgraph_sptr d_fg; + std::vector<gr_endpoint_vector_t> d_inputs; // Multiple internal endpoints per external input + gr_endpoint_vector_t d_outputs; // Single internal endpoint per external output + gr_basic_block_vector_t d_blocks; + + + void connect_input(int my_port, int port, gr_basic_block_sptr block); + void connect_output(int my_port, int port, gr_basic_block_sptr block); + void disconnect_input(int my_port, int port, gr_basic_block_sptr block); + void disconnect_output(int my_port, int port, gr_basic_block_sptr block); + + gr_endpoint_vector_t resolve_port(int port, bool is_input); + gr_endpoint_vector_t resolve_endpoint(const gr_endpoint &endp, bool is_input) const; +}; + +#endif /* INCLUDED_GR_HIER_BLOCK2_DETAIL_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_io_signature.cc b/gnuradio-core/src/lib/runtime/gr_io_signature.cc new file mode 100644 index 000000000..6ac9acd17 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_io_signature.cc @@ -0,0 +1,112 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_io_signature.h> +#include <stdexcept> +#include <iostream> + +gr_io_signature_sptr +gr_make_io_signaturev(int min_streams, int max_streams, + const std::vector<int> &sizeof_stream_items) +{ + return gr_io_signature_sptr (new gr_io_signature (min_streams, max_streams, + sizeof_stream_items)); +} + +gr_io_signature_sptr +gr_make_io_signature(int min_streams, int max_streams, + int sizeof_stream_item) +{ + std::vector<int> sizeof_items(1); + sizeof_items[0] = sizeof_stream_item; + return gr_make_io_signaturev(min_streams, max_streams, sizeof_items); +} + +gr_io_signature_sptr +gr_make_io_signature2(int min_streams, int max_streams, + int sizeof_stream_item1, + int sizeof_stream_item2) +{ + std::vector<int> sizeof_items(2); + sizeof_items[0] = sizeof_stream_item1; + sizeof_items[1] = sizeof_stream_item2; + return gr_make_io_signaturev(min_streams, max_streams, sizeof_items); +} + +gr_io_signature_sptr +gr_make_io_signature3(int min_streams, int max_streams, + int sizeof_stream_item1, + int sizeof_stream_item2, + int sizeof_stream_item3) +{ + std::vector<int> sizeof_items(3); + sizeof_items[0] = sizeof_stream_item1; + sizeof_items[1] = sizeof_stream_item2; + sizeof_items[2] = sizeof_stream_item3; + return gr_make_io_signaturev(min_streams, max_streams, sizeof_items); +} + +// ------------------------------------------------------------------------ + + +gr_io_signature::gr_io_signature (int min_streams, int max_streams, + const std::vector<int> &sizeof_stream_items) +{ + if (min_streams < 0 + || (max_streams != IO_INFINITE && max_streams < min_streams)) + throw std::invalid_argument ("gr_io_signature(1)"); + + if (sizeof_stream_items.size() < 1) + throw std::invalid_argument("gr_io_signature(2)"); + + for (size_t i = 0; i < sizeof_stream_items.size(); i++){ + if (max_streams != 0 && sizeof_stream_items[i] < 1) + throw std::invalid_argument("gr_io_signature(3)"); + } + + d_min_streams = min_streams; + d_max_streams = max_streams; + d_sizeof_stream_item = sizeof_stream_items; +} + +gr_io_signature::~gr_io_signature () +{ +} + +int +gr_io_signature::sizeof_stream_item (int _index) const +{ + if (_index < 0) + throw std::invalid_argument ("gr_io_signature::sizeof_stream_item"); + + size_t index = _index; + return d_sizeof_stream_item[std::min(index, d_sizeof_stream_item.size() - 1)]; +} + +std::vector<int> +gr_io_signature::sizeof_stream_items() const +{ + return d_sizeof_stream_item; +} diff --git a/gnuradio-core/src/lib/runtime/gr_io_signature.h b/gnuradio-core/src/lib/runtime/gr_io_signature.h new file mode 100644 index 000000000..fd1825797 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_io_signature.h @@ -0,0 +1,117 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_IO_SIGNATURE_H +#define INCLUDED_IO_SIGNATURE_H + +#include <gr_core_api.h> +#include <gr_runtime_types.h> + +/*! + * \brief Create an i/o signature + * + * \ingroup internal + * \param min_streams specify minimum number of streams (>= 0) + * \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite) + * \param sizeof_stream_item specify the size of the items in each stream + */ +GR_CORE_API gr_io_signature_sptr +gr_make_io_signature(int min_streams, int max_streams, + int sizeof_stream_item); + +/*! + * \brief Create an i/o signature + * + * \param min_streams specify minimum number of streams (>= 0) + * \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite) + * \param sizeof_stream_item1 specify the size of the items in the first stream + * \param sizeof_stream_item2 specify the size of the items in the second and subsequent streams + */ +GR_CORE_API gr_io_signature_sptr +gr_make_io_signature2(int min_streams, int max_streams, + int sizeof_stream_item1, + int sizeof_stream_item2 + ); + +/*! + * \brief Create an i/o signature + * + * \param min_streams specify minimum number of streams (>= 0) + * \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite) + * \param sizeof_stream_item1 specify the size of the items in the first stream + * \param sizeof_stream_item2 specify the size of the items in the second stream + * \param sizeof_stream_item3 specify the size of the items in the third and subsequent streams + */ +GR_CORE_API gr_io_signature_sptr +gr_make_io_signature3(int min_streams, int max_streams, + int sizeof_stream_item1, + int sizeof_stream_item2, + int sizeof_stream_item3 + ); + +/*! + * \brief Create an i/o signature + * + * \param min_streams specify minimum number of streams (>= 0) + * \param max_streams specify maximum number of streams (>= min_streams or -1 -> infinite) + * \param sizeof_stream_items specify the size of the items in the streams + * + * If there are more streams than there are entries in sizeof_stream_items, the + * value of the last entry in sizeof_stream_items is used for the missing values. + * sizeof_stream_items must contain at least 1 entry. + */ +GR_CORE_API gr_io_signature_sptr +gr_make_io_signaturev(int min_streams, int max_streams, + const std::vector<int> &sizeof_stream_items); + + +/*! + * \brief i/o signature for input and output ports. + * \brief misc + */ +class GR_CORE_API gr_io_signature { + int d_min_streams; + int d_max_streams; + std::vector<int> d_sizeof_stream_item; + + gr_io_signature(int min_streams, int max_streams, + const std::vector<int> &sizeof_stream_items); + + friend GR_CORE_API gr_io_signature_sptr + gr_make_io_signaturev(int min_streams, + int max_streams, + const std::vector<int> &sizeof_stream_items); + + public: + + static const int IO_INFINITE = -1; + + ~gr_io_signature (); + + int min_streams () const { return d_min_streams; } + int max_streams () const { return d_max_streams; } + int sizeof_stream_item (int index) const; + std::vector<int> sizeof_stream_items() const; +}; + + +#endif /* INCLUDED_IO_SIGNATURE_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_io_signature.i b/gnuradio-core/src/lib/runtime/gr_io_signature.i new file mode 100644 index 000000000..fe1707e41 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_io_signature.i @@ -0,0 +1,73 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2005,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. + */ + +class gr_io_signature; +typedef boost::shared_ptr<gr_io_signature> gr_io_signature_sptr; +%template(gr_io_signature_sptr) boost::shared_ptr<gr_io_signature>; + +%rename(io_signature) gr_make_io_signature; +%rename(io_signature2) gr_make_io_signature2; +%rename(io_signature3) gr_make_io_signature3; +%rename(io_signaturev) gr_make_io_signaturev; + + +gr_io_signature_sptr +gr_make_io_signature(int min_streams, int max_streams, + int sizeof_stream_item); + +gr_io_signature_sptr +gr_make_io_signature2(int min_streams, int max_streams, + int sizeof_stream_item1, + int sizeof_stream_item2 + ); +gr_io_signature_sptr +gr_make_io_signature3(int min_streams, int max_streams, + int sizeof_stream_item1, + int sizeof_stream_item2, + int sizeof_stream_item3 + ); +gr_io_signature_sptr +gr_make_io_signaturev(int min_streams, int max_streams, + const std::vector<int> &sizeof_stream_items); + + +class gr_io_signature { + gr_io_signature (int min_streams, int max_streams, int sizeof_stream_item); + + friend gr_io_signature_sptr + gr_make_io_signaturev(int min_streams, + int max_streams, + const std::vector<int> &sizeof_stream_item); + + public: + + // disabled. Suspected bug in SWIG 1.3.24 + // static const int IO_INFINITE = -1; + + ~gr_io_signature (); + + int min_streams () const { return d_min_streams; } + int max_streams () const { return d_max_streams; } + int sizeof_stream_item (int index) const; + std::vector<int> sizeof_stream_items() const; +}; + diff --git a/gnuradio-core/src/lib/runtime/gr_local_sighandler.cc b/gnuradio-core/src/lib/runtime/gr_local_sighandler.cc new file mode 100644 index 000000000..fb31742e1 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_local_sighandler.cc @@ -0,0 +1,187 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_local_sighandler.h> +#include <stdexcept> +#include <stdio.h> +#include <string.h> + + +gr_local_sighandler::gr_local_sighandler (int signum, + void (*new_handler)(int)) + : d_signum (signum) +{ +#ifdef HAVE_SIGACTION + struct sigaction new_action; + memset (&new_action, 0, sizeof (new_action)); + + new_action.sa_handler = new_handler; + sigemptyset (&new_action.sa_mask); + new_action.sa_flags = 0; + + if (sigaction (d_signum, &new_action, &d_old_action) < 0){ + perror ("sigaction (install new)"); + throw std::runtime_error ("sigaction"); + } +#endif +} + +gr_local_sighandler::~gr_local_sighandler () +{ +#ifdef HAVE_SIGACTION + if (sigaction (d_signum, &d_old_action, 0) < 0){ + perror ("sigaction (restore old)"); + throw std::runtime_error ("sigaction"); + } +#endif +} + +void +gr_local_sighandler::throw_signal (int signum) +{ + throw gr_signal (signum); +} + +/* + * Semi-hideous way to may a signal number into a signal name + */ + +#define SIGNAME(x) case x: return #x + +std::string +gr_signal::name () const +{ + char tmp[128]; + + switch (signal ()){ +#ifdef SIGHUP + SIGNAME (SIGHUP); +#endif +#ifdef SIGINT + SIGNAME (SIGINT); +#endif +#ifdef SIGQUIT + SIGNAME (SIGQUIT); +#endif +#ifdef SIGILL + SIGNAME (SIGILL); +#endif +#ifdef SIGTRAP + SIGNAME (SIGTRAP); +#endif +#ifdef SIGABRT + SIGNAME (SIGABRT); +#endif +#ifdef SIGBUS + SIGNAME (SIGBUS); +#endif +#ifdef SIGFPE + SIGNAME (SIGFPE); +#endif +#ifdef SIGKILL + SIGNAME (SIGKILL); +#endif +#ifdef SIGUSR1 + SIGNAME (SIGUSR1); +#endif +#ifdef SIGSEGV + SIGNAME (SIGSEGV); +#endif +#ifdef SIGUSR2 + SIGNAME (SIGUSR2); +#endif +#ifdef SIGPIPE + SIGNAME (SIGPIPE); +#endif +#ifdef SIGALRM + SIGNAME (SIGALRM); +#endif +#ifdef SIGTERM + SIGNAME (SIGTERM); +#endif +#ifdef SIGSTKFLT + SIGNAME (SIGSTKFLT); +#endif +#ifdef SIGCHLD + SIGNAME (SIGCHLD); +#endif +#ifdef SIGCONT + SIGNAME (SIGCONT); +#endif +#ifdef SIGSTOP + SIGNAME (SIGSTOP); +#endif +#ifdef SIGTSTP + SIGNAME (SIGTSTP); +#endif +#ifdef SIGTTIN + SIGNAME (SIGTTIN); +#endif +#ifdef SIGTTOU + SIGNAME (SIGTTOU); +#endif +#ifdef SIGURG + SIGNAME (SIGURG); +#endif +#ifdef SIGXCPU + SIGNAME (SIGXCPU); +#endif +#ifdef SIGXFSZ + SIGNAME (SIGXFSZ); +#endif +#ifdef SIGVTALRM + SIGNAME (SIGVTALRM); +#endif +#ifdef SIGPROF + SIGNAME (SIGPROF); +#endif +#ifdef SIGWINCH + SIGNAME (SIGWINCH); +#endif +#ifdef SIGIO + SIGNAME (SIGIO); +#endif +#ifdef SIGPWR + SIGNAME (SIGPWR); +#endif +#ifdef SIGSYS + SIGNAME (SIGSYS); +#endif + default: +#if defined (HAVE_SNPRINTF) +#if defined (SIGRTMIN) && defined (SIGRTMAX) + if (signal () >= SIGRTMIN && signal () <= SIGRTMAX){ + snprintf (tmp, sizeof (tmp), "SIGRTMIN + %d", signal ()); + return tmp; + } +#endif + snprintf (tmp, sizeof (tmp), "SIGNAL %d", signal ()); + return tmp; +#else + return "Unknown signal"; +#endif + } +} diff --git a/gnuradio-core/src/lib/runtime/gr_local_sighandler.h b/gnuradio-core/src/lib/runtime/gr_local_sighandler.h new file mode 100644 index 000000000..a30e2c13a --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_local_sighandler.h @@ -0,0 +1,65 @@ +/* -*- 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_LOCAL_SIGHANDLER_H +#define INCLUDED_GR_LOCAL_SIGHANDLER_H + +#ifdef HAVE_SIGNAL_H +#include <signal.h> +#endif + +#include <gr_core_api.h> +#include <string> + +/*! + * \brief Get and set signal handler. + * + * \ingroup internal + * Constructor installs new handler, destructor reinstalls + * original value. + */ +class GR_CORE_API gr_local_sighandler { + int d_signum; +#ifdef HAVE_SIGACTION + struct sigaction d_old_action; +#endif +public: + gr_local_sighandler (int signum, void (*new_handler)(int)); + ~gr_local_sighandler (); + + /* throw gr_signal (signum) */ + static void throw_signal (int signum); +}; + +/*! + * \brief Representation of signal. + */ +class GR_CORE_API gr_signal +{ + int d_signum; +public: + gr_signal (int signum) : d_signum (signum) {} + int signal () const { return d_signum; } + std::string name () const; +}; + +#endif /* INCLUDED_GR_LOCAL_SIGHANDLER_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_message.cc b/gnuradio-core/src/lib/runtime/gr_message.cc new file mode 100644 index 000000000..a99dcd765 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_message.cc @@ -0,0 +1,78 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include <gr_message.h> +#include <assert.h> +#include <string.h> + +static long s_ncurrently_allocated = 0; + +gr_message_sptr +gr_make_message (long type, double arg1, double arg2, size_t length) +{ + return gr_message_sptr (new gr_message (type, arg1, arg2, length)); +} + +gr_message_sptr +gr_make_message_from_string(const std::string s, long type, double arg1, double arg2) +{ + gr_message_sptr m = gr_make_message(type, arg1, arg2, s.size()); + memcpy(m->msg(), s.data(), s.size()); + return m; +} + + +gr_message::gr_message (long type, double arg1, double arg2, size_t length) + : d_type(type), d_arg1(arg1), d_arg2(arg2) +{ + if (length == 0) + d_buf_start = d_msg_start = d_msg_end = d_buf_end = 0; + else { + d_buf_start = new unsigned char [length]; + d_msg_start = d_buf_start; + d_msg_end = d_buf_end = d_buf_start + length; + } + s_ncurrently_allocated++; +} + +gr_message::~gr_message () +{ + assert (d_next == 0); + delete [] d_buf_start; + d_msg_start = d_msg_end = d_buf_end = 0; + s_ncurrently_allocated--; +} + +std::string +gr_message::to_string() const +{ + return std::string((char *)d_msg_start, length()); +} + +long +gr_message_ncurrently_allocated () +{ + return s_ncurrently_allocated; +} diff --git a/gnuradio-core/src/lib/runtime/gr_message.h b/gnuradio-core/src/lib/runtime/gr_message.h new file mode 100644 index 000000000..d386ca009 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_message.h @@ -0,0 +1,91 @@ +/* -*- 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_MESSAGE_H +#define INCLUDED_GR_MESSAGE_H + +#include <gr_core_api.h> +#include <gr_types.h> +#include <string> + +class gr_message; +typedef boost::shared_ptr<gr_message> gr_message_sptr; + +/*! + * \brief public constructor for gr_message + */ +GR_CORE_API gr_message_sptr +gr_make_message(long type = 0, double arg1 = 0, double arg2 = 0, size_t length = 0); + +GR_CORE_API gr_message_sptr +gr_make_message_from_string(const std::string s, long type = 0, double arg1 = 0, double arg2 = 0); + +/*! + * \brief Message class. + * + * \ingroup misc + * The ideas and method names for adjustable message length were + * lifted from the click modular router "Packet" class. + */ +class GR_CORE_API gr_message { + gr_message_sptr d_next; // link field for msg queue + long d_type; // type of the message + double d_arg1; // optional arg1 + double d_arg2; // optional arg2 + + unsigned char *d_buf_start; // start of allocated buffer + unsigned char *d_msg_start; // where the msg starts + unsigned char *d_msg_end; // one beyond end of msg + unsigned char *d_buf_end; // one beyond end of allocated buffer + + gr_message (long type, double arg1, double arg2, size_t length); + + friend GR_CORE_API gr_message_sptr + gr_make_message (long type, double arg1, double arg2, size_t length); + + friend GR_CORE_API gr_message_sptr + gr_make_message_from_string (const std::string s, long type, double arg1, double arg2); + + friend class gr_msg_queue; + + unsigned char *buf_data() const { return d_buf_start; } + size_t buf_len() const { return d_buf_end - d_buf_start; } + +public: + ~gr_message (); + + long type() const { return d_type; } + double arg1() const { return d_arg1; } + double arg2() const { return d_arg2; } + + void set_type(long type) { d_type = type; } + void set_arg1(double arg1) { d_arg1 = arg1; } + void set_arg2(double arg2) { d_arg2 = arg2; } + + unsigned char *msg() const { return d_msg_start; } + size_t length() const { return d_msg_end - d_msg_start; } + std::string to_string() const; + +}; + +GR_CORE_API long gr_message_ncurrently_allocated (); + +#endif /* INCLUDED_GR_MESSAGE_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_message.i b/gnuradio-core/src/lib/runtime/gr_message.i new file mode 100644 index 000000000..356bba5b5 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_message.i @@ -0,0 +1,65 @@ +/* -*- 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. + */ + +class gr_message; +typedef boost::shared_ptr<gr_message> gr_message_sptr; +%template(gr_message_sptr) boost::shared_ptr<gr_message>; + +%rename(message_from_string) gr_make_message_from_string; +gr_message_sptr +gr_make_message_from_string(const std::string s, long type = 0, double arg1 = 0, double arg2 = 0); + +%rename(message) gr_make_message; +gr_message_sptr +gr_make_message(long type = 0, double arg1 = 0, double arg2 = 0, size_t length = 0); + +/*! + * \brief Message. + * + * The ideas and method names for adjustable message length were + * lifted from the click modular router "Packet" class. + */ +class gr_message { + gr_message (long type, double arg1, double arg2, size_t length); + + unsigned char *buf_data() const { return d_buf_start; } + size_t buf_len() const { return d_buf_end - d_buf_start; } + +public: + ~gr_message (); + + long type() const { return d_type; } + double arg1() const { return d_arg1; } + double arg2() const { return d_arg2; } + + void set_type(long type) { d_type = type; } + void set_arg1(double arg1) { d_arg1 = arg1; } + void set_arg2(double arg2) { d_arg2 = arg2; } + + size_t length() const; + std::string to_string() const; + +}; + +%rename(message_ncurrently_allocated) gr_message_ncurrently_allocated; +long gr_message_ncurrently_allocated(); + diff --git a/gnuradio-core/src/lib/runtime/gr_msg_accepter.cc b/gnuradio-core/src/lib/runtime/gr_msg_accepter.cc new file mode 100644 index 000000000..93d5fb20e --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_msg_accepter.cc @@ -0,0 +1,59 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#if HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gr_msg_accepter.h> +#include <gr_block.h> +#include <gr_block_detail.h> +#include <gr_hier_block2.h> +#include <stdexcept> + +using namespace pmt; + +gr_msg_accepter::gr_msg_accepter() +{ +} + +gr_msg_accepter::~gr_msg_accepter() +{ + // NOP, required as virtual destructor +} + +void +gr_msg_accepter::post(pmt_t which_port, pmt_t msg) +{ + // Notify derived class, handled case by case + gr_block *p = dynamic_cast<gr_block *>(this); + if (p) { + p->_post(which_port,msg); + return; + } + gr_hier_block2 *p2 = dynamic_cast<gr_hier_block2 *>(this); + if (p2){ + // FIXME do the right thing + return; + } + + throw std::runtime_error("unknown derived class"); +} diff --git a/gnuradio-core/src/lib/runtime/gr_msg_accepter.h b/gnuradio-core/src/lib/runtime/gr_msg_accepter.h new file mode 100644 index 000000000..a497ba6e7 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_msg_accepter.h @@ -0,0 +1,43 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef INCLUDED_GR_MSG_ACCEPTER_H +#define INCLUDED_GR_MSG_ACCEPTER_H + +#include <gr_core_api.h> +#include <gruel/msg_accepter.h> +#include <gruel/pmt.h> + +/*! + * \brief Accepts messages and inserts them into a message queue, then notifies + * subclass gr_basic_block there is a message pending. + */ +class GR_CORE_API gr_msg_accepter : public gruel::msg_accepter +{ +public: + gr_msg_accepter(); + ~gr_msg_accepter(); + + void post(pmt::pmt_t which_port, pmt::pmt_t msg); + +}; + +#endif /* INCLUDED_GR_MSG_ACCEPTER_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_msg_handler.cc b/gnuradio-core/src/lib/runtime/gr_msg_handler.cc new file mode 100644 index 000000000..0f9349708 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_msg_handler.cc @@ -0,0 +1,30 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include <gr_msg_handler.h> + +gr_msg_handler::~gr_msg_handler () +{ +} diff --git a/gnuradio-core/src/lib/runtime/gr_msg_handler.h b/gnuradio-core/src/lib/runtime/gr_msg_handler.h new file mode 100644 index 000000000..57e8a95d6 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_msg_handler.h @@ -0,0 +1,43 @@ +/* -*- 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_MSG_HANDLER_H +#define INCLUDED_GR_MSG_HANDLER_H + +#include <gr_core_api.h> +#include <gr_message.h> + +class gr_msg_handler; +typedef boost::shared_ptr<gr_msg_handler> gr_msg_handler_sptr; + +/*! + * \brief abstract class of message handlers + * \ingroup base + */ +class GR_CORE_API gr_msg_handler { +public: + virtual ~gr_msg_handler (); + + //! handle \p msg + virtual void handle (gr_message_sptr msg) = 0; +}; + +#endif /* INCLUDED_GR_MSG_HANDLER_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_msg_handler.i b/gnuradio-core/src/lib/runtime/gr_msg_handler.i new file mode 100644 index 000000000..f493dac1b --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_msg_handler.i @@ -0,0 +1,32 @@ +/* -*- 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. + */ + +/*! + * \brief abstract class of message handlers + */ +class gr_msg_handler { +public: + virtual ~gr_msg_handler () = 0; + + //! handle \p msg + virtual void handle (gr_message_sptr msg) = 0; +}; diff --git a/gnuradio-core/src/lib/runtime/gr_msg_queue.cc b/gnuradio-core/src/lib/runtime/gr_msg_queue.cc new file mode 100644 index 000000000..0cf046771 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_msg_queue.cc @@ -0,0 +1,125 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2009 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_msg_queue.h> +#include <stdexcept> + +gr_msg_queue_sptr +gr_make_msg_queue(unsigned int limit) +{ + return gr_msg_queue_sptr (new gr_msg_queue(limit)); +} + +gr_msg_queue::gr_msg_queue(unsigned int limit) + : d_not_empty(), d_not_full(), + /*d_head(0), d_tail(0),*/ d_count(0), d_limit(limit) +{ +} + +gr_msg_queue::~gr_msg_queue() +{ + flush (); +} + +void +gr_msg_queue::insert_tail(gr_message_sptr msg) +{ + if (msg->d_next) + throw std::invalid_argument("gr_msg_queue::insert_tail: msg already in queue"); + + gruel::scoped_lock guard(d_mutex); + + while (full_p()) + d_not_full.wait(guard); + + if (d_tail == 0){ + d_tail = d_head = msg; + //msg->d_next = 0; + msg->d_next.reset(); + } + else { + d_tail->d_next = msg; + d_tail = msg; + //msg->d_next = 0; + msg->d_next.reset(); + } + d_count++; + d_not_empty.notify_one(); +} + +gr_message_sptr +gr_msg_queue::delete_head() +{ + gruel::scoped_lock guard(d_mutex); + gr_message_sptr m; + + while ((m = d_head) == 0) + d_not_empty.wait(guard); + + d_head = m->d_next; + if (d_head == 0){ + //d_tail = 0; + d_tail.reset(); + } + + d_count--; + // m->d_next = 0; + m->d_next.reset(); + d_not_full.notify_one(); + return m; +} + +gr_message_sptr +gr_msg_queue::delete_head_nowait() +{ + gruel::scoped_lock guard(d_mutex); + gr_message_sptr m; + + if ((m = d_head) == 0){ + //return 0; + return gr_message_sptr(); + } + + d_head = m->d_next; + if (d_head == 0){ + //d_tail = 0; + d_tail.reset(); + } + + d_count--; + //m->d_next = 0; + m->d_next.reset(); + d_not_full.notify_one(); + return m; +} + +void +gr_msg_queue::flush() +{ + gr_message_sptr m; + + while ((m = delete_head_nowait ()) != 0) + ; +} diff --git a/gnuradio-core/src/lib/runtime/gr_msg_queue.h b/gnuradio-core/src/lib/runtime/gr_msg_queue.h new file mode 100644 index 000000000..86440bbb0 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_msg_queue.h @@ -0,0 +1,92 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,2009 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_MSG_QUEUE_H +#define INCLUDED_GR_MSG_QUEUE_H + +#include <gr_core_api.h> +#include <gr_msg_handler.h> +#include <gruel/thread.h> + +class gr_msg_queue; +typedef boost::shared_ptr<gr_msg_queue> gr_msg_queue_sptr; + +GR_CORE_API gr_msg_queue_sptr gr_make_msg_queue(unsigned int limit=0); + +/*! + * \brief thread-safe message queue + * \ingroup misc + */ +class GR_CORE_API gr_msg_queue : public gr_msg_handler { + + gruel::mutex d_mutex; + gruel::condition_variable d_not_empty; + gruel::condition_variable d_not_full; + gr_message_sptr d_head; + gr_message_sptr d_tail; + unsigned int d_count; // # of messages in queue. + unsigned int d_limit; // max # of messages in queue. 0 -> unbounded + +public: + gr_msg_queue(unsigned int limit); + ~gr_msg_queue(); + + //! Generic msg_handler method: insert the message. + void handle(gr_message_sptr msg) { insert_tail (msg); } + + /*! + * \brief Insert message at tail of queue. + * \param msg message + * + * Block if queue if full. + */ + void insert_tail(gr_message_sptr msg); + + /*! + * \brief Delete message from head of queue and return it. + * Block if no message is available. + */ + gr_message_sptr delete_head(); + + /*! + * \brief If there's a message in the q, delete it and return it. + * If no message is available, return 0. + */ + gr_message_sptr delete_head_nowait(); + + //! Delete all messages from the queue + void flush(); + + //! is the queue empty? + bool empty_p() const { return d_count == 0; } + + //! is the queue full? + bool full_p() const { return d_limit != 0 && d_count >= d_limit; } + + //! return number of messages in queue + unsigned int count() const { return d_count; } + + //! return limit on number of message in queue. 0 -> unbounded + unsigned int limit() const { return d_limit; } + +}; + +#endif /* INCLUDED_GR_MSG_QUEUE_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_msg_queue.i b/gnuradio-core/src/lib/runtime/gr_msg_queue.i new file mode 100644 index 000000000..65cbe782b --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_msg_queue.i @@ -0,0 +1,107 @@ +/* -*- c++ -*- */ +/* + * Copyright 2005,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. + */ + +class gr_msg_queue; +typedef boost::shared_ptr<gr_msg_queue> gr_msg_queue_sptr; +%template(gr_msg_queue_sptr) boost::shared_ptr<gr_msg_queue>; + +%rename(msg_queue) gr_make_msg_queue; +gr_msg_queue_sptr gr_make_msg_queue(unsigned limit=0); + +/*! + * \brief thread-safe message queue + */ +%ignore gr_msg_queue; +class gr_msg_queue : public gr_msg_handler { +public: + gr_msg_queue(unsigned int limit); + ~gr_msg_queue(); + + //! Generic msg_handler method: insert the message. + //void handle(gr_message_sptr msg) { insert_tail (msg); } + + /*! + * \brief Insert message at tail of queue. + * \param msg message + * + * Block if queue if full. + */ + //void insert_tail(gr_message_sptr msg); + + /*! + * \brief Delete message from head of queue and return it. + * Block if no message is available. + */ + //gr_message_sptr delete_head(); + + /*! + * \brief If there's a message in the q, delete it and return it. + * If no message is available, return 0. + */ + gr_message_sptr delete_head_nowait(); + + //! is the queue empty? + bool empty_p() const; + + //! is the queue full? + bool full_p() const; + + //! return number of messages in queue + unsigned int count() const; + + //! Delete all messages from the queue + void flush(); +}; + +/* + * The following kludge-o-rama releases the Python global interpreter + * lock around these potentially blocking calls. We don't want + * libgnuradio-core to be dependent on Python, thus we create these + * functions that serve as replacements for the normal C++ delete_head + * and insert_tail methods. The %pythoncode smashes these new C++ + * functions into the gr.msg_queue wrapper class, so that everything + * appears normal. (An evil laugh is heard in the distance...) + */ +#ifdef SWIGPYTHON +%inline %{ + gr_message_sptr gr_py_msg_queue__delete_head(gr_msg_queue_sptr q) { + gr_message_sptr msg; + GR_PYTHON_BLOCKING_CODE( + msg = q->delete_head(); + ) + return msg; + } + + void gr_py_msg_queue__insert_tail(gr_msg_queue_sptr q, gr_message_sptr msg) { + GR_PYTHON_BLOCKING_CODE( + q->insert_tail(msg); + ) + } +%} + +// smash in new python delete_head and insert_tail methods... +%pythoncode %{ +gr_msg_queue_sptr.delete_head = gr_py_msg_queue__delete_head +gr_msg_queue_sptr.insert_tail = gr_py_msg_queue__insert_tail +gr_msg_queue_sptr.handle = gr_py_msg_queue__insert_tail +%} +#endif // SWIGPYTHON diff --git a/gnuradio-core/src/lib/runtime/gr_pagesize.cc b/gnuradio-core/src/lib/runtime/gr_pagesize.cc new file mode 100644 index 000000000..e31e05ca7 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_pagesize.cc @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 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_pagesize.h> +#include <unistd.h> +#include <stdio.h> + +#if defined(_WIN32) && defined(HAVE_GETPAGESIZE) +extern "C" size_t getpagesize(void); +#endif + +int +gr_pagesize () +{ + static int s_pagesize = -1; + + if (s_pagesize == -1){ +#if defined(HAVE_GETPAGESIZE) + s_pagesize = getpagesize (); +#elif defined (HAVE_SYSCONF) + s_pagesize = sysconf (_SC_PAGESIZE); + if (s_pagesize == -1){ + perror ("_SC_PAGESIZE"); + s_pagesize = 4096; + } +#else + fprintf (stderr, "gr_pagesize: no info; setting pagesize = 4096\n"); + s_pagesize = 4096; +#endif + } + return s_pagesize; +} + diff --git a/gnuradio-core/src/lib/runtime/gr_pagesize.h b/gnuradio-core/src/lib/runtime/gr_pagesize.h new file mode 100644 index 000000000..3e2daa925 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_pagesize.h @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 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 _GR_PAGESIZE_H_ +#define _GR_PAGESIZE_H_ + +#include <gr_core_api.h> + +/*! + * \brief return the page size in bytes + */ + +GR_CORE_API int gr_pagesize (); + + +#endif /* _GR_PAGESIZE_H_ */
\ No newline at end of file diff --git a/gnuradio-core/src/lib/runtime/gr_preferences.cc b/gnuradio-core/src/lib/runtime/gr_preferences.cc new file mode 100644 index 000000000..a0f561660 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_preferences.cc @@ -0,0 +1,108 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,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_preferences.h> +#include <gr_sys_paths.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <string.h> + +#include <boost/filesystem/operations.hpp> +#include <boost/filesystem/path.hpp> +namespace fs = boost::filesystem; + +/* + * The simplest thing that could possibly work: + * the key is the filename; the value is the file contents. + */ + +static const char * +pathname (const char *key) +{ + static fs::path path; + path = fs::path(gr_appdata_path()) / ".gnuradio" / "prefs" / key; + return path.string().c_str(); +} + +static void +ensure_dir_path () +{ + fs::path path = fs::path(gr_appdata_path()) / ".gnuradio"; + if (!fs::is_directory(path)) fs::create_directory(path); + + path = path / "prefs"; + if (!fs::is_directory(path)) fs::create_directory(path); +} + +const char * +gr_preferences::get (const char *key) +{ + static char buf[1024]; + + FILE *fp = fopen (pathname (key), "r"); + if (fp == 0) { + perror (pathname (key)); + return 0; + } + + memset (buf, 0, sizeof (buf)); + size_t ret = fread (buf, 1, sizeof (buf) - 1, fp); + if(ret == 0) { + if(ferror(fp) != 0) { + perror (pathname (key)); + fclose (fp); + return 0; + } + } + fclose (fp); + return buf; +} + +void +gr_preferences::set (const char *key, const char *value) +{ + ensure_dir_path (); + + FILE *fp = fopen (pathname (key), "w"); + if (fp == 0){ + perror (pathname (key)); + return; + } + + size_t ret = fwrite (value, 1, strlen (value), fp); + if(ret == 0) { + if(ferror(fp) != 0) { + perror (pathname (key)); + fclose (fp); + return; + } + } + fclose (fp); +}; diff --git a/gnuradio-core/src/lib/runtime/gr_preferences.h b/gnuradio-core/src/lib/runtime/gr_preferences.h new file mode 100644 index 000000000..bfcc0424b --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_preferences.h @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 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 _GR_PREFERENCES_H_ +#define _GR_PREFERENCES_H_ + +#include <gr_core_api.h> + +class GR_CORE_API gr_preferences { + public: + static const char *get (const char *key); + static void set (const char *key, const char *value); +}; + +#endif /* _GR_PREFERENCES_H_ */
\ No newline at end of file diff --git a/gnuradio-core/src/lib/runtime/gr_realtime.cc b/gnuradio-core/src/lib/runtime/gr_realtime.cc new file mode 100644 index 000000000..75b497999 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_realtime.cc @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2007,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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_realtime.h> + +gr_rt_status_t +gr_enable_realtime_scheduling() +{ + return gruel::enable_realtime_scheduling(); +} diff --git a/gnuradio-core/src/lib/runtime/gr_realtime.h b/gnuradio-core/src/lib/runtime/gr_realtime.h new file mode 100644 index 000000000..fe6549039 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_realtime.h @@ -0,0 +1,37 @@ +/* -*- 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_REALTIME_H +#define INCLUDED_GR_REALTIME_H + +#include <gr_core_api.h> +#include <gruel/realtime.h> + +typedef gruel::rt_status_t gr_rt_status_t; + +/*! + * \brief If possible, enable high-priority "real time" scheduling. + * \ingroup misc + */ +GR_CORE_API gr_rt_status_t gr_enable_realtime_scheduling(); + +#endif /* INCLUDED_GR_REALTIME_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_realtime.i b/gnuradio-core/src/lib/runtime/gr_realtime.i new file mode 100644 index 000000000..1051d3e2b --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_realtime.i @@ -0,0 +1,44 @@ +/* -*- 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. + */ + +%rename(enable_realtime_scheduling) gr_enable_realtime_scheduling; + +// NOTE: This is duplicated from gruel/src/include/gruel/gr_realtime.h, +// and must be kept in sync with it. This is the least evil workaround +// for allowing 3rd party code builds to work when GNU Radio is +// installed from binary packages into the standard system directories. +// Otherwise, they can't find #include <gruel/gr_realtime.h>, since +// pkg-config strips -I/usr/include from the --cflags path. + +namespace gruel { + + typedef enum { + RT_OK = 0, + RT_NOT_IMPLEMENTED, + RT_NO_PRIVS, + RT_OTHER_ERROR + } rt_status_t; + +} + +typedef gruel::rt_status_t gr_rt_status_t; +gr_rt_status_t gr_enable_realtime_scheduling(); diff --git a/gnuradio-core/src/lib/runtime/gr_runtime_types.h b/gnuradio-core/src/lib/runtime/gr_runtime_types.h new file mode 100644 index 000000000..0d6149288 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_runtime_types.h @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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_RUNTIME_TYPES_H +#define INCLUDED_GR_RUNTIME_TYPES_H + +#include <gr_core_api.h> +#include <gr_types.h> + +/* + * typedefs for smart pointers we use throughout the runtime system + */ + +class gr_basic_block; +class gr_block; +class gr_block_detail; +class gr_hier_block2; +class gr_io_signature; +class gr_buffer; +class gr_buffer_reader; +class gr_flowgraph; +class gr_flat_flowgraph; +class gr_top_block; +class gr_top_block_detail; + +typedef boost::shared_ptr<gr_basic_block> gr_basic_block_sptr; +typedef boost::shared_ptr<gr_block> gr_block_sptr; +typedef boost::shared_ptr<gr_block_detail> gr_block_detail_sptr; +typedef boost::shared_ptr<gr_hier_block2> gr_hier_block2_sptr; +typedef boost::shared_ptr<gr_io_signature> gr_io_signature_sptr; +typedef boost::shared_ptr<gr_buffer> gr_buffer_sptr; +typedef boost::shared_ptr<gr_buffer_reader> gr_buffer_reader_sptr; +typedef boost::shared_ptr<gr_flowgraph> gr_flowgraph_sptr; +typedef boost::shared_ptr<gr_flat_flowgraph> gr_flat_flowgraph_sptr; +typedef boost::shared_ptr<gr_top_block> gr_top_block_sptr; + +#endif /* INCLUDED_GR_RUNTIME_TYPES_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_scheduler.cc b/gnuradio-core/src/lib/runtime/gr_scheduler.cc new file mode 100644 index 000000000..c691f5d99 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_scheduler.cc @@ -0,0 +1,33 @@ +/* -*- 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_scheduler.h> + +gr_scheduler::gr_scheduler(gr_flat_flowgraph_sptr ffg, int max_noutput_items) +{ +} + +gr_scheduler::~gr_scheduler() +{ +} diff --git a/gnuradio-core/src/lib/runtime/gr_scheduler.h b/gnuradio-core/src/lib/runtime/gr_scheduler.h new file mode 100644 index 000000000..6d130327f --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_scheduler.h @@ -0,0 +1,65 @@ +/* -*- 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef INCLUDED_GR_SCHEDULER_H +#define INCLUDED_GR_SCHEDULER_H + +#include <gr_core_api.h> +#include <boost/utility.hpp> +#include <gr_block.h> +#include <gr_flat_flowgraph.h> + + +class gr_scheduler; +typedef boost::shared_ptr<gr_scheduler> gr_scheduler_sptr; + + +/*! + * \brief Abstract scheduler that takes a flattened flow graph and runs it. + * + * Preconditions: details, buffers and buffer readers have been assigned. + */ +class GR_CORE_API gr_scheduler : boost::noncopyable +{ + +public: + /*! + * \brief Construct a scheduler and begin evaluating the graph. + * + * The scheduler will continue running until all blocks until they + * report that they are done or the stop method is called. + */ + gr_scheduler(gr_flat_flowgraph_sptr ffg, int max_noutput_items); + + virtual ~gr_scheduler(); + + /*! + * \brief Tell the scheduler to stop executing. + */ + virtual void stop() = 0; + + /*! + * \brief Block until the graph is done. + */ + virtual void wait() = 0; +}; + +#endif /* INCLUDED_GR_SCHEDULER_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_scheduler_sts.cc b/gnuradio-core/src/lib/runtime/gr_scheduler_sts.cc new file mode 100644 index 000000000..2c96def6d --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_scheduler_sts.cc @@ -0,0 +1,87 @@ +/* -*- 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_scheduler_sts.h> +#include <gr_single_threaded_scheduler.h> +#include <gruel/thread_body_wrapper.h> + +class sts_container +{ + gr_block_vector_t d_blocks; + +public: + + sts_container(gr_block_vector_t blocks) + : d_blocks(blocks) {} + + void operator()() + { + gr_make_single_threaded_scheduler(d_blocks)->run(); + } +}; + + +gr_scheduler_sptr +gr_scheduler_sts::make(gr_flat_flowgraph_sptr ffg, int max_noutput_items) +{ + return gr_scheduler_sptr(new gr_scheduler_sts(ffg, max_noutput_items)); +} + +gr_scheduler_sts::gr_scheduler_sts(gr_flat_flowgraph_sptr ffg, int max_noutput_items) + : gr_scheduler(ffg, max_noutput_items) +{ + // Split the flattened flow graph into discrete partitions, each + // of which is topologically sorted. + + std::vector<gr_basic_block_vector_t> graphs = ffg->partition(); + + // For each partition, create a thread to evaluate it using + // an instance of the gr_single_threaded_scheduler + + for (std::vector<gr_basic_block_vector_t>::iterator p = graphs.begin(); + p != graphs.end(); p++) { + + gr_block_vector_t blocks = gr_flat_flowgraph::make_block_vector(*p); + d_threads.create_thread( + gruel::thread_body_wrapper<sts_container>(sts_container(blocks), + "single-threaded-scheduler")); + } +} + +gr_scheduler_sts::~gr_scheduler_sts() +{ + stop(); +} + +void +gr_scheduler_sts::stop() +{ + d_threads.interrupt_all(); +} + +void +gr_scheduler_sts::wait() +{ + d_threads.join_all(); +} diff --git a/gnuradio-core/src/lib/runtime/gr_scheduler_sts.h b/gnuradio-core/src/lib/runtime/gr_scheduler_sts.h new file mode 100644 index 000000000..011874ec0 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_scheduler_sts.h @@ -0,0 +1,63 @@ +/* -*- 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef INCLUDED_GR_SCHEDULER_STS_H +#define INCLUDED_GR_SCHEDULER_STS_H + +#include <gr_core_api.h> +#include <gr_scheduler.h> +#include <gruel/thread_group.h> + +/*! + * \brief Concrete scheduler that uses the single_threaded_scheduler + */ +class GR_CORE_API gr_scheduler_sts : public gr_scheduler +{ + gruel::thread_group d_threads; + +protected: + /*! + * \brief Construct a scheduler and begin evaluating the graph. + * + * The scheduler will continue running until all blocks until they + * report that they are done or the stop method is called. + */ + gr_scheduler_sts(gr_flat_flowgraph_sptr ffg, int max_noutput_items); + +public: + static gr_scheduler_sptr make(gr_flat_flowgraph_sptr ffg, int max_noutput_items); + + ~gr_scheduler_sts(); + + /*! + * \brief Tell the scheduler to stop executing. + */ + void stop(); + + /*! + * \brief Block until the graph is done. + */ + void wait(); +}; + + + + +#endif /* INCLUDED_GR_SCHEDULER_STS_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_scheduler_tpb.cc b/gnuradio-core/src/lib/runtime/gr_scheduler_tpb.cc new file mode 100644 index 000000000..2824eb1b3 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_scheduler_tpb.cc @@ -0,0 +1,103 @@ +/* -*- 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_scheduler_tpb.h> +#include <gr_tpb_thread_body.h> +#include <gruel/thread_body_wrapper.h> +#include <sstream> + +/* + * You know, a lambda expression would be sooo much easier... + */ +class tpb_container +{ + gr_block_sptr d_block; + int d_max_noutput_items; + +public: + tpb_container(gr_block_sptr block, int max_noutput_items) + : d_block(block), d_max_noutput_items(max_noutput_items) {} + + void operator()() + { + gr_tpb_thread_body body(d_block, d_max_noutput_items); + } +}; + + +gr_scheduler_sptr +gr_scheduler_tpb::make(gr_flat_flowgraph_sptr ffg, int max_noutput_items) +{ + return gr_scheduler_sptr(new gr_scheduler_tpb(ffg, max_noutput_items)); +} + +gr_scheduler_tpb::gr_scheduler_tpb(gr_flat_flowgraph_sptr ffg, int max_noutput_items) + : gr_scheduler(ffg, max_noutput_items) +{ + // Get a topologically sorted vector of all the blocks in use. + // Being topologically sorted probably isn't going to matter, but + // there's a non-zero chance it might help... + + gr_basic_block_vector_t used_blocks = ffg->calc_used_blocks(); + used_blocks = ffg->topological_sort(used_blocks); + gr_block_vector_t blocks = gr_flat_flowgraph::make_block_vector(used_blocks); + + // Ensure that the done flag is clear on all blocks + + for (size_t i = 0; i < blocks.size(); i++){ + blocks[i]->detail()->set_done(false); + } + + // Fire off a thead for each block + + for (size_t i = 0; i < blocks.size(); i++){ + std::stringstream name; + name << "thread-per-block[" << i << "]: " << blocks[i]; + + // If set, use internal value instead of global value + if(blocks[i]->is_set_max_noutput_items()) + max_noutput_items = blocks[i]->max_noutput_items(); + + d_threads.create_thread( + gruel::thread_body_wrapper<tpb_container>(tpb_container(blocks[i], max_noutput_items), + name.str())); + } +} + +gr_scheduler_tpb::~gr_scheduler_tpb() +{ + stop(); +} + +void +gr_scheduler_tpb::stop() +{ + d_threads.interrupt_all(); +} + +void +gr_scheduler_tpb::wait() +{ + d_threads.join_all(); +} diff --git a/gnuradio-core/src/lib/runtime/gr_scheduler_tpb.h b/gnuradio-core/src/lib/runtime/gr_scheduler_tpb.h new file mode 100644 index 000000000..a9b3abcfa --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_scheduler_tpb.h @@ -0,0 +1,61 @@ +/* -*- 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef INCLUDED_GR_SCHEDULER_TPB_H +#define INCLUDED_GR_SCHEDULER_TPB_H + +#include <gr_core_api.h> +#include <gr_scheduler.h> +#include <gruel/thread_group.h> + +/*! + * \brief Concrete scheduler that uses a kernel thread-per-block + */ +class GR_CORE_API gr_scheduler_tpb : public gr_scheduler +{ + gruel::thread_group d_threads; + +protected: + /*! + * \brief Construct a scheduler and begin evaluating the graph. + * + * The scheduler will continue running until all blocks until they + * report that they are done or the stop method is called. + */ + gr_scheduler_tpb(gr_flat_flowgraph_sptr ffg, int max_noutput_items); + +public: + static gr_scheduler_sptr make(gr_flat_flowgraph_sptr ffg, int max_noutput_items=100000); + + ~gr_scheduler_tpb(); + + /*! + * \brief Tell the scheduler to stop executing. + */ + void stop(); + + /*! + * \brief Block until the graph is done. + */ + void wait(); +}; + + +#endif /* INCLUDED_GR_SCHEDULER_TPB_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_select_handler.cc b/gnuradio-core/src/lib/runtime/gr_select_handler.cc new file mode 100644 index 000000000..0fc86354a --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_select_handler.cc @@ -0,0 +1,36 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_select_handler.h> + +gr_select_handler::gr_select_handler(int fd) + : d_fd(fd) +{ +} + +gr_select_handler::~gr_select_handler() +{ +} diff --git a/gnuradio-core/src/lib/runtime/gr_select_handler.h b/gnuradio-core/src/lib/runtime/gr_select_handler.h new file mode 100644 index 000000000..c4c359213 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_select_handler.h @@ -0,0 +1,85 @@ +/* -*- 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_SELECT_HANDLER_H +#define INCLUDED_GR_SELECT_HANDLER_H + +#include <gr_core_api.h> +#include <boost/shared_ptr.hpp> + +class gr_select_handler; +typedef boost::shared_ptr<gr_select_handler> gr_select_handler_sptr; + + +/*! + * \brief Abstract handler for select based notification. + * \ingroup base + * + * \sa gr_dispatcher + */ +class GR_CORE_API gr_select_handler +{ + int d_fd; + +protected: + gr_select_handler(int file_descriptor); + +public: + virtual ~gr_select_handler(); + + int fd() const { return d_fd; } + int file_descriptor() const { return d_fd; } + + /*! + * \brief Called when file_descriptor is readable. + * + * Called when the dispatcher detects that file_descriptor can + * be read without blocking. + */ + virtual void handle_read() = 0; + + /*! + * \brief Called when file_descriptor is writable. + * + * Called when dispatcher detects that file descriptor can be + * written without blocking. + */ + virtual void handle_write() = 0; + + /*! + * Called each time around the dispatcher loop to determine whether + * this handler's file descriptor should be added to the list on which + * read events can occur. The default method returns true, indicating + * that by default, all handlers are interested in read events. + */ + virtual bool readable() { return true; } + + /*! + * Called each time around the dispatcher loop to determine whether + * this handler's file descriptor should be added to the list on which + * write events can occur. The default method returns true, indicating + * that by default, all handlers are interested in write events. + */ + virtual bool writable() { return true; } +}; + +#endif /* INCLUDED_GR_SELECT_HANDLER_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.cc b/gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.cc new file mode 100644 index 000000000..1bb9e9b0a --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.cc @@ -0,0 +1,364 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_single_threaded_scheduler.h> +#include <gr_block.h> +#include <gr_block_detail.h> +#include <gr_buffer.h> +#include <boost/thread.hpp> +#include <boost/format.hpp> +#include <iostream> +#include <limits> +#include <assert.h> +#include <stdio.h> + +// must be defined to either 0 or 1 +#define ENABLE_LOGGING 0 + +#if (ENABLE_LOGGING) +#define LOG(x) do { x; } while(0) +#else +#define LOG(x) do {;} while(0) +#endif + +static int which_scheduler = 0; + +gr_single_threaded_scheduler_sptr +gr_make_single_threaded_scheduler (const std::vector<gr_block_sptr> &blocks) +{ + return + gr_single_threaded_scheduler_sptr (new gr_single_threaded_scheduler (blocks)); +} + +gr_single_threaded_scheduler::gr_single_threaded_scheduler ( + const std::vector<gr_block_sptr> &blocks) + : d_blocks (blocks), d_enabled (true), d_log(0) +{ + if (ENABLE_LOGGING){ + std::string name = str(boost::format("sst-%d.log") % which_scheduler++); + d_log = new std::ofstream(name.c_str()); + *d_log << "gr_single_threaded_scheduler: " + << d_blocks.size () + << " blocks\n"; + } +} + +gr_single_threaded_scheduler::~gr_single_threaded_scheduler () +{ + if (ENABLE_LOGGING) + delete d_log; +} + +void +gr_single_threaded_scheduler::run () +{ + // d_enabled = true; // KLUDGE + main_loop (); +} + +void +gr_single_threaded_scheduler::stop () +{ + if (0) + std::cout << "gr_singled_threaded_scheduler::stop() " + << this << std::endl; + d_enabled = false; +} + +inline static unsigned int +round_up (unsigned int n, unsigned int multiple) +{ + return ((n + multiple - 1) / multiple) * multiple; +} + +inline static unsigned int +round_down (unsigned int n, unsigned int multiple) +{ + return (n / multiple) * multiple; +} + +// +// Return minimum available write space in all our downstream buffers +// or -1 if we're output blocked and the output we're blocked +// on is done. +// +static int +min_available_space (gr_block_detail *d, int output_multiple) +{ + int min_space = std::numeric_limits<int>::max(); + + for (int i = 0; i < d->noutputs (); i++){ + int n = round_down (d->output(i)->space_available (), output_multiple); + if (n == 0){ // We're blocked on output. + if (d->output(i)->done()){ // Downstream is done, therefore we're done. + return -1; + } + return 0; + } + min_space = std::min (min_space, n); + } + return min_space; +} + +void +gr_single_threaded_scheduler::main_loop () +{ + static const int DEFAULT_CAPACITY = 16; + + int noutput_items; + gr_vector_int ninput_items_required (DEFAULT_CAPACITY); + gr_vector_int ninput_items (DEFAULT_CAPACITY); + gr_vector_const_void_star input_items (DEFAULT_CAPACITY); + gr_vector_void_star output_items (DEFAULT_CAPACITY); + unsigned int bi; + unsigned int nalive; + int max_items_avail; + bool made_progress_last_pass; + bool making_progress; + + for (unsigned i = 0; i < d_blocks.size (); i++) + d_blocks[i]->detail()->set_done (false); // reset any done flags + + for (unsigned i = 0; i < d_blocks.size (); i++) // enable any drivers, etc. + d_blocks[i]->start(); + + + bi = 0; + made_progress_last_pass = true; + making_progress = false; + + // Loop while there are still blocks alive + + nalive = d_blocks.size (); + while (d_enabled && nalive > 0){ + + if (boost::this_thread::interruption_requested()) + break; + + gr_block *m = d_blocks[bi].get (); + gr_block_detail *d = m->detail().get (); + + LOG(*d_log << std::endl << m); + + if (d->done ()) + goto next_block; + + if (d->source_p ()){ + // Invoke sources as a last resort. As long as the previous pass + // made progress, don't call a source. + if (made_progress_last_pass){ + LOG(*d_log << " Skipping source\n"); + goto next_block; + } + + ninput_items_required.resize (0); + ninput_items.resize (0); + input_items.resize (0); + output_items.resize (d->noutputs ()); + + // determine the minimum available output space + noutput_items = min_available_space (d, m->output_multiple ()); + LOG(*d_log << " source\n noutput_items = " << noutput_items << std::endl); + if (noutput_items == -1) // we're done + goto were_done; + + if (noutput_items == 0){ // we're output blocked + LOG(*d_log << " BLKD_OUT\n"); + goto next_block; + } + + goto setup_call_to_work; // jump to common code + } + + else if (d->sink_p ()){ + ninput_items_required.resize (d->ninputs ()); + ninput_items.resize (d->ninputs ()); + input_items.resize (d->ninputs ()); + output_items.resize (0); + LOG(*d_log << " sink\n"); + + max_items_avail = 0; + for (int i = 0; i < d->ninputs (); i++){ + ninput_items[i] = d->input(i)->items_available(); + //if (ninput_items[i] == 0 && d->input(i)->done()) + if (ninput_items[i] < m->output_multiple() && d->input(i)->done()) + goto were_done; + + max_items_avail = std::max (max_items_avail, ninput_items[i]); + } + + // take a swag at how much output we can sink + noutput_items = (int) (max_items_avail * m->relative_rate ()); + noutput_items = round_down (noutput_items, m->output_multiple ()); + LOG(*d_log << " max_items_avail = " << max_items_avail << std::endl); + LOG(*d_log << " noutput_items = " << noutput_items << std::endl); + + if (noutput_items == 0){ // we're blocked on input + LOG(*d_log << " BLKD_IN\n"); + goto next_block; + } + + goto try_again; // Jump to code shared with regular case. + } + + else { + // do the regular thing + ninput_items_required.resize (d->ninputs ()); + ninput_items.resize (d->ninputs ()); + input_items.resize (d->ninputs ()); + output_items.resize (d->noutputs ()); + + max_items_avail = 0; + for (int i = 0; i < d->ninputs (); i++){ + ninput_items[i] = d->input(i)->items_available (); + max_items_avail = std::max (max_items_avail, ninput_items[i]); + } + + // determine the minimum available output space + noutput_items = min_available_space (d, m->output_multiple ()); + if (ENABLE_LOGGING){ + *d_log << " regular "; + if (m->relative_rate() >= 1.0) + *d_log << "1:" << m->relative_rate() << std::endl; + else + *d_log << 1.0/m->relative_rate() << ":1\n"; + *d_log << " max_items_avail = " << max_items_avail << std::endl; + *d_log << " noutput_items = " << noutput_items << std::endl; + } + if (noutput_items == -1) // we're done + goto were_done; + + if (noutput_items == 0){ // we're output blocked + LOG(*d_log << " BLKD_OUT\n"); + goto next_block; + } + +#if 0 + // Compute best estimate of noutput_items that we can really use. + noutput_items = + std::min ((unsigned) noutput_items, + std::max ((unsigned) m->output_multiple(), + round_up ((unsigned) (max_items_avail * m->relative_rate()), + m->output_multiple ()))); + + LOG(*d_log << " revised noutput_items = " << noutput_items << std::endl); +#endif + + try_again: + if (m->fixed_rate()){ + // try to work it forward starting with max_items_avail. + // We want to try to consume all the input we've got. + int reqd_noutput_items = m->fixed_rate_ninput_to_noutput(max_items_avail); + reqd_noutput_items = round_up(reqd_noutput_items, m->output_multiple()); + if (reqd_noutput_items > 0 && reqd_noutput_items <= noutput_items) + noutput_items = reqd_noutput_items; + } + + // ask the block how much input they need to produce noutput_items + m->forecast (noutput_items, ninput_items_required); + + // See if we've got sufficient input available + + int i; + for (i = 0; i < d->ninputs (); i++) + if (ninput_items_required[i] > ninput_items[i]) // not enough + break; + + if (i < d->ninputs ()){ // not enough input on input[i] + // if we can, try reducing the size of our output request + if (noutput_items > m->output_multiple ()){ + noutput_items /= 2; + noutput_items = round_up (noutput_items, m->output_multiple ()); + goto try_again; + } + + // We're blocked on input + LOG(*d_log << " BLKD_IN\n"); + if (d->input(i)->done()) // If the upstream block is done, we're done + goto were_done; + + // Is it possible to ever fulfill this request? + if (ninput_items_required[i] > d->input(i)->max_possible_items_available ()){ + // Nope, never going to happen... + std::cerr << "\nsched: <gr_block " << m->name() + << " (" << m->unique_id() << ")>" + << " is requesting more input data\n" + << " than we can provide.\n" + << " ninput_items_required = " + << ninput_items_required[i] << "\n" + << " max_possible_items_available = " + << d->input(i)->max_possible_items_available() << "\n" + << " If this is a filter, consider reducing the number of taps.\n"; + goto were_done; + } + + goto next_block; + } + + // We've got enough data on each input to produce noutput_items. + // Finish setting up the call to work. + + for (int i = 0; i < d->ninputs (); i++) + input_items[i] = d->input(i)->read_pointer(); + + setup_call_to_work: + + for (int i = 0; i < d->noutputs (); i++) + output_items[i] = d->output(i)->write_pointer(); + + // Do the actual work of the block + int n = m->general_work (noutput_items, ninput_items, + input_items, output_items); + LOG(*d_log << " general_work: noutput_items = " << noutput_items + << " result = " << n << std::endl); + + if (n == -1) // block is done + goto were_done; + + d->produce_each (n); // advance write pointers + if (n > 0) + making_progress = true; + + goto next_block; + } + assert (0); + + were_done: + LOG(*d_log << " were_done\n"); + d->set_done (true); + nalive--; + + next_block: + if (++bi >= d_blocks.size ()){ + bi = 0; + made_progress_last_pass = making_progress; + making_progress = false; + } + } + + for (unsigned i = 0; i < d_blocks.size (); i++) // disable any drivers, etc. + d_blocks[i]->stop(); +} diff --git a/gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.h b/gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.h new file mode 100644 index 000000000..3a95c7194 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.h @@ -0,0 +1,62 @@ +/* -*- 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_SINGLE_THREADED_SCHEDULER_H +#define INCLUDED_GR_SINGLE_THREADED_SCHEDULER_H + +#include <gr_core_api.h> +#include <gr_runtime_types.h> +#include <fstream> + +class gr_single_threaded_scheduler; +typedef boost::shared_ptr<gr_single_threaded_scheduler> gr_single_threaded_scheduler_sptr; + + +/*! + * \brief Simple scheduler for stream computations. + * \ingroup internal + */ + +class GR_CORE_API gr_single_threaded_scheduler { + public: + ~gr_single_threaded_scheduler (); + + void run (); + void stop (); + + private: + const std::vector<gr_block_sptr> d_blocks; + volatile bool d_enabled; + std::ofstream *d_log; + + gr_single_threaded_scheduler (const std::vector<gr_block_sptr> &blocks); + + void main_loop (); + + friend GR_CORE_API gr_single_threaded_scheduler_sptr + gr_make_single_threaded_scheduler (const std::vector<gr_block_sptr> &blocks); +}; + +GR_CORE_API gr_single_threaded_scheduler_sptr +gr_make_single_threaded_scheduler (const std::vector<gr_block_sptr> &blocks); + +#endif /* INCLUDED_GR_SINGLE_THREADED_SCHEDULER_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.i b/gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.i new file mode 100644 index 000000000..7305cc9ad --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.i @@ -0,0 +1,54 @@ +/* -*- 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. + */ + +#include <gr_runtime.h> + +class gr_single_threaded_scheduler; +typedef boost::shared_ptr<gr_single_threaded_scheduler> gr_single_threaded_scheduler_sptr; +%template(gr_single_threaded_scheduler_sptr) boost::shared_ptr<gr_single_threaded_scheduler>; +%rename(single_threaded_scheduler) gr_make_single_threaded_scheduler; +%ignore gr_single_threaded_scheduler; + +gr_single_threaded_scheduler_sptr +gr_make_single_threaded_scheduler (const std::vector<gr_block_sptr> &modules); + +class gr_single_threaded_scheduler { + public: + ~gr_single_threaded_scheduler (); + + // void run (); + void stop (); + + private: + gr_single_threaded_scheduler (const std::vector<gr_block_sptr> &modules); +}; + +#ifdef SWIGPYTHON +%inline %{ + void sts_pyrun (gr_single_threaded_scheduler_sptr s) { + Py_BEGIN_ALLOW_THREADS; // release global interpreter lock + s->run (); + Py_END_ALLOW_THREADS; // acquire global interpreter lock + } +%} +#endif + diff --git a/gnuradio-core/src/lib/runtime/gr_sptr_magic.cc b/gnuradio-core/src/lib/runtime/gr_sptr_magic.cc new file mode 100644 index 000000000..7fdadf24a --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_sptr_magic.cc @@ -0,0 +1,72 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_sptr_magic.h> +#include <gr_hier_block2.h> +#include <map> +#include <stdexcept> + + +#include <gruel/thread.h> + +namespace gnuradio { + + static gruel::mutex s_mutex; + typedef std::map<gr_basic_block*, gr_basic_block_sptr> sptr_map; + static sptr_map s_map; + + void + detail::sptr_magic::create_and_stash_initial_sptr(gr_hier_block2 *p) + { + gr_basic_block_sptr sptr(p); + gruel::scoped_lock guard(s_mutex); + s_map.insert(sptr_map::value_type(static_cast<gr_basic_block *>(p), sptr)); + } + + + gr_basic_block_sptr + detail::sptr_magic::fetch_initial_sptr(gr_basic_block *p) + { + /* + * If p isn't a subclass of gr_hier_block2, just create the + * shared ptr and return it. + */ + gr_hier_block2 *hb2 = dynamic_cast<gr_hier_block2 *>(p); + if (!hb2){ + return gr_basic_block_sptr(p); + } + + /* + * p is a subclass of gr_hier_block2, thus we've already created the shared pointer + * and stashed it away. Fish it out and return it. + */ + gruel::scoped_lock guard(s_mutex); + sptr_map::iterator pos = s_map.find(static_cast<gr_basic_block *>(p)); + if (pos == s_map.end()) + throw std::invalid_argument("gr_sptr_magic: invalid pointer!"); + + gr_basic_block_sptr sptr = pos->second; + s_map.erase(pos); + return sptr; + } +}; diff --git a/gnuradio-core/src/lib/runtime/gr_sptr_magic.h b/gnuradio-core/src/lib/runtime/gr_sptr_magic.h new file mode 100644 index 000000000..d9c7f26c4 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_sptr_magic.h @@ -0,0 +1,52 @@ +/* -*- 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef INCLUDED_GR_SPTR_MAGIC_H +#define INCLUDED_GR_SPTR_MAGIC_H + +#include <gr_core_api.h> +#include <boost/shared_ptr.hpp> + +class gr_basic_block; +class gr_hier_block2; + +namespace gnuradio { + + namespace detail { + + class GR_CORE_API sptr_magic { + public: + static boost::shared_ptr<gr_basic_block> fetch_initial_sptr(gr_basic_block *p); + static void create_and_stash_initial_sptr(gr_hier_block2 *p); + }; + }; + + /* + * \brief New! Improved! Standard method to get/create the boost::shared_ptr for a block. + */ + template<class T> + boost::shared_ptr<T> + get_initial_sptr(T *p) + { + return boost::shared_ptr<T>(p);//return boost::dynamic_pointer_cast<T, gr_basic_block>(detail::sptr_magic::fetch_initial_sptr(p)); + } +}; + +#endif /* INCLUDED_GR_SPTR_MAGIC_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_sync_block.cc b/gnuradio-core/src/lib/runtime/gr_sync_block.cc new file mode 100644 index 000000000..3c79e630d --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_sync_block.cc @@ -0,0 +1,55 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_sync_block.h> + +gr_sync_block::gr_sync_block(void) +{ + //NOP +} + +gr_sync_block::gr_sync_block( + const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature +): + gr_block(name, input_signature, output_signature) +{ + this->set_fixed_rate(true); +} + +gr_sync_block::~gr_sync_block(void) +{ + //NOP +} + +int gr_sync_block::work( + int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items +){ + throw std::runtime_error("gr_block subclasses must overload general_work!"); +} diff --git a/gnuradio-core/src/lib/runtime/gr_sync_block.h b/gnuradio-core/src/lib/runtime/gr_sync_block.h new file mode 100644 index 000000000..0f3daccf2 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_sync_block.h @@ -0,0 +1,74 @@ +/* + * Copyright 2012-2013 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_GNURADIO_GR_SYNC_BLOCK_H +#define INCLUDED_GNURADIO_GR_SYNC_BLOCK_H + +#include <gr_block.h> + +struct GR_CORE_API gr_sync_block : public gr_block +{ + gr_sync_block(void); + + gr_sync_block( + const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature + ); + + virtual ~gr_sync_block(void); + + //! implements work -> calls work + int general_work( + int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items + ); + + /*! + * \brief just like gr_block::general_work, only this arranges to call consume_each for you + * + * The user must override work to define the signal processing code + */ + virtual int work( + int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items + ); + +}; + +GRAS_FORCE_INLINE int gr_sync_block::general_work( + int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items +){ + const int work_ret = this->work(noutput_items, input_items, output_items); + if (work_ret > 0) + { + this->consume_each((decimation()*size_t(work_ret))/interpolation()); + } + return work_ret; +} + +#endif /*INCLUDED_GNURADIO_GR_SYNC_BLOCK_H*/ diff --git a/gnuradio-core/src/lib/runtime/gr_sync_block.i b/gnuradio-core/src/lib/runtime/gr_sync_block.i new file mode 100644 index 000000000..d3e1bb957 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_sync_block.i @@ -0,0 +1,29 @@ +/* -*- 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. + */ +class gr_sync_block : public gr_block +{ + protected: + + gr_sync_block (const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); +}; diff --git a/gnuradio-core/src/lib/runtime/gr_sync_decimator.cc b/gnuradio-core/src/lib/runtime/gr_sync_decimator.cc new file mode 100644 index 000000000..a39c53b09 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_sync_decimator.cc @@ -0,0 +1,48 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_sync_decimator.h> + +gr_sync_decimator::gr_sync_decimator(void) +{ + //NOP +} + +gr_sync_decimator::gr_sync_decimator( + const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature, + const size_t decim_rate +): + gr_sync_block(name, input_signature, output_signature) +{ + this->set_decimation(decim_rate); +} + +gr_sync_decimator::~gr_sync_decimator(void) +{ + //NOP +} diff --git a/gnuradio-core/src/lib/runtime/gr_sync_decimator.h b/gnuradio-core/src/lib/runtime/gr_sync_decimator.h new file mode 100644 index 000000000..32edfd78e --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_sync_decimator.h @@ -0,0 +1,43 @@ +/* + * Copyright 2012-2013 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_GNURADIO_GR_SYNC_DECIMATOR_H +#define INCLUDED_GNURADIO_GR_SYNC_DECIMATOR_H + +#include <gr_sync_block.h> + +struct GR_CORE_API gr_sync_decimator : gr_sync_block +{ + + gr_sync_decimator(void); + + gr_sync_decimator( + const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature, + const size_t decim_rate + ); + + virtual ~gr_sync_decimator(void); + +}; + +#endif /*INCLUDED_GNURADIO_GR_SYNC_DECIMATOR_H*/ diff --git a/gnuradio-core/src/lib/runtime/gr_sync_decimator.i b/gnuradio-core/src/lib/runtime/gr_sync_decimator.i new file mode 100644 index 000000000..af4574b19 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_sync_decimator.i @@ -0,0 +1,31 @@ +/* -*- 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. + */ + +class gr_sync_decimator : public gr_sync_block +{ + protected: + + gr_sync_decimator (const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature, + unsigned decimation); +}; diff --git a/gnuradio-core/src/lib/runtime/gr_sync_interpolator.cc b/gnuradio-core/src/lib/runtime/gr_sync_interpolator.cc new file mode 100644 index 000000000..17f60e613 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_sync_interpolator.cc @@ -0,0 +1,48 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_sync_interpolator.h> + +gr_sync_interpolator::gr_sync_interpolator(void) +{ + //NOP +} + +gr_sync_interpolator::gr_sync_interpolator( + const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature, + const size_t interp_rate +): + gr_sync_block(name, input_signature, output_signature) +{ + this->set_interpolation(interp_rate); +} + +gr_sync_interpolator::~gr_sync_interpolator(void) +{ + //NOP +} diff --git a/gnuradio-core/src/lib/runtime/gr_sync_interpolator.h b/gnuradio-core/src/lib/runtime/gr_sync_interpolator.h new file mode 100644 index 000000000..81c17c18e --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_sync_interpolator.h @@ -0,0 +1,43 @@ +/* + * Copyright 2012-2013 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_GNURADIO_GR_SYNC_INTERPOLATOR_H +#define INCLUDED_GNURADIO_GR_SYNC_INTERPOLATOR_H + +#include <gr_sync_block.h> + +struct GR_CORE_API gr_sync_interpolator : gr_sync_block +{ + + gr_sync_interpolator(void); + + gr_sync_interpolator( + const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature, + const size_t interp_rate + ); + + virtual ~gr_sync_interpolator(void); + +}; + +#endif /*INCLUDED_GNURADIO_GR_SYNC_INTERPOLATOR_H*/ diff --git a/gnuradio-core/src/lib/runtime/gr_sync_interpolator.i b/gnuradio-core/src/lib/runtime/gr_sync_interpolator.i new file mode 100644 index 000000000..6f8b08252 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_sync_interpolator.i @@ -0,0 +1,31 @@ +/* -*- 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. + */ + +class gr_sync_interpolator : public gr_sync_block +{ + protected: + + gr_sync_interpolator (const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature, + unsigned interpolation); +}; diff --git a/gnuradio-core/src/lib/runtime/gr_sys_paths.cc b/gnuradio-core/src/lib/runtime/gr_sys_paths.cc new file mode 100644 index 000000000..b4918af33 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_sys_paths.cc @@ -0,0 +1,55 @@ +/* + * 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 <gr_sys_paths.h> +#include <cstdlib> //getenv +#include <cstdio> //P_tmpdir (maybe) + +const char *gr_tmp_path(){ + const char *path; + + //first case, try TMP environment variable + path = getenv("TMP"); + if (path) return path; + + //second case, try P_tmpdir when its defined + #ifdef P_tmpdir + if (P_tmpdir) return P_tmpdir; + #endif /*P_tmpdir*/ + + //fall-through case, nothing worked + return "/tmp"; +} + +const char *gr_appdata_path(){ + const char *path; + + //first case, try HOME environment variable (unix) + path = getenv("HOME"); + if (path) return path; + + //second case, try APPDATA environment variable (windows) + path = getenv("APPDATA"); + if (path) return path; + + //fall-through case, nothing worked + return gr_tmp_path(); +} diff --git a/gnuradio-core/src/lib/runtime/gr_sys_paths.h b/gnuradio-core/src/lib/runtime/gr_sys_paths.h new file mode 100644 index 000000000..bd51ebdf9 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_sys_paths.h @@ -0,0 +1,33 @@ +/* + * 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 _GR_SYS_PATHS_H_ +#define _GR_SYS_PATHS_H_ + +#include <gr_core_api.h> + +//! directory to create temporary files +GR_CORE_API const char *gr_tmp_path(); + +//! directory to store application data +GR_CORE_API const char *gr_appdata_path(); + +#endif /* _GR_SYS_PATHS_H_ */ diff --git a/gnuradio-core/src/lib/runtime/gr_tags.h b/gnuradio-core/src/lib/runtime/gr_tags.h new file mode 100644 index 000000000..a9ca90235 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_tags.h @@ -0,0 +1,55 @@ +/* + * 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_GR_TAGS_H +#define INCLUDED_GR_TAGS_H + +#include <gr_core_api.h> +#include <gruel/pmt.h> + +struct GR_CORE_API gr_tag_t{ + + //! the item \p tag occurred at (as a uint64_t) + uint64_t offset; + + //! the key of \p tag (as a PMT symbol) + pmt::pmt_t key; + + //! the value of \p tag (as a PMT) + pmt::pmt_t value; + + //! the source ID of \p tag (as a PMT) + pmt::pmt_t srcid; + + //! Comparison function to test which tag, \p x or \p y, came first in time + static inline bool offset_compare( + const gr_tag_t &x, const gr_tag_t &y + ){ + return x.offset < y.offset; + } + + inline bool operator == (const gr_tag_t &t) const + { + return (t.key == key) && (t.value == value) && (t.srcid == srcid) && (t.offset == offset); + } +}; + +#endif /*INCLUDED_GR_TAGS_H*/ diff --git a/gnuradio-core/src/lib/runtime/gr_tags.i b/gnuradio-core/src/lib/runtime/gr_tags.i new file mode 100644 index 000000000..f2ee69ce8 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_tags.i @@ -0,0 +1,32 @@ +/* + * 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 <gr_tags.h> +%} + +%import <pmt_swig.i> //for pmt support + +%include <gr_tags.h> + +//gives support for a vector of tags (get tags in range) +%include "std_vector.i" +%template(tags_vector_t) std::vector<gr_tag_t>; diff --git a/gnuradio-core/src/lib/runtime/gr_timer.h b/gnuradio-core/src/lib/runtime/gr_timer.h new file mode 100644 index 000000000..e0b4cc437 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_timer.h @@ -0,0 +1,84 @@ +/* -*- 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_TIMER_H +#define INCLUDED_GR_TIMER_H + +#include <gr_core_api.h> +#include <gr_types.h> + +class gr_timer; + +typedef boost::shared_ptr<gr_timer> gr_timer_sptr; + +GR_CORE_API typedef void (*gr_timer_hook)(gr_timer *, void *); + +/*! + * \brief create a timeout. + * + * \ingroup misc + * gr_timer_hook is called when timer fires. + */ +GR_CORE_API gr_timer_sptr gr_make_timer (gr_timer_hook, void *); + +/*! + * \brief implement timeouts + */ +class GR_CORE_API gr_timer { + double d_expiry; + double d_period; + gr_timer_hook d_hook; + void *d_hook_arg; + + friend GR_CORE_API gr_timer_sptr gr_make_timer (gr_timer_hook, void *); + + gr_timer (...); + +public: + ~gr_timer (); + + //! return absolute current time (seconds since the epoc). + static double now (); + + /*! + * \brief schedule timer to fire at abs_when + * \param abs_when absolute time in seconds since the epoc. + */ + void schedule_at (double abs_when); + + /*! + * \brief schedule timer to fire rel_when seconds from now. + * \param rel_when relative time in seconds from now. + */ + void schedule_after (double rel_when); // relative time in seconds + + /*! + * \brief schedule a periodic timeout. + * \param abs_when absolute time to fire first time + * \param period time between firings + */ + void schedule_periodic (double abs_when, double period); + + //! cancel timer + void unschedule (); +}; + +#endif /* INCLUDED_GR_TIMER_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_top_block.cc b/gnuradio-core/src/lib/runtime/gr_top_block.cc new file mode 100644 index 000000000..fa090b4ef --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_top_block.cc @@ -0,0 +1,95 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <unistd.h> +#include <gr_top_block.h> +#include <boost/detail/atomic_count.hpp> + +static boost::detail::atomic_count unique_id_pool(0); + +gr_top_block::gr_top_block(void): + //cannot make a null top block, use name constructor + gras::TopBlock("top"), + _unique_id(++unique_id_pool), + _name("top") +{ + //NOP +} + +gr_top_block::gr_top_block(const std::string &name): + gras::TopBlock(name), + _unique_id(++unique_id_pool), + _name(name) +{ + //NOP +} + +gr_top_block_sptr gr_make_top_block(const std::string &name) +{ + return gr_top_block_sptr(new gr_top_block(name)); +} + +void gr_top_block::start(const size_t max_items) +{ + this->set_max_noutput_items(max_items); + this->start(); +} + +void gr_top_block::run(const size_t max_items) +{ + this->set_max_noutput_items(max_items); + this->run(); +} + +int gr_top_block::max_noutput_items(void) const +{ + return this->global_config().maximum_output_items; +} + +void gr_top_block::set_max_noutput_items(int max_items) +{ + this->global_config().maximum_output_items = max_items; +} + +void gr_top_block::run(void) +{ + gras::TopBlock::run(); +} + +void gr_top_block::start(void) +{ + gras::TopBlock::start(); +} + +void gr_top_block::stop(void) +{ + gras::TopBlock::stop(); +} + +void gr_top_block::wait(void) +{ + gras::TopBlock::wait(); +} diff --git a/gnuradio-core/src/lib/runtime/gr_top_block.h b/gnuradio-core/src/lib/runtime/gr_top_block.h new file mode 100644 index 000000000..4e4becd1f --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_top_block.h @@ -0,0 +1,67 @@ +/* + * Copyright 2012-2013 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_GNURADIO_GR_TOP_BLOCK_H +#define INCLUDED_GNURADIO_GR_TOP_BLOCK_H + +#include <gr_core_api.h> +#include <gras/top_block.hpp> +#include <gr_hier_block2.h> + +struct GR_CORE_API gr_top_block : gras::TopBlock +{ + + gr_top_block(void); + + gr_top_block(const std::string &name); + + long unique_id(void) const{return _unique_id;} + std::string name(void) const{return _name;} + long _unique_id; + std::string _name; + + void start(const size_t max_items); + + void run(const size_t max_items); + + int max_noutput_items(void) const; + + void set_max_noutput_items(int max_items); + + void run(void); + + virtual void start(void); + + virtual void stop(void); + + virtual void wait(void); + + inline void lock(void){} + + inline void unlock(void){this->commit();} + +}; + +typedef boost::shared_ptr<gr_top_block> gr_top_block_sptr; + +GR_CORE_API gr_top_block_sptr gr_make_top_block(const std::string &name); + +#endif /*INCLUDED_GNURADIO_GR_TOP_BLOCK_H*/ diff --git a/gnuradio-core/src/lib/runtime/gr_top_block.i b/gnuradio-core/src/lib/runtime/gr_top_block.i new file mode 100644 index 000000000..6ae4c65a9 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_top_block.i @@ -0,0 +1,73 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,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. + */ + +class gr_top_block; +typedef boost::shared_ptr<gr_top_block> gr_top_block_sptr; +%template(gr_top_block_sptr) boost::shared_ptr<gr_top_block>; + +// Hack to have a Python shim implementation of gr.top_block +// that instantiates one of these and passes through calls +%rename(top_block_swig) gr_make_top_block; +gr_top_block_sptr gr_make_top_block(const std::string name) + throw (std::logic_error); + +class gr_top_block : public gr_hier_block2 +{ +private: + gr_top_block(const std::string &name); + +public: + ~gr_top_block(); + + void start(int max_noutput_items=100000) throw (std::runtime_error); + void stop(); + //void wait(); + //void run() throw (std::runtime_error); + void lock(); + void unlock() throw (std::runtime_error); + void dump(); + + int max_noutput_items(); + void set_max_noutput_items(int nmax); + + gr_top_block_sptr to_top_block(); // Needed for Python type coercion +}; + +#ifdef SWIGPYTHON + +%inline %{ +void top_block_run_unlocked(gr_top_block_sptr r) throw (std::runtime_error) +{ + Py_BEGIN_ALLOW_THREADS; // release global interpreter lock + r->run(); + Py_END_ALLOW_THREADS; // acquire global interpreter lock +} + +void top_block_wait_unlocked(gr_top_block_sptr r) throw (std::runtime_error) +{ + Py_BEGIN_ALLOW_THREADS; // release global interpreter lock + r->wait(); + Py_END_ALLOW_THREADS; // acquire global interpreter lock +} +%} + +#endif diff --git a/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc b/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc new file mode 100644 index 000000000..4a3694163 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_top_block_impl.cc @@ -0,0 +1,195 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_top_block.h> +#include <gr_top_block_impl.h> +#include <gr_flat_flowgraph.h> +#include <gr_scheduler_sts.h> +#include <gr_scheduler_tpb.h> + +#include <stdexcept> +#include <iostream> +#include <string.h> +#include <unistd.h> +#include <stdlib.h> + +#define GR_TOP_BLOCK_IMPL_DEBUG 0 + + +typedef gr_scheduler_sptr (*scheduler_maker)(gr_flat_flowgraph_sptr ffg, + int max_noutput_items); + +static struct scheduler_table { + const char *name; + scheduler_maker f; +} scheduler_table[] = { + { "TPB", gr_scheduler_tpb::make }, // first entry is default + { "STS", gr_scheduler_sts::make } +}; + +static gr_scheduler_sptr +make_scheduler(gr_flat_flowgraph_sptr ffg, int max_noutput_items) +{ + static scheduler_maker factory = 0; + + if (factory == 0){ + char *v = getenv("GR_SCHEDULER"); + if (!v) + factory = scheduler_table[0].f; // use default + else { + for (size_t i = 0; i < sizeof(scheduler_table)/sizeof(scheduler_table[0]); i++){ + if (strcmp(v, scheduler_table[i].name) == 0){ + factory = scheduler_table[i].f; + break; + } + } + if (factory == 0){ + std::cerr << "warning: Invalid GR_SCHEDULER environment variable value \"" + << v << "\". Using \"" << scheduler_table[0].name << "\"\n"; + factory = scheduler_table[0].f; + } + } + } + return factory(ffg, max_noutput_items); +} + + +gr_top_block_impl::gr_top_block_impl(gr_top_block *owner) + : d_owner(owner), d_ffg(), + d_state(IDLE), d_lock_count(0) +{ +} + +gr_top_block_impl::~gr_top_block_impl() +{ + d_owner = 0; +} + +void +gr_top_block_impl::start(int max_noutput_items) +{ + gruel::scoped_lock l(d_mutex); + + d_max_noutput_items = max_noutput_items; + + if (d_state != IDLE) + throw std::runtime_error("top_block::start: top block already running or wait() not called after previous stop()"); + + if (d_lock_count > 0) + throw std::runtime_error("top_block::start: can't start with flow graph locked"); + + // Create new flat flow graph by flattening hierarchy + d_ffg = d_owner->flatten(); + + // Validate new simple flow graph and wire it up + d_ffg->validate(); + d_ffg->setup_connections(); + + d_scheduler = make_scheduler(d_ffg, d_max_noutput_items); + d_state = RUNNING; +} + +void +gr_top_block_impl::stop() +{ + if (d_scheduler) + d_scheduler->stop(); +} + + +void +gr_top_block_impl::wait() +{ + if (d_scheduler) + d_scheduler->wait(); + + d_state = IDLE; +} + +// N.B. lock() and unlock() cannot be called from a flow graph thread or +// deadlock will occur when reconfiguration happens +void +gr_top_block_impl::lock() +{ + gruel::scoped_lock lock(d_mutex); + d_lock_count++; +} + +void +gr_top_block_impl::unlock() +{ + gruel::scoped_lock lock(d_mutex); + + if (d_lock_count <= 0){ + d_lock_count = 0; // fix it, then complain + throw std::runtime_error("unpaired unlock() call"); + } + + d_lock_count--; + if (d_lock_count > 0 || d_state == IDLE) // nothing to do + return; + + restart(); +} + +/* + * restart is called with d_mutex held + */ +void +gr_top_block_impl::restart() +{ + stop(); // Stop scheduler and wait for completion + wait(); + + // Create new simple flow graph + gr_flat_flowgraph_sptr new_ffg = d_owner->flatten(); + new_ffg->validate(); // check consistency, sanity, etc + new_ffg->merge_connections(d_ffg); // reuse buffers, etc + d_ffg = new_ffg; + + // Create a new scheduler to execute it + d_scheduler = make_scheduler(d_ffg, d_max_noutput_items); + d_state = RUNNING; +} + +void +gr_top_block_impl::dump() +{ + if (d_ffg) + d_ffg->dump(); +} + +int +gr_top_block_impl::max_noutput_items() +{ + return d_max_noutput_items; +} + +void +gr_top_block_impl::set_max_noutput_items(int nmax) +{ + d_max_noutput_items = nmax; +} diff --git a/gnuradio-core/src/lib/runtime/gr_top_block_impl.h b/gnuradio-core/src/lib/runtime/gr_top_block_impl.h new file mode 100644 index 000000000..f55c3f021 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_top_block_impl.h @@ -0,0 +1,85 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,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_TOP_BLOCK_IMPL_H +#define INCLUDED_GR_TOP_BLOCK_IMPL_H + +#include <gr_core_api.h> +#include <gr_scheduler.h> +#include <gruel/thread.h> + +/*! + *\brief Abstract implementation details of gr_top_block + * \ingroup internal + * + * The actual implementation of gr_top_block. Separate class allows + * decoupling of changes from dependent classes. + * + */ +class GR_CORE_API gr_top_block_impl +{ +public: + gr_top_block_impl(gr_top_block *owner); + ~gr_top_block_impl(); + + // Create and start scheduler threads + void start(int max_noutput_items=100000); + + // Signal scheduler threads to stop + void stop(); + + // Wait for scheduler threads to exit + void wait(); + + // Lock the top block to allow reconfiguration + void lock(); + + // Unlock the top block at end of reconfiguration + void unlock(); + + // Dump the flowgraph to stdout + void dump(); + + // Get the number of max noutput_items in the flowgraph + int max_noutput_items(); + + // Set the maximum number of noutput_items in the flowgraph + void set_max_noutput_items(int nmax); + +protected: + + enum tb_state { IDLE, RUNNING }; + + gr_top_block *d_owner; + gr_flat_flowgraph_sptr d_ffg; + gr_scheduler_sptr d_scheduler; + + gruel::mutex d_mutex; // protects d_state and d_lock_count + tb_state d_state; + int d_lock_count; + int d_max_noutput_items; + +private: + void restart(); +}; + +#endif /* INCLUDED_GR_TOP_BLOCK_IMPL_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_tpb_detail.cc b/gnuradio-core/src/lib/runtime/gr_tpb_detail.cc new file mode 100644 index 000000000..46eb6bbe0 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_tpb_detail.cc @@ -0,0 +1,70 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_tpb_detail.h> +#include <gr_block.h> +#include <gr_block_detail.h> +#include <gr_buffer.h> + +using namespace pmt; + +/* + * We assume that no worker threads are ever running when the + * graph structure is being manipulated, thus it's safe for us to poke + * around in our neighbors w/o holding any locks. + */ + +void +gr_tpb_detail::notify_upstream(gr_block_detail *d) +{ + // For each of our inputs, tell the guy upstream that we've consumed + // some input, and that he most likely has more output buffer space + // available. + + for (size_t i = 0; i < d->d_input.size(); i++){ + // Can you say, "pointer chasing?" + d->d_input[i]->buffer()->link()->detail()->d_tpb.set_output_changed(); + } +} + +void +gr_tpb_detail::notify_downstream(gr_block_detail *d) +{ + // For each of our outputs, tell the guys downstream that they have + // new input available. + + for (size_t i = 0; i < d->d_output.size(); i++){ + gr_buffer_sptr buf = d->d_output[i]; + for (size_t j = 0, k = buf->nreaders(); j < k; j++) + buf->reader(j)->link()->detail()->d_tpb.set_input_changed(); + } +} + +void +gr_tpb_detail::notify_neighbors(gr_block_detail *d) +{ + notify_downstream(d); + notify_upstream(d); +} + diff --git a/gnuradio-core/src/lib/runtime/gr_tpb_detail.h b/gnuradio-core/src/lib/runtime/gr_tpb_detail.h new file mode 100644 index 000000000..69feb6007 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_tpb_detail.h @@ -0,0 +1,89 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2009 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef INCLUDED_GR_TPB_DETAIL_H +#define INCLUDED_GR_TPB_DETAIL_H + +#include <gr_core_api.h> +#include <gruel/thread.h> +#include <deque> +#include <gruel/pmt.h> + +class gr_block_detail; + +/*! + * \brief used by thread-per-block scheduler + */ +struct GR_CORE_API gr_tpb_detail { + + gruel::mutex mutex; //< protects all vars + bool input_changed; + gruel::condition_variable input_cond; + bool output_changed; + gruel::condition_variable output_cond; + +public: + gr_tpb_detail() + : input_changed(false), output_changed(false) { } + + //! Called by us to tell all our upstream blocks that their output may have changed. + void notify_upstream(gr_block_detail *d); + + //! Called by us to tell all our downstream blocks that their input may have changed. + void notify_downstream(gr_block_detail *d); + + //! Called by us to notify both upstream and downstream + void notify_neighbors(gr_block_detail *d); + + //! Called by pmt msg posters + void notify_msg(){ + input_cond.notify_one(); + output_cond.notify_one(); + } + + //! Called by us + void clear_changed() + { + gruel::scoped_lock guard(mutex); + input_changed = false; + output_changed = false; + } + +private: + + //! Used by notify_downstream + void set_input_changed() + { + gruel::scoped_lock guard(mutex); + input_changed = true; + input_cond.notify_one(); + } + + //! Used by notify_upstream + void set_output_changed() + { + gruel::scoped_lock guard(mutex); + output_changed = true; + output_cond.notify_one(); + } + +}; + +#endif /* INCLUDED_GR_TPB_DETAIL_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc b/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc new file mode 100644 index 000000000..679fd1512 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.cc @@ -0,0 +1,151 @@ +/* -*- 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_tpb_thread_body.h> +#include <gr_prefs.h> +#include <iostream> +#include <boost/thread.hpp> +#include <gruel/pmt.h> +#include <boost/foreach.hpp> + +using namespace pmt; + +gr_tpb_thread_body::gr_tpb_thread_body(gr_block_sptr block, int max_noutput_items) + : d_exec(block, max_noutput_items) +{ + //std::cerr << "gr_tpb_thread_body: " << block << std::endl; + + gr_block_detail *d = block->detail().get(); + gr_block_executor::state s; + pmt_t msg; + + d->threaded = true; + d->thread = gruel::get_current_thread_id(); + + gr_prefs *p = gr_prefs::singleton(); + size_t max_nmsgs = static_cast<size_t>(p->get_long("DEFAULT", "max_messages", 100)); + + // Set thread affinity if it was set before fg was started. + if(block->processor_affinity().size() > 0) { + gruel::thread_bind_to_processor(d->thread, block->processor_affinity()); + } + + while (1){ + boost::this_thread::interruption_point(); + + // handle any queued up messages + //BOOST_FOREACH( pmt::pmt_t port, block->msg_queue.keys() ) + + BOOST_FOREACH( gr_basic_block::msg_queue_map_t::value_type &i, block->msg_queue ) + { + // Check if we have a message handler attached before getting + // any messages. This is mostly a protection for the unknown + // startup sequence of the threads. + if(block->has_msg_handler(i.first)) { + while ((msg = block->delete_head_nowait(i.first))){ + block->dispatch_msg(i.first,msg); + } + } + else { + // If we don't have a handler but are building up messages, + // prune the queue from the front to keep memory in check. + if(block->nmsgs(i.first) > max_nmsgs) + msg = block->delete_head_nowait(i.first); + } + } + + d->d_tpb.clear_changed(); + // run one iteration if we are a connected stream block + if(d->noutputs() >0 || d->ninputs()>0){ + s = d_exec.run_one_iteration(); + } else { + s = gr_block_executor::BLKD_IN; + } + + switch(s){ + case gr_block_executor::READY: // Tell neighbors we made progress. + d->d_tpb.notify_neighbors(d); + break; + + case gr_block_executor::READY_NO_OUTPUT: // Notify upstream only + d->d_tpb.notify_upstream(d); + break; + + case gr_block_executor::DONE: // Game over. + d->d_tpb.notify_neighbors(d); + return; + + case gr_block_executor::BLKD_IN: // Wait for input. + { + gruel::scoped_lock guard(d->d_tpb.mutex); + while (!d->d_tpb.input_changed){ + + // wait for input or message + while(!d->d_tpb.input_changed && block->empty_p()) + d->d_tpb.input_cond.wait(guard); + + // handle all pending messages + BOOST_FOREACH( gr_basic_block::msg_queue_map_t::value_type &i, block->msg_queue ) + { + while ((msg = block->delete_head_nowait(i.first))){ + guard.unlock(); // release lock while processing msg + block->dispatch_msg(i.first, msg); + guard.lock(); + } + } + } + } + break; + + + case gr_block_executor::BLKD_OUT: // Wait for output buffer space. + { + gruel::scoped_lock guard(d->d_tpb.mutex); + while (!d->d_tpb.output_changed){ + + // wait for output room or message + while(!d->d_tpb.output_changed && block->empty_p()) + d->d_tpb.output_cond.wait(guard); + + // handle all pending messages + BOOST_FOREACH( gr_basic_block::msg_queue_map_t::value_type &i, block->msg_queue ) + { + while ((msg = block->delete_head_nowait(i.first))){ + guard.unlock(); // release lock while processing msg + block->dispatch_msg(i.first,msg); + guard.lock(); + } + } + } + } + break; + + default: + assert(0); + } + } +} + +gr_tpb_thread_body::~gr_tpb_thread_body() +{ +} diff --git a/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.h b/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.h new file mode 100644 index 000000000..f920663a2 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_tpb_thread_body.h @@ -0,0 +1,46 @@ +/* -*- 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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ +#ifndef INCLUDED_GR_TPB_THREAD_BODY_H +#define INCLUDED_GR_TPB_THREAD_BODY_H + +#include <gr_core_api.h> +#include <gr_block_executor.h> +#include <gr_block.h> +#include <gr_block_detail.h> + +/*! + * \brief The body of each thread-per-block thread. + * + * One of these is instantiated in its own thread for each block. The + * constructor turns into the main loop which returns when the block is + * done or is interrupted. + */ + +class GR_CORE_API gr_tpb_thread_body { + gr_block_executor d_exec; + +public: + gr_tpb_thread_body(gr_block_sptr block, int max_noutput_items=100000); + ~gr_tpb_thread_body(); +}; + + +#endif /* INCLUDED_GR_TPB_THREAD_BODY_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_types.h b/gnuradio-core/src/lib/runtime/gr_types.h new file mode 100644 index 000000000..b7c297d61 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_types.h @@ -0,0 +1,56 @@ +/* + * Copyright 2012-2013 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_GRNURADIO_TYPES_H +#define INCLUDED_GRNURADIO_TYPES_H + +// this section is to satisfy swig includes for gras.i +// since gras.i includes gr_types.h, we only have to edit this file +#include <gras/element.hpp> +#include <gras/block.hpp> +#include <gras/top_block.hpp> +#include <gras/hier_block.hpp> + +// and gnuradio apparently needs its own typedefs for stdint... +#ifdef __cplusplus + +#include <boost/cstdint.hpp> +typedef boost::int16_t gr_int16; +typedef boost::int32_t gr_int32; +typedef boost::int64_t gr_int64; +typedef boost::uint16_t gr_uint16; +typedef boost::uint32_t gr_uint32; +typedef boost::uint64_t gr_uint64; + +typedef std::vector<int> gr_vector_int; +typedef std::vector<unsigned int> gr_vector_uint; +typedef std::vector<float> gr_vector_float; +typedef std::vector<double> gr_vector_double; +typedef std::vector<void *> gr_vector_void_star; +typedef std::vector<const void *> gr_vector_const_void_star; + +#include <complex> +typedef std::complex<float> gr_complex; +typedef std::complex<double> gr_complexd; + +#endif + +#endif /* INCLUDED_GRNURADIO_TYPES_H */ diff --git a/gnuradio-core/src/lib/runtime/gr_unittests.h b/gnuradio-core/src/lib/runtime/gr_unittests.h new file mode 100644 index 000000000..9fbf228cd --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_unittests.h @@ -0,0 +1,43 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_core_api.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <string> + +#include <boost/filesystem/operations.hpp> +#include <boost/filesystem/path.hpp> + +static std::string get_unittest_path(const std::string &filename){ + boost::filesystem::path path = boost::filesystem::current_path() / ".unittests"; + if (!boost::filesystem::is_directory(path)) boost::filesystem::create_directory(path); + return (path / filename).string(); +} diff --git a/gnuradio-core/src/lib/runtime/gr_vmcircbuf.cc b/gnuradio-core/src/lib/runtime/gr_vmcircbuf.cc new file mode 100644 index 000000000..522d9515d --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf.cc @@ -0,0 +1,295 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 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_vmcircbuf.h> +#include <assert.h> +#include <stdexcept> +#include <gr_preferences.h> +#include <stdio.h> +#include <string.h> +#include <gr_local_sighandler.h> +#include <vector> +#include <boost/format.hpp> + +// all the factories we know about +#include <gr_vmcircbuf_createfilemapping.h> +#include <gr_vmcircbuf_sysv_shm.h> +#include <gr_vmcircbuf_mmap_shm_open.h> +#include <gr_vmcircbuf_mmap_tmpfile.h> + +static const char *FACTORY_PREF_KEY = "gr_vmcircbuf_default_factory"; + +gr_vmcircbuf::~gr_vmcircbuf () +{ +} + +gr_vmcircbuf_factory::~gr_vmcircbuf_factory () +{ +} + +// ---------------------------------------------------------------- + +static gr_vmcircbuf_factory *s_default_factory = 0; + +gr_vmcircbuf_factory * +gr_vmcircbuf_sysconfig::get_default_factory () +{ + if (s_default_factory) + return s_default_factory; + + bool verbose = false; + + std::vector<gr_vmcircbuf_factory *> all = all_factories (); + + const char *name = gr_preferences::get (FACTORY_PREF_KEY); + + if (name){ + for (unsigned int i = 0; i < all.size (); i++){ + if (strcmp (name, all[i]->name ()) == 0){ + s_default_factory = all[i]; + if (verbose) + fprintf (stderr, "gr_vmcircbuf_sysconfig: using %s\n", + s_default_factory->name ()); + return s_default_factory; + } + } + } + + // either we don't have a default, or the default named is not in our + // list of factories. Find the first factory that works. + + if (verbose) + fprintf (stderr, "gr_vmcircbuf_sysconfig: finding a working factory...\n"); + + for (unsigned int i = 0; i < all.size (); i++){ + if (test_factory (all[i], verbose)){ + set_default_factory (all[i]); + return s_default_factory; + } + } + + // We're screwed! + + fprintf (stderr, "gr_vmcircbuf_sysconfig: unable to find a working factory!\n"); + throw std::runtime_error ("gr_vmcircbuf_sysconfig"); +} + +std::vector<gr_vmcircbuf_factory *> +gr_vmcircbuf_sysconfig::all_factories () +{ + std::vector<gr_vmcircbuf_factory *> result; + + result.push_back (gr_vmcircbuf_createfilemapping_factory::singleton ()); +#ifdef TRY_SHM_VMCIRCBUF + result.push_back (gr_vmcircbuf_sysv_shm_factory::singleton ()); + result.push_back (gr_vmcircbuf_mmap_shm_open_factory::singleton ()); +#endif + result.push_back (gr_vmcircbuf_mmap_tmpfile_factory::singleton ()); + + return result; +} + +void +gr_vmcircbuf_sysconfig::set_default_factory (gr_vmcircbuf_factory *f) +{ + gr_preferences::set (FACTORY_PREF_KEY, f->name ()); + s_default_factory = f; +} + + +// ------------------------------------------------------------------------ +// test code for vmcircbuf factories +// ------------------------------------------------------------------------ + +static void +init_buffer (gr_vmcircbuf *c, int counter, int size) +{ + unsigned int *p = (unsigned int *) c->pointer_to_first_copy (); + for (unsigned int i = 0; i < size / sizeof (int); i++) + p[i] = counter + i; +} + +static bool +check_mapping (gr_vmcircbuf *c, int counter, int size, const char *msg, bool verbose) +{ + bool ok = true; + + if (verbose) + fprintf (stderr, "... %s", msg); + + unsigned int *p1 = (unsigned int *) c->pointer_to_first_copy (); + unsigned int *p2 = (unsigned int *) c->pointer_to_second_copy (); + + // fprintf (stderr, "p1 = %p, p2 = %p\n", p1, p2); + + for (unsigned int i = 0; i < size / sizeof (int); i++){ + if (p1[i] != counter + i){ + ok = false; + if (verbose) + fprintf (stderr, " p1[%d] == %u, expected %u\n", i, p1[i], counter + i); + break; + } + if (p2[i] != counter + i){ + if (verbose) + fprintf (stderr, " p2[%d] == %u, expected %u\n", i, p2[i], counter + i); + ok = false; + break; + } + } + + if (ok && verbose){ + fprintf (stderr, " OK\n"); + } + return ok; +} + +static const char * +memsize (int size) +{ + static std::string buf; + if (size >= (1 << 20)){ + buf = str(boost::format("%dMB") % (size / (1 << 20))); + } + else if (size >= (1 << 10)){ + buf = str(boost::format("%dKB") % (size / (1 << 10))); + } + else { + buf = str(boost::format("%d") % size); + } + return buf.c_str(); +} + +static bool +test_a_bunch (gr_vmcircbuf_factory *factory, int n, int size, int *start_ptr, bool verbose) +{ + bool ok = true; + std::vector<int> counter(n); + std::vector<gr_vmcircbuf *> c(n); + int cum_size = 0; + + for (int i = 0; i < n; i++){ + counter[i] = *start_ptr; + *start_ptr += size; + if ((c[i] = factory->make (size)) == 0){ + if (verbose) + fprintf (stderr, + "Failed to allocate gr_vmcircbuf number %d of size %d (cum = %s)\n", + i + 1, size, memsize (cum_size)); + return false; + } + init_buffer (c[i], counter[i], size); + cum_size += size; + } + + for (int i = 0; i < n; i++){ + std::string msg = str(boost::format("test_a_bunch_%dx%s[%d]") % n % memsize (size) % i); + ok &= check_mapping (c[i], counter[i], size, msg.c_str(), verbose); + } + + for (int i = 0; i < n; i++){ + delete c[i]; + c[i] = 0; + } + + return ok; +} + +static bool +standard_tests (gr_vmcircbuf_factory *f, int verbose) +{ + if (verbose >= 1) + fprintf (stderr, "Testing %s...\n", f->name ()); + + bool v = verbose >= 2; + int granularity = f->granularity (); + int start = 0; + bool ok = true; + + ok &= test_a_bunch (f, 1, 1 * granularity, &start, v); // 1 x 4KB = 4KB + + if (ok){ + ok &= test_a_bunch (f, 64, 4 * granularity, &start, v); // 64 x 16KB = 1MB + ok &= test_a_bunch (f, 4, 4 * (1L << 20), &start, v); // 4 x 4MB = 16MB +// ok &= test_a_bunch (f, 256, 256 * (1L << 10), &start, v); // 256 x 256KB = 64MB + } + + if (verbose >= 1) + fprintf (stderr, "....... %s: %s", f->name (), ok ? "OK\n" : "Doesn't work\n"); + + return ok; +} + +bool +gr_vmcircbuf_sysconfig::test_factory (gr_vmcircbuf_factory *f, int verbose) +{ + // Install local signal handlers for SIGSEGV and SIGBUS. + // If something goes wrong, these signals may be invoked. + +#ifdef SIGSEGV + gr_local_sighandler sigsegv (SIGSEGV, gr_local_sighandler::throw_signal); +#endif +#ifdef SIGBUS + gr_local_sighandler sigbus (SIGBUS, gr_local_sighandler::throw_signal); +#endif +#ifdef SIGSYS + gr_local_sighandler sigsys (SIGSYS, gr_local_sighandler::throw_signal); +#endif + + try { + return standard_tests (f, verbose); + } + catch (gr_signal &sig){ + if (verbose){ + fprintf (stderr, "....... %s: %s", f->name (), "Doesn't work\n"); + fprintf (stderr, + "gr_vmcircbuf_factory::test_factory (%s): caught %s\n", + f->name (), sig.name().c_str()); + return false; + } + } + catch (...){ + if (verbose){ + fprintf (stderr, "....... %s: %s", f->name (), "Doesn't work\n"); + fprintf (stderr, + "gr_vmcircbuf_factory::test_factory (%s): some kind of uncaught exception\n", + f->name ()); + } + return false; + } + return false; // never gets here. shut compiler up. +} + +bool +gr_vmcircbuf_sysconfig::test_all_factories (int verbose) +{ + bool ok = false; + + std::vector<gr_vmcircbuf_factory *> all = all_factories (); + + for (unsigned int i = 0; i < all.size (); i++) + ok |= test_factory (all[i], verbose); + + return ok; +} diff --git a/gnuradio-core/src/lib/runtime/gr_vmcircbuf.h b/gnuradio-core/src/lib/runtime/gr_vmcircbuf.h new file mode 100644 index 000000000..45c6f969c --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf.h @@ -0,0 +1,122 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 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 _GR_VMCIRCBUF_H_ +#define _GR_VMCIRCBUF_H_ + +#include <gr_core_api.h> +#include <vector> + +/*! + * \brief abstract class to implement doubly mapped virtual memory circular buffers + * \ingroup internal + */ +class GR_CORE_API gr_vmcircbuf { + protected: + int d_size; + char *d_base; + + // CREATORS + gr_vmcircbuf (int size) : d_size (size), d_base (0) {}; + + public: + virtual ~gr_vmcircbuf (); + + // ACCESSORS + void *pointer_to_first_copy () const { return d_base; } + void *pointer_to_second_copy () const { return d_base + d_size; } +}; + +/*! + * \brief abstract factory for creating circular buffers + */ +class GR_CORE_API gr_vmcircbuf_factory { + protected: + gr_vmcircbuf_factory () {}; + virtual ~gr_vmcircbuf_factory (); + + public: + + /*! + * \brief return name of this factory + */ + virtual const char *name () const = 0; + + /*! + * \brief return granularity of mapping, typically equal to page size + */ + virtual int granularity () = 0; + + /*! + * \brief return a gr_vmcircbuf, or 0 if unable. + * + * Call this to create a doubly mapped circular buffer. + */ + virtual gr_vmcircbuf *make (int size) = 0; +}; + +/* + * \brief pulls together all implementations of gr_vmcircbuf + */ +class GR_CORE_API gr_vmcircbuf_sysconfig { + public: + + /* + * \brief return the single instance of the default factory. + * + * returns the default factory to use if it's already defined, + * else find the first working factory and use it. + */ + static gr_vmcircbuf_factory *get_default_factory (); + + + static int granularity () { return get_default_factory()->granularity(); } + static gr_vmcircbuf *make (int size) { return get_default_factory()->make(size); } + + + // N.B. not all factories are guaranteed to work. + // It's too hard to check everything at config time, so we check at runtime + static std::vector<gr_vmcircbuf_factory *> all_factories (); + + // make this factory the default + static void set_default_factory (gr_vmcircbuf_factory *f); + + /*! + * \brief Does this factory really work? + * + * verbose = 0: silent + * verbose = 1: names of factories tested and results + * verbose = 2: all intermediate results + */ + static bool test_factory (gr_vmcircbuf_factory *f, int verbose); + + /*! + * \brief Test all factories, return true if at least one of them works + * verbose = 0: silent + * verbose = 1: names of factories tested and results + * verbose = 2: all intermediate results + */ + static bool test_all_factories (int verbose); +}; + + +#endif /* _GR_VMCIRCBUF_H_ */ diff --git a/gnuradio-core/src/lib/runtime/gr_vmcircbuf_createfilemapping.cc b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_createfilemapping.cc new file mode 100644 index 000000000..1b4d9700a --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_createfilemapping.cc @@ -0,0 +1,204 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2005,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 <stdexcept> +#include <assert.h> +#include <unistd.h> +#include <fcntl.h> +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_MMAN_H +#include <sys/mman.h> +#endif +#include <errno.h> +#include <stdio.h> +#include <gr_pagesize.h> +#include <gr_vmcircbuf_createfilemapping.h> +#include <boost/format.hpp> + +#ifdef HAVE_CREATEFILEMAPPING +// Print Windows error (could/should be global?) +static void +werror( char *where, DWORD last_error ) +{ + char buf[1024]; + + FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + last_error, + 0, // default language + buf, + sizeof(buf)/sizeof(TCHAR), // buffer size + NULL ); + fprintf( stderr, "%s: Error %d: %s", where, last_error, buf ); + return; +} +#endif + + +gr_vmcircbuf_createfilemapping::gr_vmcircbuf_createfilemapping (int size) + : gr_vmcircbuf (size) +{ +#if !defined(HAVE_CREATEFILEMAPPING) + fprintf (stderr, "%s: createfilemapping is not available\n",__FUNCTION__); + throw std::runtime_error ("gr_vmcircbuf_createfilemapping"); +#else + static int s_seg_counter = 0; + + if (size <= 0 || (size % gr_pagesize ()) != 0){ + fprintf (stderr, "gr_vmcircbuf_createfilemapping: invalid size = %d\n", size); + throw std::runtime_error ("gr_vmcircbuf_createfilemapping"); + } + + std::string seg_name = str(boost::format("/gnuradio-%d-%d") % getpid () % s_seg_counter); + + d_handle = CreateFileMapping(INVALID_HANDLE_VALUE, // use paging file + NULL, // default security + PAGE_READWRITE, // read/write access + 0, // max. object size + size, // buffer size + seg_name.c_str()); // name of mapping object + + s_seg_counter++; + if (d_handle == NULL || d_handle == INVALID_HANDLE_VALUE){ + std::string msg = str(boost::format( + "gr_vmcircbuf_mmap_createfilemapping: CreateFileMapping [%s]") % + seg_name ); + werror((char *) msg.c_str(), GetLastError() ); + throw std::runtime_error ("gr_vmcircbuf_mmap_createfilemapping"); + } + + // Allocate virtual memory of the needed size, then free it so we can use it + LPVOID first_tmp; + first_tmp = VirtualAlloc( NULL, 2*size, MEM_RESERVE, PAGE_NOACCESS ); + if (first_tmp == NULL){ + werror( "gr_vmcircbuf_mmap_createfilemapping: VirtualAlloc", GetLastError()); + CloseHandle(d_handle); // cleanup + throw std::runtime_error ("gr_vmcircbuf_mmap_createfilemapping"); + } + + if (VirtualFree(first_tmp, 0, MEM_RELEASE) == 0){ + werror( "gr_vmcircbuf_mmap_createfilemapping: VirtualFree", GetLastError()); + CloseHandle(d_handle); // cleanup + throw std::runtime_error ("gr_vmcircbuf_mmap_createfilemapping"); + } + + d_first_copy = MapViewOfFileEx((HANDLE)d_handle, // handle to map object + FILE_MAP_WRITE, // read/write permission + 0, + 0, + size, + first_tmp); + if (d_first_copy != first_tmp){ + werror( "gr_vmcircbuf_mmap_createfilemapping: MapViewOfFileEx(1)", GetLastError()); + CloseHandle(d_handle); // cleanup + throw std::runtime_error ("gr_vmcircbuf_mmap_createfilemapping"); + } + + d_second_copy = MapViewOfFileEx((HANDLE)d_handle, // handle to map object + FILE_MAP_WRITE, // read/write permission + 0, + 0, + size, + (char *)first_tmp + size);//(LPVOID) ((char *)d_first_copy + size)); + + if (d_second_copy != (char *)first_tmp + size){ + werror( "gr_vmcircbuf_mmap_createfilemapping: MapViewOfFileEx(2)", GetLastError()); + UnmapViewOfFile(d_first_copy); + CloseHandle(d_handle); // cleanup + throw std::runtime_error ("gr_vmcircbuf_mmap_createfilemapping"); + } + +#ifdef DEBUG + fprintf (stderr,"gr_vmcircbuf_mmap_createfilemapping: contiguous? mmap %p %p %p %p\n", + (char *)d_first_copy, (char *)d_second_copy, size, (char *)d_first_copy + size); +#endif + + // Now remember the important stuff + d_base = (char *) d_first_copy; + d_size = size; +#endif /*HAVE_CREATEFILEMAPPING*/ +} + +gr_vmcircbuf_createfilemapping::~gr_vmcircbuf_createfilemapping () +{ +#ifdef HAVE_CREATEFILEMAPPING + if (UnmapViewOfFile(d_first_copy) == 0) + { + werror("gr_vmcircbuf_createfilemapping: UnmapViewOfFile(d_first_copy)", GetLastError()); + } + d_base=NULL; + if (UnmapViewOfFile(d_second_copy) == 0) + { + werror("gr_vmcircbuf_createfilemapping: UnmapViewOfFile(d_second_copy)", GetLastError()); + } + //d_second=NULL; + CloseHandle(d_handle); +#endif +} + +// ---------------------------------------------------------------- +// The factory interface +// ---------------------------------------------------------------- + + +gr_vmcircbuf_factory *gr_vmcircbuf_createfilemapping_factory::s_the_factory = 0; + +gr_vmcircbuf_factory * +gr_vmcircbuf_createfilemapping_factory::singleton () +{ + if (s_the_factory) + return s_the_factory; + s_the_factory = new gr_vmcircbuf_createfilemapping_factory (); + return s_the_factory; +} + +int +gr_vmcircbuf_createfilemapping_factory::granularity () +{ +#ifdef HAVE_CREATEFILEMAPPING + // return 65536;//TODO, check, is this needed or can we just use gr_pagesize() + SYSTEM_INFO system_info; + GetSystemInfo(&system_info); + //fprintf(stderr,"win32 AllocationGranularity %p\n",(int)system_info.dwAllocationGranularity); + return (int)system_info.dwAllocationGranularity; +#else + return gr_pagesize (); +#endif +} + +gr_vmcircbuf * +gr_vmcircbuf_createfilemapping_factory::make (int size) +{ + try + { + return new gr_vmcircbuf_createfilemapping (size); + } + catch (...) + { + return 0; + } +} diff --git a/gnuradio-core/src/lib/runtime/gr_vmcircbuf_createfilemapping.h b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_createfilemapping.h new file mode 100644 index 000000000..5ef31f5c6 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_createfilemapping.h @@ -0,0 +1,76 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,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 _GR_VMCIRCBUF_CREATEFILEMAPPING_H_ +#define _GR_VMCIRCBUF_CREATEFILEMAPPING_H_ + +#include <gr_core_api.h> +#include <gr_vmcircbuf.h> + +#ifdef HAVE_CREATEFILEMAPPING +#include <windows.h> +#endif +/*! + * \brief concrete class to implement circular buffers with mmap and shm_open + * \ingroup internal + */ +class GR_CORE_API gr_vmcircbuf_createfilemapping : public gr_vmcircbuf +{ + public: + // CREATORS + gr_vmcircbuf_createfilemapping (int size); + virtual ~gr_vmcircbuf_createfilemapping (); +#ifdef HAVE_CREATEFILEMAPPING + private: + HANDLE d_handle; + LPVOID d_first_copy; + LPVOID d_second_copy; +#endif +}; + +/*! + * \brief concrete factory for circular buffers built using mmap and shm_open + */ +class GR_CORE_API gr_vmcircbuf_createfilemapping_factory : public gr_vmcircbuf_factory +{ + private: + static gr_vmcircbuf_factory *s_the_factory; + + public: + static gr_vmcircbuf_factory *singleton (); + + virtual const char *name () const { return "gr_vmcircbuf_createfilemapping_factory"; } + + /*! + * \brief return granularity of mapping, typically equal to page size + */ + virtual int granularity (); + + /*! + * \brief return a gr_vmcircbuf, or 0 if unable. + * + * Call this to create a doubly mapped circular buffer. + */ + virtual gr_vmcircbuf *make (int size); +}; + +#endif /* _GR_VMCIRCBUF_CREATEFILEMAPPING_H_ */ diff --git a/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_shm_open.cc b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_shm_open.cc new file mode 100644 index 000000000..3d170081d --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_shm_open.cc @@ -0,0 +1,205 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,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_vmcircbuf_mmap_shm_open.h> +#include <stdexcept> +#include <assert.h> +#include <unistd.h> +#include <fcntl.h> +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_MMAN_H +#include <sys/mman.h> +#endif +#include <errno.h> +#include <stdio.h> +#include <gr_pagesize.h> +#include <gr_sys_paths.h> + + +gr_vmcircbuf_mmap_shm_open::gr_vmcircbuf_mmap_shm_open (int size) + : gr_vmcircbuf (size) +{ +#if !defined(HAVE_MMAP) || !defined(HAVE_SHM_OPEN) + fprintf (stderr, "gr_vmcircbuf_mmap_shm_open: mmap or shm_open is not available\n"); + throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); +#else + static int s_seg_counter = 0; + + if (size <= 0 || (size % gr_pagesize ()) != 0){ + fprintf (stderr, "gr_vmcircbuf_mmap_shm_open: invalid size = %d\n", size); + throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); + } + + int shm_fd = -1; + char seg_name[1024]; + static bool portable_format = true; + + // open a new named shared memory segment + + while (1){ + if (portable_format){ + + // This is the POSIX recommended "portable format". + // Of course the "portable format" doesn't work on some systems... + + snprintf (seg_name, sizeof (seg_name), + "/gnuradio-%d-%d", getpid (), s_seg_counter); + } + else { + + // Where the "portable format" doesn't work, we try building + // a full filesystem pathname pointing into a suitable temporary directory. + + snprintf (seg_name, sizeof (seg_name), + "%s/gnuradio-%d-%d", gr_tmp_path (), getpid (), s_seg_counter); + } + + shm_fd = shm_open (seg_name, O_RDWR | O_CREAT | O_EXCL, 0600); + if (shm_fd == -1 && errno == EACCES && portable_format){ + portable_format = false; + continue; // try again using "non-portable format" + } + + s_seg_counter++; + + if (shm_fd == -1){ + if (errno == EEXIST) // Named segment already exists (shouldn't happen). Try again + continue; + + char msg[1024]; + snprintf (msg, sizeof (msg), "gr_vmcircbuf_mmap_shm_open: shm_open [%s]", seg_name); + perror (msg); + throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); + } + break; + } + + // We've got a new shared memory segment fd open. + // Now set it's length to 2x what we really want and mmap it in. + + if (ftruncate (shm_fd, (off_t) 2 * size) == -1){ + close (shm_fd); // cleanup + perror ("gr_vmcircbuf_mmap_shm_open: ftruncate (1)"); + throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); + } + + void *first_copy = mmap (0, 2 * size, + PROT_READ | PROT_WRITE, MAP_SHARED, + shm_fd, (off_t) 0); + + if (first_copy == MAP_FAILED){ + close (shm_fd); // cleanup + perror ("gr_vmcircbuf_mmap_shm_open: mmap (1)"); + throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); + } + + // unmap the 2nd half + if (munmap ((char *) first_copy + size, size) == -1){ + close (shm_fd); // cleanup + perror ("gr_vmcircbuf_mmap_shm_open: munmap (1)"); + throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); + } + + // map the first half into the now available hole where the + // second half used to be. + + void *second_copy = mmap ((char *) first_copy + size, size, + PROT_READ | PROT_WRITE, MAP_SHARED, + shm_fd, (off_t) 0); + + if (second_copy == MAP_FAILED){ + close (shm_fd); // cleanup + perror ("gr_vmcircbuf_mmap_shm_open: mmap (2)"); + throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); + } + +#if 0 // OS/X doesn't allow you to resize the segment + + // cut the shared memory segment down to size + if (ftruncate (shm_fd, (off_t) size) == -1){ + close (shm_fd); // cleanup + perror ("gr_vmcircbuf_mmap_shm_open: ftruncate (2)"); + throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); + } +#endif + + close (shm_fd); // fd no longer needed. The mapping is retained. + + if (shm_unlink (seg_name) == -1){ // unlink the seg_name. + perror ("gr_vmcircbuf_mmap_shm_open: shm_unlink"); + throw std::runtime_error ("gr_vmcircbuf_mmap_shm_open"); + } + + // Now remember the important stuff + + d_base = (char *) first_copy; + d_size = size; +#endif +} + +gr_vmcircbuf_mmap_shm_open::~gr_vmcircbuf_mmap_shm_open () +{ +#if defined(HAVE_MMAP) + if (munmap (d_base, 2 * d_size) == -1){ + perror ("gr_vmcircbuf_mmap_shm_open: munmap (2)"); + } +#endif +} + +// ---------------------------------------------------------------- +// The factory interface +// ---------------------------------------------------------------- + + +gr_vmcircbuf_factory *gr_vmcircbuf_mmap_shm_open_factory::s_the_factory = 0; + +gr_vmcircbuf_factory * +gr_vmcircbuf_mmap_shm_open_factory::singleton () +{ + if (s_the_factory) + return s_the_factory; + + s_the_factory = new gr_vmcircbuf_mmap_shm_open_factory (); + return s_the_factory; +} + +int +gr_vmcircbuf_mmap_shm_open_factory::granularity () +{ + return gr_pagesize (); +} + +gr_vmcircbuf * +gr_vmcircbuf_mmap_shm_open_factory::make (int size) +{ + try { + return new gr_vmcircbuf_mmap_shm_open (size); + } + catch (...){ + return 0; + } +} diff --git a/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_shm_open.h b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_shm_open.h new file mode 100644 index 000000000..bcbbbac42 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_shm_open.h @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 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 _GR_VMCIRCBUF_MMAP_SHM_OPEN_H_ +#define _GR_VMCIRCBUF_MMAP_SHM_OPEN_H_ + +#include <gr_core_api.h> +#include <gr_vmcircbuf.h> + +/*! + * \brief concrete class to implement circular buffers with mmap and shm_open + * \ingroup internal + */ +class GR_CORE_API gr_vmcircbuf_mmap_shm_open : public gr_vmcircbuf { + public: + + // CREATORS + + gr_vmcircbuf_mmap_shm_open (int size); + virtual ~gr_vmcircbuf_mmap_shm_open (); +}; + +/*! + * \brief concrete factory for circular buffers built using mmap and shm_open + */ +class GR_CORE_API gr_vmcircbuf_mmap_shm_open_factory : public gr_vmcircbuf_factory { + private: + static gr_vmcircbuf_factory *s_the_factory; + + public: + static gr_vmcircbuf_factory *singleton (); + + virtual const char *name () const { return "gr_vmcircbuf_mmap_shm_open_factory"; } + + /*! + * \brief return granularity of mapping, typically equal to page size + */ + virtual int granularity (); + + /*! + * \brief return a gr_vmcircbuf, or 0 if unable. + * + * Call this to create a doubly mapped circular buffer. + */ + virtual gr_vmcircbuf *make (int size); +}; + +#endif /* _GR_VMCIRCBUF_MMAP_SHM_OPEN_H_ */ diff --git a/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.cc b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.cc new file mode 100644 index 000000000..35de64699 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.cc @@ -0,0 +1,197 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,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_vmcircbuf_mmap_tmpfile.h> +#include <stdexcept> +#include <assert.h> +#include <unistd.h> +#include <stdlib.h> +#ifdef HAVE_SYS_TYPES_H +#include <sys/types.h> +#endif +#ifdef HAVE_SYS_MMAN_H +#include <sys/mman.h> +#endif +#include <fcntl.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <gr_pagesize.h> +#include <gr_sys_paths.h> + +gr_vmcircbuf_mmap_tmpfile::gr_vmcircbuf_mmap_tmpfile (int size) + : gr_vmcircbuf (size) +{ +#if !defined(HAVE_MMAP) + fprintf (stderr, "gr_vmcircbuf_mmap_tmpfile: mmap or mkstemp is not available\n"); + throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); +#else + + if (size <= 0 || (size % gr_pagesize ()) != 0){ + fprintf (stderr, "gr_vmcircbuf_mmap_tmpfile: invalid size = %d\n", size); + throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); + } + + int seg_fd = -1; + char seg_name[1024]; + + static int s_seg_counter = 0; + + + // open a temporary file that we'll map in a bit later + + while (1){ + snprintf (seg_name, sizeof (seg_name), + "%s/gnuradio-%d-%d-XXXXXX", gr_tmp_path (), getpid (), s_seg_counter); + s_seg_counter++; + + seg_fd = open (seg_name, O_RDWR | O_CREAT | O_EXCL, 0600); + if (seg_fd == -1){ + if (errno == EEXIST) // File already exists (shouldn't happen). Try again + continue; + + char msg[1024]; + snprintf (msg, sizeof (msg), + "gr_vmcircbuf_mmap_tmpfile: open [%s]", seg_name); + perror (msg); + throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); + } + break; + } + + if (unlink (seg_name) == -1){ + perror ("gr_vmcircbuf_mmap_tmpfile: unlink"); + throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); + } + + // We've got a valid file descriptor to a tmp file. + // Now set it's length to 2x what we really want and mmap it in. + + if (ftruncate (seg_fd, (off_t) 2 * size) == -1){ + close (seg_fd); // cleanup + perror ("gr_vmcircbuf_mmap_tmpfile: ftruncate (1)"); + throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); + } + + void *first_copy = mmap (0, 2 * size, + PROT_READ | PROT_WRITE, MAP_SHARED, + seg_fd, (off_t) 0); + + if (first_copy == MAP_FAILED){ + close (seg_fd); // cleanup + perror ("gr_vmcircbuf_mmap_tmpfile: mmap (1)"); + throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); + } + + // unmap the 2nd half + if (munmap ((char *) first_copy + size, size) == -1){ + close (seg_fd); // cleanup + perror ("gr_vmcircbuf_mmap_tmpfile: munmap (1)"); + throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); + } + + // map the first half into the now available hole where the + // second half used to be. + + void *second_copy = mmap ((char *) first_copy + size, size, + PROT_READ | PROT_WRITE, MAP_SHARED, + seg_fd, (off_t) 0); + + if (second_copy == MAP_FAILED){ + munmap(first_copy, size); // cleanup + close (seg_fd); + perror ("gr_vmcircbuf_mmap_tmpfile: mmap (2)"); + throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); + } + + // check for contiguity + if ((char *) second_copy != (char *) first_copy + size){ + munmap(first_copy, size); // cleanup + munmap(second_copy, size); + close (seg_fd); + perror ("gr_vmcircbuf_mmap_tmpfile: non-contiguous second copy"); + throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); + } + + // cut the tmp file down to size + if (ftruncate (seg_fd, (off_t) size) == -1){ + munmap(first_copy, size); // cleanup + munmap(second_copy, size); + close (seg_fd); + perror ("gr_vmcircbuf_mmap_tmpfile: ftruncate (2)"); + throw std::runtime_error ("gr_vmcircbuf_mmap_tmpfile"); + } + + close (seg_fd); // fd no longer needed. The mapping is retained. + + // Now remember the important stuff + + d_base = (char *) first_copy; + d_size = size; +#endif +} + +gr_vmcircbuf_mmap_tmpfile::~gr_vmcircbuf_mmap_tmpfile () +{ +#if defined(HAVE_MMAP) + if (munmap (d_base, 2 * d_size) == -1){ + perror ("gr_vmcircbuf_mmap_tmpfile: munmap (2)"); + } +#endif +} + +// ---------------------------------------------------------------- +// The factory interface +// ---------------------------------------------------------------- + + +gr_vmcircbuf_factory *gr_vmcircbuf_mmap_tmpfile_factory::s_the_factory = 0; + +gr_vmcircbuf_factory * +gr_vmcircbuf_mmap_tmpfile_factory::singleton () +{ + if (s_the_factory) + return s_the_factory; + + s_the_factory = new gr_vmcircbuf_mmap_tmpfile_factory (); + return s_the_factory; +} + +int +gr_vmcircbuf_mmap_tmpfile_factory::granularity () +{ + return gr_pagesize (); +} + +gr_vmcircbuf * +gr_vmcircbuf_mmap_tmpfile_factory::make (int size) +{ + try { + return new gr_vmcircbuf_mmap_tmpfile (size); + } + catch (...){ + return 0; + } +} diff --git a/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.h b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.h new file mode 100644 index 000000000..28ff31490 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.h @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 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 _GR_VMCIRCBUF_MMAP_TMPFILE_H_ +#define _GR_VMCIRCBUF_MMAP_TMPFILE_H_ + +#include <gr_core_api.h> +#include <gr_vmcircbuf.h> + +/*! + * \brief concrete class to implement circular buffers with mmap and shm_open + * \ingroup internal + */ +class GR_CORE_API gr_vmcircbuf_mmap_tmpfile : public gr_vmcircbuf { + public: + + // CREATORS + + gr_vmcircbuf_mmap_tmpfile (int size); + virtual ~gr_vmcircbuf_mmap_tmpfile (); +}; + +/*! + * \brief concrete factory for circular buffers built using mmap and shm_open + */ +class GR_CORE_API gr_vmcircbuf_mmap_tmpfile_factory : public gr_vmcircbuf_factory { + private: + static gr_vmcircbuf_factory *s_the_factory; + + public: + static gr_vmcircbuf_factory *singleton (); + + virtual const char *name () const { return "gr_vmcircbuf_mmap_tmpfile_factory"; } + + /*! + * \brief return granularity of mapping, typically equal to page size + */ + virtual int granularity (); + + /*! + * \brief return a gr_vmcircbuf, or 0 if unable. + * + * Call this to create a doubly mapped circular buffer. + */ + virtual gr_vmcircbuf *make (int size); +}; + +#endif /* _GR_VMCIRCBUF_MMAP_TMPFILE_H_ */ diff --git a/gnuradio-core/src/lib/runtime/gr_vmcircbuf_sysv_shm.cc b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_sysv_shm.cc new file mode 100644 index 000000000..d9cf75e70 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_sysv_shm.cc @@ -0,0 +1,194 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 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_vmcircbuf_sysv_shm.h> +#include <stdexcept> +#include <assert.h> +#include <unistd.h> +#include <stdlib.h> +#include <fcntl.h> +#ifdef HAVE_SYS_IPC_H +#include <sys/ipc.h> +#endif +#ifdef HAVE_SYS_SHM_H +#include <sys/shm.h> +#endif +#include <errno.h> +#include <stdio.h> +#include <gr_pagesize.h> + + +gr_vmcircbuf_sysv_shm::gr_vmcircbuf_sysv_shm (int size) + : gr_vmcircbuf (size) +{ +#if !defined(HAVE_SYS_SHM_H) + fprintf (stderr, "gr_vmcircbuf_sysv_shm: sysv shared memory is not available\n"); + throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); +#else + + int pagesize = gr_pagesize(); + + if (size <= 0 || (size % pagesize) != 0){ + fprintf (stderr, "gr_vmcircbuf_sysv_shm: invalid size = %d\n", size); + throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); + } + + int shmid_guard = -1; + int shmid1 = -1; + int shmid2 = -1; + + // We use this as a guard page. We'll map it read-only on both ends of the buffer. + // Ideally we'd map it no access, but I don't think that's possible with SysV + if ((shmid_guard = shmget (IPC_PRIVATE, pagesize, IPC_CREAT | 0400)) == -1){ + perror ("gr_vmcircbuf_sysv_shm: shmget (0)"); + throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); + } + + if ((shmid2 = shmget (IPC_PRIVATE, 2 * size + 2 * pagesize, IPC_CREAT | 0700)) == -1){ + perror ("gr_vmcircbuf_sysv_shm: shmget (1)"); + shmctl (shmid_guard, IPC_RMID, 0); + throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); + } + + if ((shmid1 = shmget (IPC_PRIVATE, size, IPC_CREAT | 0700)) == -1){ + perror ("gr_vmcircbuf_sysv_shm: shmget (2)"); + shmctl (shmid_guard, IPC_RMID, 0); + shmctl (shmid2, IPC_RMID, 0); + throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); + } + + void *first_copy = shmat (shmid2, 0, 0); + if (first_copy == (void *) -1){ + perror ("gr_vmcircbuf_sysv_shm: shmat (1)"); + shmctl (shmid_guard, IPC_RMID, 0); + shmctl (shmid2, IPC_RMID, 0); + shmctl (shmid1, IPC_RMID, 0); + throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); + } + + shmctl (shmid2, IPC_RMID, 0); + + // There may be a race between our detach and attach. + // + // If the system allocates all shared memory segments at the same + // virtual addresses in all processes and if the system allocates + // some other segment to first_copy or first_copoy + size between + // our detach and attach, the attaches below could fail [I've never + // seen it fail for this reason]. + + shmdt (first_copy); + + // first read-only guard page + if (shmat (shmid_guard, first_copy, SHM_RDONLY) == (void *) -1){ + perror ("gr_vmcircbuf_sysv_shm: shmat (2)"); + shmctl (shmid_guard, IPC_RMID, 0); + shmctl (shmid1, IPC_RMID, 0); + throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); + } + + // first copy + if (shmat (shmid1, (char *) first_copy + pagesize, 0) == (void *) -1){ + perror ("gr_vmcircbuf_sysv_shm: shmat (3)"); + shmctl (shmid_guard, IPC_RMID, 0); + shmctl (shmid1, IPC_RMID, 0); + shmdt (first_copy); + throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); + } + + // second copy + if (shmat (shmid1, (char *) first_copy + pagesize + size, 0) == (void *) -1){ + perror ("gr_vmcircbuf_sysv_shm: shmat (4)"); + shmctl (shmid_guard, IPC_RMID, 0); + shmctl (shmid1, IPC_RMID, 0); + shmdt ((char *)first_copy + pagesize); + throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); + } + + // second read-only guard page + if (shmat (shmid_guard, (char *) first_copy + pagesize + 2 * size, SHM_RDONLY) == (void *) -1){ + perror ("gr_vmcircbuf_sysv_shm: shmat (5)"); + shmctl (shmid_guard, IPC_RMID, 0); + shmctl (shmid1, IPC_RMID, 0); + shmdt (first_copy); + shmdt ((char *)first_copy + pagesize); + shmdt ((char *)first_copy + pagesize + size); + throw std::runtime_error ("gr_vmcircbuf_sysv_shm"); + } + + shmctl (shmid1, IPC_RMID, 0); + shmctl (shmid_guard, IPC_RMID, 0); + + // Now remember the important stuff + + d_base = (char *) first_copy + pagesize; + d_size = size; +#endif +} + +gr_vmcircbuf_sysv_shm::~gr_vmcircbuf_sysv_shm () +{ +#if defined(HAVE_SYS_SHM_H) + if (shmdt (d_base - gr_pagesize()) == -1 + || shmdt (d_base) == -1 + || shmdt (d_base + d_size) == -1 + || shmdt (d_base + 2 * d_size) == -1){ + perror ("gr_vmcircbuf_sysv_shm: shmdt (2)"); + } +#endif +} + +// ---------------------------------------------------------------- +// The factory interface +// ---------------------------------------------------------------- + + +gr_vmcircbuf_factory *gr_vmcircbuf_sysv_shm_factory::s_the_factory = 0; + +gr_vmcircbuf_factory * +gr_vmcircbuf_sysv_shm_factory::singleton () +{ + if (s_the_factory) + return s_the_factory; + + s_the_factory = new gr_vmcircbuf_sysv_shm_factory (); + return s_the_factory; +} + +int +gr_vmcircbuf_sysv_shm_factory::granularity () +{ + return gr_pagesize (); +} + +gr_vmcircbuf * +gr_vmcircbuf_sysv_shm_factory::make (int size) +{ + try { + return new gr_vmcircbuf_sysv_shm (size); + } + catch (...){ + return 0; + } +} diff --git a/gnuradio-core/src/lib/runtime/gr_vmcircbuf_sysv_shm.h b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_sysv_shm.h new file mode 100644 index 000000000..9f5c04f0d --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_sysv_shm.h @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 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 _GR_VMCIRCBUF_SYSV_SHM_H_ +#define _GR_VMCIRCBUF_SYSV_SHM_H_ + +#include <gr_core_api.h> +#include <gr_vmcircbuf.h> + +/*! + * \brief concrete class to implement circular buffers with mmap and shm_open + * \ingroup internal + */ +class GR_CORE_API gr_vmcircbuf_sysv_shm : public gr_vmcircbuf { + public: + + // CREATORS + + gr_vmcircbuf_sysv_shm (int size); + virtual ~gr_vmcircbuf_sysv_shm (); +}; + +/*! + * \brief concrete factory for circular buffers built using mmap and shm_open + */ +class GR_CORE_API gr_vmcircbuf_sysv_shm_factory : public gr_vmcircbuf_factory { + private: + static gr_vmcircbuf_factory *s_the_factory; + + public: + static gr_vmcircbuf_factory *singleton (); + + virtual const char *name () const { return "gr_vmcircbuf_sysv_shm_factory"; } + + /*! + * \brief return granularity of mapping, typically equal to page size + */ + virtual int granularity (); + + /*! + * \brief return a gr_vmcircbuf, or 0 if unable. + * + * Call this to create a doubly mapped circular buffer. + */ + virtual gr_vmcircbuf *make (int size); +}; + +#endif /* _GR_VMCIRCBUF_SYSV_SHM_H_ */ diff --git a/gnuradio-core/src/lib/runtime/pmx_helper.hpp b/gnuradio-core/src/lib/runtime/pmx_helper.hpp new file mode 100644 index 000000000..44cc2997c --- /dev/null +++ b/gnuradio-core/src/lib/runtime/pmx_helper.hpp @@ -0,0 +1,268 @@ +/* + * Copyright 2012-2013 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_LIBGRAS_PMX_HELPER_HPP +#define INCLUDED_LIBGRAS_PMX_HELPER_HPP + +#include <PMC/PMC.hpp> +#include <PMC/Containers.hpp> +#include <gruel/pmt.h> +#include <boost/foreach.hpp> + +namespace pmt +{ + +inline pmt_t pmc_to_pmt(const PMCC &p) +{ + //the container is null + if (not p) return pmt::pmt_t(); + + #define decl_pmc_to_pmt(type, conv) if (p.is<type >()) return conv(p.as<type >()) + + //bool + decl_pmc_to_pmt(bool, pmt_from_bool); + + //string + decl_pmc_to_pmt(std::string, pmt_string_to_symbol); + + //numeric types + decl_pmc_to_pmt(int8_t, pmt_from_long); + decl_pmc_to_pmt(int16_t, pmt_from_long); + decl_pmc_to_pmt(int32_t, pmt_from_long); + decl_pmc_to_pmt(uint8_t, pmt_from_long); + decl_pmc_to_pmt(uint16_t, pmt_from_long); + decl_pmc_to_pmt(uint32_t, pmt_from_long); + decl_pmc_to_pmt(int64_t, pmt_from_uint64); + decl_pmc_to_pmt(uint64_t, pmt_from_uint64); + decl_pmc_to_pmt(float, pmt_from_double); + decl_pmc_to_pmt(double, pmt_from_double); + #define pmt_from_complex(x) pmt_make_rectangular((x).real(), (x).imag()) + decl_pmc_to_pmt(std::complex<float>, pmt_from_complex); + decl_pmc_to_pmt(std::complex<double>, pmt_from_complex); + + //pair container + if (p.is<PMCPair>()) + { + const PMCPair &pr = p.as<PMCPair>(); + return pmt_cons(pmc_to_pmt(pr.first), pmc_to_pmt(pr.second)); + } + + //fucking tuples +/* +for i in range(11): + args = list() + for j in range(i): + args.append('pmc_to_pmt(p.as<PMCTuple<%d> >()[%d])'%(i, j)) + print ' if (p.is<PMCTuple<%d> >())'%i + print ' return pmt_make_tuple(%s);'%(', '.join(args),) +*/ + if (p.is<PMCTuple<0> >()) + return pmt_make_tuple(); + if (p.is<PMCTuple<1> >()) + return pmt_make_tuple(pmc_to_pmt(p.as<PMCTuple<1> >()[0])); + if (p.is<PMCTuple<2> >()) + return pmt_make_tuple(pmc_to_pmt(p.as<PMCTuple<2> >()[0]), pmc_to_pmt(p.as<PMCTuple<2> >()[1])); + if (p.is<PMCTuple<3> >()) + return pmt_make_tuple(pmc_to_pmt(p.as<PMCTuple<3> >()[0]), pmc_to_pmt(p.as<PMCTuple<3> >()[1]), pmc_to_pmt(p.as<PMCTuple<3> >()[2])); + if (p.is<PMCTuple<4> >()) + return pmt_make_tuple(pmc_to_pmt(p.as<PMCTuple<4> >()[0]), pmc_to_pmt(p.as<PMCTuple<4> >()[1]), pmc_to_pmt(p.as<PMCTuple<4> >()[2]), pmc_to_pmt(p.as<PMCTuple<4> >()[3])); + if (p.is<PMCTuple<5> >()) + return pmt_make_tuple(pmc_to_pmt(p.as<PMCTuple<5> >()[0]), pmc_to_pmt(p.as<PMCTuple<5> >()[1]), pmc_to_pmt(p.as<PMCTuple<5> >()[2]), pmc_to_pmt(p.as<PMCTuple<5> >()[3]), pmc_to_pmt(p.as<PMCTuple<5> >()[4])); + if (p.is<PMCTuple<6> >()) + return pmt_make_tuple(pmc_to_pmt(p.as<PMCTuple<6> >()[0]), pmc_to_pmt(p.as<PMCTuple<6> >()[1]), pmc_to_pmt(p.as<PMCTuple<6> >()[2]), pmc_to_pmt(p.as<PMCTuple<6> >()[3]), pmc_to_pmt(p.as<PMCTuple<6> >()[4]), pmc_to_pmt(p.as<PMCTuple<6> >()[5])); + if (p.is<PMCTuple<7> >()) + return pmt_make_tuple(pmc_to_pmt(p.as<PMCTuple<7> >()[0]), pmc_to_pmt(p.as<PMCTuple<7> >()[1]), pmc_to_pmt(p.as<PMCTuple<7> >()[2]), pmc_to_pmt(p.as<PMCTuple<7> >()[3]), pmc_to_pmt(p.as<PMCTuple<7> >()[4]), pmc_to_pmt(p.as<PMCTuple<7> >()[5]), pmc_to_pmt(p.as<PMCTuple<7> >()[6])); + if (p.is<PMCTuple<8> >()) + return pmt_make_tuple(pmc_to_pmt(p.as<PMCTuple<8> >()[0]), pmc_to_pmt(p.as<PMCTuple<8> >()[1]), pmc_to_pmt(p.as<PMCTuple<8> >()[2]), pmc_to_pmt(p.as<PMCTuple<8> >()[3]), pmc_to_pmt(p.as<PMCTuple<8> >()[4]), pmc_to_pmt(p.as<PMCTuple<8> >()[5]), pmc_to_pmt(p.as<PMCTuple<8> >()[6]), pmc_to_pmt(p.as<PMCTuple<8> >()[7])); + if (p.is<PMCTuple<9> >()) + return pmt_make_tuple(pmc_to_pmt(p.as<PMCTuple<9> >()[0]), pmc_to_pmt(p.as<PMCTuple<9> >()[1]), pmc_to_pmt(p.as<PMCTuple<9> >()[2]), pmc_to_pmt(p.as<PMCTuple<9> >()[3]), pmc_to_pmt(p.as<PMCTuple<9> >()[4]), pmc_to_pmt(p.as<PMCTuple<9> >()[5]), pmc_to_pmt(p.as<PMCTuple<9> >()[6]), pmc_to_pmt(p.as<PMCTuple<9> >()[7]), pmc_to_pmt(p.as<PMCTuple<9> >()[8])); + if (p.is<PMCTuple<10> >()) + return pmt_make_tuple(pmc_to_pmt(p.as<PMCTuple<10> >()[0]), pmc_to_pmt(p.as<PMCTuple<10> >()[1]), pmc_to_pmt(p.as<PMCTuple<10> >()[2]), pmc_to_pmt(p.as<PMCTuple<10> >()[3]), pmc_to_pmt(p.as<PMCTuple<10> >()[4]), pmc_to_pmt(p.as<PMCTuple<10> >()[5]), pmc_to_pmt(p.as<PMCTuple<10> >()[6]), pmc_to_pmt(p.as<PMCTuple<10> >()[7]), pmc_to_pmt(p.as<PMCTuple<10> >()[8]), pmc_to_pmt(p.as<PMCTuple<10> >()[9])); + + //vector container + if (p.is<PMCList>()) + { + const PMCList &l = p.as<PMCList>(); + pmt_t v = pmt_make_vector(l.size(), pmt_t()); + for (size_t i = 0; i < l.size(); i++) + { + pmt_vector_set(v, i, pmc_to_pmt(l[i])); + } + return v; + } + + //numeric arrays + #define decl_pmc_to_pmt_numeric_array(type, suffix) \ + if (p.is<std::vector<type> >()) return pmt_init_ ## suffix ## vector(p.as<std::vector<type> >().size(), &p.as<std::vector<type> >()[0]) + decl_pmc_to_pmt_numeric_array(uint8_t, u8); + decl_pmc_to_pmt_numeric_array(uint16_t, u16); + decl_pmc_to_pmt_numeric_array(uint32_t, u32); + decl_pmc_to_pmt_numeric_array(uint64_t, u64); + decl_pmc_to_pmt_numeric_array(int8_t, s8); + decl_pmc_to_pmt_numeric_array(int16_t, s16); + decl_pmc_to_pmt_numeric_array(int32_t, s32); + decl_pmc_to_pmt_numeric_array(int64_t, s64); + decl_pmc_to_pmt_numeric_array(float, f32); + decl_pmc_to_pmt_numeric_array(double, f64); + decl_pmc_to_pmt_numeric_array(std::complex<float>, c32); + decl_pmc_to_pmt_numeric_array(std::complex<double>, c64); + + //dictionary container + if (p.is<PMCDict>()) + { + const PMCDict &m = p.as<PMCDict>(); + pmt_t d = pmt_make_dict(); + BOOST_FOREACH(const PMCPair &pr, m) + { + d = pmt_dict_add(d, pmc_to_pmt(pr.first), pmc_to_pmt(pr.second)); + } + return d; + } + + //set container + if (p.is<PMCSet>()) + { + const PMCSet &s = p.as<PMCSet>(); + pmt_t l = PMT_NIL; + BOOST_FOREACH(const PMCC &elem, s) + { + l = pmt_list_add(l, pmc_to_pmt(elem)); + } + return l; + } + + //is it already a pmt? + if (p.is<pmt_t>()) return p.as<pmt_t>(); + + //backup plan... boost::any + return pmt_make_any(p); + +} + +inline PMCC pmt_to_pmc(const pmt_t &p) +{ + //if the container null? + if (not p) return PMC(); + + #define decl_pmt_to_pmc(check, conv) if (check(p)) return PMC_M(conv(p)) + + //bool + decl_pmt_to_pmc(pmt_is_bool, pmt_to_bool); + + //string (do object interning for strings) + decl_pmt_to_pmc(pmt_is_symbol, pmt_symbol_to_string).intern(); + + //numeric types + decl_pmt_to_pmc(pmt_is_integer, pmt_to_long); + decl_pmt_to_pmc(pmt_is_uint64, pmt_to_uint64); + decl_pmt_to_pmc(pmt_is_real, pmt_to_double); + decl_pmt_to_pmc(pmt_is_complex, pmt_to_complex); + + //is it a boost any holding a PMCC? + if (pmt_is_any(p)) + { + const boost::any a = pmt_any_ref(p); + if (a.type() == typeid(PMCC)) return boost::any_cast<PMCC>(a); + } + + //pair container + if (pmt_is_pair(p)) + { + PMCPair pr(pmt_to_pmc(pmt_car(p)), pmt_to_pmc(pmt_cdr(p))); + return PMC_M(pr); + } + + //fucking tuples + #define decl_pmt_to_pmc_tuple(n) \ + if (pmt_is_tuple(p) and pmt_length(p) == n) \ + { \ + PMCTuple<n> t; \ + for (size_t i = 0; i < n; i++) t[i] = pmt_to_pmc(pmt_tuple_ref(p, i)); \ + return PMC_M(t); \ + } + decl_pmt_to_pmc_tuple(0); + decl_pmt_to_pmc_tuple(1); + decl_pmt_to_pmc_tuple(2); + decl_pmt_to_pmc_tuple(3); + decl_pmt_to_pmc_tuple(4); + decl_pmt_to_pmc_tuple(5); + decl_pmt_to_pmc_tuple(6); + decl_pmt_to_pmc_tuple(7); + decl_pmt_to_pmc_tuple(8); + decl_pmt_to_pmc_tuple(9); + decl_pmt_to_pmc_tuple(10); + + //vector container + if (pmt_is_vector(p)) + { + PMCList l(pmt_length(p)); + for (size_t i = 0; i < l.size(); i++) + { + l[i] = pmt_to_pmc(pmt_vector_ref(p, i)); + } + return PMC_M(l); + } + + //numeric arrays + #define decl_pmt_to_pmc_numeric_array(type, suffix) \ + if (pmt_is_ ## suffix ## vector(p)) \ + { \ + size_t n; const type* i = pmt_ ## suffix ## vector_elements(p, n); \ + return PMC_M(std::vector<type>(i, i+n)); \ + } + decl_pmt_to_pmc_numeric_array(uint8_t, u8); + decl_pmt_to_pmc_numeric_array(uint16_t, u16); + decl_pmt_to_pmc_numeric_array(uint32_t, u32); + decl_pmt_to_pmc_numeric_array(uint64_t, u64); + decl_pmt_to_pmc_numeric_array(int8_t, s8); + decl_pmt_to_pmc_numeric_array(int16_t, s16); + decl_pmt_to_pmc_numeric_array(int32_t, s32); + decl_pmt_to_pmc_numeric_array(int64_t, s64); + decl_pmt_to_pmc_numeric_array(float, f32); + decl_pmt_to_pmc_numeric_array(double, f64); + decl_pmt_to_pmc_numeric_array(std::complex<float>, c32); + decl_pmt_to_pmc_numeric_array(std::complex<double>, c64); + + //dictionary container + if (pmt_is_dict(p)) + { + PMCDict m; + pmt_t items = pmt_dict_items(p); + for (size_t i = 0; i < pmt_length(items); i++) + { + pmt_t item = pmt_nth(i, items); + PMCC key = pmt_to_pmc(pmt_car(item)); + PMCC val = pmt_to_pmc(pmt_cdr(item)); + m[key] = val; + } + return PMC_M(m); + } + + //set container + //FIXME no pmt_is_list... + + //backup plan... store the pmt + return PMC_M(p); +} + +} + +#endif /*INCLUDED_LIBGRAS_PMX_HELPER_HPP*/ diff --git a/gnuradio-core/src/lib/runtime/qa_block_tags.cc b/gnuradio-core/src/lib/runtime/qa_block_tags.cc new file mode 100644 index 000000000..d6b1065e3 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_block_tags.cc @@ -0,0 +1,450 @@ +/* -*- c++ -*- */ +/* + * Copyright 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 <qa_block_tags.h> +#include <gr_block.h> +#include <gr_top_block.h> +#include <gr_null_source.h> +#include <gr_null_sink.h> +#include <gr_head.h> +#include <gr_annotator_alltoall.h> +#include <gr_annotator_1to1.h> +#include <gr_keep_one_in_n.h> +#include <gr_firdes.h> +#include <gr_tags.h> + + +// ---------------------------------------------------------------- + +using namespace pmt; + +// set to 1 to turn on debug output +// The debug output fully checks that the tags seen are what are expected. While +// this behavior currently works with our implementation, there is no guarentee +// that the tags will be coming in this specific order, so it's dangerous to +// rely on this as a test of the tag system working. We would really want to +// tags we know we should see and then test that they all occur once, but in no +// particular order. +#define QA_TAGS_DEBUG 0 + +void +qa_block_tags::t0 () +{ + unsigned int N = 1000; + gr_top_block_sptr tb = gr_make_top_block("top"); + gr_block_sptr src (gr_make_null_source(sizeof(int))); + gr_block_sptr head (gr_make_head(sizeof(int), N)); + gr_block_sptr snk (gr_make_null_sink(sizeof(int))); + + tb->connect(src, 0, head, 0); + tb->connect(head, 0, snk, 0); + + //CPPUNIT_ASSERT_THROW(src->nitems_read(0), std::runtime_error); + //CPPUNIT_ASSERT_THROW(src->nitems_written(0), std::runtime_error); + CPPUNIT_ASSERT_EQUAL(src->nitems_read(0), (uint64_t)0); + CPPUNIT_ASSERT_EQUAL(src->nitems_written(0), (uint64_t)0); + + tb->run(); + + CPPUNIT_ASSERT_THROW(src->nitems_read(0), std::invalid_argument); + CPPUNIT_ASSERT(src->nitems_written(0) >= N); + CPPUNIT_ASSERT_EQUAL(snk->nitems_read(0), (uint64_t)1000); + CPPUNIT_ASSERT_THROW(snk->nitems_written(0), std::invalid_argument); +} + + +void +qa_block_tags::t1 () +{ + int N = 40000; + gr_top_block_sptr tb = gr_make_top_block("top"); + gr_block_sptr src (gr_make_null_source(sizeof(int))); + gr_block_sptr head (gr_make_head(sizeof(int), N)); + gr_annotator_alltoall_sptr ann0 (gr_make_annotator_alltoall(10000, sizeof(int))); + gr_annotator_alltoall_sptr ann1 (gr_make_annotator_alltoall(10000, sizeof(int))); + gr_annotator_alltoall_sptr ann2 (gr_make_annotator_alltoall(10000, sizeof(int))); + gr_annotator_alltoall_sptr ann3 (gr_make_annotator_alltoall(10000, sizeof(int))); + gr_annotator_alltoall_sptr ann4 (gr_make_annotator_alltoall(10000, sizeof(int))); + gr_block_sptr snk0 (gr_make_null_sink(sizeof(int))); + gr_block_sptr snk1 (gr_make_null_sink(sizeof(int))); + + tb->connect(src, 0, head, 0); + tb->connect(head, 0, ann0, 0); + + tb->connect(ann0, 0, ann1, 0); + tb->connect(ann0, 1, ann2, 0); + tb->connect(ann1, 0, ann3, 0); + tb->connect(ann2, 0, ann4, 0); + + tb->connect(ann3, 0, snk0, 0); + tb->connect(ann4, 0, snk1, 0); + + tb->run(); + + std::vector<gr_tag_t> tags0 = ann0->data(); + std::vector<gr_tag_t> tags3 = ann3->data(); + std::vector<gr_tag_t> tags4 = ann4->data(); + + // The first annotator does not receive any tags from the null sink upstream + CPPUNIT_ASSERT_EQUAL(tags0.size(), (size_t)0); + CPPUNIT_ASSERT_EQUAL(tags3.size(), (size_t)8); + CPPUNIT_ASSERT_EQUAL(tags4.size(), (size_t)8); + +#if QA_TAGS_DEBUG + // Kludge together the tags that we know should result from the above graph + std::stringstream str0, str1, str2; + str0 << ann0->name() << ann0->unique_id(); + str1 << ann1->name() << ann1->unique_id(); + str2 << ann2->name() << ann2->unique_id(); + + pmt_t expected_tags3[8]; + expected_tags3[0] = mp(pmt_from_uint64(0), mp(str1.str()), mp("seq"), mp(0)); + expected_tags3[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); + expected_tags3[2] = mp(pmt_from_uint64(10000), mp(str1.str()), mp("seq"), mp(1)); + expected_tags3[3] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(2)); + expected_tags3[4] = mp(pmt_from_uint64(20000), mp(str1.str()), mp("seq"), mp(2)); + expected_tags3[5] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(4)); + expected_tags3[6] = mp(pmt_from_uint64(30000), mp(str1.str()), mp("seq"), mp(3)); + expected_tags3[7] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(6)); + + pmt_t expected_tags4[8]; + expected_tags4[0] = mp(pmt_from_uint64(0), mp(str2.str()), mp("seq"), mp(0)); + expected_tags4[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(1)); + expected_tags4[2] = mp(pmt_from_uint64(10000), mp(str2.str()), mp("seq"), mp(1)); + expected_tags4[3] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(3)); + expected_tags4[4] = mp(pmt_from_uint64(20000), mp(str2.str()), mp("seq"), mp(2)); + expected_tags4[5] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(5)); + expected_tags4[6] = mp(pmt_from_uint64(30000), mp(str2.str()), mp("seq"), mp(3)); + expected_tags4[7] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(7)); + + std::cout << std::endl << "qa_block_tags::t1" << std::endl; + + // For annotator 3, we know it gets tags from ann0 and ann1, test this + for(size_t i = 0; i < tags3.size(); i++) { + std::cout << "tags3[" << i << "] = " << tags3[i] << "\t\t" << expected_tags3[i] << std::endl; + CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags3[i]), pmt_write_string(expected_tags3[i])); + } + + // For annotator 4, we know it gets tags from ann0 and ann2, test this + std::cout << std::endl; + for(size_t i = 0; i < tags4.size(); i++) { + std::cout << "tags4[" << i << "] = " << tags4[i] << "\t\t" << expected_tags4[i] << std::endl; + CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags4[i]), pmt_write_string(expected_tags4[i])); + } +#endif +} + +void +qa_block_tags::t2 () +{ + int N = 40000; + gr_top_block_sptr tb = gr_make_top_block("top"); + gr_block_sptr src (gr_make_null_source(sizeof(int))); + gr_block_sptr head (gr_make_head(sizeof(int), N)); + gr_annotator_alltoall_sptr ann0 (gr_make_annotator_alltoall(10000, sizeof(int))); + gr_annotator_alltoall_sptr ann1 (gr_make_annotator_alltoall(10000, sizeof(int))); + gr_annotator_alltoall_sptr ann2 (gr_make_annotator_alltoall(10000, sizeof(int))); + gr_annotator_alltoall_sptr ann3 (gr_make_annotator_alltoall(10000, sizeof(int))); + gr_annotator_alltoall_sptr ann4 (gr_make_annotator_alltoall(10000, sizeof(int))); + gr_block_sptr snk0 (gr_make_null_sink(sizeof(int))); + gr_block_sptr snk1 (gr_make_null_sink(sizeof(int))); + gr_block_sptr snk2 (gr_make_null_sink(sizeof(int))); + + tb->connect(src, 0, head, 0); + tb->connect(head, 0, ann0, 0); + + tb->connect(ann0, 0, ann1, 0); + tb->connect(ann0, 1, ann1, 1); + tb->connect(ann1, 0, ann2, 0); + tb->connect(ann1, 1, ann3, 0); + tb->connect(ann1, 2, ann4, 0); + + tb->connect(ann2, 0, snk0, 0); + tb->connect(ann3, 0, snk1, 0); + tb->connect(ann4, 0, snk2, 0); + + tb->run(); + + std::vector<gr_tag_t> tags0 = ann0->data(); + std::vector<gr_tag_t> tags1 = ann1->data(); + std::vector<gr_tag_t> tags2 = ann2->data(); + std::vector<gr_tag_t> tags3 = ann4->data(); + std::vector<gr_tag_t> tags4 = ann4->data(); + + // The first annotator does not receive any tags from the null sink upstream + CPPUNIT_ASSERT_EQUAL(tags0.size(), (size_t)0); + CPPUNIT_ASSERT_EQUAL(tags1.size(), (size_t)8); + + // Make sure the rest all have 12 tags + CPPUNIT_ASSERT_EQUAL(tags2.size(), (size_t)12); + CPPUNIT_ASSERT_EQUAL(tags3.size(), (size_t)12); + CPPUNIT_ASSERT_EQUAL(tags4.size(), (size_t)12); + + +#if QA_TAGS_DEBUG + // Kludge together the tags that we know should result from the above graph + std::stringstream str0, str1; + str0 << ann0->name() << ann0->unique_id(); + str1 << ann1->name() << ann1->unique_id(); + + pmt_t expected_tags2[12]; + expected_tags2[0] = mp(pmt_from_uint64(0), mp(str1.str()), mp("seq"), mp(0)); + expected_tags2[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); + expected_tags2[2] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(1)); + expected_tags2[3] = mp(pmt_from_uint64(10000), mp(str1.str()), mp("seq"), mp(3)); + expected_tags2[4] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(2)); + expected_tags2[5] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(3)); + expected_tags2[6] = mp(pmt_from_uint64(20000), mp(str1.str()), mp("seq"), mp(6)); + expected_tags2[7] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(4)); + expected_tags2[8] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(5)); + expected_tags2[9] = mp(pmt_from_uint64(30000), mp(str1.str()), mp("seq"), mp(9)); + expected_tags2[10] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(6)); + expected_tags2[11] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(7)); + + pmt_t expected_tags4[12]; + expected_tags4[0] = mp(pmt_from_uint64(0), mp(str1.str()), mp("seq"), mp(2)); + expected_tags4[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); + expected_tags4[2] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(1)); + expected_tags4[3] = mp(pmt_from_uint64(10000), mp(str1.str()), mp("seq"), mp(5)); + expected_tags4[4] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(2)); + expected_tags4[5] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(3)); + expected_tags4[6] = mp(pmt_from_uint64(20000), mp(str1.str()), mp("seq"), mp(8)); + expected_tags4[7] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(4)); + expected_tags4[8] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(5)); + expected_tags4[9] = mp(pmt_from_uint64(30000), mp(str1.str()), mp("seq"), mp(11)); + expected_tags4[10] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(6)); + expected_tags4[11] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(7)); + + std::cout << std::endl << "qa_block_tags::t2" << std::endl; + + // For annotator[2-4], we know it gets tags from ann0 and ann1 + // but the tags from the different outputs of ann1 are different for each. + // Just testing ann2 and ann4; if they are correct it would be + // inconceivable for ann3 to have it wrong. + for(size_t i = 0; i < tags2.size(); i++) { + std::cout << "tags2[" << i << "] = " << tags2[i] << "\t\t" << expected_tags2[i] << std::endl; + CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags2[i]), pmt_write_string(expected_tags2[i])); + } + + std::cout << std::endl; + for(size_t i = 0; i < tags4.size(); i++) { + std::cout << "tags2[" << i << "] = " << tags4[i] << "\t\t" << expected_tags4[i] << std::endl; + CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags4[i]), pmt_write_string(expected_tags4[i])); + } +#endif +} + + +void +qa_block_tags::t3 () +{ + int N = 40000; + gr_top_block_sptr tb = gr_make_top_block("top"); + gr_block_sptr src (gr_make_null_source(sizeof(int))); + gr_block_sptr head (gr_make_head(sizeof(int), N)); + gr_annotator_1to1_sptr ann0 (gr_make_annotator_1to1(10000, sizeof(int))); + gr_annotator_alltoall_sptr ann1 (gr_make_annotator_alltoall(10000, sizeof(int))); + gr_annotator_alltoall_sptr ann2 (gr_make_annotator_alltoall(10000, sizeof(int))); + gr_annotator_1to1_sptr ann3 (gr_make_annotator_1to1(10000, sizeof(int))); + gr_annotator_1to1_sptr ann4 (gr_make_annotator_1to1(10000, sizeof(int))); + gr_block_sptr snk0 (gr_make_null_sink(sizeof(int))); + gr_block_sptr snk1 (gr_make_null_sink(sizeof(int))); + + tb->connect(src, 0, head, 0); + tb->connect(head, 0, ann0, 0); + tb->connect(head, 0, ann0, 1); + + tb->connect(ann0, 0, ann1, 0); + tb->connect(ann0, 1, ann2, 0); + tb->connect(ann1, 0, ann3, 0); + tb->connect(ann2, 0, ann4, 0); + + tb->connect(ann3, 0, snk0, 0); + tb->connect(ann4, 0, snk1, 0); + + tb->run(); + + + std::vector<gr_tag_t> tags0 = ann0->data(); + std::vector<gr_tag_t> tags3 = ann3->data(); + std::vector<gr_tag_t> tags4 = ann4->data(); + + // The first annotator does not receive any tags from the null sink upstream + CPPUNIT_ASSERT_EQUAL(tags0.size(), (size_t)0); + CPPUNIT_ASSERT_EQUAL(tags3.size(), (size_t)8); + CPPUNIT_ASSERT_EQUAL(tags4.size(), (size_t)8); + +#if QA_TAGS_DEBUG + // Kludge together the tags that we know should result from the above graph + std::stringstream str0, str1, str2; + str0 << ann0->name() << ann0->unique_id(); + str1 << ann1->name() << ann1->unique_id(); + str2 << ann2->name() << ann2->unique_id(); + + pmt_t expected_tags3[8]; + expected_tags3[0] = mp(pmt_from_uint64(0), mp(str1.str()), mp("seq"), mp(0)); + expected_tags3[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); + expected_tags3[2] = mp(pmt_from_uint64(10000), mp(str1.str()), mp("seq"), mp(1)); + expected_tags3[3] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(2)); + expected_tags3[4] = mp(pmt_from_uint64(20000), mp(str1.str()), mp("seq"), mp(2)); + expected_tags3[5] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(4)); + expected_tags3[6] = mp(pmt_from_uint64(30000), mp(str1.str()), mp("seq"), mp(3)); + expected_tags3[7] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(6)); + + pmt_t expected_tags4[8]; + expected_tags4[0] = mp(pmt_from_uint64(0), mp(str2.str()), mp("seq"), mp(0)); + expected_tags4[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(1)); + expected_tags4[2] = mp(pmt_from_uint64(10000), mp(str2.str()), mp("seq"), mp(1)); + expected_tags4[3] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(3)); + expected_tags4[4] = mp(pmt_from_uint64(20000), mp(str2.str()), mp("seq"), mp(2)); + expected_tags4[5] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(5)); + expected_tags4[6] = mp(pmt_from_uint64(30000), mp(str2.str()), mp("seq"), mp(3)); + expected_tags4[7] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(7)); + + std::cout << std::endl << "qa_block_tags::t3" << std::endl; + + // For annotator 3, we know it gets tags from ann0 and ann1, test this + for(size_t i = 0; i < tags3.size(); i++) { + std::cout << "tags3[" << i << "] = " << tags3[i] << "\t\t" << expected_tags3[i] << std::endl; + CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags3[i]), pmt_write_string(expected_tags3[i])); + } + + // For annotator 4, we know it gets tags from ann0 and ann2, test this + std::cout << std::endl; + for(size_t i = 0; i < tags4.size(); i++) { + std::cout << "tags4[" << i << "] = " << tags4[i] << "\t\t" << expected_tags4[i] << std::endl; + CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags4[i]), pmt_write_string(expected_tags4[i])); + } +#endif +} + + +void +qa_block_tags::t4 () +{ + int N = 40000; + gr_top_block_sptr tb = gr_make_top_block("top"); + gr_block_sptr src (gr_make_null_source(sizeof(int))); + gr_block_sptr head (gr_make_head(sizeof(int), N)); + gr_annotator_1to1_sptr ann0 (gr_make_annotator_1to1(10000, sizeof(int))); + gr_annotator_1to1_sptr ann1 (gr_make_annotator_1to1(10000, sizeof(int))); + gr_annotator_1to1_sptr ann2 (gr_make_annotator_1to1(10000, sizeof(int))); + gr_block_sptr snk0 (gr_make_null_sink(sizeof(int))); + gr_block_sptr snk1 (gr_make_null_sink(sizeof(int))); + + // using 1-to-1 tag propagation without having equal number of + // ins and outs. Make sure this works; will just exit run early. + tb->connect(src, 0, head, 0); + tb->connect(head, 0, ann0, 0); + tb->connect(ann0, 0, ann1, 0); + tb->connect(ann0, 1, ann2, 0); + tb->connect(ann1, 0, snk0, 0); + tb->connect(ann2, 0, snk1, 0); + + std::cerr << std::endl + << "NOTE: This is supposed to produce an error from gr_block_executor" + << std::endl; + tb->run(); +} + + +void +qa_block_tags::t5 () +{ + int N = 40000; + gr_top_block_sptr tb = gr_make_top_block("top"); + gr_block_sptr src (gr_make_null_source(sizeof(float))); + gr_block_sptr head (gr_make_head(sizeof(float), N)); + gr_annotator_alltoall_sptr ann0 (gr_make_annotator_alltoall(10000, sizeof(float))); + gr_annotator_alltoall_sptr ann1 (gr_make_annotator_alltoall(10000, sizeof(float))); + gr_annotator_alltoall_sptr ann2 (gr_make_annotator_alltoall(1000, sizeof(float))); + gr_block_sptr snk0 (gr_make_null_sink(sizeof(float))); + + // Rate change blocks + gr_keep_one_in_n_sptr dec10 (gr_make_keep_one_in_n(sizeof(float), 10)); + + tb->connect(src, 0, head, 0); + tb->connect(head, 0, ann0, 0); + tb->connect(ann0, 0, ann1, 0); + tb->connect(ann1, 0, dec10, 0); + tb->connect(dec10, 0, ann2, 0); + tb->connect(ann2, 0, snk0, 0); + + tb->run(); + + std::vector<gr_tag_t> tags0 = ann0->data(); + std::vector<gr_tag_t> tags1 = ann1->data(); + std::vector<gr_tag_t> tags2 = ann2->data(); + + // The first annotator does not receive any tags from the null sink upstream + CPPUNIT_ASSERT_EQUAL(tags0.size(), (size_t)0); + CPPUNIT_ASSERT_EQUAL(tags1.size(), (size_t)4); + CPPUNIT_ASSERT_EQUAL(tags2.size(), (size_t)8); + + +#if QA_TAGS_DEBUG + // Kludge together the tags that we know should result from the above graph + std::stringstream str0, str1, str2; + str0 << ann0->name() << ann0->unique_id(); + str1 << ann1->name() << ann1->unique_id(); + str2 << ann2->name() << ann2->unique_id(); + + pmt_t expected_tags1[5]; + expected_tags1[0] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); + expected_tags1[1] = mp(pmt_from_uint64(10000), mp(str0.str()), mp("seq"), mp(1)); + expected_tags1[2] = mp(pmt_from_uint64(20000), mp(str0.str()), mp("seq"), mp(2)); + expected_tags1[3] = mp(pmt_from_uint64(30000), mp(str0.str()), mp("seq"), mp(3)); + + pmt_t expected_tags2[10]; + expected_tags2[0] = mp(pmt_from_uint64(0), mp(str1.str()), mp("seq"), mp(0)); + expected_tags2[1] = mp(pmt_from_uint64(0), mp(str0.str()), mp("seq"), mp(0)); + expected_tags2[2] = mp(pmt_from_uint64(1000), mp(str1.str()), mp("seq"), mp(1)); + expected_tags2[3] = mp(pmt_from_uint64(1000), mp(str0.str()), mp("seq"), mp(1)); + expected_tags2[4] = mp(pmt_from_uint64(2000), mp(str1.str()), mp("seq"), mp(2)); + expected_tags2[5] = mp(pmt_from_uint64(2000), mp(str0.str()), mp("seq"), mp(2)); + expected_tags2[6] = mp(pmt_from_uint64(3000), mp(str1.str()), mp("seq"), mp(3)); + expected_tags2[7] = mp(pmt_from_uint64(3000), mp(str0.str()), mp("seq"), mp(3)); + expected_tags2[8] = mp(pmt_from_uint64(4000), mp(str1.str()), mp("seq"), mp(4)); + expected_tags2[9] = mp(pmt_from_uint64(4000), mp(str0.str()), mp("seq"), mp(4)); + + std::cout << std::endl << "qa_block_tags::t5" << std::endl; + + // annotator 1 gets tags from annotator 0 + std::cout << "tags1.size(): " << tags1.size() << std::endl; + for(size_t i = 0; i < tags1.size(); i++) { + std::cout << "tags1[" << i << "] = " << tags1[i] << "\t\t" << expected_tags1[i] << std::endl; + CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags1[i]), pmt_write_string(expected_tags1[i])); + } + + // annotator 2 gets tags from annotators 0 and 1 + std::cout << std::endl; + std::cout << "tags2.size(): " << tags2.size() << std::endl; + for(size_t i = 0; i < tags2.size(); i++) { + std::cout << "tags2[" << i << "] = " << tags2[i] << "\t\t" << expected_tags2[i] << std::endl; + CPPUNIT_ASSERT_EQUAL(pmt_write_string(tags2[i]), pmt_write_string(expected_tags2[i])); + } +#endif +} + diff --git a/gnuradio-core/src/lib/runtime/qa_block_tags.h b/gnuradio-core/src/lib/runtime/qa_block_tags.h new file mode 100644 index 000000000..6b7e5975d --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_block_tags.h @@ -0,0 +1,52 @@ +/* -*- c++ -*- */ +/* + * Copyright 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_QA_BLOCK_TAGS_H +#define INCLUDED_QA_BLOCK_TAGS_H + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> +#include <stdexcept> + +class qa_block_tags : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_block_tags); + CPPUNIT_TEST (t0); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST (t4); + CPPUNIT_TEST (t5); + CPPUNIT_TEST_SUITE_END (); + + private: + void t0 (); + void t1 (); + void t2 (); + void t3 (); + void t4 (); + void t5 (); + +}; + + +#endif /* INCLUDED_QA_BLOCK_TAGS_H */ diff --git a/gnuradio-core/src/lib/runtime/qa_gr_block.cc b/gnuradio-core/src/lib/runtime/qa_gr_block.cc new file mode 100644 index 000000000..aeab5b74a --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_block.cc @@ -0,0 +1,88 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <qa_gr_block.h> +#include <gr_block.h> +#include <gr_io_signature.h> +#include <gr_null_sink.h> +#include <gr_null_source.h> + + +// ---------------------------------------------------------------- + + +void +qa_gr_block::t0 () +{ + // test creation of sources + gr_block_sptr src1 (gr_make_null_source (sizeof (int))); + CPPUNIT_ASSERT_EQUAL (std::string ("null_source"), src1->name ()); + CPPUNIT_ASSERT_EQUAL (0, src1->input_signature()->max_streams ()); + CPPUNIT_ASSERT_EQUAL (1, src1->output_signature()->min_streams ()); + CPPUNIT_ASSERT_EQUAL (1, src1->output_signature()->max_streams ()); + CPPUNIT_ASSERT_EQUAL ((int) sizeof(int), + src1->output_signature()->sizeof_stream_item (0)); + + gr_block_sptr src2 (gr_make_null_source (sizeof (short))); + CPPUNIT_ASSERT_EQUAL (std::string ("null_source"), src2->name ()); + CPPUNIT_ASSERT_EQUAL (0, src2->input_signature()->max_streams ()); + CPPUNIT_ASSERT_EQUAL (1, src2->output_signature()->min_streams ()); + CPPUNIT_ASSERT_EQUAL (1, src2->output_signature()->max_streams ()); + CPPUNIT_ASSERT_EQUAL ((int) sizeof (short), + src2->output_signature()->sizeof_stream_item (0)); +} + + +void +qa_gr_block::t1 () +{ + // test creation of sinks + gr_block_sptr dst1 (gr_make_null_sink (sizeof (int))); + CPPUNIT_ASSERT_EQUAL (std::string ("null_sink"), dst1->name ()); + CPPUNIT_ASSERT_EQUAL (1, dst1->input_signature()->min_streams ()); + CPPUNIT_ASSERT_EQUAL (1, dst1->input_signature()->max_streams ()); + CPPUNIT_ASSERT_EQUAL ((int) sizeof (int), + dst1->input_signature()->sizeof_stream_item (0)); + + CPPUNIT_ASSERT_EQUAL (0, dst1->output_signature()->max_streams ()); + + gr_block_sptr dst2 (gr_make_null_sink (sizeof (short))); + CPPUNIT_ASSERT_EQUAL (std::string ("null_sink"), dst2->name ()); + CPPUNIT_ASSERT_EQUAL (1, dst2->input_signature()->min_streams ()); + CPPUNIT_ASSERT_EQUAL (1, dst2->input_signature()->max_streams ()); + CPPUNIT_ASSERT_EQUAL ((int) sizeof (short), + dst2->input_signature()->sizeof_stream_item (0)); + CPPUNIT_ASSERT_EQUAL (0, dst2->output_signature()->max_streams ()); +} + +void +qa_gr_block::t2 () +{ +} + +void +qa_gr_block::t3 () +{ +} diff --git a/gnuradio-core/src/lib/runtime/qa_gr_block.h b/gnuradio-core/src/lib/runtime/qa_gr_block.h new file mode 100644 index 000000000..14c7c40d1 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_block.h @@ -0,0 +1,48 @@ +/* -*- 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_QA_GR_BLOCK_H +#define INCLUDED_QA_GR_BLOCK_H + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> +#include <stdexcept> + +class qa_gr_block : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_block); + CPPUNIT_TEST (t0); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST_SUITE_END (); + + private: + void t0 (); + void t1 (); + void t2 (); + void t3 (); + +}; + + +#endif /* INCLUDED_QA_GR_BLOCK_H */ diff --git a/gnuradio-core/src/lib/runtime/qa_gr_buffer.cc b/gnuradio-core/src/lib/runtime/qa_gr_buffer.cc new file mode 100644 index 000000000..c74baf398 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_buffer.cc @@ -0,0 +1,307 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <qa_gr_buffer.h> +#include <gr_buffer.h> +#include <cppunit/TestAssert.h> +#include <stdlib.h> +#include <gr_random.h> + +static void +leak_check (void f ()) +{ + long buffer_count = gr_buffer_ncurrently_allocated (); + long buffer_reader_count = gr_buffer_reader_ncurrently_allocated (); + + f (); + + CPPUNIT_ASSERT_EQUAL (buffer_reader_count, gr_buffer_reader_ncurrently_allocated ()); + CPPUNIT_ASSERT_EQUAL (buffer_count, gr_buffer_ncurrently_allocated ()); +} + + +// ---------------------------------------------------------------------------- +// test single writer, no readers... +// + +static void +t0_body () +{ + int nitems = 4000 / sizeof (int); + int counter = 0; + + gr_buffer_sptr buf(gr_make_buffer(nitems, sizeof (int), gr_block_sptr())); + + int last_sa; + int sa; + + sa = buf->space_available (); + CPPUNIT_ASSERT (sa > 0); + last_sa = sa; + + for (int i = 0; i < 5; i++){ + sa = buf->space_available (); + CPPUNIT_ASSERT_EQUAL (last_sa, sa); + last_sa = sa; + + int *p = (int *) buf->write_pointer (); + CPPUNIT_ASSERT (p != 0); + + for (int j = 0; j < sa; j++) + *p++ = counter++; + + buf->update_write_pointer (sa); + } +} + +// ---------------------------------------------------------------------------- +// test single writer, single reader +// + +static void +t1_body () + { + int nitems = 4000 / sizeof (int); + int write_counter = 0; + int read_counter = 0; + + gr_buffer_sptr buf(gr_make_buffer(nitems, sizeof (int), gr_block_sptr())); + gr_buffer_reader_sptr r1 (gr_buffer_add_reader (buf, 0, gr_block_sptr())); + + + int sa; + + // write 1/3 of buffer + + sa = buf->space_available (); + CPPUNIT_ASSERT (sa > 0); + + int *p = (int *) buf->write_pointer (); + CPPUNIT_ASSERT (p != 0); + + for (int j = 0; j < sa/3; j++){ + *p++ = write_counter++; + } + buf->update_write_pointer (sa/3); + + + // write the next 1/3 (1/2 of what's left) + + sa = buf->space_available (); + CPPUNIT_ASSERT (sa > 0); + + p = (int *) buf->write_pointer (); + CPPUNIT_ASSERT (p != 0); + + for (int j = 0; j < sa/2; j++){ + *p++ = write_counter++; + } + buf->update_write_pointer (sa/2); + + + // check that we can read it OK + + int ia = r1->items_available (); + CPPUNIT_ASSERT_EQUAL (write_counter, ia); + + int *rp = (int *) r1->read_pointer (); + CPPUNIT_ASSERT (rp != 0); + + for (int i = 0; i < ia/2; i++){ + CPPUNIT_ASSERT_EQUAL (read_counter, *rp); + read_counter++; + rp++; + } + r1->update_read_pointer (ia/2); + + // read the rest + + ia = r1->items_available (); + rp = (int *) r1->read_pointer (); + CPPUNIT_ASSERT (rp != 0); + + for (int i = 0; i < ia; i++){ + CPPUNIT_ASSERT_EQUAL (read_counter, *rp); + read_counter++; + rp++; + } + r1->update_read_pointer (ia); +} + +// ---------------------------------------------------------------------------- +// single writer, single reader: check wrap-around +// + +static void +t2_body () +{ + // 64K is the largest granularity we've seen so far (MS windows file mapping). + // This allows a bit of "white box testing" + + int nitems = (64 * (1L << 10)) / sizeof (int); // 64K worth of ints + + gr_buffer_sptr buf(gr_make_buffer (nitems, sizeof (int), gr_block_sptr())); + gr_buffer_reader_sptr r1 (gr_buffer_add_reader (buf, 0, gr_block_sptr())); + + int read_counter = 0; + int write_counter = 0; + int n; + int *wp = 0; + int *rp = 0; + + // Write 3/4 of buffer + + n = (int) (buf->space_available () * 0.75); + wp = (int *) buf->write_pointer (); + + for (int i = 0; i < n; i++) + *wp++ = write_counter++; + buf->update_write_pointer (n); + + // Now read it all + + int m = r1->items_available (); + CPPUNIT_ASSERT_EQUAL (n, m); + rp = (int *) r1->read_pointer (); + + for (int i = 0; i < m; i++){ + CPPUNIT_ASSERT_EQUAL (read_counter, *rp); + read_counter++; + rp++; + } + r1->update_read_pointer (m); + + // Now write as much as we can. + // This will wrap around the buffer + + n = buf->space_available (); + CPPUNIT_ASSERT_EQUAL (nitems - 1, n); // white box test + wp = (int *) buf->write_pointer (); + + for (int i = 0; i < n; i++) + *wp++ = write_counter++; + buf->update_write_pointer (n); + + // now read it all + + m = r1->items_available (); + CPPUNIT_ASSERT_EQUAL (n, m); + rp = (int *) r1->read_pointer (); + + for (int i = 0; i < m; i++){ + CPPUNIT_ASSERT_EQUAL (read_counter, *rp); + read_counter++; + rp++; + } + r1->update_read_pointer (m); + +} + +// ---------------------------------------------------------------------------- +// single writer, N readers, randomized order and lengths +// ---------------------------------------------------------------------------- + +static void +t3_body () +{ + int nitems = (64 * (1L << 10)) / sizeof (int); + + static const int N = 5; + gr_buffer_sptr buf(gr_make_buffer(nitems, sizeof (int), gr_block_sptr())); + gr_buffer_reader_sptr reader[N]; + int read_counter[N]; + int write_counter = 0; + gr_random random; + + for (int i = 0; i < N; i++){ + read_counter[i] = 0; + reader[i] = gr_buffer_add_reader (buf, 0, gr_block_sptr()); + } + + for (int lc = 0; lc < 1000; lc++){ + + // write some + + int n = (int) (buf->space_available () * random.ran1 ()); + int *wp = (int *) buf->write_pointer (); + + for (int i = 0; i < n; i++) + *wp++ = write_counter++; + + buf->update_write_pointer (n); + + // pick a random reader and read some + + int r = (int) (N * random.ran1 ()); + CPPUNIT_ASSERT (0 <= r && r < N); + + int m = reader[r]->items_available (); + int *rp = (int *) reader[r]->read_pointer (); + + for (int i = 0; i < m; i++){ + CPPUNIT_ASSERT_EQUAL (read_counter[r], *rp); + read_counter[r]++; + rp++; + } + reader[r]->update_read_pointer (m); + } +} + + +// ---------------------------------------------------------------------------- + +void +qa_gr_buffer::t0 () +{ + leak_check (t0_body); +} + +void +qa_gr_buffer::t1 () +{ + leak_check (t1_body); +} + +void +qa_gr_buffer::t2 () +{ + leak_check (t2_body); +} + +void +qa_gr_buffer::t3 () +{ + leak_check (t3_body); +} + +void +qa_gr_buffer::t4 () +{ +} + +void +qa_gr_buffer::t5 () +{ +} diff --git a/gnuradio-core/src/lib/runtime/qa_gr_buffer.h b/gnuradio-core/src/lib/runtime/qa_gr_buffer.h new file mode 100644 index 000000000..2937c24b6 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_buffer.h @@ -0,0 +1,53 @@ +/* -*- 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_QA_GR_BUFFER_H +#define INCLUDED_QA_GR_BUFFER_H + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_gr_buffer : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_buffer); + CPPUNIT_TEST (t0); + CPPUNIT_TEST (t1); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST (t4); + CPPUNIT_TEST (t5); + CPPUNIT_TEST_SUITE_END (); + + + private: + + void t0 (); + void t1 (); + void t2 (); + void t3 (); + void t4 (); + void t5 (); +}; + + + +#endif /* INCLUDED_QA_GR_BUFFER_H */ diff --git a/gnuradio-core/src/lib/runtime/qa_gr_flowgraph.cc b/gnuradio-core/src/lib/runtime/qa_gr_flowgraph.cc new file mode 100644 index 000000000..cce83cb0a --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_flowgraph.cc @@ -0,0 +1,245 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <qa_gr_flowgraph.h> +#include <gr_flowgraph.h> +#include <gr_nop.h> +#include <gr_null_source.h> +#include <gr_null_sink.h> + +void qa_gr_flowgraph::t0() +{ + gr_flowgraph_sptr fg = gr_make_flowgraph(); + + CPPUNIT_ASSERT(fg); +} + +void qa_gr_flowgraph::t1_connect() +{ + gr_flowgraph_sptr fg = gr_make_flowgraph(); + + gr_block_sptr nop1 = gr_make_nop(sizeof(int)); + gr_block_sptr nop2 = gr_make_nop(sizeof(int)); + + fg->connect(nop1, 0, nop2, 0); +} + +void qa_gr_flowgraph::t2_connect_invalid_src_port_neg() +{ + gr_flowgraph_sptr fg = gr_make_flowgraph(); + + gr_block_sptr nop1 = gr_make_nop(sizeof(int)); + gr_block_sptr nop2 = gr_make_nop(sizeof(int)); + + CPPUNIT_ASSERT_THROW(fg->connect(nop1, -1, nop2, 0), std::invalid_argument); +} + +void qa_gr_flowgraph::t3_connect_src_port_exceeds() +{ + gr_flowgraph_sptr fg = gr_make_flowgraph(); + + gr_block_sptr src = gr_make_null_source(sizeof(int)); + gr_block_sptr dst = gr_make_null_sink(sizeof(int)); + + CPPUNIT_ASSERT_THROW(fg->connect(src, 1, dst, 0), std::invalid_argument); +} + +void qa_gr_flowgraph::t4_connect_invalid_dst_port_neg() +{ + gr_flowgraph_sptr fg = gr_make_flowgraph(); + + gr_block_sptr nop1 = gr_make_nop(sizeof(int)); + gr_block_sptr nop2 = gr_make_nop(sizeof(int)); + + CPPUNIT_ASSERT_THROW(fg->connect(nop1, 0, nop2, -1), std::invalid_argument); +} + +void qa_gr_flowgraph::t5_connect_dst_port_exceeds() +{ + gr_flowgraph_sptr fg = gr_make_flowgraph(); + + gr_block_sptr src = gr_make_null_source(sizeof(int)); + gr_block_sptr dst = gr_make_null_sink(sizeof(int)); + + CPPUNIT_ASSERT_THROW(fg->connect(src, 0, dst, 1), std::invalid_argument); +} + +void qa_gr_flowgraph::t6_connect_dst_in_use() +{ + gr_flowgraph_sptr fg = gr_make_flowgraph(); + + gr_block_sptr src1 = gr_make_null_source(sizeof(int)); + gr_block_sptr src2 = gr_make_null_source(sizeof(int)); + gr_block_sptr dst = gr_make_null_sink(sizeof(int)); + + fg->connect(src1, 0, dst, 0); + CPPUNIT_ASSERT_THROW(fg->connect(src2, 0, dst, 0), std::invalid_argument); +} + +void qa_gr_flowgraph::t7_connect_one_src_two_dst() +{ + gr_flowgraph_sptr fg = gr_make_flowgraph(); + + gr_block_sptr src = gr_make_null_source(sizeof(int)); + gr_block_sptr dst1 = gr_make_null_sink(sizeof(int)); + gr_block_sptr dst2 = gr_make_null_sink(sizeof(int)); + + fg->connect(src, 0, dst1, 0); + fg->connect(src, 0, dst2, 0); +} + +void qa_gr_flowgraph::t8_connect_type_mismatch() +{ + gr_flowgraph_sptr fg = gr_make_flowgraph(); + + gr_block_sptr nop1 = gr_make_nop(sizeof(char)); + gr_block_sptr nop2 = gr_make_nop(sizeof(int)); + + CPPUNIT_ASSERT_THROW(fg->connect(nop1, 0, nop2, 0), std::invalid_argument); +} + +void qa_gr_flowgraph::t9_disconnect() +{ + gr_flowgraph_sptr fg = gr_make_flowgraph(); + + gr_block_sptr nop1 = gr_make_nop(sizeof(int)); + gr_block_sptr nop2 = gr_make_nop(sizeof(int)); + + fg->connect(nop1, 0, nop2, 0); + fg->disconnect(nop1, 0, nop2, 0); +} + +void qa_gr_flowgraph::t10_disconnect_unconnected_block() +{ + gr_flowgraph_sptr fg = gr_make_flowgraph(); + + gr_block_sptr nop1 = gr_make_nop(sizeof(int)); + gr_block_sptr nop2 = gr_make_nop(sizeof(int)); + gr_block_sptr nop3 = gr_make_nop(sizeof(int)); + + fg->connect(nop1, 0, nop2, 0); + CPPUNIT_ASSERT_THROW(fg->disconnect(nop1, 0, nop3, 0), std::invalid_argument); +} + +void qa_gr_flowgraph::t11_disconnect_unconnected_port() +{ + gr_flowgraph_sptr fg = gr_make_flowgraph(); + + gr_block_sptr nop1 = gr_make_nop(sizeof(int)); + gr_block_sptr nop2 = gr_make_nop(sizeof(int)); + + fg->connect(nop1, 0, nop2, 0); + CPPUNIT_ASSERT_THROW(fg->disconnect(nop1, 0, nop2, 1), std::invalid_argument); +} + +void qa_gr_flowgraph::t12_validate() +{ + gr_flowgraph_sptr fg = gr_make_flowgraph(); + + gr_block_sptr nop1 = gr_make_nop(sizeof(int)); + gr_block_sptr nop2 = gr_make_nop(sizeof(int)); + + fg->connect(nop1, 0, nop2, 0); + fg->validate(); +} + +void qa_gr_flowgraph::t13_validate_missing_input_assignment() +{ + gr_flowgraph_sptr fg = gr_make_flowgraph(); + + gr_block_sptr nop1 = gr_make_nop(sizeof(int)); + gr_block_sptr nop2 = gr_make_nop(sizeof(int)); + + fg->connect(nop1, 0, nop2, 0); + fg->connect(nop1, 0, nop2, 2); + CPPUNIT_ASSERT_THROW(fg->validate(), std::runtime_error); +} + +void qa_gr_flowgraph::t14_validate_missing_output_assignment() +{ + gr_flowgraph_sptr fg = gr_make_flowgraph(); + + gr_block_sptr nop1 = gr_make_nop(sizeof(int)); + gr_block_sptr nop2 = gr_make_nop(sizeof(int)); + + fg->connect(nop1, 0, nop2, 0); + fg->connect(nop1, 2, nop2, 1); + CPPUNIT_ASSERT_THROW(fg->validate(), std::runtime_error); +} + +void qa_gr_flowgraph::t15_clear() +{ + gr_flowgraph_sptr fg = gr_make_flowgraph(); + + gr_block_sptr nop1 = gr_make_nop(sizeof(int)); + gr_block_sptr nop2 = gr_make_nop(sizeof(int)); + + fg->connect(nop1, 0, nop2, 0); + + CPPUNIT_ASSERT(fg->edges().size() == 1); + CPPUNIT_ASSERT(fg->calc_used_blocks().size() == 2); + + fg->clear(); + + CPPUNIT_ASSERT(fg->edges().size() == 0); + CPPUNIT_ASSERT(fg->calc_used_blocks().size() == 0); +} + +void qa_gr_flowgraph::t16_partition() +{ + gr_flowgraph_sptr fg = gr_make_flowgraph(); + + gr_block_sptr nop11 = gr_make_nop(sizeof(int)); + gr_block_sptr nop12 = gr_make_nop(sizeof(int)); + gr_block_sptr nop13 = gr_make_nop(sizeof(int)); + gr_block_sptr nop14 = gr_make_nop(sizeof(int)); + + gr_block_sptr nop21 = gr_make_nop(sizeof(int)); + gr_block_sptr nop22 = gr_make_nop(sizeof(int)); + gr_block_sptr nop23 = gr_make_nop(sizeof(int)); + + gr_block_sptr nop31 = gr_make_nop(sizeof(int)); + gr_block_sptr nop32 = gr_make_nop(sizeof(int)); + + // Build disjoint graph #1 + fg->connect(nop11, 0, nop12, 0); + fg->connect(nop12, 0, nop13, 0); + fg->connect(nop13, 0, nop14, 0); + + // Build disjoint graph #2 + fg->connect(nop21, 0, nop22, 0); + fg->connect(nop22, 0, nop23, 0); + + // Build disjoint graph #3 + fg->connect(nop31, 0, nop32, 0); + + std::vector<gr_basic_block_vector_t> graphs = fg->partition(); + + CPPUNIT_ASSERT(graphs.size() == 3); + CPPUNIT_ASSERT(graphs[0].size() == 4); + CPPUNIT_ASSERT(graphs[1].size() == 3); + CPPUNIT_ASSERT(graphs[2].size() == 2); +} diff --git a/gnuradio-core/src/lib/runtime/qa_gr_flowgraph.h b/gnuradio-core/src/lib/runtime/qa_gr_flowgraph.h new file mode 100644 index 000000000..2c2686f71 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_flowgraph.h @@ -0,0 +1,75 @@ +/* -*- 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_QA_GR_FLOWGRAPH_H +#define INCLUDED_QA_GR_FLOWGRAPH_H + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> +#include <stdexcept> + +class qa_gr_flowgraph : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(qa_gr_flowgraph); + + CPPUNIT_TEST(t0); + CPPUNIT_TEST(t1_connect); + CPPUNIT_TEST(t2_connect_invalid_src_port_neg); + CPPUNIT_TEST(t3_connect_src_port_exceeds); + CPPUNIT_TEST(t4_connect_invalid_dst_port_neg); + CPPUNIT_TEST(t5_connect_dst_port_exceeds); + CPPUNIT_TEST(t6_connect_dst_in_use); + CPPUNIT_TEST(t7_connect_one_src_two_dst); + CPPUNIT_TEST(t8_connect_type_mismatch); + CPPUNIT_TEST(t9_disconnect); + CPPUNIT_TEST(t10_disconnect_unconnected_block); + CPPUNIT_TEST(t11_disconnect_unconnected_port); + CPPUNIT_TEST(t12_validate); + CPPUNIT_TEST(t13_validate_missing_input_assignment); + CPPUNIT_TEST(t14_validate_missing_output_assignment); + CPPUNIT_TEST(t15_clear); + CPPUNIT_TEST(t16_partition); + + CPPUNIT_TEST_SUITE_END(); + +private: + + void t0(); + void t1_connect(); + void t2_connect_invalid_src_port_neg(); + void t3_connect_src_port_exceeds(); + void t4_connect_invalid_dst_port_neg(); + void t5_connect_dst_port_exceeds(); + void t6_connect_dst_in_use(); + void t7_connect_one_src_two_dst(); + void t8_connect_type_mismatch(); + void t9_disconnect(); + void t10_disconnect_unconnected_block(); + void t11_disconnect_unconnected_port(); + void t12_validate(); + void t13_validate_missing_input_assignment(); + void t14_validate_missing_output_assignment(); + void t15_clear(); + void t16_partition(); +}; + +#endif /* INCLUDED_QA_GR_FLOWGRAPH_H */ diff --git a/gnuradio-core/src/lib/runtime/qa_gr_hier_block2.cc b/gnuradio-core/src/lib/runtime/qa_gr_hier_block2.cc new file mode 100644 index 000000000..9844d3381 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_hier_block2.cc @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2008,2009 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 <qa_gr_hier_block2.h> +#include <gr_hier_block2.h> +#include <gr_io_signature.h> +#include <gr_null_source.h> +#include <gr_null_sink.h> + +void qa_gr_hier_block2::test_make() +{ + gr_hier_block2_sptr src1(gr_make_hier_block2("test", + gr_make_io_signature(1, 1, 1 * sizeof(int)), + gr_make_io_signature(1, 1, 1 * sizeof(int)))); + + CPPUNIT_ASSERT(src1); + CPPUNIT_ASSERT_EQUAL(std::string("test"), src1->name()); + + CPPUNIT_ASSERT_EQUAL(1 * (int) sizeof(int), + src1->input_signature()->sizeof_stream_item(0)); + + CPPUNIT_ASSERT_EQUAL(1, src1->input_signature()->min_streams()); + CPPUNIT_ASSERT_EQUAL(1, src1->input_signature()->max_streams()); + + + CPPUNIT_ASSERT_EQUAL(1 * (int) sizeof(int), + src1->output_signature()->sizeof_stream_item(0)); + + CPPUNIT_ASSERT_EQUAL(1, src1->output_signature()->min_streams()); + CPPUNIT_ASSERT_EQUAL(1, src1->output_signature()->max_streams()); + +} + + diff --git a/gnuradio-core/src/lib/runtime/qa_gr_hier_block2.h b/gnuradio-core/src/lib/runtime/qa_gr_hier_block2.h new file mode 100644 index 000000000..653cd2725 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_hier_block2.h @@ -0,0 +1,42 @@ +/* -*- 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_QA_GR_HIER_BLOCK2_H +#define INCLUDED_QA_GR_HIER_BLOCK2_H + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> +#include <stdexcept> + +class qa_gr_hier_block2 : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(qa_gr_hier_block2); + + CPPUNIT_TEST(test_make); + + CPPUNIT_TEST_SUITE_END(); + +private: + void test_make(); +}; + +#endif /* INCLUDED_QA_GR_HIER_BLOCK2_H */ diff --git a/gnuradio-core/src/lib/runtime/qa_gr_hier_block2_derived.cc b/gnuradio-core/src/lib/runtime/qa_gr_hier_block2_derived.cc new file mode 100644 index 000000000..060c4e244 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_hier_block2_derived.cc @@ -0,0 +1,87 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <qa_gr_hier_block2_derived.h> +#include <gr_top_block.h> +#include <gr_io_signature.h> +#include <gr_null_source.h> +#include <gr_null_sink.h> +#include <gr_head.h> +#include <gr_kludge_copy.h> + +// Declare a test C++ hierarchical block + +class gr_derived_block; +typedef boost::shared_ptr<gr_derived_block> gr_derived_block_sptr; +gr_derived_block_sptr gr_make_derived_block(); + +class gr_derived_block : public gr_hier_block2 +{ +private: + friend gr_derived_block_sptr gr_make_derived_block(); + gr_derived_block(); + +public: + ~gr_derived_block(); +}; + + +gr_derived_block_sptr +gr_make_derived_block() +{ + return gnuradio::get_initial_sptr(new gr_derived_block()); +} + +gr_derived_block::gr_derived_block() + : gr_hier_block2("gr_derived_block", + gr_make_io_signature(1, 1, sizeof(int)), // Input signature + gr_make_io_signature(1, 1, sizeof(int))) // Output signature +{ + gr_block_sptr copy(gr_make_kludge_copy(sizeof(int))); + + connect(self(), 0, copy, 0); + connect(copy, 0, self(), 0); +} + +gr_derived_block::~gr_derived_block() +{ +} + +void qa_gr_hier_block2_derived::test_1() +{ + gr_top_block_sptr tb(gr_make_top_block("test")); + + gr_block_sptr src(gr_make_null_source(sizeof(int))); + gr_block_sptr head(gr_make_head(sizeof(int), 1000)); + gr_derived_block_sptr blk(gr_make_derived_block()); + gr_block_sptr dst(gr_make_null_sink(sizeof(int))); + + tb->connect(src, 0, head, 0); + tb->connect(head, 0, blk, 0); + tb->connect(blk, 0, dst, 0); + + tb->run(); +} diff --git a/gnuradio-core/src/lib/runtime/qa_gr_hier_block2_derived.h b/gnuradio-core/src/lib/runtime/qa_gr_hier_block2_derived.h new file mode 100644 index 000000000..8e0a1880c --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_hier_block2_derived.h @@ -0,0 +1,41 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,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_QA_GR_HIER_BLOCK2_DERIVED_H +#define INCLUDED_QA_GR_HIER_BLOCK2_DERIVED_H + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> +#include <stdexcept> + +// Declare a QA test case +class qa_gr_hier_block2_derived : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(qa_gr_hier_block2_derived); + CPPUNIT_TEST(test_1); + CPPUNIT_TEST_SUITE_END(); + +private: + void test_1(); +}; + +#endif /* INCLUDED_QA_GR_HIER_BLOCK2_DERIVED_H */ diff --git a/gnuradio-core/src/lib/runtime/qa_gr_io_signature.cc b/gnuradio-core/src/lib/runtime/qa_gr_io_signature.cc new file mode 100644 index 000000000..c1737ffb8 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_io_signature.cc @@ -0,0 +1,64 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <qa_gr_io_signature.h> +#include <gr_io_signature.h> + +void +qa_gr_io_signature::t0 () +{ + gr_make_io_signature (1, 1, sizeof (int)); +} + +void +qa_gr_io_signature::t1 () +{ + gr_make_io_signature (3, 1, sizeof (int)); // throws std::invalid_argument +} + +void +qa_gr_io_signature::t2 () +{ + gr_io_signature_sptr p = + gr_make_io_signature (3, gr_io_signature::IO_INFINITE, sizeof (int)); + + CPPUNIT_ASSERT_EQUAL (p->min_streams (), 3); + CPPUNIT_ASSERT_EQUAL (p->sizeof_stream_item (0), (int) sizeof (int)); +} + +void +qa_gr_io_signature::t3 () +{ + gr_io_signature_sptr p = + gr_make_io_signature3 (0, 5, 1, 2, 3); + + CPPUNIT_ASSERT_EQUAL (p->min_streams (), 0); + CPPUNIT_ASSERT_EQUAL (p->max_streams (), 5); + CPPUNIT_ASSERT_EQUAL (p->sizeof_stream_item(0), 1); + CPPUNIT_ASSERT_EQUAL (p->sizeof_stream_item(1), 2); + CPPUNIT_ASSERT_EQUAL (p->sizeof_stream_item(2), 3); + CPPUNIT_ASSERT_EQUAL (p->sizeof_stream_item(3), 3); + CPPUNIT_ASSERT_EQUAL (p->sizeof_stream_item(4), 3); +} diff --git a/gnuradio-core/src/lib/runtime/qa_gr_io_signature.h b/gnuradio-core/src/lib/runtime/qa_gr_io_signature.h new file mode 100644 index 000000000..9cd6bb524 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_io_signature.h @@ -0,0 +1,46 @@ +/* -*- 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_QA_GR_IO_SIGNATURE_H +#define INCLUDED_QA_GR_IO_SIGNATURE_H + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> +#include <stdexcept> + +class qa_gr_io_signature : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_io_signature); + CPPUNIT_TEST (t0); + CPPUNIT_TEST_EXCEPTION (t1, std::invalid_argument); + CPPUNIT_TEST (t2); + CPPUNIT_TEST (t3); + CPPUNIT_TEST_SUITE_END (); + + private: + void t0 (); + void t1 (); + void t2 (); + void t3 (); +}; + +#endif /* INCLUDED_QA_GR_IO_SIGNATURE_H */ diff --git a/gnuradio-core/src/lib/runtime/qa_gr_top_block.cc b/gnuradio-core/src/lib/runtime/qa_gr_top_block.cc new file mode 100644 index 000000000..6bbc9ceb8 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_top_block.cc @@ -0,0 +1,285 @@ +/* -*- 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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <qa_gr_top_block.h> +#include <gr_top_block.h> +#include <gr_head.h> +#include <gr_nop.h> +#include <gr_null_source.h> +#include <gr_null_sink.h> +#include <iostream> + +#define VERBOSE 0 + +void qa_gr_top_block::t0() +{ + if (VERBOSE) std::cout << "qa_gr_top_block::t0()\n"; + + gr_top_block_sptr tb = gr_make_top_block("top"); + + CPPUNIT_ASSERT(tb); +} + +void qa_gr_top_block::t1_run() +{ + if (VERBOSE) std::cout << "qa_gr_top_block::t1()\n"; + + gr_top_block_sptr tb = gr_make_top_block("top"); + + gr_block_sptr src = gr_make_null_source(sizeof(int)); + gr_block_sptr head = gr_make_head(sizeof(int), 100000); + gr_block_sptr dst = gr_make_null_sink(sizeof(int)); + + tb->connect(src, 0, head, 0); + tb->connect(head, 0, dst, 0); + tb->run(); +} + +void qa_gr_top_block::t2_start_stop_wait() +{ + if (VERBOSE) std::cout << "qa_gr_top_block::t2()\n"; + + gr_top_block_sptr tb = gr_make_top_block("top"); + + gr_block_sptr src = gr_make_null_source(sizeof(int)); + gr_block_sptr head = gr_make_head(sizeof(int), 100000); + gr_block_sptr dst = gr_make_null_sink(sizeof(int)); + + tb->connect(src, 0, head, 0); + tb->connect(head, 0, dst, 0); + + tb->start(); + tb->stop(); + tb->wait(); +} + +void qa_gr_top_block::t3_lock_unlock() +{ + if (VERBOSE) std::cout << "qa_gr_top_block::t3()\n"; + + gr_top_block_sptr tb = gr_make_top_block("top"); + + gr_block_sptr src = gr_make_null_source(sizeof(int)); + gr_block_sptr dst = gr_make_null_sink(sizeof(int)); + + tb->connect(src, 0, dst, 0); + + tb->start(); + + tb->lock(); + tb->unlock(); + + tb->stop(); + tb->wait(); +} + +void qa_gr_top_block::t4_reconfigure() +{ + if (VERBOSE) std::cout << "qa_gr_top_block::t4()\n"; + + gr_top_block_sptr tb = gr_make_top_block("top"); + + gr_block_sptr src = gr_make_null_source(sizeof(int)); + gr_block_sptr head = gr_make_head(sizeof(int), 100000); + gr_block_sptr dst = gr_make_null_sink(sizeof(int)); + + // Start infinite flowgraph + tb->connect(src, 0, dst, 0); + tb->start(); + + // Reconfigure with gr_head in the middle + tb->lock(); + tb->disconnect(src, 0, dst, 0); + tb->connect(src, 0, head, 0); + tb->connect(head, 0, dst, 0); + tb->unlock(); + + // Wait for flowgraph to end on its own + tb->wait(); +} + + +void qa_gr_top_block::t5_max_noutputs() +{ + if (VERBOSE) std::cout << "qa_gr_top_block::t5()\n"; + + gr_top_block_sptr tb = gr_make_top_block("top"); + + gr_block_sptr src = gr_make_null_source(sizeof(int)); + gr_block_sptr head = gr_make_head(sizeof(int), 100000); + gr_block_sptr dst = gr_make_null_sink(sizeof(int)); + + // Start infinite flowgraph + tb->connect(src, 0, head, 0); + tb->connect(head, 0, dst, 0); + tb->start(100); + tb->wait(); +} + +void qa_gr_top_block::t6_reconfig_max_noutputs() +{ + if (VERBOSE) std::cout << "qa_gr_top_block::t6()\n"; + + gr_top_block_sptr tb = gr_make_top_block("top"); + + gr_block_sptr src = gr_make_null_source(sizeof(int)); + gr_block_sptr head = gr_make_head(sizeof(int), 100000); + gr_block_sptr dst = gr_make_null_sink(sizeof(int)); + + // Start infinite flowgraph + tb->connect(src, 0, dst, 0); + tb->start(100); + + // Reconfigure with gr_head in the middle + tb->lock(); + tb->disconnect(src, 0, dst, 0); + tb->connect(src, 0, head, 0); + tb->connect(head, 0, dst, 0); + tb->set_max_noutput_items(1000); + head->set_max_noutput_items(500); + tb->unlock(); + + // Wait for flowgraph to end on its own + tb->wait(); +} + +void qa_gr_top_block::t7_max_noutputs_per_block() +{ + if (VERBOSE) std::cout << "qa_gr_top_block::t7()\n"; + + gr_top_block_sptr tb = gr_make_top_block("top"); + + gr_block_sptr src = gr_make_null_source(sizeof(int)); + gr_block_sptr head = gr_make_head(sizeof(int), 100000); + gr_block_sptr dst = gr_make_null_sink(sizeof(int)); + + head->set_max_noutput_items(100); + + // Start infinite flowgraph + tb->connect(src, 0, head, 0); + tb->connect(head, 0, dst, 0); + tb->start(); + tb->wait(); +} + +void qa_gr_top_block::t8_reconfig_max_noutputs_per_block() +{ + if (VERBOSE) std::cout << "qa_gr_top_block::t8()\n"; + + gr_top_block_sptr tb = gr_make_top_block("top"); + + gr_block_sptr src = gr_make_null_source(sizeof(int)); + gr_block_sptr head = gr_make_head(sizeof(int), 100000); + gr_block_sptr dst = gr_make_null_sink(sizeof(int)); + + head->set_max_noutput_items(99); + + // Start infinite flowgraph + tb->connect(src, 0, dst, 0); + tb->start(201); + + // Reconfigure with gr_head in the middle + tb->lock(); + tb->disconnect(src, 0, dst, 0); + tb->connect(src, 0, head, 0); + tb->connect(head, 0, dst, 0); + tb->set_max_noutput_items(1023); + head->set_max_noutput_items(513); + tb->unlock(); + + // Wait for flowgraph to end on its own + tb->wait(); +} + +void qa_gr_top_block::t9_max_output_buffer() +{ + if (VERBOSE) std::cout << "qa_gr_top_block::t9()\n"; + + gr_top_block_sptr tb = gr_make_top_block("top"); + + gr_block_sptr src = gr_make_null_source(sizeof(int)); + gr_block_sptr head = gr_make_head(sizeof(int), 100000); + gr_block_sptr dst = gr_make_null_sink(sizeof(int)); + + head->set_max_output_buffer(1024); + + // Start infinite flowgraph + tb->connect(src, 0, head, 0); + tb->connect(head, 0, dst, 0); + tb->start(); + tb->wait(); +} + +void qa_gr_top_block::t10_reconfig_max_output_buffer() +{ + if (VERBOSE) std::cout << "qa_gr_top_block::t10()\n"; + + gr_top_block_sptr tb = gr_make_top_block("top"); + + gr_block_sptr src = gr_make_null_source(sizeof(int)); + gr_block_sptr head = gr_make_head(sizeof(int), 100000); + gr_block_sptr dst = gr_make_null_sink(sizeof(int)); + + head->set_max_output_buffer(1000); + + // Start infinite flowgraph + tb->connect(src, 0, dst, 0); + tb->start(201); + + // Reconfigure with gr_head in the middle + tb->lock(); + gr_block_sptr nop = gr_make_nop(sizeof(int)); + nop->set_max_output_buffer(4000); + tb->disconnect(src, 0, dst, 0); + tb->connect(src, 0, head, 0); + tb->connect(head, 0, nop, 0); + tb->connect(nop, 0, dst, 0); + tb->unlock(); + + // Wait for flowgraph to end on its own + tb->wait(); +} + +void qa_gr_top_block::t11_set_block_affinity() +{ + gr_top_block_sptr tb = gr_make_top_block("top"); + gr_block_sptr src (gr_make_null_source(sizeof(float))); + gr_block_sptr snk (gr_make_null_sink(sizeof(float))); + + std::vector<int> set(1, 0), ret; + src->set_processor_affinity(set); + + tb->connect(src, 0, snk, 0); + tb->start(); + tb->stop(); + tb->wait(); + + ret = src->processor_affinity(); + + // We only set the core affinity to 0 because we always know at + // least one thread core exists to use. + CPPUNIT_ASSERT_EQUAL(set[0], ret[0]); +} diff --git a/gnuradio-core/src/lib/runtime/qa_gr_top_block.h b/gnuradio-core/src/lib/runtime/qa_gr_top_block.h new file mode 100644 index 000000000..634eeab1f --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_top_block.h @@ -0,0 +1,66 @@ +/* -*- 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_QA_GR_TOP_BLOCK_H +#define INCLUDED_QA_GR_TOP_BLOCK_H + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> +#include <stdexcept> + +class qa_gr_top_block : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(qa_gr_top_block); + + CPPUNIT_TEST(t0); + CPPUNIT_TEST(t1_run); + CPPUNIT_TEST(t2_start_stop_wait); + CPPUNIT_TEST(t3_lock_unlock); + CPPUNIT_TEST(t4_reconfigure); // triggers 'join never returns' bug + CPPUNIT_TEST(t5_max_noutputs); + CPPUNIT_TEST(t6_reconfig_max_noutputs); + CPPUNIT_TEST(t7_max_noutputs_per_block); + CPPUNIT_TEST(t8_reconfig_max_noutputs_per_block); + CPPUNIT_TEST(t9_max_output_buffer); + CPPUNIT_TEST(t10_reconfig_max_output_buffer); + CPPUNIT_TEST(t11_set_block_affinity); + + CPPUNIT_TEST_SUITE_END(); + +private: + + void t0(); + void t1_run(); + void t2_start_stop_wait(); + void t3_lock_unlock(); + void t4_reconfigure(); + void t5_max_noutputs(); + void t6_reconfig_max_noutputs(); + void t7_max_noutputs_per_block(); + void t8_reconfig_max_noutputs_per_block(); + void t9_max_output_buffer(); + void t10_reconfig_max_output_buffer(); + void t11_set_block_affinity(); + +}; + +#endif /* INCLUDED_QA_GR_TOP_BLOCK_H */ diff --git a/gnuradio-core/src/lib/runtime/qa_gr_vmcircbuf.cc b/gnuradio-core/src/lib/runtime/qa_gr_vmcircbuf.cc new file mode 100644 index 000000000..e3b36d882 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_vmcircbuf.cc @@ -0,0 +1,40 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 <qa_gr_vmcircbuf.h> +#include <cppunit/TestAssert.h> +#include <gr_vmcircbuf.h> +#include <stdio.h> + +void +qa_gr_vmcircbuf::test_all () +{ + int verbose = 1; // summary + + bool ok = gr_vmcircbuf_sysconfig::test_all_factories (verbose); + + CPPUNIT_ASSERT_EQUAL (true, ok); +} diff --git a/gnuradio-core/src/lib/runtime/qa_gr_vmcircbuf.h b/gnuradio-core/src/lib/runtime/qa_gr_vmcircbuf.h new file mode 100644 index 000000000..3576660d5 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_vmcircbuf.h @@ -0,0 +1,39 @@ +/* -*- 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 _QA_GR_VMCIRCBUF_H_ +#define _QA_GR_VMCIRCBUF_H_ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> + +class qa_gr_vmcircbuf : public CppUnit::TestCase { + + CPPUNIT_TEST_SUITE (qa_gr_vmcircbuf); + CPPUNIT_TEST (test_all); + CPPUNIT_TEST_SUITE_END (); + + private: + void test_all (); +}; + + +#endif /* _QA_GR_VMCIRCBUF_H_ */ diff --git a/gnuradio-core/src/lib/runtime/qa_runtime.cc b/gnuradio-core/src/lib/runtime/qa_runtime.cc new file mode 100644 index 000000000..9091d5c00 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_runtime.cc @@ -0,0 +1,61 @@ +/* + * Copyright 2002,2007,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. + */ + +/* + * This class gathers together all the test cases for the gr + * directory into a single test suite. As you create new test cases, + * add them here. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <qa_runtime.h> +#include <qa_gr_vmcircbuf.h> +#include <qa_gr_io_signature.h> +#include <qa_gr_block.h> +#include <qa_gr_flowgraph.h> +#include <qa_gr_top_block.h> +#include <qa_gr_hier_block2.h> +#include <qa_gr_hier_block2_derived.h> +#include <qa_gr_buffer.h> +#include <qa_block_tags.h> +#include <qa_set_msg_handler.h> + +CppUnit::TestSuite * +qa_runtime::suite () +{ + CppUnit::TestSuite *s = new CppUnit::TestSuite ("runtime"); + + s->addTest (qa_gr_vmcircbuf::suite ()); + s->addTest (qa_gr_io_signature::suite ()); + s->addTest (qa_gr_block::suite ()); + //s->addTest (qa_gr_flowgraph::suite ()); + s->addTest (qa_gr_top_block::suite ()); + s->addTest (qa_gr_hier_block2::suite ()); + s->addTest (qa_gr_hier_block2_derived::suite ()); + s->addTest (qa_gr_buffer::suite ()); + //s->addTest (qa_block_tags::suite ()); + //s->addTest (qa_set_msg_handler::suite ()); + + return s; +} diff --git a/gnuradio-core/src/lib/runtime/qa_runtime.h b/gnuradio-core/src/lib/runtime/qa_runtime.h new file mode 100644 index 000000000..da71cbd0f --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_runtime.h @@ -0,0 +1,38 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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_RUNTIME_H_ +#define _QA_RUNTIME_H_ + +#include <gruel/attributes.h> +#include <cppunit/TestSuite.h> + +//! collect all the tests for the runtime directory + +class __GR_ATTR_EXPORT qa_runtime { + public: + //! return suite of tests for all of runtime directory + static CppUnit::TestSuite *suite (); +}; + + +#endif /* _QA_RUNTIME_H_ */ diff --git a/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc b/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc new file mode 100644 index 000000000..c84a219bd --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_set_msg_handler.cc @@ -0,0 +1,81 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,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 <qa_set_msg_handler.h> +#include <gr_top_block.h> +#include <gr_head.h> +#include <gr_null_source.h> +#include <gr_null_sink.h> +#include <gr_nop.h> +#include <gruel/msg_passing.h> +#include <iostream> +#include <boost/thread/thread.hpp> + + +#define VERBOSE 0 + +using namespace pmt; + +/* + * The gr_nop block has been instrumented so that it counts + * the number of messages sent to it. We use this feature + * to confirm that gr_nop's call to set_msg_handler is working + * correctly. + */ + +void qa_set_msg_handler::t0() +{ + static const int NMSGS = 10; + + if (VERBOSE) std::cout << "qa_set_msg_handler::t0()\n"; + + gr_top_block_sptr tb = gr_make_top_block("top"); + + gr_block_sptr src = gr_make_null_source(sizeof(int)); + gr_nop_sptr nop = gr_make_nop(sizeof(int)); + gr_block_sptr dst = gr_make_null_sink(sizeof(int)); + + tb->connect(src, 0, nop, 0); + tb->connect(nop, 0, dst, 0); + + // Must start graph before sending messages + tb->start(); + + // Send them... + pmt_t port(pmt_intern("port")); + for (int i = 0; i < NMSGS; i++){ + send(nop, port, mp(mp("example-msg"), mp(i))); + } + + // Give the messages a chance to be processed + boost::this_thread::sleep(boost::posix_time::milliseconds(100)); + + tb->stop(); + tb->wait(); + + // Confirm that the nop block received the right number of messages. + CPPUNIT_ASSERT_EQUAL(NMSGS, nop->nmsgs_received()); +} diff --git a/gnuradio-core/src/lib/runtime/qa_set_msg_handler.h b/gnuradio-core/src/lib/runtime/qa_set_msg_handler.h new file mode 100644 index 000000000..60277a12c --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_set_msg_handler.h @@ -0,0 +1,43 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,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_QA_SET_MSG_HANDLER_H +#define INCLUDED_QA_SET_MSG_HANDLER_H + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/TestCase.h> +#include <stdexcept> + +class qa_set_msg_handler : public CppUnit::TestCase +{ + CPPUNIT_TEST_SUITE(qa_set_msg_handler); + + CPPUNIT_TEST(t0); + + CPPUNIT_TEST_SUITE_END(); + +private: + + void t0(); +}; + +#endif /* INCLUDED_QA_SET_MSG_HANDLER_H */ diff --git a/gnuradio-core/src/lib/runtime/runtime.i b/gnuradio-core/src/lib/runtime/runtime.i new file mode 100644 index 000000000..64c28c8e1 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/runtime.i @@ -0,0 +1,123 @@ +/* + * Copyright 2012-2013 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. + */ + +#define GR_CORE_API + +//not here to fight you swig, reference() is ambigi with shared ptr, but whatevs +%ignore gri_agc_cc::reference(); +%ignore gri_agc2_ff::reference(); +%ignore gri_agc2_cc::reference(); + +//someone forgot about d_detail +%ignore gr_block::d_setlock; + +//dont export work overloads +%ignore general_work; +%ignore work; +%ignore forecast; + +%{ + +#include <gras/block.hpp> +#include <gras/hier_block.hpp> +#include <gras/top_block.hpp> +#include <gr_block.h> +#include <gr_top_block.h> +#include <gr_hier_block2.h> +#include <gr_message.h> +#include <gr_msg_handler.h> +#include <gr_msg_queue.h> +#include <gr_sync_block.h> +#include <gr_sync_decimator.h> +#include <gr_sync_interpolator.h> + +%} + +//const size types used by blocks in python +%constant int sizeof_char = sizeof(char); +%constant int sizeof_short = sizeof(short); +%constant int sizeof_int = sizeof(int); +%constant int sizeof_float = sizeof(float); +%constant int sizeof_double = sizeof(double); +%constant int sizeof_gr_complex = sizeof(gr_complex); + +%include <gr_message.i> +%include <gr_msg_handler.i> +%include <gr_msg_queue.i> +%include <gr_swig_block_magic.i> +%include <gr_io_signature.i> + +#ifdef SW_RUNTIME + +%import <gras/block.i> +%include <gr_block.h> +%include <gr_hier_block2.h> +%include <gr_top_block.h> +%include <gr_sync_block.h> +%include <gr_sync_decimator.h> +%include <gr_sync_interpolator.h> + +#else + +//the bare minimum block inheritance interface to make things work but keep swig cxx file size down +%include <gras/gras.hpp> +%import <gras/element.i> +namespace gras +{ + struct Block : gras::Element{}; + struct HierBlock : gras::Element{}; +} +struct gr_hier_block2 : gras::HierBlock{}; +struct gr_block : gras::Block +{ + gr_io_signature_sptr input_signature(void) const; + gr_io_signature_sptr output_signature(void) const; + + unsigned history () const; + + int output_multiple () const; + double relative_rate () const; + + bool start(); + bool stop(); + + uint64_t nitems_read(unsigned int which_input); + uint64_t nitems_written(unsigned int which_output); + + // Methods to manage the block's max_noutput_items size. + int max_noutput_items(); + void set_max_noutput_items(int m); + void unset_max_noutput_items(); + bool is_set_max_noutput_items(); + + // Methods to manage block's min/max buffer sizes. + long max_output_buffer(int i); + void set_max_output_buffer(long max_output_buffer); + void set_max_output_buffer(int port, long max_output_buffer); + long min_output_buffer(int i); + void set_min_output_buffer(long min_output_buffer); + void set_min_output_buffer(int port, long min_output_buffer); +}; +struct gr_sync_block : gr_block{}; +struct gr_sync_interpolator : gr_sync_block{}; +struct gr_sync_decimator : gr_sync_block{}; + +#endif diff --git a/gnuradio-core/src/lib/runtime/test_shared_block_ptr.cc b/gnuradio-core/src/lib/runtime/test_shared_block_ptr.cc new file mode 100644 index 000000000..bb4e86322 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/test_shared_block_ptr.cc @@ -0,0 +1,53 @@ +/* -*- 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. + */ + +#include <gr_shared_block_sptr.h> +#include <gr_vector_source_i.h> + +gr_block_sptr +foo (gr_vector_source_i_sptr s) +{ + return gr_block_sptr (s); +} + +typedef gr_shared_block_sptr<gr_vector_source_i> gr_vector_source_i_ptrX; +//typedef boost::shared_ptr<gr_vector_source_i> gr_vector_source_i_ptrX; + +gr_vector_source_i_ptrX +bar (gr_vector_source_i *s) +{ + return gr_vector_source_i_ptrX (s); +} + +gr_block_sptr +baz_1 (gr_vector_source_i_ptrX s) +{ + return gr_block_sptr (s); +} + +#if 0 +gr_block_sptr +baz_2 (gr_vector_source_i_ptrX s) +{ + return s.block_sptr (); +} +#endif diff --git a/gnuradio-core/src/lib/swig/CMakeLists.txt b/gnuradio-core/src/lib/swig/CMakeLists.txt new file mode 100644 index 000000000..d8a64cc0f --- /dev/null +++ b/gnuradio-core/src/lib/swig/CMakeLists.txt @@ -0,0 +1,88 @@ +# Copyright 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. + +######################################################################## +include(GrPython) +include(GrSwig) + +set(GR_SWIG_INCLUDE_DIRS + ${CMAKE_CURRENT_BINARY_DIR} + ${GNURADIO_CORE_SWIG_INCLUDE_DIRS} + ${GRUEL_INCLUDE_DIRS} + ${Boost_INCLUDE_DIRS} +) +set(GR_SWIG_LIBRARIES gnuradio-core) + +link_directories(${Boost_LIBRARY_DIRS}) + +######################################################################## +# Build and install the swig targets +######################################################################## +# ---------------------------------------------------------------- +# We've split the previously monstrous gnuradio_corethon into 6 +# smaller pieces. This reduces compile time coupling and creates +# smaller pieces for the compiler to digest. prior to this change, on +# X86_64, g++'s resident set size was 650MB! +# ---------------------------------------------------------------- + +set(GR_SWIG_TARGET_DEPS general_generated gengen_generated filter_generated pmt_swig) + +foreach(what runtime general gengen filter io hier) + SET(GR_SWIG_DOC_FILE ${CMAKE_CURRENT_BINARY_DIR}/${what}_swig_doc.i) + SET(GR_SWIG_DOC_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/../${what} ${CMAKE_CURRENT_BINARY_DIR}/../${what}) + GR_SWIG_MAKE(gnuradio_core_${what} gnuradio_core_${what}.i) + GR_SWIG_INSTALL( + TARGETS gnuradio_core_${what} + DESTINATION ${GR_PYTHON_DIR}/gnuradio/gr + COMPONENT "core_python" + ) + install( + FILES + gnuradio_core_${what}.i + ${CMAKE_CURRENT_BINARY_DIR}/${what}_swig_doc.i + DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig + COMPONENT "core_swig" + ) + list(APPEND core_swig_deps ${SWIG_MODULE_gnuradio_core_${what}_REAL_NAME}) +endforeach(what) + +add_custom_target(core_swig DEPENDS ${core_swig_deps}) + +######################################################################## +# Install various files +######################################################################## +install(FILES + gnuradio.i + gr_swig_block_magic.i + gr_shared_ptr.i + DESTINATION ${GR_INCLUDE_DIR}/gnuradio/swig + COMPONENT "core_swig" +) + +GR_PYTHON_INSTALL( + FILES gnuradio_core.py + DESTINATION ${GR_PYTHON_DIR}/gnuradio/gr + COMPONENT "core_python" +) + +install( + FILES ${CMAKE_CURRENT_SOURCE_DIR}/gnuradio_swig_bug_workaround.h + DESTINATION ${GR_INCLUDE_DIR}/gnuradio + COMPONENT "core_swig" +) diff --git a/gnuradio-core/src/lib/swig/gen-swig-bug-fix b/gnuradio-core/src/lib/swig/gen-swig-bug-fix new file mode 100755 index 000000000..5e9f82e7d --- /dev/null +++ b/gnuradio-core/src/lib/swig/gen-swig-bug-fix @@ -0,0 +1,111 @@ +#!/usr/bin/env python +# +# 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. +# + +import sys +import re + +def write_header (f): + f.write ('''/* -*- 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_GNURADIO_SWIG_BUG_WORKAROUND_H +#define INCLUDED_GNURADIO_SWIG_BUG_WORKAROUND_H + +/* + * This include files works around a bug in SWIG 1.3.21 and 22 + * where it fails to emit these declarations when doing + * %import "gnuradio.i" + */ + +''') + +def write_trailer (f): + f.write (''' +#endif /* INCLUDED_GNURADIO_SWIG_BUG_WORKAROUND_H */ +''') + +def doit (input, output): + re_RULES_BEGIN = re.compile ('RULES \(BEGIN\)') + re_RULES_END = re.compile ('RULES \(END\)') + re_RETURN = re.compile ('^\s*return') + re_NOT_ID = re.compile ('[^a-zA-Z0-9_]') + words = {} + + write_header (output) + for line in input: + if re_RULES_BEGIN.search (line): + break + + for line in input: + if re_RULES_END.search (line): + break + if not re_RETURN.match (line): + continue + line = re_NOT_ID.sub (' ', line) + line = re.sub (' +', ' ', line) + for w in line.split (' '): + words[w] = 1 + + for w in ('', 'return', 'void', 'x'): + del words[w] + + wl = words.keys() + wl.sort () + for w in wl: + output.write ('class ' + w + ';\n') + + write_trailer (output) + + +def main (): + if len (sys.argv) != 3: + sys.stderr.write ("usage: %s gnuradio_swig_python.cc gnuradio_swig_bug_workaround.h\n" + % (sys.argv[0],)) + sys.exit (1) + input_filename = sys.argv[1] + output_filename = sys.argv[2] + input = open (input_filename, "r") + output = open (output_filename, "w") + doit (input, output) + +if __name__ == '__main__': + main () + diff --git a/gnuradio-core/src/lib/swig/gnuradio.i b/gnuradio-core/src/lib/swig/gnuradio.i new file mode 100644 index 000000000..bf23bbbb2 --- /dev/null +++ b/gnuradio-core/src/lib/swig/gnuradio.i @@ -0,0 +1,91 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003,2004,2009 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. + */ + +%pythoncode %{ +import gras +%} + +// Disable warning about base class types +#pragma SWIG nowarn=401 + +//////////////////////////////////////////////////////////////////////// +// gnuradio.i +// SWIG interface definition +//////////////////////////////////////////////////////////////////////// + +%include <gruel_common.i> + +//////////////////////////////////////////////////////////////////////// +// Headers + +%{ +#include "gnuradio_swig_bug_workaround.h" // mandatory bug fix +#include <gr_types.h> +#include <stddef.h> // size_t +#include <complex> +%} + +%feature("autodoc","1"); + +// local file +%include <gr_shared_ptr.i> +%include <gr_types.h> +%include <std_complex.i> +%include <std_vector.i> +%include <stl.i> +%include <std_except.i> + +typedef std::complex<float> gr_complex; +typedef std::complex<double> gr_complexd; +typedef unsigned long long uint64_t; +typedef long long int64_t; + + +// instantiate the required template specializations + +namespace std { + %template() vector<unsigned char>; + %template() vector<char>; + %template() vector<short>; + %template() vector<int>; + %template() vector<float>; + %template() vector<double>; + // %template() std::complex<float>; + + %template() vector< std::complex<float> >; + %template() vector< std::vector< unsigned char > >; + %template() vector< std::vector< char > >; + %template() vector< std::vector< short > >; + %template() vector< std::vector< int > >; + %template() vector< std::vector< float > >; + %template() vector< std::vector< double > >; + %template() vector< std::vector< std::complex<float> > >; +}; + +//////////////////////////////////////////////////////////////////////// + +#ifndef SW_RUNTIME +// import runtime.i for all but sw_runtime, since it needs to %include +%import <runtime.i> +#endif + +//////////////////////////////////////////////////////////////////////// diff --git a/gnuradio-core/src/lib/swig/gnuradio_core.py b/gnuradio-core/src/lib/swig/gnuradio_core.py new file mode 100644 index 000000000..23de74077 --- /dev/null +++ b/gnuradio-core/src/lib/swig/gnuradio_core.py @@ -0,0 +1,28 @@ +# +# Copyright 2006,2009,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 this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +# This file implements the old gnuradio_core namespace + +from gnuradio_core_runtime import * +from gnuradio_core_general import * +from gnuradio_core_gengen import * +from gnuradio_core_filter import * +from gnuradio_core_io import * +from gnuradio_core_hier import * diff --git a/gnuradio-core/src/lib/swig/gnuradio_core_filter.i b/gnuradio-core/src/lib/swig/gnuradio_core_filter.i new file mode 100644 index 000000000..e9a44e54b --- /dev/null +++ b/gnuradio-core/src/lib/swig/gnuradio_core_filter.i @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2009,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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +%include "filter_swig_doc.i" + +#ifndef SWIGIMPORTED +%module(directors="1") gnuradio_core_filter +#endif + + //%feature("autodoc", "1"); // generate python docstrings + +%include "gnuradio.i" // the common stuff + +%include "filter.i" diff --git a/gnuradio-core/src/lib/swig/gnuradio_core_general.i b/gnuradio-core/src/lib/swig/gnuradio_core_general.i new file mode 100644 index 000000000..33f97815e --- /dev/null +++ b/gnuradio-core/src/lib/swig/gnuradio_core_general.i @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2009,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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +%include "general_swig_doc.i" + +#define GR_CORE_API + +#ifndef SWIGIMPORTED +%module(directors="1") gnuradio_core_general +#endif + + //%feature("autodoc", "1"); // generate python docstrings + +%include "gnuradio.i" // the common stuff + +%include "general.i" + + // Simple test case for complex input and output +%inline +%{ + std::complex<float> complexf_add_2j(std::complex<float> x) + { + return std::complex<float>(x.real(), x.imag() + 2); + } + + std::complex<double> complexd_add_2j(std::complex<double> x) + { + return std::complex<double>(x.real(), x.imag() + 2); + } + + std::complex<float> complexf_add_x_2j(float x, std::complex<float> y) + { + return std::complex<float>(x + y.real(), y.imag() + 2); + } + +%} diff --git a/gnuradio-core/src/lib/swig/gnuradio_core_gengen.i b/gnuradio-core/src/lib/swig/gnuradio_core_gengen.i new file mode 100644 index 000000000..b90a5bab3 --- /dev/null +++ b/gnuradio-core/src/lib/swig/gnuradio_core_gengen.i @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2009,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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +%include "gengen_swig_doc.i" + +#ifndef SWIGIMPORTED +%module(directors="1") gnuradio_core_gengen +#endif + + //%feature("autodoc", "1"); // generate python docstrings + +%include "gnuradio.i" // the common stuff + +%include "gengen.i" diff --git a/gnuradio-core/src/lib/swig/gnuradio_core_hier.i b/gnuradio-core/src/lib/swig/gnuradio_core_hier.i new file mode 100644 index 000000000..141d9b163 --- /dev/null +++ b/gnuradio-core/src/lib/swig/gnuradio_core_hier.i @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +%include "hier_swig_doc.i" + +#ifndef SWIGIMPORTED +%module(directors="1") gnuradio_hier_hier +#endif + + //%feature("autodoc", "1"); // generate python docstrings + +%include "gnuradio.i" // the common stuff + +%include "hier.i" diff --git a/gnuradio-core/src/lib/swig/gnuradio_core_io.i b/gnuradio-core/src/lib/swig/gnuradio_core_io.i new file mode 100644 index 000000000..522b12b34 --- /dev/null +++ b/gnuradio-core/src/lib/swig/gnuradio_core_io.i @@ -0,0 +1,32 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2009,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 this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +%include "io_swig_doc.i" + +#ifndef SWIGIMPORTED +%module(directors="1") gnuradio_core_io +#endif + + //%feature("autodoc", "1"); // generate python docstrings + +%include "gnuradio.i" // the common stuff + +%include "io.i" diff --git a/gnuradio-core/src/lib/swig/gnuradio_core_runtime.i b/gnuradio-core/src/lib/swig/gnuradio_core_runtime.i new file mode 100644 index 000000000..fb311d226 --- /dev/null +++ b/gnuradio-core/src/lib/swig/gnuradio_core_runtime.i @@ -0,0 +1,34 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,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. + */ + +%include "runtime_swig_doc.i" + +#ifndef SWIGIMPORTED +%module(directors="1") gnuradio_core_runtime +#endif + + //%feature("autodoc", "1"); // generate python docstrings + +#define SW_RUNTIME +%include "gnuradio.i" // the common stuff + +%include "runtime.i" diff --git a/gnuradio-core/src/lib/swig/gnuradio_swig_bug_workaround.h b/gnuradio-core/src/lib/swig/gnuradio_swig_bug_workaround.h new file mode 100644 index 000000000..1994f0660 --- /dev/null +++ b/gnuradio-core/src/lib/swig/gnuradio_swig_bug_workaround.h @@ -0,0 +1,45 @@ +/* -*- 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_GNURADIO_SWIG_BUG_WORKAROUND_H +#define INCLUDED_GNURADIO_SWIG_BUG_WORKAROUND_H + +/* + * This include files works around a bug in SWIG 1.3.21 and 22 + * where it fails to emit these declarations when doing + * %import "gnuradio.i" + */ + +class gr_base_error_handler; +class gr_basic_block; +class gr_block; +class gr_error_handler; +class gr_file_error_handler; +class gr_hier_block2; +class gr_msg_handler; +class gr_msg_queue; +class gr_sync_block; +class gr_sync_decimator; +class gr_sync_interpolator; +class gr_top_block; + +#endif /* INCLUDED_GNURADIO_SWIG_BUG_WORKAROUND_H */ diff --git a/gnuradio-core/src/lib/swig/gr_shared_ptr.i b/gnuradio-core/src/lib/swig/gr_shared_ptr.i new file mode 100644 index 000000000..323d33ad7 --- /dev/null +++ b/gnuradio-core/src/lib/swig/gr_shared_ptr.i @@ -0,0 +1,43 @@ +// +// shared_ptr +// +// An enhanced relative of scoped_ptr with reference counted copy semantics. +// The object pointed to is deleted when the last shared_ptr pointing to it +// is destroyed or reset. +// + +// +// This is highly hacked up version of boost::shared_ptr +// We just need enough to get SWIG to "do the right thing" and +// generate "Smart Pointer" code. +// + +namespace boost { + +template<class T> class shared_ptr +{ +public: + + shared_ptr() + { + } + + shared_ptr (T * p) + { + } + + + T * operator-> () // never throws + { + return px; + } + + +private: + + T * px; // contained pointer + int pn; + +}; // shared_ptr + +};
\ No newline at end of file diff --git a/gnuradio-core/src/lib/swig/gr_swig_block_magic.i b/gnuradio-core/src/lib/swig/gr_swig_block_magic.i new file mode 100644 index 000000000..4016ae772 --- /dev/null +++ b/gnuradio-core/src/lib/swig/gr_swig_block_magic.i @@ -0,0 +1,50 @@ +/* -*- 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. + */ + +%define GR_SWIG_BLOCK_MAGIC(PKG, BASE_NAME) +_GR_SWIG_BLOCK_MAGIC_HELPER(PKG, BASE_NAME, PKG ## _ ## BASE_NAME) +%enddef + +%define _GR_SWIG_BLOCK_MAGIC_HELPER_COMMON(PKG, BASE_NAME, FULL_NAME) +class FULL_NAME; +typedef boost::shared_ptr<FULL_NAME> FULL_NAME ## _sptr; +%template(FULL_NAME ## _sptr) boost::shared_ptr<FULL_NAME>; +%rename(BASE_NAME) PKG ## _make_ ## BASE_NAME; +%ignore FULL_NAME; +%enddef + +#ifdef SWIGPYTHON +%define _GR_SWIG_BLOCK_MAGIC_HELPER(PKG, BASE_NAME, FULL_NAME) +_GR_SWIG_BLOCK_MAGIC_HELPER_COMMON(PKG, BASE_NAME, FULL_NAME) +%pythoncode %{ +FULL_NAME ## _sptr.__repr__ = lambda self: "<gr_block %s (%d)>" % (self.name(), self.unique_id ()) +%} +%enddef +#endif + +%define GR_SWIG_BLOCK_MAGIC2(PKG, BASE_NAME) +%template(BASE_NAME ## _sptr) boost::shared_ptr<gr:: ## PKG ## :: ## BASE_NAME>; +%pythoncode %{ +BASE_NAME ## _sptr.__repr__ = lambda self: "<gr_block %s (%d)>" % (self.name(), self.unique_id()) +BASE_NAME = BASE_NAME.make; +%} +%enddef diff --git a/gnuradio-core/src/lib/viterbi/CMakeLists.txt b/gnuradio-core/src/lib/viterbi/CMakeLists.txt new file mode 100644 index 000000000..add5c77e8 --- /dev/null +++ b/gnuradio-core/src/lib/viterbi/CMakeLists.txt @@ -0,0 +1,63 @@ +# Copyright 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. + +######################################################################## +# This file included, use CMake directory variables +######################################################################## + +set(viterbi_sources + ${CMAKE_CURRENT_SOURCE_DIR}/metrics.c + ${CMAKE_CURRENT_SOURCE_DIR}/tab.c + ${CMAKE_CURRENT_SOURCE_DIR}/viterbi.c +) + +######################################################################## +# define missing erf function with C linkage (hack for metrics.c) +######################################################################## +if(MSVC) +file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/boost_math_erf.cc " +#include <boost/math/special_functions/erf.hpp> +extern \"C\" double erf(double x){ + return boost::math::erf(x); +} +") +list(APPEND viterbi_sources ${CMAKE_CURRENT_BINARY_DIR}/boost_math_erf.cc) +endif(MSVC) + +######################################################################## +# Append gnuradio-core library sources +######################################################################## +list(APPEND gnuradio_core_sources ${viterbi_sources}) + +######################################################################## +# Install runtime headers +######################################################################## +install( + FILES ${CMAKE_CURRENT_SOURCE_DIR}/viterbi.h + DESTINATION ${GR_INCLUDE_DIR}/gnuradio + COMPONENT "core_devel" +) + +######################################################################## +# Create some text executables (not registered tests) +# Its not much to build so the sources are just re-listed, +# rather than create a new library just for these two apps. +######################################################################## +#ADD_EXECUTABLE(viterbi_encode ${CMAKE_CURRENT_SOURCE_DIR}/encode.cc ${viterbi_sources}) +#ADD_EXECUTABLE(viterbi_decode ${CMAKE_CURRENT_SOURCE_DIR}/decode.cc ${viterbi_sources}) diff --git a/gnuradio-core/src/lib/viterbi/decode.cc b/gnuradio-core/src/lib/viterbi/decode.cc new file mode 100644 index 000000000..368e69713 --- /dev/null +++ b/gnuradio-core/src/lib/viterbi/decode.cc @@ -0,0 +1,88 @@ +/* -*- 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. + */ + +/* + * This is a minimal example demonstrating how to call the Viterbi decoder + * in continuous streaming mode. It accepts data on stdin and writes to + * stdout. + * + */ + +extern "C" { +#include "viterbi.h" +} + +#include <cstdio> +#include <cmath> + +#define MAXCHUNKSIZE 4096 +#define MAXENCSIZE MAXCHUNKSIZE*16 + +int main() +{ + unsigned char data[MAXCHUNKSIZE]; + signed char syms[MAXENCSIZE]; + int count = 0; + + // Initialize metric table + int mettab[2][256]; + int amp = 100; + float RATE=0.5; + float ebn0 = 12.0; + float esn0 = RATE*pow(10.0, ebn0/10); + gen_met(mettab, amp, esn0, 0.0, 4); + + // Initialize decoder state + struct viterbi_state state0[64]; + struct viterbi_state state1[64]; + unsigned char viterbi_in[16]; + viterbi_chunks_init(state0); + + while (!feof(stdin)) { + unsigned int n = fread(syms, 1, MAXENCSIZE, stdin); + unsigned char *out = data; + + for (unsigned int i = 0; i < n; i++) { + + // FIXME: This implements hard decoding by slicing the input stream + unsigned char sym = syms[i] > 0 ? -amp : amp; + + // Write the symbol to the decoder input + viterbi_in[count % 4] = sym; + + // Every four symbols, perform the butterfly2 operation + if ((count % 4) == 3) { + viterbi_butterfly2(viterbi_in, mettab, state0, state1); + + // Every sixteen symbols, perform the readback operation + if ((count > 64) && (count % 16) == 11) { + viterbi_get_output(state0, out); + fwrite(out++, 1, 1, stdout); + } + } + + count++; + } + } + + return 0; +} diff --git a/gnuradio-core/src/lib/viterbi/encode.cc b/gnuradio-core/src/lib/viterbi/encode.cc new file mode 100644 index 000000000..83a85fcac --- /dev/null +++ b/gnuradio-core/src/lib/viterbi/encode.cc @@ -0,0 +1,54 @@ +/* -*- 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. + */ + +/* + * This is a minimal example demonstrating how to call the ECC encoder + * in continuous streaming mode. It accepts data on stdin and writes to + * stdout. + * + * FIXME: This does not flush the final bits out of the encoder. + * + */ + +extern "C" { +#include "viterbi.h" +} + +#include <cstdio> + +#define MAXCHUNKSIZE 4096 +#define MAXENCSIZE MAXCHUNKSIZE*16 + +int main() +{ + unsigned char encoder_state = 0; + unsigned char data[MAXCHUNKSIZE]; + unsigned char syms[MAXENCSIZE]; + + while (!feof(stdin)) { + unsigned int n = fread(data, 1, MAXCHUNKSIZE, stdin); + encoder_state = encode(syms, data, n, encoder_state); + fwrite(syms, 1, n*16, stdout); + } + + return 0; +} diff --git a/gnuradio-core/src/lib/viterbi/metrics.c b/gnuradio-core/src/lib/viterbi/metrics.c new file mode 100644 index 000000000..0d91c301f --- /dev/null +++ b/gnuradio-core/src/lib/viterbi/metrics.c @@ -0,0 +1,126 @@ +/* + * Copyright 1995 Phil Karn, KA9Q + * 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. + */ + +/* + * Generate metric tables for a soft-decision convolutional decoder + * assuming gaussian noise on a PSK channel. + * + * Works from "first principles" by evaluating the normal probability + * function and then computing the log-likelihood function + * for every possible received symbol value + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +/* Symbols are offset-binary, with 128 corresponding to an erased (no + * information) symbol + */ +#define OFFSET 128 + +#include <stdlib.h> +#include <math.h> + +//declare erf in case it was missing in math.h and provided for by the build system +extern double erf(double x); + +/* Normal function integrated from -Inf to x. Range: 0-1 */ +#define normal(x) (0.5 + 0.5*erf((x)/M_SQRT2)) + +/* Logarithm base 2 */ +#define gr_log2(x) (log(x)*M_LOG2E) + +/* Generate log-likelihood metrics for 8-bit soft quantized channel + * assuming AWGN and BPSK + */ +void +gen_met(int mettab[2][256], /* Metric table, [sent sym][rx symbol] */ + int amp, /* Signal amplitude, units */ + double esn0, /* Es/N0 ratio in dB */ + double bias, /* Metric bias; 0 for viterbi, rate for sequential */ + int scale) /* Scale factor */ +{ + double noise; + int s,bit; + double metrics[2][256]; + double p0,p1; + + /* Es/N0 as power ratio */ + esn0 = pow(10.,esn0/10); + + noise = 0.5/esn0; /* only half the noise for BPSK */ + noise = sqrt(noise); /* noise/signal Voltage ratio */ + + /* Zero is a special value, since this sample includes all + * lower samples that were clipped to this value, i.e., it + * takes the whole lower tail of the curve + */ + p1 = normal(((0-OFFSET+0.5)/amp - 1)/noise); /* P(s|1) */ + + /* Prob of this value occurring for a 0-bit */ /* P(s|0) */ + p0 = normal(((0-OFFSET+0.5)/amp + 1)/noise); + metrics[0][0] = gr_log2(2*p0/(p1+p0)) - bias; + metrics[1][0] = gr_log2(2*p1/(p1+p0)) - bias; + + for(s=1;s<255;s++){ + /* P(s|1), prob of receiving s given 1 transmitted */ + p1 = normal(((s-OFFSET+0.5)/amp - 1)/noise) - + normal(((s-OFFSET-0.5)/amp - 1)/noise); + + /* P(s|0), prob of receiving s given 0 transmitted */ + p0 = normal(((s-OFFSET+0.5)/amp + 1)/noise) - + normal(((s-OFFSET-0.5)/amp + 1)/noise); + +#ifdef notdef + printf("P(%d|1) = %lg, P(%d|0) = %lg\n",s,p1,s,p0); +#endif + metrics[0][s] = gr_log2(2*p0/(p1+p0)) - bias; + metrics[1][s] = gr_log2(2*p1/(p1+p0)) - bias; + } + /* 255 is also a special value */ + /* P(s|1) */ + p1 = 1 - normal(((255-OFFSET-0.5)/amp - 1)/noise); + /* P(s|0) */ + p0 = 1 - normal(((255-OFFSET-0.5)/amp + 1)/noise); + + metrics[0][255] = gr_log2(2*p0/(p1+p0)) - bias; + metrics[1][255] = gr_log2(2*p1/(p1+p0)) - bias; +#ifdef notdef + /* The probability of a raw symbol error is the probability + * that a 1-bit would be received as a sample with value + * 0-128. This is the offset normal curve integrated from -Inf to 0. + */ + printf("symbol Pe = %lg\n",normal(-1/noise)); +#endif + for(bit=0;bit<2;bit++){ + for(s=0;s<256;s++){ + /* Scale and round to nearest integer */ + mettab[bit][s] = floor(metrics[bit][s] * scale + 0.5); +#ifdef notdef + printf("metrics[%d][%d] = %lg, mettab = %d\n", + bit,s,metrics[bit][s],mettab[bit][s]); +#endif + } + } +} diff --git a/gnuradio-core/src/lib/viterbi/tab.c b/gnuradio-core/src/lib/viterbi/tab.c new file mode 100644 index 000000000..1c135acfe --- /dev/null +++ b/gnuradio-core/src/lib/viterbi/tab.c @@ -0,0 +1,57 @@ +/* + * Copyright 1995 Phil Karn, KA9Q + * 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. + */ + +/* 8-bit parity lookup table, generated by partab.c */ +unsigned char Partab[] = { + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, +}; diff --git a/gnuradio-core/src/lib/viterbi/viterbi.c b/gnuradio-core/src/lib/viterbi/viterbi.c new file mode 100644 index 000000000..fc8886603 --- /dev/null +++ b/gnuradio-core/src/lib/viterbi/viterbi.c @@ -0,0 +1,355 @@ +/* + * Copyright 1995 Phil Karn, KA9Q + * 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. + */ + +/* + * Viterbi decoder for K=7 rate=1/2 convolutional code + * Some modifications from original Karn code by Matt Ettus + */ + +#include "viterbi.h" + +/* The two generator polynomials for the NASA Standard K=7 code. + * Since these polynomials are known to be optimal for this constraint + * length there is not much point in changing them. But if you do, you + * will have to regenerate the BUTTERFLY macro calls in viterbi() + */ +#define POLYA 0x6d +#define POLYB 0x4f + +/* The basic Viterbi decoder operation, called a "butterfly" + * operation because of the way it looks on a trellis diagram. Each + * butterfly involves an Add-Compare-Select (ACS) operation on the two nodes + * where the 0 and 1 paths from the current node merge at the next step of + * the trellis. + * + * The code polynomials are assumed to have 1's on both ends. Given a + * function encode_state() that returns the two symbols for a given + * encoder state in the low two bits, such a code will have the following + * identities for even 'n' < 64: + * + * encode_state(n) = encode_state(n+65) + * encode_state(n+1) = encode_state(n+64) = (3 ^ encode_state(n)) + * + * Any convolutional code you would actually want to use will have + * these properties, so these assumptions aren't too limiting. + * + * Doing this as a macro lets the compiler evaluate at compile time the + * many expressions that depend on the loop index and encoder state and + * emit them as immediate arguments. + * This makes an enormous difference on register-starved machines such + * as the Intel x86 family where evaluating these expressions at runtime + * would spill over into memory. + */ +#define BUTTERFLY(i,sym) { \ + int m0,m1;\ +\ + /* ACS for 0 branch */\ + m0 = state[i].metric + mets[sym]; /* 2*i */\ + m1 = state[i+32].metric + mets[3^sym]; /* 2*i + 64 */\ + if(m0 > m1){\ + next[2*i].metric = m0;\ + next[2*i].path = state[i].path << 1;\ + } else {\ + next[2*i].metric = m1;\ + next[2*i].path = (state[i+32].path << 1)|1;\ + }\ + /* ACS for 1 branch */\ + m0 = state[i].metric + mets[3^sym]; /* 2*i + 1 */\ + m1 = state[i+32].metric + mets[sym]; /* 2*i + 65 */\ + if(m0 > m1){\ + next[2*i+1].metric = m0;\ + next[2*i+1].path = state[i].path << 1;\ + } else {\ + next[2*i+1].metric = m1;\ + next[2*i+1].path = (state[i+32].path << 1)|1;\ + }\ +} + +extern unsigned char Partab[]; /* Parity lookup table */ + +/* Convolutionally encode data into binary symbols */ +unsigned char +encode(unsigned char *symbols, + unsigned char *data, + unsigned int nbytes, + unsigned char encstate) +{ + int i; + + while(nbytes-- != 0){ + for(i=7;i>=0;i--){ + encstate = (encstate << 1) | ((*data >> i) & 1); + *symbols++ = Partab[encstate & POLYA]; + *symbols++ = Partab[encstate & POLYB]; + } + data++; + } + + return encstate; +} + +/* Viterbi decoder */ +int +viterbi(unsigned long *metric, /* Final path metric (returned value) */ + unsigned char *data, /* Decoded output data */ + unsigned char *symbols, /* Raw deinterleaved input symbols */ + unsigned int nbits, /* Number of output bits */ + int mettab[2][256] /* Metric table, [sent sym][rx symbol] */ + ){ + unsigned int bitcnt = 0; + int mets[4]; + long bestmetric; + int beststate,i; + struct viterbi_state state0[64],state1[64],*state,*next; + + state = state0; + next = state1; + + /* Initialize starting metrics to prefer 0 state */ + state[0].metric = 0; + for(i=1;i<64;i++) + state[i].metric = -999999; + state[0].path = 0; + + for(bitcnt = 0;bitcnt < nbits;bitcnt++){ + /* Read input symbol pair and compute all possible branch + * metrics + */ + mets[0] = mettab[0][symbols[0]] + mettab[0][symbols[1]]; + mets[1] = mettab[0][symbols[0]] + mettab[1][symbols[1]]; + mets[2] = mettab[1][symbols[0]] + mettab[0][symbols[1]]; + mets[3] = mettab[1][symbols[0]] + mettab[1][symbols[1]]; + symbols += 2; + + /* These macro calls were generated by genbut.c */ + BUTTERFLY(0,0); + BUTTERFLY(1,1); + BUTTERFLY(2,3); + BUTTERFLY(3,2); + BUTTERFLY(4,3); + BUTTERFLY(5,2); + BUTTERFLY(6,0); + BUTTERFLY(7,1); + BUTTERFLY(8,0); + BUTTERFLY(9,1); + BUTTERFLY(10,3); + BUTTERFLY(11,2); + BUTTERFLY(12,3); + BUTTERFLY(13,2); + BUTTERFLY(14,0); + BUTTERFLY(15,1); + BUTTERFLY(16,2); + BUTTERFLY(17,3); + BUTTERFLY(18,1); + BUTTERFLY(19,0); + BUTTERFLY(20,1); + BUTTERFLY(21,0); + BUTTERFLY(22,2); + BUTTERFLY(23,3); + BUTTERFLY(24,2); + BUTTERFLY(25,3); + BUTTERFLY(26,1); + BUTTERFLY(27,0); + BUTTERFLY(28,1); + BUTTERFLY(29,0); + BUTTERFLY(30,2); + BUTTERFLY(31,3); + + /* Swap current and next states */ + if(bitcnt & 1){ + state = state0; + next = state1; + } else { + state = state1; + next = state0; + } + // ETTUS + //if(bitcnt > nbits-7){ + /* In tail, poison non-zero nodes */ + //for(i=1;i<64;i += 2) + // state[i].metric = -9999999; + //} + /* Produce output every 8 bits once path memory is full */ + if((bitcnt % 8) == 5 && bitcnt > 32){ + /* Find current best path */ + bestmetric = state[0].metric; + beststate = 0; + for(i=1;i<64;i++){ + if(state[i].metric > bestmetric){ + bestmetric = state[i].metric; + beststate = i; + } + } +#ifdef notdef + printf("metrics[%d] = %d state = %lx\n",beststate, + state[beststate].metric,state[beststate].path); +#endif + *data++ = state[beststate].path >> 24; + } + + } + /* Output remaining bits from 0 state */ + // ETTUS Find best state instead + bestmetric = state[0].metric; + beststate = 0; + for(i=1;i<64;i++){ + if(state[i].metric > bestmetric){ + bestmetric = state[i].metric; + beststate = i; + } + } + if((i = bitcnt % 8) != 6) + state[beststate].path <<= 6-i; + + *data++ = state[beststate].path >> 24; + *data++ = state[beststate].path >> 16; + *data++ = state[beststate].path >> 8; + *data = state[beststate].path; + //printf ("BS = %d\tBSM = %d\tM0 = %d\n",beststate,state[beststate].metric,state[0].metric); + *metric = state[beststate].metric; + return 0; +} + + +void +viterbi_chunks_init(struct viterbi_state* state) { + // Initialize starting metrics to prefer 0 state + int i; + state[0].metric = 0; + state[0].path = 0; + for(i=1;i<64;i++) + state[i].metric = -999999; +} + +void +viterbi_butterfly8(unsigned char *symbols, int mettab[2][256], struct viterbi_state *state0, struct viterbi_state *state1) +{ + unsigned int bitcnt; + int mets[4]; + + struct viterbi_state *state, *next; + state = state0; + next = state1; + // Operate on 16 symbols (8 bits) at a time + for(bitcnt = 0;bitcnt < 8;bitcnt++){ + // Read input symbol pair and compute all possible branch metrics + mets[0] = mettab[0][symbols[0]] + mettab[0][symbols[1]]; + mets[1] = mettab[0][symbols[0]] + mettab[1][symbols[1]]; + mets[2] = mettab[1][symbols[0]] + mettab[0][symbols[1]]; + mets[3] = mettab[1][symbols[0]] + mettab[1][symbols[1]]; + symbols += 2; + + // These macro calls were generated by genbut.c + BUTTERFLY(0,0);BUTTERFLY(1,1);BUTTERFLY(2,3);BUTTERFLY(3,2); + BUTTERFLY(4,3);BUTTERFLY(5,2);BUTTERFLY(6,0);BUTTERFLY(7,1); + BUTTERFLY(8,0);BUTTERFLY(9,1);BUTTERFLY(10,3);BUTTERFLY(11,2); + BUTTERFLY(12,3);BUTTERFLY(13,2);BUTTERFLY(14,0);BUTTERFLY(15,1); + BUTTERFLY(16,2);BUTTERFLY(17,3);BUTTERFLY(18,1);BUTTERFLY(19,0); + BUTTERFLY(20,1);BUTTERFLY(21,0);BUTTERFLY(22,2);BUTTERFLY(23,3); + BUTTERFLY(24,2);BUTTERFLY(25,3);BUTTERFLY(26,1);BUTTERFLY(27,0); + BUTTERFLY(28,1);BUTTERFLY(29,0);BUTTERFLY(30,2);BUTTERFLY(31,3); + + // Swap current and next states + if(bitcnt & 1){ + state = state0; + next = state1; + } else { + state = state1; + next = state0; + } + } +} + +void +viterbi_butterfly2(unsigned char *symbols, int mettab[2][256], struct viterbi_state *state0, struct viterbi_state *state1) +{ + //unsigned int bitcnt; + int mets[4]; + + struct viterbi_state *state, *next; + state = state0; + next = state1; + // Operate on 4 symbols (2 bits) at a time + + // Read input symbol pair and compute all possible branch metrics + mets[0] = mettab[0][symbols[0]] + mettab[0][symbols[1]]; + mets[1] = mettab[0][symbols[0]] + mettab[1][symbols[1]]; + mets[2] = mettab[1][symbols[0]] + mettab[0][symbols[1]]; + mets[3] = mettab[1][symbols[0]] + mettab[1][symbols[1]]; + + // These macro calls were generated by genbut.c + BUTTERFLY(0,0);BUTTERFLY(1,1);BUTTERFLY(2,3);BUTTERFLY(3,2); + BUTTERFLY(4,3);BUTTERFLY(5,2);BUTTERFLY(6,0);BUTTERFLY(7,1); + BUTTERFLY(8,0);BUTTERFLY(9,1);BUTTERFLY(10,3);BUTTERFLY(11,2); + BUTTERFLY(12,3);BUTTERFLY(13,2);BUTTERFLY(14,0);BUTTERFLY(15,1); + BUTTERFLY(16,2);BUTTERFLY(17,3);BUTTERFLY(18,1);BUTTERFLY(19,0); + BUTTERFLY(20,1);BUTTERFLY(21,0);BUTTERFLY(22,2);BUTTERFLY(23,3); + BUTTERFLY(24,2);BUTTERFLY(25,3);BUTTERFLY(26,1);BUTTERFLY(27,0); + BUTTERFLY(28,1);BUTTERFLY(29,0);BUTTERFLY(30,2);BUTTERFLY(31,3); + + state = state1; + next = state0; + + // Read input symbol pair and compute all possible branch metrics + mets[0] = mettab[0][symbols[2]] + mettab[0][symbols[3]]; + mets[1] = mettab[0][symbols[2]] + mettab[1][symbols[3]]; + mets[2] = mettab[1][symbols[2]] + mettab[0][symbols[3]]; + mets[3] = mettab[1][symbols[2]] + mettab[1][symbols[3]]; + + // These macro calls were generated by genbut.c + BUTTERFLY(0,0);BUTTERFLY(1,1);BUTTERFLY(2,3);BUTTERFLY(3,2); + BUTTERFLY(4,3);BUTTERFLY(5,2);BUTTERFLY(6,0);BUTTERFLY(7,1); + BUTTERFLY(8,0);BUTTERFLY(9,1);BUTTERFLY(10,3);BUTTERFLY(11,2); + BUTTERFLY(12,3);BUTTERFLY(13,2);BUTTERFLY(14,0);BUTTERFLY(15,1); + BUTTERFLY(16,2);BUTTERFLY(17,3);BUTTERFLY(18,1);BUTTERFLY(19,0); + BUTTERFLY(20,1);BUTTERFLY(21,0);BUTTERFLY(22,2);BUTTERFLY(23,3); + BUTTERFLY(24,2);BUTTERFLY(25,3);BUTTERFLY(26,1);BUTTERFLY(27,0); + BUTTERFLY(28,1);BUTTERFLY(29,0);BUTTERFLY(30,2);BUTTERFLY(31,3); +} + +unsigned char +viterbi_get_output(struct viterbi_state *state, unsigned char *outbuf) { + // Produce output every 8 bits once path memory is full + // if((bitcnt % 8) == 5 && bitcnt > 32) { + + // Find current best path + unsigned int i,beststate; + int bestmetric; + + bestmetric = state[0].metric; + beststate = 0; + for(i=1;i<64;i++) + if(state[i].metric > bestmetric) { + bestmetric = state[i].metric; + beststate = i; + } + *outbuf = state[beststate].path >> 24; + return bestmetric; +} + + +//printf ("BS = %d\tBSM = %d\tM0 = %d\n",beststate,state[beststate].metric,state[0].metric); +// In tail, poison non-zero nodes +//if(bits_out > packet_size-7) +// for(i=1;i<64;i += 2) +// state[i].metric = -9999999; + diff --git a/gnuradio-core/src/lib/viterbi/viterbi.h b/gnuradio-core/src/lib/viterbi/viterbi.h new file mode 100644 index 000000000..bcdbe116d --- /dev/null +++ b/gnuradio-core/src/lib/viterbi/viterbi.h @@ -0,0 +1,53 @@ +/* + * 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. + */ + +/* The path memory for each state is 32 bits. This is slightly shorter + * than we'd like for K=7, especially since we chain back every 8 bits. + * But it fits so nicely into a 32-bit machine word... + */ + +#include <gr_core_api.h> + +struct viterbi_state { + unsigned long path; /* Decoded path to this state */ + long metric; /* Cumulative metric to this state */ +}; + +GR_CORE_API +int gen_met(int mettab[2][256], /* Metric table */ + int amp, /* Signal amplitude */ + double esn0, /* Es/N0 ratio in dB */ + double bias, /* Metric bias */ + int scale); /* Scale factor */ + +GR_CORE_API unsigned char +encode(unsigned char *symbols, unsigned char *data, + unsigned int nbytes,unsigned char encstate); + +GR_CORE_API void +viterbi_chunks_init(struct viterbi_state* state); + + GR_CORE_API void +viterbi_butterfly2(unsigned char *symbols, int mettab[2][256], + struct viterbi_state *state0, struct viterbi_state *state1); + +GR_CORE_API unsigned char +viterbi_get_output(struct viterbi_state *state, unsigned char *outbuf); diff --git a/gnuradio-core/src/python/bin/microtune.py b/gnuradio-core/src/python/bin/microtune.py new file mode 100755 index 000000000..fbe743f39 --- /dev/null +++ b/gnuradio-core/src/python/bin/microtune.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python +# -*- Python -*- + +from gnuradio import gr +from gnuradio.eng_option import eng_option +from gnuradio.wxgui import stdgui, fftsink +from optparse import OptionParser +from gnuradio import eng_notation + + +def main (): + parser = OptionParser (option_class=eng_option) + parser.add_option ("-g", "--gain", type="eng_float", default=-1, + help="set front end gain to GAIN [0,1000]") + parser.add_option ("-f", "--freq", type="eng_float", default=-1, + help="set front end center frequency to FREQ") + parser.add_option ("-t", "--type", type="string", default="4937", + help="select eval board type {4937 or 4702}") + parser.add_option ("-p", "--port", type="int", default=0, + help="parallel port eval board is attached to") + (options, args) = parser.parse_args () + + if options.type == "4937": + front_end = gr.microtune_4937_eval_board (options.port) + elif options.type == "4702": + front_end = gr.microtune_4702_eval_board (options.port) + else: + raise RuntimeError, "Invalid board type. Must be either -t 4937 or -t 4702" + + if options.gain != -1: + front_end.set_AGC (options.gain) + + if options.freq != -1: + if options.freq < 1e6: + options.freq = options.freq * 1e6 + + actual = front_end.set_RF_freq (options.freq) + print "microtune: actual freq = %s" % (eng_notation.num_to_str (actual),) + + +if __name__ == '__main__': + main () diff --git a/gnuradio-core/src/python/build_utils.py b/gnuradio-core/src/python/build_utils.py new file mode 100644 index 000000000..cf58a9763 --- /dev/null +++ b/gnuradio-core/src/python/build_utils.py @@ -0,0 +1,226 @@ +# +# Copyright 2004,2009,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. +# + +"""Misc utilities used at build time +""" + +import re, os, os.path +from build_utils_codes import * + + +# set srcdir to the directory that contains Makefile.am +try: + srcdir = os.environ['srcdir'] +except KeyError, e: + srcdir = "." +srcdir = srcdir + '/' + +# set do_makefile to either true or false dependeing on the environment +try: + if os.environ['do_makefile'] == '0': + do_makefile = False + else: + do_makefile = True +except KeyError, e: + do_makefile = False + +# set do_sources to either true or false dependeing on the environment +try: + if os.environ['do_sources'] == '0': + do_sources = False + else: + do_sources = True +except KeyError, e: + do_sources = True + +name_dict = {} + +def log_output_name (name): + (base, ext) = os.path.splitext (name) + ext = ext[1:] # drop the leading '.' + + entry = name_dict.setdefault (ext, []) + entry.append (name) + +def open_and_log_name (name, dir): + global do_sources + if do_sources: + f = open (name, dir) + else: + f = None + log_output_name (name) + return f + +def expand_template (d, template_filename, extra = ""): + '''Given a dictionary D and a TEMPLATE_FILENAME, expand template into output file + ''' + global do_sources + output_extension = extract_extension (template_filename) + template = open_src (template_filename, 'r') + output_name = d['NAME'] + extra + '.' + output_extension + log_output_name (output_name) + if do_sources: + output = open (output_name, 'w') + do_substitution (d, template, output) + output.close () + template.close () + +def output_glue (dirname): + output_makefile_fragment () + output_ifile_include (dirname) + +def output_makefile_fragment (): + global do_makefile + if not do_makefile: + return +# overwrite the source, which must be writable; this should have been +# checked for beforehand in the top-level Makefile.gen.gen . + f = open (os.path.join (os.environ.get('gendir', os.environ.get('srcdir', '.')), 'Makefile.gen'), 'w') + f.write ('#\n# This file is machine generated. All edits will be overwritten\n#\n') + output_subfrag (f, 'h') + output_subfrag (f, 'i') + output_subfrag (f, 'cc') + f.close () + +def output_ifile_include (dirname): + global do_sources + if do_sources: + f = open ('%s_generated.i' % (dirname,), 'w') + f.write ('//\n// This file is machine generated. All edits will be overwritten\n//\n') + files = name_dict.setdefault ('i', []) + files.sort () + f.write ('%{\n') + for file in files: + f.write ('#include <%s>\n' % (file[0:-1] + 'h',)) + f.write ('%}\n\n') + for file in files: + f.write ('%%include <%s>\n' % (file,)) + +def output_subfrag (f, ext): + files = name_dict.setdefault (ext, []) + files.sort () + f.write ("GENERATED_%s =" % (ext.upper ())) + for file in files: + f.write (" \\\n\t%s" % (file,)) + f.write ("\n\n") + +def extract_extension (template_name): + # template name is something like: GrFIRfilterXXX.h.t + # we return everything between the penultimate . and .t + mo = re.search (r'\.([a-z]+)\.t$', template_name) + if not mo: + raise ValueError, "Incorrectly formed template_name '%s'" % (template_name,) + return mo.group (1) + +def open_src (name, mode): + global srcdir + return open (os.path.join (srcdir, name), mode) + +def do_substitution (d, in_file, out_file): + def repl (match_obj): + key = match_obj.group (1) + # print key + return d[key] + + inp = in_file.read () + out = re.sub (r"@([a-zA-Z0-9_]+)@", repl, inp) + out_file.write (out) + + + +copyright = '''/* -*- c++ -*- */ +/* + * Copyright 2003,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. + */ +''' + +def is_complex (code3): + if i_code (code3) == 'c' or o_code (code3) == 'c': + return '1' + else: + return '0' + + +def standard_dict (name, code3, package='gr'): + d = {} + d['NAME'] = name + d['NAME_IMPL'] = name+'_impl' + d['GUARD_NAME'] = 'INCLUDED_%s_%s_H' % (package.upper(), name.upper()) + d['GUARD_NAME_IMPL'] = 'INCLUDED_%s_%s_IMPL_H' % (package.upper(), name.upper()) + d['BASE_NAME'] = re.sub ('^' + package + '_', '', name) + d['SPTR_NAME'] = '%s_sptr' % name + d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten' + d['COPYRIGHT'] = copyright + d['TYPE'] = i_type (code3) + d['I_TYPE'] = i_type (code3) + d['O_TYPE'] = o_type (code3) + d['TAP_TYPE'] = tap_type (code3) + d['IS_COMPLEX'] = is_complex (code3) + return d + + +def standard_dict2 (name, code3, package): + d = {} + d['NAME'] = name + d['BASE_NAME'] = name + d['GUARD_NAME'] = 'INCLUDED_%s_%s_H' % (package.upper(), name.upper()) + d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten' + d['COPYRIGHT'] = copyright + d['TYPE'] = i_type (code3) + d['I_TYPE'] = i_type (code3) + d['O_TYPE'] = o_type (code3) + d['TAP_TYPE'] = tap_type (code3) + d['IS_COMPLEX'] = is_complex (code3) + return d + +def standard_impl_dict2 (name, code3, package): + d = {} + d['NAME'] = name + d['IMPL_NAME'] = name + d['BASE_NAME'] = name.rstrip("impl").rstrip("_") + d['GUARD_NAME'] = 'INCLUDED_%s_%s_H' % (package.upper(), name.upper()) + d['WARNING'] = 'WARNING: this file is machine generated. Edits will be overwritten' + d['COPYRIGHT'] = copyright + d['FIR_TYPE'] = "fir_filter_" + code3 + d['CFIR_TYPE'] = "fir_filter_" + code3[0:2] + 'c' + d['TYPE'] = i_type (code3) + d['I_TYPE'] = i_type (code3) + d['O_TYPE'] = o_type (code3) + d['TAP_TYPE'] = tap_type (code3) + d['IS_COMPLEX'] = is_complex (code3) + return d diff --git a/gnuradio-core/src/python/build_utils_codes.py b/gnuradio-core/src/python/build_utils_codes.py new file mode 100644 index 000000000..9ea96baae --- /dev/null +++ b/gnuradio-core/src/python/build_utils_codes.py @@ -0,0 +1,52 @@ +# +# 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. +# + +def i_code (code3): + return code3[0] + +def o_code (code3): + if len (code3) >= 2: + return code3[1] + else: + return code3[0] + +def tap_code (code3): + if len (code3) >= 3: + return code3[2] + else: + return code3[0] + +def i_type (code3): + return char_to_type[i_code (code3)] + +def o_type (code3): + return char_to_type[o_code (code3)] + +def tap_type (code3): + return char_to_type[tap_code (code3)] + + +char_to_type = {} +char_to_type['s'] = 'short' +char_to_type['i'] = 'int' +char_to_type['f'] = 'float' +char_to_type['c'] = 'gr_complex' +char_to_type['b'] = 'unsigned char' diff --git a/gnuradio-core/src/python/gnuradio/CMakeLists.txt b/gnuradio-core/src/python/gnuradio/CMakeLists.txt new file mode 100644 index 000000000..bf696e0d3 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright 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. + +include(GrPython) + +add_subdirectory(gr) +add_subdirectory(gru) +add_subdirectory(gruimpl) +add_subdirectory(blks2) +add_subdirectory(blks2impl) + +GR_PYTHON_INSTALL(FILES + __init__.py + eng_notation.py + eng_option.py + gr_unittest.py + gr_xmlrunner.py + optfir.py + window.py + DESTINATION ${GR_PYTHON_DIR}/gnuradio + COMPONENT "core_python" +) diff --git a/gnuradio-core/src/python/gnuradio/__init__.py b/gnuradio-core/src/python/gnuradio/__init__.py new file mode 100644 index 000000000..a4917cf64 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/__init__.py @@ -0,0 +1 @@ +# make this a package diff --git a/gnuradio-core/src/python/gnuradio/blks2/CMakeLists.txt b/gnuradio-core/src/python/gnuradio/blks2/CMakeLists.txt new file mode 100644 index 000000000..83d11dd83 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2/CMakeLists.txt @@ -0,0 +1,26 @@ +# Copyright 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. + +include(GrPython) + +GR_PYTHON_INSTALL( + FILES __init__.py + DESTINATION ${GR_PYTHON_DIR}/gnuradio/blks2 + COMPONENT "core_python" +) diff --git a/gnuradio-core/src/python/gnuradio/blks2/__init__.py b/gnuradio-core/src/python/gnuradio/blks2/__init__.py new file mode 100644 index 000000000..2dfdc77f4 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2/__init__.py @@ -0,0 +1,37 @@ +# +# 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. +# + +import glob +import os.path + +# Semi-hideous kludge to import everything in the blksimpl2 directory +# into the gnuradio.blks2 namespace. This keeps us from having to remember +# to manually update this file. + +for p in __path__: + filenames = glob.glob (os.path.join (p, "..", "blks2impl", "*.py")) + for f in filenames: + f = os.path.basename(f).lower() + f = f[:-3] + if f == '__init__': + continue + # print f + exec "from gnuradio.blks2impl.%s import *" % (f,) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/CMakeLists.txt b/gnuradio-core/src/python/gnuradio/blks2impl/CMakeLists.txt new file mode 100644 index 000000000..61fcdda42 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2impl/CMakeLists.txt @@ -0,0 +1,45 @@ +# Copyright 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. + +include(GrPython) + +GR_PYTHON_INSTALL(FILES + __init__.py + am_demod.py + channel_model.py + filterbank.py + fm_demod.py + fm_emph.py + logpwrfft.py + nbfm_rx.py + nbfm_tx.py + pfb_arb_resampler.py + pfb_channelizer.py + pfb_decimator.py + pfb_interpolator.py + rational_resampler.py + standard_squelch.py + stream_to_vector_decimator.py + wfm_rcv.py + wfm_rcv_fmdet.py + wfm_rcv_pll.py + wfm_tx.py + DESTINATION ${GR_PYTHON_DIR}/gnuradio/blks2impl + COMPONENT "core_python" +) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/__init__.py b/gnuradio-core/src/python/gnuradio/blks2impl/__init__.py new file mode 100644 index 000000000..a4917cf64 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2impl/__init__.py @@ -0,0 +1 @@ +# make this a package diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/am_demod.py b/gnuradio-core/src/python/gnuradio/blks2impl/am_demod.py new file mode 100644 index 000000000..68d024565 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2impl/am_demod.py @@ -0,0 +1,75 @@ +# +# Copyright 2006,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. +# + +from gnuradio import gr, optfir + +class am_demod_cf(gr.hier_block2): + """ + Generalized AM demodulation block with audio filtering. + + This block demodulates a band-limited, complex down-converted AM + channel into the the original baseband signal, applying low pass + filtering to the audio output. It produces a float stream in the + range [-1.0, +1.0]. + + @param channel_rate: incoming sample rate of the AM baseband + @type sample_rate: integer + @param audio_decim: input to output decimation rate + @type audio_decim: integer + @param audio_pass: audio low pass filter passband frequency + @type audio_pass: float + @param audio_stop: audio low pass filter stop frequency + @type audio_stop: float + """ + def __init__(self, channel_rate, audio_decim, audio_pass, audio_stop): + gr.hier_block2.__init__(self, "am_demod_cf", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(1, 1, gr.sizeof_float)) # Input signature + + MAG = gr.complex_to_mag() + DCR = gr.add_const_ff(-1.0) + + audio_taps = optfir.low_pass(0.5, # Filter gain + channel_rate, # Sample rate + audio_pass, # Audio passband + audio_stop, # Audio stopband + 0.1, # Passband ripple + 60) # Stopband attenuation + LPF = gr.fir_filter_fff(audio_decim, audio_taps) + + self.connect(self, MAG, DCR, LPF, self) + +class demod_10k0a3e_cf(am_demod_cf): + """ + AM demodulation block, 10 KHz channel. + + This block demodulates an AM channel conformant to 10K0A3E emission + standards, such as broadcast band AM transmissions. + + @param channel_rate: incoming sample rate of the AM baseband + @type sample_rate: integer + @param audio_decim: input to output decimation rate + @type audio_decim: integer + """ + def __init__(self, channel_rate, audio_decim): + am_demod_cf.__init__(self, channel_rate, audio_decim, + 5000, # Audio passband + 5500) # Audio stopband diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/channel_model.py b/gnuradio-core/src/python/gnuradio/blks2impl/channel_model.py new file mode 100644 index 000000000..e5cd471df --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2impl/channel_model.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python +# +# Copyright 2009 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 + +# This block is now a C++ hierarchical block, gr.channel_model +channel_model = gr.channel_model diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/digital_voice.py.real b/gnuradio-core/src/python/gnuradio/blks2impl/digital_voice.py.real new file mode 100644 index 000000000..6ec66825c --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2impl/digital_voice.py.real @@ -0,0 +1,102 @@ +#!/usr/bin/env python +# +# 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. +# + +""" +Digital voice Tx and Rx using GSM 13kbit vocoder and GMSK. + +Runs channel at 32kbit/sec. Currently uses fake channel coding, +but there's room for a rate 1/2 coder. +""" + +from gnuradio import gr, gru +from gnuradio.blksimpl.gmsk import gmsk_mod, gmsk_demod + +from gnuradio.vocoder import gsm_full_rate + +# Size of gsm full rate speech encoder output packet in bytes + +GSM_FRAME_SIZE = 33 + +# Size of packet in bytes that we send to GMSK modulator: +# +# Target: 256kS/sec air rate. +# +# 256kS 1 sym 1 bit 1 byte 0.020 sec 80 bytes +# ---- * ----- * ----- * ------ * --------- = -------- +# sec 8 S 1 sym 8 bits frame frame +# +# gr_simple_framer add 10 bytes of overhead. + +AIR_FRAME_SIZE = 70 + + +class digital_voice_tx(gr.hier_block): + """ + Hierarchical block for digital voice tranmission. + + The input is 8kS/sec floating point audio in the range [-1,+1] + The output is 256kS/sec GMSK modulated complex baseband signal in the range [-1,+1]. + """ + def __init__(self, fg): + samples_per_symbol = 8 + symbol_rate = 32000 + bt = 0.3 # Gaussian filter bandwidth * symbol time + + src_scale = gr.multiply_const_ff(32767) + f2s = gr.float_to_short() + voice_coder = gsm_full_rate.encode_sp() + + channel_coder = gr.fake_channel_encoder_pp(GSM_FRAME_SIZE, AIR_FRAME_SIZE) + p2s = gr.parallel_to_serial(gr.sizeof_char, AIR_FRAME_SIZE) + + mod = gmsk_mod(fg, sps=samples_per_symbol, + symbol_rate=symbol_rate, bt=bt, + p_size=AIR_FRAME_SIZE) + + fg.connect(src_scale, f2s, voice_coder, channel_coder, p2s, mod) + gr.hier_block.__init__(self, fg, src_scale, mod) + + +class digital_voice_rx(gr.hier_block): + """ + Hierarchical block for digital voice reception. + + The input is 256kS/sec GMSK modulated complex baseband signal. + The output is 8kS/sec floating point audio in the range [-1,+1] + """ + def __init__(self, fg): + samples_per_symbol = 8 + symbol_rate = 32000 + + demod = gmsk_demod(fg, sps=samples_per_symbol, + symbol_rate=symbol_rate, + p_size=AIR_FRAME_SIZE) + + s2p = gr.serial_to_parallel(gr.sizeof_char, AIR_FRAME_SIZE) + channel_decoder = gr.fake_channel_decoder_pp(AIR_FRAME_SIZE, GSM_FRAME_SIZE) + + voice_decoder = gsm_full_rate.decode_ps() + s2f = gr.short_to_float () + sink_scale = gr.multiply_const_ff(1.0/32767.) + + fg.connect(demod, s2p, channel_decoder, voice_decoder, s2f, sink_scale) + gr.hier_block.__init__(self, fg, demod, sink_scale) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/filterbank.py b/gnuradio-core/src/python/gnuradio/blks2impl/filterbank.py new file mode 100644 index 000000000..08f1d450b --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2impl/filterbank.py @@ -0,0 +1,169 @@ +# +# Copyright 2005,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. +# + +import sys +from gnuradio import gr, gru + +def _generate_synthesis_taps(mpoints): + return [] # FIXME + + +def _split_taps(taps, mpoints): + assert (len(taps) % mpoints) == 0 + result = [list() for x in range(mpoints)] + for i in xrange(len(taps)): + (result[i % mpoints]).append(taps[i]) + return [tuple(x) for x in result] + + +class synthesis_filterbank(gr.hier_block2): + """ + Uniformly modulated polyphase DFT filter bank: synthesis + + See http://cnx.org/content/m10424/latest + """ + def __init__(self, mpoints, taps=None): + """ + Takes M complex streams in, produces single complex stream out + that runs at M times the input sample rate + + @param mpoints: number of freq bins/interpolation factor/subbands + @param taps: filter taps for subband filter + + The channel spacing is equal to the input sample rate. + The total bandwidth and output sample rate are equal the input + sample rate * nchannels. + + Output stream to frequency mapping: + + channel zero is at zero frequency. + + if mpoints is odd: + + Channels with increasing positive frequencies come from + channels 1 through (N-1)/2. + + Channel (N+1)/2 is the maximum negative frequency, and + frequency increases through N-1 which is one channel lower + than the zero frequency. + + if mpoints is even: + + Channels with increasing positive frequencies come from + channels 1 through (N/2)-1. + + Channel (N/2) is evenly split between the max positive and + negative bins. + + Channel (N/2)+1 is the maximum negative frequency, and + frequency increases through N-1 which is one channel lower + than the zero frequency. + + Channels near the frequency extremes end up getting cut + off by subsequent filters and therefore have diminished + utility. + """ + item_size = gr.sizeof_gr_complex + gr.hier_block2.__init__(self, "synthesis_filterbank", + gr.io_signature(mpoints, mpoints, item_size), # Input signature + gr.io_signature(1, 1, item_size)) # Output signature + + + if taps is None: + taps = _generate_synthesis_taps(mpoints) + + # pad taps to multiple of mpoints + r = len(taps) % mpoints + if r != 0: + taps = taps + (mpoints - r) * (0,) + + # split in mpoints separate set of taps + sub_taps = _split_taps(taps, mpoints) + + self.ss2v = gr.streams_to_vector(item_size, mpoints) + self.ifft = gr.fft_vcc(mpoints, False, []) + self.v2ss = gr.vector_to_streams(item_size, mpoints) + # mpoints filters go in here... + self.ss2s = gr.streams_to_stream(item_size, mpoints) + + for i in range(mpoints): + self.connect((self, i), (self.ss2v, i)) + + self.connect(self.ss2v, self.ifft, self.v2ss) + + # build mpoints fir filters... + for i in range(mpoints): + f = gr.fft_filter_ccc(1, sub_taps[i]) + self.connect((self.v2ss, i), f) + self.connect(f, (self.ss2s, i)) + + self.connect(self.ss2s, self) + +class analysis_filterbank(gr.hier_block2): + """ + Uniformly modulated polyphase DFT filter bank: analysis + + See http://cnx.org/content/m10424/latest + """ + def __init__(self, mpoints, taps=None): + """ + Takes 1 complex stream in, produces M complex streams out + that runs at 1/M times the input sample rate + + @param mpoints: number of freq bins/interpolation factor/subbands + @param taps: filter taps for subband filter + + Same channel to frequency mapping as described above. + """ + item_size = gr.sizeof_gr_complex + gr.hier_block2.__init__(self, "analysis_filterbank", + gr.io_signature(1, 1, item_size), # Input signature + gr.io_signature(mpoints, mpoints, item_size)) # Output signature + + if taps is None: + taps = _generate_synthesis_taps(mpoints) + + # pad taps to multiple of mpoints + r = len(taps) % mpoints + if r != 0: + taps = taps + (mpoints - r) * (0,) + + # split in mpoints separate set of taps + sub_taps = _split_taps(taps, mpoints) + + # print >> sys.stderr, "mpoints =", mpoints, "len(sub_taps) =", len(sub_taps) + + self.s2ss = gr.stream_to_streams(item_size, mpoints) + # filters here + self.ss2v = gr.streams_to_vector(item_size, mpoints) + self.fft = gr.fft_vcc(mpoints, True, []) + self.v2ss = gr.vector_to_streams(item_size, mpoints) + + self.connect(self, self.s2ss) + + # build mpoints fir filters... + for i in range(mpoints): + f = gr.fft_filter_ccc(1, sub_taps[mpoints-i-1]) + self.connect((self.s2ss, i), f) + self.connect(f, (self.ss2v, i)) + self.connect((self.v2ss, i), (self, i)) + + self.connect(self.ss2v, self.fft, self.v2ss) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/fm_demod.py b/gnuradio-core/src/python/gnuradio/blks2impl/fm_demod.py new file mode 100644 index 000000000..6bc0d7ed0 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2impl/fm_demod.py @@ -0,0 +1,111 @@ +# +# Copyright 2006,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. +# + +from gnuradio import gr, optfir +from gnuradio.blks2impl.fm_emph import fm_deemph +from math import pi + +class fm_demod_cf(gr.hier_block2): + """ + Generalized FM demodulation block with deemphasis and audio + filtering. + + This block demodulates a band-limited, complex down-converted FM + channel into the the original baseband signal, optionally applying + deemphasis. Low pass filtering is done on the resultant signal. It + produces an output float strem in the range of [-1.0, +1.0]. + + @param channel_rate: incoming sample rate of the FM baseband + @type sample_rate: integer + @param deviation: maximum FM deviation (default = 5000) + @type deviation: float + @param audio_decim: input to output decimation rate + @type audio_decim: integer + @param audio_pass: audio low pass filter passband frequency + @type audio_pass: float + @param audio_stop: audio low pass filter stop frequency + @type audio_stop: float + @param gain: gain applied to audio output (default = 1.0) + @type gain: float + @param tau: deemphasis time constant (default = 75e-6), specify 'None' + to prevent deemphasis + """ + def __init__(self, channel_rate, audio_decim, deviation, + audio_pass, audio_stop, gain=1.0, tau=75e-6): + gr.hier_block2.__init__(self, "fm_demod_cf", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(1, 1, gr.sizeof_float)) # Output signature + + k = channel_rate/(2*pi*deviation) + QUAD = gr.quadrature_demod_cf(k) + + audio_taps = optfir.low_pass(gain, # Filter gain + channel_rate, # Sample rate + audio_pass, # Audio passband + audio_stop, # Audio stopband + 0.1, # Passband ripple + 60) # Stopband attenuation + LPF = gr.fir_filter_fff(audio_decim, audio_taps) + + if tau is not None: + DEEMPH = fm_deemph(channel_rate, tau) + self.connect(self, QUAD, DEEMPH, LPF, self) + else: + self.connect(self, QUAD, LPF, self) + +class demod_20k0f3e_cf(fm_demod_cf): + """ + NBFM demodulation block, 20 KHz channels + + This block demodulates a complex, downconverted, narrowband FM + channel conforming to 20K0F3E emission standards, outputting + floats in the range [-1.0, +1.0]. + + @param sample_rate: incoming sample rate of the FM baseband + @type sample_rate: integer + @param audio_decim: input to output decimation rate + @type audio_decim: integer + """ + def __init__(self, channel_rate, audio_decim): + fm_demod_cf.__init__(self, channel_rate, audio_decim, + 5000, # Deviation + 3000, # Audio passband frequency + 4500) # Audio stopband frequency + +class demod_200kf3e_cf(fm_demod_cf): + """ + WFM demodulation block, mono. + + This block demodulates a complex, downconverted, wideband FM + channel conforming to 200KF3E emission standards, outputting + floats in the range [-1.0, +1.0]. + + @param sample_rate: incoming sample rate of the FM baseband + @type sample_rate: integer + @param audio_decim: input to output decimation rate + @type audio_decim: integer + """ + def __init__(self, channel_rate, audio_decim): + fm_demod_cf.__init__(self, channel_rate, audio_decim, + 75000, # Deviation + 15000, # Audio passband + 16000, # Audio stopband + 20.0) # Audio gain diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/fm_emph.py b/gnuradio-core/src/python/gnuradio/blks2impl/fm_emph.py new file mode 100644 index 000000000..fc3f2d60d --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2impl/fm_emph.py @@ -0,0 +1,151 @@ +# +# Copyright 2005,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. +# + +from gnuradio import gr +import math + + +# +# 1 +# H(s) = ------- +# 1 + s +# +# tau is the RC time constant. +# critical frequency: w_p = 1/tau +# +# We prewarp and use the bilinear z-transform to get our IIR coefficients. +# See "Digital Signal Processing: A Practical Approach" by Ifeachor and Jervis +# + +class fm_deemph(gr.hier_block2): + """ + FM Deemphasis IIR filter. + """ + + + def __init__(self, fs, tau=75e-6): + """ + @param fs: sampling frequency in Hz + @type fs: float + @param tau: Time constant in seconds (75us in US, 50us in EUR) + @type tau: float + """ + gr.hier_block2.__init__(self, "fm_deemph", + gr.io_signature(1, 1, gr.sizeof_float), # Input signature + gr.io_signature(1, 1, gr.sizeof_float)) # Output signature + + w_p = 1/tau + w_pp = math.tan (w_p / (fs * 2)) # prewarped analog freq + + a1 = (w_pp - 1)/(w_pp + 1) + b0 = w_pp/(1 + w_pp) + b1 = b0 + + btaps = [b0, b1] + ataps = [1, a1] + + if 0: + print "btaps =", btaps + print "ataps =", ataps + global plot1 + plot1 = gru.gnuplot_freqz (gru.freqz (btaps, ataps), fs, True) + + deemph = gr.iir_filter_ffd(btaps, ataps) + self.connect(self, deemph, self) + +# +# 1 + s*t1 +# H(s) = ---------- +# 1 + s*t2 +# +# I think this is the right transfer function. +# +# +# This fine ASCII rendition is based on Figure 5-15 +# in "Digital and Analog Communication Systems", Leon W. Couch II +# +# +# R1 +# +-----||------+ +# | | +# o------+ +-----+--------o +# | C1 | | +# +----/\/\/\/--+ \ +# / +# \ R2 +# / +# \ +# | +# o--------------------------+--------o +# +# f1 = 1/(2*pi*t1) = 1/(2*pi*R1*C) +# +# 1 R1 + R2 +# f2 = ------- = ------------ +# 2*pi*t2 2*pi*R1*R2*C +# +# t1 is 75us in US, 50us in EUR +# f2 should be higher than our audio bandwidth. +# +# +# The Bode plot looks like this: +# +# +# /---------------- +# / +# / <-- slope = 20dB/decade +# / +# -------------/ +# f1 f2 +# +# We prewarp and use the bilinear z-transform to get our IIR coefficients. +# See "Digital Signal Processing: A Practical Approach" by Ifeachor and Jervis +# + +class fm_preemph(gr.hier_block2): + """ + FM Preemphasis IIR filter. + """ + def __init__(self, fs, tau=75e-6): + """ + @param fs: sampling frequency in Hz + @type fs: float + @param tau: Time constant in seconds (75us in US, 50us in EUR) + @type tau: float + """ + + gr.hier_block2.__init__(self, "fm_deemph", + gr.io_signature(1, 1, gr.sizeof_float), # Input signature + gr.io_signature(1, 1, gr.sizeof_float)) # Output signature + + # FIXME make this compute the right answer + + btaps = [1] + ataps = [1] + + if 0: + print "btaps =", btaps + print "ataps =", ataps + global plot2 + plot2 = gru.gnuplot_freqz (gru.freqz (btaps, ataps), fs, True) + + preemph = gr.iir_filter_ffd(btaps, ataps) + self.connect(self, preemph, self) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/logpwrfft.py b/gnuradio-core/src/python/gnuradio/blks2impl/logpwrfft.py new file mode 100644 index 000000000..6f7fc520f --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2impl/logpwrfft.py @@ -0,0 +1,155 @@ +# +# 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. +# + +from gnuradio import gr, window +from stream_to_vector_decimator import stream_to_vector_decimator +import math + +class _logpwrfft_base(gr.hier_block2): + """ + Create a log10(abs(fft)) stream chain, with real or complex input. + """ + + def __init__(self, sample_rate, fft_size, ref_scale, frame_rate, avg_alpha, average, win=None): + """ + Create an log10(abs(fft)) stream chain. + Provide access to the setting the filter and sample rate. + @param sample_rate Incoming stream sample rate + @param fft_size Number of FFT bins + @param ref_scale Sets 0 dB value input amplitude + @param frame_rate Output frame rate + @param avg_alpha FFT averaging (over time) constant [0.0-1.0] + @param average Whether to average [True, False] + @param win the window taps generation function + """ + gr.hier_block2.__init__(self, self._name, + gr.io_signature(1, 1, self._item_size), # Input signature + gr.io_signature(1, 1, gr.sizeof_float*fft_size)) # Output signature + + self._sd = stream_to_vector_decimator(item_size=self._item_size, + sample_rate=sample_rate, + vec_rate=frame_rate, + vec_len=fft_size) + + if win is None: win = window.blackmanharris + fft_window = win(fft_size) + fft = self._fft_block[0](fft_size, True, fft_window) + window_power = sum(map(lambda x: x*x, fft_window)) + + c2magsq = gr.complex_to_mag_squared(fft_size) + self._avg = gr.single_pole_iir_filter_ff(1.0, fft_size) + self._log = gr.nlog10_ff(10, fft_size, + -20*math.log10(fft_size) # Adjust for number of bins + -10*math.log10(window_power/fft_size) # Adjust for windowing loss + -20*math.log10(ref_scale/2)) # Adjust for reference scale + self.connect(self, self._sd, fft, c2magsq, self._avg, self._log, self) + + self._average = average + self._avg_alpha = avg_alpha + self.set_avg_alpha(avg_alpha) + self.set_average(average) + + def set_decimation(self, decim): + """ + Set the decimation on stream decimator. + @param decim the new decimation + """ + self._sd.set_decimation(decim) + + def set_vec_rate(self, vec_rate): + """ + Set the vector rate on stream decimator. + @param vec_rate the new vector rate + """ + self._sd.set_vec_rate(vec_rate) + + def set_sample_rate(self, sample_rate): + """ + Set the new sampling rate + @param sample_rate the new rate + """ + self._sd.set_sample_rate(sample_rate) + + def set_average(self, average): + """ + Set the averaging filter on/off. + @param average true to set averaging on + """ + self._average = average + if self._average: + self._avg.set_taps(self._avg_alpha) + else: + self._avg.set_taps(1.0) + + def set_avg_alpha(self, avg_alpha): + """ + Set the average alpha and set the taps if average was on. + @param avg_alpha the new iir filter tap + """ + self._avg_alpha = avg_alpha + self.set_average(self._average) + + def sample_rate(self): + """ + Return the current sample rate. + """ + return self._sd.sample_rate() + + def decimation(self): + """ + Return the current decimation. + """ + return self._sd.decimation() + + def frame_rate(self): + """ + Return the current frame rate. + """ + return self._sd.frame_rate() + + def average(self): + """ + Return whether or not averaging is being performed. + """ + return self._average + + def avg_alpha(self): + """ + Return averaging filter constant. + """ + return self._avg_alpha + +class logpwrfft_f(_logpwrfft_base): + """ + Create an fft block chain, with real input. + """ + _name = "logpwrfft_f" + _item_size = gr.sizeof_float + _fft_block = (gr.fft_vfc, ) + +class logpwrfft_c(_logpwrfft_base): + """ + Create an fft block chain, with complex input. + """ + _name = "logpwrfft_c" + _item_size = gr.sizeof_gr_complex + _fft_block = (gr.fft_vcc, ) + diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/nbfm_rx.py b/gnuradio-core/src/python/gnuradio/blks2impl/nbfm_rx.py new file mode 100644 index 000000000..8bcb47ae1 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2impl/nbfm_rx.py @@ -0,0 +1,88 @@ +# +# 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. +# + +import math +from gnuradio import gr, optfir +from gnuradio.blks2impl.fm_emph import fm_deemph +#from gnuradio.blks2impl.standard_squelch import standard_squelch + +class nbfm_rx(gr.hier_block2): + def __init__(self, audio_rate, quad_rate, tau=75e-6, max_dev=5e3): + """ + Narrow Band FM Receiver. + + Takes a single complex baseband input stream and produces a single + float output stream of audio sample in the range [-1, +1]. + + @param audio_rate: sample rate of audio stream, >= 16k + @type audio_rate: integer + @param quad_rate: sample rate of output stream + @type quad_rate: integer + @param tau: preemphasis time constant (default 75e-6) + @type tau: float + @param max_dev: maximum deviation in Hz (default 5e3) + @type max_dev: float + + quad_rate must be an integer multiple of audio_rate. + + Exported sub-blocks (attributes): + squelch + quad_demod + deemph + audio_filter + """ + + gr.hier_block2.__init__(self, "nbfm_rx", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(1, 1, gr.sizeof_float)) # Output signature + + # FIXME audio_rate and quad_rate ought to be exact rationals + audio_rate = int(audio_rate) + quad_rate = int(quad_rate) + + if quad_rate % audio_rate != 0: + raise ValueError, "quad_rate is not an integer multiple of audio_rate" + + squelch_threshold = 20 # dB + #self.squelch = gr.simple_squelch_cc(squelch_threshold, 0.001) + + # FM Demodulator input: complex; output: float + k = quad_rate/(2*math.pi*max_dev) + self.quad_demod = gr.quadrature_demod_cf(k) + + # FM Deemphasis IIR filter + self.deemph = fm_deemph (quad_rate, tau=tau) + + # compute FIR taps for audio filter + audio_decim = quad_rate // audio_rate + audio_taps = gr.firdes.low_pass (1.0, # gain + quad_rate, # sampling rate + 2.7e3, # Audio LPF cutoff + 0.5e3, # Transition band + gr.firdes.WIN_HAMMING) # filter type + + print "len(audio_taps) =", len(audio_taps) + + # Decimating audio filter + # input: float; output: float; taps: float + self.audio_filter = gr.fir_filter_fff(audio_decim, audio_taps) + + self.connect(self, self.quad_demod, self.deemph, self.audio_filter, self) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/nbfm_tx.py b/gnuradio-core/src/python/gnuradio/blks2impl/nbfm_tx.py new file mode 100644 index 000000000..839cf6784 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2impl/nbfm_tx.py @@ -0,0 +1,92 @@ +# +# 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. +# + +import math +from gnuradio import gr, optfir +from gnuradio.blks2impl.fm_emph import fm_preemph + +#from gnuradio import ctcss + +class nbfm_tx(gr.hier_block2): + def __init__(self, audio_rate, quad_rate, tau=75e-6, max_dev=5e3): + """ + Narrow Band FM Transmitter. + + Takes a single float input stream of audio samples in the range [-1,+1] + and produces a single FM modulated complex baseband output. + + @param audio_rate: sample rate of audio stream, >= 16k + @type audio_rate: integer + @param quad_rate: sample rate of output stream + @type quad_rate: integer + @param tau: preemphasis time constant (default 75e-6) + @type tau: float + @param max_dev: maximum deviation in Hz (default 5e3) + @type max_dev: float + + quad_rate must be an integer multiple of audio_rate. + """ + + gr.hier_block2.__init__(self, "nbfm_tx", + gr.io_signature(1, 1, gr.sizeof_float), # Input signature + gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature + + # FIXME audio_rate and quad_rate ought to be exact rationals + audio_rate = int(audio_rate) + quad_rate = int(quad_rate) + + if quad_rate % audio_rate != 0: + raise ValueError, "quad_rate is not an integer multiple of audio_rate" + + + do_interp = audio_rate != quad_rate + + if do_interp: + interp_factor = quad_rate / audio_rate + interp_taps = optfir.low_pass (interp_factor, # gain + quad_rate, # Fs + 4500, # passband cutoff + 7000, # stopband cutoff + 0.1, # passband ripple dB + 40) # stopband atten dB + + #print "len(interp_taps) =", len(interp_taps) + self.interpolator = gr.interp_fir_filter_fff (interp_factor, interp_taps) + + self.preemph = fm_preemph (quad_rate, tau=tau) + + k = 2 * math.pi * max_dev / quad_rate + self.modulator = gr.frequency_modulator_fc (k) + + if do_interp: + self.connect (self, self.interpolator, self.preemph, self.modulator, self) + else: + self.connect(self, self.preemph, self.modulator, self) + + +class ctcss_gen_f(gr.hier_block2): + def __init__(self, sample_rate, tone_freq): + gr.hier_block2.__init__(self, "ctcss_gen_f", + gr.io_signature(0, 0, 0), # Input signature + gr.io_signature(1, 1, gr.sizeof_float)) # Output signature + + self.plgen = gr.sig_source_f(sample_rate, gr.GR_SIN_WAVE, tone_freq, 0.1, 0.0) + self.connect(self.plgen, self) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/pfb_arb_resampler.py b/gnuradio-core/src/python/gnuradio/blks2impl/pfb_arb_resampler.py new file mode 100644 index 000000000..e83c327fc --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2impl/pfb_arb_resampler.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python +# +# Copyright 2009 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, optfir + +class pfb_arb_resampler_ccf(gr.hier_block2): + ''' + Convenience wrapper for the polyphase filterbank arbitrary resampler. + + The block takes a single complex stream in and outputs a single complex + stream out. As such, it requires no extra glue to handle the input/output + streams. This block is provided to be consistent with the interface to the + other PFB block. + ''' + def __init__(self, rate, taps=None, flt_size=32, atten=100): + gr.hier_block2.__init__(self, "pfb_arb_resampler_ccf", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature + + self._rate = rate + self._size = flt_size + + if taps is not None: + self._taps = taps + else: + # Create a filter that covers the full bandwidth of the input signal + bw = 0.4 + tb = 0.2 + ripple = 0.1 + #self._taps = gr.firdes.low_pass_2(self._size, self._size, bw, tb, atten) + made = False + while not made: + try: + self._taps = optfir.low_pass(self._size, self._size, bw, bw+tb, ripple, atten) + made = True + except RuntimeError: + ripple += 0.01 + made = False + print("Warning: set ripple to %.4f dB. If this is a problem, adjust the attenuation or create your own filter taps." % (ripple)) + + # Build in an exit strategy; if we've come this far, it ain't working. + if(ripple >= 1.0): + raise RuntimeError("optfir could not generate an appropriate filter.") + + self.pfb = gr.pfb_arb_resampler_ccf(self._rate, self._taps, self._size) + #print "PFB has %d taps\n" % (len(self._taps),) + + self.connect(self, self.pfb) + self.connect(self.pfb, self) + + # Note -- set_taps not implemented in base class yet + def set_taps(self, taps): + self.pfb.set_taps(taps) + + def set_rate(self, rate): + self.pfb.set_rate(rate) + + +class pfb_arb_resampler_fff(gr.hier_block2): + ''' + Convenience wrapper for the polyphase filterbank arbitrary resampler. + + The block takes a single float stream in and outputs a single float + stream out. As such, it requires no extra glue to handle the input/output + streams. This block is provided to be consistent with the interface to the + other PFB block. + ''' + def __init__(self, rate, taps=None, flt_size=32, atten=100): + gr.hier_block2.__init__(self, "pfb_arb_resampler_fff", + gr.io_signature(1, 1, gr.sizeof_float), # Input signature + gr.io_signature(1, 1, gr.sizeof_float)) # Output signature + + self._rate = rate + self._size = flt_size + + if taps is not None: + self._taps = taps + else: + # Create a filter that covers the full bandwidth of the input signal + bw = 0.4 + tb = 0.2 + ripple = 0.1 + #self._taps = gr.firdes.low_pass_2(self._size, self._size, bw, tb, atten) + made = False + while not made: + try: + self._taps = optfir.low_pass(self._size, self._size, bw, bw+tb, ripple, atten) + made = True + except RuntimeError: + ripple += 0.01 + made = False + print("Warning: set ripple to %.4f dB. If this is a problem, adjust the attenuation or create your own filter taps." % (ripple)) + + # Build in an exit strategy; if we've come this far, it ain't working. + if(ripple >= 1.0): + raise RuntimeError("optfir could not generate an appropriate filter.") + + self.pfb = gr.pfb_arb_resampler_fff(self._rate, self._taps, self._size) + #print "PFB has %d taps\n" % (len(self._taps),) + + self.connect(self, self.pfb) + self.connect(self.pfb, self) + + # Note -- set_taps not implemented in base class yet + def set_taps(self, taps): + self.pfb.set_taps(taps) + + def set_rate(self, rate): + self.pfb.set_rate(rate) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/pfb_channelizer.py b/gnuradio-core/src/python/gnuradio/blks2impl/pfb_channelizer.py new file mode 100644 index 000000000..4bbe1bec6 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2impl/pfb_channelizer.py @@ -0,0 +1,73 @@ +#!/usr/bin/env python +# +# Copyright 2009,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, optfir + +class pfb_channelizer_ccf(gr.hier_block2): + ''' + Make a Polyphase Filter channelizer (complex in, complex out, floating-point taps) + + This simplifies the interface by allowing a single input stream to connect to this block. + It will then output a stream for each channel. + ''' + def __init__(self, numchans, taps=None, oversample_rate=1, atten=100): + gr.hier_block2.__init__(self, "pfb_channelizer_ccf", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(numchans, numchans, gr.sizeof_gr_complex)) # Output signature + + self._nchans = numchans + self._oversample_rate = oversample_rate + + if taps is not None: + self._taps = taps + else: + # Create a filter that covers the full bandwidth of the input signal + bw = 0.4 + tb = 0.2 + ripple = 0.1 + made = False + while not made: + try: + self._taps = optfir.low_pass(1, self._nchans, bw, bw+tb, ripple, atten) + made = True + except RuntimeError: + ripple += 0.01 + made = False + print("Warning: set ripple to %.4f dB. If this is a problem, adjust the attenuation or create your own filter taps." % (ripple)) + + # Build in an exit strategy; if we've come this far, it ain't working. + if(ripple >= 1.0): + raise RuntimeError("optfir could not generate an appropriate filter.") + + self.s2ss = gr.stream_to_streams(gr.sizeof_gr_complex, self._nchans) + self.pfb = gr.pfb_channelizer_ccf(self._nchans, self._taps, + self._oversample_rate) + self.connect(self, self.s2ss) + + for i in xrange(self._nchans): + self.connect((self.s2ss,i), (self.pfb,i)) + self.connect((self.pfb,i), (self,i)) + + def set_channel_map(self, newmap): + self.pfb.set_channel_map(newmap) + + diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/pfb_decimator.py b/gnuradio-core/src/python/gnuradio/blks2impl/pfb_decimator.py new file mode 100644 index 000000000..adcdfe9ba --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2impl/pfb_decimator.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# +# Copyright 2009 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, optfir + +class pfb_decimator_ccf(gr.hier_block2): + ''' + Make a Polyphase Filter decimator (complex in, complex out, floating-point taps) + + This simplifies the interface by allowing a single input stream to connect to this block. + It will then output a stream that is the decimated output stream. + ''' + def __init__(self, decim, taps=None, channel=0, atten=100): + gr.hier_block2.__init__(self, "pfb_decimator_ccf", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature + + self._decim = decim + self._channel = channel + + if taps is not None: + self._taps = taps + else: + # Create a filter that covers the full bandwidth of the input signal + bw = 0.4 + tb = 0.2 + ripple = 0.1 + made = False + while not made: + try: + self._taps = optfir.low_pass(1, self._decim, bw, bw+tb, ripple, atten) + made = True + except RuntimeError: + ripple += 0.01 + made = False + print("Warning: set ripple to %.4f dB. If this is a problem, adjust the attenuation or create your own filter taps." % (ripple)) + + # Build in an exit strategy; if we've come this far, it ain't working. + if(ripple >= 1.0): + raise RuntimeError("optfir could not generate an appropriate filter.") + + self.s2ss = gr.stream_to_streams(gr.sizeof_gr_complex, self._decim) + self.pfb = gr.pfb_decimator_ccf(self._decim, self._taps, self._channel) + + self.connect(self, self.s2ss) + + for i in xrange(self._decim): + self.connect((self.s2ss,i), (self.pfb,i)) + + self.connect(self.pfb, self) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/pfb_interpolator.py b/gnuradio-core/src/python/gnuradio/blks2impl/pfb_interpolator.py new file mode 100644 index 000000000..5492dfcac --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2impl/pfb_interpolator.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python +# +# Copyright 2009 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, optfir + +class pfb_interpolator_ccf(gr.hier_block2): + ''' + Make a Polyphase Filter interpolator (complex in, complex out, floating-point taps) + + The block takes a single complex stream in and outputs a single complex + stream out. As such, it requires no extra glue to handle the input/output + streams. This block is provided to be consistent with the interface to the + other PFB block. + ''' + def __init__(self, interp, taps=None, atten=100): + gr.hier_block2.__init__(self, "pfb_interpolator_ccf", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature + + self._interp = interp + self._taps = taps + + if taps is not None: + self._taps = taps + else: + # Create a filter that covers the full bandwidth of the input signal + bw = 0.4 + tb = 0.2 + ripple = 0.99 + made = False + while not made: + try: + self._taps = optfir.low_pass(self._interp, self._interp, bw, bw+tb, ripple, atten) + made = True + except RuntimeError: + ripple += 0.01 + made = False + print("Warning: set ripple to %.4f dB. If this is a problem, adjust the attenuation or create your own filter taps." % (ripple)) + + # Build in an exit strategy; if we've come this far, it ain't working. + if(ripple >= 1.0): + raise RuntimeError("optfir could not generate an appropriate filter.") + + self.pfb = gr.pfb_interpolator_ccf(self._interp, self._taps) + + self.connect(self, self.pfb) + self.connect(self.pfb, self) + + + + diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/rational_resampler.py b/gnuradio-core/src/python/gnuradio/blks2impl/rational_resampler.py new file mode 100644 index 000000000..eea12af95 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2impl/rational_resampler.py @@ -0,0 +1,131 @@ +# +# Copyright 2005,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. +# + +from gnuradio import gr, gru + +_plot = None + +def design_filter(interpolation, decimation, fractional_bw): + """ + Given the interpolation rate, decimation rate and a fractional bandwidth, + design a set of taps. + + @param interpolation: interpolation factor + @type interpolation: integer > 0 + @param decimation: decimation factor + @type decimation: integer > 0 + @param fractional_bw: fractional bandwidth in (0, 0.5) 0.4 works well. + @type fractional_bw: float + @returns: sequence of numbers + """ + + if fractional_bw >= 0.5 or fractional_bw <= 0: + raise ValueError, "Invalid fractional_bandwidth, must be in (0, 0.5)" + + beta = 5.0 + trans_width = 0.5 - fractional_bw + mid_transition_band = 0.5 - trans_width/2 + + taps = gr.firdes.low_pass(interpolation, # gain + 1, # Fs + mid_transition_band/interpolation, # trans mid point + trans_width/interpolation, # transition width + gr.firdes.WIN_KAISER, + beta # beta + ) + + return taps + + + +class _rational_resampler_base(gr.hier_block2): + """ + base class for all rational resampler variants. + """ + def __init__(self, resampler_base, + interpolation, decimation, taps=None, fractional_bw=None): + """ + Rational resampling polyphase FIR filter. + + Either taps or fractional_bw may be specified, but not both. + If neither is specified, a reasonable default, 0.4, is used as + the fractional_bw. + + @param interpolation: interpolation factor + @type interpolation: integer > 0 + @param decimation: decimation factor + @type decimation: integer > 0 + @param taps: optional filter coefficients + @type taps: sequence + @param fractional_bw: fractional bandwidth in (0, 0.5), measured at final freq (use 0.4) + @type fractional_bw: float + """ + + if not isinstance(interpolation, int) or interpolation < 1: + raise ValueError, "interpolation must be an integer >= 1" + + if not isinstance(decimation, int) or decimation < 1: + raise ValueError, "decimation must be an integer >= 1" + + if taps is None and fractional_bw is None: + fractional_bw = 0.4 + + d = gru.gcd(interpolation, decimation) + interpolation = interpolation // d + decimation = decimation // d + + if taps is None: + taps = design_filter(interpolation, decimation, fractional_bw) + + resampler = resampler_base(interpolation, decimation, taps) + gr.hier_block2.__init__(self, "rational_resampler", + gr.io_signature(1, 1, resampler.input_signature().sizeof_stream_item(0)), + gr.io_signature(1, 1, resampler.output_signature().sizeof_stream_item(0))) + + self.connect(self, resampler, self) + + +class rational_resampler_fff(_rational_resampler_base): + def __init__(self, interpolation, decimation, taps=None, fractional_bw=None): + """ + Rational resampling polyphase FIR filter with + float input, float output and float taps. + """ + _rational_resampler_base.__init__(self, gr.rational_resampler_base_fff, + interpolation, decimation, taps, fractional_bw) + +class rational_resampler_ccf(_rational_resampler_base): + def __init__(self, interpolation, decimation, taps=None, fractional_bw=None): + """ + Rational resampling polyphase FIR filter with + complex input, complex output and float taps. + """ + _rational_resampler_base.__init__(self, gr.rational_resampler_base_ccf, + interpolation, decimation, taps, fractional_bw) + +class rational_resampler_ccc(_rational_resampler_base): + def __init__(self, interpolation, decimation, taps=None, fractional_bw=None): + """ + Rational resampling polyphase FIR filter with + complex input, complex output and complex taps. + """ + _rational_resampler_base.__init__(self, gr.rational_resampler_base_ccc, + interpolation, decimation, taps, fractional_bw) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/standard_squelch.py b/gnuradio-core/src/python/gnuradio/blks2impl/standard_squelch.py new file mode 100644 index 000000000..bd7fb535a --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2impl/standard_squelch.py @@ -0,0 +1,76 @@ +# +# Copyright 2005,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. +# + +import math +from gnuradio import gr, optfir + +class standard_squelch(gr.hier_block2): + def __init__(self, audio_rate): + gr.hier_block2.__init__(self, "standard_squelch", + gr.io_signature(1, 1, gr.sizeof_float), # Input signature + gr.io_signature(1, 1, gr.sizeof_float)) # Output signature + + self.input_node = gr.add_const_ff(0) # FIXME kludge + + self.low_iir = gr.iir_filter_ffd((0.0193,0,-0.0193),(1,1.9524,-0.9615)) + self.low_square = gr.multiply_ff() + self.low_smooth = gr.single_pole_iir_filter_ff(1/(0.01*audio_rate)) # 100ms time constant + + self.hi_iir = gr.iir_filter_ffd((0.0193,0,-0.0193),(1,1.3597,-0.9615)) + self.hi_square = gr.multiply_ff() + self.hi_smooth = gr.single_pole_iir_filter_ff(1/(0.01*audio_rate)) + + self.sub = gr.sub_ff(); + self.add = gr.add_ff(); + self.gate = gr.threshold_ff(0.3,0.43,0) + self.squelch_lpf = gr.single_pole_iir_filter_ff(1/(0.01*audio_rate)) + + self.div = gr.divide_ff() + self.squelch_mult = gr.multiply_ff() + + self.connect (self, self.input_node) + self.connect (self.input_node, (self.squelch_mult, 0)) + + self.connect (self.input_node,self.low_iir) + self.connect (self.low_iir,(self.low_square,0)) + self.connect (self.low_iir,(self.low_square,1)) + self.connect (self.low_square,self.low_smooth,(self.sub,0)) + self.connect (self.low_smooth, (self.add,0)) + + self.connect (self.input_node,self.hi_iir) + self.connect (self.hi_iir,(self.hi_square,0)) + self.connect (self.hi_iir,(self.hi_square,1)) + self.connect (self.hi_square,self.hi_smooth,(self.sub,1)) + self.connect (self.hi_smooth, (self.add,1)) + + self.connect (self.sub, (self.div, 0)) + self.connect (self.add, (self.div, 1)) + self.connect (self.div, self.gate, self.squelch_lpf, (self.squelch_mult,1)) + self.connect (self.squelch_mult, self) + + def set_threshold(self, threshold): + self.gate.set_hi(threshold) + + def threshold(self): + return self.gate.hi() + + def squelch_range(self): + return (0.0, 1.0, 1.0/100) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/stream_to_vector_decimator.py b/gnuradio-core/src/python/gnuradio/blks2impl/stream_to_vector_decimator.py new file mode 100644 index 000000000..8f75729c9 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2impl/stream_to_vector_decimator.py @@ -0,0 +1,93 @@ +# +# 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. +# + +from gnuradio import gr + +class stream_to_vector_decimator(gr.hier_block2): + """ + Convert the stream to a vector, decimate the vector stream to achieve the vector rate. + """ + + def __init__(self, item_size, sample_rate, vec_rate, vec_len): + """ + Create the block chain. + @param item_size the number of bytes per sample + @param sample_rate the rate of incoming samples + @param vec_rate the rate of outgoing vectors (same units as sample_rate) + @param vec_len the length of the outgoing vectors in items + """ + self._vec_rate = vec_rate + self._vec_len = vec_len + self._sample_rate = sample_rate + + gr.hier_block2.__init__(self, "stream_to_vector_decimator", + gr.io_signature(1, 1, item_size), # Input signature + gr.io_signature(1, 1, item_size*vec_len)) # Output signature + + s2v = gr.stream_to_vector(item_size, vec_len) + self.one_in_n = gr.keep_one_in_n(item_size*vec_len, 1) + self._update_decimator() + self.connect(self, s2v, self.one_in_n, self) + + def set_sample_rate(self, sample_rate): + """ + Set the new sampling rate and update the decimator. + @param sample_rate the new rate + """ + self._sample_rate = sample_rate + self._update_decimator() + + def set_vec_rate(self, vec_rate): + """ + Set the new vector rate and update the decimator. + @param vec_rate the new rate + """ + self._vec_rate = vec_rate + self._update_decimator() + + def set_decimation(self, decim): + """ + Set the decimation parameter directly. + @param decim the new decimation + """ + self._decim = max(1, int(round(decim))) + self.one_in_n.set_n(self._decim) + + def _update_decimator(self): + self.set_decimation(self._sample_rate/self._vec_len/self._vec_rate) + + def decimation(self): + """ + Returns the actual decimation. + """ + return self._decim + + def sample_rate(self): + """ + Returns configured sample rate. + """ + return self._sample_rate + + def frame_rate(self): + """ + Returns actual frame rate + """ + return self._sample_rate/self._vec_len/self._decim diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/wfm_rcv.py b/gnuradio-core/src/python/gnuradio/blks2impl/wfm_rcv.py new file mode 100644 index 000000000..d1cbcf912 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2impl/wfm_rcv.py @@ -0,0 +1,69 @@ +# +# Copyright 2005,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. +# + +from gnuradio import gr +from gnuradio.blks2impl.fm_emph import fm_deemph +import math + +class wfm_rcv(gr.hier_block2): + def __init__ (self, quad_rate, audio_decimation): + """ + Hierarchical block for demodulating a broadcast FM signal. + + The input is the downconverted complex baseband signal (gr_complex). + The output is the demodulated audio (float). + + @param quad_rate: input sample rate of complex baseband input. + @type quad_rate: float + @param audio_decimation: how much to decimate quad_rate to get to audio. + @type audio_decimation: integer + """ + gr.hier_block2.__init__(self, "wfm_rcv", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(1, 1, gr.sizeof_float)) # Output signature + + volume = 20. + + max_dev = 75e3 + fm_demod_gain = quad_rate/(2*math.pi*max_dev) + audio_rate = quad_rate / audio_decimation + + + # We assign to self so that outsiders can grab the demodulator + # if they need to. E.g., to plot its output. + # + # input: complex; output: float + self.fm_demod = gr.quadrature_demod_cf (fm_demod_gain) + + # input: float; output: float + self.deemph = fm_deemph (audio_rate) + + # compute FIR filter taps for audio filter + width_of_transition_band = audio_rate / 32 + audio_coeffs = gr.firdes.low_pass (1.0, # gain + quad_rate, # sampling rate + audio_rate/2 - width_of_transition_band, + width_of_transition_band, + gr.firdes.WIN_HAMMING) + # input: float; output: float + self.audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs) + + self.connect (self, self.fm_demod, self.audio_filter, self.deemph, self) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/wfm_rcv_fmdet.py b/gnuradio-core/src/python/gnuradio/blks2impl/wfm_rcv_fmdet.py new file mode 100755 index 000000000..e229bcc2e --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2impl/wfm_rcv_fmdet.py @@ -0,0 +1,216 @@ +# +# 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. +# + +from gnuradio import gr +from gnuradio.blks2impl.fm_emph import fm_deemph +import math + +class wfm_rcv_fmdet(gr.hier_block2): + def __init__ (self, demod_rate, audio_decimation): + """ + Hierarchical block for demodulating a broadcast FM signal. + + The input is the downconverted complex baseband signal + (gr_complex). The output is two streams of the demodulated + audio (float) 0=Left, 1=Right. + + @param demod_rate: input sample rate of complex baseband input. + @type demod_rate: float + @param audio_decimation: how much to decimate demod_rate to get to audio. + @type audio_decimation: integer + """ + gr.hier_block2.__init__(self, "wfm_rcv_fmdet", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(2, 2, gr.sizeof_float)) # Output signature + lowfreq = -125e3/demod_rate + highfreq = 125e3/demod_rate + audio_rate = demod_rate / audio_decimation + + # We assign to self so that outsiders can grab the demodulator + # if they need to. E.g., to plot its output. + # + # input: complex; output: float + + self.fm_demod = gr.fmdet_cf (demod_rate, lowfreq, highfreq, 0.05) + + # input: float; output: float + self.deemph_Left = fm_deemph (audio_rate) + self.deemph_Right = fm_deemph (audio_rate) + + # compute FIR filter taps for audio filter + width_of_transition_band = audio_rate / 32 + audio_coeffs = gr.firdes.low_pass (1.0 , # gain + demod_rate, # sampling rate + 15000 , + width_of_transition_band, + gr.firdes.WIN_HAMMING) + + # input: float; output: float + self.audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs) + if 1: + # Pick off the stereo carrier/2 with this filter. It + # attenuated 10 dB so apply 10 dB gain We pick off the + # negative frequency half because we want to base band by + # it! + ## NOTE THIS WAS HACKED TO OFFSET INSERTION LOSS DUE TO + ## DEEMPHASIS + + stereo_carrier_filter_coeffs = gr.firdes.complex_band_pass(10.0, + demod_rate, + -19020, + -18980, + width_of_transition_band, + gr.firdes.WIN_HAMMING) + + #print "len stereo carrier filter = ",len(stereo_carrier_filter_coeffs) + #print "stereo carrier filter ", stereo_carrier_filter_coeffs + #print "width of transition band = ",width_of_transition_band, " audio rate = ", audio_rate + + # Pick off the double side band suppressed carrier + # Left-Right audio. It is attenuated 10 dB so apply 10 dB + # gain + + stereo_dsbsc_filter_coeffs = gr.firdes.complex_band_pass(20.0, + demod_rate, + 38000-15000/2, + 38000+15000/2, + width_of_transition_band, + gr.firdes.WIN_HAMMING) + #print "len stereo dsbsc filter = ",len(stereo_dsbsc_filter_coeffs) + #print "stereo dsbsc filter ", stereo_dsbsc_filter_coeffs + + # construct overlap add filter system from coefficients + # for stereo carrier + self.stereo_carrier_filter = gr.fir_filter_fcc(audio_decimation, + stereo_carrier_filter_coeffs) + + # carrier is twice the picked off carrier so arrange to do + # a commplex multiply + self.stereo_carrier_generator = gr.multiply_cc(); + + # Pick off the rds signal + stereo_rds_filter_coeffs = gr.firdes.complex_band_pass(30.0, + demod_rate, + 57000 - 1500, + 57000 + 1500, + width_of_transition_band, + gr.firdes.WIN_HAMMING) + #print "len stereo dsbsc filter = ",len(stereo_dsbsc_filter_coeffs) + #print "stereo dsbsc filter ", stereo_dsbsc_filter_coeffs + # construct overlap add filter system from coefficients for stereo carrier + + self.rds_signal_filter = gr.fir_filter_fcc(audio_decimation, + stereo_rds_filter_coeffs) + self.rds_carrier_generator = gr.multiply_cc(); + self.rds_signal_generator = gr.multiply_cc(); + self_rds_signal_processor = gr.null_sink(gr.sizeof_gr_complex); + + loop_bw = 2*math.pi/100.0 + max_freq = -2.0*math.pi*18990/audio_rate; + min_freq = -2.0*math.pi*19010/audio_rate; + self.stereo_carrier_pll_recovery = gr.pll_refout_cc(loop_bw, + max_freq, + min_freq); + + #self.stereo_carrier_pll_recovery.squelch_enable(False) + ##pll_refout does not have squelch yet, so disabled for + #now + + # set up mixer (multiplier) to get the L-R signal at + # baseband + + self.stereo_basebander = gr.multiply_cc(); + + # pick off the real component of the basebanded L-R + # signal. The imaginary SHOULD be zero + + self.LmR_real = gr.complex_to_real(); + self.Make_Left = gr.add_ff(); + self.Make_Right = gr.sub_ff(); + + self.stereo_dsbsc_filter = gr.fir_filter_fcc(audio_decimation, + stereo_dsbsc_filter_coeffs) + + + if 1: + + # send the real signal to complex filter to pick off the + # carrier and then to one side of a multiplier + self.connect (self, self.fm_demod, self.stereo_carrier_filter, + self.stereo_carrier_pll_recovery, + (self.stereo_carrier_generator,0)) + + # send the already filtered carrier to the otherside of the carrier + # the resulting signal from this multiplier is the carrier + # with correct phase but at -38000 Hz. + self.connect (self.stereo_carrier_pll_recovery, (self.stereo_carrier_generator,1)) + + # send the new carrier to one side of the mixer (multiplier) + self.connect (self.stereo_carrier_generator, (self.stereo_basebander,0)) + + # send the demphasized audio to the DSBSC pick off filter, the complex + # DSBSC signal at +38000 Hz is sent to the other side of the mixer/multiplier + # the result is BASEBANDED DSBSC with phase zero! + self.connect (self.fm_demod,self.stereo_dsbsc_filter, (self.stereo_basebander,1)) + + # Pick off the real part since the imaginary is + # theoretically zero and then to one side of a summer + self.connect (self.stereo_basebander, self.LmR_real, (self.Make_Left,0)) + + #take the same real part of the DSBSC baseband signal and + #send it to negative side of a subtracter + self.connect (self.LmR_real,(self.Make_Right,1)) + + # Make rds carrier by taking the squared pilot tone and + # multiplying by pilot tone + self.connect (self.stereo_basebander,(self.rds_carrier_generator,0)) + self.connect (self.stereo_carrier_pll_recovery,(self.rds_carrier_generator,1)) + + # take signal, filter off rds, send into mixer 0 channel + self.connect (self.fm_demod,self.rds_signal_filter,(self.rds_signal_generator,0)) + + # take rds_carrier_generator output and send into mixer 1 + # channel + self.connect (self.rds_carrier_generator,(self.rds_signal_generator,1)) + + # send basebanded rds signal and send into "processor" + # which for now is a null sink + self.connect (self.rds_signal_generator,self_rds_signal_processor) + + + if 1: + # pick off the audio, L+R that is what we used to have and + # send it to the summer + self.connect(self.fm_demod, self.audio_filter, (self.Make_Left, 1)) + + # take the picked off L+R audio and send it to the PLUS + # side of the subtractor + self.connect(self.audio_filter,(self.Make_Right, 0)) + + # The result of Make_Left gets (L+R) + (L-R) and results in 2*L + # The result of Make_Right gets (L+R) - (L-R) and results in 2*R + self.connect(self.Make_Left , self.deemph_Left, (self, 0)) + self.connect(self.Make_Right, self.deemph_Right, (self, 1)) + + # NOTE: mono support will require variable number of outputs in hier_block2s + # See ticket:174 in Trac database + #else: + # self.connect (self.fm_demod, self.audio_filter, self) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/wfm_rcv_pll.py b/gnuradio-core/src/python/gnuradio/blks2impl/wfm_rcv_pll.py new file mode 100644 index 000000000..d4ce6d223 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2impl/wfm_rcv_pll.py @@ -0,0 +1,190 @@ +# +# 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. +# + +from gnuradio import gr +from gnuradio.blks2impl.fm_emph import fm_deemph +import math + +class wfm_rcv_pll(gr.hier_block2): + def __init__ (self, demod_rate, audio_decimation): + """ + Hierarchical block for demodulating a broadcast FM signal. + + The input is the downconverted complex baseband signal (gr_complex). + The output is two streams of the demodulated audio (float) 0=Left, 1=Right. + + @param demod_rate: input sample rate of complex baseband input. + @type demod_rate: float + @param audio_decimation: how much to decimate demod_rate to get to audio. + @type audio_decimation: integer + """ + gr.hier_block2.__init__(self, "wfm_rcv_pll", + gr.io_signature(1, 1, gr.sizeof_gr_complex), # Input signature + gr.io_signature(2, 2, gr.sizeof_float)) # Output signature + bandwidth = 250e3 + audio_rate = demod_rate / audio_decimation + + + # We assign to self so that outsiders can grab the demodulator + # if they need to. E.g., to plot its output. + # + # input: complex; output: float + loop_bw = 2*math.pi/100.0 + max_freq = 2.0*math.pi*90e3/demod_rate + self.fm_demod = gr.pll_freqdet_cf (loop_bw, max_freq,-max_freq) + + # input: float; output: float + self.deemph_Left = fm_deemph (audio_rate) + self.deemph_Right = fm_deemph (audio_rate) + + # compute FIR filter taps for audio filter + width_of_transition_band = audio_rate / 32 + audio_coeffs = gr.firdes.low_pass (1.0 , # gain + demod_rate, # sampling rate + 15000 , + width_of_transition_band, + gr.firdes.WIN_HAMMING) + # input: float; output: float + self.audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs) + if 1: + # Pick off the stereo carrier/2 with this filter. It attenuated 10 dB so apply 10 dB gain + # We pick off the negative frequency half because we want to base band by it! + ## NOTE THIS WAS HACKED TO OFFSET INSERTION LOSS DUE TO DEEMPHASIS + + stereo_carrier_filter_coeffs = gr.firdes.complex_band_pass(10.0, + demod_rate, + -19020, + -18980, + width_of_transition_band, + gr.firdes.WIN_HAMMING) + + #print "len stereo carrier filter = ",len(stereo_carrier_filter_coeffs) + #print "stereo carrier filter ", stereo_carrier_filter_coeffs + #print "width of transition band = ",width_of_transition_band, " audio rate = ", audio_rate + + # Pick off the double side band suppressed carrier Left-Right audio. It is attenuated 10 dB so apply 10 dB gain + + stereo_dsbsc_filter_coeffs = gr.firdes.complex_band_pass(20.0, + demod_rate, + 38000-15000/2, + 38000+15000/2, + width_of_transition_band, + gr.firdes.WIN_HAMMING) + #print "len stereo dsbsc filter = ",len(stereo_dsbsc_filter_coeffs) + #print "stereo dsbsc filter ", stereo_dsbsc_filter_coeffs + # construct overlap add filter system from coefficients for stereo carrier + + self.stereo_carrier_filter = gr.fir_filter_fcc(audio_decimation, stereo_carrier_filter_coeffs) + + # carrier is twice the picked off carrier so arrange to do a commplex multiply + + self.stereo_carrier_generator = gr.multiply_cc(); + + # Pick off the rds signal + + stereo_rds_filter_coeffs = gr.firdes.complex_band_pass(30.0, + demod_rate, + 57000 - 1500, + 57000 + 1500, + width_of_transition_band, + gr.firdes.WIN_HAMMING) + #print "len stereo dsbsc filter = ",len(stereo_dsbsc_filter_coeffs) + #print "stereo dsbsc filter ", stereo_dsbsc_filter_coeffs + # construct overlap add filter system from coefficients for stereo carrier + + self.rds_signal_filter = gr.fir_filter_fcc(audio_decimation, stereo_rds_filter_coeffs) + + + + + + + self.rds_carrier_generator = gr.multiply_cc(); + self.rds_signal_generator = gr.multiply_cc(); + self_rds_signal_processor = gr.null_sink(gr.sizeof_gr_complex); + + + + loop_bw = 2*math.pi/100.0 + max_freq = -2.0*math.pi*18990/audio_rate; + min_freq = -2.0*math.pi*19010/audio_rate; + + self.stereo_carrier_pll_recovery = gr.pll_refout_cc(loop_bw, max_freq, min_freq); + #self.stereo_carrier_pll_recovery.squelch_enable(False) #pll_refout does not have squelch yet, so disabled for now + + + # set up mixer (multiplier) to get the L-R signal at baseband + + self.stereo_basebander = gr.multiply_cc(); + + # pick off the real component of the basebanded L-R signal. The imaginary SHOULD be zero + + self.LmR_real = gr.complex_to_real(); + self.Make_Left = gr.add_ff(); + self.Make_Right = gr.sub_ff(); + + self.stereo_dsbsc_filter = gr.fir_filter_fcc(audio_decimation, stereo_dsbsc_filter_coeffs) + + + if 1: + + # send the real signal to complex filter to pick off the carrier and then to one side of a multiplier + self.connect (self, self.fm_demod,self.stereo_carrier_filter,self.stereo_carrier_pll_recovery, (self.stereo_carrier_generator,0)) + # send the already filtered carrier to the otherside of the carrier + self.connect (self.stereo_carrier_pll_recovery, (self.stereo_carrier_generator,1)) + # the resulting signal from this multiplier is the carrier with correct phase but at -38000 Hz. + + # send the new carrier to one side of the mixer (multiplier) + self.connect (self.stereo_carrier_generator, (self.stereo_basebander,0)) + # send the demphasized audio to the DSBSC pick off filter, the complex + # DSBSC signal at +38000 Hz is sent to the other side of the mixer/multiplier + self.connect (self.fm_demod,self.stereo_dsbsc_filter, (self.stereo_basebander,1)) + # the result is BASEBANDED DSBSC with phase zero! + + # Pick off the real part since the imaginary is theoretically zero and then to one side of a summer + self.connect (self.stereo_basebander, self.LmR_real, (self.Make_Left,0)) + #take the same real part of the DSBSC baseband signal and send it to negative side of a subtracter + self.connect (self.LmR_real,(self.Make_Right,1)) + + # Make rds carrier by taking the squared pilot tone and multiplying by pilot tone + self.connect (self.stereo_basebander,(self.rds_carrier_generator,0)) + self.connect (self.stereo_carrier_pll_recovery,(self.rds_carrier_generator,1)) + # take signal, filter off rds, send into mixer 0 channel + self.connect (self.fm_demod,self.rds_signal_filter,(self.rds_signal_generator,0)) + # take rds_carrier_generator output and send into mixer 1 channel + self.connect (self.rds_carrier_generator,(self.rds_signal_generator,1)) + # send basebanded rds signal and send into "processor" which for now is a null sink + self.connect (self.rds_signal_generator,self_rds_signal_processor) + + + if 1: + # pick off the audio, L+R that is what we used to have and send it to the summer + self.connect(self.fm_demod, self.audio_filter, (self.Make_Left, 1)) + # take the picked off L+R audio and send it to the PLUS side of the subtractor + self.connect(self.audio_filter,(self.Make_Right, 0)) + # The result of Make_Left gets (L+R) + (L-R) and results in 2*L + # The result of Make_Right gets (L+R) - (L-R) and results in 2*R + self.connect(self.Make_Left , self.deemph_Left, (self, 0)) + self.connect(self.Make_Right, self.deemph_Right, (self, 1)) + # NOTE: mono support will require variable number of outputs in hier_block2s + # See ticket:174 in Trac database + #else: + # self.connect (self.fm_demod, self.audio_filter, self) diff --git a/gnuradio-core/src/python/gnuradio/blks2impl/wfm_tx.py b/gnuradio-core/src/python/gnuradio/blks2impl/wfm_tx.py new file mode 100644 index 000000000..3fcf98f89 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks2impl/wfm_tx.py @@ -0,0 +1,79 @@ +# +# Copyright 2005,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. +# + +import math +from gnuradio import gr, optfir +from gnuradio.blks2impl.fm_emph import fm_preemph + +class wfm_tx(gr.hier_block2): + def __init__(self, audio_rate, quad_rate, tau=75e-6, max_dev=75e3): + """ + Wide Band FM Transmitter. + + Takes a single float input stream of audio samples in the range [-1,+1] + and produces a single FM modulated complex baseband output. + + @param audio_rate: sample rate of audio stream, >= 16k + @type audio_rate: integer + @param quad_rate: sample rate of output stream + @type quad_rate: integer + @param tau: preemphasis time constant (default 75e-6) + @type tau: float + @param max_dev: maximum deviation in Hz (default 75e3) + @type max_dev: float + + quad_rate must be an integer multiple of audio_rate. + """ + gr.hier_block2.__init__(self, "wfm_tx", + gr.io_signature(1, 1, gr.sizeof_float), # Input signature + gr.io_signature(1, 1, gr.sizeof_gr_complex)) # Output signature + + # FIXME audio_rate and quad_rate ought to be exact rationals + audio_rate = int(audio_rate) + quad_rate = int(quad_rate) + + if quad_rate % audio_rate != 0: + raise ValueError, "quad_rate is not an integer multiple of audio_rate" + + + do_interp = audio_rate != quad_rate + + if do_interp: + interp_factor = quad_rate / audio_rate + interp_taps = optfir.low_pass (interp_factor, # gain + quad_rate, # Fs + 16000, # passband cutoff + 18000, # stopband cutoff + 0.1, # passband ripple dB + 40) # stopband atten dB + + print "len(interp_taps) =", len(interp_taps) + self.interpolator = gr.interp_fir_filter_fff (interp_factor, interp_taps) + + self.preemph = fm_preemph (quad_rate, tau=tau) + + k = 2 * math.pi * max_dev / quad_rate + self.modulator = gr.frequency_modulator_fc (k) + + if do_interp: + self.connect (self, self.interpolator, self.preemph, self.modulator, self) + else: + self.connect(self, self.preemph, self.modulator, self) diff --git a/gnuradio-core/src/python/gnuradio/eng_notation.py b/gnuradio-core/src/python/gnuradio/eng_notation.py new file mode 100644 index 000000000..c552a45f5 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/eng_notation.py @@ -0,0 +1,71 @@ +# +# Copyright 2003 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. +# + +scale_factor = {} +scale_factor['E'] = 1e18 +scale_factor['P'] = 1e15 +scale_factor['T'] = 1e12 +scale_factor['G'] = 1e9 +scale_factor['M'] = 1e6 +scale_factor['k'] = 1e3 +scale_factor['m'] = 1e-3 +scale_factor['u'] = 1e-6 +scale_factor['n'] = 1e-9 +scale_factor['p'] = 1e-12 +scale_factor['f'] = 1e-15 +scale_factor['a'] = 1e-18 + +def num_to_str (n): + '''Convert a number to a string in engineering notation. E.g., 5e-9 -> 5n''' + m = abs(n) + if m >= 1e9: + return "%gG" % (n * 1e-9) + elif m >= 1e6: + return "%gM" % (n * 1e-6) + elif m >= 1e3: + return "%gk" % (n * 1e-3) + elif m >= 1: + return "%g" % (n) + elif m >= 1e-3: + return "%gm" % (n * 1e3) + elif m >= 1e-6: + return "%gu" % (n * 1e6) # where's that mu when you need it (unicode?) + elif m >= 1e-9: + return "%gn" % (n * 1e9) + elif m >= 1e-12: + return "%gp" % (n * 1e12) + elif m >= 1e-15: + return "%gf" % (n * 1e15) + else: + return "%g" % (n) + + +def str_to_num (value): + '''Convert a string in engineering notation to a number. E.g., '15m' -> 15e-3''' + try: + scale = 1.0 + suffix = value[-1] + if scale_factor.has_key (suffix): + return float (value[0:-1]) * scale_factor[suffix] + return float (value) + except: + raise RuntimeError ( + "Invalid engineering notation value: %r" % (value,)) diff --git a/gnuradio-core/src/python/gnuradio/eng_option.py b/gnuradio-core/src/python/gnuradio/eng_option.py new file mode 100644 index 000000000..02e9b0b6d --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/eng_option.py @@ -0,0 +1,62 @@ +# +# 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. +# + +'''Add support for engineering notation to optparse.OptionParser''' + +from copy import copy +from optparse import Option, OptionValueError +import eng_notation + +def check_eng_float (option, opt, value): + try: + return eng_notation.str_to_num(value) + except: + raise OptionValueError ( + "option %s: invalid engineering notation value: %r" % (opt, value)) + +def check_intx (option, opt, value): + try: + return int (value, 0) + except: + raise OptionValueError ( + "option %s: invalid integer value: %r" % (opt, value)) + +def check_subdev (option, opt, value): + """ + Value has the form: (A|B)(:0|1)? + + @returns a 2-tuple (0|1, 0|1) + """ + d = { 'A' : (0, 0), 'A:0' : (0, 0), 'A:1' : (0, 1), 'A:2' : (0, 2), + 'B' : (1, 0), 'B:0' : (1, 0), 'B:1' : (1, 1), 'B:2' : (1, 2) } + try: + return d[value.upper()] + except: + raise OptionValueError( + "option %s: invalid subdev: '%r', must be one of %s" % (opt, value, ', '.join(sorted(d.keys())))) + +class eng_option (Option): + TYPES = Option.TYPES + ("eng_float", "intx", "subdev") + TYPE_CHECKER = copy (Option.TYPE_CHECKER) + TYPE_CHECKER["eng_float"] = check_eng_float + TYPE_CHECKER["intx"] = check_intx + TYPE_CHECKER["subdev"] = check_subdev + diff --git a/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt b/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt new file mode 100644 index 000000000..da22a5f98 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/CMakeLists.txt @@ -0,0 +1,49 @@ +# Copyright 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. + +######################################################################## +include(GrPython) + +GR_PYTHON_INSTALL(FILES + __init__.py + exceptions.py + gateway.py + gr_threading.py + gr_threading_23.py + gr_threading_24.py + hier_block2.py + prefs.py + tag_utils.py + top_block.py + pubsub.py + DESTINATION ${GR_PYTHON_DIR}/gnuradio/gr + COMPONENT "core_python" +) + +######################################################################## +# Handle the unit tests +######################################################################## +if(ENABLE_TESTING) +include(GrTest) +file(GLOB py_qa_test_files "qa_*.py") +foreach(py_qa_test_file ${py_qa_test_files}) + get_filename_component(py_qa_test_name ${py_qa_test_file} NAME_WE) + GR_ADD_TEST(${py_qa_test_name} ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} ${py_qa_test_file}) +endforeach(py_qa_test_file) +endif(ENABLE_TESTING) diff --git a/gnuradio-core/src/python/gnuradio/gr/__init__.py b/gnuradio-core/src/python/gnuradio/gr/__init__.py new file mode 100644 index 000000000..768d88595 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/__init__.py @@ -0,0 +1,116 @@ +# +# Copyright 2003-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. +# + +# The presence of this file turns this directory into a Python package + +# This is the main GNU Radio python module. +# We pull the swig output and the other modules into the gnuradio.gr namespace + +from gnuradio_core import * +from exceptions import * +#from hier_block2 import * +#from top_block import * +from gateway import basic_block, sync_block, decim_block, interp_block +from tag_utils import tag_to_python, tag_to_pmt + +import gras + +RT_OK = 0 +RT_NOT_IMPLEMENTED = 1 +RT_NO_PRIVS = 2 +RT_OTHER_ERROR = 3 + + +def enable_realtime_scheduling(): + """ + This call is for backward compat purposes. + See gras/thread_pool.hpp for greater options. + """ + + #any prio greater than 0 means realtime scheduling + prio_value = 0.5 + + #test that prio + if not gras.ThreadPool.test_thread_priority(prio_value): + return RT_NO_PRIVS + + #create a new thread pool with thread priority set + config = gras.ThreadPoolConfig() + config.thread_priority = prio_value + tp = gras.ThreadPool(config) + tp.set_active() + + return RT_OK + +class top_block(gras.TopBlock): + def __init__(self, name="Top"): + gras.TopBlock.__init__(self, name) + + def lock(self): + pass + + def unlock(self): + self.commit() + + def start(self, *args): + if args: self.global_config().maximum_output_items = args[0] + gras.TopBlock.start(self) + + def run(self, *args): + if args: self.global_config().maximum_output_items = args[0] + gras.TopBlock.run(self) + +class hier_block2(gras.HierBlock): + def __init__(self, name="Hier", in_sig=None, out_sig=None): + gras.HierBlock.__init__(self, name) + + self.__in_sig = in_sig + self.__out_sig = out_sig + + #backwards compatible silliness + import weakref + self._hb = weakref.proxy(self) + + def lock(self): + pass + + def unlock(self): + self.commit() + + def input_signature(self): return self.__in_sig + def output_signature(self): return self.__out_sig + +# create a couple of aliases +serial_to_parallel = stream_to_vector +parallel_to_serial = vector_to_stream + +# Force the preference database to be initialized +prefs = gr_prefs.singleton + +#alias old gr_add_vXX and gr_multiply_vXX +add_vcc = add_cc +add_vff = add_ff +add_vii = add_ii +add_vss = add_ss +multiply_vcc = multiply_cc +multiply_vff = multiply_ff +multiply_vii = multiply_ii +multiply_vss = multiply_ss diff --git a/gnuradio-core/src/python/gnuradio/gr/benchmark_filters.py b/gnuradio-core/src/python/gnuradio/gr/benchmark_filters.py new file mode 100755 index 000000000..4fc10b721 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/benchmark_filters.py @@ -0,0 +1,75 @@ +#!/usr/bin/env python +# +# Copyright 2005,2006,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. +# + +import time +import random +from optparse import OptionParser +from gnuradio import gr +from gnuradio.eng_option import eng_option + +def make_random_complex_tuple(L): + result = [] + for x in range(L): + result.append(complex(random.uniform(-1000,1000), + random.uniform(-1000,1000))) + return tuple(result) + +def benchmark(name, creator, dec, ntaps, total_test_size, block_size): + block_size = 32768 + + tb = gr.top_block() + taps = make_random_complex_tuple(ntaps) + src = gr.vector_source_c(make_random_complex_tuple(block_size), True) + head = gr.head(gr.sizeof_gr_complex, int(total_test_size)) + op = creator(dec, taps) + dst = gr.null_sink(gr.sizeof_gr_complex) + tb.connect(src, head, op, dst) + start = time.time() + tb.run() + stop = time.time() + delta = stop - start + print "%16s: taps: %4d input: %4g, time: %6.3f taps/sec: %10.4g" % ( + name, ntaps, total_test_size, delta, ntaps*total_test_size/delta) + +def main(): + parser = OptionParser(option_class=eng_option) + parser.add_option("-n", "--ntaps", type="int", default=256) + parser.add_option("-t", "--total-input-size", type="eng_float", default=40e6) + parser.add_option("-b", "--block-size", type="intx", default=50000) + parser.add_option("-d", "--decimation", type="int", default=1) + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + sys.exit(1) + + ntaps = options.ntaps + total_input_size = options.total_input_size + block_size = options.block_size + dec = options.decimation + + benchmark("gr.fir_filter_ccc", gr.fir_filter_ccc, + dec, ntaps, total_input_size, block_size) + benchmark("gr.fft_filter_ccc", gr.fft_filter_ccc, + dec, ntaps, total_input_size, block_size) + +if __name__ == '__main__': + main() diff --git a/gnuradio-core/src/python/gnuradio/gr/exceptions.py b/gnuradio-core/src/python/gnuradio/gr/exceptions.py new file mode 100644 index 000000000..dba04750b --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/exceptions.py @@ -0,0 +1,27 @@ +# +# 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. + +class NotDAG (Exception): + """Not a directed acyclic graph""" + pass + +class CantHappen (Exception): + """Can't happen""" + pass diff --git a/gnuradio-core/src/python/gnuradio/gr/gateway.py b/gnuradio-core/src/python/gnuradio/gr/gateway.py new file mode 100644 index 000000000..53fda17a4 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/gateway.py @@ -0,0 +1,246 @@ +# +# 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. +# + +import gnuradio_core as gr_core +from gnuradio_core import io_signature, io_signaturev +from gnuradio_core import gr_block_gw_message_type +from gnuradio_core import block_gateway +import numpy + +######################################################################## +# Magic to turn pointers into numpy arrays +# http://docs.scipy.org/doc/numpy/reference/arrays.interface.html +######################################################################## +def pointer_to_ndarray(addr, dtype, nitems): + class array_like: + __array_interface__ = { + 'data' : (int(addr), False), + 'typestr' : dtype.base.str, + 'descr' : dtype.base.descr, + 'shape' : (nitems,) + dtype.shape, + 'strides' : None, + 'version' : 3 + } + return numpy.asarray(array_like()).view(dtype.base) + +######################################################################## +# Handler that does callbacks from C++ +######################################################################## +class gateway_handler(gr_core.feval_ll): + + #dont put a constructor, it wont work + + def init(self, callback): + self._callback = callback + + def eval(self, arg): + try: self._callback() + except Exception as ex: + print("handler caught exception: %s"%ex) + import traceback; traceback.print_exc() + raise ex + return 0 + +######################################################################## +# Handler that does callbacks from C++ +######################################################################## +class msg_handler(gr_core.feval_p): + + #dont put a constructor, it wont work + + def init(self, callback): + self._callback = callback + + def eval(self, arg): + try: self._callback(arg) + except Exception as ex: + print("handler caught exception: %s"%ex) + import traceback; traceback.print_exc() + raise ex + return 0 + +######################################################################## +# The guts that make this into a gr block +######################################################################## +class gateway_block(object): + + def __init__(self, name, in_sig, out_sig, work_type, factor): + + #ensure that the sigs are iterable dtypes + def sig_to_dtype_sig(sig): + if sig is None: sig = () + return map(numpy.dtype, sig) + self.__in_sig = sig_to_dtype_sig(in_sig) + self.__out_sig = sig_to_dtype_sig(out_sig) + + #cache the ranges to iterate when dispatching work + self.__in_indexes = range(len(self.__in_sig)) + self.__out_indexes = range(len(self.__out_sig)) + + #convert the signatures into gr.io_signatures + def sig_to_gr_io_sigv(sig): + if not len(sig): return io_signature(0, 0, 0) + return io_signaturev(len(sig), len(sig), [s.itemsize for s in sig]) + gr_in_sig = sig_to_gr_io_sigv(self.__in_sig) + gr_out_sig = sig_to_gr_io_sigv(self.__out_sig) + + #create internal gateway block + self.__handler = gateway_handler() + self.__handler.init(self.__gr_block_handle) + self.__gateway = block_gateway( + self.__handler, name, gr_in_sig, gr_out_sig, work_type, factor) + self.__message = self.__gateway.gr_block_message() + + #dict to keep references to all message handlers + self.__msg_handlers = {} + + #register gr_block functions + prefix = 'gr_block__' + for attr in [x for x in dir(self.__gateway) if x.startswith(prefix)]: + setattr(self, attr.replace(prefix, ''), getattr(self.__gateway, attr)) + self.pop_msg_queue = lambda: gr_core.gr_block_gw_pop_msg_queue_safe(self.__gateway) + + #gras version of the to_basic_block() + def to_element(self): return self.__gateway.to_element() + + def to_basic_block(self): + """ + Makes this block connectable by hier/top block python + """ + return self.__gateway.to_basic_block() + + def __gr_block_handle(self): + """ + Dispatch tasks according to the action type specified in the message. + """ + if self.__message.action == gr_block_gw_message_type.ACTION_GENERAL_WORK: + self.__message.general_work_args_return_value = self.general_work( + + input_items=[pointer_to_ndarray( + self.__message.general_work_args_input_items[i], + self.__in_sig[i], + self.__message.general_work_args_ninput_items[i] + ) for i in self.__in_indexes], + + output_items=[pointer_to_ndarray( + self.__message.general_work_args_output_items[i], + self.__out_sig[i], + self.__message.general_work_args_noutput_items + ) for i in self.__out_indexes], + ) + + elif self.__message.action == gr_block_gw_message_type.ACTION_WORK: + self.__message.work_args_return_value = self.work( + + input_items=[pointer_to_ndarray( + self.__message.work_args_input_items[i], + self.__in_sig[i], + self.__message.work_args_ninput_items + ) for i in self.__in_indexes], + + output_items=[pointer_to_ndarray( + self.__message.work_args_output_items[i], + self.__out_sig[i], + self.__message.work_args_noutput_items + ) for i in self.__out_indexes], + ) + + elif self.__message.action == gr_block_gw_message_type.ACTION_FORECAST: + self.forecast( + noutput_items=self.__message.forecast_args_noutput_items, + ninput_items_required=self.__message.forecast_args_ninput_items_required, + ) + + elif self.__message.action == gr_block_gw_message_type.ACTION_START: + self.__message.start_args_return_value = self.start() + + elif self.__message.action == gr_block_gw_message_type.ACTION_STOP: + self.__message.stop_args_return_value = self.stop() + + def forecast(self, noutput_items, ninput_items_required): + """ + forecast is only called from a general block + this is the default implementation + """ + for ninput_item in ninput_items_required: + ninput_item = noutput_items + self.history() - 1; + return + + def general_work(self, *args, **kwargs): + """general work to be overloaded in a derived class""" + raise NotImplementedError("general work not implemented") + + def work(self, *args, **kwargs): + """work to be overloaded in a derived class""" + raise NotImplementedError("work not implemented") + + def start(self): return True + def stop(self): return True + + def set_msg_handler(self, which_port, handler_func): + handler = msg_handler() + handler.init(handler_func) + self.__gateway.set_msg_handler_feval(which_port, handler) + # Save handler object in class so it's not garbage collected + self.__msg_handlers[which_port] = handler + +######################################################################## +# Wrappers for the user to inherit from +######################################################################## +class basic_block(gateway_block): + def __init__(self, name, in_sig, out_sig): + gateway_block.__init__(self, + name=name, + in_sig=in_sig, + out_sig=out_sig, + work_type=gr_core.GR_BLOCK_GW_WORK_GENERAL, + factor=1, #not relevant factor + ) + +class sync_block(gateway_block): + def __init__(self, name, in_sig, out_sig): + gateway_block.__init__(self, + name=name, + in_sig=in_sig, + out_sig=out_sig, + work_type=gr_core.GR_BLOCK_GW_WORK_SYNC, + factor=1, + ) + +class decim_block(gateway_block): + def __init__(self, name, in_sig, out_sig, decim): + gateway_block.__init__(self, + name=name, + in_sig=in_sig, + out_sig=out_sig, + work_type=gr_core.GR_BLOCK_GW_WORK_DECIM, + factor=decim, + ) + +class interp_block(gateway_block): + def __init__(self, name, in_sig, out_sig, interp): + gateway_block.__init__(self, + name=name, + in_sig=in_sig, + out_sig=out_sig, + work_type=gr_core.GR_BLOCK_GW_WORK_INTERP, + factor=interp, + ) diff --git a/gnuradio-core/src/python/gnuradio/gr/gr_threading.py b/gnuradio-core/src/python/gnuradio/gr/gr_threading.py new file mode 100644 index 000000000..5d6f0fdaf --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/gr_threading.py @@ -0,0 +1,35 @@ +# +# 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. +# + +from sys import version_info as _version_info + +# import patched version of standard threading module + +if _version_info[0:2] == (2, 3): + #print "Importing gr_threading_23" + from gr_threading_23 import * +elif _version_info[0:2] == (2, 4): + #print "Importing gr_threading_24" + from gr_threading_24 import * +else: + # assume the patch was applied... + #print "Importing system provided threading" + from threading import * diff --git a/gnuradio-core/src/python/gnuradio/gr/gr_threading_23.py b/gnuradio-core/src/python/gnuradio/gr/gr_threading_23.py new file mode 100644 index 000000000..dee8034c1 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/gr_threading_23.py @@ -0,0 +1,724 @@ +"""Thread module emulating a subset of Java's threading model.""" + +# This started life as the threading.py module of Python 2.3 +# It's been patched to fix a problem with join, where a KeyboardInterrupt +# caused a lock to be left in the acquired state. + +import sys as _sys + +try: + import thread +except ImportError: + del _sys.modules[__name__] + raise + +from StringIO import StringIO as _StringIO +from time import time as _time, sleep as _sleep +from traceback import print_exc as _print_exc + +# Rename some stuff so "from threading import *" is safe +__all__ = ['activeCount', 'Condition', 'currentThread', 'enumerate', 'Event', + 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread', + 'Timer', 'setprofile', 'settrace'] + +_start_new_thread = thread.start_new_thread +_allocate_lock = thread.allocate_lock +_get_ident = thread.get_ident +ThreadError = thread.error +del thread + + +# Debug support (adapted from ihooks.py). +# All the major classes here derive from _Verbose. We force that to +# be a new-style class so that all the major classes here are new-style. +# This helps debugging (type(instance) is more revealing for instances +# of new-style classes). + +_VERBOSE = False + +if __debug__: + + class _Verbose(object): + + def __init__(self, verbose=None): + if verbose is None: + verbose = _VERBOSE + self.__verbose = verbose + + def _note(self, format, *args): + if self.__verbose: + format = format % args + format = "%s: %s\n" % ( + currentThread().getName(), format) + _sys.stderr.write(format) + +else: + # Disable this when using "python -O" + class _Verbose(object): + def __init__(self, verbose=None): + pass + def _note(self, *args): + pass + +# Support for profile and trace hooks + +_profile_hook = None +_trace_hook = None + +def setprofile(func): + global _profile_hook + _profile_hook = func + +def settrace(func): + global _trace_hook + _trace_hook = func + +# Synchronization classes + +Lock = _allocate_lock + +def RLock(*args, **kwargs): + return _RLock(*args, **kwargs) + +class _RLock(_Verbose): + + def __init__(self, verbose=None): + _Verbose.__init__(self, verbose) + self.__block = _allocate_lock() + self.__owner = None + self.__count = 0 + + def __repr__(self): + return "<%s(%s, %d)>" % ( + self.__class__.__name__, + self.__owner and self.__owner.getName(), + self.__count) + + def acquire(self, blocking=1): + me = currentThread() + if self.__owner is me: + self.__count = self.__count + 1 + if __debug__: + self._note("%s.acquire(%s): recursive success", self, blocking) + return 1 + rc = self.__block.acquire(blocking) + if rc: + self.__owner = me + self.__count = 1 + if __debug__: + self._note("%s.acquire(%s): initial succes", self, blocking) + else: + if __debug__: + self._note("%s.acquire(%s): failure", self, blocking) + return rc + + def release(self): + me = currentThread() + assert self.__owner is me, "release() of un-acquire()d lock" + self.__count = count = self.__count - 1 + if not count: + self.__owner = None + self.__block.release() + if __debug__: + self._note("%s.release(): final release", self) + else: + if __debug__: + self._note("%s.release(): non-final release", self) + + # Internal methods used by condition variables + + def _acquire_restore(self, (count, owner)): + self.__block.acquire() + self.__count = count + self.__owner = owner + if __debug__: + self._note("%s._acquire_restore()", self) + + def _release_save(self): + if __debug__: + self._note("%s._release_save()", self) + count = self.__count + self.__count = 0 + owner = self.__owner + self.__owner = None + self.__block.release() + return (count, owner) + + def _is_owned(self): + return self.__owner is currentThread() + + +def Condition(*args, **kwargs): + return _Condition(*args, **kwargs) + +class _Condition(_Verbose): + + def __init__(self, lock=None, verbose=None): + _Verbose.__init__(self, verbose) + if lock is None: + lock = RLock() + self.__lock = lock + # Export the lock's acquire() and release() methods + self.acquire = lock.acquire + self.release = lock.release + # If the lock defines _release_save() and/or _acquire_restore(), + # these override the default implementations (which just call + # release() and acquire() on the lock). Ditto for _is_owned(). + try: + self._release_save = lock._release_save + except AttributeError: + pass + try: + self._acquire_restore = lock._acquire_restore + except AttributeError: + pass + try: + self._is_owned = lock._is_owned + except AttributeError: + pass + self.__waiters = [] + + def __repr__(self): + return "<Condition(%s, %d)>" % (self.__lock, len(self.__waiters)) + + def _release_save(self): + self.__lock.release() # No state to save + + def _acquire_restore(self, x): + self.__lock.acquire() # Ignore saved state + + def _is_owned(self): + # Return True if lock is owned by currentThread. + # This method is called only if __lock doesn't have _is_owned(). + if self.__lock.acquire(0): + self.__lock.release() + return False + else: + return True + + def wait(self, timeout=None): + currentThread() # for side-effect + assert self._is_owned(), "wait() of un-acquire()d lock" + waiter = _allocate_lock() + waiter.acquire() + self.__waiters.append(waiter) + saved_state = self._release_save() + try: # restore state no matter what (e.g., KeyboardInterrupt) + if timeout is None: + waiter.acquire() + if __debug__: + self._note("%s.wait(): got it", self) + else: + # Balancing act: We can't afford a pure busy loop, so we + # have to sleep; but if we sleep the whole timeout time, + # we'll be unresponsive. The scheme here sleeps very + # little at first, longer as time goes on, but never longer + # than 20 times per second (or the timeout time remaining). + endtime = _time() + timeout + delay = 0.0005 # 500 us -> initial delay of 1 ms + while True: + gotit = waiter.acquire(0) + if gotit: + break + remaining = endtime - _time() + if remaining <= 0: + break + delay = min(delay * 2, remaining, .05) + _sleep(delay) + if not gotit: + if __debug__: + self._note("%s.wait(%s): timed out", self, timeout) + try: + self.__waiters.remove(waiter) + except ValueError: + pass + else: + if __debug__: + self._note("%s.wait(%s): got it", self, timeout) + finally: + self._acquire_restore(saved_state) + + def notify(self, n=1): + currentThread() # for side-effect + assert self._is_owned(), "notify() of un-acquire()d lock" + __waiters = self.__waiters + waiters = __waiters[:n] + if not waiters: + if __debug__: + self._note("%s.notify(): no waiters", self) + return + self._note("%s.notify(): notifying %d waiter%s", self, n, + n!=1 and "s" or "") + for waiter in waiters: + waiter.release() + try: + __waiters.remove(waiter) + except ValueError: + pass + + def notifyAll(self): + self.notify(len(self.__waiters)) + + +def Semaphore(*args, **kwargs): + return _Semaphore(*args, **kwargs) + +class _Semaphore(_Verbose): + + # After Tim Peters' semaphore class, but not quite the same (no maximum) + + def __init__(self, value=1, verbose=None): + assert value >= 0, "Semaphore initial value must be >= 0" + _Verbose.__init__(self, verbose) + self.__cond = Condition(Lock()) + self.__value = value + + def acquire(self, blocking=1): + rc = False + self.__cond.acquire() + while self.__value == 0: + if not blocking: + break + if __debug__: + self._note("%s.acquire(%s): blocked waiting, value=%s", + self, blocking, self.__value) + self.__cond.wait() + else: + self.__value = self.__value - 1 + if __debug__: + self._note("%s.acquire: success, value=%s", + self, self.__value) + rc = True + self.__cond.release() + return rc + + def release(self): + self.__cond.acquire() + self.__value = self.__value + 1 + if __debug__: + self._note("%s.release: success, value=%s", + self, self.__value) + self.__cond.notify() + self.__cond.release() + + +def BoundedSemaphore(*args, **kwargs): + return _BoundedSemaphore(*args, **kwargs) + +class _BoundedSemaphore(_Semaphore): + """Semaphore that checks that # releases is <= # acquires""" + def __init__(self, value=1, verbose=None): + _Semaphore.__init__(self, value, verbose) + self._initial_value = value + + def release(self): + if self._Semaphore__value >= self._initial_value: + raise ValueError, "Semaphore released too many times" + return _Semaphore.release(self) + + +def Event(*args, **kwargs): + return _Event(*args, **kwargs) + +class _Event(_Verbose): + + # After Tim Peters' event class (without is_posted()) + + def __init__(self, verbose=None): + _Verbose.__init__(self, verbose) + self.__cond = Condition(Lock()) + self.__flag = False + + def isSet(self): + return self.__flag + + def set(self): + self.__cond.acquire() + try: + self.__flag = True + self.__cond.notifyAll() + finally: + self.__cond.release() + + def clear(self): + self.__cond.acquire() + try: + self.__flag = False + finally: + self.__cond.release() + + def wait(self, timeout=None): + self.__cond.acquire() + try: + if not self.__flag: + self.__cond.wait(timeout) + finally: + self.__cond.release() + +# Helper to generate new thread names +_counter = 0 +def _newname(template="Thread-%d"): + global _counter + _counter = _counter + 1 + return template % _counter + +# Active thread administration +_active_limbo_lock = _allocate_lock() +_active = {} +_limbo = {} + + +# Main class for threads + +class Thread(_Verbose): + + __initialized = False + + def __init__(self, group=None, target=None, name=None, + args=(), kwargs={}, verbose=None): + assert group is None, "group argument must be None for now" + _Verbose.__init__(self, verbose) + self.__target = target + self.__name = str(name or _newname()) + self.__args = args + self.__kwargs = kwargs + self.__daemonic = self._set_daemon() + self.__started = False + self.__stopped = False + self.__block = Condition(Lock()) + self.__initialized = True + + def _set_daemon(self): + # Overridden in _MainThread and _DummyThread + return currentThread().isDaemon() + + def __repr__(self): + assert self.__initialized, "Thread.__init__() was not called" + status = "initial" + if self.__started: + status = "started" + if self.__stopped: + status = "stopped" + if self.__daemonic: + status = status + " daemon" + return "<%s(%s, %s)>" % (self.__class__.__name__, self.__name, status) + + def start(self): + assert self.__initialized, "Thread.__init__() not called" + assert not self.__started, "thread already started" + if __debug__: + self._note("%s.start(): starting thread", self) + _active_limbo_lock.acquire() + _limbo[self] = self + _active_limbo_lock.release() + _start_new_thread(self.__bootstrap, ()) + self.__started = True + _sleep(0.000001) # 1 usec, to let the thread run (Solaris hack) + + def run(self): + if self.__target: + self.__target(*self.__args, **self.__kwargs) + + def __bootstrap(self): + try: + self.__started = True + _active_limbo_lock.acquire() + _active[_get_ident()] = self + del _limbo[self] + _active_limbo_lock.release() + if __debug__: + self._note("%s.__bootstrap(): thread started", self) + + if _trace_hook: + self._note("%s.__bootstrap(): registering trace hook", self) + _sys.settrace(_trace_hook) + if _profile_hook: + self._note("%s.__bootstrap(): registering profile hook", self) + _sys.setprofile(_profile_hook) + + try: + self.run() + except SystemExit: + if __debug__: + self._note("%s.__bootstrap(): raised SystemExit", self) + except: + if __debug__: + self._note("%s.__bootstrap(): unhandled exception", self) + s = _StringIO() + _print_exc(file=s) + _sys.stderr.write("Exception in thread %s:\n%s\n" % + (self.getName(), s.getvalue())) + else: + if __debug__: + self._note("%s.__bootstrap(): normal return", self) + finally: + self.__stop() + try: + self.__delete() + except: + pass + + def __stop(self): + self.__block.acquire() + self.__stopped = True + self.__block.notifyAll() + self.__block.release() + + def __delete(self): + _active_limbo_lock.acquire() + del _active[_get_ident()] + _active_limbo_lock.release() + + def join(self, timeout=None): + assert self.__initialized, "Thread.__init__() not called" + assert self.__started, "cannot join thread before it is started" + assert self is not currentThread(), "cannot join current thread" + if __debug__: + if not self.__stopped: + self._note("%s.join(): waiting until thread stops", self) + self.__block.acquire() + try: + if timeout is None: + while not self.__stopped: + self.__block.wait() + if __debug__: + self._note("%s.join(): thread stopped", self) + else: + deadline = _time() + timeout + while not self.__stopped: + delay = deadline - _time() + if delay <= 0: + if __debug__: + self._note("%s.join(): timed out", self) + break + self.__block.wait(delay) + else: + if __debug__: + self._note("%s.join(): thread stopped", self) + finally: + self.__block.release() + + def getName(self): + assert self.__initialized, "Thread.__init__() not called" + return self.__name + + def setName(self, name): + assert self.__initialized, "Thread.__init__() not called" + self.__name = str(name) + + def isAlive(self): + assert self.__initialized, "Thread.__init__() not called" + return self.__started and not self.__stopped + + def isDaemon(self): + assert self.__initialized, "Thread.__init__() not called" + return self.__daemonic + + def setDaemon(self, daemonic): + assert self.__initialized, "Thread.__init__() not called" + assert not self.__started, "cannot set daemon status of active thread" + self.__daemonic = daemonic + +# The timer class was contributed by Itamar Shtull-Trauring + +def Timer(*args, **kwargs): + return _Timer(*args, **kwargs) + +class _Timer(Thread): + """Call a function after a specified number of seconds: + + t = Timer(30.0, f, args=[], kwargs={}) + t.start() + t.cancel() # stop the timer's action if it's still waiting + """ + + def __init__(self, interval, function, args=[], kwargs={}): + Thread.__init__(self) + self.interval = interval + self.function = function + self.args = args + self.kwargs = kwargs + self.finished = Event() + + def cancel(self): + """Stop the timer if it hasn't finished yet""" + self.finished.set() + + def run(self): + self.finished.wait(self.interval) + if not self.finished.isSet(): + self.function(*self.args, **self.kwargs) + self.finished.set() + +# Special thread class to represent the main thread +# This is garbage collected through an exit handler + +class _MainThread(Thread): + + def __init__(self): + Thread.__init__(self, name="MainThread") + self._Thread__started = True + _active_limbo_lock.acquire() + _active[_get_ident()] = self + _active_limbo_lock.release() + import atexit + atexit.register(self.__exitfunc) + + def _set_daemon(self): + return False + + def __exitfunc(self): + self._Thread__stop() + t = _pickSomeNonDaemonThread() + if t: + if __debug__: + self._note("%s: waiting for other threads", self) + while t: + t.join() + t = _pickSomeNonDaemonThread() + if __debug__: + self._note("%s: exiting", self) + self._Thread__delete() + +def _pickSomeNonDaemonThread(): + for t in enumerate(): + if not t.isDaemon() and t.isAlive(): + return t + return None + + +# Dummy thread class to represent threads not started here. +# These aren't garbage collected when they die, +# nor can they be waited for. +# Their purpose is to return *something* from currentThread(). +# They are marked as daemon threads so we won't wait for them +# when we exit (conform previous semantics). + +class _DummyThread(Thread): + + def __init__(self): + Thread.__init__(self, name=_newname("Dummy-%d")) + self._Thread__started = True + _active_limbo_lock.acquire() + _active[_get_ident()] = self + _active_limbo_lock.release() + + def _set_daemon(self): + return True + + def join(self, timeout=None): + assert False, "cannot join a dummy thread" + + +# Global API functions + +def currentThread(): + try: + return _active[_get_ident()] + except KeyError: + ##print "currentThread(): no current thread for", _get_ident() + return _DummyThread() + +def activeCount(): + _active_limbo_lock.acquire() + count = len(_active) + len(_limbo) + _active_limbo_lock.release() + return count + +def enumerate(): + _active_limbo_lock.acquire() + active = _active.values() + _limbo.values() + _active_limbo_lock.release() + return active + +# Create the main thread object + +_MainThread() + + +# Self-test code + +def _test(): + + class BoundedQueue(_Verbose): + + def __init__(self, limit): + _Verbose.__init__(self) + self.mon = RLock() + self.rc = Condition(self.mon) + self.wc = Condition(self.mon) + self.limit = limit + self.queue = [] + + def put(self, item): + self.mon.acquire() + while len(self.queue) >= self.limit: + self._note("put(%s): queue full", item) + self.wc.wait() + self.queue.append(item) + self._note("put(%s): appended, length now %d", + item, len(self.queue)) + self.rc.notify() + self.mon.release() + + def get(self): + self.mon.acquire() + while not self.queue: + self._note("get(): queue empty") + self.rc.wait() + item = self.queue.pop(0) + self._note("get(): got %s, %d left", item, len(self.queue)) + self.wc.notify() + self.mon.release() + return item + + class ProducerThread(Thread): + + def __init__(self, queue, quota): + Thread.__init__(self, name="Producer") + self.queue = queue + self.quota = quota + + def run(self): + from random import random + counter = 0 + while counter < self.quota: + counter = counter + 1 + self.queue.put("%s.%d" % (self.getName(), counter)) + _sleep(random() * 0.00001) + + + class ConsumerThread(Thread): + + def __init__(self, queue, count): + Thread.__init__(self, name="Consumer") + self.queue = queue + self.count = count + + def run(self): + while self.count > 0: + item = self.queue.get() + print item + self.count = self.count - 1 + + NP = 3 + QL = 4 + NI = 5 + + Q = BoundedQueue(QL) + P = [] + for i in range(NP): + t = ProducerThread(Q, NI) + t.setName("Producer-%d" % (i+1)) + P.append(t) + C = ConsumerThread(Q, NI*NP) + for t in P: + t.start() + _sleep(0.000001) + C.start() + for t in P: + t.join() + C.join() + +if __name__ == '__main__': + _test() diff --git a/gnuradio-core/src/python/gnuradio/gr/gr_threading_24.py b/gnuradio-core/src/python/gnuradio/gr/gr_threading_24.py new file mode 100644 index 000000000..8539bfc04 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/gr_threading_24.py @@ -0,0 +1,793 @@ +"""Thread module emulating a subset of Java's threading model.""" + +# This started life as the threading.py module of Python 2.4 +# It's been patched to fix a problem with join, where a KeyboardInterrupt +# caused a lock to be left in the acquired state. + +import sys as _sys + +try: + import thread +except ImportError: + del _sys.modules[__name__] + raise + +from time import time as _time, sleep as _sleep +from traceback import format_exc as _format_exc +from collections import deque + +# Rename some stuff so "from threading import *" is safe +__all__ = ['activeCount', 'Condition', 'currentThread', 'enumerate', 'Event', + 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread', + 'Timer', 'setprofile', 'settrace', 'local'] + +_start_new_thread = thread.start_new_thread +_allocate_lock = thread.allocate_lock +_get_ident = thread.get_ident +ThreadError = thread.error +del thread + + +# Debug support (adapted from ihooks.py). +# All the major classes here derive from _Verbose. We force that to +# be a new-style class so that all the major classes here are new-style. +# This helps debugging (type(instance) is more revealing for instances +# of new-style classes). + +_VERBOSE = False + +if __debug__: + + class _Verbose(object): + + def __init__(self, verbose=None): + if verbose is None: + verbose = _VERBOSE + self.__verbose = verbose + + def _note(self, format, *args): + if self.__verbose: + format = format % args + format = "%s: %s\n" % ( + currentThread().getName(), format) + _sys.stderr.write(format) + +else: + # Disable this when using "python -O" + class _Verbose(object): + def __init__(self, verbose=None): + pass + def _note(self, *args): + pass + +# Support for profile and trace hooks + +_profile_hook = None +_trace_hook = None + +def setprofile(func): + global _profile_hook + _profile_hook = func + +def settrace(func): + global _trace_hook + _trace_hook = func + +# Synchronization classes + +Lock = _allocate_lock + +def RLock(*args, **kwargs): + return _RLock(*args, **kwargs) + +class _RLock(_Verbose): + + def __init__(self, verbose=None): + _Verbose.__init__(self, verbose) + self.__block = _allocate_lock() + self.__owner = None + self.__count = 0 + + def __repr__(self): + return "<%s(%s, %d)>" % ( + self.__class__.__name__, + self.__owner and self.__owner.getName(), + self.__count) + + def acquire(self, blocking=1): + me = currentThread() + if self.__owner is me: + self.__count = self.__count + 1 + if __debug__: + self._note("%s.acquire(%s): recursive success", self, blocking) + return 1 + rc = self.__block.acquire(blocking) + if rc: + self.__owner = me + self.__count = 1 + if __debug__: + self._note("%s.acquire(%s): initial succes", self, blocking) + else: + if __debug__: + self._note("%s.acquire(%s): failure", self, blocking) + return rc + + def release(self): + me = currentThread() + assert self.__owner is me, "release() of un-acquire()d lock" + self.__count = count = self.__count - 1 + if not count: + self.__owner = None + self.__block.release() + if __debug__: + self._note("%s.release(): final release", self) + else: + if __debug__: + self._note("%s.release(): non-final release", self) + + # Internal methods used by condition variables + + def _acquire_restore(self, (count, owner)): + self.__block.acquire() + self.__count = count + self.__owner = owner + if __debug__: + self._note("%s._acquire_restore()", self) + + def _release_save(self): + if __debug__: + self._note("%s._release_save()", self) + count = self.__count + self.__count = 0 + owner = self.__owner + self.__owner = None + self.__block.release() + return (count, owner) + + def _is_owned(self): + return self.__owner is currentThread() + + +def Condition(*args, **kwargs): + return _Condition(*args, **kwargs) + +class _Condition(_Verbose): + + def __init__(self, lock=None, verbose=None): + _Verbose.__init__(self, verbose) + if lock is None: + lock = RLock() + self.__lock = lock + # Export the lock's acquire() and release() methods + self.acquire = lock.acquire + self.release = lock.release + # If the lock defines _release_save() and/or _acquire_restore(), + # these override the default implementations (which just call + # release() and acquire() on the lock). Ditto for _is_owned(). + try: + self._release_save = lock._release_save + except AttributeError: + pass + try: + self._acquire_restore = lock._acquire_restore + except AttributeError: + pass + try: + self._is_owned = lock._is_owned + except AttributeError: + pass + self.__waiters = [] + + def __repr__(self): + return "<Condition(%s, %d)>" % (self.__lock, len(self.__waiters)) + + def _release_save(self): + self.__lock.release() # No state to save + + def _acquire_restore(self, x): + self.__lock.acquire() # Ignore saved state + + def _is_owned(self): + # Return True if lock is owned by currentThread. + # This method is called only if __lock doesn't have _is_owned(). + if self.__lock.acquire(0): + self.__lock.release() + return False + else: + return True + + def wait(self, timeout=None): + assert self._is_owned(), "wait() of un-acquire()d lock" + waiter = _allocate_lock() + waiter.acquire() + self.__waiters.append(waiter) + saved_state = self._release_save() + try: # restore state no matter what (e.g., KeyboardInterrupt) + if timeout is None: + waiter.acquire() + if __debug__: + self._note("%s.wait(): got it", self) + else: + # Balancing act: We can't afford a pure busy loop, so we + # have to sleep; but if we sleep the whole timeout time, + # we'll be unresponsive. The scheme here sleeps very + # little at first, longer as time goes on, but never longer + # than 20 times per second (or the timeout time remaining). + endtime = _time() + timeout + delay = 0.0005 # 500 us -> initial delay of 1 ms + while True: + gotit = waiter.acquire(0) + if gotit: + break + remaining = endtime - _time() + if remaining <= 0: + break + delay = min(delay * 2, remaining, .05) + _sleep(delay) + if not gotit: + if __debug__: + self._note("%s.wait(%s): timed out", self, timeout) + try: + self.__waiters.remove(waiter) + except ValueError: + pass + else: + if __debug__: + self._note("%s.wait(%s): got it", self, timeout) + finally: + self._acquire_restore(saved_state) + + def notify(self, n=1): + assert self._is_owned(), "notify() of un-acquire()d lock" + __waiters = self.__waiters + waiters = __waiters[:n] + if not waiters: + if __debug__: + self._note("%s.notify(): no waiters", self) + return + self._note("%s.notify(): notifying %d waiter%s", self, n, + n!=1 and "s" or "") + for waiter in waiters: + waiter.release() + try: + __waiters.remove(waiter) + except ValueError: + pass + + def notifyAll(self): + self.notify(len(self.__waiters)) + + +def Semaphore(*args, **kwargs): + return _Semaphore(*args, **kwargs) + +class _Semaphore(_Verbose): + + # After Tim Peters' semaphore class, but not quite the same (no maximum) + + def __init__(self, value=1, verbose=None): + assert value >= 0, "Semaphore initial value must be >= 0" + _Verbose.__init__(self, verbose) + self.__cond = Condition(Lock()) + self.__value = value + + def acquire(self, blocking=1): + rc = False + self.__cond.acquire() + while self.__value == 0: + if not blocking: + break + if __debug__: + self._note("%s.acquire(%s): blocked waiting, value=%s", + self, blocking, self.__value) + self.__cond.wait() + else: + self.__value = self.__value - 1 + if __debug__: + self._note("%s.acquire: success, value=%s", + self, self.__value) + rc = True + self.__cond.release() + return rc + + def release(self): + self.__cond.acquire() + self.__value = self.__value + 1 + if __debug__: + self._note("%s.release: success, value=%s", + self, self.__value) + self.__cond.notify() + self.__cond.release() + + +def BoundedSemaphore(*args, **kwargs): + return _BoundedSemaphore(*args, **kwargs) + +class _BoundedSemaphore(_Semaphore): + """Semaphore that checks that # releases is <= # acquires""" + def __init__(self, value=1, verbose=None): + _Semaphore.__init__(self, value, verbose) + self._initial_value = value + + def release(self): + if self._Semaphore__value >= self._initial_value: + raise ValueError, "Semaphore released too many times" + return _Semaphore.release(self) + + +def Event(*args, **kwargs): + return _Event(*args, **kwargs) + +class _Event(_Verbose): + + # After Tim Peters' event class (without is_posted()) + + def __init__(self, verbose=None): + _Verbose.__init__(self, verbose) + self.__cond = Condition(Lock()) + self.__flag = False + + def isSet(self): + return self.__flag + + def set(self): + self.__cond.acquire() + try: + self.__flag = True + self.__cond.notifyAll() + finally: + self.__cond.release() + + def clear(self): + self.__cond.acquire() + try: + self.__flag = False + finally: + self.__cond.release() + + def wait(self, timeout=None): + self.__cond.acquire() + try: + if not self.__flag: + self.__cond.wait(timeout) + finally: + self.__cond.release() + +# Helper to generate new thread names +_counter = 0 +def _newname(template="Thread-%d"): + global _counter + _counter = _counter + 1 + return template % _counter + +# Active thread administration +_active_limbo_lock = _allocate_lock() +_active = {} +_limbo = {} + + +# Main class for threads + +class Thread(_Verbose): + + __initialized = False + # Need to store a reference to sys.exc_info for printing + # out exceptions when a thread tries to use a global var. during interp. + # shutdown and thus raises an exception about trying to perform some + # operation on/with a NoneType + __exc_info = _sys.exc_info + + def __init__(self, group=None, target=None, name=None, + args=(), kwargs={}, verbose=None): + assert group is None, "group argument must be None for now" + _Verbose.__init__(self, verbose) + self.__target = target + self.__name = str(name or _newname()) + self.__args = args + self.__kwargs = kwargs + self.__daemonic = self._set_daemon() + self.__started = False + self.__stopped = False + self.__block = Condition(Lock()) + self.__initialized = True + # sys.stderr is not stored in the class like + # sys.exc_info since it can be changed between instances + self.__stderr = _sys.stderr + + def _set_daemon(self): + # Overridden in _MainThread and _DummyThread + return currentThread().isDaemon() + + def __repr__(self): + assert self.__initialized, "Thread.__init__() was not called" + status = "initial" + if self.__started: + status = "started" + if self.__stopped: + status = "stopped" + if self.__daemonic: + status = status + " daemon" + return "<%s(%s, %s)>" % (self.__class__.__name__, self.__name, status) + + def start(self): + assert self.__initialized, "Thread.__init__() not called" + assert not self.__started, "thread already started" + if __debug__: + self._note("%s.start(): starting thread", self) + _active_limbo_lock.acquire() + _limbo[self] = self + _active_limbo_lock.release() + _start_new_thread(self.__bootstrap, ()) + self.__started = True + _sleep(0.000001) # 1 usec, to let the thread run (Solaris hack) + + def run(self): + if self.__target: + self.__target(*self.__args, **self.__kwargs) + + def __bootstrap(self): + try: + self.__started = True + _active_limbo_lock.acquire() + _active[_get_ident()] = self + del _limbo[self] + _active_limbo_lock.release() + if __debug__: + self._note("%s.__bootstrap(): thread started", self) + + if _trace_hook: + self._note("%s.__bootstrap(): registering trace hook", self) + _sys.settrace(_trace_hook) + if _profile_hook: + self._note("%s.__bootstrap(): registering profile hook", self) + _sys.setprofile(_profile_hook) + + try: + self.run() + except SystemExit: + if __debug__: + self._note("%s.__bootstrap(): raised SystemExit", self) + except: + if __debug__: + self._note("%s.__bootstrap(): unhandled exception", self) + # If sys.stderr is no more (most likely from interpreter + # shutdown) use self.__stderr. Otherwise still use sys (as in + # _sys) in case sys.stderr was redefined since the creation of + # self. + if _sys: + _sys.stderr.write("Exception in thread %s:\n%s\n" % + (self.getName(), _format_exc())) + else: + # Do the best job possible w/o a huge amt. of code to + # approximate a traceback (code ideas from + # Lib/traceback.py) + exc_type, exc_value, exc_tb = self.__exc_info() + try: + print>>self.__stderr, ( + "Exception in thread " + self.getName() + + " (most likely raised during interpreter shutdown):") + print>>self.__stderr, ( + "Traceback (most recent call last):") + while exc_tb: + print>>self.__stderr, ( + ' File "%s", line %s, in %s' % + (exc_tb.tb_frame.f_code.co_filename, + exc_tb.tb_lineno, + exc_tb.tb_frame.f_code.co_name)) + exc_tb = exc_tb.tb_next + print>>self.__stderr, ("%s: %s" % (exc_type, exc_value)) + # Make sure that exc_tb gets deleted since it is a memory + # hog; deleting everything else is just for thoroughness + finally: + del exc_type, exc_value, exc_tb + else: + if __debug__: + self._note("%s.__bootstrap(): normal return", self) + finally: + self.__stop() + try: + self.__delete() + except: + pass + + def __stop(self): + self.__block.acquire() + self.__stopped = True + self.__block.notifyAll() + self.__block.release() + + def __delete(self): + "Remove current thread from the dict of currently running threads." + + # Notes about running with dummy_thread: + # + # Must take care to not raise an exception if dummy_thread is being + # used (and thus this module is being used as an instance of + # dummy_threading). dummy_thread.get_ident() always returns -1 since + # there is only one thread if dummy_thread is being used. Thus + # len(_active) is always <= 1 here, and any Thread instance created + # overwrites the (if any) thread currently registered in _active. + # + # An instance of _MainThread is always created by 'threading'. This + # gets overwritten the instant an instance of Thread is created; both + # threads return -1 from dummy_thread.get_ident() and thus have the + # same key in the dict. So when the _MainThread instance created by + # 'threading' tries to clean itself up when atexit calls this method + # it gets a KeyError if another Thread instance was created. + # + # This all means that KeyError from trying to delete something from + # _active if dummy_threading is being used is a red herring. But + # since it isn't if dummy_threading is *not* being used then don't + # hide the exception. + + _active_limbo_lock.acquire() + try: + try: + del _active[_get_ident()] + except KeyError: + if 'dummy_threading' not in _sys.modules: + raise + finally: + _active_limbo_lock.release() + + def join(self, timeout=None): + assert self.__initialized, "Thread.__init__() not called" + assert self.__started, "cannot join thread before it is started" + assert self is not currentThread(), "cannot join current thread" + if __debug__: + if not self.__stopped: + self._note("%s.join(): waiting until thread stops", self) + self.__block.acquire() + try: + if timeout is None: + while not self.__stopped: + self.__block.wait() + if __debug__: + self._note("%s.join(): thread stopped", self) + else: + deadline = _time() + timeout + while not self.__stopped: + delay = deadline - _time() + if delay <= 0: + if __debug__: + self._note("%s.join(): timed out", self) + break + self.__block.wait(delay) + else: + if __debug__: + self._note("%s.join(): thread stopped", self) + finally: + self.__block.release() + + def getName(self): + assert self.__initialized, "Thread.__init__() not called" + return self.__name + + def setName(self, name): + assert self.__initialized, "Thread.__init__() not called" + self.__name = str(name) + + def isAlive(self): + assert self.__initialized, "Thread.__init__() not called" + return self.__started and not self.__stopped + + def isDaemon(self): + assert self.__initialized, "Thread.__init__() not called" + return self.__daemonic + + def setDaemon(self, daemonic): + assert self.__initialized, "Thread.__init__() not called" + assert not self.__started, "cannot set daemon status of active thread" + self.__daemonic = daemonic + +# The timer class was contributed by Itamar Shtull-Trauring + +def Timer(*args, **kwargs): + return _Timer(*args, **kwargs) + +class _Timer(Thread): + """Call a function after a specified number of seconds: + + t = Timer(30.0, f, args=[], kwargs={}) + t.start() + t.cancel() # stop the timer's action if it's still waiting + """ + + def __init__(self, interval, function, args=[], kwargs={}): + Thread.__init__(self) + self.interval = interval + self.function = function + self.args = args + self.kwargs = kwargs + self.finished = Event() + + def cancel(self): + """Stop the timer if it hasn't finished yet""" + self.finished.set() + + def run(self): + self.finished.wait(self.interval) + if not self.finished.isSet(): + self.function(*self.args, **self.kwargs) + self.finished.set() + +# Special thread class to represent the main thread +# This is garbage collected through an exit handler + +class _MainThread(Thread): + + def __init__(self): + Thread.__init__(self, name="MainThread") + self._Thread__started = True + _active_limbo_lock.acquire() + _active[_get_ident()] = self + _active_limbo_lock.release() + import atexit + atexit.register(self.__exitfunc) + + def _set_daemon(self): + return False + + def __exitfunc(self): + self._Thread__stop() + t = _pickSomeNonDaemonThread() + if t: + if __debug__: + self._note("%s: waiting for other threads", self) + while t: + t.join() + t = _pickSomeNonDaemonThread() + if __debug__: + self._note("%s: exiting", self) + self._Thread__delete() + +def _pickSomeNonDaemonThread(): + for t in enumerate(): + if not t.isDaemon() and t.isAlive(): + return t + return None + + +# Dummy thread class to represent threads not started here. +# These aren't garbage collected when they die, +# nor can they be waited for. +# Their purpose is to return *something* from currentThread(). +# They are marked as daemon threads so we won't wait for them +# when we exit (conform previous semantics). + +class _DummyThread(Thread): + + def __init__(self): + Thread.__init__(self, name=_newname("Dummy-%d")) + self._Thread__started = True + _active_limbo_lock.acquire() + _active[_get_ident()] = self + _active_limbo_lock.release() + + def _set_daemon(self): + return True + + def join(self, timeout=None): + assert False, "cannot join a dummy thread" + + +# Global API functions + +def currentThread(): + try: + return _active[_get_ident()] + except KeyError: + ##print "currentThread(): no current thread for", _get_ident() + return _DummyThread() + +def activeCount(): + _active_limbo_lock.acquire() + count = len(_active) + len(_limbo) + _active_limbo_lock.release() + return count + +def enumerate(): + _active_limbo_lock.acquire() + active = _active.values() + _limbo.values() + _active_limbo_lock.release() + return active + +# Create the main thread object + +_MainThread() + +# get thread-local implementation, either from the thread +# module, or from the python fallback + +try: + from thread import _local as local +except ImportError: + from _threading_local import local + + +# Self-test code + +def _test(): + + class BoundedQueue(_Verbose): + + def __init__(self, limit): + _Verbose.__init__(self) + self.mon = RLock() + self.rc = Condition(self.mon) + self.wc = Condition(self.mon) + self.limit = limit + self.queue = deque() + + def put(self, item): + self.mon.acquire() + while len(self.queue) >= self.limit: + self._note("put(%s): queue full", item) + self.wc.wait() + self.queue.append(item) + self._note("put(%s): appended, length now %d", + item, len(self.queue)) + self.rc.notify() + self.mon.release() + + def get(self): + self.mon.acquire() + while not self.queue: + self._note("get(): queue empty") + self.rc.wait() + item = self.queue.popleft() + self._note("get(): got %s, %d left", item, len(self.queue)) + self.wc.notify() + self.mon.release() + return item + + class ProducerThread(Thread): + + def __init__(self, queue, quota): + Thread.__init__(self, name="Producer") + self.queue = queue + self.quota = quota + + def run(self): + from random import random + counter = 0 + while counter < self.quota: + counter = counter + 1 + self.queue.put("%s.%d" % (self.getName(), counter)) + _sleep(random() * 0.00001) + + + class ConsumerThread(Thread): + + def __init__(self, queue, count): + Thread.__init__(self, name="Consumer") + self.queue = queue + self.count = count + + def run(self): + while self.count > 0: + item = self.queue.get() + print item + self.count = self.count - 1 + + NP = 3 + QL = 4 + NI = 5 + + Q = BoundedQueue(QL) + P = [] + for i in range(NP): + t = ProducerThread(Q, NI) + t.setName("Producer-%d" % (i+1)) + P.append(t) + C = ConsumerThread(Q, NI*NP) + for t in P: + t.start() + _sleep(0.000001) + C.start() + for t in P: + t.join() + C.join() + +if __name__ == '__main__': + _test() diff --git a/gnuradio-core/src/python/gnuradio/gr/hier_block2.py b/gnuradio-core/src/python/gnuradio/gr/hier_block2.py new file mode 100644 index 000000000..b95782238 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/hier_block2.py @@ -0,0 +1,129 @@ +# +# Copyright 2006,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. +# + +from gnuradio_core import hier_block2_swig +try: + import pmt +except ImportError: + from gruel import pmt + +# +# This hack forces a 'has-a' relationship to look like an 'is-a' one. +# +# It allows Python classes to subclass this one, while passing through +# method calls to the C++ class shared pointer from SWIG. +# +# It also allows us to intercept method calls if needed +# +class hier_block2(object): + """ + Python wrapper around the C++ hierarchical block implementation. + Provides convenience functions and allows proper Python subclassing. + """ + + def __init__(self, name, input_signature, output_signature): + """ + Create a hierarchical block with a given name and I/O signatures. + """ + self._hb = hier_block2_swig(name, input_signature, output_signature) + + def __getattr__(self, name): + """ + Pass-through member requests to the C++ object. + """ + if not hasattr(self, "_hb"): + raise RuntimeError("hier_block2: invalid state--did you forget to call gr.hier_block2.__init__ in a derived class?") + return getattr(self._hb, name) + + def connect(self, *points): + """ + Connect two or more block endpoints. An endpoint is either a (block, port) + tuple or a block instance. In the latter case, the port number is assumed + to be zero. + + To connect the hierarchical block external inputs or outputs to internal block + inputs or outputs, use 'self' in the connect call. + + If multiple arguments are provided, connect will attempt to wire them in series, + interpreting the endpoints as inputs or outputs as appropriate. + """ + + if len (points) < 1: + raise ValueError, ("connect requires at least one endpoint; %d provided." % (len (points),)) + else: + if len(points) == 1: + self._hb.primitive_connect(points[0].to_basic_block()) + else: + for i in range (1, len (points)): + self._connect(points[i-1], points[i]) + + def _connect(self, src, dst): + (src_block, src_port) = self._coerce_endpoint(src) + (dst_block, dst_port) = self._coerce_endpoint(dst) + self._hb.primitive_connect(src_block.to_basic_block(), src_port, + dst_block.to_basic_block(), dst_port) + + def _coerce_endpoint(self, endp): + if hasattr(endp, 'to_basic_block'): + return (endp, 0) + else: + if hasattr(endp, "__getitem__") and len(endp) == 2: + return endp # Assume user put (block, port) + else: + raise ValueError("unable to coerce endpoint") + + def disconnect(self, *points): + """ + Disconnect two endpoints in the flowgraph. + + To disconnect the hierarchical block external inputs or outputs to internal block + inputs or outputs, use 'self' in the connect call. + + If more than two arguments are provided, they are disconnected successively. + """ + + if len (points) < 1: + raise ValueError, ("disconnect requires at least one endpoint; %d provided." % (len (points),)) + else: + if len (points) == 1: + self._hb.primitive_disconnect(points[0].to_basic_block()) + else: + for i in range (1, len (points)): + self._disconnect(points[i-1], points[i]) + + def _disconnect(self, src, dst): + (src_block, src_port) = self._coerce_endpoint(src) + (dst_block, dst_port) = self._coerce_endpoint(dst) + self._hb.primitive_disconnect(src_block.to_basic_block(), src_port, + dst_block.to_basic_block(), dst_port) + + def msg_connect(self, src, srcport, dst, dstport): + self.primitive_msg_connect(src.to_basic_block(), srcport, dst.to_basic_block(), dstport); + + def msg_disconnect(self, src, srcport, dst, dstport): + self.primitive_msg_disconnect(src.to_basic_block(), srcport, dst.to_basic_block(), dstport); + + def message_port_register_hier_in(self, portname): + self.primitive_message_port_register_hier_in(pmt.pmt_intern(portname)); + + def message_port_register_hier_out(self, portname): + self.primitive_message_port_register_hier_out(pmt.pmt_intern(portname)); + diff --git a/gnuradio-core/src/python/gnuradio/gr/prefs.py b/gnuradio-core/src/python/gnuradio/gr/prefs.py new file mode 100644 index 000000000..25fa8cd6a --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/prefs.py @@ -0,0 +1,127 @@ +# +# Copyright 2006,2009 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. +# + +import gnuradio_core as gsp +_prefs_base = gsp.gr_prefs + + +import ConfigParser +import os +import os.path +import sys +import glob + + +def _user_prefs_filename(): + return os.path.expanduser('~/.gnuradio/config.conf') + +def _sys_prefs_dirname(): + return gsp.prefsdir() + +def _bool(x): + """ + Try to coerce obj to a True or False + """ + if isinstance(x, bool): + return x + if isinstance(x, (float, int)): + return bool(x) + raise TypeError, x + + +class _prefs(_prefs_base): + """ + Derive our 'real class' from the stubbed out base class that has support + for SWIG directors. This allows C++ code to magically and transparently + invoke the methods in this python class. + """ + def __init__(self): + _prefs_base.__init__(self) + self.cp = ConfigParser.RawConfigParser() + self.__getattr__ = lambda self, name: getattr(self.cp, name) + + def _sys_prefs_filenames(self): + dir = _sys_prefs_dirname() + try: + fnames = glob.glob(os.path.join(dir, '*.conf')) + except (IOError, OSError): + return [] + fnames.sort() + return fnames + + def _read_files(self): + filenames = self._sys_prefs_filenames() + filenames.append(_user_prefs_filename()) + #print "filenames: ", filenames + self.cp.read(filenames) + + # ---------------------------------------------------------------- + # These methods override the C++ virtual methods of the same name + # ---------------------------------------------------------------- + def has_section(self, section): + return self.cp.has_section(section) + + def has_option(self, section, option): + return self.cp.has_option(section, option) + + def get_string(self, section, option, default_val): + try: + return self.cp.get(section, option) + except: + return default_val + + def get_bool(self, section, option, default_val): + try: + return self.cp.getboolean(section, option) + except: + return default_val + + def get_long(self, section, option, default_val): + try: + return self.cp.getint(section, option) + except: + return default_val + + def get_double(self, section, option, default_val): + try: + return self.cp.getfloat(section, option) + except: + return default_val + # ---------------------------------------------------------------- + # End override of C++ virtual methods + # ---------------------------------------------------------------- + + +_prefs_db = _prefs() + +# if GR_DONT_LOAD_PREFS is set, don't load them. +# (make check uses this to avoid interactions.) +if os.getenv("GR_DONT_LOAD_PREFS", None) is None: + _prefs_db._read_files() + + +_prefs_base.set_singleton(_prefs_db) # tell C++ what instance to use + +def prefs(): + """ + Return the global preference data base + """ + return _prefs_db diff --git a/gnuradio-core/src/python/gnuradio/gr/pubsub.py b/gnuradio-core/src/python/gnuradio/gr/pubsub.py new file mode 100644 index 000000000..90568418f --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/pubsub.py @@ -0,0 +1,153 @@ +#!/usr/bin/env python +# +# Copyright 2008,2009 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. +# + +""" +Abstract GNU Radio publisher/subscriber interface + +This is a proof of concept implementation, will likely change significantly. +""" + +class pubsub(dict): + def __init__(self): + self._publishers = { } + self._subscribers = { } + self._proxies = { } + + def __missing__(self, key, value=None): + dict.__setitem__(self, key, value) + self._publishers[key] = None + self._subscribers[key] = [] + self._proxies[key] = None + + def __setitem__(self, key, val): + if not self.has_key(key): + self.__missing__(key, val) + elif self._proxies[key] is not None: + (p, newkey) = self._proxies[key] + p[newkey] = val + else: + dict.__setitem__(self, key, val) + for sub in self._subscribers[key]: + # Note this means subscribers will get called in the thread + # context of the 'set' caller. + sub(val) + + def __getitem__(self, key): + if not self.has_key(key): self.__missing__(key) + if self._proxies[key] is not None: + (p, newkey) = self._proxies[key] + return p[newkey] + elif self._publishers[key] is not None: + return self._publishers[key]() + else: + return dict.__getitem__(self, key) + + def publish(self, key, publisher): + if not self.has_key(key): self.__missing__(key) + if self._proxies[key] is not None: + (p, newkey) = self._proxies[key] + p.publish(newkey, publisher) + else: + self._publishers[key] = publisher + + def subscribe(self, key, subscriber): + if not self.has_key(key): self.__missing__(key) + if self._proxies[key] is not None: + (p, newkey) = self._proxies[key] + p.subscribe(newkey, subscriber) + else: + self._subscribers[key].append(subscriber) + + def unpublish(self, key): + if self._proxies[key] is not None: + (p, newkey) = self._proxies[key] + p.unpublish(newkey) + else: + self._publishers[key] = None + + def unsubscribe(self, key, subscriber): + if self._proxies[key] is not None: + (p, newkey) = self._proxies[key] + p.unsubscribe(newkey, subscriber) + else: + self._subscribers[key].remove(subscriber) + + def proxy(self, key, p, newkey=None): + if not self.has_key(key): self.__missing__(key) + if newkey is None: newkey = key + self._proxies[key] = (p, newkey) + + def unproxy(self, key): + self._proxies[key] = None + +# Test code +if __name__ == "__main__": + import sys + o = pubsub() + + # Non-existent key gets auto-created with None value + print "Auto-created key 'foo' value:", o['foo'] + + # Add some subscribers + # First is a bare function + def print_len(x): + print "len=%i" % (len(x), ) + o.subscribe('foo', print_len) + + # The second is a class member function + class subber(object): + def __init__(self, param): + self._param = param + def printer(self, x): + print self._param, `x` + s = subber('param') + o.subscribe('foo', s.printer) + + # The third is a lambda function + o.subscribe('foo', lambda x: sys.stdout.write('val='+`x`+'\n')) + + # Update key 'foo', will notify subscribers + print "Updating 'foo' with three subscribers:" + o['foo'] = 'bar'; + + # Remove first subscriber + o.unsubscribe('foo', print_len) + + # Update now will only trigger second and third subscriber + print "Updating 'foo' after removing a subscriber:" + o['foo'] = 'bar2'; + + # Publish a key as a function, in this case, a lambda function + o.publish('baz', lambda : 42) + print "Published value of 'baz':", o['baz'] + + # Unpublish the key + o.unpublish('baz') + + # This will return None, as there is no publisher + print "Value of 'baz' with no publisher:", o['baz'] + + # Set 'baz' key, it gets cached + o['baz'] = 'bazzz' + + # Now will return cached value, since no provider + print "Cached value of 'baz' after being set:", o['baz'] diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_add_and_friends.py b/gnuradio-core/src/python/gnuradio/gr/qa_add_and_friends.py new file mode 100755 index 000000000..7ccbbe8ad --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_add_and_friends.py @@ -0,0 +1,163 @@ +#!/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 + +class test_add_and_friends (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def help_ii (self, src_data, exp_data, op): + for s in zip (range (len (src_data)), src_data): + src = gr.vector_source_i (s[1]) + self.tb.connect (src, (op, s[0])) + dst = gr.vector_sink_i () + self.tb.connect (op, dst) + self.tb.run () + result_data = dst.data () + self.assertEqual (exp_data, result_data) + + def help_ff (self, src_data, exp_data, op): + for s in zip (range (len (src_data)), src_data): + src = gr.vector_source_f (s[1]) + self.tb.connect (src, (op, s[0])) + dst = gr.vector_sink_f () + self.tb.connect (op, dst) + self.tb.run () + result_data = dst.data () + self.assertEqual (exp_data, result_data) + + def help_cc (self, src_data, exp_data, op): + for s in zip (range (len (src_data)), src_data): + src = gr.vector_source_c (s[1]) + self.tb.connect (src, (op, s[0])) + dst = gr.vector_sink_c () + self.tb.connect (op, dst) + self.tb.run () + result_data = dst.data () + self.assertEqual (exp_data, result_data) + + def test_add_const_ii (self): + src_data = (1, 2, 3, 4, 5) + expected_result = (6, 7, 8, 9, 10) + op = gr.add_const_ii (5) + self.help_ii ((src_data,), expected_result, op) + + def test_add_const_cc (self): + src_data = (1, 2, 3, 4, 5) + expected_result = (1+5j, 2+5j, 3+5j, 4+5j, 5+5j) + op = gr.add_const_cc (5j) + self.help_cc ((src_data,), expected_result, op) + + def test_mult_const_ii (self): + src_data = (-1, 0, 1, 2, 3) + expected_result = (-5, 0, 5, 10, 15) + op = gr.multiply_const_ii (5) + self.help_ii ((src_data,), expected_result, op) + + def test_mult_const_ff (self): + src_data = (-1, 0, 1, 2, 3) + expected_result = (-5, 0, 5, 10, 15) + op = gr.multiply_const_cc (5) + self.help_cc ((src_data,), expected_result, op) + + def test_mult_const_cc (self): + src_data = (-1-1j, 0+0j, 1+1j, 2+2j, 3+3j) + expected_result = (-5-5j, 0+0j, 5+5j, 10+10j, 15+15j) + op = gr.multiply_const_cc (5) + self.help_cc ((src_data,), expected_result, op) + + def test_mult_const_cc2 (self): + src_data = (-1-1j, 0+0j, 1+1j, 2+2j, 3+3j) + expected_result = (-3-7j, 0+0j, 3+7j, 6+14j, 9+21j) + op = gr.multiply_const_cc (5+2j) + self.help_cc ((src_data,), expected_result, op) + + def test_add_ii (self): + src1_data = (1, 2, 3, 4, 5) + src2_data = (8, -3, 4, 8, 2) + expected_result = (9, -1, 7, 12, 7) + op = gr.add_ii () + self.help_ii ((src1_data, src2_data), + expected_result, op) + + def test_mult_ii (self): + src1_data = (1, 2, 3, 4, 5) + src2_data = (8, -3, 4, 8, 2) + expected_result = (8, -6, 12, 32, 10) + op = gr.multiply_ii () + self.help_ii ((src1_data, src2_data), + expected_result, op) + + def test_mult_ff (self): + src1_data = (1, 2, 3, 4, 5) + src2_data = (8, -3, 4, 8, 2) + expected_result = (8, -6, 12, 32, 10) + op = gr.multiply_ff () + self.help_ff ((src1_data, src2_data), + expected_result, op) + + def test_mult_cc (self): + src1_data = (1+1j, 2+2j, 3+3j, 4+4j, 5+5j) + src2_data = (8, -3, 4, 8, 2) + expected_result = (8+8j, -6-6j, 12+12j, 32+32j, 10+10j) + op = gr.multiply_cc () + self.help_cc ((src1_data, src2_data), + expected_result, op) + + def test_sub_ii_1 (self): + src1_data = (1, 2, 3, 4, 5) + expected_result = (-1, -2, -3, -4, -5) + op = gr.sub_ii () + self.help_ii ((src1_data,), + expected_result, op) + + def test_sub_ii_2 (self): + src1_data = (1, 2, 3, 4, 5) + src2_data = (8, -3, 4, 8, 2) + expected_result = (-7, 5, -1, -4, 3) + op = gr.sub_ii () + self.help_ii ((src1_data, src2_data), + expected_result, op) + + def test_div_ff_1 (self): + src1_data = (1, 2, 4, -8) + expected_result = (1, 0.5, 0.25, -.125) + op = gr.divide_ff () + self.help_ff ((src1_data,), + expected_result, op) + + def test_div_ff_2 (self): + src1_data = ( 5, 9, -15, 1024) + src2_data = (10, 3, -5, 64) + expected_result = (0.5, 3, 3, 16) + op = gr.divide_ff () + self.help_ff ((src1_data, src2_data), + expected_result, op) + + +if __name__ == '__main__': + gr_unittest.run(test_add_and_friends, "test_add_and_friends.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_add_v_and_friends.py b/gnuradio-core/src/python/gnuradio/gr/qa_add_v_and_friends.py new file mode 100755 index 000000000..c8df47b39 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_add_v_and_friends.py @@ -0,0 +1,353 @@ +#!/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 + +class test_add_v_and_friends(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def help_ss(self, size, src_data, exp_data, op): + for s in zip(range (len (src_data)), src_data): + src = gr.vector_source_s(s[1]) + srcv = gr.stream_to_vector(gr.sizeof_short, size) + self.tb.connect(src, srcv) + self.tb.connect(srcv, (op, s[0])) + rhs = gr.vector_to_stream(gr.sizeof_short, size) + dst = gr.vector_sink_s() + self.tb.connect(op, rhs, dst) + self.tb.run() + result_data = dst.data() + self.assertEqual(exp_data, result_data) + + def help_ii(self, size, src_data, exp_data, op): + for s in zip(range (len (src_data)), src_data): + src = gr.vector_source_i(s[1]) + srcv = gr.stream_to_vector(gr.sizeof_int, size) + self.tb.connect(src, srcv) + self.tb.connect(srcv, (op, s[0])) + rhs = gr.vector_to_stream(gr.sizeof_int, size) + dst = gr.vector_sink_i() + self.tb.connect(op, rhs, dst) + self.tb.run() + result_data = dst.data() + self.assertEqual(exp_data, result_data) + + def help_ff(self, size, src_data, exp_data, op): + for s in zip(range (len (src_data)), src_data): + src = gr.vector_source_f(s[1]) + srcv = gr.stream_to_vector(gr.sizeof_float, size) + self.tb.connect(src, srcv) + self.tb.connect(srcv, (op, s[0])) + rhs = gr.vector_to_stream(gr.sizeof_float, size) + dst = gr.vector_sink_f() + self.tb.connect(op, rhs, dst) + self.tb.run() + result_data = dst.data() + self.assertEqual(exp_data, result_data) + + def help_cc(self, size, src_data, exp_data, op): + for s in zip(range (len (src_data)), src_data): + src = gr.vector_source_c(s[1]) + srcv = gr.stream_to_vector(gr.sizeof_gr_complex, size) + self.tb.connect(src, srcv) + self.tb.connect(srcv, (op, s[0])) + rhs = gr.vector_to_stream(gr.sizeof_gr_complex, size) + dst = gr.vector_sink_c() + self.tb.connect(op, rhs, dst) + self.tb.run() + result_data = dst.data() + self.assertEqual(exp_data, result_data) + + def help_const_ss(self, src_data, exp_data, op): + src = gr.vector_source_s(src_data) + srcv = gr.stream_to_vector(gr.sizeof_short, len(src_data)) + rhs = gr.vector_to_stream(gr.sizeof_short, len(src_data)) + dst = gr.vector_sink_s() + self.tb.connect(src, srcv, op, rhs, dst) + self.tb.run() + result_data = dst.data() + self.assertEqual(exp_data, result_data) + + def help_const_ii(self, src_data, exp_data, op): + src = gr.vector_source_i(src_data) + srcv = gr.stream_to_vector(gr.sizeof_int, len(src_data)) + rhs = gr.vector_to_stream(gr.sizeof_int, len(src_data)) + dst = gr.vector_sink_i() + self.tb.connect(src, srcv, op, rhs, dst) + self.tb.run() + result_data = dst.data() + self.assertEqual(exp_data, result_data) + + def help_const_ff(self, src_data, exp_data, op): + src = gr.vector_source_f(src_data) + srcv = gr.stream_to_vector(gr.sizeof_float, len(src_data)) + rhs = gr.vector_to_stream(gr.sizeof_float, len(src_data)) + dst = gr.vector_sink_f() + self.tb.connect(src, srcv, op, rhs, dst) + self.tb.run() + result_data = dst.data() + self.assertEqual(exp_data, result_data) + + def help_const_cc(self, src_data, exp_data, op): + src = gr.vector_source_c(src_data) + srcv = gr.stream_to_vector(gr.sizeof_gr_complex, len(src_data)) + rhs = gr.vector_to_stream(gr.sizeof_gr_complex, len(src_data)) + dst = gr.vector_sink_c() + self.tb.connect(src, srcv, op, rhs, dst) + self.tb.run() + result_data = dst.data() + self.assertEqual(exp_data, result_data) + + + def test_add_vss_one(self): + src1_data = (1,) + src2_data = (2,) + src3_data = (3,) + expected_result = (6,) + op = gr.add_vss(1) + self.help_ss(1, (src1_data, src2_data, src3_data), expected_result, op) + + def test_add_vss_five(self): + src1_data = (1, 2, 3, 4, 5) + src2_data = (6, 7, 8, 9, 10) + src3_data = (11, 12, 13, 14, 15) + expected_result = (18, 21, 24, 27, 30) + op = gr.add_vss(5) + self.help_ss(5, (src1_data, src2_data, src3_data), expected_result, op) + + def test_add_vii_one(self): + src1_data = (1,) + src2_data = (2,) + src3_data = (3,) + expected_result = (6,) + op = gr.add_vii(1) + self.help_ii(1, (src1_data, src2_data, src3_data), expected_result, op) + + def test_add_vii_five(self): + src1_data = (1, 2, 3, 4, 5) + src2_data = (6, 7, 8, 9, 10) + src3_data = (11, 12, 13, 14, 15) + expected_result = (18, 21, 24, 27, 30) + op = gr.add_vii(5) + self.help_ii(5, (src1_data, src2_data, src3_data), expected_result, op) + + def test_add_vff_one(self): + src1_data = (1.0,) + src2_data = (2.0,) + src3_data = (3.0,) + expected_result = (6.0,) + op = gr.add_vff(1) + self.help_ff(1, (src1_data, src2_data, src3_data), expected_result, op) + + def test_add_vff_five(self): + src1_data = (1.0, 2.0, 3.0, 4.0, 5.0) + src2_data = (6.0, 7.0, 8.0, 9.0, 10.0) + src3_data = (11.0, 12.0, 13.0, 14.0, 15.0) + expected_result = (18.0, 21.0, 24.0, 27.0, 30.0) + op = gr.add_vff(5) + self.help_ff(5, (src1_data, src2_data, src3_data), expected_result, op) + + def test_add_vcc_one(self): + src1_data = (1.0+2.0j,) + src2_data = (3.0+4.0j,) + src3_data = (5.0+6.0j,) + expected_result = (9.0+12j,) + op = gr.add_vcc(1) + self.help_cc(1, (src1_data, src2_data, src3_data), expected_result, op) + + def test_add_vcc_five(self): + src1_data = (1.0+2.0j, 3.0+4.0j, 5.0+6.0j, 7.0+8.0j, 9.0+10.0j) + src2_data = (11.0+12.0j, 13.0+14.0j, 15.0+16.0j, 17.0+18.0j, 19.0+20.0j) + src3_data = (21.0+22.0j, 23.0+24.0j, 25.0+26.0j, 27.0+28.0j, 29.0+30.0j) + expected_result = (33.0+36.0j, 39.0+42.0j, 45.0+48.0j, 51.0+54.0j, 57.0+60.0j) + op = gr.add_vcc(5) + self.help_cc(5, (src1_data, src2_data, src3_data), expected_result, op) + + def test_add_const_vss_one(self): + src_data = (1,) + op = gr.add_const_vss((2,)) + exp_data = (3,) + self.help_const_ss(src_data, exp_data, op) + + def test_add_const_vss_five(self): + src_data = (1, 2, 3, 4, 5) + op = gr.add_const_vss((6, 7, 8, 9, 10)) + exp_data = (7, 9, 11, 13, 15) + self.help_const_ss(src_data, exp_data, op) + + def test_add_const_vii_one(self): + src_data = (1,) + op = gr.add_const_vii((2,)) + exp_data = (3,) + self.help_const_ii(src_data, exp_data, op) + + def test_add_const_vii_five(self): + src_data = (1, 2, 3, 4, 5) + op = gr.add_const_vii((6, 7, 8, 9, 10)) + exp_data = (7, 9, 11, 13, 15) + self.help_const_ii(src_data, exp_data, op) + + def test_add_const_vff_one(self): + src_data = (1.0,) + op = gr.add_const_vff((2.0,)) + exp_data = (3.0,) + self.help_const_ff(src_data, exp_data, op) + + def test_add_const_vff_five(self): + src_data = (1.0, 2.0, 3.0, 4.0, 5.0) + op = gr.add_const_vff((6.0, 7.0, 8.0, 9.0, 10.0)) + exp_data = (7.0, 9.0, 11.0, 13.0, 15.0) + self.help_const_ff(src_data, exp_data, op) + + def test_add_const_vcc_one(self): + src_data = (1.0+2.0j,) + op = gr.add_const_vcc((2.0+3.0j,)) + exp_data = (3.0+5.0j,) + self.help_const_cc(src_data, exp_data, op) + + def test_add_const_vcc_five(self): + src_data = (1.0+2.0j, 3.0+4.0j, 5.0+6.0j, 7.0+8.0j, 9.0+10.0j) + op = gr.add_const_vcc((11.0+12.0j, 13.0+14.0j, 15.0+16.0j, 17.0+18.0j, 19.0+20.0j)) + exp_data = (12.0+14.0j, 16.0+18.0j, 20.0+22.0j, 24.0+26.0j, 28.0+30.0j) + self.help_const_cc(src_data, exp_data, op) + + + def test_multiply_vss_one(self): + src1_data = (1,) + src2_data = (2,) + src3_data = (3,) + expected_result = (6,) + op = gr.multiply_vss(1) + self.help_ss(1, (src1_data, src2_data, src3_data), expected_result, op) + + def test_multiply_vss_five(self): + src1_data = (1, 2, 3, 4, 5) + src2_data = (6, 7, 8, 9, 10) + src3_data = (11, 12, 13, 14, 15) + expected_result = (66, 168, 312, 504, 750) + op = gr.multiply_vss(5) + self.help_ss(5, (src1_data, src2_data, src3_data), expected_result, op) + + def test_multiply_vii_one(self): + src1_data = (1,) + src2_data = (2,) + src3_data = (3,) + expected_result = (6,) + op = gr.multiply_vii(1) + self.help_ii(1, (src1_data, src2_data, src3_data), expected_result, op) + + def test_multiply_vii_five(self): + src1_data = (1, 2, 3, 4, 5) + src2_data = (6, 7, 8, 9, 10) + src3_data = (11, 12, 13, 14, 15) + expected_result = (66, 168, 312, 504, 750) + op = gr.multiply_vii(5) + self.help_ii(5, (src1_data, src2_data, src3_data), expected_result, op) + + def test_multiply_vff_one(self): + src1_data = (1.0,) + src2_data = (2.0,) + src3_data = (3.0,) + expected_result = (6.0,) + op = gr.multiply_vff(1) + self.help_ff(1, (src1_data, src2_data, src3_data), expected_result, op) + + def test_multiply_vff_five(self): + src1_data = (1.0, 2.0, 3.0, 4.0, 5.0) + src2_data = (6.0, 7.0, 8.0, 9.0, 10.0) + src3_data = (11.0, 12.0, 13.0, 14.0, 15.0) + expected_result = (66.0, 168.0, 312.0, 504.0, 750.0) + op = gr.multiply_vff(5) + self.help_ff(5, (src1_data, src2_data, src3_data), expected_result, op) + + def test_multiply_vcc_one(self): + src1_data = (1.0+2.0j,) + src2_data = (3.0+4.0j,) + src3_data = (5.0+6.0j,) + expected_result = (-85+20j,) + op = gr.multiply_vcc(1) + self.help_cc(1, (src1_data, src2_data, src3_data), expected_result, op) + + def test_multiply_vcc_five(self): + src1_data = (1.0+2.0j, 3.0+4.0j, 5.0+6.0j, 7.0+8.0j, 9.0+10.0j) + src2_data = (11.0+12.0j, 13.0+14.0j, 15.0+16.0j, 17.0+18.0j, 19.0+20.0j) + src3_data = (21.0+22.0j, 23.0+24.0j, 25.0+26.0j, 27.0+28.0j, 29.0+30.0j) + expected_result = (-1021.0+428.0j, -2647.0+1754.0j, -4945.0+3704.0j, -8011.0+6374.0j, -11941.0+9860.0j) + op = gr.multiply_vcc(5) + self.help_cc(5, (src1_data, src2_data, src3_data), expected_result, op) + + def test_multiply_const_vss_one(self): + src_data = (2,) + op = gr.multiply_const_vss((3,)) + exp_data = (6,) + self.help_const_ss(src_data, exp_data, op) + + def test_multiply_const_vss_five(self): + src_data = (1, 2, 3, 4, 5) + op = gr.multiply_const_vss((6, 7, 8, 9, 10)) + exp_data = (6, 14, 24, 36, 50) + self.help_const_ss(src_data, exp_data, op) + + def test_multiply_const_vii_one(self): + src_data = (2,) + op = gr.multiply_const_vii((3,)) + exp_data = (6,) + self.help_const_ii(src_data, exp_data, op) + + def test_multiply_const_vii_five(self): + src_data = (1, 2, 3, 4, 5) + op = gr.multiply_const_vii((6, 7, 8, 9, 10)) + exp_data = (6, 14, 24, 36, 50) + self.help_const_ii(src_data, exp_data, op) + + def test_multiply_const_vff_one(self): + src_data = (2.0,) + op = gr.multiply_const_vff((3.0,)) + exp_data = (6.0,) + self.help_const_ff(src_data, exp_data, op) + + def test_multiply_const_vff_five(self): + src_data = (1.0, 2.0, 3.0, 4.0, 5.0) + op = gr.multiply_const_vff((6.0, 7.0, 8.0, 9.0, 10.0)) + exp_data = (6.0, 14.0, 24.0, 36.0, 50.0) + self.help_const_ff(src_data, exp_data, op) + + def test_multiply_const_vcc_one(self): + src_data = (1.0+2.0j,) + op = gr.multiply_const_vcc((2.0+3.0j,)) + exp_data = (-4.0+7.0j,) + self.help_const_cc(src_data, exp_data, op) + + def test_multiply_const_vcc_five(self): + src_data = (1.0+2.0j, 3.0+4.0j, 5.0+6.0j, 7.0+8.0j, 9.0+10.0j) + op = gr.multiply_const_vcc((11.0+12.0j, 13.0+14.0j, 15.0+16.0j, 17.0+18.0j, 19.0+20.0j)) + exp_data = (-13.0+34.0j, -17.0+94.0j, -21.0+170.0j, -25.0+262.0j, -29.0+370.0j) + self.help_const_cc(src_data, exp_data, op) + + +if __name__ == '__main__': + gr_unittest.run(test_add_v_and_friends, "test_add_v_and_friends.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_affinity.py b/gnuradio-core/src/python/gnuradio/gr/qa_affinity.py new file mode 100644 index 000000000..7b3ca6ed6 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_affinity.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python +# +# Copyright 2013 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_affinity(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_000(self): + # Just run some data through and make sure it doesn't puke. + src_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + + src = gr.vector_source_f(src_data) + snk = gr.vector_sink_f() + + src.set_processor_affinity([0,]) + self.tb.connect(src, snk) + self.tb.run() + + a = src.processor_affinity() + + self.assertEqual((0,), a) + +if __name__ == '__main__': + gr_unittest.run(test_affinity, "test_affinity.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_agc.py b/gnuradio-core/src/python/gnuradio/gr/qa_agc.py new file mode 100755 index 000000000..9fd633576 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_agc.py @@ -0,0 +1,433 @@ +#!/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 + +test_output = False + +class test_agc (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + + def test_001(self): + ''' Test the complex AGC loop (single rate input) ''' + tb = self.tb + + expected_result = ( + (100.000244140625+7.2191943445432116e-07j), + (72.892257690429688+52.959323883056641j), + (25.089065551757812+77.216217041015625j), + (-22.611061096191406+69.589706420898438j), + (-53.357715606689453+38.766635894775391j), + (-59.458671569824219+3.4792964243024471e-07j), + (-43.373462677001953-31.512666702270508j), + (-14.94139289855957-45.984889984130859j), + (13.478158950805664-41.48150634765625j), + (31.838506698608398-23.132022857666016j), + (35.519271850585938-3.1176801940091536e-07j), + (25.942903518676758+18.848621368408203j), + (8.9492912292480469+27.5430908203125j), + (-8.0852642059326172+24.883890151977539j), + (-19.131628036499023+13.899936676025391j), + (-21.383295059204102+3.1281737733479531e-07j), + (-15.650330543518066-11.370632171630859j), + (-5.4110145568847656-16.65339469909668j), + (4.9008159637451172-15.083160400390625j), + (11.628337860107422-8.4484796524047852j), + (13.036135673522949-2.288476110834381e-07j), + (9.5726661682128906+6.954948902130127j), + (3.3216962814331055+10.223132133483887j), + (-3.0204284191131592+9.2959251403808594j), + (-7.1977195739746094+5.2294478416442871j), + (-8.1072216033935547+1.8976157889483147e-07j), + (-5.9838657379150391-4.3475332260131836j), + (-2.0879747867584229-6.4261269569396973j), + (1.9100792407989502-5.8786196708679199j), + (4.5814824104309082-3.3286411762237549j), + (5.1967458724975586-1.3684227440080576e-07j), + (3.8647139072418213+2.8078789710998535j), + (1.3594740629196167+4.1840314865112305j), + (-1.2544282674789429+3.8607344627380371j), + (-3.0366206169128418+2.2062335014343262j), + (-3.4781389236450195+1.1194014604143376e-07j), + (-2.6133756637573242-1.8987287282943726j), + (-0.9293016791343689-2.8600969314575195j), + (0.86727333068847656-2.6691930294036865j), + (2.1243946552276611-1.5434627532958984j), + (2.4633183479309082-8.6486437567145913e-08j), + (1.8744727373123169+1.3618841171264648j), + (0.67528903484344482+2.0783262252807617j), + (-0.63866174221038818+1.965599536895752j), + (-1.5857341289520264+1.152103066444397j), + (-1.8640764951705933+7.6355092915036948e-08j), + (-1.4381576776504517-1.0448826551437378j), + (-0.52529704570770264-1.6166983842849731j), + (0.50366902351379395-1.5501341819763184j), + (1.26766037940979-0.92100900411605835j)) + + sampling_freq = 100 + src1 = gr.sig_source_c (sampling_freq, gr.GR_SIN_WAVE, + sampling_freq * 0.10, 100.0) + dst1 = gr.vector_sink_c () + head = gr.head (gr.sizeof_gr_complex, int (5*sampling_freq * 0.10)) + + agc = gr.agc_cc(1e-3, 1, 1, 1000) + + tb.connect (src1, head) + tb.connect (head, agc) + tb.connect (agc, dst1) + + if test_output == True: + tb.connect (agc, gr.file_sink(gr.sizeof_gr_complex, "test_agc_cc.dat")) + + tb.run () + dst_data = dst1.data () + self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 4) + + def test_002(self): + ''' Test the floating point AGC loop (single rate input) ''' + tb = self.tb + + expected_result = ( + 7.2191943445432116e-07, + 58.837181091308594, + 89.700050354003906, + 81.264183044433594, + 45.506141662597656, + 4.269894304798072e-07, + -42.948936462402344, + -65.50335693359375, + -59.368724822998047, + -33.261005401611328, + -4.683740257860336e-07, + 31.423542022705078, + 47.950984954833984, + 43.485683441162109, + 24.378345489501953, + 5.7254135299444897e-07, + -23.062990188598633, + -35.218441009521484, + -31.964075088500977, + -17.934831619262695, + -5.0591745548445033e-07, + 16.998210906982422, + 25.982204437255859, + 23.606258392333984, + 13.260685920715332, + 4.9936483037527069e-07, + -12.59880542755127, + -19.28221321105957, + -17.54347038269043, + -9.8700437545776367, + -4.188150626305287e-07, + 9.4074573516845703, + 14.422011375427246, + 13.145503044128418, + 7.41046142578125, + 3.8512698097292741e-07, + -7.0924453735351562, + -10.896408081054688, + -9.9552040100097656, + -5.6262712478637695, + -3.1982864356905338e-07, + 5.4131259918212891, + 8.3389215469360352, + 7.6409502029418945, + 4.3320145606994629, + 2.882407841298118e-07, + -4.194943904876709, + -6.4837145805358887, + -5.9621825218200684, + -3.3931560516357422) + + sampling_freq = 100 + src1 = gr.sig_source_f (sampling_freq, gr.GR_SIN_WAVE, + sampling_freq * 0.10, 100.0) + dst1 = gr.vector_sink_f () + head = gr.head (gr.sizeof_float, int (5*sampling_freq * 0.10)) + + agc = gr.agc_ff(1e-3, 1, 1, 1000) + + tb.connect (src1, head) + tb.connect (head, agc) + tb.connect (agc, dst1) + + if test_output == True: + tb.connect (agc, gr.file_sink(gr.sizeof_float, "test_agc_ff.dat")) + + tb.run () + dst_data = dst1.data () + self.assertFloatTuplesAlmostEqual (expected_result, dst_data, 4) + + def test_003(self): + ''' Test the complex AGC loop (attack and decay rate inputs) ''' + tb = self.tb + + expected_result = \ + ((100.000244140625+7.2191943445432116e-07j), + (0.80881959199905396+0.58764183521270752j), + (0.30894950032234192+0.95084899663925171j), + (-0.30895623564720154+0.95086973905563354j), + (-0.80887287855148315+0.58768033981323242j), + (-0.99984413385391235+5.850709250410091e-09j), + (-0.80889981985092163-0.58770018815994263j), + (-0.30897706747055054-0.95093393325805664j), + (0.30898112058639526-0.95094609260559082j), + (0.80893135070800781-0.58772283792495728j), + (0.99990922212600708-8.7766354184282136e-09j), + (0.80894720554351807+0.58773452043533325j), + (0.30899339914321899+0.95098406076431274j), + (-0.30899572372436523+0.95099133253097534j), + (-0.80896598100662231+0.58774799108505249j), + (-0.99994778633117676+1.4628290578855285e-08j), + (-0.80897533893585205-0.58775502443313599j), + (-0.30900305509567261-0.95101380348205566j), + (0.30900448560714722-0.95101797580718994j), + (0.80898630619049072-0.58776277303695679j), + (0.99997037649154663-1.7554345532744264e-08j), + (0.80899184942245483+0.58776694536209106j), + (0.30900871753692627+0.95103120803833008j), + (-0.30900952219963074+0.95103377103805542j), + (-0.8089984655380249+0.58777159452438354j), + (-0.99998390674591064+2.3406109050938539e-08j), + (-0.809001624584198-0.58777409791946411j), + (-0.30901208519935608-0.95104163885116577j), + (0.30901262164115906-0.95104306936264038j), + (0.80900543928146362-0.587776780128479j), + (0.99999171495437622-2.6332081404234486e-08j), + (0.80900734663009644+0.58777821063995361j), + (0.30901408195495605+0.95104765892028809j), + (-0.30901429057121277+0.95104855298995972j), + (-0.80900967121124268+0.58777981996536255j), + (-0.99999648332595825+3.2183805842578295e-08j), + (-0.80901080369949341-0.58778077363967896j), + (-0.30901527404785156-0.95105135440826416j), + (0.30901545286178589-0.95105189085006714j), + (0.80901217460632324-0.58778166770935059j), + (0.99999916553497314-3.5109700036173308e-08j), + (0.809012770652771+0.58778214454650879j), + (0.30901595950126648+0.9510534405708313j), + (-0.30901598930358887+0.95105385780334473j), + (-0.80901366472244263+0.58778274059295654j), + (-1.0000008344650269+4.0961388947380328e-08j), + (-0.8090139627456665-0.58778303861618042j), + (-0.30901634693145752-0.95105475187301636j), + (0.30901640653610229-0.95105493068695068j), + (0.80901449918746948-0.5877833366394043j)) + + sampling_freq = 100 + src1 = gr.sig_source_c (sampling_freq, gr.GR_SIN_WAVE, + sampling_freq * 0.10, 100) + dst1 = gr.vector_sink_c () + head = gr.head (gr.sizeof_gr_complex, int (5*sampling_freq * 0.10)) + + agc = gr.agc2_cc(1e-2, 1e-3, 1, 1, 1000) + + tb.connect (src1, head) + tb.connect (head, agc) + tb.connect (agc, dst1) + + if test_output == True: + tb.connect (agc, gr.file_sink(gr.sizeof_gr_complex, "test_agc2_cc.dat")) + + tb.run () + dst_data = dst1.data () + self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 4) + + def test_004(self): + ''' Test the floating point AGC loop (attack and decay rate inputs) ''' + tb = self.tb + + expected_result = \ + (7.2191943445432116e-07, + 58.837181091308594, + 40.194305419921875, + 2.9183335304260254, + 0.67606079578399658, + 8.6260438791896377e-09, + -1.4542514085769653, + -1.9210131168365479, + -1.0450780391693115, + -0.61939650774002075, + -1.2590258613442984e-08, + 1.4308931827545166, + 1.9054338932037354, + 1.0443156957626343, + 0.61937344074249268, + 2.0983527804219193e-08, + -1.4308838844299316, + -1.9054274559020996, + -1.0443152189254761, + -0.61937344074249268, + -2.5180233009791664e-08, + 1.4308837652206421, + 1.9054274559020996, + 1.0443154573440552, + 0.61937344074249268, + 3.3573645197293445e-08, + -1.4308838844299316, + -1.9054274559020996, + -1.0443152189254761, + -0.61937350034713745, + -3.7770352179222755e-08, + 1.4308837652206421, + 1.9054274559020996, + 1.0443154573440552, + 0.61937350034713745, + 4.6163762590367696e-08, + -1.4308838844299316, + -1.9054274559020996, + -1.0443153381347656, + -0.61937344074249268, + -5.0360466019583328e-08, + 1.4308837652206421, + 1.9054274559020996, + 1.0443155765533447, + 0.61937344074249268, + 5.8753879983441948e-08, + -1.4308837652206421, + -1.9054274559020996, + -1.0443153381347656, + -0.61937344074249268) + + sampling_freq = 100 + src1 = gr.sig_source_f (sampling_freq, gr.GR_SIN_WAVE, + sampling_freq * 0.10, 100) + dst1 = gr.vector_sink_f () + head = gr.head (gr.sizeof_float, int (5*sampling_freq * 0.10)) + + agc = gr.agc2_ff(1e-2, 1e-3, 1, 1, 1000) + + tb.connect (src1, head) + tb.connect (head, agc) + tb.connect (agc, dst1) + + if test_output == True: + tb.connect (agc, gr.file_sink(gr.sizeof_float, "test_agc2_ff.dat")) + + tb.run () + dst_data = dst1.data () + self.assertFloatTuplesAlmostEqual (expected_result, dst_data, 4) + + + def test_005(self): + ''' Test the complex AGC loop (attack and decay rate inputs) ''' + tb = self.tb + + expected_result = \ + ((100.000244140625+7.2191943445432116e-07j), + (0.80881959199905396+0.58764183521270752j), + (0.30894950032234192+0.95084899663925171j), + (-0.30895623564720154+0.95086973905563354j), + (-0.80887287855148315+0.58768033981323242j), + (-0.99984413385391235+5.850709250410091e-09j), + (-0.80889981985092163-0.58770018815994263j), + (-0.30897706747055054-0.95093393325805664j), + (0.30898112058639526-0.95094609260559082j), + (0.80893135070800781-0.58772283792495728j), + (0.99990922212600708-8.7766354184282136e-09j), + (0.80894720554351807+0.58773452043533325j), + (0.30899339914321899+0.95098406076431274j), + (-0.30899572372436523+0.95099133253097534j), + (-0.80896598100662231+0.58774799108505249j), + (-0.99994778633117676+1.4628290578855285e-08j), + (-0.80897533893585205-0.58775502443313599j), + (-0.30900305509567261-0.95101380348205566j), + (0.30900448560714722-0.95101797580718994j), + (0.80898630619049072-0.58776277303695679j), + (0.99997037649154663-1.7554345532744264e-08j), + (0.80899184942245483+0.58776694536209106j), + (0.30900871753692627+0.95103120803833008j), + (-0.30900952219963074+0.95103377103805542j), + (-0.8089984655380249+0.58777159452438354j), + (-0.99998390674591064+2.3406109050938539e-08j), + (-0.809001624584198-0.58777409791946411j), + (-0.30901208519935608-0.95104163885116577j), + (0.30901262164115906-0.95104306936264038j), + (0.80900543928146362-0.587776780128479j), + (0.99999171495437622-2.6332081404234486e-08j), + (0.80900734663009644+0.58777821063995361j), + (0.30901408195495605+0.95104765892028809j), + (-0.30901429057121277+0.95104855298995972j), + (-0.80900967121124268+0.58777981996536255j), + (-0.99999648332595825+3.2183805842578295e-08j), + (-0.80901080369949341-0.58778077363967896j), + (-0.30901527404785156-0.95105135440826416j), + (0.30901545286178589-0.95105189085006714j), + (0.80901217460632324-0.58778166770935059j), + (0.99999916553497314-3.5109700036173308e-08j), + (0.809012770652771+0.58778214454650879j), + (0.30901595950126648+0.9510534405708313j), + (-0.30901598930358887+0.95105385780334473j), + (-0.80901366472244263+0.58778274059295654j), + (-1.0000008344650269+4.0961388947380328e-08j), + (-0.8090139627456665-0.58778303861618042j), + (-0.30901634693145752-0.95105475187301636j), + (0.30901640653610229-0.95105493068695068j), + (0.80901449918746948-0.5877833366394043j)) + + sampling_freq = 100 + src1 = gr.sig_source_c (sampling_freq, gr.GR_SIN_WAVE, + sampling_freq * 0.10, 100) + dst1 = gr.vector_sink_c () + head = gr.head (gr.sizeof_gr_complex, int (5*sampling_freq * 0.10)) + + agc = gr.agc2_cc(1e-2, 1e-3, 1, 1, 1000) + + tb.connect (src1, head) + tb.connect (head, agc) + tb.connect (agc, dst1) + + if test_output == True: + tb.connect (agc, gr.file_sink(gr.sizeof_gr_complex, "test_agc2_cc.dat")) + + tb.run () + dst_data = dst1.data () + self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 4) + + + def test_100(self): # FIXME needs work + ''' Test complex feedforward agc with constant input ''' + input_data = 16*(0.0,) + 64*(1.0,) + 64*(0.0,) + expected_result = () + + src = gr.vector_source_c(input_data) + agc = gr.feedforward_agc_cc(16, 2.0) + dst = gr.vector_sink_c () + self.tb.connect (src, agc, dst) + + if test_output == True: + self.tb.connect (agc, gr.file_sink(gr.sizeof_gr_complex, "test_feedforward_cc.dat")) + + self.tb.run () + dst_data = dst.data () + #self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 4) + + +if __name__ == '__main__': + gr_unittest.run(test_agc, "test_agc.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_argmax.py b/gnuradio-core/src/python/gnuradio/gr/qa_argmax.py new file mode 100644 index 000000000..564eb620b --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_argmax.py @@ -0,0 +1,77 @@ +#!/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 +import math + + +class test_arg_max (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + + def tearDown (self): + self.tb = None + + + def test_001(self): + tb = self.tb + + src1_data = (0,0.2,-0.3,0,12,0) + src2_data = (0,0.0,3.0,0,10,0) + src3_data = (0,0.0,3.0,0,1,0) + + src1 = gr.vector_source_f (src1_data) + s2v1 = gr.stream_to_vector(gr.sizeof_float, len(src1_data)) + tb.connect( src1, s2v1 ) + + src2 = gr.vector_source_f (src2_data) + s2v2 = gr.stream_to_vector(gr.sizeof_float, len(src1_data)) + tb.connect( src2, s2v2 ) + + src3 = gr.vector_source_f (src3_data) + s2v3 = gr.stream_to_vector(gr.sizeof_float, len(src1_data)) + tb.connect( src3, s2v3 ) + + dst1 = gr.vector_sink_s () + dst2 = gr.vector_sink_s () + argmax = gr.argmax_fs (len(src1_data)) + + tb.connect (s2v1, (argmax, 0)) + tb.connect (s2v2, (argmax, 1)) + tb.connect (s2v3, (argmax, 2)) + + tb.connect ((argmax,0), dst1) + tb.connect ((argmax,1), dst2) + + tb.run () + index = dst1.data () + source = dst2.data () + self.assertEqual ( index, (4,)) + self.assertEqual ( source, (0,)) + + + +if __name__ == '__main__': + gr_unittest.run(test_arg_max, "test_arg_max.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_bin_statistics.py b/gnuradio-core/src/python/gnuradio/gr/qa_bin_statistics.py new file mode 100755 index 000000000..8a6dd9056 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_bin_statistics.py @@ -0,0 +1,230 @@ +#!/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 random +import struct + +#import os +#print "pid =", os.getpid() +#raw_input("Attach gdb and press return...") + +""" +Note: The QA tests below have been disabled by renaming them from test_* +to xtest_*. See ticket:199 on http://gnuradio.org/trac/ticket/199 +""" + +class counter(gr.feval_dd): + def __init__(self, step_size=1): + gr.feval_dd.__init__(self) + self.step_size = step_size + self.count = 0 + + def eval(self, input): + #print "eval: self.count =", self.count + t = self.count + self.count = self.count + self.step_size + return t + + +class counter3(gr.feval_dd): + def __init__(self, f, step_size): + gr.feval_dd.__init__(self) + self.f = f + self.step_size = step_size + self.count = 0 + + def eval(self, input): + try: + #print "eval: self.count =", self.count + t = self.count + self.count = self.count + self.step_size + self.f(self.count) + except Exception, e: + print "Exception: ", e + return t + +def foobar3(new_t): + #print "foobar3: new_t =", new_t + pass + + +class counter4(gr.feval_dd): + def __init__(self, obj_instance, step_size): + gr.feval_dd.__init__(self) + self.obj_instance = obj_instance + self.step_size = step_size + self.count = 0 + + def eval(self, input): + try: + #print "eval: self.count =", self.count + t = self.count + self.count = self.count + self.step_size + self.obj_instance.foobar4(self.count) + except Exception, e: + print "Exception: ", e + return t + + +class parse_msg(object): + def __init__(self, msg): + self.center_freq = msg.arg1() + self.vlen = int(msg.arg2()) + assert(msg.length() == self.vlen * gr.sizeof_float) + self.data = struct.unpack('%df' % (self.vlen,), msg.to_string()) + +# FIXME: see ticket:199 +class xtest_bin_statistics(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block () + + def tearDown(self): + self.tb = None + + def xtest_001(self): + vlen = 4 + tune = counter(1) + tune_delay = 0 + dwell_delay = 1 + msgq = gr.msg_queue() + + src_data = tuple([float(x) for x in + ( 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16 + )]) + + expected_results = tuple([float(x) for x in + ( 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16 + )]) + + src = gr.vector_source_f(src_data, False) + s2v = gr.stream_to_vector(gr.sizeof_float, vlen) + stats = gr.bin_statistics_f(vlen, msgq, tune, tune_delay, dwell_delay) + self.tb.connect(src, s2v, stats) + self.tb.run() + self.assertEqual(4, msgq.count()) + for i in range(4): + m = parse_msg(msgq.delete_head()) + #print "m =", m.center_freq, m.data + self.assertEqual(expected_results[vlen*i:vlen*i + vlen], m.data) + + def xtest_002(self): + vlen = 4 + tune = counter(1) + tune_delay = 1 + dwell_delay = 2 + msgq = gr.msg_queue() + + src_data = tuple([float(x) for x in + ( 1, 2, 3, 4, + 9, 6, 11, 8, + 5, 10, 7, 12, + 13, 14, 15, 16 + )]) + + expected_results = tuple([float(x) for x in + ( 9, 10, 11, 12)]) + + src = gr.vector_source_f(src_data, False) + s2v = gr.stream_to_vector(gr.sizeof_float, vlen) + stats = gr.bin_statistics_f(vlen, msgq, tune, tune_delay, dwell_delay) + self.tb.connect(src, s2v, stats) + self.tb.run() + self.assertEqual(1, msgq.count()) + for i in range(1): + m = parse_msg(msgq.delete_head()) + #print "m =", m.center_freq, m.data + self.assertEqual(expected_results[vlen*i:vlen*i + vlen], m.data) + + + + def xtest_003(self): + vlen = 4 + tune = counter3(foobar3, 1) + tune_delay = 1 + dwell_delay = 2 + msgq = gr.msg_queue() + + src_data = tuple([float(x) for x in + ( 1, 2, 3, 4, + 9, 6, 11, 8, + 5, 10, 7, 12, + 13, 14, 15, 16 + )]) + + expected_results = tuple([float(x) for x in + ( 9, 10, 11, 12)]) + + src = gr.vector_source_f(src_data, False) + s2v = gr.stream_to_vector(gr.sizeof_float, vlen) + stats = gr.bin_statistics_f(vlen, msgq, tune, tune_delay, dwell_delay) + self.tb.connect(src, s2v, stats) + self.tb.run() + self.assertEqual(1, msgq.count()) + for i in range(1): + m = parse_msg(msgq.delete_head()) + #print "m =", m.center_freq, m.data + self.assertEqual(expected_results[vlen*i:vlen*i + vlen], m.data) + + + def foobar4(self, new_t): + #print "foobar4: new_t =", new_t + pass + + def xtest_004(self): + vlen = 4 + tune = counter4(self, 1) + tune_delay = 1 + dwell_delay = 2 + msgq = gr.msg_queue() + + src_data = tuple([float(x) for x in + ( 1, 2, 3, 4, + 9, 6, 11, 8, + 5, 10, 7, 12, + 13, 14, 15, 16 + )]) + + expected_results = tuple([float(x) for x in + ( 9, 10, 11, 12)]) + + src = gr.vector_source_f(src_data, False) + s2v = gr.stream_to_vector(gr.sizeof_float, vlen) + stats = gr.bin_statistics_f(vlen, msgq, tune, tune_delay, dwell_delay) + self.tb.connect(src, s2v, stats) + self.tb.run() + self.assertEqual(1, msgq.count()) + for i in range(1): + m = parse_msg(msgq.delete_head()) + #print "m =", m.center_freq, m.data + self.assertEqual(expected_results[vlen*i:vlen*i + vlen], m.data) + + +if __name__ == '__main__': + gr_unittest.run(xtest_bin_statistics, "test_bin_statistics.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_block_gateway.py b/gnuradio-core/src/python/gnuradio/gr/qa_block_gateway.py new file mode 100644 index 000000000..911879f6f --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_block_gateway.py @@ -0,0 +1,235 @@ +# +# 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. +# + +from gnuradio import gr, gr_unittest +import pmt +import numpy + +class add_2_f32_1_f32(gr.sync_block): + def __init__(self): + gr.sync_block.__init__( + self, + name = "add 2 f32", + in_sig = [numpy.float32, numpy.float32], + out_sig = [numpy.float32], + ) + + def work(self, input_items, output_items): + output_items[0][:] = input_items[0] + input_items[1] + return len(output_items[0]) + +class add_2_fc32_1_fc32(gr.sync_block): + def __init__(self): + gr.sync_block.__init__( + self, + name = "add 2 fc32", + in_sig = [numpy.complex64, numpy.complex64], + out_sig = [numpy.complex64], + ) + + def work(self, input_items, output_items): + output_items[0][:] = input_items[0] + input_items[1] + return len(output_items[0]) + +class convolve(gr.sync_block): + """ + A demonstration using block history to properly perform a convolution. + """ + def __init__(self): + gr.sync_block.__init__( + self, + name = "convolve", + in_sig = [numpy.float32], + out_sig = [numpy.float32] + ) + self._taps = [1, 0, 0, 0] + self.set_history(len(self._taps)) + + def work(self, input_items, output_items): + output_items[0][:] = numpy.convolve(input_items[0], self._taps, mode='valid') + return len(output_items[0]) + +class decim2x(gr.decim_block): + def __init__(self): + gr.decim_block.__init__( + self, + name = "decim2x", + in_sig = [numpy.float32], + out_sig = [numpy.float32], + decim = 2 + ) + + def work(self, input_items, output_items): + output_items[0][:] = input_items[0][::2] + return len(output_items[0]) + +class interp2x(gr.interp_block): + def __init__(self): + gr.interp_block.__init__( + self, + name = "interp2x", + in_sig = [numpy.float32], + out_sig = [numpy.float32], + interp = 2 + ) + + def work(self, input_items, output_items): + output_items[0][1::2] = input_items[0] + output_items[0][::2] = input_items[0] + return len(output_items[0]) + +class tag_source(gr.sync_block): + def __init__(self): + gr.sync_block.__init__( + self, + name = "tag source", + in_sig = None, + out_sig = [numpy.float32], + ) + + def work(self, input_items, output_items): + num_output_items = len(output_items[0]) + + #put code here to fill the output items... + + #make a new tag on the middle element every time work is called + count = self.nitems_written(0) + num_output_items/2 + key = pmt.pmt_string_to_symbol("example_key") + value = pmt.pmt_string_to_symbol("example_value") + self.add_item_tag(0, count, key, value) + + return num_output_items + +class tag_sink(gr.sync_block): + def __init__(self): + gr.sync_block.__init__( + self, + name = "tag sink", + in_sig = [numpy.float32], + out_sig = None, + ) + self.key = None + + def work(self, input_items, output_items): + num_input_items = len(input_items[0]) + + #put code here to process the input items... + + #print all the tags received in this work call + nread = self.nitems_read(0) + tags = self.get_tags_in_range(0, nread, nread+num_input_items) + for tag in tags: + #print tag.offset + #print pmt.pmt_symbol_to_string(tag.key) + #print pmt.pmt_symbol_to_string(tag.value) + self.key = pmt.pmt_symbol_to_string(tag.key) + + return num_input_items + +class fc32_to_f32_2(gr.sync_block): + def __init__(self): + gr.sync_block.__init__( + self, + name = "fc32_to_f32_2", + in_sig = [numpy.complex64], + out_sig = [(numpy.float32, 2)], + ) + + def work(self, input_items, output_items): + output_items[0][::,0] = numpy.real(input_items[0]) + output_items[0][::,1] = numpy.imag(input_items[0]) + return len(output_items[0]) + +class test_block_gateway(gr_unittest.TestCase): + + def test_add_f32(self): + tb = gr.top_block() + src0 = gr.vector_source_f([1, 3, 5, 7, 9], False) + src1 = gr.vector_source_f([0, 2, 4, 6, 8], False) + adder = add_2_f32_1_f32() + sink = gr.vector_sink_f() + tb.connect((src0, 0), (adder, 0)) + tb.connect((src1, 0), (adder, 1)) + tb.connect(adder, sink) + tb.run() + self.assertEqual(sink.data(), (1, 5, 9, 13, 17)) + + def test_add_fc32(self): + tb = gr.top_block() + src0 = gr.vector_source_c([1, 3j, 5, 7j, 9], False) + src1 = gr.vector_source_c([0, 2j, 4, 6j, 8], False) + adder = add_2_fc32_1_fc32() + sink = gr.vector_sink_c() + tb.connect((src0, 0), (adder, 0)) + tb.connect((src1, 0), (adder, 1)) + tb.connect(adder, sink) + tb.run() + self.assertEqual(sink.data(), (1, 5j, 9, 13j, 17)) + + def test_convolve(self): + tb = gr.top_block() + src = gr.vector_source_f([1, 2, 3, 4, 5, 6, 7, 8], False) + cv = convolve() + sink = gr.vector_sink_f() + tb.connect(src, cv, sink) + tb.run() + self.assertEqual(sink.data(), (1, 2, 3, 4, 5, 6, 7, 8)) + + def test_decim2x(self): + tb = gr.top_block() + src = gr.vector_source_f([1, 2, 3, 4, 5, 6, 7, 8], False) + d2x = decim2x() + sink = gr.vector_sink_f() + tb.connect(src, d2x, sink) + tb.run() + self.assertEqual(sink.data(), (1, 3, 5, 7)) + + def test_interp2x(self): + tb = gr.top_block() + src = gr.vector_source_f([1, 3, 5, 7, 9], False) + i2x = interp2x() + sink = gr.vector_sink_f() + tb.connect(src, i2x, sink) + tb.run() + self.assertEqual(sink.data(), (1, 1, 3, 3, 5, 5, 7, 7, 9, 9)) + + def test_tags(self): + src = tag_source() + sink = tag_sink() + head = gr.head(gr.sizeof_float, 50000) #should be enough items to get a tag through + tb = gr.top_block() + tb.connect(src, head, sink) + tb.run() + self.assertEqual(sink.key, "example_key") + + def test_fc32_to_f32_2(self): + tb = gr.top_block() + src = gr.vector_source_c([1+2j, 3+4j, 5+6j, 7+8j, 9+10j], False) + convert = fc32_to_f32_2() + v2s = gr.vector_to_stream(gr.sizeof_float, 2) + sink = gr.vector_sink_f() + tb.connect(src, convert, v2s, sink) + tb.run() + self.assertEqual(sink.data(), (1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) + +if __name__ == '__main__': + gr_unittest.run(test_block_gateway, "test_block_gateway.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_boolean_operators.py b/gnuradio-core/src/python/gnuradio/gr/qa_boolean_operators.py new file mode 100755 index 000000000..d7d134dcb --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_boolean_operators.py @@ -0,0 +1,162 @@ +#!/usr/bin/env python +# +# Copyright 2004,2007,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_boolean_operators (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def help_ss (self, src_data, exp_data, op): + for s in zip (range (len (src_data)), src_data): + src = gr.vector_source_s (s[1]) + self.tb.connect (src, (op, s[0])) + dst = gr.vector_sink_s () + self.tb.connect (op, dst) + self.tb.run () + result_data = dst.data () + self.assertEqual (exp_data, result_data) + + def help_bb (self, src_data, exp_data, op): + for s in zip (range (len (src_data)), src_data): + src = gr.vector_source_b (s[1]) + self.tb.connect (src, (op, s[0])) + dst = gr.vector_sink_b () + self.tb.connect (op, dst) + self.tb.run () + result_data = dst.data () + self.assertEqual (exp_data, result_data) + + def help_ii (self, src_data, exp_data, op): + for s in zip (range (len (src_data)), src_data): + src = gr.vector_source_i (s[1]) + self.tb.connect (src, (op, s[0])) + dst = gr.vector_sink_i () + self.tb.connect (op, dst) + self.tb.run () + result_data = dst.data () + self.assertEqual (exp_data, result_data) + + def test_xor_ss (self): + src1_data = (1, 2, 3, 0x5004, 0x1150) + src2_data = (8, 2, 1 , 0x0508, 0x1105) + expected_result = (9, 0, 2, 0x550C, 0x0055) + op = gr.xor_ss () + self.help_ss ((src1_data, src2_data), + expected_result, op) + + def test_xor_bb (self): + src1_data = (1, 2, 3, 4, 0x50) + src2_data = (8, 2, 1 , 8, 0x05) + expected_result = (9, 0, 2, 0xC, 0x55) + op = gr.xor_bb () + self.help_bb ((src1_data, src2_data), + expected_result, op) + + + def test_xor_ii (self): + src1_data = (1, 2, 3, 0x5000004, 0x11000050) + src2_data = (8, 2, 1 , 0x0500008, 0x11000005) + expected_result = (9, 0, 2, 0x550000C, 0x00000055) + op = gr.xor_ii () + self.help_ii ((src1_data, src2_data), + expected_result, op) + + def test_and_ss (self): + src1_data = (1, 2, 3, 0x5004, 0x1150) + src2_data = (8, 2, 1 , 0x0508, 0x1105) + expected_result = (0, 2, 1, 0x0000, 0x1100) + op = gr.and_ss () + self.help_ss ((src1_data, src2_data), + expected_result, op) + + def test_and_bb (self): + src1_data = (1, 2, 2, 3, 0x04, 0x50) + src2_data = (8, 2, 2, 1, 0x08, 0x05) + src3_data = (8, 2, 1, 1, 0x08, 0x05) + expected_result = (0, 2, 0, 1, 0x00, 0x00) + op = gr.and_bb () + self.help_bb ((src1_data, src2_data, src3_data), + expected_result, op) + + def test_and_ii (self): + src1_data = (1, 2, 3, 0x50005004, 0x11001150) + src2_data = (8, 2, 1 , 0x05000508, 0x11001105) + expected_result = (0, 2, 1, 0x00000000, 0x11001100) + op = gr.and_ii () + self.help_ii ((src1_data, src2_data), + expected_result, op) + + def test_or_ss (self): + src1_data = (1, 2, 3, 0x5004, 0x1150) + src2_data = (8, 2, 1 , 0x0508, 0x1105) + expected_result = (9, 2, 3, 0x550C, 0x1155) + op = gr.or_ss () + self.help_ss ((src1_data, src2_data), + expected_result, op) + + def test_or_bb (self): + src1_data = (1, 2, 2, 3, 0x04, 0x50) + src2_data = (8, 2, 2, 1 , 0x08, 0x05) + src3_data = (8, 2, 1, 1 , 0x08, 0x05) + expected_result = (9, 2, 3, 3, 0x0C, 0x55) + op = gr.or_bb () + self.help_bb ((src1_data, src2_data, src3_data), + expected_result, op) + + def test_or_ii (self): + src1_data = (1, 2, 3, 0x50005004, 0x11001150) + src2_data = (8, 2, 1 , 0x05000508, 0x11001105) + expected_result = (9, 2, 3, 0x5500550C, 0x11001155) + op = gr.or_ii () + self.help_ii ((src1_data, src2_data), + expected_result, op) + + def test_not_ss (self): + src1_data = (1, 2, 3, 0x5004, 0x1150) + expected_result = (~1, ~2, ~3, ~0x5004, ~0x1150) + op = gr.not_ss () + self.help_ss ((((src1_data),)), + expected_result, op) + + def test_not_bb (self): + src1_data = (1, 2, 2, 3, 0x04, 0x50) + expected_result = (0xFE, 0xFD, 0xFD, 0xFC, 0xFB, 0xAF) + op = gr.not_bb () + self.help_bb (((src1_data), ), + expected_result, op) + + def test_not_ii (self): + src1_data = (1, 2, 3, 0x50005004, 0x11001150) + expected_result = (~1 , ~2, ~3, ~0x50005004, ~0x11001150) + op = gr.not_ii () + self.help_ii (((src1_data),), + expected_result, op) + + + +if __name__ == '__main__': + gr_unittest.run(test_boolean_operators, "test_boolean_operators.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_complex_to_xxx.py b/gnuradio-core/src/python/gnuradio/gr/qa_complex_to_xxx.py new file mode 100755 index 000000000..946c0d7f8 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_complex_to_xxx.py @@ -0,0 +1,142 @@ +#!/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_complex_ops (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_complex_to_float_1 (self): + src_data = (0, 1, -1, 3+4j, -3-4j, -3+4j) + expected_result = (0, 1, -1, 3, -3, -3) + src = gr.vector_source_c (src_data) + op = gr.complex_to_float () + dst = gr.vector_sink_f () + 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.assertFloatTuplesAlmostEqual (expected_result, actual_result) + + def test_complex_to_float_2 (self): + src_data = (0, 1, -1, 3+4j, -3-4j, -3+4j) + expected_result0 = (0, 1, -1, 3, -3, -3) + expected_result1 = (0, 0, 0, 4, -4, 4) + src = gr.vector_source_c (src_data) + op = gr.complex_to_float () + dst0 = gr.vector_sink_f () + dst1 = gr.vector_sink_f () + self.tb.connect (src, op) + self.tb.connect ((op, 0), dst0) + self.tb.connect ((op, 1), dst1) + self.tb.run () + actual_result = dst0.data () + self.assertFloatTuplesAlmostEqual (expected_result0, actual_result) + actual_result = dst1.data () + self.assertFloatTuplesAlmostEqual (expected_result1, actual_result) + + def test_complex_to_real (self): + src_data = (0, 1, -1, 3+4j, -3-4j, -3+4j) + expected_result = (0, 1, -1, 3, -3, -3) + src = gr.vector_source_c (src_data) + op = gr.complex_to_real () + dst = gr.vector_sink_f () + self.tb.connect (src, op) + self.tb.connect (op, dst) + self.tb.run () + actual_result = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, actual_result) + + def test_complex_to_imag (self): + src_data = (0, 1, -1, 3+4j, -3-4j, -3+4j) + expected_result = (0, 0, 0, 4, -4, 4) + src = gr.vector_source_c (src_data) + op = gr.complex_to_imag () + dst = gr.vector_sink_f () + self.tb.connect (src, op) + self.tb.connect (op, dst) + self.tb.run () + actual_result = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, actual_result,5) + + def test_complex_to_mag (self): + src_data = (0, 1, -1, 3+4j, -3-4j, -3+4j) + expected_result = (0, 1, 1, 5, 5, 5) + src = gr.vector_source_c (src_data) + op = gr.complex_to_mag () + dst = gr.vector_sink_f () + self.tb.connect (src, op) + self.tb.connect (op, dst) + self.tb.run () + actual_result = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, actual_result,5) + + def test_complex_to_mag_squared (self): + src_data = (0, 1, -1, 3+4j, -3-4j, -3+4j) + expected_result = (0, 1, 1, 25, 25, 25) + src = gr.vector_source_c (src_data) + op = gr.complex_to_mag_squared () + dst = gr.vector_sink_f () + self.tb.connect (src, op) + self.tb.connect (op, dst) + self.tb.run () + actual_result = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, actual_result,5) + + def test_complex_to_arg (self): + pi = math.pi + input_data = (0, pi/6, pi/4, pi/2, 3*pi/4, 7*pi/8, + -pi/6, -pi/4, -pi/2, -3*pi/4, -7*pi/8) + + expected_result = (0.0, # 0 + 0.52382522821426392, # pi/6 + 0.78539806604385376, # pi/4 + 1.5707963705062866, # pi/2 + 2.3561947345733643, # 3pi/4 + 2.7491819858551025, # 7pi/8 + -0.52382522821426392, # -pi/6 + -0.78539806604385376, # -pi/4 + -1.5707963705062866, # -pi/2 + -2.3561947345733643, # -3pi/4 + -2.7491819858551025) # -7pi/8 + + src_data = tuple ([math.cos (x) + math.sin (x) * 1j for x in input_data]) + src = gr.vector_source_c (src_data) + op = gr.complex_to_arg () + dst = gr.vector_sink_f () + self.tb.connect (src, op) + self.tb.connect (op, dst) + self.tb.run () + actual_result = dst.data () + + self.assertFloatTuplesAlmostEqual (expected_result, actual_result, 3) + + +if __name__ == '__main__': + gr_unittest.run(test_complex_ops, "test_complex_ops.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_conjugate.py b/gnuradio-core/src/python/gnuradio/gr/qa_conjugate.py new file mode 100644 index 000000000..17fa891e2 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_conjugate.py @@ -0,0 +1,53 @@ +#!/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, gr_unittest + +class test_conjugate (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_000 (self): + src_data = (-2-2j, -1-1j, -2+2j, -1+1j, + 2-2j, 1-1j, 2+2j, 1+1j, + 0+0j) + + exp_data = (-2+2j, -1+1j, -2-2j, -1-1j, + 2+2j, 1+1j, 2-2j, 1-1j, + 0-0j) + + src = gr.vector_source_c(src_data) + op = gr.conjugate_cc () + dst = gr.vector_sink_c () + + self.tb.connect(src, op) + self.tb.connect(op, dst) + self.tb.run() + result_data = dst.data () + self.assertEqual (exp_data, result_data) + +if __name__ == '__main__': + gr_unittest.run(test_conjugate, "test_conjugate.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_copy.py b/gnuradio-core/src/python/gnuradio/gr/qa_copy.py new file mode 100755 index 000000000..68c8e451f --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_copy.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# +# Copyright 2009,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_copy(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_copy (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + expected_result = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + src = gr.vector_source_b(src_data) + op = gr.copy(gr.sizeof_char) + dst = gr.vector_sink_b() + self.tb.connect(src, op, dst) + self.tb.run() + dst_data = dst.data() + self.assertEqual(expected_result, dst_data) + + def test_copy_drop (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + expected_result = () + src = gr.vector_source_b(src_data) + op = gr.copy(gr.sizeof_char) + op.set_enabled(False) + dst = gr.vector_sink_b() + self.tb.connect(src, op, dst) + self.tb.run() + dst_data = dst.data() + self.assertEqual(expected_result, dst_data) + + +if __name__ == '__main__': + gr_unittest.run(test_copy, "test_copy.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_dc_blocker.py b/gnuradio-core/src/python/gnuradio/gr/qa_dc_blocker.py new file mode 100755 index 000000000..175735867 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_dc_blocker.py @@ -0,0 +1,108 @@ +#!/usr/bin/env python +# +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest + +class test_dc_blocker(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001(self): + ''' Test impulse response - long form, cc ''' + src_data = [1,] + 100*[0,] + expected_result = ((-0.02072429656982422+0j), (-0.02081298828125+0j), + (0.979156494140625+0j), (-0.02081298828125+0j), + (-0.02072429656982422+0j)) + + src = gr.vector_source_c(src_data) + op = gr.dc_blocker_cc(32, True) + dst = gr.vector_sink_c() + + self.tb.connect (src, op, dst) + self.tb.run() + + # only test samples around 2D-2 + result_data = dst.data()[60:65] + self.assertComplexTuplesAlmostEqual (expected_result, result_data) + + def test_002(self): + ''' Test impulse response - short form, cc ''' + src_data = [1,] + 100*[0,] + expected_result = ((-0.029296875+0j), (-0.0302734375+0j), + (0.96875+0j), (-0.0302734375+0j), + (-0.029296875+0j)) + + src = gr.vector_source_c(src_data) + op = gr.dc_blocker_cc(32, False) + dst = gr.vector_sink_c() + + self.tb.connect (src, op, dst) + self.tb.run() + + # only test samples around D-1 + result_data = dst.data()[29:34] + self.assertComplexTuplesAlmostEqual (expected_result, result_data) + + + def test_003(self): + ''' Test impulse response - long form, ff ''' + src_data = [1,] + 100*[0,] + expected_result = ((-0.02072429656982422), (-0.02081298828125), + (0.979156494140625), (-0.02081298828125), + (-0.02072429656982422)) + + src = gr.vector_source_f(src_data) + op = gr.dc_blocker_ff(32, True) + dst = gr.vector_sink_f() + + self.tb.connect (src, op, dst) + self.tb.run() + + # only test samples around 2D-2 + result_data = dst.data()[60:65] + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_004(self): + ''' Test impulse response - short form, ff ''' + src_data = [1,] + 100*[0,] + expected_result = ((-0.029296875), (-0.0302734375), + (0.96875), (-0.0302734375), + (-0.029296875)) + + src = gr.vector_source_f(src_data) + op = gr.dc_blocker_ff(32, False) + dst = gr.vector_sink_f() + + self.tb.connect (src, op, dst) + self.tb.run() + + # only test samples around D-1 + result_data = dst.data()[29:34] + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + +if __name__ == '__main__': + gr_unittest.run(test_dc_blocker, "test_dc_blocker.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_delay.py b/gnuradio-core/src/python/gnuradio/gr/qa_delay.py new file mode 100755 index 000000000..0d0bc1330 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_delay.py @@ -0,0 +1,65 @@ +#!/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_delay (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_000 (self): + delta_t = 0 + tb = self.tb + src_data = [float(x) for x in range(0, 100)] + expected_result = tuple(delta_t*[0.0] + src_data) + + src = gr.vector_source_f(src_data) + op = gr.delay(gr.sizeof_float, delta_t) + dst = gr.vector_sink_f () + + tb.connect (src, op, dst) + tb.run () + dst_data = dst.data () + self.assertEqual (expected_result, dst_data) + + def test_010 (self): + delta_t = 10 + tb = self.tb + src_data = [float(x) for x in range(0, 100)] + expected_result = tuple(delta_t*[0.0] + src_data) + + src = gr.vector_source_f(src_data) + op = gr.delay(gr.sizeof_float, delta_t) + dst = gr.vector_sink_f () + + tb.connect (src, op, dst) + tb.run () + dst_data = dst.data () + self.assertEqual (expected_result, dst_data) + +if __name__ == '__main__': + gr_unittest.run(test_delay, "test_delay.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_diff_encoder.py b/gnuradio-core/src/python/gnuradio/gr/qa_diff_encoder.py new file mode 100755 index 000000000..c1fe2a700 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_diff_encoder.py @@ -0,0 +1,86 @@ +#!/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 new file mode 100755 index 000000000..41f96aa61 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_diff_phasor_cc.py @@ -0,0 +1,50 @@ +#!/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_ecc_ccsds_27.py b/gnuradio-core/src/python/gnuradio/gr/qa_ecc_ccsds_27.py new file mode 100755 index 000000000..29122ff3e --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_ecc_ccsds_27.py @@ -0,0 +1,50 @@ +#!/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 + +class test_ccsds_27 (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def xtest_ccsds_27 (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + expected = (0, 0, 0, 0, 1, 2, 3, 4, 5, 6) + src = gr.vector_source_b(src_data) + enc = gr.encode_ccsds_27_bb() + b2f = gr.char_to_float() + add = gr.add_const_ff(-0.5) + mul = gr.multiply_const_ff(2.0) + dec = gr.decode_ccsds_27_fb() + dst = gr.vector_sink_b() + self.tb.connect(src, enc, b2f, add, mul, dec, dst) + self.tb.run() + dst_data = dst.data() + self.assertEqual(expected, dst_data) + + +if __name__ == '__main__': + gr_unittest.run(test_ccsds_27, "test_ccsds_27.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_endian_swap.py b/gnuradio-core/src/python/gnuradio/gr/qa_endian_swap.py new file mode 100644 index 000000000..4d2555cc4 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_endian_swap.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr, gr_unittest +import ctypes + +class test_endian_swap (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001(self): + + src_data = [1,2,3,4] + expected_result = [256, 512, 768, 1024]; + + src = gr.vector_source_s(src_data) + op = gr.endian_swap(2) + dst = gr.vector_sink_s() + + self.tb.connect(src, op, dst) + self.tb.run() + result_data = list(dst.data()) + + self.assertEqual(expected_result, result_data) + + def test_002(self): + + src_data = [1,2,3,4] + expected_result = [16777216, 33554432, 50331648, 67108864]; + + src = gr.vector_source_i(src_data) + op = gr.endian_swap(4) + dst = gr.vector_sink_i() + + self.tb.connect(src, op, dst) + self.tb.run() + result_data = list(dst.data()) + + self.assertEqual(expected_result, result_data) + +if __name__ == '__main__': + gr_unittest.run(test_endian_swap, "test_endian_swap.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_feval.py b/gnuradio-core/src/python/gnuradio/gr/qa_feval.py new file mode 100755 index 000000000..9018e12f3 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_feval.py @@ -0,0 +1,110 @@ +#!/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 + +class my_add2_dd(gr.feval_dd): + def eval(self, x): + return x + 2 + +class my_add2_ll(gr.feval_ll): + def eval(self, x): + return x + 2 + +class my_add2_cc(gr.feval_cc): + def eval(self, x): + return x + (2 - 2j) + +class my_feval(gr.feval): + def __init__(self): + gr.feval.__init__(self) + self.fired = False + def eval(self): + self.fired = True + +class test_feval(gr_unittest.TestCase): + + def test_dd_1(self): + f = my_add2_dd() + src_data = (0.0, 1.0, 2.0, 3.0, 4.0) + expected_result = (2.0, 3.0, 4.0, 5.0, 6.0) + # this is all in python... + actual_result = tuple([f.eval(x) for x in src_data]) + self.assertEqual(expected_result, actual_result) + + def test_dd_2(self): + f = my_add2_dd() + src_data = (0.0, 1.0, 2.0, 3.0, 4.0) + expected_result = (2.0, 3.0, 4.0, 5.0, 6.0) + # this is python -> C++ -> python and back again... + actual_result = tuple([gr.feval_dd_example(f, x) for x in src_data]) + self.assertEqual(expected_result, actual_result) + + + def test_ll_1(self): + f = my_add2_ll() + src_data = (0, 1, 2, 3, 4) + expected_result = (2, 3, 4, 5, 6) + # this is all in python... + actual_result = tuple([f.eval(x) for x in src_data]) + self.assertEqual(expected_result, actual_result) + + def test_ll_2(self): + f = my_add2_ll() + src_data = (0, 1, 2, 3, 4) + expected_result = (2, 3, 4, 5, 6) + # this is python -> C++ -> python and back again... + actual_result = tuple([gr.feval_ll_example(f, x) for x in src_data]) + self.assertEqual(expected_result, actual_result) + + + def test_cc_1(self): + f = my_add2_cc() + src_data = (0+1j, 2+3j, 4+5j, 6+7j) + expected_result = (2-1j, 4+1j, 6+3j, 8+5j) + # this is all in python... + actual_result = tuple([f.eval(x) for x in src_data]) + self.assertEqual(expected_result, actual_result) + + def test_cc_2(self): + f = my_add2_cc() + src_data = (0+1j, 2+3j, 4+5j, 6+7j) + expected_result = (2-1j, 4+1j, 6+3j, 8+5j) + # this is python -> C++ -> python and back again... + actual_result = tuple([gr.feval_cc_example(f, x) for x in src_data]) + self.assertEqual(expected_result, actual_result) + + def test_void_1(self): + # this is all in python + f = my_feval() + f.eval() + self.assertEqual(True, f.fired) + + def test_void_2(self): + # this is python -> C++ -> python and back again + f = my_feval() + gr.feval_example(f) + self.assertEqual(True, f.fired) + + +if __name__ == '__main__': + gr_unittest.run(test_feval, "test_feval.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_fft.py b/gnuradio-core/src/python/gnuradio/gr/qa_fft.py new file mode 100755 index 000000000..693d0e67c --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_fft.py @@ -0,0 +1,212 @@ +#!/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 this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +from gnuradio import gr, gr_unittest +import sys +import random + +primes = (2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53, + 59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131, + 137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223, + 227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311) + + +class test_fft(gr_unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + def assert_fft_ok2(self, expected_result, result_data): + expected_result = expected_result[:len(result_data)] + self.assertComplexTuplesAlmostEqual2 (expected_result, result_data, + abs_eps=1e-9, rel_eps=4e-4) + + def assert_fft_float_ok2(self, expected_result, result_data, abs_eps=1e-9, rel_eps=4e-4): + expected_result = expected_result[:len(result_data)] + self.assertFloatTuplesAlmostEqual2 (expected_result, result_data, + abs_eps, rel_eps) + + def test_001(self): + tb = gr.top_block() + fft_size = 32 + src_data = tuple([complex(primes[2*i], primes[2*i+1]) for i in range(fft_size)]) + + expected_result = ((4377+4516j), + (-1706.1268310546875+1638.4256591796875j), + (-915.2083740234375+660.69427490234375j), + (-660.370361328125+381.59600830078125j), + (-499.96044921875+238.41630554199219j), + (-462.26748657226562+152.88948059082031j), + (-377.98440551757812+77.5928955078125j), + (-346.85821533203125+47.152004241943359j), + (-295+20j), + (-286.33609008789062-22.257017135620117j), + (-271.52999877929688-33.081821441650391j), + (-224.6358642578125-67.019538879394531j), + (-244.24473571777344-91.524826049804688j), + (-203.09068298339844-108.54627227783203j), + (-198.45195007324219-115.90768432617188j), + (-182.97744750976562-128.12318420410156j), + (-167-180j), + (-130.33688354492188-173.83778381347656j), + (-141.19784545898438-190.28807067871094j), + (-111.09677124023438-214.48896789550781j), + (-70.039543151855469-242.41630554199219j), + (-68.960540771484375-228.30015563964844j), + (-53.049201965332031-291.47097778320312j), + (-28.695289611816406-317.64553833007812j), + (57-300j), + (45.301143646240234-335.69509887695312j), + (91.936195373535156-373.32437133789062j), + (172.09465026855469-439.275146484375j), + (242.24473571777344-504.47515869140625j), + (387.81732177734375-666.6788330078125j), + (689.48553466796875-918.2142333984375j), + (1646.539306640625-1694.1956787109375j)) + + src = gr.vector_source_c(src_data) + s2v = gr.stream_to_vector(gr.sizeof_gr_complex, fft_size) + fft = gr.fft_vcc(fft_size, True, [], False) + v2s = gr.vector_to_stream(gr.sizeof_gr_complex, fft_size) + dst = gr.vector_sink_c() + tb.connect(src, s2v, fft, v2s, dst) + tb.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + #self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + self.assert_fft_ok2(expected_result, result_data) + + def test_002(self): + tb = gr.top_block() + fft_size = 32 + + tmp_data = ((4377+4516j), + (-1706.1268310546875+1638.4256591796875j), + (-915.2083740234375+660.69427490234375j), + (-660.370361328125+381.59600830078125j), + (-499.96044921875+238.41630554199219j), + (-462.26748657226562+152.88948059082031j), + (-377.98440551757812+77.5928955078125j), + (-346.85821533203125+47.152004241943359j), + (-295+20j), + (-286.33609008789062-22.257017135620117j), + (-271.52999877929688-33.081821441650391j), + (-224.6358642578125-67.019538879394531j), + (-244.24473571777344-91.524826049804688j), + (-203.09068298339844-108.54627227783203j), + (-198.45195007324219-115.90768432617188j), + (-182.97744750976562-128.12318420410156j), + (-167-180j), + (-130.33688354492188-173.83778381347656j), + (-141.19784545898438-190.28807067871094j), + (-111.09677124023438-214.48896789550781j), + (-70.039543151855469-242.41630554199219j), + (-68.960540771484375-228.30015563964844j), + (-53.049201965332031-291.47097778320312j), + (-28.695289611816406-317.64553833007812j), + (57-300j), + (45.301143646240234-335.69509887695312j), + (91.936195373535156-373.32437133789062j), + (172.09465026855469-439.275146484375j), + (242.24473571777344-504.47515869140625j), + (387.81732177734375-666.6788330078125j), + (689.48553466796875-918.2142333984375j), + (1646.539306640625-1694.1956787109375j)) + + src_data = tuple([x/fft_size for x in tmp_data]) + + expected_result = tuple([complex(primes[2*i], primes[2*i+1]) for i in range(fft_size)]) + + src = gr.vector_source_c(src_data) + s2v = gr.stream_to_vector(gr.sizeof_gr_complex, fft_size) + fft = gr.fft_vcc(fft_size, False, [], False) + v2s = gr.vector_to_stream(gr.sizeof_gr_complex, fft_size) + dst = gr.vector_sink_c() + tb.connect(src, s2v, fft, v2s, dst) + tb.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + #self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + self.assert_fft_ok2(expected_result, result_data) + + def test_003(self): + # Same test as above, only use 2 threads + + tb = gr.top_block() + fft_size = 32 + + tmp_data = ((4377+4516j), + (-1706.1268310546875+1638.4256591796875j), + (-915.2083740234375+660.69427490234375j), + (-660.370361328125+381.59600830078125j), + (-499.96044921875+238.41630554199219j), + (-462.26748657226562+152.88948059082031j), + (-377.98440551757812+77.5928955078125j), + (-346.85821533203125+47.152004241943359j), + (-295+20j), + (-286.33609008789062-22.257017135620117j), + (-271.52999877929688-33.081821441650391j), + (-224.6358642578125-67.019538879394531j), + (-244.24473571777344-91.524826049804688j), + (-203.09068298339844-108.54627227783203j), + (-198.45195007324219-115.90768432617188j), + (-182.97744750976562-128.12318420410156j), + (-167-180j), + (-130.33688354492188-173.83778381347656j), + (-141.19784545898438-190.28807067871094j), + (-111.09677124023438-214.48896789550781j), + (-70.039543151855469-242.41630554199219j), + (-68.960540771484375-228.30015563964844j), + (-53.049201965332031-291.47097778320312j), + (-28.695289611816406-317.64553833007812j), + (57-300j), + (45.301143646240234-335.69509887695312j), + (91.936195373535156-373.32437133789062j), + (172.09465026855469-439.275146484375j), + (242.24473571777344-504.47515869140625j), + (387.81732177734375-666.6788330078125j), + (689.48553466796875-918.2142333984375j), + (1646.539306640625-1694.1956787109375j)) + + src_data = tuple([x/fft_size for x in tmp_data]) + + expected_result = tuple([complex(primes[2*i], primes[2*i+1]) for i in range(fft_size)]) + + nthreads = 2 + + src = gr.vector_source_c(src_data) + s2v = gr.stream_to_vector(gr.sizeof_gr_complex, fft_size) + fft = gr.fft_vcc(fft_size, False, [], False, nthreads) + v2s = gr.vector_to_stream(gr.sizeof_gr_complex, fft_size) + dst = gr.vector_sink_c() + tb.connect(src, s2v, fft, v2s, dst) + tb.run() + result_data = dst.data() + self.assert_fft_ok2(expected_result, result_data) + +if __name__ == '__main__': + gr_unittest.run(test_fft, "test_fft.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_fft_filter.py b/gnuradio-core/src/python/gnuradio/gr/qa_fft_filter.py new file mode 100755 index 000000000..c0aadc306 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_fft_filter.py @@ -0,0 +1,383 @@ +#!/usr/bin/env python +# +# Copyright 2004,2005,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 sys +import random + +def make_random_complex_tuple(L): + result = [] + for x in range(L): + result.append(complex(random.uniform(-1000,1000), + random.uniform(-1000,1000))) + return tuple(result) + +def make_random_float_tuple(L): + result = [] + for x in range(L): + result.append(float(int(random.uniform(-1000,1000)))) + return tuple(result) + + +def reference_filter_ccc(dec, taps, input): + """ + compute result using conventional fir filter + """ + tb = gr.top_block() + #src = gr.vector_source_c(((0,) * (len(taps) - 1)) + input) + src = gr.vector_source_c(input) + op = gr.fir_filter_ccc(dec, taps) + dst = gr.vector_sink_c() + tb.connect(src, op, dst) + tb.run() + return dst.data() + +def reference_filter_fff(dec, taps, input): + """ + compute result using conventional fir filter + """ + tb = gr.top_block() + #src = gr.vector_source_f(((0,) * (len(taps) - 1)) + input) + src = gr.vector_source_f(input) + op = gr.fir_filter_fff(dec, taps) + dst = gr.vector_sink_f() + tb.connect(src, op, dst) + tb.run() + return dst.data() + + +def print_complex(x): + for i in x: + i = complex(i) + sys.stdout.write("(%6.3f,%6.3fj), " % (i.real, i.imag)) + sys.stdout.write('\n') + + +class test_fft_filter(gr_unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + def assert_fft_ok2(self, expected_result, result_data): + expected_result = expected_result[:len(result_data)] + self.assertComplexTuplesAlmostEqual2 (expected_result, result_data, + abs_eps=1e-9, rel_eps=4e-4) + + def assert_fft_float_ok2(self, expected_result, result_data, abs_eps=1e-9, rel_eps=4e-4): + expected_result = expected_result[:len(result_data)] + self.assertFloatTuplesAlmostEqual2 (expected_result, result_data, + abs_eps, rel_eps) + + #def test_ccc_000(self): + # self.assertRaises (RuntimeError, gr.fft_filter_ccc, 2, (1,)) + + def test_ccc_001(self): + tb = gr.top_block() + src_data = (0,1,2,3,4,5,6,7) + taps = (1,) + expected_result = tuple([complex(x) for x in (0,1,2,3,4,5,6,7)]) + src = gr.vector_source_c(src_data) + op = gr.fft_filter_ccc(1, taps) + dst = gr.vector_sink_c() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + + + def test_ccc_002(self): + # Test nthreads + tb = gr.top_block() + src_data = (0,1,2,3,4,5,6,7) + taps = (2,) + nthreads = 2 + expected_result = tuple([2 * complex(x) for x in (0,1,2,3,4,5,6,7)]) + src = gr.vector_source_c(src_data) + op = gr.fft_filter_ccc(1, taps, nthreads) + dst = gr.vector_sink_c() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + + def test_ccc_003(self): + tb = gr.top_block() + src_data = (0,1,2,3,4,5,6,7) + taps = (2,) + expected_result = tuple([2 * complex(x) for x in (0,1,2,3,4,5,6,7)]) + src = gr.vector_source_c(src_data) + op = gr.fft_filter_ccc(1, taps) + dst = gr.vector_sink_c() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + + + def test_ccc_004(self): + random.seed(0) + for i in xrange(25): + # sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + src_len = 4*1024 + src_data = make_random_complex_tuple(src_len) + ntaps = int(random.uniform(2, 1000)) + taps = make_random_complex_tuple(ntaps) + expected_result = reference_filter_ccc(1, taps, src_data) + + src = gr.vector_source_c(src_data) + op = gr.fft_filter_ccc(1, taps) + dst = gr.vector_sink_c() + tb = gr.top_block() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + del tb + + self.assert_fft_ok2(expected_result, result_data) + + def test_ccc_005(self): + random.seed(0) + for i in xrange(25): + # sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + dec = i + 1 + src_len = 4*1024 + src_data = make_random_complex_tuple(src_len) + ntaps = int(random.uniform(2, 100)) + taps = make_random_complex_tuple(ntaps) + expected_result = reference_filter_ccc(dec, taps, src_data) + + src = gr.vector_source_c(src_data) + op = gr.fft_filter_ccc(dec, taps) + dst = gr.vector_sink_c() + tb = gr.top_block() + tb.connect(src, op, dst) + tb.run() + del tb + result_data = dst.data() + + self.assert_fft_ok2(expected_result, result_data) + + def test_ccc_006(self): + # Test decimating with nthreads=2 + random.seed(0) + nthreads = 2 + for i in xrange(25): + # sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + dec = i + 1 + src_len = 4*1024 + src_data = make_random_complex_tuple(src_len) + ntaps = int(random.uniform(2, 100)) + taps = make_random_complex_tuple(ntaps) + expected_result = reference_filter_ccc(dec, taps, src_data) + + src = gr.vector_source_c(src_data) + op = gr.fft_filter_ccc(dec, taps, nthreads) + dst = gr.vector_sink_c() + tb = gr.top_block() + tb.connect(src, op, dst) + tb.run() + del tb + result_data = dst.data() + + self.assert_fft_ok2(expected_result, result_data) + + # ---------------------------------------------------------------- + # test _fff version + # ---------------------------------------------------------------- + + def test_fff_001(self): + tb = gr.top_block() + src_data = (0,1,2,3,4,5,6,7) + taps = (1,) + expected_result = tuple([float(x) for x in (0,1,2,3,4,5,6,7)]) + src = gr.vector_source_f(src_data) + op = gr.fft_filter_fff(1, taps) + dst = gr.vector_sink_f() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + self.assertFloatTuplesAlmostEqual (expected_result, result_data, 5) + + + def test_fff_002(self): + tb = gr.top_block() + src_data = (0,1,2,3,4,5,6,7) + taps = (2,) + expected_result = tuple([2 * float(x) for x in (0,1,2,3,4,5,6,7)]) + src = gr.vector_source_f(src_data) + op = gr.fft_filter_fff(1, taps) + dst = gr.vector_sink_f() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + self.assertFloatTuplesAlmostEqual (expected_result, result_data, 5) + + def test_fff_003(self): + # Test 02 with nthreads + tb = gr.top_block() + src_data = (0,1,2,3,4,5,6,7) + taps = (2,) + nthreads = 2 + expected_result = tuple([2 * float(x) for x in (0,1,2,3,4,5,6,7)]) + src = gr.vector_source_f(src_data) + op = gr.fft_filter_fff(1, taps, nthreads) + dst = gr.vector_sink_f() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual (expected_result, result_data, 5) + + def xtest_fff_004(self): + random.seed(0) + for i in xrange(25): + sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + src_len = 4096 + src_data = make_random_float_tuple(src_len) + ntaps = int(random.uniform(2, 1000)) + taps = make_random_float_tuple(ntaps) + expected_result = reference_filter_fff(1, taps, src_data) + + src = gr.vector_source_f(src_data) + op = gr.fft_filter_fff(1, taps) + dst = gr.vector_sink_f() + tb = gr.top_block() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + + #print "src_len =", src_len, " ntaps =", ntaps + try: + self.assert_fft_float_ok2(expected_result, result_data, abs_eps=1.0) + except: + expected = open('expected', 'w') + for x in expected_result: + expected.write(`x` + '\n') + actual = open('actual', 'w') + for x in result_data: + actual.write(`x` + '\n') + raise + + def xtest_fff_005(self): + random.seed(0) + for i in xrange(25): + sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + src_len = 4*1024 + src_data = make_random_float_tuple(src_len) + ntaps = int(random.uniform(2, 1000)) + taps = make_random_float_tuple(ntaps) + expected_result = reference_filter_fff(1, taps, src_data) + + src = gr.vector_source_f(src_data) + op = gr.fft_filter_fff(1, taps) + dst = gr.vector_sink_f() + tb = gr.top_block() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + + self.assert_fft_float_ok2(expected_result, result_data, abs_eps=2.0) + + def xtest_fff_006(self): + random.seed(0) + for i in xrange(25): + sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + dec = i + 1 + src_len = 4*1024 + src_data = make_random_float_tuple(src_len) + ntaps = int(random.uniform(2, 100)) + taps = make_random_float_tuple(ntaps) + expected_result = reference_filter_fff(dec, taps, src_data) + + src = gr.vector_source_f(src_data) + op = gr.fft_filter_fff(dec, taps) + dst = gr.vector_sink_f() + tb = gr.top_block() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + + self.assert_fft_float_ok2(expected_result, result_data) + + def xtest_fff_007(self): + # test decimation with nthreads + random.seed(0) + nthreads = 2 + for i in xrange(25): + sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + dec = i + 1 + src_len = 4*1024 + src_data = make_random_float_tuple(src_len) + ntaps = int(random.uniform(2, 100)) + taps = make_random_float_tuple(ntaps) + expected_result = reference_filter_fff(dec, taps, src_data) + + src = gr.vector_source_f(src_data) + op = gr.fft_filter_fff(dec, taps, nthreads) + dst = gr.vector_sink_f() + tb = gr.top_block() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + + self.assert_fft_float_ok2(expected_result, result_data) + + def test_fff_get0(self): + random.seed(0) + for i in xrange(25): + ntaps = int(random.uniform(2, 100)) + taps = make_random_float_tuple(ntaps) + + op = gr.fft_filter_fff(1, taps) + result_data = op.taps() + #print result_data + + self.assertEqual(taps, result_data) + + def test_ccc_get0(self): + random.seed(0) + for i in xrange(25): + ntaps = int(random.uniform(2, 100)) + taps = make_random_complex_tuple(ntaps) + + op = gr.fft_filter_ccc(1, taps) + result_data = op.taps() + #print result_data + + self.assertComplexTuplesAlmostEqual(taps, result_data, 4) + + +if __name__ == '__main__': + gr_unittest.run(test_fft_filter, "test_fft_filter.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_filter_delay_fc.py b/gnuradio-core/src/python/gnuradio/gr/qa_filter_delay_fc.py new file mode 100755 index 000000000..8d325fc3e --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_filter_delay_fc.py @@ -0,0 +1,317 @@ +#!/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_filter_delay_fc (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001_filter_delay_one_input (self): + + # expected result + expected_result = ( -1.4678005338941702e-11j, + -0.0011950774351134896j, + -0.0019336787518113852j, + -0.0034673355985432863j, + -0.0036765895783901215j, + -0.004916108213365078j, + -0.0042778430506587029j, + -0.006028641015291214j, + -0.005476709920912981j, + -0.0092810001224279404j, + -0.0095402700826525688j, + -0.016060983762145042j, + -0.016446959227323532j, + -0.02523401565849781j, + -0.024382550269365311j, + -0.035477779805660248j, + -0.033021725714206696j, + -0.048487484455108643j, + -0.04543270543217659j, + -0.069477587938308716j, + -0.066984444856643677j, + -0.10703597217798233j, + -0.10620346665382385j, + -0.1852707713842392j, + -0.19357112050056458j, + (7.2191945754696007e-09 -0.50004088878631592j), + (0.58778399229049683 -0.6155126690864563j), + (0.95105588436126709 -0.12377222627401352j), + (0.95105588436126709 +0.41524654626846313j), + (0.5877838134765625 +0.91611981391906738j), + (5.8516356205018383e-09 +1.0670661926269531j), + (-0.5877840518951416 +0.87856143712997437j), + (-0.95105588436126709 +0.35447561740875244j), + (-0.95105588436126709 -0.26055556535720825j), + (-0.5877838134765625 -0.77606213092803955j), + (-8.7774534307527574e-09 -0.96460390090942383j), + (0.58778399229049683 -0.78470128774642944j), + (0.95105588436126709 -0.28380891680717468j), + (0.95105588436126709 +0.32548999786376953j), + (0.5877838134765625 +0.82514488697052002j), + (1.4629089051254596e-08 +1.0096219778060913j), + (-0.5877840518951416 +0.81836479902267456j), + (-0.95105588436126709 +0.31451958417892456j), + (-0.95105588436126709 -0.3030143678188324j), + (-0.5877838134765625 -0.80480599403381348j), + (-1.7554906861505515e-08 -0.99516552686691284j), + (0.58778399229049683 -0.80540722608566284j), + (0.95105582475662231 -0.30557557940483093j), + (0.95105588436126709 +0.31097668409347534j), + (0.5877838134765625 +0.81027895212173462j), + (2.3406542482007353e-08 +1.0000816583633423j), + (-0.5877840518951416 +0.80908381938934326j), + (-0.95105588436126709 +0.30904293060302734j), + (-0.95105588436126709 -0.30904296040534973j), + (-0.5877838134765625 -0.80908387899398804j), + (-2.6332360292258272e-08 -1.0000815391540527j), + (0.58778399229049683 -0.80908381938934326j), + (0.95105582475662231 -0.30904299020767212j), + (0.95105588436126709 +0.30904293060302734j), + (0.5877838134765625 +0.80908381938934326j), + (3.218399768911695e-08 +1.0000815391540527j)) + + tb = self.tb + + sampling_freq = 100 + + ntaps = 51 + src1 = gr.sig_source_f (sampling_freq, gr.GR_SIN_WAVE, + sampling_freq * 0.10, 1.0) + head = gr.head (gr.sizeof_float, int (ntaps + sampling_freq * 0.10)) + dst2 = gr.vector_sink_c () + + # calculate taps + taps = gr.firdes_hilbert (ntaps) + hd = gr.filter_delay_fc (taps) + + tb.connect (src1, head) + tb.connect (head, hd) + tb.connect (hd,dst2) + + tb.run () + + # get output + result_data = dst2.data () + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + + def test_002_filter_delay_two_inputs (self): + + # giving the same signal to both the inputs should fetch the same results + # as above + + # expected result + expected_result = ( -1.4678005338941702e-11j, + -0.0011950774351134896j, + -0.0019336787518113852j, + -0.0034673355985432863j, + -0.0036765895783901215j, + -0.004916108213365078j, + -0.0042778430506587029j, + -0.006028641015291214j, + -0.005476709920912981j, + -0.0092810001224279404j, + -0.0095402700826525688j, + -0.016060983762145042j, + -0.016446959227323532j, + -0.02523401565849781j, + -0.024382550269365311j, + -0.035477779805660248j, + -0.033021725714206696j, + -0.048487484455108643j, + -0.04543270543217659j, + -0.069477587938308716j, + -0.066984444856643677j, + -0.10703597217798233j, + -0.10620346665382385j, + -0.1852707713842392j, + -0.19357112050056458j, + (7.2191945754696007e-09 -0.50004088878631592j), + (0.58778399229049683 -0.6155126690864563j), + (0.95105588436126709 -0.12377222627401352j), + (0.95105588436126709 +0.41524654626846313j), + (0.5877838134765625 +0.91611981391906738j), + (5.8516356205018383e-09 +1.0670661926269531j), + (-0.5877840518951416 +0.87856143712997437j), + (-0.95105588436126709 +0.35447561740875244j), + (-0.95105588436126709 -0.26055556535720825j), + (-0.5877838134765625 -0.77606213092803955j), + (-8.7774534307527574e-09 -0.96460390090942383j), + (0.58778399229049683 -0.78470128774642944j), + (0.95105588436126709 -0.28380891680717468j), + (0.95105588436126709 +0.32548999786376953j), + (0.5877838134765625 +0.82514488697052002j), + (1.4629089051254596e-08 +1.0096219778060913j), + (-0.5877840518951416 +0.81836479902267456j), + (-0.95105588436126709 +0.31451958417892456j), + (-0.95105588436126709 -0.3030143678188324j), + (-0.5877838134765625 -0.80480599403381348j), + (-1.7554906861505515e-08 -0.99516552686691284j), + (0.58778399229049683 -0.80540722608566284j), + (0.95105582475662231 -0.30557557940483093j), + (0.95105588436126709 +0.31097668409347534j), + (0.5877838134765625 +0.81027895212173462j), + (2.3406542482007353e-08 +1.0000816583633423j), + (-0.5877840518951416 +0.80908381938934326j), + (-0.95105588436126709 +0.30904293060302734j), + (-0.95105588436126709 -0.30904296040534973j), + (-0.5877838134765625 -0.80908387899398804j), + (-2.6332360292258272e-08 -1.0000815391540527j), + (0.58778399229049683 -0.80908381938934326j), + (0.95105582475662231 -0.30904299020767212j), + (0.95105588436126709 +0.30904293060302734j), + (0.5877838134765625 +0.80908381938934326j), + (3.218399768911695e-08 +1.0000815391540527j)) + + + tb = self.tb + + sampling_freq = 100 + ntaps = 51 + src1 = gr.sig_source_f (sampling_freq, gr.GR_SIN_WAVE, + sampling_freq * 0.10, 1.0) + head = gr.head (gr.sizeof_float, int (ntaps + sampling_freq * 0.10)) + dst2 = gr.vector_sink_c () + + + # calculate taps + taps = gr.firdes_hilbert (ntaps) + hd = gr.filter_delay_fc (taps) + + tb.connect (src1, head) + tb.connect (head, (hd,0)) + tb.connect (head, (hd,1)) + tb.connect (hd,dst2) + tb.run () + + # get output + result_data = dst2.data () + + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + + + def test_003_filter_delay_two_inputs (self): + + # give two different inputs + + # expected result + expected_result = ( -0.0020331963896751404j, + -0.0016448829555884004j, + -0.0032375147566199303j, + -0.0014826074475422502j, + -0.0033034090884029865j, + -0.00051144487224519253j, + -0.0043686260469257832j, + -0.0010198024101555347j, + -0.0082517862319946289j, + -0.003456643782556057j, + -0.014193611219525337j, + -0.005875137634575367j, + -0.020293503999710083j, + -0.0067503536120057106j, + -0.026798896491527557j, + -0.0073488112539052963j, + -0.037041611969470978j, + -0.010557252913713455j, + -0.055669989436864853j, + -0.018332764506340027j, + -0.089904911816120148j, + -0.033361352980136871j, + -0.16902604699134827j, + -0.074318811297416687j, + -0.58429563045501709j, + (7.2191945754696007e-09 -0.35892376303672791j), + (0.58778399229049683 +0.63660913705825806j), + (0.95105588436126709 +0.87681591510772705j), + (0.95105588436126709 +0.98705857992172241j), + (0.5877838134765625 +0.55447429418563843j), + (5.8516356205018383e-09 +0.026006083935499191j), + (-0.5877840518951416 -0.60616838932037354j), + (-0.95105588436126709 -0.9311758279800415j), + (-0.95105588436126709 -0.96169203519821167j), + (-0.5877838134765625 -0.57292771339416504j), + (-8.7774534307527574e-09 -0.0073488391935825348j), + (0.58778399229049683 +0.59720659255981445j), + (0.95105588436126709 +0.94438445568084717j), + (0.95105588436126709 +0.95582199096679688j), + (0.5877838134765625 +0.58196049928665161j), + (1.4629089051254596e-08 +0.0026587247848510742j), + (-0.5877840518951416 -0.59129220247268677j), + (-0.95105588436126709 -0.94841635227203369j), + (-0.95105588436126709 -0.95215457677841187j), + (-0.5877838134765625 -0.58535969257354736j), + (-1.7554906861505515e-08 -0.00051158666610717773j), + (0.58778399229049683 +0.58867418766021729j), + (0.95105582475662231 +0.94965213537216187j), + (0.95105588436126709 +0.95050644874572754j), + (0.5877838134765625 +0.58619076013565063j), + (2.3406542482007353e-08 +1.1920928955078125e-07j), + (-0.5877840518951416 -0.58783555030822754j), + (-0.95105588436126709 -0.95113480091094971j), + (-0.95105588436126709 -0.95113474130630493j), + (-0.5877838134765625 -0.58783555030822754j), + (-2.6332360292258272e-08 -8.1956386566162109e-08j), + (0.58778399229049683 +0.58783555030822754j), + (0.95105582475662231 +0.95113474130630493j), + (0.95105588436126709 +0.95113474130630493j), + (0.5877838134765625 +0.58783560991287231j), + (3.218399768911695e-08 +1.1920928955078125e-07j)) + + tb = self.tb + + sampling_freq = 100 + ntaps = 51 + + src1 = gr.sig_source_f (sampling_freq, gr.GR_SIN_WAVE,sampling_freq * 0.10, 1.0) + src2 = gr.sig_source_f (sampling_freq, gr.GR_COS_WAVE,sampling_freq * 0.10, 1.0) + + head1 = gr.head (gr.sizeof_float, int (ntaps + sampling_freq * 0.10)) + head2 = gr.head (gr.sizeof_float, int (ntaps + sampling_freq * 0.10)) + + taps = gr.firdes_hilbert (ntaps) + hd = gr.filter_delay_fc (taps) + + dst2 = gr.vector_sink_c () + + tb.connect (src1, head1) + tb.connect (src2, head2) + + tb.connect (head1, (hd,0)) + tb.connect (head2, (hd,1)) + tb.connect (hd, dst2) + + tb.run () + + # get output + result_data = dst2.data () + + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + + +if __name__ == '__main__': + gr_unittest.run(test_filter_delay_fc, "test_filter_delay_fc.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_float_to_char.py b/gnuradio-core/src/python/gnuradio/gr/qa_float_to_char.py new file mode 100755 index 000000000..057e297f9 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_float_to_char.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr, gr_unittest +class test_float_to_char (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001(self): + + src_data = (0.0, 1.1, 2.2, 3.3, 4.4, 5.5, -1.1, -2.2, -3.3) + expected_result = [0, 1, 2, 3, 4, 5, 255, 254, 253] + src = gr.vector_source_f(src_data) + op = gr.float_to_char() + dst = gr.vector_sink_b() + + self.tb.connect(src, op, dst) + self.tb.run() + result_data = list(dst.data()) + + self.assertEqual(expected_result, result_data) + + def test_002(self): + + src_data = ( 126.0, 127.0, 128.0) + expected_result = [ 126, 127, 127 ] + + src = gr.vector_source_f(src_data) + op = gr.float_to_char() + # Note: vector_sink_b returns uchar + dst = gr.vector_sink_b() + + self.tb.connect(src, op, dst) + self.tb.run() + result_data = list(dst.data()) + + self.assertEqual(expected_result, result_data) + + def test_003(self): + + scale = 2 + vlen = 3 + src_data = (0.0, 1.1, 2.2, 3.3, 4.4, 5.5, -1.1, -2.2, -3.3) + expected_result = [0, 2, 4, 6, 8, 11, 254, 252, 250] + src = gr.vector_source_f(src_data) + s2v = gr.stream_to_vector(gr.sizeof_float, vlen) + op = gr.float_to_char(vlen, scale) + v2s = gr.vector_to_stream(gr.sizeof_char, vlen) + dst = gr.vector_sink_b() + + self.tb.connect(src, s2v, op, v2s, dst) + self.tb.run() + result_data = list(dst.data()) + + self.assertEqual(expected_result, result_data) + +if __name__ == '__main__': + gr_unittest.run(test_float_to_char, "test_float_to_char.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_float_to_int.py b/gnuradio-core/src/python/gnuradio/gr/qa_float_to_int.py new file mode 100755 index 000000000..5c7a412d2 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_float_to_int.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python +# +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest + +class test_float_to_int (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001(self): + + src_data = (0.0, 1.1, 2.2, 3.3, 4.4, 5.5, -1.1, -2.2, -3.3, -4.4, -5.5) + expected_result = [0, 1, 2, 3, 4, 6, -1, -2, -3, -4, -6] + + src = gr.vector_source_f(src_data) + op = gr.float_to_int() + dst = gr.vector_sink_i() + + self.tb.connect(src, op, dst) + self.tb.run() + result_data = list(dst.data()) + + self.assertEqual(expected_result, result_data) + + def test_002(self): + + src_data = ( 2147483647, 2147483648, 2200000000, + -2147483648, -2147483649, -2200000000) + expected_result = [ 2147483647, 2147483647, 2147483647, + -2147483647, -2147483647, -2147483647] + src = gr.vector_source_f(src_data) + op = gr.float_to_int() + dst = gr.vector_sink_i() + + self.tb.connect(src, op, dst) + self.tb.run() + result_data = list(dst.data()) + + self.assertEqual(expected_result, result_data) + + + def test_003(self): + + scale = 2 + vlen = 3 + src_data = (0.0, 1.1, 2.2, 3.3, 4.4, 5.5, -1.1, -2.2, -3.3) + expected_result = [0, 2, 4, 7, 9, 11, -2, -4, -7,] + src = gr.vector_source_f(src_data) + s2v = gr.stream_to_vector(gr.sizeof_float, vlen) + op = gr.float_to_int(vlen, scale) + v2s = gr.vector_to_stream(gr.sizeof_int, vlen) + dst = gr.vector_sink_i() + + self.tb.connect(src, s2v, op, v2s, dst) + self.tb.run() + result_data = list(dst.data()) + + self.assertEqual(expected_result, result_data) + +if __name__ == '__main__': + gr_unittest.run(test_float_to_int, "test_float_to_int.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_float_to_short.py b/gnuradio-core/src/python/gnuradio/gr/qa_float_to_short.py new file mode 100755 index 000000000..3f8b66975 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_float_to_short.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr, gr_unittest +import ctypes + +class test_float_to_short (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001(self): + + src_data = (0.0, 1.1, 2.2, 3.3, 4.4, 5.5, -1.1, -2.2, -3.3, -4.4, -5.5) + expected_result = [0, 1, 2, 3, 4, 6, -1, -2, -3, -4, -6] + + src = gr.vector_source_f(src_data) + op = gr.float_to_short() + dst = gr.vector_sink_s() + + self.tb.connect(src, op, dst) + self.tb.run() + result_data = list(dst.data()) + + self.assertEqual(expected_result, result_data) + + def test_002(self): + + src_data = ( 32766, 32767, 32768, + -32767, -32768, -32769) + expected_result = [ 32766, 32767, 32767, + -32767, -32768, -32768 ] + + src = gr.vector_source_f(src_data) + op = gr.float_to_short() + dst = gr.vector_sink_s() + + self.tb.connect(src, op, dst) + self.tb.run() + result_data = list(dst.data()) + + self.assertEqual(expected_result, result_data) + + def test_003(self): + + scale = 2 + vlen = 3 + src_data = (0.0, 1.1, 2.2, 3.3, 4.4, 5.5, -1.1, -2.2, -3.3) + expected_result = [0, 2, 4, 7, 9, 11, -2, -4, -7] + src = gr.vector_source_f(src_data) + s2v = gr.stream_to_vector(gr.sizeof_float, vlen) + op = gr.float_to_short(vlen, scale) + v2s = gr.vector_to_stream(gr.sizeof_short, vlen) + dst = gr.vector_sink_s() + + self.tb.connect(src, s2v, op, v2s, dst) + self.tb.run() + result_data = list(dst.data()) + + self.assertEqual(expected_result, result_data) + +if __name__ == '__main__': + gr_unittest.run(test_float_to_short, "test_float_to_short.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_float_to_uchar.py b/gnuradio-core/src/python/gnuradio/gr/qa_float_to_uchar.py new file mode 100755 index 000000000..831bed93e --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_float_to_uchar.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import ctypes + +class test_float_to_uchar (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001(self): + + src_data = (0.0, 1.1, 2.2, 3.3, 4.4, 5.5, -1.1, -2.2, -3.3, -4.4, -5.5) + expected_result = [0, 1, 2, 3, 4, 6, 0, 0, 0, 0, 0] + src = gr.vector_source_f(src_data) + op = gr.float_to_uchar() + dst = gr.vector_sink_b() + + self.tb.connect(src, op, dst) + self.tb.run() + result_data = list(dst.data()) + + self.assertEqual(expected_result, result_data) + + def test_002(self): + + src_data = ( 254.0, 255.0, 256.0) + expected_result = [ 254, 255, 255 ] + src = gr.vector_source_f(src_data) + op = gr.float_to_uchar() + dst = gr.vector_sink_b() + + self.tb.connect(src, op, dst) + self.tb.run() + result_data = list(dst.data()) + + self.assertEqual(expected_result, result_data) + +if __name__ == '__main__': + gr_unittest.run(test_float_to_uchar, "test_float_to_uchar.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_fractional_interpolator.py b/gnuradio-core/src/python/gnuradio/gr/qa_fractional_interpolator.py new file mode 100755 index 000000000..e19bb28f3 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_fractional_interpolator.py @@ -0,0 +1,38 @@ +#!/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_fractional_resampler (gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_000_make(self): + op = gr.fractional_interpolator_ff(0.0, 1.0) + op2 = gr.fractional_interpolator_cc(0.0, 1.0) + +if __name__ == '__main__': + gr_unittest.run(test_fractional_resampler, "test_fractional_resampler.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_frequency_modulator.py b/gnuradio-core/src/python/gnuradio/gr/qa_frequency_modulator.py new file mode 100755 index 000000000..23459fff3 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_frequency_modulator.py @@ -0,0 +1,56 @@ +#!/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_frequency_modulator (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_fm_001 (self): + pi = math.pi + sensitivity = pi/4 + src_data = (1.0/4, 1.0/2, 1.0/4, -1.0/4, -1.0/2, -1/4.0) + running_sum = (pi/16, 3*pi/16, pi/4, 3*pi/16, pi/16, 0) + expected_result = tuple ([sincos (x) for x in running_sum]) + src = gr.vector_source_f (src_data) + op = gr.frequency_modulator_fc (sensitivity) + dst = gr.vector_sink_c () + self.tb.connect (src, op) + self.tb.connect (op, dst) + self.tb.run () + result_data = dst.data () + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + + +if __name__ == '__main__': + gr_unittest.run(test_frequency_modulator, "test_frequency_modulator.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 new file mode 100755 index 000000000..95b8c0664 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_fsk_stuff.py @@ -0,0 +1,75 @@ +#!/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 new file mode 100755 index 000000000..161e4a5cc --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_glfsr_source.py @@ -0,0 +1,94 @@ +#!/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_goertzel.py b/gnuradio-core/src/python/gnuradio/gr/qa_goertzel.py new file mode 100755 index 000000000..77f1b5f89 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_goertzel.py @@ -0,0 +1,64 @@ +#!/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 +from math import pi, cos + +class test_goertzel(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def make_tone_data(self, rate, freq): + return [cos(2*pi*x*freq/rate) for x in range(rate)] + + def transform(self, src_data, rate, freq): + src = gr.vector_source_f(src_data, False) + dft = gr.goertzel_fc(rate, rate, freq) + dst = gr.vector_sink_c() + self.tb.connect(src, dft, dst) + self.tb.run() + return dst.data() + + def test_001(self): # Measure single tone magnitude + rate = 8000 + freq = 100 + bin = freq + src_data = self.make_tone_data(rate, freq) + expected_result = 0.5 + actual_result = abs(self.transform(src_data, rate, bin)[0]) + self.assertAlmostEqual(expected_result, actual_result, places=4) + + def test_002(self): # Measure off frequency magnitude + rate = 8000 + freq = 100 + bin = freq/2 + src_data = self.make_tone_data(rate, freq) + expected_result = 0.0 + actual_result = abs(self.transform(src_data, rate, bin)[0]) + self.assertAlmostEqual(expected_result, actual_result, places=4) + +if __name__ == '__main__': + gr_unittest.run(test_goertzel, "test_goertzel.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_head.py b/gnuradio-core/src/python/gnuradio/gr/qa_head.py new file mode 100755 index 000000000..d7cb354dc --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_head.py @@ -0,0 +1,47 @@ +#!/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 + +class test_head (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_head (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + expected_result = (1, 2, 3, 4) + src1 = gr.vector_source_i (src_data) + op = gr.head (gr.sizeof_int, 4) + dst1 = gr.vector_sink_i () + self.tb.connect (src1, op) + self.tb.connect (op, dst1) + self.tb.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + +if __name__ == '__main__': + gr_unittest.run(test_head, "test_head.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_hier_block2.py b/gnuradio-core/src/python/gnuradio/gr/qa_hier_block2.py new file mode 100755 index 000000000..3132d91b0 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_hier_block2.py @@ -0,0 +1,369 @@ +#!/usr/bin/env python + +from gnuradio import gr, gr_unittest + +class test_hier_block2(gr_unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_001_make(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + self.assertEqual("test_block", hblock.name()) + self.assertEqual(1, hblock.input_signature().max_streams()) + self.assertEqual(1, hblock.output_signature().min_streams()) + self.assertEqual(1, hblock.output_signature().max_streams()) + self.assertEqual(gr.sizeof_int, hblock.output_signature().sizeof_stream_item(0)) + + def test_002_connect_input(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = gr.nop(gr.sizeof_int) + hblock.connect(hblock, nop1) + + def test_004_connect_output(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = gr.nop(gr.sizeof_int) + hblock.connect(nop1, hblock) + + def test_005_connect_output_in_use(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = gr.nop(gr.sizeof_int) + nop2 = gr.nop(gr.sizeof_int) + hblock.connect(nop1, hblock) + self.assertRaises(ValueError, + lambda: hblock.connect(nop2, hblock)) + + def test_006_connect_invalid_src_port_neg(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = gr.nop(gr.sizeof_int) + self.assertRaises(ValueError, + lambda: hblock.connect((hblock, -1), nop1)) + + def test_005_connect_invalid_src_port_exceeds(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = gr.nop(gr.sizeof_int) + self.assertRaises(ValueError, + lambda: hblock.connect((hblock, 1), nop1)) + + def test_007_connect_invalid_dst_port_neg(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = gr.nop(gr.sizeof_int) + nop2 = gr.nop(gr.sizeof_int) + self.assertRaises(ValueError, + lambda: hblock.connect(nop1, (nop2, -1))) + + def test_008_connect_invalid_dst_port_exceeds(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = gr.null_sink(gr.sizeof_int) + nop2 = gr.null_sink(gr.sizeof_int) + self.assertRaises(ValueError, + lambda: hblock.connect(nop1, (nop2, 1))) + + def test_009_check_topology(self): + hblock = gr.top_block("test_block") + hblock.check_topology(0, 0) + + def test_010_run(self): + expected = (1.0, 2.0, 3.0, 4.0) + hblock = gr.top_block("test_block") + src = gr.vector_source_f(expected, False) + sink1 = gr.vector_sink_f() + sink2 = gr.vector_sink_f() + hblock.connect(src, sink1) + hblock.connect(src, sink2) + hblock.run() + actual1 = sink1.data() + actual2 = sink2.data() + self.assertEquals(expected, actual1) + self.assertEquals(expected, actual2) + + def test_012_disconnect_input(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = gr.nop(gr.sizeof_int) + hblock.connect(hblock, nop1) + hblock.disconnect(hblock, nop1) + + def test_013_disconnect_input_not_connected(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = gr.nop(gr.sizeof_int) + nop2 = gr.nop(gr.sizeof_int) + hblock.connect(hblock, nop1) + self.assertRaises(ValueError, + lambda: hblock.disconnect(hblock, nop2)) + + def test_014_disconnect_input_neg(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = gr.nop(gr.sizeof_int) + hblock.connect(hblock, nop1) + self.assertRaises(ValueError, + lambda: hblock.disconnect((hblock, -1), nop1)) + + def test_015_disconnect_input_exceeds(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = gr.nop(gr.sizeof_int) + hblock.connect(hblock, nop1) + self.assertRaises(ValueError, + lambda: hblock.disconnect((hblock, 1), nop1)) + + def test_016_disconnect_output(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = gr.nop(gr.sizeof_int) + hblock.connect(nop1, hblock) + hblock.disconnect(nop1, hblock) + + def test_017_disconnect_output_not_connected(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = gr.nop(gr.sizeof_int) + nop2 = gr.nop(gr.sizeof_int) + hblock.connect(nop1, hblock) + self.assertRaises(ValueError, + lambda: hblock.disconnect(nop2, hblock)) + + def test_018_disconnect_output_neg(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = gr.nop(gr.sizeof_int) + hblock.connect(hblock, nop1) + self.assertRaises(ValueError, + lambda: hblock.disconnect(nop1, (hblock, -1))) + + def test_019_disconnect_output_exceeds(self): + hblock = gr.hier_block2("test_block", + gr.io_signature(1,1,gr.sizeof_int), + gr.io_signature(1,1,gr.sizeof_int)) + nop1 = gr.nop(gr.sizeof_int) + hblock.connect(nop1, hblock) + self.assertRaises(ValueError, + lambda: hblock.disconnect(nop1, (hblock, 1))) + + def test_020_run(self): + hblock = gr.top_block("test_block") + data = (1.0, 2.0, 3.0, 4.0) + src = gr.vector_source_f(data, False) + dst = gr.vector_sink_f() + hblock.connect(src, dst) + hblock.run() + self.assertEquals(data, dst.data()) + + def test_021_connect_single(self): + hblock = gr.top_block("test_block") + blk = gr.hier_block2("block", + gr.io_signature(0, 0, 0), + gr.io_signature(0, 0, 0)) + hblock.connect(blk) + + def test_022_connect_single_with_ports(self): + hblock = gr.top_block("test_block") + blk = gr.hier_block2("block", + gr.io_signature(1, 1, 1), + gr.io_signature(1, 1, 1)) + self.assertRaises(ValueError, + lambda: hblock.connect(blk)) + + def test_023_connect_single_twice(self): + hblock = gr.top_block("test_block") + blk = gr.hier_block2("block", + gr.io_signature(0, 0, 0), + gr.io_signature(0, 0, 0)) + hblock.connect(blk) + self.assertRaises(ValueError, + lambda: hblock.connect(blk)) + + def test_024_disconnect_single(self): + hblock = gr.top_block("test_block") + blk = gr.hier_block2("block", + gr.io_signature(0, 0, 0), + gr.io_signature(0, 0, 0)) + hblock.connect(blk) + hblock.disconnect(blk) + + def test_025_disconnect_single_not_connected(self): + hblock = gr.top_block("test_block") + blk = gr.hier_block2("block", + gr.io_signature(0, 0, 0), + gr.io_signature(0, 0, 0)) + self.assertRaises(ValueError, + lambda: hblock.disconnect(blk)) + + def test_026_run_single(self): + expected_data = (1.0,) + tb = gr.top_block("top_block") + hb = gr.hier_block2("block", + gr.io_signature(0, 0, 0), + gr.io_signature(0, 0, 0)) + src = gr.vector_source_f(expected_data) + dst = gr.vector_sink_f() + hb.connect(src, dst) + tb.connect(hb) + tb.run() + self.assertEquals(expected_data, dst.data()) + + def test_027a_internally_unconnected_input(self): + tb = gr.top_block() + hb = gr.hier_block2("block", + gr.io_signature(1, 1, 1), + gr.io_signature(1, 1, 1)) + hsrc = gr.vector_source_b([1,]) + hb.connect(hsrc, hb) # wire output internally + src = gr.vector_source_b([1, ]) + dst = gr.vector_sink_b() + tb.connect(src, hb, dst) # hb's input is not connected internally + self.assertRaises(RuntimeError, + lambda: tb.run()) + + def test_027b_internally_unconnected_output(self): + tb = gr.top_block() + + hb = gr.hier_block2("block", + gr.io_signature(1, 1, 1), + gr.io_signature(1, 1, 1)) + hdst = gr.vector_sink_b() + hb.connect(hb, hdst) # wire input internally + src = gr.vector_source_b([1, ]) + dst = gr.vector_sink_b() + tb.connect(src, hb, dst) # hb's output is not connected internally + self.assertRaises(RuntimeError, + lambda: tb.run()) + + def test_027c_fully_unconnected_output(self): + tb = gr.top_block() + hb = gr.hier_block2("block", + gr.io_signature(1, 1, 1), + gr.io_signature(1, 1, 1)) + hsrc = gr.vector_sink_b() + hb.connect(hb, hsrc) # wire input internally + src = gr.vector_source_b([1, ]) + dst = gr.vector_sink_b() + tb.connect(src, hb) # hb's output is not connected internally or externally + self.assertRaises(RuntimeError, + lambda: tb.run()) + + def test_027d_fully_unconnected_input(self): + tb = gr.top_block() + hb = gr.hier_block2("block", + gr.io_signature(1, 1, 1), + gr.io_signature(1, 1, 1)) + hdst = gr.vector_source_b([1,]) + hb.connect(hdst, hb) # wire output internally + dst = gr.vector_sink_b() + tb.connect(hb, dst) # hb's input is not connected internally or externally + self.assertRaises(RuntimeError, + lambda: tb.run()) + + def test_028_singleton_reconfigure(self): + tb = gr.top_block() + hb = gr.hier_block2("block", + gr.io_signature(0, 0, 0), gr.io_signature(0, 0, 0)) + src = gr.vector_source_b([1, ]) + dst = gr.vector_sink_b() + hb.connect(src, dst) + tb.connect(hb) # Singleton connect + tb.lock() + tb.disconnect_all() + tb.connect(src, dst) + tb.unlock() + + def test_029_singleton_disconnect(self): + tb = gr.top_block() + src = gr.vector_source_b([1, ]) + dst = gr.vector_sink_b() + tb.connect(src, dst) + tb.disconnect(src) # Singleton disconnect + tb.connect(src, dst) + tb.run() + self.assertEquals(dst.data(), (1,)) + + def test_030_nested_input(self): + tb = gr.top_block() + src = gr.vector_source_b([1,]) + hb1 = gr.hier_block2("hb1", + gr.io_signature(1, 1, gr.sizeof_char), + gr.io_signature(0, 0, 0)) + hb2 = gr.hier_block2("hb2", + gr.io_signature(1, 1, gr.sizeof_char), + gr.io_signature(0, 0, 0)) + dst = gr.vector_sink_b() + tb.connect(src, hb1) + hb1.connect(hb1, hb2) + hb2.connect(hb2, gr.kludge_copy(gr.sizeof_char), dst) + tb.run() + self.assertEquals(dst.data(), (1,)) + + def test_031_multiple_internal_inputs(self): + tb = gr.top_block() + src = gr.vector_source_f([1.0,]) + hb = gr.hier_block2("hb", + gr.io_signature(1, 1, gr.sizeof_float), + gr.io_signature(1, 1, gr.sizeof_float)) + m1 = gr.multiply_const_ff(1.0) + m2 = gr.multiply_const_ff(2.0) + add = gr.add_ff() + hb.connect(hb, m1) # m1 is connected to hb external input #0 + hb.connect(hb, m2) # m2 is also connected to hb external input #0 + hb.connect(m1, (add, 0)) + hb.connect(m2, (add, 1)) + hb.connect(add, hb) # add is connected to hb external output #0 + dst = gr.vector_sink_f() + tb.connect(src, hb, dst) + tb.run() + self.assertEquals(dst.data(), (3.0,)) + + def test_032_nested_multiple_internal_inputs(self): + tb = gr.top_block() + src = gr.vector_source_f([1.0,]) + hb = gr.hier_block2("hb", + gr.io_signature(1, 1, gr.sizeof_float), + gr.io_signature(1, 1, gr.sizeof_float)) + hb2 = gr.hier_block2("hb", + gr.io_signature(1, 1, gr.sizeof_float), + gr.io_signature(1, 1, gr.sizeof_float)) + + m1 = gr.multiply_const_ff(1.0) + m2 = gr.multiply_const_ff(2.0) + add = gr.add_ff() + hb2.connect(hb2, m1) # m1 is connected to hb2 external input #0 + hb2.connect(hb2, m2) # m2 is also connected to hb2 external input #0 + hb2.connect(m1, (add, 0)) + hb2.connect(m2, (add, 1)) + hb2.connect(add, hb2) # add is connected to hb2 external output #0 + hb.connect(hb, hb2, hb) # hb as hb2 as nested internal block + dst = gr.vector_sink_f() + tb.connect(src, hb, dst) + tb.run() + self.assertEquals(dst.data(), (3.0,)) + + +if __name__ == "__main__": + gr_unittest.run(test_hier_block2, "test_hier_block2.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_hilbert.py b/gnuradio-core/src/python/gnuradio/gr/qa_hilbert.py new file mode 100755 index 000000000..27d01092b --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_hilbert.py @@ -0,0 +1,116 @@ +#!/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_hilbert (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_hilbert (self): + tb = self.tb + ntaps = 51 + sampling_freq = 100 + + expected_result = ( -1.4678005338941702e-11j, + -0.0011950774351134896j, + -0.0019336787518113852j, + -0.0034673355985432863j, + -0.0036765895783901215j, + -0.004916108213365078j, + -0.0042778430506587029j, + -0.006028641015291214j, + -0.005476709920912981j, + -0.0092810001224279404j, + -0.0095402700826525688j, + -0.016060983762145042j, + -0.016446959227323532j, + -0.02523401565849781j, + -0.024382550269365311j, + -0.035477779805660248j, + -0.033021725714206696j, + -0.048487484455108643j, + -0.04543270543217659j, + -0.069477587938308716j, + -0.066984444856643677j, + -0.10703597217798233j, + -0.10620346665382385j, + -0.1852707713842392j, + -0.19357112050056458j, + (7.2191945754696007e-09 -0.50004088878631592j), + (0.58778399229049683 -0.6155126690864563j), + (0.95105588436126709 -0.12377222627401352j), + (0.95105588436126709 +0.41524654626846313j), + (0.5877838134765625 +0.91611981391906738j), + (5.8516356205018383e-09 +1.0670661926269531j), + (-0.5877840518951416 +0.87856143712997437j), + (-0.95105588436126709 +0.35447561740875244j), + (-0.95105588436126709 -0.26055556535720825j), + (-0.5877838134765625 -0.77606213092803955j), + (-8.7774534307527574e-09 -0.96460390090942383j), + (0.58778399229049683 -0.78470128774642944j), + (0.95105588436126709 -0.28380891680717468j), + (0.95105588436126709 +0.32548999786376953j), + (0.5877838134765625 +0.82514488697052002j), + (1.4629089051254596e-08 +1.0096219778060913j), + (-0.5877840518951416 +0.81836479902267456j), + (-0.95105588436126709 +0.31451958417892456j), + (-0.95105588436126709 -0.3030143678188324j), + (-0.5877838134765625 -0.80480599403381348j), + (-1.7554906861505515e-08 -0.99516552686691284j), + (0.58778399229049683 -0.80540722608566284j), + (0.95105582475662231 -0.30557557940483093j), + (0.95105588436126709 +0.31097668409347534j), + (0.5877838134765625 +0.81027895212173462j), + (2.3406542482007353e-08 +1.0000816583633423j), + (-0.5877840518951416 +0.80908381938934326j), + (-0.95105588436126709 +0.30904293060302734j), + (-0.95105588436126709 -0.30904296040534973j), + (-0.5877838134765625 -0.80908387899398804j), + (-2.6332360292258272e-08 -1.0000815391540527j), + (0.58778399229049683 -0.80908381938934326j), + (0.95105582475662231 -0.30904299020767212j), + (0.95105588436126709 +0.30904293060302734j), + (0.5877838134765625 +0.80908381938934326j), + (3.218399768911695e-08 +1.0000815391540527j)) + + + src1 = gr.sig_source_f (sampling_freq, gr.GR_SIN_WAVE, + sampling_freq * 0.10, 1.0) + + head = gr.head (gr.sizeof_float, int (ntaps + sampling_freq * 0.10)) + hilb = gr.hilbert_fc (ntaps) + dst1 = gr.vector_sink_c () + tb.connect (src1, head) + tb.connect (head, hilb) + tb.connect (hilb, dst1) + tb.run () + dst_data = dst1.data () + self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 5) + +if __name__ == '__main__': + gr_unittest.run(test_hilbert, "test_hilbert.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_iir.py b/gnuradio-core/src/python/gnuradio/gr/qa_iir.py new file mode 100755 index 000000000..06b8d767e --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_iir.py @@ -0,0 +1,159 @@ +#!/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 + +class test_iir (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_iir_direct_001 (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + fftaps = () + fbtaps = () + expected_result = (0, 0, 0, 0, 0, 0, 0, 0) + src = gr.vector_source_f (src_data) + op = gr.iir_filter_ffd (fftaps, fbtaps) + dst = gr.vector_sink_f () + self.tb.connect (src, op) + self.tb.connect (op, dst) + self.tb.run () + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_iir_direct_002 (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + fftaps = (2,) + fbtaps = (0,) + expected_result = (2, 4, 6, 8, 10, 12, 14, 16) + src = gr.vector_source_f (src_data) + op = gr.iir_filter_ffd (fftaps, fbtaps) + dst = gr.vector_sink_f () + self.tb.connect (src, op) + self.tb.connect (op, dst) + self.tb.run () + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_iir_direct_003 (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + fftaps = (2, 11) + fbtaps = (0, 0) + expected_result = (2, 15, 28, 41, 54, 67, 80, 93) + src = gr.vector_source_f (src_data) + op = gr.iir_filter_ffd (fftaps, fbtaps) + dst = gr.vector_sink_f () + self.tb.connect (src, op) + self.tb.connect (op, dst) + self.tb.run () + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_iir_direct_004 (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + fftaps = (2, 11) + fbtaps = (0, -1) + expected_result = (2, 13, 15, 26, 28, 39, 41, 52) + src = gr.vector_source_f (src_data) + op = gr.iir_filter_ffd (fftaps, fbtaps) + dst = gr.vector_sink_f () + self.tb.connect (src, op) + self.tb.connect (op, dst) + self.tb.run () + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_iir_direct_005 (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + fftaps = (2, 11, 0) + fbtaps = (0, -1, 3) + expected_result = (2, 13, 21, 59, 58, 186, 68, 583) + src = gr.vector_source_f (src_data) + op = gr.iir_filter_ffd (fftaps, fbtaps) + dst = gr.vector_sink_f () + self.tb.connect (src, op) + self.tb.connect (op, dst) + self.tb.run () + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_iir_direct_006 (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + expected_result = (2, 13, 21, 59, 58, 186, 68, 583) + fftaps = (2, 1) + fbtaps = (0, -1) + src = gr.vector_source_f (src_data) + op = gr.iir_filter_ffd (fftaps, fbtaps) + fftaps = (2, 11, 0) + fbtaps = (0, -1, 3) + op.set_taps (fftaps, fbtaps) + dst = gr.vector_sink_f () + self.tb.connect (src, op) + self.tb.connect (op, dst) + self.tb.run () + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_iir_direct_007 (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + expected_result = (2,2,5,5,8,8,11,11) + fftaps = (2, 1) + fbtaps = (0, -1) + src = gr.vector_source_f (src_data) + op = gr.iir_filter_ffd (fftaps, fbtaps) + fftaps = (2,0,1) + fbtaps = (0, -1) + op.set_taps (fftaps, fbtaps) + dst = gr.vector_sink_f () + self.tb.connect (src, op) + self.tb.connect (op, dst) + self.tb.run () + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_iir_direct_008 (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + expected_result = (2,4,4,10,18,14,26,56) + fftaps = (2,) + fbtaps = (0, 1) + src = gr.vector_source_f (src_data) + op = gr.iir_filter_ffd (fftaps, fbtaps) + fftaps_data = (1) + fbtaps = (0,0, -1,3) + op.set_taps (fftaps, fbtaps) + dst = gr.vector_sink_f () + self.tb.connect (src, op) + self.tb.connect (op, dst) + self.tb.run () + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + + + +if __name__ == '__main__': + gr_unittest.run(test_iir, "test_iir.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_int_to_float.py b/gnuradio-core/src/python/gnuradio/gr/qa_int_to_float.py new file mode 100755 index 000000000..7536b3820 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_int_to_float.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# +# Copyright 2011 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest + +class test_int_to_float (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001(self): + + src_data = (0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5) + expected_result = [float(s) for s in src_data] + src = gr.vector_source_i(src_data) + op = gr.int_to_float() + dst = gr.vector_sink_f() + + self.tb.connect(src, op, dst) + self.tb.run() + result_data = dst.data() + + self.assertFloatTuplesAlmostEqual(expected_result, result_data) + + def test_002(self): + + vlen = 3 + src_data = ( 65000, 65001, 65002, 65003, 65004, 65005, + -65001, -65002, -65003) + expected_result = [ 65000.0, 65001.0, 65002.0, + 65003.0, 65004.0, 65005.0, + -65001.0, -65002.0, -65003.0] + src = gr.vector_source_i(src_data) + s2v = gr.stream_to_vector(gr.sizeof_int, vlen) + op = gr.int_to_float(vlen) + v2s = gr.vector_to_stream(gr.sizeof_float, vlen) + dst = gr.vector_sink_f() + + self.tb.connect(src, s2v, op, v2s, dst) + self.tb.run() + result_data = list(dst.data()) + + self.assertEqual(expected_result, result_data) + +if __name__ == '__main__': + gr_unittest.run(test_int_to_float, "test_int_to_float.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_integrate.py b/gnuradio-core/src/python/gnuradio/gr/qa_integrate.py new file mode 100755 index 000000000..ddb1310b6 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_integrate.py @@ -0,0 +1,75 @@ +#!/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 +import math + +class test_integrate (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_000_ss(self): + src_data = (1, 2, 3, 4, 5, 6) + dst_data = (6, 15) + src = gr.vector_source_s(src_data) + itg = gr.integrate_ss(3) + dst = gr.vector_sink_s() + self.tb.connect(src, itg, dst) + self.tb.run() + self.assertEqual(dst_data, dst.data()) + + def test_001_ii(self): + src_data = (1, 2, 3, 4, 5, 6) + dst_data = (6, 15) + src = gr.vector_source_i(src_data) + itg = gr.integrate_ii(3) + dst = gr.vector_sink_i() + self.tb.connect(src, itg, dst) + self.tb.run() + self.assertEqual(dst_data, dst.data()) + + def test_002_ff(self): + src_data = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0] + dst_data = [6.0, 15.0] + src = gr.vector_source_f(src_data) + itg = gr.integrate_ff(3) + dst = gr.vector_sink_f() + self.tb.connect(src, itg, dst) + self.tb.run() + self.assertFloatTuplesAlmostEqual(dst_data, dst.data(), 6) + + def test_003_cc(self): + src_data = [1.0+1.0j, 2.0+2.0j, 3.0+3.0j, 4.0+4.0j, 5.0+5.0j, 6.0+6.0j] + dst_data = [6.0+6.0j, 15.0+15.0j] + src = gr.vector_source_c(src_data) + itg = gr.integrate_cc(3) + dst = gr.vector_sink_c() + self.tb.connect(src, itg, dst) + self.tb.run() + self.assertComplexTuplesAlmostEqual(dst_data, dst.data(), 6) + +if __name__ == '__main__': + gr_unittest.run(test_integrate, "test_integrate.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_interleave.py b/gnuradio-core/src/python/gnuradio/gr/qa_interleave.py new file mode 100755 index 000000000..1ff178251 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_interleave.py @@ -0,0 +1,81 @@ +#!/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_interleave (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_int_001 (self): + lenx = 64 + src0 = gr.vector_source_f (range (0, lenx, 4)) + src1 = gr.vector_source_f (range (1, lenx, 4)) + src2 = gr.vector_source_f (range (2, lenx, 4)) + src3 = gr.vector_source_f (range (3, lenx, 4)) + op = gr.interleave (gr.sizeof_float) + dst = gr.vector_sink_f () + + self.tb.connect (src0, (op, 0)) + self.tb.connect (src1, (op, 1)) + self.tb.connect (src2, (op, 2)) + self.tb.connect (src3, (op, 3)) + self.tb.connect (op, dst) + self.tb.run () + expected_result = tuple (range (lenx)) + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_deint_001 (self): + lenx = 64 + src = gr.vector_source_f (range (lenx)) + op = gr.deinterleave (gr.sizeof_float) + dst0 = gr.vector_sink_f () + dst1 = gr.vector_sink_f () + dst2 = gr.vector_sink_f () + dst3 = gr.vector_sink_f () + + self.tb.connect (src, op) + self.tb.connect ((op, 0), dst0) + self.tb.connect ((op, 1), dst1) + self.tb.connect ((op, 2), dst2) + self.tb.connect ((op, 3), dst3) + self.tb.run () + + expected_result0 = tuple (range (0, lenx, 4)) + expected_result1 = tuple (range (1, lenx, 4)) + expected_result2 = tuple (range (2, lenx, 4)) + expected_result3 = tuple (range (3, lenx, 4)) + + self.assertFloatTuplesAlmostEqual (expected_result0, dst0.data ()) + self.assertFloatTuplesAlmostEqual (expected_result1, dst1.data ()) + self.assertFloatTuplesAlmostEqual (expected_result2, dst2.data ()) + self.assertFloatTuplesAlmostEqual (expected_result3, dst3.data ()) + +if __name__ == '__main__': + gr_unittest.run(test_interleave, "test_interleave.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_interp_fir_filter.py b/gnuradio-core/src/python/gnuradio/gr/qa_interp_fir_filter.py new file mode 100755 index 000000000..9bd9977c7 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_interp_fir_filter.py @@ -0,0 +1,54 @@ +#!/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_interp_fir_filter (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_fff (self): + taps = [1, 10, 100, 1000, 10000] + src_data = (0, 2, 3, 5, 7, 11, 13, 17) + interpolation = 3 + xr = (0,0,0,0,2,20,200,2003,20030,300,3005,30050,500,5007,50070,700,7011,70110,1100,11013,110130,1300,13017,130170) + expected_result = tuple ([float (x) for x in xr]) + + src = gr.vector_source_f (src_data) + op = gr.interp_fir_filter_fff (interpolation, taps) + dst = gr.vector_sink_f () + self.tb.connect (src, op) + self.tb.connect (op, dst) + self.tb.run () + result_data = dst.data () + L = min(len(result_data), len(expected_result)) + self.assertEqual (expected_result[0:L], result_data[0:L]) + + +if __name__ == '__main__': + gr_unittest.run(test_interp_fir_filter, "test_interp_fir_filter.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_keep_m_in_n.py b/gnuradio-core/src/python/gnuradio/gr/qa_keep_m_in_n.py new file mode 100755 index 000000000..922671d02 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_keep_m_in_n.py @@ -0,0 +1,58 @@ +#!/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 this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +from gnuradio import gr, gr_unittest +import sys +import random + +class test_keep_m_in_n(gr_unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_001(self): + self.maxDiff = None; + tb = gr.top_block() + src = gr.vector_source_b( range(0,100) ) + + # itemsize, M, N, offset + km2 = gr.keep_m_in_n( 1, 1, 2, 0 ); + km3 = gr.keep_m_in_n( 1, 1, 3, 1 ); + km7 = gr.keep_m_in_n( 1, 1, 7, 2 ); + snk2 = gr.vector_sink_b(); + snk3 = gr.vector_sink_b(); + snk7 = gr.vector_sink_b(); + tb.connect(src,km2,snk2); + tb.connect(src,km3,snk3); + tb.connect(src,km7,snk7); + tb.run(); + + self.assertEqual(range(0,100,2), list(snk2.data())); + self.assertEqual(range(1,100,3), list(snk3.data())); + self.assertEqual(range(2,100,7), list(snk7.data())); + + +if __name__ == '__main__': + gr_unittest.run(test_keep_m_in_n, "test_keep_m_in_n.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_kludge_copy.py b/gnuradio-core/src/python/gnuradio/gr/qa_kludge_copy.py new file mode 100755 index 000000000..2a3aa44b1 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_kludge_copy.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr, gr_unittest +import math +import random + + +class test_kludge_copy(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + self.rng = random.Random() + self.rng.seed(0) + + def tearDown(self): + del self.tb + del self.rng + + def make_random_int_tuple(self, L): + result = [] + for x in range(L): + result.append(self.rng.randint(int(-1e9), int(+1e9))) + return tuple(result) + + + def test_001(self): + # 1 input stream; 1 output stream + src0_data = self.make_random_int_tuple(16000) + src0 = gr.vector_source_i(src0_data) + op = gr.kludge_copy(gr.sizeof_int) + dst0 = gr.vector_sink_i() + self.tb.connect(src0, op, dst0) + self.tb.run() + dst0_data = dst0.data() + self.assertEqual(src0_data, dst0_data) + + def test_002(self): + # 2 input streams; 2 output streams + src0_data = self.make_random_int_tuple(16000) + src1_data = self.make_random_int_tuple(16000) + src0 = gr.vector_source_i(src0_data) + src1 = gr.vector_source_i(src1_data) + op = gr.kludge_copy(gr.sizeof_int) + dst0 = gr.vector_sink_i() + dst1 = gr.vector_sink_i() + self.tb.connect(src0, (op, 0), dst0) + self.tb.connect(src1, (op, 1), dst1) + self.tb.run() + dst0_data = dst0.data() + dst1_data = dst1.data() + self.assertEqual(src0_data, dst0_data) + self.assertEqual(src1_data, dst1_data) + + # Note: this is disabled due to triggering bug in ticket:181 + # It only occurs with new top block code + def xtest_003(self): + # number of input streams != number of output streams + src0_data = self.make_random_int_tuple(16000) + src1_data = self.make_random_int_tuple(16000) + src0 = gr.vector_source_i(src0_data) + src1 = gr.vector_source_i(src1_data) + op = gr.kludge_copy(gr.sizeof_int) + dst0 = gr.vector_sink_i() + dst1 = gr.vector_sink_i() + self.tb.connect(src0, (op, 0), dst0) + self.tb.connect(src1, (op, 1)) + self.assertRaises(ValueError, self.tb.run) + +if __name__ == '__main__': + gr_unittest.run(test_kludge_copy, "test_kludge_copy.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_kludged_imports.py b/gnuradio-core/src/python/gnuradio/gr/qa_kludged_imports.py new file mode 100755 index 000000000..39b5d781e --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_kludged_imports.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +# +# Copyright 2005,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_kludged_imports (gr_unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_blks_import(self): + # make sure that this somewhat magic import works + from gnuradio import blks2 + + def test_gru_import(self): + # make sure that this somewhat magic import works + from gnuradio import gru + + +if __name__ == '__main__': + gr_unittest.run(test_kludged_imports, "test_kludged_imports.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_max.py b/gnuradio-core/src/python/gnuradio/gr/qa_max.py new file mode 100755 index 000000000..f962df457 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_max.py @@ -0,0 +1,70 @@ +#!/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 +import math + + +class test_max (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + + def tearDown (self): + self.tb = None + + + def test_001(self): + + src_data = (0,0.2,-0.3,0,12,0) + expected_result = (float(max(src_data)), ) + + src = gr.vector_source_f(src_data) + s2v = gr.stream_to_vector(gr.sizeof_float, len(src_data)) + op = gr.max_ff( len(src_data) ) + dst = gr.vector_sink_f() + + + self.tb.connect(src, s2v, op, dst) + self.tb.run() + result_data = dst.data() + self.assertEqual(expected_result, result_data) + + def test_002(self): + + src_data=(-100,-99,-98,-97,-96,-1) + expected_result = (float(max(src_data)), ) + + src = gr.vector_source_f(src_data) + s2v = gr.stream_to_vector(gr.sizeof_float, len(src_data)) + op = gr.max_ff( len(src_data) ) + dst = gr.vector_sink_f() + + self.tb.connect(src, s2v, op, dst) + self.tb.run() + result_data = dst.data() + self.assertEqual(expected_result, result_data) + +if __name__ == '__main__': + gr_unittest.run(test_max, "test_max.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_message.py b/gnuradio-core/src/python/gnuradio/gr/qa_message.py new file mode 100755 index 000000000..4cef39bd7 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_message.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr, gr_unittest + + +def all_counts (): + return (gr.block_ncurrently_allocated (), + gr.block_detail_ncurrently_allocated (), + gr.buffer_ncurrently_allocated (), + gr.buffer_reader_ncurrently_allocated (), + gr.message_ncurrently_allocated ()) + + +class test_message (gr_unittest.TestCase): + + def setUp (self): + self.msgq = gr.msg_queue () + + def tearDown (self): + self.msgq = None + + def leak_check (self, fct): + begin = all_counts () + fct () + # tear down early so we can check for leaks + self.tearDown () + end = all_counts () + self.assertEqual (begin, end) + + def test_100 (self): + msg = gr.message (0, 1.5, 2.3) + self.assertEquals (0, msg.type()) + self.assertAlmostEqual (1.5, msg.arg1()) + self.assertAlmostEqual (2.3, msg.arg2()) + self.assertEquals (0, msg.length()) + + def test_101 (self): + s = 'This is a test' + msg = gr.message_from_string(s) + self.assertEquals(s, msg.to_string()) + + def test_200 (self): + self.leak_check (self.body_200) + + def body_200 (self): + self.msgq.insert_tail (gr.message (0)) + self.assertEquals (1, self.msgq.count()) + self.msgq.insert_tail (gr.message (1)) + self.assertEquals (2, self.msgq.count()) + msg0 = self.msgq.delete_head () + self.assertEquals (0, msg0.type()) + msg1 = self.msgq.delete_head () + self.assertEquals (1, msg1.type()) + self.assertEquals (0, self.msgq.count()) + + def test_201 (self): + self.leak_check (self.body_201) + + def body_201 (self): + self.msgq.insert_tail (gr.message (0)) + self.assertEquals (1, self.msgq.count()) + self.msgq.insert_tail (gr.message (1)) + self.assertEquals (2, self.msgq.count()) + + def test_202 (self): + self.leak_check (self.body_202) + + def body_202 (self): + # global msg + msg = gr.message (666) + + def test_300(self): + input_data = (0,1,2,3,4,5,6,7,8,9) + src = gr.vector_source_b(input_data) + dst = gr.vector_sink_b() + tb = gr.top_block() + tb.connect(src, dst) + tb.run() + self.assertEquals(input_data, dst.data()) + + def test_301(self): + # Use itemsize, limit constructor + src = gr.message_source(gr.sizeof_char) + dst = gr.vector_sink_b() + tb = gr.top_block() + tb.connect(src, dst) + src.msgq().insert_tail(gr.message_from_string('01234')) + src.msgq().insert_tail(gr.message_from_string('5')) + src.msgq().insert_tail(gr.message_from_string('')) + src.msgq().insert_tail(gr.message_from_string('6789')) + src.msgq().insert_tail(gr.message(1)) # send EOF + tb.run() + self.assertEquals(tuple(map(ord, '0123456789')), dst.data()) + + def test_302(self): + # Use itemsize, msgq constructor + msgq = gr.msg_queue() + src = gr.message_source(gr.sizeof_char, msgq) + dst = gr.vector_sink_b() + tb = gr.top_block() + tb.connect(src, dst) + src.msgq().insert_tail(gr.message_from_string('01234')) + src.msgq().insert_tail(gr.message_from_string('5')) + src.msgq().insert_tail(gr.message_from_string('')) + src.msgq().insert_tail(gr.message_from_string('6789')) + src.msgq().insert_tail(gr.message(1)) # send EOF + tb.run() + self.assertEquals(tuple(map(ord, '0123456789')), dst.data()) + +if __name__ == '__main__': + gr_unittest.run(test_message, "test_message.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_multiply_conjugate.py b/gnuradio-core/src/python/gnuradio/gr/qa_multiply_conjugate.py new file mode 100644 index 000000000..1601a109e --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_multiply_conjugate.py @@ -0,0 +1,57 @@ +#!/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, gr_unittest + +class test_multiply_conjugate (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_000 (self): + src_data0 = (-2-2j, -1-1j, -2+2j, -1+1j, + 2-2j, 1-1j, 2+2j, 1+1j, + 0+0j) + src_data1 = (-3-3j, -4-4j, -3+3j, -4+4j, + 3-3j, 4-4j, 3+3j, 4+4j, + 0+0j) + + exp_data = (12+0j, 8+0j, 12+0j, 8+0j, + 12+0j, 8+0j, 12+0j, 8+0j, + 0+0j) + src0 = gr.vector_source_c(src_data0) + src1 = gr.vector_source_c(src_data1) + op = gr.multiply_conjugate_cc () + dst = gr.vector_sink_c () + + self.tb.connect(src0, (op,0)) + self.tb.connect(src1, (op,1)) + self.tb.connect(op, dst) + self.tb.run() + result_data = dst.data () + self.assertEqual (exp_data, result_data) + +if __name__ == '__main__': + gr_unittest.run(test_multiply_conjugate, "test_multiply_conjugate.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_mute.py b/gnuradio-core/src/python/gnuradio/gr/qa_mute.py new file mode 100755 index 000000000..afdfdfe13 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_mute.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +# +# Copyright 2004,2005,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_mute (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def help_ii (self, src_data, exp_data, op): + for s in zip (range (len (src_data)), src_data): + src = gr.vector_source_i (s[1]) + self.tb.connect (src, (op, s[0])) + dst = gr.vector_sink_i () + self.tb.connect (op, dst) + self.tb.run () + result_data = dst.data () + self.assertEqual (exp_data, result_data) + + def help_ff (self, src_data, exp_data, op): + for s in zip (range (len (src_data)), src_data): + src = gr.vector_source_f (s[1]) + self.tb.connect (src, (op, s[0])) + dst = gr.vector_sink_f () + self.tb.connect (op, dst) + self.tb.run () + result_data = dst.data () + self.assertEqual (exp_data, result_data) + + def help_cc (self, src_data, exp_data, op): + for s in zip (range (len (src_data)), src_data): + src = gr.vector_source_c (s[1]) + self.tb.connect (src, (op, s[0])) + dst = gr.vector_sink_c () + self.tb.connect (op, dst) + self.tb.run () + result_data = dst.data () + self.assertEqual (exp_data, result_data) + + def test_unmute_ii(self): + src_data = (1, 2, 3, 4, 5) + expected_result = (1, 2, 3, 4, 5) + op = gr.mute_ii (False) + self.help_ii ((src_data,), expected_result, op) + + def test_mute_ii(self): + src_data = (1, 2, 3, 4, 5) + expected_result = (0, 0, 0, 0, 0) + op = gr.mute_ii (True) + self.help_ii ((src_data,), expected_result, op) + + def test_unmute_cc (self): + src_data = (1+5j, 2+5j, 3+5j, 4+5j, 5+5j) + expected_result = (1+5j, 2+5j, 3+5j, 4+5j, 5+5j) + op = gr.mute_cc (False) + self.help_cc ((src_data,), expected_result, op) + + def test_unmute_cc (self): + src_data = (1+5j, 2+5j, 3+5j, 4+5j, 5+5j) + expected_result = (0+0j, 0+0j, 0+0j, 0+0j, 0+0j) + op = gr.mute_cc (True) + self.help_cc ((src_data,), expected_result, op) + + +if __name__ == '__main__': + gr_unittest.run(test_mute, "test_mute.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_nlog10.py b/gnuradio-core/src/python/gnuradio/gr/qa_nlog10.py new file mode 100755 index 000000000..a87ed87ee --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_nlog10.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python +# +# Copyright 2005,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_nlog10(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001(self): + src_data = (-10, 0, 10, 100, 1000, 10000, 100000) + expected_result = (-180, -180, 10, 20, 30, 40, 50) + src = gr.vector_source_f(src_data) + op = gr.nlog10_ff(10) + dst = gr.vector_sink_f() + self.tb.connect (src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + +if __name__ == '__main__': + gr_unittest.run(test_nlog10, "test_nlog10.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_noise.py b/gnuradio-core/src/python/gnuradio/gr/qa_noise.py new file mode 100755 index 000000000..e87519150 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_noise.py @@ -0,0 +1,51 @@ +#!/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_noise_source(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001(self): + # Just confirm that we can instantiate a noise source + op = gr.noise_source_f(gr.GR_GAUSSIAN, 10, 10) + + def test_002(self): + # Test get methods + set_type = gr.GR_GAUSSIAN + set_ampl = 10 + op = gr.noise_source_f(set_type, set_ampl, 10) + get_type = op.type() + get_ampl = op.amplitude() + + self.assertEqual(get_type, set_type) + self.assertEqual(get_ampl, set_ampl) + + +if __name__ == '__main__': + gr_unittest.run(test_noise_source, "test_noise_source.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_pack_k_bits.py b/gnuradio-core/src/python/gnuradio/gr/qa_pack_k_bits.py new file mode 100755 index 000000000..25fc5e9fc --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_pack_k_bits.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr, gr_unittest +import random + +class test_pack(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block () + + def tearDown(self): + self.tb = None + + def test_001(self): + src_data = (1,0,1,1,0,1,1,0) + expected_results = (1,0,1,1,0,1,1,0) + src = gr.vector_source_b(src_data,False) + op = gr.pack_k_bits_bb(1) + dst = gr.vector_sink_b() + self.tb.connect(src, op, dst) + self.tb.run() + self.assertEqual(expected_results, dst.data()) + + def test_002(self): + src_data = (1,0,1,1,0,0,0,1) + expected_results = ( 2, 3, 0, 1) + src = gr.vector_source_b(src_data,False) + op = gr.pack_k_bits_bb(2) + dst = gr.vector_sink_b() + self.tb.connect(src, op, dst) + self.tb.run() + #self.assertEqual(expected_results, dst.data()) + self.assertEqual(expected_results, dst.data()) + + def test_003(self): + src_data = expected_results = map(lambda x: random.randint(0,3), range(10)); + src = gr.vector_source_b( src_data ); + pack = gr.pack_k_bits_bb(2); + unpack = gr.unpack_k_bits_bb(2); + snk = gr.vector_sink_b(); + self.tb.connect(src,unpack,pack,snk); + self.tb.run() + self.assertEqual(list(expected_results), list(snk.data())); + +if __name__ == '__main__': + gr_unittest.run(test_pack, "test_pack.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_packed_to_unpacked.py b/gnuradio-core/src/python/gnuradio/gr/qa_packed_to_unpacked.py new file mode 100755 index 000000000..08accd0ad --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_packed_to_unpacked.py @@ -0,0 +1,405 @@ +#!/usr/bin/env python +# +# Copyright 2005,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 random + +class test_packing(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block () + + def tearDown(self): + self.tb = None + + def test_001(self): + """ + Test stream_to_streams. + """ + src_data = (0x80,) + expected_results = (1,0,0,0,0,0,0,0) + src = gr.vector_source_b(src_data,False) + op = gr.packed_to_unpacked_bb(1, gr.GR_MSB_FIRST) + self.tb.connect(src, op) + + dst = gr.vector_sink_b() + self.tb.connect(op, dst) + + self.tb.run() + + self.assertEqual(expected_results, dst.data()) + + def test_002(self): + """ + Test stream_to_streams. + """ + src_data = (0x80,) + expected_results = (0,0,0,0,0,0,0, 1) + src = gr.vector_source_b(src_data,False) + op = gr.packed_to_unpacked_bb(1, gr.GR_LSB_FIRST) + self.tb.connect(src, op) + + dst = gr.vector_sink_b() + self.tb.connect(op, dst) + + self.tb.run() + + self.assertEqual(expected_results, dst.data()) + + def test_003(self): + """ + Test stream_to_streams. + """ + src_data = (0x11,) + expected_results = (4, 2) + src = gr.vector_source_b(src_data,False) + op = gr.packed_to_unpacked_bb(3, gr.GR_LSB_FIRST) + self.tb.connect(src, op) + + dst = gr.vector_sink_b() + self.tb.connect(op, dst) + + self.tb.run() + + self.assertEqual(expected_results, dst.data()) + + def test_004(self): + """ + Test stream_to_streams. + """ + src_data = (0x11,) + expected_results = (0, 4) + src = gr.vector_source_b(src_data,False) + op = gr.packed_to_unpacked_bb(3, gr.GR_MSB_FIRST) + self.tb.connect(src, op) + + dst = gr.vector_sink_b() + self.tb.connect(op, dst) + + self.tb.run() + + self.assertEqual(expected_results, dst.data()) + + def test_005(self): + """ + Test stream_to_streams. + """ + src_data = (1,0,0,0,0,0,1,0,0,1,0,1,1,0,1,0) + expected_results = (0x82,0x5a) + src = gr.vector_source_b(src_data,False) + op = gr.unpacked_to_packed_bb(1, gr.GR_MSB_FIRST) + self.tb.connect(src, op) + + dst = gr.vector_sink_b() + self.tb.connect(op, dst) + + self.tb.run() + + self.assertEqual(expected_results, dst.data()) + + def test_006(self): + """ + Test stream_to_streams. + """ + src_data = (0,1,0,0,0,0,0,1,0,1,0,1,1,0,1,0) + expected_results = (0x82,0x5a) + src = gr.vector_source_b(src_data,False) + op = gr.unpacked_to_packed_bb(1, gr.GR_LSB_FIRST) + self.tb.connect(src, op) + + dst = gr.vector_sink_b() + self.tb.connect(op, dst) + + self.tb.run() + + self.assertEqual(expected_results, dst.data()) + + + def test_007(self): + """ + Test stream_to_streams. + """ + src_data = (4, 2, 0,0,0) + expected_results = (0x11,) + src = gr.vector_source_b(src_data,False) + op = gr.unpacked_to_packed_bb(3, gr.GR_LSB_FIRST) + self.tb.connect(src, op) + + dst = gr.vector_sink_b() + self.tb.connect(op, dst) + + self.tb.run() + + self.assertEqual(expected_results, dst.data()) + + def test_008(self): + """ + Test stream_to_streams. + """ + src_data = (0, 4, 2,0,0) + expected_results = (0x11,) + src = gr.vector_source_b(src_data,False) + op = gr.unpacked_to_packed_bb(3, gr.GR_MSB_FIRST) + self.tb.connect(src, op) + + dst = gr.vector_sink_b() + self.tb.connect(op, dst) + + self.tb.run() + + self.assertEqual(expected_results, dst.data()) + + def test_009(self): + """ + Test stream_to_streams. + """ + + random.seed(0) + src_data = [] + for i in xrange(202): + src_data.append((random.randint(0,255))) + src_data = tuple(src_data) + expected_results = src_data + + src = gr.vector_source_b(tuple(src_data),False) + op1 = gr.packed_to_unpacked_bb(3, gr.GR_MSB_FIRST) + op2 = gr.unpacked_to_packed_bb(3, gr.GR_MSB_FIRST) + self.tb.connect(src, op1, op2) + + dst = gr.vector_sink_b() + self.tb.connect(op2, dst) + + self.tb.run() + + self.assertEqual(expected_results[0:201], dst.data()) + + def test_010(self): + """ + Test stream_to_streams. + """ + + random.seed(0) + src_data = [] + for i in xrange(56): + src_data.append((random.randint(0,255))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_b(tuple(src_data),False) + op1 = gr.packed_to_unpacked_bb(7, gr.GR_MSB_FIRST) + op2 = gr.unpacked_to_packed_bb(7, gr.GR_MSB_FIRST) + self.tb.connect(src, op1, op2) + dst = gr.vector_sink_b() + self.tb.connect(op2, dst) + + self.tb.run() + self.assertEqual(expected_results[0:201], dst.data()) + + def test_011(self): + """ + Test stream_to_streams. + """ + + random.seed(0) + src_data = [] + for i in xrange(56): + src_data.append((random.randint(0,255))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_b(tuple(src_data),False) + op1 = gr.packed_to_unpacked_bb(7, gr.GR_LSB_FIRST) + op2 = gr.unpacked_to_packed_bb(7, gr.GR_LSB_FIRST) + self.tb.connect(src, op1, op2) + dst = gr.vector_sink_b() + self.tb.connect(op2, dst) + + self.tb.run() + self.assertEqual(expected_results[0:201], dst.data()) + + + # tests on shorts + + def test_100a(self): + """ + test short version + """ + random.seed(0) + src_data = [] + for i in xrange(100): + src_data.append((random.randint(-2**15,2**15-1))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_s(tuple(src_data),False) + op1 = gr.packed_to_unpacked_ss(1, gr.GR_MSB_FIRST) + op2 = gr.unpacked_to_packed_ss(1, gr.GR_MSB_FIRST) + self.tb.connect(src, op1, op2) + dst = gr.vector_sink_s() + self.tb.connect(op2, dst) + + self.tb.run() + self.assertEqual(expected_results, dst.data()) + + def test_100b(self): + """ + test short version + """ + random.seed(0) + src_data = [] + for i in xrange(100): + src_data.append((random.randint(-2**15,2**15-1))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_s(tuple(src_data),False) + op1 = gr.packed_to_unpacked_ss(1, gr.GR_LSB_FIRST) + op2 = gr.unpacked_to_packed_ss(1, gr.GR_LSB_FIRST) + self.tb.connect(src, op1, op2) + dst = gr.vector_sink_s() + self.tb.connect(op2, dst) + + self.tb.run() + self.assertEqual(expected_results, dst.data()) + + def test_101a(self): + """ + test short version + """ + random.seed(0) + src_data = [] + for i in xrange(100): + src_data.append((random.randint(-2**15,2**15-1))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_s(tuple(src_data),False) + op1 = gr.packed_to_unpacked_ss(8, gr.GR_MSB_FIRST) + op2 = gr.unpacked_to_packed_ss(8, gr.GR_MSB_FIRST) + self.tb.connect(src, op1, op2) + dst = gr.vector_sink_s() + self.tb.connect(op2, dst) + + self.tb.run() + self.assertEqual(expected_results, dst.data()) + + def test_101b(self): + """ + test short version + """ + random.seed(0) + src_data = [] + for i in xrange(100): + src_data.append((random.randint(-2**15,2**15-1))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_s(tuple(src_data),False) + op1 = gr.packed_to_unpacked_ss(8, gr.GR_LSB_FIRST) + op2 = gr.unpacked_to_packed_ss(8, gr.GR_LSB_FIRST) + self.tb.connect(src, op1, op2) + dst = gr.vector_sink_s() + self.tb.connect(op2, dst) + + self.tb.run() + self.assertEqual(expected_results, dst.data()) + + # tests on ints + + def test_200a(self): + """ + test int version + """ + random.seed(0) + src_data = [] + for i in xrange(100): + src_data.append((random.randint(-2**31,2**31-1))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_i(tuple(src_data),False) + op1 = gr.packed_to_unpacked_ii(1, gr.GR_MSB_FIRST) + op2 = gr.unpacked_to_packed_ii(1, gr.GR_MSB_FIRST) + self.tb.connect(src, op1, op2) + dst = gr.vector_sink_i() + self.tb.connect(op2, dst) + + self.tb.run() + self.assertEqual(expected_results, dst.data()) + + def test_200b(self): + """ + test int version + """ + random.seed(0) + src_data = [] + for i in xrange(100): + src_data.append((random.randint(-2**31,2**31-1))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_i(tuple(src_data),False) + op1 = gr.packed_to_unpacked_ii(1, gr.GR_LSB_FIRST) + op2 = gr.unpacked_to_packed_ii(1, gr.GR_LSB_FIRST) + self.tb.connect(src, op1, op2) + dst = gr.vector_sink_i() + self.tb.connect(op2, dst) + + self.tb.run() + self.assertEqual(expected_results, dst.data()) + + def test_201a(self): + """ + test int version + """ + random.seed(0) + src_data = [] + for i in xrange(100): + src_data.append((random.randint(-2**31,2**31-1))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_i(tuple(src_data),False) + op1 = gr.packed_to_unpacked_ii(8, gr.GR_MSB_FIRST) + op2 = gr.unpacked_to_packed_ii(8, gr.GR_MSB_FIRST) + self.tb.connect(src, op1, op2) + dst = gr.vector_sink_i() + self.tb.connect(op2, dst) + + self.tb.run() + self.assertEqual(expected_results, dst.data()) + + def test_201b(self): + """ + test int version + """ + random.seed(0) + src_data = [] + for i in xrange(100): + src_data.append((random.randint(-2**31,2**31-1))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_i(tuple(src_data),False) + op1 = gr.packed_to_unpacked_ii(8, gr.GR_LSB_FIRST) + op2 = gr.unpacked_to_packed_ii(8, gr.GR_LSB_FIRST) + self.tb.connect(src, op1, op2) + dst = gr.vector_sink_i() + self.tb.connect(op2, dst) + + self.tb.run() + self.assertEqual(expected_results, dst.data()) + + +if __name__ == '__main__': + gr_unittest.run(test_packing, "test_packing.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py b/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py new file mode 100755 index 000000000..098aabb4a --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_pdu.py @@ -0,0 +1,109 @@ +#!/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, gr_unittest +import pmt +import time + +class test_pdu(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_000(self): + # Just run some data through and make sure it doesn't puke. + src_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + + src = gr.pdu_to_tagged_stream(gr.pdu_byte) + snk3 = gr.tagged_stream_to_pdu(gr.pdu_byte) + snk2 = gr.vector_sink_b() + snk = gr.tag_debug(1, "test") + + dbg = gr.message_debug() + + # Test that the right number of ports exist. + pi = dbg.message_ports_in() + po = dbg.message_ports_out() + self.assertEqual(pmt.pmt_length(pi), 3) + self.assertEqual(pmt.pmt_length(po), 0) + + pi = snk3.message_ports_in() + po = snk3.message_ports_out() + self.assertEqual(pmt.pmt_length(pi), 0) + self.assertEqual(pmt.pmt_length(po), 1) + + #print "Message Debug input ports: " + #pmt.pmt_print(pi) + #print "Message Debug output ports: " + #pmt.pmt_print(po) + + #print "Stream to PDU input ports: " + #pmt.pmt_print(pi) + #print "Stream to PDU output ports: " + #pmt.pmt_print(po) + + self.tb.connect(src, snk) + self.tb.connect(src, snk2) + self.tb.connect(src, snk3) + + self.tb.msg_connect(snk3, "pdus", dbg, "store") + self.tb.start() + + # make our reference and message pmts + port = pmt.pmt_intern("pdus") + msg = pmt.pmt_cons( pmt.PMT_NIL, pmt.pmt_make_u8vector(16, 0xFF) ) + + #print "printing port & msg" + #pmt.pmt_print(port) + #pmt.pmt_print(msg) + + # post the message + src.to_basic_block()._post( port, msg ) + + while(dbg.num_messages() < 1): + time.sleep(0.1) + self.tb.stop() + self.tb.wait() + + # Get the vector of data from the vector sink + result_data = snk2.data() + + # Get the vector of data from the message sink + # Convert the message PMT as a pair into its vector + result_msg = dbg.get_message(0) + msg_vec = pmt.pmt_cdr(result_msg) + pmt.pmt_print(msg_vec) + + # Convert the PMT vector into a Python list + msg_data = [] + for i in xrange(16): + msg_data.append(pmt.pmt_u8vector_ref(msg_vec, i)) + + actual_data = 16*[0xFF,] + self.assertEqual(actual_data, list(result_data)) + self.assertEqual(actual_data, msg_data) + +if __name__ == '__main__': + gr_unittest.run(test_pdu, "test_pdu.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_pipe_fittings.py b/gnuradio-core/src/python/gnuradio/gr/qa_pipe_fittings.py new file mode 100755 index 000000000..1f24062b1 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_pipe_fittings.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python +# +# Copyright 2005,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 + +if 0: + import os + print "pid =", os.getpid() + raw_input("Attach, then press Enter to continue") + + +def calc_expected_result(src_data, n): + assert (len(src_data) % n) == 0 + result = [list() for x in range(n)] + #print "len(result) =", len(result) + for i in xrange(len(src_data)): + (result[i % n]).append(src_data[i]) + return [tuple(x) for x in result] + + +class test_pipe_fittings(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block () + + def tearDown(self): + self.tb = None + + def test_001(self): + """ + Test stream_to_streams. + """ + n = 8 + src_len = n * 8 + src_data = range(src_len) + + expected_results = calc_expected_result(src_data, n) + #print "expected results: ", expected_results + src = gr.vector_source_i(src_data) + op = gr.stream_to_streams(gr.sizeof_int, n) + self.tb.connect(src, op) + + dsts = [] + for i in range(n): + dst = gr.vector_sink_i() + self.tb.connect((op, i), (dst, 0)) + dsts.append(dst) + + self.tb.run() + + for d in range(n): + self.assertEqual(expected_results[d], dsts[d].data()) + + def test_002(self): + """ + Test streams_to_stream (using stream_to_streams). + """ + n = 8 + src_len = n * 8 + src_data = tuple(range(src_len)) + expected_results = src_data + + src = gr.vector_source_i(src_data) + op1 = gr.stream_to_streams(gr.sizeof_int, n) + op2 = gr.streams_to_stream(gr.sizeof_int, n) + dst = gr.vector_sink_i() + + self.tb.connect(src, op1) + for i in range(n): + self.tb.connect((op1, i), (op2, i)) + self.tb.connect(op2, dst) + + self.tb.run() + self.assertEqual(expected_results, dst.data()) + + def test_003(self): + """ + Test streams_to_vector (using stream_to_streams & vector_to_stream). + """ + n = 8 + src_len = n * 8 + src_data = tuple(range(src_len)) + expected_results = src_data + + src = gr.vector_source_i(src_data) + op1 = gr.stream_to_streams(gr.sizeof_int, n) + op2 = gr.streams_to_vector(gr.sizeof_int, n) + op3 = gr.vector_to_stream(gr.sizeof_int, n) + dst = gr.vector_sink_i() + + self.tb.connect(src, op1) + for i in range(n): + self.tb.connect((op1, i), (op2, i)) + self.tb.connect(op2, op3, dst) + + self.tb.run() + self.assertEqual(expected_results, dst.data()) + + def test_004(self): + """ + Test vector_to_streams. + """ + n = 8 + src_len = n * 8 + src_data = tuple(range(src_len)) + expected_results = src_data + + src = gr.vector_source_i(src_data) + op1 = gr.stream_to_vector(gr.sizeof_int, n) + op2 = gr.vector_to_streams(gr.sizeof_int, n) + op3 = gr.streams_to_stream(gr.sizeof_int, n) + dst = gr.vector_sink_i() + + self.tb.connect(src, op1, op2) + for i in range(n): + self.tb.connect((op2, i), (op3, i)) + self.tb.connect(op3, dst) + + self.tb.run() + self.assertEqual(expected_results, dst.data()) + +if __name__ == '__main__': + gr_unittest.run(test_pipe_fittings, "test_pipe_fittings.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_pll_carriertracking.py b/gnuradio-core/src/python/gnuradio/gr/qa_pll_carriertracking.py new file mode 100755 index 000000000..8964db53d --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_pll_carriertracking.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python +# +# Copyright 2004,2007,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. +# + +from gnuradio import gr, gr_unittest +import math + +class test_pll_carriertracking (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block() + + def tearDown (self): + self.tb = None + + def test_pll_carriertracking (self): + expected_result = ((1.00000238419+7.21919457547e-09j), + (0.998025715351+0.062790453434j), + (0.992777824402+0.119947694242j), + (0.985192835331+0.171441286802j), + (0.976061582565+0.217501848936j), + (0.966034710407+0.258409559727j), + (0.95565611124+0.294477283955j), + (0.945357382298+0.326030552387j), + (0.935475051403+0.353395611048j), + (0.926258146763+0.376889169216j), + (0.917895197868+0.39681750536j), + (0.910515546799+0.413470208645j), + (0.904196679592+0.427117019892j), + (0.898972511292+0.438006043434j), + (0.894769787788+0.446523308754j), + (0.891652584076+0.452715367079j), + (0.8895829916+0.456773489714j), + (0.888502895832+0.458873122931j), + (0.888343691826+0.459175437689j), + (0.889035582542+0.457833081484j), + (0.890497922897+0.454985737801j), + (0.892645597458+0.450762689114j), + (0.895388305187+0.445282936096j), + (0.898648142815+0.438664674759j), + (0.902342617512+0.431016951799j), + (0.906392872334+0.422441422939j), + (0.910642921925+0.413191765547j), + (0.915039420128+0.403358519077j), + (0.919594764709+0.392864197493j), + (0.92425006628+0.381792247295j), + (0.928944349289+0.370217680931j), + (0.933634519577+0.358220815659j), + (0.938279032707+0.345874190331j), + (0.942840516567+0.333247303963j), + (0.947280526161+0.32040438056j), + (0.951574921608+0.307409763336j), + (0.955703914165+0.294323593378j), + (0.959648966789+0.281201630831j), + (0.963392794132+0.268095195293j), + (0.966880619526+0.255221515894j), + (0.970162451267+0.242447137833j), + (0.973235487938+0.229809194803j), + (0.97609680891+0.217341512442j), + (0.978744983673+0.20507311821j), + (0.981189727783+0.193033605814j), + (0.983436584473+0.181248426437j), + (0.985490739346+0.169738590717j), + (0.987353682518+0.158523857594j), + (0.989041447639+0.147622272372j), + (0.990563035011+0.137049794197j), + (0.991928339005+0.126818582416j), + (0.993117690086+0.117111675441j), + (0.994156062603+0.107930034399j), + (0.995076179504+0.0990980416536j), + (0.995887458324+0.0906178802252j), + (0.996591091156+0.0824909061193j), + (0.997202515602+0.0747182965279j), + (0.997730851173+0.0672992765903j), + (0.998185396194+0.0602316558361j), + (0.99856698513+0.0535135567188j), + (0.998885989189+0.0471420884132j), + (0.99915266037+0.0411129891872j), + (0.999372899532+0.0354214012623j), + (0.999548316002+0.0300626158714j), + (0.999680638313+0.0252036750317j), + (0.999784469604+0.020652115345j), + (0.999865531921+0.0163950324059j), + (0.999923825264+0.0124222636223j), + (0.999960243702+0.00872156023979j), + (0.999983668327+0.00528120994568j), + (0.999997138977+0.00209015607834j), + (1.00000119209-0.00086285173893j), + (0.999992132187-0.00358882546425j), + (0.999979138374-0.00609711557627j), + (0.999963641167-0.00839691981673j), + (0.999947249889-0.0104993218556j), + (0.999924004078-0.0122378543019j), + (0.999904811382-0.0136305987835j), + (0.999888062477-0.0148707330227j), + (0.9998742342-0.0159679055214j), + (0.999856114388-0.0169314742088j), + (0.999839782715-0.0177700817585j), + (0.999826967716-0.0184917747974j), + (0.999818325043-0.0191045701504j), + (0.999807476997-0.0196143388748j), + (0.999797284603-0.0200265944004j), + (0.999791204929-0.0203481912613j), + (0.99978852272-0.0205836892128j), + (0.99978530407-0.0207380950451j), + (0.999785065651-0.0206423997879j), + (0.999787807465-0.0204866230488j), + (0.999794304371-0.0202808082104j), + (0.999800384045-0.0200312435627j), + (0.999803245068-0.0197458267212j), + (0.9998087883-0.0194311738014j), + (0.999816894531-0.0190933048725j), + (0.999825954437-0.0187371373177j), + (0.999829888344-0.0183679759502j), + (0.999835848808-0.017987690866j), + (0.999844014645-0.0176006518304j)) + + sampling_freq = 10e3 + freq = sampling_freq / 100 + + loop_bw = math.pi/100.0 + maxf = 1 + minf = -1 + + src = gr.sig_source_c (sampling_freq, gr.GR_COS_WAVE, freq, 1.0) + pll = gr.pll_carriertracking_cc(loop_bw, maxf, minf) + head = gr.head (gr.sizeof_gr_complex, int (freq)) + dst = gr.vector_sink_c () + + self.tb.connect (src, pll, head) + self.tb.connect (head, dst) + + self.tb.run () + dst_data = dst.data () + self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 5) + +if __name__ == '__main__': + gr_unittest.run(test_pll_carriertracking, "test_pll_carriertracking.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_pll_freqdet.py b/gnuradio-core/src/python/gnuradio/gr/qa_pll_freqdet.py new file mode 100755 index 000000000..219e9b84b --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_pll_freqdet.py @@ -0,0 +1,160 @@ +#!/usr/bin/env python +# +# Copyright 2004,2007,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. +# + +from gnuradio import gr, gr_unittest +import math + +class test_pll_freqdet (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block() + + def tearDown (self): + self.tb = None + + def test_pll_freqdet (self): + expected_result = (0.0, + 4.33888922882e-08, + 0.367369994515, + 1.08135249597, + 2.10983253908, + 3.42221529438, + 4.98940390402, + 6.78379190842, + 8.77923286024, + 10.9510106794, + 13.2758363182, + 15.7317829127, + 18.2982902299, + 20.9561068599, + 23.6755271122, + 26.452952094, + 29.2731265301, + 32.1219053479, + 34.9862418188, + 37.8540971414, + 40.7144315483, + 43.5571390869, + 46.3730179743, + 49.1537231663, + 51.8917218889, + 54.58026103, + 57.2015358514, + 59.7513664199, + 62.2380533124, + 64.657612252, + 67.006640002, + 69.2822432184, + 71.4820384499, + 73.6041047056, + 75.6469478817, + 77.6094829742, + 79.4909866472, + 81.2911031615, + 83.0097850853, + 84.6355598352, + 86.1820937186, + 87.6504420946, + 89.0418441206, + 90.3577286819, + 91.5996432431, + 92.7692775646, + 93.8684162704, + 94.8989269904, + 95.8627662892, + 96.7619381633, + 97.598505899, + 98.362769679, + 99.0579904444, + 99.6992633875, + 100.288805948, + 100.828805921, + 101.321421457, + 101.76878699, + 102.17300138, + 102.536116055, + 102.860158727, + 103.147085962, + 103.398830608, + 103.617254366, + 103.792467691, + 103.939387906, + 104.060030865, + 104.15631756, + 104.230085975, + 104.283067372, + 104.316933727, + 104.333238432, + 104.333440018, + 104.318914008, + 104.290941063, + 104.250742554, + 104.187634452, + 104.103822339, + 104.013227468, + 103.916810336, + 103.815448432, + 103.709936239, + 103.600997093, + 103.489283183, + 103.375351833, + 103.259712936, + 103.142828952, + 103.025091195, + 102.90686726, + 102.776726069, + 102.648078982, + 102.521459607, + 102.397294831, + 102.275999684, + 102.157882471, + 102.043215927, + 101.93218978, + 101.824958181, + 101.72159228, + 101.622151366) + + sampling_freq = 10e3 + freq = sampling_freq / 100 + + loop_bw = math.pi/100.0 + maxf = 1 + minf = -1 + + src = gr.sig_source_c (sampling_freq, gr.GR_COS_WAVE, freq, 1.0) + pll = gr.pll_freqdet_cf(loop_bw, maxf, minf) + head = gr.head (gr.sizeof_float, int (freq)) + dst = gr.vector_sink_f () + + self.tb.connect (src, pll, head) + self.tb.connect (head, dst) + + self.tb.run () + dst_data = dst.data () + + # convert it from normalized frequency to absolute frequency (Hz) + dst_data = [i*(sampling_freq/(2*math.pi)) for i in dst_data] + + self.assertFloatTuplesAlmostEqual (expected_result, dst_data, 3) + +if __name__ == '__main__': + gr_unittest.run(test_pll_freqdet, "test_pll_freqdet.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_pll_refout.py b/gnuradio-core/src/python/gnuradio/gr/qa_pll_refout.py new file mode 100755 index 000000000..f319f6381 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_pll_refout.py @@ -0,0 +1,156 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr, gr_unittest +import math + +class test_pll_refout (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block() + + def tearDown (self): + self.tb = None + + def test_pll_refout (self): + expected_result = ((1+0j), + (1+6.4087357643e-10j), + (0.999985277653+0.00542619498447j), + (0.999868750572+0.0162021834403j), + (0.99948567152+0.0320679470897j), + (0.99860727787+0.0527590736747j), + (0.996953129768+0.0780025869608j), + (0.994203746319+0.107512556016j), + (0.990011692047+0.140985429287j), + (0.984013140202+0.178095817566j), + (0.975838363171+0.218493551016j), + (0.965121984482+0.261800557375j), + (0.95151245594+0.307610183954j), + (0.934681296349+0.355486690998j), + (0.914401650429+0.404808044434j), + (0.890356600285+0.455263823271j), + (0.862329125404+0.506348133087j), + (0.830152392387+0.557536482811j), + (0.793714106083+0.608290970325j), + (0.752960026264+0.658066213131j), + (0.707896590233+0.706316053867j), + (0.658591926098+0.752500295639j), + (0.605175673962+0.796091973782j), + (0.547837555408+0.836584687233j), + (0.48682525754+0.873499393463j), + (0.42244040966+0.906390726566j), + (0.355197101831+0.934791445732j), + (0.285494059324+0.958380460739j), + (0.213591173291+0.976923108101j), + (0.139945343137+0.990159213543j), + (0.065038472414+0.997882783413j), + (-0.0106285437942+0.999943494797j), + (-0.0865436866879+0.996248066425j), + (-0.162189796567+0.986759603024j), + (-0.23705175519+0.971496999264j), + (-0.310622543097+0.950533330441j), + (-0.38240903616+0.923993110657j), + (-0.451937526464+0.89204955101j), + (-0.518758952618+0.854920566082j), + (-0.582311093807+0.812966048717j), + (-0.642372369766+0.76639264822j), + (-0.698591887951+0.715520322323j), + (-0.750654160976+0.660695314407j), + (-0.798280358315+0.602286040783j), + (-0.841228663921+0.540679454803j), + (-0.87929558754+0.476276367903j), + (-0.912315964699+0.409486919641j), + (-0.940161883831+0.340728074312j), + (-0.962742805481+0.270418733358j), + (-0.980004072189+0.198977485299j), + (-0.991925954819+0.126818284392j), + (-0.99851256609+0.0545223206282j), + (-0.999846458435-0.0175215266645j), + (-0.996021270752-0.0891158208251j), + (-0.987133920193-0.159895718098j), + (-0.973306238651-0.2295101583j), + (-0.954683184624-0.297624111176j), + (-0.931430280209-0.363919824362j), + (-0.903732538223-0.428097635508j), + (-0.871792256832-0.489875763655j), + (-0.835827112198-0.548992812634j), + (-0.796068251133-0.605206847191j), + (-0.752758979797-0.658296227455j), + (-0.706152498722-0.70805978775j), + (-0.656641483307-0.754202902317j), + (-0.604367733002-0.79670548439j), + (-0.549597978592-0.835429251194j), + (-0.492602348328-0.870254516602j), + (-0.433654457331-0.901079237461j), + (-0.373029649258-0.927819430828j), + (-0.31100410223-0.950408577919j), + (-0.247853919864-0.968797445297j), + (-0.183855071664-0.982953369617j), + (-0.119282215834-0.992860376835j), + (-0.0544078871608-0.998518764973j), + (0.0104992967099-0.999944865704j), + (0.0749994292855-0.997183561325j), + (0.138844624162-0.990314185619j), + (0.201967850327-0.979392170906j), + (0.264124274254-0.964488625526j), + (0.325075358152-0.945688128471j), + (0.3845885396-0.92308807373j), + (0.442438393831-0.89679890871j), + (0.498407125473-0.866943061352j), + (0.552284479141-0.833655714989j), + (0.603869199753-0.797083437443j), + (0.652970373631-0.757383465767j), + (0.69940674305-0.714723825455j), + (0.743007957935-0.66928255558j), + (0.78350687027-0.62138313055j), + (0.820889055729-0.571087777615j), + (0.855021059513-0.51859331131j), + (0.885780930519-0.46410369873j), + (0.913058102131-0.407829582691j), + (0.936754107475-0.349988251925j), + (0.956783294678-0.290801793337j), + (0.973072886467-0.230497643352j), + (0.985563337803-0.169307261705j), + (0.9942086339-0.1074674353j), + (0.9989772439-0.0452152714133j)) + + sampling_freq = 10e3 + freq = sampling_freq / 100 + + loop_bw = math.pi/100.0 + maxf = 1 + minf = -1 + + src = gr.sig_source_c (sampling_freq, gr.GR_COS_WAVE, freq, 1.0) + pll = gr.pll_refout_cc(loop_bw, maxf, minf) + head = gr.head (gr.sizeof_gr_complex, int (freq)) + dst = gr.vector_sink_c () + + self.tb.connect (src, pll, head) + self.tb.connect (head, dst) + + self.tb.run () + dst_data = dst.data () + self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 4) + +if __name__ == '__main__': + gr_unittest.run(test_pll_refout, "test_pll_refout.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 new file mode 100755 index 000000000..6a62a6997 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_pn_correlator_cc.py @@ -0,0 +1,50 @@ +#!/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_probe_signal.py b/gnuradio-core/src/python/gnuradio/gr/qa_probe_signal.py new file mode 100644 index 000000000..4e10afdb6 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_probe_signal.py @@ -0,0 +1,67 @@ +#!/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. +# + +import time + +from gnuradio import gr, gr_unittest + +class test_probe_signal (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block() + + def tearDown (self): + self.tb = None + + def test_001(self): + + value = 12.3 + repeats = 100 + src_data = [value] * repeats + + src = gr.vector_source_f(src_data) + dst = gr.probe_signal_f() + + self.tb.connect(src, dst) + self.tb.run() + output = dst.level() + self.assertAlmostEqual(value, output, places=6) + + def test_002(self): + + vector_length = 10 + repeats = 10 + value = [0.5+i for i in range(0, vector_length)] + src_data = value * repeats + + src = gr.vector_source_f(src_data) + s2v = gr.stream_to_vector(gr.sizeof_float, vector_length) + dst = gr.probe_signal_vf(vector_length) + + self.tb.connect(src, s2v, dst) + self.tb.run() + output = dst.level() + self.assertEqual(len(output), vector_length) + self.assertAlmostEqual(value[3], output[3], places=6) + +if __name__ == '__main__': + gr_unittest.run(test_probe_signal, "test_probe_signal.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_python_message_passing.py b/gnuradio-core/src/python/gnuradio/gr/qa_python_message_passing.py new file mode 100644 index 000000000..06bb96947 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_python_message_passing.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python +# +# Copyright 2013 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 +try: import pmt +except: from gruel import pmt +import numpy +import time + +# Simple block to generate messages +class message_generator(gr.sync_block): + def __init__(self, msg_list, msg_interval): + gr.sync_block.__init__( + self, + name = "message generator", + in_sig = [numpy.float32], + out_sig = None + ) + self.msg_list = msg_list + self.msg_interval = msg_interval + self.msg_ctr = 0 + self.message_port_register_out(pmt.pmt_intern('out_port')) + + + def work(self, input_items, output_items): + inLen = len(input_items[0]) + while self.msg_ctr < len(self.msg_list) and \ + (self.msg_ctr * self.msg_interval) < \ + (self.nitems_read(0) + inLen): + self.message_port_pub(pmt.pmt_intern('out_port'), + self.msg_list[self.msg_ctr]) + self.msg_ctr += 1 + return inLen + +# Simple block to consume messages +class message_consumer(gr.sync_block): + def __init__(self): + gr.sync_block.__init__( + self, + name = "message consumer", + in_sig = None, + out_sig = None + ) + self.msg_list = [] + self.message_port_register_in(pmt.pmt_intern('in_port')) + self.set_msg_handler(pmt.pmt_intern('in_port'), + self.handle_msg) + + def handle_msg(self, msg): + # Create a new PMT from long value and put in list + self.msg_list.append(pmt.pmt_from_long(pmt.pmt_to_long(msg))) + +class test_python_message_passing(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_000(self): + num_msgs = 10 + msg_interval = 1000 + msg_list = [] + for i in range(num_msgs): + msg_list.append(pmt.pmt_from_long(i)) + + # Create vector source with dummy data to trigger messages + src_data = [] + for i in range(num_msgs*msg_interval): + src_data.append(float(i)) + src = gr.vector_source_f(src_data, False) + msg_gen = message_generator(msg_list, msg_interval) + msg_cons = message_consumer() + + # Connect vector source to message gen + self.tb.connect(src, msg_gen) + + # Connect message generator to message consumer + self.tb.msg_connect(msg_gen, 'out_port', msg_cons, 'in_port') + + # Verify that the messgae port query functions work + self.assertEqual(pmt.pmt_symbol_to_string(pmt.pmt_vector_ref( + msg_gen.message_ports_out(), 0)), 'out_port') + self.assertEqual(pmt.pmt_symbol_to_string(pmt.pmt_vector_ref( + msg_cons.message_ports_in(), 0)), 'in_port') + + # Run to verify message passing + self.tb.start() + + # Wait for all messages to be sent + while msg_gen.msg_ctr < num_msgs: + time.sleep(0.5) + self.tb.stop() + self.tb.wait() + + # Verify that the message consumer got all the messages + self.assertEqual(num_msgs, len(msg_cons.msg_list)) + for i in range(num_msgs): + self.assertTrue(pmt.pmt_equal(msg_list[i], msg_cons.msg_list[i])) + +if __name__ == '__main__': + gr_unittest.run(test_python_message_passing, + 'test_python_message_passing.xml') diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_rational_resampler.py b/gnuradio-core/src/python/gnuradio/gr/qa_rational_resampler.py new file mode 100755 index 000000000..cc963d757 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_rational_resampler.py @@ -0,0 +1,298 @@ +#!/usr/bin/env python +# +# Copyright 2005,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 +from gnuradio import blks2 +import math +import random +import sys + +#import os +#print os.getpid() +#raw_input('Attach with gdb, then press Enter: ') + + +def random_floats(n): + r = [] + for x in xrange(n): + r.append(float(random.randint(-32768, 32768))) + return tuple(r) + + +def reference_dec_filter(src_data, decim, taps): + tb = gr.top_block() + src = gr.vector_source_f(src_data) + op = gr.fir_filter_fff(decim, taps) + dst = gr.vector_sink_f() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + tb = None + return result_data + +def reference_interp_filter(src_data, interp, taps): + tb = gr.top_block() + src = gr.vector_source_f(src_data) + op = gr.interp_fir_filter_fff(interp, taps) + dst = gr.vector_sink_f() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + tb = None + return result_data + +def reference_interp_dec_filter(src_data, interp, decim, taps): + tb = gr.top_block() + src = gr.vector_source_f(src_data) + up = gr.interp_fir_filter_fff(interp, (1,)) + dn = gr.fir_filter_fff(decim, taps) + dst = gr.vector_sink_f() + tb.connect(src, up, dn, dst) + tb.run() + result_data = dst.data() + tb = None + return result_data + + +class test_rational_resampler (gr_unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + # + # test the gr.rational_resampler_base primitives... + # + + def test_000_1_to_1(self): + taps = (-4, 5) + src_data = (234, -4, 23, -56, 45, 98, -23, -7) + xr = (-936, 1186, -112, 339, -460, -167, 582) + expected_result = tuple([float(x) for x in xr]) + + tb = gr.top_block() + src = gr.vector_source_f(src_data) + op = gr.rational_resampler_base_fff(1, 1, taps) + dst = gr.vector_sink_f() + tb.connect(src, op) + tb.connect(op, dst) + tb.run() + result_data = dst.data() + self.assertEqual(expected_result, result_data) + + def test_001_interp(self): + taps = [1, 10, 100, 1000, 10000] + src_data = (0, 2, 3, 5, 7, 11, 13, 17) + interpolation = 3 + xr = (0,0,0,0,2,20,200,2003,20030,300,3005,30050,500,5007,50070,700,7011,70110,1100,11013,110130,1300,13017,130170,1700.0,17000.0,170000.0) + expected_result = tuple([float(x) for x in xr]) + + tb = gr.top_block() + src = gr.vector_source_f(src_data) + op = gr.rational_resampler_base_fff(interpolation, 1, taps) + dst = gr.vector_sink_f() + tb.connect(src, op) + tb.connect(op, dst) + tb.run() + result_data = dst.data() + self.assertEqual(expected_result, result_data) + + def test_002_interp(self): + taps = random_floats(31) + #src_data = random_floats(10000) # FIXME the 10k case fails! + src_data = random_floats(1000) + interpolation = 3 + + expected_result = reference_interp_filter(src_data, interpolation, taps) + + tb = gr.top_block() + src = gr.vector_source_f(src_data) + op = gr.rational_resampler_base_fff(interpolation, 1, taps) + dst = gr.vector_sink_f() + tb.connect(src, op) + tb.connect(op, dst) + tb.run() + result_data = dst.data() + + L1 = len(result_data) + L2 = len(expected_result) + L = min(L1, L2) + if False: + sys.stderr.write('delta = %2d: ntaps = %d interp = %d ilen = %d\n' % + (L2 - L1, len(taps), interpolation, len(src_data))) + sys.stderr.write(' len(result_data) = %d len(expected_result) = %d\n' % + (len(result_data), len(expected_result))) + #self.assertEqual(expected_result[0:L], result_data[0:L]) + # FIXME check first 3 answers + self.assertEqual(expected_result[3:L], result_data[3:L]) + + def test_003_interp(self): + taps = random_floats(31) + src_data = random_floats(10000) + decimation = 3 + + expected_result = reference_dec_filter(src_data, decimation, taps) + + tb = gr.top_block() + src = gr.vector_source_f(src_data) + op = gr.rational_resampler_base_fff(1, decimation, taps) + dst = gr.vector_sink_f() + tb.connect(src, op) + tb.connect(op, dst) + tb.run() + result_data = dst.data() + + L1 = len(result_data) + L2 = len(expected_result) + L = min(L1, L2) + if False: + sys.stderr.write('delta = %2d: ntaps = %d decim = %d ilen = %d\n' % + (L2 - L1, len(taps), decimation, len(src_data))) + sys.stderr.write(' len(result_data) = %d len(expected_result) = %d\n' % + (len(result_data), len(expected_result))) + self.assertEqual(expected_result[0:L], result_data[0:L]) + + # FIXME disabled. Triggers hang on SuSE 10.0 + def xtest_004_decim_random_vals(self): + MAX_TAPS = 9 + MAX_DECIM = 7 + OUTPUT_LEN = 9 + + random.seed(0) # we want reproducibility + + for ntaps in xrange(1, MAX_TAPS + 1): + for decim in xrange(1, MAX_DECIM+1): + for ilen in xrange(ntaps + decim, ntaps + OUTPUT_LEN*decim): + src_data = random_floats(ilen) + taps = random_floats(ntaps) + expected_result = reference_dec_filter(src_data, decim, taps) + + tb = gr.top_block() + src = gr.vector_source_f(src_data) + op = gr.rational_resampler_base_fff(1, decim, taps) + dst = gr.vector_sink_f() + tb.connect(src, op, dst) + tb.run() + tb = None + result_data = dst.data() + L1 = len(result_data) + L2 = len(expected_result) + L = min(L1, L2) + if False: + sys.stderr.write('delta = %2d: ntaps = %d decim = %d ilen = %d\n' % (L2 - L1, ntaps, decim, ilen)) + sys.stderr.write(' len(result_data) = %d len(expected_result) = %d\n' % + (len(result_data), len(expected_result))) + self.assertEqual(expected_result[0:L], result_data[0:L]) + + + # FIXME disabled. Triggers hang on SuSE 10.0 + def xtest_005_interp_random_vals(self): + MAX_TAPS = 9 + MAX_INTERP = 7 + INPUT_LEN = 9 + + random.seed(0) # we want reproducibility + + for ntaps in xrange(1, MAX_TAPS + 1): + for interp in xrange(1, MAX_INTERP+1): + for ilen in xrange(ntaps, ntaps + INPUT_LEN): + src_data = random_floats(ilen) + taps = random_floats(ntaps) + expected_result = reference_interp_filter(src_data, interp, taps) + + tb = gr.top_block() + src = gr.vector_source_f(src_data) + op = gr.rational_resampler_base_fff(interp, 1, taps) + dst = gr.vector_sink_f() + tb.connect(src, op, dst) + tb.run() + tb = None + result_data = dst.data() + L1 = len(result_data) + L2 = len(expected_result) + L = min(L1, L2) + #if True or abs(L1-L2) > 1: + if False: + sys.stderr.write('delta = %2d: ntaps = %d interp = %d ilen = %d\n' % (L2 - L1, ntaps, interp, ilen)) + #sys.stderr.write(' len(result_data) = %d len(expected_result) = %d\n' % + # (len(result_data), len(expected_result))) + #self.assertEqual(expected_result[0:L], result_data[0:L]) + # FIXME check first ntaps+1 answers + self.assertEqual(expected_result[ntaps+1:L], result_data[ntaps+1:L]) + + + def test_006_interp_decim(self): + taps = (0,1,0,0) + src_data = range(10000) + interp = 3 + decimation = 2 + + expected_result = reference_interp_dec_filter(src_data, interp, decimation, taps) + + tb = gr.top_block() + src = gr.vector_source_f(src_data) + op = gr.rational_resampler_base_fff(interp, decimation, taps) + dst = gr.vector_sink_f() + tb.connect(src, op) + tb.connect(op, dst) + tb.run() + result_data = dst.data() + + L1 = len(result_data) + L2 = len(expected_result) + L = min(L1, L2) + if False: + sys.stderr.write('delta = %2d: ntaps = %d decim = %d ilen = %d\n' % + (L2 - L1, len(taps), decimation, len(src_data))) + sys.stderr.write(' len(result_data) = %d len(expected_result) = %d\n' % + (len(result_data), len(expected_result))) + self.assertEqual(expected_result[1:L], result_data[1:L]) + + # + # test the blks2.rational_resampler_??? primitives... + # + + def test_101_interp(self): + taps = [1, 10, 100, 1000, 10000] + src_data = (0, 2, 3, 5, 7, 11, 13, 17) + interpolation = 3 + xr = (0,0,0,0,2,20,200,2003,20030,300,3005,30050,500,5007,50070,700,7011,70110,1100,11013,110130,1300,13017,130170,1700.0,17000.0,170000.0) + expected_result = tuple([float(x) for x in xr]) + + tb = gr.top_block() + src = gr.vector_source_f(src_data) + op = blks2.rational_resampler_fff(interpolation, 1, taps=taps) + dst = gr.vector_sink_f() + tb.connect(src, op) + tb.connect(op, dst) + tb.run() + result_data = dst.data() + self.assertEqual(expected_result, result_data) + + +if __name__ == '__main__': + pass + # FIXME: Disabled, see ticket:210 + # gr_unittest.run(test_rational_resampler, "test_rational_resampler.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_regenerate.py b/gnuradio-core/src/python/gnuradio/gr/qa_regenerate.py new file mode 100755 index 000000000..5aca03b77 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_regenerate.py @@ -0,0 +1,90 @@ +#!/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 +import math + +class test_regenerate (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_regen1 (self): + tb = self.tb + + data = [0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] + + expected_result = (0, 0, 0, + 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) + + + src = gr.vector_source_b(data, False) + regen = gr.regenerate_bb(5, 2) + dst = gr.vector_sink_b() + + tb.connect (src, regen) + tb.connect (regen, dst) + tb.run () + + dst_data = dst.data () + + self.assertEqual (expected_result, dst_data) + + def test_regen2 (self): + tb = self.tb + + data = 200*[0,] + data[9] = 1 + data[99] = 1 + + expected_result = 200*[0,] + expected_result[9] = 1 + expected_result[19] = 1 + expected_result[29] = 1 + expected_result[39] = 1 + + expected_result[99] = 1 + expected_result[109] = 1 + expected_result[119] = 1 + expected_result[129] = 1 + + src = gr.vector_source_b(data, False) + regen = gr.regenerate_bb(10, 3) + dst = gr.vector_sink_b() + + tb.connect (src, regen) + tb.connect (regen, dst) + tb.run () + + dst_data = dst.data () + + self.assertEqual (tuple(expected_result), dst_data) + + +if __name__ == '__main__': + gr_unittest.run(test_regenerate, "test_regenerate.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_repeat.py b/gnuradio-core/src/python/gnuradio/gr/qa_repeat.py new file mode 100755 index 000000000..116f37115 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_repeat.py @@ -0,0 +1,48 @@ +#!/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 +import math + +class test_repeat (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001_float(self): + src_data = [n*1.0 for n in range(100)]; + dst_data = [] + for n in range(100): + dst_data += [1.0*n, 1.0*n, 1.0*n] + + src = gr.vector_source_f(src_data) + rpt = gr.repeat(gr.sizeof_float, 3) + dst = gr.vector_sink_f() + self.tb.connect(src, rpt, dst) + self.tb.run() + self.assertFloatTuplesAlmostEqual(dst_data, dst.data(), 6) + +if __name__ == '__main__': + gr_unittest.run(test_repeat, "test_repeat.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_scrambler.py b/gnuradio-core/src/python/gnuradio/gr/qa_scrambler.py new file mode 100755 index 000000000..5fe89bdc7 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_scrambler.py @@ -0,0 +1,64 @@ +#!/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/gnuradio-core/src/python/gnuradio/gr/qa_short_to_char.py b/gnuradio-core/src/python/gnuradio/gr/qa_short_to_char.py new file mode 100755 index 000000000..490b149c7 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_short_to_char.py @@ -0,0 +1,69 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr, gr_unittest +import ctypes + +class test_short_to_char (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001(self): + + src_data = range(0, 32767, 32767/127) + src_data = [int(s) for s in src_data] + expected_result = range(0, 128) + src = gr.vector_source_s(src_data) + op = gr.short_to_char() + dst = gr.vector_sink_b() + + self.tb.connect(src, op, dst) + self.tb.run() + result_data = list(dst.data()) + + self.assertEqual(expected_result, result_data) + + def test_002(self): + + vlen = 3 + src_data = range(0, 32400, 32767/127) + src_data = [int(s) for s in src_data] + expected_result = range(0, 126) + src = gr.vector_source_s(src_data) + s2v = gr.stream_to_vector(gr.sizeof_short, vlen) + op = gr.short_to_char(vlen) + v2s = gr.vector_to_stream(gr.sizeof_char, vlen) + dst = gr.vector_sink_b() + + self.tb.connect(src, s2v, op, v2s, dst) + self.tb.run() + result_data = list(dst.data()) + + self.assertEqual(expected_result, result_data) + +if __name__ == '__main__': + gr_unittest.run(test_short_to_char, "test_short_to_char.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_short_to_float.py b/gnuradio-core/src/python/gnuradio/gr/qa_short_to_float.py new file mode 100755 index 000000000..130f034ec --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_short_to_float.py @@ -0,0 +1,70 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr, gr_unittest +import ctypes + +class test_short_to_float (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001(self): + + src_data = (0, 1, 2, 3, 4, 5, -1, -2, -3, -4, -5) + expected_result = [ 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, + -1.0, -2.0, -3.0, -4.0, -5.0] + + src = gr.vector_source_s(src_data) + op = gr.short_to_float() + dst = gr.vector_sink_f() + + self.tb.connect(src, op, dst) + self.tb.run() + result_data = list(dst.data()) + + self.assertEqual(expected_result, result_data) + + def test_002(self): + + vlen = 3 + src_data = (0, 1, 2, 3, 4, 5, -1, -2, -3) + expected_result = [0.0, 1.0, 2.0, 3.0, 4.0, + 5.0, -1.0, -2.0, -3.0] + src = gr.vector_source_s(src_data) + s2v = gr.stream_to_vector(gr.sizeof_short, vlen) + op = gr.short_to_float(vlen) + v2s = gr.vector_to_stream(gr.sizeof_float, vlen) + dst = gr.vector_sink_f() + + self.tb.connect(src, s2v, op, v2s, dst) + self.tb.run() + result_data = list(dst.data()) + + self.assertEqual(expected_result, result_data) + +if __name__ == '__main__': + gr_unittest.run(test_short_to_float, "test_short_to_float.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_sig_source.py b/gnuradio-core/src/python/gnuradio/gr/qa_sig_source.py new file mode 100755 index 000000000..122b169b7 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_sig_source.py @@ -0,0 +1,157 @@ +#!/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_sig_source (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_const_f (self): + tb = self.tb + expected_result = (1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5) + src1 = gr.sig_source_f (1e6, gr.GR_CONST_WAVE, 0, 1.5) + op = gr.head (gr.sizeof_float, 10) + dst1 = gr.vector_sink_f () + tb.connect (src1, op) + tb.connect (op, dst1) + tb.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_const_i (self): + tb = self.tb + expected_result = (1, 1, 1, 1) + src1 = gr.sig_source_i (1e6, gr.GR_CONST_WAVE, 0, 1) + op = gr.head (gr.sizeof_int, 4) + dst1 = gr.vector_sink_i () + tb.connect (src1, op) + tb.connect (op, dst1) + tb.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_sine_f (self): + tb = self.tb + sqrt2 = math.sqrt(2) / 2 + expected_result = (0, sqrt2, 1, sqrt2, 0, -sqrt2, -1, -sqrt2, 0) + src1 = gr.sig_source_f (8, gr.GR_SIN_WAVE, 1.0, 1.0) + op = gr.head (gr.sizeof_float, 9) + dst1 = gr.vector_sink_f () + tb.connect (src1, op) + tb.connect (op, dst1) + tb.run () + dst_data = dst1.data () + self.assertFloatTuplesAlmostEqual (expected_result, dst_data, 5) + + def test_cosine_f (self): + tb = self.tb + sqrt2 = math.sqrt(2) / 2 + expected_result = (1, sqrt2, 0, -sqrt2, -1, -sqrt2, 0, sqrt2, 1) + src1 = gr.sig_source_f (8, gr.GR_COS_WAVE, 1.0, 1.0) + op = gr.head (gr.sizeof_float, 9) + dst1 = gr.vector_sink_f () + tb.connect (src1, op) + tb.connect (op, dst1) + tb.run () + dst_data = dst1.data () + self.assertFloatTuplesAlmostEqual (expected_result, dst_data, 5) + + def test_sqr_c (self): + tb = self.tb #arg6 is a bit before -PI/2 + expected_result = (1j, 1j, 0, 0, 1, 1, 1+0j, 1+1j, 1j) + src1 = gr.sig_source_c (8, gr.GR_SQR_WAVE, 1.0, 1.0) + op = gr.head (gr.sizeof_gr_complex, 9) + dst1 = gr.vector_sink_c () + tb.connect (src1, op) + tb.connect (op, dst1) + tb.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_tri_c (self): + tb = self.tb + expected_result = (1+.5j, .75+.75j, .5+1j, .25+.75j, 0+.5j, .25+.25j, .5+0j, .75+.25j, 1+.5j) + src1 = gr.sig_source_c (8, gr.GR_TRI_WAVE, 1.0, 1.0) + op = gr.head (gr.sizeof_gr_complex, 9) + dst1 = gr.vector_sink_c () + tb.connect (src1, op) + tb.connect (op, dst1) + tb.run () + dst_data = dst1.data () + self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 5) + + def test_saw_c (self): + tb = self.tb + expected_result = (.5+.25j, .625+.375j, .75+.5j, .875+.625j, 0+.75j, .125+.875j, .25+1j, .375+.125j, .5+.25j) + src1 = gr.sig_source_c (8, gr.GR_SAW_WAVE, 1.0, 1.0) + op = gr.head (gr.sizeof_gr_complex, 9) + dst1 = gr.vector_sink_c () + tb.connect (src1, op) + tb.connect (op, dst1) + tb.run () + dst_data = dst1.data () + self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 5) + + def test_sqr_f (self): + tb = self.tb + expected_result = (0, 0, 0, 0, 1, 1, 1, 1, 0) + src1 = gr.sig_source_f (8, gr.GR_SQR_WAVE, 1.0, 1.0) + op = gr.head (gr.sizeof_float, 9) + dst1 = gr.vector_sink_f () + tb.connect (src1, op) + tb.connect (op, dst1) + tb.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_tri_f (self): + tb = self.tb + expected_result = (1, .75, .5, .25, 0, .25, .5, .75, 1) + src1 = gr.sig_source_f (8, gr.GR_TRI_WAVE, 1.0, 1.0) + op = gr.head (gr.sizeof_float, 9) + dst1 = gr.vector_sink_f () + tb.connect (src1, op) + tb.connect (op, dst1) + tb.run () + dst_data = dst1.data () + self.assertFloatTuplesAlmostEqual (expected_result, dst_data, 5) + + def test_saw_f (self): + tb = self.tb + expected_result = (.5, .625, .75, .875, 0, .125, .25, .375, .5) + src1 = gr.sig_source_f (8, gr.GR_SAW_WAVE, 1.0, 1.0) + op = gr.head (gr.sizeof_float, 9) + dst1 = gr.vector_sink_f () + tb.connect (src1, op) + tb.connect (op, dst1) + tb.run () + dst_data = dst1.data () + self.assertFloatTuplesAlmostEqual (expected_result, dst_data, 5) + +if __name__ == '__main__': + gr_unittest.run(test_sig_source, "test_sig_source.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_single_pole_iir.py b/gnuradio-core/src/python/gnuradio/gr/qa_single_pole_iir.py new file mode 100755 index 000000000..bfe2d8fc8 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_single_pole_iir.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +# +# Copyright 2005,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_single_pole_iir(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001(self): + src_data = (0, 1000, 2000, 3000, 4000, 5000) + expected_result = src_data + src = gr.vector_source_f(src_data) + op = gr.single_pole_iir_filter_ff (1.0) + dst = gr.vector_sink_f() + self.tb.connect (src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_002(self): + src_data = (0, 1000, 2000, 3000, 4000, 5000) + expected_result = (0, 125, 359.375, 689.453125, 1103.271484, 1590.36255) + src = gr.vector_source_f(src_data) + op = gr.single_pole_iir_filter_ff (0.125) + dst = gr.vector_sink_f() + self.tb.connect (src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual (expected_result, result_data, 3) + + def test_003(self): + block_size = 2 + src_data = (0, 1000, 2000, 3000, 4000, 5000) + expected_result = (0, 125, 250, 484.375, 718.75, 1048.828125) + src = gr.vector_source_f(src_data) + s2p = gr.serial_to_parallel(gr.sizeof_float, block_size) + op = gr.single_pole_iir_filter_ff (0.125, block_size) + p2s = gr.parallel_to_serial(gr.sizeof_float, block_size) + dst = gr.vector_sink_f() + self.tb.connect (src, s2p, op, p2s, dst) + self.tb.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual (expected_result, result_data, 3) + + +if __name__ == '__main__': + gr_unittest.run(test_single_pole_iir, "test_single_pole_iir.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_single_pole_iir_cc.py b/gnuradio-core/src/python/gnuradio/gr/qa_single_pole_iir_cc.py new file mode 100755 index 000000000..353df1bc0 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_single_pole_iir_cc.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +# +# Copyright 2005,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 + +class test_single_pole_iir_cc(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001(self): + src_data = (0+0j, 1000+1000j, 2000+2000j, 3000+3000j, 4000+4000j, 5000+5000j) + expected_result = src_data + src = gr.vector_source_c(src_data) + op = gr.single_pole_iir_filter_cc (1.0) + dst = gr.vector_sink_c() + self.tb.connect (src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual (expected_result, result_data) + + def test_002(self): + src_data = (complex(0,0), complex(1000,-1000), complex(2000,-2000), complex(3000,-3000), complex(4000,-4000), complex(5000,-5000)) + expected_result = (complex(0,0), complex(125,-125), complex(359.375,-359.375), complex(689.453125,-689.453125), complex(1103.271484,-1103.271484), complex(1590.36255,-1590.36255)) + src = gr.vector_source_c(src_data) + op = gr.single_pole_iir_filter_cc (0.125) + dst = gr.vector_sink_c() + self.tb.connect (src, op, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 3) + + def test_003(self): + block_size = 2 + src_data = (complex(0,0), complex(1000,-1000), complex(2000,-2000), complex(3000,-3000), complex(4000,-4000), complex(5000,-5000)) + expected_result = (complex(0,0), complex(125,-125), complex(250,-250), complex(484.375,-484.375), complex(718.75,-718.75), complex(1048.828125,-1048.828125)) + src = gr.vector_source_c(src_data) + s2p = gr.serial_to_parallel(gr.sizeof_gr_complex, block_size) + op = gr.single_pole_iir_filter_cc (0.125, block_size) + p2s = gr.parallel_to_serial(gr.sizeof_gr_complex, block_size) + dst = gr.vector_sink_c() + self.tb.connect (src, s2p, op, p2s, dst) + self.tb.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 3) + + +if __name__ == '__main__': + gr_unittest.run(test_single_pole_iir_cc, "test_single_pole_iir_cc.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_skiphead.py b/gnuradio-core/src/python/gnuradio/gr/qa_skiphead.py new file mode 100755 index 000000000..1e730398c --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_skiphead.py @@ -0,0 +1,102 @@ +#!/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_skiphead (gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block () + self.src_data = [int(x) for x in range(65536)] + + def tearDown(self): + self.tb = None + + def test_skip_0(self): + skip_cnt = 0 + expected_result = tuple(self.src_data[skip_cnt:]) + src1 = gr.vector_source_i (self.src_data) + op = gr.skiphead (gr.sizeof_int, skip_cnt) + dst1 = gr.vector_sink_i () + self.tb.connect (src1, op, dst1) + self.tb.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_skip_1(self): + skip_cnt = 1 + expected_result = tuple(self.src_data[skip_cnt:]) + src1 = gr.vector_source_i (self.src_data) + op = gr.skiphead (gr.sizeof_int, skip_cnt) + dst1 = gr.vector_sink_i () + self.tb.connect (src1, op, dst1) + self.tb.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_skip_1023(self): + skip_cnt = 1023 + expected_result = tuple(self.src_data[skip_cnt:]) + src1 = gr.vector_source_i (self.src_data) + op = gr.skiphead (gr.sizeof_int, skip_cnt) + dst1 = gr.vector_sink_i () + self.tb.connect (src1, op, dst1) + self.tb.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_skip_6339(self): + skip_cnt = 6339 + expected_result = tuple(self.src_data[skip_cnt:]) + src1 = gr.vector_source_i (self.src_data) + op = gr.skiphead (gr.sizeof_int, skip_cnt) + dst1 = gr.vector_sink_i () + self.tb.connect (src1, op, dst1) + self.tb.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_skip_12678(self): + skip_cnt = 12678 + expected_result = tuple(self.src_data[skip_cnt:]) + src1 = gr.vector_source_i (self.src_data) + op = gr.skiphead (gr.sizeof_int, skip_cnt) + dst1 = gr.vector_sink_i () + self.tb.connect (src1, op, dst1) + self.tb.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_skip_all(self): + skip_cnt = len(self.src_data) + expected_result = tuple(self.src_data[skip_cnt:]) + src1 = gr.vector_source_i (self.src_data) + op = gr.skiphead (gr.sizeof_int, skip_cnt) + dst1 = gr.vector_sink_i () + self.tb.connect (src1, op, dst1) + self.tb.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + +if __name__ == '__main__': + gr_unittest.run(test_skiphead, "test_skiphead.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_stream_mux.py b/gnuradio-core/src/python/gnuradio/gr/qa_stream_mux.py new file mode 100755 index 000000000..779d0b25e --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_stream_mux.py @@ -0,0 +1,168 @@ +#!/usr/bin/env python +# +# Copyright 2004,2005,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_stream_mux (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def help_stream_2ff(self, N, stream_sizes): + v0 = gr.vector_source_f(N*[1,], False) + v1 = gr.vector_source_f(N*[2,], False) + + mux = gr.stream_mux(gr.sizeof_float, stream_sizes) + + dst = gr.vector_sink_f () + + self.tb.connect (v0, (mux,0)) + self.tb.connect (v1, (mux,1)) + self.tb.connect (mux, dst) + self.tb.run () + + return dst.data () + + def help_stream_ramp_2ff(self, N, stream_sizes): + r1 = range(N) + r2 = range(N) + r2.reverse() + + v0 = gr.vector_source_f(r1, False) + v1 = gr.vector_source_f(r2, False) + + mux = gr.stream_mux(gr.sizeof_float, stream_sizes) + + dst = gr.vector_sink_f () + + self.tb.connect (v0, (mux,0)) + self.tb.connect (v1, (mux,1)) + self.tb.connect (mux, dst) + self.tb.run () + + return dst.data () + + def test_stream_2NN_ff(self): + N = 40 + stream_sizes = [10, 10] + result_data = self.help_stream_2ff(N, stream_sizes) + + exp_data = (1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0) + self.assertEqual (exp_data, result_data) + + def test_stream_ramp_2NN_ff(self): + N = 40 + stream_sizes = [10, 10] + result_data = self.help_stream_ramp_2ff(N, stream_sizes) + + exp_data = ( 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, + 39.0, 38.0, 37.0, 36.0, 35.0, 34.0, 33.0, 32.0, 31.0, 30.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0, 19.0, + 29.0, 28.0, 27.0, 26.0, 25.0, 24.0, 23.0, 22.0, 21.0, 20.0, + 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, + 19.0, 18.0, 17.0, 16.0, 15.0, 14.0, 13.0, 12.0, 11.0, 10.0, + 30.0, 31.0, 32.0, 33.0, 34.0, 35.0, 36.0, 37.0, 38.0, 39.0, + 9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0, 0.0) + self.assertEqual (exp_data, result_data) + + def test_stream_2NM_ff(self): + N = 40 + stream_sizes = [7, 9] + self.help_stream_2ff(N, stream_sizes) + + result_data = self.help_stream_2ff(N, stream_sizes) + + exp_data = (1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0) + + self.assertEqual (exp_data, result_data) + + + def test_stream_2MN_ff(self): + N = 37 + stream_sizes = [7, 9] + self.help_stream_2ff(N, stream_sizes) + + result_data = self.help_stream_2ff(N, stream_sizes) + + exp_data = (1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 2.0) + + self.assertEqual (exp_data, result_data) + + def test_stream_2N0_ff(self): + N = 30 + stream_sizes = [7, 0] + self.help_stream_2ff(N, stream_sizes) + + result_data = self.help_stream_2ff(N, stream_sizes) + + exp_data = (1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, + 1.0, 1.0) + + self.assertEqual (exp_data, result_data) + + def test_stream_20N_ff(self): + N = 30 + stream_sizes = [0, 9] + self.help_stream_2ff(N, stream_sizes) + + result_data = self.help_stream_2ff(N, stream_sizes) + + exp_data = (2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, + 2.0, 2.0, 2.0) + + self.assertEqual (exp_data, result_data) + +if __name__ == '__main__': + gr_unittest.run(test_stream_mux, "test_stream_mux.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_tag_debug.py b/gnuradio-core/src/python/gnuradio/gr/qa_tag_debug.py new file mode 100755 index 000000000..81babca04 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_tag_debug.py @@ -0,0 +1,43 @@ +#!/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, gr_unittest + +class test_tag_debug(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_001(self): + # Just run some data through and make sure it doesn't puke. + src_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + src = gr.vector_source_i(src_data) + op = gr.tag_debug(gr.sizeof_int, "tag QA") + self.tb.connect(src, op) + self.tb.run() + x = op.current_tags() + +if __name__ == '__main__': + gr_unittest.run(test_tag_debug, "test_tag_debug.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_tag_utils.py b/gnuradio-core/src/python/gnuradio/gr/qa_tag_utils.py new file mode 100755 index 000000000..ca1184979 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_tag_utils.py @@ -0,0 +1,55 @@ +#!/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 +import tag_utils + +try: + import pmt_swig as pmt +except ImportError: + import pmt + +class test_tag_utils (gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + + def tearDown (self): + self.tb = None + + def test_001(self): + t = gr.gr_tag_t() + t.offset = 10 + t.key = pmt.pmt_string_to_symbol('key') + t.value = pmt.pmt_from_long(23) + t.srcid = pmt.pmt_from_bool(False) + pt = tag_utils.tag_to_python(t) + self.assertEqual(pt.key, 'key') + self.assertEqual(pt.value, 23) + self.assertEqual(pt.offset, 10) + + +if __name__ == '__main__': + print 'hi' + gr_unittest.run(test_tag_utils, "test_tag_utils.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_udp_sink_source.py b/gnuradio-core/src/python/gnuradio/gr/qa_udp_sink_source.py new file mode 100755 index 000000000..0a719990e --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_udp_sink_source.py @@ -0,0 +1,99 @@ +#!/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 +from threading import Timer + +class test_udp_sink_source(gr_unittest.TestCase): + + def setUp(self): + self.tb_snd = gr.top_block() + self.tb_rcv = gr.top_block() + + def tearDown(self): + self.tb_rcv = None + self.tb_snd = None + + def test_001(self): + port = 65500 + + n_data = 16 + src_data = [float(x) for x in range(n_data)] + expected_result = tuple(src_data) + src = gr.vector_source_f(src_data) + udp_snd = gr.udp_sink( gr.sizeof_float, 'localhost', port ) + self.tb_snd.connect( src, udp_snd ) + + udp_rcv = gr.udp_source( gr.sizeof_float, 'localhost', port ) + dst = gr.vector_sink_f() + self.tb_rcv.connect( udp_rcv, dst ) + + self.tb_rcv.start() + self.tb_snd.run() + udp_snd.disconnect() + self.timeout = False + q = Timer(3.0,self.stop_rcv) + q.start() + self.tb_rcv.wait() + q.cancel() + + result_data = dst.data() + self.assertEqual(expected_result, result_data) + self.assert_(not self.timeout) + + def test_002(self): + udp_rcv = gr.udp_source( gr.sizeof_float, '0.0.0.0', 0, eof=False ) + rcv_port = udp_rcv.get_port() + + udp_snd = gr.udp_sink( gr.sizeof_float, '127.0.0.1', 65500 ) + udp_snd.connect( 'localhost', rcv_port ) + + n_data = 16 + src_data = [float(x) for x in range(n_data)] + expected_result = tuple(src_data) + src = gr.vector_source_f(src_data) + dst = gr.vector_sink_f() + + self.tb_snd.connect( src, udp_snd ) + self.tb_rcv.connect( udp_rcv, dst ) + + self.tb_rcv.start() + self.tb_snd.run() + udp_snd.disconnect() + self.timeout = False + q = Timer(3.0,self.stop_rcv) + q.start() + self.tb_rcv.wait() + q.cancel() + + result_data = dst.data() + self.assertEqual(expected_result, result_data) + self.assert_(self.timeout) # source ignores EOF? + + def stop_rcv(self): + self.timeout = True + self.tb_rcv.stop() + #print "tb_rcv stopped by Timer" + +if __name__ == '__main__': + gr_unittest.run(test_udp_sink_source, "test_udp_sink_source.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_unpack_k_bits.py b/gnuradio-core/src/python/gnuradio/gr/qa_unpack_k_bits.py new file mode 100755 index 000000000..bb4e7733d --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_unpack_k_bits.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr, gr_unittest +import random + +class test_unpack(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block () + + def tearDown(self): + self.tb = None + + def test_001(self): + src_data = (1,0,1,1,0,1,1,0) + expected_results = (1,0,1,1,0,1,1,0) + src = gr.vector_source_b(src_data,False) + op = gr.unpack_k_bits_bb(1) + dst = gr.vector_sink_b() + self.tb.connect(src, op, dst) + self.tb.run() + self.assertEqual(expected_results, dst.data()) + + def test_002(self): + src_data = ( 2, 3, 0, 1) + expected_results = (1,0,1,1,0,0,0,1) + src = gr.vector_source_b(src_data,False) + op = gr.unpack_k_bits_bb(2) + dst = gr.vector_sink_b() + self.tb.connect(src, op, dst) + self.tb.run() + self.assertEqual(expected_results, dst.data()) + + +if __name__ == '__main__': + gr_unittest.run(test_unpack, "test_unpack.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_vector_insert.py b/gnuradio-core/src/python/gnuradio/gr/qa_vector_insert.py new file mode 100755 index 000000000..acc06dfde --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_vector_insert.py @@ -0,0 +1,58 @@ +#!/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, gr_unittest +import math + +class test_vector_insert(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001(self): + src_data = [float(x) for x in range(16)] + expected_result = tuple(src_data) + + period = 9177; + offset = 0; + + src = gr.null_source(1) + head = gr.head(1, 10000000); + ins = gr.vector_insert_b([1], period, offset); + dst = gr.vector_sink_b() + + self.tb.connect(src, head, ins, dst) + self.tb.run() + result_data = dst.data() + + for i in range(10000): + if(i%period == offset): + self.assertEqual(1, result_data[i]) + else: + self.assertEqual(0, result_data[i]) + +if __name__ == '__main__': + gr_unittest.run(test_vector_insert, "test_vector_insert.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_vector_map.py b/gnuradio-core/src/python/gnuradio/gr/qa_vector_map.py new file mode 100644 index 000000000..12f4be589 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_vector_map.py @@ -0,0 +1,105 @@ +#!/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, gr_unittest +import math + +class test_vector_map(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block() + + def tearDown (self): + self.tb = None + + def test_reversing(self): + # Chunk data in blocks of N and reverse the block contents. + N = 5 + src_data = range(0, 20) + expected_result = [] + for i in range(N-1, len(src_data), N): + for j in range(0, N): + expected_result.append(1.0*(i-j)) + mapping = [list(reversed([(0, i) for i in range(0, N)]))] + src = gr.vector_source_f(src_data, False, N) + vmap = gr.vector_map(gr.sizeof_float, (N, ), mapping) + dst = gr.vector_sink_f(N) + self.tb.connect(src, vmap, dst) + self.tb.run() + result_data = list(dst.data()) + self.assertEqual(expected_result, result_data) + + def test_vector_to_streams(self): + # Split an input vector into N streams. + N = 5 + M = 20 + src_data = range(0, M) + expected_results = [] + for n in range(0, N): + expected_results.append(range(n, M, N)) + mapping = [[(0, n)] for n in range(0, N)] + src = gr.vector_source_f(src_data, False, N) + vmap = gr.vector_map(gr.sizeof_float, (N, ), mapping) + dsts = [gr.vector_sink_f(1) for n in range(0, N)] + self.tb.connect(src, vmap) + for n in range(0, N): + self.tb.connect((vmap, n), dsts[n]) + self.tb.run() + for n in range(0, N): + result_data = list(dsts[n].data()) + self.assertEqual(expected_results[n], result_data) + + def test_interleaving(self): + # Takes 3 streams (a, b and c) + # Outputs 2 streams. + # First (d) is interleaving of a and b. + # Second (e) is interleaving of a and b and c. c is taken in + # chunks of 2 which are reversed. + A = (1, 2, 3, 4, 5) + B = (11, 12, 13, 14, 15) + C = (99, 98, 97, 96, 95, 94, 93, 92, 91, 90) + expected_D = (1, 11, 2, 12, 3, 13, 4, 14, 5, 15) + expected_E = (1, 11, 98, 99, 2, 12, 96, 97, 3, 13, 94, 95, + 4, 14, 92, 93, 5, 15, 90, 91) + mapping = [[(0, 0), (1, 0)], # mapping to produce D + [(0, 0), (1, 0), (2, 1), (2, 0)], # mapping to produce E + ] + srcA = gr.vector_source_f(A, False, 1) + srcB = gr.vector_source_f(B, False, 1) + srcC = gr.vector_source_f(C, False, 2) + vmap = gr.vector_map(gr.sizeof_int, (1, 1, 2), mapping) + dstD = gr.vector_sink_f(2) + dstE = gr.vector_sink_f(4) + self.tb.connect(srcA, (vmap, 0)) + self.tb.connect(srcB, (vmap, 1)) + self.tb.connect(srcC, (vmap, 2)) + self.tb.connect((vmap, 0), dstD) + self.tb.connect((vmap, 1), dstE) + self.tb.run() + self.assertEqual(expected_D, dstD.data()) + self.assertEqual(expected_E, dstE.data()) + + + +if __name__ == '__main__': + gr_unittest.run(test_vector_map, "test_vector_map.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_vector_sink_source.py b/gnuradio-core/src/python/gnuradio/gr/qa_vector_sink_source.py new file mode 100755 index 000000000..64cbbe72a --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_vector_sink_source.py @@ -0,0 +1,65 @@ +#!/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 +import math + +class test_vector_sink_source(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001(self): + src_data = [float(x) for x in range(16)] + expected_result = tuple(src_data) + + src = gr.vector_source_f(src_data) + dst = gr.vector_sink_f() + + self.tb.connect(src, dst) + self.tb.run() + result_data = dst.data() + self.assertEqual(expected_result, result_data) + + def test_002(self): + src_data = [float(x) for x in range(16)] + expected_result = tuple(src_data) + + src = gr.vector_source_f(src_data, False, 2) + dst = gr.vector_sink_f(2) + + self.tb.connect(src, dst) + self.tb.run() + result_data = dst.data() + self.assertEqual(expected_result, result_data) + + def test_003(self): + src_data = [float(x) for x in range(16)] + expected_result = tuple(src_data) + self.assertRaises(ValueError, lambda : gr.vector_source_f(src_data, False, 3)) + +if __name__ == '__main__': + gr_unittest.run(test_vector_sink_source, "test_vector_sink_source.xml") + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_wavefile.py b/gnuradio-core/src/python/gnuradio/gr/qa_wavefile.py new file mode 100755 index 000000000..3b9a3eb20 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_wavefile.py @@ -0,0 +1,69 @@ +#!/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 + +import os +from os.path import getsize + +g_in_file = os.path.join (os.getenv ("srcdir"), "test_16bit_1chunk.wav") + +class test_wavefile(gr_unittest.TestCase): + + def setUp (self): + self.tb = gr.top_block () + + def tearDown (self): + self.tb = None + + def test_001_checkwavread (self): + wf = gr.wavfile_source(g_in_file) + self.assertEqual(wf.sample_rate(), 8000) + + def test_002_checkwavcopy (self): + infile = g_in_file + outfile = "test_out.wav" + + wf_in = gr.wavfile_source(infile) + wf_out = gr.wavfile_sink(outfile, + wf_in.channels(), + wf_in.sample_rate(), + wf_in.bits_per_sample()) + self.tb.connect(wf_in, wf_out) + self.tb.run() + wf_out.close() + + self.assertEqual(getsize(infile), getsize(outfile)) + + in_f = file(infile, 'rb') + out_f = file(outfile, 'rb') + + in_data = in_f.read() + out_data = out_f.read() + out_f.close() + os.remove(outfile) + + self.assertEqual(in_data, out_data) + + +if __name__ == '__main__': + gr_unittest.run(test_wavefile, "test_wavefile.xml") diff --git a/gnuradio-core/src/python/gnuradio/gr/tag_utils.py b/gnuradio-core/src/python/gnuradio/gr/tag_utils.py new file mode 100644 index 000000000..923718fc9 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/tag_utils.py @@ -0,0 +1,54 @@ +# +# Copyright 2003-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. +# +""" Conversion tools between stream tags and Python objects """ + +try: import pmt +except: from gruel import pmt + +from gnuradio_core import gr_tag_t + +class PythonTag(object): + " Python container for tags " + def __init__(self): + self.offset = None + self.key = None + self.value = None + self.srcid = None + +def tag_to_python(tag): + """ Convert a stream tag to a Python-readable object """ + newtag = PythonTag() + newtag.offset = tag.offset + newtag.key = pmt.to_python(tag.key) + newtag.value = pmt.to_python(tag.value) + newtag.srcid = pmt.to_python(tag.srcid) + return newtag + +def tag_to_pmt(tag): + """ Convert a Python-readable object to a stream tag """ + newtag = gr_tag_t() + newtag.offset = tag.offset + newtag.key = pmt.to_python(tag.key) + newtag.value = pmt.from_python(tag.value) + newtag.srcid = pmt.from_python(tag.srcid) + return newtag + + diff --git a/gnuradio-core/src/python/gnuradio/gr/test_16bit_1chunk.wav b/gnuradio-core/src/python/gnuradio/gr/test_16bit_1chunk.wav Binary files differnew file mode 100644 index 000000000..0fe12a7a1 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/test_16bit_1chunk.wav diff --git a/gnuradio-core/src/python/gnuradio/gr/top_block.py b/gnuradio-core/src/python/gnuradio/gr/top_block.py new file mode 100644 index 000000000..dc1f443aa --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/top_block.py @@ -0,0 +1,165 @@ +# +# 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. +# + +from gnuradio_core import top_block_swig, \ + top_block_wait_unlocked, top_block_run_unlocked + +#import gnuradio.gr.gr_threading as _threading +import gr_threading as _threading + + +# +# There is no problem that can't be solved with an additional +# level of indirection... +# +# This kludge allows ^C to interrupt top_block.run and top_block.wait +# +# The problem that we are working around is that Python only services +# signals (e.g., KeyboardInterrupt) in its main thread. If the main +# thread is blocked in our C++ version of wait, even though Python's +# SIGINT handler fires, and even though there may be other python +# threads running, no one will know. Thus instead of directly waiting +# in the thread that calls wait (which is likely to be the Python main +# thread), we create a separate thread that does the blocking wait, +# and then use the thread that called wait to do a slow poll of an +# event queue. That thread, which is executing "wait" below is +# interruptable, and if it sees a KeyboardInterrupt, executes a stop +# on the top_block, then goes back to waiting for it to complete. +# This ensures that the unlocked wait that was in progress (in the +# _top_block_waiter thread) can complete, release its mutex and back +# out. If we don't do that, we are never able to clean up, and nasty +# things occur like leaving the USRP transmitter sending a carrier. +# +# See also top_block.wait (below), which uses this class to implement +# the interruptable wait. +# +class _top_block_waiter(_threading.Thread): + def __init__(self, tb): + _threading.Thread.__init__(self) + self.setDaemon(1) + self.tb = tb + self.event = _threading.Event() + self.start() + + def run(self): + top_block_wait_unlocked(self.tb) + self.event.set() + + def wait(self): + try: + while not self.event.isSet(): + self.event.wait(0.100) + except KeyboardInterrupt: + self.tb.stop() + self.wait() + + +# +# This hack forces a 'has-a' relationship to look like an 'is-a' one. +# +# It allows Python classes to subclass this one, while passing through +# method calls to the C++ class shared pointer from SWIG. +# +# It also allows us to intercept method calls if needed. +# +# This allows the 'run_locked' methods, which are defined in gr_top_block.i, +# to release the Python global interpreter lock before calling the actual +# method in gr_top_block +# +class top_block(object): + def __init__(self, name="top_block"): + self._tb = top_block_swig(name) + + def __getattr__(self, name): + if not hasattr(self, "_tb"): + raise RuntimeError("top_block: invalid state--did you forget to call gr.top_block.__init__ in a derived class?") + return getattr(self._tb, name) + + def start(self, max_noutput_items=100000): + self._tb.start(max_noutput_items) + + def stop(self): + self._tb.stop() + + def run(self, max_noutput_items=100000): + self.start(max_noutput_items) + self.wait() + + def wait(self): + _top_block_waiter(self._tb).wait() + + + # FIXME: these are duplicated from hier_block2.py; they should really be implemented + # in the original C++ class (gr_hier_block2), then they would all be inherited here + + def connect(self, *points): + '''connect requires one or more arguments that can be coerced to endpoints. + If more than two arguments are provided, they are connected together successively. + ''' + if len (points) < 1: + raise ValueError, ("connect requires at least one endpoint; %d provided." % (len (points),)) + else: + if len(points) == 1: + self._tb.primitive_connect(points[0].to_basic_block()) + else: + for i in range (1, len (points)): + self._connect(points[i-1], points[i]) + + def msg_connect(self, src, srcport, dst, dstport): + self.primitive_msg_connect(src.to_basic_block(), srcport, dst.to_basic_block(), dstport); + + def msg_disconnect(self, src, srcport, dst, dstport): + self.primitive_msg_disconnect(src.to_basic_block(), srcport, dst.to_basic_block(), dstport); + + def _connect(self, src, dst): + (src_block, src_port) = self._coerce_endpoint(src) + (dst_block, dst_port) = self._coerce_endpoint(dst) + self._tb.primitive_connect(src_block.to_basic_block(), src_port, + dst_block.to_basic_block(), dst_port) + + def _coerce_endpoint(self, endp): + if hasattr(endp, 'to_basic_block'): + return (endp, 0) + else: + if hasattr(endp, "__getitem__") and len(endp) == 2: + return endp # Assume user put (block, port) + else: + raise ValueError("unable to coerce endpoint") + + def disconnect(self, *points): + '''disconnect requires one or more arguments that can be coerced to endpoints. + If more than two arguments are provided, they are disconnected successively. + ''' + if len (points) < 1: + raise ValueError, ("disconnect requires at least one endpoint; %d provided." % (len (points),)) + else: + if len(points) == 1: + self._tb.primitive_disconnect(points[0].to_basic_block()) + else: + for i in range (1, len (points)): + self._disconnect(points[i-1], points[i]) + + def _disconnect(self, src, dst): + (src_block, src_port) = self._coerce_endpoint(src) + (dst_block, dst_port) = self._coerce_endpoint(dst) + self._tb.primitive_disconnect(src_block.to_basic_block(), src_port, + dst_block.to_basic_block(), dst_port) + diff --git a/gnuradio-core/src/python/gnuradio/gr_unittest.py b/gnuradio-core/src/python/gnuradio/gr_unittest.py new file mode 100755 index 000000000..e4510a6eb --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr_unittest.py @@ -0,0 +1,167 @@ +#!/usr/bin/env python +# +# 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. +# + +import unittest +import gr_xmlrunner +import sys, os, stat + +class TestCase(unittest.TestCase): + """A subclass of unittest.TestCase that adds additional assertions + + Adds new methods assertComplexAlmostEqual, + assertComplexTuplesAlmostEqual and assertFloatTuplesAlmostEqual + """ + + def assertComplexAlmostEqual (self, first, second, places=7, msg=None): + """Fail if the two complex objects are unequal as determined by their + difference rounded to the given number of decimal places + (default 7) and comparing to zero. + + Note that decimal places (from zero) is usually not the same + as significant digits (measured from the most signficant digit). + """ + if round(second.real-first.real, places) != 0: + raise self.failureException, \ + (msg or '%s != %s within %s places' % (`first`, `second`, `places` )) + if round(second.imag-first.imag, places) != 0: + raise self.failureException, \ + (msg or '%s != %s within %s places' % (`first`, `second`, `places` )) + + def assertComplexAlmostEqual2 (self, ref, x, abs_eps=1e-12, rel_eps=1e-6, msg=None): + """ + Fail if the two complex objects are unequal as determined by... + """ + if abs(ref - x) < abs_eps: + return + + if abs(ref) > abs_eps: + if abs(ref-x)/abs(ref) > rel_eps: + raise self.failureException, \ + (msg or '%s != %s rel_error = %s rel_limit = %s' % ( + `ref`, `x`, abs(ref-x)/abs(ref), `rel_eps` )) + else: + raise self.failureException, \ + (msg or '%s != %s rel_error = %s rel_limit = %s' % ( + `ref`, `x`, abs(ref-x)/abs(ref), `rel_eps` )) + + + + def assertComplexTuplesAlmostEqual (self, a, b, places=7, msg=None): + self.assertEqual (len(a), len(b)) + for i in xrange (len(a)): + self.assertComplexAlmostEqual (a[i], b[i], places, msg) + + def assertComplexTuplesAlmostEqual2 (self, ref, x, + abs_eps=1e-12, rel_eps=1e-6, msg=None): + self.assertEqual (len(ref), len(x)) + for i in xrange (len(ref)): + try: + self.assertComplexAlmostEqual2 (ref[i], x[i], abs_eps, rel_eps, msg) + except self.failureException, e: + #sys.stderr.write("index = %d " % (i,)) + #sys.stderr.write("%s\n" % (e,)) + raise + + def assertFloatTuplesAlmostEqual (self, a, b, places=7, msg=None): + self.assertEqual (len(a), len(b)) + for i in xrange (len(a)): + self.assertAlmostEqual (a[i], b[i], places, msg) + + + def assertFloatTuplesAlmostEqual2 (self, ref, x, + abs_eps=1e-12, rel_eps=1e-6, msg=None): + self.assertEqual (len(ref), len(x)) + for i in xrange (len(ref)): + try: + self.assertComplexAlmostEqual2 (ref[i], x[i], abs_eps, rel_eps, msg) + except self.failureException, e: + #sys.stderr.write("index = %d " % (i,)) + #sys.stderr.write("%s\n" % (e,)) + raise + + +TestResult = unittest.TestResult +TestSuite = unittest.TestSuite +FunctionTestCase = unittest.FunctionTestCase +TestLoader = unittest.TestLoader +TextTestRunner = unittest.TextTestRunner +TestProgram = unittest.TestProgram +main = TestProgram + +def run(PUT, filename=None): + ''' + Runs the unittest on a TestCase and produces an optional XML report + PUT: the program under test and should be a gr_unittest.TestCase + filename: an optional filename to save the XML report of the tests + this will live in ./.unittests/python + ''' + + # Run this is given a file name + if(filename is not None): + basepath = "./.unittests" + path = basepath + "/python" + + if not os.path.exists(basepath): + os.makedirs(basepath, 0750) + + xmlrunner = None + # only proceed if .unittests is writable + st = os.stat(basepath)[stat.ST_MODE] + if(st & stat.S_IWUSR > 0): + # Test if path exists; if not, build it + if not os.path.exists(path): + os.makedirs(path, 0750) + + # Just for safety: make sure we can write here, too + st = os.stat(path)[stat.ST_MODE] + if(st & stat.S_IWUSR > 0): + # Create an XML runner to filename + fout = file(path+"/"+filename, "w") + xmlrunner = gr_xmlrunner.XMLTestRunner(fout) + + txtrunner = TextTestRunner(verbosity=1) + + # Run the test; runner also creates XML output file + # FIXME: make xmlrunner output to screen so we don't have to do run and main + suite = TestLoader().loadTestsFromTestCase(PUT) + + # use the xmlrunner if we can write the the directory + if(xmlrunner is not None): + xmlrunner.run(suite) + + main() + + # This will run and fail make check if problem + # but does not output to screen. + #main(testRunner = xmlrunner) + + else: + # If no filename is given, just run the test + main() + + +############################################################################## +# Executing this module from the command line +############################################################################## + +if __name__ == "__main__": + main(module=None) diff --git a/gnuradio-core/src/python/gnuradio/gr_xmlrunner.py b/gnuradio-core/src/python/gnuradio/gr_xmlrunner.py new file mode 100644 index 000000000..31298197f --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr_xmlrunner.py @@ -0,0 +1,387 @@ +""" +XML Test Runner for PyUnit +""" + +# Written by Sebastian Rittau <srittau@jroger.in-berlin.de> and placed in +# the Public Domain. With contributions by Paolo Borelli and others. +# Added to GNU Radio Oct. 3, 2010 + +__version__ = "0.1" + +import os.path +import re +import sys +import time +import traceback +import unittest +from xml.sax.saxutils import escape + +try: + from StringIO import StringIO +except ImportError: + from io import StringIO + + +class _TestInfo(object): + + """Information about a particular test. + + Used by _XMLTestResult. + + """ + + def __init__(self, test, time): + (self._class, self._method) = test.id().rsplit(".", 1) + self._time = time + self._error = None + self._failure = None + + @staticmethod + def create_success(test, time): + """Create a _TestInfo instance for a successful test.""" + return _TestInfo(test, time) + + @staticmethod + def create_failure(test, time, failure): + """Create a _TestInfo instance for a failed test.""" + info = _TestInfo(test, time) + info._failure = failure + return info + + @staticmethod + def create_error(test, time, error): + """Create a _TestInfo instance for an erroneous test.""" + info = _TestInfo(test, time) + info._error = error + return info + + def print_report(self, stream): + """Print information about this test case in XML format to the + supplied stream. + + """ + stream.write(' <testcase classname="%(class)s" name="%(method)s" time="%(time).4f">' % \ + { + "class": self._class, + "method": self._method, + "time": self._time, + }) + if self._failure is not None: + self._print_error(stream, 'failure', self._failure) + if self._error is not None: + self._print_error(stream, 'error', self._error) + stream.write('</testcase>\n') + + def _print_error(self, stream, tagname, error): + """Print information from a failure or error to the supplied stream.""" + text = escape(str(error[1])) + stream.write('\n') + stream.write(' <%s type="%s">%s\n' \ + % (tagname, _clsname(error[0]), text)) + tb_stream = StringIO() + traceback.print_tb(error[2], None, tb_stream) + stream.write(escape(tb_stream.getvalue())) + stream.write(' </%s>\n' % tagname) + stream.write(' ') + + +def _clsname(cls): + return cls.__module__ + "." + cls.__name__ + + +class _XMLTestResult(unittest.TestResult): + + """A test result class that stores result as XML. + + Used by XMLTestRunner. + + """ + + def __init__(self, classname): + unittest.TestResult.__init__(self) + self._test_name = classname + self._start_time = None + self._tests = [] + self._error = None + self._failure = None + + def startTest(self, test): + unittest.TestResult.startTest(self, test) + self._error = None + self._failure = None + self._start_time = time.time() + + def stopTest(self, test): + time_taken = time.time() - self._start_time + unittest.TestResult.stopTest(self, test) + if self._error: + info = _TestInfo.create_error(test, time_taken, self._error) + elif self._failure: + info = _TestInfo.create_failure(test, time_taken, self._failure) + else: + info = _TestInfo.create_success(test, time_taken) + self._tests.append(info) + + def addError(self, test, err): + unittest.TestResult.addError(self, test, err) + self._error = err + + def addFailure(self, test, err): + unittest.TestResult.addFailure(self, test, err) + self._failure = err + + def print_report(self, stream, time_taken, out, err): + """Prints the XML report to the supplied stream. + + The time the tests took to perform as well as the captured standard + output and standard error streams must be passed in.a + + """ + stream.write('<testsuite errors="%(e)d" failures="%(f)d" ' % \ + { "e": len(self.errors), "f": len(self.failures) }) + stream.write('name="%(n)s" tests="%(t)d" time="%(time).3f">\n' % \ + { + "n": self._test_name, + "t": self.testsRun, + "time": time_taken, + }) + for info in self._tests: + info.print_report(stream) + stream.write(' <system-out><![CDATA[%s]]></system-out>\n' % out) + stream.write(' <system-err><![CDATA[%s]]></system-err>\n' % err) + stream.write('</testsuite>\n') + + +class XMLTestRunner(object): + + """A test runner that stores results in XML format compatible with JUnit. + + XMLTestRunner(stream=None) -> XML test runner + + The XML file is written to the supplied stream. If stream is None, the + results are stored in a file called TEST-<module>.<class>.xml in the + current working directory (if not overridden with the path property), + where <module> and <class> are the module and class name of the test class. + + """ + + def __init__(self, stream=None): + self._stream = stream + self._path = "." + + def run(self, test): + """Run the given test case or test suite.""" + class_ = test.__class__ + classname = class_.__module__ + "." + class_.__name__ + if self._stream == None: + filename = "TEST-%s.xml" % classname + stream = file(os.path.join(self._path, filename), "w") + stream.write('<?xml version="1.0" encoding="utf-8"?>\n') + else: + stream = self._stream + + result = _XMLTestResult(classname) + start_time = time.time() + + fss = _fake_std_streams() + fss.__enter__() + try: + test(result) + try: + out_s = sys.stdout.getvalue() + except AttributeError: + out_s = "" + try: + err_s = sys.stderr.getvalue() + except AttributeError: + err_s = "" + finally: + fss.__exit__(None, None, None) + + time_taken = time.time() - start_time + result.print_report(stream, time_taken, out_s, err_s) + if self._stream is None: + stream.close() + + return result + + def _set_path(self, path): + self._path = path + + path = property(lambda self: self._path, _set_path, None, + """The path where the XML files are stored. + + This property is ignored when the XML file is written to a file + stream.""") + + +class _fake_std_streams(object): + + def __enter__(self): + self._orig_stdout = sys.stdout + self._orig_stderr = sys.stderr + #sys.stdout = StringIO() + #sys.stderr = StringIO() + + def __exit__(self, exc_type, exc_val, exc_tb): + sys.stdout = self._orig_stdout + sys.stderr = self._orig_stderr + + +class XMLTestRunnerTest(unittest.TestCase): + + def setUp(self): + self._stream = StringIO() + + def _try_test_run(self, test_class, expected): + + """Run the test suite against the supplied test class and compare the + XML result against the expected XML string. Fail if the expected + string doesn't match the actual string. All time attributes in the + expected string should have the value "0.000". All error and failure + messages are reduced to "Foobar". + + """ + + runner = XMLTestRunner(self._stream) + runner.run(unittest.makeSuite(test_class)) + + got = self._stream.getvalue() + # Replace all time="X.YYY" attributes by time="0.000" to enable a + # simple string comparison. + got = re.sub(r'time="\d+\.\d+"', 'time="0.000"', got) + # Likewise, replace all failure and error messages by a simple "Foobar" + # string. + got = re.sub(r'(?s)<failure (.*?)>.*?</failure>', r'<failure \1>Foobar</failure>', got) + got = re.sub(r'(?s)<error (.*?)>.*?</error>', r'<error \1>Foobar</error>', got) + # And finally Python 3 compatibility. + got = got.replace('type="builtins.', 'type="exceptions.') + + self.assertEqual(expected, got) + + def test_no_tests(self): + """Regression test: Check whether a test run without any tests + matches a previous run. + + """ + class TestTest(unittest.TestCase): + pass + self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="0" time="0.000"> + <system-out><![CDATA[]]></system-out> + <system-err><![CDATA[]]></system-err> +</testsuite> +""") + + def test_success(self): + """Regression test: Check whether a test run with a successful test + matches a previous run. + + """ + class TestTest(unittest.TestCase): + def test_foo(self): + pass + self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="1" time="0.000"> + <testcase classname="__main__.TestTest" name="test_foo" time="0.000"></testcase> + <system-out><![CDATA[]]></system-out> + <system-err><![CDATA[]]></system-err> +</testsuite> +""") + + def test_failure(self): + """Regression test: Check whether a test run with a failing test + matches a previous run. + + """ + class TestTest(unittest.TestCase): + def test_foo(self): + self.assert_(False) + self._try_test_run(TestTest, """<testsuite errors="0" failures="1" name="unittest.TestSuite" tests="1" time="0.000"> + <testcase classname="__main__.TestTest" name="test_foo" time="0.000"> + <failure type="exceptions.AssertionError">Foobar</failure> + </testcase> + <system-out><![CDATA[]]></system-out> + <system-err><![CDATA[]]></system-err> +</testsuite> +""") + + def test_error(self): + """Regression test: Check whether a test run with a erroneous test + matches a previous run. + + """ + class TestTest(unittest.TestCase): + def test_foo(self): + raise IndexError() + self._try_test_run(TestTest, """<testsuite errors="1" failures="0" name="unittest.TestSuite" tests="1" time="0.000"> + <testcase classname="__main__.TestTest" name="test_foo" time="0.000"> + <error type="exceptions.IndexError">Foobar</error> + </testcase> + <system-out><![CDATA[]]></system-out> + <system-err><![CDATA[]]></system-err> +</testsuite> +""") + + def test_stdout_capture(self): + """Regression test: Check whether a test run with output to stdout + matches a previous run. + + """ + class TestTest(unittest.TestCase): + def test_foo(self): + sys.stdout.write("Test\n") + self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="1" time="0.000"> + <testcase classname="__main__.TestTest" name="test_foo" time="0.000"></testcase> + <system-out><![CDATA[Test +]]></system-out> + <system-err><![CDATA[]]></system-err> +</testsuite> +""") + + def test_stderr_capture(self): + """Regression test: Check whether a test run with output to stderr + matches a previous run. + + """ + class TestTest(unittest.TestCase): + def test_foo(self): + sys.stderr.write("Test\n") + self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="1" time="0.000"> + <testcase classname="__main__.TestTest" name="test_foo" time="0.000"></testcase> + <system-out><![CDATA[]]></system-out> + <system-err><![CDATA[Test +]]></system-err> +</testsuite> +""") + + class NullStream(object): + """A file-like object that discards everything written to it.""" + def write(self, buffer): + pass + + def test_unittests_changing_stdout(self): + """Check whether the XMLTestRunner recovers gracefully from unit tests + that change stdout, but don't change it back properly. + + """ + class TestTest(unittest.TestCase): + def test_foo(self): + sys.stdout = XMLTestRunnerTest.NullStream() + + runner = XMLTestRunner(self._stream) + runner.run(unittest.makeSuite(TestTest)) + + def test_unittests_changing_stderr(self): + """Check whether the XMLTestRunner recovers gracefully from unit tests + that change stderr, but don't change it back properly. + + """ + class TestTest(unittest.TestCase): + def test_foo(self): + sys.stderr = XMLTestRunnerTest.NullStream() + + runner = XMLTestRunner(self._stream) + runner.run(unittest.makeSuite(TestTest)) + + +if __name__ == "__main__": + unittest.main() diff --git a/gnuradio-core/src/python/gnuradio/gru/CMakeLists.txt b/gnuradio-core/src/python/gnuradio/gru/CMakeLists.txt new file mode 100644 index 000000000..1c50989d9 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gru/CMakeLists.txt @@ -0,0 +1,26 @@ +# Copyright 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. + +include(GrPython) + +GR_PYTHON_INSTALL( + FILES __init__.py + DESTINATION ${GR_PYTHON_DIR}/gnuradio/gru + COMPONENT "core_python" +) diff --git a/gnuradio-core/src/python/gnuradio/gru/__init__.py b/gnuradio-core/src/python/gnuradio/gru/__init__.py new file mode 100644 index 000000000..c24439ff5 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gru/__init__.py @@ -0,0 +1,37 @@ +# +# 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. +# + +import glob +import os.path + +# Semi-hideous kludge to import everything in the gruimpl directory +# into the gnuradio.gru namespace. This keeps us from having to remember +# to manually update this file. + +for p in __path__: + filenames = glob.glob (os.path.join (p, "..", "gruimpl", "*.py")) + for f in filenames: + f = os.path.basename(f).lower() + f = f[:-3] + if f == '__init__': + continue + # print f + exec "from gnuradio.gruimpl.%s import *" % (f,) diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/CMakeLists.txt b/gnuradio-core/src/python/gnuradio/gruimpl/CMakeLists.txt new file mode 100644 index 000000000..7d48f3512 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright 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. + +include(GrPython) + +GR_PYTHON_INSTALL(FILES + __init__.py + freqz.py + gnuplot_freqz.py + hexint.py + listmisc.py + mathmisc.py + lmx2306.py + msgq_runner.py + os_read_exactly.py + sdr_1000.py + seq_with_cursor.py + socket_stuff.py + daemon.py + DESTINATION ${GR_PYTHON_DIR}/gnuradio/gruimpl + COMPONENT "core_python" +) diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/__init__.py b/gnuradio-core/src/python/gnuradio/gruimpl/__init__.py new file mode 100644 index 000000000..a4917cf64 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/__init__.py @@ -0,0 +1 @@ +# make this a package diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/daemon.py b/gnuradio-core/src/python/gnuradio/gruimpl/daemon.py new file mode 100644 index 000000000..e04702152 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/daemon.py @@ -0,0 +1,102 @@ +# +# 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. +# +import os, sys, signal + +# Turn application into a background daemon process. +# +# When this function returns: +# +# 1) The calling process is disconnected from its controlling terminal +# and will not exit when the controlling session exits +# 2) If a pidfile name is provided, it is created and the new pid is +# written into it. +# 3) If a logfile name is provided, it is opened and stdout/stderr are +# redirected to it. +# 4) The process current working directory is changed to '/' to avoid +# pinning any filesystem mounts. +# 5) The process umask is set to 0111. +# +# The return value is the new pid. +# +# To create GNU Radio applications that operate as daemons, add a call to this +# function after all initialization but just before calling gr.top_block.run() +# or .start(). +# +# Daemonized GNU Radio applications may be stopped by sending them a +# SIGINT, SIGKILL, or SIGTERM, e.g., using 'kill pid' from the command line. +# +# If your application uses gr.top_block.run(), the flowgraph will be stopped +# and the function will return. You should allow your daemon program to exit +# at this point. +# +# If your application uses gr.top_block.start(), you are responsible for hooking +# the Python signal handler (see 'signal' module) and calling gr.top_block.stop() +# on your top block, and otherwise causing your daemon process to exit. +# + +def daemonize(pidfile=None, logfile=None): + # fork() into background + try: + pid = os.fork() + except OSError, e: + raise Exception, "%s [%d]" % (e.strerror, e.errno) + + if pid == 0: # First child of first fork() + # Become session leader of new session + os.setsid() + + # fork() into background again + try: + pid = os.fork() + except OSError, e: + raise Exception, "%s [%d]" % (e.strerror, e.errno) + + if pid != 0: + os._exit(0) # Second child of second fork() + + else: # Second child of first fork() + os._exit(0) + + os.umask(0111) + + # Write pid + pid = os.getpid() + if pidfile is not None: + open(pidfile, 'w').write('%d\n'%pid) + + # Redirect streams + if logfile is not None: + lf = open(logfile, 'a+') + sys.stdout = lf + sys.stderr = lf + + # Prevent pinning any filesystem mounts + os.chdir('/') + + # Tell caller what pid to send future signals to + return pid + +if __name__ == "__main__": + import time + daemonize() + print "Hello, world, from daemon process." + time.sleep(20) + print "Goodbye, world, from daemon process." diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/freqz.py b/gnuradio-core/src/python/gnuradio/gruimpl/freqz.py new file mode 100644 index 000000000..60dca64a5 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/freqz.py @@ -0,0 +1,344 @@ +#!/usr/bin/env python +# +# Copyright 2005,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. +# + +# This code lifted from various parts of www.scipy.org -eb 2005-01-24 + +# Copyright (c) 2001, 2002 Enthought, Inc. +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# a. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# b. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# c. Neither the name of the Enthought nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +# DAMAGE. +# + +__all__ = ['freqz'] + +import numpy +from numpy import * +Num=numpy + +def atleast_1d(*arys): + """ Force a sequence of arrays to each be at least 1D. + + Description: + Force an array to be at least 1D. If an array is 0D, the + array is converted to a single row of values. Otherwise, + the array is unaltered. + Arguments: + *arys -- arrays to be converted to 1 or more dimensional array. + Returns: + input array converted to at least 1D array. + """ + res = [] + for ary in arys: + ary = asarray(ary) + if len(ary.shape) == 0: + result = numpy.array([ary[0]]) + else: + result = ary + res.append(result) + if len(res) == 1: + return res[0] + else: + return res + + +def polyval(p,x): + """Evaluate the polynomial p at x. If x is a polynomial then composition. + + Description: + + If p is of length N, this function returns the value: + p[0]*(x**N-1) + p[1]*(x**N-2) + ... + p[N-2]*x + p[N-1] + + x can be a sequence and p(x) will be returned for all elements of x. + or x can be another polynomial and the composite polynomial p(x) will be + returned. + """ + p = asarray(p) + if isinstance(x,poly1d): + y = 0 + else: + x = asarray(x) + y = numpy.zeros(x.shape,x.typecode()) + for i in range(len(p)): + y = x * y + p[i] + return y + +class poly1d: + """A one-dimensional polynomial class. + + p = poly1d([1,2,3]) constructs the polynomial x**2 + 2 x + 3 + + p(0.5) evaluates the polynomial at the location + p.r is a list of roots + p.c is the coefficient array [1,2,3] + p.order is the polynomial order (after leading zeros in p.c are removed) + p[k] is the coefficient on the kth power of x (backwards from + sequencing the coefficient array. + + polynomials can be added, substracted, multplied and divided (returns + quotient and remainder). + asarray(p) will also give the coefficient array, so polynomials can + be used in all functions that accept arrays. + """ + def __init__(self, c_or_r, r=0): + if isinstance(c_or_r,poly1d): + for key in c_or_r.__dict__.keys(): + self.__dict__[key] = c_or_r.__dict__[key] + return + if r: + c_or_r = poly(c_or_r) + c_or_r = atleast_1d(c_or_r) + if len(c_or_r.shape) > 1: + raise ValueError, "Polynomial must be 1d only." + c_or_r = trim_zeros(c_or_r, trim='f') + if len(c_or_r) == 0: + c_or_r = numpy.array([0]) + self.__dict__['coeffs'] = c_or_r + self.__dict__['order'] = len(c_or_r) - 1 + + def __array__(self,t=None): + if t: + return asarray(self.coeffs,t) + else: + return asarray(self.coeffs) + + def __coerce__(self,other): + return None + + def __repr__(self): + vals = repr(self.coeffs) + vals = vals[6:-1] + return "poly1d(%s)" % vals + + def __len__(self): + return self.order + + def __str__(self): + N = self.order + thestr = "0" + for k in range(len(self.coeffs)): + coefstr ='%.4g' % abs(self.coeffs[k]) + if coefstr[-4:] == '0000': + coefstr = coefstr[:-5] + power = (N-k) + if power == 0: + if coefstr != '0': + newstr = '%s' % (coefstr,) + else: + if k == 0: + newstr = '0' + else: + newstr = '' + elif power == 1: + if coefstr == '0': + newstr = '' + elif coefstr == '1': + newstr = 'x' + else: + newstr = '%s x' % (coefstr,) + else: + if coefstr == '0': + newstr = '' + elif coefstr == '1': + newstr = 'x**%d' % (power,) + else: + newstr = '%s x**%d' % (coefstr, power) + + if k > 0: + if newstr != '': + if self.coeffs[k] < 0: + thestr = "%s - %s" % (thestr, newstr) + else: + thestr = "%s + %s" % (thestr, newstr) + elif (k == 0) and (newstr != '') and (self.coeffs[k] < 0): + thestr = "-%s" % (newstr,) + else: + thestr = newstr + return _raise_power(thestr) + + + def __call__(self, val): + return polyval(self.coeffs, val) + + def __mul__(self, other): + if isscalar(other): + return poly1d(self.coeffs * other) + else: + other = poly1d(other) + return poly1d(polymul(self.coeffs, other.coeffs)) + + def __rmul__(self, other): + if isscalar(other): + return poly1d(other * self.coeffs) + else: + other = poly1d(other) + return poly1d(polymul(self.coeffs, other.coeffs)) + + def __add__(self, other): + other = poly1d(other) + return poly1d(polyadd(self.coeffs, other.coeffs)) + + def __radd__(self, other): + other = poly1d(other) + return poly1d(polyadd(self.coeffs, other.coeffs)) + + def __pow__(self, val): + if not isscalar(val) or int(val) != val or val < 0: + raise ValueError, "Power to non-negative integers only." + res = [1] + for k in range(val): + res = polymul(self.coeffs, res) + return poly1d(res) + + def __sub__(self, other): + other = poly1d(other) + return poly1d(polysub(self.coeffs, other.coeffs)) + + def __rsub__(self, other): + other = poly1d(other) + return poly1d(polysub(other.coeffs, self.coeffs)) + + def __div__(self, other): + if isscalar(other): + return poly1d(self.coeffs/other) + else: + other = poly1d(other) + return map(poly1d,polydiv(self.coeffs, other.coeffs)) + + def __rdiv__(self, other): + if isscalar(other): + return poly1d(other/self.coeffs) + else: + other = poly1d(other) + return map(poly1d,polydiv(other.coeffs, self.coeffs)) + + def __setattr__(self, key, val): + raise ValueError, "Attributes cannot be changed this way." + + def __getattr__(self, key): + if key in ['r','roots']: + return roots(self.coeffs) + elif key in ['c','coef','coefficients']: + return self.coeffs + elif key in ['o']: + return self.order + else: + return self.__dict__[key] + + def __getitem__(self, val): + ind = self.order - val + if val > self.order: + return 0 + if val < 0: + return 0 + return self.coeffs[ind] + + def __setitem__(self, key, val): + ind = self.order - key + if key < 0: + raise ValueError, "Does not support negative powers." + if key > self.order: + zr = numpy.zeros(key-self.order,self.coeffs.typecode()) + self.__dict__['coeffs'] = numpy.concatenate((zr,self.coeffs)) + self.__dict__['order'] = key + ind = 0 + self.__dict__['coeffs'][ind] = val + return + + def integ(self, m=1, k=0): + return poly1d(polyint(self.coeffs,m=m,k=k)) + + def deriv(self, m=1): + return poly1d(polyder(self.coeffs,m=m)) + +def freqz(b, a, worN=None, whole=0, plot=None): + """Compute frequency response of a digital filter. + + Description: + + Given the numerator (b) and denominator (a) of a digital filter compute + its frequency response. + + jw -jw -jmw + jw B(e) b[0] + b[1]e + .... + b[m]e + H(e) = ---- = ------------------------------------ + jw -jw -jnw + A(e) a[0] + a[2]e + .... + a[n]e + + Inputs: + + b, a --- the numerator and denominator of a linear filter. + worN --- If None, then compute at 512 frequencies around the unit circle. + If a single integer, the compute at that many frequencies. + Otherwise, compute the response at frequencies given in worN + whole -- Normally, frequencies are computed from 0 to pi (upper-half of + unit-circle. If whole is non-zero compute frequencies from 0 + to 2*pi. + + Outputs: (h,w) + + h -- The frequency response. + w -- The frequencies at which h was computed. + """ + b, a = map(atleast_1d, (b,a)) + if whole: + lastpoint = 2*pi + else: + lastpoint = pi + if worN is None: + N = 512 + w = Num.arange(0,lastpoint,lastpoint/N) + elif isinstance(worN, types.IntType): + N = worN + w = Num.arange(0,lastpoint,lastpoint/N) + else: + w = worN + w = atleast_1d(w) + zm1 = exp(-1j*w) + h = polyval(b[::-1], zm1) / polyval(a[::-1], zm1) + # if not plot is None: + # plot(w, h) + return h, w diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/gnuplot_freqz.py b/gnuradio-core/src/python/gnuradio/gruimpl/gnuplot_freqz.py new file mode 100755 index 000000000..defc47b59 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/gnuplot_freqz.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python +# +# Copyright 2005,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. +# + +__all__ = ['gnuplot_freqz'] + +import tempfile +import os +import math +import numpy + +from gnuradio import gr +from gnuradio.gruimpl.freqz import freqz + + +def gnuplot_freqz (hw, Fs=None, logfreq=False): + + """hw is a tuple of the form (h, w) where h is sequence of complex + freq responses, and w is a sequence of corresponding frequency + points. Plot the frequency response using gnuplot. If Fs is + provide, use it as the sampling frequency, else use 2*pi. + + Returns a handle to the gnuplot graph. When the handle is reclaimed + the graph is torn down.""" + + data_file = tempfile.NamedTemporaryFile () + cmd_file = os.popen ('gnuplot', 'w') + + h, w = hw + ampl = 20 * numpy.log10 (numpy.absolute (h) + 1e-9) + phase = map (lambda x: math.atan2 (x.imag, x.real), h) + + if Fs: + w *= (Fs/(2*math.pi)) + + for freq, a, ph in zip (w, ampl, phase): + data_file.write ("%g\t%g\t%g\n" % (freq, a, ph)) + + data_file.flush () + + cmd_file.write ("set grid\n") + if logfreq: + cmd_file.write ("set logscale x\n") + else: + cmd_file.write ("unset logscale x\n") + cmd_file.write ("plot '%s' using 1:2 with lines\n" % (data_file.name,)) + cmd_file.flush () + + return (cmd_file, data_file) + + +def test_plot (): + sample_rate = 2.0e6 + taps = gr.firdes.low_pass (1.0, # gain + sample_rate, # sampling rate + 200e3, # low pass cutoff freq + 100e3, # width of trans. band + gr.firdes.WIN_HAMMING) + # print len (taps) + return gnuplot_freqz (freqz (taps, 1), sample_rate) + +if __name__ == '__main__': + handle = test_plot () + raw_input ('Press Enter to continue: ') diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/hexint.py b/gnuradio-core/src/python/gnuradio/gruimpl/hexint.py new file mode 100644 index 000000000..0fb5ecde0 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/hexint.py @@ -0,0 +1,44 @@ +# +# 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. +# + +def hexint(mask): + """ + Convert unsigned masks into signed ints. + + This allows us to use hex constants like 0xf0f0f0f2 when talking to + our hardware and not get screwed by them getting treated as python + longs. + """ + if mask >= 2**31: + return int(mask-2**32) + return mask + +def hexshort(mask): + """ + Convert unsigned masks into signed shorts. + + This allows us to use hex constants like 0x8000 when talking to + our hardware and not get screwed by them getting treated as python + longs. + """ + if mask >= 2**15: + return int(mask-2**16) + return mask diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/listmisc.py b/gnuradio-core/src/python/gnuradio/gruimpl/listmisc.py new file mode 100644 index 000000000..9e70eb863 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/listmisc.py @@ -0,0 +1,29 @@ +# +# 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. +# + +def list_reverse(x): + """ + Return a copy of x that is reverse order. + """ + r = list(x) + r.reverse() + return r + diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/lmx2306.py b/gnuradio-core/src/python/gnuradio/gruimpl/lmx2306.py new file mode 100755 index 000000000..aa4efc3e9 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/lmx2306.py @@ -0,0 +1,186 @@ +#!/usr/bin/env python +# +# 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. +# + +'''Control National LMX2306 based frequency synthesizer''' + +from gnuradio import gr +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +# bottom two bits of 21 bit word select which register to program + +R_REG = 0x0 +AB_REG = 0x1 +F_REG = 0x2 + +F_counter_reset = (1 << 2) +F_phase_detector_polarity = (1 << 7) + +F_LD_tri_state = (0 << 4) +F_LD_R_divider_output = (4 << 4) +F_LD_N_divider_output = (2 << 4) +F_LD_serial_data_output = (6 << 4) +F_LD_digital_lock_detect = (1 << 4) +F_LD_open_drain = (5 << 4) +F_LD_high = (3 << 4) +F_LD_low = (7 << 4) + +# F_default = F_LD_digital_lock_detect | F_phase_detector_polarity +F_default = F_LD_open_drain | F_phase_detector_polarity + +# +# 4 control pins: +# CE always high +# LE load enable. When LE goes high, data stored in the shift register +# is loaded into one of the three registers +# CLK data is clocked in on the rising edge +# DATA single data bit. Entered MSB first + +DB_CLK = (1 << 0) +DB_DATA = (1 << 1) +DB_LE = (1 << 2) +DB_CE = (1 << 3) + +class lmx2306 (object): + '''Control the National LMX2306 PLL''' + __slots__ = ['pp', 'shadow', 'fosc', 'r', 'step_size', 'verbose'] + def __init__ (self, fosc, step_size, which_pp = 0): + '''FOSC is the frequency of the reference oscillator, + STEP_SIZE is the step between valid frequencies, + WHICH_PP specifies which parallel port to use + ''' + self.pp = gr.make_ppio (which_pp) + self.shadow = DB_CE + self.pp.lock () + self.pp.write_data (self.shadow) + self.pp.unlock () + self.verbose = False + self._set_fosc (fosc) + self._set_step (step_size) + + + def program (self, r, a, b): + if self.verbose: + print "lmx2306: r = %d a = %d b = %d" % (r, a, b) + self.pp.lock () + self._write_word (F_REG | F_default | F_counter_reset) + self._write_word (R_REG | ((r & 0x3fff) << 2)) + self._write_word (AB_REG | ((a & 0x1f) << 2) | ((b & 0x1fff) << 7)) + self._write_word (F_REG | F_default) + self.pp.unlock () + + def set_freq (self, freq): + '''Set the PLL frequency to FREQ + + Return the actual freq value set. It will be rounded down to a + multiple of step_size + ''' + divisor = int (freq / self.step_size) + actual = divisor * self.step_size + (a, b) = self._compute_ab (divisor) + self.program (self.r, a, b) + return actual + + # ---------------------------------------------------------------- + + def _set_fosc (self, ref_oscillator_freq): + self.fosc = ref_oscillator_freq + + def _set_step (self, step_size): + r = int (self.fosc / step_size) + if r * step_size != self.fosc: + raise ValueError, "step_size is not a factor of self.fosc" + if r < 3 or r > 16383: + raise ValueError, "r is out of range" + self.r = r + self.step_size = step_size + + def _compute_ab (self, divisor): + b = divisor / 8 + a = divisor - (b * 8) + if b < 3 or b > 8191 or a > b: + raise ValueError, "Invalid divisor" + return (a, b) + + def _write_word (self, w): + for i in range(21): + if w & (1 << 20): + self._set_DATA_1 () + else: + self._set_DATA_0 () + w = (w << 1) & 0x0ffffff + self._set_CLK_1 () + self._set_CLK_0 () + self._set_LE_1 () + self._set_LE_0 () + + def _set_LE_0 (self): + self.shadow = self.shadow & ~DB_LE + self.pp.write_data (self.shadow) + + def _set_LE_1 (self): + self.shadow = self.shadow | DB_LE + self.pp.write_data (self.shadow) + + def _set_CLK_0 (self): + self.shadow = self.shadow & ~DB_CLK + self.pp.write_data (self.shadow) + + def _set_CLK_1 (self): + self.shadow = self.shadow | DB_CLK + self.pp.write_data (self.shadow) + + def _set_DATA_0 (self): + self.shadow = self.shadow & ~DB_DATA + self.pp.write_data (self.shadow) + + def _set_DATA_1 (self): + self.shadow = self.shadow | DB_DATA + self.pp.write_data (self.shadow) + +if __name__ == '__main__': + parser = OptionParser (option_class=eng_option) + parser.add_option ("-o", "--fosc", type="eng_float", default=32e6, + help="set reference oscillator freq to FREQ", metavar="FREQ") + parser.add_option ("-s", "--step-size", type="eng_float", default=10e3, + help="set the frequency step size to STEP_SIZE") + parser.add_option ("-f", "--freq", type="eng_float", default=430e6, + help="set VCO frequency to FREQ") + parser.add_option ("-v", "--verbose", action="store_true", default=False) + (options, args) = parser.parse_args () + + if options.verbose: + print "fosc = %s step = %s fvco = %s" % ( + eng_notation.num_to_str (options.fosc), + eng_notation.num_to_str (options.step_size), + eng_notation.num_to_str (options.freq)) + + lmx = lmx2306 (options.fosc, options.step_size) + lmx.verbose = options.verbose + + actual = lmx.set_freq (options.freq) + + if options.verbose: + print "fvco_actual = %s delta = %s" % ( + eng_notation.num_to_str (actual), + eng_notation.num_to_str (options.freq - actual)) diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/mathmisc.py b/gnuradio-core/src/python/gnuradio/gruimpl/mathmisc.py new file mode 100644 index 000000000..7e6f23a34 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/mathmisc.py @@ -0,0 +1,33 @@ +# +# 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. +# + +import math + +def gcd(a,b): + while b: + a,b = b, a % b + return a + +def lcm(a,b): + return a * b / gcd(a, b) + +def log2(x): + return math.log(x)/math.log(2) diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/msgq_runner.py b/gnuradio-core/src/python/gnuradio/gruimpl/msgq_runner.py new file mode 100644 index 000000000..767a74a71 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/msgq_runner.py @@ -0,0 +1,82 @@ +# +# Copyright 2009 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. +# + +""" +Convenience class for dequeuing messages from a gr.msg_queue and +invoking a callback. + +Creates a Python thread that does a blocking read on the supplied +gr.msg_queue, then invokes callback each time a msg is received. + +If the msg type is not 0, then it is treated as a signal to exit +its loop. + +If the callback raises an exception, and the runner was created +with 'exit_on_error' equal to True, then the runner will store the +exception and exit its loop, otherwise the exception is ignored. + +To get the exception that the callback raised, if any, call +exit_error() on the object. + +To manually stop the runner, call stop() on the object. + +To determine if the runner has exited, call exited() on the object. +""" + +from gnuradio import gr +import gnuradio.gr.gr_threading as _threading + +class msgq_runner(_threading.Thread): + + def __init__(self, msgq, callback, exit_on_error=False): + _threading.Thread.__init__(self) + + self._msgq = msgq + self._callback = callback + self._exit_on_error = exit_on_error + self._done = False + self._exited = False + self._exit_error = None + self.setDaemon(1) + self.start() + + def run(self): + while not self._done: + msg = self._msgq.delete_head() + if msg.type() != 0: + self.stop() + else: + try: + self._callback(msg) + except Exception, e: + if self._exit_on_error: + self._exit_error = e + self.stop() + self._exited = True + + def stop(self): + self._done = True + + def exited(self): + return self._exited + + def exit_error(self): + return self._exit_error diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/os_read_exactly.py b/gnuradio-core/src/python/gnuradio/gruimpl/os_read_exactly.py new file mode 100644 index 000000000..40b053770 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/os_read_exactly.py @@ -0,0 +1,36 @@ +# +# 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. +# + +import os + +def os_read_exactly(file_descriptor, nbytes): + """ + Replacement for os.read that blocks until it reads exactly nbytes. + + """ + s = '' + while nbytes > 0: + sbuf = os.read(file_descriptor, nbytes) + if not(sbuf): + return '' + nbytes -= len(sbuf) + s = s + sbuf + return s diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/sdr_1000.py b/gnuradio-core/src/python/gnuradio/gruimpl/sdr_1000.py new file mode 100644 index 000000000..5192a7155 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/sdr_1000.py @@ -0,0 +1,84 @@ +# +# Copyright 2003,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. +# + +from gnuradio import gr + +class sdr_1000 (gr.sdr_1000_base): + "Control the DDS on the SDR-1000" + def __init__(self, pport = 0): + gr.sdr_1000_base.__init__(self, pport) + self.write_latch (3, 0x00, 0xC0) # Reset low, WRS/ low + self.write_reg (0x20, 0x40) + + def write_reg(self, addr, data): + self.write_latch (3, addr & 0x3f, 0x3f) + self.write_latch (2, data, 0xff) + self.write_latch (3, 0x40, 0x40) + self.write_latch (3, 0x00, 0x40) + + def set_freq(self, freq): + self.set_band (freq) + ftw = freq / 200e6; + for i in xrange(6): + word = int(ftw * 256) + ftw = ftw*256 - word + # print (('%d [%02x]') % (i, word)) + self.write_reg (4+i, word) + + def set_band (self, freq): + if freq <= 2.25e6: + band = 0 + elif freq <= 5.5e6: + band = 1 + elif freq <= 11e6: + band = 3 # due to wiring mistake on board + elif freq <= 22e6: + band = 2 # due to wiring mistake on board + elif freq <= 37.5e6: + band = 4 + else: + band = 5 + + self.write_latch (1, 1 << band, 0x3f) + + def set_bit (self, reg, bit, state): + val = 0x00 + if state: val = 1<<bit + self.write_latch (reg, val, 1<<bit) + + def set_tx (self, on = 1): + self.set_bit(1, 6, on) + + def set_rx (self): + self.set_bit(1, 6, 0) + + def set_gain (self, high): + self.set_bit(0, 7, high) + + def set_mute (self, mute = 1): + self.set_bit(1, 7, mute) + + def set_unmute (self): + self.set_bit(1, 7, 0) + + def set_external_pin (self, pin, on = 1): + assert (pin < 8 and pin > 0), "Out of range 1..7" + self.set_bit(0, pin-1, on) diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/seq_with_cursor.py b/gnuradio-core/src/python/gnuradio/gruimpl/seq_with_cursor.py new file mode 100644 index 000000000..def3299b6 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/seq_with_cursor.py @@ -0,0 +1,77 @@ +# +# Copyright 2003,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. +# + +# misc utilities + +import types +import exceptions + +class seq_with_cursor (object): + __slots__ = [ 'items', 'index' ] + + def __init__ (self, items, initial_index = None, initial_value = None): + assert len (items) > 0, "seq_with_cursor: len (items) == 0" + self.items = items + self.set_index (initial_index) + if initial_value is not None: + self.set_index_by_value(initial_value) + + def set_index (self, initial_index): + if initial_index is None: + self.index = len (self.items) / 2 + elif initial_index >= 0 and initial_index < len (self.items): + self.index = initial_index + else: + raise exceptions.ValueError + + def set_index_by_value(self, v): + """ + Set index to the smallest value such that items[index] >= v. + If there is no such item, set index to the maximum value. + """ + self.set_index(0) # side effect! + cv = self.current() + more = True + while cv < v and more: + cv, more = self.next() # side effect! + + def next (self): + new_index = self.index + 1 + if new_index < len (self.items): + self.index = new_index + return self.items[new_index], True + else: + return self.items[self.index], False + + def prev (self): + new_index = self.index - 1 + if new_index >= 0: + self.index = new_index + return self.items[new_index], True + else: + return self.items[self.index], False + + def current (self): + return self.items[self.index] + + def get_seq (self): + return self.items[:] # copy of items + diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/socket_stuff.py b/gnuradio-core/src/python/gnuradio/gruimpl/socket_stuff.py new file mode 100644 index 000000000..329fd2ed3 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/socket_stuff.py @@ -0,0 +1,56 @@ +# +# 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. +# + +# random socket related stuff + +import socket +import os +import sys + +def tcp_connect_or_die(sock_addr): + """ + @param sock_addr: (host, port) to connect to + @type sock_addr: tuple + @returns: socket or exits + """ + s = socket.socket (socket.AF_INET, socket.SOCK_STREAM) + try: + s.connect(sock_addr) + except socket.error, err: + sys.stderr.write('Failed to connect to %s: %s\n' % + (sock_addr, os.strerror (err.args[0]),)) + sys.exit(1) + return s + +def udp_connect_or_die(sock_addr): + """ + @param sock_addr: (host, port) to connect to + @type sock_addr: tuple + @returns: socket or exits + """ + s = socket.socket (socket.AF_INET, socket.SOCK_DGRAM) + try: + s.connect(sock_addr) + except socket.error, err: + sys.stderr.write('Failed to connect to %s: %s\n' % + (sock_addr, os.strerror (err.args[0]),)) + sys.exit(1) + return s diff --git a/gnuradio-core/src/python/gnuradio/optfir.py b/gnuradio-core/src/python/gnuradio/optfir.py new file mode 100644 index 000000000..bbf9ead74 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/optfir.py @@ -0,0 +1,341 @@ +# +# Copyright 2004,2005,2009 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. +# + +''' +Routines for designing optimal FIR filters. + +For a great intro to how all this stuff works, see section 6.6 of +"Digital Signal Processing: A Practical Approach", Emmanuael C. Ifeachor +and Barrie W. Jervis, Adison-Wesley, 1993. ISBN 0-201-54413-X. +''' + +import math, cmath +from gnuradio import gr + +remez = gr.remez + +# ---------------------------------------------------------------- + +## Builds a low pass filter. +# @param gain Filter gain in the passband (linear) +# @param Fs Sampling rate (sps) +# @param freq1 End of pass band (in Hz) +# @param freq2 Start of stop band (in Hz) +# @param passband_ripple_db Pass band ripple in dB (should be small, < 1) +# @param stopband_atten_db Stop band attenuation in dB (should be large, >= 60) +# @param nextra_taps Extra taps to use in the filter (default=2) +def low_pass (gain, Fs, freq1, freq2, passband_ripple_db, stopband_atten_db, + nextra_taps=2): + passband_dev = passband_ripple_to_dev (passband_ripple_db) + stopband_dev = stopband_atten_to_dev (stopband_atten_db) + desired_ampls = (gain, 0) + (n, fo, ao, w) = remezord ([freq1, freq2], desired_ampls, + [passband_dev, stopband_dev], Fs) + # The remezord typically under-estimates the filter order, so add 2 taps by default + taps = gr.remez (n + nextra_taps, fo, ao, w, "bandpass") + return taps + +## Builds a band pass filter. +# @param gain Filter gain in the passband (linear) +# @param Fs Sampling rate (sps) +# @param freq_sb1 End of stop band (in Hz) +# @param freq_pb1 Start of pass band (in Hz) +# @param freq_pb2 End of pass band (in Hz) +# @param freq_sb2 Start of stop band (in Hz) +# @param passband_ripple_db Pass band ripple in dB (should be small, < 1) +# @param stopband_atten_db Stop band attenuation in dB (should be large, >= 60) +# @param nextra_taps Extra taps to use in the filter (default=2) +def band_pass (gain, Fs, freq_sb1, freq_pb1, freq_pb2, freq_sb2, + passband_ripple_db, stopband_atten_db, + nextra_taps=2): + passband_dev = passband_ripple_to_dev (passband_ripple_db) + stopband_dev = stopband_atten_to_dev (stopband_atten_db) + desired_ampls = (0, gain, 0) + desired_freqs = [freq_sb1, freq_pb1, freq_pb2, freq_sb2] + desired_ripple = [stopband_dev, passband_dev, stopband_dev] + (n, fo, ao, w) = remezord (desired_freqs, desired_ampls, + desired_ripple, Fs) + # The remezord typically under-estimates the filter order, so add 2 taps by default + taps = gr.remez (n + nextra_taps, fo, ao, w, "bandpass") + return taps + + +## Builds a band pass filter with complex taps by making an LPF and +# spinning it up to the right center frequency +# @param gain Filter gain in the passband (linear) +# @param Fs Sampling rate (sps) +# @param freq_sb1 End of stop band (in Hz) +# @param freq_pb1 Start of pass band (in Hz) +# @param freq_pb2 End of pass band (in Hz) +# @param freq_sb2 Start of stop band (in Hz) +# @param passband_ripple_db Pass band ripple in dB (should be small, < 1) +# @param stopband_atten_db Stop band attenuation in dB (should be large, >= 60) +# @param nextra_taps Extra taps to use in the filter (default=2) +def complex_band_pass (gain, Fs, freq_sb1, freq_pb1, freq_pb2, freq_sb2, + passband_ripple_db, stopband_atten_db, + nextra_taps=2): + center_freq = (freq_pb2 + freq_pb1) / 2.0 + lp_pb = (freq_pb2 - center_freq)/1.0 + lp_sb = freq_sb2 - center_freq + lptaps = low_pass(gain, Fs, lp_pb, lp_sb, passband_ripple_db, + stopband_atten_db, nextra_taps) + spinner = [cmath.exp(2j*cmath.pi*center_freq/Fs*i) for i in xrange(len(lptaps))] + taps = [s*t for s,t in zip(spinner, lptaps)] + return taps + + +## Builds a band reject filter +# spinning it up to the right center frequency +# @param gain Filter gain in the passband (linear) +# @param Fs Sampling rate (sps) +# @param freq_pb1 End of pass band (in Hz) +# @param freq_sb1 Start of stop band (in Hz) +# @param freq_sb2 End of stop band (in Hz) +# @param freq_pb2 Start of pass band (in Hz) +# @param passband_ripple_db Pass band ripple in dB (should be small, < 1) +# @param stopband_atten_db Stop band attenuation in dB (should be large, >= 60) +# @param nextra_taps Extra taps to use in the filter (default=2) +def band_reject (gain, Fs, freq_pb1, freq_sb1, freq_sb2, freq_pb2, + passband_ripple_db, stopband_atten_db, + nextra_taps=2): + passband_dev = passband_ripple_to_dev (passband_ripple_db) + stopband_dev = stopband_atten_to_dev (stopband_atten_db) + desired_ampls = (gain, 0, gain) + desired_freqs = [freq_pb1, freq_sb1, freq_sb2, freq_pb2] + desired_ripple = [passband_dev, stopband_dev, passband_dev] + (n, fo, ao, w) = remezord (desired_freqs, desired_ampls, + desired_ripple, Fs) + # Make sure we use an odd number of taps + if((n+nextra_taps)%2 == 1): + n += 1 + # The remezord typically under-estimates the filter order, so add 2 taps by default + taps = gr.remez (n + nextra_taps, fo, ao, w, "bandpass") + return taps + + +## Builds a high pass filter. +# @param gain Filter gain in the passband (linear) +# @param Fs Sampling rate (sps) +# @param freq1 End of stop band (in Hz) +# @param freq2 Start of pass band (in Hz) +# @param passband_ripple_db Pass band ripple in dB (should be small, < 1) +# @param stopband_atten_db Stop band attenuation in dB (should be large, >= 60) +# @param nextra_taps Extra taps to use in the filter (default=2) +def high_pass (gain, Fs, freq1, freq2, passband_ripple_db, stopband_atten_db, + nextra_taps=2): + passband_dev = passband_ripple_to_dev (passband_ripple_db) + stopband_dev = stopband_atten_to_dev (stopband_atten_db) + desired_ampls = (0, 1) + (n, fo, ao, w) = remezord ([freq1, freq2], desired_ampls, + [stopband_dev, passband_dev], Fs) + # For a HPF, we need to use an odd number of taps + # In gr.remez, ntaps = n+1, so n must be even + if((n+nextra_taps)%2 == 1): + n += 1 + + # The remezord typically under-estimates the filter order, so add 2 taps by default + taps = gr.remez (n + nextra_taps, fo, ao, w, "bandpass") + return taps + +# ---------------------------------------------------------------- + +def stopband_atten_to_dev (atten_db): + """Convert a stopband attenuation in dB to an absolute value""" + return 10**(-atten_db/20) + +def passband_ripple_to_dev (ripple_db): + """Convert passband ripple spec expressed in dB to an absolute value""" + return (10**(ripple_db/20)-1)/(10**(ripple_db/20)+1) + +# ---------------------------------------------------------------- + +def remezord (fcuts, mags, devs, fsamp = 2): + ''' + FIR order estimator (lowpass, highpass, bandpass, mulitiband). + + (n, fo, ao, w) = remezord (f, a, dev) + (n, fo, ao, w) = remezord (f, a, dev, fs) + + (n, fo, ao, w) = remezord (f, a, dev) finds the approximate order, + normalized frequency band edges, frequency band amplitudes, and + weights that meet input specifications f, a, and dev, to use with + the remez command. + + * f is a sequence of frequency band edges (between 0 and Fs/2, where + Fs is the sampling frequency), and a is a sequence specifying the + desired amplitude on the bands defined by f. The length of f is + twice the length of a, minus 2. The desired function is + piecewise constant. + + * dev is a sequence the same size as a that specifies the maximum + allowable deviation or ripples between the frequency response + and the desired amplitude of the output filter, for each band. + + Use remez with the resulting order n, frequency sequence fo, + amplitude response sequence ao, and weights w to design the filter b + which approximately meets the specifications given by remezord + input parameters f, a, and dev: + + b = remez (n, fo, ao, w) + + (n, fo, ao, w) = remezord (f, a, dev, Fs) specifies a sampling frequency Fs. + + Fs defaults to 2 Hz, implying a Nyquist frequency of 1 Hz. You can + therefore specify band edges scaled to a particular applications + sampling frequency. + + In some cases remezord underestimates the order n. If the filter + does not meet the specifications, try a higher order such as n+1 + or n+2. + ''' + # get local copies + fcuts = fcuts[:] + mags = mags[:] + devs = devs[:] + + for i in range (len (fcuts)): + fcuts[i] = float (fcuts[i]) / fsamp + + nf = len (fcuts) + nm = len (mags) + nd = len (devs) + nbands = nm + + if nm != nd: + raise ValueError, "Length of mags and devs must be equal" + + if nf != 2 * (nbands - 1): + raise ValueError, "Length of f must be 2 * len (mags) - 2" + + for i in range (len (mags)): + if mags[i] != 0: # if not stopband, get relative deviation + devs[i] = devs[i] / mags[i] + + # separate the passband and stopband edges + f1 = fcuts[0::2] + f2 = fcuts[1::2] + + n = 0 + min_delta = 2 + for i in range (len (f1)): + if f2[i] - f1[i] < min_delta: + n = i + min_delta = f2[i] - f1[i] + + if nbands == 2: + # lowpass or highpass case (use formula) + l = lporder (f1[n], f2[n], devs[0], devs[1]) + else: + # bandpass or multipass case + # try different lowpasses and take the worst one that + # goes through the BP specs + l = 0 + for i in range (1, nbands-1): + l1 = lporder (f1[i-1], f2[i-1], devs[i], devs[i-1]) + l2 = lporder (f1[i], f2[i], devs[i], devs[i+1]) + l = max (l, l1, l2) + + n = int (math.ceil (l)) - 1 # need order, not length for remez + + # cook up remez compatible result + ff = [0] + fcuts + [1] + for i in range (1, len (ff) - 1): + ff[i] *= 2 + + aa = [] + for a in mags: + aa = aa + [a, a] + + max_dev = max (devs) + wts = [1] * len(devs) + for i in range (len (wts)): + wts[i] = max_dev / devs[i] + + return (n, ff, aa, wts) + +# ---------------------------------------------------------------- + +def lporder (freq1, freq2, delta_p, delta_s): + ''' + FIR lowpass filter length estimator. freq1 and freq2 are + normalized to the sampling frequency. delta_p is the passband + deviation (ripple), delta_s is the stopband deviation (ripple). + + Note, this works for high pass filters too (freq1 > freq2), but + doesnt work well if the transition is near f == 0 or f == fs/2 + + From Herrmann et al (1973), Practical design rules for optimum + finite impulse response filters. Bell System Technical J., 52, 769-99 + ''' + df = abs (freq2 - freq1) + ddp = math.log10 (delta_p) + dds = math.log10 (delta_s) + + a1 = 5.309e-3 + a2 = 7.114e-2 + a3 = -4.761e-1 + a4 = -2.66e-3 + a5 = -5.941e-1 + a6 = -4.278e-1 + + b1 = 11.01217 + b2 = 0.5124401 + + t1 = a1 * ddp * ddp + t2 = a2 * ddp + t3 = a4 * ddp * ddp + t4 = a5 * ddp + + dinf=((t1 + t2 + a3) * dds) + (t3 + t4 + a6) + ff = b1 + b2 * (ddp - dds) + n = dinf / df - ff * df + 1 + return n + + +def bporder (freq1, freq2, delta_p, delta_s): + ''' + FIR bandpass filter length estimator. freq1 and freq2 are + normalized to the sampling frequency. delta_p is the passband + deviation (ripple), delta_s is the stopband deviation (ripple). + + From Mintzer and Liu (1979) + ''' + df = abs (freq2 - freq1) + ddp = math.log10 (delta_p) + dds = math.log10 (delta_s) + + a1 = 0.01201 + a2 = 0.09664 + a3 = -0.51325 + a4 = 0.00203 + a5 = -0.57054 + a6 = -0.44314 + + t1 = a1 * ddp * ddp + t2 = a2 * ddp + t3 = a4 * ddp * ddp + t4 = a5 * ddp + + cinf = dds * (t1 + t2 + a3) + t3 + t4 + a6 + ginf = -14.6 * math.log10 (delta_p / delta_s) - 16.9 + n = cinf / df + ginf * df + 1 + return n + diff --git a/gnuradio-core/src/python/gnuradio/window.py b/gnuradio-core/src/python/gnuradio/window.py new file mode 100644 index 000000000..4a1d0c516 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/window.py @@ -0,0 +1,180 @@ +# +# Copyright 2004,2005,2009 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. +# + +''' +Routines for designing window functions. +''' + +import math +from gnuradio import gr + +def izero(x): + izeroepsilon = 1e-21 + halfx = x/2.0 + accum = u = n = 1 + while 1: + temp = halfx/n + n += 1 + temp *= temp + u *= temp + accum += u + if u >= IzeroEPSILON*sum: + break + return accum + +def midm1(fft_size): + return (fft_size - 1)/2 + +def midp1(fft_size): + return (fft_size+1)/2 + +def freq(fft_size): + return 2.0*math.pi/fft_size + +def rate(fft_size): + return 1.0/(fft_size >> 1) + +def expn(fft_size): + math.log(2.0)/(midn(fft_size) + 1.0) + +def hamming(fft_size): + window = [] + for index in xrange(fft_size): + window.append(0.54 - 0.46 * math.cos (2 * math.pi / fft_size * index)) # Hamming window + return window + +def hanning(fft_size): + window = [] + for index in xrange(fft_size): + window.append(0.5 - 0.5 * math.cos (2 * math.pi / fft_size * index)) # von Hann window + return window + +def welch(fft_size): + window = [0 for i in range(fft_size)] + j = fft_size-1 + for index in xrange(midn(fft_size)+1): + window[j] = window[index] = (1.0 - math.sqrt((index - midm1(fft_size)) / midp1(fft_size))) + j -= 1 + return window + +def parzen(fft_size): + window = [0 for i in range(fft_size)] + j = fft_size-1 + for index in xrange(midn(fft_size)+1): + window[j] = window[index] = (1.0 - math.abs((index - midm1(fft_size)) / midp1(fft_size))) + j -= 1 + return window + +def bartlett(fft_size): + mfrq = freq(fft_size) + angle = 0 + window = [0 for i in range(fft_size)] + j = fft_size-1 + for index in xrange(midn(fft_size)+1): + window[j] = window[index] = angle + angle += freq + j -= 1 + return window + +def blackman2(fft_size): + mfrq = freq(fft_size) + angle = 0 + window = [0 for i in range(fft_size)] + j = fft_size-1 + for index in xrange(midn(fft_size)+1): + cx = math.cos(angle) + window[j] = window[index] = (.34401 + (cx * (-.49755 + (cx * .15844)))) + angle += freq + j -= 1 + return window + +def blackman3(fft_size): + mfrq = freq(fft_size) + angle = 0 + window = [0 for i in range(fft_size)] + j = fft_size-1 + for index in xrange(midn(fft_size)+1): + cx = math.cos(angle) + window[j] = window[index] = (.21747 + (cx * (-.45325 + (cx * (.28256 - (cx * .04672)))))) + angle += freq + j -= 1 + return window + +def blackman4(fft_size): + mfrq = freq(fft_size) + angle = 0 + window = [0 for i in range(fft_size)] + j = fft_size-1 + for index in xrange(midn(fft_size)+1): + cx = math.cos(angle) + window[j] = window[index] = (.084037 + (cx * (-.29145 + (cx * (.375696 + (cx * (-.20762 + (cx * .041194)))))))) + angle += freq + j -= 1 + return window + +def exponential(fft_size): + expsum = 1.0 + window = [0 for i in range(fft_size)] + j = fft_size-1 + for index in xrange(midn(fft_size)+1): + window[j] = window[i] = (expsum - 1.0) + expsum *= expn(fft_size) + j -= 1 + return window + +def riemann(fft_size): + sr1 = freq(fft_size) + window = [0 for i in range(fft_size)] + j = fft_size-1 + for index in xrange(midn(fft_size)): + if index == midn(fft_size): + window[index] = window[j] = 1.0 + else: + cx = sr1*midn(fft_size) - index + window[index] = window[j] = math.sin(cx)/cx + j -= 1 + return window + +def kaiser(fft_size,beta): + ibeta = 1.0/izero(beta) + inm1 = 1.0/(fft_size) + window = [0 for i in range(fft_size)] + for index in xrange(fft_size): + window[index] = izero(beta*math.sqrt(1.0 - (index * inm1)*(index * inm1))) * ibeta + return window + +# Closure to generate functions to create cos windows + +def coswindow(coeffs): + def closure(fft_size): + window = [0] * fft_size + #print list(enumerate(coeffs)) + for w_index in range(fft_size): + for (c_index, coeff) in enumerate(coeffs): + window[w_index] += (-1)**c_index * coeff * math.cos(2.0*c_index*math.pi*(w_index+0.5)/(fft_size-1)) + return window + return closure + +blackmanharris = coswindow((0.35875,0.48829,0.14128,0.01168)) +nuttall = coswindow((0.3635819,0.4891775,0.1365995,0.0106411)) # Wikipedia calls this Blackman-Nuttall +nuttall_cfd = coswindow((0.355768,0.487396,0.144232,0.012604)) # Wikipedia calls this Nuttall, continuous first deriv +flattop = coswindow((1.0,1.93,1.29,0.388,0.032)) # Flat top window, coeffs from Wikipedia +rectangular = lambda fft_size: [1]*fft_size diff --git a/gnuradio-core/src/tests/CMakeLists.txt b/gnuradio-core/src/tests/CMakeLists.txt new file mode 100644 index 000000000..dbd52f05c --- /dev/null +++ b/gnuradio-core/src/tests/CMakeLists.txt @@ -0,0 +1,72 @@ +# Copyright 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. + +######################################################################## +include(GrMiscUtils) #check n def +GR_CHECK_HDR_N_DEF(sys/resource.h HAVE_SYS_RESOURCE_H) + +######################################################################## +# Setup the include and linker paths +######################################################################## +include_directories( + ${GNURADIO_CORE_INCLUDE_DIRS} + ${GRUEL_INCLUDE_DIRS} + ${Boost_INCLUDE_DIRS} + ${CPPUNIT_INCLUDE_DIRS} +) + +link_directories( + ${Boost_LIBRARY_DIRS} + ${CPPUNIT_LIBRARY_DIRS} +) + +######################################################################## +# Build benchmarks and non-registered tests +######################################################################## +set(tests_not_run #single source per test + benchmark_dotprod_fff.cc + benchmark_dotprod_fsf.cc + benchmark_dotprod_ccf.cc + benchmark_dotprod_fcc.cc + benchmark_dotprod_scc.cc + benchmark_dotprod_ccc.cc + benchmark_nco.cc + benchmark_vco.cc + test_runtime.cc + test_general.cc + test_filter.cc + #test_atsc.cc + test_vmcircbuf.cc +) + +foreach(test_not_run_src ${tests_not_run}) + get_filename_component(name ${test_not_run_src} NAME_WE) + add_executable(${name} ${test_not_run_src}) + target_link_libraries(${name} test-gnuradio-core) +endforeach(test_not_run_src) + +######################################################################## +# Build the test-all test to end all tests +# Set the test environment so the build libs will be found under MSVC. +######################################################################## +include(GrTest) +list(APPEND GR_TEST_TARGET_DEPS test-gnuradio-core) +add_executable(gr_core_test_all test_all.cc) +target_link_libraries(gr_core_test_all test-gnuradio-core) +GR_ADD_TEST(gr-core-test-all gr_core_test_all) diff --git a/gnuradio-core/src/tests/benchmark_dotprod b/gnuradio-core/src/tests/benchmark_dotprod new file mode 100755 index 000000000..82f3b5c3f --- /dev/null +++ b/gnuradio-core/src/tests/benchmark_dotprod @@ -0,0 +1,46 @@ +#!/bin/sh +# +# 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 this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + +DIR=. + +tests=" +benchmark_dotprod_fff +benchmark_dotprod_ccf +benchmark_dotprod_ccc +benchmark_dotprod_fcc +benchmark_dotprod_scc +benchmark_dotprod_fsf +" + +echo "uname -a" +uname -a + +if test -e /proc/cpuinfo +then + cat /proc/cpuinfo +fi + +for t in $tests +do + echo + echo "$t": + $DIR/$t +done diff --git a/gnuradio-core/src/tests/benchmark_dotprod_ccc.cc b/gnuradio-core/src/tests/benchmark_dotprod_ccc.cc new file mode 100644 index 000000000..8ef26a40d --- /dev/null +++ b/gnuradio-core/src/tests/benchmark_dotprod_ccc.cc @@ -0,0 +1,151 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 <stdio.h> +#include <sys/time.h> +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif +#include <unistd.h> +#include <gr_fir_util.h> +#include <gr_fir_ccc.h> +#include <random.h> + +#define TOTAL_TEST_SIZE (40 * 1000 * 1000L) +#define NTAPS 256 +#define BLOCK_SIZE (50 * 1000) /* fits in cache */ + +#if ((TOTAL_TEST_SIZE % BLOCK_SIZE) != 0) +#error "TOTAL_TEST_SIZE % BLOCK_SIZE must equal 0" +#endif + +typedef gr_fir_ccc* (*fir_maker_t)(const std::vector<gr_complex> &taps); +typedef gr_fir_ccc filter_t; + + +static double +timeval_to_double (const struct timeval *tv) +{ + return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6; +} + + +static void +benchmark (fir_maker_t filter_maker, const char *implementation_name) +{ + int i; + gr_complex coeffs[NTAPS]; + //gr_complex input[BLOCK_SIZE + NTAPS]; // not always 16-bit aligned + gr_complex *input = new gr_complex[BLOCK_SIZE + NTAPS]; + long n; + gr_complex result; +#ifdef HAVE_SYS_RESOURCE_H + struct rusage rusage_start; + struct rusage rusage_stop; +#else + double clock_start; + double clock_end; +#endif + + + // setup coefficients and input data + + for (i = 0; i < NTAPS; i++) + coeffs[i] = gr_complex(random() - RANDOM_MAX/2, random() - RANDOM_MAX/2); + + for (i = 0; i < BLOCK_SIZE + NTAPS; i++) + input[i] = gr_complex(random() - RANDOM_MAX/2, random() - RANDOM_MAX/2); + + std::vector<gr_complex> taps (&coeffs[0], &coeffs[NTAPS]); + filter_t *f = filter_maker (taps); + + // get starting CPU usage +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_start) < 0){ + perror ("getrusage"); + exit (1); + } +#else + clock_start= (double) clock() / CLOCKS_PER_SEC; +#endif + // do the actual work + + for (n = 0; n < TOTAL_TEST_SIZE; n += BLOCK_SIZE){ + int j; + for (j = 0; j < BLOCK_SIZE; j++){ + result = f->filter ((gr_complex*)&input[j]); + } + } + + // get ending CPU usage +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_stop) < 0){ + perror ("getrusage"); + exit (1); + } + + // compute results + + double user = + timeval_to_double (&rusage_stop.ru_utime) + - timeval_to_double (&rusage_start.ru_utime); + + double sys = + timeval_to_double (&rusage_stop.ru_stime) + - timeval_to_double (&rusage_start.ru_stime); + + double total = user + sys; +#else + clock_end = (double) clock() / CLOCKS_PER_SEC; + double total = clock_end - clock_start; +#endif + + double macs = NTAPS * (double) TOTAL_TEST_SIZE; + + printf ("%10s: taps: %4d input: %4g cpu: %6.3f taps/sec: %10.4g \n", + implementation_name, NTAPS, (double) TOTAL_TEST_SIZE, total, macs / total); + + delete f; + delete [] input; +} + +static void +do_all () +{ + std::vector<gr_fir_ccc_info> info; + gr_fir_util::get_gr_fir_ccc_info (&info); // get all known CCC implementations + + for (std::vector<gr_fir_ccc_info>::iterator p = info.begin (); + p != info.end () ; + ++p){ + benchmark (p->create, p->name); + } +} + +int +main (int argc, char **argv) +{ + do_all (); + return 0; +} diff --git a/gnuradio-core/src/tests/benchmark_dotprod_ccf.cc b/gnuradio-core/src/tests/benchmark_dotprod_ccf.cc new file mode 100644 index 000000000..ed3c49165 --- /dev/null +++ b/gnuradio-core/src/tests/benchmark_dotprod_ccf.cc @@ -0,0 +1,153 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 <stdio.h> +#include <sys/time.h> +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif +#include <unistd.h> +#include <gr_fir_util.h> +#include <gr_fir_ccf.h> +#include <random.h> + +#define TOTAL_TEST_SIZE (40 * 1000 * 1000L) +#define NTAPS 256 +#define BLOCK_SIZE (50 * 1000) /* fits in cache */ + +#if ((TOTAL_TEST_SIZE % BLOCK_SIZE) != 0) +#error "TOTAL_TEST_SIZE % BLOCK_SIZE must equal 0" +#endif + +typedef gr_fir_ccf* (*fir_maker_t)(const std::vector<float> &taps); +typedef gr_fir_ccf filter_t; + + +static double +timeval_to_double (const struct timeval *tv) +{ + return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6; +} + + +static void +benchmark (fir_maker_t filter_maker, const char *implementation_name) +{ + int i; + float coeffs[NTAPS]; + //gr_complex input[BLOCK_SIZE + NTAPS]; // not always 16-bit aligned + gr_complex *input = new gr_complex[BLOCK_SIZE + NTAPS]; + long n; + gr_complex result; +#ifdef HAVE_SYS_RESOURCE_H + struct rusage rusage_start; + struct rusage rusage_stop; +#else + double clock_start; + double clock_end; +#endif + + // setup coefficients and input data + + for (i = 0; i < NTAPS; i++) + coeffs[i] = random() - RANDOM_MAX/2; + + for (i = 0; i < BLOCK_SIZE + NTAPS; i++) + input[i] = gr_complex(random() - RANDOM_MAX/2, random() - RANDOM_MAX/2); + + std::vector<float> taps (&coeffs[0], &coeffs[NTAPS]); + filter_t *f = filter_maker (taps); + + // get starting CPU usage + +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_start) < 0){ + perror ("getrusage"); + exit (1); + } +#else + clock_start= (double) clock() / CLOCKS_PER_SEC; +#endif + + // do the actual work + + for (n = 0; n < TOTAL_TEST_SIZE; n += BLOCK_SIZE){ + int j; + for (j = 0; j < BLOCK_SIZE; j++){ + result = f->filter (&input[j]); + } + } + + // get ending CPU usage + +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_stop) < 0){ + perror ("getrusage"); + exit (1); + } + + // compute results + + double user = + timeval_to_double (&rusage_stop.ru_utime) + - timeval_to_double (&rusage_start.ru_utime); + + double sys = + timeval_to_double (&rusage_stop.ru_stime) + - timeval_to_double (&rusage_start.ru_stime); + + double total = user + sys; +#else + clock_end= (double) clock() / CLOCKS_PER_SEC; + double total = clock_end - clock_start; +#endif + + double macs = NTAPS * (double) TOTAL_TEST_SIZE; + + printf ("%10s: taps: %4d input: %4g cpu: %6.3f taps/sec: %10.4g \n", + implementation_name, NTAPS, (double) TOTAL_TEST_SIZE, total, macs / total); + + delete f; + delete [] input; +} + +static void +do_all () +{ + std::vector<gr_fir_ccf_info> info; + gr_fir_util::get_gr_fir_ccf_info (&info); // get all known CCF implementations + + for (std::vector<gr_fir_ccf_info>::iterator p = info.begin (); + p != info.end () ; + ++p){ + benchmark (p->create, p->name); + } +} + +int +main (int argc, char **argv) +{ + do_all (); + return 0; +} diff --git a/gnuradio-core/src/tests/benchmark_dotprod_fcc.cc b/gnuradio-core/src/tests/benchmark_dotprod_fcc.cc new file mode 100644 index 000000000..e9eeee43a --- /dev/null +++ b/gnuradio-core/src/tests/benchmark_dotprod_fcc.cc @@ -0,0 +1,152 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 <stdio.h> +#include <sys/time.h> +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif +#include <unistd.h> +#include <gr_fir_util.h> +#include <gr_fir_fcc.h> +#include <random.h> + +#define TOTAL_TEST_SIZE (40 * 1000 * 1000L) +#define NTAPS 256 +#define BLOCK_SIZE (50 * 1000) /* fits in cache */ + +#if ((TOTAL_TEST_SIZE % BLOCK_SIZE) != 0) +#error "TOTAL_TEST_SIZE % BLOCK_SIZE must equal 0" +#endif + +typedef gr_fir_fcc* (*fir_maker_t)(const std::vector<gr_complex> &taps); +typedef gr_fir_fcc filter_t; + + +static double +timeval_to_double (const struct timeval *tv) +{ + return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6; +} + + +static void +benchmark (fir_maker_t filter_maker, const char *implementation_name) +{ + int i; + gr_complex coeffs[NTAPS]; + float input[BLOCK_SIZE + NTAPS]; + long n; + gr_complex result; +#ifdef HAVE_SYS_RESOURCE_H + struct rusage rusage_start; + struct rusage rusage_stop; +#else + double clock_start; + double clock_end; +#endif + + + + // setup coefficients and input data + + for (i = 0; i < NTAPS; i++) + coeffs[i] = gr_complex(random() - RANDOM_MAX/2, random() - RANDOM_MAX/2); + + for (i = 0; i < BLOCK_SIZE + NTAPS; i++) + input[i] = random() - RANDOM_MAX/2; + + std::vector<gr_complex> taps (&coeffs[0], &coeffs[NTAPS]); + filter_t *f = filter_maker (taps); + + // get starting CPU usage +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_start) < 0){ + perror ("getrusage"); + exit (1); + } +#else + clock_start = (double) clock() * (1000000. / CLOCKS_PER_SEC); +#endif + + // do the actual work + + for (n = 0; n < TOTAL_TEST_SIZE; n += BLOCK_SIZE){ + int j; + for (j = 0; j < BLOCK_SIZE; j++){ + result = f->filter (&input[j]); + } + } + + // get ending CPU usage + +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_stop) < 0){ + perror ("getrusage"); + exit (1); + } + + // compute results + + double user = + timeval_to_double (&rusage_stop.ru_utime) + - timeval_to_double (&rusage_start.ru_utime); + + double sys = + timeval_to_double (&rusage_stop.ru_stime) + - timeval_to_double (&rusage_start.ru_stime); + + double total = user + sys; +#else + clock_end= (double) clock() * (1000000. / CLOCKS_PER_SEC); + double total = clock_end - clock_start; +#endif + + double macs = NTAPS * (double) TOTAL_TEST_SIZE; + + printf ("%10s: taps: %4d input: %4g cpu: %6.3f taps/sec: %10.4g \n", + implementation_name, NTAPS, (double) TOTAL_TEST_SIZE, total, macs / total); + + delete f; +} + +static void +do_all () +{ + std::vector<gr_fir_fcc_info> info; + gr_fir_util::get_gr_fir_fcc_info (&info); // get all known FCC implementations + + for (std::vector<gr_fir_fcc_info>::iterator p = info.begin (); + p != info.end () ; + ++p){ + benchmark (p->create, p->name); + } +} + +int +main (int argc, char **argv) +{ + do_all (); + return 0; +} diff --git a/gnuradio-core/src/tests/benchmark_dotprod_fff.cc b/gnuradio-core/src/tests/benchmark_dotprod_fff.cc new file mode 100644 index 000000000..56e064506 --- /dev/null +++ b/gnuradio-core/src/tests/benchmark_dotprod_fff.cc @@ -0,0 +1,148 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 <stdio.h> +#include <sys/time.h> +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif + +#include <unistd.h> +#include <gr_fir_util.h> +#include <gr_fir_fff.h> +#include <random.h> + +#define TOTAL_TEST_SIZE (40 * 1000 * 1000L) +#define NTAPS 256 +#define BLOCK_SIZE (50 * 1000) /* fits in cache */ + +#if ((TOTAL_TEST_SIZE % BLOCK_SIZE) != 0) +#error "TOTAL_TEST_SIZE % BLOCK_SIZE must equal 0" +#endif + +typedef gr_fir_fff* (*fir_maker_t)(const std::vector<float> &taps); +typedef gr_fir_fff filter_t; + + +static double +timeval_to_double (const struct timeval *tv) +{ + return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6; +} + + +static void +benchmark (fir_maker_t filter_maker, const char *implementation_name) +{ + int i; + float coeffs[NTAPS]; + float input[BLOCK_SIZE + NTAPS]; + long n; + float result; +#ifdef HAVE_SYS_RESOURCE_H + struct rusage rusage_start; + struct rusage rusage_stop; +#else + double clock_start; + double clock_end; +#endif + // setup coefficients and input data + + for (i = 0; i < NTAPS; i++) + coeffs[i] = random() - RANDOM_MAX/2; + + for (i = 0; i < BLOCK_SIZE + NTAPS; i++) + input[i] = random() - RANDOM_MAX/2; + + std::vector<float> taps (&coeffs[0], &coeffs[NTAPS]); + filter_t *f = filter_maker (taps); + + // get starting CPU usage +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_start) < 0){ + perror ("getrusage"); + exit (1); + } +#else + clock_start = (double) clock() * (1000000. / CLOCKS_PER_SEC); +#endif + // do the actual work + + for (n = 0; n < TOTAL_TEST_SIZE; n += BLOCK_SIZE){ + int j; + for (j = 0; j < BLOCK_SIZE; j++){ + result = f->filter (&input[j]); + } + } + + // get ending CPU usage +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_stop) < 0){ + perror ("getrusage"); + exit (1); + } + + // compute results + + double user = + timeval_to_double (&rusage_stop.ru_utime) + - timeval_to_double (&rusage_start.ru_utime); + + double sys = + timeval_to_double (&rusage_stop.ru_stime) + - timeval_to_double (&rusage_start.ru_stime); + + double total = user + sys; +#else + clock_end = (double) clock () * (1000000. / CLOCKS_PER_SEC); + double total = clock_end -clock_start; +#endif + double macs = NTAPS * (double) TOTAL_TEST_SIZE; + + printf ("%10s: taps: %4d input: %4g cpu: %6.3f taps/sec: %10.4g \n", + implementation_name, NTAPS, (double) TOTAL_TEST_SIZE, total, macs / total); + + delete f; +} + +static void +do_all () +{ + std::vector<gr_fir_fff_info> info; + gr_fir_util::get_gr_fir_fff_info (&info); // get all known FFF implementations + + for (std::vector<gr_fir_fff_info>::iterator p = info.begin (); + p != info.end (); + ++p){ + + benchmark (p->create, p->name); + } +} + +int +main (int argc, char **argv) +{ + do_all (); + return 0; +} diff --git a/gnuradio-core/src/tests/benchmark_dotprod_fsf.cc b/gnuradio-core/src/tests/benchmark_dotprod_fsf.cc new file mode 100644 index 000000000..a254a8eab --- /dev/null +++ b/gnuradio-core/src/tests/benchmark_dotprod_fsf.cc @@ -0,0 +1,151 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 <stdio.h> +#include <sys/time.h> +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif +#include <unistd.h> +#include <gr_fir_util.h> +#include <gr_fir_fsf.h> +#include <random.h> + +#define TOTAL_TEST_SIZE (40 * 1000 * 1000L) +#define NTAPS 256 +#define BLOCK_SIZE (50 * 1000) /* fits in cache */ + +#if ((TOTAL_TEST_SIZE % BLOCK_SIZE) != 0) +#error "TOTAL_TEST_SIZE % BLOCK_SIZE must equal 0" +#endif + +typedef gr_fir_fsf* (*fir_maker_t)(const std::vector<float> &taps); +typedef gr_fir_fsf filter_t; + + +static double +timeval_to_double (const struct timeval *tv) +{ + return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6; +} + + +static void +benchmark (fir_maker_t filter_maker, const char *implementation_name) +{ + int i; + float coeffs[NTAPS]; + float input[BLOCK_SIZE + NTAPS]; + long n; + short result; +#ifdef HAVE_SYS_RESOURCE_H + struct rusage rusage_start; + struct rusage rusage_stop; +#else + double clock_start; + double clock_end; +#endif + + // setup coefficients and input data + + for (i = 0; i < NTAPS; i++) + coeffs[i] = random() - RANDOM_MAX/2; + + for (i = 0; i < BLOCK_SIZE + NTAPS; i++) + input[i] = random() - RANDOM_MAX/2; + + std::vector<float> taps (&coeffs[0], &coeffs[NTAPS]); + filter_t *f = filter_maker (taps); + + // get starting CPU usage +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_start) < 0){ + perror ("getrusage"); + exit (1); + } +#else + clock_start= (double) clock() * (1000000. / CLOCKS_PER_SEC); +#endif + + // do the actual work + + for (n = 0; n < TOTAL_TEST_SIZE; n += BLOCK_SIZE){ + int j; + for (j = 0; j < BLOCK_SIZE; j++){ + result = f->filter (&input[j]); + } + } + + // get ending CPU usage + +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_stop) < 0){ + perror ("getrusage"); + exit (1); + } + + // compute results + + double user = + timeval_to_double (&rusage_stop.ru_utime) + - timeval_to_double (&rusage_start.ru_utime); + + double sys = + timeval_to_double (&rusage_stop.ru_stime) + - timeval_to_double (&rusage_start.ru_stime); + + double total = user + sys; +#else + clock_end= (double) clock() * (1000000. / CLOCKS_PER_SEC); + double total = clock_end - clock_start; +#endif + + double macs = NTAPS * (double) TOTAL_TEST_SIZE; + + printf ("%10s: taps: %4d input: %4g cpu: %6.3f taps/sec: %10.4g \n", + implementation_name, NTAPS, (double) TOTAL_TEST_SIZE, total, macs / total); + + delete f; +} + +static void +do_all () +{ + std::vector<gr_fir_fsf_info> info; + gr_fir_util::get_gr_fir_fsf_info (&info); // get all known FFF implementations + + for (std::vector<gr_fir_fsf_info>::iterator p = info.begin (); + p != info.end (); + ++p){ + + benchmark (p->create, p->name); + } +} + +int +main (int argc, char **argv) +{ + do_all (); + return 0; +} diff --git a/gnuradio-core/src/tests/benchmark_dotprod_scc.cc b/gnuradio-core/src/tests/benchmark_dotprod_scc.cc new file mode 100644 index 000000000..9a65bb4c6 --- /dev/null +++ b/gnuradio-core/src/tests/benchmark_dotprod_scc.cc @@ -0,0 +1,151 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 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 <stdio.h> +#include <sys/time.h> +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif +#include <unistd.h> +#include <gr_fir_util.h> +#include <gr_fir_scc.h> +#include <random.h> + +#define TOTAL_TEST_SIZE (40 * 1000 * 1000L) +#define NTAPS 256 +#define BLOCK_SIZE (50 * 1000) /* fits in cache */ + +#if ((TOTAL_TEST_SIZE % BLOCK_SIZE) != 0) +#error "TOTAL_TEST_SIZE % BLOCK_SIZE must equal 0" +#endif + +typedef gr_fir_scc* (*fir_maker_t)(const std::vector<gr_complex> &taps); +typedef gr_fir_scc filter_t; + + +static double +timeval_to_double (const struct timeval *tv) +{ + return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6; +} + + +static void +benchmark (fir_maker_t filter_maker, const char *implementation_name) +{ + int i; + gr_complex coeffs[NTAPS]; + short input[BLOCK_SIZE + NTAPS]; + long n; + gr_complex result; +#ifdef HAVE_SYS_RESOURCE_H + struct rusage rusage_start; + struct rusage rusage_stop; +#else + double clock_start; + double clock_end; +#endif + + + // setup coefficients and input data + + for (i = 0; i < NTAPS; i++) + coeffs[i] = gr_complex(random() - RANDOM_MAX/2, random() - RANDOM_MAX/2); + + for (i = 0; i < BLOCK_SIZE + NTAPS; i++) + input[i] = random() - RANDOM_MAX/2; + + std::vector<gr_complex> taps (&coeffs[0], &coeffs[NTAPS]); + filter_t *f = filter_maker (taps); + + // get starting CPU usage + +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_start) < 0){ + perror ("getrusage"); + exit (1); + } +#else + clock_start = (double) clock() * (1000000. / CLOCKS_PER_SEC); +#endif + + // do the actual work + + for (n = 0; n < TOTAL_TEST_SIZE; n += BLOCK_SIZE){ + int j; + for (j = 0; j < BLOCK_SIZE; j++){ + result = f->filter (&input[j]); + } + } + + // get ending CPU usage +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_stop) < 0){ + perror ("getrusage"); + exit (1); + } + + // compute results + + double user = + timeval_to_double (&rusage_stop.ru_utime) + - timeval_to_double (&rusage_start.ru_utime); + + double sys = + timeval_to_double (&rusage_stop.ru_stime) + - timeval_to_double (&rusage_start.ru_stime); + + double total = user + sys; +#else + clock_end= (double) clock () * (1000000. / CLOCKS_PER_SEC); + double total = clock_end -clock_start; +#endif + + double macs = NTAPS * (double) TOTAL_TEST_SIZE; + + printf ("%10s: taps: %4d input: %4g cpu: %6.3f taps/sec: %10.4g \n", + implementation_name, NTAPS, (double) TOTAL_TEST_SIZE, total, macs / total); + + delete f; +} + +static void +do_all () +{ + std::vector<gr_fir_scc_info> info; + gr_fir_util::get_gr_fir_scc_info (&info); // get all known SCC implementations + + for (std::vector<gr_fir_scc_info>::iterator p = info.begin (); + p != info.end () ; + ++p){ + benchmark (p->create, p->name); + } +} + +int +main (int argc, char **argv) +{ + do_all (); + return 0; +} diff --git a/gnuradio-core/src/tests/benchmark_nco.cc b/gnuradio-core/src/tests/benchmark_nco.cc new file mode 100644 index 000000000..20d53e410 --- /dev/null +++ b/gnuradio-core/src/tests/benchmark_nco.cc @@ -0,0 +1,220 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include <stdio.h> +#include <sys/time.h> +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif +#include <unistd.h> +#include <gr_nco.h> +#include <gr_fxpt_nco.h> +#include <string.h> + +#define ITERATIONS 20000000 +#define BLOCK_SIZE (10 * 1000) // fits in cache + +#define FREQ 5003.123 + +static double +timeval_to_double (const struct timeval *tv) +{ + return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6; +} + + +static void +benchmark (void test (float *x, float *y), const char *implementation_name) +{ +#ifdef HAVE_SYS_RESOURCE_H + struct rusage rusage_start; + struct rusage rusage_stop; +#else + double clock_start; + double clock_end; +#endif + float output[2*BLOCK_SIZE]; + float *x = &output[0], *y = &output[BLOCK_SIZE]; + + // touch memory + memset(output, 0, 2*BLOCK_SIZE*sizeof(float)); + + // get starting CPU usage +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_start) < 0){ + perror ("getrusage"); + exit (1); + } +#else + clock_start = (double) clock() * (1000000. / CLOCKS_PER_SEC); +#endif + // do the actual work + + test (x, y); + + // get ending CPU usage + +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_stop) < 0){ + perror ("getrusage"); + exit (1); + } + + // compute results + + double user = + timeval_to_double (&rusage_stop.ru_utime) + - timeval_to_double (&rusage_start.ru_utime); + + double sys = + timeval_to_double (&rusage_stop.ru_stime) + - timeval_to_double (&rusage_start.ru_stime); + + double total = user + sys; +#else + clock_end = (double) clock () * (1000000. / CLOCKS_PER_SEC); + double total = clock_end - clock_start; +#endif + + printf ("%18s: cpu: %6.3f steps/sec: %10.3e\n", + implementation_name, total, ITERATIONS / total); +} + +// ---------------------------------------------------------------- +// Don't compare the _vec with other functions since memory store's +// are involved. + +void basic_sincos_vec (float *x, float *y) +{ + gr_nco<float,float> nco; + + nco.set_freq (2 * M_PI / FREQ); + + for (int i = 0; i < ITERATIONS/BLOCK_SIZE; i++){ + for (int j = 0; j < BLOCK_SIZE; j++){ + nco.sincos (&x[2*j+1], &x[2*j]); + nco.step (); + } + } +} + +void native_sincos_vec (float *x, float *y) +{ + gr_nco<float,float> nco; + + nco.set_freq (2 * M_PI / FREQ); + + for (int i = 0; i < ITERATIONS/BLOCK_SIZE; i++){ + nco.sincos ((gr_complex*)x, BLOCK_SIZE); + } +} + +void fxpt_sincos_vec (float *x, float *y) +{ + gr_fxpt_nco nco; + + nco.set_freq (2 * M_PI / FREQ); + + for (int i = 0; i < ITERATIONS/BLOCK_SIZE; i++){ + nco.sincos ((gr_complex*)x, BLOCK_SIZE); + } +} + +// ---------------------------------------------------------------- + +void native_sincos (float *x, float *y) +{ + gr_nco<float,float> nco; + + nco.set_freq (2 * M_PI / FREQ); + + for (int i = 0; i < ITERATIONS; i++){ + nco.sincos (x, y); + nco.step (); + } +} + +void fxpt_sincos (float *x, float *y) +{ + gr_fxpt_nco nco; + + nco.set_freq (2 * M_PI / FREQ); + + for (int i = 0; i < ITERATIONS; i++){ + nco.sincos (x, y); + nco.step (); + } +} + +// ---------------------------------------------------------------- + +void native_sin (float *x, float *y) +{ + gr_nco<float,float> nco; + + nco.set_freq (2 * M_PI / FREQ); + + for (int i = 0; i < ITERATIONS; i++){ + *x = nco.sin (); + nco.step (); + } +} + +void fxpt_sin (float *x, float *y) +{ + gr_fxpt_nco nco; + + nco.set_freq (2 * M_PI / FREQ); + + for (int i = 0; i < ITERATIONS; i++){ + *x = nco.sin (); + nco.step (); + } +} + +// ---------------------------------------------------------------- + +void nop_fct (float *x, float *y) +{ +} + +void nop_loop (float *x, float *y) +{ + for (int i = 0; i < ITERATIONS; i++){ + nop_fct (x, y); + } +} + +int +main (int argc, char **argv) +{ + benchmark (nop_loop, "nop loop"); + benchmark (native_sin, "native sine"); + benchmark (fxpt_sin, "fxpt sine"); + benchmark (native_sincos, "native sin/cos"); + benchmark (fxpt_sincos, "fxpt sin/cos"); + benchmark (basic_sincos_vec, "basic sin/cos vec"); + benchmark (native_sincos_vec, "native sin/cos vec"); + benchmark (fxpt_sincos_vec, "fxpt sin/cos vec"); +} diff --git a/gnuradio-core/src/tests/benchmark_vco.cc b/gnuradio-core/src/tests/benchmark_vco.cc new file mode 100644 index 000000000..3a6ade78c --- /dev/null +++ b/gnuradio-core/src/tests/benchmark_vco.cc @@ -0,0 +1,167 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,2004,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. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include <stdio.h> +#include <sys/time.h> +#ifdef HAVE_SYS_RESOURCE_H +#include <sys/resource.h> +#endif +#include <unistd.h> +#include <gr_vco.h> +#include <gr_fxpt_vco.h> +#include <string.h> + +#define ITERATIONS 5000000 +#define BLOCK_SIZE (10 * 1000) // fits in cache + +#define FREQ 5003.123 +#define K 4.9999999 +#define AMPLITUDE 2.444444444 + + +static double +timeval_to_double (const struct timeval *tv) +{ + return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6; +} + + +static void +benchmark (void test (float *x, const float *y), const char *implementation_name) +{ +#ifdef HAVE_SYS_RESOURCE_H + struct rusage rusage_start; + struct rusage rusage_stop; +#else + double clock_start; + double clock_end; +#endif + float output[BLOCK_SIZE]; + float input[BLOCK_SIZE]; + + // touch memory + memset(output, 0, BLOCK_SIZE*sizeof(float)); + for (int i = 0; i<BLOCK_SIZE; i++) + input[i] = sin(double(i)); + + // get starting CPU usage +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_start) < 0){ + perror ("getrusage"); + exit (1); + } +#else + clock_start = (double) clock() * (1000000. / CLOCKS_PER_SEC); +#endif + // do the actual work + + test (output, input); + + // get ending CPU usage + +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_stop) < 0){ + perror ("getrusage"); + exit (1); + } + + // compute results + + double user = + timeval_to_double (&rusage_stop.ru_utime) + - timeval_to_double (&rusage_start.ru_utime); + + double sys = + timeval_to_double (&rusage_stop.ru_stime) + - timeval_to_double (&rusage_start.ru_stime); + + double total = user + sys; +#else + clock_end = (double) clock () * (1000000. / CLOCKS_PER_SEC); + double total = clock_end - clock_start; +#endif + + printf ("%18s: cpu: %6.3f steps/sec: %10.3e\n", + implementation_name, total, ITERATIONS / total); +} + +// ---------------------------------------------------------------- + +void basic_vco (float *output, const float *input) +{ + double phase = 0; + + for (int j = 0; j < ITERATIONS/BLOCK_SIZE; j++){ + for (int i = 0; i < BLOCK_SIZE; i++){ + output[i] = cos(phase) * AMPLITUDE; + phase += input[i] * K; + + while (phase > 2 * M_PI) + phase -= 2 * M_PI; + + while (phase < -2 * M_PI) + phase += 2 * M_PI; + } + } +} + +void native_vco (float *output, const float *input) +{ + gr_vco<float,float> vco; + + for (int j = 0; j < ITERATIONS/BLOCK_SIZE; j++){ + vco.cos(output, input, BLOCK_SIZE, K, AMPLITUDE); + } + } + +void fxpt_vco (float *output, const float *input) +{ + gr_fxpt_vco vco; + + for (int j = 0; j < ITERATIONS/BLOCK_SIZE; j++){ + vco.cos(output, input, BLOCK_SIZE, K, AMPLITUDE); + } +} + +// ---------------------------------------------------------------- + +void nop_fct (float *x, const float *y) +{ +} + +void nop_loop (float *x, const float *y) +{ + for (int i = 0; i < ITERATIONS; i++){ + nop_fct (x, y); + } +} + +int +main (int argc, char **argv) +{ + benchmark (nop_loop, "nop loop"); + benchmark (basic_vco, "basic vco"); + benchmark (native_vco, "native vco"); + benchmark (fxpt_vco, "fxpt vco"); +} diff --git a/gnuradio-core/src/tests/nco_results b/gnuradio-core/src/tests/nco_results new file mode 100644 index 000000000..5bdf5dd1c --- /dev/null +++ b/gnuradio-core/src/tests/nco_results @@ -0,0 +1,48 @@ +================================================================ +These are on a 1.4 GHz Pentium M using g++ 3.4.1 +================================================================ + +Default compiler options -O2 + + nop loop: cpu: 0.015 steps/sec: 6.668e+08 + native sine: cpu: 0.900 steps/sec: 1.111e+07 + fxpt sine: cpu: 0.281 steps/sec: 3.559e+07 + native sin/cos: cpu: 1.138 steps/sec: 8.789e+06 + fxpt sin/cos: cpu: 0.550 steps/sec: 1.818e+07 + +-O2 -march=pentium-m -fomit-frame-pointer + + nop loop: cpu: 0.015 steps/sec: 6.668e+08 + native sine: cpu: 0.903 steps/sec: 1.108e+07 + fxpt sine: cpu: 0.271 steps/sec: 3.691e+07 + native sin/cos: cpu: 1.092 steps/sec: 9.159e+06 + fxpt sin/cos: cpu: 0.542 steps/sec: 1.845e+07 + +Inlined fxpt::sin & cos +-O2 -march=pentium-m -fomit-frame-pointer + + nop loop: cpu: 0.015 steps/sec: 6.668e+08 + native sine: cpu: 0.904 steps/sec: 1.106e+07 + fxpt sine: cpu: 0.187 steps/sec: 5.348e+07 + native sin/cos: cpu: 1.091 steps/sec: 9.167e+06 + fxpt sin/cos: cpu: 0.373 steps/sec: 2.681e+07 + +================================================================ +These are on a 1.5 GHz Athon MP 1800+ +================================================================ + +Default compiler options: -O2 + + nop loop: cpu: 0.013 steps/sec: 7.693e+08 + native sine: cpu: 0.733 steps/sec: 1.364e+07 + fxpt sine: cpu: 0.210 steps/sec: 4.763e+07 + native sin/cos: cpu: 1.183 steps/sec: 8.454e+06 + fxpt sin/cos: cpu: 0.420 steps/sec: 2.381e+07 + +-O2 -fomit-frame-pointer -march=athlon-mp + + nop loop: cpu: 0.013 steps/sec: 7.693e+08 + native sine: cpu: 0.679 steps/sec: 1.473e+07 + fxpt sine: cpu: 0.200 steps/sec: 5.001e+07 + native sin/cos: cpu: 1.147 steps/sec: 8.720e+06 + fxpt sin/cos: cpu: 0.444 steps/sec: 2.253e+07 diff --git a/gnuradio-core/src/tests/test_all.cc b/gnuradio-core/src/tests/test_all.cc new file mode 100644 index 000000000..8a1423e9e --- /dev/null +++ b/gnuradio-core/src/tests/test_all.cc @@ -0,0 +1,50 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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. + */ + +#include <cppunit/TextTestRunner.h> +#include <cppunit/XmlOutputter.h> + +#include <gr_unittests.h> +#include <qa_runtime.h> +#include <qa_general.h> +#include <qa_filter.h> +// #include <qa_atsc.h> + +// FIXME add atsc back in. + +int +main (int argc, char **argv) +{ + CppUnit::TextTestRunner runner; + std::ofstream xmlfile(get_unittest_path("gnuradio_core_all.xml").c_str()); + CppUnit::XmlOutputter *xmlout = new CppUnit::XmlOutputter(&runner.result(), xmlfile); + + runner.addTest (qa_runtime::suite ()); + runner.addTest (qa_general::suite ()); + runner.addTest (qa_filter::suite ()); + // runner.addTest (qa_atsc::suite ()); + runner.setOutputter(xmlout); + + bool was_successful = runner.run ("", false); + + return was_successful ? 0 : 1; +} diff --git a/gnuradio-core/src/tests/test_atsc.cc b/gnuradio-core/src/tests/test_atsc.cc new file mode 100644 index 000000000..d99bccce5 --- /dev/null +++ b/gnuradio-core/src/tests/test_atsc.cc @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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 <cppunit/TextTestRunner.h> +#include <cppunit/XmlOutputter.h> + +#include <gr_unittests.h> +#include <qa_atsc.h> + +int +main (int argc, char **argv) +{ + CppUnit::TextTestRunner runner; + std::ofstream xmlfile(get_unittest_path("gnuradio_core_atsc.xml").c_str()); + CppUnit::XmlOutputter *xmlout = new CppUnit::XmlOutputter(&runner.result(), xmlfile); + + runner.addTest (qa_atsc::suite ()); + runner.setOutputter(xmlout); + + bool was_successful = runner.run ("", false); + + return was_successful ? 0 : 1; +} diff --git a/gnuradio-core/src/tests/test_buffers.py b/gnuradio-core/src/tests/test_buffers.py new file mode 100755 index 000000000..b867c727c --- /dev/null +++ b/gnuradio-core/src/tests/test_buffers.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr, gru +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +import time +import sys + +# Test script to test setting up the buffers using gr_test +# For very large buffers it will fail when you hit the circbuf memory limit. +# On linux this limit is shmmax, it will fail when it tries to create a buffer > shmmax. +# With a 2.6 or later kernel you can set the shmmax limit manually in a root console +#show current shmmax limit +#$ cat /proc/sys/kernel/shmmax +#33554432 + +#set shmmax limit manually to 300MB +#echo 300000000 >/proc/sys/kernel/shmmax + +#show new shmmax limit +#$ cat /proc/sys/kernel/shmmax +#300000000 + +class my_graph(gr.top_block): + + def __init__(self, seconds,history,output_multiple): + gr.top_block.__init__(self) + + parser = OptionParser(option_class=eng_option) + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-r", "--sample-rate", type="eng_float", default=48000, + help="set sample rate to RATE (48000)") + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + sample_rate = int(options.sample_rate) + ampl = 0.1 + + src0 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 350, ampl) + + nsamples=int(sample_rate * seconds) #1 seconds + # gr.test (const std::string &name=std::string("gr_test"), + # int min_inputs=1, int max_inputs=1, unsigned int sizeof_input_item=1, + # int min_outputs=1, int max_outputs=1, unsigned int sizeof_output_item=1, + # unsigned int history=1,unsigned int output_multiple=1,double relative_rate=1.0, + # bool fixed_rate=true,gr_consume_type_t cons_type=CONSUME_NOUTPUT_ITEMS, gr_produce_type_t prod_type=PRODUCE_NOUTPUT_ITEMS); + name="gr_test" + min_inputs=1 + max_inputs=1 + sizeof_input_item=gr.sizeof_float + min_outputs=1 + max_outputs=1 + sizeof_output_item=gr.sizeof_float + #history=1 # problems start at 8150 + #output_multiple=1 #problems start at 8000 in combination with large history + relative_rate=1.0 + fixed_rate=True + consume_type=gr.CONSUME_NOUTPUT_ITEMS + produce_type=gr.PRODUCE_NOUTPUT_ITEMS + test = gr.test(name, min_inputs,max_inputs,sizeof_input_item, + min_outputs,max_outputs,sizeof_output_item, + history,output_multiple,relative_rate, + fixed_rate, consume_type,produce_type) + #test = gr.test("gr_test",1,1,gr.sizeof_float, + # 1,1,gr.sizeof_float, + # 1,1,1.0, + # True, gr.CONSUME_NOUTPUT_ITEMS,gr.PRODUCE_NOUTPUT_ITEMS) + #unsigned int history=1,unsigned int output_multiple=1,double relative_rate=1.0, + #bool fixed_rate=false + dst = audio.sink (sample_rate, options.audio_output) + head= gr.head(gr.sizeof_float, nsamples) + + self.connect (src0,test,head,(dst, 0)) + + +if __name__ == '__main__': + + seconds=5.0 + output_multiple=1 + for history in (1,1000,8000,8100,8150,8175,8190,8191,8192,8193,8194,8195,9000,10000,100000,1000000,10000000): #,100000000): + sys.stdout.flush() + sys.stderr.flush() + print 'Test with history=', history, 'output_multiple=',output_multiple + sys.stdout.flush() + sys.stderr.flush() + succeed=True + starttime=time.time() + try: + my_graph(seconds,history,output_multiple).run() + except KeyboardInterrupt: + pass + except: + print "\nAn exception has terminated the graph." + exception=True + succeed=False + sys.stdout.flush() + sys.stderr.flush() + if succeed: + print '' + endtime=time.time() + duration=endtime - starttime + if (duration < 0.5*seconds) and (succeed): + print "A problem has terminated the graph." + succeed=False + if (duration > 1.5*seconds) and (succeed): + print "Something slowed the graph down considerably." + succeed=False + + print 'The test result was:' , succeed + print 'Test duration' , duration + print '' diff --git a/gnuradio-core/src/tests/test_filter.cc b/gnuradio-core/src/tests/test_filter.cc new file mode 100644 index 000000000..8b17034c6 --- /dev/null +++ b/gnuradio-core/src/tests/test_filter.cc @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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. + */ + +#include <cppunit/TextTestRunner.h> +#include <cppunit/XmlOutputter.h> + +#include <gr_unittests.h> +#include <qa_filter.h> + +int +main (int argc, char **argv) +{ + CppUnit::TextTestRunner runner; + std::ofstream xmlfile(get_unittest_path("gnuradio_core_filter.xml").c_str()); + CppUnit::XmlOutputter *xmlout = new CppUnit::XmlOutputter(&runner.result(), xmlfile); + + runner.addTest (qa_filter::suite ()); + runner.setOutputter(xmlout); + + bool was_successful = runner.run ("", false); + + return was_successful ? 0 : 1; +} diff --git a/gnuradio-core/src/tests/test_general.cc b/gnuradio-core/src/tests/test_general.cc new file mode 100644 index 000000000..32fac1b35 --- /dev/null +++ b/gnuradio-core/src/tests/test_general.cc @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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. + */ + +#include <cppunit/TextTestRunner.h> +#include <cppunit/XmlOutputter.h> + +#include <gr_unittests.h> +#include <qa_general.h> + +int +main (int argc, char **argv) +{ + CppUnit::TextTestRunner runner; + std::ofstream xmlfile(get_unittest_path("gnuradio_core_general.xml").c_str()); + CppUnit::XmlOutputter *xmlout = new CppUnit::XmlOutputter(&runner.result(), xmlfile); + + runner.addTest (qa_general::suite ()); + runner.setOutputter(xmlout); + + bool was_successful = runner.run ("", false); + + return was_successful ? 0 : 1; +} diff --git a/gnuradio-core/src/tests/test_runtime.cc b/gnuradio-core/src/tests/test_runtime.cc new file mode 100644 index 000000000..bd5378332 --- /dev/null +++ b/gnuradio-core/src/tests/test_runtime.cc @@ -0,0 +1,42 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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. + */ + +#include <cppunit/TextTestRunner.h> +#include <cppunit/XmlOutputter.h> + +#include <gr_unittests.h> +#include <qa_runtime.h> + +int +main (int argc, char **argv) +{ + CppUnit::TextTestRunner runner; + std::ofstream xmlfile(get_unittest_path("gnuradio_core_runtime.xml").c_str()); + CppUnit::XmlOutputter *xmlout = new CppUnit::XmlOutputter(&runner.result(), xmlfile); + + runner.addTest (qa_runtime::suite ()); + runner.setOutputter(xmlout); + + bool was_successful = runner.run ("", false); + + return was_successful ? 0 : 1; +} diff --git a/gnuradio-core/src/tests/test_vmcircbuf.cc b/gnuradio-core/src/tests/test_vmcircbuf.cc new file mode 100644 index 000000000..ee24b6d62 --- /dev/null +++ b/gnuradio-core/src/tests/test_vmcircbuf.cc @@ -0,0 +1,44 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 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 <gr_vmcircbuf.h> +#include <stdio.h> + +int +main (int argc, char **argv) +{ + int verbose = 1; // summary + + if (argc > 1) + verbose = 2; // extra chatty + + bool ok = gr_vmcircbuf_sysconfig::test_all_factories (verbose); + + if (ok){ + fprintf (stdout, "test_vmcircbuf: OK. We've got at least one workable solution\n"); + return 0; + } + else { + fprintf (stdout, "test_vmcircbuf: NOT OK. We don't have a workable solution\n"); + return 1; + } +} diff --git a/gnuradio-core/src/utils/cic_comp_taps.m b/gnuradio-core/src/utils/cic_comp_taps.m new file mode 100644 index 000000000..9ae5cb167 --- /dev/null +++ b/gnuradio-core/src/utils/cic_comp_taps.m @@ -0,0 +1,45 @@ +# +# 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. +# + +# See Altera Application Note AN455 +# +# R = decimation factor, 8-256 +# Fc = passband (one-sided) cutoff frequency +# L = number of taps + +function taps = cic_comp_taps(R, Fc, L) + M = 1; %% Differential delay + N = 4; %% Number of stages + B = 18; %% Coeffi. Bit-width + Fs = 64e6; %% (High) Sampling freq in Hz before decimation + Fo = R*Fc/Fs; %% Normalized Cutoff freq; 0<Fo<=0.5/M; + p = 2e3; %% Granularity + s = 0.25/p; %% Step size + fp = [0:s:Fo]; %% Pass band frequency samples + fs = (Fo+s):s:0.5; %% Stop band frequency samples + f = [fp fs]*2; %% Normalized frequency samples; 0<=f<=1 + Mp = ones(1,length(fp)); %% Pass band response; Mp(1)=1 + Mp(2:end) = abs( M*R*sin(pi*fp(2:end)/R)./sin(pi*M*fp(2:end))).^N; + Mf = [Mp zeros(1,length(fs))]; + f(end) = 1; + h = fir2(L,f,Mf); %% Filter length L+1 + taps = h/sum(h); %% Floating point coefficients +endfunction diff --git a/gnuradio-core/src/utils/cool.m b/gnuradio-core/src/utils/cool.m new file mode 100644 index 000000000..f8b8a5cea --- /dev/null +++ b/gnuradio-core/src/utils/cool.m @@ -0,0 +1,50 @@ +%% Copyright (C) 1999,2000 Kai Habel +%% +%% This program 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 of the License, or +%% (at your option) any later version. +%% +%% This program 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 this program; if not, write to the Free Software +%% Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301 USA + +%% -*- texinfo -*- +%% @deftypefn {Function File} {} cool (@var{n}) +%% Create color colormap. +%% (cyan to magenta) +%% The argument @var{n} should be a scalar. If it +%% is omitted, the length of the current colormap or 64 is assumed. +%% @end deftypefn +%% @seealso{colormap} + +%% Author: Kai Habel <kai.habel@gmx.de> + +function map = cool (number) + + if (nargin == 0) + number = rows (colormap); + elseif (nargin == 1) + if (! is_scalar (number)) + error ("cool: argument must be a scalar"); + end + else + usage ("cool (number)"); + end + + if (number == 1) + map = [0, 1, 1]; + elseif (number > 1) + r = (0:number - 1)' ./ (number - 1); + g = 1 - r; + b = ones (number, 1); + map = [r, g, b]; + else + map = []; + end + diff --git a/gnuradio-core/src/utils/db_width.m b/gnuradio-core/src/utils/db_width.m new file mode 100644 index 000000000..e9c64cc79 --- /dev/null +++ b/gnuradio-core/src/utils/db_width.m @@ -0,0 +1,35 @@ +% +% Copyright 2001 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. + +%% find the N-dB width of the given filter +%% E.g., to find the 3-dB width, use width = db_width (taps, -3.0) +%% the result is normalized to nyquist == 1 + +function width = db_width (taps, db) + [H,w] = freqz (taps, 1, 4096); + Habs = abs(H); + max_H = max(Habs); + min_H = min(Habs); + threshold = max_H * 10^(db/20); + if (min_H > threshold) + error ("The %g dB point is never reached", db); + end + above = Habs >= threshold; + width = sum(above) / length (above); diff --git a/gnuradio-core/src/utils/filter_tools.m b/gnuradio-core/src/utils/filter_tools.m new file mode 100644 index 000000000..552791e33 --- /dev/null +++ b/gnuradio-core/src/utils/filter_tools.m @@ -0,0 +1,42 @@ +% +% Copyright 2001 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. +% +%% equivalent to the C++ code in VrComplexFIRfilter::buildFilterComplex + +1; + +%% hamming window, nothing fancy + +function taps = build_filter_complex_lp (gain, ntaps) + + taps = gain * (0.54 - 0.46 * cos (2 * pi * (0:ntaps-1)' / (ntaps-1))); + +end + +%% old_taps describes a low pass filter, convert it to bandpass +%% centered at center_freq. center_freq is normalized to Fs (sampling freq) + +function new_taps = freq_shift_filter (old_taps, center_freq) + + ntaps = length(old_taps); + + new_taps = exp (j*2*pi*center_freq*(0:ntaps-1)') .* old_taps; + +end diff --git a/gnuradio-core/src/utils/is_complex.m b/gnuradio-core/src/utils/is_complex.m new file mode 100644 index 000000000..4700467b1 --- /dev/null +++ b/gnuradio-core/src/utils/is_complex.m @@ -0,0 +1,24 @@ +# +# 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. +# + +function p = is_complex (x) + p = any (imag (x) != 0); +endfunction; diff --git a/gnuradio-core/src/utils/lp_to_bp.m b/gnuradio-core/src/utils/lp_to_bp.m new file mode 100644 index 000000000..4e73f6cc7 --- /dev/null +++ b/gnuradio-core/src/utils/lp_to_bp.m @@ -0,0 +1,27 @@ +# +# Copyright 2002 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. +# + +## transform low pass coefficients into bandpass coefficients + +function bp_taps = lp_to_bp (lp_taps, center_freq, sampling_freq) + arg = 2 * pi * center_freq / sampling_freq; + bp_taps = lp_taps .* exp (j*arg*(0:length(lp_taps)-1)'); +endfunction diff --git a/gnuradio-core/src/utils/partition-cascaded-decimating-filters.scm b/gnuradio-core/src/utils/partition-cascaded-decimating-filters.scm new file mode 100644 index 000000000..6ae7877f9 --- /dev/null +++ b/gnuradio-core/src/utils/partition-cascaded-decimating-filters.scm @@ -0,0 +1,67 @@ +;; Estimate the total work (ntaps * sampling rate) for two cascaded +;; decimating low pass filters. +;; +;; The basic assumption is that the number of taps required in any +;; section is inversely proportional to the normalized transition width +;; for that section. +;; +;; FS is the input sampling frequency +;; F1 is the cutoff frequency +;; F2 is the far edge of the transition band +;; DEC1 is the decimation factor for the first filter +;; DEC2 is the decimation factor for the 2nd filter +;; +;; The total decimation factor is DEC1 * DEC2. Therefore, +;; the output rate of the filter is FS / (DEC1 * DEC2) + +(require 'common-list-functions) +(require 'factor) + + + +(define (work2 fs f1 f2 dec1 dec2) + (+ (work1 fs f1 (/ fs (* 2 dec1)) dec1) + (work1 (/ fs dec1) f1 f2 dec2))) + + +;; work for a single section + +(define (work1 fs f1 f2 dec) + (/ (* fs (/ fs (- f2 f1))) dec)) + + +;; return the max integer dec such that fs/(2*dec) >= f2 + +(define (max-dec fs f2) + (inexact->exact (floor (/ fs (* 2 f2))))) + + +;; `adjoin' returns the adjoint of the element OBJ and the list LST. +;; That is, if OBJ is in LST, `adjoin' returns LST, otherwise, it returns +;; `(cons OBJ LST)'. + +(define (adjoin-equal obj lst) + (if (member obj lst) lst (cons obj lst))) + + +;;; not quite right + +(define (permute lst) + (let ((result '())) + (define (aux set head) + (if (null? set) + (set! result (cons head result)) + (for-each (lambda (x) + (aux (set-difference set (list x)) + (cons x head))) + set))) + (aux lst '()) + result)) + +;; `extract-nth' returns the Nth element of LST consed on to the +;; list resulting from splicing out the Nth element of LST. +;; Indexing is 0 based. + +(define (extract-nth n lst) + lst) + diff --git a/gnuradio-core/src/utils/permute.scm b/gnuradio-core/src/utils/permute.scm new file mode 100644 index 000000000..23ddfc999 --- /dev/null +++ b/gnuradio-core/src/utils/permute.scm @@ -0,0 +1,27 @@ +(require 'common-list-functions) + + +(define (permute lst) + (define (aux set head) + (cond ((null? set) head) + (else + (map (lambda (x) + (aux (set-difference set (list x)) + (cons x head))) + set)))) + (aux lst '())) + +(define (permute-2 lst) + (let ((result '())) + (define (aux set head) + (if (null? set) + (set! result (cons head result)) + (for-each (lambda (x) + (aux (set-difference set (list x)) + (cons x head))) + set))) + (aux lst '()) + result)) + + + diff --git a/gnuradio-core/src/utils/plot_cic_decimator_response.m b/gnuradio-core/src/utils/plot_cic_decimator_response.m new file mode 100644 index 000000000..8f06aeafe --- /dev/null +++ b/gnuradio-core/src/utils/plot_cic_decimator_response.m @@ -0,0 +1,44 @@ +# +# 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. +# + +function plot_cic_decimator_response (R, N, M) + ## R = decimation rate + ## N = number of stages (4) + ## M = 1 + gain = (R*M)^N + npoints = 1024; + w = 0:1/npoints:1-1/npoints; + w = w * 1 * pi; + ## w = w * R; + length(w); + num = sin (w*R*M/2); + length (num); + ## H = sin (w*R*M/2) ./ sin (w/2) + denom = sin(w/2); + length (denom); + H = (num ./ denom) .^ N; + H(1) = gain; + H = H ./ gain; + plot (R*w/(2*pi), 10 * log10 (H)); + ## plot (R*w/(2*pi), H); +endfunction + + diff --git a/gnuradio-core/src/utils/plot_freq_response.m b/gnuradio-core/src/utils/plot_freq_response.m new file mode 100644 index 000000000..335c51d62 --- /dev/null +++ b/gnuradio-core/src/utils/plot_freq_response.m @@ -0,0 +1,36 @@ +# +# Copyright 2001 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. +# + +function plot_freq_response (b,...) + if (nargin == 1) + ## Response of an FIR filter + a = 1; + elseif (nargin == 2) + ## response of an IIR filter + a = va_arg (); + endif + + [H,w] = freqz (b,a); + plot (w/(2*pi), abs(H)); + grid; + xlabel ('Normalized Frequency (Fs == 1)'); + ylabel ('Magnitude (linear)'); +endfunction diff --git a/gnuradio-core/src/utils/plot_freq_response_db.m b/gnuradio-core/src/utils/plot_freq_response_db.m new file mode 100644 index 000000000..10ce7d6e1 --- /dev/null +++ b/gnuradio-core/src/utils/plot_freq_response_db.m @@ -0,0 +1,39 @@ +# +# Copyright 2001 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. +# + +function plot_freq_response_db (b,...) + if (nargin == 1) + ## Response of an FIR filter + a = 1; + elseif (nargin == 2) + ## response of an IIR filter + a = va_arg (); + endif + + [H,w] = freqz (b,a); + + grid; + xlabel ('Normalized Frequency (Fs == 1)'); + ylabel ('Magnitude Squared (dB)'); + abs = abs(H); +# plot (w/(2*pi), 20 * log10 (abs/max(abs))); + plot (w/(2*pi), 20 * log10 (abs)); +endfunction diff --git a/gnuradio-core/src/utils/plot_freq_response_phase.m b/gnuradio-core/src/utils/plot_freq_response_phase.m new file mode 100644 index 000000000..591bd5b94 --- /dev/null +++ b/gnuradio-core/src/utils/plot_freq_response_phase.m @@ -0,0 +1,38 @@ +# +# Copyright 2001 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. +# + +function plot_freq_response_db (b,...) + if (nargin == 1) + ## Response of an FIR filter + a = 1; + elseif (nargin == 2) + ## response of an IIR filter + a = va_arg (); + endif + + [H,w] = freqz (b,a); + + grid; + xlabel ('Normalized Frequency (Fs == 1)'); + ylabel ('Phase (radians)'); + abs = abs(H); + plot (w/(2*pi), atan2(imag(H), real(H))) +endfunction diff --git a/gnuradio-core/src/utils/plotfft.m b/gnuradio-core/src/utils/plotfft.m new file mode 100644 index 000000000..20a2efd4c --- /dev/null +++ b/gnuradio-core/src/utils/plotfft.m @@ -0,0 +1,40 @@ +# +# Copyright 2001 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. +# + +function plotfft (data, sample_rate) + + if (nargin == 1) + sample_rate = 1.0; + endif; + + if ((m = nargchk (1,2,nargin))) + usage (m); + endif; + + len = length(data); + s = fft (data.*kaiser(len, 5)); + + incr = sample_rate/len; + min_x = -sample_rate/2; + max_x = sample_rate/2 - incr; + plot (min_x:incr:max_x, abs(fftshift(s))); + +endfunction diff --git a/gnuradio-core/src/utils/plotfftavgk.m b/gnuradio-core/src/utils/plotfftavgk.m new file mode 100644 index 000000000..c82c540f3 --- /dev/null +++ b/gnuradio-core/src/utils/plotfftavgk.m @@ -0,0 +1,61 @@ +# +# Copyright 2002 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. +# + +function plotfftavgk_db (all_data, k, sample_rate) + + if (nargin == 2) + sample_rate = 1.0; + endif; + + if ((m = nargchk (2,3,nargin))) + usage (m); + endif; + + ## len = 1024; + len = 8192; + ##window = ones (len, 1); + window = kaiser (len, 5); + + s = zeros (len,1); + + count = min (100, floor (length (all_data)/len)); + + for i = 0:count-1; + data = all_data((k+i)*len + 1 : (k+i+1)*len); + s = s + abs (fft (data.*window)); + endfor; + + s = s ./ count; + + incr = sample_rate/len; + min_x = -sample_rate/2; + max_x = sample_rate/2 - incr; + + x = min_x:incr:max_x; + ## y = 20 * log10(fftshift(s)); + y = (fftshift(s)); + plot (x, y); + + i = find (y == max(y)) + x(i) + y(i) + +endfunction diff --git a/gnuradio-core/src/utils/plotfftavgk_db.m b/gnuradio-core/src/utils/plotfftavgk_db.m new file mode 100644 index 000000000..73cee140d --- /dev/null +++ b/gnuradio-core/src/utils/plotfftavgk_db.m @@ -0,0 +1,73 @@ +# +# Copyright 2001 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. +# + +function plotfftavgk_db (all_data, k, sample_rate) + + if (nargin == 2) + sample_rate = 1.0; + endif; + + if ((m = nargchk (2,3,nargin))) + usage (m); + endif; + + len = 1024; + ## len = 8192; + ##window = ones (len, 1); + #window = kaiser (len, 5); + window = hanning (len); + + s = zeros (len,1); + + count = min (100, floor (length (all_data)/len)); + + for i = 0:count-1; + data = all_data((k+i)*len + 1 : (k+i+1)*len); + s = s + abs (fft (data.*window)); + endfor; + + s = s ./ count; + + incr = sample_rate/len; + + if is_complex (all_data); + min_x = -sample_rate/2; + max_x = sample_rate/2 - incr; + + x = min_x:incr:max_x; + y = 20 * log10(fftshift(s)); + plot (x, y); + else + min_x = 0 + max_x = sample_rate/2 - incr; + + x = min_x:incr:max_x; + y = 20 * log10(s(1:len/2)); + plot (x, y); + + endif; + + + i = find (y == max(y)) + x(i) + y(i) + +endfunction diff --git a/gnuradio-core/src/utils/plotfftk.m b/gnuradio-core/src/utils/plotfftk.m new file mode 100644 index 000000000..df2bf3aca --- /dev/null +++ b/gnuradio-core/src/utils/plotfftk.m @@ -0,0 +1,41 @@ +# +# Copyright 2001 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. +# + +function plotfftk (all_data, k, sample_rate) + + if (nargin == 2) + sample_rate = 1.0; + endif; + + if ((m = nargchk (2,3,nargin))) + usage (m); + endif; + + len = 1024; + data = all_data(k*len + 1 : (k+1)*len); + s = fft (data.*kaiser(len, 5)); + + incr = sample_rate/len; + min_x = -sample_rate/2; + max_x = sample_rate/2 - incr; + plot (min_x:incr:max_x, abs(fftshift(s))); + +endfunction diff --git a/gnuradio-core/src/utils/plotfftk_db.m b/gnuradio-core/src/utils/plotfftk_db.m new file mode 100644 index 000000000..b2c85412f --- /dev/null +++ b/gnuradio-core/src/utils/plotfftk_db.m @@ -0,0 +1,43 @@ +# +# Copyright 2001 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. +# + +function plotfftk_db (all_data, k, sample_rate) + + if (nargin == 2) + sample_rate = 1.0; + endif; + + if ((m = nargchk (2,3,nargin))) + usage (m); + endif; + + len = 1024; + data = all_data(k*len + 1 : (k+1)*len); + ## s = fft (data.*kaiser(len, 5)); + ## s = fft (data.*hamming(len)); + s = fft (data.*hanning(len)); + + incr = sample_rate/len; + min_x = -sample_rate/2; + max_x = sample_rate/2 - incr; + plot (min_x:incr:max_x, 20 * log10(abs(fftshift(s)))); + +endfunction diff --git a/gnuradio-core/src/utils/put_markers.m b/gnuradio-core/src/utils/put_markers.m new file mode 100644 index 000000000..1244d31aa --- /dev/null +++ b/gnuradio-core/src/utils/put_markers.m @@ -0,0 +1,32 @@ +# +# Copyright 2002 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. +# + +function put_markers (y) + + if (nargin == 0) + y = 25; + endif; + + hold on; + plot (3.06e6, y, '@'); + plot (8.44e6, y, '@'); + +endfunction diff --git a/gnuradio-core/src/utils/rainbow.m b/gnuradio-core/src/utils/rainbow.m new file mode 100644 index 000000000..35fab19b8 --- /dev/null +++ b/gnuradio-core/src/utils/rainbow.m @@ -0,0 +1,53 @@ +## Copyright (C) 1999,2000 Kai Habel +## +## This program 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 of the License, or +## (at your option) any later version. +## +## This program 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 this program; if not, write to the Free Software +## Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301 USA + +## -*- texinfo -*- +## @deftypefn {Function File} {} rainbow (@var{n}) +## Create color colormap. +## (red through yellow, green, cyan,blue,magenta to red) +## The argument @var{n} should be a scalar. If it +## is omitted, the length of the current colormap or 64 is assumed. +## @end deftypefn +## @seealso{colormap} + +## Author: Kai Habel <kai.habel@gmx.de> + +## 2001-09-13 Paul Kienzle <pkienzle@users.sf.net> +## * renamed to rainbow for use with tk_octave +## * remove reference to __current_color_map__ + +function map = rainbow (number) + + if (nargin == 0) + number = length(colormap); + elseif (nargin == 1) + if (! is_scalar (number)) + error ("rainbow: argument must be a scalar"); + endif + else + usage ("rainbow (number)"); + endif + + if (number == 1) + map = [1, 0, 0]; + elseif (number > 1) + h = linspace (0, 1, number)'; + map = hsv2rgb ([h, ones(number, 1), ones(number, 1)]); + else + map = []; + endif + +endfunction diff --git a/gnuradio-core/src/utils/read_char_binary.m b/gnuradio-core/src/utils/read_char_binary.m new file mode 100644 index 000000000..029cea783 --- /dev/null +++ b/gnuradio-core/src/utils/read_char_binary.m @@ -0,0 +1,45 @@ +% +% Copyright 2001 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. +% + +function v = read_char_binary (filename, count) + + %% usage: read_char (filename, [count]) + %% + %% open filename and return the contents, treating them as + %% signed short integers + %% + + m = nargchk (1,2,nargin); + if (m) + usage (m); + end + + if (nargin < 2) + count = Inf; + end + + f = fopen (filename, 'rb'); + if (f < 0) + v = 0; + else + v = fread (f, count, 'char'); + fclose (f); + end diff --git a/gnuradio-core/src/utils/read_complex_binary.m b/gnuradio-core/src/utils/read_complex_binary.m new file mode 100644 index 000000000..eb81f0fa0 --- /dev/null +++ b/gnuradio-core/src/utils/read_complex_binary.m @@ -0,0 +1,48 @@ +% +% Copyright 2001 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. +% + +function v = read_complex_binary (filename, count) + + %% usage: read_complex_binary (filename, [count]) + %% + %% open filename and return the contents as a column vector, + %% treating them as 32 bit complex numbers + %% + + m = nargchk (1,2,nargin); + if (m) + usage (m); + end + + if (nargin < 2) + count = Inf; + end + + f = fopen (filename, 'rb'); + if (f < 0) + v = 0; + else + t = fread (f, [2, count], 'float'); + fclose (f); + v = t(1,:) + t(2,:)*i; + [r, c] = size (v); + v = reshape (v, c, r); + end diff --git a/gnuradio-core/src/utils/read_cshort_binary.m b/gnuradio-core/src/utils/read_cshort_binary.m new file mode 100644 index 000000000..149b6ca88 --- /dev/null +++ b/gnuradio-core/src/utils/read_cshort_binary.m @@ -0,0 +1,46 @@ +% +% Copyright 2001,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. +% + +function cv = read_cshort_binary (filename, count) + + %% usage: read_cshort_binary (filename, [count]) + %% + %% open filename and return the contents, treating them as + %% signed short integers + %% + + m = nargchk (1,2,nargin); + if (m) + usage (m); + end + + if (nargin < 2) + count = Inf; + end + + f = fopen (filename, 'rb'); + if (f < 0) + cv = 0; + else + v = fread (f, count, 'short'); + fclose (f); + cv = v(1:2:end)+v(2:2:end)*j; + end diff --git a/gnuradio-core/src/utils/read_float_binary.m b/gnuradio-core/src/utils/read_float_binary.m new file mode 100644 index 000000000..d27d09b9c --- /dev/null +++ b/gnuradio-core/src/utils/read_float_binary.m @@ -0,0 +1,45 @@ +% +% Copyright 2001 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. +% + +function v = read_float_binary (filename, count) + + %% usage: read_float_binary (filename, [count]) + %% + %% open filename and return the contents, treating them as + %% 32 bit floats + %% + + m = nargchk (1,2,nargin); + if (m) + usage (m); + end + + if (nargin < 2) + count = Inf; + end + + f = fopen (filename, 'rb'); + if (f < 0) + v = 0; + else + v = fread (f, count, 'float'); + fclose (f); + end diff --git a/gnuradio-core/src/utils/read_int_binary.m b/gnuradio-core/src/utils/read_int_binary.m new file mode 100644 index 000000000..cd83bb663 --- /dev/null +++ b/gnuradio-core/src/utils/read_int_binary.m @@ -0,0 +1,46 @@ +% +% Copyright 2001,2002 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. +% + +function v = read_int_binary (filename, count) + + %% usage: read_int_binary (filename, [count]) + %% + %% open filename and return the contents, treating them as + %% signed integers + %% + + m = nargchk (1,2,nargin); + if (m) + usage (m); + end + + if (nargin < 2) + count = Inf; + end + + f = fopen (filename, 'rb'); + if (f < 0) + v = 0; + else + v = fread (f, count, 'int'); + fclose (f); + end +end diff --git a/gnuradio-core/src/utils/read_short_binary.m b/gnuradio-core/src/utils/read_short_binary.m new file mode 100644 index 000000000..7b42f5e2b --- /dev/null +++ b/gnuradio-core/src/utils/read_short_binary.m @@ -0,0 +1,45 @@ +% +% Copyright 2001 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. +% + +function v = read_short_binary (filename, count) + + %% usage: read_short_binary (filename, [count]) + %% + %% open filename and return the contents, treating them as + %% signed short integers + %% + + m = nargchk (1,2,nargin); + if (m) + usage (m); + end + + if (nargin < 2) + count = Inf; + end + + f = fopen (filename, 'rb'); + if (f < 0) + v = 0; + else + v = fread (f, count, 'short'); + fclose (f); + end diff --git a/gnuradio-core/src/utils/read_xambi.m b/gnuradio-core/src/utils/read_xambi.m new file mode 100644 index 000000000..5adb94264 --- /dev/null +++ b/gnuradio-core/src/utils/read_xambi.m @@ -0,0 +1,46 @@ +# +# Copyright 2001,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. +# + +function v = read_xambi (filename) + + ## usage: read_xambi (filename) + ## + ## read binary cross-ambiguity data from radar tools. + ## The file has an 8 float header, the first word of which specifies + ## the number of doppler bins. + ## returns a matrix + + if ((m = nargchk (1,1,nargin))) + usage (m); + endif; + + f = fopen (filename, "rb"); + if (f < 0) + v = 0; + else + header = fread(f, 8, "float"); + ndoppler_bins = header(1) + min_doppler = header(2) + max_doppler = header(3) + v = fread (f, [ndoppler_bins, Inf], "float"); + fclose (f); + endif; +endfunction; diff --git a/gnuradio-core/src/utils/runsum.m b/gnuradio-core/src/utils/runsum.m new file mode 100644 index 000000000..0f530b015 --- /dev/null +++ b/gnuradio-core/src/utils/runsum.m @@ -0,0 +1,9 @@ +function r = runsum(x) + len = length(x); + r = zeros (1, len); + r(1) = x(1); + for i = 2:len; + r(i) = r(i-1) + x(i); + endfor; +endfunction; + diff --git a/gnuradio-core/src/utils/single_pole_iir.m b/gnuradio-core/src/utils/single_pole_iir.m new file mode 100644 index 000000000..12e21f2ac --- /dev/null +++ b/gnuradio-core/src/utils/single_pole_iir.m @@ -0,0 +1,25 @@ +# +# Copyright 2002 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. +# + +function [b, a] = single_pole_iir (alpha) + b = [alpha]; + a = [1, alpha - 1]; +endfunction
\ No newline at end of file diff --git a/gnuradio-core/src/utils/split_vect.m b/gnuradio-core/src/utils/split_vect.m new file mode 100644 index 000000000..aef5c5c38 --- /dev/null +++ b/gnuradio-core/src/utils/split_vect.m @@ -0,0 +1,15 @@ +% split vector into packets + +function y = split_vect(vect,N) + Z = floor(max(size(vect))/N); + y = []; + if(size(vect)(1)>size(vect)(2)) + v = vect'; + else + v = vect; + end + for i=1:Z + y(i,1:N) = v((i-1)*N+1:i*N); + end +end + diff --git a/gnuradio-core/src/utils/write_float_binary.m b/gnuradio-core/src/utils/write_float_binary.m new file mode 100644 index 000000000..79414878b --- /dev/null +++ b/gnuradio-core/src/utils/write_float_binary.m @@ -0,0 +1,40 @@ +# +# Copyright 2001 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. +# + +function v = write_float_binary (data, filename) + + ## usage: write_float_binary (data, filename) + ## + ## open filename and write data to it as 32 bit floats + ## + + if ((m = nargchk (2,2,nargin))) + usage (m); + endif; + + f = fopen (filename, "wb"); + if (f < 0) + v = 0; + else + v = fwrite (f, data, "float"); + fclose (f); + endif; +endfunction; diff --git a/gnuradio-core/src/utils/write_short_binary.m b/gnuradio-core/src/utils/write_short_binary.m new file mode 100644 index 000000000..72b3c408e --- /dev/null +++ b/gnuradio-core/src/utils/write_short_binary.m @@ -0,0 +1,40 @@ +# +# Copyright 2001 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. +# + +function v = write_short_binary (data, filename) + + ## usage: write_short_binary (data, filename) + ## + ## open filename and write data to it as 16 bit shorts + ## + + if ((m = nargchk (2,2,nargin))) + usage (m); + endif; + + f = fopen (filename, "wb"); + if (f < 0) + v = 0; + else + v = fwrite (f, data, "short"); + fclose (f); + endif; +endfunction; |