diff options
Diffstat (limited to 'gnuradio-core/src/lib')
768 files changed, 69006 insertions, 0 deletions
diff --git a/gnuradio-core/src/lib/Makefile.am b/gnuradio-core/src/lib/Makefile.am new file mode 100644 index 0000000000..2b31b3fcef --- /dev/null +++ b/gnuradio-core/src/lib/Makefile.am @@ -0,0 +1,62 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +## Process this file with automake to produce Makefile.in + +# We've got to build . before swig +# FIXME add atsc back +SUBDIRS = missing runtime filter general g72x reed-solomon omnithread io . swig + +# generate libgnuradio-core.la from the convenience libraries in subdirs + +lib_LTLIBRARIES = libgnuradio-core.la libgnuradio-core-qa.la + +libgnuradio_core_la_SOURCES = bug_work_around_6.cc +libgnuradio_core_la_LDFLAGS = $(NO_UNDEFINED) -version-info 0:0:0 + +libgnuradio_core_qa_la_SOURCES = bug_work_around_6.cc +libgnuradio_core_qa_la_LDFLAGS = $(NO_UNDEFINED) -version-info 0:0:0 \ + $(LIBGNURADIO_CORE_EXTRA_LDFLAGS) + +FIXME = \ + atsc/libatsc.la + +libgnuradio_core_la_LIBADD = \ + filter/libfilter.la \ + g72x/libccitt.la \ + general/libgeneral.la \ + io/libio.la \ + missing/libmissing.la \ + omnithread/libomnithread.la \ + reed-solomon/librs.la \ + runtime/libruntime.la \ + $(FFTW3F_LIBS) + +libgnuradio_core_qa_la_LIBADD = \ + filter/libfilter-qa.la \ + general/libgeneral-qa.la \ + runtime/libruntime-qa.la \ + missing/libmissing.la \ + libgnuradio-core.la \ + $(CPPUNIT_LIBS) + 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 0000000000..929c7f81dc --- /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 + +static int gr_bug_work_around_6; 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 0000000000..5aee102f02 --- /dev/null +++ b/gnuradio-core/src/lib/filter/3dnow_float_dotprod_really_simple.S @@ -0,0 +1,95 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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" 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 0000000000..4c4936d315 --- /dev/null +++ b/gnuradio-core/src/lib/filter/3dnow_float_dotprod_simple.S @@ -0,0 +1,102 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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" diff --git a/gnuradio-core/src/lib/filter/Makefile.am b/gnuradio-core/src/lib/filter/Makefile.am new file mode 100644 index 0000000000..01885a8490 --- /dev/null +++ b/gnuradio-core/src/lib/filter/Makefile.am @@ -0,0 +1,306 @@ +# +# Copyright 2001,2002,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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# +# This directory contains mostly filter routines, plus a few +# other performance critical items +# + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(CPPUNIT_INCLUDES) + +noinst_LTLIBRARIES = libfilter.la libfilter-qa.la + +# ---------------------------------------------------------------- +# these scripts generate FIR code +# + +CODE_GENERATOR = \ + generate_all.py \ + generate_gr_fir_XXX.py \ + generate_gr_fir_filter_XXX.py \ + generate_gr_interp_fir_filter_XXX.py \ + generate_gr_rational_resampler_base_XXX.py \ + generate_gr_fir_sysconfig.py \ + generate_gr_fir_sysconfig_generic.py \ + generate_gr_fir_util.py \ + generate_gr_freq_xlating_fir_filter_XXX.py \ + generate_utils.py \ + gr_fir_XXX.cc.t \ + gr_fir_XXX.h.t \ + gr_fir_XXX_generic.cc.t \ + gr_fir_XXX_generic.h.t \ + gr_fir_filter_XXX.cc.t \ + gr_fir_filter_XXX.h.t \ + gr_fir_filter_XXX.i.t \ + gr_interp_fir_filter_XXX.cc.t \ + gr_interp_fir_filter_XXX.h.t \ + gr_interp_fir_filter_XXX.i.t \ + gr_rational_resampler_base_XXX.cc.t \ + gr_rational_resampler_base_XXX.h.t \ + gr_rational_resampler_base_XXX.i.t \ + gr_freq_xlating_fir_filter_XXX.cc.t \ + gr_freq_xlating_fir_filter_XXX.h.t \ + gr_freq_xlating_fir_filter_XXX.i.t + + + +# include $(srcdir)/Makefile.gen +include Makefile.gen + + +$(GENERATED_H) $(GENERATED_I) $(GENERATED_CC): $(CODE_GENERATOR) + PYTHONPATH=$(top_srcdir)/gnuradio-core/src/python srcdir=$(srcdir) $(srcdir)/generate_all.py + + +BUILT_SOURCES = $(GENERATED_H) $(GENERATED_I) $(GENERATED_CC) + + +# ---------------------------------------------------------------- +# MD_CPU and MD_SUBCPU are set at configure time by way of +# gnuradio/config/gr_set_md_cpu.m4. +# It indicates which set of machine dependent code we should be building. +# We currently implement "generic" and "x86" + +# +# <foo>_CODE entry for each set of machine specific speedups +# + +generic_CODE = \ + sysconfig_generic.cc + +generic_qa_CODE = \ + qa_dotprod_generic.cc + +x86_CODE = \ + sysconfig_x86.cc \ + gr_fir_sysconfig_x86.cc \ + gr_cpu.cc \ + gr_fir_ccc_simd.cc \ + gr_fir_ccc_x86.cc \ + gr_fir_fff_simd.cc \ + gr_fir_fff_x86.cc \ + gr_fir_fsf_simd.cc \ + gr_fir_fsf_x86.cc \ + gr_fir_scc_simd.cc \ + gr_fir_scc_x86.cc \ + gr_fir_fcc_simd.cc \ + gr_fir_fcc_x86.cc \ + gr_fir_ccf_simd.cc \ + gr_fir_ccf_x86.cc \ + sse_debug.c + +x86_SUBCODE = \ + float_dotprod_sse.S \ + float_dotprod_3dnow.S \ + complex_dotprod_3dnowext.S \ + complex_dotprod_3dnow.S \ + complex_dotprod_sse.S \ + ccomplex_dotprod_3dnowext.S \ + ccomplex_dotprod_3dnow.S \ + ccomplex_dotprod_sse.S \ + fcomplex_dotprod_3dnow.S \ + fcomplex_dotprod_sse.S \ + short_dotprod_mmx.S \ + cpuid_x86.S + +x86_64_SUBCODE = \ + float_dotprod_sse64.S \ + float_dotprod_3dnow64.S \ + complex_dotprod_3dnowext64.S \ + complex_dotprod_3dnow64.S \ + complex_dotprod_sse64.S \ + ccomplex_dotprod_3dnowext64.S \ + ccomplex_dotprod_3dnow64.S \ + ccomplex_dotprod_sse64.S \ + fcomplex_dotprod_3dnow64.S \ + fcomplex_dotprod_sse64.S \ + short_dotprod_mmx64.S \ + cpuid_x86_64.S + +x86_qa_CODE = \ + qa_dotprod_x86.cc \ + qa_float_dotprod_x86.cc \ + qa_complex_dotprod_x86.cc \ + qa_ccomplex_dotprod_x86.cc + +# +# include each <foo>_CODE entry here... +# +EXTRA_libfilter_la_SOURCES = \ + $(generic_CODE) \ + $(generic_qa_CODE) \ + $(x86_CODE) \ + $(x86_SUBCODE) \ + $(x86_64_SUBCODE) \ + $(x86_qa_CODE) + + +EXTRA_DIST = \ + 3dnow_float_dotprod_really_simple.S \ + 3dnow_float_dotprod_simple.S \ + $(CODE_GENERATOR) + + +# work around automake deficiency +libfilter_la_common_SOURCES = \ + $(GENERATED_CC) \ + gr_adaptive_fir_ccf.cc \ + gr_cma_equalizer_cc.cc \ + gr_fft_filter_ccc.cc \ + gr_fft_filter_fff.cc \ + gr_goertzel_fc.cc \ + gr_filter_delay_fc.cc \ + gr_fractional_interpolator.cc \ + gr_hilbert_fc.cc \ + gr_iir_filter_ffd.cc \ + gr_sincos.c \ + gr_single_pole_iir_filter_ff.cc \ + gr_single_pole_avg_filter_ff.cc \ + gr_single_pole_rec_filter_ff.cc \ + gr_single_zero_avg_filter_ff.cc \ + gr_single_zero_rec_filter_ff.cc \ + gr_single_pole_iir_filter_cc.cc \ + gri_goertzel.cc \ + gri_mmse_fir_interpolator.cc \ + gri_mmse_fir_interpolator_cc.cc \ + complex_dotprod_generic.cc \ + ccomplex_dotprod_generic.cc \ + float_dotprod_generic.c \ + short_dotprod_generic.c + +libfilter_qa_la_common_SOURCES = \ + qa_filter.cc \ + qa_gr_fir_ccf.cc \ + qa_gr_fir_fcc.cc \ + qa_gr_fir_fff.cc \ + qa_gr_fir_ccc.cc \ + qa_gr_fir_scc.cc \ + qa_gri_mmse_fir_interpolator.cc + +if MD_CPU_generic +libfilter_la_SOURCES = $(libfilter_la_common_SOURCES) $(generic_CODE) +libfilter_qa_la_SOURCES = $(libfilter_qa_la_common_SOURCES) $(generic_qa_CODE) +endif + +if MD_CPU_x86 +if MD_SUBCPU_x86_64 +libfilter_la_SOURCES = $(libfilter_la_common_SOURCES) $(x86_64_SUBCODE) $(x86_CODE) +else +libfilter_la_SOURCES = $(libfilter_la_common_SOURCES) $(x86_SUBCODE) $(x86_CODE) +endif + +libfilter_qa_la_SOURCES = $(libfilter_qa_la_common_SOURCES) $(x86_qa_CODE) +endif + + +grinclude_HEADERS = \ + $(GENERATED_H) \ + complex_dotprod_generic.h \ + complex_dotprod_x86.h \ + fcomplex_dotprod_x86.h \ + ccomplex_dotprod_generic.h \ + ccomplex_dotprod_x86.h \ + float_dotprod_generic.h \ + float_dotprod_x86.h \ + gr_adaptive_fir_ccf.h \ + gr_cma_equalizer_cc.h \ + gr_cpu.h \ + gr_fft_filter_ccc.h \ + gr_fft_filter_fff.h \ + gr_filter_delay_fc.h \ + gr_fir_sysconfig_x86.h \ + gr_fractional_interpolator.h \ + gr_goertzel_fc.h \ + gr_hilbert_fc.h \ + gr_iir_filter_ffd.h \ + gr_rotator.h \ + gr_sincos.h \ + gr_single_pole_avg.h \ + gr_single_pole_rec.h \ + gr_single_pole_iir.h \ + gr_single_pole_iir_filter_ff.h \ + gr_single_pole_avg_filter_ff.h \ + gr_single_pole_rec_filter_ff.h \ + gr_single_zero_avg_filter_ff.h \ + gr_single_zero_rec_filter_ff.h \ + gr_single_pole_iir_filter_cc.h \ + gr_single_zero_avg.h \ + gr_single_zero_rec.h \ + gri_goertzel.h \ + gri_iir.h \ + gri_mmse_fir_interpolator.h \ + gri_mmse_fir_interpolator_cc.h \ + qa_filter.h \ + short_dotprod_generic.h \ + short_dotprod_x86.h \ + sse_debug.h + +noinst_HEADERS = \ + assembly.h \ + gr_fir_scc_simd.h \ + gr_fir_scc_x86.h \ + gr_fir_fcc_simd.h \ + gr_fir_fcc_x86.h \ + gr_fir_ccf_simd.h \ + gr_fir_ccf_x86.h \ + gr_fir_ccc_simd.h \ + gr_fir_ccc_x86.h \ + gr_fir_fff_simd.h \ + gr_fir_fff_x86.h \ + gr_fir_fsf_simd.h \ + gr_fir_fsf_x86.h \ + interpolator_taps.h \ + qa_complex_dotprod_x86.h \ + qa_ccomplex_dotprod_x86.h \ + qa_dotprod.h \ + qa_float_dotprod_x86.h \ + qa_gr_fir_ccf.h \ + qa_gr_fir_fcc.h \ + qa_gr_fir_fff.h \ + qa_gr_fir_ccc.h \ + qa_gr_fir_scc.h \ + qa_gri_mmse_fir_interpolator.h + + + +swiginclude_HEADERS = \ + filter.i \ + filter_generated.i \ + gr_adaptive_fir_ccf.i \ + gr_cma_equalizer_cc.i \ + gr_fft_filter_ccc.i \ + gr_fft_filter_fff.i \ + gr_filter_delay_fc.i \ + gr_goertzel_fc.i \ + gr_hilbert_fc.i \ + gr_iir_filter_ffd.i \ + gr_single_pole_iir_filter_ff.i \ + gr_single_pole_avg_filter_ff.i \ + gr_single_pole_rec_filter_ff.i \ + gr_single_zero_avg_filter_ff.i \ + gr_single_zero_rec_filter_ff.i \ + gr_single_pole_iir_filter_cc.i \ + $(GENERATED_I) + + +CLEANFILES = $(BUILT_SOURCES) *.pyc diff --git a/gnuradio-core/src/lib/filter/Makefile.gen b/gnuradio-core/src/lib/filter/Makefile.gen new file mode 100644 index 0000000000..6809274fa9 --- /dev/null +++ b/gnuradio-core/src/lib/filter/Makefile.gen @@ -0,0 +1,111 @@ +# +# 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 + +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 + diff --git a/gnuradio-core/src/lib/filter/README b/gnuradio-core/src/lib/filter/README new file mode 100644 index 0000000000..00730f8338 --- /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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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 0000000000..9398a0a1e8 --- /dev/null +++ b/gnuradio-core/src/lib/filter/assembly.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _ASSEMBLY_H_ +#define _ASSEMBLY_H_ + + + +#ifndef __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 0000000000..79826e8a3c --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow.S @@ -0,0 +1,216 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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" + 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 0000000000..bff045e113 --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow64.S @@ -0,0 +1,213 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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" + 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 0000000000..39057e46ed --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext.S @@ -0,0 +1,191 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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" + 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 0000000000..c6f907c9ba --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext64.S @@ -0,0 +1,188 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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" + 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 0000000000..edd5b1b096 --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_generic.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_complex.h> +#include "gr_fir_ccc_simd.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 0000000000..70d3b6bda4 --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_generic.h @@ -0,0 +1,32 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _CCOMPLEX_DOTPROD_GENERIC_H_ +#define _CCOMPLEX_DOTPROD_GENERIC_H_ + +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 0000000000..a16d053537 --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse.S @@ -0,0 +1,194 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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" 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 0000000000..216df6e526 --- /dev/null +++ b/gnuradio-core/src/lib/filter/ccomplex_dotprod_sse64.S @@ -0,0 +1,191 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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" 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 0000000000..0a8c73633f --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..37608ece1b --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_3dnow.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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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" + 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 0000000000..1413c6ceba --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_3dnow64.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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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" + 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 0000000000..443949ed2e --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext.S @@ -0,0 +1,167 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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" + 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 0000000000..195dc37761 --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_3dnowext64.S @@ -0,0 +1,164 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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" + 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 0000000000..300f4700f1 --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_generic.cc @@ -0,0 +1,55 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_complex.h> +#include "gr_fir_scc_simd.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 0000000000..44a4ea55f1 --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_generic.h @@ -0,0 +1,32 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _COMPLEX_DOTPROD_GENERIC_H_ +#define _COMPLEX_DOTPROD_GENERIC_H_ + +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 0000000000..acafb1a31f --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_sse.S @@ -0,0 +1,202 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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 .cleanup # 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. + +.cleanup: # 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" 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 0000000000..0fb95db003 --- /dev/null +++ b/gnuradio-core/src/lib/filter/complex_dotprod_sse64.S @@ -0,0 +1,198 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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 .cleanup # 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. + +.cleanup: # 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" 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 0000000000..86ac0e7819 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/cpuid_x86.S b/gnuradio-core/src/lib/filter/cpuid_x86.S new file mode 100644 index 0000000000..3152b91d75 --- /dev/null +++ b/gnuradio-core/src/lib/filter/cpuid_x86.S @@ -0,0 +1,56 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# +# execute CPUID instruction, return EAX, EBX, ECX and EDX values in result +# +# void cpuid_x86 (unsigned int op, unsigned int result[4]); +# + +#include "assembly.h" + +.file "cpuid_x86.S" + .version "01.01" +.text +.globl GLOB_SYMB(cpuid_x86) + DEF_FUNC_HEAD(cpuid_x86) +GLOB_SYMB(cpuid_x86): + pushl %ebp + movl %esp, %ebp + pushl %ebx # must save in PIC mode, holds GOT pointer + pushl %esi + + movl 8(%ebp), %eax # op + movl 12(%ebp), %esi # result + cpuid + movl %eax, 0(%esi) + movl %ebx, 4(%esi) + movl %ecx, 8(%esi) + movl %edx, 12(%esi) + + popl %esi + popl %ebx + popl %ebp + ret + +FUNC_TAIL(cpuid_x86) + .ident "Hand coded cpuid assembly" + diff --git a/gnuradio-core/src/lib/filter/cpuid_x86_64.S b/gnuradio-core/src/lib/filter/cpuid_x86_64.S new file mode 100644 index 0000000000..98137db183 --- /dev/null +++ b/gnuradio-core/src/lib/filter/cpuid_x86_64.S @@ -0,0 +1,50 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# +# execute CPUID instruction, return EAX, EBX, ECX and EDX values in result +# +# void cpuid_x86 (unsigned int op, unsigned int result[4]); +# + +#include "assembly.h" + +.file "cpuid_x86_64.S" + .version "01.01" +.text +.globl GLOB_SYMB(cpuid_x86) + DEF_FUNC_HEAD(cpuid_x86) +GLOB_SYMB(cpuid_x86): + mov %rbx, %r11 # must save in PIC mode, holds GOT pointer + + mov %rdi, %rax # op + cpuid + movl %eax, 0(%rsi) # result + movl %ebx, 4(%rsi) + movl %ecx, 8(%rsi) + movl %edx, 12(%rsi) + + mov %r11, %rbx + retq + +FUNC_TAIL(cpuid_x86) + .ident "Hand coded cpuid64 assembly" + 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 0000000000..20dc5b2d56 --- /dev/null +++ b/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow.S @@ -0,0 +1,172 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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" 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 0000000000..32772bf433 --- /dev/null +++ b/gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow64.S @@ -0,0 +1,166 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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" 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 0000000000..2d8b4ccb30 --- /dev/null +++ b/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse.S @@ -0,0 +1,184 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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 .cleanup # 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. + +.cleanup: # 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" 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 0000000000..cba035795d --- /dev/null +++ b/gnuradio-core/src/lib/filter/fcomplex_dotprod_sse64.S @@ -0,0 +1,179 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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 .cleanup # 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. + +.cleanup: # 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" 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 0000000000..d9f7eaca22 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..2d434699e3 --- /dev/null +++ b/gnuradio-core/src/lib/filter/filter.i @@ -0,0 +1,45 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_goertzel_fc.h> +#include <gr_cma_equalizer_cc.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_goertzel_fc.i" +%include "gr_cma_equalizer_cc.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 0000000000..784fa0b55c --- /dev/null +++ b/gnuradio-core/src/lib/filter/float_dotprod_3dnow.S @@ -0,0 +1,148 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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" 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 0000000000..0f6a948067 --- /dev/null +++ b/gnuradio-core/src/lib/filter/float_dotprod_3dnow64.S @@ -0,0 +1,145 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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" 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 0000000000..21912afd2d --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..4f4d4ebf36 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..0e59f5e3bf --- /dev/null +++ b/gnuradio-core/src/lib/filter/float_dotprod_sse.S @@ -0,0 +1,167 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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 .cleanup # 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... + +.cleanup: # 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" 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 0000000000..c7f821a3df --- /dev/null +++ b/gnuradio-core/src/lib/filter/float_dotprod_sse64.S @@ -0,0 +1,161 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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 .cleanup # 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... + +.cleanup: # 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" 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 0000000000..7a101920c8 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/generate_all.py b/gnuradio-core/src/lib/filter/generate_all.py new file mode 100755 index 0000000000..dcbe75df08 --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_all.py @@ -0,0 +1,46 @@ +#!/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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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 + +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() + 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 0000000000..e55ff85400 --- /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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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 0000000000..e3c0ec7a00 --- /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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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 0000000000..3c78daa2d4 --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_gr_fir_sysconfig.py @@ -0,0 +1,127 @@ +#!/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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from generate_utils import * + + +# ---------------------------------------------------------------- + +def make_gr_fir_sysconfig_h (): + out = open_and_log_name ('gr_fir_sysconfig.h', 'w') + 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') + 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 0000000000..78cf3773cb --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_gr_fir_sysconfig_generic.py @@ -0,0 +1,182 @@ +#!/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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from generate_utils import * + + +# ---------------------------------------------------------------- + +def make_gr_fir_sysconfig_generic_h (): + out = open_and_log_name ('gr_fir_sysconfig_generic.h', 'w') + 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') + 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 0000000000..80d91863bb --- /dev/null +++ b/gnuradio-core/src/lib/filter/generate_gr_fir_util.py @@ -0,0 +1,185 @@ +#!/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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from generate_utils import * + +def make_info_struct (out, sig): + out.write ( +''' +struct 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') + 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_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_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') + 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 0000000000..4a34556fd1 --- /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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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 0000000000..00b3c7889b --- /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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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 0000000000..0f96451a38 --- /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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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_utils.py b/gnuradio-core/src/lib/filter/generate_utils.py new file mode 100644 index 0000000000..2eeb38e779 --- /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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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_ccf.cc b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccf.cc new file mode 100644 index 0000000000..f2ab319bf2 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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(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 0000000000..57a95a3339 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_adaptive_fir_ccf.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_ADAPTIVE_FIR_CCF_H +#define INCLUDED_GR_ADAPTIVE_FIR_CCF_H + +#include <gr_sync_decimator.h> + +/*! + * \brief Adaptive FIR filter with gr_complex input, gr_complex output and float taps + * \ingroup filter + */ +class 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; + +public: + gr_adaptive_fir_ccf(char *name, int decimation, const std::vector<float> &taps); + 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 0000000000..896fb42c7b --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +class gr_adaptive_fir_ccf : public gr_sync_decimator +{ +private: + 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_cma_equalizer_cc.cc b/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.cc new file mode 100644 index 0000000000..29b8a3e40d --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_cma_equalizer_cc.h> + +gr_cma_equalizer_cc_sptr +gr_make_cma_equalizer_cc(int num_taps, float modulus, float mu) +{ + return gr_cma_equalizer_cc_sptr(new gr_cma_equalizer_cc(num_taps, modulus, mu)); +} + +gr_cma_equalizer_cc::gr_cma_equalizer_cc(int num_taps, float modulus, float mu) + : gr_adaptive_fir_ccf("cma_equalizer_cc", 1, std::vector<float>(num_taps)), + d_modulus(modulus), d_mu(mu) +{ + d_taps[0] = 1.0; +} + diff --git a/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.h b/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.h new file mode 100644 index 0000000000..25c996893d --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.h @@ -0,0 +1,62 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_CMA_EQUALIZER_CC_H +#define INCLUDED_GR_CMA_EQUALIZER_CC_H + +#include <gr_adaptive_fir_ccf.h> + +class gr_cma_equalizer_cc; +typedef boost::shared_ptr<gr_cma_equalizer_cc> gr_cma_equalizer_cc_sptr; + +gr_cma_equalizer_cc_sptr +gr_make_cma_equalizer_cc(int num_taps, float modulus, float mu); + +/*! + * \brief Implements constant modulus adaptive filter on complex stream + * \ingroup filter + */ +class gr_cma_equalizer_cc : public gr_adaptive_fir_ccf +{ +private: + float d_modulus; + float d_mu; + + friend gr_cma_equalizer_cc_sptr gr_make_cma_equalizer_cc(int num_taps, float modulus, float mu); + gr_cma_equalizer_cc(int num_taps, float modulus, float mu); + +protected: + + virtual float error(const gr_complex &out) + { + return (d_modulus - norm(out)); + } + + virtual void update_tap(float &tap, const gr_complex &in) + { + tap += d_mu*d_error*abs(in); + } + +public: +}; + +#endif diff --git a/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.i b/gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.i new file mode 100644 index 0000000000..c64bfc3a09 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_cma_equalizer_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,cma_equalizer_cc) + +%include <gr_adaptive_fir_ccf.i> + +gr_cma_equalizer_cc_sptr gr_make_cma_equalizer_cc(int num_taps, float modulus, float mu); + +class gr_cma_equalizer_cc : public gr_adaptive_fir_ccf +{ +private: + gr_cma_equalizer_cc(int num_taps, float modulus, float mu); + +public: +}; diff --git a/gnuradio-core/src/lib/filter/gr_cpu.cc b/gnuradio-core/src/lib/filter/gr_cpu.cc new file mode 100644 index 0000000000..7e926f34a9 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_cpu.cc @@ -0,0 +1,107 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <gr_cpu.h> + +/* + * execute CPUID instruction, return EAX, EBX, ECX and EDX values in result + */ +extern "C" { +void cpuid_x86 (unsigned int op, unsigned int result[4]); +}; + +/* + * CPUID functions returning a single datum + */ + +static inline unsigned int cpuid_eax(unsigned int op) +{ + unsigned int regs[4]; + cpuid_x86 (op, regs); + return regs[0]; +} + +static inline unsigned int cpuid_ebx(unsigned int op) +{ + unsigned int regs[4]; + cpuid_x86 (op, regs); + return regs[1]; +} + +static inline unsigned int cpuid_ecx(unsigned int op) +{ + unsigned int regs[4]; + cpuid_x86 (op, regs); + return regs[2]; +} + +static inline unsigned int cpuid_edx(unsigned int op) +{ + unsigned int regs[4]; + 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; +} 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 0000000000..563b60cb17 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_cpu.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GR_CPU_H_ +#define _GR_CPU_H_ + +struct gr_cpu { + static bool has_mmx (); + static bool has_sse (); + static bool has_sse2 (); + static bool has_3dnow (); + static bool has_3dnowext (); +}; + +#endif /* _GR_CPU_H_ */ 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 0000000000..c90e3a0f42 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.cc @@ -0,0 +1,210 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 <gr_io_signature.h> +#include <gri_fft.h> +#include <math.h> +#include <assert.h> +#include <stdexcept> +#include <gr_firdes.h> + +#include <iostream> + +gr_fft_filter_ccc_sptr gr_make_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps) +{ + return gr_fft_filter_ccc_sptr (new gr_fft_filter_ccc (decimation, taps)); +} + + +gr_fft_filter_ccc::gr_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps) + : 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_fftsize(-1), d_fwdfft(0), d_invfft(0), d_updated(false) +{ + // if (decimation != 1) + // throw std::invalid_argument("gr_fft_filter_ccc: decimation must be 1"); + + set_history(1); + actual_set_taps(taps); +} + +gr_fft_filter_ccc::~gr_fft_filter_ccc () +{ + delete d_fwdfft; + delete d_invfft; +} + +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"; +} + +void +gr_fft_filter_ccc::set_taps (const std::vector<gr_complex> &taps) +{ + d_new_taps = taps; + d_updated = true; +} + +/* + * determines d_ntaps, d_nsamples, d_fftsize, d_xformed_taps + */ +void +gr_fft_filter_ccc::actual_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]; + + //print_vector_complex("transformed taps:", d_xformed_taps); +} + +// determine and set d_ntaps, d_nsamples, d_fftsize + +void +gr_fft_filter_ccc::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, "gr_fft_filter: 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); + d_xformed_taps.resize(d_fftsize); + } + + set_output_multiple(d_nsamples); +} + +int +gr_fft_filter_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){ + actual_set_taps(d_new_taps); + d_updated = false; + return 0; // output multiple may have changed + } + + assert(noutput_items % d_nsamples == 0); + + int dec_ctr = 0; + int j = 0; + int ninput_items = noutput_items * decimation(); + + for (int i = 0; i < ninput_items; i += d_nsamples){ + + memcpy(d_fwdfft->get_inbuf(), &in[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[0]; + gr_complex *c = d_invfft->get_inbuf(); + + for (j = 0; j < d_fftsize; j++) // filter in the freq domain + c[j] = a[j] * 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(gr_complex)); + //out += d_nsamples; + + j = dec_ctr; + while (j < d_nsamples) { + *out++ = d_invfft->get_outbuf()[j]; + j += decimation(); + } + dec_ctr = (j - d_nsamples); + + // stash the tail + memcpy(&d_tail[0], d_invfft->get_outbuf() + d_nsamples, + tailsize() * sizeof(gr_complex)); + } + + assert((out - (gr_complex *) output_items[0]) == noutput_items); + assert(dec_ctr == 0); + + 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 0000000000..06bc7c1b94 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.h @@ -0,0 +1,77 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_FFT_FILTER_CCC_H +#define INCLUDED_GR_FFT_FILTER_CCC_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_fft_filter_ccc_sptr gr_make_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps); + +class gr_fir_ccc; +class gri_fft_complex; + +/*! + * \brief Fast FFT filter with gr_complex input, gr_complex output and gr_complex taps + * \ingroup filter + */ +class gr_fft_filter_ccc : public gr_sync_decimator +{ + private: + friend gr_fft_filter_ccc_sptr gr_make_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps); + + int d_ntaps; + int d_nsamples; + int d_fftsize; // fftsize = ntaps + nsamples - 1 + 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 + std::vector<gr_complex> d_xformed_taps; // Fourier xformed taps + std::vector<gr_complex> d_new_taps; + bool d_updated; + + /*! + * Construct a FFT filter with the given taps + * + * \param decimation >= 1 + * \param taps complex filter taps + */ + gr_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps); + + void compute_sizes(int ntaps); + int tailsize() const { return d_ntaps - 1; } + void actual_set_taps (const std::vector<gr_complex> &taps); + + public: + ~gr_fft_filter_ccc (); + + 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 /* 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 0000000000..65cbb3627a --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.i @@ -0,0 +1,39 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 + ) 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); + + public: + ~gr_fft_filter_ccc (); + + void set_taps (const std::vector<gr_complex> &taps); +}; 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 0000000000..ceb2e8284b --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.cc @@ -0,0 +1,211 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_fft_filter_fff.h> +#include <gr_io_signature.h> +#include <gri_fft.h> +#include <math.h> +#include <assert.h> +#include <stdexcept> +#include <gr_firdes.h> + +#include <iostream> + +gr_fft_filter_fff_sptr gr_make_fft_filter_fff (int decimation, const std::vector<float> &taps) +{ + return gr_fft_filter_fff_sptr (new gr_fft_filter_fff (decimation, taps)); +} + + +gr_fft_filter_fff::gr_fft_filter_fff (int decimation, const std::vector<float> &taps) + : gr_sync_decimator ("fft_filter_fff", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (float)), + decimation), + d_fftsize(-1), d_fwdfft(0), d_invfft(0), d_updated(false) +{ + set_history(1); + actual_set_taps(taps); +} + +gr_fft_filter_fff::~gr_fft_filter_fff () +{ + delete d_fwdfft; + delete d_invfft; +} + +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"; +} + +static void +print_vector_float(const std::string label, const std::vector<float> &x) +{ + std::cout << label; + for (unsigned i = 0; i < x.size(); i++) + std::cout << x[i] << " "; + std::cout << "\n"; +} + +void +gr_fft_filter_fff::set_taps (const std::vector<float> &taps) +{ + d_new_taps = taps; + d_updated = true; +} + +/* + * determines d_ntaps, d_nsamples, d_fftsize, d_xformed_taps + */ +void +gr_fft_filter_fff::actual_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]; + + //print_vector_complex("transformed taps:", d_xformed_taps); +} + +// determine and set d_ntaps, d_nsamples, d_fftsize + +void +gr_fft_filter_fff::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, "gr_fft_filter: 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); + } + + set_output_multiple(d_nsamples); +} + +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){ + actual_set_taps(d_new_taps); + d_updated = false; + return 0; // output multiple may have changed + } + + assert(noutput_items % d_nsamples == 0); + + int dec_ctr = 0; + int j = 0; + int ninput_items = noutput_items * decimation(); + + for (int i = 0; i < ninput_items; i += d_nsamples){ + + memcpy(d_fwdfft->get_inbuf(), &in[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[0]; + gr_complex *c = d_invfft->get_inbuf(); + + for (j = 0; j < d_fftsize/2+1; j++) // filter in the freq domain + c[j] = a[j] * 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) { + *out++ = d_invfft->get_outbuf()[j]; + j += decimation(); + } + dec_ctr = (j - d_nsamples); + + // stash the tail + memcpy(&d_tail[0], d_invfft->get_outbuf() + d_nsamples, + tailsize() * sizeof(float)); + } + + assert((out - (float *) output_items[0]) == noutput_items); + assert(dec_ctr == 0); + + 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 0000000000..bdd29b7030 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.h @@ -0,0 +1,76 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_FFT_FILTER_FFF_H +#define INCLUDED_GR_FFT_FILTER_FFF_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_fft_filter_fff_sptr gr_make_fft_filter_fff (int decimation, const std::vector<float> &taps); + +class gr_fir_fff; +class gri_fft_real_fwd; +class gri_fft_real_rev; + +/*! + * \brief Fast FFT filter with float input, float output and float taps + * \ingroup filter + */ +class gr_fft_filter_fff : public gr_sync_decimator +{ + private: + friend gr_fft_filter_fff_sptr gr_make_fft_filter_fff (int decimation, const std::vector<float> &taps); + + int d_ntaps; + int d_nsamples; + int d_fftsize; // fftsize = ntaps + nsamples - 1 + 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 + std::vector<float> d_new_taps; + bool d_updated; + + /*! + * Construct a FFT filter with the given taps + * + * \param decimation >= 1 + * \param taps float filter taps + */ + gr_fft_filter_fff (int decimation, const std::vector<float> &taps); + + void compute_sizes(int ntaps); + int tailsize() const { return d_ntaps - 1; } + void actual_set_taps (const std::vector<float> &taps); + + public: + ~gr_fft_filter_fff (); + + 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 /* 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 0000000000..5ee30ebbb3 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.i @@ -0,0 +1,39 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 + ) 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); + + public: + ~gr_fft_filter_fff (); + + void set_taps (const std::vector<float> &taps); +}; 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 0000000000..09f181ea12 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_filter_delay_fc.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_filter_delay_fc_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 0000000000..2b65c67233 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_filter_delay_fc.h @@ -0,0 +1,72 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FILTER_DELAY_FC_H +#define INCLUDED_GR_FILTER_DELAY_FC_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_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 + * + * 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_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_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 0000000000..85603ce22d --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..1f7866229d --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..a5bf3ed035 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_XXX.h.t @@ -0,0 +1,123 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 <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 @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 0000000000..7bc7a5eb2b --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..b1b2f4025f --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_XXX_generic.h.t @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#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 @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 0000000000..6d5cba3bde --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_ccc_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_fir_ccc_simd.h> + +#include <assert.h> +#include <malloc16.h> +#include <iostream> + +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; + + + // 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 0000000000..8988887110 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_ccc_simd.h @@ -0,0 +1,63 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_FIR_CCC_SIMD_H +#define INCLUDED_GR_FIR_CCC_SIMD_H + +#include <gr_fir_ccc_generic.h> + +/*! + * \brief common base class for SIMD versions of gr_fir_ccc + * + * This base class handles alignment issues common to SSE and 3DNOW + * subclasses. + */ + +class 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 0000000000..8b96c23d6e --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..ee2fe9b1f8 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_ccc_x86.h @@ -0,0 +1,55 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FIR_CCC_X86_H +#define INCLUDED_GR_FIR_CCC_X86_H + +#include <gr_fir_ccc_simd.h> + +/*! + * \brief 3DNow! version of gr_fir_ccc + */ +class 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_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_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_simd.cc b/gnuradio-core/src/lib/filter/gr_fir_ccf_simd.cc new file mode 100644 index 0000000000..d1992d7c99 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_ccf_simd.cc @@ -0,0 +1,138 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_fir_ccf_simd.h> + +#include <assert.h> +#include <malloc16.h> +#include <iostream> + +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; + + + // 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 0000000000..60898b43d7 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_ccf_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_FIR_CCF_SIMD_H +#define INCLUDED_GR_FIR_CCF_SIMD_H + +#include <gr_fir_ccf_generic.h> + + +/*! + * \brief common base class for SIMD versions of gr_fir_ccf + * + * This base class handles alignment issues common to SSE and 3DNOW + * subclasses. + */ + +class 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 0000000000..9f288fc221 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..5c51a5f931 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_ccf_x86.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FIR_CCF_X86_H +#define INCLUDED_GR_FIR_CCF_X86_H + +#include <gr_fir_ccf_simd.h> + +/*! + * \brief 3DNow! version of gr_fir_ccf + */ +class 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 + */ +class 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 0000000000..c17d29f7da --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..5624820902 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fcc_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_FIR_FCC_SIMD_H +#define INCLUDED_GR_FIR_FCC_SIMD_H + +#include <gr_fir_fcc_generic.h> + + +/*! + * \brief common base class for SIMD versions of gr_fir_fcc + * + * This base class handles alignment issues common to SSE and 3DNOW + * subclasses. + */ + +class 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 0000000000..e80dfe1f4f --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..500f4fb5f0 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fcc_x86.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FIR_FCC_X86_H +#define INCLUDED_GR_FIR_FCC_X86_H + +#include <gr_fir_fcc_simd.h> + +/*! + * \brief 3DNow! version of gr_fir_fcc + */ +class 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 + */ +class 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_simd.cc b/gnuradio-core/src/lib/filter/gr_fir_fff_simd.cc new file mode 100644 index 0000000000..92c4256e07 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..375b1191b3 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fff_simd.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_FIR_FFF_SIMD_H +#define INCLUDED_GR_FIR_FFF_SIMD_H + +#include <gr_fir_fff_generic.h> + +/*! + * \brief common base class for SIMD versions of gr_fir_fff + * + * This base class handles alignment issues common to SSE and 3DNOW + * subclasses. + */ + +class 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 0000000000..494a0f7e7c --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..407ae3ffcb --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fff_x86.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FIR_FFF_X86_H +#define INCLUDED_GR_FIR_FFF_X86_H + +#include <gr_fir_fff_simd.h> + +/*! + * \brief 3DNow! version of gr_fir_fff + */ +class 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_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 0000000000..91b3111e99 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.cc.t @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 @SPTR_NAME@ (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; +} + +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 0000000000..b6e5d1aa60 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_filter_XXX.h.t @@ -0,0 +1,67 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_sync_decimator.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; +@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 + */ +class @NAME@ : public gr_sync_decimator +{ + private: + friend @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); + + 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 0000000000..13c919d1ab --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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); +}; 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 0000000000..00b4e60997 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..77e093ca84 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fsf_simd.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GR_FIR_FSF_SIMD_H_ +#define _GR_FIR_FSF_SIMD_H_ + +#include <gr_fir_fsf_generic.h> + +/*! + * \brief common base class for SIMD versions of gr_fir_fsf + * + * This base class handles alignment issues common to SSE and 3DNOW + * subclasses. + */ + +class 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 0000000000..c407789db7 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..e8ae763f6c --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_fsf_x86.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FIR_FSF_X86_H +#define INCLUDED_GR_FIR_FSF_X86_H + +#include <gr_fir_fsf_simd.h> + +/*! + * \brief 3DNow! version of gr_fir_fsf + */ +class 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 + */ +class 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 0000000000..b6f91a7479 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..098b02a502 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_scc_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_FIR_SCC_SIMD_H +#define INCLUDED_GR_FIR_SCC_SIMD_H + +#include <gr_fir_scc_generic.h> + + +/*! + * \brief common base class for SIMD versions of gr_fir_scc + * + * This base class handles alignment issues common to SSE and 3DNOW + * subclasses. + */ + +class 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 0000000000..c654fce141 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..bbdf5eb7b0 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_scc_x86.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FIR_SCC_X86_H +#define INCLUDED_GR_FIR_SCC_X86_H + +#include <gr_fir_scc_simd.h> + +/*! + * \brief 3DNow! version of gr_fir_scc + */ +class 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_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_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_x86.cc b/gnuradio-core/src/lib/filter/gr_fir_sysconfig_x86.cc new file mode 100644 index 0000000000..7d576e8bbc --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..2f1d48efd6 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fir_sysconfig_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_FIR_SYSCONFIG_X86_H +#define INCLUDED_GR_FIR_SYSCONFIG_X86_H + +#include <gr_fir_sysconfig_generic.h> + +class 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 b/gnuradio-core/src/lib/filter/gr_fractional_interpolator.cc new file mode 100644 index 0000000000..6abb963d94 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fractional_interpolator.cc @@ -0,0 +1,97 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_io_signature.h> +#include <gr_fractional_interpolator.h> +#include <gri_mmse_fir_interpolator.h> +#include <stdexcept> + +// Public constructor +gr_fractional_interpolator_sptr gr_make_fractional_interpolator(float phase_shift, float interp_ratio) +{ + return gr_fractional_interpolator_sptr(new gr_fractional_interpolator(phase_shift, interp_ratio)); +} + +gr_fractional_interpolator::gr_fractional_interpolator(float phase_shift, float interp_ratio) + : gr_block ("fractional_interpolator", + 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() +{ + 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::~gr_fractional_interpolator() +{ + delete d_interp; +} + +void +gr_fractional_interpolator::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::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){ + + // produce output sample + + out[oo++] = d_interp->interpolate(&in[ii], d_mu); + + // printf( "%4d %9.6f\n", 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.h b/gnuradio-core/src/lib/filter/gr_fractional_interpolator.h new file mode 100644 index 0000000000..b024c44162 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_fractional_interpolator.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FRACTIONAL_INTERPOLATOR_H +#define INCLUDED_GR_FRACTIONAL_INTERPOLATOR_H + +#include <gr_block.h> + +class gri_mmse_fir_interpolator; + +class gr_fractional_interpolator; +typedef boost::shared_ptr<gr_fractional_interpolator> gr_fractional_interpolator_sptr; + +// public constructor +gr_fractional_interpolator_sptr gr_make_fractional_interpolator (float phase_shift, float interp_ratio); + +/*! + * \brief Interpolating mmse filter with float input, float output + * \ingroup filter + */ +class gr_fractional_interpolator : public gr_block +{ + public: + ~gr_fractional_interpolator (); + 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); + +protected: + gr_fractional_interpolator (float phase_shift, float interp_ratio); + + private: + float d_mu; + float d_mu_inc; + gri_mmse_fir_interpolator *d_interp; + + friend gr_fractional_interpolator_sptr + gr_make_fractional_interpolator (float phase_shift, float interp_ratio); +}; + +#endif 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 0000000000..4592e754e0 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_freq_xlating_fir_filter_XXX.cc.t @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 @SPTR_NAME@ (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; + } + + 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 0000000000..d1351e20ee --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_freq_xlating_fir_filter_XXX.h.t @@ -0,0 +1,100 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_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. + */ +@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 + * + * 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 @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 @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 0000000000..0a4f8b316a --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..264b96e672 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_goertzel_fc.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_goertzel_fc_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; +} + +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; +} 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 0000000000..c8363bc473 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_goertzel_fc.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_GOERTZEL_FC_H +#define INCLUDED_GR_GOERTZEL_FC_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_goertzel_fc_sptr gr_make_goertzel_fc(int rate, int len, float freq); + +/*! + * \brief Goertzel single-bin DFT calculation. + * \ingroup filter + */ +class gr_goertzel_fc : public gr_sync_decimator +{ +private: + friend 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; + +public: + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +#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 0000000000..6d5efd2332 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_goertzel_fc.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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(); +}; 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 0000000000..371363c38e --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_hilbert_fc.cc @@ -0,0 +1,67 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_hilbert_fc_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 0000000000..54082a95e1 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_hilbert_fc.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_HILBERT_FC_H +#define INCLUDED_GR_HILBERT_FC_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_hilbert_fc_sptr gr_make_hilbert_fc (unsigned int ntaps); + + +class gr_fir_fff; + +/*! + * \brief Hilbert transformer. + * \ingroup filter + * + * real output is input appropriately delayed. + * imaginary output is hilbert filtered (90 degree phase shift) + * version of input. + */ +class 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_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 0000000000..f69f624aea --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..4e825e7a89 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_iir_filter_ffd.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_iir_filter_ffd_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) +{ + if (fftaps.size () != fbtaps.size ()){ + fprintf (stderr, + "gr_iir_filter_ffd::set_taps: fftaps and fbtaps must have the same number of elements.\n"); + throw std::invalid_argument ("gr_iir_filter_ffd::set_taps"); + } + + 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]; + + // fprintf (stderr, "gr_iir_filter_ffd::work noutput_items = %d\n", noutput_items); + + 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 0000000000..5ef36349e1 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_iir_filter_ffd.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_IIR_FILTER_FFD_H +#define INCLUDED_GR_IIR_FILTER_FFD_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_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 + * + * 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}^{N} a_k y[n-k] = \sum_{k=0}^{M} b_k x[n-k] + \f] + + * with the corresponding rational system function + + \f[ + H(z) = \frac{\sum_{k=0}^{M} b_k z^{-k}}{1 - \sum_{k=1}^{N} 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. + */ +class gr_iir_filter_ffd : public gr_sync_block +{ + private: + friend 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 0000000000..bab8310fec --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..f382a7cd04 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_interp_fir_filter_XXX.cc.t @@ -0,0 +1,146 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 @SPTR_NAME@ (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 0000000000..866c43ab21 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_interp_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_sync_interpolator.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; +@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 + */ +class @NAME@ : public gr_sync_interpolator +{ + private: + friend @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 0000000000..d58c823f74 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_rational_resampler_base_XXX.cc.t b/gnuradio-core/src/lib/filter/gr_rational_resampler_base_XXX.cc.t new file mode 100644 index 0000000000..a07b739ef9 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_rational_resampler_base_XXX.cc.t @@ -0,0 +1,172 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 @SPTR_NAME@ (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 0000000000..011726935d --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_rational_resampler_base_XXX.h.t @@ -0,0 +1,87 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; +@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 + */ +class @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 @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 0000000000..2411d0347b --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..930b1cc24d --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_rotator.h @@ -0,0 +1,50 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GR_ROTATOR_H_ +#define _GR_ROTATOR_H_ + +#include <gr_complex.h> + +class gr_rotator { + gr_complex d_phase; + gr_complex d_phase_incr; + + public: + gr_rotator () : d_phase (1), d_phase_incr (0) { } + + void set_phase (gr_complex phase) { d_phase = phase; } + void set_phase_incr (gr_complex incr) { d_phase_incr = incr; } + + gr_complex rotate (gr_complex in){ + d_phase *= d_phase_incr; // incr our phase (complex mult == add phases) + + d_phase /= abs(d_phase); // ensure multiplication is rotation + // FIXME. This is expensive. Maybe workaround using + // double precision complex??? + + return in * d_phase; // rotate in by phase + } + +}; + +#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 0000000000..44c85740c3 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_sincos.c @@ -0,0 +1,81 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#define _GNU_SOURCE // ask for GNU extensions if available + +#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 0000000000..2e8f3ff7ac --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_sincos.h @@ -0,0 +1,39 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SINCOS_H +#define INCLUDED_GR_SINCOS_H + +#ifdef __cplusplus +extern "C" { +#endif + +// compute sine and cosine at the same time + +void gr_sincos (double x, double *sin, double *cos); +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_avg.h b/gnuradio-core/src/lib/filter/gr_single_pole_avg.h new file mode 100644 index 0000000000..adf871ae49 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_avg.h @@ -0,0 +1,110 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GR_SINGLE_POLE_AVG_H_ +#define _GR_SINGLE_POLE_AVG_H_ + +#include <stdexcept> + +/*! + * \brief class template for single pole moving average filter + */ +template<class o_type, class i_type, class tap_type> +class gr_single_pole_avg { +public: + /*! + * \brief construct new single pole moving average filter with given alpha + * + * computes y(i) = alpha * x(i) - (1-alpha) * y(i-1) + */ + gr_single_pole_avg (tap_type alpha = 1.0) + { + d_prev_input = 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_input = 0; + } + + tap_type prev_input () { return d_prev_input; } + +protected: + tap_type d_alpha; + tap_type d_one_minus_alpha; + tap_type d_prev_input; +}; + + +// +// general case. We may want to specialize this +// +template<class o_type, class i_type, class tap_type> +o_type +gr_single_pole_avg<o_type, i_type, tap_type>::filter (const i_type input) +{ + tap_type output; + + output = d_alpha * input - d_one_minus_alpha * d_prev_input; + d_prev_input = input; + + return (o_type) output; +} + + +template<class o_type, class i_type, class tap_type> +void +gr_single_pole_avg<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]); +} + + +#endif /* _GR_SINGLE_POLE_AVG_H_ */ diff --git a/gnuradio-core/src/lib/filter/gr_single_pole_avg_filter_ff.cc b/gnuradio-core/src/lib/filter/gr_single_pole_avg_filter_ff.cc new file mode 100644 index 0000000000..99f8b1103e --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_avg_filter_ff.cc @@ -0,0 +1,81 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_single_pole_avg_filter_ff.h> +#include <gr_io_signature.h> +#include <stdio.h> + + +gr_single_pole_avg_filter_ff_sptr +gr_make_single_pole_avg_filter_ff (double alpha, unsigned int vlen) +{ + return gr_single_pole_avg_filter_ff_sptr(new gr_single_pole_avg_filter_ff(alpha, vlen)); +} + +gr_single_pole_avg_filter_ff::gr_single_pole_avg_filter_ff ( + double alpha, unsigned int vlen) + : gr_sync_block ("single_pole_avg_filter_ff", + gr_make_io_signature (1, 1, sizeof (float) * vlen), + gr_make_io_signature (1, 1, sizeof (float) * vlen)), + d_vlen(vlen), d_rec(vlen) +{ + set_taps(alpha); +} + +gr_single_pole_avg_filter_ff::~gr_single_pole_avg_filter_ff () +{ + // nop +} + +void +gr_single_pole_avg_filter_ff::set_taps (double alpha) +{ + for (unsigned int i = 0; i < d_vlen; i++) + d_rec[i].set_taps(alpha); +} + +int +gr_single_pole_avg_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_rec[0].filter (in[i]); + } + else { + for (int i = 0; i < noutput_items; i++){ + for (unsigned int j = 0; j < vlen; j++){ + *out++ = d_rec[j].filter (*in++); + } + } + } + return noutput_items; +}; diff --git a/gnuradio-core/src/lib/filter/gr_single_pole_avg_filter_ff.h b/gnuradio-core/src/lib/filter/gr_single_pole_avg_filter_ff.h new file mode 100644 index 0000000000..cc3640f689 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_avg_filter_ff.h @@ -0,0 +1,76 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SINGLE_POLE_REC_FILTER_FF_H +#define INCLUDED_GR_SINGLE_POLE_REC_FILTER_FF_H + +#include <gr_sync_block.h> +#include <gr_single_pole_avg.h> +#include <stdexcept> + +class gr_single_pole_avg_filter_ff; +typedef boost::shared_ptr<gr_single_pole_avg_filter_ff> gr_single_pole_avg_filter_ff_sptr; + +gr_single_pole_avg_filter_ff_sptr +gr_make_single_pole_avg_filter_ff (double alpha, unsigned int vlen=1); + +/*! + * \brief single pole moving average filter with float input, float output + * \ingroup filter + * + * The input and output satisfy a difference equation of the form + + \f[ + y[n] - (1-alpha) y[n-1] = alpha x[n] + \f] + + * with the corresponding rational system function + + \f[ + H(z) = \frac{alpha}{1 - (1-alpha) z^{-1}} + \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 tap. + */ +class gr_single_pole_avg_filter_ff : public gr_sync_block +{ + private: + friend gr_single_pole_avg_filter_ff_sptr + gr_make_single_pole_avg_filter_ff (double alpha, unsigned int vlen); + + unsigned int d_vlen; + std::vector<gr_single_pole_avg<float,float,double> > d_rec; + + gr_single_pole_avg_filter_ff (double alpha, unsigned int vlen); + + public: + ~gr_single_pole_avg_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_avg_filter_ff.i b/gnuradio-core/src/lib/filter/gr_single_pole_avg_filter_ff.i new file mode 100644 index 0000000000..f0ffe6cef9 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_avg_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,single_pole_avg_filter_ff); + +gr_single_pole_avg_filter_ff_sptr +gr_make_single_pole_avg_filter_ff (double alpha, unsigned int vlen=1); + +class gr_single_pole_avg_filter_ff : public gr_sync_block +{ + public: + ~gr_single_pole_avg_filter_ff (); + + void set_taps (double alpha); +}; 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 0000000000..c1d3f748da --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_iir.h @@ -0,0 +1,190 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GR_SINGLE_POLE_IIR_H_ +#define _GR_SINGLE_POLE_IIR_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; + } + + tap_type prev_output () { return d_prev_output; } + +protected: + tap_type d_alpha; + tap_type d_one_minus_alpha; + tap_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) +{ + tap_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 () { 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 0000000000..0218452ca6 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_cc.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_single_pole_iir_filter_cc_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 0000000000..38caa614bb --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_cc.h @@ -0,0 +1,77 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SINGLE_POLE_IIR_FILTER_CC_H +#define INCLUDED_GR_SINGLE_POLE_IIR_FILTER_CC_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_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 + * + * The input and output satisfy a difference equation of the form + + \f[ + y[n] - (1-alpha) y[n-1] = alpha x[n] + \f] + + * with the corresponding rational system function + + \f[ + H(z) = \frac{alpha}{1 - (1-alpha) z^{-1}} + \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 tap. + */ +class gr_single_pole_iir_filter_cc : public gr_sync_block +{ + private: + friend 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 0000000000..683bbe99df --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..03e27484f3 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_ff.cc @@ -0,0 +1,81 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_single_pole_iir_filter_ff_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 0000000000..ff6bae3bfa --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_ff.h @@ -0,0 +1,76 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SINGLE_POLE_IIR_FILTER_FF_H +#define INCLUDED_GR_SINGLE_POLE_IIR_FILTER_FF_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_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 + * + * The input and output satisfy a difference equation of the form + + \f[ + y[n] - (1-alpha) y[n-1] = alpha x[n] + \f] + + * with the corresponding rational system function + + \f[ + H(z) = \frac{alpha}{1 - (1-alpha) z^{-1}} + \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 tap. + */ +class gr_single_pole_iir_filter_ff : public gr_sync_block +{ + private: + friend 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 0000000000..6680c84ee3 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_single_pole_rec.h b/gnuradio-core/src/lib/filter/gr_single_pole_rec.h new file mode 100644 index 0000000000..f443678dc2 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_rec.h @@ -0,0 +1,110 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GR_SINGLE_POLE_REC_H_ +#define _GR_SINGLE_POLE_REC_H_ + +#include <stdexcept> + +/*! + * \brief class template for single pole recursive filter + */ +template<class o_type, class i_type, class tap_type> +class gr_single_pole_rec { +public: + /*! + * \brief construct new single pole IIR with given alpha + * + * computes y(i) = alpha * x(i) - (1-alpha) * y(i-1) + */ + gr_single_pole_rec (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 pole + void reset () + { + d_prev_output = 0; + } + + tap_type prev_output () { return d_prev_output; } + +protected: + tap_type d_alpha; + tap_type d_one_minus_alpha; + tap_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_rec<o_type, i_type, tap_type>::filter (const i_type input) +{ + tap_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_rec<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]); +} + + +#endif /* _GR_SINGLE_POLE_REC_H_ */ diff --git a/gnuradio-core/src/lib/filter/gr_single_pole_rec_filter_ff.cc b/gnuradio-core/src/lib/filter/gr_single_pole_rec_filter_ff.cc new file mode 100644 index 0000000000..7c0a9aa95b --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_rec_filter_ff.cc @@ -0,0 +1,81 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_single_pole_rec_filter_ff.h> +#include <gr_io_signature.h> +#include <stdio.h> + + +gr_single_pole_rec_filter_ff_sptr +gr_make_single_pole_rec_filter_ff (double alpha, unsigned int vlen) +{ + return gr_single_pole_rec_filter_ff_sptr(new gr_single_pole_rec_filter_ff(alpha, vlen)); +} + +gr_single_pole_rec_filter_ff::gr_single_pole_rec_filter_ff ( + double alpha, unsigned int vlen) + : gr_sync_block ("single_pole_rec_filter_ff", + gr_make_io_signature (1, 1, sizeof (float) * vlen), + gr_make_io_signature (1, 1, sizeof (float) * vlen)), + d_vlen(vlen), d_rec(vlen) +{ + set_taps(alpha); +} + +gr_single_pole_rec_filter_ff::~gr_single_pole_rec_filter_ff () +{ + // nop +} + +void +gr_single_pole_rec_filter_ff::set_taps (double alpha) +{ + for (unsigned int i = 0; i < d_vlen; i++) + d_rec[i].set_taps(alpha); +} + +int +gr_single_pole_rec_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_rec[0].filter (in[i]); + } + else { + for (int i = 0; i < noutput_items; i++){ + for (unsigned int j = 0; j < vlen; j++){ + *out++ = d_rec[j].filter (*in++); + } + } + } + return noutput_items; +}; diff --git a/gnuradio-core/src/lib/filter/gr_single_pole_rec_filter_ff.h b/gnuradio-core/src/lib/filter/gr_single_pole_rec_filter_ff.h new file mode 100644 index 0000000000..d1861e759b --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_rec_filter_ff.h @@ -0,0 +1,76 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SINGLE_POLE_REC_FILTER_FF_H +#define INCLUDED_GR_SINGLE_POLE_REC_FILTER_FF_H + +#include <gr_sync_block.h> +#include <gr_single_pole_rec.h> +#include <stdexcept> + +class gr_single_pole_rec_filter_ff; +typedef boost::shared_ptr<gr_single_pole_rec_filter_ff> gr_single_pole_rec_filter_ff_sptr; + +gr_single_pole_rec_filter_ff_sptr +gr_make_single_pole_rec_filter_ff (double alpha, unsigned int vlen=1); + +/*! + * \brief single pole recursive filter with float input, float output + * \ingroup filter + * + * The input and output satisfy a difference equation of the form + + \f[ + y[n] - (1-alpha) y[n-1] = alpha x[n] + \f] + + * with the corresponding rational system function + + \f[ + H(z) = \frac{alpha}{1 - (1-alpha) z^{-1}} + \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 tap. + */ +class gr_single_pole_rec_filter_ff : public gr_sync_block +{ + private: + friend gr_single_pole_rec_filter_ff_sptr + gr_make_single_pole_rec_filter_ff (double alpha, unsigned int vlen); + + unsigned int d_vlen; + std::vector<gr_single_pole_rec<float,float,double> > d_rec; + + gr_single_pole_rec_filter_ff (double alpha, unsigned int vlen); + + public: + ~gr_single_pole_rec_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_rec_filter_ff.i b/gnuradio-core/src/lib/filter/gr_single_pole_rec_filter_ff.i new file mode 100644 index 0000000000..06da737b6b --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_pole_rec_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,single_pole_rec_filter_ff); + +gr_single_pole_rec_filter_ff_sptr +gr_make_single_pole_rec_filter_ff (double alpha, unsigned int vlen=1); + +class gr_single_pole_rec_filter_ff : public gr_sync_block +{ + public: + ~gr_single_pole_rec_filter_ff (); + + void set_taps (double alpha); +}; diff --git a/gnuradio-core/src/lib/filter/gr_single_zero_avg.h b/gnuradio-core/src/lib/filter/gr_single_zero_avg.h new file mode 100644 index 0000000000..def340a05d --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_zero_avg.h @@ -0,0 +1,110 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GR_SINGLE_ZERO_AVG_H_ +#define _GR_SINGLE_ZERO_AVG_H_ + +#include <stdexcept> + +/*! + * \brief class template for single zero moving average filter + */ +template<class o_type, class i_type, class tap_type> +class gr_single_zero_avg { +public: + /*! + * \brief construct new single zero moving average filter with given alpha + * + * computes y(i) = alpha * x(i) + (1-alpha) * y(i-1) + */ + gr_single_zero_avg (tap_type alpha = 1.0) + { + d_prev_input = 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_input = 0; + } + + tap_type prev_input () { return d_prev_input; } + +protected: + tap_type d_alpha; + tap_type d_one_minus_alpha; + tap_type d_prev_input; +}; + + +// +// general case. We may want to specialize this +// +template<class o_type, class i_type, class tap_type> +o_type +gr_single_zero_avg<o_type, i_type, tap_type>::filter (const i_type input) +{ + tap_type output; + + output = d_alpha * input + d_one_minus_alpha * d_prev_input; + d_prev_input = input; + + return (o_type) output; +} + + +template<class o_type, class i_type, class tap_type> +void +gr_single_zero_avg<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]); +} + + +#endif /* _GR_SINGLE_ZERO_AVG_H_ */ diff --git a/gnuradio-core/src/lib/filter/gr_single_zero_avg_filter_ff.cc b/gnuradio-core/src/lib/filter/gr_single_zero_avg_filter_ff.cc new file mode 100644 index 0000000000..62feb4ca8e --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_zero_avg_filter_ff.cc @@ -0,0 +1,81 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_single_zero_avg_filter_ff.h> +#include <gr_io_signature.h> +#include <stdio.h> + + +gr_single_zero_avg_filter_ff_sptr +gr_make_single_zero_avg_filter_ff (double alpha, unsigned int vlen) +{ + return gr_single_zero_avg_filter_ff_sptr(new gr_single_zero_avg_filter_ff(alpha, vlen)); +} + +gr_single_zero_avg_filter_ff::gr_single_zero_avg_filter_ff ( + double alpha, unsigned int vlen) + : gr_sync_block ("single_zero_avg_filter_ff", + gr_make_io_signature (1, 1, sizeof (float) * vlen), + gr_make_io_signature (1, 1, sizeof (float) * vlen)), + d_vlen(vlen), d_rec(vlen) +{ + set_taps(alpha); +} + +gr_single_zero_avg_filter_ff::~gr_single_zero_avg_filter_ff () +{ + // nop +} + +void +gr_single_zero_avg_filter_ff::set_taps (double alpha) +{ + for (unsigned int i = 0; i < d_vlen; i++) + d_rec[i].set_taps(alpha); +} + +int +gr_single_zero_avg_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_rec[0].filter (in[i]); + } + else { + for (int i = 0; i < noutput_items; i++){ + for (unsigned int j = 0; j < vlen; j++){ + *out++ = d_rec[j].filter (*in++); + } + } + } + return noutput_items; +}; diff --git a/gnuradio-core/src/lib/filter/gr_single_zero_avg_filter_ff.h b/gnuradio-core/src/lib/filter/gr_single_zero_avg_filter_ff.h new file mode 100644 index 0000000000..4a283d3c9c --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_zero_avg_filter_ff.h @@ -0,0 +1,76 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SINGLE_ZERO_REC_FILTER_FF_H +#define INCLUDED_GR_SINGLE_ZERO_REC_FILTER_FF_H + +#include <gr_sync_block.h> +#include <gr_single_zero_avg.h> +#include <stdexcept> + +class gr_single_zero_avg_filter_ff; +typedef boost::shared_ptr<gr_single_zero_avg_filter_ff> gr_single_zero_avg_filter_ff_sptr; + +gr_single_zero_avg_filter_ff_sptr +gr_make_single_zero_avg_filter_ff (double alpha, unsigned int vlen=1); + +/*! + * \brief single zero moving average filter with float input, float output + * \ingroup filter + * + * The input and output satisfy a difference equation of the form + + \f[ + y[n] - (1-alpha) y[n-1] = alpha x[n] + \f] + + * with the corresponding rational system function + + \f[ + H(z) = \frac{alpha}{1 - (1-alpha) z^{-1}} + \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 tap. + */ +class gr_single_zero_avg_filter_ff : public gr_sync_block +{ + private: + friend gr_single_zero_avg_filter_ff_sptr + gr_make_single_zero_avg_filter_ff (double alpha, unsigned int vlen); + + unsigned int d_vlen; + std::vector<gr_single_zero_avg<float,float,double> > d_rec; + + gr_single_zero_avg_filter_ff (double alpha, unsigned int vlen); + + public: + ~gr_single_zero_avg_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_zero_avg_filter_ff.i b/gnuradio-core/src/lib/filter/gr_single_zero_avg_filter_ff.i new file mode 100644 index 0000000000..0e6d84fa6d --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_zero_avg_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,single_zero_avg_filter_ff); + +gr_single_zero_avg_filter_ff_sptr +gr_make_single_zero_avg_filter_ff (double alpha, unsigned int vlen=1); + +class gr_single_zero_avg_filter_ff : public gr_sync_block +{ + public: + ~gr_single_zero_avg_filter_ff (); + + void set_taps (double alpha); +}; diff --git a/gnuradio-core/src/lib/filter/gr_single_zero_rec.h b/gnuradio-core/src/lib/filter/gr_single_zero_rec.h new file mode 100644 index 0000000000..f91640c590 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_zero_rec.h @@ -0,0 +1,110 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GR_SINGLE_ZERO_REC_H_ +#define _GR_SINGLE_ZERO_REC_H_ + +#include <stdexcept> + +/*! + * \brief class template for single zero recursive filter + */ +template<class o_type, class i_type, class tap_type> +class gr_single_zero_rec { +public: + /*! + * \brief construct new single zero IIR with given alpha + * + * computes y(i) = alpha * x(i) - (1-alpha) * y(i-1) + */ + gr_single_zero_rec (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; + } + + tap_type prev_output () { return d_prev_output; } + +protected: + tap_type d_alpha; + tap_type d_one_minus_alpha; + tap_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_zero_rec<o_type, i_type, tap_type>::filter (const i_type input) +{ + tap_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_zero_rec<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]); +} + + +#endif /* _GR_SINGLE_ZERO_REC_H_ */ diff --git a/gnuradio-core/src/lib/filter/gr_single_zero_rec_filter_ff.cc b/gnuradio-core/src/lib/filter/gr_single_zero_rec_filter_ff.cc new file mode 100644 index 0000000000..fe704f453c --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_zero_rec_filter_ff.cc @@ -0,0 +1,81 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_single_zero_rec_filter_ff.h> +#include <gr_io_signature.h> +#include <stdio.h> + + +gr_single_zero_rec_filter_ff_sptr +gr_make_single_zero_rec_filter_ff (double alpha, unsigned int vlen) +{ + return gr_single_zero_rec_filter_ff_sptr(new gr_single_zero_rec_filter_ff(alpha, vlen)); +} + +gr_single_zero_rec_filter_ff::gr_single_zero_rec_filter_ff ( + double alpha, unsigned int vlen) + : gr_sync_block ("single_zero_rec_filter_ff", + gr_make_io_signature (1, 1, sizeof (float) * vlen), + gr_make_io_signature (1, 1, sizeof (float) * vlen)), + d_vlen(vlen), d_rec(vlen) +{ + set_taps(alpha); +} + +gr_single_zero_rec_filter_ff::~gr_single_zero_rec_filter_ff () +{ + // nop +} + +void +gr_single_zero_rec_filter_ff::set_taps (double alpha) +{ + for (unsigned int i = 0; i < d_vlen; i++) + d_rec[i].set_taps(alpha); +} + +int +gr_single_zero_rec_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_rec[0].filter (in[i]); + } + else { + for (int i = 0; i < noutput_items; i++){ + for (unsigned int j = 0; j < vlen; j++){ + *out++ = d_rec[j].filter (*in++); + } + } + } + return noutput_items; +}; diff --git a/gnuradio-core/src/lib/filter/gr_single_zero_rec_filter_ff.h b/gnuradio-core/src/lib/filter/gr_single_zero_rec_filter_ff.h new file mode 100644 index 0000000000..98215e9024 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_zero_rec_filter_ff.h @@ -0,0 +1,76 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SINGLE_POLE_REC_FILTER_FF_H +#define INCLUDED_GR_SINGLE_POLE_REC_FILTER_FF_H + +#include <gr_sync_block.h> +#include <gr_single_zero_rec.h> +#include <stdexcept> + +class gr_single_zero_rec_filter_ff; +typedef boost::shared_ptr<gr_single_zero_rec_filter_ff> gr_single_zero_rec_filter_ff_sptr; + +gr_single_zero_rec_filter_ff_sptr +gr_make_single_zero_rec_filter_ff (double alpha, unsigned int vlen=1); + +/*! + * \brief single zero recursive filter with float input, float output + * \ingroup filter + * + * The input and output satisfy a difference equation of the form + + \f[ + y[n] - (1-alpha) y[n-1] = -alpha x[n] + \f] + + * with the corresponding system function + + \f[ + H(z) = {alpha - (1-alpha) z^{-1}} + \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 tap. + */ +class gr_single_zero_rec_filter_ff : public gr_sync_block +{ + private: + friend gr_single_zero_rec_filter_ff_sptr + gr_make_single_zero_rec_filter_ff (double alpha, unsigned int vlen); + + unsigned int d_vlen; + std::vector<gr_single_zero_rec<float,float,double> > d_rec; + + gr_single_zero_rec_filter_ff (double alpha, unsigned int vlen); + + public: + ~gr_single_zero_rec_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_zero_rec_filter_ff.i b/gnuradio-core/src/lib/filter/gr_single_zero_rec_filter_ff.i new file mode 100644 index 0000000000..e2cbbfc94a --- /dev/null +++ b/gnuradio-core/src/lib/filter/gr_single_zero_rec_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,single_zero_rec_filter_ff); + +gr_single_zero_rec_filter_ff_sptr +gr_make_single_zero_rec_filter_ff (double alpha, unsigned int vlen=1); + +class gr_single_zero_rec_filter_ff : public gr_sync_block +{ + public: + ~gr_single_zero_rec_filter_ff (); + + void set_taps (double alpha); +}; 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 0000000000..571de61679 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_goertzel.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <cmath> + +#include <gri_goertzel.h> + +gri_goertzel::gri_goertzel(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 0000000000..6baf94e98a --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_goertzel.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_GOERTZEL_H +#define INCLUDED_GRI_GOERTZEL_H + +#include <gr_types.h> + +/*! + * \brief implements Goertzel single-bin DFT calculation + */ + +class gri_goertzel +{ +public: + gri_goertzel() {} + gri_goertzel(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 0000000000..7de8c69a59 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_iir.h @@ -0,0 +1,164 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_IIR_H +#define INCLUDED_GRI_IIR_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}^{N} a_k y[n-k] = \sum_{k=0}^{M} b_k x[n-k] + \f] + + * with the corresponding rational system function + + \f[ + H(z) = \frac{\sum_{k=0}^{M} b_k z^{-k}}{1 - \sum_{k=1}^{N} 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(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 () const { return d_fftaps.size (); } + + /*! + * \brief install new taps. + */ + void set_taps (const std::vector<tap_type> &fftaps, + const std::vector<tap_type> &fbtaps) throw (std::invalid_argument) + { + if (fftaps.size () != fbtaps.size ()) + throw std::invalid_argument ("gri_iir::set_taps"); + + d_latest = 0; + d_fftaps = fftaps; + d_fbtaps = fbtaps; + + int n = fftaps.size (); + d_prev_input.resize (2 * n); + d_prev_output.resize (2 * n); + + for (int i = 0; i < 2 * n; i++){ + d_prev_input[i] = 0; + d_prev_output[i] = 0; + } + } + +protected: + std::vector<tap_type> d_fftaps; + std::vector<tap_type> d_fbtaps; + int d_latest; + 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 (); + + if (n == 0) + return (o_type) 0; + + int latest = d_latest; + + acc = d_fftaps[0] * input; + for (i = 1; i < n; i ++) + acc += (d_fftaps[i] * d_prev_input[latest + i] + + d_fbtaps[i] * d_prev_output[latest + i]); + + // store the values twice to avoid having to handle wrap-around in the loop + d_prev_output[latest] = acc; + d_prev_output[latest+n] = acc; + d_prev_input[latest] = input; + d_prev_input[latest+n] = input; + + latest--; + if (latest < 0) + latest += n; + + d_latest = latest; + 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 0000000000..ff7eca89ce --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..e2fb8f79cf --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GRI_MMSE_FIR_INTERPOLATOR_H_ +#define _GRI_MMSE_FIR_INTERPOLATOR_H_ + +#include <vector> + +class gr_fir_fff; + +/*! + * \brief Compute intermediate samples between signal samples x(k*Ts) + * + * 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. + */ + +class 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 0000000000..3f75aedcdd --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..d0c1411770 --- /dev/null +++ b/gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator_cc.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GRI_MMSE_FIR_INTERPOLATOR_CC_H_ +#define _GRI_MMSE_FIR_INTERPOLATOR_CC_H_ + +#include <gr_complex.h> +#include <vector> + +class gr_fir_ccf; + +/*! + * \brief Compute intermediate samples between signal samples x(k*Ts) + * + * 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. + */ + +class 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. + * 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. + */ + 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 0000000000..76702b63fa --- /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 0000000000..ad6f6c6e80 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..f10f0060f0 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..91c8e9e272 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..53509ea6d9 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..3fbbdc3dc2 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_generic.cc b/gnuradio-core/src/lib/filter/qa_dotprod_generic.cc new file mode 100644 index 0000000000..d0f66cc9d5 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..6aeb49324a --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..75415a7999 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_filter.cc @@ -0,0 +1,52 @@ +/* + * 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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> + +CppUnit::TestSuite * +qa_filter::suite () +{ + CppUnit::TestSuite *s = new CppUnit::TestSuite ("filter"); + + s->addTest (qa_dotprod_suite ()); + s->addTest (qa_gri_mmse_fir_interpolator::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 ()); + + 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 0000000000..71371ae1a9 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_filter.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _QA_FILTER_H_ +#define _QA_FILTER_H_ + +#include <cppunit/TestSuite.h> + +//! collect all the tests for the gr directory + +class 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 0000000000..a16977977c --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..005681290f --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..9c70a16775 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_fir_ccc.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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> + +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++){ + 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 0000000000..46fa9b0e94 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..c45e085347 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_fir_ccf.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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> + +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++){ + 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 0000000000..bf87136d05 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..0706b585d9 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_fir_fcc.cc @@ -0,0 +1,180 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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> + +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++){ + 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 0000000000..145f72f004 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..1ba3bee551 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gr_fir_fff.cc @@ -0,0 +1,225 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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> + +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 = 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_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]) * 1e-4); + } + + 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 0000000000..34d86f9d16 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..38a76924c6 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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++){ + 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 0000000000..2662d02b44 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_gri_mmse_fir_interpolator.cc b/gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator.cc new file mode 100644 index 0000000000..a756bbc4a4 --- /dev/null +++ b/gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#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 0000000000..85be45e89f --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/short_dotprod_generic.c b/gnuradio-core/src/lib/filter/short_dotprod_generic.c new file mode 100644 index 0000000000..4fca2e5dd3 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..6e3709ff31 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..7c9ae07818 --- /dev/null +++ b/gnuradio-core/src/lib/filter/short_dotprod_mmx.S @@ -0,0 +1,113 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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" 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 0000000000..4c46e0ea42 --- /dev/null +++ b/gnuradio-core/src/lib/filter/short_dotprod_mmx64.S @@ -0,0 +1,101 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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" 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 0000000000..03b47489e4 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..f27d3930b3 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..f356a0e034 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_generic.cc b/gnuradio-core/src/lib/filter/sysconfig_generic.cc new file mode 100644 index 0000000000..1cecf49f45 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_x86.cc b/gnuradio-core/src/lib/filter/sysconfig_x86.cc new file mode 100644 index 0000000000..d2c31612ac --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/g72x/Makefile.am b/gnuradio-core/src/lib/g72x/Makefile.am new file mode 100644 index 0000000000..c8ba3e8dc4 --- /dev/null +++ b/gnuradio-core/src/lib/g72x/Makefile.am @@ -0,0 +1,27 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +noinst_LTLIBRARIES = libccitt.la +libccitt_la_SOURCES = g711.c g72x.c g721.c g723_24.c g723_40.c g72x.h + +EXTRA_DIST = encode.c decode.c diff --git a/gnuradio-core/src/lib/g72x/README b/gnuradio-core/src/lib/g72x/README new file mode 100644 index 0000000000..23b0e7dd50 --- /dev/null +++ b/gnuradio-core/src/lib/g72x/README @@ -0,0 +1,94 @@ +The files in this directory comprise ANSI-C language reference implementations +of the CCITT (International Telegraph and Telephone Consultative Committee) +G.711, G.721 and G.723 voice compressions. They have been tested on Sun +SPARCstations and passed 82 out of 84 test vectors published by CCITT +(Dec. 20, 1988) for G.721 and G.723. [The two remaining test vectors, +which the G.721 decoder implementation for u-law samples did not pass, +may be in error because they are identical to two other vectors for G.723_40.] + +This source code is released by Sun Microsystems, Inc. to the public domain. +Please give your acknowledgement in product literature if this code is used +in your product implementation. + +Sun Microsystems supports some CCITT audio formats in Solaris 2.0 system +software. However, Sun's implementations have been optimized for higher +performance on SPARCstations. + + +The source files for CCITT conversion routines in this directory are: + + g72x.h header file for g721.c, g723_24.c and g723_40.c + g711.c CCITT G.711 u-law and A-law compression + g72x.c common denominator of G.721 and G.723 ADPCM codes + g721.c CCITT G.721 32Kbps ADPCM coder (with g72x.c) + g723_24.c CCITT G.723 24Kbps ADPCM coder (with g72x.c) + g723_40.c CCITT G.723 40Kbps ADPCM coder (with g72x.c) + + +Simple conversions between u-law, A-law, and 16-bit linear PCM are invoked +as follows: + + unsigned char ucode, acode; + short pcm_val; + + ucode = linear2ulaw(pcm_val); + ucode = alaw2ulaw(acode); + + acode = linear2alaw(pcm_val); + acode = ulaw2alaw(ucode); + + pcm_val = ulaw2linear(ucode); + pcm_val = alaw2linear(acode); + + +The other CCITT compression routines are invoked as follows: + + #include "g72x.h" + + struct g72x_state state; + int sample, code; + + g72x_init_state(&state); + code = {g721,g723_24,g723_40}_encoder(sample, coding, &state); + sample = {g721,g723_24,g723_40}_decoder(code, coding, &state); + +where + coding = AUDIO_ENCODING_ULAW for 8-bit u-law samples + AUDIO_ENCODING_ALAW for 8-bit A-law samples + AUDIO_ENCODING_LINEAR for 16-bit linear PCM samples + + + +This directory also includes the following sample programs: + + encode.c CCITT ADPCM encoder + decode.c CCITT ADPCM decoder + Makefile makefile for the sample programs + + +The sample programs contain examples of how to call the various compression +routines and pack/unpack the bits. The sample programs read byte streams from +stdin and write to stdout. The input/output data is raw data (no file header +or other identifying information is embedded). The sample programs are +invoked as follows: + + encode [-3|4|5] [-a|u|l] <infile >outfile + decode [-3|4|5] [-a|u|l] <infile >outfile +where: + -3 encode to (decode from) G.723 24kbps (3-bit) data + -4 encode to (decode from) G.721 32kbps (4-bit) data [the default] + -5 encode to (decode from) G.723 40kbps (5-bit) data + -a encode from (decode to) A-law data + -u encode from (decode to) u-law data [the default] + -l encode from (decode to) 16-bit linear data + +Examples: + # Read 16-bit linear and output G.721 + encode -4 -l <pcmfile >g721file + + # Read 40Kbps G.723 and output A-law + decode -5 -a <g723file >alawfile + + # Compress and then decompress u-law data using 24Kbps G.723 + encode -3 <ulawin | deoced -3 >ulawout + diff --git a/gnuradio-core/src/lib/g72x/decode.c b/gnuradio-core/src/lib/g72x/decode.c new file mode 100644 index 0000000000..cf8c739c55 --- /dev/null +++ b/gnuradio-core/src/lib/g72x/decode.c @@ -0,0 +1,113 @@ +/* + * decode.c + * + * CCITT ADPCM decoder + * + * Usage : decode [-3|4|5] [-a|u|l] < infile > outfile + */ +#include <stdio.h> +#include "g72x.h" + + +/* + * Unpack input codes and pass them back as bytes. + * Returns 1 if there is residual input, returns -1 if eof, else returns 0. + */ +int +unpack_input( + unsigned char *code, + int bits) +{ + static unsigned int in_buffer = 0; + static int in_bits = 0; + unsigned char in_byte; + + if (in_bits < bits) { + if (fread(&in_byte, sizeof (char), 1, stdin) != 1) { + *code = 0; + return (-1); + } + in_buffer |= (in_byte << in_bits); + in_bits += 8; + } + *code = in_buffer & ((1 << bits) - 1); + in_buffer >>= bits; + in_bits -= bits; + return (in_bits > 0); +} + + +main( + int argc, + char **argv) +{ + short sample; + unsigned char code; + int n; + struct g72x_state state; + int out_coding; + int out_size; + int (*dec_routine)(); + int dec_bits; + + g72x_init_state(&state); + out_coding = AUDIO_ENCODING_ULAW; + out_size = sizeof (char); + dec_routine = g721_decoder; + dec_bits = 4; + + /* Process encoding argument, if any */ + while ((argc > 1) && (argv[1][0] == '-')) { + switch (argv[1][1]) { + case '3': + dec_routine = g723_24_decoder; + dec_bits = 3; + break; + case '4': + dec_routine = g721_decoder; + dec_bits = 4; + break; + case '5': + dec_routine = g723_40_decoder; + dec_bits = 5; + break; + case 'u': + out_coding = AUDIO_ENCODING_ULAW; + out_size = sizeof (char); + break; + case 'a': + out_coding = AUDIO_ENCODING_ALAW; + out_size = sizeof (char); + break; + case 'l': + out_coding = AUDIO_ENCODING_LINEAR; + out_size = sizeof (short); + break; + default: +fprintf(stderr, "CCITT ADPCM Decoder -- usage:\n"); +fprintf(stderr, "\tdecode [-3|4|5] [-a|u|l] < infile > outfile\n"); +fprintf(stderr, "where:\n"); +fprintf(stderr, "\t-3\tProcess G.723 24kbps (3-bit) input data\n"); +fprintf(stderr, "\t-4\tProcess G.721 32kbps (4-bit) input data [default]\n"); +fprintf(stderr, "\t-5\tProcess G.723 40kbps (5-bit) input data\n"); +fprintf(stderr, "\t-a\tGenerate 8-bit A-law data\n"); +fprintf(stderr, "\t-u\tGenerate 8-bit u-law data [default]\n"); +fprintf(stderr, "\t-l\tGenerate 16-bit linear PCM data\n"); + exit(1); + } + argc--; + argv++; + } + + /* Read and unpack input codes and process them */ + while (unpack_input(&code, dec_bits) >= 0) { + sample = (*dec_routine)(code, out_coding, &state); + if (out_size == 2) { + fwrite(&sample, out_size, 1, stdout); + } else { + code = (unsigned char)sample; + fwrite(&code, out_size, 1, stdout); + } + } + fclose(stdout); +} diff --git a/gnuradio-core/src/lib/g72x/encode.c b/gnuradio-core/src/lib/g72x/encode.c new file mode 100644 index 0000000000..e744828692 --- /dev/null +++ b/gnuradio-core/src/lib/g72x/encode.c @@ -0,0 +1,119 @@ +/* + * encode.c + * + * CCITT ADPCM encoder + * + * Usage : encode [-3|4|5] [-a|u|l] < infile > outfile + */ +#include <stdio.h> +#include "g72x.h" + + +/* + * Pack output codes into bytes and write them to stdout. + * Returns 1 if there is residual output, else returns 0. + */ +int +pack_output( + unsigned code, + int bits) +{ + static unsigned int out_buffer = 0; + static int out_bits = 0; + unsigned char out_byte; + + out_buffer |= (code << out_bits); + out_bits += bits; + if (out_bits >= 8) { + out_byte = out_buffer & 0xff; + out_bits -= 8; + out_buffer >>= 8; + fwrite(&out_byte, sizeof (char), 1, stdout); + } + return (out_bits > 0); +} + + +main( + int argc, + char **argv) +{ + struct g72x_state state; + unsigned char sample_char; + short sample_short; + unsigned char code; + int resid; + int in_coding; + int in_size; + unsigned *in_buf; + int (*enc_routine)(); + int enc_bits; + + g72x_init_state(&state); + + /* Set defaults to u-law input, G.721 output */ + in_coding = AUDIO_ENCODING_ULAW; + in_size = sizeof (char); + in_buf = (unsigned *)&sample_char; + enc_routine = g721_encoder; + enc_bits = 4; + + /* Process encoding argument, if any */ + while ((argc > 1) && (argv[1][0] == '-')) { + switch (argv[1][1]) { + case '3': + enc_routine = g723_24_encoder; + enc_bits = 3; + break; + case '4': + enc_routine = g721_encoder; + enc_bits = 4; + break; + case '5': + enc_routine = g723_40_encoder; + enc_bits = 5; + break; + case 'u': + in_coding = AUDIO_ENCODING_ULAW; + in_size = sizeof (char); + in_buf = (unsigned *)&sample_char; + break; + case 'a': + in_coding = AUDIO_ENCODING_ALAW; + in_size = sizeof (char); + in_buf = (unsigned *)&sample_char; + break; + case 'l': + in_coding = AUDIO_ENCODING_LINEAR; + in_size = sizeof (short); + in_buf = (unsigned *)&sample_short; + break; + default: +fprintf(stderr, "CCITT ADPCM Encoder -- usage:\n"); +fprintf(stderr, "\tencode [-3|4|5] [-a|u|l] < infile > outfile\n"); +fprintf(stderr, "where:\n"); +fprintf(stderr, "\t-3\tGenerate G.723 24kbps (3-bit) data\n"); +fprintf(stderr, "\t-4\tGenerate G.721 32kbps (4-bit) data [default]\n"); +fprintf(stderr, "\t-5\tGenerate G.723 40kbps (5-bit) data\n"); +fprintf(stderr, "\t-a\tProcess 8-bit A-law input data\n"); +fprintf(stderr, "\t-u\tProcess 8-bit u-law input data [default]\n"); +fprintf(stderr, "\t-l\tProcess 16-bit linear PCM input data\n"); + exit(1); + } + argc--; + argv++; + } + + /* Read input file and process */ + while (fread(in_buf, in_size, 1, stdin) == 1) { + code = (*enc_routine)(in_size == 2 ? sample_short : sample_char, + in_coding, &state); + resid = pack_output(code, enc_bits); + } + + /* Write zero codes until all residual codes are written out */ + while (resid) { + resid = pack_output(0, enc_bits); + } + fclose(stdout); +} diff --git a/gnuradio-core/src/lib/g72x/g711.c b/gnuradio-core/src/lib/g72x/g711.c new file mode 100644 index 0000000000..d4d60a5c26 --- /dev/null +++ b/gnuradio-core/src/lib/g72x/g711.c @@ -0,0 +1,283 @@ +/* + * This source code is a product of Sun Microsystems, Inc. and is provided + * for unrestricted use. Users may copy or modify this source code without + * charge. + * + * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING + * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun source code is provided with no support and without any obligation on + * the part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * g711.c + * + * u-law, A-law and linear PCM conversions. + */ +#define SIGN_BIT (0x80) /* Sign bit for a A-law byte. */ +#define QUANT_MASK (0xf) /* Quantization field mask. */ +#define NSEGS (8) /* Number of A-law segments. */ +#define SEG_SHIFT (4) /* Left shift for segment number. */ +#define SEG_MASK (0x70) /* Segment field mask. */ + +static short seg_end[8] = {0xFF, 0x1FF, 0x3FF, 0x7FF, + 0xFFF, 0x1FFF, 0x3FFF, 0x7FFF}; + +/* copy from CCITT G.711 specifications */ +unsigned char _u2a[128] = { /* u- to A-law conversions */ + 1, 1, 2, 2, 3, 3, 4, 4, + 5, 5, 6, 6, 7, 7, 8, 8, + 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, + 25, 27, 29, 31, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, + 46, 48, 49, 50, 51, 52, 53, 54, + 55, 56, 57, 58, 59, 60, 61, 62, + 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, + 81, 82, 83, 84, 85, 86, 87, 88, + 89, 90, 91, 92, 93, 94, 95, 96, + 97, 98, 99, 100, 101, 102, 103, 104, + 105, 106, 107, 108, 109, 110, 111, 112, + 113, 114, 115, 116, 117, 118, 119, 120, + 121, 122, 123, 124, 125, 126, 127, 128}; + +unsigned char _a2u[128] = { /* A- to u-law conversions */ + 1, 3, 5, 7, 9, 11, 13, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, + 32, 32, 33, 33, 34, 34, 35, 35, + 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 48, 49, 49, + 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62, 63, 64, 64, + 65, 66, 67, 68, 69, 70, 71, 72, + 73, 74, 75, 76, 77, 78, 79, 79, + 80, 81, 82, 83, 84, 85, 86, 87, + 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, + 104, 105, 106, 107, 108, 109, 110, 111, + 112, 113, 114, 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127}; + +static int +search( + int val, + short *table, + int size) +{ + int i; + + for (i = 0; i < size; i++) { + if (val <= *table++) + return (i); + } + return (size); +} + +/* + * linear2alaw() - Convert a 16-bit linear PCM value to 8-bit A-law + * + * linear2alaw() accepts an 16-bit integer and encodes it as A-law data. + * + * Linear Input Code Compressed Code + * ------------------------ --------------- + * 0000000wxyza 000wxyz + * 0000001wxyza 001wxyz + * 000001wxyzab 010wxyz + * 00001wxyzabc 011wxyz + * 0001wxyzabcd 100wxyz + * 001wxyzabcde 101wxyz + * 01wxyzabcdef 110wxyz + * 1wxyzabcdefg 111wxyz + * + * For further information see John C. Bellamy's Digital Telephony, 1982, + * John Wiley & Sons, pps 98-111 and 472-476. + */ +unsigned char +linear2alaw( + int pcm_val) /* 2's complement (16-bit range) */ +{ + int mask; + int seg; + unsigned char aval; + + if (pcm_val >= 0) { + mask = 0xD5; /* sign (7th) bit = 1 */ + } else { + mask = 0x55; /* sign bit = 0 */ + pcm_val = -pcm_val - 8; + } + + /* Convert the scaled magnitude to segment number. */ + seg = search(pcm_val, seg_end, 8); + + /* Combine the sign, segment, and quantization bits. */ + + if (seg >= 8) /* out of range, return maximum value. */ + return (0x7F ^ mask); + else { + aval = seg << SEG_SHIFT; + if (seg < 2) + aval |= (pcm_val >> 4) & QUANT_MASK; + else + aval |= (pcm_val >> (seg + 3)) & QUANT_MASK; + return (aval ^ mask); + } +} + +/* + * alaw2linear() - Convert an A-law value to 16-bit linear PCM + * + */ +int +alaw2linear( + unsigned char a_val) +{ + int t; + int seg; + + a_val ^= 0x55; + + t = (a_val & QUANT_MASK) << 4; + seg = ((unsigned)a_val & SEG_MASK) >> SEG_SHIFT; + switch (seg) { + case 0: + t += 8; + break; + case 1: + t += 0x108; + break; + default: + t += 0x108; + t <<= seg - 1; + } + return ((a_val & SIGN_BIT) ? t : -t); +} + +#define BIAS (0x84) /* Bias for linear code. */ + +/* + * linear2ulaw() - Convert a linear PCM value to u-law + * + * In order to simplify the encoding process, the original linear magnitude + * is biased by adding 33 which shifts the encoding range from (0 - 8158) to + * (33 - 8191). The result can be seen in the following encoding table: + * + * Biased Linear Input Code Compressed Code + * ------------------------ --------------- + * 00000001wxyza 000wxyz + * 0000001wxyzab 001wxyz + * 000001wxyzabc 010wxyz + * 00001wxyzabcd 011wxyz + * 0001wxyzabcde 100wxyz + * 001wxyzabcdef 101wxyz + * 01wxyzabcdefg 110wxyz + * 1wxyzabcdefgh 111wxyz + * + * Each biased linear code has a leading 1 which identifies the segment + * number. The value of the segment number is equal to 7 minus the number + * of leading 0's. The quantization interval is directly available as the + * four bits wxyz. * The trailing bits (a - h) are ignored. + * + * Ordinarily the complement of the resulting code word is used for + * transmission, and so the code word is complemented before it is returned. + * + * For further information see John C. Bellamy's Digital Telephony, 1982, + * John Wiley & Sons, pps 98-111 and 472-476. + */ +unsigned char +linear2ulaw( + int pcm_val) /* 2's complement (16-bit range) */ +{ + int mask; + int seg; + unsigned char uval; + + /* Get the sign and the magnitude of the value. */ + if (pcm_val < 0) { + pcm_val = BIAS - pcm_val; + mask = 0x7F; + } else { + pcm_val += BIAS; + mask = 0xFF; + } + + /* Convert the scaled magnitude to segment number. */ + seg = search(pcm_val, seg_end, 8); + + /* + * Combine the sign, segment, quantization bits; + * and complement the code word. + */ + if (seg >= 8) /* out of range, return maximum value. */ + return (0x7F ^ mask); + else { + uval = (seg << 4) | ((pcm_val >> (seg + 3)) & 0xF); + return (uval ^ mask); + } + +} + +/* + * ulaw2linear() - Convert a u-law value to 16-bit linear PCM + * + * First, a biased linear code is derived from the code word. An unbiased + * output can then be obtained by subtracting 33 from the biased code. + * + * Note that this function expects to be passed the complement of the + * original code word. This is in keeping with ISDN conventions. + */ +int +ulaw2linear( + unsigned char u_val) +{ + int t; + + /* Complement to obtain normal u-law value. */ + u_val = ~u_val; + + /* + * Extract and bias the quantization bits. Then + * shift up by the segment number and subtract out the bias. + */ + t = ((u_val & QUANT_MASK) << 3) + BIAS; + t <<= ((unsigned)u_val & SEG_MASK) >> SEG_SHIFT; + + return ((u_val & SIGN_BIT) ? (BIAS - t) : (t - BIAS)); +} + +/* A-law to u-law conversion */ +unsigned char +alaw2ulaw( + unsigned char aval) +{ + aval &= 0xff; + return ((aval & 0x80) ? (0xFF ^ _a2u[aval ^ 0xD5]) : + (0x7F ^ _a2u[aval ^ 0x55])); +} + +/* u-law to A-law conversion */ +unsigned char +ulaw2alaw( + unsigned char uval) +{ + uval &= 0xff; + return ((uval & 0x80) ? (0xD5 ^ (_u2a[0xFF ^ uval] - 1)) : + (0x55 ^ (_u2a[0x7F ^ uval] - 1))); +} diff --git a/gnuradio-core/src/lib/g72x/g721.c b/gnuradio-core/src/lib/g72x/g721.c new file mode 100644 index 0000000000..445f177e84 --- /dev/null +++ b/gnuradio-core/src/lib/g72x/g721.c @@ -0,0 +1,173 @@ +/* + * This source code is a product of Sun Microsystems, Inc. and is provided + * for unrestricted use. Users may copy or modify this source code without + * charge. + * + * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING + * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun source code is provided with no support and without any obligation on + * the part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * g721.c + * + * Description: + * + * g721_encoder(), g721_decoder() + * + * These routines comprise an implementation of the CCITT G.721 ADPCM + * coding algorithm. Essentially, this implementation is identical to + * the bit level description except for a few deviations which + * take advantage of work station attributes, such as hardware 2's + * complement arithmetic and large memory. Specifically, certain time + * consuming operations such as multiplications are replaced + * with lookup tables and software 2's complement operations are + * replaced with hardware 2's complement. + * + * The deviation from the bit level specification (lookup tables) + * preserves the bit level performance specifications. + * + * As outlined in the G.721 Recommendation, the algorithm is broken + * down into modules. Each section of code below is preceded by + * the name of the module which it is implementing. + * + */ +#include "g72x.h" + +static short qtab_721[7] = {-124, 80, 178, 246, 300, 349, 400}; +/* + * Maps G.721 code word to reconstructed scale factor normalized log + * magnitude values. + */ +static short _dqlntab[16] = {-2048, 4, 135, 213, 273, 323, 373, 425, + 425, 373, 323, 273, 213, 135, 4, -2048}; + +/* Maps G.721 code word to log of scale factor multiplier. */ +static short _witab[16] = {-12, 18, 41, 64, 112, 198, 355, 1122, + 1122, 355, 198, 112, 64, 41, 18, -12}; +/* + * Maps G.721 code words to a set of values whose long and short + * term averages are computed and then compared to give an indication + * how stationary (steady state) the signal is. + */ +static short _fitab[16] = {0, 0, 0, 0x200, 0x200, 0x200, 0x600, 0xE00, + 0xE00, 0x600, 0x200, 0x200, 0x200, 0, 0, 0}; + +/* + * g721_encoder() + * + * Encodes the input vale of linear PCM, A-law or u-law data sl and returns + * the resulting code. -1 is returned for unknown input coding value. + */ +int +g721_encoder( + int sl, + int in_coding, + struct g72x_state *state_ptr) +{ + short sezi, se, sez; /* ACCUM */ + short d; /* SUBTA */ + short sr; /* ADDB */ + short y; /* MIX */ + short dqsez; /* ADDC */ + short dq, i; + + switch (in_coding) { /* linearize input sample to 14-bit PCM */ + case AUDIO_ENCODING_ALAW: + sl = alaw2linear(sl) >> 2; + break; + case AUDIO_ENCODING_ULAW: + sl = ulaw2linear(sl) >> 2; + break; + case AUDIO_ENCODING_LINEAR: + sl >>= 2; /* 14-bit dynamic range */ + break; + default: + return (-1); + } + + sezi = predictor_zero(state_ptr); + sez = sezi >> 1; + se = (sezi + predictor_pole(state_ptr)) >> 1; /* estimated signal */ + + d = sl - se; /* estimation difference */ + + /* quantize the prediction difference */ + y = step_size(state_ptr); /* quantizer step size */ + i = quantize(d, y, qtab_721, 7); /* i = ADPCM code */ + + dq = reconstruct(i & 8, _dqlntab[i], y); /* quantized est diff */ + + sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconst. signal */ + + dqsez = sr + sez - se; /* pole prediction diff. */ + + update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr); + + return (i); +} + +/* + * g721_decoder() + * + * Description: + * + * Decodes a 4-bit code of G.721 encoded data of i and + * returns the resulting linear PCM, A-law or u-law value. + * return -1 for unknown out_coding value. + */ +int +g721_decoder( + int i, + int out_coding, + struct g72x_state *state_ptr) +{ + short sezi, sei, sez, se; /* ACCUM */ + short y; /* MIX */ + short sr; /* ADDB */ + short dq; + short dqsez; + + i &= 0x0f; /* mask to get proper bits */ + sezi = predictor_zero(state_ptr); + sez = sezi >> 1; + sei = sezi + predictor_pole(state_ptr); + se = sei >> 1; /* se = estimated signal */ + + y = step_size(state_ptr); /* dynamic quantizer step size */ + + dq = reconstruct(i & 0x08, _dqlntab[i], y); /* quantized diff. */ + + sr = (dq < 0) ? (se - (dq & 0x3FFF)) : se + dq; /* reconst. signal */ + + dqsez = sr - se + sez; /* pole prediction diff. */ + + update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr); + + switch (out_coding) { + case AUDIO_ENCODING_ALAW: + return (tandem_adjust_alaw(sr, se, y, i, 8, qtab_721)); + case AUDIO_ENCODING_ULAW: + return (tandem_adjust_ulaw(sr, se, y, i, 8, qtab_721)); + case AUDIO_ENCODING_LINEAR: + return (sr << 2); /* sr was 14-bit dynamic range */ + default: + return (-1); + } +} diff --git a/gnuradio-core/src/lib/g72x/g723_24.c b/gnuradio-core/src/lib/g72x/g723_24.c new file mode 100644 index 0000000000..452f4daebe --- /dev/null +++ b/gnuradio-core/src/lib/g72x/g723_24.c @@ -0,0 +1,158 @@ +/* + * This source code is a product of Sun Microsystems, Inc. and is provided + * for unrestricted use. Users may copy or modify this source code without + * charge. + * + * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING + * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun source code is provided with no support and without any obligation on + * the part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * g723_24.c + * + * Description: + * + * g723_24_encoder(), g723_24_decoder() + * + * These routines comprise an implementation of the CCITT G.723 24 Kbps + * ADPCM coding algorithm. Essentially, this implementation is identical to + * the bit level description except for a few deviations which take advantage + * of workstation attributes, such as hardware 2's complement arithmetic. + * + */ +#include "g72x.h" + +/* + * Maps G.723_24 code word to reconstructed scale factor normalized log + * magnitude values. + */ +static short _dqlntab[8] = {-2048, 135, 273, 373, 373, 273, 135, -2048}; + +/* Maps G.723_24 code word to log of scale factor multiplier. */ +static short _witab[8] = {-128, 960, 4384, 18624, 18624, 4384, 960, -128}; + +/* + * Maps G.723_24 code words to a set of values whose long and short + * term averages are computed and then compared to give an indication + * how stationary (steady state) the signal is. + */ +static short _fitab[8] = {0, 0x200, 0x400, 0xE00, 0xE00, 0x400, 0x200, 0}; + +static short qtab_723_24[3] = {8, 218, 331}; + +/* + * g723_24_encoder() + * + * Encodes a linear PCM, A-law or u-law input sample and returns its 3-bit code. + * Returns -1 if invalid input coding value. + */ +int +g723_24_encoder( + int sl, + int in_coding, + struct g72x_state *state_ptr) +{ + short sei, sezi, se, sez; /* ACCUM */ + short d; /* SUBTA */ + short y; /* MIX */ + short sr; /* ADDB */ + short dqsez; /* ADDC */ + short dq, i; + + switch (in_coding) { /* linearize input sample to 14-bit PCM */ + case AUDIO_ENCODING_ALAW: + sl = alaw2linear(sl) >> 2; + break; + case AUDIO_ENCODING_ULAW: + sl = ulaw2linear(sl) >> 2; + break; + case AUDIO_ENCODING_LINEAR: + sl >>= 2; /* sl of 14-bit dynamic range */ + break; + default: + return (-1); + } + + sezi = predictor_zero(state_ptr); + sez = sezi >> 1; + sei = sezi + predictor_pole(state_ptr); + se = sei >> 1; /* se = estimated signal */ + + d = sl - se; /* d = estimation diff. */ + + /* quantize prediction difference d */ + y = step_size(state_ptr); /* quantizer step size */ + i = quantize(d, y, qtab_723_24, 3); /* i = ADPCM code */ + dq = reconstruct(i & 4, _dqlntab[i], y); /* quantized diff. */ + + sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconstructed signal */ + + dqsez = sr + sez - se; /* pole prediction diff. */ + + update(3, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr); + + return (i); +} + +/* + * g723_24_decoder() + * + * Decodes a 3-bit CCITT G.723_24 ADPCM code and returns + * the resulting 16-bit linear PCM, A-law or u-law sample value. + * -1 is returned if the output coding is unknown. + */ +int +g723_24_decoder( + int i, + int out_coding, + struct g72x_state *state_ptr) +{ + short sezi, sei, sez, se; /* ACCUM */ + short y; /* MIX */ + short sr; /* ADDB */ + short dq; + short dqsez; + + i &= 0x07; /* mask to get proper bits */ + sezi = predictor_zero(state_ptr); + sez = sezi >> 1; + sei = sezi + predictor_pole(state_ptr); + se = sei >> 1; /* se = estimated signal */ + + y = step_size(state_ptr); /* adaptive quantizer step size */ + dq = reconstruct(i & 0x04, _dqlntab[i], y); /* unquantize pred diff */ + + sr = (dq < 0) ? (se - (dq & 0x3FFF)) : (se + dq); /* reconst. signal */ + + dqsez = sr - se + sez; /* pole prediction diff. */ + + update(3, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr); + + switch (out_coding) { + case AUDIO_ENCODING_ALAW: + return (tandem_adjust_alaw(sr, se, y, i, 4, qtab_723_24)); + case AUDIO_ENCODING_ULAW: + return (tandem_adjust_ulaw(sr, se, y, i, 4, qtab_723_24)); + case AUDIO_ENCODING_LINEAR: + return (sr << 2); /* sr was of 14-bit dynamic range */ + default: + return (-1); + } +} diff --git a/gnuradio-core/src/lib/g72x/g723_40.c b/gnuradio-core/src/lib/g72x/g723_40.c new file mode 100644 index 0000000000..4858baf40b --- /dev/null +++ b/gnuradio-core/src/lib/g72x/g723_40.c @@ -0,0 +1,178 @@ +/* + * This source code is a product of Sun Microsystems, Inc. and is provided + * for unrestricted use. Users may copy or modify this source code without + * charge. + * + * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING + * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun source code is provided with no support and without any obligation on + * the part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * g723_40.c + * + * Description: + * + * g723_40_encoder(), g723_40_decoder() + * + * These routines comprise an implementation of the CCITT G.723 40Kbps + * ADPCM coding algorithm. Essentially, this implementation is identical to + * the bit level description except for a few deviations which + * take advantage of workstation attributes, such as hardware 2's + * complement arithmetic. + * + * The deviation from the bit level specification (lookup tables), + * preserves the bit level performance specifications. + * + * As outlined in the G.723 Recommendation, the algorithm is broken + * down into modules. Each section of code below is preceded by + * the name of the module which it is implementing. + * + */ +#include "g72x.h" + +/* + * Maps G.723_40 code word to ructeconstructed scale factor normalized log + * magnitude values. + */ +static short _dqlntab[32] = {-2048, -66, 28, 104, 169, 224, 274, 318, + 358, 395, 429, 459, 488, 514, 539, 566, + 566, 539, 514, 488, 459, 429, 395, 358, + 318, 274, 224, 169, 104, 28, -66, -2048}; + +/* Maps G.723_40 code word to log of scale factor multiplier. */ +static short _witab[32] = {448, 448, 768, 1248, 1280, 1312, 1856, 3200, + 4512, 5728, 7008, 8960, 11456, 14080, 16928, 22272, + 22272, 16928, 14080, 11456, 8960, 7008, 5728, 4512, + 3200, 1856, 1312, 1280, 1248, 768, 448, 448}; + +/* + * Maps G.723_40 code words to a set of values whose long and short + * term averages are computed and then compared to give an indication + * how stationary (steady state) the signal is. + */ +static short _fitab[32] = {0, 0, 0, 0, 0, 0x200, 0x200, 0x200, + 0x200, 0x200, 0x400, 0x600, 0x800, 0xA00, 0xC00, 0xC00, + 0xC00, 0xC00, 0xA00, 0x800, 0x600, 0x400, 0x200, 0x200, + 0x200, 0x200, 0x200, 0, 0, 0, 0, 0}; + +static short qtab_723_40[15] = {-122, -16, 68, 139, 198, 250, 298, 339, + 378, 413, 445, 475, 502, 528, 553}; + +/* + * g723_40_encoder() + * + * Encodes a 16-bit linear PCM, A-law or u-law input sample and retuens + * the resulting 5-bit CCITT G.723 40Kbps code. + * Returns -1 if the input coding value is invalid. + */ +int +g723_40_encoder( + int sl, + int in_coding, + struct g72x_state *state_ptr) +{ + short sei, sezi, se, sez; /* ACCUM */ + short d; /* SUBTA */ + short y; /* MIX */ + short sr; /* ADDB */ + short dqsez; /* ADDC */ + short dq, i; + + switch (in_coding) { /* linearize input sample to 14-bit PCM */ + case AUDIO_ENCODING_ALAW: + sl = alaw2linear(sl) >> 2; + break; + case AUDIO_ENCODING_ULAW: + sl = ulaw2linear(sl) >> 2; + break; + case AUDIO_ENCODING_LINEAR: + sl >>= 2; /* sl of 14-bit dynamic range */ + break; + default: + return (-1); + } + + sezi = predictor_zero(state_ptr); + sez = sezi >> 1; + sei = sezi + predictor_pole(state_ptr); + se = sei >> 1; /* se = estimated signal */ + + d = sl - se; /* d = estimation difference */ + + /* quantize prediction difference */ + y = step_size(state_ptr); /* adaptive quantizer step size */ + i = quantize(d, y, qtab_723_40, 15); /* i = ADPCM code */ + + dq = reconstruct(i & 0x10, _dqlntab[i], y); /* quantized diff */ + + sr = (dq < 0) ? se - (dq & 0x7FFF) : se + dq; /* reconstructed signal */ + + dqsez = sr + sez - se; /* dqsez = pole prediction diff. */ + + update(5, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr); + + return (i); +} + +/* + * g723_40_decoder() + * + * Decodes a 5-bit CCITT G.723 40Kbps code and returns + * the resulting 16-bit linear PCM, A-law or u-law sample value. + * -1 is returned if the output coding is unknown. + */ +int +g723_40_decoder( + int i, + int out_coding, + struct g72x_state *state_ptr) +{ + short sezi, sei, sez, se; /* ACCUM */ + short y; /* MIX */ + short sr; /* ADDB */ + short dq; + short dqsez; + + i &= 0x1f; /* mask to get proper bits */ + sezi = predictor_zero(state_ptr); + sez = sezi >> 1; + sei = sezi + predictor_pole(state_ptr); + se = sei >> 1; /* se = estimated signal */ + + y = step_size(state_ptr); /* adaptive quantizer step size */ + dq = reconstruct(i & 0x10, _dqlntab[i], y); /* estimation diff. */ + + sr = (dq < 0) ? (se - (dq & 0x7FFF)) : (se + dq); /* reconst. signal */ + + dqsez = sr - se + sez; /* pole prediction diff. */ + + update(5, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr); + + switch (out_coding) { + case AUDIO_ENCODING_ALAW: + return (tandem_adjust_alaw(sr, se, y, i, 0x10, qtab_723_40)); + case AUDIO_ENCODING_ULAW: + return (tandem_adjust_ulaw(sr, se, y, i, 0x10, qtab_723_40)); + case AUDIO_ENCODING_LINEAR: + return (sr << 2); /* sr was of 14-bit dynamic range */ + default: + return (-1); + } +} diff --git a/gnuradio-core/src/lib/g72x/g72x.c b/gnuradio-core/src/lib/g72x/g72x.c new file mode 100644 index 0000000000..9a823c7555 --- /dev/null +++ b/gnuradio-core/src/lib/g72x/g72x.c @@ -0,0 +1,576 @@ +/* + * This source code is a product of Sun Microsystems, Inc. and is provided + * for unrestricted use. Users may copy or modify this source code without + * charge. + * + * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING + * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun source code is provided with no support and without any obligation on + * the part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +#include <stdlib.h> +/* + * g72x.c + * + * Common routines for G.721 and G.723 conversions. + */ + +#include "g72x.h" + +static short power2[15] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, + 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000}; + +/* + * quan() + * + * quantizes the input val against the table of size short integers. + * It returns i if table[i - 1] <= val < table[i]. + * + * Using linear search for simple coding. + */ +static int +quan( + int val, + short *table, + int size) +{ + int i; + + for (i = 0; i < size; i++) + if (val < *table++) + break; + return (i); +} + +/* + * fmult() + * + * returns the integer product of the 14-bit integer "an" and + * "floating point" representation (4-bit exponent, 6-bit mantessa) "srn". + */ +static int +fmult( + int an, + int srn) +{ + short anmag, anexp, anmant; + short wanexp, wanmant; + short retval; + + anmag = (an > 0) ? an : ((-an) & 0x1FFF); + anexp = quan(anmag, power2, 15) - 6; + anmant = (anmag == 0) ? 32 : + (anexp >= 0) ? anmag >> anexp : anmag << -anexp; + wanexp = anexp + ((srn >> 6) & 0xF) - 13; + + wanmant = (anmant * (srn & 077) + 0x30) >> 4; + retval = (wanexp >= 0) ? ((wanmant << wanexp) & 0x7FFF) : + (wanmant >> -wanexp); + + return (((an ^ srn) < 0) ? -retval : retval); +} + +/* + * g72x_init_state() + * + * This routine initializes and/or resets the g72x_state structure + * pointed to by 'state_ptr'. + * All the initial state values are specified in the CCITT G.721 document. + */ +void +g72x_init_state( + struct g72x_state *state_ptr) +{ + int cnta; + + state_ptr->yl = 34816; + state_ptr->yu = 544; + state_ptr->dms = 0; + state_ptr->dml = 0; + state_ptr->ap = 0; + for (cnta = 0; cnta < 2; cnta++) { + state_ptr->a[cnta] = 0; + state_ptr->pk[cnta] = 0; + state_ptr->sr[cnta] = 32; + } + for (cnta = 0; cnta < 6; cnta++) { + state_ptr->b[cnta] = 0; + state_ptr->dq[cnta] = 32; + } + state_ptr->td = 0; +} + +/* + * predictor_zero() + * + * computes the estimated signal from 6-zero predictor. + * + */ +int +predictor_zero( + struct g72x_state *state_ptr) +{ + int i; + int sezi; + + sezi = fmult(state_ptr->b[0] >> 2, state_ptr->dq[0]); + for (i = 1; i < 6; i++) /* ACCUM */ + sezi += fmult(state_ptr->b[i] >> 2, state_ptr->dq[i]); + return (sezi); +} +/* + * predictor_pole() + * + * computes the estimated signal from 2-pole predictor. + * + */ +int +predictor_pole( + struct g72x_state *state_ptr) +{ + return (fmult(state_ptr->a[1] >> 2, state_ptr->sr[1]) + + fmult(state_ptr->a[0] >> 2, state_ptr->sr[0])); +} +/* + * step_size() + * + * computes the quantization step size of the adaptive quantizer. + * + */ +int +step_size( + struct g72x_state *state_ptr) +{ + int y; + int dif; + int al; + + if (state_ptr->ap >= 256) + return (state_ptr->yu); + else { + y = state_ptr->yl >> 6; + dif = state_ptr->yu - y; + al = state_ptr->ap >> 2; + if (dif > 0) + y += (dif * al) >> 6; + else if (dif < 0) + y += (dif * al + 0x3F) >> 6; + return (y); + } +} + +/* + * quantize() + * + * Given a raw sample, 'd', of the difference signal and a + * quantization step size scale factor, 'y', this routine returns the + * ADPCM codeword to which that sample gets quantized. The step + * size scale factor division operation is done in the log base 2 domain + * as a subtraction. + */ +int +quantize( + int d, /* Raw difference signal sample */ + int y, /* Step size multiplier */ + short *table, /* quantization table */ + int size) /* table size of short integers */ +{ + short dqm; /* Magnitude of 'd' */ + short exp; /* Integer part of base 2 log of 'd' */ + short mant; /* Fractional part of base 2 log */ + short dl; /* Log of magnitude of 'd' */ + short dln; /* Step size scale factor normalized log */ + int i; + + /* + * LOG + * + * Compute base 2 log of 'd', and store in 'dl'. + */ + dqm = abs(d); + exp = quan(dqm >> 1, power2, 15); + mant = ((dqm << 7) >> exp) & 0x7F; /* Fractional portion. */ + dl = (exp << 7) + mant; + + /* + * SUBTB + * + * "Divide" by step size multiplier. + */ + dln = dl - (y >> 2); + + /* + * QUAN + * + * Obtain codword i for 'd'. + */ + i = quan(dln, table, size); + if (d < 0) /* take 1's complement of i */ + return ((size << 1) + 1 - i); + else if (i == 0) /* take 1's complement of 0 */ + return ((size << 1) + 1); /* new in 1988 */ + else + return (i); +} +/* + * reconstruct() + * + * Returns reconstructed difference signal 'dq' obtained from + * codeword 'i' and quantization step size scale factor 'y'. + * Multiplication is performed in log base 2 domain as addition. + */ +int +reconstruct( + int sign, /* 0 for non-negative value */ + int dqln, /* G.72x codeword */ + int y) /* Step size multiplier */ +{ + short dql; /* Log of 'dq' magnitude */ + short dex; /* Integer part of log */ + short dqt; + short dq; /* Reconstructed difference signal sample */ + + dql = dqln + (y >> 2); /* ADDA */ + + if (dql < 0) { + return ((sign) ? -0x8000 : 0); + } else { /* ANTILOG */ + dex = (dql >> 7) & 15; + dqt = 128 + (dql & 127); + dq = (dqt << 7) >> (14 - dex); + return ((sign) ? (dq - 0x8000) : dq); + } +} + + +/* + * update() + * + * updates the state variables for each output code + */ +void +update( + int code_size, /* distinguish 723_40 with others */ + int y, /* quantizer step size */ + int wi, /* scale factor multiplier */ + int fi, /* for long/short term energies */ + int dq, /* quantized prediction difference */ + int sr, /* reconstructed signal */ + int dqsez, /* difference from 2-pole predictor */ + struct g72x_state *state_ptr) /* coder state pointer */ +{ + int cnt; + short mag, exp; /* Adaptive predictor, FLOAT A */ + short a2p = 0; /* LIMC */ + short a1ul; /* UPA1 */ + short pks1; /* UPA2 */ + short fa1; + char tr; /* tone/transition detector */ + short ylint, thr2, dqthr; + short ylfrac, thr1; + short pk0; + + pk0 = (dqsez < 0) ? 1 : 0; /* needed in updating predictor poles */ + + mag = dq & 0x7FFF; /* prediction difference magnitude */ + /* TRANS */ + ylint = state_ptr->yl >> 15; /* exponent part of yl */ + ylfrac = (state_ptr->yl >> 10) & 0x1F; /* fractional part of yl */ + thr1 = (32 + ylfrac) << ylint; /* threshold */ + thr2 = (ylint > 9) ? 31 << 10 : thr1; /* limit thr2 to 31 << 10 */ + dqthr = (thr2 + (thr2 >> 1)) >> 1; /* dqthr = 0.75 * thr2 */ + if (state_ptr->td == 0) /* signal supposed voice */ + tr = 0; + else if (mag <= dqthr) /* supposed data, but small mag */ + tr = 0; /* treated as voice */ + else /* signal is data (modem) */ + tr = 1; + + /* + * Quantizer scale factor adaptation. + */ + + /* FUNCTW & FILTD & DELAY */ + /* update non-steady state step size multiplier */ + state_ptr->yu = y + ((wi - y) >> 5); + + /* LIMB */ + if (state_ptr->yu < 544) /* 544 <= yu <= 5120 */ + state_ptr->yu = 544; + else if (state_ptr->yu > 5120) + state_ptr->yu = 5120; + + /* FILTE & DELAY */ + /* update steady state step size multiplier */ + state_ptr->yl += state_ptr->yu + ((-state_ptr->yl) >> 6); + + /* + * Adaptive predictor coefficients. + */ + if (tr == 1) { /* reset a's and b's for modem signal */ + state_ptr->a[0] = 0; + state_ptr->a[1] = 0; + state_ptr->b[0] = 0; + state_ptr->b[1] = 0; + state_ptr->b[2] = 0; + state_ptr->b[3] = 0; + state_ptr->b[4] = 0; + state_ptr->b[5] = 0; + } else { /* update a's and b's */ + pks1 = pk0 ^ state_ptr->pk[0]; /* UPA2 */ + + /* update predictor pole a[1] */ + a2p = state_ptr->a[1] - (state_ptr->a[1] >> 7); + if (dqsez != 0) { + fa1 = (pks1) ? state_ptr->a[0] : -state_ptr->a[0]; + if (fa1 < -8191) /* a2p = function of fa1 */ + a2p -= 0x100; + else if (fa1 > 8191) + a2p += 0xFF; + else + a2p += fa1 >> 5; + + if (pk0 ^ state_ptr->pk[1]) + /* LIMC */ + if (a2p <= -12160) + a2p = -12288; + else if (a2p >= 12416) + a2p = 12288; + else + a2p -= 0x80; + else if (a2p <= -12416) + a2p = -12288; + else if (a2p >= 12160) + a2p = 12288; + else + a2p += 0x80; + } + + /* TRIGB & DELAY */ + state_ptr->a[1] = a2p; + + /* UPA1 */ + /* update predictor pole a[0] */ + state_ptr->a[0] -= state_ptr->a[0] >> 8; + if (dqsez != 0){ + if (pks1 == 0) + state_ptr->a[0] += 192; + else + state_ptr->a[0] -= 192; + } + + /* LIMD */ + a1ul = 15360 - a2p; + if (state_ptr->a[0] < -a1ul) + state_ptr->a[0] = -a1ul; + else if (state_ptr->a[0] > a1ul) + state_ptr->a[0] = a1ul; + + /* UPB : update predictor zeros b[6] */ + for (cnt = 0; cnt < 6; cnt++) { + if (code_size == 5) /* for 40Kbps G.723 */ + state_ptr->b[cnt] -= state_ptr->b[cnt] >> 9; + else /* for G.721 and 24Kbps G.723 */ + state_ptr->b[cnt] -= state_ptr->b[cnt] >> 8; + if (dq & 0x7FFF) { /* XOR */ + if ((dq ^ state_ptr->dq[cnt]) >= 0) + state_ptr->b[cnt] += 128; + else + state_ptr->b[cnt] -= 128; + } + } + } + + for (cnt = 5; cnt > 0; cnt--) + state_ptr->dq[cnt] = state_ptr->dq[cnt-1]; + /* FLOAT A : convert dq[0] to 4-bit exp, 6-bit mantissa f.p. */ + if (mag == 0) { + state_ptr->dq[0] = (dq >= 0) ? 0x20 : 0xFC20; + } else { + exp = quan(mag, power2, 15); + state_ptr->dq[0] = (dq >= 0) ? + (exp << 6) + ((mag << 6) >> exp) : + (exp << 6) + ((mag << 6) >> exp) - 0x400; + } + + state_ptr->sr[1] = state_ptr->sr[0]; + /* FLOAT B : convert sr to 4-bit exp., 6-bit mantissa f.p. */ + if (sr == 0) { + state_ptr->sr[0] = 0x20; + } else if (sr > 0) { + exp = quan(sr, power2, 15); + state_ptr->sr[0] = (exp << 6) + ((sr << 6) >> exp); + } else if (sr > -32768) { + mag = -sr; + exp = quan(mag, power2, 15); + state_ptr->sr[0] = (exp << 6) + ((mag << 6) >> exp) - 0x400; + } else + state_ptr->sr[0] = 0xFC20; + + /* DELAY A */ + state_ptr->pk[1] = state_ptr->pk[0]; + state_ptr->pk[0] = pk0; + + /* TONE */ + if (tr == 1) /* this sample has been treated as data */ + state_ptr->td = 0; /* next one will be treated as voice */ + else if (a2p < -11776) /* small sample-to-sample correlation */ + state_ptr->td = 1; /* signal may be data */ + else /* signal is voice */ + state_ptr->td = 0; + + /* + * Adaptation speed control. + */ + state_ptr->dms += (fi - state_ptr->dms) >> 5; /* FILTA */ + state_ptr->dml += (((fi << 2) - state_ptr->dml) >> 7); /* FILTB */ + + if (tr == 1) + state_ptr->ap = 256; + else if (y < 1536) /* SUBTC */ + state_ptr->ap += (0x200 - state_ptr->ap) >> 4; + else if (state_ptr->td == 1) + state_ptr->ap += (0x200 - state_ptr->ap) >> 4; + else if (abs((state_ptr->dms << 2) - state_ptr->dml) >= + (state_ptr->dml >> 3)) + state_ptr->ap += (0x200 - state_ptr->ap) >> 4; + else + state_ptr->ap += (-state_ptr->ap) >> 4; +} + +/* + * tandem_adjust(sr, se, y, i, sign) + * + * At the end of ADPCM decoding, it simulates an encoder which may be receiving + * the output of this decoder as a tandem process. If the output of the + * simulated encoder differs from the input to this decoder, the decoder output + * is adjusted by one level of A-law or u-law codes. + * + * Input: + * sr decoder output linear PCM sample, + * se predictor estimate sample, + * y quantizer step size, + * i decoder input code, + * sign sign bit of code i + * + * Return: + * adjusted A-law or u-law compressed sample. + */ +int +tandem_adjust_alaw( + int sr, /* decoder output linear PCM sample */ + int se, /* predictor estimate sample */ + int y, /* quantizer step size */ + int i, /* decoder input code */ + int sign, + short *qtab) +{ + unsigned char sp; /* A-law compressed 8-bit code */ + short dx; /* prediction error */ + char id; /* quantized prediction error */ + int sd; /* adjusted A-law decoded sample value */ + int im; /* biased magnitude of i */ + int imx; /* biased magnitude of id */ + + if (sr <= -32768) + sr = -1; + sp = linear2alaw((sr >> 1) << 3); /* short to A-law compression */ + dx = (alaw2linear(sp) >> 2) - se; /* 16-bit prediction error */ + id = quantize(dx, y, qtab, sign - 1); + + if (id == i) { /* no adjustment on sp */ + return (sp); + } else { /* sp adjustment needed */ + /* ADPCM codes : 8, 9, ... F, 0, 1, ... , 6, 7 */ + im = i ^ sign; /* 2's complement to biased unsigned */ + imx = id ^ sign; + + if (imx > im) { /* sp adjusted to next lower value */ + if (sp & 0x80) { + sd = (sp == 0xD5) ? 0x55 : + ((sp ^ 0x55) - 1) ^ 0x55; + } else { + sd = (sp == 0x2A) ? 0x2A : + ((sp ^ 0x55) + 1) ^ 0x55; + } + } else { /* sp adjusted to next higher value */ + if (sp & 0x80) + sd = (sp == 0xAA) ? 0xAA : + ((sp ^ 0x55) + 1) ^ 0x55; + else + sd = (sp == 0x55) ? 0xD5 : + ((sp ^ 0x55) - 1) ^ 0x55; + } + return (sd); + } +} + +int +tandem_adjust_ulaw( + int sr, /* decoder output linear PCM sample */ + int se, /* predictor estimate sample */ + int y, /* quantizer step size */ + int i, /* decoder input code */ + int sign, + short *qtab) +{ + unsigned char sp; /* u-law compressed 8-bit code */ + short dx; /* prediction error */ + char id; /* quantized prediction error */ + int sd; /* adjusted u-law decoded sample value */ + int im; /* biased magnitude of i */ + int imx; /* biased magnitude of id */ + + if (sr <= -32768) + sr = 0; + sp = linear2ulaw(sr << 2); /* short to u-law compression */ + dx = (ulaw2linear(sp) >> 2) - se; /* 16-bit prediction error */ + id = quantize(dx, y, qtab, sign - 1); + if (id == i) { + return (sp); + } else { + /* ADPCM codes : 8, 9, ... F, 0, 1, ... , 6, 7 */ + im = i ^ sign; /* 2's complement to biased unsigned */ + imx = id ^ sign; + if (imx > im) { /* sp adjusted to next lower value */ + if (sp & 0x80) + sd = (sp == 0xFF) ? 0x7E : sp + 1; + else + sd = (sp == 0) ? 0 : sp - 1; + + } else { /* sp adjusted to next higher value */ + if (sp & 0x80) + sd = (sp == 0x80) ? 0x80 : sp - 1; + else + sd = (sp == 0x7F) ? 0xFE : sp + 1; + } + return (sd); + } +} + + + + + + + + + + + + diff --git a/gnuradio-core/src/lib/g72x/g72x.h b/gnuradio-core/src/lib/g72x/g72x.h new file mode 100644 index 0000000000..33807171aa --- /dev/null +++ b/gnuradio-core/src/lib/g72x/g72x.h @@ -0,0 +1,156 @@ +/* + * This source code is a product of Sun Microsystems, Inc. and is provided + * for unrestricted use. Users may copy or modify this source code without + * charge. + * + * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING + * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun source code is provided with no support and without any obligation on + * the part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * g72x.h + * + * Header file for CCITT conversion routines. + * + */ +#ifndef _G72X_H +#define _G72X_H + +#define AUDIO_ENCODING_ULAW (1) /* ISDN u-law */ +#define AUDIO_ENCODING_ALAW (2) /* ISDN A-law */ +#define AUDIO_ENCODING_LINEAR (3) /* PCM 2's-complement (0-center) */ + +/* + * The following is the definition of the state structure + * used by the G.721/G.723 encoder and decoder to preserve their internal + * state between successive calls. The meanings of the majority + * of the state structure fields are explained in detail in the + * CCITT Recommendation G.721. The field names are essentially indentical + * to variable names in the bit level description of the coding algorithm + * included in this Recommendation. + */ +struct g72x_state { + long yl; /* Locked or steady state step size multiplier. */ + short yu; /* Unlocked or non-steady state step size multiplier. */ + short dms; /* Short term energy estimate. */ + short dml; /* Long term energy estimate. */ + short ap; /* Linear weighting coefficient of 'yl' and 'yu'. */ + + short a[2]; /* Coefficients of pole portion of prediction filter. */ + short b[6]; /* Coefficients of zero portion of prediction filter. */ + short pk[2]; /* + * Signs of previous two samples of a partially + * reconstructed signal. + */ + short dq[6]; /* + * Previous 6 samples of the quantized difference + * signal represented in an internal floating point + * format. + */ + short sr[2]; /* + * Previous 2 samples of the quantized difference + * signal represented in an internal floating point + * format. + */ + char td; /* delayed tone detect, new in 1988 version */ +}; + +/* External function definitions. */ + +extern void g72x_init_state(struct g72x_state *); +extern int g721_encoder( + int sample, + int in_coding, + struct g72x_state *state_ptr); +extern int g721_decoder( + int code, + int out_coding, + struct g72x_state *state_ptr); +extern int g723_24_encoder( + int sample, + int in_coding, + struct g72x_state *state_ptr); +extern int g723_24_decoder( + int code, + int out_coding, + struct g72x_state *state_ptr); +extern int g723_40_encoder( + int sample, + int in_coding, + struct g72x_state *state_ptr); +extern int g723_40_decoder( + int code, + int out_coding, + struct g72x_state *state_ptr); + + +extern int +quantize( + int d, + int y, + short *table, + int size); +extern int reconstruct(int,int,int);void + +extern update( + int code_size, + int y, + int wi, + int fi, + int dq, + int sr, + int dqsez, + struct g72x_state *state_ptr); +extern int +tandem_adjust_alaw( + int sr, + int se, + int y, + int i, + int sign, + short *qtab); + +extern int +tandem_adjust_ulaw( + int sr, + int se, + int y, + int i, + int sign, + short *qtab); + +extern unsigned char +linear2alaw( + int pcm_val); + +extern int +alaw2linear( + unsigned char a_val); + +extern unsigned char +linear2ulaw(int pcm_val); + +extern int ulaw2linear( unsigned char u_val); + +extern int predictor_zero(struct g72x_state *state_ptr); + +extern int predictor_pole( struct g72x_state *state_ptr); +extern int step_size( struct g72x_state *state_ptr); +#endif /* !_G72X_H */ diff --git a/gnuradio-core/src/lib/general/Makefile.am b/gnuradio-core/src/lib/general/Makefile.am new file mode 100644 index 0000000000..a240cc9175 --- /dev/null +++ b/gnuradio-core/src/lib/general/Makefile.am @@ -0,0 +1,440 @@ +# +# Copyright 2001,2002,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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(CPPUNIT_INCLUDES) + +noinst_LTLIBRARIES = libgeneral.la libgeneral-qa.la + +# ---------------------------------------------------------------- +# these scripts generate code + +CODE_GENERATOR = \ + generate_all.py \ + generate_common.py \ + gr_add_XX.cc.t \ + gr_add_XX.h.t \ + gr_add_XX.i.t \ + gr_add_const_XX.cc.t \ + gr_add_const_XX.h.t \ + gr_add_const_XX.i.t \ + gr_chunks_to_symbols_XX.cc.t \ + gr_chunks_to_symbols_XX.h.t \ + gr_chunks_to_symbols_XX.i.t \ + gr_divide_XX.cc.t \ + gr_divide_XX.h.t \ + gr_divide_XX.i.t \ + gr_multiply_XX.cc.t \ + gr_multiply_XX.h.t \ + gr_multiply_XX.i.t \ + gr_multiply_const_XX.cc.t \ + gr_multiply_const_XX.h.t \ + gr_multiply_const_XX.i.t \ + gr_mute_XX.cc.t \ + gr_mute_XX.h.t \ + gr_mute_XX.i.t \ + gr_noise_source_X.cc.t \ + gr_noise_source_X.h.t \ + gr_noise_source_X.i.t \ + gr_packed_to_unpacked_XX.cc.t \ + gr_packed_to_unpacked_XX.h.t \ + gr_packed_to_unpacked_XX.i.t \ + gr_sig_source_X.cc.t \ + gr_sig_source_X.h.t \ + gr_sig_source_X.i.t \ + gr_sub_XX.cc.t \ + gr_sub_XX.h.t \ + gr_sub_XX.i.t \ + gr_unpacked_to_packed_XX.cc.t \ + gr_unpacked_to_packed_XX.h.t \ + gr_unpacked_to_packed_XX.i.t \ + gr_vector_source_X.cc.t \ + gr_vector_source_X.h.t \ + gr_vector_source_X.i.t \ + gr_vector_sink_X.cc.t \ + gr_vector_sink_X.h.t \ + gr_vector_sink_X.i.t + +# include $(srcdir)/Makefile.gen +include Makefile.gen + + +$(GENERATED_H) $(GENERATED_I) $(GENERATED_CC): $(CODE_GENERATOR) + PYTHONPATH=$(top_srcdir)/gnuradio-core/src/python srcdir=$(srcdir) $(srcdir)/generate_all.py + + +BUILT_SOURCES = $(GENERATED_H) $(GENERATED_I) $(GENERATED_CC) + +# ---------------------------------------------------------------- + +EXTRA_DIST = \ + $(CODE_GENERATOR) \ + gen_sine_table.py \ + gr_prefix.cc.in + +libgeneral_la_SOURCES = \ + $(GENERATED_CC) \ + gr_agc_cc.cc \ + gr_agc_ff.cc \ + gr_align_on_samplenumbers_ss.cc \ + gr_binary_slicer_fb.cc \ + gr_bytes_to_syms.cc \ + gr_char_to_float.cc \ + gr_check_counting_s.cc \ + gr_check_lfsr_32k_s.cc \ + gr_circular_file.cc \ + gr_clock_recovery_mm_cc.cc \ + gr_clock_recovery_mm_ff.cc \ + gr_complex_to_interleaved_short.cc \ + gr_complex_to_xxx.cc \ + gr_conjugate_cc.cc \ + gr_constellation_decoder_cb.cc \ + gr_correlate_access_code_bb.cc \ + gr_costas_loop_cc.cc \ + gr_count_bits.cc \ + gr_crc32.cc \ + gr_ctcss_squelch_ff.cc \ + gr_dd_mpsk_sync_cc.cc \ + gr_deinterleave.cc \ + gr_diff_decoder_bb.cc \ + gr_diff_encoder_bb.cc \ + gr_diff_phasor_cc.cc \ + gr_fake_channel_coder_pp.cc \ + gr_fast_atan2f.cc \ + gr_feval.cc \ + gr_fft_vcc.cc \ + gr_fft_vfc.cc \ + gr_firdes.cc \ + gr_float_to_char.cc \ + gr_float_to_complex.cc \ + gr_float_to_short.cc \ + gr_float_to_uchar.cc \ + gr_frequency_modulator_fc.cc \ + gr_fxpt.cc \ + gr_framer_sink_1.cc \ + gr_head.cc \ + gr_interleave.cc \ + gr_interleaved_short_to_complex.cc \ + gr_keep_one_in_n.cc \ + gr_kludge_copy.cc \ + gr_lfsr_32k_source_s.cc \ + gr_lms_dfe_cc.cc \ + gr_lms_dfe_ff.cc \ + gr_map_bb.cc \ + gr_math.cc \ + gr_misc.cc \ + gr_nlog10_ff.cc \ + gr_nop.cc \ + gr_null_sink.cc \ + gr_null_source.cc \ + gr_pa_2x2_phase_combiner.cc \ + gr_packet_sink.cc \ + gr_phase_modulator_fc.cc \ + gr_pll_carriertracking_cc.cc \ + gr_pll_freqdet_cf.cc \ + gr_pll_refout_cc.cc \ + gr_prefix.cc \ + gr_prefs.cc \ + gr_probe_avg_mag_sqrd_c.cc \ + gr_probe_avg_mag_sqrd_f.cc \ + gr_probe_signal_f.cc \ + gr_pwr_squelch_cc.cc \ + gr_pwr_squelch_ff.cc \ + gr_quadrature_demod_cf.cc \ + gr_random.cc \ + gr_remez.cc \ + gr_reverse.cc \ + gr_rms_cf.cc \ + gr_rms_ff.cc \ + gr_short_to_float.cc \ + gr_simple_correlator.cc \ + gr_simple_framer.cc \ + gr_simple_squelch_cc.cc \ + gr_skiphead.cc \ + gr_squelch_base_cc.cc \ + gr_squelch_base_ff.cc \ + gr_stream_to_streams.cc \ + gr_stream_to_vector.cc \ + gr_streams_to_stream.cc \ + gr_streams_to_vector.cc \ + gr_sync_block.cc \ + gr_sync_decimator.cc \ + gr_sync_interpolator.cc \ + gr_test.cc \ + gr_threshold_ff.cc \ + gr_throttle.cc \ + gr_uchar_to_float.cc \ + gr_vco_f.cc \ + gr_vector_to_stream.cc \ + gr_vector_to_streams.cc \ + gri_add_const_ss_generic.cc \ + gri_char_to_float.cc \ + gri_debugger_hook.cc \ + gri_fft.cc \ + gri_float_to_char.cc \ + gri_float_to_short.cc \ + gri_float_to_uchar.cc \ + gri_interleaved_short_to_complex.cc \ + gri_short_to_float.cc \ + gri_uchar_to_float.cc \ + malloc16.c \ + gr_unpack_k_bits_bb.cc + +libgeneral_qa_la_SOURCES = \ + qa_general.cc \ + qa_gr_circular_file.cc \ + qa_gr_firdes.cc \ + qa_gr_fxpt.cc \ + qa_gr_fxpt_nco.cc \ + qa_gr_fxpt_vco.cc + + + +grinclude_HEADERS = \ + $(GENERATED_H) \ + gr_agc_cc.h \ + gr_agc_ff.h \ + gr_align_on_samplenumbers_ss.h \ + gr_binary_slicer_fb.h \ + gr_bytes_to_syms.h \ + gr_char_to_float.h \ + gr_check_counting_s.h \ + gr_check_lfsr_32k_s.h \ + gr_circular_file.h \ + gr_clock_recovery_mm_cc.h \ + gr_clock_recovery_mm_ff.h \ + gr_complex_to_interleaved_short.h \ + gr_complex_to_xxx.h \ + gr_conjugate_cc.h \ + gr_constellation_decoder_cb.h \ + gr_correlate_access_code_bb.h \ + gr_costas_loop_cc.h \ + gr_count_bits.h \ + gr_crc32.h \ + gr_ctcss_squelch_ff.h \ + gr_dd_mpsk_sync_cc.h \ + gr_diff_decoder_bb.h \ + gr_diff_encoder_bb.h \ + gr_deinterleave.h \ + gr_diff_phasor_cc.h \ + gr_endianness.h \ + gr_expj.h \ + gr_fake_channel_coder_pp.h \ + gr_feval.h \ + gr_fft_vcc.h \ + gr_fft_vfc.h \ + gr_firdes.h \ + gr_float_to_char.h \ + gr_float_to_complex.h \ + gr_float_to_short.h \ + gr_float_to_uchar.h \ + gr_framer_sink_1.h \ + gr_frequency_modulator_fc.h \ + gr_fxpt.h \ + gr_fxpt_nco.h \ + gr_fxpt_vco.h \ + gr_head.h \ + gr_interleave.h \ + gr_interleaved_short_to_complex.h \ + gr_keep_one_in_n.h \ + gr_kludge_copy.h \ + gr_lfsr_32k_source_s.h \ + gr_lms_dfe_cc.h \ + gr_lms_dfe_ff.h \ + gr_log2_const.h \ + gr_map_bb.h \ + gr_math.h \ + gr_misc.h \ + gr_nco.h \ + gr_nlog10_ff.h \ + gr_noise_type.h \ + gr_nop.h \ + gr_null_sink.h \ + gr_null_source.h \ + gr_pa_2x2_phase_combiner.h \ + gr_packet_sink.h \ + gr_phase_modulator_fc.h \ + gr_pll_carriertracking_cc.h \ + gr_pll_freqdet_cf.h \ + gr_pll_refout_cc.h \ + gr_prefix.h \ + gr_prefs.h \ + gr_probe_avg_mag_sqrd_c.h \ + gr_probe_avg_mag_sqrd_f.h \ + gr_probe_signal_f.h \ + gr_pwr_squelch_cc.h \ + gr_pwr_squelch_ff.h \ + gr_quadrature_demod_cf.h \ + gr_random.h \ + gr_remez.h \ + gr_reverse.h \ + gr_rms_cf.h \ + gr_rms_ff.h \ + gr_short_to_float.h \ + gr_sig_source_waveform.h \ + gr_simple_correlator.h \ + gr_simple_framer.h \ + gr_simple_framer_sync.h \ + gr_simple_squelch_cc.h \ + gr_skiphead.h \ + gr_squelch_base_cc.h \ + gr_squelch_base_ff.h \ + gr_stream_to_streams.h \ + gr_stream_to_vector.h \ + gr_streams_to_stream.h \ + gr_streams_to_vector.h \ + gr_sync_block.h \ + gr_sync_decimator.h \ + gr_sync_interpolator.h \ + gr_test_types.h \ + gr_test.h \ + gr_threshold_ff.h \ + gr_throttle.h \ + gr_uchar_to_float.h \ + gr_vco.h \ + gr_vco_f.h \ + gr_vector_to_stream.h \ + gr_vector_to_streams.h \ + gri_add_const_ss.h \ + gri_agc.h \ + gri_agc_cc.h \ + gri_char_to_float.h \ + gri_debugger_hook.h \ + gri_fft.h \ + gri_float_to_char.h \ + gri_float_to_short.h \ + gri_float_to_uchar.h \ + gri_interleaved_short_to_complex.h \ + gri_lfsr_15_1_0.h \ + gri_lfsr_32k.h \ + gri_short_to_float.h \ + gri_uchar_to_float.h \ + malloc16.h \ + random.h \ + gr_unpack_k_bits_bb.h + + +noinst_HEADERS = \ + qa_general.h \ + qa_gr_circular_file.h \ + qa_gr_firdes.h \ + qa_gr_fxpt.h \ + qa_gr_fxpt_nco.h \ + qa_gr_fxpt_vco.h \ + sine_table.h + +swiginclude_HEADERS = \ + $(GENERATED_I) \ + general.i \ + general_generated.i \ + gr_agc_cc.i \ + gr_agc_ff.i \ + gr_align_on_samplenumbers_ss.i \ + gr_binary_slicer_fb.i \ + gr_bytes_to_syms.i \ + gr_char_to_float.i \ + gr_check_counting_s.i \ + gr_check_lfsr_32k_s.i \ + gr_clock_recovery_mm_cc.i \ + gr_clock_recovery_mm_ff.i \ + gr_complex_to_interleaved_short.i \ + gr_complex_to_xxx.i \ + gr_conjugate_cc.i \ + gr_constellation_decoder_cb.i \ + gr_correlate_access_code_bb.i \ + gr_costas_loop_cc.i \ + gr_crc32.i \ + gr_ctcss_squelch_ff.i \ + gr_dd_mpsk_sync_cc.i \ + gr_diff_decoder_bb.i \ + gr_diff_encoder_bb.i \ + gr_diff_phasor_cc.i \ + gr_deinterleave.i \ + gr_endianness.i \ + gr_fake_channel_coder_pp.i \ + gr_feval.i \ + gr_fft_vcc.i \ + gr_fft_vfc.i \ + gr_firdes.i \ + gr_float_to_char.i \ + gr_float_to_complex.i \ + gr_float_to_short.i \ + gr_float_to_uchar.i \ + gr_frequency_modulator_fc.i \ + gr_framer_sink_1.i \ + gr_head.i \ + gr_interleave.i \ + gr_interleaved_short_to_complex.i \ + gr_keep_one_in_n.i \ + gr_kludge_copy.i \ + gr_lfsr_32k_source_s.i \ + gr_lms_dfe_cc.i \ + gr_lms_dfe_ff.i \ + gr_map_bb.i \ + gr_nlog10_ff.i \ + gr_nop.i \ + gr_null_sink.i \ + gr_null_source.i \ + gr_pa_2x2_phase_combiner.i \ + gr_packet_sink.i \ + gr_phase_modulator_fc.i \ + gr_pll_carriertracking_cc.i \ + gr_pll_freqdet_cf.i \ + gr_pll_refout_cc.i \ + gr_prefix.i \ + gr_prefs.i \ + gr_probe_avg_mag_sqrd_c.i \ + gr_probe_avg_mag_sqrd_f.i \ + gr_probe_signal_f.i \ + gr_pwr_squelch_cc.i \ + gr_pwr_squelch_ff.i \ + gr_quadrature_demod_cf.i \ + gr_remez.i \ + gr_rms_cf.i \ + gr_rms_ff.i \ + gr_short_to_float.i \ + gr_simple_correlator.i \ + gr_simple_framer.i \ + gr_simple_squelch_cc.i \ + gr_skiphead.i \ + gr_squelch_base_cc.i \ + gr_squelch_base_ff.i \ + gr_stream_to_streams.i \ + gr_stream_to_vector.i \ + gr_streams_to_stream.i \ + gr_streams_to_vector.i \ + gr_sync_block.i \ + gr_sync_decimator.i \ + gr_sync_interpolator.i \ + gr_test.i \ + gr_threshold_ff.i \ + gr_throttle.i \ + gr_uchar_to_float.i \ + gr_vco_f.i \ + gr_vector_to_stream.i \ + gr_vector_to_streams.i \ + gri_agc.i \ + gri_agc_cc.i \ + gr_unpack_k_bits_bb.i + + +CLEANFILES = $(BUILT_SOURCES) *.pyc diff --git a/gnuradio-core/src/lib/general/Makefile.gen b/gnuradio-core/src/lib/general/Makefile.gen new file mode 100644 index 0000000000..f0c477e3d0 --- /dev/null +++ b/gnuradio-core/src/lib/general/Makefile.gen @@ -0,0 +1,234 @@ +# +# This file is machine generated. All edits will be overwritten +# +GENERATED_H = \ + gr_add_cc.h \ + gr_add_const_cc.h \ + gr_add_const_ff.h \ + gr_add_const_ii.h \ + gr_add_const_sf.h \ + gr_add_const_ss.h \ + gr_add_const_vcc.h \ + gr_add_const_vff.h \ + gr_add_const_vii.h \ + gr_add_const_vss.h \ + gr_add_ff.h \ + gr_add_ii.h \ + gr_add_ss.h \ + gr_add_vcc.h \ + gr_add_vff.h \ + gr_add_vii.h \ + gr_add_vss.h \ + gr_chunks_to_symbols_bc.h \ + gr_chunks_to_symbols_bf.h \ + gr_chunks_to_symbols_ic.h \ + gr_chunks_to_symbols_if.h \ + gr_chunks_to_symbols_sc.h \ + gr_chunks_to_symbols_sf.h \ + gr_divide_cc.h \ + gr_divide_ff.h \ + gr_divide_ii.h \ + gr_divide_ss.h \ + gr_multiply_cc.h \ + gr_multiply_const_cc.h \ + gr_multiply_const_ff.h \ + gr_multiply_const_ii.h \ + gr_multiply_const_ss.h \ + gr_multiply_const_vcc.h \ + gr_multiply_const_vff.h \ + gr_multiply_const_vii.h \ + gr_multiply_const_vss.h \ + gr_multiply_ff.h \ + gr_multiply_ii.h \ + gr_multiply_ss.h \ + gr_multiply_vcc.h \ + gr_multiply_vff.h \ + gr_multiply_vii.h \ + gr_multiply_vss.h \ + gr_mute_cc.h \ + gr_mute_ff.h \ + gr_mute_ii.h \ + gr_mute_ss.h \ + gr_noise_source_c.h \ + gr_noise_source_f.h \ + gr_noise_source_i.h \ + gr_noise_source_s.h \ + gr_packed_to_unpacked_bb.h \ + gr_packed_to_unpacked_ii.h \ + gr_packed_to_unpacked_ss.h \ + gr_sig_source_c.h \ + gr_sig_source_f.h \ + gr_sig_source_i.h \ + gr_sig_source_s.h \ + gr_sub_cc.h \ + gr_sub_ff.h \ + gr_sub_ii.h \ + gr_sub_ss.h \ + gr_unpacked_to_packed_bb.h \ + gr_unpacked_to_packed_ii.h \ + gr_unpacked_to_packed_ss.h \ + gr_vector_sink_b.h \ + gr_vector_sink_c.h \ + gr_vector_sink_f.h \ + gr_vector_sink_i.h \ + gr_vector_sink_s.h \ + gr_vector_source_b.h \ + gr_vector_source_c.h \ + gr_vector_source_f.h \ + gr_vector_source_i.h \ + gr_vector_source_s.h + +GENERATED_I = \ + gr_add_cc.i \ + gr_add_const_cc.i \ + gr_add_const_ff.i \ + gr_add_const_ii.i \ + gr_add_const_sf.i \ + gr_add_const_ss.i \ + gr_add_const_vcc.i \ + gr_add_const_vff.i \ + gr_add_const_vii.i \ + gr_add_const_vss.i \ + gr_add_ff.i \ + gr_add_ii.i \ + gr_add_ss.i \ + gr_add_vcc.i \ + gr_add_vff.i \ + gr_add_vii.i \ + gr_add_vss.i \ + gr_chunks_to_symbols_bc.i \ + gr_chunks_to_symbols_bf.i \ + gr_chunks_to_symbols_ic.i \ + gr_chunks_to_symbols_if.i \ + gr_chunks_to_symbols_sc.i \ + gr_chunks_to_symbols_sf.i \ + gr_divide_cc.i \ + gr_divide_ff.i \ + gr_divide_ii.i \ + gr_divide_ss.i \ + gr_multiply_cc.i \ + gr_multiply_const_cc.i \ + gr_multiply_const_ff.i \ + gr_multiply_const_ii.i \ + gr_multiply_const_ss.i \ + gr_multiply_const_vcc.i \ + gr_multiply_const_vff.i \ + gr_multiply_const_vii.i \ + gr_multiply_const_vss.i \ + gr_multiply_ff.i \ + gr_multiply_ii.i \ + gr_multiply_ss.i \ + gr_multiply_vcc.i \ + gr_multiply_vff.i \ + gr_multiply_vii.i \ + gr_multiply_vss.i \ + gr_mute_cc.i \ + gr_mute_ff.i \ + gr_mute_ii.i \ + gr_mute_ss.i \ + gr_noise_source_c.i \ + gr_noise_source_f.i \ + gr_noise_source_i.i \ + gr_noise_source_s.i \ + gr_packed_to_unpacked_bb.i \ + gr_packed_to_unpacked_ii.i \ + gr_packed_to_unpacked_ss.i \ + gr_sig_source_c.i \ + gr_sig_source_f.i \ + gr_sig_source_i.i \ + gr_sig_source_s.i \ + gr_sub_cc.i \ + gr_sub_ff.i \ + gr_sub_ii.i \ + gr_sub_ss.i \ + gr_unpacked_to_packed_bb.i \ + gr_unpacked_to_packed_ii.i \ + gr_unpacked_to_packed_ss.i \ + gr_vector_sink_b.i \ + gr_vector_sink_c.i \ + gr_vector_sink_f.i \ + gr_vector_sink_i.i \ + gr_vector_sink_s.i \ + gr_vector_source_b.i \ + gr_vector_source_c.i \ + gr_vector_source_f.i \ + gr_vector_source_i.i \ + gr_vector_source_s.i + +GENERATED_CC = \ + gr_add_cc.cc \ + gr_add_const_cc.cc \ + gr_add_const_ff.cc \ + gr_add_const_ii.cc \ + gr_add_const_sf.cc \ + gr_add_const_ss.cc \ + gr_add_const_vcc.cc \ + gr_add_const_vff.cc \ + gr_add_const_vii.cc \ + gr_add_const_vss.cc \ + gr_add_ff.cc \ + gr_add_ii.cc \ + gr_add_ss.cc \ + gr_add_vcc.cc \ + gr_add_vff.cc \ + gr_add_vii.cc \ + gr_add_vss.cc \ + gr_chunks_to_symbols_bc.cc \ + gr_chunks_to_symbols_bf.cc \ + gr_chunks_to_symbols_ic.cc \ + gr_chunks_to_symbols_if.cc \ + gr_chunks_to_symbols_sc.cc \ + gr_chunks_to_symbols_sf.cc \ + gr_divide_cc.cc \ + gr_divide_ff.cc \ + gr_divide_ii.cc \ + gr_divide_ss.cc \ + gr_multiply_cc.cc \ + gr_multiply_const_cc.cc \ + gr_multiply_const_ff.cc \ + gr_multiply_const_ii.cc \ + gr_multiply_const_ss.cc \ + gr_multiply_const_vcc.cc \ + gr_multiply_const_vff.cc \ + gr_multiply_const_vii.cc \ + gr_multiply_const_vss.cc \ + gr_multiply_ff.cc \ + gr_multiply_ii.cc \ + gr_multiply_ss.cc \ + gr_multiply_vcc.cc \ + gr_multiply_vff.cc \ + gr_multiply_vii.cc \ + gr_multiply_vss.cc \ + gr_mute_cc.cc \ + gr_mute_ff.cc \ + gr_mute_ii.cc \ + gr_mute_ss.cc \ + gr_noise_source_c.cc \ + gr_noise_source_f.cc \ + gr_noise_source_i.cc \ + gr_noise_source_s.cc \ + gr_packed_to_unpacked_bb.cc \ + gr_packed_to_unpacked_ii.cc \ + gr_packed_to_unpacked_ss.cc \ + gr_sig_source_c.cc \ + gr_sig_source_f.cc \ + gr_sig_source_i.cc \ + gr_sig_source_s.cc \ + gr_sub_cc.cc \ + gr_sub_ff.cc \ + gr_sub_ii.cc \ + gr_sub_ss.cc \ + gr_unpacked_to_packed_bb.cc \ + gr_unpacked_to_packed_ii.cc \ + gr_unpacked_to_packed_ss.cc \ + gr_vector_sink_b.cc \ + gr_vector_sink_c.cc \ + gr_vector_sink_f.cc \ + gr_vector_sink_i.cc \ + gr_vector_sink_s.cc \ + gr_vector_source_b.cc \ + gr_vector_source_c.cc \ + gr_vector_source_f.cc \ + gr_vector_source_i.cc \ + gr_vector_source_s.cc + diff --git a/gnuradio-core/src/lib/general/README b/gnuradio-core/src/lib/general/README new file mode 100644 index 0000000000..26d829f1be --- /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 0000000000..3466412fb4 --- /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 0000000000..94445e96ec --- /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 0000000000..ca7812cbfc --- /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/gen_sine_table.py b/gnuradio-core/src/lib/general/gen_sine_table.py new file mode 100755 index 0000000000..06a5e7c8ef --- /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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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 0000000000..3f410a9ead --- /dev/null +++ b/gnuradio-core/src/lib/general/general.i @@ -0,0 +1,203 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%{ + +#include <gr_sync_block.h> +#include <gr_sync_decimator.h> +#include <gr_sync_interpolator.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_sig_source_waveform.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_fft_vcc.h> +#include <gr_fft_vfc.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_char_to_float.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_firdes.h> +#include <gr_interleave.h> +#include <gr_deinterleave.h> +#include <gr_simple_squelch_cc.h> +#include <gr_agc_ff.h> +#include <gr_agc_cc.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_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_crc32.h> +#include <gr_threshold_ff.h> +#include <gr_clock_recovery_mm_ff.h> +#include <gr_clock_recovery_mm_cc.h> +#include <gr_dd_mpsk_sync_cc.h> +#include <gr_packet_sink.h> +#include <gr_lms_dfe_cc.h> +#include <gr_lms_dfe_ff.h> +#include <gr_pll_freqdet_cf.h> +#include <gr_pll_refout_cc.h> +#include <gr_pll_carriertracking_cc.h> +#include <gr_probe_avg_mag_sqrd_c.h> +#include <gr_probe_avg_mag_sqrd_f.h> +#include <gr_probe_signal_f.h> +#include <gr_costas_loop_cc.h> +#include <gr_pa_2x2_phase_combiner.h> +#include <gr_kludge_copy.h> +#include <gr_prefs.h> +#include <gr_prefix.h> +#include <gr_test_types.h> +#include <gr_test.h> +#include <gr_unpack_k_bits_bb.h> +#include <gr_correlate_access_code_bb.h> +#include <gr_diff_phasor_cc.h> +#include <gr_constellation_decoder_cb.h> +#include <gr_binary_slicer_fb.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_feval.h> +#include <gr_pwr_squelch_cc.h> +#include <gr_pwr_squelch_ff.h> +#include <gr_ctcss_squelch_ff.h> +%} + +%include "gr_sync_block.i" +%include "gr_sync_decimator.i" +%include "gr_sync_interpolator.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_sig_source_waveform.h" +%include "gr_noise_type.h" +%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_fft_vcc.i" +%include "gr_fft_vfc.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_char_to_float.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_interleaved_short_to_complex.i" +%include "gr_firdes.i" +%include "gr_interleave.i" +%include "gr_deinterleave.i" +%include "gr_simple_squelch_cc.i" +%include "gr_agc_ff.i" +%include "gr_agc_cc.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_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_crc32.i" +%include "gr_threshold_ff.i" +%include "gr_clock_recovery_mm_ff.i" +%include "gr_clock_recovery_mm_cc.i" +%include "gr_dd_mpsk_sync_cc.i" +%include "gr_packet_sink.i" +%include "gr_lms_dfe_cc.i" +%include "gr_lms_dfe_ff.i" +%include "gr_pll_freqdet_cf.i" +%include "gr_pll_refout_cc.i" +%include "gr_pll_carriertracking_cc.i" +%include "gr_probe_avg_mag_sqrd_c.i" +%include "gr_probe_avg_mag_sqrd_f.i" +%include "gr_probe_signal_f.i" +%include "gr_costas_loop_cc.i" +%include "gr_pa_2x2_phase_combiner.i" +%include "gr_kludge_copy.i" +%include "gr_prefs.i" +%include "gr_prefix.i" +%include "gr_test_types.h" +%include "gr_test.i" +%include "gr_unpack_k_bits_bb.i" +%include "gr_correlate_access_code_bb.i" +%include "gr_diff_phasor_cc.i" +%include "gr_constellation_decoder_cb.i" +%include "gr_binary_slicer_fb.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_feval.i" +%include "gr_pwr_squelch_cc.i" +%include "gr_pwr_squelch_ff.i" +%include "gr_ctcss_squelch_ff.i" + +%include "general_generated.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 0000000000..a41f30a3da --- /dev/null +++ b/gnuradio-core/src/lib/general/general_generated.i @@ -0,0 +1,156 @@ +// +// 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_ff.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_cc.h> +#include <gr_multiply_const_cc.h> +#include <gr_multiply_const_ff.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_ff.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_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_ff.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_cc.i> +%include <gr_multiply_const_cc.i> +%include <gr_multiply_const_ff.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_ff.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_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/generate_all.py b/gnuradio-core/src/lib/general/generate_all.py new file mode 100755 index 0000000000..1b33abb9ad --- /dev/null +++ b/gnuradio-core/src/lib/general/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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +from build_utils import output_glue + +import generate_common + +def generate_all (): + generate_common.generate () + output_glue ('general') + + +if __name__ == '__main__': + generate_all () diff --git a/gnuradio-core/src/lib/general/generate_common.py b/gnuradio-core/src/lib/general/generate_common.py new file mode 100755 index 0000000000..4616f4a979 --- /dev/null +++ b/gnuradio-core/src/lib/general/generate_common.py @@ -0,0 +1,93 @@ +#!/usr/bin/env python +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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' + ] + +# regular blocks +reg_signatures = ['ss', 'ii', 'ff', 'cc'] + +reg_roots = [ + 'gr_add_const_XX', + 'gr_multiply_const_XX', + 'gr_add_XX', + 'gr_sub_XX', + 'gr_multiply_XX', + 'gr_divide_XX', + 'gr_mute_XX', + 'gr_add_vXX', + 'gr_multiply_vXX', + 'gr_add_const_vXX', + 'gr_multiply_const_vXX' + ] + +# 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')) + ) + + +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') + 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/general/gr_add_XX.cc.t b/gnuradio-core/src/lib/general/gr_add_XX.cc.t new file mode 100644 index 0000000000..f743d87363 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_XX.cc.t @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 @SPTR_NAME@ (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 += ((@I_TYPE@ *) input_items[j])[i]; + + *optr++ = (@O_TYPE@) acc; + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_add_XX.h.t b/gnuradio-core/src/lib/general/gr_add_XX.h.t new file mode 100644 index 0000000000..1fa42e3627 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_XX.h.t @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ gr_make_@BASE_NAME@ (); + +/*! + * \brief output = sum (input_0, input_1, ...) + * \ingroup block + * + * Add across all input streams. + */ +class @NAME@ : public gr_sync_block +{ + friend @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/general/gr_add_XX.i.t b/gnuradio-core/src/lib/general/gr_add_XX.i.t new file mode 100644 index 0000000000..8479aad683 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/general/gr_add_const_XX.cc.t b/gnuradio-core/src/lib/general/gr_add_const_XX.cc.t new file mode 100644 index 0000000000..1a2cf08db0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_const_XX.cc.t @@ -0,0 +1,72 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 @SPTR_NAME@ (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/general/gr_add_const_XX.h.t b/gnuradio-core/src/lib/general/gr_add_const_XX.h.t new file mode 100644 index 0000000000..c965df3a1e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_const_XX.h.t @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ gr_make_@BASE_NAME@ (@O_TYPE@ k); + +/*! + * \brief output = input + constant + * \ingroup block + */ +class @NAME@ : public gr_sync_block +{ + friend @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/general/gr_add_const_XX.i.t b/gnuradio-core/src/lib/general/gr_add_const_XX.i.t new file mode 100644 index 0000000000..c2c814b524 --- /dev/null +++ b/gnuradio-core/src/lib/general/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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/general/gr_add_const_vXX.cc.t b/gnuradio-core/src/lib/general/gr_add_const_vXX.cc.t new file mode 100755 index 0000000000..7966331b10 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_const_vXX.cc.t @@ -0,0 +1,61 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 @SPTR_NAME@ (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/general/gr_add_const_vXX.h.t b/gnuradio-core/src/lib/general/gr_add_const_vXX.h.t new file mode 100755 index 0000000000..b42bc2d943 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_const_vXX.h.t @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ gr_make_@BASE_NAME@ (const std::vector<@I_TYPE@> k); + +/*! + * \brief output vector = input vector + constant vector + * \ingroup block + */ +class @NAME@ : public gr_sync_block +{ + friend @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/general/gr_add_const_vXX.i.t b/gnuradio-core/src/lib/general/gr_add_const_vXX.i.t new file mode 100755 index 0000000000..38c399438a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_const_vXX.i.t @@ -0,0 +1,37 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/general/gr_add_vXX.cc.t b/gnuradio-core/src/lib/general/gr_add_vXX.cc.t new file mode 100755 index 0000000000..480b4a4582 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_vXX.cc.t @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 nitems_per_block) +{ + return @SPTR_NAME@ (new @NAME@ (nitems_per_block)); +} + +@NAME@::@NAME@ (size_t nitems_per_block) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, -1, sizeof (@I_TYPE@)*nitems_per_block), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@)*nitems_per_block)) +{ +} + +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 (); + 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++){ + @I_TYPE@ acc = ((@I_TYPE@ *) input_items[0])[i*nitems_per_block+j]; + for (int k = 1; k < ninputs; k++) + acc += ((@I_TYPE@ *) input_items[k])[i*nitems_per_block+j]; + + *optr++ = (@O_TYPE@) acc; + } + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_add_vXX.h.t b/gnuradio-core/src/lib/general/gr_add_vXX.h.t new file mode 100755 index 0000000000..29a0b03b09 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_vXX.h.t @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ gr_make_@BASE_NAME@ (size_t nitems_per_block); + +/*! + * \brief output = sum (input_0, input_1, ...) + * \ingroup block + * + * Add across all input vectors. + */ +class @NAME@ : public gr_sync_block +{ + friend @SPTR_NAME@ gr_make_@BASE_NAME@ (size_t nitems_per_block); + + @NAME@ (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 diff --git a/gnuradio-core/src/lib/general/gr_add_vXX.i.t b/gnuradio-core/src/lib/general/gr_add_vXX.i.t new file mode 100755 index 0000000000..0810961039 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_add_vXX.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (size_t nitems_per_block); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (size_t nitems_per_block); +}; 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 0000000000..7249ee1525 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_agc_cc.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_agc_cc_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 0000000000..c7676a516a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_agc_cc.h @@ -0,0 +1,50 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_AGC_CC_H +#define INCLUDED_GR_AGC_CC_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_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 + * + * For Power the absolute value of the complex number is used. + */ + +class gr_agc_cc : public gr_sync_block, public gri_agc_cc +{ + friend 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 0000000000..79ebf19dda --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_agc_cc.i @@ -0,0 +1,33 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..6b0d01e7b8 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_agc_ff.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_agc_ff.h> +#include <gr_io_signature.h> +#include <gri_agc.h> + +gr_agc_ff_sptr +gr_make_agc_ff (float rate, float reference, float gain, float max_gain) +{ + return gr_agc_ff_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 (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 0000000000..da7edb7aa2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_agc_ff.h @@ -0,0 +1,50 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_AGC_FF_H +#define INCLUDED_GR_AGC_FF_H + +#include <gr_sync_block.h> +#include <gri_agc.h> +class gr_agc_ff; +typedef boost::shared_ptr<gr_agc_ff> gr_agc_ff_sptr; + +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 + * + * Power is approximated by absolute value + */ + +class gr_agc_ff : public gr_sync_block, public gri_agc +{ + friend 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 0000000000..9b6312714d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_agc_ff.i @@ -0,0 +1,33 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,agc_ff) + +%include <gri_agc.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 +{ + 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 0000000000..005b575b43 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.cc @@ -0,0 +1,461 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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> + +//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 gr_align_on_samplenumbers_ss_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 0000000000..69d68b2aac --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.h @@ -0,0 +1,89 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_ALIGN_ON_SAMPLE_NUMBERS_SS_H +#define INCLUDED_GR_ALIGN_ON_SAMPLE_NUMBERS_SS_H + +#include <gr_block.h> + +class gr_align_on_samplenumbers_ss; +typedef boost::shared_ptr<gr_align_on_samplenumbers_ss> gr_align_on_samplenumbers_ss_sptr; + +gr_align_on_samplenumbers_ss_sptr gr_make_align_on_samplenumbers_ss (int nchan=2, int align_interval=128); + +/*! + * \brief align several complex short (interleaved short) input channels with corresponding unsigned 32 bit sample_counters (provided as interleaved 16 bit values) + * \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 : public gr_block +{ + int d_align_interval; + int d_sample_counter; + int d_nchan; + bool d_in_presync; + unsigned int d_ninputs; + class 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_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 0000000000..00d3174973 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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); + +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_binary_slicer_fb.cc b/gnuradio-core/src/lib/general/gr_binary_slicer_fb.cc new file mode 100644 index 0000000000..a74746d32f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_binary_slicer_fb.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_binary_slicer_fb.h> +#include <gr_io_signature.h> +#include <stdexcept> + +gr_binary_slicer_fb_sptr +gr_make_binary_slicer_fb () +{ + return gr_binary_slicer_fb_sptr (new gr_binary_slicer_fb ()); +} + +gr_binary_slicer_fb::gr_binary_slicer_fb () + : gr_sync_block ("binary_slicer_fb", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (unsigned char))) +{ +} + +static inline int +slice(float x) +{ + return x < 0 ? 0 : 1; +} + +int +gr_binary_slicer_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; i++){ + out[i] = slice(in[i]); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_binary_slicer_fb.h b/gnuradio-core/src/lib/general/gr_binary_slicer_fb.h new file mode 100644 index 0000000000..ce755718f7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_binary_slicer_fb.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_BINARY_SLICER_FB_H +#define INCLUDED_GR_BINARY_SLICER_FB_H + +#include <gr_sync_block.h> + +class gr_binary_slicer_fb; +typedef boost::shared_ptr<gr_binary_slicer_fb> gr_binary_slicer_fb_sptr; + +gr_binary_slicer_fb_sptr gr_make_binary_slicer_fb (); + +/*! + * \brief slice float binary symbol outputting 1 bit output + * \ingroup block + * + * x < 0 --> 0 + * x >= 0 --> 1 + */ +class gr_binary_slicer_fb : public gr_sync_block +{ + friend gr_binary_slicer_fb_sptr gr_make_binary_slicer_fb (); + gr_binary_slicer_fb (); + + 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_binary_slicer_fb.i b/gnuradio-core/src/lib/general/gr_binary_slicer_fb.i new file mode 100644 index 0000000000..0d66429bf5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_binary_slicer_fb.i @@ -0,0 +1,33 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,binary_slicer_fb); + +gr_binary_slicer_fb_sptr gr_make_binary_slicer_fb (); + +class gr_binary_slicer_fb : public gr_sync_block +{ + private: + gr_binary_slicer_fb (); + + public: +}; 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 0000000000..3b492cdb94 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_bytes_to_syms.cc @@ -0,0 +1,74 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_bytes_to_syms_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 0000000000..72f844d4f9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_bytes_to_syms.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_BYTES_TO_SYMS_H +#define INCLUDED_GR_BYTES_TO_SYMS_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_bytes_to_syms_sptr gr_make_bytes_to_syms (); + +/*! + * \brief Convert stream of bytes to stream of +/- 1 symbols + * \ingroup block + * + * 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_bytes_to_syms : public gr_sync_interpolator +{ + friend 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 0000000000..33ef089d0b --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..c4151eeeec --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_char_to_float.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_char_to_float.h> +#include <gr_io_signature.h> +#include <gri_char_to_float.h> + +gr_char_to_float_sptr +gr_make_char_to_float () +{ + return gr_char_to_float_sptr (new gr_char_to_float ()); +} + +gr_char_to_float::gr_char_to_float () + : gr_sync_block ("gr_char_to_float", + gr_make_io_signature (1, 1, sizeof (char)), + gr_make_io_signature (1, 1, sizeof (float))) +{ +} + +int +gr_char_to_float::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]; + float *out = (float *) output_items[0]; + + gri_char_to_float (in, out, 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 0000000000..d2b287ff3b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_char_to_float.h @@ -0,0 +1,51 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_CHAR_TO_FLOAT_H +#define INCLUDED_GR_CHAR_TO_FLOAT_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_char_to_float_sptr +gr_make_char_to_float (); + +/*! + * \brief Convert stream of chars to a stream of float + * \ingroup converter + */ + +class gr_char_to_float : public gr_sync_block +{ + friend gr_char_to_float_sptr gr_make_char_to_float (); + gr_char_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_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 0000000000..3f1c7e19f4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_char_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,char_to_float) + +gr_char_to_float_sptr gr_make_char_to_float (); + +class gr_char_to_float : public gr_sync_block +{ + gr_char_to_float (); +}; 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 0000000000..59e740c10d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_check_counting_s.cc @@ -0,0 +1,190 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_check_counting_s_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 0000000000..3037e9f0d0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_check_counting_s.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_CHECK_COUNTING_S_H +#define INCLUDED_GR_CHECK_COUNTING_S_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_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 + * + * This sink is typically used to test the USRP "Counting Mode" or "Counting mode 32 bit". + */ +class gr_check_counting_s : public gr_sync_block +{ + friend 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 0000000000..f52f872408 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..72051cf5b5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_check_lfsr_32k_s.cc @@ -0,0 +1,169 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_check_lfsr_32k_s_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 0000000000..4b7eb8a1b0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_check_lfsr_32k_s.h @@ -0,0 +1,102 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_CHECK_LFSR_32K_S_H +#define INCLUDED_GR_CHECK_LFSR_32K_S_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_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 + * + * This sink is typically used along with gr_lfsr_32k_source_s to test + * the USRP using its digital loopback mode. + */ +class gr_check_lfsr_32k_s : public gr_sync_block +{ + friend 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 0000000000..422b7cd296 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_chunks_to_symbols_XX.cc.t b/gnuradio-core/src/lib/general/gr_chunks_to_symbols_XX.cc.t new file mode 100644 index 0000000000..a488733598 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_chunks_to_symbols_XX.cc.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <gr_io_signature.h> +#include <assert.h> +#include <iostream> + +@SPTR_NAME@ +gr_make_@BASE_NAME@ (const std::vector<@O_TYPE@> &symbol_table, const int D) +{ + return @SPTR_NAME@ (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_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/general/gr_chunks_to_symbols_XX.h.t b/gnuradio-core/src/lib/general/gr_chunks_to_symbols_XX.h.t new file mode 100644 index 0000000000..16763c9df7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_chunks_to_symbols_XX.h.t @@ -0,0 +1,72 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_sync_interpolator.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@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 block + * + * 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 @NAME@ : public gr_sync_interpolator +{ + friend @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/general/gr_chunks_to_symbols_XX.i.t b/gnuradio-core/src/lib/general/gr_chunks_to_symbols_XX.i.t new file mode 100644 index 0000000000..e67e480412 --- /dev/null +++ b/gnuradio-core/src/lib/general/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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/general/gr_circular_file.cc b/gnuradio-core/src/lib/general/gr_circular_file.cc new file mode 100644 index 0000000000..8aa8af08e4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_circular_file.cc @@ -0,0 +1,194 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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> + +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 */ + ftruncate (d_fd, size + HEADER_SIZE); +#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 0000000000..33407457cc --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_circular_file.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GR_CIRCULAR_FILE_H_ +#define _GR_CIRCULAR_FILE_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_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_ */ diff --git a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.cc b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.cc new file mode 100644 index 0000000000..0d8c7f38d1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.cc @@ -0,0 +1,182 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_io_signature.h> +#include <gr_prefs.h> +#include <gr_clock_recovery_mm_cc.h> +#include <gri_mmse_fir_interpolator_cc.h> +#include <stdexcept> + +// Public constructor + + +gr_clock_recovery_mm_cc_sptr +gr_make_clock_recovery_mm_cc(float omega, float gain_omega, float mu, float gain_mu, + float omega_relative_limit) +{ + return gr_clock_recovery_mm_cc_sptr (new gr_clock_recovery_mm_cc (omega, + gain_omega, + mu, + gain_mu, + omega_relative_limit)); +} + +gr_clock_recovery_mm_cc::gr_clock_recovery_mm_cc (float omega, float gain_omega, float mu, + float gain_mu, float omega_relative_limit) + : gr_block ("clock_recovery_mm_cc", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (gr_complex))), + d_mu (mu), d_omega(omega), d_gain_omega(gain_omega), + d_omega_relative_limit(omega_relative_limit), + d_gain_mu(gain_mu), d_last_sample(0), d_interp(new gri_mmse_fir_interpolator_cc()), + d_verbose(gr_prefs::singleton()->get_bool("clock_recovery_mm_cc", "verbose", false)), + d_p_2T(0), d_p_1T(0), d_p_0T(0), d_c_2T(0), d_c_1T(0), d_c_0T(0) +{ + if (omega <= 0.0) + throw std::out_of_range ("clock rate must be > 0"); + if (gain_mu < 0 || gain_omega < 0) + throw std::out_of_range ("Gains must be non-negative"); + + set_omega(omega); // also sets min and max omega + set_relative_rate (1.0 / omega); + set_history(3); // ensure 2 extra input sample is available +} + +gr_clock_recovery_mm_cc::~gr_clock_recovery_mm_cc () +{ + delete d_interp; +} + +void +gr_clock_recovery_mm_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_omega) + d_interp->ntaps()); +} + +gr_complex +gr_clock_recovery_mm_cc::slicer_0deg (gr_complex sample) +{ + float real=0, imag=0; + + if(sample.real() > 0) + real = 1; + if(sample.imag() > 0) + imag = 1; + return gr_complex(real,imag); +} + +gr_complex +gr_clock_recovery_mm_cc::slicer_45deg (gr_complex sample) +{ + float real= -1, imag = -1; + if(sample.real() > 0) + real=1; + if(sample.imag() > 0) + imag = 1; + return gr_complex(real,imag); +} + +/* + Modified Mueller and Muller clock recovery circuit + Based: + G. R. Danesfahani, T.G. Jeans, "Optimisation of modified Mueller and Muller + algorithm," Electronics Letters, Vol. 31, no. 13, 22 June 1995, pp. 1032 - 1033. +*/ + +static const int FUDGE = 16; + +int +gr_clock_recovery_mm_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 + int ni = ninput_items[0] - d_interp->ntaps() - FUDGE; // don't use more input than this + + assert(d_mu >= 0.0); + assert(d_mu <= 1.0); + + float mm_val=0; + gr_complex u, x, y; + + while(oo < noutput_items && ii < ni) { + d_p_2T = d_p_1T; + d_p_1T = d_p_0T; + d_p_0T = d_interp->interpolate (&in[ii], d_mu); + + d_c_2T = d_c_1T; + d_c_1T = d_c_0T; + d_c_0T = slicer_0deg(d_p_0T); + + x = (d_c_0T - d_c_2T) * conj(d_p_1T); + y = (d_p_0T - d_p_2T) * conj(d_c_1T); + u = y - x; + mm_val = u.real(); + out[oo++] = d_p_0T; + + // limit mm_val + if (mm_val > 1.0) + mm_val = 1.0; + else if (mm_val < -1.0) + mm_val = -1.0; + + d_omega = d_omega + d_gain_omega * mm_val; + if (d_omega > d_max_omega) + d_omega = d_max_omega; + else if (d_omega < d_min_omega) + d_omega = d_min_omega; + + d_mu = d_mu + d_omega + d_gain_mu * mm_val; + ii += (int)floor(d_mu); + d_mu -= floor(d_mu); + + if(d_verbose) { + printf("%f\t%f\n", d_omega, d_mu); + } + + if (ii < 0) // clamp it. This should only happen with bogus input + ii = 0; + } + + if (ii > 0){ + if (ii > ninput_items[0]){ + fprintf(stderr, "gr_clock_recovery_mm_cc: ii > ninput_items[0] (%d > %d)\n", + ii, ninput_items[0]); + assert(0); + } + consume_each (ii); + } + + return oo; +} diff --git a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.h b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.h new file mode 100644 index 0000000000..8a65ae4dd1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.h @@ -0,0 +1,105 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_CLOCK_RECOVERY_MM_CC_H +#define INCLUDED_GR_CLOCK_RECOVERY_MM_CC_H + +#include <gr_block.h> +#include <gr_complex.h> + +class gri_mmse_fir_interpolator_cc; + +class gr_clock_recovery_mm_cc; +typedef boost::shared_ptr<gr_clock_recovery_mm_cc> gr_clock_recovery_mm_cc_sptr; + +// public constructor +gr_clock_recovery_mm_cc_sptr +gr_make_clock_recovery_mm_cc (float omega, float gain_omega, float mu, float gain_mu, + float omega_relative_limit=0.001); + +/*! + * \brief Mueller and Müller (M&M) based clock recovery block with complex input, complex output. + * \ingroup block + * + * This implements the Mueller and Müller (M&M) discrete-time error-tracking synchronizer. + * + * See "Digital Communication Receivers: Synchronization, Channel + * Estimation and Signal Processing" by Heinrich Meyr, Marc Moeneclaey, & Stefan Fechtel. + * ISBN 0-471-50275-8. + */ +class gr_clock_recovery_mm_cc : public gr_block +{ + public: + ~gr_clock_recovery_mm_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 omega() const { return d_omega;} + float gain_mu() const { return d_gain_mu;} + float gain_omega() const { return d_gain_omega;} + void set_verbose (bool verbose) { d_verbose = verbose; } + + void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; } + void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; } + void set_mu (float mu) { d_mu = mu; } + void set_omega (float omega) { + d_omega = omega; + d_min_omega = omega*(1.0 - d_omega_relative_limit); + d_max_omega = omega*(1.0 + d_omega_relative_limit); + } + +protected: + gr_clock_recovery_mm_cc (float omega, float gain_omega, float mu, float gain_mu, + float omega_relative_limi); + + private: + float d_mu; + float d_omega; + float d_gain_omega; + float d_min_omega; // minimum allowed omega + float d_max_omega; // maximum allowed omeg + float d_omega_relative_limit; // used to compute min and max omega + float d_gain_mu; + gr_complex d_last_sample; + gri_mmse_fir_interpolator_cc *d_interp; + bool d_verbose; + + gr_complex d_p_2T; + gr_complex d_p_1T; + gr_complex d_p_0T; + + gr_complex d_c_2T; + gr_complex d_c_1T; + gr_complex d_c_0T; + + gr_complex slicer_0deg (gr_complex sample); + gr_complex slicer_45deg (gr_complex sample); + + friend gr_clock_recovery_mm_cc_sptr + gr_make_clock_recovery_mm_cc (float omega, float gain_omega, float mu, float gain_mu, + float omega_relative_limit); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.i b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.i new file mode 100644 index 0000000000..4db01afff5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.i @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,clock_recovery_mm_cc); + +gr_clock_recovery_mm_cc_sptr gr_make_clock_recovery_mm_cc (float omega, float gain_omega, + float mu, float gain_mu, + float omega_relative_limit); + +class gr_clock_recovery_mm_cc : public gr_sync_block +{ + private: + gr_clock_recovery_mm_cc (float omega, float gain_omega, float mu, + float gain_mu, float omega_relative_limit); + +public: + float mu() const { return d_mu;} + float omega() const { return d_omega;} + float gain_mu() const { return d_gain_mu;} + float gain_omega() const { return d_gain_omega;} + + void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; } + void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; } + void set_mu (float omega) { d_mu = mu; } + void set_omega (float omega) { d_omega = omega; + d_min_omega = omega*(1.0 - d_omega_relative_limit); + d_max_omega = omega*(1.0 + d_omega_relative_limit); + } + void set_verbose (bool verbose) { d_verbose = verbose; } +}; diff --git a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.cc b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.cc new file mode 100644 index 0000000000..1219df7bd3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.cc @@ -0,0 +1,140 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_io_signature.h> +#include <gr_clock_recovery_mm_ff.h> +#include <gri_mmse_fir_interpolator.h> +#include <stdexcept> + +#define DEBUG_CR_MM_FF 0 // must be defined as 0 or 1 + +// Public constructor + +gr_clock_recovery_mm_ff_sptr +gr_make_clock_recovery_mm_ff(float omega, float gain_omega, float mu, float gain_mu, + float omega_relative_limit) +{ + return gr_clock_recovery_mm_ff_sptr (new gr_clock_recovery_mm_ff (omega, + gain_omega, + mu, + gain_mu, + omega_relative_limit)); +} + +gr_clock_recovery_mm_ff::gr_clock_recovery_mm_ff (float omega, float gain_omega, float mu, float gain_mu, + float omega_relative_limit) + : gr_block ("clock_recovery_mm_ff", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (float))), + d_mu (mu), d_gain_omega(gain_omega), d_gain_mu(gain_mu), + d_last_sample(0), d_interp(new gri_mmse_fir_interpolator()), + d_logfile(0), d_omega_relative_limit(omega_relative_limit) +{ + if (omega < 1) + throw std::out_of_range ("clock rate must be > 0"); + if (gain_mu < 0 || gain_omega < 0) + throw std::out_of_range ("Gains must be non-negative"); + + set_omega(omega); // also sets min and max omega + set_relative_rate (1.0 / omega); + + if (DEBUG_CR_MM_FF) + d_logfile = fopen("cr_mm_ff.dat", "wb"); +} + +gr_clock_recovery_mm_ff::~gr_clock_recovery_mm_ff () +{ + delete d_interp; + + if (DEBUG_CR_MM_FF && d_logfile){ + fclose(d_logfile); + d_logfile = 0; + } +} + +void +gr_clock_recovery_mm_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_omega) + d_interp->ntaps()); +} + +static inline float +slice(float x) +{ + return x < 0 ? -1.0F : 1.0F; +} + +/* + * This implements the Mueller and Müller (M&M) discrete-time error-tracking synchronizer. + * + * See "Digital Communication Receivers: Synchronization, Channel + * Estimation and Signal Processing" by Heinrich Meyr, Marc Moeneclaey, & Stefan Fechtel. + * ISBN 0-471-50275-8. + */ +int +gr_clock_recovery_mm_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 + float mm_val; + + while (oo < noutput_items){ + + // produce output sample + out[oo] = d_interp->interpolate (&in[ii], d_mu); + mm_val = slice(d_last_sample) * out[oo] - slice(out[oo]) * d_last_sample; + d_last_sample = out[oo]; + + d_omega = d_omega + d_gain_omega * mm_val; + if (d_omega > d_max_omega) + d_omega = d_max_omega; + else if (d_omega < d_min_omega) + d_omega = d_min_omega; + + d_mu = d_mu + d_omega + d_gain_mu * mm_val; + + ii += (int) floor(d_mu); + d_mu = d_mu - floor(d_mu); + oo++; + + if (DEBUG_CR_MM_FF && d_logfile){ + fwrite(&d_omega, sizeof(d_omega), 1, d_logfile); + } + } + + consume_each (ii); + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.h b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.h new file mode 100644 index 0000000000..e970bcce81 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.h @@ -0,0 +1,93 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_CLOCK_RECOVERY_MM_FF_H +#define INCLUDED_GR_CLOCK_RECOVERY_MM_FF_H + +#include <gr_block.h> +#include <stdio.h> + +class gri_mmse_fir_interpolator; + +class gr_clock_recovery_mm_ff; +typedef boost::shared_ptr<gr_clock_recovery_mm_ff> gr_clock_recovery_mm_ff_sptr; + +// public constructor +gr_clock_recovery_mm_ff_sptr +gr_make_clock_recovery_mm_ff (float omega, float gain_omega, float mu, float gain_mu, + float omega_relative_limit=0.001); + +/*! + * \brief Mueller and Müller (M&M) based clock recovery block with float input, float output. + * \ingroup block + * + * This implements the Mueller and Müller (M&M) discrete-time error-tracking synchronizer. + * + * See "Digital Communication Receivers: Synchronization, Channel + * Estimation and Signal Processing" by Heinrich Meyr, Marc Moeneclaey, & Stefan Fechtel. + * ISBN 0-471-50275-8. + */ +class gr_clock_recovery_mm_ff : public gr_block +{ + public: + ~gr_clock_recovery_mm_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 omega() const { return d_omega;} + float gain_mu() const { return d_gain_mu;} + float gain_omega() const { return d_gain_omega;} + + void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; } + void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; } + void set_mu (float mu) { d_mu = mu; } + void set_omega (float omega){ + d_omega = omega; + d_min_omega = omega*(1.0 - d_omega_relative_limit); + d_max_omega = omega*(1.0 + d_omega_relative_limit); + } + +protected: + gr_clock_recovery_mm_ff (float omega, float gain_omega, float mu, float gain_mu, + float omega_relative_limit); + + private: + float d_mu; // fractional sample position [0.0, 1.0] + float d_omega; // nominal frequency + float d_min_omega; // minimum allowed omega + float d_max_omega; // maximum allowed omega + float d_gain_omega; // gain for adjusting omega + float d_gain_mu; // gain for adjusting mu + float d_last_sample; + gri_mmse_fir_interpolator *d_interp; + FILE *d_logfile; + float d_omega_relative_limit; // used to compute min and max omega + + friend gr_clock_recovery_mm_ff_sptr + gr_make_clock_recovery_mm_ff (float omega, float gain_omega, float mu, float gain_mu, + float omega_relative_limit); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.i b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.i new file mode 100644 index 0000000000..5b7bd45d2c --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,clock_recovery_mm_ff); + +gr_clock_recovery_mm_ff_sptr gr_make_clock_recovery_mm_ff (float omega, float gain_omega, + float mu, float gain_mu, + float omega_relative_limit=0.001); + +class gr_clock_recovery_mm_ff : public gr_sync_block +{ + private: + gr_clock_recovery_mm_ff (float omega, float gain_omega, float mu, float gain_mu, + float omega_relative_limit); + +public: + float mu() const; + float omega() const; + float gain_mu() const; + float gain_omega() const; + + void set_gain_mu (float gain_mu); + void set_gain_omega (float gain_omega); + void set_mu (float omega); + void set_omega (float omega); +}; 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 0000000000..65fbbe93b2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_complex_to_interleaved_short.cc @@ -0,0 +1,62 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_complex_to_interleaved_short_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 0000000000..1afca560af --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_complex_to_interleaved_short.h @@ -0,0 +1,51 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_COMPLEX_TO_INTERLEAVED_SHORT_H +#define INCLUDED_GR_COMPLEX_TO_INTERLEAVED_SHORT_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_complex_to_interleaved_short_sptr +gr_make_complex_to_interleaved_short (); + +/*! + * \brief Convert stream of complex to a stream of interleaved shorts + * \ingroup converter + */ + +class gr_complex_to_interleaved_short : public gr_sync_interpolator +{ + friend 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 0000000000..1b4b6baa03 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..727f44f073 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_complex_to_xxx.cc @@ -0,0 +1,199 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_complex_to_xxx.h> +#include <gr_io_signature.h> + +// ---------------------------------------------------------------- + +gr_complex_to_float_sptr +gr_make_complex_to_float (unsigned int vlen) +{ + return gr_complex_to_float_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) +{ +} + +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 = (float *) output_items[1]; + int noi = noutput_items * d_vlen; + + switch (output_items.size ()){ + case 1: + for (int i = 0; i < noi; i++){ + out0[i] = in[i].real (); + } + break; + + case 2: + for (int i = 0; i < noi; i++){ + out0[i] = in[i].real (); + out1[i] = in[i].imag (); + } + break; + + default: + abort (); + } + + return noutput_items; +} + +// ---------------------------------------------------------------- + +gr_complex_to_real_sptr +gr_make_complex_to_real (unsigned int vlen) +{ + return gr_complex_to_real_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) +{ +} + +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; + + for (int i = 0; i < noi; i++){ + out[i] = in[i].real (); + } + return noutput_items; +} + +// ---------------------------------------------------------------- + +gr_complex_to_imag_sptr +gr_make_complex_to_imag (unsigned int vlen) +{ + return gr_complex_to_imag_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) +{ +} + +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; + + for (int i = 0; i < noi; i++){ + out[i] = in[i].imag (); + } + return noutput_items; +} + +// ---------------------------------------------------------------- + +gr_complex_to_mag_sptr +gr_make_complex_to_mag (unsigned int vlen) +{ + return gr_complex_to_mag_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) +{ +} + +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; + + for (int i = 0; i < noi; i++){ + out[i] = std::abs (in[i]); + } + return noutput_items; +} + +// ---------------------------------------------------------------- + +gr_complex_to_arg_sptr +gr_make_complex_to_arg (unsigned int vlen) +{ + return gr_complex_to_arg_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) +{ +} + +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; + + for (int i = 0; i < noi; i++){ + out[i] = std::arg (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 0000000000..02a9fc8fd9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_complex_to_xxx.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_COMPLEX_TO_XXX_H +#define INCLUDED_GR_COMPLEX_TO_XXX_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_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_arg> gr_complex_to_arg_sptr; + +gr_complex_to_float_sptr gr_make_complex_to_float (unsigned int vlen=1); +gr_complex_to_real_sptr gr_make_complex_to_real (unsigned int vlen=1); +gr_complex_to_imag_sptr gr_make_complex_to_imag (unsigned int vlen=1); +gr_complex_to_mag_sptr gr_make_complex_to_mag (unsigned int vlen=1); +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 + * \param vlen vector len (default 1) + */ +class gr_complex_to_float : public gr_sync_block +{ + friend 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 + * \param vlen vector len (default 1) + */ +class gr_complex_to_real : public gr_sync_block +{ + friend 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 + * \param vlen vector len (default 1) + */ +class gr_complex_to_imag : public gr_sync_block +{ + friend 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 + * \param vlen vector len (default 1) + */ +class gr_complex_to_mag : public gr_sync_block +{ + friend 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, angle out (float) + * \ingroup converter + * \param vlen vector len (default 1) + */ +class gr_complex_to_arg : public gr_sync_block +{ + friend 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 0000000000..06f1020a02 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_complex_to_xxx.i @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_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 0000000000..50e25efafe --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_conjugate_cc.cc @@ -0,0 +1,71 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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> + +gr_conjugate_cc_sptr +gr_make_conjugate_cc () +{ + return gr_conjugate_cc_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))) +{ +} + +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]; + + int size = noutput_items; + + while (size >= 8){ + *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; + *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; + *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; + *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; + *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; + *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; + *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; + *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; + size -= 8; + } + + while (size-- > 0) + *optr++ = gr_complex(real(*iptr),-imag(*iptr));iptr++; + + 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 0000000000..f1551b863b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_conjugate_cc.h @@ -0,0 +1,51 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_sync_block.h> + +class gr_conjugate_cc; +typedef boost::shared_ptr<gr_conjugate_cc> gr_conjugate_cc_sptr; + +gr_conjugate_cc_sptr gr_make_conjugate_cc (); + +/*! + * \brief output = complex conjugate of input + * \ingroup block + */ +class gr_conjugate_cc : public gr_sync_block +{ + friend 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 0000000000..efafa84c70 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_constellation_decoder_cb.cc b/gnuradio-core/src/lib/general/gr_constellation_decoder_cb.cc new file mode 100644 index 0000000000..5b4f719d06 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_constellation_decoder_cb.cc @@ -0,0 +1,113 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_constellation_decoder_cb.h> +#include <gr_io_signature.h> +#include <stdexcept> + +#include <iostream> +using std::cout; +using std::endl; + +static const bool compute_EVM = false; + +gr_constellation_decoder_cb_sptr +gr_make_constellation_decoder_cb (const std::vector<gr_complex> &sym_position, + const std::vector<unsigned char> &sym_value_out) +{ + return gr_constellation_decoder_cb_sptr + (new gr_constellation_decoder_cb(sym_position, sym_value_out)); +} + +gr_constellation_decoder_cb:: +gr_constellation_decoder_cb (const std::vector<gr_complex> &sym_position, + const std::vector<unsigned char> &sym_value_out) + : gr_sync_block ("constellation_decoder_cb", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (unsigned char))) +{ + if (!set_constellation(sym_position,sym_value_out)) + throw std::invalid_argument("constellation_decoder_cb"); +} + + +gr_constellation_decoder_cb::~gr_constellation_decoder_cb(){} + + +bool +gr_constellation_decoder_cb::set_constellation(const std::vector<gr_complex> &sym_position, + const std::vector<unsigned char> &sym_value_out) +{ + if (sym_position.size() != sym_value_out.size()) + return false; + + if (sym_position.size()<1) + return false; + + d_sym_position = sym_position; + d_sym_value_out = sym_value_out; + return true; +} + + +int +gr_constellation_decoder_cb::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]; + unsigned char *out = (unsigned char *) output_items[0]; + unsigned int table_size = d_sym_value_out.size(); + unsigned int min_index = 0; + float min_euclid_dist = 0; + float euclid_dist = 0; + double total_error = 0; + + for(int i = 0; i < noutput_items; i++){ + min_euclid_dist = norm(in[i] - d_sym_position[0]); + min_index = 0; + for (unsigned int j = 1; j < table_size; j++){ + euclid_dist = norm(in[i] - d_sym_position[j]); + if (euclid_dist < min_euclid_dist){ + min_euclid_dist = euclid_dist; + min_index = j; + } + } + + out[i] = d_sym_value_out[min_index]; + + if (compute_EVM) + total_error += sqrtf(min_euclid_dist); + } + + if (compute_EVM){ + double mean = total_error / noutput_items; + double rms = sqrt(mean * mean); + fprintf(stderr, "EVM = %8.4f\n", rms); + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_constellation_decoder_cb.h b/gnuradio-core/src/lib/general/gr_constellation_decoder_cb.h new file mode 100644 index 0000000000..2cc16c57db --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_constellation_decoder_cb.h @@ -0,0 +1,61 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_CONSTELLATION_DECODER_CB_H +#define INCLUDED_GR_CONSTELLATION_DECODER_CB_H + +#include <gr_sync_block.h> +#include <vector> + +class gr_constellation_decoder_cb; +typedef boost::shared_ptr<gr_constellation_decoder_cb> gr_constellation_decoder_cb_sptr; + +gr_constellation_decoder_cb_sptr + gr_make_constellation_decoder_cb (const std::vector<gr_complex> &sym_position, + const std::vector<unsigned char> &sym_value_out); + + +class gr_constellation_decoder_cb : public gr_sync_block +{ + + private: + std::vector<gr_complex> d_sym_position; + std::vector<unsigned char> d_sym_value_out; + + friend gr_constellation_decoder_cb_sptr + gr_make_constellation_decoder_cb (const std::vector<gr_complex> &sym_position, const std::vector<unsigned char> &sym_value_out); + + gr_constellation_decoder_cb (const std::vector<gr_complex> &sym_position, + const std::vector<unsigned char> &sym_value_out); //constructor + + public: + bool set_constellation(const std::vector<gr_complex> &sym_position, + const std::vector<unsigned char> &sym_value_out); + + ~gr_constellation_decoder_cb(); //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_constellation_decoder_cb.i b/gnuradio-core/src/lib/general/gr_constellation_decoder_cb.i new file mode 100644 index 0000000000..ba1e38f6b4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_constellation_decoder_cb.i @@ -0,0 +1,43 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,constellation_decoder_cb) + +gr_constellation_decoder_cb_sptr + gr_make_constellation_decoder_cb (const std::vector<gr_complex> &sym_position, + const std::vector<unsigned char> &sym_value_out); + +class gr_constellation_decoder_cb : public gr_sync_block +{ + private: + gr_constellation_decoder_cb (const std::vector<gr_complex> &sym_position, + const std::vector<unsigned char> &sym_value_out); + + friend gr_constellation_decoder_cb_sptr + gr_make_constellation_decoder_cb (const std::vector<gr_complex> &sym_position, + const std::vector<unsigned char> &sym_value_out); + + public: + int set_constellation(const std::vector<gr_complex> &sym_position, + const std::vector<unsigned char> &sym_value_out); + ~gr_constellation_decoder_cb(); +}; diff --git a/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.cc b/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.cc new file mode 100644 index 0000000000..0f25986078 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_correlate_access_code_bb.h> +#include <gr_io_signature.h> +#include <stdexcept> +#include <gr_count_bits.h> + +#define VERBOSE 0 + + +gr_correlate_access_code_bb_sptr +gr_make_correlate_access_code_bb (const std::string &access_code, int threshold) +{ + return gr_correlate_access_code_bb_sptr (new gr_correlate_access_code_bb (access_code, threshold)); +} + + +gr_correlate_access_code_bb::gr_correlate_access_code_bb ( + const std::string &access_code, int threshold) + : gr_sync_block ("correlate_access_code_bb", + gr_make_io_signature (1, 1, sizeof(char)), + gr_make_io_signature (1, 1, sizeof(char))), + d_data_reg(0), d_flag_reg(0), d_flag_bit(0), d_mask(0), + d_threshold(threshold), d_flip(0) + +{ + if (!set_access_code(access_code)){ + fprintf(stderr, "gr_correlate_access_code_bb: access_code is > 64 bits\n"); + throw std::out_of_range ("access_code is > 64 bits"); + } +} + +gr_correlate_access_code_bb::~gr_correlate_access_code_bb () +{ +} + +bool +gr_correlate_access_code_bb::set_access_code( + const std::string &access_code) +{ + unsigned len = access_code.length(); // # of bytes in string + if (len > 64) + return false; + + // set len top bits to 1. + d_mask = ((~0ULL) >> (64 - len)) << (64 - len); + + d_flag_bit = 1LL << (64 - len); // Where we or-in new flag values. + // new data always goes in 0x0000000000000001 + d_access_code = 0; + for (unsigned i=0; i < 64; i++){ + d_access_code <<= 1; + if (i < len) + d_access_code |= access_code[i] & 1; // look at LSB only + } + + return true; +} + +int +gr_correlate_access_code_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++){ + + // compute output value + unsigned int t = 0; + + t |= d_flip ^ (((d_data_reg >> 63) & 0x1) << 0); + t |= ((d_flag_reg >> 63) & 0x1) << 1; // flag bit + out[i] = t; + + // 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 or its compelement + new_flag = (nwrong <= d_threshold) || (nwrong >= (64-d_threshold)); + +#if 0 + if(new_flag) { + printf("%llx ==> %llx : d_flip=%u\n", d_access_code, d_data_reg, d_flip); + } +#endif + + // shift in new data and new flag + d_data_reg = (d_data_reg << 1) | (in[i] & 0x1); + d_flag_reg = (d_flag_reg << 1); + if (new_flag) { + d_flag_reg |= d_flag_bit; + d_flip = nwrong >= (64-d_threshold); // flip bits if this is true + } + } + + return noutput_items; +} + diff --git a/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.h b/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.h new file mode 100644 index 0000000000..519258cae6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.h @@ -0,0 +1,85 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_CORRELATE_ACCESS_CODE_BB_H +#define INCLUDED_GR_CORRELATE_ACCESS_CODE_BB_H + +#include <gr_sync_block.h> +#include <string> + +class gr_correlate_access_code_bb; +typedef boost::shared_ptr<gr_correlate_access_code_bb> gr_correlate_access_code_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 + */ +gr_correlate_access_code_bb_sptr +gr_make_correlate_access_code_bb (const std::string &access_code, int threshold); + +/*! + * \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_bb : public gr_sync_block +{ + friend gr_correlate_access_code_bb_sptr + gr_make_correlate_access_code_bb (const std::string &access_code, int threshold); + 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_flag_reg; // keep track of decisions + unsigned long long d_flag_bit; // mask containing 1 bit which is location of new flag + 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_flip; // flip bits if 180 degress out of sync + + + protected: + gr_correlate_access_code_bb(const std::string &access_code, int threshold); + + public: + ~gr_correlate_access_code_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_BB_H */ diff --git a/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.i b/gnuradio-core/src/lib/general/gr_correlate_access_code_bb.i new file mode 100644 index 0000000000..688f3f694b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_correlate_access_code_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,correlate_access_code_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_bb_sptr +gr_make_correlate_access_code_bb (const std::string &access_code, int threshold) + 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_bb : public gr_sync_block +{ + friend gr_correlate_access_code_bb_sptr + gr_make_correlate_access_code_bb (const std::string &access_code, int threshold); + protected: + gr_correlate_access_code_bb(const std::string &access_code, int threshold); + + public: + ~gr_correlate_access_code_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_costas_loop_cc.cc b/gnuradio-core/src/lib/general/gr_costas_loop_cc.cc new file mode 100644 index 0000000000..4ad627f029 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_costas_loop_cc.cc @@ -0,0 +1,118 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_costas_loop_cc.h> +#include <gr_io_signature.h> +#include <gr_expj.h> +#include <gr_sincos.h> +#include <math.h> + +#define M_TWOPI (2*M_PI) + +gr_costas_loop_cc_sptr +gr_make_costas_loop_cc (float alpha, float beta, + float max_freq, float min_freq, + int order + ) throw (std::invalid_argument) +{ + return gr_costas_loop_cc_sptr (new gr_costas_loop_cc (alpha, beta, + max_freq, min_freq, + order)); +} + +gr_costas_loop_cc::gr_costas_loop_cc (float alpha, float beta, + float max_freq, float min_freq, + int order + ) throw (std::invalid_argument) + : gr_sync_block ("costas_loop_cc", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (gr_complex))), + d_alpha(alpha), d_beta(beta), + d_max_freq(max_freq), d_min_freq(min_freq), + d_phase(0), d_freq((max_freq+min_freq)/2), + d_order(order), d_phase_detector(0) +{ + switch(d_order) { + case 2: + d_phase_detector = &gr_costas_loop_cc::phase_detector_2; + break; + + case 4: + d_phase_detector = &gr_costas_loop_cc::phase_detector_4; + break; + + default: + throw std::invalid_argument("order must be 2 or 4"); + break; + } +} + + +float +gr_costas_loop_cc::phase_detector_4(gr_complex sample) const +{ + + return ((sample.real()>0 ? 1.0 : -1.0) * sample.imag() - + (sample.imag()>0 ? 1.0 : -1.0) * sample.real()); +} + +float +gr_costas_loop_cc::phase_detector_2(gr_complex sample) const +{ + return (sample.real()*sample.imag()); +} + +int +gr_costas_loop_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; + gr_complex nco_out; + + for (int i = 0; i < noutput_items; i++){ + nco_out = gr_expj(-d_phase); + optr[i] = iptr[i] * nco_out; + + error = (*this.*d_phase_detector)(optr[i]); + + d_freq = d_freq + d_beta * error; + d_phase = d_phase + d_freq + d_alpha * error; + while(d_phase>M_TWOPI) + d_phase -= M_TWOPI; + while(d_phase<-M_TWOPI) + d_phase += M_TWOPI; + + if (d_freq > d_max_freq) + d_freq = d_max_freq; + else if (d_freq < d_min_freq) + d_freq = d_min_freq; + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_costas_loop_cc.h b/gnuradio-core/src/lib/general/gr_costas_loop_cc.h new file mode 100644 index 0000000000..4672c0949f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_costas_loop_cc.h @@ -0,0 +1,72 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef INCLUDED_GR_COSTAS_LOOP_CC_H +#define INCLUDED_GR_COSTAS_LOOP_CC_H + +#include <gr_sync_block.h> +#include <stdexcept> + +class gr_costas_loop_cc; +typedef boost::shared_ptr<gr_costas_loop_cc> gr_costas_loop_cc_sptr; + +gr_costas_loop_cc_sptr +gr_make_costas_loop_cc (float alpha, float beta, + float max_freq, float min_freq, + int order + ) throw (std::invalid_argument); + + +/*! + * \brief Carrier tracking PLL for QPSK + * input: complex; output: complex + * + * \p order must be 2 or 4. + */ +class gr_costas_loop_cc : public gr_sync_block +{ + friend gr_costas_loop_cc_sptr gr_make_costas_loop_cc (float alpha, float beta, + float max_freq, float min_freq, + int order + ) throw (std::invalid_argument); + + float d_alpha, d_beta, d_max_freq, d_min_freq, d_phase, d_freq; + int d_order; + + gr_costas_loop_cc (float alpha, float beta, + float max_freq, float min_freq, + int order + ) throw (std::invalid_argument); + + float phase_detector_4(gr_complex sample) const; // for QPSK + float phase_detector_2(gr_complex sample) const; // for BPSK + float (gr_costas_loop_cc::*d_phase_detector)(gr_complex sample) const; + +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_costas_loop_cc.i b/gnuradio-core/src/lib/general/gr_costas_loop_cc.i new file mode 100644 index 0000000000..85d2ada512 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_costas_loop_cc.i @@ -0,0 +1,37 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,costas_loop_cc); + +gr_costas_loop_cc_sptr +gr_make_costas_loop_cc (float alpha, float beta, + float max_freq, float min_freq, + int order + ) throw (std::invalid_argument); + + +class gr_costas_loop_cc : public gr_sync_block +{ + private: + gr_costas_loop_cc (float alpha, float beta, + float max_freq, float min_freq, int order); +}; 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 0000000000..cd51ce8a11 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..b0e83c832c --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_count_bits.h @@ -0,0 +1,31 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GR_COUNT_BITS_H_ +#define _GR_COUNT_BITS_H_ + +unsigned int gr_count_bits8(unsigned int x); // return number of set bits in the low 8 bits of x +unsigned int gr_count_bits16(unsigned int x); // return number of set bits in the low 16 bits of x +unsigned int gr_count_bits32(unsigned int x); // return number of set bits in the low 32 bits of x +unsigned int gr_count_bits64(unsigned long long int x); + +#endif /* _GR_COUNT_BITS_H_ */ diff --git a/gnuradio-core/src/lib/general/gr_crc32.cc b/gnuradio-core/src/lib/general/gr_crc32.cc new file mode 100644 index 0000000000..3b0ebd409d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_crc32.cc @@ -0,0 +1,130 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * See also ISO 3309 [ISO-3309] or ITU-T V.42 [ITU-V42] for a formal specification. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_crc32.h> + + +// Automatically generated CRC function +// polynomial: 0x104C11DB7 +unsigned int +gr_update_crc32(unsigned int crc, const unsigned char *data, size_t len) +{ + static const unsigned int table[256] = { + 0x00000000U,0x04C11DB7U,0x09823B6EU,0x0D4326D9U, + 0x130476DCU,0x17C56B6BU,0x1A864DB2U,0x1E475005U, + 0x2608EDB8U,0x22C9F00FU,0x2F8AD6D6U,0x2B4BCB61U, + 0x350C9B64U,0x31CD86D3U,0x3C8EA00AU,0x384FBDBDU, + 0x4C11DB70U,0x48D0C6C7U,0x4593E01EU,0x4152FDA9U, + 0x5F15ADACU,0x5BD4B01BU,0x569796C2U,0x52568B75U, + 0x6A1936C8U,0x6ED82B7FU,0x639B0DA6U,0x675A1011U, + 0x791D4014U,0x7DDC5DA3U,0x709F7B7AU,0x745E66CDU, + 0x9823B6E0U,0x9CE2AB57U,0x91A18D8EU,0x95609039U, + 0x8B27C03CU,0x8FE6DD8BU,0x82A5FB52U,0x8664E6E5U, + 0xBE2B5B58U,0xBAEA46EFU,0xB7A96036U,0xB3687D81U, + 0xAD2F2D84U,0xA9EE3033U,0xA4AD16EAU,0xA06C0B5DU, + 0xD4326D90U,0xD0F37027U,0xDDB056FEU,0xD9714B49U, + 0xC7361B4CU,0xC3F706FBU,0xCEB42022U,0xCA753D95U, + 0xF23A8028U,0xF6FB9D9FU,0xFBB8BB46U,0xFF79A6F1U, + 0xE13EF6F4U,0xE5FFEB43U,0xE8BCCD9AU,0xEC7DD02DU, + 0x34867077U,0x30476DC0U,0x3D044B19U,0x39C556AEU, + 0x278206ABU,0x23431B1CU,0x2E003DC5U,0x2AC12072U, + 0x128E9DCFU,0x164F8078U,0x1B0CA6A1U,0x1FCDBB16U, + 0x018AEB13U,0x054BF6A4U,0x0808D07DU,0x0CC9CDCAU, + 0x7897AB07U,0x7C56B6B0U,0x71159069U,0x75D48DDEU, + 0x6B93DDDBU,0x6F52C06CU,0x6211E6B5U,0x66D0FB02U, + 0x5E9F46BFU,0x5A5E5B08U,0x571D7DD1U,0x53DC6066U, + 0x4D9B3063U,0x495A2DD4U,0x44190B0DU,0x40D816BAU, + 0xACA5C697U,0xA864DB20U,0xA527FDF9U,0xA1E6E04EU, + 0xBFA1B04BU,0xBB60ADFCU,0xB6238B25U,0xB2E29692U, + 0x8AAD2B2FU,0x8E6C3698U,0x832F1041U,0x87EE0DF6U, + 0x99A95DF3U,0x9D684044U,0x902B669DU,0x94EA7B2AU, + 0xE0B41DE7U,0xE4750050U,0xE9362689U,0xEDF73B3EU, + 0xF3B06B3BU,0xF771768CU,0xFA325055U,0xFEF34DE2U, + 0xC6BCF05FU,0xC27DEDE8U,0xCF3ECB31U,0xCBFFD686U, + 0xD5B88683U,0xD1799B34U,0xDC3ABDEDU,0xD8FBA05AU, + 0x690CE0EEU,0x6DCDFD59U,0x608EDB80U,0x644FC637U, + 0x7A089632U,0x7EC98B85U,0x738AAD5CU,0x774BB0EBU, + 0x4F040D56U,0x4BC510E1U,0x46863638U,0x42472B8FU, + 0x5C007B8AU,0x58C1663DU,0x558240E4U,0x51435D53U, + 0x251D3B9EU,0x21DC2629U,0x2C9F00F0U,0x285E1D47U, + 0x36194D42U,0x32D850F5U,0x3F9B762CU,0x3B5A6B9BU, + 0x0315D626U,0x07D4CB91U,0x0A97ED48U,0x0E56F0FFU, + 0x1011A0FAU,0x14D0BD4DU,0x19939B94U,0x1D528623U, + 0xF12F560EU,0xF5EE4BB9U,0xF8AD6D60U,0xFC6C70D7U, + 0xE22B20D2U,0xE6EA3D65U,0xEBA91BBCU,0xEF68060BU, + 0xD727BBB6U,0xD3E6A601U,0xDEA580D8U,0xDA649D6FU, + 0xC423CD6AU,0xC0E2D0DDU,0xCDA1F604U,0xC960EBB3U, + 0xBD3E8D7EU,0xB9FF90C9U,0xB4BCB610U,0xB07DABA7U, + 0xAE3AFBA2U,0xAAFBE615U,0xA7B8C0CCU,0xA379DD7BU, + 0x9B3660C6U,0x9FF77D71U,0x92B45BA8U,0x9675461FU, + 0x8832161AU,0x8CF30BADU,0x81B02D74U,0x857130C3U, + 0x5D8A9099U,0x594B8D2EU,0x5408ABF7U,0x50C9B640U, + 0x4E8EE645U,0x4A4FFBF2U,0x470CDD2BU,0x43CDC09CU, + 0x7B827D21U,0x7F436096U,0x7200464FU,0x76C15BF8U, + 0x68860BFDU,0x6C47164AU,0x61043093U,0x65C52D24U, + 0x119B4BE9U,0x155A565EU,0x18197087U,0x1CD86D30U, + 0x029F3D35U,0x065E2082U,0x0B1D065BU,0x0FDC1BECU, + 0x3793A651U,0x3352BBE6U,0x3E119D3FU,0x3AD08088U, + 0x2497D08DU,0x2056CD3AU,0x2D15EBE3U,0x29D4F654U, + 0xC5A92679U,0xC1683BCEU,0xCC2B1D17U,0xC8EA00A0U, + 0xD6AD50A5U,0xD26C4D12U,0xDF2F6BCBU,0xDBEE767CU, + 0xE3A1CBC1U,0xE760D676U,0xEA23F0AFU,0xEEE2ED18U, + 0xF0A5BD1DU,0xF464A0AAU,0xF9278673U,0xFDE69BC4U, + 0x89B8FD09U,0x8D79E0BEU,0x803AC667U,0x84FBDBD0U, + 0x9ABC8BD5U,0x9E7D9662U,0x933EB0BBU,0x97FFAD0CU, + 0xAFB010B1U,0xAB710D06U,0xA6322BDFU,0xA2F33668U, + 0xBCB4666DU,0xB8757BDAU,0xB5365D03U,0xB1F740B4U, + }; + + while (len > 0) + { + crc = table[*data ^ ((crc >> 24) & 0xff)] ^ (crc << 8); + data++; + len--; + } + return crc; +} + +unsigned int +gr_update_crc32(unsigned int crc, const std::string s) +{ + return gr_update_crc32(crc, (const unsigned char *) s.data(), s.size()); +} + +unsigned int +gr_crc32(const unsigned char *buf, size_t len) +{ + return gr_update_crc32(0xffffffff, buf, len) ^ 0xffffffff; +} + +unsigned int +gr_crc32(const std::string s) +{ + return gr_crc32((const unsigned char *) s.data(), s.size()); +} diff --git a/gnuradio-core/src/lib/general/gr_crc32.h b/gnuradio-core/src/lib/general/gr_crc32.h new file mode 100644 index 0000000000..2d6fdc85dd --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_crc32.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_CRC32_H +#define INCLUDED_GR_CRC32_H + +#include <string> +#include <gr_types.h> + +/*! + * \brief update running CRC-32 + * + * Update a running CRC with the bytes buf[0..len-1] The CRC should be + * initialized to all 1's, and the transmitted value is the 1's + * complement of the final running CRC. The resulting CRC should be + * transmitted in big endian order. + */ +unsigned int gr_update_crc32(unsigned int crc, const unsigned char *buf, int len); +unsigned int gr_update_crc32(unsigned int crc, const std::string buf); + +unsigned int gr_crc32(const unsigned char *buf, int len); +unsigned int gr_crc32(const std::string buf); + +#endif /* INCLUDED_CRC32_H */ diff --git a/gnuradio-core/src/lib/general/gr_crc32.i b/gnuradio-core/src/lib/general/gr_crc32.i new file mode 100644 index 0000000000..79e1d08674 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_crc32.i @@ -0,0 +1,27 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%rename(update_crc32) gr_update_crc32; +%rename(crc32) gr_crc32; + +unsigned int gr_update_crc32(unsigned int crc, const std::string buf); +unsigned int gr_crc32(const std::string buf); 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 0000000000..7ad31cbdc4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ctcss_squelch_ff.cc @@ -0,0 +1,112 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_ctcss_squelch_ff_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 0000000000..337e5cabe6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_ctcss_squelch_ff.h @@ -0,0 +1,67 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_CTCSS_SQUELCH_FF_H +#define INCLUDED_GR_CTCSS_SQUELCH_FF_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_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 block + */ +class 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_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 0000000000..6d32c7d0e3 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_dd_mpsk_sync_cc.cc b/gnuradio-core/src/lib/general/gr_dd_mpsk_sync_cc.cc new file mode 100644 index 0000000000..1f0bc0157f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_dd_mpsk_sync_cc.cc @@ -0,0 +1,195 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_dd_mpsk_sync_cc.h> +#include <gr_io_signature.h> +#include <gr_sincos.h> +#include <gri_mmse_fir_interpolator_cc.h> +#include <math.h> +#include <stdexcept> + +#include <gr_complex.h> + +#define M_TWOPI (2*M_PI) + +gr_dd_mpsk_sync_cc_sptr +gr_make_dd_mpsk_sync_cc (float alpha, float beta, float max_freq, float min_freq, float ref_phase, + float omega, float gain_omega, float mu, float gain_mu) +{ + return gr_dd_mpsk_sync_cc_sptr (new gr_dd_mpsk_sync_cc (alpha, beta, max_freq, min_freq,ref_phase, + omega,gain_omega,mu,gain_mu)); +} + +gr_dd_mpsk_sync_cc::gr_dd_mpsk_sync_cc (float alpha, float beta, float max_freq, float min_freq, + float ref_phase, + float omega, float gain_omega, float mu, float gain_mu) + : gr_block ("dd_mpsk_sync_cc", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (gr_complex))), + d_alpha(alpha), d_beta(beta), + d_max_freq(max_freq), d_min_freq(min_freq), + d_ref_phase(ref_phase),d_omega(omega), d_gain_omega(gain_omega), + d_mu(mu), d_gain_mu(gain_mu), + d_phase(0), d_freq((max_freq+min_freq)/2), d_last_sample(0), + d_interp(new gri_mmse_fir_interpolator_cc()), + d_dl_idx(0) +{ + if (omega <= 0.0) + throw std::out_of_range ("clock rate must be > 0"); + if (gain_mu < 0 || gain_omega < 0) + throw std::out_of_range ("Gains must be non-negative"); + + assert(d_interp->ntaps() <= DLLEN); + + // zero double length delay line. + for (unsigned int i = 0; i < 2 * DLLEN; i++) + d_dl[i] = gr_complex(0.0,0.0); +} + +gr_dd_mpsk_sync_cc::~gr_dd_mpsk_sync_cc() +{ + delete d_interp; +} + +float +gr_dd_mpsk_sync_cc::phase_detector(gr_complex sample,float ref_phase) +{ + return ((sample.real()>0 ? 1.0 : -1.0) * sample.imag() - + (sample.imag()>0 ? 1.0 : -1.0) * sample.real()); +} + +void +gr_dd_mpsk_sync_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_omega) + d_interp->ntaps()); +} +gr_complex +gr_dd_mpsk_sync_cc::slicer_45deg (gr_complex sample) +{ + float real,imag; + if(sample.real() > 0) + real=1; + else + real=-1; + if(sample.imag() > 0) + imag = 1; + else + imag = -1; + return gr_complex(real,imag); +} + +gr_complex +gr_dd_mpsk_sync_cc::slicer_0deg (gr_complex sample) +{ + gr_complex out; + if( fabs(sample.real()) > fabs(sample.imag()) ) { + if(sample.real() > 0) + return gr_complex(1.0,0.0); + else + return gr_complex(-1.0,0.0); + } + else { + if(sample.imag() > 0) + return gr_complex(0.0, 1.0); + else + return gr_complex(0.0, -1.0); + } +} + +int +gr_dd_mpsk_sync_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 = (gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + int ii, oo; + ii = 0; oo = 0; + + float error; + float t_imag, t_real; + gr_complex nco_out; + float mm_val; + + while (oo < noutput_items) { + // + // generate an output sample by interpolating between the carrier + // tracked samples in the delay line. d_mu, the fractional + // interpolation amount (in [0.0, 1.0]) is controlled by the + // symbol timing loop below. + // + out[oo] = d_interp->interpolate (&d_dl[d_dl_idx], d_mu); + + error = phase_detector(out[oo], d_ref_phase); + + d_freq = d_freq + d_beta * error; + d_phase = d_phase + d_alpha * error; + while(d_phase>M_TWOPI) + d_phase -= M_TWOPI; + while(d_phase<-M_TWOPI) + d_phase += M_TWOPI; + + if (d_freq > d_max_freq) + d_freq = d_max_freq; + else if (d_freq < d_min_freq) + d_freq = d_min_freq; + + mm_val = real(d_last_sample * slicer_0deg(out[oo]) - out[oo] * slicer_0deg(d_last_sample)); + d_last_sample = out[oo]; + + d_omega = d_omega + d_gain_omega * mm_val; + d_mu = d_mu + d_omega + d_gain_mu * mm_val; + + while(d_mu >= 1.0) { + // + // Generate more carrier tracked samples for the delay line + // + d_mu -= 1.0; + gr_sincosf(d_phase, &t_imag, &t_real); + nco_out = gr_complex(t_real, -t_imag); + gr_complex new_sample = in[ii] * nco_out; + + d_dl[d_dl_idx] = new_sample; // overwrite oldest sample + d_dl[(d_dl_idx + DLLEN)] = new_sample; // and second copy + d_dl_idx = (d_dl_idx+1) % DLLEN; // point to the new oldest sample + d_phase = d_phase + d_freq; + ii++; + } + oo++; + printf("%f\t%f\t%f\t%f\t%f\n",d_mu,d_omega,mm_val,d_freq,d_phase); + //printf("%f\t%f\t%f\t%f\t%f\t%f\t%f\n",mple).real(),slicer_0deg(d_last_sample).imag(),mm_val,d_omega,d_mu); + } + + assert(ii <= ninput_items[0]); + + consume_each (ii); + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_dd_mpsk_sync_cc.h b/gnuradio-core/src/lib/general/gr_dd_mpsk_sync_cc.h new file mode 100644 index 0000000000..fdc2561425 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_dd_mpsk_sync_cc.h @@ -0,0 +1,92 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_DD_MPSK_SYNC_CC_H +#define INCLUDED_GR_DD_MPSK_SYNC_CC_H + +#include <gr_sync_block.h> + +class gri_mmse_fir_interpolator_cc; + +class gr_dd_mpsk_sync_cc; +typedef boost::shared_ptr<gr_dd_mpsk_sync_cc> gr_dd_mpsk_sync_cc_sptr; + +gr_dd_mpsk_sync_cc_sptr +gr_make_dd_mpsk_sync_cc (float alpha, float beta, + float max_freq, float min_freq, float ref_phase, + float omega, float gain_omega, float mu, float gain_mu); + +/*! + * \brief Decision directed M-PSK synchronous demod + * This block performs joint carrier tracking and symbol timing recovery. + * + * input: complex baseband; output: properly timed complex samples ready for slicing. + * + * N.B, at this point, it handles only QPSK. + */ + +class gr_dd_mpsk_sync_cc : public gr_block +{ + friend gr_dd_mpsk_sync_cc_sptr gr_make_dd_mpsk_sync_cc (float alpha, float beta, + float max_freq, float min_freq, float ref_phase, + float omega, float gain_omega, float mu, float gain_mu); +public: + ~gr_dd_mpsk_sync_cc (); + void forecast(int noutput_items, gr_vector_int &ninput_items_required); + float mu() const { return d_mu;} + float omega() const { return d_omega;} + float gain_mu() const { return d_gain_mu;} + float gain_omega() const { return d_gain_omega;} + + void set_gain_mu (float gain_mu) { d_gain_mu = gain_mu; } + void set_gain_omega (float gain_omega) { d_gain_omega = gain_omega; } + void set_mu (float mu) { d_mu = mu; } + void set_omega (float omega) { d_omega = omega; } + +protected: + gr_dd_mpsk_sync_cc (float alpha, float beta, float max_freq, float min_freq, float ref_phase, + float omega, float gain_omega, float mu, float gain_mu); + + int general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + +private: + static const unsigned int DLLEN = 8; // delay line length. + + float d_alpha,d_beta,d_max_freq,d_min_freq,d_ref_phase; + float d_omega, d_gain_omega, d_mu, d_gain_mu; + float d_phase, d_freq; + gr_complex slicer_45deg (gr_complex sample); + gr_complex slicer_0deg (gr_complex sample); + gr_complex d_last_sample; + gri_mmse_fir_interpolator_cc *d_interp; + + gr_complex d_dl[2 * DLLEN]; // Holds post carrier tracking samples. + // double length delay line to avoid wraps. + unsigned int d_dl_idx; // indexes oldest sample in delay line. + + float phase_detector(gr_complex sample,float ref_phase); +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_dd_mpsk_sync_cc.i b/gnuradio-core/src/lib/general/gr_dd_mpsk_sync_cc.i new file mode 100644 index 0000000000..3bab9e2f30 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_dd_mpsk_sync_cc.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,dd_mpsk_sync_cc) + + gr_dd_mpsk_sync_cc_sptr gr_make_dd_mpsk_sync_cc (float alpha, float beta, + float max_freq, float min_freq, float ref_phase, + float omega, float gain_omega, float mu, float gain_mu); + +class gr_dd_mpsk_sync_cc : public gr_block +{ + private: + gr_dd_mpsk_sync_cc (float alpha, float beta, float max_freq, float min_freq, float ref_phase, + float omega, float gain_omega, float mu, float gain_mu); +}; 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 0000000000..375a40d21f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_deinterleave.cc @@ -0,0 +1,78 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_deinterleave_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 0000000000..0eb9874eda --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_deinterleave.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_DEINTERLEAVE_H +#define INCLUDED_GR_DEINTERLEAVE_H + +#include <gr_sync_decimator.h> + +class gr_deinterleave; +typedef boost::shared_ptr<gr_deinterleave> gr_deinterleave_sptr; + +gr_deinterleave_sptr gr_make_deinterleave (size_t itemsize); + +/*! + * \brief deinterleave a single input into N outputs + * \ingroup block + */ +class gr_deinterleave : public gr_sync_decimator +{ + friend 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 0000000000..f1eac5cab2 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_diff_decoder_bb.cc b/gnuradio-core/src/lib/general/gr_diff_decoder_bb.cc new file mode 100644 index 0000000000..5ab88a9c01 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_diff_decoder_bb.cc @@ -0,0 +1,61 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_diff_decoder_bb_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 0000000000..c88e0e25b1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_diff_decoder_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_DIFF_DECODER_BB_H +#define INCLUDED_GR_DIFF_DECODER_BB_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_diff_decoder_bb_sptr gr_make_diff_decoder_bb (unsigned int modulus); + +/*! + * \brief y[0] = (x[0] - x[-1]) % M + * \ingroup block + * + * Differential decoder + */ +class gr_diff_decoder_bb : public gr_sync_block +{ + friend 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 0000000000..b4ad5f6ad8 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..bd4135c4ca --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_diff_encoder_bb.cc @@ -0,0 +1,62 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_diff_encoder_bb_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 0000000000..c839d399fa --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_diff_encoder_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_DIFF_ENCODER_BB_H +#define INCLUDED_GR_DIFF_ENCODER_BB_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_diff_encoder_bb_sptr gr_make_diff_encoder_bb (unsigned int modulus); + +/*! + * \brief y[0] = (x[0] + y[-1]) % M + * \ingroup block + * + * Differential encoder + */ +class gr_diff_encoder_bb : public gr_sync_block +{ + friend 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 0000000000..890779c469 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..c5eae5f336 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_diff_phasor_cc.cc @@ -0,0 +1,61 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_diff_phasor_cc_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 0000000000..64a3f291b5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_diff_phasor_cc.h @@ -0,0 +1,48 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_DIFF_PHASOR_CC_H +#define INCLUDED_GR_DIFF_PHASOR_CC_H + +#include <gr_sync_block.h> + +class gr_diff_phasor_cc; +typedef boost::shared_ptr<gr_diff_phasor_cc> gr_diff_phasor_cc_sptr; + +gr_diff_phasor_cc_sptr gr_make_diff_phasor_cc (); + + +class gr_diff_phasor_cc : public gr_sync_block +{ + friend 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 0000000000..773d276ba9 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_divide_XX.cc.t b/gnuradio-core/src/lib/general/gr_divide_XX.cc.t new file mode 100644 index 0000000000..e85f7b0a50 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_divide_XX.cc.t @@ -0,0 +1,71 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 @SPTR_NAME@ (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 (); + + if (ninputs == 1){ // compute reciprocal + for (int i = 0; i < noutput_items; i++) + *optr++ = (@O_TYPE@) ((@O_TYPE@) 1 / + ((@I_TYPE@ *) input_items[0])[i]); + } + + else { + 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 /= ((@I_TYPE@ *) input_items[j])[i]; + + *optr++ = (@O_TYPE@) acc; + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_divide_XX.h.t b/gnuradio-core/src/lib/general/gr_divide_XX.h.t new file mode 100644 index 0000000000..193d6f82a2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_divide_XX.h.t @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ gr_make_@BASE_NAME@ (); + +/*! + * \brief output = input_0 / input_1 / input_x ...) + * \ingroup block + * + * Divide across all input streams. + */ +class @NAME@ : public gr_sync_block +{ + friend @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/general/gr_divide_XX.i.t b/gnuradio-core/src/lib/general/gr_divide_XX.i.t new file mode 100644 index 0000000000..8479aad683 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_divide_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/general/gr_endianness.h b/gnuradio-core/src/lib/general/gr_endianness.h new file mode 100644 index 0000000000..e33af166d1 --- /dev/null +++ b/gnuradio-core/src/lib/general/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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/general/gr_endianness.i b/gnuradio-core/src/lib/general/gr_endianness.i new file mode 100644 index 0000000000..d05b06a099 --- /dev/null +++ b/gnuradio-core/src/lib/general/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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%include <gr_endianness.h> 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 0000000000..502bfe9ee4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_expj.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_EXPJ_H +#define INCLUDED_GR_EXPJ_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 0000000000..0ef4c46dbe --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fake_channel_coder_pp.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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> + +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 gr_fake_channel_encoder_pp_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 gr_fake_channel_decoder_pp_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 0000000000..03b651e83f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fake_channel_coder_pp.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FAKE_CHANNEL_CODER_PP_H +#define INCLUDED_GR_FAKE_CHANNEL_CODER_PP_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_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 block + * + * input: stream of byte vectors; output: stream of byte vectors + */ +class 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_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_fake_channel_decoder_pp_sptr +gr_make_fake_channel_decoder_pp(int input_vlen, int output_vlen); + +/*! + * \brief remove fake padding from packet + * \ingroup block + * + * input: stream of byte vectors; output: stream of byte vectors + */ +class 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_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 0000000000..3bf394e272 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..ebbece57f5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fast_atan2f.cc @@ -0,0 +1,198 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_feval.cc b/gnuradio-core/src/lib/general/gr_feval.cc new file mode 100644 index 0000000000..b30930ecba --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_feval.cc @@ -0,0 +1,86 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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; +} + +gr_feval_ff::~gr_feval_ff(){} + +float +gr_feval_ff::eval(float x) +{ + return 0; +} + +gr_feval_cc::~gr_feval_cc(){} + +gr_complex +gr_feval_cc::eval(gr_complex x) +{ + return 0; +} + +gr_feval_ll::~gr_feval_ll(){} + +long +gr_feval_ll::eval(long x) +{ + return 0; +} + +/* + * Trivial examples showing C++ (transparently) calling Python + */ +double +gr_feval_dd_example(gr_feval_dd *f, double x) +{ + return f->eval(x); +} + +float +gr_feval_ff_example(gr_feval_ff *f, float x) +{ + return f->eval(x); +} + +gr_complex +gr_feval_cc_example(gr_feval_cc *f, gr_complex x) +{ + return f->eval(x); +} + +long +gr_feval_ll_example(gr_feval_ll *f, long x) +{ + return f->eval(x); +} 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 0000000000..e9f3ae3506 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_feval.h @@ -0,0 +1,116 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_FEVAL_H +#define INCLUDED_GR_FEVAL_H + +#include <gr_complex.h> + +/*! + * \brief base class for evaluating a function: double -> double + * + * 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. + */ +class gr_feval_dd +{ +public: + gr_feval_dd() {} + virtual ~gr_feval_dd(); + + /*! + * \brief override this to define the function + */ + virtual double eval(double x); +}; + +/*! + * \brief base class for evaluating a function: float -> float + * + * 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. + */ +class gr_feval_ff +{ +public: + gr_feval_ff() {} + virtual ~gr_feval_ff(); + + /*! + * \brief override this to define the function + */ + virtual float eval(float x); +}; + +/*! + * \brief base class for evaluating a function: complex -> complex + * + * 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. + */ +class gr_feval_cc +{ +public: + gr_feval_cc() {} + virtual ~gr_feval_cc(); + + /*! + * \brief override this to define the function + */ + virtual gr_complex eval(gr_complex x); +}; + +/*! + * \brief base class for evaluating a function: long -> long + * + * 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. + */ +class gr_feval_ll +{ +public: + gr_feval_ll() {} + virtual ~gr_feval_ll(); + + /*! + * \brief override this to define the function + */ + virtual long eval(long x); +}; + +/*! + * \brief trivial examples / test cases showing C++ calling Python code + */ +double gr_feval_dd_example(gr_feval_dd *f, double x); +float gr_feval_ff_example(gr_feval_ff *f, float x); +gr_complex gr_feval_cc_example(gr_feval_cc *f, gr_complex x); +long gr_feval_ll_example(gr_feval_ll *f, long x); + + +#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 0000000000..f7d8c2219a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_feval.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// Enable SWIG directors for these classes +%feature("director") gr_feval_dd; +%feature("director") gr_feval_cc; +%feature("director") gr_feval_ll; + + +%rename(feval_dd) gr_feval_dd; +class gr_feval_dd +{ +public: + gr_feval_dd() {} + virtual ~gr_feval_dd(); + + virtual double eval(double x); +}; + +%rename(feval_cc) gr_feval_cc; +class gr_feval_cc +{ +public: + gr_feval_cc() {} + virtual ~gr_feval_cc(); + + virtual gr_complex eval(gr_complex x); +}; + +%rename(feval_ll) gr_feval_ll; +class gr_feval_ll +{ +public: + gr_feval_ll() {} + virtual ~gr_feval_ll(); + + virtual long eval(long 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); 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 0000000000..e529159081 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fft_vcc.cc @@ -0,0 +1,102 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_fft_vcc.h> +#include <gr_io_signature.h> +#include <gri_fft.h> +#include <math.h> + +gr_fft_vcc_sptr +gr_make_fft_vcc (int fft_size, bool forward,const std::vector<float> window) +{ + return gr_fft_vcc_sptr (new gr_fft_vcc (fft_size, forward, window)); +} + +gr_fft_vcc::gr_fft_vcc (int fft_size, bool forward, const std::vector<float> window) + : gr_sync_block ("fft_vcc", + 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_fft = new gri_fft_complex (d_fft_size, forward); + + set_window(window); + +} + +gr_fft_vcc::~gr_fft_vcc () +{ + delete d_fft; +} + +int +gr_fft_vcc::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(); + for (unsigned int i = 0; i < d_fft_size; i++) // apply window + dst[i] = in[i] * d_window[i]; + } + else + memcpy (d_fft->get_inbuf(), in, input_data_size); + + // 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_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; +} 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 0000000000..784471a316 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fft_vcc.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FFT_VCC_H +#define INCLUDED_GR_FFT_VCC_H + +#include <gr_sync_block.h> + +class gri_fft_complex; + +class gr_fft_vcc; +typedef boost::shared_ptr<gr_fft_vcc> gr_fft_vcc_sptr; + +gr_fft_vcc_sptr +gr_make_fft_vcc (int fft_size, bool forward, const std::vector<float> window); + +/*! + * \brief Compute forward or reverse FFT. complex vector in / complex vector out. + * \ingroup block + */ + +class gr_fft_vcc : public gr_sync_block +{ + friend gr_fft_vcc_sptr + gr_make_fft_vcc (int fft_size, bool forward, const std::vector<float> window); + + unsigned int d_fft_size; + std::vector<float> d_window; + gri_fft_complex *d_fft; + + gr_fft_vcc (int fft_size, bool forward, const std::vector<float> window); + + public: + ~gr_fft_vcc (); + + 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_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 0000000000..a171d122ba --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fft_vcc.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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); + +class gr_fft_vcc : public gr_sync_block +{ + protected: + gr_fft_vcc (int fft_size, bool forward, const std::vector<float> window); + + public: + bool set_window(const std::vector<float> window); +}; 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 0000000000..d6d2479114 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fft_vfc.cc @@ -0,0 +1,116 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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> + + +// 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) +{ + return gr_fft_vfc_sptr (new gr_fft_vfc (fft_size, forward, window)); +} + +gr_fft_vfc::gr_fft_vfc (int fft_size, bool forward, const std::vector<float> window) + : 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); + + set_window(window); +} + +gr_fft_vfc::~gr_fft_vfc () +{ + delete d_fft; +} + +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 0000000000..a30495d8ff --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fft_vfc.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FFT_VFC_H +#define INCLUDED_GR_FFT_VFC_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_fft_vfc_sptr +gr_make_fft_vfc (int fft_size, bool forward, const std::vector<float>); + +/*! + * \brief Compute forward FFT. float vector in / complex vector out. + * \ingroup block + */ + +class gr_fft_vfc : public gr_sync_block +{ + friend gr_fft_vfc_sptr + gr_make_fft_vfc (int fft_size, bool forward, const std::vector<float> window); + + 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); + + public: + ~gr_fft_vfc (); + + 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 0000000000..f30606d824 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fft_vfc.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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); + +class gr_fft_vfc : public gr_sync_block +{ + protected: + gr_fft_vfc (int fft_size, bool forward, const std::vector<float> window); + + public: + bool set_window(const std::vector<float> window); +}; 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 0000000000..d09d68d610 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_firdes.cc @@ -0,0 +1,584 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#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 (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 (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 (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 (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 (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)) / (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 (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; + +#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::runtime_error ("not_implemented"); + } + + 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 0000000000..734f8ee9fe --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_firdes.h @@ -0,0 +1,225 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GR_FIRDES_H_ +#define _GR_FIRDES_H_ + +#include <vector> +#include <cmath> +#include <gr_complex.h> + +/*! + * \brief Finite Impulse Response (FIR) filter design functions. + */ + +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 a function of beta, google it + }; + + + // ... 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 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 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 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 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 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, + 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); +}; + +#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 0000000000..a0ea2f4533 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_firdes.i @@ -0,0 +1,187 @@ +/* -*- C++ -*- */ + +/*! + * \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 + }; + + // ... 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 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 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-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<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 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 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, + 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 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); + + /*! + * Return window given type, ntaps and optional beta. + */ + static std::vector<float> gr_firdes::window (win_type type, int ntaps, double beta); +}; 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 0000000000..ed9538fc19 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_char.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_float_to_char.h> +#include <gr_io_signature.h> +#include <gri_float_to_char.h> + +gr_float_to_char_sptr +gr_make_float_to_char () +{ + return gr_float_to_char_sptr (new gr_float_to_char ()); +} + +gr_float_to_char::gr_float_to_char () + : gr_sync_block ("gr_float_to_char", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (char))) +{ +} + +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]; + char *out = (char *) output_items[0]; + + gri_float_to_char (in, out, 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 0000000000..e1d0f9f0a1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_char.h @@ -0,0 +1,51 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FLOAT_TO_CHAR_H +#define INCLUDED_GR_FLOAT_TO_CHAR_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_float_to_char_sptr +gr_make_float_to_char (); + +/*! + * \brief Convert stream of float to a stream of char + * \ingroup converter + */ + +class gr_float_to_char : public gr_sync_block +{ + friend gr_float_to_char_sptr gr_make_float_to_char (); + gr_float_to_char (); + + 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_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 0000000000..139439c3d5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_char.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,float_to_char) + +gr_float_to_char_sptr gr_make_float_to_char (); + +class gr_float_to_char : public gr_sync_block +{ + gr_float_to_char (); +}; 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 0000000000..547d9173a8 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_complex.cc @@ -0,0 +1,71 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 () +{ + return gr_float_to_complex_sptr (new gr_float_to_complex ()); +} + +gr_float_to_complex::gr_float_to_complex () + : gr_sync_block ("gr_float_to_complex", + gr_make_io_signature (1, 2, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (gr_complex))) +{ +} + +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 (int j = 0; j < noutput_items; j++) + out[j] = gr_complex (r[j], 0); + break; + + case 2: + for (int j = 0; j < noutput_items; 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 0000000000..8c285217a1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FLOAT_TO_COMPLEX_H +#define INCLUDED_GR_FLOAT_TO_COMPLEX_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_float_to_complex_sptr +gr_make_float_to_complex (); + +/*! + * \brief Convert 1 or 2 streams of float to a stream of gr_complex + * \ingroup converter + */ + +class gr_float_to_complex : public gr_sync_block +{ + friend gr_float_to_complex_sptr gr_make_float_to_complex (); + gr_float_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_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 0000000000..4a6ea324be --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,float_to_complex) + +gr_float_to_complex_sptr gr_make_float_to_complex (); + +class gr_float_to_complex : public gr_sync_block +{ + gr_float_to_complex (); +}; 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 0000000000..171726b828 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_short.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_float_to_short.h> +#include <gr_io_signature.h> +#include <gri_float_to_short.h> + +gr_float_to_short_sptr +gr_make_float_to_short () +{ + return gr_float_to_short_sptr (new gr_float_to_short ()); +} + +gr_float_to_short::gr_float_to_short () + : gr_sync_block ("gr_float_to_short", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (short))) +{ +} + +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]; + + gri_float_to_short (in, out, 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 0000000000..75fdd9439d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_short.h @@ -0,0 +1,51 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FLOAT_TO_SHORT_H +#define INCLUDED_GR_FLOAT_TO_SHORT_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_float_to_short_sptr +gr_make_float_to_short (); + +/*! + * \brief Convert stream of float to a stream of short + * \ingroup converter + */ + +class gr_float_to_short : public gr_sync_block +{ + friend gr_float_to_short_sptr gr_make_float_to_short (); + gr_float_to_short (); + + 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_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 0000000000..10726bc8ac --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,float_to_short) + +gr_float_to_short_sptr gr_make_float_to_short (); + +class gr_float_to_short : public gr_sync_block +{ + gr_float_to_short (); +}; 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 0000000000..d940242728 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_uchar.cc @@ -0,0 +1,58 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_float_to_uchar_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 0000000000..bab00c4292 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_float_to_uchar.h @@ -0,0 +1,51 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FLOAT_TO_UCHAR_H +#define INCLUDED_GR_FLOAT_TO_UCHAR_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_float_to_uchar_sptr +gr_make_float_to_uchar (); + +/*! + * \brief Convert stream of float to a stream of unsigned char + * \ingroup converter + */ + +class gr_float_to_uchar : public gr_sync_block +{ + friend 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 0000000000..8c0ee58439 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_framer_sink_1.cc b/gnuradio-core/src/lib/general/gr_framer_sink_1.cc new file mode 100644 index 0000000000..c1afc434ba --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_framer_sink_1.cc @@ -0,0 +1,175 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_framer_sink_1.h> +#include <gr_io_signature.h> +#include <cstdio> +#include <stdexcept> + +#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) +{ + 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_framer_sink_1_sptr +gr_make_framer_sink_1(gr_msg_queue_sptr target_queue) +{ + return gr_framer_sink_1_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 = 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"); + + 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 + 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_framer_sink_1.h b/gnuradio-core/src/lib/general/gr_framer_sink_1.h new file mode 100644 index 0000000000..3e38aeedc0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_framer_sink_1.h @@ -0,0 +1,103 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FRAMER_SINK_1_H +#define INCLUDED_GR_FRAMER_SINK_1_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_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 + * + * 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_framer_sink_1 : public gr_sync_block +{ + friend 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_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); + + 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_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 0000000000..fbc556961e --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..271b8d33ab --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_frequency_modulator_fc.h> +#include <gr_io_signature.h> +#include <gr_sincos.h> +#include <math.h> + + +gr_frequency_modulator_fc_sptr gr_make_frequency_modulator_fc (double sensitivity) +{ + return gr_frequency_modulator_fc_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]; + float oi, oq; + gr_sincosf (d_phase, &oq, &oi); + out[i] = gr_complex (oi, oq); + } + + // Limit the phase accumulator to [-16*pi,16*pi] + // to avoid loss of precision in the addition above. + + if (fabs (d_phase) > 16 * M_PI){ + double ii = trunc (d_phase / (2 * M_PI)); + d_phase = d_phase - (ii * 2 * M_PI); + } + + 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 0000000000..6080adb9e3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FREQUENCY_MODULATOR_FC_H +#define INCLUDED_GR_FREQUENCY_MODULATOR_FC_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_frequency_modulator_fc_sptr gr_make_frequency_modulator_fc (double sensitivity); + +/*! + * \brief Frequency modulator block + * \ingroup block + * + * float input; complex baseband output + */ +class gr_frequency_modulator_fc : public gr_sync_block +{ + double d_sensitivity; + double d_phase; + + friend gr_frequency_modulator_fc_sptr + gr_make_frequency_modulator_fc (double sensitivity); + + gr_frequency_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_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 0000000000..04a8b5363a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_frequency_modulator_fc.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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); +}; 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 0000000000..62ed8bd67a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fxpt.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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" +}; + +// gcc 4.x fix +const float gr_fxpt::TWO_TO_THE_31; +const float gr_fxpt::PI; + +#if 0 +/* + * Compute sine using table lookup with linear interpolation. + * Each table entry contains slope and intercept. + */ +float +gr_fxpt::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]; +} + +float +gr_fxpt::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]; +} +#endif 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 0000000000..fc8432d64b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fxpt.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_FXPT_H +#define INCLUDED_GR_FXPT_H + +#include <gr_types.h> + +/*! + * \brief fixed point sine and cosine and friends. + * + * fixed pt radians + * --------- -------- + * -2**31 -pi + * 0 0 + * 2**31-1 pi - epsilon + * + */ +class 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 = 3.14159265358979323846; + static const float TWO_TO_THE_31 = 2147483648.0; +public: + + static gr_int32 + float_to_fixed (float x) + { + 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]; + } + +}; + +#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 0000000000..c779bdfe53 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fxpt_nco.h @@ -0,0 +1,151 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_FXPT_NCO_H +#define INCLUDED_GR_FXPT_NCO_H + +#include <gr_fxpt.h> +#include <gr_complex.h> + +/*! + * \brief Numerically Controlled Oscillator (NCO) + */ +class gr_fxpt_nco { + gr_int32 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 0000000000..c57a577b3b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_fxpt_vco.h @@ -0,0 +1,71 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_FXPT_VCO_H +#define INCLUDED_GR_FXPT_VCO_H + +#include <gr_fxpt.h> +#include <gr_complex.h> + +/*! + * \brief Voltage Controlled Oscillator (VCO) + */ +class 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_head.cc b/gnuradio-core/src/lib/general/gr_head.cc new file mode 100644 index 0000000000..7771ed515b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_head.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_head.h> +#include <gr_io_signature.h> + +gr_head::gr_head (size_t sizeof_stream_item, int 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_block_sptr +gr_make_head (size_t sizeof_stream_item, int nitems) +{ + return gr_block_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, 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 0000000000..125ee14b66 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_head.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_HEAD_H +#define INCLUDED_GR_HEAD_H + +#include <gr_sync_block.h> +#include <stddef.h> // size_t + +/*! + * \brief copies the first N items to the output then signals done + * \ingroup block + * + * Useful for building test cases + */ + +class gr_head : public gr_sync_block +{ + friend gr_block_sptr gr_make_head (size_t sizeof_stream_item, int nitems); + gr_head (size_t sizeof_stream_item, int nitems); + + int d_nitems; + int d_ncopied_items; + + public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +gr_block_sptr +gr_make_head (size_t sizeof_stream_item, int 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 0000000000..0a34214dbf --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_head.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%ignore gr_head; +class gr_head : public gr_block { + friend gr_block_sptr gr_make_head (size_t sizeof_stream_item, int nitems); + gr_head (size_t sizeof_stream_item, int nitems); +}; + +%rename(head) gr_make_head; +gr_block_sptr gr_make_head (size_t sizeof_stream_item, int nitems); 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 0000000000..cae0cd9dc1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_interleave.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_interleave_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 0000000000..128ed7ce13 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_interleave.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_INTERLEAVE_H +#define INCLUDED_GR_INTERLEAVE_H + +#include <gr_sync_interpolator.h> + +class gr_interleave; +typedef boost::shared_ptr<gr_interleave> gr_interleave_sptr; + +gr_interleave_sptr gr_make_interleave (size_t itemsize); + +/*! + * \brief interleave N inputs to a single output + * \ingroup block + */ +class gr_interleave : public gr_sync_interpolator +{ + friend 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 0000000000..f082531fc7 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..c43e725438 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_interleaved_short_to_complex.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_interleaved_short_to_complex_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 0000000000..0eb1a32fa8 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_interleaved_short_to_complex.h @@ -0,0 +1,51 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_INTERLEAVED_SHORT_TO_COMPLEX_H +#define INCLUDED_GR_INTERLEAVED_SHORT_TO_COMPLEX_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_interleaved_short_to_complex_sptr +gr_make_interleaved_short_to_complex (); + +/*! + * \brief Convert stream of interleaved shorts to a stream of complex + * \ingroup converter + */ + +class gr_interleaved_short_to_complex : public gr_sync_decimator +{ + friend 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 0000000000..02d1ec0126 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_keep_one_in_n.cc b/gnuradio-core/src/lib/general/gr_keep_one_in_n.cc new file mode 100644 index 0000000000..e302070863 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_keep_one_in_n.cc @@ -0,0 +1,81 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_keep_one_in_n.h> +#include <gr_io_signature.h> + +gr_keep_one_in_n_sptr +gr_make_keep_one_in_n (size_t item_size, int n) +{ + return gr_keep_one_in_n_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_n (n), d_count(n) +{ +} + +void +gr_keep_one_in_n::set_n(int n) +{ + if (n < 1) + n = 1; + + d_n = n; + d_count = 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++; + } + + 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 0000000000..44a8474071 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_keep_one_in_n.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_KEEP_ONE_IN_N_H +#define INCLUDED_GR_KEEP_ONE_IN_N_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_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 block + */ +class gr_keep_one_in_n : public gr_block +{ + friend gr_keep_one_in_n_sptr + gr_make_keep_one_in_n (size_t item_size, int n); + + int d_n; + int d_count; + + 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 0000000000..13ed9a3869 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..bf980d239f --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_kludge_copy_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, sizeof (float)), + gr_make_io_signature (1, -1, sizeof (float))), + 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 0000000000..d1cf54eecc --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_kludge_copy.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_KLUDGE_COPY_H +#define INCLUDED_GR_KLUDGE_COPY_H + +#include <gr_sync_block.h> + +class gr_kludge_copy; +typedef boost::shared_ptr<gr_kludge_copy> gr_kludge_copy_sptr; + +gr_kludge_copy_sptr gr_make_kludge_copy(size_t itemsize); + +/*! + * \brief output[i] = input[i] + * \ingroup block + * + * This is a short term kludge to work around a problem with the hierarchical block impl. + */ +class gr_kludge_copy : public gr_sync_block +{ + size_t d_itemsize; + + friend 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 0000000000..828ec212f0 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..8a0b876862 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_lfsr_32k_source_s.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_lfsr_32k_source_s_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 0000000000..d3d72a9868 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_lfsr_32k_source_s.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_LFSR_32K_SOURCE_S_H +#define INCLUDED_GR_LFSR_32K_SOURCE_S_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_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 + * + * This source is typically used along with gr_check_lfsr_32k_s to test + * the USRP using its digital loopback mode. + */ +class gr_lfsr_32k_source_s : public gr_sync_block +{ + friend 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 0000000000..60b6267961 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_lms_dfe_cc.cc b/gnuradio-core/src/lib/general/gr_lms_dfe_cc.cc new file mode 100644 index 0000000000..874ad84f9f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_lms_dfe_cc.cc @@ -0,0 +1,148 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_lms_dfe_cc.h> +#include <gr_io_signature.h> +#include <gr_misc.h> +#include <iostream> + +gr_complex +gr_lms_dfe_cc::slicer_0deg (gr_complex sample) +{ + gr_complex out; + if(fabs(real(sample))>fabs(imag(sample))) { + if(real(sample) > 0) + out = gr_complex(1,0); + else + out = gr_complex(-1,0); + } + else { + if(imag(sample) > 0) + out = gr_complex(0,1); + else + out = gr_complex(0,-1); + } + return out; +} + +gr_complex +gr_lms_dfe_cc::slicer_45deg (gr_complex sample) +{ + gr_complex out; + if(real(sample) > 0) + out = gr_complex(1,0); + else + out = gr_complex(-1,0); + if(imag(sample) > 0) + out += gr_complex(0,1); + else + out += gr_complex(0,-1); + return out; +} + +gr_lms_dfe_cc_sptr +gr_make_lms_dfe_cc (float lambda_ff, float lambda_fb, + unsigned int num_fftaps, unsigned int num_fbtaps) +{ + return gr_lms_dfe_cc_sptr (new gr_lms_dfe_cc (lambda_ff, lambda_fb, + num_fftaps, num_fbtaps)); +} + +gr_lms_dfe_cc::gr_lms_dfe_cc (float lambda_ff, float lambda_fb , + unsigned int num_fftaps, unsigned int num_fbtaps) + : gr_sync_block ("lms_dfe_cc", + gr_make_io_signature (1, 1, sizeof (gr_complex)), + gr_make_io_signature (1, 1, sizeof (gr_complex))), + d_lambda_ff (lambda_ff), d_lambda_fb (lambda_fb), + d_ff_delayline(gr_rounduppow2(num_fftaps)), + d_fb_delayline(gr_rounduppow2(num_fbtaps)), + d_ff_taps(num_fftaps),d_fb_taps(num_fbtaps), + d_ff_index(0), d_fb_index(0) +{ + gr_zero_vector(d_ff_taps); + d_ff_taps [d_ff_taps.size()/2] = 1; + + gr_zero_vector(d_fb_taps); + gr_zero_vector(d_ff_delayline); + gr_zero_vector(d_fb_delayline); +} + +int +gr_lms_dfe_cc::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const gr_complex *iptr = (const gr_complex *) input_items[0]; + gr_complex *optr = (gr_complex *) output_items[0]; + + gr_complex acc, decision, error; + unsigned int i; + + unsigned int ff_mask = d_ff_delayline.size() - 1; // size is power of 2 + unsigned int fb_mask = d_fb_delayline.size() - 1; + + int size = noutput_items; + while (size-- > 0){ + acc = 0; + d_ff_delayline[d_ff_index] = *iptr++; + + // Compute output + for (i=0; i < d_ff_taps.size(); i++) + acc += conj(d_ff_delayline[(i+d_ff_index) & ff_mask]) * d_ff_taps[i]; + + for (i=0; i < d_fb_taps.size(); i++) + acc -= conj(d_fb_delayline[(i+d_fb_index) & fb_mask]) * d_fb_taps[i]; + + decision = slicer_45deg(acc); + error = decision - acc; + + // Update taps + for (i=0; i < d_ff_taps.size(); i++) + d_ff_taps[i] += d_lambda_ff * conj(error) * d_ff_delayline[(i+d_ff_index) & ff_mask]; + + for (i=0; i < d_fb_taps.size(); i++) + d_fb_taps[i] -= d_lambda_fb * conj(error) * d_fb_delayline[(i+d_fb_index) & fb_mask]; + + d_fb_index = (d_fb_index - 1) & fb_mask; // Decrement index + d_ff_index = (d_ff_index - 1) & ff_mask; // Decrement index + + d_fb_delayline[d_fb_index] = decision; // Save decision in feedback + + *optr++ = acc; // Output decision + } + + if (0){ + std::cout << "FF Taps\t"; + for(i=0;i<d_ff_taps.size();i++) + std::cout << d_ff_taps[i] << "\t"; + std::cout << std::endl << "FB Taps\t"; + for(i=0;i<d_fb_taps.size();i++) + std::cout << d_fb_taps[i] << "\t"; + std::cout << std::endl; + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_lms_dfe_cc.h b/gnuradio-core/src/lib/general/gr_lms_dfe_cc.h new file mode 100644 index 0000000000..034c26d86e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_lms_dfe_cc.h @@ -0,0 +1,64 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_LMS_DFE_CC_H +#define INCLUDED_GR_LMS_DFE_CC_H + +#include <gr_sync_block.h> + +class gr_lms_dfe_cc; +typedef boost::shared_ptr<gr_lms_dfe_cc> gr_lms_dfe_cc_sptr; + +gr_lms_dfe_cc_sptr gr_make_lms_dfe_cc (float lambda_ff, float lambda_fb, + unsigned int num_fftaps, unsigned int num_fbtaps); + +/*! + * \brief Least-Mean-Square Decision Feedback Equalizer (complex in/out) + * \ingroup block + */ +class gr_lms_dfe_cc : public gr_sync_block +{ + friend gr_lms_dfe_cc_sptr gr_make_lms_dfe_cc (float lambda_ff, float lambda_fb, + unsigned int num_fftaps, unsigned int num_fbtaps); + + float d_lambda_ff; + float d_lambda_fb; + std::vector<gr_complex> d_ff_delayline; + std::vector<gr_complex> d_fb_delayline; + std::vector<gr_complex> d_ff_taps; + std::vector<gr_complex> d_fb_taps; + unsigned int d_ff_index; + unsigned int d_fb_index; + + gr_lms_dfe_cc (float lambda_ff, float lambda_fb, + unsigned int num_fftaps, unsigned int num_fbtaps); + gr_complex slicer_0deg(gr_complex baud); + gr_complex slicer_45deg(gr_complex baud); + + 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_lms_dfe_cc.i b/gnuradio-core/src/lib/general/gr_lms_dfe_cc.i new file mode 100644 index 0000000000..4ea4a6ae1f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_lms_dfe_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +GR_SWIG_BLOCK_MAGIC(gr,lms_dfe_cc) + +gr_lms_dfe_cc_sptr gr_make_lms_dfe_cc (float lambda_ff, float lambda_fb, + unsigned int num_fftaps, unsigned int num_fbtaps); + +class gr_lms_dfe_cc : public gr_sync_block +{ + private: + gr_lms_dfe_cc (float lambda_ff, float lambda_fb, + unsigned int num_fftaps, unsigned int num_fbtaps); + gr_complex slicer_0deg(gr_complex baud); + gr_complex slicer_45deg(gr_complex baud); + gr_complex conjg(gr_complex val); +}; diff --git a/gnuradio-core/src/lib/general/gr_lms_dfe_ff.cc b/gnuradio-core/src/lib/general/gr_lms_dfe_ff.cc new file mode 100644 index 0000000000..017c90a215 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_lms_dfe_ff.cc @@ -0,0 +1,122 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_lms_dfe_ff.h> +#include <gr_io_signature.h> +#include <gr_misc.h> +#include <iostream> + +float +slice(float val) +{ + if (val>0) + return 1; + else + return -1; +} + +gr_lms_dfe_ff_sptr +gr_make_lms_dfe_ff (float lambda_ff, float lambda_fb, + unsigned int num_fftaps, unsigned int num_fbtaps) +{ + return gr_lms_dfe_ff_sptr (new gr_lms_dfe_ff (lambda_ff,lambda_fb,num_fftaps,num_fbtaps)); +} + +gr_lms_dfe_ff::gr_lms_dfe_ff (float lambda_ff, float lambda_fb , + unsigned int num_fftaps, unsigned int num_fbtaps) + : gr_sync_block ("lms_dfe_ff", + gr_make_io_signature (1, 1, sizeof (float)), + gr_make_io_signature (1, 1, sizeof (float))), + d_lambda_ff (lambda_ff), d_lambda_fb (lambda_fb), + d_ff_delayline(gr_rounduppow2(num_fftaps)), + d_fb_delayline(gr_rounduppow2(num_fbtaps)), + d_ff_taps(num_fftaps), d_fb_taps(num_fbtaps), + d_ff_index(0), d_fb_index(0) +{ + gr_zero_vector(d_ff_taps); + d_ff_taps [d_ff_taps.size()/2] = 1; + + gr_zero_vector(d_fb_taps); + gr_zero_vector(d_ff_delayline); + gr_zero_vector(d_fb_delayline); +} + +int +gr_lms_dfe_ff::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const float *iptr = (const float *) input_items[0]; + float *optr = (float *) output_items[0]; + + float acc, decision, error; + unsigned int i; + + unsigned int ff_mask = d_ff_delayline.size() - 1; // size is power of 2 + unsigned int fb_mask = d_fb_delayline.size() - 1; + + int size = noutput_items; + while(size-- > 0) { + acc = 0; + d_ff_delayline[d_ff_index] = *iptr++; + + // Compute output + for (i=0; i < d_ff_taps.size(); i++) + acc += d_ff_delayline[(i+d_ff_index) & ff_mask] * d_ff_taps[i]; + + for (i=0; i < d_fb_taps.size(); i++) + acc -= d_fb_delayline[(i+d_fb_index) & fb_mask] * d_fb_taps[i]; + + decision = slice(acc); + error = decision - acc; + + // Update taps + for (i=0; i < d_ff_taps.size(); i++) + d_ff_taps[i] += d_lambda_ff * error * d_ff_delayline[(i+d_ff_index) & ff_mask]; + + for (i=0; i < d_fb_taps.size(); i++) + d_fb_taps[i] -= d_lambda_fb * error * d_fb_delayline[(i+d_fb_index) & fb_mask]; + + d_fb_index = (d_fb_index - 1) & fb_mask; // Decrement index + d_ff_index = (d_ff_index - 1) & ff_mask; // Decrement index + + d_fb_delayline[d_fb_index] = decision; // Save decision in feedback + + *optr++ = acc; // Output decision + } + + if (0){ + std::cout << "FF Taps\t"; + for(i=0;i<d_ff_taps.size();i++) + std::cout << d_ff_taps[i] << "\t"; + std::cout << std::endl << "FB Taps\t"; + for(i=0;i<d_fb_taps.size();i++) + std::cout << d_fb_taps[i] << "\t"; + std::cout << std::endl; + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_lms_dfe_ff.h b/gnuradio-core/src/lib/general/gr_lms_dfe_ff.h new file mode 100644 index 0000000000..338b0a1447 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_lms_dfe_ff.h @@ -0,0 +1,62 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_LMS_DFE_FF_H +#define INCLUDED_GR_LMS_DFE_FF_H + +#include <gr_sync_block.h> + +class gr_lms_dfe_ff; +typedef boost::shared_ptr<gr_lms_dfe_ff> gr_lms_dfe_ff_sptr; + +gr_lms_dfe_ff_sptr gr_make_lms_dfe_ff (float lambda_ff, float lambda_fb, + unsigned int num_fftaps, unsigned int num_fbtaps); + +/*! + * \brief Least-Mean-Square Decision Feedback Equalizer (float in/out) + * \ingroup block + */ +class gr_lms_dfe_ff : public gr_sync_block +{ + friend gr_lms_dfe_ff_sptr gr_make_lms_dfe_ff (float lambda_ff, float lambda_fb, + unsigned int num_fftaps, unsigned int num_fbtaps); + + float d_lambda_ff; + float d_lambda_fb; + std::vector<float> d_ff_delayline; + std::vector<float> d_fb_delayline; + std::vector<float> d_ff_taps; + std::vector<float> d_fb_taps; + unsigned int d_ff_index; + unsigned int d_fb_index; + + gr_lms_dfe_ff (float lambda_ff, float lambda_fb, + unsigned int num_fftaps, unsigned int num_fbtaps); + + 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_lms_dfe_ff.i b/gnuradio-core/src/lib/general/gr_lms_dfe_ff.i new file mode 100644 index 0000000000..6b9e439d08 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_lms_dfe_ff.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +GR_SWIG_BLOCK_MAGIC(gr,lms_dfe_ff) + +gr_lms_dfe_ff_sptr gr_make_lms_dfe_ff (float lambda_ff, float lambda_fb, + unsigned int num_fftaps, unsigned int num_fbtaps); + +class gr_lms_dfe_ff : public gr_sync_block +{ + private: + gr_lms_dfe_ff (float lambda_ff, float lambda_fb, + unsigned int num_fftaps, unsigned int num_fbtaps); +}; 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 0000000000..fe255045cc --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_log2_const.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +/* + * a bit of template hackery... + */ +#ifndef INCLUDED_GR_LOG2_CONST_H +#define INCLUDED_GR_LOG2_CONST_H + +#include <assert.h> + +template<unsigned int k> static inline int gr_log2_const() { assert(0); } + +template<> static inline int gr_log2_const<1>() { return 0; } +template<> static inline int gr_log2_const<2>() { return 1; } +template<> static inline int gr_log2_const<4>() { return 2; } +template<> static inline int gr_log2_const<8>() { return 3; } +template<> static inline int gr_log2_const<16>() { return 4; } +template<> static inline int gr_log2_const<32>() { return 5; } +template<> static inline int gr_log2_const<64>() { return 6; } +template<> static inline int gr_log2_const<128>() { return 7; } +template<> static inline int gr_log2_const<256>() { return 8; } +template<> static inline int gr_log2_const<512>() { return 9; } +template<> static 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 0000000000..891ff02ce3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_map_bb.cc @@ -0,0 +1,61 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_map_bb_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::max((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 0000000000..f5f7fa8dd0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_map_bb.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_MAP_BB_H +#define INCLUDED_GR_MAP_BB_H + +#include <gr_sync_block.h> + +class gr_map_bb; +typedef boost::shared_ptr<gr_map_bb> gr_map_bb_sptr; + +gr_map_bb_sptr gr_make_map_bb(const std::vector<int> &map); + +/*! + * \brief output[i] = map[input[i]] + * \ingroup block + */ + +class gr_map_bb : public gr_sync_block +{ + friend 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 0000000000..a4282a3ebe --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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.cc b/gnuradio-core/src/lib/general/gr_math.cc new file mode 100644 index 0000000000..e2e7249e2b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_math.cc @@ -0,0 +1,102 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gr_math.h> +#include <math.h> + +/* + * Greatest Common Divisor, using Euclid's algorithm. + * [There are faster algorithms. See Knuth 4.5.2 if you care] + */ + +long +gr_gcd (long m, long n) +{ + if (m < 0) + m = -m; + + if (n < 0) + n = -n; + + while (n != 0){ + long t = m % n; + m = n; + n = t; + } + + return m; +} + + +/* + * These really need some configure hacking to figure out the right answer. + * As a stop gap, try for a macro, and if not that, then try std:: + */ + +// returns a non-zero value if value is "not-a-number" (NaN), and 0 otherwise + +#if defined(isnan) || !defined(CXX_HAS_STD_ISNAN) + +int +gr_isnan (double value) +{ + return isnan (value); +} + +#else + +int +gr_isnan (double value) +{ + return std::isnan (value); +} + +#endif + +// returns a non-zero value if the value of x has its sign bit set. +// +// This is not the same as `x < 0.0', because IEEE 754 floating point +// allows zero to be signed. The comparison `-0.0 < 0.0' is false, but +// `gr_signbit (-0.0)' will return a nonzero value. + +#ifdef signbit + +int +gr_signbit (double x) +{ + return signbit (x); +} + +#else + +int +gr_signbit (double x) +{ + return std::signbit (x); +} + + +#endif 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 0000000000..5ce8fb7827 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_math.h @@ -0,0 +1,60 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* + * mathematical odds and ends. + */ + +#ifndef _GR_MATH_H_ +#define _GR_MATH_H_ + +long gr_gcd (long m, long n); + +// returns a non-zero value if value is "not-a-number" (NaN), and 0 otherwise +int gr_isnan (double value); + +// returns a non-zero value if the value of x has its sign bit set. +// +// This is not the same as `x < 0.0', because IEEE 754 floating point +// allows zero to be signed. The comparison `-0.0 < 0.0' is false, but +// `gr_signbit (-0.0)' will return a nonzero value. + +int gr_signbit (double x); + +/*! + * \brief Fast arc tangent using table lookup and linear interpolation + * + * \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. + */ +float gr_fast_atan2f(float y, float x); + +#endif /* _GR_MATH_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 0000000000..d15202273a --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..177df96485 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_misc.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_MISC_H +#define INCLUDED_GR_MISC_H + +#include <gr_types.h> + +unsigned int +gr_rounduppow2(unsigned int n); + +// FIXME should be template +void gr_zero_vector(std::vector<float> &v); +void gr_zero_vector(std::vector<double> &v); +void gr_zero_vector(std::vector<int> &v); +void gr_zero_vector(std::vector<gr_complex> &v); + + +#endif /* INCLUDED_GR_MISC_H */ diff --git a/gnuradio-core/src/lib/general/gr_multiply_XX.cc.t b/gnuradio-core/src/lib/general/gr_multiply_XX.cc.t new file mode 100644 index 0000000000..a9c43224f5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_XX.cc.t @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 @SPTR_NAME@ (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 *= ((@I_TYPE@ *) input_items[j])[i]; + + *optr++ = (@O_TYPE@) acc; + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_multiply_XX.h.t b/gnuradio-core/src/lib/general/gr_multiply_XX.h.t new file mode 100644 index 0000000000..cfa416f1fa --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_XX.h.t @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ gr_make_@BASE_NAME@ (); + +/*! + * \brief output = prod (input_0, input_1, ...) + * \ingroup block + * + * Multiply across all input streams. + */ +class @NAME@ : public gr_sync_block +{ + friend @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/general/gr_multiply_XX.i.t b/gnuradio-core/src/lib/general/gr_multiply_XX.i.t new file mode 100644 index 0000000000..8479aad683 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/general/gr_multiply_const_XX.cc.t b/gnuradio-core/src/lib/general/gr_multiply_const_XX.cc.t new file mode 100644 index 0000000000..b312b9c013 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_const_XX.cc.t @@ -0,0 +1,72 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 @SPTR_NAME@ (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/general/gr_multiply_const_XX.h.t b/gnuradio-core/src/lib/general/gr_multiply_const_XX.h.t new file mode 100644 index 0000000000..6e771e0b02 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_const_XX.h.t @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ gr_make_@BASE_NAME@ (@O_TYPE@ k); + +/*! + * \brief output = input * constant + * \ingroup block + */ +class @NAME@ : public gr_sync_block +{ + friend @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/general/gr_multiply_const_XX.i.t b/gnuradio-core/src/lib/general/gr_multiply_const_XX.i.t new file mode 100644 index 0000000000..c2c814b524 --- /dev/null +++ b/gnuradio-core/src/lib/general/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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/general/gr_multiply_const_vXX.cc.t b/gnuradio-core/src/lib/general/gr_multiply_const_vXX.cc.t new file mode 100755 index 0000000000..9b723a3e8c --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_const_vXX.cc.t @@ -0,0 +1,61 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 @SPTR_NAME@ (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/general/gr_multiply_const_vXX.h.t b/gnuradio-core/src/lib/general/gr_multiply_const_vXX.h.t new file mode 100755 index 0000000000..dba875c3f2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_const_vXX.h.t @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ gr_make_@BASE_NAME@ (const std::vector<@I_TYPE@> k); + +/*! + * \brief output vector = input vector * constant vector (element-wise) + * \ingroup block + */ +class @NAME@ : public gr_sync_block +{ + friend @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/general/gr_multiply_const_vXX.i.t b/gnuradio-core/src/lib/general/gr_multiply_const_vXX.i.t new file mode 100755 index 0000000000..38c399438a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_const_vXX.i.t @@ -0,0 +1,37 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/general/gr_multiply_vXX.cc.t b/gnuradio-core/src/lib/general/gr_multiply_vXX.cc.t new file mode 100755 index 0000000000..cc242ddadd --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_vXX.cc.t @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 nitems_per_block) +{ + return @SPTR_NAME@ (new @NAME@ (nitems_per_block)); +} + +@NAME@::@NAME@ (size_t nitems_per_block) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, -1, sizeof (@I_TYPE@)*nitems_per_block), + gr_make_io_signature (1, 1, sizeof (@O_TYPE@)*nitems_per_block)) +{ +} + +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 (); + 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++){ + @I_TYPE@ acc = ((@I_TYPE@ *) input_items[0])[i*nitems_per_block+j]; + for (int k = 1; k < ninputs; k++) + acc *= ((@I_TYPE@ *) input_items[k])[i*nitems_per_block+j]; + + *optr++ = (@O_TYPE@) acc; + } + } + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_multiply_vXX.h.t b/gnuradio-core/src/lib/general/gr_multiply_vXX.h.t new file mode 100755 index 0000000000..c6388d931f --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_vXX.h.t @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ gr_make_@BASE_NAME@ (size_t nitems_per_block); + +/*! + * \brief output = prod (input_0, input_1, ...) + * \ingroup block + * + * Element-wise multiply across all input vectors. + */ +class @NAME@ : public gr_sync_block +{ + friend @SPTR_NAME@ gr_make_@BASE_NAME@ (size_t nitems_per_block); + + @NAME@ (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 diff --git a/gnuradio-core/src/lib/general/gr_multiply_vXX.i.t b/gnuradio-core/src/lib/general/gr_multiply_vXX.i.t new file mode 100755 index 0000000000..0810961039 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_multiply_vXX.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@) + +@SPTR_NAME@ gr_make_@BASE_NAME@ (size_t nitems_per_block); + +class @NAME@ : public gr_sync_block +{ + private: + @NAME@ (size_t nitems_per_block); +}; diff --git a/gnuradio-core/src/lib/general/gr_mute_XX.cc.t b/gnuradio-core/src/lib/general/gr_mute_XX.cc.t new file mode 100644 index 0000000000..740821e5ea --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_mute_XX.cc.t @@ -0,0 +1,79 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 @SPTR_NAME@ (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/general/gr_mute_XX.h.t b/gnuradio-core/src/lib/general/gr_mute_XX.h.t new file mode 100644 index 0000000000..88915322e5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_mute_XX.h.t @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ gr_make_@BASE_NAME@ (bool mute=false); + +/*! + * \brief output = input or zero if muted. + * \ingroup block + */ +class @NAME@ : public gr_sync_block +{ + friend @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/general/gr_mute_XX.i.t b/gnuradio-core/src/lib/general/gr_mute_XX.i.t new file mode 100644 index 0000000000..413e529812 --- /dev/null +++ b/gnuradio-core/src/lib/general/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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/general/gr_nco.h b/gnuradio-core/src/lib/general/gr_nco.h new file mode 100644 index 0000000000..2cf41fd775 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_nco.h @@ -0,0 +1,197 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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) + */ + + +//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 0000000000..71e8279abc --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_nlog10_ff.cc @@ -0,0 +1,64 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_nlog10_ff_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 0000000000..04a6f80d0c --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_nlog10_ff.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_NLOG10_FF_H +#define INCLUDED_GR_NLOG10_FF_H + +#include <gr_sync_block.h> + +class gr_nlog10_ff; +typedef boost::shared_ptr<gr_nlog10_ff> gr_nlog10_ff_sptr; + +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 block + */ +class gr_nlog10_ff : public gr_sync_block +{ + friend 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 0000000000..3dbd12d833 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_noise_source_X.cc.t b/gnuradio-core/src/lib/general/gr_noise_source_X.cc.t new file mode 100644 index 0000000000..401bed1903 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_noise_source_X.cc.t @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 @NAME@_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/general/gr_noise_source_X.h.t b/gnuradio-core/src/lib/general/gr_noise_source_X.h.t new file mode 100644 index 0000000000..bc016affe1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_noise_source_X.h.t @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_sync_block.h> +#include <gr_noise_type.h> +#include <gr_random.h> + + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @NAME@_sptr; + +@NAME@_sptr +gr_make_@BASE_NAME@ (gr_noise_type_t type, float ampl, long seed = 3021); + +/*! + * \brief random number source + * \ingroup source + */ +class @NAME@ : public gr_sync_block { + friend @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 = 3021); + + public: + void set_type (gr_noise_type_t type) { d_type = type; } + void set_amplitude (float ampl) { d_ampl = 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/general/gr_noise_source_X.i.t b/gnuradio-core/src/lib/general/gr_noise_source_X.i.t new file mode 100644 index 0000000000..0a3ad96a72 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_noise_source_X.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@); + +@NAME@_sptr +gr_make_@BASE_NAME@ (gr_noise_type_t type, float ampl, long seed = 3021); + +class @NAME@ : public gr_block { + private: + @NAME@ (gr_noise_type_t type, float ampl, long seed = 3021); + + public: + void set_type (gr_noise_type_t type) { d_type = type; } + void set_amplitude (float ampl) { d_ampl = ampl; } +}; diff --git a/gnuradio-core/src/lib/general/gr_noise_type.h b/gnuradio-core/src/lib/general/gr_noise_type.h new file mode 100644 index 0000000000..886d5f446f --- /dev/null +++ b/gnuradio-core/src/lib/general/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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/general/gr_nop.cc b/gnuradio-core/src/lib/general/gr_nop.cc new file mode 100644 index 0000000000..0a3f4f330b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_nop.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_nop.h> +#include <gr_io_signature.h> + +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)) +{ +} + +gr_block_sptr +gr_make_nop (size_t sizeof_stream_item) +{ + return gr_block_sptr (new gr_nop (sizeof_stream_item)); +} + +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 0000000000..faf938625d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_nop.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_NOP_H +#define INCLUDED_GR_NOP_H + +#include <gr_block.h> +#include <stddef.h> // size_t + +/*! + * \brief Does nothing. Used for testing only. + * \ingroup block + */ +class gr_nop : public gr_block +{ + friend gr_block_sptr gr_make_nop (size_t sizeof_stream_item); + + gr_nop (size_t sizeof_stream_item); + + 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); +}; + +gr_block_sptr +gr_make_nop (size_t sizeof_stream_item); + +#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 0000000000..556ad57304 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_nop.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%ignore gr_nop; +class gr_nop : public gr_block { + friend gr_block_sptr gr_make_nop (size_t sizeof_stream_item); + gr_nop (size_t sizeof_stream_item); +}; + +%rename(nop) gr_make_nop; +gr_block_sptr gr_make_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 0000000000..7e9c7a790b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_null_sink.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_block_sptr +gr_make_null_sink (size_t sizeof_stream_item) +{ + return gr_block_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 0000000000..55b61aacc4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_null_sink.h @@ -0,0 +1,51 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_NULL_SINK_H +#define INCLUDED_GR_NULL_SINK_H + +#include <gr_sync_block.h> +#include <stddef.h> // size_t + +/*! + * \brief Bit bucket + * \ingroup sink + */ + +class gr_null_sink : public gr_sync_block +{ + friend gr_block_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); + +}; + +gr_block_sptr +gr_make_null_sink (size_t sizeof_stream_item); + +#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 0000000000..145be901ff --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_null_sink.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%ignore gr_null_sink; +class gr_null_sink : public gr_sync_block { + friend gr_block_sptr gr_make_null_sink (size_t sizeof_stream_item); + gr_null_sink (size_t sizeof_stream_item); +}; + +%rename(null_sink) gr_make_null_sink; +gr_block_sptr gr_make_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 0000000000..65923cf764 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_null_source.cc @@ -0,0 +1,51 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_null_source.h> +#include <gr_io_signature.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_block_sptr +gr_make_null_source (size_t sizeof_stream_item) +{ + return gr_block_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 0000000000..9fc43a0708 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_null_source.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_NULL_SOURCE_H +#define INCLUDED_GR_NULL_SOURCE_H + +#include <gr_sync_block.h> + +/*! + * \brief A source of zeros. + * \ingroup source + */ + +class gr_null_source : public gr_sync_block +{ + friend gr_block_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); + +}; + +gr_block_sptr +gr_make_null_source (size_t sizeof_stream_item); + +#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 0000000000..8a88f359c7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_null_source.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%ignore gr_null_source; +class gr_null_source : public gr_sync_block { + friend gr_block_sptr gr_make_null_source (size_t sizeof_stream_item); + gr_null_source (size_t sizeof_stream_item); +}; + +%rename(null_source) gr_make_null_source; +gr_block_sptr gr_make_null_source (size_t sizeof_stream_item); 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 0000000000..7f470af9a0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pa_2x2_phase_combiner.cc @@ -0,0 +1,74 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_pa_2x2_phase_combiner_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 0000000000..e8634968bd --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pa_2x2_phase_combiner.h @@ -0,0 +1,62 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_PA_2X2_PHASE_COMBINER_H +#define INCLUDED_GR_PA_2X2_PHASE_COMBINER_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_pa_2x2_phase_combiner_sptr gr_make_pa_2x2_phase_combiner (); + +/*! + * \brief pa_2x2 phase combiner + * \ingroup block + * + * Anntenas are arranged like this: + * + * 2 3 + * 0 1 + * + * dx and dy are lambda/2. + */ +class 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_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 0000000000..a19413afd5 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_packed_to_unpacked_XX.cc.t b/gnuradio-core/src/lib/general/gr_packed_to_unpacked_XX.cc.t new file mode 100644 index 0000000000..f585c4a6af --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_packed_to_unpacked_XX.cc.t @@ -0,0 +1,133 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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) +{ + 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 + + 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++, d_index++) + x = (x<<1) | get_bit_be(in, d_index); + 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++, d_index++) + x = (x<<1) | get_bit_le(in, d_index); + 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)); + } + + 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/general/gr_packed_to_unpacked_XX.h.t b/gnuradio-core/src/lib/general/gr_packed_to_unpacked_XX.h.t new file mode 100644 index 0000000000..1c9d2a0d6c --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_packed_to_unpacked_XX.h.t @@ -0,0 +1,84 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_block.h> +#include <gr_endianness.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@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 block + * + * 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 @NAME@ : public gr_block +{ + friend @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/general/gr_packed_to_unpacked_XX.i.t b/gnuradio-core/src/lib/general/gr_packed_to_unpacked_XX.i.t new file mode 100644 index 0000000000..9517a8ac24 --- /dev/null +++ b/gnuradio-core/src/lib/general/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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/general/gr_packet_sink.cc b/gnuradio-core/src/lib/general/gr_packet_sink.cc new file mode 100644 index 0000000000..f88758b9b0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_packet_sink.cc @@ -0,0 +1,206 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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> + +#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 gr_packet_sink_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 0000000000..3c468afd11 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_packet_sink.h @@ -0,0 +1,111 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_PACKET_SINK_H +#define INCLUDED_GR_PACKET_SINK_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_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 + */ +class gr_packet_sink : public gr_sync_block +{ + friend 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 0000000000..fb96072926 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_phase_modulator_fc.cc b/gnuradio-core/src/lib/general/gr_phase_modulator_fc.cc new file mode 100644 index 0000000000..95631f09f7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_phase_modulator_fc.cc @@ -0,0 +1,62 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_phase_modulator_fc_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 0000000000..ea27427524 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_phase_modulator_fc.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_PHASE_MODULATOR_FC_H +#define INCLUDED_GR_PHASE_MODULATOR_FC_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_phase_modulator_fc_sptr gr_make_phase_modulator_fc (double sensitivity); + +/*! + * \brief Phase modulator block + * \ingroup block + * output=complex(cos(in*sensitivity),sin(in*sensitivity)) + */ +class gr_phase_modulator_fc : public gr_sync_block +{ + double d_sensitivity; + double d_phase; + + friend 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 0000000000..0ce25fd19c --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..4736e77cf4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.cc @@ -0,0 +1,117 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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> + +#define M_TWOPI (2*M_PI) + +gr_pll_carriertracking_cc_sptr +gr_make_pll_carriertracking_cc (float alpha, float beta, float max_freq, float min_freq) +{ + return gr_pll_carriertracking_cc_sptr (new gr_pll_carriertracking_cc (alpha, beta, max_freq, min_freq)); +} + +gr_pll_carriertracking_cc::gr_pll_carriertracking_cc (float alpha, float beta, 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))), + d_alpha(alpha), d_beta(beta), + d_max_freq(max_freq), d_min_freq(min_freq), + d_phase(0), d_freq((max_freq+min_freq)/2), + 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()); + return mod_2pi(sample_phase-ref_phase); +} + +bool +gr_pll_carriertracking_cc::lock_detector(void) +{ + return (fabs(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++){ + error = phase_detector(iptr[i],d_phase); + + d_freq = d_freq + d_beta * error; + d_phase = mod_2pi(d_phase + d_freq + d_alpha * error); + + if (d_freq > d_max_freq) + d_freq = d_max_freq; + else if (d_freq < d_min_freq) + d_freq = d_min_freq; + gr_sincosf(d_phase,&t_imag,&t_real); + optr[i] = gr_complex(t_real,t_imag); + 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 0000000000..679eb24d95 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.h @@ -0,0 +1,70 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,206 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can 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, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_PLL_CARRIERTRACKING_CC_H +#define INCLUDED_GR_PLL_CARRIERTRACKING_CC_H + +#include <gr_sync_block.h> + +class gr_pll_carriertracking_cc; +typedef boost::shared_ptr<gr_pll_carriertracking_cc> gr_pll_carriertracking_cc_sptr; + +gr_pll_carriertracking_cc_sptr gr_make_pll_carriertracking_cc (float alpha, float beta, + 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 block + * + * 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. Alpha is the phase gain (first order, units of radians per radian) + * and beta is the frequency gain (second order, units of radians per sample per radian) + * \sa gr_pll_freqdet_cf, gr_pll_carriertracking_cc + */ + +class gr_pll_carriertracking_cc : public gr_sync_block +{ + friend gr_pll_carriertracking_cc_sptr gr_make_pll_carriertracking_cc (float alpha, float beta, + float max_freq, float min_freq); + + float d_alpha,d_beta,d_max_freq,d_min_freq,d_phase,d_freq,d_locksig,d_lock_threshold; + bool d_squelch_enable; + gr_pll_carriertracking_cc (float alpha, float beta, 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 0000000000..2653f8e8a1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,pll_carriertracking_cc); + +gr_pll_carriertracking_cc_sptr +gr_make_pll_carriertracking_cc (float alpha, float beta, + float max_freq, float min_freq); + +class gr_pll_carriertracking_cc : public gr_sync_block +{ + private: + gr_pll_carriertracking_cc (float alpha, float beta, 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 0000000000..f15f160dc0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.cc @@ -0,0 +1,94 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// WARNING: this file is machine generated. Edits will be over written + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_pll_freqdet_cf.h> +#include <gr_io_signature.h> +#include <math.h> + +#define M_TWOPI (2*M_PI) + +gr_pll_freqdet_cf_sptr +gr_make_pll_freqdet_cf (float alpha, float beta, float max_freq, float min_freq) +{ + return gr_pll_freqdet_cf_sptr (new gr_pll_freqdet_cf (alpha, beta, max_freq, min_freq)); +} + +gr_pll_freqdet_cf::gr_pll_freqdet_cf (float alpha, float beta, 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))), + d_alpha(alpha), d_beta(beta), + d_max_freq(max_freq), d_min_freq(min_freq), + d_phase(0), d_freq((max_freq+min_freq)/2) +{ +} + +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 = atan2(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) { + error = phase_detector(*iptr++,d_phase); + + d_freq = d_freq + d_beta * error; + d_phase = mod_2pi(d_phase + d_freq + d_alpha * error); + + if (d_freq > d_max_freq) + d_freq = d_max_freq; + else if (d_freq < d_min_freq) + d_freq = d_min_freq; + *optr++ = d_freq; + } + 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 0000000000..3d05a1c2c9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_PLL_FREQDET_CF_H +#define INCLUDED_GR_PLL_FREQDET_CF_H + +#include <gr_sync_block.h> + +class gr_pll_freqdet_cf; +typedef boost::shared_ptr<gr_pll_freqdet_cf> gr_pll_freqdet_cf_sptr; + +gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float alpha, float beta, + 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 block + * + * 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. Alpha is the phase gain (first order, units of radians per radian) + * and beta is the frequency gain (second order, units of radians per sample per radian) + * \sa gr_pll_refout_cc, gr_pll_carriertracking_cc + */ + +class gr_pll_freqdet_cf : public gr_sync_block +{ + friend gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float alpha, float beta, + float max_freq, float min_freq); + + float d_alpha,d_beta,d_max_freq,d_min_freq,d_phase,d_freq; + gr_pll_freqdet_cf (float alpha, float beta, 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_freqdet_cf.i b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.i new file mode 100644 index 0000000000..8a27c4fd04 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_freqdet_cf.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,pll_freqdet_cf) + + gr_pll_freqdet_cf_sptr gr_make_pll_freqdet_cf (float alpha, float beta, + float max_freq, float min_freq); + +class gr_pll_freqdet_cf : public gr_sync_block +{ + private: + gr_pll_freqdet_cf (float alpha, float beta, 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 0000000000..e535611890 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_refout_cc.cc @@ -0,0 +1,97 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// WARNING: this file is machine generated. Edits will be over written + +#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> + +#define M_TWOPI (2*M_PI) + +gr_pll_refout_cc_sptr +gr_make_pll_refout_cc (float alpha, float beta, float max_freq, float min_freq) +{ + return gr_pll_refout_cc_sptr (new gr_pll_refout_cc (alpha, beta, max_freq, min_freq)); +} + +gr_pll_refout_cc::gr_pll_refout_cc (float alpha, float beta, 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))), + d_alpha(alpha), d_beta(beta), + d_max_freq(max_freq), d_min_freq(min_freq), + d_phase(0), d_freq((max_freq+min_freq)/2) +{ +} + +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 = atan2(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) { + error = phase_detector(*iptr++,d_phase); + + d_freq = d_freq + d_beta * error; + d_phase = mod_2pi(d_phase + d_freq + d_alpha * error); + + if (d_freq > d_max_freq) + d_freq = d_max_freq; + else if (d_freq < d_min_freq) + d_freq = d_min_freq; + gr_sincosf(d_phase,&t_imag,&t_real); + *optr++ = gr_complex(t_real,t_imag); + } + 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 0000000000..c46a65ee2e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_refout_cc.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + + +#ifndef INCLUDED_GR_PLL_REFOUT_CC_H +#define INCLUDED_GR_PLL_REFOUT_CC_H + +#include <gr_sync_block.h> + +class gr_pll_refout_cc; +typedef boost::shared_ptr<gr_pll_refout_cc> gr_pll_refout_cc_sptr; + +gr_pll_refout_cc_sptr gr_make_pll_refout_cc (float alpha, float beta, + float max_freq, float min_freq); +/*! + * \brief Implements a PLL which locks to the input frequency and outputs a carrier + * \ingroup block + * + * 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. Alpha is the phase gain (first order, units of radians per radian) + * and beta is the frequency gain (second order, units of radians per sample per radian) + * \sa gr_pll_freqdet_cf, gr_pll_carriertracking_cc + */ +class gr_pll_refout_cc : public gr_sync_block +{ + friend gr_pll_refout_cc_sptr gr_make_pll_refout_cc (float alpha, float beta, + float max_freq, float min_freq); + + float d_alpha,d_beta,d_max_freq,d_min_freq,d_phase,d_freq; + gr_pll_refout_cc (float alpha, float beta, 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 0000000000..8cb4fde8d6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pll_refout_cc.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,pll_refout_cc) + + gr_pll_refout_cc_sptr gr_make_pll_refout_cc (float alpha, float beta, + float max_freq, float min_freq); + +class gr_pll_refout_cc : public gr_sync_block +{ + private: + gr_pll_refout_cc (float alpha, float beta, float max_freq, float min_freq); +}; diff --git a/gnuradio-core/src/lib/general/gr_prefix.cc.in b/gnuradio-core/src/lib/general/gr_prefix.cc.in new file mode 100644 index 0000000000..25c6960ca4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_prefix.cc.in @@ -0,0 +1,29 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <gr_prefix.h> + +const std::string +gr_prefix() +{ + return "@prefix@"; +} diff --git a/gnuradio-core/src/lib/general/gr_prefix.h b/gnuradio-core/src/lib/general/gr_prefix.h new file mode 100644 index 0000000000..a521b619b3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_prefix.h @@ -0,0 +1,33 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_PREFIX_H +#define INCLUDED_GR_PREFIX_H + +#include <string> + +/*! + * \brief return ./configure --prefix argument. Typically /usr/local + */ +const std::string gr_prefix(); + + +#endif /* INCLUDED_GR_PREFIX_H */ diff --git a/gnuradio-core/src/lib/general/gr_prefix.i b/gnuradio-core/src/lib/general/gr_prefix.i new file mode 100644 index 0000000000..04e1899a64 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_prefix.i @@ -0,0 +1,5 @@ +/* -*- c++ -*- */ + +%rename(prefix) gr_prefix; + +const std::string gr_prefix(); 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 0000000000..c9721f0f5e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_prefs.cc @@ -0,0 +1,88 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gr_prefs.h> + +/* + * 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() +{ + // nop +} + +bool +gr_prefs::has_section(const std::string section) +{ + return false; +} + +bool +gr_prefs::has_option(const std::string section, const std::string option) +{ + return false; +} + +const std::string +gr_prefs::get_string(const std::string section, const std::string option, const std::string default_val) +{ + return default_val; +} + +bool +gr_prefs::get_bool(const std::string section, const std::string option, bool default_val) +{ + return default_val; +} + +long +gr_prefs::get_long(const std::string section, const std::string option, long default_val) +{ + return default_val; +} + +double +gr_prefs::get_double(const std::string section, const std::string option, double default_val) +{ + 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 0000000000..eaf74870c1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_prefs.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_PREFS_H +#define INCLUDED_GR_PREFS_H + +#include <string> + +/*! + * \brief Base class for representing user preferences a la windows INI files. + * + * The real implementation is in Python, and is accessable from C++ + * via the magic of SWIG directors. + */ + +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 section); + + /*! + * \brief Does \p option exist? + */ + virtual bool has_option(const std::string section, const std::string option); + + /*! + * \brief If option exists return associated value; else default_val. + */ + virtual const std::string get_string(const std::string section, + 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 section, + 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 section, + 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 section, + const std::string option, + double default_val); +}; + + +#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 0000000000..d11da173e3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_prefs.i @@ -0,0 +1,72 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// Generate SWIG directors for gr_prefs. +%feature("director") gr_prefs; + +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 section); + + /*! + * \brief Does \p option exist? + */ + virtual bool has_option(const std::string section, const std::string option); + + /*! + * \brief If option exists return associated value; else default_val. + */ + virtual const std::string get_string(const std::string section, + 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 section, + 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 section, + 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 section, + 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 0000000000..73c7343b32 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_c.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_probe_avg_mag_sqrd_c_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 0000000000..85e2244b94 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_c.h @@ -0,0 +1,74 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_PROBE_AVG_MAG_SQRD_C_H +#define INCLUDED_GR_PROBE_AVG_MAG_SQRD_C_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_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 + * + * 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_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_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 0000000000..0b8000c52f --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_f.cc b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_f.cc new file mode 100644 index 0000000000..439138f059 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_f.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_probe_avg_mag_sqrd_f_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 0000000000..5f20a5ca82 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_f.h @@ -0,0 +1,74 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_PROBE_AVG_MAG_SQRD_F_H +#define INCLUDED_GR_PROBE_AVG_MAG_SQRD_F_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_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 + * + * 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_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_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 0000000000..f58caa2d44 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_signal_f.cc b/gnuradio-core/src/lib/general/gr_probe_signal_f.cc new file mode 100644 index 0000000000..8c94b0367d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_signal_f.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include <gr_probe_signal_f.h> +#include <gr_io_signature.h> + +gr_probe_signal_f_sptr +gr_make_probe_signal_f() +{ + return gr_probe_signal_f_sptr(new gr_probe_signal_f()); +} + +gr_probe_signal_f::gr_probe_signal_f () + : gr_sync_block ("probe_signal_f", + gr_make_io_signature(1, 1, sizeof(float)), + gr_make_io_signature(0, 0, 0)), + d_level(0) +{ +} + +gr_probe_signal_f::~gr_probe_signal_f() +{ +} + + +int +gr_probe_signal_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]; + + if (noutput_items > 0) + d_level = in[noutput_items-1]; + + return noutput_items; +} + diff --git a/gnuradio-core/src/lib/general/gr_probe_signal_f.h b/gnuradio-core/src/lib/general/gr_probe_signal_f.h new file mode 100644 index 0000000000..72811b20f1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_signal_f.h @@ -0,0 +1,57 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_PROBE_SIGNAL_F_H +#define INCLUDED_GR_PROBE_SIGNAL_F_H + +#include <gr_sync_block.h> + +class gr_probe_signal_f; +typedef boost::shared_ptr<gr_probe_signal_f> gr_probe_signal_f_sptr; + +gr_probe_signal_f_sptr +gr_make_probe_signal_f (); + +/*! + * \brief Sink that allows a sample to be grabbed from Python. + * \ingroup sink + */ +class gr_probe_signal_f : public gr_sync_block +{ + float d_level; + + friend gr_probe_signal_f_sptr + gr_make_probe_signal_f(); + + gr_probe_signal_f(); + +public: + ~gr_probe_signal_f(); + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + float level() const { return d_level; } + +}; + +#endif /* INCLUDED_GR_PROBE_SIGNAL_F_H */ diff --git a/gnuradio-core/src/lib/general/gr_probe_signal_f.i b/gnuradio-core/src/lib/general/gr_probe_signal_f.i new file mode 100644 index 0000000000..14fc6f1941 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_probe_signal_f.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,probe_signal_f); + +gr_probe_signal_f_sptr +gr_make_probe_signal_f (); + +class gr_probe_signal_f : public gr_sync_block +{ +public: + float level () const { return d_level; } +}; 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 0000000000..33c128725e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pwr_squelch_cc.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_pwr_squelch_cc_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 0000000000..2822ee5990 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pwr_squelch_cc.h @@ -0,0 +1,62 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_PWR_SQUELCH_CC_H +#define INCLUDED_GR_PWR_SQUELCH_CC_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_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 block + */ +class 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_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 0000000000..41832ab746 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pwr_squelch_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,pwr_squelch_cc); + +%include 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 0000000000..8bc3aad6c7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pwr_squelch_ff.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_pwr_squelch_ff_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 0000000000..1eb61b160d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pwr_squelch_ff.h @@ -0,0 +1,62 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_PWR_SQUELCH_FF_H +#define INCLUDED_GR_PWR_SQUELCH_FF_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_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 block + */ +class 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_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 0000000000..4bc16b1061 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_pwr_squelch_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,pwr_squelch_ff); + +%include 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 0000000000..eb1fae8575 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_quadrature_demod_cf.cc @@ -0,0 +1,62 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_quadrature_demod_cf_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 0000000000..7e625e7ad1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_quadrature_demod_cf.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_QUADRATURE_DEMOD_CF_H +#define INCLUDED_GR_QUADRATURE_DEMOD_CF_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_quadrature_demod_cf_sptr gr_make_quadrature_demod_cf (float gain); + +/*! + * \brief quadrature demodulator: complex in, float out + * \ingroup block + * + * This can be used to demod FM, FSK, GMSK, etc. + * The input is complex baseband. + */ +class gr_quadrature_demod_cf : public gr_sync_block +{ + friend gr_quadrature_demod_cf_sptr gr_make_quadrature_demod_cf (float gain); + gr_quadrature_demod_cf (float gain); + + float d_gain; + + public: + + 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 0000000000..685b278f1a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_quadrature_demod_cf.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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); +}; 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 0000000000..a56f2875b5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_random.cc @@ -0,0 +1,180 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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. + * + */ + +#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 0000000000..9726ee9b83 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_random.h @@ -0,0 +1,63 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_RANDOM_H +#define INCLUDED_GR_RANDOM_H + +#include <gr_complex.h> + +/*! + * \brief pseudo random number generator + */ +class 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_remez.cc b/gnuradio-core/src/lib/general/gr_remez.cc new file mode 100644 index 0000000000..1003900068 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_remez.cc @@ -0,0 +1,1031 @@ +/************************************************************************** + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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]"); + + for (int i = 0; i < 2 * numbands; i++) + bands[i] = arg_bands[i] / 2; // FIXME why / 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 0000000000..c910803bd1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_remez.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_REMEZ_H +#define INCLUDED_GR_REMEZ_H + +#include <gr_types.h> +#include <string> +#include <stdexcept> + +/*! + * \brief Parks-McClellan FIR 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. + */ + +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 0000000000..2e2471e2a3 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_reverse.cc b/gnuradio-core/src/lib/general/gr_reverse.cc new file mode 100644 index 0000000000..099deb6018 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..cff5325591 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_reverse.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_REVERSE_H +#define INCLUDED_GR_REVERSE_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 0000000000..7abfefd1d0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_rms_cf.cc @@ -0,0 +1,71 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_rms_cf_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 0000000000..bc16c23ed3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_rms_cf.h @@ -0,0 +1,59 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_RMS_CF_H +#define INCLUDED_GR_RMS_CF_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_rms_cf_sptr +gr_make_rms_cf (double alpha = 0.0001); + +/*! + * \brief RMS average power + */ +class gr_rms_cf : public gr_sync_block +{ + gr_single_pole_iir<double,double,double> d_iir; + bool d_unmuted; + + friend 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 0000000000..0d7b05c8ae --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..187be638e6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_rms_ff.cc @@ -0,0 +1,71 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_rms_ff_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 0000000000..3f276eb216 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_rms_ff.h @@ -0,0 +1,59 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_RMS_FF_H +#define INCLUDED_GR_RMS_FF_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_rms_ff_sptr +gr_make_rms_ff (double alpha = 0.0001); + +/*! + * \brief RMS average power + */ +class gr_rms_ff : public gr_sync_block +{ + gr_single_pole_iir<double,double,double> d_iir; + bool d_unmuted; + + friend 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 0000000000..bf9dbe2dfa --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_short_to_float.cc b/gnuradio-core/src/lib/general/gr_short_to_float.cc new file mode 100644 index 0000000000..3ca7937334 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_short_to_float.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_short_to_float.h> +#include <gr_io_signature.h> +#include <gri_short_to_float.h> + +gr_short_to_float_sptr +gr_make_short_to_float () +{ + return gr_short_to_float_sptr (new gr_short_to_float ()); +} + +gr_short_to_float::gr_short_to_float () + : gr_sync_block ("gr_short_to_float", + gr_make_io_signature (1, 1, sizeof (short)), + gr_make_io_signature (1, 1, sizeof (float))) +{ +} + +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]; + + gri_short_to_float (in, out, 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 0000000000..ee5a4ee1cb --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_short_to_float.h @@ -0,0 +1,51 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SHORT_TO_FLOAT_H +#define INCLUDED_GR_SHORT_TO_FLOAT_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_short_to_float_sptr +gr_make_short_to_float (); + +/*! + * \brief Convert stream of short to a stream of float + * \ingroup converter + */ + +class gr_short_to_float : public gr_sync_block +{ + friend gr_short_to_float_sptr gr_make_short_to_float (); + gr_short_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_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 0000000000..724165d5e9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_short_to_float.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,short_to_float) + +gr_short_to_float_sptr gr_make_short_to_float (); + +class gr_short_to_float : public gr_sync_block +{ + gr_short_to_float (); +}; diff --git a/gnuradio-core/src/lib/general/gr_sig_source_X.cc.t b/gnuradio-core/src/lib/general/gr_sig_source_X.cc.t new file mode 100644 index 0000000000..079864b253 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sig_source_X.cc.t @@ -0,0 +1,149 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <@NAME@.h> +#include <algorithm> +#include <gr_io_signature.h> +#include <stdexcept> +#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 @NAME@_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; + for (int i = 0; i < noutput_items; i++) // FIXME unroll + optr[i] = 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; + +#else // nope... + + case GR_CONST_WAVE: + t = (@TYPE@) d_ampl + d_offset; + for (int i = 0; i < noutput_items; i++) // FIXME unroll + optr[i] = 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; +#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/general/gr_sig_source_X.h.t b/gnuradio-core/src/lib/general/gr_sig_source_X.h.t new file mode 100644 index 0000000000..2cdeb32621 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sig_source_X.h.t @@ -0,0 +1,81 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#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 + */ + +class @NAME@ : public gr_sync_block { + friend @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); +}; + +@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/general/gr_sig_source_X.i.t b/gnuradio-core/src/lib/general/gr_sig_source_X.i.t new file mode 100644 index 0000000000..3e769d4216 --- /dev/null +++ b/gnuradio-core/src/lib/general/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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/general/gr_sig_source_waveform.h b/gnuradio-core/src/lib/general/gr_sig_source_waveform.h new file mode 100644 index 0000000000..2d0dc56722 --- /dev/null +++ b/gnuradio-core/src/lib/general/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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_waveform_t; + +#endif /* INCLUDED_GR_SIG_SOURCE_WAVEFORM_H */ 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 0000000000..09c812391e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_correlator.cc @@ -0,0 +1,230 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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> + + +static const int THRESHOLD = 3; + +gr_simple_correlator_sptr +gr_make_simple_correlator (int payload_bytesize) +{ + return gr_simple_correlator_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_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; +} + + +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; + + struct debug_data { + float raw_data; + float sampled; + float enter_locked; + } debug_data; + + 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"); + unsigned char pktbuf[d_bblen/GRSF_BITS_PER_BYTE]; + packit (pktbuf, d_bitbuf, d_bbi); + printf ("seqno %3d\n", pktbuf[0]); + memcpy (out, &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 (); + debug_data.enter_locked = 1.0; + } + 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 0000000000..5697e170af --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_correlator.h @@ -0,0 +1,109 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SIMPLE_CORRELATOR_H +#define INCLUDED_GR_SIMPLE_CORRELATOR_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_simple_correlator_sptr gr_make_simple_correlator (int payload_bytesize); + +/*! + * \brief inverse of gr_simple_framer (more or less) + * \ingroup block + */ +class 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 + 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_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 0000000000..d143648f6c --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..797b1f3ba3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_framer.cc @@ -0,0 +1,100 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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> + + +gr_simple_framer_sptr +gr_make_simple_framer (int payload_bytesize) +{ + return gr_simple_framer_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 0000000000..33813741bb --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_framer.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SIMPLE_FRAMER_H +#define INCLUDED_GR_SIMPLE_FRAMER_H + +#include <gr_block.h> + +class gr_simple_framer; +typedef boost::shared_ptr<gr_simple_framer> gr_simple_framer_sptr; + +gr_simple_framer_sptr gr_make_simple_framer (int payload_bytesize); + +/*! + * \brief add sync field, seq number and command field to payload + * \ingroup block + */ +class 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_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 0000000000..4083ce1632 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..c7f65528b0 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_framer_sync.h @@ -0,0 +1,49 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SIMPLE_FRAMER_SYNC_H +#define INCLUDED_GR_SIMPLE_FRAMER_SYNC_H + +/* + * Here are a couple of maximum length sequences (m-sequences) that were generated by the + * the "mseq" matlab/octave code downloaded from: + * http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=990&objectType=file + * + * 31-bit m-sequence: + * 0110100100001010111011000111110 + * 0x690AEC76 (padded on right with a zero) + * + * 63-bit m-sequence: + * 101011001101110110100100111000101111001010001100001000001111110 + * 0xACDDA4E2F28C20FC (padded on right with a zero) + */ + +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 0000000000..e34f9a138d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_squelch_cc.cc @@ -0,0 +1,99 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_simple_squelch_cc_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 0000000000..31fde1286d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_simple_squelch_cc.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_SIMPLE_SQUELCH_CC_H +#define INCLUDED_GR_SIMPLE_SQUELCH_CC_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_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. + */ +class 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_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 0000000000..5e3339a2fa --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..599d00bf65 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_skiphead.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_skiphead.h> +#include <gr_io_signature.h> + +gr_skiphead::gr_skiphead (size_t sizeof_stream_item, int nitems) + : gr_sync_block ("skiphead", + gr_make_io_signature (1, 1, sizeof_stream_item), + gr_make_io_signature (1, 1, sizeof_stream_item)), + d_nitems (nitems), d_nskipped_items (0) +{ +} + +gr_block_sptr +gr_make_skiphead (size_t sizeof_stream_item, int nitems) +{ + return gr_block_sptr (new gr_skiphead (sizeof_stream_item, nitems)); +} + +int +gr_skiphead::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + int items_to_skip = d_nitems - d_nskipped_items; + if (items_to_skip <=0) + { + //Done with skipping, copy all input to the output; + memcpy (output_items[0], input_items[0], noutput_items * input_signature()->sizeof_stream_item (0)); + return noutput_items; + } else if (items_to_skip < noutput_items) + { + memcpy (output_items[0], &(((char *)input_items[0])[items_to_skip*input_signature()->sizeof_stream_item (0)]), (noutput_items -items_to_skip) * input_signature()->sizeof_stream_item (0)); + //memcpy (output_items[0], &((input_items[0])[items_to_skip]), (noutput_items -items_to_skip) * input_signature()->sizeof_stream_item (0)); + //memcpy (output_items[0], input_items[0]+items_to_skip*input_signature()->sizeof_stream_item (0), (noutput_items -items_to_skip) * input_signature()->sizeof_stream_item (0)); + d_nskipped_items += items_to_skip; + consume_each (items_to_skip); + return (noutput_items -items_to_skip); + } else + { + d_nskipped_items += noutput_items; + consume_each (items_to_skip); + return 0; + } + + return -1;//Should never get here +} 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 0000000000..e87f8a4ec6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_skiphead.h @@ -0,0 +1,54 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SKIPHEAD_H +#define INCLUDED_GR_SKIPHEAD_H + +#include <gr_sync_block.h> +#include <stddef.h> // size_t + +/*! + * \brief skips the first N items, from then on copies items to the output + * \ingroup block + * + * Useful for building test cases and sources which have metadata or junk at the start + */ + +class gr_skiphead : public gr_sync_block +{ + friend gr_block_sptr gr_make_skiphead (size_t sizeof_stream_item, int nitems); + gr_skiphead (size_t sizeof_stream_item, int nitems); + + int d_nitems; + int d_nskipped_items; + + public: + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +gr_block_sptr +gr_make_skiphead (size_t sizeof_stream_item, int nitems); + + +#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 0000000000..deedeb3be3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_skiphead.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%ignore gr_skiphead; +class gr_skiphead : public gr_block { + friend gr_block_sptr gr_make_skiphead (size_t sizeof_stream_item, int nitems); + gr_skiphead (size_t sizeof_stream_item, int nitems); +}; + +%rename(skiphead) gr_make_skiphead; +gr_block_sptr gr_make_skiphead (size_t sizeof_stream_item, int nitems); 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 0000000000..b3e61fcc56 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..4e3312844a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_squelch_base_cc.h @@ -0,0 +1,58 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SQUELCH_BASE_CC_H +#define INCLUDED_GR_SQUELCH_BASE_CC_H + +#include <gr_block.h> + +class 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 0000000000..0ef674c4f7 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..a457c5f6ca --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..4128735a7d --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_squelch_base_ff.h @@ -0,0 +1,58 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SQUELCH_BASE_FF_H +#define INCLUDED_GR_SQUELCH_BASE_FF_H + +#include <gr_block.h> + +class 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 0000000000..d749d498fb --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_to_streams.cc b/gnuradio-core/src/lib/general/gr_stream_to_streams.cc new file mode 100644 index 0000000000..d4627964e6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_stream_to_streams.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_stream_to_streams.h> +#include <gr_io_signature.h> + +gr_stream_to_streams_sptr +gr_make_stream_to_streams (size_t item_size, size_t nstreams) +{ + return gr_stream_to_streams_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 0000000000..3775e79b26 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_stream_to_streams.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_STREAM_TO_STREAMS_H +#define INCLUDED_GR_STREAM_TO_STREAMS_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_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 block + * + * Converts a stream of N items into N streams of 1 item. + * Repeat ad infinitum. + */ +class gr_stream_to_streams : public gr_sync_decimator +{ + friend 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 0000000000..59b93da048 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..3d815cf59a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_stream_to_vector.cc @@ -0,0 +1,57 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_stream_to_vector.h> +#include <gr_io_signature.h> + +gr_stream_to_vector_sptr +gr_make_stream_to_vector (size_t item_size, size_t nitems_per_block) +{ + return gr_stream_to_vector_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 0000000000..a0a318b6ae --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_stream_to_vector.h @@ -0,0 +1,54 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_STREAM_TO_VECTOR_H +#define INCLUDED_GR_STREAM_TO_VECTOR_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_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 block + */ +class gr_stream_to_vector : public gr_sync_decimator +{ + friend 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 0000000000..16550ac018 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..9d05fbf762 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_streams_to_stream.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_streams_to_stream.h> +#include <gr_io_signature.h> + +gr_streams_to_stream_sptr +gr_make_streams_to_stream (size_t item_size, size_t nstreams) +{ + return gr_streams_to_stream_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 0000000000..86d390948e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_streams_to_stream.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_STREAMS_TO_STREAM_H +#define INCLUDED_GR_STREAMS_TO_STREAM_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_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 block + * + * Convert N streams of 1 item into 1 stream of N items. + * Repeat ad infinitum. + */ +class gr_streams_to_stream : public gr_sync_interpolator +{ + friend 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 0000000000..0f9e46fc5c --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..794254dd4c --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_streams_to_vector.cc @@ -0,0 +1,63 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_streams_to_vector.h> +#include <gr_io_signature.h> + +gr_streams_to_vector_sptr +gr_make_streams_to_vector (size_t item_size, size_t nstreams) +{ + return gr_streams_to_vector_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 0000000000..d3a8903587 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_streams_to_vector.h @@ -0,0 +1,53 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_STREAMS_TO_VECTOR_H +#define INCLUDED_GR_STREAMS_TO_VECTOR_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_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 block + */ +class gr_streams_to_vector : public gr_sync_block +{ + friend 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 0000000000..a69c2e5ada --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_sub_XX.cc.t b/gnuradio-core/src/lib/general/gr_sub_XX.cc.t new file mode 100644 index 0000000000..2cfdc6e946 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sub_XX.cc.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 @SPTR_NAME@ (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 (); + + if (ninputs == 1){ // negate + for (int i = 0; i < noutput_items; i++) + *optr++ = (@O_TYPE@) -((@I_TYPE@ *) input_items[0])[i]; + } + + else { + 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 -= ((@I_TYPE@ *) input_items[j])[i]; + + *optr++ = (@O_TYPE@) acc; + } + } + + return noutput_items; +} diff --git a/gnuradio-core/src/lib/general/gr_sub_XX.h.t b/gnuradio-core/src/lib/general/gr_sub_XX.h.t new file mode 100644 index 0000000000..025c077a07 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sub_XX.h.t @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @SPTR_NAME@; + +@SPTR_NAME@ gr_make_@BASE_NAME@ (); + +/*! + * \brief output = input_0 - input_1 - ...) + * \ingroup block + * + * Subtract across all input streams. + */ +class @NAME@ : public gr_sync_block +{ + friend @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/general/gr_sub_XX.i.t b/gnuradio-core/src/lib/general/gr_sub_XX.i.t new file mode 100644 index 0000000000..8479aad683 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sub_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/general/gr_sync_block.cc b/gnuradio-core/src/lib/general/gr_sync_block.cc new file mode 100644 index 0000000000..57b6c556b4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sync_block.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_sync_block.h> + +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) +{ + set_fixed_rate(true); +} + + +void +gr_sync_block::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] = fixed_rate_noutput_to_ninput (noutput_items); +} + +int +gr_sync_block::fixed_rate_noutput_to_ninput(int noutput_items) +{ + return noutput_items + history() - 1; +} + +int +gr_sync_block::fixed_rate_ninput_to_noutput(int ninput_items) +{ + return std::max(0, ninput_items - (int)history() + 1); +} + +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) +{ + int r = work (noutput_items, input_items, output_items); + if (r > 0) + consume_each (r); + return r; +} diff --git a/gnuradio-core/src/lib/general/gr_sync_block.h b/gnuradio-core/src/lib/general/gr_sync_block.h new file mode 100644 index 0000000000..b4a2d008e5 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sync_block.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SYNC_BLOCK_H +#define INCLUDED_GR_SYNC_BLOCK_H + +#include <gr_block.h> + +/*! + * \brief synchronous 1:1 input to output with history + * \ingroup block + * + * Override work to provide the signal processing implementation. + */ +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); + + public: + + /*! + * \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) = 0; + + + // gr_sync_block overrides these to assist work + 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); + + int fixed_rate_ninput_to_noutput(int ninput); + int fixed_rate_noutput_to_ninput(int noutput); +}; + +#endif /* INCLUDED_GR_SYNC_BLOCK_H */ diff --git a/gnuradio-core/src/lib/general/gr_sync_block.i b/gnuradio-core/src/lib/general/gr_sync_block.i new file mode 100644 index 0000000000..c078a8b898 --- /dev/null +++ b/gnuradio-core/src/lib/general/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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/general/gr_sync_decimator.cc b/gnuradio-core/src/lib/general/gr_sync_decimator.cc new file mode 100644 index 0000000000..4b168a5da8 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sync_decimator.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_sync_decimator.h> + +gr_sync_decimator::gr_sync_decimator (const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature, + unsigned decimation) + : gr_sync_block (name, input_signature, output_signature) +{ + set_decimation (decimation); +} + +void +gr_sync_decimator::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] = fixed_rate_noutput_to_ninput(noutput_items); +} + +int +gr_sync_decimator::fixed_rate_noutput_to_ninput(int noutput_items) +{ + return noutput_items * decimation() + history() - 1; +} + +int +gr_sync_decimator::fixed_rate_ninput_to_noutput(int ninput_items) +{ + return std::max(0, ninput_items - (int)history() + 1) / decimation(); +} + +int +gr_sync_decimator::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + int r = work (noutput_items, input_items, output_items); + if (r > 0) + consume_each (r * decimation ()); + return r; +} + diff --git a/gnuradio-core/src/lib/general/gr_sync_decimator.h b/gnuradio-core/src/lib/general/gr_sync_decimator.h new file mode 100644 index 0000000000..6cdd35a44b --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sync_decimator.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SYNC_DECIMATOR_H +#define INCLUDED_GR_SYNC_DECIMATOR_H + +#include <gr_sync_block.h> + +/*! + * \brief synchronous N:1 input to output with history + * \ingroup block + * + * Override work to provide the signal processing implementation. + */ +class gr_sync_decimator : public gr_sync_block +{ + private: + unsigned d_decimation; + + protected: + + gr_sync_decimator (const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature, + unsigned decimation); + public: + + unsigned decimation () const { return d_decimation; } + void set_decimation (unsigned decimation) + { + d_decimation = decimation; + set_relative_rate (1.0 / decimation); + } + + // gr_sync_decimator overrides these to assist work + 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); + + // derived classes should override work + + int fixed_rate_ninput_to_noutput(int ninput); + int fixed_rate_noutput_to_ninput(int noutput); +}; + + +#endif /* INCLUDED_GR_SYNC_DECIMATOR_H */ diff --git a/gnuradio-core/src/lib/general/gr_sync_decimator.i b/gnuradio-core/src/lib/general/gr_sync_decimator.i new file mode 100644 index 0000000000..d9f6483af6 --- /dev/null +++ b/gnuradio-core/src/lib/general/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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/general/gr_sync_interpolator.cc b/gnuradio-core/src/lib/general/gr_sync_interpolator.cc new file mode 100644 index 0000000000..024d7e7802 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sync_interpolator.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_sync_interpolator.h> + +gr_sync_interpolator::gr_sync_interpolator (const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature, + unsigned interpolation) + : gr_sync_block (name, input_signature, output_signature) +{ + set_interpolation (interpolation); +} + +void +gr_sync_interpolator::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] = fixed_rate_noutput_to_ninput(noutput_items); +} + +int +gr_sync_interpolator::fixed_rate_noutput_to_ninput(int noutput_items) +{ + return noutput_items / interpolation() + history() - 1; +} + +int +gr_sync_interpolator::fixed_rate_ninput_to_noutout(int ninput_items) +{ + return std::max(0, ninput_items - (int)history() + 1) * interpolation(); +} + +int +gr_sync_interpolator::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + int r = work (noutput_items, input_items, output_items); + if (r > 0) + consume_each (r / interpolation ()); + return r; +} + + diff --git a/gnuradio-core/src/lib/general/gr_sync_interpolator.h b/gnuradio-core/src/lib/general/gr_sync_interpolator.h new file mode 100644 index 0000000000..914ea8e5a9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_sync_interpolator.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SYNC_INTERPOLATOR_H +#define INCLUDED_GR_SYNC_INTERPOLATOR_H + +#include <gr_sync_block.h> + +/*! + * \brief synchronous 1:N input to output with history + * \ingroup block + * + * Override work to provide the signal processing implementation. + */ +class gr_sync_interpolator : public gr_sync_block +{ + private: + unsigned d_interpolation; + + protected: + gr_sync_interpolator (const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature, + unsigned interpolation); + public: + + unsigned interpolation () const { return d_interpolation; } + void set_interpolation (unsigned interpolation) + { + d_interpolation = interpolation; + set_relative_rate (1.0 * interpolation); + set_output_multiple (interpolation); + } + + // gr_sync_interpolator overrides these to assist work + 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); + + // derived classes should override work + + int fixed_rate_ninput_to_noutout(int ninput); + int fixed_rate_noutput_to_ninput(int noutput); +}; + + +#endif /* INCLUDED_GR_SYNC_INTERPOLATOR_H */ diff --git a/gnuradio-core/src/lib/general/gr_sync_interpolator.i b/gnuradio-core/src/lib/general/gr_sync_interpolator.i new file mode 100644 index 0000000000..9b69d334c4 --- /dev/null +++ b/gnuradio-core/src/lib/general/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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/general/gr_test.cc b/gnuradio-core/src/lib/general/gr_test.cc new file mode 100644 index 0000000000..17263f490e --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_test.cc @@ -0,0 +1,176 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_test.h> +#include <gr_io_signature.h> +#include <stdexcept> +#include <iostream> + +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 gr_test_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 untill 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 0000000000..7bda9ae0ad --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_test.h @@ -0,0 +1,199 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_TEST_H +#define INCLUDED_GR_TEST_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_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 block + * + * 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_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_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 0000000000..e6f922c074 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..92fe3f742d --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..4041f46731 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_threshold_ff.cc @@ -0,0 +1,67 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_threshold_ff_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 0000000000..30ca67f5c6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_threshold_ff.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_THRESHOLD_FF_H +#define INCLUDED_GR_THRESHOLD_FF_H + +#include <gr_sync_block.h> + +class gr_threshold_ff; +typedef boost::shared_ptr<gr_threshold_ff> gr_threshold_ff_sptr; + +gr_threshold_ff_sptr gr_make_threshold_ff (float lo, float hi, float initial_state=0); + +/*! + * \brief + * \ingroup block + */ +class gr_threshold_ff : public gr_sync_block +{ + friend 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 0000000000..2fcf1deab2 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..9fbf23eddd --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_throttle.cc @@ -0,0 +1,109 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_throttle.h> +#include <gr_io_signature.h> +#include <errno.h> +#include <stdio.h> +#include <math.h> +#ifdef HAVE_TIME_H +#include <time.h> +#endif + + +#ifdef HAVE_NANOSLEEP +void +gr_nanosleep(struct timespec *ts) +{ + struct timespec *req = ts; + struct timespec rem; + int r = nanosleep(req, &rem); + while (r < 0 && errno == EINTR){ + req = &rem; + r = nanosleep(req, &rem); + } + if (r < 0) + perror ("gr_nanosleep"); +} +#endif + +gr_throttle_sptr +gr_make_throttle(size_t itemsize, double samples_per_sec) +{ + return gr_throttle_sptr(new gr_throttle(itemsize, samples_per_sec)); +} + +gr_throttle::gr_throttle(size_t itemsize, double samples_per_sec) + : gr_sync_block("throttle", + gr_make_io_signature(1, 1, itemsize), + gr_make_io_signature(1, 1, itemsize)), + d_itemsize(itemsize), d_samples_per_sec(samples_per_sec), + d_total_samples(0) +{ +#ifdef HAVE_GETTIMEOFDAY + gettimeofday(&d_start, 0); +#endif +} + +gr_throttle::~gr_throttle() +{ +} + +int +gr_throttle::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]; + +#if defined(HAVE_GETTIMEOFDAY) && defined(HAVE_NANOSLEEP) + // + // If our average sample rate exceeds our target sample rate, + // delay long enough to reduce to our target rate. + // + struct timeval now; + gettimeofday(&now, 0); + long t_usec = now.tv_usec - d_start.tv_usec; + long t_sec = now.tv_sec - d_start.tv_sec; + double t = (double)t_sec + (double)t_usec * 1e-6; + if (t < 1e-6) // avoid unlikely divide by zero + t = 1e-6; + + double actual_samples_per_sec = d_total_samples / t; + if (actual_samples_per_sec > d_samples_per_sec){ // need to delay + double delay = d_total_samples / d_samples_per_sec - t; + struct timespec ts; + ts.tv_sec = (time_t)floor(delay); + ts.tv_nsec = (long)((delay - floor(delay)) * 1e9); + gr_nanosleep(&ts); + } +#endif + + memcpy(out, in, noutput_items * d_itemsize); + d_total_samples += noutput_items; + return noutput_items; +} 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 0000000000..c926a405fe --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_throttle.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_THROTTLE_H +#define INCLUDED_GR_THROTTLE_H + +#include <gr_sync_block.h> +#ifdef HAVE_SYS_TIME_H +#include <sys/time.h> +#endif + +class gr_throttle; +typedef boost::shared_ptr<gr_throttle> gr_throttle_sptr; + + +gr_throttle_sptr gr_make_throttle(size_t itemsize, double samples_per_sec); + +/*! + * \brief throttle flow of samples such that the average rate does not exceed samples_per_sec. + * \ingroup block + * + * input: one stream of itemsize; output: one stream of itemsize + */ +class gr_throttle : public gr_sync_block +{ + friend gr_throttle_sptr gr_make_throttle(size_t itemsize, double samples_per_sec); + size_t d_itemsize; + double d_samples_per_sec; + double d_total_samples; +#ifdef HAVE_SYS_TIME_H + struct timeval d_start; +#endif + + gr_throttle(size_t itemsize, double samples_per_sec); + +public: + ~gr_throttle(); + + int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + + +#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 0000000000..eb237b352a --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_throttle.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,throttle); + +gr_throttle_sptr gr_make_throttle (size_t itemsize, double samples_per_sec); + +class gr_throttle : public gr_sync_block +{ + gr_throttle (size_t itemsize, double samples_per_sec); +}; 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 0000000000..e162d777fa --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_uchar_to_float.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_uchar_to_float_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 0000000000..7de5572694 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_uchar_to_float.h @@ -0,0 +1,51 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_UCHAR_TO_FLOAT_H +#define INCLUDED_GR_UCHAR_TO_FLOAT_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_uchar_to_float_sptr +gr_make_uchar_to_float (); + +/*! + * \brief Convert stream of unsigned chars to a stream of float + * \ingroup converter + */ + +class gr_uchar_to_float : public gr_sync_block +{ + friend 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 0000000000..4b7e8bce6d --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..399bc11122 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_unpack_k_bits_bb.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_unpack_k_bits_bb_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 0000000000..38a8bc1a90 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_unpack_k_bits_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_UNPACK_K_BITS_BB_H +#define INCLUDED_GR_UNPACK_K_BITS_BB_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_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 + */ +class gr_unpack_k_bits_bb : public gr_sync_interpolator +{ + private: + friend 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 0000000000..eb6bda9d8f --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,unpack_k_bits_bb) + +gr_unpack_k_bits_bb_sptr gr_make_unpack_k_bits_bb (int k); + +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_unpacked_to_packed_XX.cc.t b/gnuradio-core/src/lib/general/gr_unpacked_to_packed_XX.cc.t new file mode 100644 index 0000000000..7d5d72e651 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_unpacked_to_packed_XX.cc.t @@ -0,0 +1,125 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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) +{ + 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 + + //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,d_index,d_bits_per_chunk); + d_index++; + } + 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,d_index,d_bits_per_chunk)<<(BITS_PER_TYPE-1)); + d_index++; + } + out[i] = tmp; + } + break; + + default: + assert(0); + } + } + + 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/general/gr_unpacked_to_packed_XX.h.t b/gnuradio-core/src/lib/general/gr_unpacked_to_packed_XX.h.t new file mode 100644 index 0000000000..8d8c14d2a4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_unpacked_to_packed_XX.h.t @@ -0,0 +1,81 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_block.h> +#include <gr_endianness.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @NAME@_sptr; + +@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 block + * + * 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 @NAME@ : public gr_block +{ + friend @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/general/gr_unpacked_to_packed_XX.i.t b/gnuradio-core/src/lib/general/gr_unpacked_to_packed_XX.i.t new file mode 100644 index 0000000000..7fdcb5d7b6 --- /dev/null +++ b/gnuradio-core/src/lib/general/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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/general/gr_vco.h b/gnuradio-core/src/lib/general/gr_vco.h new file mode 100644 index 0000000000..3c35bdffe1 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vco.h @@ -0,0 +1,93 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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) + */ + +//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 0000000000..7421e4ec84 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vco_f.cc @@ -0,0 +1,58 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_vco_f_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 0000000000..2872d38792 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vco_f.h @@ -0,0 +1,72 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_VCO_F_H +#define INCLUDED_GR_VCO_F_H + +#include <gr_sync_block.h> +#include <gr_fxpt_vco.h> + +class gr_vco_f; +typedef boost::shared_ptr<gr_vco_f> gr_vco_f_sptr; + +/*! + * \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); + +/*! + * \brief VCO - Voltage controlled oscillator + * \ingroup block + * + * input: float stream of control voltages; output: float oscillator output + */ +class gr_vco_f : public gr_sync_block +{ + friend 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 0000000000..d344745042 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_sink_X.cc.t b/gnuradio-core/src/lib/general/gr_vector_sink_X.cc.t new file mode 100644 index 0000000000..5e99a92839 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_sink_X.cc.t @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <@NAME@.h> +#include <algorithm> +#include <gr_io_signature.h> + + +@NAME@::@NAME@ () + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (1, 1, sizeof (@TYPE@)), + gr_make_io_signature (0, 0, 0)) +{ +} + +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; i++) + d_data.push_back (iptr[i]); + + return noutput_items; +} + + +@NAME@_sptr +gr_make_@BASE_NAME@ () +{ + return @NAME@_sptr (new @NAME@ ()); +} + +std::vector<@TYPE@> +@NAME@::data () const +{ + return d_data; +} diff --git a/gnuradio-core/src/lib/general/gr_vector_sink_X.h.t b/gnuradio-core/src/lib/general/gr_vector_sink_X.h.t new file mode 100644 index 0000000000..e549f1fbca --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_sink_X.h.t @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @NAME@_sptr; + +@NAME@_sptr +gr_make_@BASE_NAME@ (); + + +/*! + * \brief @TYPE@ sink that writes to a vector + * \ingroup sink + */ + +class @NAME@ : public gr_sync_block { + friend @NAME@_sptr gr_make_@BASE_NAME@ (); + std::vector<@TYPE@> d_data; + @NAME@ (); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + + std::vector<@TYPE@> data () const; +}; + +#endif diff --git a/gnuradio-core/src/lib/general/gr_vector_sink_X.i.t b/gnuradio-core/src/lib/general/gr_vector_sink_X.i.t new file mode 100644 index 0000000000..d10636cfb4 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_sink_X.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@); + +@SPTR_NAME@ gr_make_@BASE_NAME@ (); + +class @NAME@ : public gr_sync_block { + private: + @NAME@ (); + + public: + std::vector<@TYPE@> data () const; +}; + diff --git a/gnuradio-core/src/lib/general/gr_vector_source_X.cc.t b/gnuradio-core/src/lib/general/gr_vector_source_X.cc.t new file mode 100644 index 0000000000..4ec2dd8bbc --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_source_X.cc.t @@ -0,0 +1,85 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <@NAME@.h> +#include <algorithm> +#include <gr_io_signature.h> + + +@NAME@::@NAME@ (const std::vector<@TYPE@> &data, bool repeat) + : gr_sync_block ("@BASE_NAME@", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 1, sizeof (@TYPE@))), + d_data (data), + d_repeat (repeat), + d_offset (0) +{ +} + +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; 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); + for (unsigned i = 0; i < n; i++) + optr[i] = d_data[d_offset + i]; + + d_offset += n; + return n; + } +} + +@NAME@_sptr +gr_make_@BASE_NAME@ (const std::vector<@TYPE@> &data, bool repeat) +{ + return @NAME@_sptr (new @NAME@ (data, repeat)); +} + diff --git a/gnuradio-core/src/lib/general/gr_vector_source_X.h.t b/gnuradio-core/src/lib/general/gr_vector_source_X.h.t new file mode 100644 index 0000000000..631ab867c6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_source_X.h.t @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <gr_sync_block.h> + +class @NAME@; +typedef boost::shared_ptr<@NAME@> @NAME@_sptr; + +/*! + * \brief source of @TYPE@'s that gets its data from a vector + * \ingroup source + */ + +class @NAME@ : public gr_sync_block { + friend @NAME@_sptr + gr_make_@BASE_NAME@ (const std::vector<@TYPE@> &data, bool repeat = false); + + std::vector<@TYPE@> d_data; + bool d_repeat; + unsigned int d_offset; + + @NAME@ (const std::vector<@TYPE@> &data, bool repeat); + + public: + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); +}; + +@NAME@_sptr +gr_make_@BASE_NAME@ (const std::vector<@TYPE@> &data, bool repeat); + +#endif diff --git a/gnuradio-core/src/lib/general/gr_vector_source_X.i.t b/gnuradio-core/src/lib/general/gr_vector_source_X.i.t new file mode 100644 index 0000000000..f3b98c62e7 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_source_X.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +// @WARNING@ + +GR_SWIG_BLOCK_MAGIC(gr,@BASE_NAME@); + +@NAME@_sptr +gr_make_@BASE_NAME@ (const std::vector<@TYPE@> &data, bool repeat = false); + +class @NAME@ : public gr_sync_block { + private: + @NAME@ (const std::vector<@TYPE@> &data); +}; 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 0000000000..130f961322 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_to_stream.cc @@ -0,0 +1,57 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_vector_to_stream.h> +#include <gr_io_signature.h> + +gr_vector_to_stream_sptr +gr_make_vector_to_stream (size_t item_size, size_t nitems_per_block) +{ + return gr_vector_to_stream_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 0000000000..5efff73301 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_to_stream.h @@ -0,0 +1,53 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_VECTOR_TO_STREAM_H +#define INCLUDED_GR_VECTOR_TO_STREAM_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_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 block + */ +class gr_vector_to_stream : public gr_sync_interpolator +{ + friend 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 0000000000..66ae1739ef --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..4a3f110e04 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_to_streams.cc @@ -0,0 +1,63 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_vector_to_streams.h> +#include <gr_io_signature.h> + +gr_vector_to_streams_sptr +gr_make_vector_to_streams (size_t item_size, size_t nstreams) +{ + return gr_vector_to_streams_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 0000000000..ae13fae443 --- /dev/null +++ b/gnuradio-core/src/lib/general/gr_vector_to_streams.h @@ -0,0 +1,53 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_VECTOR_TO_STREAMS_H +#define INCLUDED_GR_VECTOR_TO_STREAMS_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_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 block + */ +class gr_vector_to_streams : public gr_sync_block +{ + friend 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 0000000000..7444d0d6f1 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..49fddb68d2 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..f94db30e98 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_agc.h b/gnuradio-core/src/lib/general/gri_agc.h new file mode 100644 index 0000000000..eaaed8c3e8 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_agc.h @@ -0,0 +1,70 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GRI_AGC_H_ +#define _GRI_AGC_H_ + +#include <math.h> + +/*! + * \brief high performance Automatic Gain Control class + * + * Power is approximated by absolute value + */ + +class gri_agc { + + public: + gri_agc (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 /* _GRI_AGC_H_ */ diff --git a/gnuradio-core/src/lib/general/gri_agc.i b/gnuradio-core/src/lib/general/gri_agc.i new file mode 100644 index 0000000000..0bdbd40443 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_agc.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <math.h> + +/*! + * \brief high performance Automatic Gain Control class + * + * Power is approximated by absolute value + */ + + +class gri_agc { + + public: + gri_agc (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_agc_cc.h b/gnuradio-core/src/lib/general/gri_agc_cc.h new file mode 100644 index 0000000000..5cdd4e4657 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_agc_cc.h @@ -0,0 +1,71 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GRI_AGC_CC_H_ +#define _GRI_AGC_CC_H_ + +#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) + : _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 += (_reference - sqrt(output.real()*output.real()+output.imag()*output.imag())) * _rate; //use abs or cabs to get approximation by absolute value, + //note that abs is computationally more intensive then norm for a complex number + 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 /* _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 0000000000..70c1baa7b6 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_agc_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_char_to_float.cc b/gnuradio-core/src/lib/general/gri_char_to_float.cc new file mode 100644 index 0000000000..ca02ca27cd --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..7aa38d0204 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_char_to_float.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_CHAR_TO_FLOAT_H +#define INCLUDED_GRI_CHAR_TO_FLOAT_H + +/* + * convert array of chars to floats + */ +void gri_char_to_float (const char *in, float *out, int nsamples); + + +#endif /* INCLUDED_GRI_CHAR_TO_FLOAT_H */ 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 0000000000..35e138aa23 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..612b7c59bb --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_debugger_hook.h @@ -0,0 +1,28 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_DEBUGGER_HOOK_H +#define INCLUDED_GRI_DEBUGGER_HOOK_H + +void gri_debugger_hook (); + +#endif /* INCLUDED_GRI_DEBUGGER_HOOK_H */ 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 0000000000..30b012716d --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_fft.cc @@ -0,0 +1,229 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <gri_fft.h> +#include <fftw3.h> +#include <gr_complex.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <cassert> +#include <stdexcept> + +static char * +wisdom_filename () +{ + static char *filename = ".gr_fftw_wisdom"; + + char *home = getenv ("HOME"); + if (home){ + char *p = new char[strlen (home) + strlen (filename) + 2]; + strcpy (p, home); + strcat (p, "/"); + strcat (p, filename); + return p; + } + return 0; +} + +static void +gri_fftw_import_wisdom () +{ + 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); + } + } + delete [] filename; +} + +static void +gri_fftw_export_wisdom () +{ + 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); + } + delete [] filename; +} + +// ---------------------------------------------------------------- + +gri_fft_complex::gri_fft_complex (int fft_size, bool forward) +{ + 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"); + } + + // 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. + + 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 () +{ + fftwf_destroy_plan ((fftwf_plan) d_plan); + fftwf_free (d_inbuf); + fftwf_free (d_outbuf); +} + +void +gri_fft_complex::execute () +{ + fftwf_execute ((fftwf_plan) d_plan); +} + +// ---------------------------------------------------------------- + +gri_fft_real_fwd::gri_fft_real_fwd (int fft_size) +{ + 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"); + } + + // 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. + + 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 () +{ + fftwf_destroy_plan ((fftwf_plan) d_plan); + fftwf_free (d_inbuf); + fftwf_free (d_outbuf); +} + +void +gri_fft_real_fwd::execute () +{ + fftwf_execute ((fftwf_plan) d_plan); +} + +// ---------------------------------------------------------------- + +gri_fft_real_rev::gri_fft_real_rev (int fft_size) +{ + 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"); + } + + // 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. + + gri_fftw_import_wisdom (); // load prior wisdom from disk + 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::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 0000000000..5034774845 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_fft.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GRI_FFT_H_ +#define _GRI_FFT_H_ + +/* + * Wrappers for FFTW single precision 1d dft + */ + +#include <gr_complex.h> + +/*! + * \brief FFT: complex in, complex out + */ + +class gri_fft_complex { + int d_fft_size; + gr_complex *d_inbuf; + gr_complex *d_outbuf; + void *d_plan; + +public: + gri_fft_complex (int fft_size, bool forward = true); + 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; } + + /*! + * compute FFT. The input comes from inbuf, the output is placed in outbuf. + */ + void execute (); +}; + +/*! + * \brief FFT: real in, complex out + */ +class gri_fft_real_fwd { + int d_fft_size; + float *d_inbuf; + gr_complex *d_outbuf; + void *d_plan; + +public: + gri_fft_real_fwd (int fft_size); + 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; } + + /*! + * compute FFT. The input comes from inbuf, the output is placed in outbuf. + */ + void execute (); +}; + +/*! + * \brief FFT: complex in, float out + */ +class gri_fft_real_rev { + int d_fft_size; + gr_complex *d_inbuf; + float *d_outbuf; + void *d_plan; + +public: + gri_fft_real_rev (int fft_size); + 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; } + + /*! + * 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 0000000000..b94c53442a --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_float_to_char.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#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 0000000000..8891ac1abd --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_float_to_char.h @@ -0,0 +1,32 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_FLOAT_TO_CHAR_H +#define INCLUDED_GRI_FLOAT_TO_CHAR_H + +/*! + * convert array of floats to chars with rounding and saturation. + */ +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_short.cc b/gnuradio-core/src/lib/general/gri_float_to_short.cc new file mode 100644 index 0000000000..b2910616c9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_float_to_short.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#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 0000000000..e13b61d5d9 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_float_to_short.h @@ -0,0 +1,32 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_FLOAT_TO_SHORT_H +#define INCLUDED_GRI_FLOAT_TO_SHORT_H + +/*! + * convert array of floats to shorts with rounding and saturation. + */ +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 0000000000..8281a967e3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_float_to_uchar.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#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 0000000000..fbde8c51a3 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_float_to_uchar.h @@ -0,0 +1,32 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_FLOAT_TO_UCHAR_H +#define INCLUDED_GRI_FLOAT_TO_UCHAR_H + +/*! + * convert array of floats to unsigned chars with rounding and saturation. + */ +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_interleaved_short_to_complex.cc b/gnuradio-core/src/lib/general/gri_interleaved_short_to_complex.cc new file mode 100644 index 0000000000..56e3c39a56 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..3a0fc3de6b --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_interleaved_short_to_complex.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_INTERLEAVED_SHORT_TO_COMPLEX_H +#define INCLUDED_GRI_INTERLEAVED_SHORT_TO_COMPLEX_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. + */ +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_15_1_0.h b/gnuradio-core/src/lib/general/gri_lfsr_15_1_0.h new file mode 100644 index 0000000000..561ba6c525 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_lfsr_15_1_0.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_LFSR_15_1_0_H +#define INCLUDED_GRI_LFSR_15_1_0_H + +/*! + * \brief Linear Feedback Shift Register using primitive polynomial x^15 + x + 1 + * + * Generates a maximal length pseudo-random sequence of length 2^15 - 1 bits. + */ + +class 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 */ 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 0000000000..653223e671 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_lfsr_32k.h @@ -0,0 +1,78 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_LFSR_32k_H +#define INCLUDED_GRI_LFSR_32k_H + +#include <gri_lfsr_15_1_0.h> + +/*! + * \brief generate pseudo-random sequence of length 32768 bits. + * + * This is based on gri_lfsr_15_1_0 with an extra 0 added at the end + * of the sequence. + */ + +class 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 0000000000..f6beb45605 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..1abd0dd549 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_short_to_float.h @@ -0,0 +1,32 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_SHORT_TO_FLOAT_H +#define INCLUDED_GRI_SHORT_TO_FLOAT_H + +/* + * convert array of shorts to floats + */ +void gri_short_to_float (const short *in, float *out, int nsamples); + + +#endif /* INCLUDED_GRI_SHORT_TO_FLOAT_H */ 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 0000000000..8a5f87a564 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..50646e46e2 --- /dev/null +++ b/gnuradio-core/src/lib/general/gri_uchar_to_float.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GRI_UCHAR_TO_FLOAT_H +#define INCLUDED_GRI_UCHAR_TO_FLOAT_H + +/* + * convert array of unsigned chars to floats + */ +void gri_uchar_to_float (const unsigned char *in, float *out, int nsamples); + + +#endif /* INCLUDED_GRI_UCHAR_TO_FLOAT_H */ diff --git a/gnuradio-core/src/lib/general/malloc16.c b/gnuradio-core/src/lib/general/malloc16.c new file mode 100644 index 0000000000..2cc6135e77 --- /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 0000000000..0376ec567e --- /dev/null +++ b/gnuradio-core/src/lib/general/malloc16.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdlib.h> + +void *malloc16Align(int size); +void *calloc16Align(size_t nmemb,size_t size); +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 0000000000..1fa2b93580 --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_general.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_fxpt.h> +#include <qa_gr_fxpt_nco.h> +#include <qa_gr_fxpt_vco.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_fxpt::suite ()); + s->addTest (qa_gr_fxpt_nco::suite ()); + s->addTest (qa_gr_fxpt_vco::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 0000000000..6bf57df67a --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_general.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _QA_GENERAL_H_ +#define _QA_GENERAL_H_ + +#include <cppunit/TestSuite.h> + +//! collect all the tests for the gr directory + +class 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 0000000000..adfa33cb4d --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..45ebfd8e12 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_firdes.cc b/gnuradio-core/src/lib/general/qa_gr_firdes.cc new file mode 100644 index 0000000000..072bcb6807 --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_firdes.cc @@ -0,0 +1,344 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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; + +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]); + } +} + +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 +}; + + +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 () +{ +} 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 0000000000..8fb4d5a3dd --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_firdes.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_SUITE_END (); + + private: + void t1 (); + void t2 (); + void t3 (); + void t4 (); + +}; + + +#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 0000000000..6cd582ad94 --- /dev/null +++ b/gnuradio-core/src/lib/general/qa_gr_fxpt.cc @@ -0,0 +1,94 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 () +{ +} 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 0000000000..a21be5ccd3 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..5b774fb841 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..3d0c84a01d --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..70c2da366a --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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(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(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 0000000000..80ea0253c2 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/random.h b/gnuradio-core/src/lib/general/random.h new file mode 100644 index 0000000000..816aca3492 --- /dev/null +++ b/gnuradio-core/src/lib/general/random.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _RANDOM_H_ +#define _RANDOM_H_ + +// we use this because some systems (solaris) define RAND_MAX as 32767 + +static const int RANDOM_MAX = 2147483647; + +#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 0000000000..69834943bc --- /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/io/Makefile.am b/gnuradio-core/src/lib/io/Makefile.am new file mode 100644 index 0000000000..e390e1344a --- /dev/null +++ b/gnuradio-core/src/lib/io/Makefile.am @@ -0,0 +1,96 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) + +noinst_LTLIBRARIES = libio.la + + +libio_la_SOURCES = \ + gr_file_sink.cc \ + gr_file_source.cc \ + gr_file_descriptor_sink.cc \ + gr_file_descriptor_source.cc \ + gr_message_sink.cc \ + gr_message_source.cc \ + gr_oscope_guts.cc \ + gr_oscope_sink_f.cc \ + gr_oscope_sink_x.cc \ + gri_logger.cc \ + i2c.cc \ + i2c_bitbang.cc \ + i2c_bbio.cc \ + i2c_bbio_pp.cc \ + microtune_4702.cc \ + microtune_4937.cc \ + microtune_4702_eval_board.cc \ + microtune_4937_eval_board.cc \ + microtune_xxxx.cc \ + microtune_xxxx_eval_board.cc \ + ppio.cc \ + ppio_ppdev.cc \ + sdr_1000.cc + +grinclude_HEADERS = \ + gr_file_sink.h \ + gr_file_source.h \ + gr_file_descriptor_sink.h \ + gr_file_descriptor_source.h \ + gr_message_sink.h \ + gr_message_source.h \ + gr_oscope_guts.h \ + gr_oscope_sink_f.h \ + gr_oscope_sink_x.h \ + gr_trigger_mode.h \ + gri_logger.h \ + i2c.h \ + i2c_bitbang.h \ + i2c_bbio.h \ + i2c_bbio_pp.h \ + microtune_4702.h \ + microtune_4937.h \ + microtune_4702_eval_board.h \ + microtune_4937_eval_board.h \ + microtune_eval_board_defs.h \ + microtune_xxxx.h \ + microtune_xxxx_eval_board.h \ + ppio.h \ + ppio_ppdev.h \ + sdr_1000.h + + +swiginclude_HEADERS = \ + io.i \ + gr_file_sink.i \ + gr_file_source.i \ + gr_file_descriptor_sink.i \ + gr_file_descriptor_source.i \ + gr_message_sink.i \ + gr_message_source.i \ + gr_oscope_sink.i \ + microtune_xxxx_eval_board.i \ + microtune_4702_eval_board.i \ + microtune_4937_eval_board.i \ + ppio.i \ + sdr_1000.i 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 0000000000..6a0b1ca4ab --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_descriptor_sink.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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> + + +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 gr_file_descriptor_sink_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 0000000000..a811ce7056 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_descriptor_sink.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FILE_DESCRIPTOR_SINK_H +#define INCLUDED_GR_FILE_DESCRIPTOR_SINK_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_file_descriptor_sink_sptr gr_make_file_descriptor_sink (size_t itemsize, int fd); + +/*! + * \brief Write stream to file descriptor. + * \ingroup sink + */ + +class gr_file_descriptor_sink : public gr_sync_block +{ + friend 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 0000000000..e058186569 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..38b9da010e --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_descriptor_source.cc @@ -0,0 +1,146 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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> + + +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 0000000000..9f678dcf57 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_descriptor_source.h @@ -0,0 +1,67 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FILE_DESCRIPTOR_SOURCE_H +#define INCLUDED_GR_FILE_DESCRIPTOR_SOURCE_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_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 + */ + +class gr_file_descriptor_source : public gr_sync_block +{ + friend 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 0000000000..ba9b3894f9 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..d22488bf69 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_sink.cc @@ -0,0 +1,144 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_file_sink.h> +#include <gr_io_signature.h> +#include <cstdio> +#include <sys/types.h> +#include <sys/stat.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_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)), + d_itemsize(itemsize), d_fp(0), d_new_fp(0), d_updated(false) +{ + if (!open(filename)) + throw std::runtime_error ("can't open file"); +} + +gr_file_sink_sptr +gr_make_file_sink (size_t itemsize, const char *filename) +{ + return gr_file_sink_sptr (new gr_file_sink (itemsize, filename)); +} + +gr_file_sink::~gr_file_sink () +{ + close(); + if (d_fp){ + fclose((FILE *) d_fp); + d_fp = 0; + } +} + +bool +gr_file_sink::open(const char *filename) +{ + omni_mutex_lock l(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((FILE *) 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. + } + + d_updated = true; + return d_new_fp != 0; +} + +void +gr_file_sink::close() +{ + omni_mutex_lock l(d_mutex); // hold mutex for duration of this function + + if (d_new_fp){ + fclose((FILE *) d_new_fp); + d_new_fp = 0; + } + d_updated = true; +} + +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; + + if (d_updated){ + omni_mutex_lock l(d_mutex); // hold mutex for duration of this block + if (d_fp) + fclose((FILE *)d_fp); + d_fp = d_new_fp; // install new file pointer + d_new_fp = 0; + d_updated = false; + } + + if (!d_fp) + return noutput_items; // drop output on the floor + + while (nwritten < noutput_items){ + int count = fwrite (inbuf, d_itemsize, noutput_items - nwritten, (FILE *) d_fp); + if (count == 0) // FIXME add error handling + break; + nwritten += count; + inbuf += count * d_itemsize; + } + 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 0000000000..9c11bf72bd --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_sink.h @@ -0,0 +1,75 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FILE_SINK_H +#define INCLUDED_GR_FILE_SINK_H + +#include <gr_sync_block.h> +#include <omnithread.h> + +class gr_file_sink; +typedef boost::shared_ptr<gr_file_sink> gr_file_sink_sptr; + +gr_file_sink_sptr gr_make_file_sink(size_t itemsize, const char *filename); + +/*! + * \brief Write stream to file. + * \ingroup sink + */ + +class gr_file_sink : public gr_sync_block +{ + friend gr_file_sink_sptr gr_make_file_sink(size_t itemsize, const char *filename); + + private: + size_t d_itemsize; + void *d_fp; // current FILE pointer + void *d_new_fp; // new FILE pointer + bool d_updated; // is there a new FILE pointer? + omni_mutex d_mutex; + + 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. + * + * Closes current output file and ignores any output until + * open is called to connect to another file. + */ + void close(); + + 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 0000000000..ffcf02aa6f --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 +{ + 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_source.cc b/gnuradio-core/src/lib/io/gr_file_source.cc new file mode 100644 index 0000000000..2573a37e0d --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_source.cc @@ -0,0 +1,131 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#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> + +// 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_repeat (repeat) +{ + // 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"); + } +} + +// public constructor that returns a shared_ptr + +gr_file_source_sptr +gr_make_file_source (size_t itemsize, const char *filename, bool repeat) +{ + return gr_file_source_sptr (new gr_file_source (itemsize, filename, repeat)); +} + +gr_file_source::~gr_file_source () +{ + fclose ((FILE *) d_fp); +} + +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; + + 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) { + fprintf(stderr, "[%s] fseek failed\n", __FILE__); + exit(-1); + } + } + + 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) +{ + return fseek ((FILE *) d_fp, seek_point * d_itemsize, whence) == 0; +} 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 0000000000..6b635c53bc --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_FILE_SOURCE_H +#define INCLUDED_GR_FILE_SOURCE_H + +#include <gr_sync_block.h> + +class gr_file_source; +typedef boost::shared_ptr<gr_file_source> gr_file_source_sptr; + +gr_file_source_sptr +gr_make_file_source (size_t itemsize, const char *filename, bool repeat = false); + +/*! + * \brief Read stream from file + * \ingroup source + */ + +class gr_file_source : public gr_sync_block +{ + friend gr_file_source_sptr gr_make_file_source (size_t itemsize, + const char *filename, + bool repeat); + private: + size_t d_itemsize; + void *d_fp; + bool d_repeat; + + protected: + gr_file_source (size_t itemsize, const char *filename, bool repeat); + + public: + ~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); +}; + +#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 0000000000..08fdfaf930 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_file_source.i @@ -0,0 +1,43 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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); +}; 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 0000000000..8a0784ec43 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_sink.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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> + + +// 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 gr_message_sink_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 0000000000..8011ab290d --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_sink.h @@ -0,0 +1,62 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_MESSAGE_SINK_H +#define INCLUDED_GR_MESSAGE_SINK_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_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 + */ +class gr_message_sink : public gr_sync_block +{ + private: + size_t d_itemsize; + gr_msg_queue_sptr d_msgq; + bool d_dont_block; + + friend 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 0000000000..ca73479c53 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..797433be55 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_source.cc @@ -0,0 +1,104 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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> + + +// public constructor that returns a shared_ptr + +gr_message_source_sptr +gr_make_message_source(size_t itemsize, int msgq_limit) +{ + return gr_message_source_sptr(new gr_message_source(itemsize, msgq_limit)); +} + +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() +{ +} + +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 0000000000..0206012401 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_source.h @@ -0,0 +1,64 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_MESSAGE_SOURCE_H +#define INCLUDED_GR_MESSAGE_SOURCE_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_message_source_sptr gr_make_message_source (size_t itemsize, int msgq_limit=0); + +/*! + * \brief Turn received messages into a stream + * \ingroup source + */ +class 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_message_source_sptr + gr_make_message_source(size_t itemsize, int msgq_limit); + + protected: + gr_message_source (size_t itemsize, int msgq_limit); + + 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 0000000000..369112eff4 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_message_source.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +GR_SWIG_BLOCK_MAGIC(gr,message_source); + +gr_message_source_sptr gr_make_message_source (size_t itemsize, int msgq_limit=0); + +class gr_message_source : public gr_sync_block +{ + protected: + gr_message_source (size_t itemsize, int msgq_limit); + + 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 0000000000..6636fff1c7 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_guts.cc @@ -0,0 +1,382 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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> + +static const int OUTPUT_RECORD_SIZE = 2048; // must be power of 2 + +static inline int +wrap_bi (int buffer_index) // wrap buffer index +{ + return buffer_index & (OUTPUT_RECORD_SIZE - 1); +} + +static inline int +incr_bi (int buffer_index) // increment buffer index +{ + return wrap_bi (buffer_index + 1); +} + +static inline int +decr_bi (int buffer_index) // decrement buffer index +{ + return wrap_bi (buffer_index - 1); +} + +gr_oscope_guts::gr_oscope_guts (int nchannels, double sample_rate, gr_msg_queue_sptr msgq) + : d_nchannels (nchannels), + d_msgq (msgq), + d_trigger_mode (gr_TRIG_POS_SLOPE), + d_trigger_channel (0), + d_sample_rate (sample_rate), + d_update_rate (20), + d_trigger_level (0), + d_obi (0), + d_state (LOOK_FOR_TRIGGER), + d_decimator_count (0), + d_decimator_count_init (1), + d_hold_off_count (0), + d_hold_off_count_init (0), + d_post_trigger_count (0), + d_post_trigger_count_init (OUTPUT_RECORD_SIZE/2), + d_prev_sample (0) +{ + if (d_nchannels > MAX_CHANNELS){ + fprintf (stderr, "gr_oscope_guts: too many channels. MAX_CHANNELS = %d\n", MAX_CHANNELS); + throw std::runtime_error ("too many channels"); + } + + for (int i = 0; i < MAX_CHANNELS; i++) + d_buffer[i] = 0; + + for (int i = 0; i < d_nchannels; i++) + d_buffer[i] = new float [OUTPUT_RECORD_SIZE]; + + update_rate_or_decimation_changed (); + enter_look_for_trigger (); +} + +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; + + for (int i = 0; i < d_nchannels; i++) + d_buffer[i][d_obi] = channel_data[i]; // copy data into buffer + + int trigger = 0; + + 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: + trigger = found_trigger (d_buffer[d_trigger_channel][d_obi]); + if (trigger != 0){ + enter_post_trigger (); + if (trigger < 0) // previous sample was closer + d_post_trigger_count--; + } + 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); +} + +/* + * 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_state = LOOK_FOR_TRIGGER; + d_prev_sample = d_buffer[d_trigger_channel][d_obi]; +} + +void +gr_oscope_guts::enter_post_trigger () +{ + d_state = POST_TRIGGER; + d_post_trigger_count = d_post_trigger_count_init; +} + +// ---------------------------------------------------------------- +// returns 0 if no trigger found. +// returns +1 if this sample is the trigger point +// returns -1 if the previous sample is the trigger point + +int +gr_oscope_guts::found_trigger (float new_sample) +{ + float prev_sample = d_prev_sample; + d_prev_sample = new_sample; + bool trig; + + switch (d_trigger_mode){ + + case gr_TRIG_AUTO: // always trigger + return +1; + + case gr_TRIG_POS_SLOPE: + trig = prev_sample < d_trigger_level && new_sample >= d_trigger_level; + if (trig){ + if (fabs (prev_sample - d_trigger_level) < fabs (new_sample - d_trigger_level)) + return -1; + else + return +1; + } + return 0; + + case gr_TRIG_NEG_SLOPE: + trig = prev_sample > d_trigger_level && new_sample <= d_trigger_level; + if (trig){ + if (fabs (prev_sample - d_trigger_level) < fabs (new_sample - d_trigger_level)) + return -1; + else + return +1; + } + return 0; + + default: + assert (0); + return 0; + } +} + +// ---------------------------------------------------------------- +// write output records (duh!) + +void +gr_oscope_guts::write_output_records () +{ + // if the output queue if full, drop the data on the ground. + 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 + OUTPUT_RECORD_SIZE, // arg2 for other side + d_nchannels * OUTPUT_RECORD_SIZE * 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 points at the oldest sample in the buffer + for (int i = 0; i < OUTPUT_RECORD_SIZE; i++) + out[i] = d_buffer[ch][wrap_bi(d_obi + i)]; + + out += OUTPUT_RECORD_SIZE; + } + + 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) +{ + switch (mode){ + case gr_TRIG_POS_SLOPE: + case gr_TRIG_NEG_SLOPE: + case gr_TRIG_AUTO: + d_trigger_mode = mode; + trigger_changed (); + return true; + } + return false; +} + +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]); + } + + d_trigger_level = (min_v + max_v) * 0.5; + trigger_changed (); + return true; +} + +void +gr_oscope_guts::trigger_changed () +{ + // d_prev_sample = d_buffer[d_trigger_channel][decr_bi(d_obi)]; + 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; +} + +double +gr_oscope_guts::get_trigger_level () const +{ + return d_trigger_level; +} + +int +gr_oscope_guts::get_samples_per_output_record () const +{ + return OUTPUT_RECORD_SIZE; +} 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 0000000000..4094a65308 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_guts.h @@ -0,0 +1,116 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef INCLUDED_GR_OSCOPE_GUTS_H +#define INCLUDED_GR_OSCOPE_GUTS_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_oscope_guts { +private: + static const int MAX_CHANNELS = 16; + 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; + 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_post_trigger_count; + int d_post_trigger_count_init; + float d_prev_sample; // used for trigger checking + + // 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 (); + int found_trigger (float sample); // returns -1, 0, +1 + 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 (int nchannels, 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_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; + 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 0000000000..ea8419909e --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_sink.i @@ -0,0 +1,79 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +enum gr_trigger_mode { + gr_TRIG_AUTO, // auto trigger (on anything) + gr_TRIG_POS_SLOPE, // trigger on positive slope across trigger level + gr_TRIG_NEG_SLOPE // trigger on negative slope across trigger level +}; + +// 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_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; + 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 0000000000..b505381da3 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_sink_f.cc @@ -0,0 +1,80 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 gr_oscope_sink_f_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, MAX_CHANNELS, sizeof (float)), + sampling_rate), + d_msgq(msgq) +{ +} + + +bool +gr_oscope_sink_f::check_topology (int ninputs, int noutputs) +{ + delete d_guts; + d_guts = 0; + d_guts = new gr_oscope_guts (ninputs, d_sampling_rate, d_msgq); + return true; +} + + +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[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 0000000000..7b92a78500 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_sink_f.h @@ -0,0 +1,65 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_OSCOPE_SINK_F_H +#define INCLUDED_GR_OSCOPE_SINK_F_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_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 + * + * Accepts 1 to 16 float streams. + */ +class gr_oscope_sink_f : public gr_oscope_sink_x +{ +public: + static const int MAX_CHANNELS = 16; + +private: + friend 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 0000000000..51c28678e8 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_sink_x.cc @@ -0,0 +1,138 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_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); +} + +// 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 (); +} + +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 0000000000..45cccc0d46 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_oscope_sink_x.h @@ -0,0 +1,73 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_OSCOPE_SINK_X_H +#define INCLUDED_GR_OSCOPE_SINK_X_H + +#include <gr_sync_block.h> +#include <gr_trigger_mode.h> + +class gr_oscope_guts; + +/*! + * \brief Abstract class for python oscilloscope module. + * \ingroup sink + * + * Don't instantiate this. Use gr_oscope_sink_f or gr_oscope_sink_c instead. + */ +class 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_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; + 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_trigger_mode.h b/gnuradio-core/src/lib/io/gr_trigger_mode.h new file mode 100644 index 0000000000..0928c6a342 --- /dev/null +++ b/gnuradio-core/src/lib/io/gr_trigger_mode.h @@ -0,0 +1,32 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_TRIGGER_MODE_H +#define INCLUDED_GR_TRIGGER_MODE_H + +enum gr_trigger_mode { + gr_TRIG_AUTO, // auto trigger (on anything) + gr_TRIG_POS_SLOPE, // trigger on positive slope across trigger level + gr_TRIG_NEG_SLOPE // trigger on negative slope across trigger level +}; + +#endif /* INCLUDED_GR_TRIGGER_MODE_H */ diff --git a/gnuradio-core/src/lib/io/gri_logger.cc b/gnuradio-core/src/lib/io/gri_logger.cc new file mode 100644 index 0000000000..a1bdfb0e28 --- /dev/null +++ b/gnuradio-core/src/lib/io/gri_logger.cc @@ -0,0 +1,173 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <gri_logger.h> +#include <stdio.h> +#include <stdarg.h> +#include <stdexcept> +#include <boost/weak_ptr.hpp> + + +/* + * This class creates the thread that reads from the ringbuffer and + * and writes to the file. This is opaque to the user. + */ +class gri_log_poster : public omni_thread +{ + FILE *d_fp; + gr_buffer_sptr d_writer; + gr_buffer_reader_sptr d_reader; + omni_semaphore d_ringbuffer_ready; + volatile bool d_time_to_die; + volatile bool d_writer_overrun; + + virtual void* run_undetached(void * arg); + +public: + gri_log_poster(const char *filename); + ~gri_log_poster(); + + void kill() { d_time_to_die = true; post(); } + gr_buffer_sptr writer() const { return d_writer; } + void post() { d_ringbuffer_ready.post(); } + void note_writer_overrun() { d_writer_overrun = true; } +}; + +gri_log_poster::gri_log_poster(const char *filename) + : omni_thread(), + d_ringbuffer_ready(1, 1), // binary semaphore + d_time_to_die(false), + d_writer_overrun(false) +{ + if ((d_fp = fopen(filename, "w")) == 0){ + perror (filename); + throw std::runtime_error("can't open file"); + } + + // Create a 1MB buffer. + d_writer = gr_make_buffer(1 * 1024 * 1024, sizeof(unsigned char)); + d_reader = gr_buffer_add_reader(d_writer, 0); + + start_undetached(); // start the thread +} + +gri_log_poster::~gri_log_poster() +{ + if (d_fp != 0){ + fclose(d_fp); + d_fp = 0; + } +} + +/* + * This is the body of the logging thread. + */ +void * +gri_log_poster::run_undetached(void *arg) +{ + int nbytes; + + //fprintf(stderr, "Enter: run_undetached!\n"); + + while (!d_time_to_die){ + while ((nbytes = d_reader->items_available()) > 0){ + fwrite(d_reader->read_pointer(), 1, nbytes, d_fp); + d_reader->update_read_pointer(nbytes); + } + fflush(d_fp); + d_ringbuffer_ready.wait(); + + if (d_writer_overrun){ + fputs(">>>>> gri_logger: writer overrun. Info lost <<<<<\n", d_fp); + d_writer_overrun = false; + } + } + + // fprintf(stderr, "Exit: run_undetached!\n"); + return 0; +} + +// ------------------------------------------------------------------------ + +static boost::weak_ptr<gri_logger> s_singleton; // weak pointer IQ test ;-) +static omni_mutex s_singleton_mutex; + +gri_logger_sptr +gri_logger::singleton() +{ + omni_mutex_lock l(s_singleton_mutex); + gri_logger_sptr r; + + if (r = s_singleton.lock()) + return r; + + r = gri_logger_sptr(new gri_logger("gri_logger.log")); + s_singleton = r; + return r; +} + + +gri_logger::gri_logger(const char *filename) +{ + d_poster = new gri_log_poster(filename); +} + +gri_logger::~gri_logger() +{ + d_poster->kill(); + d_poster->join(NULL); +} + +void +gri_logger::write(const void *buf, size_t count) +{ + omni_mutex_lock l(d_write_mutex); + gr_buffer_sptr writer = d_poster->writer(); + + // either write it all, or drop it on the ground + if (count <= (size_t) writer->space_available()){ + memcpy(writer->write_pointer(), buf, count); + writer->update_write_pointer(count); + d_poster->post(); + } + else { + d_poster->note_writer_overrun(); + } +} + +void +gri_logger::printf(const char *format, ...) +{ + va_list ap; + char buf[4096]; + int n; + + va_start(ap, format); + n = vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + if (n > -1 && n < (ssize_t) sizeof(buf)) + write(buf, n); +} diff --git a/gnuradio-core/src/lib/io/gri_logger.h b/gnuradio-core/src/lib/io/gri_logger.h new file mode 100644 index 0000000000..ecbd3141ee --- /dev/null +++ b/gnuradio-core/src/lib/io/gri_logger.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GRI_LOGGER_H +#define INCLUDED_GRI_LOGGER_H + +#include <stddef.h> +#include <omnithread.h> +#include <gr_buffer.h> + +class gri_log_poster; +class gri_logger; +typedef boost::shared_ptr<gri_logger> gri_logger_sptr; + + +/*! + * \brief non-blocking logging to a file. + * + * In reality, this may block, but only for a bounded time. + * Trust me, it's safe to use from portaudio and JACK callbacks. + */ +class gri_logger +{ + gri_log_poster *d_poster; + omni_mutex d_write_mutex; + +public: + static gri_logger_sptr singleton(); + + gri_logger(const char *filename); + ~gri_logger(); + + void write(const void *buf, size_t count); + void printf(const char *format, ...); +}; + +#endif /* INCLUDED_GRI_LOGGER_H */ diff --git a/gnuradio-core/src/lib/io/i2c.cc b/gnuradio-core/src/lib/io/i2c.cc new file mode 100644 index 0000000000..9b9fbcd156 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..88b3c91354 --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c.h @@ -0,0 +1,48 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_I2C_H +#define INCLUDED_I2C_H + +#include <boost/shared_ptr.hpp> + +class i2c; +typedef boost::shared_ptr<i2c> i2c_sptr; + +/*! + * \brief abstract class for controlling i2c bus + */ +class 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 0000000000..8f3839768d --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..f0ea3b6646 --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c_bbio.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_I2C_BBIO_H +#define INCLUDED_I2C_BBIO_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. + */ +class 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 0000000000..125f01c339 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..25af0cf428 --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c_bbio_pp.h @@ -0,0 +1,55 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_I2C_BBIO_PP_H +#define INCLUDED_I2C_BBIO_PP_H + +#include "i2c_bbio.h" +#include "ppio.h" + +/*! + * \brief concrete class that bit bangs eval board i2c bus using parallel port + * + * 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 i2c_bbio_pp : public i2c_bbio { + friend 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; +}; + +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 0000000000..6bf37b604d --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..5196cd2342 --- /dev/null +++ b/gnuradio-core/src/lib/io/i2c_bitbang.h @@ -0,0 +1,63 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_I2C_BITBANG_H +#define INCLUDED_I2C_BITBANG_H + +#include <i2c.h> +#include <i2c_bbio.h> + +/*! + * \brief class for controlling i2c bus + */ +class i2c_bitbang : public i2c { + friend 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; +}; + +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 0000000000..ae4ca26820 --- /dev/null +++ b/gnuradio-core/src/lib/io/io.i @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%{ + +#include <gr_file_sink.h> +#include <gr_file_source.h> +#include <gr_file_descriptor_sink.h> +#include <gr_file_descriptor_source.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_sink.h> + +%} + +%include "gr_file_sink.i" +%include "gr_file_source.i" +%include "gr_file_descriptor_sink.i" +%include "gr_file_descriptor_source.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_sink.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 0000000000..9b180ff8be --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..b5890774fa --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4702.h @@ -0,0 +1,69 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_MICROTUNE_4702_H +#define INCLUDED_MICROTUNE_4702_H + +#include <microtune_xxxx.h> + +/*! + * \brief class for controlling microtune 4702 tuner module + */ + +class 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 0000000000..88cf2b6a0c --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..9fc2914edb --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4702_eval_board.h @@ -0,0 +1,47 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_MICROTUNE_4702_EVAL_BOARD_H +#define INCLUDED_MICROTUNE_4702_EVAL_BOARD_H + +#include "microtune_xxxx_eval_board.h" + +/*! + * \brief control microtune 4702 eval board + */ + +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); +}; + +#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 0000000000..6205c93033 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..c05f63c113 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..84c8d6112c --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4937.h @@ -0,0 +1,66 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_MICROTUNE_4937_H +#define INCLUDED_MICROTUNE_4937_H + +#include <microtune_xxxx.h> + +/*! + * \brief class for controlling microtune 4937 tuner module + */ +class 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 0000000000..82a03740c4 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..8a8f46b062 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_4937_eval_board.h @@ -0,0 +1,48 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_MICROTUNE_4937_EVAL_BOARD_H +#define INCLUDED_MICROTUNE_4937_EVAL_BOARD_H + +#include "microtune_xxxx_eval_board.h" + +/*! + * \brief control microtune 4937 eval board + */ + +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); +}; + + +#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 0000000000..106832e3d5 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..7c673e3a5b --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..5245fd5ceb --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..8633b111b2 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..8fac06d8f8 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_xxxx.h @@ -0,0 +1,64 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_MICROTUNE_XXXX_H +#define INCLUDED_MICROTUNE_XXXX_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 + */ +class 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 0000000000..a7ea98d6f1 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.cc @@ -0,0 +1,140 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#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 0000000000..3a817b6985 --- /dev/null +++ b/gnuradio-core/src/lib/io/microtune_xxxx_eval_board.h @@ -0,0 +1,96 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_MICROTUNE_XXXX_EVAL_BOARD_H +#define INCLUDED_MICROTUNE_XXXX_EVAL_BOARD_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 + */ +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; + + /*! + * \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 0000000000..2e43f27aad --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..86f402bbf7 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..4181387057 --- /dev/null +++ b/gnuradio-core/src/lib/io/ppio.h @@ -0,0 +1,61 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_PPIO_H +#define INCLUDED_PPIO_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 + */ + +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; +}; + +/*! + * \brief Factory method. + * + * Split out from class to make life easier for SWIG + */ + +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 0000000000..2eaddc204b --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..bfdaa3de09 --- /dev/null +++ b/gnuradio-core/src/lib/io/ppio_ppdev.cc @@ -0,0 +1,221 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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> +#ifdef HAVE_LINUX_PPDEV_H +#include <sys/ioctl.h> +#include <linux/ppdev.h> +#include <linux/parport.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; + +#ifndef HAVE_LINUX_PPDEV_H // use stubs + +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 () +{ +} + +#else + +// The real 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"); + } +} + +#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 0000000000..8ac4a35de4 --- /dev/null +++ b/gnuradio-core/src/lib/io/ppio_ppdev.h @@ -0,0 +1,60 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_PPIO_PPDEV_H +#define INCLUDED_PPIO_PPDEV_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 + */ + +class ppio_ppdev : public ppio { + friend 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 0000000000..1cb9b9afb9 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..f9ddb35ccf --- /dev/null +++ b/gnuradio-core/src/lib/io/sdr_1000.h @@ -0,0 +1,51 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_SDR_1000_H +#define INCLUDED_SDR_1000_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. + */ +class 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 0000000000..46690e0ce2 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/Makefile.am b/gnuradio-core/src/lib/missing/Makefile.am new file mode 100644 index 0000000000..7985fb3e11 --- /dev/null +++ b/gnuradio-core/src/lib/missing/Makefile.am @@ -0,0 +1,33 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = \ + getopt.h \ + getopt.c \ + gettimeofday.c \ + usleep.c + +noinst_LTLIBRARIES = libmissing.la + +libmissing_la_SOURCES = \ + bug_work_around_8.cc 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 0000000000..b79702275c --- /dev/null +++ b/gnuradio-core/src/lib/missing/bug_work_around_8.cc @@ -0,0 +1,2 @@ +// if libmisc has no sources, it doesn't get built correctly +static int gr_bug_work_around_8; diff --git a/gnuradio-core/src/lib/missing/getopt.c b/gnuradio-core/src/lib/missing/getopt.c new file mode 100644 index 0000000000..93fb6ea5b1 --- /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 2, 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 0000000000..45541f5ac0 --- /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 2, 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 0000000000..4ed15e21f8 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/usleep.c b/gnuradio-core/src/lib/missing/usleep.c new file mode 100644 index 0000000000..4a0f75ea8f --- /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 2 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/omnithread/Makefile.am b/gnuradio-core/src/lib/omnithread/Makefile.am new file mode 100644 index 0000000000..f2234468f8 --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/Makefile.am @@ -0,0 +1,67 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# This is the omnithread package, +# extracted from the omniORB-4.0.1 distribution + +# we should do some configure hacking to determine these on the fly +OMNITHREAD_DEFINES = -DPthreadDraftVersion=10 + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(OMNITHREAD_DEFINES) + +noinst_LTLIBRARIES = libomnithread.la + +# At this point we only support the posix and nt pthreads i/f... + +if OMNITHREAD_POSIX +libomnithread_la_SOURCES = \ + posix.cc +endif + +if OMNITHREAD_NT +libomnithread_la_SOURCES = \ + nt.cc +endif + +libomnithread_la_LIBADD = \ + $(PTHREAD_LIBS) + +# ... but this code also came with the package + +EXTRA_DIST = \ + mach.cc \ + nt.cc \ + posix.cc \ + solaris.cc \ + threaddata.cc \ + vxWorks.cc \ + dir.mk + +grinclude_HEADERS = \ + omnithread.h \ + ot_mach.h \ + ot_nt.h \ + ot_posix.h \ + ot_pthread_nt.h \ + ot_solaris.h \ + ot_VxThread.h diff --git a/gnuradio-core/src/lib/omnithread/dir.mk b/gnuradio-core/src/lib/omnithread/dir.mk new file mode 100644 index 0000000000..d53803417c --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/dir.mk @@ -0,0 +1,229 @@ +ifeq ($(ThreadSystem),Solaris) +CXXSRCS = solaris.cc +DIR_CPPFLAGS = $(OMNITHREAD_CPPFLAGS) +endif + +ifeq ($(ThreadSystem),Posix) +CXXSRCS = posix.cc +DIR_CPPFLAGS = $(OMNITHREAD_CPPFLAGS) $(OMNITHREAD_POSIX_CPPFLAGS) +endif + +ifeq ($(ThreadSystem),NT) +CXXSRCS = nt.cc +DIR_CPPFLAGS = $(OMNITHREAD_CPPFLAGS) +MSVC_STATICLIB_CXXNODEBUGFLAGS += -D_WINSTATIC +MSVC_STATICLIB_CXXDEBUGFLAGS += -D_WINSTATIC +MSVC_DLL_CXXNODEBUGFLAGS += -D_OMNITHREAD_DLL +MSVC_DLL_CXXDEBUGFLAGS += -D_OMNITHREAD_DLL +endif + +ifeq ($(ThreadSystem),NTPosix) +CXXSRCS = posix.cc +DIR_CPPFLAGS = $(OMNITHREAD_CPPFLAGS) +MSVC_STATICLIB_CXXNODEBUGFLAGS += -D_WINSTATIC +MSVC_STATICLIB_CXXDEBUGFLAGS += -D_WINSTATIC +MSVC_DLL_CXXNODEBUGFLAGS += -D_OMNITHREAD_DLL +MSVC_DLL_CXXDEBUGFLAGS += -D_OMNITHREAD_DLL +endif + +ifeq ($(ThreadSystem),Mach) +CXXSRCS = mach.cc +DIR_CPPFLAGS = $(OMNITHREAD_CPPFLAGS) +endif + +ifeq ($(ThreadSystem),vxWorks) +CXXSRCS = vxWorks.cc +OBJS = vxWorks.o +DIR_CPPFLAGS = $(OMNITHREAD_CPPFLAGS) +endif + +LIB_NAME := omnithread +LIB_VERSION := $(OMNITHREAD_VERSION) +LIB_OBJS := $(CXXSRCS:.cc=.o) +LIB_IMPORTS := $(OMNITHREAD_PLATFORM_LIB) + +all:: mkstatic mkshared + +export:: mkstatic mkshared + +ifdef INSTALLTARGET +install:: mkstatic mkshared +endif + +vers := $(subst ., ,$(LIB_VERSION)) +ifeq ($(words $(vers)), 2) + vers := _ $(vers) + major := "" +else + major := $(word 1, $(vers)) +endif + +namespec := $(LIB_NAME) $(vers) + +############################################################################## +# Build Static library +############################################################################## + +ifndef NoStaticLibrary + +staticlib := static/$(patsubst %,$(LibNoDebugPattern),$(LIB_NAME)$(major)) + +mkstatic:: + @(dir=static; $(CreateDir)) + +mkstatic:: $(staticlib) + +$(staticlib): $(patsubst %, static/%, $(LIB_OBJS)) + @$(StaticLinkLibrary) + +export:: $(staticlib) + @$(ExportLibrary) + +ifdef INSTALLTARGET +install:: $(staticlib) + @$(InstallLibrary) +endif + +clean:: + $(RM) static/*.o + $(RM) $(staticlib) + +veryclean:: + $(RM) static/*.o + $(RM) $(staticlib) + +else + +mkstatic:: + +endif + + +############################################################################## +# Build Shared library +############################################################################## +ifdef BuildSharedLibrary + +shlib := shared/$(shell $(SharedLibraryFullName) $(namespec)) + +ifdef Win32Platform +# in case of Win32 lossage: + imps := $(patsubst $(DLLDebugSearchPattern),$(DLLNoDebugSearchPattern), \ + $(LIB_IMPORTS)) +else + imps := $(LIB_IMPORTS) +endif + +mkshared:: + @(dir=shared; $(CreateDir)) + +mkshared:: $(shlib) + +$(shlib): $(patsubst %, shared/%, $(LIB_OBJS)) + @(namespec="$(namespec)" extralibs="$(imps)" nodeffile=1; \ + $(MakeCXXSharedLibrary)) + +export:: $(shlib) + @(namespec="$(namespec)"; \ + $(ExportSharedLibrary)) + +ifdef INSTALLTARGET +install:: $(shlib) + @(namespec="$(namespec)"; \ + $(InstallSharedLibrary)) +endif + +clean:: + $(RM) shared/*.o + (dir=shared; $(CleanSharedLibrary)) + +veryclean:: + $(RM) shared/*.o + @(dir=shared; $(CleanSharedLibrary)) + +else + +mkshared:: + +endif + +############################################################################## +# Build debug libraries for Win32 +############################################################################## +ifdef Win32Platform + +ifdef BuildSharedLibrary + +all:: mkstaticdbug mkshareddbug + +export:: mkstaticdbug mkshareddbug + +else + +all:: mkstaticdbug + +export:: mkstaticdbug + +endif + + +##################################################### +# Static debug libraries +##################################################### + +dbuglib := debug/$(patsubst %,$(LibDebugPattern),$(LIB_NAME)$(major)) + +mkstaticdbug:: + @(dir=debug; $(CreateDir)) + +mkstaticdbug:: $(dbuglib) + +$(dbuglib): $(patsubst %, debug/%, $(LIB_OBJS)) + @$(StaticLinkLibrary) + +export:: $(dbuglib) + @$(ExportLibrary) + +clean:: + $(RM) debug/*.o + $(RM) $(dbuglib) + +veryclean:: + $(RM) debug/*.o + $(RM) $(dbuglib) + +##################################################### +# DLL debug libraries +##################################################### + +ifdef BuildSharedLibrary + +dbugshlib := shareddebug/$(shell $(SharedLibraryDebugFullName) $(namespec)) + +dbugimps := $(patsubst $(DLLNoDebugSearchPattern),$(DLLDebugSearchPattern), \ + $(LIB_IMPORTS)) + +mkshareddbug:: + @(dir=shareddebug; $(CreateDir)) + +mkshareddbug:: $(dbugshlib) + +$(dbugshlib): $(patsubst %, shareddebug/%, $(LIB_OBJS)) + (namespec="$(namespec)" debug=1 extralibs="$(dbugimps)" nodeffile=1; \ + $(MakeCXXSharedLibrary)) + +export:: $(dbugshlib) + @(namespec="$(namespec)" debug=1; \ + $(ExportSharedLibrary)) + +clean:: + $(RM) shareddebug/*.o + @(dir=shareddebug; $(CleanSharedLibrary)) + +veryclean:: + $(RM) shareddebug/*.o + @(dir=shareddebug; $(CleanSharedLibrary)) + +endif +endif + diff --git a/gnuradio-core/src/lib/omnithread/mach.cc b/gnuradio-core/src/lib/omnithread/mach.cc new file mode 100644 index 0000000000..06f8a11e11 --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/mach.cc @@ -0,0 +1,714 @@ +// Package : omnithread +// omnithread/mach.cc Created : 7/97 lars immisch lars@ibp.de +// +// Copyright (C) 1997 Immisch, Becker & Partner +// +// This file is part of the omnithread library +// +// The omnithread 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 +// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA +// + +// +// Implementation of OMNI thread abstraction for mach threads +// +// to the author's pleasure, mach cthreads are very similar to posix threads +// + +#include <stdlib.h> +#include <errno.h> +#include <sys/time.h> +#include <mach/cthreads.h> +#include "omnithread.h" + +#define DB(x) // x +// #include <iostream> or #include <iostream.h> if DB is on. + +#define ERRNO(x) (x) + +// +// static variables +// + +int omni_thread::init_t::count = 0; + +omni_mutex* omni_thread::next_id_mutex; +int omni_thread::next_id = 0; + +static int normal_priority; +static int highest_priority; + +static size_t stack_size = 0; + +/////////////////////////////////////////////////////////////////////////// +// +// Mutex +// +/////////////////////////////////////////////////////////////////////////// + + +omni_mutex::omni_mutex(void) +{ + mutex_init(&mach_mutex); +} + + +omni_mutex::~omni_mutex(void) +{ + mutex_clear(&mach_mutex); +} + + +void omni_mutex::lock(void) +{ + mutex_lock(&mach_mutex); +} + + +void omni_mutex::unlock(void) +{ + mutex_unlock(&mach_mutex); +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Condition variable +// +/////////////////////////////////////////////////////////////////////////// + + +omni_condition::omni_condition(omni_mutex* m) : mutex(m) +{ + condition_init(&mach_cond); +} + + +omni_condition::~omni_condition(void) +{ + condition_clear(&mach_cond); +} + +void +omni_condition::wait(void) +{ + condition_wait(&mach_cond, &mutex->mach_mutex); +} + +typedef struct alarmclock_args { + unsigned long secs; + unsigned long nsecs; + bool wakeup; + condition_t condition; + mutex_t mutex; +}; + +any_t alarmclock(any_t arg) +{ + alarmclock_args* alarm = (alarmclock_args*)arg; + + omni_thread::sleep(alarm->secs, alarm->nsecs); + + mutex_lock(alarm->mutex); + + alarm->wakeup = TRUE; + + condition_signal(alarm->condition); + + mutex_unlock(alarm->mutex); + + return (any_t)TRUE; +} + +int omni_condition::timedwait(unsigned long abs_secs, unsigned long abs_nsecs) +{ + alarmclock_args alarm; + + omni_thread::get_time(&alarm.secs, &alarm.nsecs, 0, 0); + + if (abs_secs < alarm.secs || (abs_secs == alarm.secs && abs_nsecs <= alarm.nsecs)) + return ETIMEDOUT; + + alarm.secs = abs_secs - alarm.secs; + if (abs_nsecs <= alarm.nsecs) { + alarm.nsecs = 1000000 - alarm.nsecs + abs_nsecs; + alarm.secs--; + } + else { + alarm.nsecs = abs_nsecs - alarm.nsecs; + } + + alarm.mutex = &mutex->mach_mutex; + alarm.condition = &mach_cond; + alarm.wakeup = FALSE; + + cthread_t ct = cthread_fork((cthread_fn_t)alarmclock, (any_t)&alarm); + cthread_detach(ct); + + condition_wait(&mach_cond, &mutex->mach_mutex); + + if (alarm.wakeup) { + return 0; + } + + // interrupt the alarmclock thread sleep + cthread_abort(ct); + + // wait until it has signalled the condition + condition_wait(&mach_cond, &mutex->mach_mutex); + + return 1; +} + + +void omni_condition::signal(void) +{ + condition_signal(&mach_cond); +} + + +void omni_condition::broadcast(void) +{ + condition_signal(&mach_cond); +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Counting semaphore +// +/////////////////////////////////////////////////////////////////////////// + + +omni_semaphore::omni_semaphore(unsigned int initial) : c(&m) +{ + value = initial; +} + + +omni_semaphore::~omni_semaphore(void) +{ +} + + +void +omni_semaphore::wait(void) +{ + omni_mutex_lock l(m); + + while (value == 0) + c.wait(); + + value--; +} + + +int +omni_semaphore::trywait(void) +{ + omni_mutex_lock l(m); + + if (value == 0) + return 0; + + value--; + return 1; +} + + +void +omni_semaphore::post(void) +{ + omni_mutex_lock l(m); + + if (value == 0) + c.signal(); + + value++; +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Thread +// +/////////////////////////////////////////////////////////////////////////// + + + +// +// Initialisation function (gets called before any user code). +// + +omni_thread::init_t::init_t(void) +{ + if (count++ != 0) // only do it once however many objects get created. + return; + + // + // find base and max priority. + // This is the initial thread, so the max priority of this + // thread also applies to any newly created thread. + // + + kern_return_t error; + struct thread_sched_info info; + unsigned int info_count = THREAD_SCHED_INFO_COUNT; + + error = thread_info(thread_self(), THREAD_SCHED_INFO, (thread_info_t)&info, &info_count); + if (error != KERN_SUCCESS) { + DB(cerr << "omni_thread::init: error determining thread_info" << endl); + ::exit(1); + } + else { + normal_priority = info.base_priority; + highest_priority = info.max_priority; + } + + next_id_mutex = new omni_mutex; + + // + // Create object for this (i.e. initial) thread. + // + + omni_thread* t = new omni_thread; + + if (t->_state != STATE_NEW) { + DB(cerr << "omni_thread::init: problem creating initial thread object\n"); + ::exit(1); + } + + t->_state = STATE_RUNNING; + + t->mach_thread = cthread_self(); + + DB(cerr << "initial thread " << t->id() << endl); + + cthread_set_data(t->mach_thread, (any_t)t); +} + + +// +// Wrapper for thread creation. +// + +extern "C" void* +omni_thread_wrapper(void* ptr) +{ + omni_thread* me = (omni_thread*)ptr; + + DB(cerr << "omni_thread::wrapper: thread " << me->id() + << " started\n"); + + cthread_set_data(cthread_self(), (any_t)me); + + // + // Now invoke the thread function with the given argument. + // + + if (me->fn_void != NULL) { + (*me->fn_void)(me->thread_arg); + omni_thread::exit(); + } + + if (me->fn_ret != NULL) { + void* return_value = (*me->fn_ret)(me->thread_arg); + omni_thread::exit(return_value); + } + + if (me->detached) { + me->run(me->thread_arg); + omni_thread::exit(); + } else { + void* return_value = me->run_undetached(me->thread_arg); + omni_thread::exit(return_value); + } + + // should never get here. + + return NULL; +} + + +// +// Constructors for omni_thread - set up the thread object but don't +// start it running. +// + +// construct a detached thread running a given function. + +omni_thread::omni_thread(void (*fn)(void*), void* arg, priority_t pri) +{ + common_constructor(arg, pri, 1); + fn_void = fn; + fn_ret = NULL; +} + +// construct an undetached thread running a given function. + +omni_thread::omni_thread(void* (*fn)(void*), void* arg, priority_t pri) +{ + common_constructor(arg, pri, 0); + fn_void = NULL; + fn_ret = fn; +} + +// construct a thread which will run either run() or run_undetached(). + +omni_thread::omni_thread(void* arg, priority_t pri) +{ + common_constructor(arg, pri, 1); + fn_void = NULL; + fn_ret = NULL; +} + +// common part of all constructors. + +void omni_thread::common_constructor(void* arg, priority_t pri, int det) +{ + _state = STATE_NEW; + _priority = pri; + + next_id_mutex->lock(); + _id = next_id++; + next_id_mutex->unlock(); + + thread_arg = arg; + detached = det; // may be altered in start_undetached() + + _dummy = 0; + _values = 0; + _value_alloc = 0; + // posix_thread is set up in initialisation routine or start(). +} + + +// +// Destructor for omni_thread. +// + +omni_thread::~omni_thread(void) +{ + DB(cerr << "destructor called for thread " << id() << endl); + if (_values) { + for (key_t i=0; i < _value_alloc; i++) { + if (_values[i]) { + delete _values[i]; + } + } + delete [] _values; + } +} + + +// +// Start the thread +// + +void +omni_thread::start(void) +{ + omni_mutex_lock l(mutex); + + int rc; + + if (_state != STATE_NEW) + throw omni_thread_invalid(); + + mach_thread = cthread_fork(omni_thread_wrapper, (any_t)this); + + _state = STATE_RUNNING; + + if (detached) { + cthread_detach(mach_thread); + } +} + +// +// Start a thread which will run the member function run_undetached(). +// + +void +omni_thread::start_undetached(void) +{ + if ((fn_void != NULL) || (fn_ret != NULL)) + throw omni_thread_invalid(); + + detached = 0; + start(); +} + + +// +// join - simply check error conditions & call cthread_join. +// + +void +omni_thread::join(void** status) +{ + mutex.lock(); + + if ((_state != STATE_RUNNING) && (_state != STATE_TERMINATED)) { + mutex.unlock(); + throw omni_thread_invalid(); + } + + mutex.unlock(); + + if (this == self()) + throw omni_thread_invalid(); + + if (detached) + throw omni_thread_invalid(); + + DB(cerr << "omni_thread::join: doing cthread_join\n"); + + *status = cthread_join(mach_thread); + + delete this; +} + + +// +// Change this thread's priority. +// + +void +omni_thread::set_priority(priority_t pri) +{ + omni_mutex_lock l(mutex); + + if (_state != STATE_RUNNING) + throw omni_thread_invalid(); + + _priority = pri; + + kern_return_t rc = cthread_priority(mach_thread, mach_priority(pri), FALSE); + + if (rc != KERN_SUCCESS) + throw omni_thread_fatal(errno); +} + +// +// create - construct a new thread object and start it running. Returns thread +// object if successful, null pointer if not. +// + +// detached version + +omni_thread* +omni_thread::create(void (*fn)(void*), void* arg, priority_t pri) +{ + omni_thread* t = new omni_thread(fn, arg, pri); + + t->start(); + + return t; +} + +// undetached version + +omni_thread* +omni_thread::create(void* (*fn)(void*), void* arg, priority_t pri) +{ + omni_thread* t = new omni_thread(fn, arg, pri); + + t->start(); + + return t; +} + +// +// exit() _must_ lock the mutex even in the case of a detached thread. This is +// because a thread may run to completion before the thread that created it has +// had a chance to get out of start(). By locking the mutex we ensure that the +// creating thread must have reached the end of start() before we delete the +// thread object. Of course, once the call to start() returns, the user can +// still incorrectly refer to the thread object, but that's their problem. +// + +void omni_thread::exit(void* return_value) +{ + omni_thread* me = self(); + + if (me) + { + me->mutex.lock(); + + if (me->_state != STATE_RUNNING) + DB(cerr << "omni_thread::exit: thread not in \"running\" state\n"); + + me->_state = STATE_TERMINATED; + + me->mutex.unlock(); + + DB(cerr << "omni_thread::exit: thread " << me->id() << " detached " + << me->detached << " return value " << return_value << endl); + + if (me->detached) + delete me; + } + else + { + DB(cerr << "omni_thread::exit: called with a non-omnithread. Exit quietly." << endl); + } + cthread_exit(return_value); +} + +omni_thread* omni_thread::self(void) +{ + omni_thread* me; + + me = (omni_thread*)cthread_data(cthread_self()); + + if (!me) { + // This thread is not created by omni_thread::start because it + // doesn't has a class omni_thread instance attached to its key. + DB(cerr << "omni_thread::self: called with a non-ominthread. NULL is returned." << endl); + } + + return me; +} + +void omni_thread::yield(void) +{ + cthread_yield(); +} + +#define MAX_SLEEP_SECONDS (unsigned)4294966 // (2**32-2)/1000 + +void +omni_thread::sleep(unsigned long secs, unsigned long nanosecs) +{ + if (secs <= MAX_SLEEP_SECONDS) { + thread_switch(THREAD_NULL, SWITCH_OPTION_WAIT, secs * 1000 + nanosecs / 1000000); + return; + } + + unsigned no_of_max_sleeps = secs / MAX_SLEEP_SECONDS; + + for (unsigned i = 0; i < no_of_max_sleeps; i++) + thread_switch(THREAD_NULL, SWITCH_OPTION_WAIT, MAX_SLEEP_SECONDS * 1000); + + thread_switch(THREAD_NULL, SWITCH_OPTION_WAIT, + (secs % MAX_SLEEP_SECONDS) * 1000 + nanosecs / 1000000); + + return; +} + +void +omni_thread::get_time(unsigned long* abs_sec, unsigned long* abs_nsec, + unsigned long rel_sec, unsigned long rel_nsec) +{ + int rc; + unsigned long tv_sec; + unsigned long tv_nsec; + struct timeval tv; + + rc = gettimeofday(&tv, NULL); + if (rc) throw omni_thread_fatal(rc); + + tv_sec = tv.tv_sec; + tv_nsec = tv.tv_usec * 1000; + + tv_nsec += rel_nsec; + tv_sec += rel_sec + tv_nsec / 1000000000; + tv_nsec = tv_nsec % 1000000000; + + *abs_sec = tv_sec; + *abs_nsec = tv_nsec; +} + + +int +omni_thread::mach_priority(priority_t pri) +{ + switch (pri) { + + case PRIORITY_LOW: + return 0; + + case PRIORITY_NORMAL: + return normal_priority; + + case PRIORITY_HIGH: + return highest_priority; + + default: + return -1; + } +} + +void +omni_thread::stacksize(unsigned long sz) +{ + stack_size = sz; +} + +unsigned long +omni_thread::stacksize() +{ + return stack_size; +} + + +// +// Dummy thread +// + +#error This dummy thread code is not tested. It might work if you're lucky. + +class omni_thread_dummy : public omni_thread { +public: + inline omni_thread_dummy() : omni_thread() + { + _dummy = 1; + _state = STATE_RUNNING; + mach_thread = cthread_self(); + cthread_set_data(mach_thread, (any_t)this)); + } + inline ~omni_thread_dummy() + { + cthread_set_data(mach_thread, (any_t)0)); + } +}; + +omni_thread* +omni_thread::create_dummy() +{ + if (omni_thread::self()) + throw omni_thread_invalid(); + + return new omni_thread_dummy; +} + +void +omni_thread::release_dummy() +{ + omni_thread* self = omni_thread::self(); + if (!self || !self->_dummy) + throw omni_thread_invalid(); + + omni_thread_dummy* dummy = (omni_thread_dummy*)self; + delete dummy; +} + + +#define INSIDE_THREAD_IMPL_CC +#include "threaddata.cc" +#undef INSIDE_THREAD_IMPL_CC diff --git a/gnuradio-core/src/lib/omnithread/nt.cc b/gnuradio-core/src/lib/omnithread/nt.cc new file mode 100644 index 0000000000..09be422917 --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/nt.cc @@ -0,0 +1,967 @@ +// Package : omnithread +// omnithread/nt.cc Created : 6/95 tjr +// +// Copyright (C) 2006 Free Software Foundation, Inc. +// Copyright (C) 1995-1999 AT&T Laboratories Cambridge +// +// This file is part of the omnithread library +// +// The omnithread 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 +// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA +// + +// +// Implementation of OMNI thread abstraction for NT threads +// + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> +#include <errno.h> +#include <omnithread.h> +#include <process.h> + +#define DB(x) // x +//#include <iostream.h> or #include <iostream> if DB is on. + +static void get_time_now(unsigned long* abs_sec, unsigned long* abs_nsec); + +/////////////////////////////////////////////////////////////////////////// +// +// Mutex +// +/////////////////////////////////////////////////////////////////////////// + + +omni_mutex::omni_mutex(void) +{ + InitializeCriticalSection(&crit); +} + +omni_mutex::~omni_mutex(void) +{ + DeleteCriticalSection(&crit); +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Condition variable +// +/////////////////////////////////////////////////////////////////////////// + + +// +// Condition variables are tricky to implement using NT synchronisation +// primitives, since none of them have the atomic "release mutex and wait to be +// signalled" which is central to the idea of a condition variable. To get +// around this the solution is to record which threads are waiting and +// explicitly wake up those threads. +// +// Here we implement a condition variable using a list of waiting threads +// (protected by a critical section), and a per-thread semaphore (which +// actually only needs to be a binary semaphore). +// +// To wait on the cv, a thread puts itself on the list of waiting threads for +// that cv, then releases the mutex and waits on its own personal semaphore. A +// signalling thread simply takes a thread from the head of the list and kicks +// that thread's semaphore. Broadcast is simply implemented by kicking the +// semaphore of each waiting thread. +// +// The only other tricky part comes when a thread gets a timeout from a timed +// wait on its semaphore. Between returning with a timeout from the wait and +// entering the critical section, a signalling thread could get in, kick the +// waiting thread's semaphore and remove it from the list. If this happens, +// the waiting thread's semaphore is now out of step so it needs resetting, and +// the thread should indicate that it was signalled rather than that it timed +// out. +// +// It is possible that the thread calling wait or timedwait is not a +// omni_thread. In this case we have to provide a temporary data structure, +// i.e. for the duration of the call, for the thread to link itself on the +// list of waiting threads. _internal_omni_thread_dummy provides such +// a data structure and _internal_omni_thread_helper is a helper class to +// deal with this special case for wait() and timedwait(). Once created, +// the _internal_omni_thread_dummy is cached for use by the next wait() or +// timedwait() call from a non-omni_thread. This is probably worth doing +// because creating a Semaphore is quite heavy weight. + +class _internal_omni_thread_helper; + +class _internal_omni_thread_dummy : public omni_thread { +public: + inline _internal_omni_thread_dummy() : next(0) { } + inline ~_internal_omni_thread_dummy() { } + friend class _internal_omni_thread_helper; +private: + _internal_omni_thread_dummy* next; +}; + +class _internal_omni_thread_helper { +public: + inline _internal_omni_thread_helper() { + d = 0; + t = omni_thread::self(); + if (!t) { + omni_mutex_lock sync(cachelock); + if (cache) { + d = cache; + cache = cache->next; + } + else { + d = new _internal_omni_thread_dummy; + } + t = d; + } + } + inline ~_internal_omni_thread_helper() { + if (d) { + omni_mutex_lock sync(cachelock); + d->next = cache; + cache = d; + } + } + inline operator omni_thread* () { return t; } + inline omni_thread* operator->() { return t; } + + static _internal_omni_thread_dummy* cache; + static omni_mutex cachelock; + +private: + _internal_omni_thread_dummy* d; + omni_thread* t; +}; + +_internal_omni_thread_dummy* _internal_omni_thread_helper::cache = 0; +omni_mutex _internal_omni_thread_helper::cachelock; + + +omni_condition::omni_condition(omni_mutex* m) : mutex(m) +{ + InitializeCriticalSection(&crit); + waiting_head = waiting_tail = NULL; +} + + +omni_condition::~omni_condition(void) +{ + DeleteCriticalSection(&crit); + DB( if (waiting_head != NULL) { + cerr << "omni_condition::~omni_condition: list of waiting threads " + << "is not empty\n"; + } ) +} + + +void +omni_condition::wait(void) +{ + _internal_omni_thread_helper me; + + EnterCriticalSection(&crit); + + me->cond_next = NULL; + me->cond_prev = waiting_tail; + if (waiting_head == NULL) + waiting_head = me; + else + waiting_tail->cond_next = me; + waiting_tail = me; + me->cond_waiting = TRUE; + + LeaveCriticalSection(&crit); + + mutex->unlock(); + + DWORD result = WaitForSingleObject(me->cond_semaphore, INFINITE); + + mutex->lock(); + + if (result != WAIT_OBJECT_0) + throw omni_thread_fatal(GetLastError()); +} + + +int +omni_condition::timedwait(unsigned long abs_sec, unsigned long abs_nsec) +{ + _internal_omni_thread_helper me; + + EnterCriticalSection(&crit); + + me->cond_next = NULL; + me->cond_prev = waiting_tail; + if (waiting_head == NULL) + waiting_head = me; + else + waiting_tail->cond_next = me; + waiting_tail = me; + me->cond_waiting = TRUE; + + LeaveCriticalSection(&crit); + + mutex->unlock(); + + unsigned long now_sec, now_nsec; + + get_time_now(&now_sec, &now_nsec); + + DWORD timeout; + if ((abs_sec <= now_sec) && ((abs_sec < now_sec) || (abs_nsec < now_nsec))) + timeout = 0; + else { + timeout = (abs_sec-now_sec) * 1000; + + if( abs_nsec < now_nsec ) timeout -= (now_nsec-abs_nsec) / 1000000; + else timeout += (abs_nsec-now_nsec) / 1000000; + } + + DWORD result = WaitForSingleObject(me->cond_semaphore, timeout); + + if (result == WAIT_TIMEOUT) { + EnterCriticalSection(&crit); + + if (me->cond_waiting) { + if (me->cond_prev != NULL) + me->cond_prev->cond_next = me->cond_next; + else + waiting_head = me->cond_next; + if (me->cond_next != NULL) + me->cond_next->cond_prev = me->cond_prev; + else + waiting_tail = me->cond_prev; + me->cond_waiting = FALSE; + + LeaveCriticalSection(&crit); + + mutex->lock(); + return 0; + } + + // + // We timed out but another thread still signalled us. Wait for + // the semaphore (it _must_ have been signalled) to decrement it + // again. Return that we were signalled, not that we timed out. + // + + LeaveCriticalSection(&crit); + + result = WaitForSingleObject(me->cond_semaphore, INFINITE); + } + + if (result != WAIT_OBJECT_0) + throw omni_thread_fatal(GetLastError()); + + mutex->lock(); + return 1; +} + + +void +omni_condition::signal(void) +{ + EnterCriticalSection(&crit); + + if (waiting_head != NULL) { + omni_thread* t = waiting_head; + waiting_head = t->cond_next; + if (waiting_head == NULL) + waiting_tail = NULL; + else + waiting_head->cond_prev = NULL; + t->cond_waiting = FALSE; + + if (!ReleaseSemaphore(t->cond_semaphore, 1, NULL)) { + int rc = GetLastError(); + LeaveCriticalSection(&crit); + throw omni_thread_fatal(rc); + } + } + + LeaveCriticalSection(&crit); +} + + +void +omni_condition::broadcast(void) +{ + EnterCriticalSection(&crit); + + while (waiting_head != NULL) { + omni_thread* t = waiting_head; + waiting_head = t->cond_next; + if (waiting_head == NULL) + waiting_tail = NULL; + else + waiting_head->cond_prev = NULL; + t->cond_waiting = FALSE; + + if (!ReleaseSemaphore(t->cond_semaphore, 1, NULL)) { + int rc = GetLastError(); + LeaveCriticalSection(&crit); + throw omni_thread_fatal(rc); + } + } + + LeaveCriticalSection(&crit); +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Counting semaphore +// +/////////////////////////////////////////////////////////////////////////// + + +#define SEMAPHORE_MAX 0x7fffffff + + +omni_semaphore::omni_semaphore(unsigned int initial, unsigned int max_count) +{ + if (max_count > SEMAPHORE_MAX) + max_count= SEMAPHORE_MAX; + + nt_sem = CreateSemaphore(NULL, initial, max_count, NULL); + + if (nt_sem == NULL) { + DB( cerr << "omni_semaphore::omni_semaphore: CreateSemaphore error " + << GetLastError() << endl ); + throw omni_thread_fatal(GetLastError()); + } +} + + +omni_semaphore::~omni_semaphore(void) +{ + if (!CloseHandle(nt_sem)) { + DB( cerr << "omni_semaphore::~omni_semaphore: CloseHandle error " + << GetLastError() << endl ); + throw omni_thread_fatal(GetLastError()); + } +} + + +void +omni_semaphore::wait(void) +{ + if (WaitForSingleObject(nt_sem, INFINITE) != WAIT_OBJECT_0) + throw omni_thread_fatal(GetLastError()); +} + + +int +omni_semaphore::trywait(void) +{ + switch (WaitForSingleObject(nt_sem, 0)) { + + case WAIT_OBJECT_0: + return 1; + case WAIT_TIMEOUT: + return 0; + } + + throw omni_thread_fatal(GetLastError()); + return 0; /* keep msvc++ happy */ +} + + +void +omni_semaphore::post(void) +{ + if (!ReleaseSemaphore(nt_sem, 1, NULL)) + throw omni_thread_fatal(GetLastError()); +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Thread +// +/////////////////////////////////////////////////////////////////////////// + + +// +// Static variables +// + +omni_mutex* omni_thread::next_id_mutex; +int omni_thread::next_id = 0; +static DWORD self_tls_index; + +static unsigned int stack_size = 0; + +// +// Initialisation function (gets called before any user code). +// + +static int& count() { + static int the_count = 0; + return the_count; +} + +omni_thread::init_t::init_t(void) +{ + if (count()++ != 0) // only do it once however many objects get created. + return; + + DB(cerr << "omni_thread::init: NT implementation initialising\n"); + + self_tls_index = TlsAlloc(); + + if (self_tls_index == 0xffffffff) + throw omni_thread_fatal(GetLastError()); + + next_id_mutex = new omni_mutex; + + // + // Create object for this (i.e. initial) thread. + // + + omni_thread* t = new omni_thread; + + t->_state = STATE_RUNNING; + + if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), + GetCurrentProcess(), &t->handle, + 0, FALSE, DUPLICATE_SAME_ACCESS)) + throw omni_thread_fatal(GetLastError()); + + t->nt_id = GetCurrentThreadId(); + + DB(cerr << "initial thread " << t->id() << " NT thread id " << t->nt_id + << endl); + + if (!TlsSetValue(self_tls_index, (LPVOID)t)) + throw omni_thread_fatal(GetLastError()); + + if (!SetThreadPriority(t->handle, nt_priority(PRIORITY_NORMAL))) + throw omni_thread_fatal(GetLastError()); +} + +omni_thread::init_t::~init_t(void) +{ + if (--count() != 0) return; + + omni_thread* self = omni_thread::self(); + if (!self) return; + + TlsSetValue(self_tls_index, (LPVOID)0); + delete self; + + delete next_id_mutex; + + TlsFree(self_tls_index); +} + +// +// Wrapper for thread creation. +// + +extern "C" +#ifndef __BCPLUSPLUS__ +unsigned __stdcall +#else +void _USERENTRY +#endif +omni_thread_wrapper(void* ptr) +{ + omni_thread* me = (omni_thread*)ptr; + + DB(cerr << "omni_thread_wrapper: thread " << me->id() + << " started\n"); + + if (!TlsSetValue(self_tls_index, (LPVOID)me)) + throw omni_thread_fatal(GetLastError()); + + // + // Now invoke the thread function with the given argument. + // + + if (me->fn_void != NULL) { + (*me->fn_void)(me->thread_arg); + omni_thread::exit(); + } + + if (me->fn_ret != NULL) { + void* return_value = (*me->fn_ret)(me->thread_arg); + omni_thread::exit(return_value); + } + + if (me->detached) { + me->run(me->thread_arg); + omni_thread::exit(); + } else { + void* return_value = me->run_undetached(me->thread_arg); + omni_thread::exit(return_value); + } + + // should never get here. +#ifndef __BCPLUSPLUS__ + return 0; +#endif +} + + +// +// Constructors for omni_thread - set up the thread object but don't +// start it running. +// + +// construct a detached thread running a given function. + +omni_thread::omni_thread(void (*fn)(void*), void* arg, priority_t pri) +{ + common_constructor(arg, pri, 1); + fn_void = fn; + fn_ret = NULL; +} + +// construct an undetached thread running a given function. + +omni_thread::omni_thread(void* (*fn)(void*), void* arg, priority_t pri) +{ + common_constructor(arg, pri, 0); + fn_void = NULL; + fn_ret = fn; +} + +// construct a thread which will run either run() or run_undetached(). + +omni_thread::omni_thread(void* arg, priority_t pri) +{ + common_constructor(arg, pri, 1); + fn_void = NULL; + fn_ret = NULL; +} + +// common part of all constructors. + +void +omni_thread::common_constructor(void* arg, priority_t pri, int det) +{ + _state = STATE_NEW; + _priority = pri; + + next_id_mutex->lock(); + _id = next_id++; + next_id_mutex->unlock(); + + thread_arg = arg; + detached = det; // may be altered in start_undetached() + + cond_semaphore = CreateSemaphore(NULL, 0, SEMAPHORE_MAX, NULL); + + if (cond_semaphore == NULL) + throw omni_thread_fatal(GetLastError()); + + cond_next = cond_prev = NULL; + cond_waiting = FALSE; + + handle = NULL; + + _dummy = 0; + _values = 0; + _value_alloc = 0; +} + + +// +// Destructor for omni_thread. +// + +omni_thread::~omni_thread(void) +{ + DB(cerr << "destructor called for thread " << id() << endl); + if (_values) { + for (key_t i=0; i < _value_alloc; i++) { + if (_values[i]) { + delete _values[i]; + } + } + delete [] _values; + } + if (handle && !CloseHandle(handle)) + throw omni_thread_fatal(GetLastError()); + if (cond_semaphore && !CloseHandle(cond_semaphore)) + throw omni_thread_fatal(GetLastError()); +} + + +// +// Start the thread +// + +void +omni_thread::start(void) +{ + omni_mutex_lock l(mutex); + + if (_state != STATE_NEW) + throw omni_thread_invalid(); + +#ifndef __BCPLUSPLUS__ + // MSVC++ or compatiable + unsigned int t; + handle = (HANDLE)_beginthreadex( + NULL, + stack_size, + omni_thread_wrapper, + (LPVOID)this, + CREATE_SUSPENDED, + &t); + nt_id = t; + if (handle == NULL) + throw omni_thread_fatal(GetLastError()); +#else + // Borland C++ + handle = (HANDLE)_beginthreadNT(omni_thread_wrapper, + stack_size, + (void*)this, + NULL, + CREATE_SUSPENDED, + &nt_id); + if (handle == INVALID_HANDLE_VALUE) + throw omni_thread_fatal(errno); +#endif + + if (!SetThreadPriority(handle, nt_priority(_priority))) + throw omni_thread_fatal(GetLastError()); + + if (ResumeThread(handle) == 0xffffffff) + throw omni_thread_fatal(GetLastError()); + + _state = STATE_RUNNING; +} + + +// +// Start a thread which will run the member function run_undetached(). +// + +void +omni_thread::start_undetached(void) +{ + if ((fn_void != NULL) || (fn_ret != NULL)) + throw omni_thread_invalid(); + + detached = 0; + start(); +} + + +// +// join - simply check error conditions & call WaitForSingleObject. +// + +void +omni_thread::join(void** status) +{ + mutex.lock(); + + if ((_state != STATE_RUNNING) && (_state != STATE_TERMINATED)) { + mutex.unlock(); + throw omni_thread_invalid(); + } + + mutex.unlock(); + + if (this == self()) + throw omni_thread_invalid(); + + if (detached) + throw omni_thread_invalid(); + + DB(cerr << "omni_thread::join: doing WaitForSingleObject\n"); + + if (WaitForSingleObject(handle, INFINITE) != WAIT_OBJECT_0) + throw omni_thread_fatal(GetLastError()); + + DB(cerr << "omni_thread::join: WaitForSingleObject succeeded\n"); + + if (status) + *status = return_val; + + delete this; +} + + +// +// Change this thread's priority. +// + +void +omni_thread::set_priority(priority_t pri) +{ + omni_mutex_lock l(mutex); + + if (_state != STATE_RUNNING) + throw omni_thread_invalid(); + + _priority = pri; + + if (!SetThreadPriority(handle, nt_priority(pri))) + throw omni_thread_fatal(GetLastError()); +} + + +// +// create - construct a new thread object and start it running. Returns thread +// object if successful, null pointer if not. +// + +// detached version + +omni_thread* +omni_thread::create(void (*fn)(void*), void* arg, priority_t pri) +{ + omni_thread* t = new omni_thread(fn, arg, pri); + t->start(); + return t; +} + +// undetached version + +omni_thread* +omni_thread::create(void* (*fn)(void*), void* arg, priority_t pri) +{ + omni_thread* t = new omni_thread(fn, arg, pri); + t->start(); + return t; +} + + +// +// exit() _must_ lock the mutex even in the case of a detached thread. This is +// because a thread may run to completion before the thread that created it has +// had a chance to get out of start(). By locking the mutex we ensure that the +// creating thread must have reached the end of start() before we delete the +// thread object. Of course, once the call to start() returns, the user can +// still incorrectly refer to the thread object, but that's their problem. +// + +void +omni_thread::exit(void* return_value) +{ + omni_thread* me = self(); + + if (me) + { + me->mutex.lock(); + + me->_state = STATE_TERMINATED; + + me->mutex.unlock(); + + DB(cerr << "omni_thread::exit: thread " << me->id() << " detached " + << me->detached << " return value " << return_value << endl); + + if (me->detached) { + delete me; + } else { + me->return_val = return_value; + } + } + else + { + DB(cerr << "omni_thread::exit: called with a non-omnithread. Exit quietly." << endl); + } +#ifndef __BCPLUSPLUS__ + // MSVC++ or compatiable + // _endthreadex() does not automatically closes the thread handle. + // The omni_thread dtor closes the thread handle. + _endthreadex(0); +#else + // Borland C++ + // _endthread() does not automatically closes the thread handle. + // _endthreadex() is only available if __MFC_COMPAT__ is defined and + // all it does is to call _endthread(). + _endthread(); +#endif +} + + +omni_thread* +omni_thread::self(void) +{ + LPVOID me; + + me = TlsGetValue(self_tls_index); + + if (me == NULL) { + DB(cerr << "omni_thread::self: called with a non-ominthread. NULL is returned." << endl); + } + return (omni_thread*)me; +} + + +void +omni_thread::yield(void) +{ + Sleep(0); +} + + +#define MAX_SLEEP_SECONDS (DWORD)4294966 // (2**32-2)/1000 + +void +omni_thread::sleep(unsigned long secs, unsigned long nanosecs) +{ + if (secs <= MAX_SLEEP_SECONDS) { + Sleep(secs * 1000 + nanosecs / 1000000); + return; + } + + DWORD no_of_max_sleeps = secs / MAX_SLEEP_SECONDS; + + for (DWORD i = 0; i < no_of_max_sleeps; i++) + Sleep(MAX_SLEEP_SECONDS * 1000); + + Sleep((secs % MAX_SLEEP_SECONDS) * 1000 + nanosecs / 1000000); +} + + +void +omni_thread::get_time(unsigned long* abs_sec, unsigned long* abs_nsec, + unsigned long rel_sec, unsigned long rel_nsec) +{ + get_time_now(abs_sec, abs_nsec); + *abs_nsec += rel_nsec; + *abs_sec += rel_sec + *abs_nsec / 1000000000; + *abs_nsec = *abs_nsec % 1000000000; +} + + +int +omni_thread::nt_priority(priority_t pri) +{ + switch (pri) { + + case PRIORITY_LOW: + return THREAD_PRIORITY_LOWEST; + + case PRIORITY_NORMAL: + return THREAD_PRIORITY_NORMAL; + + case PRIORITY_HIGH: + return THREAD_PRIORITY_HIGHEST; + } + + throw omni_thread_invalid(); + return 0; /* keep msvc++ happy */ +} + + +static void +get_time_now(unsigned long* abs_sec, unsigned long* abs_nsec) +{ + static int days_in_preceding_months[12] + = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; + static int days_in_preceding_months_leap[12] + = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }; + + SYSTEMTIME st; + + GetSystemTime(&st); + *abs_nsec = st.wMilliseconds * 1000000; + + // this formula should work until 1st March 2100 + + DWORD days = ((st.wYear - 1970) * 365 + (st.wYear - 1969) / 4 + + ((st.wYear % 4) + ? days_in_preceding_months[st.wMonth - 1] + : days_in_preceding_months_leap[st.wMonth - 1]) + + st.wDay - 1); + + *abs_sec = st.wSecond + 60 * (st.wMinute + 60 * (st.wHour + 24 * days)); +} + +void +omni_thread::stacksize(unsigned long sz) +{ + stack_size = sz; +} + +unsigned long +omni_thread::stacksize() +{ + return stack_size; +} + +// +// Dummy thread +// + +class omni_thread_dummy : public omni_thread { +public: + inline omni_thread_dummy() : omni_thread() + { + _dummy = 1; + _state = STATE_RUNNING; + + if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), + GetCurrentProcess(), &handle, + 0, FALSE, DUPLICATE_SAME_ACCESS)) + throw omni_thread_fatal(GetLastError()); + + nt_id = GetCurrentThreadId(); + + if (!TlsSetValue(self_tls_index, (LPVOID)this)) + throw omni_thread_fatal(GetLastError()); + } + inline ~omni_thread_dummy() + { + if (!TlsSetValue(self_tls_index, (LPVOID)0)) + throw omni_thread_fatal(GetLastError()); + } +}; + +omni_thread* +omni_thread::create_dummy() +{ + if (omni_thread::self()) + throw omni_thread_invalid(); + + return new omni_thread_dummy; +} + +void +omni_thread::release_dummy() +{ + omni_thread* self = omni_thread::self(); + if (!self || !self->_dummy) + throw omni_thread_invalid(); + + omni_thread_dummy* dummy = (omni_thread_dummy*)self; + delete dummy; +} + + +#if defined(__DMC__) && defined(_WINDLL) +BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + return TRUE; +} +#endif + + +#define INSIDE_THREAD_IMPL_CC +#include "threaddata.cc" +#undef INSIDE_THREAD_IMPL_CC diff --git a/gnuradio-core/src/lib/omnithread/omnithread.h b/gnuradio-core/src/lib/omnithread/omnithread.h new file mode 100644 index 0000000000..f63adc4fed --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/omnithread.h @@ -0,0 +1,622 @@ +// -*- Mode: C++; -*- +// Package : omnithread +// omnithread.h Created : 7/94 tjr +// +// Copyright (C) 2006 Free Software Foundation, Inc. +// Copyright (C) 1994,1995,1996, 1997 Olivetti & Oracle Research Laboratory +// +// This file is part of the omnithread library +// +// The omnithread 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 +// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA +// + +// +// Interface to OMNI thread abstraction. +// +// This file declares classes for threads and synchronisation objects +// (mutexes, condition variables and counting semaphores). +// +// Wherever a seemingly arbitrary choice has had to be made as to the interface +// provided, the intention here has been to be as POSIX-like as possible. This +// is why there is no semaphore timed wait, for example. +// + +#ifndef __omnithread_h_ +#define __omnithread_h_ + +#ifndef NULL +#define NULL 0 +#endif + +class omni_mutex; +class omni_condition; +class omni_semaphore; +class omni_thread; + +// +// OMNI_THREAD_EXPOSE can be defined as public or protected to expose the +// implementation class - this may be useful for debugging. Hopefully this +// won't change the underlying structure which the compiler generates so that +// this can work without recompiling the library. +// + +#ifndef OMNI_THREAD_EXPOSE +#define OMNI_THREAD_EXPOSE private +#endif + +// +// Include implementation-specific header file. +// +// This must define 4 CPP macros of the form OMNI_x_IMPLEMENTATION for mutex, +// condition variable, semaphore and thread. Each should define any +// implementation-specific members of the corresponding classes. +// + + +// +// For now, we assume they've always got a Posix Threads implementation. +// If not, it'll take some configure hacking to sort it out, along with +// the relevant libraries to link with, etc. +// + +#if !defined(OMNITHREAD_POSIX) && !defined(OMNITHREAD_NT) && defined HAVE_CONFIG_H +#include <config.h> +#endif + +#if defined(OMNITHREAD_POSIX) +#include <ot_posix.h> + +#elif defined(OMNITHREAD_NT) +#include <ot_nt.h> + +#ifdef _MSC_VER + +// Using MSVC++ to compile. If compiling library as a DLL, +// define _OMNITHREAD_DLL. If compiling as a statuc library, define +// _WINSTATIC +// If compiling an application that is to be statically linked to omnithread, +// define _WINSTATIC (if the application is to be dynamically linked, +// there is no need to define any of these macros). + +#if defined (_OMNITHREAD_DLL) && defined(_WINSTATIC) +#error "Both _OMNITHREAD_DLL and _WINSTATIC are defined." +#elif defined(_OMNITHREAD_DLL) +#define _OMNITHREAD_NTDLL_ __declspec(dllexport) +#elif !defined(_WINSTATIC) +#define _OMNITHREAD_NTDLL_ __declspec(dllimport) +#elif defined(_WINSTATIC) +#define _OMNITHREAD_NTDLL_ +#endif + // _OMNITHREAD_DLL && _WINSTATIC + +#else + +// Not using MSVC++ to compile +#define _OMNITHREAD_NTDLL_ + +#endif + // _MSC_VER + +#elif defined(__vxWorks__) +#include <ot_VxThread.h> + +#elif defined(__sunos__) +#if __OSVERSION__ != 5 +// XXX Workaround for SUN C++ compiler (seen on 4.2) Template.DB code +// regeneration bug. See omniORB2/CORBA_sysdep.h for details. +#if !defined(__SUNPRO_CC) || __OSVERSION__ != '5' +#error "Only SunOS 5.x or later is supported." +#endif +#endif +#ifdef UseSolarisThreads +#include <ot_solaris.h> +#else +#include <ot_posix.h> +#endif + +#elif defined(__rtems__) +#include <ot_posix.h> +#include <sched.h> + +#elif defined(__macos__) +#include <ot_posix.h> +#include <sched.h> + +#else +#error "No implementation header file" +#endif + + +#if !defined(__WIN32__) +#define _OMNITHREAD_NTDLL_ +#endif + +#if (!defined(OMNI_MUTEX_IMPLEMENTATION) || \ + !defined(OMNI_MUTEX_LOCK_IMPLEMENTATION) || \ + !defined(OMNI_MUTEX_TRYLOCK_IMPLEMENTATION)|| \ + !defined(OMNI_MUTEX_UNLOCK_IMPLEMENTATION) || \ + !defined(OMNI_CONDITION_IMPLEMENTATION) || \ + !defined(OMNI_SEMAPHORE_IMPLEMENTATION) || \ + !defined(OMNI_THREAD_IMPLEMENTATION)) +#error "Implementation header file incomplete" +#endif + + +// +// This exception is thrown in the event of a fatal error. +// + +class _OMNITHREAD_NTDLL_ omni_thread_fatal { +public: + int error; + omni_thread_fatal(int e = 0) : error(e) {} +}; + + +// +// This exception is thrown when an operation is invoked with invalid +// arguments. +// + +class _OMNITHREAD_NTDLL_ omni_thread_invalid {}; + + +/////////////////////////////////////////////////////////////////////////// +// +// Mutex +// +/////////////////////////////////////////////////////////////////////////// + +class _OMNITHREAD_NTDLL_ omni_mutex { + +public: + omni_mutex(void); + ~omni_mutex(void); + + inline void lock(void) { OMNI_MUTEX_LOCK_IMPLEMENTATION } + inline void unlock(void) { OMNI_MUTEX_UNLOCK_IMPLEMENTATION } + inline int trylock(void) { return OMNI_MUTEX_TRYLOCK_IMPLEMENTATION } + // if mutex is unlocked, lock it and return 1 (true). + // If it's already locked then return 0 (false). + + inline void acquire(void) { lock(); } + inline void release(void) { unlock(); } + // the names lock and unlock are preferred over acquire and release + // since we are attempting to be as POSIX-like as possible. + + friend class omni_condition; + +private: + // dummy copy constructor and operator= to prevent copying + omni_mutex(const omni_mutex&); + omni_mutex& operator=(const omni_mutex&); + +OMNI_THREAD_EXPOSE: + OMNI_MUTEX_IMPLEMENTATION +}; + +// +// As an alternative to: +// { +// mutex.lock(); +// ..... +// mutex.unlock(); +// } +// +// you can use a single instance of the omni_mutex_lock class: +// +// { +// omni_mutex_lock l(mutex); +// .... +// } +// +// This has the advantage that mutex.unlock() will be called automatically +// when an exception is thrown. +// + +class _OMNITHREAD_NTDLL_ omni_mutex_lock { + omni_mutex& mutex; +public: + omni_mutex_lock(omni_mutex& m) : mutex(m) { mutex.lock(); } + ~omni_mutex_lock(void) { mutex.unlock(); } +private: + // dummy copy constructor and operator= to prevent copying + omni_mutex_lock(const omni_mutex_lock&); + omni_mutex_lock& operator=(const omni_mutex_lock&); +}; + + +/////////////////////////////////////////////////////////////////////////// +// +// Condition variable +// +/////////////////////////////////////////////////////////////////////////// + +class _OMNITHREAD_NTDLL_ omni_condition { + + omni_mutex* mutex; + +public: + omni_condition(omni_mutex* m); + // constructor must be given a pointer to an existing mutex. The + // condition variable is then linked to the mutex, so that there is an + // implicit unlock and lock around wait() and timed_wait(). + + ~omni_condition(void); + + void wait(void); + // wait for the condition variable to be signalled. The mutex is + // implicitly released before waiting and locked again after waking up. + // If wait() is called by multiple threads, a signal may wake up more + // than one thread. See POSIX threads documentation for details. + + int timedwait(unsigned long secs, unsigned long nanosecs = 0); + // timedwait() is given an absolute time to wait until. To wait for a + // relative time from now, use omni_thread::get_time. See POSIX threads + // documentation for why absolute times are better than relative. + // Returns 1 (true) if successfully signalled, 0 (false) if time + // expired. + + void signal(void); + // if one or more threads have called wait(), signal wakes up at least + // one of them, possibly more. See POSIX threads documentation for + // details. + + void broadcast(void); + // broadcast is like signal but wakes all threads which have called + // wait(). + +private: + // dummy copy constructor and operator= to prevent copying + omni_condition(const omni_condition&); + omni_condition& operator=(const omni_condition&); + +OMNI_THREAD_EXPOSE: + OMNI_CONDITION_IMPLEMENTATION +}; + + +/////////////////////////////////////////////////////////////////////////// +// +// Counting (or binary) semaphore +// +/////////////////////////////////////////////////////////////////////////// + +class _OMNITHREAD_NTDLL_ omni_semaphore { + +public: + // if max_count == 1, you've got a binary semaphore. + omni_semaphore(unsigned int initial = 1, unsigned int max_count = 0x7fffffff); + ~omni_semaphore(void); + + void wait(void); + // if semaphore value is > 0 then decrement it and carry on. If it's + // already 0 then block. + + int trywait(void); + // if semaphore value is > 0 then decrement it and return 1 (true). + // If it's already 0 then return 0 (false). + + void post(void); + // if any threads are blocked in wait(), wake one of them up. Otherwise + // increment the value of the semaphore. + +private: + // dummy copy constructor and operator= to prevent copying + omni_semaphore(const omni_semaphore&); + omni_semaphore& operator=(const omni_semaphore&); + +OMNI_THREAD_EXPOSE: + OMNI_SEMAPHORE_IMPLEMENTATION +}; + +// +// A helper class for semaphores, similar to omni_mutex_lock above. +// + +class _OMNITHREAD_NTDLL_ omni_semaphore_lock { + omni_semaphore& sem; +public: + omni_semaphore_lock(omni_semaphore& s) : sem(s) { sem.wait(); } + ~omni_semaphore_lock(void) { sem.post(); } +private: + // dummy copy constructor and operator= to prevent copying + omni_semaphore_lock(const omni_semaphore_lock&); + omni_semaphore_lock& operator=(const omni_semaphore_lock&); +}; + + +/////////////////////////////////////////////////////////////////////////// +// +// Thread +// +/////////////////////////////////////////////////////////////////////////// + +class _OMNITHREAD_NTDLL_ omni_thread { + +public: + + enum priority_t { + PRIORITY_LOW, + PRIORITY_NORMAL, + PRIORITY_HIGH + }; + + enum state_t { + STATE_NEW, // thread object exists but thread hasn't + // started yet. + STATE_RUNNING, // thread is running. + STATE_TERMINATED // thread has terminated but storage has not + // been reclaimed (i.e. waiting to be joined). + }; + + // + // Constructors set up the thread object but the thread won't start until + // start() is called. The create method can be used to construct and start + // a thread in a single call. + // + + omni_thread(void (*fn)(void*), void* arg = NULL, + priority_t pri = PRIORITY_NORMAL); + omni_thread(void* (*fn)(void*), void* arg = NULL, + priority_t pri = PRIORITY_NORMAL); + // these constructors create a thread which will run the given function + // when start() is called. The thread will be detached if given a + // function with void return type, undetached if given a function + // returning void*. If a thread is detached, storage for the thread is + // reclaimed automatically on termination. Only an undetached thread + // can be joined. + + void start(void); + // start() causes a thread created with one of the constructors to + // start executing the appropriate function. + +protected: + + omni_thread(void* arg = NULL, priority_t pri = PRIORITY_NORMAL); + // this constructor is used in a derived class. The thread will + // execute the run() or run_undetached() member functions depending on + // whether start() or start_undetached() is called respectively. + + void start_undetached(void); + // can be used with the above constructor in a derived class to cause + // the thread to be undetached. In this case the thread executes the + // run_undetached member function. + + virtual ~omni_thread(void); + // destructor cannot be called by user (except via a derived class). + // Use exit() or cancel() instead. This also means a thread object must + // be allocated with new - it cannot be statically or automatically + // allocated. The destructor of a class that inherits from omni_thread + // shouldn't be public either (otherwise the thread object can be + // destroyed while the underlying thread is still running). + +public: + + void join(void**); + // join causes the calling thread to wait for another's completion, + // putting the return value in the variable of type void* whose address + // is given (unless passed a null pointer). Only undetached threads + // may be joined. Storage for the thread will be reclaimed. + + void set_priority(priority_t); + // set the priority of the thread. + + static omni_thread* create(void (*fn)(void*), void* arg = NULL, + priority_t pri = PRIORITY_NORMAL); + static omni_thread* create(void* (*fn)(void*), void* arg = NULL, + priority_t pri = PRIORITY_NORMAL); + // create spawns a new thread executing the given function with the + // given argument at the given priority. Returns a pointer to the + // thread object. It simply constructs a new thread object then calls + // start. + + static void exit(void* return_value = NULL); + // causes the calling thread to terminate. + + static omni_thread* self(void); + // returns the calling thread's omni_thread object. If the + // calling thread is not the main thread and is not created + // using this library, returns 0. (But see create_dummy() + // below.) + + static void yield(void); + // allows another thread to run. + + static void sleep(unsigned long secs, unsigned long nanosecs = 0); + // sleeps for the given time. + + static void get_time(unsigned long* abs_sec, unsigned long* abs_nsec, + unsigned long rel_sec = 0, unsigned long rel_nsec=0); + // calculates an absolute time in seconds and nanoseconds, suitable for + // use in timed_waits on condition variables, which is the current time + // plus the given relative offset. + + + static void stacksize(unsigned long sz); + static unsigned long stacksize(); + // Use this value as the stack size when spawning a new thread. + // The default value (0) means that the thread library default is + // to be used. + + + // Per-thread data + // + // These functions allow you to attach additional data to an + // omni_thread. First allocate a key for yourself with + // allocate_key(). Then you can store any object whose class is + // derived from value_t. Any values still stored in the + // omni_thread when the thread exits are deleted. + // + // These functions are NOT thread safe, so you should be very + // careful about setting/getting data in a different thread to the + // current thread. + + typedef unsigned int key_t; + static key_t allocate_key(); + + class value_t { + public: + virtual ~value_t() {} + }; + + value_t* set_value(key_t k, value_t* v); + // Sets a value associated with the given key. The key must + // have been allocated with allocate_key(). If a value has + // already been set with the specified key, the old value_t + // object is deleted and replaced. Returns the value which was + // set, or zero if the key is invalid. + + value_t* get_value(key_t k); + // Returns the value associated with the key. If the key is + // invalid, or there is no value for the key, returns zero. + + value_t* remove_value(key_t k); + // Removes the value associated with the key and returns it. + // If the key is invalid, or there is no value for the key, + // returns zero. + + + // Dummy omni_thread + // + // Sometimes, an application finds itself with threads created + // outside of omnithread which must interact with omnithread + // features such as the per-thread data. In this situation, + // omni_thread::self() would normally return 0. These functions + // allow the application to create a suitable dummy omni_thread + // object. + + static omni_thread* create_dummy(void); + // creates a dummy omni_thread for the calling thread. Future + // calls to self() will return the dummy omni_thread. Throws + // omni_thread_invalid if this thread already has an + // associated omni_thread (real or dummy). + + static void release_dummy(); + // release the dummy omni_thread for this thread. This + // function MUST be called before the thread exits. Throws + // omni_thread_invalid if the calling thread does not have a + // dummy omni_thread. + + // class ensure_self should be created on the stack. If created in + // a thread without an associated omni_thread, it creates a dummy + // thread which is released when the ensure_self object is deleted. + + class ensure_self { + public: + inline ensure_self() : _dummy(0) + { + _self = omni_thread::self(); + if (!_self) { + _dummy = 1; + _self = omni_thread::create_dummy(); + } + } + inline ~ensure_self() + { + if (_dummy) + omni_thread::release_dummy(); + } + inline omni_thread* self() { return _self; } + private: + omni_thread* _self; + int _dummy; + }; + + +private: + + virtual void run(void* /*arg*/) {} + virtual void* run_undetached(void* /*arg*/) { return NULL; } + // can be overridden in a derived class. When constructed using the + // the constructor omni_thread(void*, priority_t), these functions are + // called by start() and start_undetached() respectively. + + void common_constructor(void* arg, priority_t pri, int det); + // implements the common parts of the constructors. + + omni_mutex mutex; + // used to protect any members which can change after construction, + // i.e. the following 2 members. + + state_t _state; + priority_t _priority; + + static omni_mutex* next_id_mutex; + static int next_id; + int _id; + + void (*fn_void)(void*); + void* (*fn_ret)(void*); + void* thread_arg; + int detached; + int _dummy; + value_t** _values; + unsigned long _value_alloc; + + omni_thread(const omni_thread&); + omni_thread& operator=(const omni_thread&); + // Not implemented + +public: + + priority_t priority(void) { + + // return this thread's priority. + + omni_mutex_lock l(mutex); + return _priority; + } + + state_t state(void) { + + // return thread state (invalid, new, running or terminated). + + omni_mutex_lock l(mutex); + return _state; + } + + int id(void) { return _id; } + // return unique thread id within the current process. + + + // This class plus the instance of it declared below allows us to execute + // some initialisation code before main() is called. + + class _OMNITHREAD_NTDLL_ init_t { + public: + init_t(void); + ~init_t(void); + }; + + friend class init_t; + friend class omni_thread_dummy; + +OMNI_THREAD_EXPOSE: + OMNI_THREAD_IMPLEMENTATION +}; + +#ifndef __rtems__ +static omni_thread::init_t omni_thread_init; +#else +// RTEMS calls global Ctor/Dtor in a context that is not +// a posix thread. Calls to functions to pthread_self() in +// that context returns NULL. +// So, for RTEMS we will make the thread initialization at the +// beginning of the Init task that has a posix context. +#endif + +#endif diff --git a/gnuradio-core/src/lib/omnithread/ot_VxThread.h b/gnuradio-core/src/lib/omnithread/ot_VxThread.h new file mode 100644 index 0000000000..e96c036cce --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/ot_VxThread.h @@ -0,0 +1,118 @@ +#ifndef __VXTHREAD_H__ +#define __VXTHREAD_H__ +/* +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Project: omniORB +%% Filename: $Filename$ +%% Author: Guillaume/Bill ARRECKX +%% Copyright Wavetek Wandel & Goltermann, Plymouth. +%% Description: OMNI thread implementation classes for VxWorks threads +%% Notes: +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% $Log$ +%% Revision 1.1 2004/04/10 18:00:52 eb +%% Initial revision +%% +%% Revision 1.1.1.1 2004/03/01 00:20:27 eb +%% initial checkin +%% +%% Revision 1.1 2003/05/25 05:29:04 eb +%% see ChangeLog +%% +%% Revision 1.1.2.1 2003/02/17 02:03:07 dgrisby +%% vxWorks port. (Thanks Michael Sturm / Acterna Eningen GmbH). +%% +%% Revision 1.1.1.1 2002/11/19 14:55:21 sokcevti +%% OmniOrb4.0.0 VxWorks port +%% +%% Revision 1.2 2002/06/14 12:45:50 engeln +%% unnecessary members in condition removed. +%% --- +%% +%% Revision 1.1.1.1 2002/04/02 10:08:49 sokcevti +%% omniORB4 initial realease +%% +%% Revision 1.1 2001/03/23 16:50:23 hartmut +%% Initial Version 2.8 +%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +*/ + + +/////////////////////////////////////////////////////////////////////////// +// Includes +/////////////////////////////////////////////////////////////////////////// +#include <vxWorks.h> +#include <semLib.h> +#include <taskLib.h> + + +/////////////////////////////////////////////////////////////////////////// +// Externs prototypes +/////////////////////////////////////////////////////////////////////////// +extern "C" void omni_thread_wrapper(void* ptr); + + +/////////////////////////////////////////////////////////////////////////// +// Exported macros +// Note: These are added as private members in each class implementation. +/////////////////////////////////////////////////////////////////////////// +#define OMNI_MUTEX_IMPLEMENTATION \ + SEM_ID mutexID; \ + bool m_bConstructed; + +#define OMNI_CONDITION_IMPLEMENTATION \ + long waiters_; \ + SEM_ID waiters_lock_; \ + SEM_ID sema_; + +#define OMNI_SEMAPHORE_IMPLEMENTATION \ + SEM_ID semID; + +#define OMNI_MUTEX_LOCK_IMPLEMENTATION \ + if(semTake(mutexID, WAIT_FOREVER) != OK) \ + { \ + throw omni_thread_fatal(errno); \ + } + +#define OMNI_MUTEX_UNLOCK_IMPLEMENTATION \ + if(semGive(mutexID) != OK) \ + { \ + throw omni_thread_fatal(errno); \ + } + +#define OMNI_THREAD_IMPLEMENTATION \ + friend void omni_thread_wrapper(void* ptr); \ + static int vxworks_priority(priority_t); \ + omni_condition *running_cond; \ + void* return_val; \ + int tid; \ + public: \ + static void attach(void); \ + static void detach(void); \ + static void show(void); + + +/////////////////////////////////////////////////////////////////////////// +// Porting macros +/////////////////////////////////////////////////////////////////////////// +// This is a wrapper function for the 'main' function which does not exists +// as such in VxWorks. The wrapper creates a launch function instead, +// which spawns the application wrapped in a omni_thread. +// Argc will always be null. +/////////////////////////////////////////////////////////////////////////// +#define main( discarded_argc, discarded_argv ) \ + omni_discard_retval() \ + { \ + throw; \ + } \ + int omni_main( int argc, char **argv ); \ + void launch( ) \ + { \ + omni_thread* th = new omni_thread( (void(*)(void*))omni_main );\ + th->start();\ + }\ + int omni_main( int argc, char **argv ) + + +#endif // ndef __VXTHREAD_H__ diff --git a/gnuradio-core/src/lib/omnithread/ot_mach.h b/gnuradio-core/src/lib/omnithread/ot_mach.h new file mode 100644 index 0000000000..483f600fe9 --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/ot_mach.h @@ -0,0 +1,51 @@ +// Package : omnithread +// omnithread/posix.h Created : 7/97 lars immisch lars@ibp.de +// +// Copyright (C) 1994,1995,1996, 1997 Immisch, becker & Partner +// +// This file is part of the omnithread library +// +// The omnithread 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 +// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA +// +// +// OMNI thread implementation classes for posix threads +// + +#ifndef __omnithread_mach_h_ +#define __omnithread_mach_h_ + +#include <mach/cthreads.h> + +extern "C" void* omni_thread_wrapper(void* ptr); + +#define OMNI_MUTEX_IMPLEMENTATION \ + struct mutex mach_mutex; + +#define OMNI_CONDITION_IMPLEMENTATION \ + struct condition mach_cond; + +#define OMNI_SEMAPHORE_IMPLEMENTATION \ + omni_mutex m; \ + omni_condition c; \ + int value; + + +#define OMNI_THREAD_IMPLEMENTATION \ + cthread_t mach_thread; \ + static int mach_priority(priority_t); \ + friend void* omni_thread_wrapper(void* ptr); + +#endif diff --git a/gnuradio-core/src/lib/omnithread/ot_nt.h b/gnuradio-core/src/lib/omnithread/ot_nt.h new file mode 100644 index 0000000000..3ed173f29b --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/ot_nt.h @@ -0,0 +1,85 @@ +// Package : omnithread +// omnithread/nt.h Created : 6/95 tjr +// +// Copyright (C) 1995, 1996, 1997 Olivetti & Oracle Research Laboratory +// +// This file is part of the omnithread library +// +// The omnithread 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 +// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA +// +// +// OMNI thread implementation classes for NT threads. +// + +#ifndef __omnithread_nt_h_ +#define __omnithread_nt_h_ + +#ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# define OMNI_DEFINED_WIN32_LEAN_AND_MEAN +#endif + +#include <windows.h> + +#ifdef OMNI_DEFINED_WIN32_LEAN_AND_MEAN +# undef WIN32_LEAN_AND_MEAN +# undef OMNI_DEFINED_WIN32_LEAN_AND_MEAN +#endif + + +#ifndef __BCPLUSPLUS__ +#define OMNI_THREAD_WRAPPER \ + unsigned __stdcall omni_thread_wrapper(LPVOID ptr); +#else +#define OMNI_THREAD_WRAPPER \ + void _USERENTRY omni_thread_wrapper(void *ptr); +#endif + +extern "C" OMNI_THREAD_WRAPPER; + +#define OMNI_MUTEX_IMPLEMENTATION \ + CRITICAL_SECTION crit; + +#define OMNI_MUTEX_LOCK_IMPLEMENTATION \ + EnterCriticalSection(&crit); + +#define OMNI_MUTEX_TRYLOCK_IMPLEMENTATION \ + TryEnterCriticalSection(&crit); + +#define OMNI_MUTEX_UNLOCK_IMPLEMENTATION \ + LeaveCriticalSection(&crit); + +#define OMNI_CONDITION_IMPLEMENTATION \ + CRITICAL_SECTION crit; \ + omni_thread* waiting_head; \ + omni_thread* waiting_tail; + +#define OMNI_SEMAPHORE_IMPLEMENTATION \ + HANDLE nt_sem; + +#define OMNI_THREAD_IMPLEMENTATION \ + HANDLE handle; \ + DWORD nt_id; \ + void* return_val; \ + HANDLE cond_semaphore; \ + omni_thread* cond_next; \ + omni_thread* cond_prev; \ + BOOL cond_waiting; \ + static int nt_priority(priority_t); \ + friend class omni_condition; \ + friend OMNI_THREAD_WRAPPER; + +#endif diff --git a/gnuradio-core/src/lib/omnithread/ot_posix.h b/gnuradio-core/src/lib/omnithread/ot_posix.h new file mode 100644 index 0000000000..1e5bf9d294 --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/ot_posix.h @@ -0,0 +1,81 @@ +// Package : omnithread +// omnithread/posix.h Created : 7/94 tjr +// +// Copyright (C) 2006 Free Software Foundation, Inc. +// Copyright (C) 1994,1995,1996, 1997 Olivetti & Oracle Research Laboratory +// +// This file is part of the omnithread library +// +// The omnithread 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 +// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA +// +// +// OMNI thread implementation classes for posix threads +// + +#ifndef __omnithread_posix_h_ +#define __omnithread_posix_h_ + +#if defined(__alpha__) && defined(__osf1__) || defined(__hpux__) +// stop unnecessary definitions of TRY, etc on OSF +#ifndef EXC_HANDLING +#define EXC_HANDLING +#endif +#endif + +#ifndef __POSIX_NT__ +# include <pthread.h> +#else +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# define OMNI_DEFINED_WIN32_LEAN_AND_MEAN +# endif +# include <windows.h> +# include "pthread_nt.h" +# ifdef OMNI_DEFINED_WIN32_LEAN_AND_MEAN +# undef WIN32_LEAN_AND_MEAN +# undef OMNI_DEFINED_WIN32_LEAN_AND_MEAN +# endif +#endif + +extern "C" void* omni_thread_wrapper(void* ptr); + +#define OMNI_MUTEX_IMPLEMENTATION \ + pthread_mutex_t posix_mutex; + +#define OMNI_MUTEX_LOCK_IMPLEMENTATION \ + pthread_mutex_lock(&posix_mutex); + +#define OMNI_MUTEX_TRYLOCK_IMPLEMENTATION \ + (pthread_mutex_trylock(&posix_mutex)==0); + +#define OMNI_MUTEX_UNLOCK_IMPLEMENTATION \ + pthread_mutex_unlock(&posix_mutex); + +#define OMNI_CONDITION_IMPLEMENTATION \ + pthread_cond_t posix_cond; + +#define OMNI_SEMAPHORE_IMPLEMENTATION \ + omni_mutex m; \ + omni_condition c; \ + int value; \ + int max_count; + +#define OMNI_THREAD_IMPLEMENTATION \ + pthread_t posix_thread; \ + static int posix_priority(priority_t); \ + friend void* omni_thread_wrapper(void* ptr); + +#endif diff --git a/gnuradio-core/src/lib/omnithread/ot_pthread_nt.h b/gnuradio-core/src/lib/omnithread/ot_pthread_nt.h new file mode 100644 index 0000000000..cf3d879427 --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/ot_pthread_nt.h @@ -0,0 +1,186 @@ +/* Package : omnithread + omnithread/pthread_nt.h Created : Steven Brenneis <brennes1@rjrt.com> + + Copyright (C) 1998 Steven Brennes + + This file is part of the omnithread library + + The omnithread 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 + Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA + + Posix Threads implementation for Windows NT, version 4.0 +*/ + +#ifndef PTHREAD_NT_H_INCLUDED +#define PTHREAD_NT_H_INCLUDED + +#include <errno.h> + +#ifndef ETIMEDOUT +// May have to be changed if NT starts supporting more errno values +#define ETIMEDOUT 60 +#endif + +#undef PthreadDraftVersion +#define PthreadDraftVersion 10 + +#define NoNanoSleep + +#define PthreadSupportThreadPriority + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _TIMERS_T_ +#define _TIMERS_T_ + typedef struct timespec { + unsigned long tv_sec; + long tv_nsec; + } timespec_t; +#endif + +typedef char* __pthreadLongString_t; +typedef void* __pthreadLongAddr_t; +typedef __pthreadLongAddr_t* __pthreadLongAddr_p; +typedef long __pthreadLongInt_t; +typedef unsigned long __pthreadLongUint_t; +typedef __pthreadLongAddr_p __pthreadTsd_t; + +typedef struct __pthread_mutex_t { + unsigned int lock; /* LOCK, SLOW, TYPE, RECURSIVE */ + unsigned int valid; /* Validation info */ + __pthreadLongString_t name; /* Name of mutex */ + unsigned int arg; /* printf argument for name */ + unsigned int depth; /* Recursive lock depth */ + unsigned long sequence; /* Mutex sequence number */ + unsigned long owner; /* Current owner (if known */ + __pthreadLongAddr_t block; /* Pointer to blocking struct */ +} pthread_mutex_t; + +typedef struct __pthread_mutexattr_t { + long valid; + __pthreadLongUint_t reserved[15]; +} pthread_mutexattr_t; + +typedef struct __pthread_cond_t { + unsigned int state; /* EVENT, SLOW, REFCNT */ + unsigned int valid; /* Validation info */ + __pthreadLongString_t name; /* Name of condition variable */ + unsigned int arg; /* printf argument for name */ + unsigned long sequence; /* Condition variable seq # */ + __pthreadLongAddr_t block; /* Pointer to blocking struct */ +} pthread_cond_t ; + +typedef struct __pthread_condattr_t { + long valid; + __pthreadLongUint_t reserved[13]; +} pthread_condattr_t ; + +typedef struct __pthread_transp_t { + __pthreadLongAddr_t reserved1; /* Reserved to posix_nt */ + __pthreadLongAddr_t reserved2; /* Reserved to posix_nt */ + unsigned short size; /* Size of data structure */ + unsigned char reserved3[2]; /* Reserved to posix_nt */ + __pthreadLongAddr_t reserved4; /* Reserved to posix_nt */ + __pthreadLongUint_t sequence; /* Thread sequence number */ + __pthreadLongUint_t reserved5[2]; /* Reserved to posix_nt */ + __pthreadLongAddr_t per_kt_area; /* Pointer to kernel context */ + __pthreadLongAddr_t stack_base; /* Current stack base */ + __pthreadLongAddr_t stack_reserve; /* Current stack reserve zone */ + __pthreadLongAddr_t stack_yellow; /* Current stack yellow zone */ + __pthreadLongAddr_t stack_guard; /* Current stack guard zone */ + __pthreadLongUint_t stack_size; /* Size of stack */ + __pthreadTsd_t tsd_values; /* TSD array (indexed by key) */ + unsigned long tsd_count; /* Number of TSD cells */ + __pthreadLongAddr_t reserved6; /* Reserved to posix_nt */ + __pthreadLongAddr_t reserved7; /* Reserved to posix_nt */ + unsigned int thread_flags; /* Dynamic external state */ +} pthread_transp_t, *pthread_transp_p; + +typedef pthread_transp_p pthread_t; + +typedef struct __pthread_attr_t { + long valid; + __pthreadLongString_t name; + __pthreadLongUint_t arg; + __pthreadLongUint_t reserved[19]; +} pthread_attr_t ; + +typedef unsigned int pthread_key_t; + +typedef struct sched_param { + int sched_priority; +} sched_param_t; + +/* Function Prototypes */ + +int pthread_create(pthread_t *thread, const pthread_attr_t *attr, + void *(*start_routine)(void*), void *arg); +int pthread_detach(pthread_t thread); +int pthread_join(pthread_t thread, void **value_ptr); +void pthread_exit(void *value_ptr); +int pthread_attr_init(pthread_attr_t *attr); +int pthread_attr_destroy(pthread_attr_t *attr); +int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize); +int pthread_attr_getstacksize(const pthread_attr_t *attr, + size_t *stacksize); +int pthread_cond_init(pthread_cond_t *cond, + const pthread_condattr_t *attr); +int pthread_cond_destroy(pthread_cond_t *cond); +int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex); +int pthread_cond_timedwait(pthread_cond_t *cond, + pthread_mutex_t *mutex, + const struct timespec *abstime); +int pthread_cond_signal(pthread_cond_t *cond); +int pthread_cond_broadcast(pthread_cond_t *cond); +int pthread_key_create(pthread_key_t *key, void (*destructor)(void*)); +int pthread_key_delete(pthread_key_t key); +int pthread_mutex_destroy(pthread_mutex_t *mutex); +int pthread_mutex_init(pthread_mutex_t *mutex, + const pthread_mutexattr_t *attr); +int pthread_mutex_lock(pthread_mutex_t *mutex); +int pthread_mutex_trylock(pthread_mutex_t *mutex); +int pthread_mutex_unlock(pthread_mutex_t *mutex); +pthread_t pthread_self(); +int pthread_setspecific(pthread_key_t key, const void *value); +void *pthread_getspecific(pthread_key_t key); +int pthread_getschedparam(pthread_t thread, int *policy, + struct sched_param *param); +int pthread_setschedparam(pthread_t thread, int policy, + const struct sched_param *param); +int pthread_attr_setschedparam(pthread_attr_t *attr, + const struct sched_param *param); +int pthread_attr_getschedparam(const pthread_attr_t *attr, + struct sched_param *param); + +int pthread_delay_np(const struct timespec *interval); +int pthread_get_expiration_np(const struct timespec *delta, + struct timespec *abstime); + +# define SCHED_FIFO 1 +# define SCHED_RR 2 +# define SCHED_OTHER 3 + +int sched_yield(); +int sched_get_priority_max(int policy); +int sched_get_priority_min(int policy); + + +#ifdef __cplusplus +} +#endif + +#endif // PTHREAD_NT_H_INCLUDED diff --git a/gnuradio-core/src/lib/omnithread/ot_solaris.h b/gnuradio-core/src/lib/omnithread/ot_solaris.h new file mode 100644 index 0000000000..aaef036f18 --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/ot_solaris.h @@ -0,0 +1,47 @@ +// Package : omnithread +// omnithread/solaris.h Created : 7/94 tjr +// +// Copyright (C) 1994,1995,1996, 1997 Olivetti & Oracle Research Laboratory +// +// This file is part of the omnithread library +// +// The omnithread 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 +// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA +// +// OMNI thread implementation classes for solaris threads. +// + +#ifndef __omnithread_solaris_h_ +#define __omnithread_solaris_h_ + +#include <thread.h> + +extern "C" void* omni_thread_wrapper(void* ptr); + +#define OMNI_MUTEX_IMPLEMENTATION \ + mutex_t sol_mutex; + +#define OMNI_CONDITION_IMPLEMENTATION \ + cond_t sol_cond; + +#define OMNI_SEMAPHORE_IMPLEMENTATION \ + sema_t sol_sem; + +#define OMNI_THREAD_IMPLEMENTATION \ + thread_t sol_thread; \ + static int sol_priority(priority_t); \ + friend void* omni_thread_wrapper(void* ptr); + +#endif diff --git a/gnuradio-core/src/lib/omnithread/posix.cc b/gnuradio-core/src/lib/omnithread/posix.cc new file mode 100644 index 0000000000..5fda14fcba --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/posix.cc @@ -0,0 +1,972 @@ +// Package : omnithread +// omnithread/posix.cc Created : 7/94 tjr +// +// Copyright (C) 2006 Free Software Foundation, Inc. +// Copyright (C) 1994-1999 AT&T Laboratories Cambridge +// +// This file is part of the omnithread library +// +// The omnithread 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 +// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA +// + +// +// Implementation of OMNI thread abstraction for posix threads +// +// The source below tests for the definition of the macros: +// PthreadDraftVersion +// PthreadSupportThreadPriority +// NoNanoSleep +// NeedPthreadInit +// +// As different draft versions of the pthread standard P1003.4a/P1003.1c +// define slightly different APIs, the macro 'PthreadDraftVersion' +// identifies the draft version supported by this particular platform. +// +// Some unix variants do not support thread priority unless a real-time +// kernel option is installed. The macro 'PthreadSupportThreadPriority', +// if defined, enables the use of thread priority. If it is not defined, +// setting or changing thread priority will be silently ignored. +// +// nanosleep() is defined in Posix P1003.4 since Draft 9 (?). +// Not all platforms support this standard. The macro 'NoNanoSleep' +// identifies platform that don't. +// + +#include <config.h> +#include <stdlib.h> +#include <errno.h> +#include <time.h> +#include <omnithread.h> + +#ifdef HAVE_NANOSLEEP +#undef NoNanoSleep +#else +#define NoNanoSleep +#endif + +#ifdef HAVE_SYS_TIME_H +// typedef of struct timeval and gettimeofday(); +#include <sys/time.h> +#include <unistd.h> +#endif + +#if defined(__linux__) && defined(_MIT_POSIX_THREADS) +#include <pthread/mit/sys/timers.h> +#endif + +#if defined(__irix__) && defined(PthreadSupportThreadPriority) +#if _POSIX_THREAD_PRIORITY_SCHEDULING +#include <sched.h> +#endif +#endif + +#define DB(x) // x +//#include <iostream.h> or #include <iostream> if DB is on. + +#if (PthreadDraftVersion <= 6) +#define ERRNO(x) (((x) != 0) ? (errno) : 0) +#ifdef __VMS +// pthread_setprio returns old priority on success (draft version 4: +// OpenVms version < 7) +#define THROW_ERRORS(x) { if ((x) == -1) throw omni_thread_fatal(errno); } +#else +#define THROW_ERRORS(x) { if ((x) != 0) throw omni_thread_fatal(errno); } +#endif +#else +#define ERRNO(x) (x) +#define THROW_ERRORS(x) { int rc = (x); \ + if (rc != 0) throw omni_thread_fatal(rc); } +#endif + + + +/////////////////////////////////////////////////////////////////////////// +// +// Mutex +// +/////////////////////////////////////////////////////////////////////////// + + +omni_mutex::omni_mutex(void) +{ +#if (PthreadDraftVersion == 4) + THROW_ERRORS(pthread_mutex_init(&posix_mutex, pthread_mutexattr_default)); +#else + THROW_ERRORS(pthread_mutex_init(&posix_mutex, 0)); +#endif +} + +omni_mutex::~omni_mutex(void) +{ + THROW_ERRORS(pthread_mutex_destroy(&posix_mutex)); +} + + +/////////////////////////////////////////////////////////////////////////// +// +// Condition variable +// +/////////////////////////////////////////////////////////////////////////// + + +omni_condition::omni_condition(omni_mutex* m) : mutex(m) +{ +#if (PthreadDraftVersion == 4) + THROW_ERRORS(pthread_cond_init(&posix_cond, pthread_condattr_default)); +#else + THROW_ERRORS(pthread_cond_init(&posix_cond, 0)); +#endif +} + +omni_condition::~omni_condition(void) +{ + THROW_ERRORS(pthread_cond_destroy(&posix_cond)); +} + +void +omni_condition::wait(void) +{ + THROW_ERRORS(pthread_cond_wait(&posix_cond, &mutex->posix_mutex)); +} + +int +omni_condition::timedwait(unsigned long secs, unsigned long nanosecs) +{ + timespec rqts = { secs, nanosecs }; + +again: + int rc = ERRNO(pthread_cond_timedwait(&posix_cond, + &mutex->posix_mutex, &rqts)); + if (rc == 0) + return 1; + +#if (PthreadDraftVersion <= 6) + if (rc == EAGAIN) + return 0; +#endif + + // Some versions of unix produces this errno when the wait was + // interrupted by a unix signal or fork. + // Some versions of the glibc 2.0.x produces this errno when the + // program is debugged under gdb. Straightly speaking this is non-posix + // compliant. We catch this here to make debugging possible. + if (rc == EINTR) + goto again; + + if (rc == ETIMEDOUT) + return 0; + + throw omni_thread_fatal(rc); +#ifdef _MSC_VER + return 0; +#endif +} + +void +omni_condition::signal(void) +{ + THROW_ERRORS(pthread_cond_signal(&posix_cond)); +} + +void +omni_condition::broadcast(void) +{ + THROW_ERRORS(pthread_cond_broadcast(&posix_cond)); +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Counting (or binary) semaphore +// +/////////////////////////////////////////////////////////////////////////// + + +omni_semaphore::omni_semaphore(unsigned int initial, unsigned int _max_count) : c(&m) +{ + value = initial; + max_count = _max_count; + if (value < 0 || max_count < 1) + throw omni_thread_fatal(0); +} + +omni_semaphore::~omni_semaphore(void) +{ +} + +void +omni_semaphore::wait(void) +{ + omni_mutex_lock l(m); + + while (value == 0) + c.wait(); + + value--; +} + +int +omni_semaphore::trywait(void) +{ + omni_mutex_lock l(m); + + if (value == 0) + return 0; + + value--; + return 1; +} + +void +omni_semaphore::post(void) +{ + { + omni_mutex_lock l(m); + if (value < max_count) + value++; + } + + c.signal(); +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Thread +// +/////////////////////////////////////////////////////////////////////////// + + +// +// static variables +// + +omni_mutex* omni_thread::next_id_mutex; +int omni_thread::next_id = 0; + +static pthread_key_t self_key; + +#ifdef PthreadSupportThreadPriority +static int lowest_priority; +static int normal_priority; +static int highest_priority; +#endif + +#if defined(__osf1__) && defined(__alpha__) || defined(__VMS) +// omniORB requires a larger stack size than the default (21120) on OSF/1 +static size_t stack_size = 32768; +#elif defined(__rtems__) +static size_t stack_size = ThreadStackSize; +#elif defined(__aix__) +static size_t stack_size = 262144; +#else +static size_t stack_size = 0; +#endif + +// +// Initialisation function (gets called before any user code). +// + +static int& count() { + static int the_count = 0; + return the_count; +} + +omni_thread::init_t::init_t(void) +{ + if (count()++ != 0) // only do it once however many objects get created. + return; + + DB(cerr << "omni_thread::init: posix 1003.4a/1003.1c (draft " + << PthreadDraftVersion << ") implementation initialising\n"); + +#ifdef NeedPthreadInit + + pthread_init(); + +#endif + +#if (PthreadDraftVersion == 4) + THROW_ERRORS(pthread_keycreate(&self_key, NULL)); +#else + THROW_ERRORS(pthread_key_create(&self_key, NULL)); +#endif + +#ifdef PthreadSupportThreadPriority + +#if defined(__osf1__) && defined(__alpha__) || defined(__VMS) + + lowest_priority = PRI_OTHER_MIN; + highest_priority = PRI_OTHER_MAX; + +#elif defined(__hpux__) + + lowest_priority = PRI_OTHER_MIN; + highest_priority = PRI_OTHER_MAX; + +#elif defined(__sunos__) && (__OSVERSION__ == 5) + + // a bug in pthread_attr_setschedparam means lowest priority is 1 not 0 + + lowest_priority = 1; + highest_priority = 3; + +#else + + lowest_priority = sched_get_priority_min(SCHED_FIFO); + highest_priority = sched_get_priority_max(SCHED_FIFO); + +#endif + + switch (highest_priority - lowest_priority) { + + case 0: + case 1: + normal_priority = lowest_priority; + break; + + default: + normal_priority = lowest_priority + 1; + break; + } + +#endif /* PthreadSupportThreadPriority */ + + next_id_mutex = new omni_mutex; + + // + // Create object for this (i.e. initial) thread. + // + + omni_thread* t = new omni_thread; + + t->_state = STATE_RUNNING; + + t->posix_thread = pthread_self (); + + DB(cerr << "initial thread " << t->id() << endl); + + THROW_ERRORS(pthread_setspecific(self_key, (void*)t)); + +#ifdef PthreadSupportThreadPriority + +#if (PthreadDraftVersion == 4) + + THROW_ERRORS(pthread_setprio(t->posix_thread, + posix_priority(PRIORITY_NORMAL))); + +#elif (PthreadDraftVersion == 6) + + pthread_attr_t attr; + pthread_attr_init(&attr); + + THROW_ERRORS(pthread_attr_setprio(&attr, posix_priority(PRIORITY_NORMAL))); + + THROW_ERRORS(pthread_setschedattr(t->posix_thread, attr)); + +#else + + struct sched_param sparam; + + sparam.sched_priority = posix_priority(PRIORITY_NORMAL); + + THROW_ERRORS(pthread_setschedparam(t->posix_thread, SCHED_OTHER, &sparam)); + +#endif /* PthreadDraftVersion */ + +#endif /* PthreadSupportThreadPriority */ +} + +omni_thread::init_t::~init_t(void) +{ + if (--count() != 0) return; + + omni_thread* self = omni_thread::self(); + if (!self) return; + + pthread_setspecific(self_key, 0); + delete self; + + delete next_id_mutex; +} + +// +// Wrapper for thread creation. +// + +extern "C" void* +omni_thread_wrapper(void* ptr) +{ + omni_thread* me = (omni_thread*)ptr; + + DB(cerr << "omni_thread_wrapper: thread " << me->id() + << " started\n"); + + THROW_ERRORS(pthread_setspecific(self_key, me)); + + // + // Now invoke the thread function with the given argument. + // + + if (me->fn_void != NULL) { + (*me->fn_void)(me->thread_arg); + omni_thread::exit(); + } + + if (me->fn_ret != NULL) { + void* return_value = (*me->fn_ret)(me->thread_arg); + omni_thread::exit(return_value); + } + + if (me->detached) { + me->run(me->thread_arg); + omni_thread::exit(); + } else { + void* return_value = me->run_undetached(me->thread_arg); + omni_thread::exit(return_value); + } + + // should never get here. + + return NULL; +} + + +// +// Constructors for omni_thread - set up the thread object but don't +// start it running. +// + +// construct a detached thread running a given function. + +omni_thread::omni_thread(void (*fn)(void*), void* arg, priority_t pri) +{ + common_constructor(arg, pri, 1); + fn_void = fn; + fn_ret = NULL; +} + +// construct an undetached thread running a given function. + +omni_thread::omni_thread(void* (*fn)(void*), void* arg, priority_t pri) +{ + common_constructor(arg, pri, 0); + fn_void = NULL; + fn_ret = fn; +} + +// construct a thread which will run either run() or run_undetached(). + +omni_thread::omni_thread(void* arg, priority_t pri) +{ + common_constructor(arg, pri, 1); + fn_void = NULL; + fn_ret = NULL; +} + +// common part of all constructors. + +void +omni_thread::common_constructor(void* arg, priority_t pri, int det) +{ + _state = STATE_NEW; + _priority = pri; + + next_id_mutex->lock(); + _id = next_id++; + next_id_mutex->unlock(); + + thread_arg = arg; + detached = det; // may be altered in start_undetached() + + _dummy = 0; + _values = 0; + _value_alloc = 0; + // posix_thread is set up in initialisation routine or start(). +} + + +// +// Destructor for omni_thread. +// + +omni_thread::~omni_thread(void) +{ + DB(cerr << "destructor called for thread " << id() << endl); + if (_values) { + for (key_t i=0; i < _value_alloc; i++) { + if (_values[i]) { + delete _values[i]; + } + } + delete [] _values; + } +} + + +// +// Start the thread +// + +void +omni_thread::start(void) +{ + omni_mutex_lock l(mutex); + + if (_state != STATE_NEW) + throw omni_thread_invalid(); + + pthread_attr_t attr; + +#if (PthreadDraftVersion == 4) + pthread_attr_create(&attr); +#else + pthread_attr_init(&attr); +#endif + +#if (PthreadDraftVersion == 8) + pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_UNDETACHED); +#endif + +#ifdef PthreadSupportThreadPriority + +#if (PthreadDraftVersion <= 6) + + THROW_ERRORS(pthread_attr_setprio(&attr, posix_priority(_priority))); + +#else + + struct sched_param sparam; + + sparam.sched_priority = posix_priority(_priority); + + THROW_ERRORS(pthread_attr_setschedparam(&attr, &sparam)); + +#endif /* PthreadDraftVersion */ + +#endif /* PthreadSupportThreadPriority */ + +#if !defined(__linux__) + if (stack_size) { + THROW_ERRORS(pthread_attr_setstacksize(&attr, stack_size)); + } +#endif + + +#if (PthreadDraftVersion == 4) + THROW_ERRORS(pthread_create(&posix_thread, attr, omni_thread_wrapper, + (void*)this)); + pthread_attr_delete(&attr); +#else + THROW_ERRORS(pthread_create(&posix_thread, &attr, omni_thread_wrapper, + (void*)this)); + pthread_attr_destroy(&attr); +#endif + + _state = STATE_RUNNING; + + if (detached) { + +#if (PthreadDraftVersion <= 6) + THROW_ERRORS(pthread_detach(&posix_thread)); +#else + THROW_ERRORS(pthread_detach(posix_thread)); +#endif + } +} + + +// +// Start a thread which will run the member function run_undetached(). +// + +void +omni_thread::start_undetached(void) +{ + if ((fn_void != NULL) || (fn_ret != NULL)) + throw omni_thread_invalid(); + + detached = 0; + start(); +} + + +// +// join - simply check error conditions & call pthread_join. +// + +void +omni_thread::join(void** status) +{ + mutex.lock(); + + if ((_state != STATE_RUNNING) && (_state != STATE_TERMINATED)) { + mutex.unlock(); + throw omni_thread_invalid(); + } + + mutex.unlock(); + + if (this == self()) + throw omni_thread_invalid(); + + if (detached) + throw omni_thread_invalid(); + + DB(cerr << "omni_thread::join: doing pthread_join\n"); + + THROW_ERRORS(pthread_join(posix_thread, status)); + + DB(cerr << "omni_thread::join: pthread_join succeeded\n"); + +#if (PthreadDraftVersion == 4) + // With draft 4 pthreads implementations (HPUX 10.x and + // Digital Unix 3.2), have to detach the thread after + // join. If not, the storage for the thread will not be + // be reclaimed. + THROW_ERRORS(pthread_detach(&posix_thread)); +#endif + + delete this; +} + + +// +// Change this thread's priority. +// + +void +omni_thread::set_priority(priority_t pri) +{ + omni_mutex_lock l(mutex); + + if (_state != STATE_RUNNING) + throw omni_thread_invalid(); + + _priority = pri; + +#ifdef PthreadSupportThreadPriority + +#if (PthreadDraftVersion == 4) + + THROW_ERRORS(pthread_setprio(posix_thread, posix_priority(pri))); + +#elif (PthreadDraftVersion == 6) + + pthread_attr_t attr; + pthread_attr_init(&attr); + + THROW_ERRORS(pthread_attr_setprio(&attr, posix_priority(pri))); + + THROW_ERRORS(pthread_setschedattr(posix_thread, attr)); + +#else + + struct sched_param sparam; + + sparam.sched_priority = posix_priority(pri); + + THROW_ERRORS(pthread_setschedparam(posix_thread, SCHED_OTHER, &sparam)); + +#endif /* PthreadDraftVersion */ + +#endif /* PthreadSupportThreadPriority */ +} + + +// +// create - construct a new thread object and start it running. Returns thread +// object if successful, null pointer if not. +// + +// detached version + +omni_thread* +omni_thread::create(void (*fn)(void*), void* arg, priority_t pri) +{ + omni_thread* t = new omni_thread(fn, arg, pri); + + t->start(); + + return t; +} + +// undetached version + +omni_thread* +omni_thread::create(void* (*fn)(void*), void* arg, priority_t pri) +{ + omni_thread* t = new omni_thread(fn, arg, pri); + + t->start(); + + return t; +} + + +// +// exit() _must_ lock the mutex even in the case of a detached thread. This is +// because a thread may run to completion before the thread that created it has +// had a chance to get out of start(). By locking the mutex we ensure that the +// creating thread must have reached the end of start() before we delete the +// thread object. Of course, once the call to start() returns, the user can +// still incorrectly refer to the thread object, but that's their problem. +// + +void +omni_thread::exit(void* return_value) +{ + omni_thread* me = self(); + + if (me) + { + me->mutex.lock(); + + me->_state = STATE_TERMINATED; + + me->mutex.unlock(); + + DB(cerr << "omni_thread::exit: thread " << me->id() << " detached " + << me->detached << " return value " << return_value << endl); + + if (me->detached) + delete me; + } + else + { + DB(cerr << "omni_thread::exit: called with a non-omnithread. Exit quietly." << endl); + } + + pthread_exit(return_value); +} + + +omni_thread* +omni_thread::self(void) +{ + omni_thread* me; + +#if (PthreadDraftVersion <= 6) + + THROW_ERRORS(pthread_getspecific(self_key, (void**)&me)); + +#else + + me = (omni_thread *)pthread_getspecific(self_key); + +#endif + + if (!me) { + // This thread is not created by omni_thread::start because it + // doesn't has a class omni_thread instance attached to its key. + DB(cerr << "omni_thread::self: called with a non-omnithread. NULL is returned." << endl); + } + + return me; +} + + +void +omni_thread::yield(void) +{ +#if (PthreadDraftVersion == 6) + + pthread_yield(NULL); + +#elif (PthreadDraftVersion < 9) + + pthread_yield(); + +#else + + THROW_ERRORS(sched_yield()); + +#endif +} + + +void +omni_thread::sleep(unsigned long secs, unsigned long nanosecs) +{ + timespec rqts = { secs, nanosecs }; + +#ifndef NoNanoSleep + + timespec remain; + while (nanosleep(&rqts, &remain)) { + if (errno == EINTR) { + rqts.tv_sec = remain.tv_sec; + rqts.tv_nsec = remain.tv_nsec; + continue; + } + else + throw omni_thread_fatal(errno); + } +#else + +#if defined(__osf1__) && defined(__alpha__) || defined(__hpux__) && (__OSVERSION__ == 10) || defined(__VMS) || defined(__SINIX__) || defined (__POSIX_NT__) + + if (pthread_delay_np(&rqts) != 0) + throw omni_thread_fatal(errno); + +#elif defined(__linux__) || defined(__aix__) + + if (secs > 2000) { + while ((secs = ::sleep(secs))) ; + } else { + usleep(secs * 1000000 + (nanosecs / 1000)); + } + +#elif defined(__darwin__) || defined(__macos__) + + // Single UNIX Specification says argument of usleep() must be + // less than 1,000,000. + secs += nanosecs / 1000000000; + nanosecs %= 1000000000; + while ((secs = ::sleep(secs))) ; + usleep(nanosecs / 1000); + +#else + + throw omni_thread_invalid(); + +#endif +#endif /* NoNanoSleep */ +} + + +void +omni_thread::get_time(unsigned long* abs_sec, unsigned long* abs_nsec, + unsigned long rel_sec, unsigned long rel_nsec) +{ + timespec abs; + +#if defined(__osf1__) && defined(__alpha__) || defined(__hpux__) && (__OSVERSION__ == 10) || defined(__VMS) || defined(__SINIX__) || defined(__POSIX_NT__) + + timespec rel; + rel.tv_sec = rel_sec; + rel.tv_nsec = rel_nsec; + THROW_ERRORS(pthread_get_expiration_np(&rel, &abs)); + +#else + +#ifdef HAVE_CLOCK_GETTIME /* __linux__ || __aix__ */ + + clock_gettime(CLOCK_REALTIME, &abs); + +#elif defined(HAVE_GETTIMEOFDAY) /* defined(__linux__) || defined(__aix__) || defined(__SCO_VERSION__) || defined(__darwin__) || defined(__macos__) */ + + struct timeval tv; + gettimeofday(&tv, NULL); + abs.tv_sec = tv.tv_sec; + abs.tv_nsec = tv.tv_usec * 1000; + +#else +#error no get time support +#endif /* __linux__ || __aix__ */ + + abs.tv_nsec += rel_nsec; + abs.tv_sec += rel_sec + abs.tv_nsec / 1000000000; + abs.tv_nsec = abs.tv_nsec % 1000000000; + +#endif /* __osf1__ && __alpha__ */ + + *abs_sec = abs.tv_sec; + *abs_nsec = abs.tv_nsec; +} + + +int +omni_thread::posix_priority(priority_t pri) +{ +#ifdef PthreadSupportThreadPriority + switch (pri) { + + case PRIORITY_LOW: + return lowest_priority; + + case PRIORITY_NORMAL: + return normal_priority; + + case PRIORITY_HIGH: + return highest_priority; + + } +#endif + + throw omni_thread_invalid(); +#ifdef _MSC_VER + return 0; +#endif +} + +void +omni_thread::stacksize(unsigned long sz) +{ + stack_size = sz; +} + +unsigned long +omni_thread::stacksize() +{ + return stack_size; +} + +// +// Dummy thread +// + +class omni_thread_dummy : public omni_thread { +public: + inline omni_thread_dummy() : omni_thread() + { + _dummy = 1; + _state = STATE_RUNNING; + posix_thread = pthread_self(); + THROW_ERRORS(pthread_setspecific(self_key, (void*)this)); + } + inline ~omni_thread_dummy() + { + THROW_ERRORS(pthread_setspecific(self_key, 0)); + } +}; + +omni_thread* +omni_thread::create_dummy() +{ + if (omni_thread::self()) + throw omni_thread_invalid(); + + return new omni_thread_dummy; +} + +void +omni_thread::release_dummy() +{ + omni_thread* self = omni_thread::self(); + if (!self || !self->_dummy) + throw omni_thread_invalid(); + + omni_thread_dummy* dummy = (omni_thread_dummy*)self; + delete dummy; +} + + +#define INSIDE_THREAD_IMPL_CC +#include "threaddata.cc" +#undef INSIDE_THREAD_IMPL_CC diff --git a/gnuradio-core/src/lib/omnithread/solaris.cc b/gnuradio-core/src/lib/omnithread/solaris.cc new file mode 100644 index 0000000000..827a645faf --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/solaris.cc @@ -0,0 +1,615 @@ +// Package : omnithread +// omnithread/solaris.cc Created : 7/94 tjr +// +// Copyright (C) 1994-1999 AT&T Laboratories Cambridge +// +// This file is part of the omnithread library +// +// The omnithread 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 +// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA +// +// +// Implementation of OMNI thread abstraction for solaris threads. +// + +#include <stdlib.h> +#include <errno.h> +#include <omnithread.h> + +#define DB(x) // x +// #include <iostream> or #include <iostream.h> if DB is on. + +#define THROW_ERRORS(x) { int rc = (x); \ + if (rc != 0) throw omni_thread_fatal(rc); } + + + +/////////////////////////////////////////////////////////////////////////// +// +// Mutex +// +/////////////////////////////////////////////////////////////////////////// + + +omni_mutex::omni_mutex(void) +{ + THROW_ERRORS(mutex_init(&sol_mutex, USYNC_THREAD, 0)); +} + +omni_mutex::~omni_mutex(void) +{ + THROW_ERRORS(mutex_destroy(&sol_mutex)); +} + +void +omni_mutex::lock(void) +{ + THROW_ERRORS(mutex_lock(&sol_mutex)); +} + +void +omni_mutex::unlock(void) +{ + THROW_ERRORS(mutex_unlock(&sol_mutex)); +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Condition variable +// +/////////////////////////////////////////////////////////////////////////// + + +omni_condition::omni_condition(omni_mutex* m) : mutex(m) +{ + THROW_ERRORS(cond_init(&sol_cond, USYNC_THREAD, 0)); +} + +omni_condition::~omni_condition(void) +{ + THROW_ERRORS(cond_destroy(&sol_cond)); +} + +void +omni_condition::wait(void) +{ + THROW_ERRORS(cond_wait(&sol_cond, &mutex->sol_mutex)); +} + +int +omni_condition::timedwait(unsigned long secs, unsigned long nanosecs) +{ + timespec rqts = { secs, nanosecs }; + + again: + int rc = cond_timedwait(&sol_cond, &mutex->sol_mutex, &rqts); + + if (rc == 0) + return 1; + + if (rc == EINTR) + goto again; + + if (rc == ETIME) + return 0; + + throw omni_thread_fatal(rc); +} + +void +omni_condition::signal(void) +{ + THROW_ERRORS(cond_signal(&sol_cond)); +} + +void +omni_condition::broadcast(void) +{ + THROW_ERRORS(cond_broadcast(&sol_cond)); +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Counting semaphore +// +/////////////////////////////////////////////////////////////////////////// + + +omni_semaphore::omni_semaphore(unsigned int initial) +{ + THROW_ERRORS(sema_init(&sol_sem, initial, USYNC_THREAD, NULL)); +} + +omni_semaphore::~omni_semaphore(void) +{ + THROW_ERRORS(sema_destroy(&sol_sem)); +} + +void +omni_semaphore::wait(void) +{ + THROW_ERRORS(sema_wait(&sol_sem)); +} + +void +omni_semaphore::post(void) +{ + THROW_ERRORS(sema_post(&sol_sem)); +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Thread +// +/////////////////////////////////////////////////////////////////////////// + + +// +// Static variables +// + +int omni_thread::init_t::count = 0; + +omni_mutex* omni_thread::next_id_mutex; +int omni_thread::next_id = 0; + +static thread_key_t self_key; + +static size_t stack_size = 0; + +// +// Initialisation function (gets called before any user code). +// + +omni_thread::init_t::init_t(void) +{ + if (count++ != 0) // only do it once however many objects get created. + return; + + DB(cerr << "omni_thread::init: solaris implementation initialising\n"); + + THROW_ERRORS(thr_keycreate(&self_key, NULL)); + + next_id_mutex = new omni_mutex; + + // + // Create object for this (i.e. initial) thread. + // + + omni_thread* t = new omni_thread; + + t->_state = STATE_RUNNING; + + t->sol_thread = thr_self(); + + DB(cerr << "initial thread " << t->id() << " sol_thread " << t->sol_thread + << endl); + + THROW_ERRORS(thr_setspecific(self_key, (void*)t)); + + THROW_ERRORS(thr_setprio(t->sol_thread, sol_priority(PRIORITY_NORMAL))); +} + + +// +// Wrapper for thread creation. +// + +extern "C" void* +omni_thread_wrapper(void* ptr) +{ + omni_thread* me = (omni_thread*)ptr; + + DB(cerr << "omni_thread::wrapper: thread " << me->id() + << " started\n"); + + THROW_ERRORS(thr_setspecific(self_key, me)); + + // + // Now invoke the thread function with the given argument. + // + + if (me->fn_void != NULL) { + (*me->fn_void)(me->thread_arg); + omni_thread::exit(); + } + + if (me->fn_ret != NULL) { + void* return_value = (*me->fn_ret)(me->thread_arg); + omni_thread::exit(return_value); + } + + if (me->detached) { + me->run(me->thread_arg); + omni_thread::exit(); + } else { + void* return_value = me->run_undetached(me->thread_arg); + omni_thread::exit(return_value); + } + + // should never get here. + + return NULL; +} + + +// +// Constructors for omni_thread - set up the thread object but don't +// start it running. +// + +// construct a detached thread running a given function. + +omni_thread::omni_thread(void (*fn)(void*), void* arg, priority_t pri) +{ + common_constructor(arg, pri, 1); + fn_void = fn; + fn_ret = NULL; +} + +// construct an undetached thread running a given function. + +omni_thread::omni_thread(void* (*fn)(void*), void* arg, priority_t pri) +{ + common_constructor(arg, pri, 0); + fn_void = NULL; + fn_ret = fn; +} + +// construct a thread which will run either run() or run_undetached(). + +omni_thread::omni_thread(void* arg, priority_t pri) +{ + common_constructor(arg, pri, 1); + fn_void = NULL; + fn_ret = NULL; +} + +// common part of all constructors. + +void +omni_thread::common_constructor(void* arg, priority_t pri, int det) +{ + _state = STATE_NEW; + _priority = pri; + + next_id_mutex->lock(); + _id = next_id++; + next_id_mutex->unlock(); + + thread_arg = arg; + detached = det; // may be altered in start_undetached() + + _dummy = 0; + _values = 0; + _value_alloc = 0; + // sol_thread is set up in initialisation routine or start(). +} + + +// +// Destructor for omni_thread. +// + +omni_thread::~omni_thread(void) +{ + DB(cerr << "destructor called for thread " << id() << endl); + if (_values) { + for (key_t i=0; i < _value_alloc; i++) { + if (_values[i]) { + delete _values[i]; + } + } + delete [] _values; + } +} + + +// +// Start the thread +// + +void +omni_thread::start(void) +{ + long flags = 0; + + if (detached) + flags |= THR_DETACHED; + + omni_mutex_lock l(mutex); + + if (_state != STATE_NEW) + throw omni_thread_invalid(); + + THROW_ERRORS(thr_create(0, stack_size, omni_thread_wrapper, (void*)this, flags, + &sol_thread)); + + _state = STATE_RUNNING; + + THROW_ERRORS(thr_setprio(sol_thread, sol_priority(_priority))); +} + + +// +// Start a thread which will run the member function run_undetached(). +// + +void +omni_thread::start_undetached(void) +{ + if ((fn_void != NULL) || (fn_ret != NULL)) + throw omni_thread_invalid(); + + detached = 0; + start(); +} + + +// +// join - simply check error conditions & call thr_join. +// + +void +omni_thread::join(void** status) +{ + mutex.lock(); + + if ((_state != STATE_RUNNING) && (_state != STATE_TERMINATED)) { + mutex.unlock(); + throw omni_thread_invalid(); + } + + mutex.unlock(); + + if (this == self()) + throw omni_thread_invalid(); + + if (detached) + throw omni_thread_invalid(); + + DB(cerr << "omni_thread::join: doing thr_join\n"); + + THROW_ERRORS(thr_join(sol_thread, (thread_t *)NULL, status)); + + DB(cerr << "omni_thread::join: thr_join succeeded\n"); + + delete this; +} + + +// +// Change this thread's priority. +// + +void +omni_thread::set_priority(priority_t pri) +{ + omni_mutex_lock l(mutex); + + if (_state != STATE_RUNNING) + throw omni_thread_invalid(); + + _priority = pri; + + THROW_ERRORS(thr_setprio(sol_thread, sol_priority(pri))); +} + + +// +// create - construct a new thread object and start it running. Returns thread +// object if successful, null pointer if not. +// + +// detached version + +omni_thread* +omni_thread::create(void (*fn)(void*), void* arg, priority_t pri) +{ + omni_thread* t = new omni_thread(fn, arg, pri); + + t->start(); + + return t; +} + +// undetached version + +omni_thread* +omni_thread::create(void* (*fn)(void*), void* arg, priority_t pri) +{ + omni_thread* t = new omni_thread(fn, arg, pri); + + t->start(); + + return t; +} + + +// +// exit() _must_ lock the mutex even in the case of a detached thread. This is +// because a thread may run to completion before the thread that created it has +// had a chance to get out of start(). By locking the mutex we ensure that the +// creating thread must have reached the end of start() before we delete the +// thread object. Of course, once the call to start() returns, the user can +// still incorrectly refer to the thread object, but that's their problem. +// + +void +omni_thread::exit(void* return_value) +{ + omni_thread* me = self(); + + if (me) + { + me->mutex.lock(); + + me->_state = STATE_TERMINATED; + + me->mutex.unlock(); + + DB(cerr << "omni_thread::exit: thread " << me->id() << " detached " + << me->detached << " return value " << return_value << endl); + + if (me->detached) + delete me; + } + else + { + DB(cerr << "omni_thread::exit: called with a non-omnithread. Exit quietly." << endl); + } + + thr_exit(return_value); +} + + +omni_thread* +omni_thread::self(void) +{ + omni_thread* me; + + THROW_ERRORS(thr_getspecific(self_key, (void**)&me)); + + if (!me) { + // This thread is not created by omni_thread::start because it + // doesn't has a class omni_thread instance attached to its key. + DB(cerr << "omni_thread::self: called with a non-ominthread. NULL is returned." << endl); + } + + return me; +} + + +void +omni_thread::yield(void) +{ + thr_yield(); +} + + +void +omni_thread::sleep(unsigned long secs, unsigned long nanosecs) +{ + timespec rqts = { secs, nanosecs }; + timespec remain; + while (nanosleep(&rqts, &remain)) { + if (errno == EINTR) { + rqts.tv_sec = remain.tv_sec; + rqts.tv_nsec = remain.tv_nsec; + continue; + } + else + throw omni_thread_fatal(errno); + } +} + + +void +omni_thread::get_time(unsigned long* abs_sec, unsigned long* abs_nsec, + unsigned long rel_sec, unsigned long rel_nsec) +{ + timespec abs; + clock_gettime(CLOCK_REALTIME, &abs); + abs.tv_nsec += rel_nsec; + abs.tv_sec += rel_sec + abs.tv_nsec / 1000000000; + abs.tv_nsec = abs.tv_nsec % 1000000000; + *abs_sec = abs.tv_sec; + *abs_nsec = abs.tv_nsec; +} + + +int +omni_thread::sol_priority(priority_t pri) +{ + switch (pri) { + + case PRIORITY_LOW: + return 0; + + case PRIORITY_NORMAL: + return 1; + + case PRIORITY_HIGH: + return 2; + } + + throw omni_thread_invalid(); +} + + +void +omni_thread::stacksize(unsigned long sz) +{ + stack_size = sz; +} + +unsigned long +omni_thread::stacksize() +{ + return stack_size; +} + + +// +// Dummy thread +// + +#error This dummy thread code is not tested. It might work if you're lucky. + +class omni_thread_dummy : public omni_thread { +public: + inline omni_thread_dummy() : omni_thread() + { + _dummy = 1; + _state = STATE_RUNNING; + sol_thread = thr_self(); + THROW_ERRORS(thr_setspecific(self_key, (void*)this)); + } + inline ~omni_thread_dummy() + { + THROW_ERRORS(thr_setspecific(self_key, 0)); + } +}; + +omni_thread* +omni_thread::create_dummy() +{ + if (omni_thread::self()) + throw omni_thread_invalid(); + + return new omni_thread_dummy; +} + +void +omni_thread::release_dummy() +{ + omni_thread* self = omni_thread::self(); + if (!self || !self->_dummy) + throw omni_thread_invalid(); + + omni_thread_dummy* dummy = (omni_thread_dummy*)self; + delete dummy; +} + + +#define INSIDE_THREAD_IMPL_CC +#include "threaddata.cc" +#undef INSIDE_THREAD_IMPL_CC diff --git a/gnuradio-core/src/lib/omnithread/threaddata.cc b/gnuradio-core/src/lib/omnithread/threaddata.cc new file mode 100644 index 0000000000..3d007714f6 --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/threaddata.cc @@ -0,0 +1,83 @@ +// Package : omnithread +// omnithread/threaddata.cc Created : 10/2000 dpg1 +// +// Copyright (C) 2000 AT&T Laboratories Cambridge +// +// This file is part of the omnithread library +// +// The omnithread 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 +// Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +// 02111-1307, USA +// + +// Implementation of per-thread data + +#ifndef INSIDE_THREAD_IMPL_CC +#error "threaddata.cc must be #included by a thread implementation." +#endif + + +static omni_thread::key_t allocated_keys = 0; + +omni_thread::key_t +omni_thread::allocate_key() +{ + omni_mutex_lock l(*next_id_mutex); + return ++allocated_keys; +} + +omni_thread::value_t* +omni_thread::set_value(key_t k, value_t* v) +{ + if (k == 0) return 0; + if (k > _value_alloc) { + next_id_mutex->lock(); + key_t alloc = allocated_keys; + next_id_mutex->unlock(); + + if (k > alloc) return 0; + + value_t** nv = new value_t*[alloc]; + key_t i = 0; + if (_values) { + for (; i < _value_alloc; i++) + nv[i] = _values[i]; + delete [] _values; + } + for (; i < alloc; i++) + nv[i] = 0; + + _values = nv; + _value_alloc = alloc; + } + if (_values[k-1]) delete _values[k-1]; + _values[k-1] = v; + return v; +} + +omni_thread::value_t* +omni_thread::get_value(key_t k) +{ + if (k > _value_alloc) return 0; + return _values[k-1]; +} + +omni_thread::value_t* +omni_thread::remove_value(key_t k) +{ + if (k > _value_alloc) return 0; + value_t* v = _values[k-1]; + _values[k-1] = 0; + return v; +} diff --git a/gnuradio-core/src/lib/omnithread/vxWorks.cc b/gnuradio-core/src/lib/omnithread/vxWorks.cc new file mode 100644 index 0000000000..25634ce938 --- /dev/null +++ b/gnuradio-core/src/lib/omnithread/vxWorks.cc @@ -0,0 +1,1160 @@ +////////////////////////////////////////////////////////////////////////////// +// Filename: vxWorks.cc +// Author: Tihomir Sokcevic +// Acterna, Eningen. +// Description: vxWorks adaptation of the omnithread wrapper classes +// Notes: Munching strategy is imperative +////////////////////////////////////////////////////////////////////////////// +// $Log$ +// Revision 1.1 2004/04/10 18:00:52 eb +// Initial revision +// +// Revision 1.1.1.1 2004/03/01 00:20:27 eb +// initial checkin +// +// Revision 1.1 2003/05/25 05:29:04 eb +// see ChangeLog +// +// Revision 1.1.2.1 2003/02/17 02:03:11 dgrisby +// vxWorks port. (Thanks Michael Sturm / Acterna Eningen GmbH). +// +// Revision 1.1.1.1 2002/11/19 14:58:04 sokcevti +// OmniOrb4.0.0 VxWorks port +// +// Revision 1.4 2002/10/15 07:54:09 kuttlest +// change semaphore from SEM_FIFO to SEM_PRIO +// --- +// +// Revision 1.3 2002/07/05 07:38:52 engeln +// made priority redefinable on load time by defining int variables +// omni_thread_prio_low = 220; +// omni_thread_prio_normal = 110; +// omni_thread_prio_high = 55; +// the default priority is prio_normal. +// The normal priority default has been increased from 200 to 110 and the +// high priority from 100 to 55. +// --- +// +// Revision 1.2 2002/06/14 12:44:57 engeln +// replaced possibly unsafe wakeup procedure in broadcast. +// --- +// +// Revision 1.1.1.1 2002/04/02 10:09:34 sokcevti +// omniORB4 initial realease +// +// Revision 1.0 2001/10/23 14:22:45 sokcevti +// Initial Version 4.00 +// --- +// +////////////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////////////// +// Include files +////////////////////////////////////////////////////////////////////////////// +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <time.h> +#include <omnithread.h> +#include <sysLib.h> + +#include <assert.h> // assert +#include <intLib.h> // intContext + + +////////////////////////////////////////////////////////////////////////////// +// Local defines +////////////////////////////////////////////////////////////////////////////// +#define ERRNO(x) (((x) != 0) ? (errno) : 0) +#define THROW_ERRORS(x) { if((x) != OK) throw omni_thread_fatal(errno); } +#define OMNI_THREAD_ID 0x7F7155AAl +#define OMNI_STACK_SIZE 32768l + +#ifdef _DEBUG + #include <fstream> + #define DBG_TRACE(X) X +#else // _DEBUG + #define DBG_TRACE(X) +#endif // _DEBUG + +#define DBG_ASSERT(X) + +#define DBG_THROW(X) X + +int omni_thread_prio_low = 220; +int omni_thread_prio_normal = 110; +int omni_thread_prio_high = 55; +/////////////////////////////////////////////////////////////////////////// +// +// Mutex +// +/////////////////////////////////////////////////////////////////////////// +omni_mutex::omni_mutex(void):m_bConstructed(false) +{ + mutexID = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE); + + DBG_ASSERT(assert(mutexID != NULL)); + + if(mutexID==NULL) + { + DBG_TRACE(cout<<"Exception: omni_mutex::omni_mutex() tid: "<<(int)taskIdSelf()<<endl); + DBG_THROW(throw omni_thread_fatal(-1)); + } + + m_bConstructed = true; +} + +omni_mutex::~omni_mutex(void) +{ + m_bConstructed = false; + + STATUS status = semDelete(mutexID); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_mutex::~omni_mutex() mutexID: "<<(int)mutexID<<" tid: "<<(int)taskIdSelf()<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } +} + +/* +void omni_mutex::lock(void) +{ + DBG_ASSERT(assert(!intContext())); // not in ISR context + DBG_ASSERT(assert(m_bConstructed)); + + STATUS status = semTake(mutexID, WAIT_FOREVER); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_mutex::lock() mutexID: "<<(int)mutexID<<" tid: "<<(int)taskIdSelf()<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } +} + +void omni_mutex::unlock(void) +{ + DBG_ASSERT(assert(m_bConstructed)); + + STATUS status = semGive(mutexID); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_mutex::unlock() mutexID: "<<(int)mutexID<<" tid: "<<(int)taskIdSelf()<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } +} +*/ + +/////////////////////////////////////////////////////////////////////////// +// +// Condition variable +// +/////////////////////////////////////////////////////////////////////////// +omni_condition::omni_condition(omni_mutex* m) : mutex(m) +{ + DBG_TRACE(cout<<"omni_condition::omni_condition mutexID: "<<(int)mutex->mutexID<<" tid:"<<(int)taskIdSelf()<<endl); + + waiters_ = 0; + + sema_ = semCCreate(SEM_Q_PRIORITY, 0); + if(sema_ == NULL) + { + DBG_TRACE(cout<<"Exception: omni_condition::omni_condition() tid: "<<(int)taskIdSelf()<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } + + waiters_lock_ = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE); + if(waiters_lock_ == NULL) + { + DBG_TRACE(cout<<"Exception: omni_condition::omni_condition() tid: "<<(int)taskIdSelf()<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } + +} + +omni_condition::~omni_condition(void) +{ + STATUS status = semDelete(waiters_lock_); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::~omni_condition"<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } + + status = semDelete(sema_); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::~omni_condition"<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } +} + +void omni_condition::wait(void) +{ + DBG_TRACE(cout<<"omni_condition::wait mutexID: "<<(int)mutex->mutexID<<" tid:"<<(int)taskIdSelf()<<endl); + + // Prevent race conditions on the <waiters_> count. + + STATUS status = semTake(waiters_lock_,WAIT_FOREVER); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::wait"<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } + + ++waiters_; + + status = semGive(waiters_lock_); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::wait"<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } + + // disable task lock to have an atomic unlock+semTake + taskLock(); + + // We keep the lock held just long enough to increment the count of + // waiters by one. Note that we can't keep it held across the call + // to wait() since that will deadlock other calls to signal(). + mutex->unlock(); + + // Wait to be awakened by a cond_signal() or cond_broadcast(). + status = semTake(sema_,WAIT_FOREVER); + + // reenable task rescheduling + taskUnlock(); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::wait"<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } + + // Reacquire lock to avoid race conditions on the <waiters_> count. + status = semTake(waiters_lock_,WAIT_FOREVER); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::wait"<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } + + // We're ready to return, so there's one less waiter. + --waiters_; + + // Release the lock so that other collaborating threads can make + // progress. + status = semGive(waiters_lock_); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::wait"<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } + + // Bad things happened, so let's just return below. + + // We must always regain the <external_mutex>, even when errors + // occur because that's the guarantee that we give to our callers. + mutex->lock(); +} + + +// The time given is absolute. Return 0 is timeout +int omni_condition::timedwait(unsigned long secs, unsigned long nanosecs) +{ + STATUS result = OK; + timespec now; + unsigned long timeout; + int ticks; + + // Prevent race conditions on the <waiters_> count. + STATUS status = semTake(waiters_lock_, WAIT_FOREVER); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::timedwait"<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } + + ++waiters_; + + status = semGive(waiters_lock_); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::timedwait"<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } + + clock_gettime(CLOCK_REALTIME, &now); + + if(((unsigned long)secs <= (unsigned long)now.tv_sec) && + (((unsigned long)secs < (unsigned long)now.tv_sec) || + (nanosecs < (unsigned long)now.tv_nsec))) + timeout = 0; + else + timeout = (secs-now.tv_sec) * 1000 + (nanosecs-now.tv_nsec) / 1000000l; + + // disable task lock to have an atomic unlock+semTake + taskLock(); + + // We keep the lock held just long enough to increment the count + // of waiters by one. + mutex->unlock(); + + // Wait to be awakened by a signal() or broadcast(). + ticks = (timeout * sysClkRateGet()) / 1000L; + result = semTake(sema_, ticks); + + // reenable task rescheduling + taskUnlock(); + + // Reacquire lock to avoid race conditions. + status = semTake(waiters_lock_, WAIT_FOREVER); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::timedwait"<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } + + --waiters_; + + status = semGive(waiters_lock_); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::timedwait"<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } + + // A timeout has occured - fires exception if the origin is other than timeout + if(result!=OK && !(errno == S_objLib_OBJ_TIMEOUT || errno == S_objLib_OBJ_UNAVAILABLE)) + { + DBG_TRACE(cout<<"omni_condition::timedwait! - thread:"<<omni_thread::self()->id()<<" SemID:"<<(int)sema_<<" errno:"<<errno<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } + + // We must always regain the <external_mutex>, even when errors + // occur because that's the guarantee that we give to our callers. + mutex->lock(); + + if(result!=OK) // timeout + return 0; + + return 1; +} + +void omni_condition::signal(void) +{ + DBG_TRACE(cout<<"omni_condition::signal mutexID: "<<(int)mutex->mutexID<<" tid:"<<(int)taskIdSelf()<<endl); + + STATUS status = semTake(waiters_lock_, WAIT_FOREVER); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::signal"<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } + + int have_waiters = waiters_ > 0; + + status = semGive(waiters_lock_); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::signal"<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } + + if(have_waiters != 0) + { + status = semGive(sema_); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::signal"<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } + } +} + +void omni_condition::broadcast(void) +{ + DBG_TRACE(cout<<"omni_condition::broadcast mutexID: "<<(int)mutex->mutexID<<" tid:"<<(int)taskIdSelf()<<endl); + + int have_waiters = 0; + + // The <external_mutex> must be locked before this call is made. + // This is needed to ensure that <waiters_> and <was_broadcast_> are + // consistent relative to each other. + STATUS status = semTake(waiters_lock_, WAIT_FOREVER); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::signal"<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } + + if(waiters_ > 0) + { + // We are broadcasting, even if there is just one waiter... + // Record the fact that we are broadcasting. This helps the + // cond_wait() method know how to optimize itself. Be sure to + // set this with the <waiters_lock_> held. + have_waiters = 1; + } + + status = semGive(waiters_lock_); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::signal"<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } + + if(have_waiters) + { + // Wake up all the waiters. + status = semFlush(sema_); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"omni_condition::broadcast1! - thread:"<<omni_thread::self()->id()<<" SemID:"<<(int)sema_<<" errno:"<<errno<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } + + } +} + + +/////////////////////////////////////////////////////////////////////////// +// +// Counting semaphore +// +/////////////////////////////////////////////////////////////////////////// +omni_semaphore::omni_semaphore(unsigned int initial) +{ + + DBG_ASSERT(assert(0 <= (int)initial)); // POSIX expects only unsigned init values + + semID = semCCreate(SEM_Q_PRIORITY, (int)initial); + + DBG_ASSERT(assert(semID!=NULL)); + + if(semID==NULL) + { + DBG_TRACE(cout<<"Exception: omni_semaphore::omni_semaphore"<<endl); + DBG_THROW(throw omni_thread_fatal(-1)); + } +} + +omni_semaphore::~omni_semaphore(void) +{ + STATUS status = semDelete(semID); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_semaphore::~omni_semaphore"<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } +} + +void omni_semaphore::wait(void) +{ + DBG_ASSERT(assert(!intContext())); // no wait in ISR + + STATUS status = semTake(semID, WAIT_FOREVER); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_semaphore::wait"<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } +} + +int omni_semaphore::trywait(void) +{ + STATUS status = semTake(semID, NO_WAIT); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + if(errno == S_objLib_OBJ_UNAVAILABLE) + { + return 0; + } + else + { + DBG_ASSERT(assert(false)); + + DBG_TRACE(cout<<"Exception: omni_semaphore::trywait"<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } + } + + return 1; +} + +void omni_semaphore::post(void) +{ + STATUS status = semGive(semID); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_semaphore::post"<<endl); + DBG_THROW(throw omni_thread_fatal(errno)); + } +} + + + +/////////////////////////////////////////////////////////////////////////// +// +// Thread +// +/////////////////////////////////////////////////////////////////////////// + + +// +// static variables +// +omni_mutex* omni_thread::next_id_mutex = 0; +int omni_thread::next_id = 0; + +// omniORB requires a larger stack size than the default (21120) on OSF/1 +static size_t stack_size = OMNI_STACK_SIZE; + + +// +// Initialisation function (gets called before any user code). +// + +static int& count() { + static int the_count = 0; + return the_count; +} + +omni_thread::init_t::init_t(void) +{ + // Only do it once however many objects get created. + if(count()++ != 0) + return; + + attach(); +} + +omni_thread::init_t::~init_t(void) +{ + if (--count() != 0) return; + + omni_thread* self = omni_thread::self(); + if (!self) return; + + taskTcb(taskIdSelf())->spare1 = 0; + delete self; + + delete next_id_mutex; +} + + +// +// Wrapper for thread creation. +// +extern "C" void omni_thread_wrapper(void* ptr) +{ + omni_thread* me = (omni_thread*)ptr; + + DBG_TRACE(cout<<"omni_thread_wrapper: thread "<<me->id()<<" started\n"); + + // + // We can now tweaked the task info since the tcb exist now + // + me->mutex.lock(); // To ensure that start has had time to finish + taskTcb(me->tid)->spare1 = OMNI_THREAD_ID; + taskTcb(me->tid)->spare2 = (int)ptr; + me->mutex.unlock(); + + // + // Now invoke the thread function with the given argument. + // + if(me->fn_void != NULL) + { + (*me->fn_void)(me->thread_arg); + omni_thread::exit(); + } + + if(me->fn_ret != NULL) + { + void* return_value = (*me->fn_ret)(me->thread_arg); + omni_thread::exit(return_value); + } + + if(me->detached) + { + me->run(me->thread_arg); + omni_thread::exit(); + } + else + { + void* return_value = me->run_undetached(me->thread_arg); + omni_thread::exit(return_value); + } +} + + +// +// Special functions for VxWorks only +// +void omni_thread::attach(void) +{ + DBG_TRACE(cout<<"omni_thread_attach: VxWorks mapping thread initialising\n"); + + int _tid = taskIdSelf(); + + // Check the task is not already attached + if(taskTcb(_tid)->spare1 == OMNI_THREAD_ID) + return; + + // Create the mutex required to lock the threads debugging id (create before the thread!!!) + if(next_id_mutex == 0) + next_id_mutex = new omni_mutex; + + // Create a thread object for THIS running process + omni_thread* t = new omni_thread; + + // Lock its mutex straigh away! + omni_mutex_lock l(t->mutex); + + // Adjust data members of this instance + t->_state = STATE_RUNNING; + t->tid = taskIdSelf(); + + // Set the thread values so it can be recongnised as a omni_thread + // Set the id last can possibly prevent race condition + taskTcb(t->tid)->spare2 = (int)t; + taskTcb(t->tid)->spare1 = OMNI_THREAD_ID; + + // Create the running_mutex at this stage, but leave it empty. We are not running + // in the task context HERE, so taking it would be disastrous. + t->running_cond = new omni_condition(&t->mutex); +} + + +void omni_thread::detach(void) +{ + DBG_TRACE(cout<<"omni_thread_detach: VxWorks detaching thread mapping\n"); + + int _tid = taskIdSelf(); + + // Check the task has a OMNI_THREAD attached + if(taskTcb(_tid)->spare1 != OMNI_THREAD_ID) + return; + + // Invalidate the id NOW ! + taskTcb(_tid)->spare1 = 0; + + // Even if NULL, it is safe to delete the thread + omni_thread* t = (omni_thread*)taskTcb(_tid)->spare2; + // Fininsh cleaning the tcb structure + taskTcb(_tid)->spare2 = 0; + + delete t; +} + + +// +// Constructors for omni_thread - set up the thread object but don't +// start it running. +// + +// construct a detached thread running a given function. +omni_thread::omni_thread(void (*fn)(void*), void* arg, priority_t pri) +{ + common_constructor(arg, pri, 1); + fn_void = fn; + fn_ret = NULL; +} + +// construct an undetached thread running a given function. +omni_thread::omni_thread(void* (*fn)(void*), void* arg, priority_t pri) +{ + common_constructor(arg, pri, 0); + fn_void = NULL; + fn_ret = fn; +} + +// construct a thread which will run either run() or run_undetached(). + +omni_thread::omni_thread(void* arg, priority_t pri) +{ + common_constructor(arg, pri, 1); + fn_void = NULL; + fn_ret = NULL; +} + +// common part of all constructors. +void omni_thread::common_constructor(void* arg, priority_t pri, int det) +{ + _state = STATE_NEW; + _priority = pri; + + // Set the debugging id + next_id_mutex->lock(); + _id = next_id++; + next_id_mutex->unlock(); + + // Note : tid can only be setup when the task is up and running + tid = 0; + + thread_arg = arg; + detached = det; // may be altered in start_undetached() + + _dummy = 0; + _values = 0; + _value_alloc = 0; +} + +// +// Destructor for omni_thread. +// +omni_thread::~omni_thread(void) +{ + DBG_TRACE(cout<<"omni_thread::~omni_thread for thread "<<id()<<endl); + + if (_values) { + for (key_t i=0; i < _value_alloc; i++) { + if (_values[i]) { + delete _values[i]; + } + } + delete [] _values; + } + + delete running_cond; +} + + +// +// Start the thread +// +void omni_thread::start(void) +{ + omni_mutex_lock l(mutex); + + DBG_ASSERT(assert(_state == STATE_NEW)); + + if(_state != STATE_NEW) + DBG_THROW(throw omni_thread_invalid()); + + // Allocate memory for the task. (The returned id cannot be trusted by the task) + tid = taskSpawn( + NULL, // Task name + vxworks_priority(_priority), // Priority + 0, // Option + stack_size, // Stack size + (FUNCPTR)omni_thread_wrapper, // Priority + (int)this, // First argument is this + 0,0,0,0,0,0,0,0,0 // Remaining unused args + ); + + DBG_ASSERT(assert(tid!=ERROR)); + + if(tid==ERROR) + DBG_THROW(throw omni_thread_invalid()); + + _state = STATE_RUNNING; + + // Create the running_mutex at this stage, but leave it empty. We are not running + // in the task context HERE, so taking it would be disastrous. + running_cond = new omni_condition(&mutex); +} + + +// +// Start a thread which will run the member function run_undetached(). +// +void omni_thread::start_undetached(void) +{ + DBG_ASSERT(assert(!((fn_void != NULL) || (fn_ret != NULL)))); + + if((fn_void != NULL) || (fn_ret != NULL)) + DBG_THROW(throw omni_thread_invalid()); + + detached = 0; + + start(); +} + + +// +// join - Wait for the task to complete before returning to the calling process +// +void omni_thread::join(void** status) +{ + mutex.lock(); + + if((_state != STATE_RUNNING) && (_state != STATE_TERMINATED)) + { + mutex.unlock(); + + DBG_ASSERT(assert(false)); + + DBG_THROW(throw omni_thread_invalid()); + } + + mutex.unlock(); + + DBG_ASSERT(assert(this != self())); + + if(this == self()) + DBG_THROW(throw omni_thread_invalid()); + + DBG_ASSERT(assert(!detached)); + + if(detached) + DBG_THROW(throw omni_thread_invalid()); + + mutex.lock(); + running_cond->wait(); + mutex.unlock(); + + if(status) + *status = return_val; + + delete this; +} + + +// +// Change this thread's priority. +// +void omni_thread::set_priority(priority_t pri) +{ + omni_mutex_lock l(mutex); + + DBG_ASSERT(assert(_state == STATE_RUNNING)); + + if(_state != STATE_RUNNING) + { + DBG_THROW(throw omni_thread_invalid()); + } + + _priority = pri; + + if(taskPrioritySet(tid, vxworks_priority(pri))==ERROR) + { + DBG_ASSERT(assert(false)); + + DBG_THROW(throw omni_thread_fatal(errno)); + } +} + + +// +// create - construct a new thread object and start it running. Returns thread +// object if successful, null pointer if not. +// + +// detached version (the entry point is a void) +omni_thread* omni_thread::create(void (*fn)(void*), void* arg, priority_t pri) +{ + omni_thread* t = new omni_thread(fn, arg, pri); + + t->start(); + + return t; +} + +// undetached version (the entry point is a void*) +omni_thread* omni_thread::create(void* (*fn)(void*), void* arg, priority_t pri) +{ + omni_thread* t = new omni_thread(fn, arg, pri); + + t->start(); + + return t; +} + + +// +// exit() _must_ lock the mutex even in the case of a detached thread. This is +// because a thread may run to completion before the thread that created it has +// had a chance to get out of start(). By locking the mutex we ensure that the +// creating thread must have reached the end of start() before we delete the +// thread object. Of course, once the call to start() returns, the user can +// still incorrectly refer to the thread object, but that's their problem. +// +void omni_thread::exit(void* return_value) +{ + omni_thread* me = self(); + + if(me) + { + me->mutex.lock(); + + me->return_val = return_value; + me->_state = STATE_TERMINATED; + me->running_cond->signal(); + + me->mutex.unlock(); + + DBG_TRACE(cout<<"omni_thread::exit: thread "<<me->id()<<" detached "<<me->detached<<" return value "<<(int)return_value<<endl); + + if(me->detached) + delete me; + } + else + DBG_TRACE(cout<<"omni_thread::exit: called with a non-omnithread. Exit quietly."<<endl); + + taskDelete(taskIdSelf()); +} + + +omni_thread* omni_thread::self(void) +{ + if(taskTcb(taskIdSelf())->spare1 != OMNI_THREAD_ID) + return NULL; + + return (omni_thread*)taskTcb(taskIdSelf())->spare2; +} + + +void omni_thread::yield(void) +{ + taskDelay(NO_WAIT); +} + + +void omni_thread::sleep(unsigned long secs, unsigned long nanosecs) +{ + int tps = sysClkRateGet(); + + // Convert to us to avoid overflow in the multiplication + // tps should always be less than 1000 ! + nanosecs /= 1000; + + taskDelay(secs*tps + (nanosecs*tps)/1000000l); +} + + +void omni_thread::get_time( unsigned long* abs_sec, + unsigned long* abs_nsec, + unsigned long rel_sec, + unsigned long rel_nsec) +{ + timespec abs; + clock_gettime(CLOCK_REALTIME, &abs); + abs.tv_nsec += rel_nsec; + abs.tv_sec += rel_sec + abs.tv_nsec / 1000000000; + abs.tv_nsec = abs.tv_nsec % 1000000000; + *abs_sec = abs.tv_sec; + *abs_nsec = abs.tv_nsec; +} + + +int omni_thread::vxworks_priority(priority_t pri) +{ + switch (pri) + { + case PRIORITY_LOW: + return omni_thread_prio_low; + + case PRIORITY_NORMAL: + return omni_thread_prio_normal; + + case PRIORITY_HIGH: + return omni_thread_prio_high; + } + + DBG_ASSERT(assert(false)); + + DBG_THROW(throw omni_thread_invalid()); +} + + +void omni_thread::stacksize(unsigned long sz) +{ + stack_size = sz; +} + + +unsigned long omni_thread::stacksize() +{ + return stack_size; +} + + +void omni_thread::show(void) +{ + omni_thread *pThread; + int s1, s2; + int tid = taskIdSelf(); + + printf("TaskId is %.8x\n", tid); + + s1 = taskTcb(tid)->spare1; + + if(s1 != OMNI_THREAD_ID) + { + printf("Spare 1 is %.8x, and not recongnized\n", s1); + + return; + } + else + { + printf("Spare 1 indicate an omni_thread.\n"); + } + + s2 = taskTcb(tid)->spare2; + + if(s2 == 0) + { + printf("Spare 2 is NULL! - No thread object attached !!\n"); + + return; + } + else + { + printf("Thread object at %.8x\n", s2); + } + + pThread = (omni_thread *)s2; + + state_t status = pThread->_state; + + printf(" | Thread status is "); + + switch (status) + { + case STATE_NEW: + printf("NEW\n"); break; + case STATE_RUNNING: + printf("STATE_RUNNING\n"); break; + case STATE_TERMINATED: + printf("TERMINATED\n"); break; + default: + printf("Illegal (=%.8x)\n", (unsigned int)status); + + return; + } + + if(pThread->tid != tid) + { + printf(" | Task ID in thread object is different!! (=%.8x)\n", pThread->tid); + + return; + } + else + { + printf(" | Task ID in thread consistent\n"); + } + + printf("\n"); +} + + +// +// Dummy thread +// + +class omni_thread_dummy : public omni_thread { +public: + inline omni_thread_dummy() : omni_thread() + { + _dummy = 1; + _state = STATE_RUNNING; + + // Adjust data members of this instance + tid = taskIdSelf(); + + // Set the thread values so it can be recongnised as a omni_thread + // Set the id last can possibly prevent race condition + taskTcb(tid)->spare2 = (int)this; + taskTcb(tid)->spare1 = OMNI_THREAD_ID; + } + inline ~omni_thread_dummy() + { + taskTcb(taskIdSelf())->spare1 = 0; + } +}; + +omni_thread* +omni_thread::create_dummy() +{ + if (omni_thread::self()) + throw omni_thread_invalid(); + + return new omni_thread_dummy; +} + +void +omni_thread::release_dummy() +{ + omni_thread* self = omni_thread::self(); + if (!self || !self->_dummy) + throw omni_thread_invalid(); + + omni_thread_dummy* dummy = (omni_thread_dummy*)self; + delete dummy; +} + + +#define INSIDE_THREAD_IMPL_CC +#include "threaddata.cc" +#undef INSIDE_THREAD_IMPL_CC diff --git a/gnuradio-core/src/lib/reed-solomon/Makefile.am b/gnuradio-core/src/lib/reed-solomon/Makefile.am new file mode 100644 index 0000000000..71af766415 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/Makefile.am @@ -0,0 +1,55 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# Note, this Makefile.am only builds the char versions of the reed soloman routines. +# If you need the int versions too, please figure out how to add them *cleanly* to +# this Makefile.am. + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(CPPUNIT_INCLUDES) + +TESTS = rstest + +EXTRA_DIST = \ + README.karn + +noinst_LTLIBRARIES = librs.la + +noinst_PROGRAMS = \ + rstest + +librs_la_SOURCES = \ + encode_rs.c \ + decode_rs.c \ + init_rs.c + +grinclude_HEADERS = \ + rs.h + +noinst_HEADERS = \ + ccsds.h \ + char.h \ + int.h \ + fixed.h + +rstest_SOURCES = rstest.c exercise.c +rstest_LDADD = librs.la 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 0000000000..8550b41581 --- /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 0000000000..341832dbd5 --- /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 0000000000..f30644ffea --- /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 0000000000..0f2bde6186 --- /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 0000000000..2fbcb504aa --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/char.h @@ -0,0 +1,56 @@ +/* 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 + +/* 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 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_char +#define DECODE_RS decode_rs_char +#define INIT_RS init_rs_char +#define FREE_RS free_rs_char + +void ENCODE_RS(void *p,DTYPE *data,DTYPE *parity); +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); +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 0000000000..ca409782fa --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/decode_rs.c @@ -0,0 +1,262 @@ +/* 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; + 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]; + int syn_error, count; + + /* form the syndromes; i.e., evaluate data(x) at roots of g(x) */ + for(i=0;i<NROOTS;i++) + s[i] = data[0]; + + for(j=1;j<NN;j++){ + for(i=0;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;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;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 (++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 ; 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; 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;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; 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; 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 = min(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 0000000000..2543d3a640 --- /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 0000000000..9d56d0bf11 --- /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 + 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 0000000000..a748b34689 --- /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 0000000000..91d43e1572 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/exercise.c @@ -0,0 +1,126 @@ +/* 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 + DTYPE block[NN],tblock[NN]; + int i; + int errors; + int errlocs[NN]; + int derrlocs[NROOTS]; + 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;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<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<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 0000000000..9f0ddd9a4d --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/fixed.h @@ -0,0 +1,38 @@ +/* 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 + +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 + +void ENCODE_RS(DTYPE *data,DTYPE *parity); +int DECODE_RS(DTYPE *data, int *eras_pos, int no_eras); 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 0000000000..1e4e4f5363 --- /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 0000000000..9dde18917b --- /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 0000000000..11d7c81707 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/init_rs.c @@ -0,0 +1,128 @@ +/* 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 i, j, sr,root,iprim; + + if(symsize > 8*sizeof(DTYPE)) + return NULL; /* Need version with ints rather than chars */ + + if(fcr >= (1<<symsize)) + return NULL; + if(prim == 0 || prim >= (1<<symsize)) + return NULL; + if(nroots >= (1<<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 0000000000..2b0405ae02 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/int.h @@ -0,0 +1,54 @@ +/* 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 + +/* Reed-Solomon codec control block */ +struct 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 + +void ENCODE_RS(void *p,DTYPE *data,DTYPE *parity); +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); +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 0000000000..c3953ce57a --- /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 0000000000..9e731d9d92 --- /dev/null +++ b/gnuradio-core/src/lib/reed-solomon/rs.h @@ -0,0 +1,30 @@ +/* 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 */ +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 *init_rs_char(unsigned int symsize,unsigned int gfpoly, + unsigned int fcr,unsigned int prim,unsigned int nroots); +void free_rs_char(void *rs); + +/* General purpose RS codec, integer symbols */ +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 *init_rs_int(unsigned int symsize,unsigned int gfpoly,unsigned int fcr, + unsigned int prim,unsigned int nroots); +void free_rs_int(void *rs); + +/* CCSDS standard (255,223) RS codec with conventional (*not* dual-basis) + * symbol representation + */ +void encode_rs_8(unsigned char *data,unsigned char *parity); +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 0000000000..d8fc5448a7 --- /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/Makefile.am b/gnuradio-core/src/lib/runtime/Makefile.am new file mode 100644 index 0000000000..7ee94ba1b8 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/Makefile.am @@ -0,0 +1,109 @@ +# +# 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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(CPPUNIT_INCLUDES) + +noinst_LTLIBRARIES = libruntime.la libruntime-qa.la + +libruntime_la_LIBADD = \ + $(SHM_OPEN_LIBS) + + +libruntime_la_SOURCES = \ + gr_block.cc \ + gr_block_detail.cc \ + gr_buffer.cc \ + gr_dispatcher.cc \ + gr_error_handler.cc \ + gr_io_signature.cc \ + gr_local_sighandler.cc \ + gr_message.cc \ + gr_msg_handler.cc \ + gr_msg_queue.cc \ + gr_pagesize.cc \ + gr_preferences.cc \ + gr_realtime.cc \ + gr_single_threaded_scheduler.cc \ + gr_tmp_path.cc \ + gr_vmcircbuf.cc \ + gr_vmcircbuf_mmap_shm_open.cc \ + gr_vmcircbuf_mmap_tmpfile.cc \ + gr_vmcircbuf_createfilemapping.cc \ + gr_vmcircbuf_sysv_shm.cc \ + gr_select_handler.cc + +libruntime_qa_la_SOURCES = \ + qa_gr_block.cc \ + qa_gr_buffer.cc \ + qa_gr_io_signature.cc \ + qa_gr_vmcircbuf.cc \ + qa_runtime.cc + +grinclude_HEADERS = \ + gr_block.h \ + gr_block_detail.h \ + gr_buffer.h \ + gr_complex.h \ + gr_dispatcher.h \ + gr_error_handler.h \ + gr_io_signature.h \ + gr_local_sighandler.h \ + gr_message.h \ + gr_msg_handler.h \ + gr_msg_queue.h \ + gr_pagesize.h \ + gr_preferences.h \ + gr_realtime.h \ + gr_runtime.h \ + gr_select_handler.h \ + gr_single_threaded_scheduler.h \ + gr_timer.h \ + gr_tmp_path.h \ + gr_types.h \ + gr_vmcircbuf.h + +noinst_HEADERS = \ + gr_vmcircbuf_mmap_shm_open.h \ + gr_vmcircbuf_mmap_tmpfile.h \ + gr_vmcircbuf_sysv_shm.h \ + gr_vmcircbuf_createfilemapping.h \ + qa_gr_block.h \ + qa_gr_buffer.h \ + qa_gr_io_signature.h \ + qa_gr_vmcircbuf.h \ + qa_runtime.h + +swiginclude_HEADERS = \ + gr_block.i \ + gr_block_detail.i \ + gr_buffer.i \ + gr_dispatcher.i \ + gr_error_handler.i \ + gr_io_signature.i \ + gr_message.i \ + gr_msg_handler.i \ + gr_msg_queue.i \ + gr_realtime.i \ + gr_single_threaded_scheduler.i \ + gr_swig_block_magic.i \ + runtime.i 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 0000000000..8378c8f7de --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_block.cc @@ -0,0 +1,131 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_block.h> +#include <gr_block_detail.h> +#include <stdexcept> + +static long s_next_id = 0; +static long s_ncurrently_allocated = 0; + +long +gr_block_ncurrently_allocated () +{ + return s_ncurrently_allocated; +} + +gr_block::gr_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_output_multiple (1), + d_relative_rate (1.0), + d_unique_id (s_next_id++), + d_history(1), + d_fixed_rate(false) +{ + s_ncurrently_allocated++; +} + +gr_block::~gr_block () +{ + s_ncurrently_allocated--; +} + +// stub implementation: 1:1 + +void +gr_block::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] = noutput_items; +} + +// default implementation + +bool +gr_block::check_topology (int ninputs, int noutputs) +{ + return true; +} + +bool +gr_block::start() +{ + return true; +} + +bool +gr_block::stop() +{ + return true; +} + +void +gr_block::set_output_multiple (int multiple) +{ + if (multiple < 1) + throw std::invalid_argument ("gr_block::set_output_multiple"); + + d_output_multiple = multiple; +} + +void +gr_block::set_relative_rate (double relative_rate) +{ + if (relative_rate < 0.0) + throw std::invalid_argument ("gr_block::set_relative_rate"); + + d_relative_rate = relative_rate; +} + + +void +gr_block::consume (int which_input, int how_many_items) +{ + d_detail->consume (which_input, how_many_items); +} + +void +gr_block::consume_each (int how_many_items) +{ + d_detail->consume_each (how_many_items); +} + +int +gr_block::fixed_rate_ninput_to_noutput(int ninput) +{ + throw std::runtime_error("Unimplemented"); +} + +int +gr_block::fixed_rate_noutput_to_ninput(int noutput) +{ + throw std::runtime_error("Unimplemented"); +} 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 0000000000..df72e1a3fd --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_block.h @@ -0,0 +1,247 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_BLOCK_H +#define INCLUDED_GR_BLOCK_H + +#include <gr_runtime.h> +#include <string> + +/*! + * \brief The abstract base class for all signal processing blocks. + * \ingroup block + * + * Blocks have a set of input streams and output streams. The + * input_signature and output_signature define the number of input + * streams and output streams respectively, and the type of the data + * items in each stream. + * + * Although blocks may consume data on each input stream at a + * different rate, all outputs streams must produce data at the same + * rate. That rate may be different from any of the input rates. + * + * User derived blocks override two methods, forecast and general_work, + * to implement their signal processing behavior. forecast is called + * by the system scheduler to determine how many items are required on + * each input stream in order to produce a given number of output + * items. + * + * general_work is called to perform the signal processing in the block. + * It reads the input items and writes the output items. + */ + +class gr_block { + + public: + + virtual ~gr_block (); + + std::string name () const { return d_name; } + gr_io_signature_sptr input_signature () const { return d_input_signature; } + gr_io_signature_sptr output_signature () const { return d_output_signature; } + long unique_id () const { return d_unique_id; } + + /*! + * Assume block computes y_i = f(x_i, x_i-1, x_i-2, x_i-3...) + * History is the number of x_i's that are examined to produce one y_i. + * This comes in handy for FIR filters, where we use history to + * ensure that our input contains the appropriate "history" for the + * filter. History should be equal to the number of filter taps. + */ + unsigned history () const { return d_history; } + void set_history (unsigned history) { d_history = history; } + + /*! + * \brief return true if this block has a fixed input to output rate + * + * If true, then fixed_rate_in_to_out and fixed_rate_out_to_in may be called. + */ + bool fixed_rate() const { return d_fixed_rate; } + + // ---------------------------------------------------------------- + // 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. + */ + virtual void forecast (int noutput_items, + gr_vector_int &ninput_items_required); + + /*! + * \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) = 0; + + /*! + * \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); + + /*! + * \brief Called to enable drivers, etc for i/o devices. + * + * This allows a block to enable an associated driver to begin + * transfering data just before we start to execute the scheduler. + * The end result is that this reduces latency in the pipeline when + * dealing with audio devices, usrps, etc. + */ + virtual bool start(); + + /*! + * \brief Called to disable drivers, etc for i/o devices. + */ + virtual bool stop(); + + // ---------------------------------------------------------------- + + /*! + * \brief Constrain the noutput_items argument passed to forecast and general_work + * + * set_output_multiple causes the scheduler to ensure that the noutput_items + * argument passed to forecast and general_work will be an integer multiple + * of \param multiple The default value of output multiple is 1. + */ + void set_output_multiple (int multiple); + int output_multiple () const { return d_output_multiple; } + + /*! + * \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 Set the approximate output rate / input rate + * + * Provide a hint to the buffer allocator and scheduler. + * The default relative_rate is 1.0 + * + * decimators have relative_rates < 1.0 + * interpolators have relative_rates > 1.0 + */ + void set_relative_rate (double relative_rate); + + /*! + * \brief return the approximate output rate / input rate + */ + double relative_rate () const { return d_relative_rate; } + + /* + * 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. + */ + virtual int fixed_rate_ninput_to_noutput(int ninput); + + /*! + * \brief Given noutput samples, return number of input samples required to produce noutput. + * N.B. this is only defined if fixed_rate returns true. + * Generally speaking, you don't need to override this. + */ + virtual int fixed_rate_noutput_to_ninput(int noutput); + + // ---------------------------------------------------------------------------- + + private: + + std::string d_name; + gr_io_signature_sptr d_input_signature; + gr_io_signature_sptr d_output_signature; + int d_output_multiple; + double d_relative_rate; // approx output_rate / input_rate + gr_block_detail_sptr d_detail; // implementation details + long d_unique_id; // convenient for debugging + unsigned d_history; + bool d_fixed_rate; + + + protected: + + gr_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; + } + + void set_fixed_rate(bool fixed_rate){ d_fixed_rate = fixed_rate; } + + // These are really only for internal use, but leaving them public avoids + // having to work up an ever-varying list of friends + + public: + gr_block_detail_sptr detail () const { return d_detail; } + void set_detail (gr_block_detail_sptr detail) { d_detail = detail; } +}; + +long gr_block_ncurrently_allocated (); + +#endif /* INCLUDED_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 0000000000..f1f0332e85 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_block.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +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 { + protected: + gr_block (const std::string &name, + gr_io_signature_sptr input_signature, + gr_io_signature_sptr output_signature); + + public: + + virtual ~gr_block (); + + std::string name () const; + gr_io_signature_sptr input_signature () const; + gr_io_signature_sptr output_signature () const; + long unique_id () const; + unsigned history () const; + + int output_multiple () const; + double relative_rate () const; + + bool check_topology (int ninputs, int noutputs); + bool start(); + bool stop(); + + // internal use + gr_block_detail_sptr detail () const { return d_detail; } + void set_detail (gr_block_detail_sptr detail) { d_detail = detail; } +}; + +%rename(block_ncurrently_allocated) gr_block_ncurrently_allocated; +long gr_block_ncurrently_allocated (); + +%pythoncode %{ +gr_block_sptr.__repr__ = lambda self: "<gr_block %s (%d)>" % (self.name(), self.unique_id ()) +gr_block_sptr.block = lambda self: self +%} 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 0000000000..0ad5da49ce --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_block_detail.cc @@ -0,0 +1,108 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_block_detail.h> +#include <gr_buffer.h> + +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_ninputs (ninputs), d_noutputs (noutputs), + d_input (ninputs), d_output (noutputs), + d_done (false) +{ + 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_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); +} 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 0000000000..90c912c25a --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_block_detail.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_BLOCK_DETAIL_H +#define INCLUDED_GR_BLOCK_DETAIL_H + +#include <gr_runtime.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_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); + + void produce_each (int how_many_items); + + // ---------------------------------------------------------------------------- + + 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; + + gr_block_detail (unsigned int ninputs, unsigned int noutputs); + + friend gr_block_detail_sptr + gr_make_block_detail (unsigned int ninputs, unsigned int noutputs); +}; + +gr_block_detail_sptr +gr_make_block_detail (unsigned int ninputs, unsigned int noutputs); + +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 0000000000..9d3843ebe7 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_buffer.cc b/gnuradio-core/src/lib/runtime/gr_buffer.cc new file mode 100644 index 0000000000..d3d1230967 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_buffer.cc @@ -0,0 +1,248 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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> + +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 / gr_gcd (type_size, page_size); +} + + +gr_buffer::gr_buffer (int nitems, size_t sizeof_item) + : d_base (0), d_bufsize (0), d_vmcircbuf (0), + d_sizeof_item (sizeof_item), d_write_index (0), + d_done (false) +{ + 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) +{ + return gr_buffer_sptr (new gr_buffer (nitems, sizeof_item)); +} + +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 () const +{ + 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 (); + for (unsigned int i = 1; i < d_readers.size (); i++) + most_data = std::max (most_data, d_readers[i]->items_available ()); + + // 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) +{ + d_write_index = index_add (d_write_index, nitems); +} + +gr_buffer_reader_sptr +gr_buffer_add_reader (gr_buffer_sptr buf, int history) +{ + gr_buffer_reader_sptr r (new gr_buffer_reader (buf, + buf->index_sub(buf->d_write_index, + history-1))); + 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); +} + +long +gr_buffer_ncurrently_allocated () +{ + return s_buffer_count; +} + +// ---------------------------------------------------------------------------- + +gr_buffer_reader::gr_buffer_reader (gr_buffer_sptr buffer, unsigned int read_index) + : d_buffer (buffer), d_read_index (read_index) +{ + 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) +{ + d_read_index = d_buffer->index_add (d_read_index, nitems); +} + +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 0000000000..6f85f275ee --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_buffer.h @@ -0,0 +1,196 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_BUFFER_H +#define INCLUDED_GR_BUFFER_H + +#include <gr_runtime.h> + +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. + */ +gr_buffer_sptr gr_make_buffer (int nitems, size_t sizeof_item); + + +/*! + * \brief Single writer, multiple reader fifo. + * \ingroup internal + */ +class gr_buffer { + public: + virtual ~gr_buffer (); + + /*! + * \brief return number of items worth of space available for writing + */ + int space_available () const; + + /*! + * \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) { d_done = done; } + bool done () const { return d_done; } + + // ------------------------------------------------------------------------- + + private: + + friend class gr_buffer_reader; + friend gr_buffer_sptr gr_make_buffer (int nitems, size_t sizeof_item); + friend gr_buffer_reader_sptr gr_buffer_add_reader (gr_buffer_sptr buf, int history); + + 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 + unsigned int d_write_index; // in items [0,d_bufsize) + std::vector<gr_buffer_reader *> d_readers; + bool d_done; + + 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. + * + * 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); + + /*! + * \brief disassociate \p reader from this buffer + */ + void drop_reader (gr_buffer_reader *reader); + +}; + +//! create a new gr_buffer_reader and attach it to buffer \p buf +gr_buffer_reader_sptr gr_buffer_add_reader (gr_buffer_sptr buf, int history); + +//! returns # of gr_buffers currently allocated +long gr_buffer_ncurrently_allocated (); + + +// --------------------------------------------------------------------------- + +/*! + * \brief How we keep track of the readers of a gr_buffer. + * \ingroup internal + */ + +class gr_buffer_reader { + + public: + ~gr_buffer_reader (); + + /*! + * \brief Return number of items available for reading. + */ + int items_available () const; + + /*! + * \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 (); } + + // ------------------------------------------------------------------------- + + private: + + friend class gr_buffer; + friend gr_buffer_reader_sptr gr_buffer_add_reader (gr_buffer_sptr buf, int history); + + + gr_buffer_sptr d_buffer; + unsigned int d_read_index; // in items [0,d->buffer.d_bufsize) + + //! constructor is private. Use gr_buffer::add_reader to create instances + gr_buffer_reader (gr_buffer_sptr buffer, unsigned int read_index); +}; + +//! returns # of gr_buffer_readers currently allocated +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 0000000000..80f92ece12 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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); + +class gr_buffer { + public: + ~gr_buffer (); + + private: + gr_buffer (int nitems, size_t sizeof_item); +}; + + +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 history); + +class gr_buffer_reader { + public: + ~gr_buffer_reader (); + + private: + friend class gr_buffer; + gr_buffer_reader (gr_buffer_sptr buffer, unsigned int read_index); +}; + + +%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 0000000000..242b2f54d4 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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) { return true;} +inline bool is_complex (gr_complexd x) { return true;} +inline bool is_complex (float x) { return false;} +inline bool is_complex (double x) { return false;} +inline bool is_complex (int x) { return false;} +inline bool is_complex (char x) { return false;} +inline bool is_complex (short x) { return false;} + + +// this doesn't really belong here, but there are worse places for it... + +#define 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 0000000000..c2a1eb50af --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_dispatcher.cc @@ -0,0 +1,192 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_dispatcher.h> +#include <math.h> +#include <errno.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 0000000000..a3d8579727 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_dispatcher.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_DISPATCHER_H +#define INCLUDED_GR_DISPATCHER_H + +#include <gr_select_handler.h> +#include <vector> + +class gr_dispatcher; +typedef boost::shared_ptr<gr_dispatcher> gr_dispatcher_sptr; + +gr_dispatcher_sptr gr_dispatcher_singleton(); +gr_dispatcher_sptr gr_make_dispatcher(); + +/*! + * \brief invoke callbacks based on select. + * + * \sa gr_select_handler + */ +class gr_dispatcher +{ + gr_dispatcher(); + friend 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 0000000000..5feca75713 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..a3148cfde6 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..275db64c33 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_error_handler.h @@ -0,0 +1,114 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 <stdarg.h> +#include <string> + +/*! + * \brief abstract 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); + + 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_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 { + 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 0000000000..d0e61496f4 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_io_signature.cc b/gnuradio-core/src/lib/runtime/gr_io_signature.cc new file mode 100644 index 0000000000..7277108cae --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_io_signature.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_io_signature.h> +#include <stdexcept> +#include <iostream> + +gr_io_signature::gr_io_signature (int min_streams, int max_streams, size_t sizeof_stream_item) +{ + if (min_streams < 0 + || (max_streams != IO_INFINITE && max_streams < min_streams)) + throw std::invalid_argument ("gr_io_signature"); + + d_min_streams = min_streams; + d_max_streams = max_streams; + d_sizeof_stream_item = sizeof_stream_item; +} + +gr_io_signature::~gr_io_signature () +{ + // NOP for now + // std::cout << "destroying gr_io_signature: " << this << '\n'; +} + +gr_io_signature_sptr +gr_make_io_signature (int min_streams, int max_streams, size_t sizeof_stream_item) +{ + return gr_io_signature_sptr (new gr_io_signature (min_streams, max_streams, + 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 0000000000..e0d979070c --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_io_signature.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_IO_SIGNATURE_H +#define INCLUDED_IO_SIGNATURE_H + +#include <gr_runtime.h> + +/*! + * \brief i/o signature for input and output ports. + * + * For now, we restrict all streams to be the same type. + * We can fix this later. + */ + +class gr_io_signature { + 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; } + size_t sizeof_stream_item (int index) const { return d_sizeof_stream_item; } + + // ---------------------------------------------------------------------------- + + private: + + int d_min_streams; + int d_max_streams; + size_t d_sizeof_stream_item; + + gr_io_signature (int min_streams, int max_streams, size_t sizeof_stream_item); + + friend gr_io_signature_sptr gr_make_io_signature (int min_streams, + int max_streams, + size_t sizeof_stream_item); +}; + +gr_io_signature_sptr +gr_make_io_signature (int min_streams, int max_streams, size_t sizeof_stream_item); + + +#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 0000000000..601142e287 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_io_signature.i @@ -0,0 +1,49 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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; + +gr_io_signature_sptr +gr_make_io_signature (int min_streams, + int max_streams, + size_t sizeof_stream_item); + +class gr_io_signature { + 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; } + size_t sizeof_stream_item (int index) const { return d_sizeof_stream_item; } + + private: + gr_io_signature (int min_streams, int max_streams, size_t sizeof_stream_item); +}; + 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 0000000000..c6da0978c3 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_local_sighandler.cc @@ -0,0 +1,186 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_local_sighandler.h> +#include <stdexcept> +#include <stdio.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 0000000000..69eb65d80d --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_local_sighandler.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_LOCAL_SIGHANDLER_H +#define INCLUDED_GR_LOCAL_SIGHANDLER_H + +#include <signal.h> +#include <string> + +/*! + * \brief Get and set signal handler. + * + * Constructor installs new handler, destructor reinstalls + * original value. + */ +class 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_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 0000000000..e9427e64df --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_message.cc @@ -0,0 +1,77 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include <gr_message.h> +#include <assert.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 0000000000..272a82ee47 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_message.h @@ -0,0 +1,89 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_MESSAGE_H +#define INCLUDED_GR_MESSAGE_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_message_sptr +gr_make_message(long type = 0, double arg1 = 0, double arg2 = 0, size_t length = 0); + +gr_message_sptr +gr_make_message_from_string(const std::string s, long type = 0, double arg1 = 0, double arg2 = 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_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_message_sptr + gr_make_message (long type, double arg1, double arg2, size_t length); + + friend 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; + +}; + +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 0000000000..19d5d1cd17 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_handler.cc b/gnuradio-core/src/lib/runtime/gr_msg_handler.cc new file mode 100644 index 0000000000..98007e239a --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..15aab338a5 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_msg_handler.h @@ -0,0 +1,41 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_MSG_HANDLER_H +#define INCLUDED_GR_MSG_HANDLER_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 + */ +class 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 0000000000..5571665ac7 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..6b53fc7ea1 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_msg_queue.cc @@ -0,0 +1,127 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_mutex), d_not_full(&d_mutex), + /*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"); + + omni_mutex_lock l(d_mutex); + + while (full_p()) + d_not_full.wait(); + + 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.signal(); +} + +gr_message_sptr +gr_msg_queue::delete_head() +{ + omni_mutex_lock l(d_mutex); + gr_message_sptr m; + + while ((m = d_head) == 0) + d_not_empty.wait(); + + 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.signal(); + return m; +} + +gr_message_sptr +gr_msg_queue::delete_head_nowait() +{ + omni_mutex_lock l(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.signal(); + 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 0000000000..6a9147ee38 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_msg_queue.h @@ -0,0 +1,89 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_MSG_QUEUE_H +#define INCLUDED_GR_MSG_QUEUE_H + +#include <gr_msg_handler.h> +#include <omnithread.h> + +class gr_msg_queue; +typedef boost::shared_ptr<gr_msg_queue> gr_msg_queue_sptr; + +gr_msg_queue_sptr gr_make_msg_queue(unsigned int limit=0); + +/*! + * \brief thread-safe message queue + */ +class gr_msg_queue : public gr_msg_handler { + omni_mutex d_mutex; + omni_condition d_not_empty; + omni_condition 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 0000000000..28292d66fb --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_msg_queue.i @@ -0,0 +1,111 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 { + omni_mutex d_mutex; + omni_condition d_cond; + gr_message_sptr d_head; + gr_message_sptr d_tail; + int d_count; + +public: + gr_msg_queue(); + ~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...) + */ +%inline { + gr_message_sptr gr_py_msg_queue__delete_head(gr_msg_queue_sptr q) { + gr_message_sptr msg; + Py_BEGIN_ALLOW_THREADS; // release global interpreter lock + msg = q->delete_head(); // possibly blocking call + Py_END_ALLOW_THREADS; // acquire global interpreter lock + return msg; + } + + void gr_py_msg_queue__insert_tail(gr_msg_queue_sptr q, gr_message_sptr msg) { + Py_BEGIN_ALLOW_THREADS; // release global interpreter lock + q->insert_tail(msg); // possibly blocking call + Py_END_ALLOW_THREADS; // acquire global interpreter lock + } +} + +// 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 +%} 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 0000000000..dec40678b3 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..a5cadb7074 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_pagesize.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GR_PAGESIZE_H_ +#define _GR_PAGESIZE_H_ + +/*! + * \brief return the page size in bytes + */ + +int gr_pagesize (); + + +#endif /* _GR_PAGESIZE_H_ */ 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 0000000000..854314447a --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_preferences.cc @@ -0,0 +1,101 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <gr_preferences.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + + +#ifdef MKDIR_TAKES_ONE_ARG +#define gr_mkdir(pathname, mode) mkdir(pathname) +#else +#define gr_mkdir(pathname, mode) mkdir((pathname), (mode)) +#endif + +/* + * 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 char buf[200]; + snprintf (buf, sizeof (buf), "%s/.gnuradio/prefs/%s", getenv ("HOME"), key); + return buf; +} + +static void +ensure_dir_path () +{ + char path[200]; + struct stat statbuf; + + snprintf (path, sizeof (path), "%s/.gnuradio/prefs", getenv ("HOME")); + if (stat (path, &statbuf) == 0 && S_ISDIR (statbuf.st_mode)) + return; + + // blindly try to make it // FIXME make this robust. C++ SUCKS! + + snprintf (path, sizeof (path), "%s/.gnuradio", getenv ("HOME")); + gr_mkdir (path, 0750); + snprintf (path, sizeof (path), "%s/.gnuradio/prefs", getenv ("HOME")); + gr_mkdir (path, 0750); +} + +const char * +gr_preferences::get (const char *key) +{ + static char buf[1024]; + + FILE *fp = fopen (pathname (key), "r"); + if (fp == 0) + return 0; + + memset (buf, 0, sizeof (buf)); + fread (buf, 1, sizeof (buf) - 1, fp); + 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; + } + + fwrite (value, 1, strlen (value), fp); + 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 0000000000..5a7cad454d --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_preferences.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GR_PREFERENCES_H_ +#define _GR_PREFERENCES_H_ + +class gr_preferences { + public: + static const char *get (const char *key); + static void set (const char *key, const char *value); +}; + +#endif /* _GR_PREFERENCES_H_ */ 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 0000000000..4f23ea0c63 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_realtime.cc @@ -0,0 +1,71 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <gr_realtime.h> + +#ifdef HAVE_SCHED_H +#include <sched.h> +#endif + +#include <string.h> +#include <errno.h> +#include <stdio.h> + +#if defined(HAVE_SCHED_SETSCHEDULER) + +gr_rt_status_t +gr_enable_realtime_scheduling() +{ + int policy = SCHED_FIFO; + int pri = (sched_get_priority_max (policy) - sched_get_priority_min (policy)) / 2; + int pid = 0; // this process + + struct sched_param param; + memset(¶m, 0, sizeof(param)); + param.sched_priority = pri; + int result = sched_setscheduler(pid, policy, ¶m); + if (result != 0){ + if (errno == EPERM) + return RT_NO_PRIVS; + else { + perror ("sched_setscheduler: failed to set real time priority"); + return RT_OTHER_ERROR; + } + } + //printf("SCHED_FIFO enabled with priority = %d\n", pri); + return RT_OK; +} + +// #elif // could try negative niceness + +#else + +gr_rt_status_t +gr_enable_realtime_scheduling() +{ + return RT_NOT_IMPLEMENTED; +} + +#endif 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 0000000000..3aeafa5338 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_realtime.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_REALTIME_H +#define INCLUDED_GR_REALTIME_H + +typedef enum { + RT_OK = 0, + RT_NOT_IMPLEMENTED, + RT_NO_PRIVS, + RT_OTHER_ERROR +} gr_rt_status_t; + +/*! + * \brief If possible, enable high-priority "real time" scheduling. + */ +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 0000000000..cb43e0514c --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_realtime.i @@ -0,0 +1,4 @@ +%rename(enable_realtime_scheduling) gr_enable_realtime_scheduling; + +%include <gr_realtime.h> + diff --git a/gnuradio-core/src/lib/runtime/gr_runtime.h b/gnuradio-core/src/lib/runtime/gr_runtime.h new file mode 100644 index 0000000000..f138e6ac41 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_runtime.h @@ -0,0 +1,44 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_RUNTIME_H +#define INCLUDED_GR_RUNTIME_H + +#include <gr_types.h> + +/* + * typedefs for smart pointers we use throughout the runtime system + */ + +class gr_block; +class gr_block_detail; +class gr_io_signature; +class gr_buffer; +class gr_buffer_reader; + +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_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; + +#endif /* INCLUDED_GR_RUNTIME_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 0000000000..d85883a655 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..d07ff007f8 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_select_handler.h @@ -0,0 +1,83 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SELECT_HANDLER_H +#define INCLUDED_GR_SELECT_HANDLER_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. + * + * \sa gr_dispatcher + */ +class 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 0000000000..3d401557be --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.cc @@ -0,0 +1,360 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 <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; + + +std::ostream& +operator << (std::ostream& os, const gr_block *m) +{ + os << "<gr_block " << m->name() << " (" << m->unique_id() << ")>"; + return os; +} + +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){ + char name[100]; + snprintf(name, sizeof(name), "sst-%d.log", which_scheduler++); + d_log = new std::ofstream(name); + *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; + main_loop (); +} + + +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){ + + 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 0000000000..1272831e59 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_SINGLE_THREADED_SCHEDULER_H +#define INCLUDED_GR_SINGLE_THREADED_SCHEDULER_H + +#include <gr_runtime.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_single_threaded_scheduler { + public: + ~gr_single_threaded_scheduler (); + + void run (); + void stop () { d_enabled = false; } + + 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_single_threaded_scheduler_sptr + gr_make_single_threaded_scheduler (const std::vector<gr_block_sptr> &blocks); +}; + +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 0000000000..40058228b2 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.i @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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); +}; + +%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 + } +} + diff --git a/gnuradio-core/src/lib/runtime/gr_swig_block_magic.i b/gnuradio-core/src/lib/runtime/gr_swig_block_magic.i new file mode 100644 index 0000000000..ca4f6e600d --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_swig_block_magic.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%define GR_SWIG_BLOCK_MAGIC(PKG, BASE_NAME) +_GR_SWIG_BLOCK_MAGIC_HELPER(PKG, PKG ## _ ## BASE_NAME, BASE_NAME) +%enddef + +%define _GR_SWIG_BLOCK_MAGIC_HELPER(PKG, NAME, BASE_NAME) +class NAME; +typedef boost::shared_ptr<NAME> NAME ## _sptr; +%template(NAME ## _sptr) boost::shared_ptr<NAME>; +%rename(BASE_NAME) PKG ## _make_ ## BASE_NAME; +%inline { + gr_block_sptr NAME ## _block (NAME ## _sptr r) + { + return gr_block_sptr (r); + } +} + +%pythoncode %{ +NAME ## _sptr.block = lambda self: NAME ## _block (self) +NAME ## _sptr.__repr__ = lambda self: "<gr_block %s (%d)>" % (self.name(), self.unique_id ()) +%} + +%ignore NAME; +%enddef 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 0000000000..709b98470e --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_timer.h @@ -0,0 +1,82 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef INCLUDED_GR_TIMER_H +#define INCLUDED_GR_TIMER_H + +#include <gr_types.h> + +class gr_timer; + +typedef boost::shared_ptr<gr_timer> gr_timer_sptr; + +typedef void (*gr_timer_hook)(gr_timer *, void *); + +/*! + * \brief create a timeout. + * + * gr_timer_hook is called when timer fires. + */ +gr_timer_sptr gr_make_timer (gr_timer_hook, void *); + +/*! + * \brief implement timeouts + */ +class gr_timer { + double d_expiry; + double d_period; + gr_timer_hook d_hook; + void *d_hook_arg; + + friend 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_tmp_path.cc b/gnuradio-core/src/lib/runtime/gr_tmp_path.cc new file mode 100644 index 0000000000..7eb03b5d55 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_tmp_path.cc @@ -0,0 +1,52 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <gr_tmp_path.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +const char * +gr_tmp_path () +{ + static char *pp = 0; + + if (pp) + return pp; + + char *s = getenv ("TMP"); + if (s){ + pp = strdup (s); + return pp; + } + +#ifdef P_tmpdir + if (P_tmpdir){ + pp = strdup (P_tmpdir); + return pp; + } +#endif + + pp = strdup ("/tmp"); + return pp; +} + diff --git a/gnuradio-core/src/lib/runtime/gr_tmp_path.h b/gnuradio-core/src/lib/runtime/gr_tmp_path.h new file mode 100644 index 0000000000..742ce05633 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_tmp_path.h @@ -0,0 +1,31 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GR_TMP_PATH_H_ +#define _GR_TMP_PATH_H_ + +/*! + * \brief return directory portion of pathname used for temporary files. + */ +const char *gr_tmp_path (); + +#endif /* _GR_TMP_PATH_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 0000000000..370ca56424 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_types.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef INCLUDED_GR_TYPES_H +#define INCLUDED_GR_TYPES_H + +#include <boost/shared_ptr.hpp> +#include <vector> +#include <stddef.h> // size_t + +#include <gr_complex.h> + +typedef std::vector<int> gr_vector_int; +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 <config.h> must be placed beforehand + * in the source file including gr_types.h for + * the following to work correctly + */ +#ifdef HAVE_STDINT_H +#include <stdint.h> +typedef int16_t gr_int16; +typedef int32_t gr_int32; +typedef int64_t gr_int64; +typedef uint16_t gr_uint16; +typedef uint32_t gr_uint32; +typedef uint64_t gr_uint64; +#else +/* + * Note: these defaults may be wrong on 64-bit systems + */ +typedef short gr_int16; +typedef int gr_int32; +typedef long long gr_int64; +typedef unsigned short gr_uint16; +typedef unsigned int gr_uint32; +typedef unsigned long long gr_uint64; +#endif /* HAVE_STDINT_H */ + +#endif /* INCLUDED_GR_TYPES_H */ 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 0000000000..3586c4c73d --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf.cc @@ -0,0 +1,291 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 <gr_local_sighandler.h> + +// 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 ()); + result.push_back (gr_vmcircbuf_sysv_shm_factory::singleton ()); + result.push_back (gr_vmcircbuf_mmap_shm_open_factory::singleton ()); + 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, 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 char * +memsize (int size) +{ + static char buf[100]; + if (size >= (1 << 20)){ + snprintf (buf, sizeof (buf), "%dMB", size / (1 << 20)); + } + else if (size >= (1 << 10)){ + snprintf (buf, sizeof (buf), "%dKB", size / (1 << 10)); + } + else { + snprintf (buf, sizeof (buf), "%d", size); + } + return buf; +} + +static bool +test_a_bunch (gr_vmcircbuf_factory *factory, int n, int size, int *start_ptr, bool verbose) +{ + bool ok = true; + int counter[n]; + 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++){ + char msg[100]; + snprintf (msg, sizeof (msg), "test_a_bunch_%dx%s[%d]", n, memsize (size), i); + ok &= check_mapping (c[i], counter[i], size, msg, 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); // 256 x 16KB = 4MB + ok &= test_a_bunch (f, 32, 4 * (1L << 20), &start, v); // 32 x 4MB = 64MB + 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 0000000000..e2af935877 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf.h @@ -0,0 +1,120 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GR_VMCIRCBUF_H_ +#define _GR_VMCIRCBUF_H_ + +#include <vector> + +/*! + * \brief abstract class to implement doubly mapped virtual memory circular buffers + */ +class 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_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_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 0000000000..8f3540b4b4 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_createfilemapping.cc @@ -0,0 +1,191 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_tmp_path.h> +#include <gr_vmcircbuf_createfilemapping.h> + + +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"); + } + + char seg_name[1024]; + snprintf (seg_name, sizeof (seg_name), "/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); // name of mapping object + + s_seg_counter++; + if (d_handle == NULL || d_handle == INVALID_HANDLE_VALUE){ + char msg[1024]; + snprintf (msg, sizeof (msg), "gr_vmcircbuf_mmap_createfilemapping: CreateFileMapping [%s] :%d", seg_name,(int)GetLastError()); + perror (msg); + throw std::runtime_error ("gr_vmcircbuf_mmap_createfilemapping"); + } + + int i = 0; + d_first_copy = d_second_copy = NULL; + + while (i++ < 8 && d_second_copy == NULL){ + // keep the first map allocation to force allocation in a new address + // space + LPVOID first_tmp = d_first_copy; + + d_first_copy = MapViewOfFile((HANDLE)d_handle, // handle to map object + FILE_MAP_WRITE, // read/write permission + 0, + 0, + size); + + if (d_first_copy == NULL){ + if (first_tmp) + UnmapViewOfFile(first_tmp); + + CloseHandle(d_handle); // cleanup + char msg[1024]; + snprintf (msg, sizeof (msg), + "gr_vmcircbuf_mmap_createfilemapping: MapViewOfFile (1) :%d", (int)GetLastError()); + perror (msg); + throw std::runtime_error ("gr_vmcircbuf_mmap_createfilemapping"); + } + + // NOTE: d_second_copy will be NULL if MapViewFileEx() fails to allocate the + // requested address space + d_second_copy = MapViewOfFileEx((HANDLE)d_handle, // handle to map object + FILE_MAP_WRITE, // read/write permission + 0, + 0, + size, + (char *)d_first_copy + size);//(LPVOID) ((char *)d_first_copy + size)); + + if (first_tmp) + UnmapViewOfFile(first_tmp); + +#ifdef DEBUG + fprintf (stderr,"gr_vmcircbuf_mmap_createfilemapping: contiguous? mmap %p %p %p %p, %d\n", + (char *)d_first_copy, (char *)d_second_copy, size, (char *)d_first_copy + size,i); +#endif + } + + if (d_second_copy == NULL){ // cleanup + fprintf (stderr,"gr_vmcircbuf_mmap_createfilemapping: non contiguous mmap - %p %p %p %p\n", + d_first_copy, d_second_copy, size, (char *)d_first_copy + size); + UnmapViewOfFile(d_first_copy); + CloseHandle(d_handle); // cleanup + throw std::runtime_error ("gr_vmcircbuf_mmap_createfilemapping"); + } + + // 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) + { + perror ("gr_vmcircbuf_createfilemapping: UnmapViewOfFile(d_first_copy)"); + } + d_base=NULL; + if (UnmapViewOfFile(d_second_copy) == 0) + { + perror ("gr_vmcircbuf_createfilemapping: UnmapViewOfFile(d_second_copy)"); + } + //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 0000000000..f7113cf4fd --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_createfilemapping.h @@ -0,0 +1,74 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GR_VMCIRCBUF_CREATEFILEMAPPING_H_ +#define _GR_VMCIRCBUF_CREATEFILEMAPPING_H_ + +#include <gr_vmcircbuf.h> + +#ifdef HAVE_CREATEFILEMAPPING +#include <windows.h> +#endif +/*! + * \brief concrete class to implement circular buffers with mmap and shm_open + */ +class 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_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 0000000000..65fa1183b4 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_shm_open.cc @@ -0,0 +1,205 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_tmp_path.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 0000000000..4b1feafff2 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_shm_open.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GR_VMCIRCBUF_MMAP_SHM_OPEN_H_ +#define _GR_VMCIRCBUF_MMAP_SHM_OPEN_H_ + +#include <gr_vmcircbuf.h> + +/*! + * \brief concrete class to implement circular buffers with mmap and shm_open + */ +class 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_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 0000000000..a07df779c0 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.cc @@ -0,0 +1,198 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_tmp_path.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 0000000000..3b9f5dba8a --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GR_VMCIRCBUF_MMAP_TMPFILE_H_ +#define _GR_VMCIRCBUF_MMAP_TMPFILE_H_ + +#include <gr_vmcircbuf.h> + +/*! + * \brief concrete class to implement circular buffers with mmap and shm_open + */ +class 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_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 0000000000..4b6fcfe338 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_sysv_shm.cc @@ -0,0 +1,192 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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)"); + 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 (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 0000000000..9a8c128a52 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_vmcircbuf_sysv_shm.h @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GR_VMCIRCBUF_SYSV_SHM_H_ +#define _GR_VMCIRCBUF_SYSV_SHM_H_ + +#include <gr_vmcircbuf.h> + +/*! + * \brief concrete class to implement circular buffers with mmap and shm_open + */ +class 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_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/qa_gr_block.cc b/gnuradio-core/src/lib/runtime/qa_gr_block.cc new file mode 100644 index 0000000000..e3a21be350 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_block.cc @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <qa_gr_block.h> +#include <gr_block.h> +#include <gr_runtime.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 (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 (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 (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 (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 0000000000..6e30825146 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..5c549d0b98 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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))); + + 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_buffer_reader_sptr r1 (gr_buffer_add_reader (buf, 1)); + + + 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_buffer_reader_sptr r1 (gr_buffer_add_reader (buf, 1)); + + 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_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, 1); + } + + 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 0000000000..700629cc4c --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_io_signature.cc b/gnuradio-core/src/lib/runtime/qa_gr_io_signature.cc new file mode 100644 index 0000000000..c180e7b742 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_io_signature.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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), sizeof (int)); +} + +void +qa_gr_io_signature::t3 () +{ +} + 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 0000000000..225ce80687 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_gr_io_signature.h @@ -0,0 +1,47 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_vmcircbuf.cc b/gnuradio-core/src/lib/runtime/qa_gr_vmcircbuf.cc new file mode 100644 index 0000000000..f3c815a0d5 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..41f69c3534 --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..668628f2ac --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_runtime.cc @@ -0,0 +1,49 @@ +/* + * 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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_buffer.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_buffer::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 0000000000..5862b1ea20 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/qa_runtime.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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _QA_RUNTIME_H_ +#define _QA_RUNTIME_H_ + +#include <cppunit/TestSuite.h> + +//! collect all the tests for the runtime directory + +class 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/runtime.i b/gnuradio-core/src/lib/runtime/runtime.i new file mode 100644 index 0000000000..d8dd34f1ee --- /dev/null +++ b/gnuradio-core/src/lib/runtime/runtime.i @@ -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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%{ +#include <gr_runtime.h> +#include <gr_io_signature.h> +#include <gr_buffer.h> +#include <gr_block.h> +#include <gr_block_detail.h> +#include <gr_single_threaded_scheduler.h> +#include <gr_message.h> +#include <gr_msg_handler.h> +#include <gr_msg_queue.h> +#include <gr_dispatcher.h> +#include <gr_error_handler.h> +#include <gr_realtime.h> +%} + +%include <gr_io_signature.i> +%include <gr_buffer.i> +%include <gr_block.i> +%include <gr_block_detail.i> +%include <gr_swig_block_magic.i> +%include <gr_single_threaded_scheduler.i> +%include <gr_message.i> +%include <gr_msg_handler.i> +%include <gr_msg_queue.i> +%include <gr_dispatcher.i> +%include <gr_error_handler.i> +%include <gr_realtime.i> 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 0000000000..26bfa6d2db --- /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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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/Makefile.am b/gnuradio-core/src/lib/swig/Makefile.am new file mode 100644 index 0000000000..77bd030836 --- /dev/null +++ b/gnuradio-core/src/lib/swig/Makefile.am @@ -0,0 +1,111 @@ +# +# Copyright 2001,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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +include $(top_srcdir)/Makefile.common + +# Install this stuff in the gr subdirectory of the python pkg dir. +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio/gr + +grgrpythondir = $(grpythondir)/gr +grgrlibdir = $(grpyexecdir)/gr + + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) -I$(srcdir) + + +EXTRA_DIST = gen-swig-bug-fix + + +LOCAL_IFILES = \ + gnuradio.i \ + shared_ptr.i + +ALL_IFILES = \ + $(LOCAL_IFILES) + + +BUILT_SOURCES = \ + gnuradio_swig_python.cc \ + gnuradio_swig_python.py \ + gnuradio_swig_python.h \ + gnuradio_swig_bug_workaround.h + +grgrpython_PYTHON = \ + gnuradio_swig_python.py + + +SWIGPYTHONARGS = $(SWIGPYTHONFLAGS) $(INCLUDES) + + +# ---------------------------------------------------------------- +# _gnuradio_swig_python contains all the glue that implements +# the gnuradio.gr python package + +grgrlib_LTLIBRARIES = \ + _gnuradio_swig_python.la + +_gnuradio_swig_python_la_SOURCES = \ + gnuradio_swig_python.cc + + +_gnuradio_swig_python_la_LIBADD = \ + $(top_builddir)/gnuradio-core/src/lib/libgnuradio-core.la \ + $(PYTHON_LDFLAGS) \ + -lstdc++ + +_gnuradio_swig_python_la_LDFLAGS = -module -avoid-version $(NO_UNDEFINED) + + +# KLUDGE: Force runtime include of gnuradio_swig_python.d dependency file. +# This is not guaranteed to be portable, but will probably work. +# If it works, we have accurate dependencies for our swig stuff, which is good. +@am__include@ @am__quote@./gnuradio_swig_python.d@am__quote@ + +gnuradio_swig_python.cc gnuradio_swig_python.py gnuradio_swig_python.h : gnuradio.i + if $(SWIG) $(SWIGPYTHONARGS) -MMD -MF gnuradio_swig_python.Td -module gnuradio_swig_python -o gnuradio_swig_python.cc $< ;\ + then if test $(host_os) = mingw32; \ + then sed 's,\\\\,/,g' <gnuradio_swig_python.Td >gnuradio_swig_python.d; rm -f gnuradio_swig_python.Td; \ + else mv -f gnuradio_swig_python.Td gnuradio_swig_python.d; fi \ + else rm -f gnuradio_swig_python.Td; exit 1; fi + +gnuradio_swig_bug_workaround.h : gnuradio_swig_python.cc $(srcdir)/gen-swig-bug-fix + $(srcdir)/gen-swig-bug-fix $< $@ + + +# ---------------------------------------------------------------- + +# Don't distribute output of swig +dist-hook: + @for file in $(BUILT_SOURCES); do echo $(RM) $(distdir)/$$file; done + @for file in $(BUILT_SOURCES); do $(RM) $(distdir)/$$file; done + + +grinclude_HEADERS = \ + gnuradio_swig_bug_workaround.h + +swiginclude_HEADERS = \ + $(LOCAL_IFILES) + +MOSTLYCLEANFILES = \ + $(BUILT_SOURCES) *~ *.pyc + +DISTCLEANFILES = gnuradio_swig_python.d diff --git a/gnuradio-core/src/lib/swig/atsc.i b/gnuradio-core/src/lib/swig/atsc.i new file mode 100644 index 0000000000..4e8bf48f29 --- /dev/null +++ b/gnuradio-core/src/lib/swig/atsc.i @@ -0,0 +1,136 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +%{ +#include <atsc_types.h> +#include <atsc_consts.h> +#include <GrAtscRandomizer.h> +#include <GrAtscRSEncoder.h> +#include <GrAtscInterleaver.h> +#include <GrAtscTrellisEncoder.h> +#include <GrAtscFieldSyncMux.h> +#include <GrAtscSymbolMapper.h> +#include <GrAtscConvert2xTo20.h> +#include <GrWeaverModHead.h> +#include <GrWeaverModTail.h> + +%} + +// from atsc_types.h +class plinfo; +class atsc_mpeg_packet; +class atsc_mpeg_packet_no_sync; +class atsc_mpeg_packet_rs_encoded; +class atsc_data_segment; +class atsc_soft_data_segment; + +%include <atsc_consts.h> + + +// leave out the VrHistoryProc and pretend we're directly derived from VrSigProc + +// %template(VrHistoryProc_1) VrHistoryProc<atsc_mpeg_packet,atsc_mpeg_packet_no_sync>; + +class GrAtscRandomizer : public VrSigProc +// class GrAtscRandomizer : public VrHistoryProc<atsc_mpeg_packet, atsc_mpeg_packet_no_sync> +{ +public: + GrAtscRandomizer (); + ~GrAtscRandomizer (); +}; + +class GrAtscRSEncoder : public VrSigProc +{ +public: + GrAtscRSEncoder (); + ~GrAtscRSEncoder (); +}; + +class GrAtscInterleaver : public VrSigProc +{ +public: + GrAtscInterleaver (); + ~GrAtscInterleaver (); +}; + +class GrAtscTrellisEncoder : public VrSigProc +{ +public: + GrAtscTrellisEncoder (); + ~GrAtscTrellisEncoder (); +}; + +class GrAtscFieldSyncMux : public VrSigProc +{ +public: + GrAtscFieldSyncMux (); + ~GrAtscFieldSyncMux (); +}; + +template<class oType> +class GrAtscSymbolMapper : public VrSigProc +{ +public: + GrAtscSymbolMapper (); + ~GrAtscSymbolMapper (); +}; + +%template(GrAtscSymbolMapperF) GrAtscSymbolMapper<float>; + +template<class iType, class oType> +class GrWeaverModHead : public VrSigProc +{ +public: + GrWeaverModHead (int interp_factor); + ~GrWeaverModHead (); +}; + +%template(GrWeaverModHeadFF) GrWeaverModHead<float,float>; + +template<class iType, class oType> +class GrWeaverModTail : public VrSigProc { +public: + GrWeaverModTail (float freq, float gain); + ~GrWeaverModTail (); + + //! frequency is in Hz + void set_freq (float frequency); + void set_gain (float g); +}; + +%template(GrWeaverModTailFS) GrWeaverModTail<float,short>; + +class GrAtscConvert2xTo20 : public VrSigProc +{ +public: + GrAtscConvert2xTo20 (); + ~GrAtscConvert2xTo20 (); +}; + + +#if 0 // FIXME +%template(VrSource_mpeg_packet) VrSource<atsc_mpeg_packet>; +%template(VrFileSource_mpeg_packet) VrFileSource<atsc_mpeg_packet>; + +%template(VrSink_mpeg_packet) VrSink<atsc_mpeg_packet>; +%template(VrFileSink_mpeg_packet) VrFileSink<atsc_mpeg_packet>; +#endif 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 0000000000..36332cc599 --- /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 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, 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 0000000000..b8c58538cd --- /dev/null +++ b/gnuradio-core/src/lib/swig/gnuradio.i @@ -0,0 +1,84 @@ +/* -*- 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 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +//////////////////////////////////////////////////////////////////////// +// gnuradio.i +// SWIG interface definition +//////////////////////////////////////////////////////////////////////// + + +#ifndef SWIGIMPORTED +// we set the module name on the command line (not any more) +%module(directors="1") gnuradio_swig_python +#endif + +//////////////////////////////////////////////////////////////////////// +// Headers + + +%{ +#include <gr_types.h> +#include <stddef.h> // size_t +%} + +%feature("autodoc","1"); + +%include <shared_ptr.i> +%include <stl.i> +%include <std_complex.i> + + +typedef std::complex<float> gr_complex; +typedef std::complex<double> gr_complexd; + + +// 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() vector<std::complex<float> >; +}; + +//////////////////////////////////////////////////////////////////////// + +%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 <runtime.i> +%include <general.i> +%include <filter.i> +%include <io.i> + +// %include <atsc.i> + +//////////////////////////////////////////////////////////////////////// diff --git a/gnuradio-core/src/lib/swig/shared_ptr.i b/gnuradio-core/src/lib/swig/shared_ptr.i new file mode 100644 index 0000000000..9663033ae7 --- /dev/null +++ b/gnuradio-core/src/lib/swig/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 |