From 5d69a524f81f234b3fbc41d49ba18d6f6886baba Mon Sep 17 00:00:00 2001 From: jcorgan Date: Thu, 3 Aug 2006 04:51:51 +0000 Subject: [PATCH] Houston, we have a trunk. git-svn-id: http://gnuradio.org/svn/gnuradio/trunk@3122 221aa14e-8319-0410-a670-987f0aec2ac5 --- AUTHORS | 12 + COPYING | 340 + ChangeLog | 20 + INSTALL | 229 + Makefile.am | 29 + Makefile.common | 40 + NEWS | 15 + README | 190 + bootstrap | 29 + config.guess | 1465 +++ config.sub | 1587 +++ config/Makefile.am | 66 + config/acx_pthread.m4 | 190 + config/bnv_have_qt.m4 | 404 + config/cppunit.m4 | 80 + config/gr_as.m4 | 34 + config/gr_atsc.m4 | 36 + config/gr_audio_alsa.m4 | 41 + config/gr_audio_jack.m4 | 41 + config/gr_audio_oss.m4 | 45 + config/gr_audio_osx.m4 | 38 + config/gr_audio_portaudio.m4 | 43 + config/gr_audio_windows.m4 | 39 + config/gr_boost.m4 | 111 + config/gr_check_createfilemapping.m4 | 52 + config/gr_check_mc4020.m4 | 37 + config/gr_check_shm_open.m4 | 29 + config/gr_check_usrp.m4 | 32 + config/gr_comedi.m4 | 41 + config/gr_doxygen.m4 | 59 + config/gr_error_correcting_codes.m4 | 38 + config/gr_fortran.m4 | 31 + config/gr_gnuradio_core.m4 | 63 + config/gr_gnuradio_examples.m4 | 35 + config/gr_gprof.m4 | 72 + config/gr_gsm_fr_vocoder.m4 | 36 + config/gr_libgnuradio_core_extra_ldflags.m4 | 40 + config/gr_no_undefined.m4 | 44 + config/gr_omnithread.m4 | 51 + config/gr_pmt.m4 | 34 + config/gr_pwin32.m4 | 146 + config/gr_python.m4 | 116 + config/gr_radar.m4 | 36 + config/gr_radio_astronomy.m4 | 35 + config/gr_require_mc4020.m4 | 33 + config/gr_scripting.m4 | 30 + config/gr_set_md_cpu.m4 | 44 + config/gr_swig.m4 | 85 + config/gr_sysv_shm.m4 | 36 + config/gr_usrp.m4 | 113 + config/gr_video_sdl.m4 | 45 + config/gr_wxgui.m4 | 33 + config/gr_x86_64.m4 | 39 + config/lf_cc.m4 | 42 + config/lf_cxx.m4 | 121 + config/lf_warnings.m4 | 128 + config/lf_x11.m4 | 39 + config/macosx_audiounit.m4 | 49 + config/mkstemp.m4 | 89 + config/onceonly.m4 | 63 + config/pkg.m4 | 68 + config/sdl.m4 | 175 + config/usrp_fusb_tech.m4 | 55 + config/usrp_libusb.m4 | 51 + config/usrp_sdcc.m4 | 75 + configure.ac | 200 + docs/COPYING | 340 + docs/ChangeLog | 24 + docs/exploring-gnuradio/Makefile | 30 + docs/exploring-gnuradio/ddc.eps | 3105 +++++ docs/exploring-gnuradio/ddc.png | Bin 0 -> 42199 bytes docs/exploring-gnuradio/dial_tone.py | 43 + docs/exploring-gnuradio/dial_tone_example.xml | 28 + .../exploring-gnuradio/exploring-gnuradio.xml | 460 + docs/exploring-gnuradio/fm_demod.py | 150 + docs/exploring-gnuradio/fm_demod_example.xml | 123 + docs/exploring-gnuradio/swr-block-diagram.eps | 2399 ++++ docs/exploring-gnuradio/swr-block-diagram.png | Bin 0 -> 24686 bytes .../exploring-gnuradio/usrp-block-diagram.eps | 2785 +++++ .../exploring-gnuradio/usrp-block-diagram.png | Bin 0 -> 35729 bytes docs/howto-write-a-block/README | 3 + dtools/COPYING | 340 + dtools/README | 25 + dtools/bin/check-config-files | 72 + dtools/bin/check-imports | 4 + dtools/bin/check-tarball-h-files | 23 + dtools/bin/get-config-files | 6 + dtools/bin/incr_release | 37 + dtools/bin/make-upload | 12 + dtools/bin/show_release | 36 + dtools/bin/tag_release | 47 + dtools/python/release_tools.py | 87 + gnuradio-core/ChangeLog | 1893 ++++ gnuradio-core/Makefile.am | 36 + gnuradio-core/NEWS | 35 + gnuradio-core/README | 190 + gnuradio-core/README-win32-mingw-short.txt | 92 + gnuradio-core/README.hacking | 178 + gnuradio-core/THANKS | 7 + gnuradio-core/TODO | 14 + gnuradio-core/doc/Doxyfile.in | 1224 ++ gnuradio-core/doc/Makefile.am | 71 + gnuradio-core/doc/other/Makefile.am | 31 + gnuradio-core/doc/other/group_defs.dox | 31 + gnuradio-core/doc/other/main_page.dox | 5 + gnuradio-core/doc/other/omnithread.html | 411 + gnuradio-core/doc/other/omnithread.pdf | Bin 0 -> 126474 bytes gnuradio-core/doc/other/omnithread.ps | 730 ++ gnuradio-core/doc/other/shared_ptr_docstub.h | 24 + .../doc/other/tv-channel-frequencies | 79 + gnuradio-core/doc/other/vector_docstub.h | 16 + gnuradio-core/doc/xml/Makefile.am | 25 + gnuradio-core/doc/xml/README | 129 + gnuradio-core/doc/xml/doxy2swig.py | 371 + gnuradio-core/doc/xml/swig.xsl | 38 + gnuradio-core/gnuradio-core.conf | 19 + gnuradio-core/gnuradio-core.pc.in | 11 + gnuradio-core/src/Makefile.am | 26 + .../src/gen_interpolator_taps/Makefile.am | 33 + .../src/gen_interpolator_taps/README | 47 + .../gen_interpolator_taps.c | 186 + .../src/gen_interpolator_taps/objective_fct.c | 124 + .../src/gen_interpolator_taps/praxis.f | 1705 +++ .../src/gen_interpolator_taps/praxis.txt | 176 + .../src/gen_interpolator_taps/simpson.c | 76 + .../src/gen_interpolator_taps/simpson.h | 3 + gnuradio-core/src/lib/Makefile.am | 62 + gnuradio-core/src/lib/bug_work_around_6.cc | 3 + .../3dnow_float_dotprod_really_simple.S | 95 + .../lib/filter/3dnow_float_dotprod_simple.S | 102 + gnuradio-core/src/lib/filter/Makefile.am | 306 + gnuradio-core/src/lib/filter/Makefile.gen | 111 + gnuradio-core/src/lib/filter/README | 28 + gnuradio-core/src/lib/filter/assembly.h | 58 + .../src/lib/filter/ccomplex_dotprod_3dnow.S | 216 + .../src/lib/filter/ccomplex_dotprod_3dnow64.S | 213 + .../lib/filter/ccomplex_dotprod_3dnowext.S | 191 + .../lib/filter/ccomplex_dotprod_3dnowext64.S | 188 + .../lib/filter/ccomplex_dotprod_generic.cc | 59 + .../src/lib/filter/ccomplex_dotprod_generic.h | 32 + .../src/lib/filter/ccomplex_dotprod_sse.S | 194 + .../src/lib/filter/ccomplex_dotprod_sse64.S | 191 + .../src/lib/filter/ccomplex_dotprod_x86.h | 46 + .../src/lib/filter/complex_dotprod_3dnow.S | 188 + .../src/lib/filter/complex_dotprod_3dnow64.S | 183 + .../src/lib/filter/complex_dotprod_3dnowext.S | 167 + .../lib/filter/complex_dotprod_3dnowext64.S | 164 + .../src/lib/filter/complex_dotprod_generic.cc | 55 + .../src/lib/filter/complex_dotprod_generic.h | 32 + .../src/lib/filter/complex_dotprod_sse.S | 202 + .../src/lib/filter/complex_dotprod_sse64.S | 198 + .../src/lib/filter/complex_dotprod_x86.h | 46 + gnuradio-core/src/lib/filter/cpuid_x86.S | 56 + gnuradio-core/src/lib/filter/cpuid_x86_64.S | 50 + .../src/lib/filter/fcomplex_dotprod_3dnow.S | 172 + .../src/lib/filter/fcomplex_dotprod_3dnow64.S | 166 + .../src/lib/filter/fcomplex_dotprod_sse.S | 184 + .../src/lib/filter/fcomplex_dotprod_sse64.S | 179 + .../src/lib/filter/fcomplex_dotprod_x86.h | 42 + gnuradio-core/src/lib/filter/filter.i | 45 + .../src/lib/filter/float_dotprod_3dnow.S | 148 + .../src/lib/filter/float_dotprod_3dnow64.S | 145 + .../src/lib/filter/float_dotprod_generic.c | 49 + .../src/lib/filter/float_dotprod_generic.h | 41 + .../src/lib/filter/float_dotprod_sse.S | 167 + .../src/lib/filter/float_dotprod_sse64.S | 161 + .../src/lib/filter/float_dotprod_x86.h | 44 + gnuradio-core/src/lib/filter/generate_all.py | 46 + .../src/lib/filter/generate_gr_fir_XXX.py | 75 + .../lib/filter/generate_gr_fir_filter_XXX.py | 49 + .../lib/filter/generate_gr_fir_sysconfig.py | 127 + .../generate_gr_fir_sysconfig_generic.py | 182 + .../src/lib/filter/generate_gr_fir_util.py | 185 + ...generate_gr_freq_xlating_fir_filter_XXX.py | 53 + .../generate_gr_interp_fir_filter_XXX.py | 48 + ...generate_gr_rational_resampler_base_XXX.py | 48 + .../src/lib/filter/generate_utils.py | 31 + .../src/lib/filter/gr_adaptive_fir_ccf.cc | 81 + .../src/lib/filter/gr_adaptive_fir_ccf.h | 57 + .../src/lib/filter/gr_adaptive_fir_ccf.i | 30 + .../src/lib/filter/gr_cma_equalizer_cc.cc | 41 + .../src/lib/filter/gr_cma_equalizer_cc.h | 62 + .../src/lib/filter/gr_cma_equalizer_cc.i | 35 + gnuradio-core/src/lib/filter/gr_cpu.cc | 107 + gnuradio-core/src/lib/filter/gr_cpu.h | 34 + .../src/lib/filter/gr_fft_filter_ccc.cc | 210 + .../src/lib/filter/gr_fft_filter_ccc.h | 77 + .../src/lib/filter/gr_fft_filter_ccc.i | 39 + .../src/lib/filter/gr_fft_filter_fff.cc | 211 + .../src/lib/filter/gr_fft_filter_fff.h | 76 + .../src/lib/filter/gr_fft_filter_fff.i | 39 + .../src/lib/filter/gr_filter_delay_fc.cc | 80 + .../src/lib/filter/gr_filter_delay_fc.h | 72 + .../src/lib/filter/gr_filter_delay_fc.i | 34 + gnuradio-core/src/lib/filter/gr_fir_XXX.cc.t | 30 + gnuradio-core/src/lib/filter/gr_fir_XXX.h.t | 123 + .../src/lib/filter/gr_fir_XXX_generic.cc.t | 103 + .../src/lib/filter/gr_fir_XXX_generic.h.t | 77 + .../src/lib/filter/gr_fir_ccc_simd.cc | 139 + .../src/lib/filter/gr_fir_ccc_simd.h | 63 + .../src/lib/filter/gr_fir_ccc_x86.cc | 77 + gnuradio-core/src/lib/filter/gr_fir_ccc_x86.h | 55 + .../src/lib/filter/gr_fir_ccf_simd.cc | 138 + .../src/lib/filter/gr_fir_ccf_simd.h | 64 + .../src/lib/filter/gr_fir_ccf_x86.cc | 60 + gnuradio-core/src/lib/filter/gr_fir_ccf_x86.h | 48 + .../src/lib/filter/gr_fir_fcc_simd.cc | 139 + .../src/lib/filter/gr_fir_fcc_simd.h | 64 + .../src/lib/filter/gr_fir_fcc_x86.cc | 60 + gnuradio-core/src/lib/filter/gr_fir_fcc_x86.h | 48 + .../src/lib/filter/gr_fir_fff_simd.cc | 134 + .../src/lib/filter/gr_fir_fff_simd.h | 62 + .../src/lib/filter/gr_fir_fff_x86.cc | 60 + gnuradio-core/src/lib/filter/gr_fir_fff_x86.h | 48 + .../src/lib/filter/gr_fir_filter_XXX.cc.t | 88 + .../src/lib/filter/gr_fir_filter_XXX.h.t | 67 + .../src/lib/filter/gr_fir_filter_XXX.i.t | 41 + .../src/lib/filter/gr_fir_fsf_simd.cc | 133 + .../src/lib/filter/gr_fir_fsf_simd.h | 62 + .../src/lib/filter/gr_fir_fsf_x86.cc | 60 + gnuradio-core/src/lib/filter/gr_fir_fsf_x86.h | 48 + .../src/lib/filter/gr_fir_scc_simd.cc | 140 + .../src/lib/filter/gr_fir_scc_simd.h | 64 + .../src/lib/filter/gr_fir_scc_x86.cc | 77 + gnuradio-core/src/lib/filter/gr_fir_scc_x86.h | 58 + .../src/lib/filter/gr_fir_sysconfig_x86.cc | 553 + .../src/lib/filter/gr_fir_sysconfig_x86.h | 46 + .../lib/filter/gr_fractional_interpolator.cc | 97 + .../lib/filter/gr_fractional_interpolator.h | 62 + .../gr_freq_xlating_fir_filter_XXX.cc.t | 122 + .../filter/gr_freq_xlating_fir_filter_XXX.h.t | 100 + .../filter/gr_freq_xlating_fir_filter_XXX.i.t | 47 + .../src/lib/filter/gr_goertzel_fc.cc | 60 + gnuradio-core/src/lib/filter/gr_goertzel_fc.h | 55 + gnuradio-core/src/lib/filter/gr_goertzel_fc.i | 31 + gnuradio-core/src/lib/filter/gr_hilbert_fc.cc | 67 + gnuradio-core/src/lib/filter/gr_hilbert_fc.h | 68 + gnuradio-core/src/lib/filter/gr_hilbert_fc.i | 34 + .../src/lib/filter/gr_iir_filter_ffd.cc | 88 + .../src/lib/filter/gr_iir_filter_ffd.h | 89 + .../src/lib/filter/gr_iir_filter_ffd.i | 40 + .../lib/filter/gr_interp_fir_filter_XXX.cc.t | 146 + .../lib/filter/gr_interp_fir_filter_XXX.h.t | 69 + .../lib/filter/gr_interp_fir_filter_XXX.i.t | 41 + .../gr_rational_resampler_base_XXX.cc.t | 172 + .../filter/gr_rational_resampler_base_XXX.h.t | 87 + .../filter/gr_rational_resampler_base_XXX.i.t | 42 + gnuradio-core/src/lib/filter/gr_rotator.h | 50 + gnuradio-core/src/lib/filter/gr_sincos.c | 81 + gnuradio-core/src/lib/filter/gr_sincos.h | 39 + .../src/lib/filter/gr_single_pole_avg.h | 110 + .../filter/gr_single_pole_avg_filter_ff.cc | 81 + .../lib/filter/gr_single_pole_avg_filter_ff.h | 76 + .../lib/filter/gr_single_pole_avg_filter_ff.i | 34 + .../src/lib/filter/gr_single_pole_iir.h | 190 + .../filter/gr_single_pole_iir_filter_cc.cc | 81 + .../lib/filter/gr_single_pole_iir_filter_cc.h | 77 + .../lib/filter/gr_single_pole_iir_filter_cc.i | 34 + .../filter/gr_single_pole_iir_filter_ff.cc | 81 + .../lib/filter/gr_single_pole_iir_filter_ff.h | 76 + .../lib/filter/gr_single_pole_iir_filter_ff.i | 34 + .../src/lib/filter/gr_single_pole_rec.h | 110 + .../filter/gr_single_pole_rec_filter_ff.cc | 81 + .../lib/filter/gr_single_pole_rec_filter_ff.h | 76 + .../lib/filter/gr_single_pole_rec_filter_ff.i | 34 + .../src/lib/filter/gr_single_zero_avg.h | 110 + .../filter/gr_single_zero_avg_filter_ff.cc | 81 + .../lib/filter/gr_single_zero_avg_filter_ff.h | 76 + .../lib/filter/gr_single_zero_avg_filter_ff.i | 34 + .../src/lib/filter/gr_single_zero_rec.h | 110 + .../filter/gr_single_zero_rec_filter_ff.cc | 81 + .../lib/filter/gr_single_zero_rec_filter_ff.h | 76 + .../lib/filter/gr_single_zero_rec_filter_ff.i | 34 + gnuradio-core/src/lib/filter/gri_goertzel.cc | 66 + gnuradio-core/src/lib/filter/gri_goertzel.h | 55 + gnuradio-core/src/lib/filter/gri_iir.h | 164 + .../lib/filter/gri_mmse_fir_interpolator.cc | 71 + .../lib/filter/gri_mmse_fir_interpolator.h | 65 + .../filter/gri_mmse_fir_interpolator_cc.cc | 71 + .../lib/filter/gri_mmse_fir_interpolator_cc.h | 66 + .../src/lib/filter/interpolator_taps.h | 141 + .../src/lib/filter/qa_ccomplex_dotprod_x86.cc | 341 + .../src/lib/filter/qa_ccomplex_dotprod_x86.h | 74 + .../src/lib/filter/qa_complex_dotprod_x86.cc | 347 + .../src/lib/filter/qa_complex_dotprod_x86.h | 74 + gnuradio-core/src/lib/filter/qa_dotprod.h | 30 + .../src/lib/filter/qa_dotprod_generic.cc | 32 + .../src/lib/filter/qa_dotprod_x86.cc | 37 + gnuradio-core/src/lib/filter/qa_filter.cc | 52 + gnuradio-core/src/lib/filter/qa_filter.h | 37 + .../src/lib/filter/qa_float_dotprod_x86.cc | 270 + .../src/lib/filter/qa_float_dotprod_x86.h | 69 + gnuradio-core/src/lib/filter/qa_gr_fir_ccc.cc | 183 + gnuradio-core/src/lib/filter/qa_gr_fir_ccc.h | 40 + gnuradio-core/src/lib/filter/qa_gr_fir_ccf.cc | 183 + gnuradio-core/src/lib/filter/qa_gr_fir_ccf.h | 43 + gnuradio-core/src/lib/filter/qa_gr_fir_fcc.cc | 180 + gnuradio-core/src/lib/filter/qa_gr_fir_fcc.h | 40 + gnuradio-core/src/lib/filter/qa_gr_fir_fff.cc | 225 + gnuradio-core/src/lib/filter/qa_gr_fir_fff.h | 43 + gnuradio-core/src/lib/filter/qa_gr_fir_scc.cc | 179 + gnuradio-core/src/lib/filter/qa_gr_fir_scc.h | 40 + .../filter/qa_gri_mmse_fir_interpolator.cc | 62 + .../lib/filter/qa_gri_mmse_fir_interpolator.h | 40 + .../src/lib/filter/short_dotprod_generic.c | 49 + .../src/lib/filter/short_dotprod_generic.h | 41 + .../src/lib/filter/short_dotprod_mmx.S | 113 + .../src/lib/filter/short_dotprod_mmx64.S | 101 + .../src/lib/filter/short_dotprod_x86.h | 44 + gnuradio-core/src/lib/filter/sse_debug.c | 62 + gnuradio-core/src/lib/filter/sse_debug.h | 48 + .../src/lib/filter/sysconfig_generic.cc | 35 + gnuradio-core/src/lib/filter/sysconfig_x86.cc | 38 + gnuradio-core/src/lib/g72x/Makefile.am | 27 + gnuradio-core/src/lib/g72x/README | 94 + gnuradio-core/src/lib/g72x/decode.c | 113 + gnuradio-core/src/lib/g72x/encode.c | 119 + gnuradio-core/src/lib/g72x/g711.c | 283 + gnuradio-core/src/lib/g72x/g721.c | 173 + gnuradio-core/src/lib/g72x/g723_24.c | 158 + gnuradio-core/src/lib/g72x/g723_40.c | 178 + gnuradio-core/src/lib/g72x/g72x.c | 576 + gnuradio-core/src/lib/g72x/g72x.h | 156 + gnuradio-core/src/lib/general/Makefile.am | 440 + gnuradio-core/src/lib/general/Makefile.gen | 234 + gnuradio-core/src/lib/general/README | 98 + gnuradio-core/src/lib/general/atsc_rrc1x.dat | 57 + gnuradio-core/src/lib/general/atsc_rrc20.dat | 101 + gnuradio-core/src/lib/general/atsc_rrc2x.dat | 102 + .../src/lib/general/gen_sine_table.py | 77 + gnuradio-core/src/lib/general/general.i | 203 + .../src/lib/general/general_generated.i | 156 + gnuradio-core/src/lib/general/generate_all.py | 33 + .../src/lib/general/generate_common.py | 93 + gnuradio-core/src/lib/general/gr_add_XX.cc.t | 62 + gnuradio-core/src/lib/general/gr_add_XX.h.t | 54 + gnuradio-core/src/lib/general/gr_add_XX.i.t | 33 + .../src/lib/general/gr_add_const_XX.cc.t | 72 + .../src/lib/general/gr_add_const_XX.h.t | 55 + .../src/lib/general/gr_add_const_XX.i.t | 37 + .../src/lib/general/gr_add_const_vXX.cc.t | 61 + .../src/lib/general/gr_add_const_vXX.h.t | 55 + .../src/lib/general/gr_add_const_vXX.i.t | 37 + gnuradio-core/src/lib/general/gr_add_vXX.cc.t | 65 + gnuradio-core/src/lib/general/gr_add_vXX.h.t | 54 + gnuradio-core/src/lib/general/gr_add_vXX.i.t | 33 + gnuradio-core/src/lib/general/gr_agc_cc.cc | 54 + gnuradio-core/src/lib/general/gr_agc_cc.h | 50 + gnuradio-core/src/lib/general/gr_agc_cc.i | 33 + gnuradio-core/src/lib/general/gr_agc_ff.cc | 54 + gnuradio-core/src/lib/general/gr_agc_ff.h | 50 + gnuradio-core/src/lib/general/gr_agc_ff.i | 33 + .../general/gr_align_on_samplenumbers_ss.cc | 461 + .../general/gr_align_on_samplenumbers_ss.h | 89 + .../general/gr_align_on_samplenumbers_ss.i | 33 + .../src/lib/general/gr_binary_slicer_fb.cc | 64 + .../src/lib/general/gr_binary_slicer_fb.h | 51 + .../src/lib/general/gr_binary_slicer_fb.i | 33 + .../src/lib/general/gr_bytes_to_syms.cc | 74 + .../src/lib/general/gr_bytes_to_syms.h | 60 + .../src/lib/general/gr_bytes_to_syms.i | 30 + .../src/lib/general/gr_char_to_float.cc | 55 + .../src/lib/general/gr_char_to_float.h | 51 + .../src/lib/general/gr_char_to_float.i | 30 + .../src/lib/general/gr_check_counting_s.cc | 190 + .../src/lib/general/gr_check_counting_s.h | 88 + .../src/lib/general/gr_check_counting_s.i | 31 + .../src/lib/general/gr_check_lfsr_32k_s.cc | 169 + .../src/lib/general/gr_check_lfsr_32k_s.h | 102 + .../src/lib/general/gr_check_lfsr_32k_s.i | 36 + .../lib/general/gr_chunks_to_symbols_XX.cc.t | 73 + .../lib/general/gr_chunks_to_symbols_XX.h.t | 72 + .../lib/general/gr_chunks_to_symbols_XX.i.t | 37 + .../src/lib/general/gr_circular_file.cc | 194 + .../src/lib/general/gr_circular_file.h | 58 + .../lib/general/gr_clock_recovery_mm_cc.cc | 182 + .../src/lib/general/gr_clock_recovery_mm_cc.h | 105 + .../src/lib/general/gr_clock_recovery_mm_cc.i | 49 + .../lib/general/gr_clock_recovery_mm_ff.cc | 140 + .../src/lib/general/gr_clock_recovery_mm_ff.h | 93 + .../src/lib/general/gr_clock_recovery_mm_ff.i | 45 + .../gr_complex_to_interleaved_short.cc | 62 + .../general/gr_complex_to_interleaved_short.h | 51 + .../general/gr_complex_to_interleaved_short.i | 30 + .../src/lib/general/gr_complex_to_xxx.cc | 199 + .../src/lib/general/gr_complex_to_xxx.h | 137 + .../src/lib/general/gr_complex_to_xxx.i | 57 + .../src/lib/general/gr_conjugate_cc.cc | 71 + .../src/lib/general/gr_conjugate_cc.h | 51 + .../src/lib/general/gr_conjugate_cc.i | 33 + .../general/gr_constellation_decoder_cb.cc | 113 + .../lib/general/gr_constellation_decoder_cb.h | 61 + .../lib/general/gr_constellation_decoder_cb.i | 43 + .../general/gr_correlate_access_code_bb.cc | 129 + .../lib/general/gr_correlate_access_code_bb.h | 85 + .../lib/general/gr_correlate_access_code_bb.i | 60 + .../src/lib/general/gr_costas_loop_cc.cc | 118 + .../src/lib/general/gr_costas_loop_cc.h | 72 + .../src/lib/general/gr_costas_loop_cc.i | 37 + .../src/lib/general/gr_count_bits.cc | 93 + gnuradio-core/src/lib/general/gr_count_bits.h | 31 + gnuradio-core/src/lib/general/gr_crc32.cc | 130 + gnuradio-core/src/lib/general/gr_crc32.h | 43 + gnuradio-core/src/lib/general/gr_crc32.i | 27 + .../src/lib/general/gr_ctcss_squelch_ff.cc | 112 + .../src/lib/general/gr_ctcss_squelch_ff.h | 67 + .../src/lib/general/gr_ctcss_squelch_ff.i | 39 + .../src/lib/general/gr_dd_mpsk_sync_cc.cc | 195 + .../src/lib/general/gr_dd_mpsk_sync_cc.h | 92 + .../src/lib/general/gr_dd_mpsk_sync_cc.i | 34 + .../src/lib/general/gr_deinterleave.cc | 78 + .../src/lib/general/gr_deinterleave.h | 56 + .../src/lib/general/gr_deinterleave.i | 30 + .../src/lib/general/gr_diff_decoder_bb.cc | 61 + .../src/lib/general/gr_diff_decoder_bb.h | 52 + .../src/lib/general/gr_diff_decoder_bb.i | 31 + .../src/lib/general/gr_diff_encoder_bb.cc | 62 + .../src/lib/general/gr_diff_encoder_bb.h | 53 + .../src/lib/general/gr_diff_encoder_bb.i | 31 + .../src/lib/general/gr_diff_phasor_cc.cc | 61 + .../src/lib/general/gr_diff_phasor_cc.h | 48 + .../src/lib/general/gr_diff_phasor_cc.i | 34 + .../src/lib/general/gr_divide_XX.cc.t | 71 + .../src/lib/general/gr_divide_XX.h.t | 54 + .../src/lib/general/gr_divide_XX.i.t | 33 + gnuradio-core/src/lib/general/gr_endianness.h | 27 + gnuradio-core/src/lib/general/gr_endianness.i | 23 + gnuradio-core/src/lib/general/gr_expj.h | 37 + .../lib/general/gr_fake_channel_coder_pp.cc | 112 + .../lib/general/gr_fake_channel_coder_pp.h | 90 + .../lib/general/gr_fake_channel_coder_pp.i | 53 + .../src/lib/general/gr_fast_atan2f.cc | 198 + gnuradio-core/src/lib/general/gr_feval.cc | 86 + gnuradio-core/src/lib/general/gr_feval.h | 116 + gnuradio-core/src/lib/general/gr_feval.i | 69 + gnuradio-core/src/lib/general/gr_fft_vcc.cc | 102 + gnuradio-core/src/lib/general/gr_fft_vcc.h | 62 + gnuradio-core/src/lib/general/gr_fft_vcc.i | 35 + gnuradio-core/src/lib/general/gr_fft_vfc.cc | 116 + gnuradio-core/src/lib/general/gr_fft_vfc.h | 62 + gnuradio-core/src/lib/general/gr_fft_vfc.i | 35 + gnuradio-core/src/lib/general/gr_firdes.cc | 584 + gnuradio-core/src/lib/general/gr_firdes.h | 225 + gnuradio-core/src/lib/general/gr_firdes.i | 187 + .../src/lib/general/gr_float_to_char.cc | 58 + .../src/lib/general/gr_float_to_char.h | 51 + .../src/lib/general/gr_float_to_char.i | 30 + .../src/lib/general/gr_float_to_complex.cc | 71 + .../src/lib/general/gr_float_to_complex.h | 52 + .../src/lib/general/gr_float_to_complex.i | 30 + .../src/lib/general/gr_float_to_short.cc | 58 + .../src/lib/general/gr_float_to_short.h | 51 + .../src/lib/general/gr_float_to_short.i | 30 + .../src/lib/general/gr_float_to_uchar.cc | 58 + .../src/lib/general/gr_float_to_uchar.h | 51 + .../src/lib/general/gr_float_to_uchar.i | 30 + .../src/lib/general/gr_framer_sink_1.cc | 175 + .../src/lib/general/gr_framer_sink_1.h | 103 + .../src/lib/general/gr_framer_sink_1.i | 35 + .../lib/general/gr_frequency_modulator_fc.cc | 70 + .../lib/general/gr_frequency_modulator_fc.h | 56 + .../lib/general/gr_frequency_modulator_fc.i | 31 + gnuradio-core/src/lib/general/gr_fxpt.cc | 57 + gnuradio-core/src/lib/general/gr_fxpt.h | 82 + gnuradio-core/src/lib/general/gr_fxpt_nco.h | 151 + gnuradio-core/src/lib/general/gr_fxpt_vco.h | 71 + gnuradio-core/src/lib/general/gr_head.cc | 60 + gnuradio-core/src/lib/general/gr_head.h | 54 + gnuradio-core/src/lib/general/gr_head.i | 30 + .../src/lib/general/gr_interleave.cc | 77 + gnuradio-core/src/lib/general/gr_interleave.h | 56 + gnuradio-core/src/lib/general/gr_interleave.i | 30 + .../gr_interleaved_short_to_complex.cc | 59 + .../general/gr_interleaved_short_to_complex.h | 51 + .../general/gr_interleaved_short_to_complex.i | 30 + .../src/lib/general/gr_keep_one_in_n.cc | 81 + .../src/lib/general/gr_keep_one_in_n.h | 60 + .../src/lib/general/gr_keep_one_in_n.i | 35 + .../src/lib/general/gr_kludge_copy.cc | 64 + .../src/lib/general/gr_kludge_copy.h | 55 + .../src/lib/general/gr_kludge_copy.i | 31 + .../src/lib/general/gr_lfsr_32k_source_s.cc | 70 + .../src/lib/general/gr_lfsr_32k_source_s.h | 60 + .../src/lib/general/gr_lfsr_32k_source_s.i | 31 + .../src/lib/general/gr_lms_dfe_cc.cc | 148 + gnuradio-core/src/lib/general/gr_lms_dfe_cc.h | 64 + gnuradio-core/src/lib/general/gr_lms_dfe_cc.i | 37 + .../src/lib/general/gr_lms_dfe_ff.cc | 122 + gnuradio-core/src/lib/general/gr_lms_dfe_ff.h | 62 + gnuradio-core/src/lib/general/gr_lms_dfe_ff.i | 34 + gnuradio-core/src/lib/general/gr_log2_const.h | 46 + gnuradio-core/src/lib/general/gr_map_bb.cc | 61 + gnuradio-core/src/lib/general/gr_map_bb.h | 51 + gnuradio-core/src/lib/general/gr_map_bb.i | 32 + gnuradio-core/src/lib/general/gr_math.cc | 102 + gnuradio-core/src/lib/general/gr_math.h | 60 + gnuradio-core/src/lib/general/gr_misc.cc | 65 + gnuradio-core/src/lib/general/gr_misc.h | 38 + .../src/lib/general/gr_multiply_XX.cc.t | 62 + .../src/lib/general/gr_multiply_XX.h.t | 54 + .../src/lib/general/gr_multiply_XX.i.t | 33 + .../src/lib/general/gr_multiply_const_XX.cc.t | 72 + .../src/lib/general/gr_multiply_const_XX.h.t | 55 + .../src/lib/general/gr_multiply_const_XX.i.t | 37 + .../lib/general/gr_multiply_const_vXX.cc.t | 61 + .../src/lib/general/gr_multiply_const_vXX.h.t | 55 + .../src/lib/general/gr_multiply_const_vXX.i.t | 37 + .../src/lib/general/gr_multiply_vXX.cc.t | 65 + .../src/lib/general/gr_multiply_vXX.h.t | 54 + .../src/lib/general/gr_multiply_vXX.i.t | 33 + gnuradio-core/src/lib/general/gr_mute_XX.cc.t | 79 + gnuradio-core/src/lib/general/gr_mute_XX.h.t | 55 + gnuradio-core/src/lib/general/gr_mute_XX.i.t | 37 + gnuradio-core/src/lib/general/gr_nco.h | 197 + gnuradio-core/src/lib/general/gr_nlog10_ff.cc | 64 + gnuradio-core/src/lib/general/gr_nlog10_ff.h | 55 + gnuradio-core/src/lib/general/gr_nlog10_ff.i | 33 + .../src/lib/general/gr_noise_source_X.cc.t | 99 + .../src/lib/general/gr_noise_source_X.h.t | 63 + .../src/lib/general/gr_noise_source_X.i.t | 37 + gnuradio-core/src/lib/general/gr_noise_type.h | 30 + gnuradio-core/src/lib/general/gr_nop.cc | 55 + gnuradio-core/src/lib/general/gr_nop.h | 49 + gnuradio-core/src/lib/general/gr_nop.i | 30 + gnuradio-core/src/lib/general/gr_null_sink.cc | 49 + gnuradio-core/src/lib/general/gr_null_sink.h | 51 + gnuradio-core/src/lib/general/gr_null_sink.i | 30 + .../src/lib/general/gr_null_source.cc | 51 + .../src/lib/general/gr_null_source.h | 49 + .../src/lib/general/gr_null_source.i | 30 + .../lib/general/gr_pa_2x2_phase_combiner.cc | 74 + .../lib/general/gr_pa_2x2_phase_combiner.h | 62 + .../lib/general/gr_pa_2x2_phase_combiner.i | 34 + .../lib/general/gr_packed_to_unpacked_XX.cc.t | 133 + .../lib/general/gr_packed_to_unpacked_XX.h.t | 84 + .../lib/general/gr_packed_to_unpacked_XX.i.t | 33 + .../src/lib/general/gr_packet_sink.cc | 206 + .../src/lib/general/gr_packet_sink.h | 111 + .../src/lib/general/gr_packet_sink.i | 41 + .../src/lib/general/gr_phase_modulator_fc.cc | 62 + .../src/lib/general/gr_phase_modulator_fc.h | 55 + .../src/lib/general/gr_phase_modulator_fc.i | 31 + .../lib/general/gr_pll_carriertracking_cc.cc | 117 + .../lib/general/gr_pll_carriertracking_cc.h | 70 + .../lib/general/gr_pll_carriertracking_cc.i | 38 + .../src/lib/general/gr_pll_freqdet_cf.cc | 94 + .../src/lib/general/gr_pll_freqdet_cf.h | 64 + .../src/lib/general/gr_pll_freqdet_cf.i | 32 + .../src/lib/general/gr_pll_refout_cc.cc | 97 + .../src/lib/general/gr_pll_refout_cc.h | 66 + .../src/lib/general/gr_pll_refout_cc.i | 32 + gnuradio-core/src/lib/general/gr_prefix.cc.in | 29 + gnuradio-core/src/lib/general/gr_prefix.h | 33 + gnuradio-core/src/lib/general/gr_prefix.i | 5 + gnuradio-core/src/lib/general/gr_prefs.cc | 88 + gnuradio-core/src/lib/general/gr_prefs.h | 82 + gnuradio-core/src/lib/general/gr_prefs.i | 72 + .../lib/general/gr_probe_avg_mag_sqrd_c.cc | 84 + .../src/lib/general/gr_probe_avg_mag_sqrd_c.h | 74 + .../src/lib/general/gr_probe_avg_mag_sqrd_c.i | 36 + .../lib/general/gr_probe_avg_mag_sqrd_f.cc | 84 + .../src/lib/general/gr_probe_avg_mag_sqrd_f.h | 74 + .../src/lib/general/gr_probe_avg_mag_sqrd_f.i | 36 + .../src/lib/general/gr_probe_signal_f.cc | 60 + .../src/lib/general/gr_probe_signal_f.h | 57 + .../src/lib/general/gr_probe_signal_f.i | 32 + .../src/lib/general/gr_pwr_squelch_cc.cc | 55 + .../src/lib/general/gr_pwr_squelch_cc.h | 62 + .../src/lib/general/gr_pwr_squelch_cc.i | 40 + .../src/lib/general/gr_pwr_squelch_ff.cc | 55 + .../src/lib/general/gr_pwr_squelch_ff.h | 62 + .../src/lib/general/gr_pwr_squelch_ff.i | 40 + .../src/lib/general/gr_quadrature_demod_cf.cc | 62 + .../src/lib/general/gr_quadrature_demod_cf.h | 53 + .../src/lib/general/gr_quadrature_demod_cf.i | 30 + gnuradio-core/src/lib/general/gr_random.cc | 180 + gnuradio-core/src/lib/general/gr_random.h | 63 + gnuradio-core/src/lib/general/gr_remez.cc | 1031 ++ gnuradio-core/src/lib/general/gr_remez.h | 63 + gnuradio-core/src/lib/general/gr_remez.i | 32 + gnuradio-core/src/lib/general/gr_reverse.cc | 60 + gnuradio-core/src/lib/general/gr_reverse.h | 33 + gnuradio-core/src/lib/general/gr_rms_cf.cc | 71 + gnuradio-core/src/lib/general/gr_rms_cf.h | 59 + gnuradio-core/src/lib/general/gr_rms_cf.i | 33 + gnuradio-core/src/lib/general/gr_rms_ff.cc | 71 + gnuradio-core/src/lib/general/gr_rms_ff.h | 59 + gnuradio-core/src/lib/general/gr_rms_ff.i | 33 + .../src/lib/general/gr_short_to_float.cc | 58 + .../src/lib/general/gr_short_to_float.h | 51 + .../src/lib/general/gr_short_to_float.i | 30 + .../src/lib/general/gr_sig_source_X.cc.t | 149 + .../src/lib/general/gr_sig_source_X.h.t | 81 + .../src/lib/general/gr_sig_source_X.i.t | 52 + .../src/lib/general/gr_sig_source_waveform.h | 29 + .../src/lib/general/gr_simple_correlator.cc | 230 + .../src/lib/general/gr_simple_correlator.h | 109 + .../src/lib/general/gr_simple_correlator.i | 31 + .../src/lib/general/gr_simple_framer.cc | 100 + .../src/lib/general/gr_simple_framer.h | 58 + .../src/lib/general/gr_simple_framer.i | 31 + .../src/lib/general/gr_simple_framer_sync.h | 49 + .../src/lib/general/gr_simple_squelch_cc.cc | 99 + .../src/lib/general/gr_simple_squelch_cc.h | 65 + .../src/lib/general/gr_simple_squelch_cc.i | 37 + gnuradio-core/src/lib/general/gr_skiphead.cc | 70 + gnuradio-core/src/lib/general/gr_skiphead.h | 54 + gnuradio-core/src/lib/general/gr_skiphead.i | 30 + .../src/lib/general/gr_squelch_base_cc.cc | 93 + .../src/lib/general/gr_squelch_base_cc.h | 58 + .../src/lib/general/gr_squelch_base_cc.i | 40 + .../src/lib/general/gr_squelch_base_ff.cc | 93 + .../src/lib/general/gr_squelch_base_ff.h | 58 + .../src/lib/general/gr_squelch_base_ff.i | 40 + .../src/lib/general/gr_stream_to_streams.cc | 65 + .../src/lib/general/gr_stream_to_streams.h | 55 + .../src/lib/general/gr_stream_to_streams.i | 34 + .../src/lib/general/gr_stream_to_vector.cc | 57 + .../src/lib/general/gr_stream_to_vector.h | 54 + .../src/lib/general/gr_stream_to_vector.i | 34 + .../src/lib/general/gr_streams_to_stream.cc | 67 + .../src/lib/general/gr_streams_to_stream.h | 55 + .../src/lib/general/gr_streams_to_stream.i | 34 + .../src/lib/general/gr_streams_to_vector.cc | 63 + .../src/lib/general/gr_streams_to_vector.h | 53 + .../src/lib/general/gr_streams_to_vector.i | 34 + gnuradio-core/src/lib/general/gr_sub_XX.cc.t | 70 + gnuradio-core/src/lib/general/gr_sub_XX.h.t | 54 + gnuradio-core/src/lib/general/gr_sub_XX.i.t | 33 + .../src/lib/general/gr_sync_block.cc | 68 + gnuradio-core/src/lib/general/gr_sync_block.h | 65 + gnuradio-core/src/lib/general/gr_sync_block.i | 29 + .../src/lib/general/gr_sync_decimator.cc | 69 + .../src/lib/general/gr_sync_decimator.h | 68 + .../src/lib/general/gr_sync_decimator.i | 31 + .../src/lib/general/gr_sync_interpolator.cc | 70 + .../src/lib/general/gr_sync_interpolator.h | 68 + .../src/lib/general/gr_sync_interpolator.i | 31 + gnuradio-core/src/lib/general/gr_test.cc | 176 + gnuradio-core/src/lib/general/gr_test.h | 199 + gnuradio-core/src/lib/general/gr_test.i | 64 + gnuradio-core/src/lib/general/gr_test_types.h | 46 + .../src/lib/general/gr_threshold_ff.cc | 67 + .../src/lib/general/gr_threshold_ff.h | 58 + .../src/lib/general/gr_threshold_ff.i | 39 + gnuradio-core/src/lib/general/gr_throttle.cc | 109 + gnuradio-core/src/lib/general/gr_throttle.h | 63 + gnuradio-core/src/lib/general/gr_throttle.i | 30 + .../src/lib/general/gr_uchar_to_float.cc | 55 + .../src/lib/general/gr_uchar_to_float.h | 51 + .../src/lib/general/gr_uchar_to_float.i | 30 + .../src/lib/general/gr_unpack_k_bits_bb.cc | 70 + .../src/lib/general/gr_unpack_k_bits_bb.h | 54 + .../src/lib/general/gr_unpack_k_bits_bb.i | 34 + .../lib/general/gr_unpacked_to_packed_XX.cc.t | 125 + .../lib/general/gr_unpacked_to_packed_XX.h.t | 81 + .../lib/general/gr_unpacked_to_packed_XX.i.t | 33 + gnuradio-core/src/lib/general/gr_vco.h | 93 + gnuradio-core/src/lib/general/gr_vco_f.cc | 58 + gnuradio-core/src/lib/general/gr_vco_f.h | 72 + gnuradio-core/src/lib/general/gr_vco_f.i | 38 + .../src/lib/general/gr_vector_sink_X.cc.t | 63 + .../src/lib/general/gr_vector_sink_X.h.t | 55 + .../src/lib/general/gr_vector_sink_X.i.t | 37 + .../src/lib/general/gr_vector_source_X.cc.t | 85 + .../src/lib/general/gr_vector_source_X.h.t | 57 + .../src/lib/general/gr_vector_source_X.i.t | 33 + .../src/lib/general/gr_vector_to_stream.cc | 57 + .../src/lib/general/gr_vector_to_stream.h | 53 + .../src/lib/general/gr_vector_to_stream.i | 34 + .../src/lib/general/gr_vector_to_streams.cc | 63 + .../src/lib/general/gr_vector_to_streams.h | 53 + .../src/lib/general/gr_vector_to_streams.i | 34 + .../src/lib/general/gri_add_const_ss.h | 36 + .../lib/general/gri_add_const_ss_generic.cc | 49 + gnuradio-core/src/lib/general/gri_agc.h | 70 + gnuradio-core/src/lib/general/gri_agc.i | 36 + gnuradio-core/src/lib/general/gri_agc_cc.h | 71 + gnuradio-core/src/lib/general/gri_agc_cc.i | 40 + .../src/lib/general/gri_char_to_float.cc | 40 + .../src/lib/general/gri_char_to_float.h | 32 + .../src/lib/general/gri_debugger_hook.cc | 29 + .../src/lib/general/gri_debugger_hook.h | 28 + gnuradio-core/src/lib/general/gri_fft.cc | 229 + gnuradio-core/src/lib/general/gri_fft.h | 122 + .../src/lib/general/gri_float_to_char.cc | 42 + .../src/lib/general/gri_float_to_char.h | 32 + .../src/lib/general/gri_float_to_short.cc | 42 + .../src/lib/general/gri_float_to_short.h | 32 + .../src/lib/general/gri_float_to_uchar.cc | 42 + .../src/lib/general/gri_float_to_uchar.h | 32 + .../gri_interleaved_short_to_complex.cc | 39 + .../gri_interleaved_short_to_complex.h | 37 + .../src/lib/general/gri_lfsr_15_1_0.h | 57 + gnuradio-core/src/lib/general/gri_lfsr_32k.h | 78 + .../src/lib/general/gri_short_to_float.cc | 40 + .../src/lib/general/gri_short_to_float.h | 32 + .../src/lib/general/gri_uchar_to_float.cc | 40 + .../src/lib/general/gri_uchar_to_float.h | 32 + gnuradio-core/src/lib/general/malloc16.c | 46 + gnuradio-core/src/lib/general/malloc16.h | 35 + gnuradio-core/src/lib/general/qa_general.cc | 47 + gnuradio-core/src/lib/general/qa_general.h | 37 + .../src/lib/general/qa_gr_circular_file.cc | 72 + .../src/lib/general/qa_gr_circular_file.h | 40 + gnuradio-core/src/lib/general/qa_gr_firdes.cc | 344 + gnuradio-core/src/lib/general/qa_gr_firdes.h | 46 + gnuradio-core/src/lib/general/qa_gr_fxpt.cc | 94 + gnuradio-core/src/lib/general/qa_gr_fxpt.h | 48 + .../src/lib/general/qa_gr_fxpt_nco.cc | 119 + .../src/lib/general/qa_gr_fxpt_nco.h | 48 + .../src/lib/general/qa_gr_fxpt_vco.cc | 110 + .../src/lib/general/qa_gr_fxpt_vco.h | 48 + gnuradio-core/src/lib/general/random.h | 32 + gnuradio-core/src/lib/general/sine_table.h | 1025 ++ gnuradio-core/src/lib/io/Makefile.am | 96 + .../src/lib/io/gr_file_descriptor_sink.cc | 83 + .../src/lib/io/gr_file_descriptor_sink.h | 58 + .../src/lib/io/gr_file_descriptor_sink.i | 35 + .../src/lib/io/gr_file_descriptor_source.cc | 146 + .../src/lib/io/gr_file_descriptor_source.h | 67 + .../src/lib/io/gr_file_descriptor_source.i | 35 + gnuradio-core/src/lib/io/gr_file_sink.cc | 144 + gnuradio-core/src/lib/io/gr_file_sink.h | 75 + gnuradio-core/src/lib/io/gr_file_sink.i | 45 + gnuradio-core/src/lib/io/gr_file_source.cc | 131 + gnuradio-core/src/lib/io/gr_file_source.h | 68 + gnuradio-core/src/lib/io/gr_file_source.i | 43 + gnuradio-core/src/lib/io/gr_message_sink.cc | 78 + gnuradio-core/src/lib/io/gr_message_sink.h | 62 + gnuradio-core/src/lib/io/gr_message_sink.i | 36 + gnuradio-core/src/lib/io/gr_message_source.cc | 104 + gnuradio-core/src/lib/io/gr_message_source.h | 64 + gnuradio-core/src/lib/io/gr_message_source.i | 36 + gnuradio-core/src/lib/io/gr_oscope_guts.cc | 382 + gnuradio-core/src/lib/io/gr_oscope_guts.h | 116 + gnuradio-core/src/lib/io/gr_oscope_sink.i | 79 + gnuradio-core/src/lib/io/gr_oscope_sink_f.cc | 80 + gnuradio-core/src/lib/io/gr_oscope_sink_f.h | 65 + gnuradio-core/src/lib/io/gr_oscope_sink_x.cc | 138 + gnuradio-core/src/lib/io/gr_oscope_sink_x.h | 73 + gnuradio-core/src/lib/io/gr_trigger_mode.h | 32 + gnuradio-core/src/lib/io/gri_logger.cc | 173 + gnuradio-core/src/lib/io/gri_logger.h | 55 + gnuradio-core/src/lib/io/i2c.cc | 28 + gnuradio-core/src/lib/io/i2c.h | 48 + gnuradio-core/src/lib/io/i2c_bbio.cc | 29 + gnuradio-core/src/lib/io/i2c_bbio.h | 49 + gnuradio-core/src/lib/io/i2c_bbio_pp.cc | 87 + gnuradio-core/src/lib/io/i2c_bbio_pp.h | 55 + gnuradio-core/src/lib/io/i2c_bitbang.cc | 144 + gnuradio-core/src/lib/io/i2c_bitbang.h | 63 + gnuradio-core/src/lib/io/io.i | 52 + gnuradio-core/src/lib/io/microtune_4702.cc | 183 + gnuradio-core/src/lib/io/microtune_4702.h | 69 + .../src/lib/io/microtune_4702_eval_board.cc | 88 + .../src/lib/io/microtune_4702_eval_board.h | 47 + .../src/lib/io/microtune_4702_eval_board.i | 36 + gnuradio-core/src/lib/io/microtune_4937.cc | 146 + gnuradio-core/src/lib/io/microtune_4937.h | 66 + .../src/lib/io/microtune_4937_eval_board.cc | 97 + .../src/lib/io/microtune_4937_eval_board.h | 48 + .../src/lib/io/microtune_4937_eval_board.i | 36 + .../src/lib/io/microtune_eval_board.i | 95 + .../src/lib/io/microtune_eval_board_defs.h | 71 + gnuradio-core/src/lib/io/microtune_xxxx.cc | 41 + gnuradio-core/src/lib/io/microtune_xxxx.h | 64 + .../src/lib/io/microtune_xxxx_eval_board.cc | 140 + .../src/lib/io/microtune_xxxx_eval_board.h | 96 + .../src/lib/io/microtune_xxxx_eval_board.i | 58 + gnuradio-core/src/lib/io/ppio.cc | 39 + gnuradio-core/src/lib/io/ppio.h | 61 + gnuradio-core/src/lib/io/ppio.i | 48 + gnuradio-core/src/lib/io/ppio_ppdev.cc | 221 + gnuradio-core/src/lib/io/ppio_ppdev.h | 60 + gnuradio-core/src/lib/io/sdr_1000.cc | 65 + gnuradio-core/src/lib/io/sdr_1000.h | 51 + gnuradio-core/src/lib/io/sdr_1000.i | 36 + gnuradio-core/src/lib/missing/Makefile.am | 33 + .../src/lib/missing/bug_work_around_8.cc | 2 + gnuradio-core/src/lib/missing/getopt.c | 733 ++ gnuradio-core/src/lib/missing/getopt.h | 129 + gnuradio-core/src/lib/missing/gettimeofday.c | 50 + gnuradio-core/src/lib/missing/usleep.c | 67 + gnuradio-core/src/lib/omnithread/Makefile.am | 67 + gnuradio-core/src/lib/omnithread/dir.mk | 229 + gnuradio-core/src/lib/omnithread/mach.cc | 714 ++ gnuradio-core/src/lib/omnithread/nt.cc | 967 ++ gnuradio-core/src/lib/omnithread/omnithread.h | 622 + .../src/lib/omnithread/ot_VxThread.h | 118 + gnuradio-core/src/lib/omnithread/ot_mach.h | 51 + gnuradio-core/src/lib/omnithread/ot_nt.h | 85 + gnuradio-core/src/lib/omnithread/ot_posix.h | 81 + .../src/lib/omnithread/ot_pthread_nt.h | 186 + gnuradio-core/src/lib/omnithread/ot_solaris.h | 47 + gnuradio-core/src/lib/omnithread/posix.cc | 972 ++ gnuradio-core/src/lib/omnithread/solaris.cc | 615 + .../src/lib/omnithread/threaddata.cc | 83 + gnuradio-core/src/lib/omnithread/vxWorks.cc | 1160 ++ .../src/lib/reed-solomon/Makefile.am | 55 + .../src/lib/reed-solomon/Makefile.in.karn | 99 + gnuradio-core/src/lib/reed-solomon/README | 5 + .../src/lib/reed-solomon/README.karn | 22 + gnuradio-core/src/lib/reed-solomon/ccsds.h | 1 + gnuradio-core/src/lib/reed-solomon/char.h | 56 + .../src/lib/reed-solomon/decode_rs.c | 262 + .../src/lib/reed-solomon/decode_rs_ccsds.c | 27 + .../src/lib/reed-solomon/encode_rs.c | 47 + .../src/lib/reed-solomon/encode_rs_ccsds.c | 24 + gnuradio-core/src/lib/reed-solomon/exercise.c | 126 + gnuradio-core/src/lib/reed-solomon/fixed.h | 38 + .../src/lib/reed-solomon/gen_ccsds.c | 34 + .../src/lib/reed-solomon/gen_ccsds_tal.c | 50 + gnuradio-core/src/lib/reed-solomon/init_rs.c | 128 + gnuradio-core/src/lib/reed-solomon/int.h | 54 + gnuradio-core/src/lib/reed-solomon/rs.3 | 170 + gnuradio-core/src/lib/reed-solomon/rs.h | 30 + gnuradio-core/src/lib/reed-solomon/rstest.c | 117 + gnuradio-core/src/lib/runtime/Makefile.am | 109 + gnuradio-core/src/lib/runtime/gr_block.cc | 131 + gnuradio-core/src/lib/runtime/gr_block.h | 247 + gnuradio-core/src/lib/runtime/gr_block.i | 66 + .../src/lib/runtime/gr_block_detail.cc | 108 + .../src/lib/runtime/gr_block_detail.h | 99 + .../src/lib/runtime/gr_block_detail.i | 66 + gnuradio-core/src/lib/runtime/gr_buffer.cc | 248 + gnuradio-core/src/lib/runtime/gr_buffer.h | 196 + gnuradio-core/src/lib/runtime/gr_buffer.i | 63 + gnuradio-core/src/lib/runtime/gr_complex.h | 46 + .../src/lib/runtime/gr_dispatcher.cc | 192 + gnuradio-core/src/lib/runtime/gr_dispatcher.h | 67 + gnuradio-core/src/lib/runtime/gr_dispatcher.i | 55 + .../src/lib/runtime/gr_error_handler.cc | 244 + .../src/lib/runtime/gr_error_handler.h | 114 + .../src/lib/runtime/gr_error_handler.i | 69 + .../src/lib/runtime/gr_io_signature.cc | 54 + .../src/lib/runtime/gr_io_signature.h | 65 + .../src/lib/runtime/gr_io_signature.i | 49 + .../src/lib/runtime/gr_local_sighandler.cc | 186 + .../src/lib/runtime/gr_local_sighandler.h | 60 + gnuradio-core/src/lib/runtime/gr_message.cc | 77 + gnuradio-core/src/lib/runtime/gr_message.h | 89 + gnuradio-core/src/lib/runtime/gr_message.i | 65 + .../src/lib/runtime/gr_msg_handler.cc | 30 + .../src/lib/runtime/gr_msg_handler.h | 41 + .../src/lib/runtime/gr_msg_handler.i | 32 + gnuradio-core/src/lib/runtime/gr_msg_queue.cc | 127 + gnuradio-core/src/lib/runtime/gr_msg_queue.h | 89 + gnuradio-core/src/lib/runtime/gr_msg_queue.i | 111 + gnuradio-core/src/lib/runtime/gr_pagesize.cc | 56 + gnuradio-core/src/lib/runtime/gr_pagesize.h | 32 + .../src/lib/runtime/gr_preferences.cc | 101 + .../src/lib/runtime/gr_preferences.h | 32 + gnuradio-core/src/lib/runtime/gr_realtime.cc | 71 + gnuradio-core/src/lib/runtime/gr_realtime.h | 39 + gnuradio-core/src/lib/runtime/gr_realtime.i | 4 + gnuradio-core/src/lib/runtime/gr_runtime.h | 44 + .../src/lib/runtime/gr_select_handler.cc | 36 + .../src/lib/runtime/gr_select_handler.h | 83 + .../runtime/gr_single_threaded_scheduler.cc | 360 + .../runtime/gr_single_threaded_scheduler.h | 61 + .../runtime/gr_single_threaded_scheduler.i | 52 + .../src/lib/runtime/gr_swig_block_magic.i | 45 + gnuradio-core/src/lib/runtime/gr_timer.h | 82 + gnuradio-core/src/lib/runtime/gr_tmp_path.cc | 52 + gnuradio-core/src/lib/runtime/gr_tmp_path.h | 31 + gnuradio-core/src/lib/runtime/gr_types.h | 63 + gnuradio-core/src/lib/runtime/gr_vmcircbuf.cc | 291 + gnuradio-core/src/lib/runtime/gr_vmcircbuf.h | 120 + .../runtime/gr_vmcircbuf_createfilemapping.cc | 191 + .../runtime/gr_vmcircbuf_createfilemapping.h | 74 + .../lib/runtime/gr_vmcircbuf_mmap_shm_open.cc | 205 + .../lib/runtime/gr_vmcircbuf_mmap_shm_open.h | 65 + .../lib/runtime/gr_vmcircbuf_mmap_tmpfile.cc | 198 + .../lib/runtime/gr_vmcircbuf_mmap_tmpfile.h | 65 + .../src/lib/runtime/gr_vmcircbuf_sysv_shm.cc | 192 + .../src/lib/runtime/gr_vmcircbuf_sysv_shm.h | 65 + gnuradio-core/src/lib/runtime/qa_gr_block.cc | 89 + gnuradio-core/src/lib/runtime/qa_gr_block.h | 48 + gnuradio-core/src/lib/runtime/qa_gr_buffer.cc | 307 + gnuradio-core/src/lib/runtime/qa_gr_buffer.h | 53 + .../src/lib/runtime/qa_gr_io_signature.cc | 55 + .../src/lib/runtime/qa_gr_io_signature.h | 47 + .../src/lib/runtime/qa_gr_vmcircbuf.cc | 40 + .../src/lib/runtime/qa_gr_vmcircbuf.h | 39 + gnuradio-core/src/lib/runtime/qa_runtime.cc | 49 + gnuradio-core/src/lib/runtime/qa_runtime.h | 37 + gnuradio-core/src/lib/runtime/runtime.i | 49 + .../src/lib/runtime/test_shared_block_ptr.cc | 53 + gnuradio-core/src/lib/swig/Makefile.am | 111 + gnuradio-core/src/lib/swig/atsc.i | 136 + gnuradio-core/src/lib/swig/gen-swig-bug-fix | 111 + gnuradio-core/src/lib/swig/gnuradio.i | 84 + gnuradio-core/src/lib/swig/shared_ptr.i | 43 + gnuradio-core/src/python/Makefile.am | 29 + gnuradio-core/src/python/bin/Makefile.am | 30 + gnuradio-core/src/python/bin/microtune.py | 42 + gnuradio-core/src/python/build_utils.py | 163 + gnuradio-core/src/python/build_utils_codes.py | 52 + gnuradio-core/src/python/gnuradio/Makefile.am | 36 + gnuradio-core/src/python/gnuradio/__init__.py | 1 + gnuradio-core/src/python/gnuradio/audio.py | 88 + .../src/python/gnuradio/blks/Makefile.am | 35 + .../src/python/gnuradio/blks/__init__.py | 37 + .../src/python/gnuradio/blksimpl/Makefile.am | 49 + .../src/python/gnuradio/blksimpl/__init__.py | 1 + .../src/python/gnuradio/blksimpl/am_demod.py | 75 + .../gnuradio/blksimpl/digital_voice.py.real | 102 + .../python/gnuradio/blksimpl/filterbank.py | 160 + .../src/python/gnuradio/blksimpl/fm_demod.py | 122 + .../src/python/gnuradio/blksimpl/fm_emph.py | 145 + .../src/python/gnuradio/blksimpl/gmsk2.py | 159 + .../src/python/gnuradio/blksimpl/gmsk2_pkt.py | 174 + .../src/python/gnuradio/blksimpl/nbfm_rx.py | 87 + .../src/python/gnuradio/blksimpl/nbfm_tx.py | 95 + .../src/python/gnuradio/blksimpl/pkt.py | 156 + .../gnuradio/blksimpl/rational_resampler.py | 137 + .../gnuradio/blksimpl/standard_squelch.py | 73 + .../src/python/gnuradio/blksimpl/wfm_rcv.py | 72 + .../python/gnuradio/blksimpl/wfm_rcv_pll.py | 206 + .../src/python/gnuradio/blksimpl/wfm_tx.py | 79 + .../src/python/gnuradio/eng_notation.py | 71 + .../src/python/gnuradio/eng_option.py | 80 + .../src/python/gnuradio/gr/Makefile.am | 77 + .../src/python/gnuradio/gr/__init__.py | 40 + .../python/gnuradio/gr/basic_flow_graph.py | 267 + .../python/gnuradio/gr/benchmark_filters.py | 55 + .../src/python/gnuradio/gr/exceptions.py | 27 + .../src/python/gnuradio/gr/flow_graph.py | 234 + .../src/python/gnuradio/gr/gr_threading.py | 35 + .../src/python/gnuradio/gr/gr_threading_23.py | 724 ++ .../src/python/gnuradio/gr/gr_threading_24.py | 793 ++ .../src/python/gnuradio/gr/hier_block.py | 132 + gnuradio-core/src/python/gnuradio/gr/prefs.py | 129 + .../python/gnuradio/gr/qa_add_and_friends.py | 129 + .../gnuradio/gr/qa_add_v_and_friends.py | 353 + .../python/gnuradio/gr/qa_basic_flow_graph.py | 190 + .../python/gnuradio/gr/qa_cma_equalizer.py | 29 + .../python/gnuradio/gr/qa_complex_to_xxx.py | 116 + .../gr/qa_constellation_decoder_cb.py | 53 + .../gnuradio/gr/qa_correlate_access_code.py | 83 + .../src/python/gnuradio/gr/qa_diff_encoder.py | 86 + .../python/gnuradio/gr/qa_diff_phasor_cc.py | 50 + .../src/python/gnuradio/gr/qa_feval.py | 92 + .../src/python/gnuradio/gr/qa_fft_filter.py | 268 + .../python/gnuradio/gr/qa_filter_delay_fc.py | 317 + .../src/python/gnuradio/gr/qa_flow_graph.py | 356 + .../gnuradio/gr/qa_frequency_modulator.py | 56 + .../src/python/gnuradio/gr/qa_fsk_stuff.py | 75 + .../src/python/gnuradio/gr/qa_goertzel.py | 64 + .../src/python/gnuradio/gr/qa_head.py | 47 + .../src/python/gnuradio/gr/qa_hilbert.py | 116 + .../src/python/gnuradio/gr/qa_iir.py | 135 + .../src/python/gnuradio/gr/qa_interleave.py | 81 + .../gnuradio/gr/qa_interp_fir_filter.py | 54 + .../src/python/gnuradio/gr/qa_kludge_copy.py | 89 + .../python/gnuradio/gr/qa_kludged_imports.py | 43 + .../src/python/gnuradio/gr/qa_message.py | 117 + .../src/python/gnuradio/gr/qa_mute.py | 89 + .../src/python/gnuradio/gr/qa_nlog10.py | 47 + .../gnuradio/gr/qa_packed_to_unpacked.py | 405 + .../python/gnuradio/gr/qa_pipe_fittings.py | 143 + .../gnuradio/gr/qa_rational_resampler.py | 290 + .../src/python/gnuradio/gr/qa_sig_source.py | 85 + .../python/gnuradio/gr/qa_single_pole_iir.py | 72 + .../gnuradio/gr/qa_single_pole_iir_cc.py | 72 + .../python/gnuradio/gr/qa_unpack_k_bits.py | 57 + .../src/python/gnuradio/gr/run_tests.in | 33 + .../src/python/gnuradio/gr/scheduler.py | 70 + .../src/python/gnuradio/gr_unittest.py | 114 + .../src/python/gnuradio/gru/Makefile.am | 35 + .../src/python/gnuradio/gru/__init__.py | 37 + .../src/python/gnuradio/gruimpl/Makefile.am | 40 + .../src/python/gnuradio/gruimpl/__init__.py | 1 + .../src/python/gnuradio/gruimpl/crc.py | 36 + .../src/python/gnuradio/gruimpl/freqz.py | 344 + .../python/gnuradio/gruimpl/gnuplot_freqz.py | 82 + .../src/python/gnuradio/gruimpl/hexint.py | 32 + .../src/python/gnuradio/gruimpl/listmisc.py | 29 + .../src/python/gnuradio/gruimpl/lmx2306.py | 186 + .../src/python/gnuradio/gruimpl/mathmisc.py | 33 + .../gnuradio/gruimpl/os_read_exactly.py | 36 + .../src/python/gnuradio/gruimpl/sdr_1000.py | 84 + .../gnuradio/gruimpl/seq_with_cursor.py | 77 + .../python/gnuradio/gruimpl/socket_stuff.py | 56 + gnuradio-core/src/python/gnuradio/optfir.py | 242 + .../src/python/gnuradio/packet_utils.py | 433 + gnuradio-core/src/python/gnuradio/window.py | 190 + gnuradio-core/src/tests/Makefile.am | 96 + gnuradio-core/src/tests/benchmark_dotprod.cc | 148 + .../src/tests/benchmark_dotprod_ccc.cc | 149 + .../src/tests/benchmark_dotprod_ccf.cc | 151 + .../src/tests/benchmark_dotprod_fcc.cc | 152 + .../src/tests/benchmark_dotprod_fsf.cc | 151 + .../src/tests/benchmark_dotprod_scc.cc | 151 + gnuradio-core/src/tests/benchmark_nco.cc | 219 + gnuradio-core/src/tests/benchmark_vco.cc | 166 + gnuradio-core/src/tests/nco_results | 48 + gnuradio-core/src/tests/test_all.cc | 46 + gnuradio-core/src/tests/test_atsc.cc | 37 + gnuradio-core/src/tests/test_buffers.py | 136 + gnuradio-core/src/tests/test_filter.cc | 37 + gnuradio-core/src/tests/test_general.cc | 37 + gnuradio-core/src/tests/test_runtime.cc | 37 + gnuradio-core/src/tests/test_vmcircbuf.cc | 44 + gnuradio-core/src/utils/Makefile.am | 43 + gnuradio-core/src/utils/cool.m | 50 + gnuradio-core/src/utils/db_width.m | 35 + gnuradio-core/src/utils/filter_tools.m | 42 + gnuradio-core/src/utils/is_complex.m | 24 + gnuradio-core/src/utils/lp_to_bp.m | 27 + .../partition-cascaded-decimating-filters.scm | 68 + gnuradio-core/src/utils/permute.scm | 27 + .../src/utils/plot_cic_decimator_response.m | 45 + gnuradio-core/src/utils/plot_freq_response.m | 36 + .../src/utils/plot_freq_response_db.m | 39 + .../src/utils/plot_freq_response_phase.m | 38 + gnuradio-core/src/utils/plotfft.m | 40 + gnuradio-core/src/utils/plotfftavgk.m | 61 + gnuradio-core/src/utils/plotfftavgk_db.m | 73 + gnuradio-core/src/utils/plotfftk.m | 41 + gnuradio-core/src/utils/plotfftk_db.m | 43 + gnuradio-core/src/utils/put_markers.m | 32 + gnuradio-core/src/utils/rainbow.m | 53 + gnuradio-core/src/utils/read_char_binary.m | 45 + gnuradio-core/src/utils/read_complex_binary.m | 48 + gnuradio-core/src/utils/read_float_binary.m | 45 + gnuradio-core/src/utils/read_int_binary.m | 46 + gnuradio-core/src/utils/read_short_binary.m | 45 + gnuradio-core/src/utils/read_xambi.m | 46 + gnuradio-core/src/utils/runsum.m | 9 + gnuradio-core/src/utils/single_pole_iir.m | 25 + gnuradio-core/src/utils/write_float_binary.m | 40 + gnuradio-core/src/utils/write_short_binary.m | 40 + gnuradio-examples/AUTHORS | 2 + gnuradio-examples/ChangeLog | 381 + gnuradio-examples/Makefile.am | 28 + gnuradio-examples/NEWS | 0 gnuradio-examples/README | 68 + gnuradio-examples/README.hacking | 39 + gnuradio-examples/python/Makefile.am | 22 + gnuradio-examples/python/apps/README | 26 + .../python/apps/hf_explorer/README | 48 + .../python/apps/hf_explorer/hfx2.py | 786 ++ .../python/apps/hf_explorer/hfx_help | 180 + .../python/apps/hf_radio/README.TXT | 53 + .../python/apps/hf_radio/hfir.sci | 59 + .../python/apps/hf_radio/input.py | 41 + .../python/apps/hf_radio/output.py | 17 + .../python/apps/hf_radio/radio.py | 304 + .../python/apps/hf_radio/radio.xml | 441 + .../python/apps/hf_radio/ssb_taps | 1023 ++ .../python/apps/hf_radio/ssbagc.py | 48 + .../python/apps/hf_radio/ssbdemod.py | 97 + .../python/apps/hf_radio/startup.py | 1 + gnuradio-examples/python/apps/hf_radio/ui.py | 295 + gnuradio-examples/python/audio/Makefile.am | 32 + gnuradio-examples/python/audio/audio_copy.py | 64 + gnuradio-examples/python/audio/audio_play.py | 57 + .../python/audio/audio_to_file.py | 63 + .../python/audio/dial_squelch.py | 89 + gnuradio-examples/python/audio/dial_tone.py | 57 + gnuradio-examples/python/audio/dialtone_v.py | 71 + gnuradio-examples/python/audio/mono_tone.py | 66 + gnuradio-examples/python/audio/multi_tone.py | 90 + .../python/audio/spectrum_inversion.py | 48 + .../python/audio/test_resampler.py | 66 + .../python/digital_voice/Makefile.am | 23 + .../python/digital_voice/encdec.py | 58 + gnuradio-examples/python/gmsk2/Makefile.am | 38 + gnuradio-examples/python/gmsk2/README | 81 + .../python/gmsk2/benchmark_gmsk_rx.py | 128 + .../python/gmsk2/benchmark_gmsk_tx.py | 146 + .../python/gmsk2/benchmark_mpsk_rx.py | 149 + .../python/gmsk2/benchmark_mpsk_tx.py | 157 + gnuradio-examples/python/gmsk2/bpsk.py | 256 + gnuradio-examples/python/gmsk2/dbpsk.py | 282 + gnuradio-examples/python/gmsk2/dqpsk.py | 280 + .../python/gmsk2/fusb_options.py | 31 + .../python/gmsk2/gen_whitener.py | 40 + gnuradio-examples/python/gmsk2/gmsk_test.py | 115 + gnuradio-examples/python/gmsk2/mpsk_test.py | 125 + .../python/gmsk2/pick_bitrate.py | 143 + gnuradio-examples/python/gmsk2/qpsk.py | 418 + gnuradio-examples/python/gmsk2/qpsk_tester.py | 127 + .../python/gmsk2/qpsk_usrp_tester.py | 103 + .../python/gmsk2/receive_path.py | 150 + gnuradio-examples/python/gmsk2/rx_voice.py | 132 + .../python/gmsk2/transmit_path.py | 108 + gnuradio-examples/python/gmsk2/tunnel.py | 300 + gnuradio-examples/python/gmsk2/tx_voice.py | 139 + gnuradio-examples/python/mc4020/Makefile.am | 28 + gnuradio-examples/python/mc4020/fm_demod.py | 150 + gnuradio-examples/python/mc4020/mc4020_fft.py | 53 + .../python/multi-antenna/multi_fft.py | 128 + .../python/multi-antenna/multi_file.py | 136 + .../python/multi-antenna/multi_scope.py | 138 + .../python/multi_usrp/Makefile.am | 28 + gnuradio-examples/python/multi_usrp/README | 260 + .../python/multi_usrp/multi_usrp_oscope.py | 343 + .../python/multi_usrp/multi_usrp_rx_cfile.py | 131 + .../python/networking/measurement_slave.py | 241 + gnuradio-examples/python/usrp/Makefile.am | 52 + gnuradio-examples/python/usrp/am_rcv.py | 115 + gnuradio-examples/python/usrp/ayfabtu.dat | Bin 0 -> 544640 bytes gnuradio-examples/python/usrp/ayfabtu.py | 169 + .../python/usrp/benchmark_usb.py | 106 + gnuradio-examples/python/usrp/dsb_tx.py | 51 + gnuradio-examples/python/usrp/flexrf_debug.py | 169 + .../python/usrp/flexrf_siggen.py | 148 + gnuradio-examples/python/usrp/fm_tx4.py | 171 + .../python/usrp/fm_tx_2_daughterboards.py | 160 + gnuradio-examples/python/usrp/max_power.py | 83 + gnuradio-examples/python/usrp/siggen_min2.py | 62 + .../python/usrp/test_counting.py | 53 + .../python/usrp/test_dft_analysis.py | 72 + .../python/usrp/test_dft_synth.py | 79 + .../usrp/test_digital_loopback_counting.py | 65 + .../python/usrp/test_digital_loopback_lfsr.py | 62 + .../python/usrp/tvrx_am_rcv_gui.py | 154 + gnuradio-examples/python/usrp/usrp_fft.py | 251 + gnuradio-examples/python/usrp/usrp_fft_old.py | 110 + .../python/usrp/usrp_nbfm_ptt.py | 491 + .../python/usrp/usrp_nbfm_rcv.py | 362 + gnuradio-examples/python/usrp/usrp_oscope.py | 252 + .../python/usrp/usrp_rx_cfile.py | 107 + .../python/usrp/usrp_rx_nogui.py | 186 + gnuradio-examples/python/usrp/usrp_siggen.py | 180 + gnuradio-examples/python/usrp/usrp_tv_rcv.py | 394 + .../python/usrp/usrp_tv_rcv_nogui.py | 179 + gnuradio-examples/python/usrp/usrp_wfm_rcv.py | 269 + .../python/usrp/usrp_wfm_rcv2_nogui.py | 144 + .../python/usrp/usrp_wfm_rcv_nogui.py | 153 + .../python/usrp/usrp_wfm_rcv_pll.py | 311 + .../python/usrp/usrp_wxapt_rcv.py | 267 + gnuradio-examples/python/usrp/wfm_rcv_file.py | 99 + gr-atsc/AUTHORS | 3 + gr-atsc/ChangeLog | 37 + gr-atsc/Makefile.am | 28 + gr-atsc/NEWS | 0 gr-atsc/README | 50 + gr-atsc/README.signal_flow | 41 + gr-atsc/doc/Makefile.am | 0 gr-atsc/src/Makefile.am | 22 + gr-atsc/src/lib/GrAtscBitTimingLoop.cc | 223 + gr-atsc/src/lib/GrAtscBitTimingLoop.h | 90 + gr-atsc/src/lib/GrAtscBitTimingLoop2.cc | 173 + gr-atsc/src/lib/GrAtscBitTimingLoop2.h | 80 + gr-atsc/src/lib/GrAtscBitTimingLoop3.cc | 106 + gr-atsc/src/lib/GrAtscBitTimingLoop3.h | 72 + gr-atsc/src/lib/GrAtscConvert2xTo20.cc | 106 + gr-atsc/src/lib/GrAtscConvert2xTo20.h | 50 + gr-atsc/src/lib/GrAtscDataSegToSoftDataSeg.cc | 101 + gr-atsc/src/lib/GrAtscDataSegToSoftDataSeg.h | 50 + gr-atsc/src/lib/GrAtscDeinterleaver.cc | 92 + gr-atsc/src/lib/GrAtscDeinterleaver.h | 51 + gr-atsc/src/lib/GrAtscDerandomizer.cc | 106 + gr-atsc/src/lib/GrAtscDerandomizer.h | 51 + gr-atsc/src/lib/GrAtscEqualizer.cc | 135 + gr-atsc/src/lib/GrAtscEqualizer.h | 59 + gr-atsc/src/lib/GrAtscFPLL.cc | 150 + gr-atsc/src/lib/GrAtscFPLL.h | 88 + gr-atsc/src/lib/GrAtscFieldSyncChecker.cc | 101 + gr-atsc/src/lib/GrAtscFieldSyncChecker.h | 54 + gr-atsc/src/lib/GrAtscFieldSyncCorrelator.cc | 95 + gr-atsc/src/lib/GrAtscFieldSyncCorrelator.h | 56 + gr-atsc/src/lib/GrAtscFieldSyncDemux.cc | 173 + gr-atsc/src/lib/GrAtscFieldSyncDemux.h | 60 + gr-atsc/src/lib/GrAtscFieldSyncMux.cc | 246 + gr-atsc/src/lib/GrAtscFieldSyncMux.h | 58 + gr-atsc/src/lib/GrAtscInterleaver.cc | 101 + gr-atsc/src/lib/GrAtscInterleaver.h | 51 + gr-atsc/src/lib/GrAtscRSDecoder.cc | 81 + gr-atsc/src/lib/GrAtscRSDecoder.h | 51 + gr-atsc/src/lib/GrAtscRSEncoder.cc | 84 + gr-atsc/src/lib/GrAtscRSEncoder.h | 51 + gr-atsc/src/lib/GrAtscRandomizer.cc | 110 + gr-atsc/src/lib/GrAtscRandomizer.h | 55 + gr-atsc/src/lib/GrAtscSegSymSync.cc | 50 + gr-atsc/src/lib/GrAtscSegSymSync.h | 64 + gr-atsc/src/lib/GrAtscSegSymSyncImpl.cc | 103 + gr-atsc/src/lib/GrAtscSegSymSyncImpl.h | 69 + gr-atsc/src/lib/GrAtscSegSymSyncImpl_export.h | 26 + gr-atsc/src/lib/GrAtscSymbolMapper.h | 97 + gr-atsc/src/lib/GrAtscTrellisEncoder.cc | 144 + gr-atsc/src/lib/GrAtscTrellisEncoder.h | 50 + gr-atsc/src/lib/GrAtscViterbiDecoder.cc | 135 + gr-atsc/src/lib/GrAtscViterbiDecoder.h | 51 + gr-atsc/src/lib/Makefile.am | 268 + gr-atsc/src/lib/atsc.i | 269 + gr-atsc/src/lib/atsc_bit_timing_loop.cc | 118 + gr-atsc/src/lib/atsc_bit_timing_loop.h | 89 + gr-atsc/src/lib/atsc_consts.h | 42 + gr-atsc/src/lib/atsc_deinterleaver.cc | 59 + gr-atsc/src/lib/atsc_deinterleaver.h | 56 + gr-atsc/src/lib/atsc_depad.cc | 80 + gr-atsc/src/lib/atsc_depad.h | 55 + gr-atsc/src/lib/atsc_derandomizer.cc | 79 + gr-atsc/src/lib/atsc_derandomizer.h | 56 + gr-atsc/src/lib/atsc_ds_to_softds.cc | 73 + gr-atsc/src/lib/atsc_ds_to_softds.h | 58 + gr-atsc/src/lib/atsc_equalizer.cc | 97 + gr-atsc/src/lib/atsc_equalizer.h | 63 + gr-atsc/src/lib/atsc_field_sync_demux.cc | 188 + gr-atsc/src/lib/atsc_field_sync_demux.h | 68 + gr-atsc/src/lib/atsc_field_sync_mux.cc | 203 + gr-atsc/src/lib/atsc_field_sync_mux.h | 63 + gr-atsc/src/lib/atsc_fpll.cc | 136 + gr-atsc/src/lib/atsc_fpll.h | 78 + gr-atsc/src/lib/atsc_fs_checker.cc | 75 + gr-atsc/src/lib/atsc_fs_checker.h | 62 + gr-atsc/src/lib/atsc_interleaver.cc | 59 + gr-atsc/src/lib/atsc_interleaver.h | 55 + gr-atsc/src/lib/atsc_randomizer.cc | 87 + gr-atsc/src/lib/atsc_randomizer.h | 58 + gr-atsc/src/lib/atsc_rs_decoder.cc | 63 + gr-atsc/src/lib/atsc_rs_decoder.h | 56 + gr-atsc/src/lib/atsc_rs_encoder.cc | 62 + gr-atsc/src/lib/atsc_rs_encoder.h | 56 + gr-atsc/src/lib/atsc_trellis_encoder.cc | 60 + gr-atsc/src/lib/atsc_trellis_encoder.h | 56 + gr-atsc/src/lib/atsc_types.h | 238 + gr-atsc/src/lib/atsc_viterbi_decoder.cc | 84 + gr-atsc/src/lib/atsc_viterbi_decoder.h | 60 + .../src/lib/atsci_basic_trellis_encoder.cc | 62 + gr-atsc/src/lib/atsci_basic_trellis_encoder.h | 60 + gr-atsc/src/lib/atsci_data_interleaver.cc | 61 + gr-atsc/src/lib/atsci_data_interleaver.h | 64 + gr-atsc/src/lib/atsci_diag_output.h | 29 + gr-atsc/src/lib/atsci_equalizer.cc | 248 + gr-atsc/src/lib/atsci_equalizer.h | 163 + gr-atsc/src/lib/atsci_equalizer_lms.cc | 306 + gr-atsc/src/lib/atsci_equalizer_lms.h | 75 + gr-atsc/src/lib/atsci_equalizer_lms2.cc | 373 + gr-atsc/src/lib/atsci_equalizer_lms2.h | 79 + gr-atsc/src/lib/atsci_equalizer_nop.cc | 133 + gr-atsc/src/lib/atsci_equalizer_nop.h | 62 + gr-atsc/src/lib/atsci_exp2_lp.cc | 84 + gr-atsc/src/lib/atsci_exp2_lp.h | 34 + gr-atsc/src/lib/atsci_exp2_lp20.dat | 178 + gr-atsc/src/lib/atsci_exp2_lp2x.dat | 196 + gr-atsc/src/lib/atsci_fake_single_viterbi.cc | 72 + gr-atsc/src/lib/atsci_fake_single_viterbi.h | 50 + gr-atsc/src/lib/atsci_fs_checker.cc | 33 + gr-atsc/src/lib/atsci_fs_checker.h | 69 + gr-atsc/src/lib/atsci_fs_checker_naive.cc | 140 + gr-atsc/src/lib/atsci_fs_checker_naive.h | 73 + gr-atsc/src/lib/atsci_fs_correlator.cc | 33 + gr-atsc/src/lib/atsci_fs_correlator.h | 63 + gr-atsc/src/lib/atsci_fs_correlator_naive.cc | 125 + gr-atsc/src/lib/atsci_fs_correlator_naive.h | 69 + gr-atsc/src/lib/atsci_pnXXX.cc | 55 + gr-atsc/src/lib/atsci_pnXXX.h | 24 + gr-atsc/src/lib/atsci_randomizer.cc | 112 + gr-atsc/src/lib/atsci_randomizer.h | 96 + gr-atsc/src/lib/atsci_reed_solomon.cc | 93 + gr-atsc/src/lib/atsci_reed_solomon.h | 56 + gr-atsc/src/lib/atsci_root_raised_cosine.cc | 36 + gr-atsc/src/lib/atsci_root_raised_cosine.h | 34 + .../lib/atsci_root_raised_cosine_bandpass.cc | 51 + .../lib/atsci_root_raised_cosine_bandpass.h | 38 + gr-atsc/src/lib/atsci_single_viterbi.cc | 100 + gr-atsc/src/lib/atsci_single_viterbi.h | 56 + gr-atsc/src/lib/atsci_slicer_agc.h | 68 + gr-atsc/src/lib/atsci_sliding_correlator.cc | 90 + gr-atsc/src/lib/atsci_sliding_correlator.h | 83 + gr-atsc/src/lib/atsci_sssr.cc | 286 + gr-atsc/src/lib/atsci_sssr.h | 240 + gr-atsc/src/lib/atsci_syminfo.h | 58 + gr-atsc/src/lib/atsci_sync_tag.h | 56 + gr-atsc/src/lib/atsci_trellis_encoder.cc | 207 + gr-atsc/src/lib/atsci_trellis_encoder.h | 66 + gr-atsc/src/lib/atsci_viterbi_decoder.cc | 175 + gr-atsc/src/lib/atsci_viterbi_decoder.h | 83 + gr-atsc/src/lib/atsci_viterbi_gen.cc | 267 + gr-atsc/src/lib/atsci_vsbtx_lp.cc | 59 + gr-atsc/src/lib/atsci_vsbtx_lp.dat | 49 + gr-atsc/src/lib/atsci_vsbtx_lp.h | 36 + gr-atsc/src/lib/convolutional_interleaver.h | 126 + gr-atsc/src/lib/create_atsci_equalizer.cc | 44 + gr-atsc/src/lib/create_atsci_equalizer.h | 31 + gr-atsc/src/lib/create_atsci_fs_checker.cc | 30 + gr-atsc/src/lib/create_atsci_fs_checker.h | 34 + gr-atsc/src/lib/create_atsci_fs_correlator.cc | 30 + gr-atsc/src/lib/create_atsci_fs_correlator.h | 34 + gr-atsc/src/lib/fpll_btloop_coupling.h | 38 + gr-atsc/src/lib/gen_encoder.py | 63 + gr-atsc/src/lib/interleaver_fifo.h | 86 + gr-atsc/src/lib/plinfo.cc | 59 + gr-atsc/src/lib/qa_atsci.cc | 63 + gr-atsc/src/lib/qa_atsci.h | 37 + .../src/lib/qa_atsci_basic_trellis_encoder.cc | 67 + .../src/lib/qa_atsci_basic_trellis_encoder.h | 44 + gr-atsc/src/lib/qa_atsci_data_interleaver.cc | 196 + gr-atsc/src/lib/qa_atsci_data_interleaver.h | 60 + gr-atsc/src/lib/qa_atsci_equalizer_nop.cc | 246 + gr-atsc/src/lib/qa_atsci_equalizer_nop.h | 51 + .../src/lib/qa_atsci_fake_single_viterbi.cc | 143 + .../src/lib/qa_atsci_fake_single_viterbi.h | 51 + gr-atsc/src/lib/qa_atsci_fs_correlator.cc | 255 + gr-atsc/src/lib/qa_atsci_fs_correlator.h | 58 + gr-atsc/src/lib/qa_atsci_randomizer.cc | 144 + gr-atsc/src/lib/qa_atsci_randomizer.h | 62 + gr-atsc/src/lib/qa_atsci_reed_solomon.cc | 114 + gr-atsc/src/lib/qa_atsci_reed_solomon.h | 43 + gr-atsc/src/lib/qa_atsci_single_viterbi.cc | 283 + gr-atsc/src/lib/qa_atsci_single_viterbi.h | 53 + .../src/lib/qa_atsci_sliding_correlator.cc | 51 + gr-atsc/src/lib/qa_atsci_sliding_correlator.h | 52 + gr-atsc/src/lib/qa_atsci_trellis_encoder.cc | 115 + gr-atsc/src/lib/qa_atsci_trellis_encoder.h | 54 + .../lib/qa_atsci_trellis_encoder_t1_input.dat | 2484 ++++ .../qa_atsci_trellis_encoder_t1_output.dat | 9984 +++++++++++++++++ gr-atsc/src/lib/qa_atsci_viterbi_decoder.cc | 178 + gr-atsc/src/lib/qa_atsci_viterbi_decoder.h | 54 + .../lib/qa_atsci_viterbi_decoder_t1_input.dat | 9984 +++++++++++++++++ .../qa_atsci_viterbi_decoder_t1_output.dat | 2484 ++++ .../src/lib/qa_convolutional_interleaver.cc | 131 + .../src/lib/qa_convolutional_interleaver.h | 69 + gr-atsc/src/lib/qa_interleaver_fifo.cc | 58 + gr-atsc/src/lib/qa_interleaver_fifo.h | 57 + gr-atsc/src/lib/test_atsci.cc | 37 + gr-atsc/src/python/Makefile.am | 33 + gr-atsc/src/python/atsc_utils.py | 74 + gr-atsc/src/python/qa_atsc.py | 217 + gr-atsc/src/python/run_tests.in | 47 + gr-audio-alsa/AUTHORS | 2 + gr-audio-alsa/ChangeLog | 88 + gr-audio-alsa/Makefile.am | 32 + gr-audio-alsa/README | 4 + gr-audio-alsa/build-stamp | 0 gr-audio-alsa/gr-audio-alsa.conf | 11 + gr-audio-alsa/src/Makefile.am | 91 + gr-audio-alsa/src/audio_alsa.i | 80 + gr-audio-alsa/src/audio_alsa_sink.cc | 538 + gr-audio-alsa/src/audio_alsa_sink.h | 124 + gr-audio-alsa/src/audio_alsa_source.cc | 506 + gr-audio-alsa/src/audio_alsa_source.h | 124 + gr-audio-alsa/src/gri_alsa.cc | 175 + gr-audio-alsa/src/gri_alsa.h | 44 + gr-audio-alsa/src/qa_alsa.py | 40 + gr-audio-alsa/src/run_tests.in | 47 + gr-audio-jack/AUTHORS | 1 + gr-audio-jack/ChangeLog | 42 + gr-audio-jack/Makefile.am | 28 + gr-audio-jack/gr-audio-jack.conf | 8 + gr-audio-jack/src/Makefile.am | 98 + gr-audio-jack/src/audio_jack.i | 80 + gr-audio-jack/src/audio_jack_sink.cc | 231 + gr-audio-jack/src/audio_jack_sink.h | 97 + gr-audio-jack/src/audio_jack_source.cc | 231 + gr-audio-jack/src/audio_jack_source.h | 97 + gr-audio-jack/src/gri_jack.cc | 30 + gr-audio-jack/src/gri_jack.h | 28 + gr-audio-jack/src/qa_jack.py | 40 + gr-audio-jack/src/run_tests.in | 47 + gr-audio-oss/AUTHORS | 1 + gr-audio-oss/ChangeLog | 91 + gr-audio-oss/Makefile.am | 30 + gr-audio-oss/gr-audio-oss.conf | 9 + gr-audio-oss/src/Makefile.am | 90 + gr-audio-oss/src/audio_oss.i | 70 + gr-audio-oss/src/audio_oss_sink.cc | 161 + gr-audio-oss/src/audio_oss_sink.h | 66 + gr-audio-oss/src/audio_oss_source.cc | 178 + gr-audio-oss/src/audio_oss_source.h | 70 + gr-audio-oss/src/qa_oss.py | 40 + gr-audio-oss/src/run_tests.in | 47 + gr-audio-osx/AUTHORS | 1 + gr-audio-osx/ChangeLog | 25 + gr-audio-osx/Makefile.am | 25 + gr-audio-osx/README_OSX | 61 + gr-audio-osx/TODO | 51 + gr-audio-osx/src/Makefile.am | 88 + gr-audio-osx/src/audio_osx.h | 49 + gr-audio-osx/src/audio_osx.i | 95 + gr-audio-osx/src/audio_osx_sink.cc | 398 + gr-audio-osx/src/audio_osx_sink.h | 96 + gr-audio-osx/src/audio_osx_source.cc | 978 ++ gr-audio-osx/src/audio_osx_source.h | 132 + gr-audio-osx/src/circular_buffer.h | 326 + gr-audio-osx/src/mld_threads.h | 255 + gr-audio-osx/src/qa_osx.py | 40 + gr-audio-osx/src/run_tests.in | 47 + gr-audio-osx/src/test_audio_loop.py | 65 + gr-audio-portaudio/AUTHORS | 2 + gr-audio-portaudio/ChangeLog | 31 + gr-audio-portaudio/Makefile.am | 28 + gr-audio-portaudio/README | 92 + gr-audio-portaudio/autoconfiscate.patch | 1299 +++ gr-audio-portaudio/gr-audio-portaudio.conf | 10 + gr-audio-portaudio/src/Makefile.am | 92 + gr-audio-portaudio/src/audio_portaudio.i | 77 + .../src/audio_portaudio_sink.cc | 340 + gr-audio-portaudio/src/audio_portaudio_sink.h | 102 + .../src/audio_portaudio_source.cc | 355 + .../src/audio_portaudio_source.h | 101 + gr-audio-portaudio/src/gri_portaudio.cc | 111 + gr-audio-portaudio/src/gri_portaudio.h | 32 + gr-audio-portaudio/src/qa_portaudio.py | 40 + gr-audio-portaudio/src/run_tests.in | 47 + gr-audio-windows/AUTHORS | 2 + gr-audio-windows/ChangeLog | 42 + gr-audio-windows/Makefile.am | 24 + gr-audio-windows/README | 66 + gr-audio-windows/src/Makefile.am | 87 + gr-audio-windows/src/audio_windows.i | 68 + gr-audio-windows/src/audio_windows_sink.cc | 324 + gr-audio-windows/src/audio_windows_sink.h | 83 + gr-audio-windows/src/audio_windows_source.cc | 208 + gr-audio-windows/src/audio_windows_source.h | 68 + gr-audio-windows/src/qa_audio_windows.py | 40 + gr-audio-windows/src/run_tests.in | 47 + gr-comedi/AUTHORS | 1 + gr-comedi/ChangeLog | 25 + gr-comedi/Makefile.am | 24 + gr-comedi/src/Makefile.am | 91 + gr-comedi/src/comedi.i | 76 + gr-comedi/src/comedi_sink_s.cc | 233 + gr-comedi/src/comedi_sink_s.h | 89 + gr-comedi/src/comedi_source_s.cc | 229 + gr-comedi/src/comedi_source_s.h | 90 + gr-comedi/src/gri_comedi.cc | 30 + gr-comedi/src/gri_comedi.h | 28 + gr-comedi/src/qa_comedi.py | 40 + gr-comedi/src/run_tests.in | 47 + gr-error-correcting-codes/AUTHORS | 1 + gr-error-correcting-codes/ChangeLog | 31 + gr-error-correcting-codes/Makefile.am | 27 + gr-error-correcting-codes/src/Makefile.am | 24 + gr-error-correcting-codes/src/lib/Makefile.am | 101 + gr-error-correcting-codes/src/lib/__init__.py | 20 + gr-error-correcting-codes/src/lib/ecc.i | 41 + .../gr_metrics_decode_viterbi_full_block.cc | 228 + .../gr_metrics_decode_viterbi_full_block.h | 163 + .../gr_metrics_decode_viterbi_full_block.i | 77 + .../lib/gr_streams_encode_convolutional.cc | 220 + .../src/lib/gr_streams_encode_convolutional.h | 155 + .../src/lib/gr_streams_encode_convolutional.i | 77 + .../src/lib/gr_streams_encode_turbo.cc | 209 + .../src/lib/gr_streams_encode_turbo.h | 104 + .../src/lib/gr_streams_encode_turbo.i | 41 + .../src/lib/gr_syms_to_metrics.cc | 167 + .../src/lib/gr_syms_to_metrics.h | 121 + .../src/lib/gr_syms_to_metrics.i | 41 + .../src/lib/libecc/Makefile.am | 60 + .../lib/libecc/code_convolutional_trellis.cc | 1028 ++ .../lib/libecc/code_convolutional_trellis.h | 372 + .../src/lib/libecc/code_metrics.cc | 445 + .../src/lib/libecc/code_metrics.h | 155 + .../src/lib/libecc/code_types.h | 31 + .../src/lib/libecc/decoder.cc | 117 + .../src/lib/libecc/decoder.h | 59 + .../src/lib/libecc/decoder_viterbi.cc | 1060 ++ .../src/lib/libecc/decoder_viterbi.h | 189 + .../lib/libecc/decoder_viterbi_full_block.cc | 1120 ++ .../lib/libecc/decoder_viterbi_full_block.h | 78 + .../decoder_viterbi_full_block_i1_ic1.cc | 162 + .../decoder_viterbi_full_block_i1_ic1.h | 66 + .../src/lib/libecc/encoder.cc | 123 + .../src/lib/libecc/encoder.h | 72 + .../src/lib/libecc/encoder_convolutional.cc | 290 + .../src/lib/libecc/encoder_convolutional.h | 230 + .../libecc/encoder_convolutional_ic1_ic1.cc | 188 + .../libecc/encoder_convolutional_ic1_ic1.h | 91 + .../libecc/encoder_convolutional_ic8_ic8.cc | 224 + .../libecc/encoder_convolutional_ic8_ic8.h | 96 + .../src/lib/libecc/encoder_turbo.cc | 52 + .../src/lib/libecc/encoder_turbo.h | 147 + .../src/lib/libecc/mld/Makefile.am | 36 + .../src/lib/libecc/mld/mld_timer.cc | 50 + .../src/lib/libecc/mld/mld_timer.h | 28 + .../src/lib/libecc/mld/n2bs.cc | 73 + .../src/lib/libecc/mld/n2bs.h | 32 + .../src/lib/libecc/tests/Makefile.am | 47 + .../src/lib/libecc/tests/qa_ecc.cc | 40 + .../src/lib/libecc/tests/qa_ecc.h | 36 + .../tests/qa_encoder_convolutional_ic1_ic1.cc | 430 + .../tests/qa_encoder_convolutional_ic1_ic1.h | 65 + .../src/lib/libecc/tests/test_all.cc | 38 + gr-error-correcting-codes/src/lib/qa_ecc.py | 39 + .../src/python/Makefile.am | 32 + .../src/python/qa_test_coding_1.py | 94 + .../src/python/qa_test_coding_2.py | 91 + .../python/qa_test_encoder_convolutional_1.py | 74 + .../python/qa_test_encoder_convolutional_2.py | 35 + .../src/python/run_tests.in | 47 + gr-gsm-fr-vocoder/AUTHORS | 3 + gr-gsm-fr-vocoder/ChangeLog | 45 + gr-gsm-fr-vocoder/INSTALL | 229 + gr-gsm-fr-vocoder/Makefile.am | 25 + gr-gsm-fr-vocoder/src/Makefile.am | 22 + gr-gsm-fr-vocoder/src/lib/Makefile.am | 102 + gr-gsm-fr-vocoder/src/lib/__init__.py | 20 + gr-gsm-fr-vocoder/src/lib/gsm/COPYRIGHT | 16 + gr-gsm-fr-vocoder/src/lib/gsm/Makefile.am | 75 + gr-gsm-fr-vocoder/src/lib/gsm/README | 4 + gr-gsm-fr-vocoder/src/lib/gsm/README.orig | 37 + gr-gsm-fr-vocoder/src/lib/gsm/add.c | 235 + gr-gsm-fr-vocoder/src/lib/gsm/code.c | 99 + gr-gsm-fr-vocoder/src/lib/gsm/config.h | 37 + gr-gsm-fr-vocoder/src/lib/gsm/debug.c | 76 + gr-gsm-fr-vocoder/src/lib/gsm/decode.c | 63 + gr-gsm-fr-vocoder/src/lib/gsm/gsm.h | 73 + gr-gsm-fr-vocoder/src/lib/gsm/gsm_create.c | 45 + gr-gsm-fr-vocoder/src/lib/gsm/gsm_decode.c | 361 + gr-gsm-fr-vocoder/src/lib/gsm/gsm_destroy.c | 26 + gr-gsm-fr-vocoder/src/lib/gsm/gsm_encode.c | 451 + gr-gsm-fr-vocoder/src/lib/gsm/gsm_explode.c | 417 + gr-gsm-fr-vocoder/src/lib/gsm/gsm_implode.c | 515 + gr-gsm-fr-vocoder/src/lib/gsm/gsm_option.c | 69 + gr-gsm-fr-vocoder/src/lib/gsm/gsm_print.c | 167 + gr-gsm-fr-vocoder/src/lib/gsm/long_term.c | 949 ++ gr-gsm-fr-vocoder/src/lib/gsm/lpc.c | 341 + gr-gsm-fr-vocoder/src/lib/gsm/preprocess.c | 113 + gr-gsm-fr-vocoder/src/lib/gsm/private.h | 268 + gr-gsm-fr-vocoder/src/lib/gsm/proto.h | 65 + gr-gsm-fr-vocoder/src/lib/gsm/rpe.c | 488 + gr-gsm-fr-vocoder/src/lib/gsm/short_term.c | 429 + gr-gsm-fr-vocoder/src/lib/gsm/table.c | 63 + gr-gsm-fr-vocoder/src/lib/gsm/unproto.h | 23 + gr-gsm-fr-vocoder/src/lib/gsm_fr_decode_ps.cc | 72 + gr-gsm-fr-vocoder/src/lib/gsm_fr_decode_ps.h | 49 + gr-gsm-fr-vocoder/src/lib/gsm_fr_encode_sp.cc | 69 + gr-gsm-fr-vocoder/src/lib/gsm_fr_encode_sp.h | 52 + gr-gsm-fr-vocoder/src/lib/gsm_full_rate.i | 52 + gr-gsm-fr-vocoder/src/python/Makefile.am | 33 + gr-gsm-fr-vocoder/src/python/encdec.py | 44 + .../src/python/qa_gsm_full_rate.py | 35 + gr-gsm-fr-vocoder/src/python/run_tests.in | 47 + gr-howto-write-a-block/.buildpri | 1 + gr-howto-write-a-block/AUTHORS | 1 + gr-howto-write-a-block/COPYING | 340 + gr-howto-write-a-block/ChangeLog | 46 + gr-howto-write-a-block/INSTALL | 229 + gr-howto-write-a-block/Makefile.am | 29 + gr-howto-write-a-block/Makefile.common | 38 + gr-howto-write-a-block/NEWS | 0 gr-howto-write-a-block/README | 44 + gr-howto-write-a-block/bootstrap | 29 + gr-howto-write-a-block/config.guess | 1465 +++ gr-howto-write-a-block/config.sub | 1587 +++ gr-howto-write-a-block/config/Makefile.am | 66 + gr-howto-write-a-block/config/acx_pthread.m4 | 190 + gr-howto-write-a-block/config/bnv_have_qt.m4 | 404 + gr-howto-write-a-block/config/cppunit.m4 | 80 + gr-howto-write-a-block/config/gr_as.m4 | 34 + gr-howto-write-a-block/config/gr_boost.m4 | 111 + .../config/gr_check_createfilemapping.m4 | 52 + .../config/gr_check_mc4020.m4 | 37 + .../config/gr_check_shm_open.m4 | 29 + .../config/gr_check_usrp.m4 | 32 + gr-howto-write-a-block/config/gr_doxygen.m4 | 59 + gr-howto-write-a-block/config/gr_gprof.m4 | 72 + .../gr_libgnuradio_core_extra_ldflags.m4 | 40 + .../config/gr_no_undefined.m4 | 44 + .../config/gr_omnithread.m4 | 51 + gr-howto-write-a-block/config/gr_pwin32.m4 | 146 + gr-howto-write-a-block/config/gr_python.m4 | 116 + .../config/gr_require_mc4020.m4 | 33 + gr-howto-write-a-block/config/gr_scripting.m4 | 30 + .../config/gr_set_md_cpu.m4 | 44 + gr-howto-write-a-block/config/gr_swig.m4 | 85 + gr-howto-write-a-block/config/gr_sysv_shm.m4 | 36 + gr-howto-write-a-block/config/gr_x86_64.m4 | 39 + gr-howto-write-a-block/config/lf_cc.m4 | 42 + gr-howto-write-a-block/config/lf_cxx.m4 | 121 + gr-howto-write-a-block/config/lf_warnings.m4 | 128 + gr-howto-write-a-block/config/lf_x11.m4 | 39 + gr-howto-write-a-block/config/mkstemp.m4 | 89 + gr-howto-write-a-block/config/onceonly.m4 | 63 + gr-howto-write-a-block/config/pkg.m4 | 68 + .../config/usrp_fusb_tech.m4 | 56 + gr-howto-write-a-block/config/usrp_libusb.m4 | 43 + gr-howto-write-a-block/config/usrp_sdcc.m4 | 67 + gr-howto-write-a-block/configure.ac | 104 + gr-howto-write-a-block/doc/Makefile.am | 81 + .../doc/howto-write-a-block.xml | 959 ++ gr-howto-write-a-block/doc/howto_1.i | 29 + .../doc/make_numbered_listing.py | 45 + gr-howto-write-a-block/doc/qa_howto_1.py | 27 + .../doc/src_lib_Makefile_1.am | 25 + .../doc/src_lib_Makefile_2.am | 86 + gr-howto-write-a-block/src/Makefile.am | 22 + gr-howto-write-a-block/src/lib/Makefile.am | 94 + gr-howto-write-a-block/src/lib/howto.i | 44 + .../src/lib/howto_square2_ff.cc | 92 + .../src/lib/howto_square2_ff.h | 77 + .../src/lib/howto_square_ff.cc | 98 + .../src/lib/howto_square_ff.h | 78 + gr-howto-write-a-block/src/python/Makefile.am | 32 + gr-howto-write-a-block/src/python/qa_howto.py | 59 + .../src/python/run_tests.in | 50 + gr-radar/AUTHORS | 1 + gr-radar/ChangeLog | 20 + gr-radar/Makefile.am | 25 + gr-radar/doc/Makefile.am | 0 gr-radar/src/Makefile.am | 22 + gr-radar/src/lib/Makefile.am | 118 + gr-radar/src/lib/eb-xambi.cc | 291 + gr-radar/src/lib/gen_run | 26 + gr-radar/src/lib/plot_rd.m | 38 + gr-radar/src/lib/plot_xambi.m | 15 + gr-radar/src/lib/plot_xambi_to_file.m | 17 + gr-radar/src/lib/plot_xambi_tool.m | 8 + gr-radar/src/lib/sim-airplane.cc | 296 + gr-radar/src/lib/sim-airplane2.cc | 372 + gr-radar/src/lib/simulation.cc | 89 + gr-radar/src/lib/simulation.h | 116 + gr-radar/src/lib/time_series.cc | 96 + gr-radar/src/lib/time_series.h | 73 + gr-radar/src/lib/xambi.cc | 259 + gr-radar/src/python/Makefile.am | 33 + gr-radar/src/python/complex_to_short.py | 33 + gr-radar/src/python/fm_demod_file.py | 66 + gr-radar/src/python/gen_fm_signal.py | 66 + gr-radar/src/python/gen_random_signal.py | 66 + gr-radar/src/python/qa_nothing.py | 0 gr-radar/src/python/run_tests.in | 47 + gr-radar/src/python/signal_levels.py | 62 + gr-radar/src/python/split_files.py | 93 + gr-radar/src/python/usrp_rx_radar.py | 89 + gr-radio-astronomy/AUTHORS | 2 + gr-radio-astronomy/ChangeLog | 30 + gr-radio-astronomy/Makefile.am | 24 + gr-radio-astronomy/README | 38 + gr-radio-astronomy/src/Makefile.am | 22 + gr-radio-astronomy/src/lib/Makefile.am | 90 + gr-radio-astronomy/src/lib/ra.i | 45 + gr-radio-astronomy/src/python/Makefile.am | 56 + .../src/python/local_calibrator.py | 149 + gr-radio-astronomy/src/python/qa_ra.py | 38 + gr-radio-astronomy/src/python/ra_fftsink.py | 520 + .../src/python/ra_stripchartsink.py | 399 + gr-radio-astronomy/src/python/run_tests.in | 47 + .../src/python/usrp_psr_receiver.help | 111 + .../src/python/usrp_psr_receiver.py | 1101 ++ .../src/python/usrp_ra_receiver.help | 90 + .../src/python/usrp_ra_receiver.py | 584 + gr-usrp/AUTHORS | 1 + gr-usrp/ChangeLog | 374 + gr-usrp/Makefile.am | 25 + gr-usrp/README_MULTI_USRP.txt | 251 + gr-usrp/src/Makefile.am | 120 + gr-usrp/src/db_base.py | 234 + gr-usrp/src/db_basic.py | 252 + gr-usrp/src/db_dbs_rx.py | 345 + gr-usrp/src/db_flexrf.py | 680 ++ gr-usrp/src/db_flexrf_mimo.py | 286 + gr-usrp/src/db_instantiator.py | 31 + gr-usrp/src/db_tv_rx.py | 198 + gr-usrp/src/flexrf_debug_gui.py | 176 + gr-usrp/src/qa_usrp.py | 40 + gr-usrp/src/run_tests.in | 47 + gr-usrp/src/tx_debug_gui.py | 187 + gr-usrp/src/usrp.py | 474 + gr-usrp/src/usrp1.i | 657 ++ gr-usrp/src/usrp1_sink_base.cc | 359 + gr-usrp/src/usrp1_sink_base.h | 359 + gr-usrp/src/usrp1_sink_c.cc | 106 + gr-usrp/src/usrp1_sink_c.h | 87 + gr-usrp/src/usrp1_sink_s.cc | 106 + gr-usrp/src/usrp1_sink_s.h | 86 + gr-usrp/src/usrp1_source_base.cc | 425 + gr-usrp/src/usrp1_source_base.h | 455 + gr-usrp/src/usrp1_source_c.cc | 131 + gr-usrp/src/usrp1_source_c.h | 93 + gr-usrp/src/usrp1_source_s.cc | 131 + gr-usrp/src/usrp1_source_s.h | 94 + gr-usrp/src/usrp_multi.py | 233 + gr-video-sdl/AUTHORS | 1 + gr-video-sdl/ChangeLog | 25 + gr-video-sdl/Makefile.am | 24 + gr-video-sdl/src/Makefile.am | 86 + gr-video-sdl/src/qa_video_sdl.py | 40 + gr-video-sdl/src/run_tests.in | 47 + gr-video-sdl/src/video_sdl.i | 67 + gr-video-sdl/src/video_sdl_sink_s.cc | 301 + gr-video-sdl/src/video_sdl_sink_s.h | 90 + gr-video-sdl/src/video_sdl_sink_uc.cc | 291 + gr-video-sdl/src/video_sdl_sink_uc.h | 90 + gr-wxgui/ChangeLog | 171 + gr-wxgui/Makefile.am | 28 + gr-wxgui/README | 1 + gr-wxgui/gr-wxgui.conf | 7 + gr-wxgui/src/Makefile.am | 24 + gr-wxgui/src/python/Makefile.am | 40 + gr-wxgui/src/python/__init__.py | 1 + gr-wxgui/src/python/fftsink.py | 488 + gr-wxgui/src/python/form.py | 391 + gr-wxgui/src/python/plot.py | 1744 +++ gr-wxgui/src/python/powermate.py | 437 + gr-wxgui/src/python/scopesink.py | 650 ++ gr-wxgui/src/python/slider.py | 49 + gr-wxgui/src/python/stdgui.py | 90 + gr-wxgui/src/python/waterfallsink.py | 469 + pmt/AUTHORS | 1 + pmt/ChangeLog | 20 + pmt/Makefile.am | 25 + pmt/README | 45 + pmt/doc/Makefile.am | 43 + pmt/src/Makefile.am | 22 + pmt/src/lib/Makefile.am | 71 + pmt/src/lib/pmt.cc | 705 ++ pmt/src/lib/pmt.h | 554 + pmt/src/lib/pmt_int.h | 178 + pmt/src/lib/qa_pmt.cc | 40 + pmt/src/lib/qa_pmt.h | 36 + pmt/src/lib/qa_pmt_prims.cc | 284 + pmt/src/lib/qa_pmt_prims.h | 57 + pmt/src/lib/test_pmt.cc | 37 + usrp/AUTHORS | 4 + usrp/ChangeLog | 1055 ++ usrp/Makefile.am | 25 + usrp/README | 37 + usrp/doc/Doxyfile.in | 1167 ++ usrp/doc/Makefile.am | 79 + usrp/doc/ddc.eps | 3105 +++++ usrp/doc/ddc.png | Bin 0 -> 42199 bytes usrp/doc/other/Makefile.am | 25 + usrp/doc/other/mainpage.dox | 9 + usrp/doc/usrp-block-diagram.eps | 2785 +++++ usrp/doc/usrp-block-diagram.png | Bin 0 -> 35729 bytes usrp/doc/usrp.jpg | Bin 0 -> 114386 bytes usrp/doc/usrp_guide.xml | 399 + usrp/firmware/Makefile.am | 22 + usrp/firmware/include/Makefile.am | 59 + usrp/firmware/include/delay.h | 38 + usrp/firmware/include/fpga_regs0.h | 42 + usrp/firmware/include/fpga_regs_common.h | 147 + usrp/firmware/include/fpga_regs_common.v | 114 + usrp/firmware/include/fpga_regs_standard.h | 284 + usrp/firmware/include/fpga_regs_standard.v | 240 + usrp/firmware/include/fx2regs.h | 716 ++ usrp/firmware/include/fx2utils.h | 31 + usrp/firmware/include/generate_regs.py | 57 + usrp/firmware/include/i2c.h | 32 + usrp/firmware/include/isr.h | 172 + usrp/firmware/include/syncdelay.h | 65 + usrp/firmware/include/timer.h | 35 + usrp/firmware/include/usb_common.h | 37 + usrp/firmware/include/usb_descriptors.h | 40 + usrp/firmware/include/usb_requests.h | 88 + usrp/firmware/include/usrp_commands.h | 99 + usrp/firmware/include/usrp_config.h | 44 + usrp/firmware/include/usrp_i2c_addr.h | 78 + usrp/firmware/include/usrp_ids.h | 53 + usrp/firmware/include/usrp_interfaces.h | 47 + usrp/firmware/include/usrp_spi_defs.h | 86 + usrp/firmware/lib/Makefile.am | 83 + usrp/firmware/lib/delay.c | 76 + usrp/firmware/lib/fx2utils.c | 54 + usrp/firmware/lib/i2c-compiler-bug.c | 129 + usrp/firmware/lib/i2c.c | 123 + usrp/firmware/lib/isr.c | 167 + usrp/firmware/lib/timer.c | 49 + usrp/firmware/lib/usb_common.c | 385 + usrp/firmware/src/Makefile.am | 22 + usrp/firmware/src/common/Makefile.am | 50 + usrp/firmware/src/common/_startup.a51 | 80 + usrp/firmware/src/common/_startup.a51.brittle | 78 + usrp/firmware/src/common/blink_leds.c | 36 + usrp/firmware/src/common/build_eeprom.py | 182 + usrp/firmware/src/common/check_mdelay.c | 37 + usrp/firmware/src/common/check_udelay.c | 37 + usrp/firmware/src/common/edit-gpif | 114 + usrp/firmware/src/common/fpga.h | 31 + usrp/firmware/src/common/fpga_load.c | 193 + usrp/firmware/src/common/fpga_load.h | 28 + usrp/firmware/src/common/gpif.c | 292 + usrp/firmware/src/common/gpif.gpf | Bin 0 -> 5281 bytes usrp/firmware/src/common/init_gpif.c | 59 + usrp/firmware/src/common/usrp_common.c | 109 + usrp/firmware/src/common/usrp_globals.h | 32 + usrp/firmware/src/common/vectors.a51 | 180 + usrp/firmware/src/usrp2/Makefile.am | 168 + usrp/firmware/src/usrp2/_startup.a51 | 1 + usrp/firmware/src/usrp2/blink_leds.c | 1 + usrp/firmware/src/usrp2/board_specific.c | 113 + usrp/firmware/src/usrp2/check_mdelay.c | 1 + usrp/firmware/src/usrp2/check_udelay.c | 1 + usrp/firmware/src/usrp2/edit-gpif | 114 + usrp/firmware/src/usrp2/eeprom_boot.a51 | 573 + usrp/firmware/src/usrp2/eeprom_init.c | 116 + usrp/firmware/src/usrp2/eeprom_io.c | 65 + usrp/firmware/src/usrp2/eeprom_io.h | 38 + usrp/firmware/src/usrp2/fpga_load.c | 1 + usrp/firmware/src/usrp2/fpga_rev2.c | 122 + usrp/firmware/src/usrp2/fpga_rev2.h | 58 + usrp/firmware/src/usrp2/gpif.c | 292 + usrp/firmware/src/usrp2/gpif.gpf | Bin 0 -> 5341 bytes usrp/firmware/src/usrp2/init_gpif.c | 1 + usrp/firmware/src/usrp2/spi.c | 381 + usrp/firmware/src/usrp2/spi.h | 43 + usrp/firmware/src/usrp2/usb_descriptors.a51 | 404 + usrp/firmware/src/usrp2/usrp_common.c | 1 + usrp/firmware/src/usrp2/usrp_common.h | 77 + usrp/firmware/src/usrp2/usrp_main.c | 380 + usrp/firmware/src/usrp2/usrp_rev2_regs.h | 163 + usrp/firmware/src/usrp2/vectors.a51 | 1 + usrp/fpga/Makefile.am | 24 + usrp/fpga/Makefile.extra | 150 + usrp/fpga/TODO | 23 + usrp/fpga/gen_makefile_extra.py | 67 + usrp/fpga/megacells/accum32.bsf | 86 + usrp/fpga/megacells/accum32.cmp | 31 + usrp/fpga/megacells/accum32.inc | 32 + usrp/fpga/megacells/accum32.v | 765 ++ usrp/fpga/megacells/accum32_bb.v | 35 + usrp/fpga/megacells/accum32_inst.v | 7 + usrp/fpga/megacells/add32.bsf | 62 + usrp/fpga/megacells/add32.cmp | 29 + usrp/fpga/megacells/add32.inc | 30 + usrp/fpga/megacells/add32.v | 221 + usrp/fpga/megacells/add32_bb.v | 31 + usrp/fpga/megacells/add32_inst.v | 5 + usrp/fpga/megacells/addsub16.bsf | 96 + usrp/fpga/megacells/addsub16.cmp | 33 + usrp/fpga/megacells/addsub16.inc | 34 + usrp/fpga/megacells/addsub16.v | 438 + usrp/fpga/megacells/addsub16_bb.v | 39 + usrp/fpga/megacells/addsub16_inst.v | 9 + usrp/fpga/megacells/bustri.bsf | 62 + usrp/fpga/megacells/bustri.cmp | 29 + usrp/fpga/megacells/bustri.inc | 30 + usrp/fpga/megacells/bustri.v | 71 + usrp/fpga/megacells/bustri_bb.v | 31 + usrp/fpga/megacells/bustri_inst.v | 5 + usrp/fpga/megacells/clk_doubler.v | 198 + usrp/fpga/megacells/clk_doubler_bb.v | 143 + usrp/fpga/megacells/dspclkpll.v | 237 + usrp/fpga/megacells/dspclkpll_bb.v | 31 + usrp/fpga/megacells/fifo_2k.v | 3343 ++++++ usrp/fpga/megacells/fifo_2k_bb.v | 131 + usrp/fpga/megacells/fifo_4k.v | 3495 ++++++ usrp/fpga/megacells/fifo_4k_bb.v | 131 + usrp/fpga/megacells/mylpm_addsub.bsf | 80 + usrp/fpga/megacells/mylpm_addsub.cmp | 31 + usrp/fpga/megacells/mylpm_addsub.inc | 32 + usrp/fpga/megacells/mylpm_addsub.v | 102 + usrp/fpga/megacells/mylpm_addsub_bb.v | 35 + usrp/fpga/megacells/mylpm_addsub_inst.v | 7 + usrp/fpga/megacells/pll.v | 207 + usrp/fpga/megacells/pll_bb.v | 29 + usrp/fpga/megacells/pll_inst.v | 4 + usrp/fpga/megacells/sub32.bsf | 87 + usrp/fpga/megacells/sub32.cmp | 32 + usrp/fpga/megacells/sub32.inc | 33 + usrp/fpga/megacells/sub32.v | 675 ++ usrp/fpga/megacells/sub32_bb.v | 37 + usrp/fpga/megacells/sub32_inst.v | 8 + usrp/fpga/models/bustri.v | 17 + usrp/fpga/models/fifo.v | 81 + usrp/fpga/models/fifo_1c_1k.v | 81 + usrp/fpga/models/fifo_1c_2k.v | 81 + usrp/fpga/models/fifo_1c_4k.v | 76 + usrp/fpga/models/fifo_1k.v | 24 + usrp/fpga/models/fifo_2k.v | 24 + usrp/fpga/models/fifo_4k.v | 24 + usrp/fpga/models/pll.v | 33 + usrp/fpga/models/ssram.v | 38 + usrp/fpga/rbf/Makefile.am | 49 + usrp/fpga/rbf/rev2/multi_2rxhb_2tx.rbf | Bin 0 -> 180809 bytes usrp/fpga/rbf/rev2/multi_4rx_0tx.rbf | Bin 0 -> 180537 bytes usrp/fpga/rbf/rev2/std_2rxhb_2tx.rbf | Bin 0 -> 175896 bytes usrp/fpga/rbf/rev2/std_4rx_0tx.rbf | Bin 0 -> 171213 bytes usrp/fpga/rbf/rev4/multi_2rxhb_2tx.rbf | Bin 0 -> 180809 bytes usrp/fpga/rbf/rev4/multi_4rx_0tx.rbf | Bin 0 -> 180537 bytes usrp/fpga/rbf/rev4/std_2rxhb_2tx.rbf | Bin 0 -> 175896 bytes usrp/fpga/rbf/rev4/std_4rx_0tx.rbf | Bin 0 -> 171213 bytes usrp/fpga/sdr_lib/adc_interface.v | 71 + usrp/fpga/sdr_lib/bidir_reg.v | 29 + usrp/fpga/sdr_lib/bus_interface.v | 213 + usrp/fpga/sdr_lib/cic_decim.v | 106 + usrp/fpga/sdr_lib/cic_int_shifter.v | 98 + usrp/fpga/sdr_lib/cic_interp.v | 88 + usrp/fpga/sdr_lib/clk_divider.v | 43 + usrp/fpga/sdr_lib/cordic.v | 109 + usrp/fpga/sdr_lib/cordic_stage.v | 60 + usrp/fpga/sdr_lib/ddc.v | 97 + usrp/fpga/sdr_lib/dpram.v | 47 + usrp/fpga/sdr_lib/duc.v | 95 + usrp/fpga/sdr_lib/ext_fifo.v | 126 + usrp/fpga/sdr_lib/gen_cordic_consts.py | 10 + usrp/fpga/sdr_lib/gen_sync.v | 43 + usrp/fpga/sdr_lib/hb/acc.v | 22 + usrp/fpga/sdr_lib/hb/coeff_ram.v | 26 + usrp/fpga/sdr_lib/hb/coeff_rom.v | 19 + usrp/fpga/sdr_lib/hb/halfband_decim.v | 163 + usrp/fpga/sdr_lib/hb/halfband_interp.v | 121 + usrp/fpga/sdr_lib/hb/hbd_tb/HBD | 80 + usrp/fpga/sdr_lib/hb/hbd_tb/really_golden | 142 + usrp/fpga/sdr_lib/hb/hbd_tb/regression | 95 + usrp/fpga/sdr_lib/hb/hbd_tb/run_hbd | 4 + usrp/fpga/sdr_lib/hb/hbd_tb/test_hbd.v | 75 + usrp/fpga/sdr_lib/hb/mac.v | 58 + usrp/fpga/sdr_lib/hb/mult.v | 16 + usrp/fpga/sdr_lib/hb/ram16_2port.v | 22 + usrp/fpga/sdr_lib/hb/ram16_2sum.v | 27 + usrp/fpga/sdr_lib/hb/ram32_2sum.v | 22 + usrp/fpga/sdr_lib/io_pins.v | 52 + usrp/fpga/sdr_lib/master_control.v | 155 + usrp/fpga/sdr_lib/master_control_multi.v | 73 + usrp/fpga/sdr_lib/phase_acc.v | 52 + usrp/fpga/sdr_lib/ram.v | 16 + usrp/fpga/sdr_lib/ram16.v | 17 + usrp/fpga/sdr_lib/ram32.v | 17 + usrp/fpga/sdr_lib/ram64.v | 16 + usrp/fpga/sdr_lib/rssi.v | 30 + usrp/fpga/sdr_lib/rx_buffer.v | 182 + usrp/fpga/sdr_lib/rx_chain.v | 105 + usrp/fpga/sdr_lib/rx_chain_dual.v | 103 + usrp/fpga/sdr_lib/rx_dcoffset.v | 22 + usrp/fpga/sdr_lib/serial_io.v | 118 + usrp/fpga/sdr_lib/setting_reg.v | 23 + usrp/fpga/sdr_lib/setting_reg_masked.v | 26 + usrp/fpga/sdr_lib/sign_extend.v | 35 + usrp/fpga/sdr_lib/strobe_gen.v | 44 + usrp/fpga/sdr_lib/tx_buffer.v | 138 + usrp/fpga/sdr_lib/tx_chain.v | 65 + usrp/fpga/sdr_lib/tx_chain_hb.v | 76 + usrp/fpga/tb/cbus_tb.v | 71 + usrp/fpga/tb/cordic_tb.v | 61 + usrp/fpga/tb/decim_tb.v | 108 + usrp/fpga/tb/fullchip_tb.v | 174 + usrp/fpga/tb/interp_tb.v | 108 + usrp/fpga/tb/justinterp_tb.v | 73 + usrp/fpga/tb/makesine.pl | 14 + usrp/fpga/tb/run_cordic | 4 + usrp/fpga/tb/run_fullchip | 4 + usrp/fpga/tb/usrp_tasks.v | 145 + usrp/fpga/toplevel/mrfm/biquad_2stage.v | 131 + usrp/fpga/toplevel/mrfm/biquad_6stage.v | 137 + usrp/fpga/toplevel/mrfm/mrfm.csf | 444 + usrp/fpga/toplevel/mrfm/mrfm.esf | 14 + usrp/fpga/toplevel/mrfm/mrfm.psf | 312 + usrp/fpga/toplevel/mrfm/mrfm.py | 129 + usrp/fpga/toplevel/mrfm/mrfm.qpf | 29 + usrp/fpga/toplevel/mrfm/mrfm.qsf | 411 + usrp/fpga/toplevel/mrfm/mrfm.v | 199 + usrp/fpga/toplevel/mrfm/mrfm.vh | 21 + usrp/fpga/toplevel/mrfm/mrfm_compensator.v | 80 + usrp/fpga/toplevel/mrfm/mrfm_fft.py | 319 + usrp/fpga/toplevel/mrfm/mrfm_proc.v | 96 + usrp/fpga/toplevel/mrfm/shifter.v | 106 + usrp/fpga/toplevel/sizetest/sizetest.csf | 160 + usrp/fpga/toplevel/sizetest/sizetest.psf | 228 + usrp/fpga/toplevel/sizetest/sizetest.quartus | 19 + usrp/fpga/toplevel/sizetest/sizetest.ssf | 14 + usrp/fpga/toplevel/sizetest/sizetest.v | 39 + usrp/fpga/toplevel/usrp_multi/usrp_multi.csf | 444 + usrp/fpga/toplevel/usrp_multi/usrp_multi.esf | 14 + usrp/fpga/toplevel/usrp_multi/usrp_multi.psf | 312 + usrp/fpga/toplevel/usrp_multi/usrp_multi.qpf | 29 + usrp/fpga/toplevel/usrp_multi/usrp_multi.qsf | 408 + usrp/fpga/toplevel/usrp_multi/usrp_multi.v | 379 + usrp/fpga/toplevel/usrp_multi/usrp_multi.vh | 141 + .../usrp_multi/usrp_multi_config_2rx_0tx.vh | 62 + .../usrp_multi/usrp_multi_config_2rxhb_0tx.vh | 62 + .../usrp_multi/usrp_multi_config_2rxhb_2tx.vh | 62 + .../usrp_multi/usrp_multi_config_4rx_0tx.vh | 62 + usrp/fpga/toplevel/usrp_multi/usrp_std.vh | 29 + usrp/fpga/toplevel/usrp_std/usrp_std.csf | 444 + usrp/fpga/toplevel/usrp_std/usrp_std.esf | 14 + usrp/fpga/toplevel/usrp_std/usrp_std.psf | 312 + usrp/fpga/toplevel/usrp_std/usrp_std.qpf | 29 + usrp/fpga/toplevel/usrp_std/usrp_std.qsf | 406 + usrp/fpga/toplevel/usrp_std/usrp_std.v | 324 + usrp/fpga/toplevel/usrp_std/usrp_std.vh | 119 + .../usrp_std/usrp_std_config_2rxhb_2tx.vh | 61 + .../usrp_std/usrp_std_config_4rx_0tx.vh | 61 + usrp/host/Makefile.am | 23 + usrp/host/apps/Makefile.am | 53 + usrp/host/apps/burn-db-eeprom | 164 + usrp/host/apps/burn-serial-number | 80 + usrp/host/apps/check_order | 39 + usrp/host/apps/check_order_quickly.cc | 62 + usrp/host/apps/dump_12bit_shorts | 23 + usrp/host/apps/dump_shorts | 23 + usrp/host/apps/print-db | 19 + usrp/host/apps/run | 6 + usrp/host/apps/run2 | 4 + usrp/host/apps/run_input | 5 + usrp/host/apps/test_usrp_standard_rx.cc | 276 + usrp/host/apps/test_usrp_standard_tx.cc | 319 + usrp/host/apps/time_stuff.c | 68 + usrp/host/apps/time_stuff.h | 48 + usrp/host/apps/usrp_cal_dc_offset.cc | 242 + usrp/host/apps/usrper.cc | 352 + usrp/host/lib/Makefile.am | 137 + usrp/host/lib/README_OSX | 63 + usrp/host/lib/ad9862.h | 221 + usrp/host/lib/check_data.py | 50 + usrp/host/lib/circular_buffer.h | 325 + usrp/host/lib/circular_linked_list.h | 267 + usrp/host/lib/darwin_libusb.h | 190 + usrp/host/lib/dump_data.py | 40 + usrp/host/lib/dxc-io-assignments.gnumeric | Bin 0 -> 3251 bytes usrp/host/lib/fusb.cc | 60 + usrp/host/lib/fusb.h | 128 + usrp/host/lib/fusb_darwin.cc | 499 + usrp/host/lib/fusb_darwin.h | 215 + usrp/host/lib/fusb_generic.cc | 108 + usrp/host/lib/fusb_generic.h | 83 + usrp/host/lib/fusb_linux.cc | 684 ++ usrp/host/lib/fusb_linux.h | 116 + usrp/host/lib/fusb_sysconfig_darwin.cc | 37 + usrp/host/lib/fusb_sysconfig_generic.cc | 37 + usrp/host/lib/fusb_sysconfig_linux.cc | 37 + usrp/host/lib/fusb_sysconfig_win32.cc | 37 + usrp/host/lib/fusb_win32.cc | 265 + usrp/host/lib/fusb_win32.h | 90 + usrp/host/lib/gen-ratios | 48 + usrp/host/lib/gen_usrp_dbid.py | 137 + usrp/host/lib/md5.c | 452 + usrp/host/lib/md5.h | 129 + usrp/host/lib/mld_threads.h | 257 + usrp/host/lib/rate_to_regval.h | 97 + usrp/host/lib/std_paths.h.in | 27 + usrp/host/lib/usrp_basic.cc | 1239 ++ usrp/host/lib/usrp_basic.h | 776 ++ usrp/host/lib/usrp_bytesex.h | 74 + usrp/host/lib/usrp_config.cc | 35 + usrp/host/lib/usrp_config.h | 67 + usrp/host/lib/usrp_dbid.dat | 75 + usrp/host/lib/usrp_local_sighandler.cc | 190 + usrp/host/lib/usrp_local_sighandler.h | 61 + usrp/host/lib/usrp_prims.cc | 1355 +++ usrp/host/lib/usrp_prims.h | 294 + usrp/host/lib/usrp_slots.h | 33 + usrp/host/lib/usrp_standard.cc | 831 ++ usrp/host/lib/usrp_standard.h | 366 + usrp/host/misc/Makefile.am | 31 + usrp/host/misc/bug_work_around_8.cc | 2 + usrp/host/misc/getopt.c | 733 ++ usrp/host/misc/getopt.h | 129 + usrp/host/misc/gettimeofday.c | 50 + usrp/host/misc/mkstemp.c | 42 + usrp/host/misc/tempname.c | 352 + usrp/host/misc/usleep.c | 67 + usrp/host/swig/Makefile.am | 84 + usrp/host/swig/__init__.py | 1 + usrp/host/swig/prims.i | 266 + usrp/host/swig/usrp_fpga_regs.py | 30 + usrp/host/swig/util.py | 95 + usrp/usrp.inf | 91 + usrp/usrp.iss.in | 69 + usrp/usrp.pc.in | 11 + 2048 files changed, 277084 insertions(+) create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 ChangeLog create mode 100644 INSTALL create mode 100644 Makefile.am create mode 100644 Makefile.common create mode 100644 NEWS create mode 100644 README create mode 100755 bootstrap create mode 100755 config.guess create mode 100755 config.sub create mode 100644 config/Makefile.am create mode 100644 config/acx_pthread.m4 create mode 100644 config/bnv_have_qt.m4 create mode 100644 config/cppunit.m4 create mode 100644 config/gr_as.m4 create mode 100644 config/gr_atsc.m4 create mode 100644 config/gr_audio_alsa.m4 create mode 100644 config/gr_audio_jack.m4 create mode 100644 config/gr_audio_oss.m4 create mode 100644 config/gr_audio_osx.m4 create mode 100644 config/gr_audio_portaudio.m4 create mode 100644 config/gr_audio_windows.m4 create mode 100644 config/gr_boost.m4 create mode 100644 config/gr_check_createfilemapping.m4 create mode 100644 config/gr_check_mc4020.m4 create mode 100644 config/gr_check_shm_open.m4 create mode 100644 config/gr_check_usrp.m4 create mode 100644 config/gr_comedi.m4 create mode 100644 config/gr_doxygen.m4 create mode 100644 config/gr_error_correcting_codes.m4 create mode 100644 config/gr_fortran.m4 create mode 100644 config/gr_gnuradio_core.m4 create mode 100644 config/gr_gnuradio_examples.m4 create mode 100644 config/gr_gprof.m4 create mode 100644 config/gr_gsm_fr_vocoder.m4 create mode 100644 config/gr_libgnuradio_core_extra_ldflags.m4 create mode 100644 config/gr_no_undefined.m4 create mode 100644 config/gr_omnithread.m4 create mode 100644 config/gr_pmt.m4 create mode 100644 config/gr_pwin32.m4 create mode 100644 config/gr_python.m4 create mode 100644 config/gr_radar.m4 create mode 100644 config/gr_radio_astronomy.m4 create mode 100644 config/gr_require_mc4020.m4 create mode 100644 config/gr_scripting.m4 create mode 100644 config/gr_set_md_cpu.m4 create mode 100644 config/gr_swig.m4 create mode 100644 config/gr_sysv_shm.m4 create mode 100644 config/gr_usrp.m4 create mode 100644 config/gr_video_sdl.m4 create mode 100644 config/gr_wxgui.m4 create mode 100644 config/gr_x86_64.m4 create mode 100644 config/lf_cc.m4 create mode 100644 config/lf_cxx.m4 create mode 100644 config/lf_warnings.m4 create mode 100644 config/lf_x11.m4 create mode 100644 config/macosx_audiounit.m4 create mode 100644 config/mkstemp.m4 create mode 100644 config/onceonly.m4 create mode 100644 config/pkg.m4 create mode 100644 config/sdl.m4 create mode 100644 config/usrp_fusb_tech.m4 create mode 100644 config/usrp_libusb.m4 create mode 100644 config/usrp_sdcc.m4 create mode 100644 configure.ac create mode 100644 docs/COPYING create mode 100644 docs/ChangeLog create mode 100644 docs/exploring-gnuradio/Makefile create mode 100644 docs/exploring-gnuradio/ddc.eps create mode 100644 docs/exploring-gnuradio/ddc.png create mode 100755 docs/exploring-gnuradio/dial_tone.py create mode 100644 docs/exploring-gnuradio/dial_tone_example.xml create mode 100644 docs/exploring-gnuradio/exploring-gnuradio.xml create mode 100755 docs/exploring-gnuradio/fm_demod.py create mode 100644 docs/exploring-gnuradio/fm_demod_example.xml create mode 100644 docs/exploring-gnuradio/swr-block-diagram.eps create mode 100644 docs/exploring-gnuradio/swr-block-diagram.png create mode 100644 docs/exploring-gnuradio/usrp-block-diagram.eps create mode 100644 docs/exploring-gnuradio/usrp-block-diagram.png create mode 100644 docs/howto-write-a-block/README create mode 100644 dtools/COPYING create mode 100644 dtools/README create mode 100755 dtools/bin/check-config-files create mode 100755 dtools/bin/check-imports create mode 100755 dtools/bin/check-tarball-h-files create mode 100755 dtools/bin/get-config-files create mode 100755 dtools/bin/incr_release create mode 100755 dtools/bin/make-upload create mode 100755 dtools/bin/show_release create mode 100755 dtools/bin/tag_release create mode 100644 dtools/python/release_tools.py create mode 100644 gnuradio-core/ChangeLog create mode 100644 gnuradio-core/Makefile.am create mode 100644 gnuradio-core/NEWS create mode 100644 gnuradio-core/README create mode 100644 gnuradio-core/README-win32-mingw-short.txt create mode 100644 gnuradio-core/README.hacking create mode 100644 gnuradio-core/THANKS create mode 100644 gnuradio-core/TODO create mode 100644 gnuradio-core/doc/Doxyfile.in create mode 100644 gnuradio-core/doc/Makefile.am create mode 100644 gnuradio-core/doc/other/Makefile.am create mode 100644 gnuradio-core/doc/other/group_defs.dox create mode 100644 gnuradio-core/doc/other/main_page.dox create mode 100644 gnuradio-core/doc/other/omnithread.html create mode 100644 gnuradio-core/doc/other/omnithread.pdf create mode 100644 gnuradio-core/doc/other/omnithread.ps create mode 100755 gnuradio-core/doc/other/shared_ptr_docstub.h create mode 100644 gnuradio-core/doc/other/tv-channel-frequencies create mode 100644 gnuradio-core/doc/other/vector_docstub.h create mode 100644 gnuradio-core/doc/xml/Makefile.am create mode 100644 gnuradio-core/doc/xml/README create mode 100644 gnuradio-core/doc/xml/doxy2swig.py create mode 100644 gnuradio-core/doc/xml/swig.xsl create mode 100644 gnuradio-core/gnuradio-core.conf create mode 100644 gnuradio-core/gnuradio-core.pc.in create mode 100644 gnuradio-core/src/Makefile.am create mode 100644 gnuradio-core/src/gen_interpolator_taps/Makefile.am create mode 100644 gnuradio-core/src/gen_interpolator_taps/README create mode 100644 gnuradio-core/src/gen_interpolator_taps/gen_interpolator_taps.c create mode 100644 gnuradio-core/src/gen_interpolator_taps/objective_fct.c create mode 100644 gnuradio-core/src/gen_interpolator_taps/praxis.f create mode 100644 gnuradio-core/src/gen_interpolator_taps/praxis.txt create mode 100644 gnuradio-core/src/gen_interpolator_taps/simpson.c create mode 100644 gnuradio-core/src/gen_interpolator_taps/simpson.h create mode 100644 gnuradio-core/src/lib/Makefile.am create mode 100644 gnuradio-core/src/lib/bug_work_around_6.cc create mode 100644 gnuradio-core/src/lib/filter/3dnow_float_dotprod_really_simple.S create mode 100644 gnuradio-core/src/lib/filter/3dnow_float_dotprod_simple.S create mode 100644 gnuradio-core/src/lib/filter/Makefile.am create mode 100644 gnuradio-core/src/lib/filter/Makefile.gen create mode 100644 gnuradio-core/src/lib/filter/README create mode 100644 gnuradio-core/src/lib/filter/assembly.h create mode 100644 gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow.S create mode 100644 gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnow64.S create mode 100644 gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext.S create mode 100644 gnuradio-core/src/lib/filter/ccomplex_dotprod_3dnowext64.S create mode 100644 gnuradio-core/src/lib/filter/ccomplex_dotprod_generic.cc create mode 100644 gnuradio-core/src/lib/filter/ccomplex_dotprod_generic.h create mode 100644 gnuradio-core/src/lib/filter/ccomplex_dotprod_sse.S create mode 100644 gnuradio-core/src/lib/filter/ccomplex_dotprod_sse64.S create mode 100644 gnuradio-core/src/lib/filter/ccomplex_dotprod_x86.h create mode 100644 gnuradio-core/src/lib/filter/complex_dotprod_3dnow.S create mode 100644 gnuradio-core/src/lib/filter/complex_dotprod_3dnow64.S create mode 100644 gnuradio-core/src/lib/filter/complex_dotprod_3dnowext.S create mode 100644 gnuradio-core/src/lib/filter/complex_dotprod_3dnowext64.S create mode 100644 gnuradio-core/src/lib/filter/complex_dotprod_generic.cc create mode 100644 gnuradio-core/src/lib/filter/complex_dotprod_generic.h create mode 100644 gnuradio-core/src/lib/filter/complex_dotprod_sse.S create mode 100644 gnuradio-core/src/lib/filter/complex_dotprod_sse64.S create mode 100644 gnuradio-core/src/lib/filter/complex_dotprod_x86.h create mode 100644 gnuradio-core/src/lib/filter/cpuid_x86.S create mode 100644 gnuradio-core/src/lib/filter/cpuid_x86_64.S create mode 100644 gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow.S create mode 100644 gnuradio-core/src/lib/filter/fcomplex_dotprod_3dnow64.S create mode 100644 gnuradio-core/src/lib/filter/fcomplex_dotprod_sse.S create mode 100644 gnuradio-core/src/lib/filter/fcomplex_dotprod_sse64.S create mode 100644 gnuradio-core/src/lib/filter/fcomplex_dotprod_x86.h create mode 100644 gnuradio-core/src/lib/filter/filter.i create mode 100644 gnuradio-core/src/lib/filter/float_dotprod_3dnow.S create mode 100644 gnuradio-core/src/lib/filter/float_dotprod_3dnow64.S create mode 100644 gnuradio-core/src/lib/filter/float_dotprod_generic.c create mode 100644 gnuradio-core/src/lib/filter/float_dotprod_generic.h create mode 100644 gnuradio-core/src/lib/filter/float_dotprod_sse.S create mode 100644 gnuradio-core/src/lib/filter/float_dotprod_sse64.S create mode 100644 gnuradio-core/src/lib/filter/float_dotprod_x86.h create mode 100755 gnuradio-core/src/lib/filter/generate_all.py create mode 100755 gnuradio-core/src/lib/filter/generate_gr_fir_XXX.py create mode 100755 gnuradio-core/src/lib/filter/generate_gr_fir_filter_XXX.py create mode 100755 gnuradio-core/src/lib/filter/generate_gr_fir_sysconfig.py create mode 100755 gnuradio-core/src/lib/filter/generate_gr_fir_sysconfig_generic.py create mode 100755 gnuradio-core/src/lib/filter/generate_gr_fir_util.py create mode 100755 gnuradio-core/src/lib/filter/generate_gr_freq_xlating_fir_filter_XXX.py create mode 100644 gnuradio-core/src/lib/filter/generate_gr_interp_fir_filter_XXX.py create mode 100644 gnuradio-core/src/lib/filter/generate_gr_rational_resampler_base_XXX.py create mode 100644 gnuradio-core/src/lib/filter/generate_utils.py create mode 100644 gnuradio-core/src/lib/filter/gr_adaptive_fir_ccf.cc create mode 100644 gnuradio-core/src/lib/filter/gr_adaptive_fir_ccf.h create mode 100644 gnuradio-core/src/lib/filter/gr_adaptive_fir_ccf.i create mode 100644 gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.cc create mode 100644 gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.h create mode 100644 gnuradio-core/src/lib/filter/gr_cma_equalizer_cc.i create mode 100644 gnuradio-core/src/lib/filter/gr_cpu.cc create mode 100644 gnuradio-core/src/lib/filter/gr_cpu.h create mode 100644 gnuradio-core/src/lib/filter/gr_fft_filter_ccc.cc create mode 100644 gnuradio-core/src/lib/filter/gr_fft_filter_ccc.h create mode 100644 gnuradio-core/src/lib/filter/gr_fft_filter_ccc.i create mode 100644 gnuradio-core/src/lib/filter/gr_fft_filter_fff.cc create mode 100644 gnuradio-core/src/lib/filter/gr_fft_filter_fff.h create mode 100644 gnuradio-core/src/lib/filter/gr_fft_filter_fff.i create mode 100644 gnuradio-core/src/lib/filter/gr_filter_delay_fc.cc create mode 100644 gnuradio-core/src/lib/filter/gr_filter_delay_fc.h create mode 100644 gnuradio-core/src/lib/filter/gr_filter_delay_fc.i create mode 100644 gnuradio-core/src/lib/filter/gr_fir_XXX.cc.t create mode 100644 gnuradio-core/src/lib/filter/gr_fir_XXX.h.t create mode 100644 gnuradio-core/src/lib/filter/gr_fir_XXX_generic.cc.t create mode 100644 gnuradio-core/src/lib/filter/gr_fir_XXX_generic.h.t create mode 100644 gnuradio-core/src/lib/filter/gr_fir_ccc_simd.cc create mode 100644 gnuradio-core/src/lib/filter/gr_fir_ccc_simd.h create mode 100644 gnuradio-core/src/lib/filter/gr_fir_ccc_x86.cc create mode 100644 gnuradio-core/src/lib/filter/gr_fir_ccc_x86.h create mode 100644 gnuradio-core/src/lib/filter/gr_fir_ccf_simd.cc create mode 100644 gnuradio-core/src/lib/filter/gr_fir_ccf_simd.h create mode 100644 gnuradio-core/src/lib/filter/gr_fir_ccf_x86.cc create mode 100644 gnuradio-core/src/lib/filter/gr_fir_ccf_x86.h create mode 100644 gnuradio-core/src/lib/filter/gr_fir_fcc_simd.cc create mode 100644 gnuradio-core/src/lib/filter/gr_fir_fcc_simd.h create mode 100644 gnuradio-core/src/lib/filter/gr_fir_fcc_x86.cc create mode 100644 gnuradio-core/src/lib/filter/gr_fir_fcc_x86.h create mode 100644 gnuradio-core/src/lib/filter/gr_fir_fff_simd.cc create mode 100644 gnuradio-core/src/lib/filter/gr_fir_fff_simd.h create mode 100644 gnuradio-core/src/lib/filter/gr_fir_fff_x86.cc create mode 100644 gnuradio-core/src/lib/filter/gr_fir_fff_x86.h create mode 100644 gnuradio-core/src/lib/filter/gr_fir_filter_XXX.cc.t create mode 100644 gnuradio-core/src/lib/filter/gr_fir_filter_XXX.h.t create mode 100644 gnuradio-core/src/lib/filter/gr_fir_filter_XXX.i.t create mode 100644 gnuradio-core/src/lib/filter/gr_fir_fsf_simd.cc create mode 100644 gnuradio-core/src/lib/filter/gr_fir_fsf_simd.h create mode 100644 gnuradio-core/src/lib/filter/gr_fir_fsf_x86.cc create mode 100644 gnuradio-core/src/lib/filter/gr_fir_fsf_x86.h create mode 100644 gnuradio-core/src/lib/filter/gr_fir_scc_simd.cc create mode 100644 gnuradio-core/src/lib/filter/gr_fir_scc_simd.h create mode 100644 gnuradio-core/src/lib/filter/gr_fir_scc_x86.cc create mode 100644 gnuradio-core/src/lib/filter/gr_fir_scc_x86.h create mode 100644 gnuradio-core/src/lib/filter/gr_fir_sysconfig_x86.cc create mode 100644 gnuradio-core/src/lib/filter/gr_fir_sysconfig_x86.h create mode 100644 gnuradio-core/src/lib/filter/gr_fractional_interpolator.cc create mode 100644 gnuradio-core/src/lib/filter/gr_fractional_interpolator.h create mode 100644 gnuradio-core/src/lib/filter/gr_freq_xlating_fir_filter_XXX.cc.t create mode 100644 gnuradio-core/src/lib/filter/gr_freq_xlating_fir_filter_XXX.h.t create mode 100644 gnuradio-core/src/lib/filter/gr_freq_xlating_fir_filter_XXX.i.t create mode 100644 gnuradio-core/src/lib/filter/gr_goertzel_fc.cc create mode 100644 gnuradio-core/src/lib/filter/gr_goertzel_fc.h create mode 100644 gnuradio-core/src/lib/filter/gr_goertzel_fc.i create mode 100644 gnuradio-core/src/lib/filter/gr_hilbert_fc.cc create mode 100644 gnuradio-core/src/lib/filter/gr_hilbert_fc.h create mode 100644 gnuradio-core/src/lib/filter/gr_hilbert_fc.i create mode 100644 gnuradio-core/src/lib/filter/gr_iir_filter_ffd.cc create mode 100644 gnuradio-core/src/lib/filter/gr_iir_filter_ffd.h create mode 100644 gnuradio-core/src/lib/filter/gr_iir_filter_ffd.i create mode 100644 gnuradio-core/src/lib/filter/gr_interp_fir_filter_XXX.cc.t create mode 100644 gnuradio-core/src/lib/filter/gr_interp_fir_filter_XXX.h.t create mode 100644 gnuradio-core/src/lib/filter/gr_interp_fir_filter_XXX.i.t create mode 100644 gnuradio-core/src/lib/filter/gr_rational_resampler_base_XXX.cc.t create mode 100644 gnuradio-core/src/lib/filter/gr_rational_resampler_base_XXX.h.t create mode 100644 gnuradio-core/src/lib/filter/gr_rational_resampler_base_XXX.i.t create mode 100644 gnuradio-core/src/lib/filter/gr_rotator.h create mode 100644 gnuradio-core/src/lib/filter/gr_sincos.c create mode 100644 gnuradio-core/src/lib/filter/gr_sincos.h create mode 100644 gnuradio-core/src/lib/filter/gr_single_pole_avg.h create mode 100644 gnuradio-core/src/lib/filter/gr_single_pole_avg_filter_ff.cc create mode 100644 gnuradio-core/src/lib/filter/gr_single_pole_avg_filter_ff.h create mode 100644 gnuradio-core/src/lib/filter/gr_single_pole_avg_filter_ff.i create mode 100644 gnuradio-core/src/lib/filter/gr_single_pole_iir.h create mode 100644 gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_cc.cc create mode 100644 gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_cc.h create mode 100644 gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_cc.i create mode 100644 gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_ff.cc create mode 100644 gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_ff.h create mode 100644 gnuradio-core/src/lib/filter/gr_single_pole_iir_filter_ff.i create mode 100644 gnuradio-core/src/lib/filter/gr_single_pole_rec.h create mode 100644 gnuradio-core/src/lib/filter/gr_single_pole_rec_filter_ff.cc create mode 100644 gnuradio-core/src/lib/filter/gr_single_pole_rec_filter_ff.h create mode 100644 gnuradio-core/src/lib/filter/gr_single_pole_rec_filter_ff.i create mode 100644 gnuradio-core/src/lib/filter/gr_single_zero_avg.h create mode 100644 gnuradio-core/src/lib/filter/gr_single_zero_avg_filter_ff.cc create mode 100644 gnuradio-core/src/lib/filter/gr_single_zero_avg_filter_ff.h create mode 100644 gnuradio-core/src/lib/filter/gr_single_zero_avg_filter_ff.i create mode 100644 gnuradio-core/src/lib/filter/gr_single_zero_rec.h create mode 100644 gnuradio-core/src/lib/filter/gr_single_zero_rec_filter_ff.cc create mode 100644 gnuradio-core/src/lib/filter/gr_single_zero_rec_filter_ff.h create mode 100644 gnuradio-core/src/lib/filter/gr_single_zero_rec_filter_ff.i create mode 100644 gnuradio-core/src/lib/filter/gri_goertzel.cc create mode 100644 gnuradio-core/src/lib/filter/gri_goertzel.h create mode 100644 gnuradio-core/src/lib/filter/gri_iir.h create mode 100644 gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator.cc create mode 100644 gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator.h create mode 100644 gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator_cc.cc create mode 100644 gnuradio-core/src/lib/filter/gri_mmse_fir_interpolator_cc.h create mode 100644 gnuradio-core/src/lib/filter/interpolator_taps.h create mode 100644 gnuradio-core/src/lib/filter/qa_ccomplex_dotprod_x86.cc create mode 100644 gnuradio-core/src/lib/filter/qa_ccomplex_dotprod_x86.h create mode 100644 gnuradio-core/src/lib/filter/qa_complex_dotprod_x86.cc create mode 100644 gnuradio-core/src/lib/filter/qa_complex_dotprod_x86.h create mode 100644 gnuradio-core/src/lib/filter/qa_dotprod.h create mode 100644 gnuradio-core/src/lib/filter/qa_dotprod_generic.cc create mode 100644 gnuradio-core/src/lib/filter/qa_dotprod_x86.cc create mode 100644 gnuradio-core/src/lib/filter/qa_filter.cc create mode 100644 gnuradio-core/src/lib/filter/qa_filter.h create mode 100644 gnuradio-core/src/lib/filter/qa_float_dotprod_x86.cc create mode 100644 gnuradio-core/src/lib/filter/qa_float_dotprod_x86.h create mode 100644 gnuradio-core/src/lib/filter/qa_gr_fir_ccc.cc create mode 100644 gnuradio-core/src/lib/filter/qa_gr_fir_ccc.h create mode 100644 gnuradio-core/src/lib/filter/qa_gr_fir_ccf.cc create mode 100644 gnuradio-core/src/lib/filter/qa_gr_fir_ccf.h create mode 100644 gnuradio-core/src/lib/filter/qa_gr_fir_fcc.cc create mode 100644 gnuradio-core/src/lib/filter/qa_gr_fir_fcc.h create mode 100644 gnuradio-core/src/lib/filter/qa_gr_fir_fff.cc create mode 100644 gnuradio-core/src/lib/filter/qa_gr_fir_fff.h create mode 100644 gnuradio-core/src/lib/filter/qa_gr_fir_scc.cc create mode 100644 gnuradio-core/src/lib/filter/qa_gr_fir_scc.h create mode 100644 gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator.cc create mode 100644 gnuradio-core/src/lib/filter/qa_gri_mmse_fir_interpolator.h create mode 100644 gnuradio-core/src/lib/filter/short_dotprod_generic.c create mode 100644 gnuradio-core/src/lib/filter/short_dotprod_generic.h create mode 100644 gnuradio-core/src/lib/filter/short_dotprod_mmx.S create mode 100644 gnuradio-core/src/lib/filter/short_dotprod_mmx64.S create mode 100644 gnuradio-core/src/lib/filter/short_dotprod_x86.h create mode 100644 gnuradio-core/src/lib/filter/sse_debug.c create mode 100644 gnuradio-core/src/lib/filter/sse_debug.h create mode 100644 gnuradio-core/src/lib/filter/sysconfig_generic.cc create mode 100644 gnuradio-core/src/lib/filter/sysconfig_x86.cc create mode 100644 gnuradio-core/src/lib/g72x/Makefile.am create mode 100644 gnuradio-core/src/lib/g72x/README create mode 100644 gnuradio-core/src/lib/g72x/decode.c create mode 100644 gnuradio-core/src/lib/g72x/encode.c create mode 100644 gnuradio-core/src/lib/g72x/g711.c create mode 100644 gnuradio-core/src/lib/g72x/g721.c create mode 100644 gnuradio-core/src/lib/g72x/g723_24.c create mode 100644 gnuradio-core/src/lib/g72x/g723_40.c create mode 100644 gnuradio-core/src/lib/g72x/g72x.c create mode 100644 gnuradio-core/src/lib/g72x/g72x.h create mode 100644 gnuradio-core/src/lib/general/Makefile.am create mode 100644 gnuradio-core/src/lib/general/Makefile.gen create mode 100644 gnuradio-core/src/lib/general/README create mode 100644 gnuradio-core/src/lib/general/atsc_rrc1x.dat create mode 100644 gnuradio-core/src/lib/general/atsc_rrc20.dat create mode 100644 gnuradio-core/src/lib/general/atsc_rrc2x.dat create mode 100755 gnuradio-core/src/lib/general/gen_sine_table.py create mode 100644 gnuradio-core/src/lib/general/general.i create mode 100644 gnuradio-core/src/lib/general/general_generated.i create mode 100755 gnuradio-core/src/lib/general/generate_all.py create mode 100755 gnuradio-core/src/lib/general/generate_common.py create mode 100644 gnuradio-core/src/lib/general/gr_add_XX.cc.t create mode 100644 gnuradio-core/src/lib/general/gr_add_XX.h.t create mode 100644 gnuradio-core/src/lib/general/gr_add_XX.i.t create mode 100644 gnuradio-core/src/lib/general/gr_add_const_XX.cc.t create mode 100644 gnuradio-core/src/lib/general/gr_add_const_XX.h.t create mode 100644 gnuradio-core/src/lib/general/gr_add_const_XX.i.t create mode 100755 gnuradio-core/src/lib/general/gr_add_const_vXX.cc.t create mode 100755 gnuradio-core/src/lib/general/gr_add_const_vXX.h.t create mode 100755 gnuradio-core/src/lib/general/gr_add_const_vXX.i.t create mode 100755 gnuradio-core/src/lib/general/gr_add_vXX.cc.t create mode 100755 gnuradio-core/src/lib/general/gr_add_vXX.h.t create mode 100755 gnuradio-core/src/lib/general/gr_add_vXX.i.t create mode 100644 gnuradio-core/src/lib/general/gr_agc_cc.cc create mode 100644 gnuradio-core/src/lib/general/gr_agc_cc.h create mode 100644 gnuradio-core/src/lib/general/gr_agc_cc.i create mode 100644 gnuradio-core/src/lib/general/gr_agc_ff.cc create mode 100644 gnuradio-core/src/lib/general/gr_agc_ff.h create mode 100644 gnuradio-core/src/lib/general/gr_agc_ff.i create mode 100644 gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.cc create mode 100644 gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.h create mode 100644 gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.i create mode 100644 gnuradio-core/src/lib/general/gr_binary_slicer_fb.cc create mode 100644 gnuradio-core/src/lib/general/gr_binary_slicer_fb.h create mode 100644 gnuradio-core/src/lib/general/gr_binary_slicer_fb.i create mode 100644 gnuradio-core/src/lib/general/gr_bytes_to_syms.cc create mode 100644 gnuradio-core/src/lib/general/gr_bytes_to_syms.h create mode 100644 gnuradio-core/src/lib/general/gr_bytes_to_syms.i create mode 100644 gnuradio-core/src/lib/general/gr_char_to_float.cc create mode 100644 gnuradio-core/src/lib/general/gr_char_to_float.h create mode 100644 gnuradio-core/src/lib/general/gr_char_to_float.i create mode 100644 gnuradio-core/src/lib/general/gr_check_counting_s.cc create mode 100644 gnuradio-core/src/lib/general/gr_check_counting_s.h create mode 100644 gnuradio-core/src/lib/general/gr_check_counting_s.i create mode 100644 gnuradio-core/src/lib/general/gr_check_lfsr_32k_s.cc create mode 100644 gnuradio-core/src/lib/general/gr_check_lfsr_32k_s.h create mode 100644 gnuradio-core/src/lib/general/gr_check_lfsr_32k_s.i create mode 100644 gnuradio-core/src/lib/general/gr_chunks_to_symbols_XX.cc.t create mode 100644 gnuradio-core/src/lib/general/gr_chunks_to_symbols_XX.h.t create mode 100644 gnuradio-core/src/lib/general/gr_chunks_to_symbols_XX.i.t create mode 100644 gnuradio-core/src/lib/general/gr_circular_file.cc create mode 100644 gnuradio-core/src/lib/general/gr_circular_file.h create mode 100644 gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.cc create mode 100644 gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.h create mode 100644 gnuradio-core/src/lib/general/gr_clock_recovery_mm_cc.i create mode 100644 gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.cc create mode 100644 gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.h create mode 100644 gnuradio-core/src/lib/general/gr_clock_recovery_mm_ff.i create mode 100644 gnuradio-core/src/lib/general/gr_complex_to_interleaved_short.cc create mode 100644 gnuradio-core/src/lib/general/gr_complex_to_interleaved_short.h create mode 100644 gnuradio-core/src/lib/general/gr_complex_to_interleaved_short.i create mode 100644 gnuradio-core/src/lib/general/gr_complex_to_xxx.cc create mode 100644 gnuradio-core/src/lib/general/gr_complex_to_xxx.h create mode 100644 gnuradio-core/src/lib/general/gr_complex_to_xxx.i create mode 100644 gnuradio-core/src/lib/general/gr_conjugate_cc.cc create mode 100644 gnuradio-core/src/lib/general/gr_conjugate_cc.h create mode 100644 gnuradio-core/src/lib/general/gr_conjugate_cc.i create mode 100644 gnuradio-core/src/lib/general/gr_constellation_decoder_cb.cc create mode 100644 gnuradio-core/src/lib/general/gr_constellation_decoder_cb.h create mode 100644 gnuradio-core/src/lib/general/gr_constellation_decoder_cb.i create mode 100644 gnuradio-core/src/lib/general/gr_correlate_access_code_bb.cc create mode 100644 gnuradio-core/src/lib/general/gr_correlate_access_code_bb.h create mode 100644 gnuradio-core/src/lib/general/gr_correlate_access_code_bb.i create mode 100644 gnuradio-core/src/lib/general/gr_costas_loop_cc.cc create mode 100644 gnuradio-core/src/lib/general/gr_costas_loop_cc.h create mode 100644 gnuradio-core/src/lib/general/gr_costas_loop_cc.i create mode 100644 gnuradio-core/src/lib/general/gr_count_bits.cc create mode 100644 gnuradio-core/src/lib/general/gr_count_bits.h create mode 100644 gnuradio-core/src/lib/general/gr_crc32.cc create mode 100644 gnuradio-core/src/lib/general/gr_crc32.h create mode 100644 gnuradio-core/src/lib/general/gr_crc32.i create mode 100644 gnuradio-core/src/lib/general/gr_ctcss_squelch_ff.cc create mode 100644 gnuradio-core/src/lib/general/gr_ctcss_squelch_ff.h create mode 100644 gnuradio-core/src/lib/general/gr_ctcss_squelch_ff.i create mode 100644 gnuradio-core/src/lib/general/gr_dd_mpsk_sync_cc.cc create mode 100644 gnuradio-core/src/lib/general/gr_dd_mpsk_sync_cc.h create mode 100644 gnuradio-core/src/lib/general/gr_dd_mpsk_sync_cc.i create mode 100644 gnuradio-core/src/lib/general/gr_deinterleave.cc create mode 100644 gnuradio-core/src/lib/general/gr_deinterleave.h create mode 100644 gnuradio-core/src/lib/general/gr_deinterleave.i create mode 100644 gnuradio-core/src/lib/general/gr_diff_decoder_bb.cc create mode 100644 gnuradio-core/src/lib/general/gr_diff_decoder_bb.h create mode 100644 gnuradio-core/src/lib/general/gr_diff_decoder_bb.i create mode 100644 gnuradio-core/src/lib/general/gr_diff_encoder_bb.cc create mode 100644 gnuradio-core/src/lib/general/gr_diff_encoder_bb.h create mode 100644 gnuradio-core/src/lib/general/gr_diff_encoder_bb.i create mode 100644 gnuradio-core/src/lib/general/gr_diff_phasor_cc.cc create mode 100644 gnuradio-core/src/lib/general/gr_diff_phasor_cc.h create mode 100644 gnuradio-core/src/lib/general/gr_diff_phasor_cc.i create mode 100644 gnuradio-core/src/lib/general/gr_divide_XX.cc.t create mode 100644 gnuradio-core/src/lib/general/gr_divide_XX.h.t create mode 100644 gnuradio-core/src/lib/general/gr_divide_XX.i.t create mode 100644 gnuradio-core/src/lib/general/gr_endianness.h create mode 100644 gnuradio-core/src/lib/general/gr_endianness.i create mode 100644 gnuradio-core/src/lib/general/gr_expj.h create mode 100644 gnuradio-core/src/lib/general/gr_fake_channel_coder_pp.cc create mode 100644 gnuradio-core/src/lib/general/gr_fake_channel_coder_pp.h create mode 100644 gnuradio-core/src/lib/general/gr_fake_channel_coder_pp.i create mode 100644 gnuradio-core/src/lib/general/gr_fast_atan2f.cc create mode 100644 gnuradio-core/src/lib/general/gr_feval.cc create mode 100644 gnuradio-core/src/lib/general/gr_feval.h create mode 100644 gnuradio-core/src/lib/general/gr_feval.i create mode 100644 gnuradio-core/src/lib/general/gr_fft_vcc.cc create mode 100644 gnuradio-core/src/lib/general/gr_fft_vcc.h create mode 100644 gnuradio-core/src/lib/general/gr_fft_vcc.i create mode 100644 gnuradio-core/src/lib/general/gr_fft_vfc.cc create mode 100644 gnuradio-core/src/lib/general/gr_fft_vfc.h create mode 100644 gnuradio-core/src/lib/general/gr_fft_vfc.i create mode 100644 gnuradio-core/src/lib/general/gr_firdes.cc create mode 100644 gnuradio-core/src/lib/general/gr_firdes.h create mode 100644 gnuradio-core/src/lib/general/gr_firdes.i create mode 100644 gnuradio-core/src/lib/general/gr_float_to_char.cc create mode 100644 gnuradio-core/src/lib/general/gr_float_to_char.h create mode 100644 gnuradio-core/src/lib/general/gr_float_to_char.i create mode 100644 gnuradio-core/src/lib/general/gr_float_to_complex.cc create mode 100644 gnuradio-core/src/lib/general/gr_float_to_complex.h create mode 100644 gnuradio-core/src/lib/general/gr_float_to_complex.i create mode 100644 gnuradio-core/src/lib/general/gr_float_to_short.cc create mode 100644 gnuradio-core/src/lib/general/gr_float_to_short.h create mode 100644 gnuradio-core/src/lib/general/gr_float_to_short.i create mode 100644 gnuradio-core/src/lib/general/gr_float_to_uchar.cc create mode 100644 gnuradio-core/src/lib/general/gr_float_to_uchar.h create mode 100644 gnuradio-core/src/lib/general/gr_float_to_uchar.i create mode 100644 gnuradio-core/src/lib/general/gr_framer_sink_1.cc create mode 100644 gnuradio-core/src/lib/general/gr_framer_sink_1.h create mode 100644 gnuradio-core/src/lib/general/gr_framer_sink_1.i create mode 100644 gnuradio-core/src/lib/general/gr_frequency_modulator_fc.cc create mode 100644 gnuradio-core/src/lib/general/gr_frequency_modulator_fc.h create mode 100644 gnuradio-core/src/lib/general/gr_frequency_modulator_fc.i create mode 100644 gnuradio-core/src/lib/general/gr_fxpt.cc create mode 100644 gnuradio-core/src/lib/general/gr_fxpt.h create mode 100644 gnuradio-core/src/lib/general/gr_fxpt_nco.h create mode 100644 gnuradio-core/src/lib/general/gr_fxpt_vco.h create mode 100644 gnuradio-core/src/lib/general/gr_head.cc create mode 100644 gnuradio-core/src/lib/general/gr_head.h create mode 100644 gnuradio-core/src/lib/general/gr_head.i create mode 100644 gnuradio-core/src/lib/general/gr_interleave.cc create mode 100644 gnuradio-core/src/lib/general/gr_interleave.h create mode 100644 gnuradio-core/src/lib/general/gr_interleave.i create mode 100644 gnuradio-core/src/lib/general/gr_interleaved_short_to_complex.cc create mode 100644 gnuradio-core/src/lib/general/gr_interleaved_short_to_complex.h create mode 100644 gnuradio-core/src/lib/general/gr_interleaved_short_to_complex.i create mode 100644 gnuradio-core/src/lib/general/gr_keep_one_in_n.cc create mode 100644 gnuradio-core/src/lib/general/gr_keep_one_in_n.h create mode 100644 gnuradio-core/src/lib/general/gr_keep_one_in_n.i create mode 100644 gnuradio-core/src/lib/general/gr_kludge_copy.cc create mode 100644 gnuradio-core/src/lib/general/gr_kludge_copy.h create mode 100644 gnuradio-core/src/lib/general/gr_kludge_copy.i create mode 100644 gnuradio-core/src/lib/general/gr_lfsr_32k_source_s.cc create mode 100644 gnuradio-core/src/lib/general/gr_lfsr_32k_source_s.h create mode 100644 gnuradio-core/src/lib/general/gr_lfsr_32k_source_s.i create mode 100644 gnuradio-core/src/lib/general/gr_lms_dfe_cc.cc create mode 100644 gnuradio-core/src/lib/general/gr_lms_dfe_cc.h create mode 100644 gnuradio-core/src/lib/general/gr_lms_dfe_cc.i create mode 100644 gnuradio-core/src/lib/general/gr_lms_dfe_ff.cc create mode 100644 gnuradio-core/src/lib/general/gr_lms_dfe_ff.h create mode 100644 gnuradio-core/src/lib/general/gr_lms_dfe_ff.i create mode 100644 gnuradio-core/src/lib/general/gr_log2_const.h create mode 100644 gnuradio-core/src/lib/general/gr_map_bb.cc create mode 100644 gnuradio-core/src/lib/general/gr_map_bb.h create mode 100644 gnuradio-core/src/lib/general/gr_map_bb.i create mode 100644 gnuradio-core/src/lib/general/gr_math.cc create mode 100644 gnuradio-core/src/lib/general/gr_math.h create mode 100644 gnuradio-core/src/lib/general/gr_misc.cc create mode 100644 gnuradio-core/src/lib/general/gr_misc.h create mode 100644 gnuradio-core/src/lib/general/gr_multiply_XX.cc.t create mode 100644 gnuradio-core/src/lib/general/gr_multiply_XX.h.t create mode 100644 gnuradio-core/src/lib/general/gr_multiply_XX.i.t create mode 100644 gnuradio-core/src/lib/general/gr_multiply_const_XX.cc.t create mode 100644 gnuradio-core/src/lib/general/gr_multiply_const_XX.h.t create mode 100644 gnuradio-core/src/lib/general/gr_multiply_const_XX.i.t create mode 100755 gnuradio-core/src/lib/general/gr_multiply_const_vXX.cc.t create mode 100755 gnuradio-core/src/lib/general/gr_multiply_const_vXX.h.t create mode 100755 gnuradio-core/src/lib/general/gr_multiply_const_vXX.i.t create mode 100755 gnuradio-core/src/lib/general/gr_multiply_vXX.cc.t create mode 100755 gnuradio-core/src/lib/general/gr_multiply_vXX.h.t create mode 100755 gnuradio-core/src/lib/general/gr_multiply_vXX.i.t create mode 100644 gnuradio-core/src/lib/general/gr_mute_XX.cc.t create mode 100644 gnuradio-core/src/lib/general/gr_mute_XX.h.t create mode 100644 gnuradio-core/src/lib/general/gr_mute_XX.i.t create mode 100644 gnuradio-core/src/lib/general/gr_nco.h create mode 100644 gnuradio-core/src/lib/general/gr_nlog10_ff.cc create mode 100644 gnuradio-core/src/lib/general/gr_nlog10_ff.h create mode 100644 gnuradio-core/src/lib/general/gr_nlog10_ff.i create mode 100644 gnuradio-core/src/lib/general/gr_noise_source_X.cc.t create mode 100644 gnuradio-core/src/lib/general/gr_noise_source_X.h.t create mode 100644 gnuradio-core/src/lib/general/gr_noise_source_X.i.t create mode 100644 gnuradio-core/src/lib/general/gr_noise_type.h create mode 100644 gnuradio-core/src/lib/general/gr_nop.cc create mode 100644 gnuradio-core/src/lib/general/gr_nop.h create mode 100644 gnuradio-core/src/lib/general/gr_nop.i create mode 100644 gnuradio-core/src/lib/general/gr_null_sink.cc create mode 100644 gnuradio-core/src/lib/general/gr_null_sink.h create mode 100644 gnuradio-core/src/lib/general/gr_null_sink.i create mode 100644 gnuradio-core/src/lib/general/gr_null_source.cc create mode 100644 gnuradio-core/src/lib/general/gr_null_source.h create mode 100644 gnuradio-core/src/lib/general/gr_null_source.i create mode 100644 gnuradio-core/src/lib/general/gr_pa_2x2_phase_combiner.cc create mode 100644 gnuradio-core/src/lib/general/gr_pa_2x2_phase_combiner.h create mode 100644 gnuradio-core/src/lib/general/gr_pa_2x2_phase_combiner.i create mode 100644 gnuradio-core/src/lib/general/gr_packed_to_unpacked_XX.cc.t create mode 100644 gnuradio-core/src/lib/general/gr_packed_to_unpacked_XX.h.t create mode 100644 gnuradio-core/src/lib/general/gr_packed_to_unpacked_XX.i.t create mode 100644 gnuradio-core/src/lib/general/gr_packet_sink.cc create mode 100644 gnuradio-core/src/lib/general/gr_packet_sink.h create mode 100644 gnuradio-core/src/lib/general/gr_packet_sink.i create mode 100644 gnuradio-core/src/lib/general/gr_phase_modulator_fc.cc create mode 100644 gnuradio-core/src/lib/general/gr_phase_modulator_fc.h create mode 100644 gnuradio-core/src/lib/general/gr_phase_modulator_fc.i create mode 100644 gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.cc create mode 100644 gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.h create mode 100644 gnuradio-core/src/lib/general/gr_pll_carriertracking_cc.i create mode 100644 gnuradio-core/src/lib/general/gr_pll_freqdet_cf.cc create mode 100644 gnuradio-core/src/lib/general/gr_pll_freqdet_cf.h create mode 100644 gnuradio-core/src/lib/general/gr_pll_freqdet_cf.i create mode 100644 gnuradio-core/src/lib/general/gr_pll_refout_cc.cc create mode 100644 gnuradio-core/src/lib/general/gr_pll_refout_cc.h create mode 100644 gnuradio-core/src/lib/general/gr_pll_refout_cc.i create mode 100644 gnuradio-core/src/lib/general/gr_prefix.cc.in create mode 100644 gnuradio-core/src/lib/general/gr_prefix.h create mode 100644 gnuradio-core/src/lib/general/gr_prefix.i create mode 100644 gnuradio-core/src/lib/general/gr_prefs.cc create mode 100644 gnuradio-core/src/lib/general/gr_prefs.h create mode 100644 gnuradio-core/src/lib/general/gr_prefs.i create mode 100644 gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_c.cc create mode 100644 gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_c.h create mode 100644 gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_c.i create mode 100644 gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_f.cc create mode 100644 gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_f.h create mode 100644 gnuradio-core/src/lib/general/gr_probe_avg_mag_sqrd_f.i create mode 100644 gnuradio-core/src/lib/general/gr_probe_signal_f.cc create mode 100644 gnuradio-core/src/lib/general/gr_probe_signal_f.h create mode 100644 gnuradio-core/src/lib/general/gr_probe_signal_f.i create mode 100644 gnuradio-core/src/lib/general/gr_pwr_squelch_cc.cc create mode 100644 gnuradio-core/src/lib/general/gr_pwr_squelch_cc.h create mode 100644 gnuradio-core/src/lib/general/gr_pwr_squelch_cc.i create mode 100644 gnuradio-core/src/lib/general/gr_pwr_squelch_ff.cc create mode 100644 gnuradio-core/src/lib/general/gr_pwr_squelch_ff.h create mode 100644 gnuradio-core/src/lib/general/gr_pwr_squelch_ff.i create mode 100644 gnuradio-core/src/lib/general/gr_quadrature_demod_cf.cc create mode 100644 gnuradio-core/src/lib/general/gr_quadrature_demod_cf.h create mode 100644 gnuradio-core/src/lib/general/gr_quadrature_demod_cf.i create mode 100644 gnuradio-core/src/lib/general/gr_random.cc create mode 100644 gnuradio-core/src/lib/general/gr_random.h create mode 100644 gnuradio-core/src/lib/general/gr_remez.cc create mode 100644 gnuradio-core/src/lib/general/gr_remez.h create mode 100644 gnuradio-core/src/lib/general/gr_remez.i create mode 100644 gnuradio-core/src/lib/general/gr_reverse.cc create mode 100644 gnuradio-core/src/lib/general/gr_reverse.h create mode 100644 gnuradio-core/src/lib/general/gr_rms_cf.cc create mode 100644 gnuradio-core/src/lib/general/gr_rms_cf.h create mode 100644 gnuradio-core/src/lib/general/gr_rms_cf.i create mode 100644 gnuradio-core/src/lib/general/gr_rms_ff.cc create mode 100644 gnuradio-core/src/lib/general/gr_rms_ff.h create mode 100644 gnuradio-core/src/lib/general/gr_rms_ff.i create mode 100644 gnuradio-core/src/lib/general/gr_short_to_float.cc create mode 100644 gnuradio-core/src/lib/general/gr_short_to_float.h create mode 100644 gnuradio-core/src/lib/general/gr_short_to_float.i create mode 100644 gnuradio-core/src/lib/general/gr_sig_source_X.cc.t create mode 100644 gnuradio-core/src/lib/general/gr_sig_source_X.h.t create mode 100644 gnuradio-core/src/lib/general/gr_sig_source_X.i.t create mode 100644 gnuradio-core/src/lib/general/gr_sig_source_waveform.h create mode 100644 gnuradio-core/src/lib/general/gr_simple_correlator.cc create mode 100644 gnuradio-core/src/lib/general/gr_simple_correlator.h create mode 100644 gnuradio-core/src/lib/general/gr_simple_correlator.i create mode 100644 gnuradio-core/src/lib/general/gr_simple_framer.cc create mode 100644 gnuradio-core/src/lib/general/gr_simple_framer.h create mode 100644 gnuradio-core/src/lib/general/gr_simple_framer.i create mode 100644 gnuradio-core/src/lib/general/gr_simple_framer_sync.h create mode 100644 gnuradio-core/src/lib/general/gr_simple_squelch_cc.cc create mode 100644 gnuradio-core/src/lib/general/gr_simple_squelch_cc.h create mode 100644 gnuradio-core/src/lib/general/gr_simple_squelch_cc.i create mode 100644 gnuradio-core/src/lib/general/gr_skiphead.cc create mode 100644 gnuradio-core/src/lib/general/gr_skiphead.h create mode 100644 gnuradio-core/src/lib/general/gr_skiphead.i create mode 100644 gnuradio-core/src/lib/general/gr_squelch_base_cc.cc create mode 100644 gnuradio-core/src/lib/general/gr_squelch_base_cc.h create mode 100644 gnuradio-core/src/lib/general/gr_squelch_base_cc.i create mode 100644 gnuradio-core/src/lib/general/gr_squelch_base_ff.cc create mode 100644 gnuradio-core/src/lib/general/gr_squelch_base_ff.h create mode 100644 gnuradio-core/src/lib/general/gr_squelch_base_ff.i create mode 100644 gnuradio-core/src/lib/general/gr_stream_to_streams.cc create mode 100644 gnuradio-core/src/lib/general/gr_stream_to_streams.h create mode 100644 gnuradio-core/src/lib/general/gr_stream_to_streams.i create mode 100644 gnuradio-core/src/lib/general/gr_stream_to_vector.cc create mode 100644 gnuradio-core/src/lib/general/gr_stream_to_vector.h create mode 100644 gnuradio-core/src/lib/general/gr_stream_to_vector.i create mode 100644 gnuradio-core/src/lib/general/gr_streams_to_stream.cc create mode 100644 gnuradio-core/src/lib/general/gr_streams_to_stream.h create mode 100644 gnuradio-core/src/lib/general/gr_streams_to_stream.i create mode 100644 gnuradio-core/src/lib/general/gr_streams_to_vector.cc create mode 100644 gnuradio-core/src/lib/general/gr_streams_to_vector.h create mode 100644 gnuradio-core/src/lib/general/gr_streams_to_vector.i create mode 100644 gnuradio-core/src/lib/general/gr_sub_XX.cc.t create mode 100644 gnuradio-core/src/lib/general/gr_sub_XX.h.t create mode 100644 gnuradio-core/src/lib/general/gr_sub_XX.i.t create mode 100644 gnuradio-core/src/lib/general/gr_sync_block.cc create mode 100644 gnuradio-core/src/lib/general/gr_sync_block.h create mode 100644 gnuradio-core/src/lib/general/gr_sync_block.i create mode 100644 gnuradio-core/src/lib/general/gr_sync_decimator.cc create mode 100644 gnuradio-core/src/lib/general/gr_sync_decimator.h create mode 100644 gnuradio-core/src/lib/general/gr_sync_decimator.i create mode 100644 gnuradio-core/src/lib/general/gr_sync_interpolator.cc create mode 100644 gnuradio-core/src/lib/general/gr_sync_interpolator.h create mode 100644 gnuradio-core/src/lib/general/gr_sync_interpolator.i create mode 100644 gnuradio-core/src/lib/general/gr_test.cc create mode 100644 gnuradio-core/src/lib/general/gr_test.h create mode 100644 gnuradio-core/src/lib/general/gr_test.i create mode 100644 gnuradio-core/src/lib/general/gr_test_types.h create mode 100644 gnuradio-core/src/lib/general/gr_threshold_ff.cc create mode 100644 gnuradio-core/src/lib/general/gr_threshold_ff.h create mode 100644 gnuradio-core/src/lib/general/gr_threshold_ff.i create mode 100644 gnuradio-core/src/lib/general/gr_throttle.cc create mode 100644 gnuradio-core/src/lib/general/gr_throttle.h create mode 100644 gnuradio-core/src/lib/general/gr_throttle.i create mode 100644 gnuradio-core/src/lib/general/gr_uchar_to_float.cc create mode 100644 gnuradio-core/src/lib/general/gr_uchar_to_float.h create mode 100644 gnuradio-core/src/lib/general/gr_uchar_to_float.i create mode 100644 gnuradio-core/src/lib/general/gr_unpack_k_bits_bb.cc create mode 100644 gnuradio-core/src/lib/general/gr_unpack_k_bits_bb.h create mode 100644 gnuradio-core/src/lib/general/gr_unpack_k_bits_bb.i create mode 100644 gnuradio-core/src/lib/general/gr_unpacked_to_packed_XX.cc.t create mode 100644 gnuradio-core/src/lib/general/gr_unpacked_to_packed_XX.h.t create mode 100644 gnuradio-core/src/lib/general/gr_unpacked_to_packed_XX.i.t create mode 100644 gnuradio-core/src/lib/general/gr_vco.h create mode 100644 gnuradio-core/src/lib/general/gr_vco_f.cc create mode 100644 gnuradio-core/src/lib/general/gr_vco_f.h create mode 100644 gnuradio-core/src/lib/general/gr_vco_f.i create mode 100644 gnuradio-core/src/lib/general/gr_vector_sink_X.cc.t create mode 100644 gnuradio-core/src/lib/general/gr_vector_sink_X.h.t create mode 100644 gnuradio-core/src/lib/general/gr_vector_sink_X.i.t create mode 100644 gnuradio-core/src/lib/general/gr_vector_source_X.cc.t create mode 100644 gnuradio-core/src/lib/general/gr_vector_source_X.h.t create mode 100644 gnuradio-core/src/lib/general/gr_vector_source_X.i.t create mode 100644 gnuradio-core/src/lib/general/gr_vector_to_stream.cc create mode 100644 gnuradio-core/src/lib/general/gr_vector_to_stream.h create mode 100644 gnuradio-core/src/lib/general/gr_vector_to_stream.i create mode 100644 gnuradio-core/src/lib/general/gr_vector_to_streams.cc create mode 100644 gnuradio-core/src/lib/general/gr_vector_to_streams.h create mode 100644 gnuradio-core/src/lib/general/gr_vector_to_streams.i create mode 100644 gnuradio-core/src/lib/general/gri_add_const_ss.h create mode 100644 gnuradio-core/src/lib/general/gri_add_const_ss_generic.cc create mode 100644 gnuradio-core/src/lib/general/gri_agc.h create mode 100644 gnuradio-core/src/lib/general/gri_agc.i create mode 100644 gnuradio-core/src/lib/general/gri_agc_cc.h create mode 100644 gnuradio-core/src/lib/general/gri_agc_cc.i create mode 100644 gnuradio-core/src/lib/general/gri_char_to_float.cc create mode 100644 gnuradio-core/src/lib/general/gri_char_to_float.h create mode 100644 gnuradio-core/src/lib/general/gri_debugger_hook.cc create mode 100644 gnuradio-core/src/lib/general/gri_debugger_hook.h create mode 100644 gnuradio-core/src/lib/general/gri_fft.cc create mode 100644 gnuradio-core/src/lib/general/gri_fft.h create mode 100644 gnuradio-core/src/lib/general/gri_float_to_char.cc create mode 100644 gnuradio-core/src/lib/general/gri_float_to_char.h create mode 100644 gnuradio-core/src/lib/general/gri_float_to_short.cc create mode 100644 gnuradio-core/src/lib/general/gri_float_to_short.h create mode 100644 gnuradio-core/src/lib/general/gri_float_to_uchar.cc create mode 100644 gnuradio-core/src/lib/general/gri_float_to_uchar.h create mode 100644 gnuradio-core/src/lib/general/gri_interleaved_short_to_complex.cc create mode 100644 gnuradio-core/src/lib/general/gri_interleaved_short_to_complex.h create mode 100644 gnuradio-core/src/lib/general/gri_lfsr_15_1_0.h create mode 100644 gnuradio-core/src/lib/general/gri_lfsr_32k.h create mode 100644 gnuradio-core/src/lib/general/gri_short_to_float.cc create mode 100644 gnuradio-core/src/lib/general/gri_short_to_float.h create mode 100644 gnuradio-core/src/lib/general/gri_uchar_to_float.cc create mode 100644 gnuradio-core/src/lib/general/gri_uchar_to_float.h create mode 100644 gnuradio-core/src/lib/general/malloc16.c create mode 100644 gnuradio-core/src/lib/general/malloc16.h create mode 100644 gnuradio-core/src/lib/general/qa_general.cc create mode 100644 gnuradio-core/src/lib/general/qa_general.h create mode 100644 gnuradio-core/src/lib/general/qa_gr_circular_file.cc create mode 100644 gnuradio-core/src/lib/general/qa_gr_circular_file.h create mode 100644 gnuradio-core/src/lib/general/qa_gr_firdes.cc create mode 100644 gnuradio-core/src/lib/general/qa_gr_firdes.h create mode 100644 gnuradio-core/src/lib/general/qa_gr_fxpt.cc create mode 100644 gnuradio-core/src/lib/general/qa_gr_fxpt.h create mode 100644 gnuradio-core/src/lib/general/qa_gr_fxpt_nco.cc create mode 100644 gnuradio-core/src/lib/general/qa_gr_fxpt_nco.h create mode 100644 gnuradio-core/src/lib/general/qa_gr_fxpt_vco.cc create mode 100644 gnuradio-core/src/lib/general/qa_gr_fxpt_vco.h create mode 100644 gnuradio-core/src/lib/general/random.h create mode 100644 gnuradio-core/src/lib/general/sine_table.h create mode 100644 gnuradio-core/src/lib/io/Makefile.am create mode 100644 gnuradio-core/src/lib/io/gr_file_descriptor_sink.cc create mode 100644 gnuradio-core/src/lib/io/gr_file_descriptor_sink.h create mode 100644 gnuradio-core/src/lib/io/gr_file_descriptor_sink.i create mode 100644 gnuradio-core/src/lib/io/gr_file_descriptor_source.cc create mode 100644 gnuradio-core/src/lib/io/gr_file_descriptor_source.h create mode 100644 gnuradio-core/src/lib/io/gr_file_descriptor_source.i create mode 100644 gnuradio-core/src/lib/io/gr_file_sink.cc create mode 100644 gnuradio-core/src/lib/io/gr_file_sink.h create mode 100644 gnuradio-core/src/lib/io/gr_file_sink.i create mode 100644 gnuradio-core/src/lib/io/gr_file_source.cc create mode 100644 gnuradio-core/src/lib/io/gr_file_source.h create mode 100644 gnuradio-core/src/lib/io/gr_file_source.i create mode 100644 gnuradio-core/src/lib/io/gr_message_sink.cc create mode 100644 gnuradio-core/src/lib/io/gr_message_sink.h create mode 100644 gnuradio-core/src/lib/io/gr_message_sink.i create mode 100644 gnuradio-core/src/lib/io/gr_message_source.cc create mode 100644 gnuradio-core/src/lib/io/gr_message_source.h create mode 100644 gnuradio-core/src/lib/io/gr_message_source.i create mode 100644 gnuradio-core/src/lib/io/gr_oscope_guts.cc create mode 100644 gnuradio-core/src/lib/io/gr_oscope_guts.h create mode 100644 gnuradio-core/src/lib/io/gr_oscope_sink.i create mode 100644 gnuradio-core/src/lib/io/gr_oscope_sink_f.cc create mode 100644 gnuradio-core/src/lib/io/gr_oscope_sink_f.h create mode 100644 gnuradio-core/src/lib/io/gr_oscope_sink_x.cc create mode 100644 gnuradio-core/src/lib/io/gr_oscope_sink_x.h create mode 100644 gnuradio-core/src/lib/io/gr_trigger_mode.h create mode 100644 gnuradio-core/src/lib/io/gri_logger.cc create mode 100644 gnuradio-core/src/lib/io/gri_logger.h create mode 100644 gnuradio-core/src/lib/io/i2c.cc create mode 100644 gnuradio-core/src/lib/io/i2c.h create mode 100644 gnuradio-core/src/lib/io/i2c_bbio.cc create mode 100644 gnuradio-core/src/lib/io/i2c_bbio.h create mode 100644 gnuradio-core/src/lib/io/i2c_bbio_pp.cc create mode 100644 gnuradio-core/src/lib/io/i2c_bbio_pp.h create mode 100644 gnuradio-core/src/lib/io/i2c_bitbang.cc create mode 100644 gnuradio-core/src/lib/io/i2c_bitbang.h create mode 100644 gnuradio-core/src/lib/io/io.i create mode 100644 gnuradio-core/src/lib/io/microtune_4702.cc create mode 100644 gnuradio-core/src/lib/io/microtune_4702.h create mode 100644 gnuradio-core/src/lib/io/microtune_4702_eval_board.cc create mode 100644 gnuradio-core/src/lib/io/microtune_4702_eval_board.h create mode 100644 gnuradio-core/src/lib/io/microtune_4702_eval_board.i create mode 100644 gnuradio-core/src/lib/io/microtune_4937.cc create mode 100644 gnuradio-core/src/lib/io/microtune_4937.h create mode 100644 gnuradio-core/src/lib/io/microtune_4937_eval_board.cc create mode 100644 gnuradio-core/src/lib/io/microtune_4937_eval_board.h create mode 100644 gnuradio-core/src/lib/io/microtune_4937_eval_board.i create mode 100644 gnuradio-core/src/lib/io/microtune_eval_board.i create mode 100644 gnuradio-core/src/lib/io/microtune_eval_board_defs.h create mode 100644 gnuradio-core/src/lib/io/microtune_xxxx.cc create mode 100644 gnuradio-core/src/lib/io/microtune_xxxx.h create mode 100644 gnuradio-core/src/lib/io/microtune_xxxx_eval_board.cc create mode 100644 gnuradio-core/src/lib/io/microtune_xxxx_eval_board.h create mode 100644 gnuradio-core/src/lib/io/microtune_xxxx_eval_board.i create mode 100644 gnuradio-core/src/lib/io/ppio.cc create mode 100644 gnuradio-core/src/lib/io/ppio.h create mode 100644 gnuradio-core/src/lib/io/ppio.i create mode 100644 gnuradio-core/src/lib/io/ppio_ppdev.cc create mode 100644 gnuradio-core/src/lib/io/ppio_ppdev.h create mode 100644 gnuradio-core/src/lib/io/sdr_1000.cc create mode 100644 gnuradio-core/src/lib/io/sdr_1000.h create mode 100644 gnuradio-core/src/lib/io/sdr_1000.i create mode 100644 gnuradio-core/src/lib/missing/Makefile.am create mode 100644 gnuradio-core/src/lib/missing/bug_work_around_8.cc create mode 100644 gnuradio-core/src/lib/missing/getopt.c create mode 100644 gnuradio-core/src/lib/missing/getopt.h create mode 100644 gnuradio-core/src/lib/missing/gettimeofday.c create mode 100644 gnuradio-core/src/lib/missing/usleep.c create mode 100644 gnuradio-core/src/lib/omnithread/Makefile.am create mode 100644 gnuradio-core/src/lib/omnithread/dir.mk create mode 100644 gnuradio-core/src/lib/omnithread/mach.cc create mode 100644 gnuradio-core/src/lib/omnithread/nt.cc create mode 100644 gnuradio-core/src/lib/omnithread/omnithread.h create mode 100644 gnuradio-core/src/lib/omnithread/ot_VxThread.h create mode 100644 gnuradio-core/src/lib/omnithread/ot_mach.h create mode 100644 gnuradio-core/src/lib/omnithread/ot_nt.h create mode 100644 gnuradio-core/src/lib/omnithread/ot_posix.h create mode 100644 gnuradio-core/src/lib/omnithread/ot_pthread_nt.h create mode 100644 gnuradio-core/src/lib/omnithread/ot_solaris.h create mode 100644 gnuradio-core/src/lib/omnithread/posix.cc create mode 100644 gnuradio-core/src/lib/omnithread/solaris.cc create mode 100644 gnuradio-core/src/lib/omnithread/threaddata.cc create mode 100644 gnuradio-core/src/lib/omnithread/vxWorks.cc create mode 100644 gnuradio-core/src/lib/reed-solomon/Makefile.am create mode 100644 gnuradio-core/src/lib/reed-solomon/Makefile.in.karn create mode 100644 gnuradio-core/src/lib/reed-solomon/README create mode 100644 gnuradio-core/src/lib/reed-solomon/README.karn create mode 100644 gnuradio-core/src/lib/reed-solomon/ccsds.h create mode 100644 gnuradio-core/src/lib/reed-solomon/char.h create mode 100644 gnuradio-core/src/lib/reed-solomon/decode_rs.c create mode 100644 gnuradio-core/src/lib/reed-solomon/decode_rs_ccsds.c create mode 100644 gnuradio-core/src/lib/reed-solomon/encode_rs.c create mode 100644 gnuradio-core/src/lib/reed-solomon/encode_rs_ccsds.c create mode 100644 gnuradio-core/src/lib/reed-solomon/exercise.c create mode 100644 gnuradio-core/src/lib/reed-solomon/fixed.h create mode 100644 gnuradio-core/src/lib/reed-solomon/gen_ccsds.c create mode 100644 gnuradio-core/src/lib/reed-solomon/gen_ccsds_tal.c create mode 100644 gnuradio-core/src/lib/reed-solomon/init_rs.c create mode 100644 gnuradio-core/src/lib/reed-solomon/int.h create mode 100644 gnuradio-core/src/lib/reed-solomon/rs.3 create mode 100644 gnuradio-core/src/lib/reed-solomon/rs.h create mode 100644 gnuradio-core/src/lib/reed-solomon/rstest.c create mode 100644 gnuradio-core/src/lib/runtime/Makefile.am create mode 100644 gnuradio-core/src/lib/runtime/gr_block.cc create mode 100644 gnuradio-core/src/lib/runtime/gr_block.h create mode 100644 gnuradio-core/src/lib/runtime/gr_block.i create mode 100644 gnuradio-core/src/lib/runtime/gr_block_detail.cc create mode 100644 gnuradio-core/src/lib/runtime/gr_block_detail.h create mode 100644 gnuradio-core/src/lib/runtime/gr_block_detail.i create mode 100644 gnuradio-core/src/lib/runtime/gr_buffer.cc create mode 100644 gnuradio-core/src/lib/runtime/gr_buffer.h create mode 100644 gnuradio-core/src/lib/runtime/gr_buffer.i create mode 100644 gnuradio-core/src/lib/runtime/gr_complex.h create mode 100644 gnuradio-core/src/lib/runtime/gr_dispatcher.cc create mode 100644 gnuradio-core/src/lib/runtime/gr_dispatcher.h create mode 100644 gnuradio-core/src/lib/runtime/gr_dispatcher.i create mode 100644 gnuradio-core/src/lib/runtime/gr_error_handler.cc create mode 100644 gnuradio-core/src/lib/runtime/gr_error_handler.h create mode 100644 gnuradio-core/src/lib/runtime/gr_error_handler.i create mode 100644 gnuradio-core/src/lib/runtime/gr_io_signature.cc create mode 100644 gnuradio-core/src/lib/runtime/gr_io_signature.h create mode 100644 gnuradio-core/src/lib/runtime/gr_io_signature.i create mode 100644 gnuradio-core/src/lib/runtime/gr_local_sighandler.cc create mode 100644 gnuradio-core/src/lib/runtime/gr_local_sighandler.h create mode 100644 gnuradio-core/src/lib/runtime/gr_message.cc create mode 100644 gnuradio-core/src/lib/runtime/gr_message.h create mode 100644 gnuradio-core/src/lib/runtime/gr_message.i create mode 100644 gnuradio-core/src/lib/runtime/gr_msg_handler.cc create mode 100644 gnuradio-core/src/lib/runtime/gr_msg_handler.h create mode 100644 gnuradio-core/src/lib/runtime/gr_msg_handler.i create mode 100644 gnuradio-core/src/lib/runtime/gr_msg_queue.cc create mode 100644 gnuradio-core/src/lib/runtime/gr_msg_queue.h create mode 100644 gnuradio-core/src/lib/runtime/gr_msg_queue.i create mode 100644 gnuradio-core/src/lib/runtime/gr_pagesize.cc create mode 100644 gnuradio-core/src/lib/runtime/gr_pagesize.h create mode 100644 gnuradio-core/src/lib/runtime/gr_preferences.cc create mode 100644 gnuradio-core/src/lib/runtime/gr_preferences.h create mode 100644 gnuradio-core/src/lib/runtime/gr_realtime.cc create mode 100644 gnuradio-core/src/lib/runtime/gr_realtime.h create mode 100644 gnuradio-core/src/lib/runtime/gr_realtime.i create mode 100644 gnuradio-core/src/lib/runtime/gr_runtime.h create mode 100644 gnuradio-core/src/lib/runtime/gr_select_handler.cc create mode 100644 gnuradio-core/src/lib/runtime/gr_select_handler.h create mode 100644 gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.cc create mode 100644 gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.h create mode 100644 gnuradio-core/src/lib/runtime/gr_single_threaded_scheduler.i create mode 100644 gnuradio-core/src/lib/runtime/gr_swig_block_magic.i create mode 100644 gnuradio-core/src/lib/runtime/gr_timer.h create mode 100644 gnuradio-core/src/lib/runtime/gr_tmp_path.cc create mode 100644 gnuradio-core/src/lib/runtime/gr_tmp_path.h create mode 100644 gnuradio-core/src/lib/runtime/gr_types.h create mode 100644 gnuradio-core/src/lib/runtime/gr_vmcircbuf.cc create mode 100644 gnuradio-core/src/lib/runtime/gr_vmcircbuf.h create mode 100644 gnuradio-core/src/lib/runtime/gr_vmcircbuf_createfilemapping.cc create mode 100644 gnuradio-core/src/lib/runtime/gr_vmcircbuf_createfilemapping.h create mode 100644 gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_shm_open.cc create mode 100644 gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_shm_open.h create mode 100644 gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.cc create mode 100644 gnuradio-core/src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.h create mode 100644 gnuradio-core/src/lib/runtime/gr_vmcircbuf_sysv_shm.cc create mode 100644 gnuradio-core/src/lib/runtime/gr_vmcircbuf_sysv_shm.h create mode 100644 gnuradio-core/src/lib/runtime/qa_gr_block.cc create mode 100644 gnuradio-core/src/lib/runtime/qa_gr_block.h create mode 100644 gnuradio-core/src/lib/runtime/qa_gr_buffer.cc create mode 100644 gnuradio-core/src/lib/runtime/qa_gr_buffer.h create mode 100644 gnuradio-core/src/lib/runtime/qa_gr_io_signature.cc create mode 100644 gnuradio-core/src/lib/runtime/qa_gr_io_signature.h create mode 100644 gnuradio-core/src/lib/runtime/qa_gr_vmcircbuf.cc create mode 100644 gnuradio-core/src/lib/runtime/qa_gr_vmcircbuf.h create mode 100644 gnuradio-core/src/lib/runtime/qa_runtime.cc create mode 100644 gnuradio-core/src/lib/runtime/qa_runtime.h create mode 100644 gnuradio-core/src/lib/runtime/runtime.i create mode 100644 gnuradio-core/src/lib/runtime/test_shared_block_ptr.cc create mode 100644 gnuradio-core/src/lib/swig/Makefile.am create mode 100644 gnuradio-core/src/lib/swig/atsc.i create mode 100755 gnuradio-core/src/lib/swig/gen-swig-bug-fix create mode 100644 gnuradio-core/src/lib/swig/gnuradio.i create mode 100644 gnuradio-core/src/lib/swig/shared_ptr.i create mode 100644 gnuradio-core/src/python/Makefile.am create mode 100644 gnuradio-core/src/python/bin/Makefile.am create mode 100755 gnuradio-core/src/python/bin/microtune.py create mode 100644 gnuradio-core/src/python/build_utils.py create mode 100644 gnuradio-core/src/python/build_utils_codes.py create mode 100644 gnuradio-core/src/python/gnuradio/Makefile.am create mode 100644 gnuradio-core/src/python/gnuradio/__init__.py create mode 100644 gnuradio-core/src/python/gnuradio/audio.py create mode 100644 gnuradio-core/src/python/gnuradio/blks/Makefile.am create mode 100644 gnuradio-core/src/python/gnuradio/blks/__init__.py create mode 100644 gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am create mode 100644 gnuradio-core/src/python/gnuradio/blksimpl/__init__.py create mode 100644 gnuradio-core/src/python/gnuradio/blksimpl/am_demod.py create mode 100644 gnuradio-core/src/python/gnuradio/blksimpl/digital_voice.py.real create mode 100644 gnuradio-core/src/python/gnuradio/blksimpl/filterbank.py create mode 100644 gnuradio-core/src/python/gnuradio/blksimpl/fm_demod.py create mode 100644 gnuradio-core/src/python/gnuradio/blksimpl/fm_emph.py create mode 100644 gnuradio-core/src/python/gnuradio/blksimpl/gmsk2.py create mode 100644 gnuradio-core/src/python/gnuradio/blksimpl/gmsk2_pkt.py create mode 100644 gnuradio-core/src/python/gnuradio/blksimpl/nbfm_rx.py create mode 100644 gnuradio-core/src/python/gnuradio/blksimpl/nbfm_tx.py create mode 100644 gnuradio-core/src/python/gnuradio/blksimpl/pkt.py create mode 100644 gnuradio-core/src/python/gnuradio/blksimpl/rational_resampler.py create mode 100644 gnuradio-core/src/python/gnuradio/blksimpl/standard_squelch.py create mode 100644 gnuradio-core/src/python/gnuradio/blksimpl/wfm_rcv.py create mode 100644 gnuradio-core/src/python/gnuradio/blksimpl/wfm_rcv_pll.py create mode 100644 gnuradio-core/src/python/gnuradio/blksimpl/wfm_tx.py create mode 100644 gnuradio-core/src/python/gnuradio/eng_notation.py create mode 100644 gnuradio-core/src/python/gnuradio/eng_option.py create mode 100644 gnuradio-core/src/python/gnuradio/gr/Makefile.am create mode 100644 gnuradio-core/src/python/gnuradio/gr/__init__.py create mode 100644 gnuradio-core/src/python/gnuradio/gr/basic_flow_graph.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/benchmark_filters.py create mode 100644 gnuradio-core/src/python/gnuradio/gr/exceptions.py create mode 100644 gnuradio-core/src/python/gnuradio/gr/flow_graph.py create mode 100644 gnuradio-core/src/python/gnuradio/gr/gr_threading.py create mode 100644 gnuradio-core/src/python/gnuradio/gr/gr_threading_23.py create mode 100644 gnuradio-core/src/python/gnuradio/gr/gr_threading_24.py create mode 100644 gnuradio-core/src/python/gnuradio/gr/hier_block.py create mode 100644 gnuradio-core/src/python/gnuradio/gr/prefs.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_add_and_friends.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_add_v_and_friends.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_basic_flow_graph.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_cma_equalizer.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_complex_to_xxx.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_constellation_decoder_cb.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_correlate_access_code.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_diff_encoder.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_diff_phasor_cc.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_feval.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_fft_filter.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_filter_delay_fc.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_flow_graph.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_frequency_modulator.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_fsk_stuff.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_goertzel.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_head.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_hilbert.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_iir.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_interleave.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_interp_fir_filter.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_kludge_copy.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_kludged_imports.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_message.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_mute.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_nlog10.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_packed_to_unpacked.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_pipe_fittings.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_rational_resampler.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_sig_source.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_single_pole_iir.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_single_pole_iir_cc.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/qa_unpack_k_bits.py create mode 100755 gnuradio-core/src/python/gnuradio/gr/run_tests.in create mode 100644 gnuradio-core/src/python/gnuradio/gr/scheduler.py create mode 100755 gnuradio-core/src/python/gnuradio/gr_unittest.py create mode 100644 gnuradio-core/src/python/gnuradio/gru/Makefile.am create mode 100644 gnuradio-core/src/python/gnuradio/gru/__init__.py create mode 100644 gnuradio-core/src/python/gnuradio/gruimpl/Makefile.am create mode 100644 gnuradio-core/src/python/gnuradio/gruimpl/__init__.py create mode 100644 gnuradio-core/src/python/gnuradio/gruimpl/crc.py create mode 100644 gnuradio-core/src/python/gnuradio/gruimpl/freqz.py create mode 100755 gnuradio-core/src/python/gnuradio/gruimpl/gnuplot_freqz.py create mode 100644 gnuradio-core/src/python/gnuradio/gruimpl/hexint.py create mode 100644 gnuradio-core/src/python/gnuradio/gruimpl/listmisc.py create mode 100755 gnuradio-core/src/python/gnuradio/gruimpl/lmx2306.py create mode 100644 gnuradio-core/src/python/gnuradio/gruimpl/mathmisc.py create mode 100644 gnuradio-core/src/python/gnuradio/gruimpl/os_read_exactly.py create mode 100644 gnuradio-core/src/python/gnuradio/gruimpl/sdr_1000.py create mode 100644 gnuradio-core/src/python/gnuradio/gruimpl/seq_with_cursor.py create mode 100644 gnuradio-core/src/python/gnuradio/gruimpl/socket_stuff.py create mode 100644 gnuradio-core/src/python/gnuradio/optfir.py create mode 100644 gnuradio-core/src/python/gnuradio/packet_utils.py create mode 100644 gnuradio-core/src/python/gnuradio/window.py create mode 100644 gnuradio-core/src/tests/Makefile.am create mode 100644 gnuradio-core/src/tests/benchmark_dotprod.cc create mode 100644 gnuradio-core/src/tests/benchmark_dotprod_ccc.cc create mode 100644 gnuradio-core/src/tests/benchmark_dotprod_ccf.cc create mode 100644 gnuradio-core/src/tests/benchmark_dotprod_fcc.cc create mode 100644 gnuradio-core/src/tests/benchmark_dotprod_fsf.cc create mode 100644 gnuradio-core/src/tests/benchmark_dotprod_scc.cc create mode 100644 gnuradio-core/src/tests/benchmark_nco.cc create mode 100644 gnuradio-core/src/tests/benchmark_vco.cc create mode 100644 gnuradio-core/src/tests/nco_results create mode 100644 gnuradio-core/src/tests/test_all.cc create mode 100644 gnuradio-core/src/tests/test_atsc.cc create mode 100755 gnuradio-core/src/tests/test_buffers.py create mode 100644 gnuradio-core/src/tests/test_filter.cc create mode 100644 gnuradio-core/src/tests/test_general.cc create mode 100644 gnuradio-core/src/tests/test_runtime.cc create mode 100644 gnuradio-core/src/tests/test_vmcircbuf.cc create mode 100644 gnuradio-core/src/utils/Makefile.am create mode 100644 gnuradio-core/src/utils/cool.m create mode 100644 gnuradio-core/src/utils/db_width.m create mode 100644 gnuradio-core/src/utils/filter_tools.m create mode 100644 gnuradio-core/src/utils/is_complex.m create mode 100644 gnuradio-core/src/utils/lp_to_bp.m create mode 100644 gnuradio-core/src/utils/partition-cascaded-decimating-filters.scm create mode 100644 gnuradio-core/src/utils/permute.scm create mode 100644 gnuradio-core/src/utils/plot_cic_decimator_response.m create mode 100644 gnuradio-core/src/utils/plot_freq_response.m create mode 100644 gnuradio-core/src/utils/plot_freq_response_db.m create mode 100644 gnuradio-core/src/utils/plot_freq_response_phase.m create mode 100644 gnuradio-core/src/utils/plotfft.m create mode 100644 gnuradio-core/src/utils/plotfftavgk.m create mode 100644 gnuradio-core/src/utils/plotfftavgk_db.m create mode 100644 gnuradio-core/src/utils/plotfftk.m create mode 100644 gnuradio-core/src/utils/plotfftk_db.m create mode 100644 gnuradio-core/src/utils/put_markers.m create mode 100644 gnuradio-core/src/utils/rainbow.m create mode 100644 gnuradio-core/src/utils/read_char_binary.m create mode 100644 gnuradio-core/src/utils/read_complex_binary.m create mode 100644 gnuradio-core/src/utils/read_float_binary.m create mode 100644 gnuradio-core/src/utils/read_int_binary.m create mode 100644 gnuradio-core/src/utils/read_short_binary.m create mode 100644 gnuradio-core/src/utils/read_xambi.m create mode 100644 gnuradio-core/src/utils/runsum.m create mode 100644 gnuradio-core/src/utils/single_pole_iir.m create mode 100644 gnuradio-core/src/utils/write_float_binary.m create mode 100644 gnuradio-core/src/utils/write_short_binary.m create mode 100644 gnuradio-examples/AUTHORS create mode 100644 gnuradio-examples/ChangeLog create mode 100644 gnuradio-examples/Makefile.am create mode 100644 gnuradio-examples/NEWS create mode 100644 gnuradio-examples/README create mode 100644 gnuradio-examples/README.hacking create mode 100644 gnuradio-examples/python/Makefile.am create mode 100644 gnuradio-examples/python/apps/README create mode 100644 gnuradio-examples/python/apps/hf_explorer/README create mode 100755 gnuradio-examples/python/apps/hf_explorer/hfx2.py create mode 100644 gnuradio-examples/python/apps/hf_explorer/hfx_help create mode 100644 gnuradio-examples/python/apps/hf_radio/README.TXT create mode 100644 gnuradio-examples/python/apps/hf_radio/hfir.sci create mode 100644 gnuradio-examples/python/apps/hf_radio/input.py create mode 100644 gnuradio-examples/python/apps/hf_radio/output.py create mode 100755 gnuradio-examples/python/apps/hf_radio/radio.py create mode 100644 gnuradio-examples/python/apps/hf_radio/radio.xml create mode 100644 gnuradio-examples/python/apps/hf_radio/ssb_taps create mode 100644 gnuradio-examples/python/apps/hf_radio/ssbagc.py create mode 100644 gnuradio-examples/python/apps/hf_radio/ssbdemod.py create mode 100644 gnuradio-examples/python/apps/hf_radio/startup.py create mode 100755 gnuradio-examples/python/apps/hf_radio/ui.py create mode 100644 gnuradio-examples/python/audio/Makefile.am create mode 100755 gnuradio-examples/python/audio/audio_copy.py create mode 100755 gnuradio-examples/python/audio/audio_play.py create mode 100755 gnuradio-examples/python/audio/audio_to_file.py create mode 100755 gnuradio-examples/python/audio/dial_squelch.py create mode 100755 gnuradio-examples/python/audio/dial_tone.py create mode 100755 gnuradio-examples/python/audio/dialtone_v.py create mode 100755 gnuradio-examples/python/audio/mono_tone.py create mode 100755 gnuradio-examples/python/audio/multi_tone.py create mode 100755 gnuradio-examples/python/audio/spectrum_inversion.py create mode 100755 gnuradio-examples/python/audio/test_resampler.py create mode 100644 gnuradio-examples/python/digital_voice/Makefile.am create mode 100755 gnuradio-examples/python/digital_voice/encdec.py create mode 100644 gnuradio-examples/python/gmsk2/Makefile.am create mode 100644 gnuradio-examples/python/gmsk2/README create mode 100755 gnuradio-examples/python/gmsk2/benchmark_gmsk_rx.py create mode 100755 gnuradio-examples/python/gmsk2/benchmark_gmsk_tx.py create mode 100755 gnuradio-examples/python/gmsk2/benchmark_mpsk_rx.py create mode 100755 gnuradio-examples/python/gmsk2/benchmark_mpsk_tx.py create mode 100644 gnuradio-examples/python/gmsk2/bpsk.py create mode 100644 gnuradio-examples/python/gmsk2/dbpsk.py create mode 100644 gnuradio-examples/python/gmsk2/dqpsk.py create mode 100644 gnuradio-examples/python/gmsk2/fusb_options.py create mode 100755 gnuradio-examples/python/gmsk2/gen_whitener.py create mode 100755 gnuradio-examples/python/gmsk2/gmsk_test.py create mode 100755 gnuradio-examples/python/gmsk2/mpsk_test.py create mode 100644 gnuradio-examples/python/gmsk2/pick_bitrate.py create mode 100644 gnuradio-examples/python/gmsk2/qpsk.py create mode 100644 gnuradio-examples/python/gmsk2/qpsk_tester.py create mode 100644 gnuradio-examples/python/gmsk2/qpsk_usrp_tester.py create mode 100644 gnuradio-examples/python/gmsk2/receive_path.py create mode 100755 gnuradio-examples/python/gmsk2/rx_voice.py create mode 100644 gnuradio-examples/python/gmsk2/transmit_path.py create mode 100755 gnuradio-examples/python/gmsk2/tunnel.py create mode 100755 gnuradio-examples/python/gmsk2/tx_voice.py create mode 100644 gnuradio-examples/python/mc4020/Makefile.am create mode 100755 gnuradio-examples/python/mc4020/fm_demod.py create mode 100755 gnuradio-examples/python/mc4020/mc4020_fft.py create mode 100755 gnuradio-examples/python/multi-antenna/multi_fft.py create mode 100755 gnuradio-examples/python/multi-antenna/multi_file.py create mode 100755 gnuradio-examples/python/multi-antenna/multi_scope.py create mode 100644 gnuradio-examples/python/multi_usrp/Makefile.am create mode 100644 gnuradio-examples/python/multi_usrp/README create mode 100755 gnuradio-examples/python/multi_usrp/multi_usrp_oscope.py create mode 100755 gnuradio-examples/python/multi_usrp/multi_usrp_rx_cfile.py create mode 100755 gnuradio-examples/python/networking/measurement_slave.py create mode 100644 gnuradio-examples/python/usrp/Makefile.am create mode 100755 gnuradio-examples/python/usrp/am_rcv.py create mode 100644 gnuradio-examples/python/usrp/ayfabtu.dat create mode 100755 gnuradio-examples/python/usrp/ayfabtu.py create mode 100755 gnuradio-examples/python/usrp/benchmark_usb.py create mode 100755 gnuradio-examples/python/usrp/dsb_tx.py create mode 100755 gnuradio-examples/python/usrp/flexrf_debug.py create mode 100755 gnuradio-examples/python/usrp/flexrf_siggen.py create mode 100755 gnuradio-examples/python/usrp/fm_tx4.py create mode 100755 gnuradio-examples/python/usrp/fm_tx_2_daughterboards.py create mode 100755 gnuradio-examples/python/usrp/max_power.py create mode 100755 gnuradio-examples/python/usrp/siggen_min2.py create mode 100755 gnuradio-examples/python/usrp/test_counting.py create mode 100755 gnuradio-examples/python/usrp/test_dft_analysis.py create mode 100755 gnuradio-examples/python/usrp/test_dft_synth.py create mode 100755 gnuradio-examples/python/usrp/test_digital_loopback_counting.py create mode 100755 gnuradio-examples/python/usrp/test_digital_loopback_lfsr.py create mode 100755 gnuradio-examples/python/usrp/tvrx_am_rcv_gui.py create mode 100755 gnuradio-examples/python/usrp/usrp_fft.py create mode 100755 gnuradio-examples/python/usrp/usrp_fft_old.py create mode 100755 gnuradio-examples/python/usrp/usrp_nbfm_ptt.py create mode 100755 gnuradio-examples/python/usrp/usrp_nbfm_rcv.py create mode 100755 gnuradio-examples/python/usrp/usrp_oscope.py create mode 100755 gnuradio-examples/python/usrp/usrp_rx_cfile.py create mode 100755 gnuradio-examples/python/usrp/usrp_rx_nogui.py create mode 100755 gnuradio-examples/python/usrp/usrp_siggen.py create mode 100755 gnuradio-examples/python/usrp/usrp_tv_rcv.py create mode 100755 gnuradio-examples/python/usrp/usrp_tv_rcv_nogui.py create mode 100755 gnuradio-examples/python/usrp/usrp_wfm_rcv.py create mode 100755 gnuradio-examples/python/usrp/usrp_wfm_rcv2_nogui.py create mode 100755 gnuradio-examples/python/usrp/usrp_wfm_rcv_nogui.py create mode 100755 gnuradio-examples/python/usrp/usrp_wfm_rcv_pll.py create mode 100755 gnuradio-examples/python/usrp/usrp_wxapt_rcv.py create mode 100755 gnuradio-examples/python/usrp/wfm_rcv_file.py create mode 100644 gr-atsc/AUTHORS create mode 100644 gr-atsc/ChangeLog create mode 100644 gr-atsc/Makefile.am create mode 100644 gr-atsc/NEWS create mode 100644 gr-atsc/README create mode 100644 gr-atsc/README.signal_flow create mode 100644 gr-atsc/doc/Makefile.am create mode 100644 gr-atsc/src/Makefile.am create mode 100644 gr-atsc/src/lib/GrAtscBitTimingLoop.cc create mode 100644 gr-atsc/src/lib/GrAtscBitTimingLoop.h create mode 100644 gr-atsc/src/lib/GrAtscBitTimingLoop2.cc create mode 100644 gr-atsc/src/lib/GrAtscBitTimingLoop2.h create mode 100644 gr-atsc/src/lib/GrAtscBitTimingLoop3.cc create mode 100644 gr-atsc/src/lib/GrAtscBitTimingLoop3.h create mode 100644 gr-atsc/src/lib/GrAtscConvert2xTo20.cc create mode 100644 gr-atsc/src/lib/GrAtscConvert2xTo20.h create mode 100644 gr-atsc/src/lib/GrAtscDataSegToSoftDataSeg.cc create mode 100644 gr-atsc/src/lib/GrAtscDataSegToSoftDataSeg.h create mode 100644 gr-atsc/src/lib/GrAtscDeinterleaver.cc create mode 100644 gr-atsc/src/lib/GrAtscDeinterleaver.h create mode 100644 gr-atsc/src/lib/GrAtscDerandomizer.cc create mode 100644 gr-atsc/src/lib/GrAtscDerandomizer.h create mode 100644 gr-atsc/src/lib/GrAtscEqualizer.cc create mode 100644 gr-atsc/src/lib/GrAtscEqualizer.h create mode 100644 gr-atsc/src/lib/GrAtscFPLL.cc create mode 100644 gr-atsc/src/lib/GrAtscFPLL.h create mode 100644 gr-atsc/src/lib/GrAtscFieldSyncChecker.cc create mode 100644 gr-atsc/src/lib/GrAtscFieldSyncChecker.h create mode 100644 gr-atsc/src/lib/GrAtscFieldSyncCorrelator.cc create mode 100644 gr-atsc/src/lib/GrAtscFieldSyncCorrelator.h create mode 100644 gr-atsc/src/lib/GrAtscFieldSyncDemux.cc create mode 100644 gr-atsc/src/lib/GrAtscFieldSyncDemux.h create mode 100644 gr-atsc/src/lib/GrAtscFieldSyncMux.cc create mode 100644 gr-atsc/src/lib/GrAtscFieldSyncMux.h create mode 100644 gr-atsc/src/lib/GrAtscInterleaver.cc create mode 100644 gr-atsc/src/lib/GrAtscInterleaver.h create mode 100644 gr-atsc/src/lib/GrAtscRSDecoder.cc create mode 100644 gr-atsc/src/lib/GrAtscRSDecoder.h create mode 100644 gr-atsc/src/lib/GrAtscRSEncoder.cc create mode 100644 gr-atsc/src/lib/GrAtscRSEncoder.h create mode 100644 gr-atsc/src/lib/GrAtscRandomizer.cc create mode 100644 gr-atsc/src/lib/GrAtscRandomizer.h create mode 100644 gr-atsc/src/lib/GrAtscSegSymSync.cc create mode 100644 gr-atsc/src/lib/GrAtscSegSymSync.h create mode 100644 gr-atsc/src/lib/GrAtscSegSymSyncImpl.cc create mode 100644 gr-atsc/src/lib/GrAtscSegSymSyncImpl.h create mode 100644 gr-atsc/src/lib/GrAtscSegSymSyncImpl_export.h create mode 100644 gr-atsc/src/lib/GrAtscSymbolMapper.h create mode 100644 gr-atsc/src/lib/GrAtscTrellisEncoder.cc create mode 100644 gr-atsc/src/lib/GrAtscTrellisEncoder.h create mode 100644 gr-atsc/src/lib/GrAtscViterbiDecoder.cc create mode 100644 gr-atsc/src/lib/GrAtscViterbiDecoder.h create mode 100644 gr-atsc/src/lib/Makefile.am create mode 100644 gr-atsc/src/lib/atsc.i create mode 100644 gr-atsc/src/lib/atsc_bit_timing_loop.cc create mode 100644 gr-atsc/src/lib/atsc_bit_timing_loop.h create mode 100644 gr-atsc/src/lib/atsc_consts.h create mode 100644 gr-atsc/src/lib/atsc_deinterleaver.cc create mode 100644 gr-atsc/src/lib/atsc_deinterleaver.h create mode 100644 gr-atsc/src/lib/atsc_depad.cc create mode 100644 gr-atsc/src/lib/atsc_depad.h create mode 100644 gr-atsc/src/lib/atsc_derandomizer.cc create mode 100644 gr-atsc/src/lib/atsc_derandomizer.h create mode 100644 gr-atsc/src/lib/atsc_ds_to_softds.cc create mode 100644 gr-atsc/src/lib/atsc_ds_to_softds.h create mode 100644 gr-atsc/src/lib/atsc_equalizer.cc create mode 100644 gr-atsc/src/lib/atsc_equalizer.h create mode 100644 gr-atsc/src/lib/atsc_field_sync_demux.cc create mode 100644 gr-atsc/src/lib/atsc_field_sync_demux.h create mode 100644 gr-atsc/src/lib/atsc_field_sync_mux.cc create mode 100644 gr-atsc/src/lib/atsc_field_sync_mux.h create mode 100644 gr-atsc/src/lib/atsc_fpll.cc create mode 100644 gr-atsc/src/lib/atsc_fpll.h create mode 100644 gr-atsc/src/lib/atsc_fs_checker.cc create mode 100644 gr-atsc/src/lib/atsc_fs_checker.h create mode 100644 gr-atsc/src/lib/atsc_interleaver.cc create mode 100644 gr-atsc/src/lib/atsc_interleaver.h create mode 100644 gr-atsc/src/lib/atsc_randomizer.cc create mode 100644 gr-atsc/src/lib/atsc_randomizer.h create mode 100644 gr-atsc/src/lib/atsc_rs_decoder.cc create mode 100644 gr-atsc/src/lib/atsc_rs_decoder.h create mode 100644 gr-atsc/src/lib/atsc_rs_encoder.cc create mode 100644 gr-atsc/src/lib/atsc_rs_encoder.h create mode 100644 gr-atsc/src/lib/atsc_trellis_encoder.cc create mode 100644 gr-atsc/src/lib/atsc_trellis_encoder.h create mode 100644 gr-atsc/src/lib/atsc_types.h create mode 100644 gr-atsc/src/lib/atsc_viterbi_decoder.cc create mode 100644 gr-atsc/src/lib/atsc_viterbi_decoder.h create mode 100644 gr-atsc/src/lib/atsci_basic_trellis_encoder.cc create mode 100644 gr-atsc/src/lib/atsci_basic_trellis_encoder.h create mode 100644 gr-atsc/src/lib/atsci_data_interleaver.cc create mode 100644 gr-atsc/src/lib/atsci_data_interleaver.h create mode 100644 gr-atsc/src/lib/atsci_diag_output.h create mode 100644 gr-atsc/src/lib/atsci_equalizer.cc create mode 100644 gr-atsc/src/lib/atsci_equalizer.h create mode 100644 gr-atsc/src/lib/atsci_equalizer_lms.cc create mode 100644 gr-atsc/src/lib/atsci_equalizer_lms.h create mode 100644 gr-atsc/src/lib/atsci_equalizer_lms2.cc create mode 100644 gr-atsc/src/lib/atsci_equalizer_lms2.h create mode 100644 gr-atsc/src/lib/atsci_equalizer_nop.cc create mode 100644 gr-atsc/src/lib/atsci_equalizer_nop.h create mode 100644 gr-atsc/src/lib/atsci_exp2_lp.cc create mode 100644 gr-atsc/src/lib/atsci_exp2_lp.h create mode 100644 gr-atsc/src/lib/atsci_exp2_lp20.dat create mode 100644 gr-atsc/src/lib/atsci_exp2_lp2x.dat create mode 100644 gr-atsc/src/lib/atsci_fake_single_viterbi.cc create mode 100644 gr-atsc/src/lib/atsci_fake_single_viterbi.h create mode 100644 gr-atsc/src/lib/atsci_fs_checker.cc create mode 100644 gr-atsc/src/lib/atsci_fs_checker.h create mode 100644 gr-atsc/src/lib/atsci_fs_checker_naive.cc create mode 100644 gr-atsc/src/lib/atsci_fs_checker_naive.h create mode 100644 gr-atsc/src/lib/atsci_fs_correlator.cc create mode 100644 gr-atsc/src/lib/atsci_fs_correlator.h create mode 100644 gr-atsc/src/lib/atsci_fs_correlator_naive.cc create mode 100644 gr-atsc/src/lib/atsci_fs_correlator_naive.h create mode 100644 gr-atsc/src/lib/atsci_pnXXX.cc create mode 100644 gr-atsc/src/lib/atsci_pnXXX.h create mode 100644 gr-atsc/src/lib/atsci_randomizer.cc create mode 100644 gr-atsc/src/lib/atsci_randomizer.h create mode 100644 gr-atsc/src/lib/atsci_reed_solomon.cc create mode 100644 gr-atsc/src/lib/atsci_reed_solomon.h create mode 100644 gr-atsc/src/lib/atsci_root_raised_cosine.cc create mode 100644 gr-atsc/src/lib/atsci_root_raised_cosine.h create mode 100644 gr-atsc/src/lib/atsci_root_raised_cosine_bandpass.cc create mode 100644 gr-atsc/src/lib/atsci_root_raised_cosine_bandpass.h create mode 100644 gr-atsc/src/lib/atsci_single_viterbi.cc create mode 100644 gr-atsc/src/lib/atsci_single_viterbi.h create mode 100644 gr-atsc/src/lib/atsci_slicer_agc.h create mode 100644 gr-atsc/src/lib/atsci_sliding_correlator.cc create mode 100644 gr-atsc/src/lib/atsci_sliding_correlator.h create mode 100644 gr-atsc/src/lib/atsci_sssr.cc create mode 100644 gr-atsc/src/lib/atsci_sssr.h create mode 100644 gr-atsc/src/lib/atsci_syminfo.h create mode 100644 gr-atsc/src/lib/atsci_sync_tag.h create mode 100644 gr-atsc/src/lib/atsci_trellis_encoder.cc create mode 100644 gr-atsc/src/lib/atsci_trellis_encoder.h create mode 100644 gr-atsc/src/lib/atsci_viterbi_decoder.cc create mode 100644 gr-atsc/src/lib/atsci_viterbi_decoder.h create mode 100644 gr-atsc/src/lib/atsci_viterbi_gen.cc create mode 100644 gr-atsc/src/lib/atsci_vsbtx_lp.cc create mode 100644 gr-atsc/src/lib/atsci_vsbtx_lp.dat create mode 100644 gr-atsc/src/lib/atsci_vsbtx_lp.h create mode 100644 gr-atsc/src/lib/convolutional_interleaver.h create mode 100644 gr-atsc/src/lib/create_atsci_equalizer.cc create mode 100644 gr-atsc/src/lib/create_atsci_equalizer.h create mode 100644 gr-atsc/src/lib/create_atsci_fs_checker.cc create mode 100644 gr-atsc/src/lib/create_atsci_fs_checker.h create mode 100644 gr-atsc/src/lib/create_atsci_fs_correlator.cc create mode 100644 gr-atsc/src/lib/create_atsci_fs_correlator.h create mode 100644 gr-atsc/src/lib/fpll_btloop_coupling.h create mode 100755 gr-atsc/src/lib/gen_encoder.py create mode 100644 gr-atsc/src/lib/interleaver_fifo.h create mode 100644 gr-atsc/src/lib/plinfo.cc create mode 100644 gr-atsc/src/lib/qa_atsci.cc create mode 100644 gr-atsc/src/lib/qa_atsci.h create mode 100644 gr-atsc/src/lib/qa_atsci_basic_trellis_encoder.cc create mode 100644 gr-atsc/src/lib/qa_atsci_basic_trellis_encoder.h create mode 100644 gr-atsc/src/lib/qa_atsci_data_interleaver.cc create mode 100644 gr-atsc/src/lib/qa_atsci_data_interleaver.h create mode 100644 gr-atsc/src/lib/qa_atsci_equalizer_nop.cc create mode 100644 gr-atsc/src/lib/qa_atsci_equalizer_nop.h create mode 100644 gr-atsc/src/lib/qa_atsci_fake_single_viterbi.cc create mode 100644 gr-atsc/src/lib/qa_atsci_fake_single_viterbi.h create mode 100644 gr-atsc/src/lib/qa_atsci_fs_correlator.cc create mode 100644 gr-atsc/src/lib/qa_atsci_fs_correlator.h create mode 100644 gr-atsc/src/lib/qa_atsci_randomizer.cc create mode 100644 gr-atsc/src/lib/qa_atsci_randomizer.h create mode 100644 gr-atsc/src/lib/qa_atsci_reed_solomon.cc create mode 100644 gr-atsc/src/lib/qa_atsci_reed_solomon.h create mode 100644 gr-atsc/src/lib/qa_atsci_single_viterbi.cc create mode 100644 gr-atsc/src/lib/qa_atsci_single_viterbi.h create mode 100644 gr-atsc/src/lib/qa_atsci_sliding_correlator.cc create mode 100644 gr-atsc/src/lib/qa_atsci_sliding_correlator.h create mode 100644 gr-atsc/src/lib/qa_atsci_trellis_encoder.cc create mode 100644 gr-atsc/src/lib/qa_atsci_trellis_encoder.h create mode 100644 gr-atsc/src/lib/qa_atsci_trellis_encoder_t1_input.dat create mode 100644 gr-atsc/src/lib/qa_atsci_trellis_encoder_t1_output.dat create mode 100644 gr-atsc/src/lib/qa_atsci_viterbi_decoder.cc create mode 100644 gr-atsc/src/lib/qa_atsci_viterbi_decoder.h create mode 100644 gr-atsc/src/lib/qa_atsci_viterbi_decoder_t1_input.dat create mode 100644 gr-atsc/src/lib/qa_atsci_viterbi_decoder_t1_output.dat create mode 100644 gr-atsc/src/lib/qa_convolutional_interleaver.cc create mode 100644 gr-atsc/src/lib/qa_convolutional_interleaver.h create mode 100644 gr-atsc/src/lib/qa_interleaver_fifo.cc create mode 100644 gr-atsc/src/lib/qa_interleaver_fifo.h create mode 100644 gr-atsc/src/lib/test_atsci.cc create mode 100644 gr-atsc/src/python/Makefile.am create mode 100644 gr-atsc/src/python/atsc_utils.py create mode 100755 gr-atsc/src/python/qa_atsc.py create mode 100644 gr-atsc/src/python/run_tests.in create mode 100644 gr-audio-alsa/AUTHORS create mode 100644 gr-audio-alsa/ChangeLog create mode 100644 gr-audio-alsa/Makefile.am create mode 100644 gr-audio-alsa/README create mode 100644 gr-audio-alsa/build-stamp create mode 100644 gr-audio-alsa/gr-audio-alsa.conf create mode 100644 gr-audio-alsa/src/Makefile.am create mode 100644 gr-audio-alsa/src/audio_alsa.i create mode 100644 gr-audio-alsa/src/audio_alsa_sink.cc create mode 100644 gr-audio-alsa/src/audio_alsa_sink.h create mode 100644 gr-audio-alsa/src/audio_alsa_source.cc create mode 100644 gr-audio-alsa/src/audio_alsa_source.h create mode 100644 gr-audio-alsa/src/gri_alsa.cc create mode 100644 gr-audio-alsa/src/gri_alsa.h create mode 100755 gr-audio-alsa/src/qa_alsa.py create mode 100644 gr-audio-alsa/src/run_tests.in create mode 100644 gr-audio-jack/AUTHORS create mode 100644 gr-audio-jack/ChangeLog create mode 100644 gr-audio-jack/Makefile.am create mode 100644 gr-audio-jack/gr-audio-jack.conf create mode 100644 gr-audio-jack/src/Makefile.am create mode 100644 gr-audio-jack/src/audio_jack.i create mode 100644 gr-audio-jack/src/audio_jack_sink.cc create mode 100644 gr-audio-jack/src/audio_jack_sink.h create mode 100644 gr-audio-jack/src/audio_jack_source.cc create mode 100644 gr-audio-jack/src/audio_jack_source.h create mode 100644 gr-audio-jack/src/gri_jack.cc create mode 100644 gr-audio-jack/src/gri_jack.h create mode 100755 gr-audio-jack/src/qa_jack.py create mode 100644 gr-audio-jack/src/run_tests.in create mode 100644 gr-audio-oss/AUTHORS create mode 100644 gr-audio-oss/ChangeLog create mode 100644 gr-audio-oss/Makefile.am create mode 100644 gr-audio-oss/gr-audio-oss.conf create mode 100644 gr-audio-oss/src/Makefile.am create mode 100644 gr-audio-oss/src/audio_oss.i create mode 100644 gr-audio-oss/src/audio_oss_sink.cc create mode 100644 gr-audio-oss/src/audio_oss_sink.h create mode 100644 gr-audio-oss/src/audio_oss_source.cc create mode 100644 gr-audio-oss/src/audio_oss_source.h create mode 100755 gr-audio-oss/src/qa_oss.py create mode 100644 gr-audio-oss/src/run_tests.in create mode 100644 gr-audio-osx/AUTHORS create mode 100644 gr-audio-osx/ChangeLog create mode 100644 gr-audio-osx/Makefile.am create mode 100644 gr-audio-osx/README_OSX create mode 100644 gr-audio-osx/TODO create mode 100644 gr-audio-osx/src/Makefile.am create mode 100644 gr-audio-osx/src/audio_osx.h create mode 100644 gr-audio-osx/src/audio_osx.i create mode 100644 gr-audio-osx/src/audio_osx_sink.cc create mode 100644 gr-audio-osx/src/audio_osx_sink.h create mode 100644 gr-audio-osx/src/audio_osx_source.cc create mode 100644 gr-audio-osx/src/audio_osx_source.h create mode 100644 gr-audio-osx/src/circular_buffer.h create mode 100644 gr-audio-osx/src/mld_threads.h create mode 100755 gr-audio-osx/src/qa_osx.py create mode 100644 gr-audio-osx/src/run_tests.in create mode 100755 gr-audio-osx/src/test_audio_loop.py create mode 100644 gr-audio-portaudio/AUTHORS create mode 100644 gr-audio-portaudio/ChangeLog create mode 100644 gr-audio-portaudio/Makefile.am create mode 100644 gr-audio-portaudio/README create mode 100755 gr-audio-portaudio/autoconfiscate.patch create mode 100644 gr-audio-portaudio/gr-audio-portaudio.conf create mode 100644 gr-audio-portaudio/src/Makefile.am create mode 100644 gr-audio-portaudio/src/audio_portaudio.i create mode 100644 gr-audio-portaudio/src/audio_portaudio_sink.cc create mode 100644 gr-audio-portaudio/src/audio_portaudio_sink.h create mode 100644 gr-audio-portaudio/src/audio_portaudio_source.cc create mode 100644 gr-audio-portaudio/src/audio_portaudio_source.h create mode 100644 gr-audio-portaudio/src/gri_portaudio.cc create mode 100644 gr-audio-portaudio/src/gri_portaudio.h create mode 100755 gr-audio-portaudio/src/qa_portaudio.py create mode 100644 gr-audio-portaudio/src/run_tests.in create mode 100644 gr-audio-windows/AUTHORS create mode 100644 gr-audio-windows/ChangeLog create mode 100644 gr-audio-windows/Makefile.am create mode 100644 gr-audio-windows/README create mode 100644 gr-audio-windows/src/Makefile.am create mode 100644 gr-audio-windows/src/audio_windows.i create mode 100644 gr-audio-windows/src/audio_windows_sink.cc create mode 100644 gr-audio-windows/src/audio_windows_sink.h create mode 100644 gr-audio-windows/src/audio_windows_source.cc create mode 100644 gr-audio-windows/src/audio_windows_source.h create mode 100755 gr-audio-windows/src/qa_audio_windows.py create mode 100755 gr-audio-windows/src/run_tests.in create mode 100644 gr-comedi/AUTHORS create mode 100644 gr-comedi/ChangeLog create mode 100644 gr-comedi/Makefile.am create mode 100644 gr-comedi/src/Makefile.am create mode 100644 gr-comedi/src/comedi.i create mode 100644 gr-comedi/src/comedi_sink_s.cc create mode 100644 gr-comedi/src/comedi_sink_s.h create mode 100644 gr-comedi/src/comedi_source_s.cc create mode 100644 gr-comedi/src/comedi_source_s.h create mode 100644 gr-comedi/src/gri_comedi.cc create mode 100644 gr-comedi/src/gri_comedi.h create mode 100755 gr-comedi/src/qa_comedi.py create mode 100644 gr-comedi/src/run_tests.in create mode 100644 gr-error-correcting-codes/AUTHORS create mode 100644 gr-error-correcting-codes/ChangeLog create mode 100644 gr-error-correcting-codes/Makefile.am create mode 100644 gr-error-correcting-codes/src/Makefile.am create mode 100644 gr-error-correcting-codes/src/lib/Makefile.am create mode 100644 gr-error-correcting-codes/src/lib/__init__.py create mode 100644 gr-error-correcting-codes/src/lib/ecc.i create mode 100644 gr-error-correcting-codes/src/lib/gr_metrics_decode_viterbi_full_block.cc create mode 100644 gr-error-correcting-codes/src/lib/gr_metrics_decode_viterbi_full_block.h create mode 100644 gr-error-correcting-codes/src/lib/gr_metrics_decode_viterbi_full_block.i create mode 100644 gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.cc create mode 100644 gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.h create mode 100644 gr-error-correcting-codes/src/lib/gr_streams_encode_convolutional.i create mode 100644 gr-error-correcting-codes/src/lib/gr_streams_encode_turbo.cc create mode 100644 gr-error-correcting-codes/src/lib/gr_streams_encode_turbo.h create mode 100644 gr-error-correcting-codes/src/lib/gr_streams_encode_turbo.i create mode 100644 gr-error-correcting-codes/src/lib/gr_syms_to_metrics.cc create mode 100644 gr-error-correcting-codes/src/lib/gr_syms_to_metrics.h create mode 100644 gr-error-correcting-codes/src/lib/gr_syms_to_metrics.i create mode 100644 gr-error-correcting-codes/src/lib/libecc/Makefile.am create mode 100644 gr-error-correcting-codes/src/lib/libecc/code_convolutional_trellis.cc create mode 100644 gr-error-correcting-codes/src/lib/libecc/code_convolutional_trellis.h create mode 100644 gr-error-correcting-codes/src/lib/libecc/code_metrics.cc create mode 100644 gr-error-correcting-codes/src/lib/libecc/code_metrics.h create mode 100644 gr-error-correcting-codes/src/lib/libecc/code_types.h create mode 100644 gr-error-correcting-codes/src/lib/libecc/decoder.cc create mode 100644 gr-error-correcting-codes/src/lib/libecc/decoder.h create mode 100644 gr-error-correcting-codes/src/lib/libecc/decoder_viterbi.cc create mode 100644 gr-error-correcting-codes/src/lib/libecc/decoder_viterbi.h create mode 100644 gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block.cc create mode 100644 gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block.h create mode 100644 gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block_i1_ic1.cc create mode 100644 gr-error-correcting-codes/src/lib/libecc/decoder_viterbi_full_block_i1_ic1.h create mode 100644 gr-error-correcting-codes/src/lib/libecc/encoder.cc create mode 100644 gr-error-correcting-codes/src/lib/libecc/encoder.h create mode 100644 gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.cc create mode 100644 gr-error-correcting-codes/src/lib/libecc/encoder_convolutional.h create mode 100644 gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic1_ic1.cc create mode 100644 gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic1_ic1.h create mode 100644 gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic8_ic8.cc create mode 100644 gr-error-correcting-codes/src/lib/libecc/encoder_convolutional_ic8_ic8.h create mode 100644 gr-error-correcting-codes/src/lib/libecc/encoder_turbo.cc create mode 100644 gr-error-correcting-codes/src/lib/libecc/encoder_turbo.h create mode 100644 gr-error-correcting-codes/src/lib/libecc/mld/Makefile.am create mode 100644 gr-error-correcting-codes/src/lib/libecc/mld/mld_timer.cc create mode 100644 gr-error-correcting-codes/src/lib/libecc/mld/mld_timer.h create mode 100644 gr-error-correcting-codes/src/lib/libecc/mld/n2bs.cc create mode 100644 gr-error-correcting-codes/src/lib/libecc/mld/n2bs.h create mode 100644 gr-error-correcting-codes/src/lib/libecc/tests/Makefile.am create mode 100644 gr-error-correcting-codes/src/lib/libecc/tests/qa_ecc.cc create mode 100644 gr-error-correcting-codes/src/lib/libecc/tests/qa_ecc.h create mode 100644 gr-error-correcting-codes/src/lib/libecc/tests/qa_encoder_convolutional_ic1_ic1.cc create mode 100644 gr-error-correcting-codes/src/lib/libecc/tests/qa_encoder_convolutional_ic1_ic1.h create mode 100644 gr-error-correcting-codes/src/lib/libecc/tests/test_all.cc create mode 100755 gr-error-correcting-codes/src/lib/qa_ecc.py create mode 100644 gr-error-correcting-codes/src/python/Makefile.am create mode 100755 gr-error-correcting-codes/src/python/qa_test_coding_1.py create mode 100755 gr-error-correcting-codes/src/python/qa_test_coding_2.py create mode 100755 gr-error-correcting-codes/src/python/qa_test_encoder_convolutional_1.py create mode 100755 gr-error-correcting-codes/src/python/qa_test_encoder_convolutional_2.py create mode 100644 gr-error-correcting-codes/src/python/run_tests.in create mode 100644 gr-gsm-fr-vocoder/AUTHORS create mode 100644 gr-gsm-fr-vocoder/ChangeLog create mode 100644 gr-gsm-fr-vocoder/INSTALL create mode 100644 gr-gsm-fr-vocoder/Makefile.am create mode 100644 gr-gsm-fr-vocoder/src/Makefile.am create mode 100644 gr-gsm-fr-vocoder/src/lib/Makefile.am create mode 100644 gr-gsm-fr-vocoder/src/lib/__init__.py create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/COPYRIGHT create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/Makefile.am create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/README create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/README.orig create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/add.c create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/code.c create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/config.h create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/debug.c create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/decode.c create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/gsm.h create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/gsm_create.c create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/gsm_decode.c create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/gsm_destroy.c create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/gsm_encode.c create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/gsm_explode.c create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/gsm_implode.c create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/gsm_option.c create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/gsm_print.c create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/long_term.c create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/lpc.c create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/preprocess.c create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/private.h create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/proto.h create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/rpe.c create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/short_term.c create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/table.c create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm/unproto.h create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm_fr_decode_ps.cc create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm_fr_decode_ps.h create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm_fr_encode_sp.cc create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm_fr_encode_sp.h create mode 100644 gr-gsm-fr-vocoder/src/lib/gsm_full_rate.i create mode 100644 gr-gsm-fr-vocoder/src/python/Makefile.am create mode 100755 gr-gsm-fr-vocoder/src/python/encdec.py create mode 100755 gr-gsm-fr-vocoder/src/python/qa_gsm_full_rate.py create mode 100644 gr-gsm-fr-vocoder/src/python/run_tests.in create mode 100644 gr-howto-write-a-block/.buildpri create mode 100644 gr-howto-write-a-block/AUTHORS create mode 100644 gr-howto-write-a-block/COPYING create mode 100644 gr-howto-write-a-block/ChangeLog create mode 100644 gr-howto-write-a-block/INSTALL create mode 100644 gr-howto-write-a-block/Makefile.am create mode 100644 gr-howto-write-a-block/Makefile.common create mode 100644 gr-howto-write-a-block/NEWS create mode 100644 gr-howto-write-a-block/README create mode 100755 gr-howto-write-a-block/bootstrap create mode 100644 gr-howto-write-a-block/config.guess create mode 100644 gr-howto-write-a-block/config.sub create mode 100644 gr-howto-write-a-block/config/Makefile.am create mode 100644 gr-howto-write-a-block/config/acx_pthread.m4 create mode 100644 gr-howto-write-a-block/config/bnv_have_qt.m4 create mode 100644 gr-howto-write-a-block/config/cppunit.m4 create mode 100644 gr-howto-write-a-block/config/gr_as.m4 create mode 100644 gr-howto-write-a-block/config/gr_boost.m4 create mode 100644 gr-howto-write-a-block/config/gr_check_createfilemapping.m4 create mode 100644 gr-howto-write-a-block/config/gr_check_mc4020.m4 create mode 100644 gr-howto-write-a-block/config/gr_check_shm_open.m4 create mode 100644 gr-howto-write-a-block/config/gr_check_usrp.m4 create mode 100644 gr-howto-write-a-block/config/gr_doxygen.m4 create mode 100644 gr-howto-write-a-block/config/gr_gprof.m4 create mode 100644 gr-howto-write-a-block/config/gr_libgnuradio_core_extra_ldflags.m4 create mode 100644 gr-howto-write-a-block/config/gr_no_undefined.m4 create mode 100644 gr-howto-write-a-block/config/gr_omnithread.m4 create mode 100644 gr-howto-write-a-block/config/gr_pwin32.m4 create mode 100644 gr-howto-write-a-block/config/gr_python.m4 create mode 100644 gr-howto-write-a-block/config/gr_require_mc4020.m4 create mode 100644 gr-howto-write-a-block/config/gr_scripting.m4 create mode 100644 gr-howto-write-a-block/config/gr_set_md_cpu.m4 create mode 100644 gr-howto-write-a-block/config/gr_swig.m4 create mode 100644 gr-howto-write-a-block/config/gr_sysv_shm.m4 create mode 100644 gr-howto-write-a-block/config/gr_x86_64.m4 create mode 100644 gr-howto-write-a-block/config/lf_cc.m4 create mode 100644 gr-howto-write-a-block/config/lf_cxx.m4 create mode 100644 gr-howto-write-a-block/config/lf_warnings.m4 create mode 100644 gr-howto-write-a-block/config/lf_x11.m4 create mode 100644 gr-howto-write-a-block/config/mkstemp.m4 create mode 100644 gr-howto-write-a-block/config/onceonly.m4 create mode 100644 gr-howto-write-a-block/config/pkg.m4 create mode 100644 gr-howto-write-a-block/config/usrp_fusb_tech.m4 create mode 100644 gr-howto-write-a-block/config/usrp_libusb.m4 create mode 100644 gr-howto-write-a-block/config/usrp_sdcc.m4 create mode 100644 gr-howto-write-a-block/configure.ac create mode 100644 gr-howto-write-a-block/doc/Makefile.am create mode 100644 gr-howto-write-a-block/doc/howto-write-a-block.xml create mode 100644 gr-howto-write-a-block/doc/howto_1.i create mode 100755 gr-howto-write-a-block/doc/make_numbered_listing.py create mode 100755 gr-howto-write-a-block/doc/qa_howto_1.py create mode 100644 gr-howto-write-a-block/doc/src_lib_Makefile_1.am create mode 100644 gr-howto-write-a-block/doc/src_lib_Makefile_2.am create mode 100644 gr-howto-write-a-block/src/Makefile.am create mode 100644 gr-howto-write-a-block/src/lib/Makefile.am create mode 100644 gr-howto-write-a-block/src/lib/howto.i create mode 100644 gr-howto-write-a-block/src/lib/howto_square2_ff.cc create mode 100644 gr-howto-write-a-block/src/lib/howto_square2_ff.h create mode 100644 gr-howto-write-a-block/src/lib/howto_square_ff.cc create mode 100644 gr-howto-write-a-block/src/lib/howto_square_ff.h create mode 100644 gr-howto-write-a-block/src/python/Makefile.am create mode 100755 gr-howto-write-a-block/src/python/qa_howto.py create mode 100644 gr-howto-write-a-block/src/python/run_tests.in create mode 100644 gr-radar/AUTHORS create mode 100644 gr-radar/ChangeLog create mode 100644 gr-radar/Makefile.am create mode 100644 gr-radar/doc/Makefile.am create mode 100644 gr-radar/src/Makefile.am create mode 100644 gr-radar/src/lib/Makefile.am create mode 100644 gr-radar/src/lib/eb-xambi.cc create mode 100755 gr-radar/src/lib/gen_run create mode 100644 gr-radar/src/lib/plot_rd.m create mode 100755 gr-radar/src/lib/plot_xambi.m create mode 100755 gr-radar/src/lib/plot_xambi_to_file.m create mode 100755 gr-radar/src/lib/plot_xambi_tool.m create mode 100644 gr-radar/src/lib/sim-airplane.cc create mode 100644 gr-radar/src/lib/sim-airplane2.cc create mode 100644 gr-radar/src/lib/simulation.cc create mode 100644 gr-radar/src/lib/simulation.h create mode 100644 gr-radar/src/lib/time_series.cc create mode 100644 gr-radar/src/lib/time_series.h create mode 100644 gr-radar/src/lib/xambi.cc create mode 100644 gr-radar/src/python/Makefile.am create mode 100755 gr-radar/src/python/complex_to_short.py create mode 100755 gr-radar/src/python/fm_demod_file.py create mode 100755 gr-radar/src/python/gen_fm_signal.py create mode 100755 gr-radar/src/python/gen_random_signal.py create mode 100755 gr-radar/src/python/qa_nothing.py create mode 100644 gr-radar/src/python/run_tests.in create mode 100755 gr-radar/src/python/signal_levels.py create mode 100755 gr-radar/src/python/split_files.py create mode 100755 gr-radar/src/python/usrp_rx_radar.py create mode 100644 gr-radio-astronomy/AUTHORS create mode 100644 gr-radio-astronomy/ChangeLog create mode 100644 gr-radio-astronomy/Makefile.am create mode 100644 gr-radio-astronomy/README create mode 100644 gr-radio-astronomy/src/Makefile.am create mode 100644 gr-radio-astronomy/src/lib/Makefile.am create mode 100644 gr-radio-astronomy/src/lib/ra.i create mode 100644 gr-radio-astronomy/src/python/Makefile.am create mode 100755 gr-radio-astronomy/src/python/local_calibrator.py create mode 100755 gr-radio-astronomy/src/python/qa_ra.py create mode 100755 gr-radio-astronomy/src/python/ra_fftsink.py create mode 100755 gr-radio-astronomy/src/python/ra_stripchartsink.py create mode 100644 gr-radio-astronomy/src/python/run_tests.in create mode 100644 gr-radio-astronomy/src/python/usrp_psr_receiver.help create mode 100755 gr-radio-astronomy/src/python/usrp_psr_receiver.py create mode 100644 gr-radio-astronomy/src/python/usrp_ra_receiver.help create mode 100755 gr-radio-astronomy/src/python/usrp_ra_receiver.py create mode 100644 gr-usrp/AUTHORS create mode 100644 gr-usrp/ChangeLog create mode 100644 gr-usrp/Makefile.am create mode 100644 gr-usrp/README_MULTI_USRP.txt create mode 100644 gr-usrp/src/Makefile.am create mode 100644 gr-usrp/src/db_base.py create mode 100644 gr-usrp/src/db_basic.py create mode 100644 gr-usrp/src/db_dbs_rx.py create mode 100644 gr-usrp/src/db_flexrf.py create mode 100644 gr-usrp/src/db_flexrf_mimo.py create mode 100644 gr-usrp/src/db_instantiator.py create mode 100644 gr-usrp/src/db_tv_rx.py create mode 100755 gr-usrp/src/flexrf_debug_gui.py create mode 100755 gr-usrp/src/qa_usrp.py create mode 100644 gr-usrp/src/run_tests.in create mode 100755 gr-usrp/src/tx_debug_gui.py create mode 100644 gr-usrp/src/usrp.py create mode 100644 gr-usrp/src/usrp1.i create mode 100644 gr-usrp/src/usrp1_sink_base.cc create mode 100644 gr-usrp/src/usrp1_sink_base.h create mode 100644 gr-usrp/src/usrp1_sink_c.cc create mode 100644 gr-usrp/src/usrp1_sink_c.h create mode 100644 gr-usrp/src/usrp1_sink_s.cc create mode 100644 gr-usrp/src/usrp1_sink_s.h create mode 100644 gr-usrp/src/usrp1_source_base.cc create mode 100644 gr-usrp/src/usrp1_source_base.h create mode 100644 gr-usrp/src/usrp1_source_c.cc create mode 100644 gr-usrp/src/usrp1_source_c.h create mode 100644 gr-usrp/src/usrp1_source_s.cc create mode 100644 gr-usrp/src/usrp1_source_s.h create mode 100644 gr-usrp/src/usrp_multi.py create mode 100644 gr-video-sdl/AUTHORS create mode 100644 gr-video-sdl/ChangeLog create mode 100644 gr-video-sdl/Makefile.am create mode 100644 gr-video-sdl/src/Makefile.am create mode 100755 gr-video-sdl/src/qa_video_sdl.py create mode 100644 gr-video-sdl/src/run_tests.in create mode 100644 gr-video-sdl/src/video_sdl.i create mode 100644 gr-video-sdl/src/video_sdl_sink_s.cc create mode 100644 gr-video-sdl/src/video_sdl_sink_s.h create mode 100644 gr-video-sdl/src/video_sdl_sink_uc.cc create mode 100644 gr-video-sdl/src/video_sdl_sink_uc.h create mode 100644 gr-wxgui/ChangeLog create mode 100644 gr-wxgui/Makefile.am create mode 100644 gr-wxgui/README create mode 100644 gr-wxgui/gr-wxgui.conf create mode 100644 gr-wxgui/src/Makefile.am create mode 100644 gr-wxgui/src/python/Makefile.am create mode 100644 gr-wxgui/src/python/__init__.py create mode 100755 gr-wxgui/src/python/fftsink.py create mode 100755 gr-wxgui/src/python/form.py create mode 100644 gr-wxgui/src/python/plot.py create mode 100755 gr-wxgui/src/python/powermate.py create mode 100755 gr-wxgui/src/python/scopesink.py create mode 100755 gr-wxgui/src/python/slider.py create mode 100644 gr-wxgui/src/python/stdgui.py create mode 100755 gr-wxgui/src/python/waterfallsink.py create mode 100644 pmt/AUTHORS create mode 100644 pmt/ChangeLog create mode 100644 pmt/Makefile.am create mode 100644 pmt/README create mode 100644 pmt/doc/Makefile.am create mode 100644 pmt/src/Makefile.am create mode 100644 pmt/src/lib/Makefile.am create mode 100644 pmt/src/lib/pmt.cc create mode 100644 pmt/src/lib/pmt.h create mode 100644 pmt/src/lib/pmt_int.h create mode 100644 pmt/src/lib/qa_pmt.cc create mode 100644 pmt/src/lib/qa_pmt.h create mode 100644 pmt/src/lib/qa_pmt_prims.cc create mode 100644 pmt/src/lib/qa_pmt_prims.h create mode 100644 pmt/src/lib/test_pmt.cc create mode 100644 usrp/AUTHORS create mode 100644 usrp/ChangeLog create mode 100644 usrp/Makefile.am create mode 100644 usrp/README create mode 100644 usrp/doc/Doxyfile.in create mode 100644 usrp/doc/Makefile.am create mode 100644 usrp/doc/ddc.eps create mode 100644 usrp/doc/ddc.png create mode 100644 usrp/doc/other/Makefile.am create mode 100644 usrp/doc/other/mainpage.dox create mode 100644 usrp/doc/usrp-block-diagram.eps create mode 100644 usrp/doc/usrp-block-diagram.png create mode 100644 usrp/doc/usrp.jpg create mode 100644 usrp/doc/usrp_guide.xml create mode 100644 usrp/firmware/Makefile.am create mode 100644 usrp/firmware/include/Makefile.am create mode 100644 usrp/firmware/include/delay.h create mode 100644 usrp/firmware/include/fpga_regs0.h create mode 100644 usrp/firmware/include/fpga_regs_common.h create mode 100644 usrp/firmware/include/fpga_regs_common.v create mode 100644 usrp/firmware/include/fpga_regs_standard.h create mode 100644 usrp/firmware/include/fpga_regs_standard.v create mode 100644 usrp/firmware/include/fx2regs.h create mode 100644 usrp/firmware/include/fx2utils.h create mode 100755 usrp/firmware/include/generate_regs.py create mode 100644 usrp/firmware/include/i2c.h create mode 100644 usrp/firmware/include/isr.h create mode 100644 usrp/firmware/include/syncdelay.h create mode 100644 usrp/firmware/include/timer.h create mode 100644 usrp/firmware/include/usb_common.h create mode 100644 usrp/firmware/include/usb_descriptors.h create mode 100644 usrp/firmware/include/usb_requests.h create mode 100644 usrp/firmware/include/usrp_commands.h create mode 100644 usrp/firmware/include/usrp_config.h create mode 100644 usrp/firmware/include/usrp_i2c_addr.h create mode 100644 usrp/firmware/include/usrp_ids.h create mode 100644 usrp/firmware/include/usrp_interfaces.h create mode 100644 usrp/firmware/include/usrp_spi_defs.h create mode 100644 usrp/firmware/lib/Makefile.am create mode 100644 usrp/firmware/lib/delay.c create mode 100644 usrp/firmware/lib/fx2utils.c create mode 100644 usrp/firmware/lib/i2c-compiler-bug.c create mode 100644 usrp/firmware/lib/i2c.c create mode 100644 usrp/firmware/lib/isr.c create mode 100644 usrp/firmware/lib/timer.c create mode 100644 usrp/firmware/lib/usb_common.c create mode 100644 usrp/firmware/src/Makefile.am create mode 100644 usrp/firmware/src/common/Makefile.am create mode 100644 usrp/firmware/src/common/_startup.a51 create mode 100644 usrp/firmware/src/common/_startup.a51.brittle create mode 100644 usrp/firmware/src/common/blink_leds.c create mode 100755 usrp/firmware/src/common/build_eeprom.py create mode 100644 usrp/firmware/src/common/check_mdelay.c create mode 100644 usrp/firmware/src/common/check_udelay.c create mode 100755 usrp/firmware/src/common/edit-gpif create mode 100644 usrp/firmware/src/common/fpga.h create mode 100644 usrp/firmware/src/common/fpga_load.c create mode 100644 usrp/firmware/src/common/fpga_load.h create mode 100755 usrp/firmware/src/common/gpif.c create mode 100755 usrp/firmware/src/common/gpif.gpf create mode 100644 usrp/firmware/src/common/init_gpif.c create mode 100644 usrp/firmware/src/common/usrp_common.c create mode 100644 usrp/firmware/src/common/usrp_globals.h create mode 100644 usrp/firmware/src/common/vectors.a51 create mode 100644 usrp/firmware/src/usrp2/Makefile.am create mode 100644 usrp/firmware/src/usrp2/_startup.a51 create mode 100644 usrp/firmware/src/usrp2/blink_leds.c create mode 100644 usrp/firmware/src/usrp2/board_specific.c create mode 100644 usrp/firmware/src/usrp2/check_mdelay.c create mode 100644 usrp/firmware/src/usrp2/check_udelay.c create mode 100755 usrp/firmware/src/usrp2/edit-gpif create mode 100644 usrp/firmware/src/usrp2/eeprom_boot.a51 create mode 100644 usrp/firmware/src/usrp2/eeprom_init.c create mode 100644 usrp/firmware/src/usrp2/eeprom_io.c create mode 100644 usrp/firmware/src/usrp2/eeprom_io.h create mode 100644 usrp/firmware/src/usrp2/fpga_load.c create mode 100644 usrp/firmware/src/usrp2/fpga_rev2.c create mode 100644 usrp/firmware/src/usrp2/fpga_rev2.h create mode 100644 usrp/firmware/src/usrp2/gpif.c create mode 100755 usrp/firmware/src/usrp2/gpif.gpf create mode 100644 usrp/firmware/src/usrp2/init_gpif.c create mode 100644 usrp/firmware/src/usrp2/spi.c create mode 100644 usrp/firmware/src/usrp2/spi.h create mode 100644 usrp/firmware/src/usrp2/usb_descriptors.a51 create mode 100644 usrp/firmware/src/usrp2/usrp_common.c create mode 100644 usrp/firmware/src/usrp2/usrp_common.h create mode 100644 usrp/firmware/src/usrp2/usrp_main.c create mode 100644 usrp/firmware/src/usrp2/usrp_rev2_regs.h create mode 100644 usrp/firmware/src/usrp2/vectors.a51 create mode 100644 usrp/fpga/Makefile.am create mode 100644 usrp/fpga/Makefile.extra create mode 100644 usrp/fpga/TODO create mode 100755 usrp/fpga/gen_makefile_extra.py create mode 100755 usrp/fpga/megacells/accum32.bsf create mode 100755 usrp/fpga/megacells/accum32.cmp create mode 100755 usrp/fpga/megacells/accum32.inc create mode 100755 usrp/fpga/megacells/accum32.v create mode 100755 usrp/fpga/megacells/accum32_bb.v create mode 100755 usrp/fpga/megacells/accum32_inst.v create mode 100755 usrp/fpga/megacells/add32.bsf create mode 100755 usrp/fpga/megacells/add32.cmp create mode 100755 usrp/fpga/megacells/add32.inc create mode 100755 usrp/fpga/megacells/add32.v create mode 100755 usrp/fpga/megacells/add32_bb.v create mode 100755 usrp/fpga/megacells/add32_inst.v create mode 100755 usrp/fpga/megacells/addsub16.bsf create mode 100755 usrp/fpga/megacells/addsub16.cmp create mode 100755 usrp/fpga/megacells/addsub16.inc create mode 100755 usrp/fpga/megacells/addsub16.v create mode 100755 usrp/fpga/megacells/addsub16_bb.v create mode 100755 usrp/fpga/megacells/addsub16_inst.v create mode 100755 usrp/fpga/megacells/bustri.bsf create mode 100755 usrp/fpga/megacells/bustri.cmp create mode 100755 usrp/fpga/megacells/bustri.inc create mode 100755 usrp/fpga/megacells/bustri.v create mode 100755 usrp/fpga/megacells/bustri_bb.v create mode 100755 usrp/fpga/megacells/bustri_inst.v create mode 100644 usrp/fpga/megacells/clk_doubler.v create mode 100644 usrp/fpga/megacells/clk_doubler_bb.v create mode 100644 usrp/fpga/megacells/dspclkpll.v create mode 100644 usrp/fpga/megacells/dspclkpll_bb.v create mode 100644 usrp/fpga/megacells/fifo_2k.v create mode 100644 usrp/fpga/megacells/fifo_2k_bb.v create mode 100644 usrp/fpga/megacells/fifo_4k.v create mode 100644 usrp/fpga/megacells/fifo_4k_bb.v create mode 100755 usrp/fpga/megacells/mylpm_addsub.bsf create mode 100755 usrp/fpga/megacells/mylpm_addsub.cmp create mode 100755 usrp/fpga/megacells/mylpm_addsub.inc create mode 100755 usrp/fpga/megacells/mylpm_addsub.v create mode 100755 usrp/fpga/megacells/mylpm_addsub_bb.v create mode 100755 usrp/fpga/megacells/mylpm_addsub_inst.v create mode 100644 usrp/fpga/megacells/pll.v create mode 100644 usrp/fpga/megacells/pll_bb.v create mode 100644 usrp/fpga/megacells/pll_inst.v create mode 100755 usrp/fpga/megacells/sub32.bsf create mode 100755 usrp/fpga/megacells/sub32.cmp create mode 100755 usrp/fpga/megacells/sub32.inc create mode 100755 usrp/fpga/megacells/sub32.v create mode 100755 usrp/fpga/megacells/sub32_bb.v create mode 100755 usrp/fpga/megacells/sub32_inst.v create mode 100644 usrp/fpga/models/bustri.v create mode 100644 usrp/fpga/models/fifo.v create mode 100644 usrp/fpga/models/fifo_1c_1k.v create mode 100644 usrp/fpga/models/fifo_1c_2k.v create mode 100644 usrp/fpga/models/fifo_1c_4k.v create mode 100644 usrp/fpga/models/fifo_1k.v create mode 100644 usrp/fpga/models/fifo_2k.v create mode 100644 usrp/fpga/models/fifo_4k.v create mode 100644 usrp/fpga/models/pll.v create mode 100644 usrp/fpga/models/ssram.v create mode 100644 usrp/fpga/rbf/Makefile.am create mode 100755 usrp/fpga/rbf/rev2/multi_2rxhb_2tx.rbf create mode 100755 usrp/fpga/rbf/rev2/multi_4rx_0tx.rbf create mode 100755 usrp/fpga/rbf/rev2/std_2rxhb_2tx.rbf create mode 100755 usrp/fpga/rbf/rev2/std_4rx_0tx.rbf create mode 100755 usrp/fpga/rbf/rev4/multi_2rxhb_2tx.rbf create mode 100755 usrp/fpga/rbf/rev4/multi_4rx_0tx.rbf create mode 100755 usrp/fpga/rbf/rev4/std_2rxhb_2tx.rbf create mode 100755 usrp/fpga/rbf/rev4/std_4rx_0tx.rbf create mode 100644 usrp/fpga/sdr_lib/adc_interface.v create mode 100644 usrp/fpga/sdr_lib/bidir_reg.v create mode 100755 usrp/fpga/sdr_lib/bus_interface.v create mode 100755 usrp/fpga/sdr_lib/cic_decim.v create mode 100644 usrp/fpga/sdr_lib/cic_int_shifter.v create mode 100755 usrp/fpga/sdr_lib/cic_interp.v create mode 100755 usrp/fpga/sdr_lib/clk_divider.v create mode 100755 usrp/fpga/sdr_lib/cordic.v create mode 100755 usrp/fpga/sdr_lib/cordic_stage.v create mode 100755 usrp/fpga/sdr_lib/ddc.v create mode 100644 usrp/fpga/sdr_lib/dpram.v create mode 100755 usrp/fpga/sdr_lib/duc.v create mode 100644 usrp/fpga/sdr_lib/ext_fifo.v create mode 100755 usrp/fpga/sdr_lib/gen_cordic_consts.py create mode 100644 usrp/fpga/sdr_lib/gen_sync.v create mode 100644 usrp/fpga/sdr_lib/hb/acc.v create mode 100644 usrp/fpga/sdr_lib/hb/coeff_ram.v create mode 100644 usrp/fpga/sdr_lib/hb/coeff_rom.v create mode 100644 usrp/fpga/sdr_lib/hb/halfband_decim.v create mode 100644 usrp/fpga/sdr_lib/hb/halfband_interp.v create mode 100644 usrp/fpga/sdr_lib/hb/hbd_tb/HBD create mode 100644 usrp/fpga/sdr_lib/hb/hbd_tb/really_golden create mode 100644 usrp/fpga/sdr_lib/hb/hbd_tb/regression create mode 100755 usrp/fpga/sdr_lib/hb/hbd_tb/run_hbd create mode 100644 usrp/fpga/sdr_lib/hb/hbd_tb/test_hbd.v create mode 100644 usrp/fpga/sdr_lib/hb/mac.v create mode 100644 usrp/fpga/sdr_lib/hb/mult.v create mode 100644 usrp/fpga/sdr_lib/hb/ram16_2port.v create mode 100644 usrp/fpga/sdr_lib/hb/ram16_2sum.v create mode 100644 usrp/fpga/sdr_lib/hb/ram32_2sum.v create mode 100644 usrp/fpga/sdr_lib/io_pins.v create mode 100644 usrp/fpga/sdr_lib/master_control.v create mode 100644 usrp/fpga/sdr_lib/master_control_multi.v create mode 100755 usrp/fpga/sdr_lib/phase_acc.v create mode 100644 usrp/fpga/sdr_lib/ram.v create mode 100644 usrp/fpga/sdr_lib/ram16.v create mode 100644 usrp/fpga/sdr_lib/ram32.v create mode 100644 usrp/fpga/sdr_lib/ram64.v create mode 100644 usrp/fpga/sdr_lib/rssi.v create mode 100644 usrp/fpga/sdr_lib/rx_buffer.v create mode 100644 usrp/fpga/sdr_lib/rx_chain.v create mode 100644 usrp/fpga/sdr_lib/rx_chain_dual.v create mode 100644 usrp/fpga/sdr_lib/rx_dcoffset.v create mode 100644 usrp/fpga/sdr_lib/serial_io.v create mode 100644 usrp/fpga/sdr_lib/setting_reg.v create mode 100644 usrp/fpga/sdr_lib/setting_reg_masked.v create mode 100644 usrp/fpga/sdr_lib/sign_extend.v create mode 100644 usrp/fpga/sdr_lib/strobe_gen.v create mode 100644 usrp/fpga/sdr_lib/tx_buffer.v create mode 100644 usrp/fpga/sdr_lib/tx_chain.v create mode 100644 usrp/fpga/sdr_lib/tx_chain_hb.v create mode 100644 usrp/fpga/tb/cbus_tb.v create mode 100644 usrp/fpga/tb/cordic_tb.v create mode 100644 usrp/fpga/tb/decim_tb.v create mode 100755 usrp/fpga/tb/fullchip_tb.v create mode 100755 usrp/fpga/tb/interp_tb.v create mode 100644 usrp/fpga/tb/justinterp_tb.v create mode 100755 usrp/fpga/tb/makesine.pl create mode 100755 usrp/fpga/tb/run_cordic create mode 100755 usrp/fpga/tb/run_fullchip create mode 100755 usrp/fpga/tb/usrp_tasks.v create mode 100644 usrp/fpga/toplevel/mrfm/biquad_2stage.v create mode 100644 usrp/fpga/toplevel/mrfm/biquad_6stage.v create mode 100644 usrp/fpga/toplevel/mrfm/mrfm.csf create mode 100644 usrp/fpga/toplevel/mrfm/mrfm.esf create mode 100644 usrp/fpga/toplevel/mrfm/mrfm.psf create mode 100644 usrp/fpga/toplevel/mrfm/mrfm.py create mode 100644 usrp/fpga/toplevel/mrfm/mrfm.qpf create mode 100644 usrp/fpga/toplevel/mrfm/mrfm.qsf create mode 100644 usrp/fpga/toplevel/mrfm/mrfm.v create mode 100644 usrp/fpga/toplevel/mrfm/mrfm.vh create mode 100644 usrp/fpga/toplevel/mrfm/mrfm_compensator.v create mode 100755 usrp/fpga/toplevel/mrfm/mrfm_fft.py create mode 100644 usrp/fpga/toplevel/mrfm/mrfm_proc.v create mode 100644 usrp/fpga/toplevel/mrfm/shifter.v create mode 100644 usrp/fpga/toplevel/sizetest/sizetest.csf create mode 100644 usrp/fpga/toplevel/sizetest/sizetest.psf create mode 100644 usrp/fpga/toplevel/sizetest/sizetest.quartus create mode 100644 usrp/fpga/toplevel/sizetest/sizetest.ssf create mode 100644 usrp/fpga/toplevel/sizetest/sizetest.v create mode 100644 usrp/fpga/toplevel/usrp_multi/usrp_multi.csf create mode 100644 usrp/fpga/toplevel/usrp_multi/usrp_multi.esf create mode 100644 usrp/fpga/toplevel/usrp_multi/usrp_multi.psf create mode 100644 usrp/fpga/toplevel/usrp_multi/usrp_multi.qpf create mode 100644 usrp/fpga/toplevel/usrp_multi/usrp_multi.qsf create mode 100644 usrp/fpga/toplevel/usrp_multi/usrp_multi.v create mode 100644 usrp/fpga/toplevel/usrp_multi/usrp_multi.vh create mode 100644 usrp/fpga/toplevel/usrp_multi/usrp_multi_config_2rx_0tx.vh create mode 100644 usrp/fpga/toplevel/usrp_multi/usrp_multi_config_2rxhb_0tx.vh create mode 100644 usrp/fpga/toplevel/usrp_multi/usrp_multi_config_2rxhb_2tx.vh create mode 100644 usrp/fpga/toplevel/usrp_multi/usrp_multi_config_4rx_0tx.vh create mode 100644 usrp/fpga/toplevel/usrp_multi/usrp_std.vh create mode 100644 usrp/fpga/toplevel/usrp_std/usrp_std.csf create mode 100644 usrp/fpga/toplevel/usrp_std/usrp_std.esf create mode 100644 usrp/fpga/toplevel/usrp_std/usrp_std.psf create mode 100644 usrp/fpga/toplevel/usrp_std/usrp_std.qpf create mode 100644 usrp/fpga/toplevel/usrp_std/usrp_std.qsf create mode 100644 usrp/fpga/toplevel/usrp_std/usrp_std.v create mode 100644 usrp/fpga/toplevel/usrp_std/usrp_std.vh create mode 100644 usrp/fpga/toplevel/usrp_std/usrp_std_config_2rxhb_2tx.vh create mode 100644 usrp/fpga/toplevel/usrp_std/usrp_std_config_4rx_0tx.vh create mode 100644 usrp/host/Makefile.am create mode 100644 usrp/host/apps/Makefile.am create mode 100755 usrp/host/apps/burn-db-eeprom create mode 100755 usrp/host/apps/burn-serial-number create mode 100755 usrp/host/apps/check_order create mode 100644 usrp/host/apps/check_order_quickly.cc create mode 100755 usrp/host/apps/dump_12bit_shorts create mode 100755 usrp/host/apps/dump_shorts create mode 100755 usrp/host/apps/print-db create mode 100755 usrp/host/apps/run create mode 100755 usrp/host/apps/run2 create mode 100755 usrp/host/apps/run_input create mode 100644 usrp/host/apps/test_usrp_standard_rx.cc create mode 100644 usrp/host/apps/test_usrp_standard_tx.cc create mode 100644 usrp/host/apps/time_stuff.c create mode 100644 usrp/host/apps/time_stuff.h create mode 100644 usrp/host/apps/usrp_cal_dc_offset.cc create mode 100644 usrp/host/apps/usrper.cc create mode 100644 usrp/host/lib/Makefile.am create mode 100644 usrp/host/lib/README_OSX create mode 100644 usrp/host/lib/ad9862.h create mode 100755 usrp/host/lib/check_data.py create mode 100644 usrp/host/lib/circular_buffer.h create mode 100644 usrp/host/lib/circular_linked_list.h create mode 100644 usrp/host/lib/darwin_libusb.h create mode 100755 usrp/host/lib/dump_data.py create mode 100644 usrp/host/lib/dxc-io-assignments.gnumeric create mode 100644 usrp/host/lib/fusb.cc create mode 100644 usrp/host/lib/fusb.h create mode 100644 usrp/host/lib/fusb_darwin.cc create mode 100644 usrp/host/lib/fusb_darwin.h create mode 100644 usrp/host/lib/fusb_generic.cc create mode 100644 usrp/host/lib/fusb_generic.h create mode 100644 usrp/host/lib/fusb_linux.cc create mode 100644 usrp/host/lib/fusb_linux.h create mode 100644 usrp/host/lib/fusb_sysconfig_darwin.cc create mode 100644 usrp/host/lib/fusb_sysconfig_generic.cc create mode 100644 usrp/host/lib/fusb_sysconfig_linux.cc create mode 100644 usrp/host/lib/fusb_sysconfig_win32.cc create mode 100644 usrp/host/lib/fusb_win32.cc create mode 100644 usrp/host/lib/fusb_win32.h create mode 100755 usrp/host/lib/gen-ratios create mode 100755 usrp/host/lib/gen_usrp_dbid.py create mode 100644 usrp/host/lib/md5.c create mode 100644 usrp/host/lib/md5.h create mode 100644 usrp/host/lib/mld_threads.h create mode 100644 usrp/host/lib/rate_to_regval.h create mode 100644 usrp/host/lib/std_paths.h.in create mode 100644 usrp/host/lib/usrp_basic.cc create mode 100644 usrp/host/lib/usrp_basic.h create mode 100644 usrp/host/lib/usrp_bytesex.h create mode 100644 usrp/host/lib/usrp_config.cc create mode 100644 usrp/host/lib/usrp_config.h create mode 100644 usrp/host/lib/usrp_dbid.dat create mode 100644 usrp/host/lib/usrp_local_sighandler.cc create mode 100644 usrp/host/lib/usrp_local_sighandler.h create mode 100644 usrp/host/lib/usrp_prims.cc create mode 100644 usrp/host/lib/usrp_prims.h create mode 100644 usrp/host/lib/usrp_slots.h create mode 100644 usrp/host/lib/usrp_standard.cc create mode 100644 usrp/host/lib/usrp_standard.h create mode 100644 usrp/host/misc/Makefile.am create mode 100644 usrp/host/misc/bug_work_around_8.cc create mode 100644 usrp/host/misc/getopt.c create mode 100644 usrp/host/misc/getopt.h create mode 100644 usrp/host/misc/gettimeofday.c create mode 100644 usrp/host/misc/mkstemp.c create mode 100644 usrp/host/misc/tempname.c create mode 100644 usrp/host/misc/usleep.c create mode 100644 usrp/host/swig/Makefile.am create mode 100644 usrp/host/swig/__init__.py create mode 100644 usrp/host/swig/prims.i create mode 100644 usrp/host/swig/usrp_fpga_regs.py create mode 100644 usrp/host/swig/util.py create mode 100644 usrp/usrp.inf create mode 100644 usrp/usrp.iss.in create mode 100644 usrp/usrp.pc.in diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 00000000..d1fb4ddc --- /dev/null +++ b/AUTHORS @@ -0,0 +1,12 @@ +Eric Blossom Most of the guts +Matt Ettus ongoing code, ideas, bugfixes, the USRP +John Gilmore ideas, bug fixes, financial support +Stephane Fillod SIMD speed ups, lots of other good stuff +Chuck Swiger hf stuff, enthusiasm ;) +Ramakrishnan Muthukrishnan Debian pkgs + misc stuff +Martin Dudok van Heel lots of stuff +Bob McGwier N4HY wisdom, code, bugfixes. +Krzysztof Kamieniecki bugfixes +Andrew Thomas Beck bugfixes +Joshua Lackey Original GMSK implementation. +Johnathan Corgan Goertzel, squelch, adaptive filtering, misc. diff --git a/COPYING b/COPYING new file mode 100644 index 00000000..2b7b643f --- /dev/null +++ b/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + 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 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 00000000..2237a4ab --- /dev/null +++ b/ChangeLog @@ -0,0 +1,20 @@ +# +# Copyright 2001,2002,2003,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. +# diff --git a/INSTALL b/INSTALL new file mode 100644 index 00000000..54caf7c1 --- /dev/null +++ b/INSTALL @@ -0,0 +1,229 @@ +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software +Foundation, Inc. + + This file is free documentation; the Free Software Foundation gives +unlimited permission to copy, distribute and modify it. + +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, and a +file `config.log' containing compiler output (useful mainly for +debugging `configure'). + + It can also use an optional file (typically called `config.cache' +and enabled with `--cache-file=config.cache' or simply `-C') that saves +the results of its tests to speed up reconfiguring. (Caching is +disabled by default to prevent problems with accidental use of stale +cache files.) + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If you are using the cache, and at +some point `config.cache' contains results you don't want to keep, you +may remove or edit it. + + The file `configure.ac' (or `configure.in') is used to create +`configure' by a program called `autoconf'. You only need +`configure.ac' if you want to change it or regenerate `configure' using +a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. Run `./configure --help' +for details on some of the pertinent environment variables. + + You can give `configure' initial values for configuration parameters +by setting variables in the command line or in the environment. Here +is an example: + + ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix + + *Note Defining Variables::, for more details. + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not support the `VPATH' +variable, you have to compile the package for one architecture at a +time in the source code directory. After you have installed the +package for one architecture, use `make distclean' before reconfiguring +for another architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' cannot figure out +automatically, but needs to determine by the type of machine the package +will run on. Usually, assuming the package is built to be run on the +_same_ architectures, `configure' can figure that out, but if it prints +a message saying it cannot guess the machine type, give it the +`--build=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name which has the form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS KERNEL-OS + + See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the machine type. + + If you are _building_ compiler tools for cross-compiling, you should +use the `--target=TYPE' option to select the type of system they will +produce code for. + + If you want to _use_ a cross compiler, that generates code for a +platform different from the build platform, you should specify the +"host" platform (i.e., that on which the generated programs will +eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Defining Variables +================== + + Variables not defined in a site shell script can be set in the +environment passed to `configure'. However, some packages may run +configure again during the build, and the customized values of these +variables may be lost. In order to avoid this problem, you should set +them in the `configure' command line, using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +will cause the specified gcc to be used as the C compiler (unless it is +overridden in the site shell script). + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of the options to `configure', and exit. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000..883a490a --- /dev/null +++ b/Makefile.am @@ -0,0 +1,29 @@ +# +# Copyright 2001,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 + +EXTRA_DIST = \ + bootstrap \ + configure \ + config.h.in + +SUBDIRS = @subdirs@ diff --git a/Makefile.common b/Makefile.common new file mode 100644 index 00000000..2259cac0 --- /dev/null +++ b/Makefile.common @@ -0,0 +1,40 @@ +# -*- Makefile -*- +# +# 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. +# + +# includes +grincludedir = $(includedir)/gnuradio + +# swig includes +swigincludedir = $(grincludedir)/swig + +# Install this stuff in the appropriate subdirectory +# This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio + +grpythondir = $(pythondir)/gnuradio +grpyexecdir = $(pyexecdir)/gnuradio + +# swig flags +SWIGPYTHONFLAGS = -fvirtual -python -modern + +# gnuradio-core library link command +GNURADIO_CORE_LIBS = -L$(top_srcdir)/gnuradio-core/src/lib/.libs -lgnuradio-core -lfftw3f -lm diff --git a/NEWS b/NEWS new file mode 100644 index 00000000..d93a0dd6 --- /dev/null +++ b/NEWS @@ -0,0 +1,15 @@ +------------------------------------------------------- +Copying information: + +Copyright (C) 2001, Free Software Foundation, Inc. + + Permission is granted to anyone to make or distribute verbatim copies + of this document as received, in any medium, provided that the + copyright notice and this permission notice are preserved, + thus giving the recipient permission to redistribute in turn. + + Permission is granted to distribute modified versions + of this document, or of portions of it, + under the above conditions, provided also that they + carry prominent notices stating who last changed them. + diff --git a/README b/README new file mode 100644 index 00000000..dfc0ac8d --- /dev/null +++ b/README @@ -0,0 +1,190 @@ +# +# Copyright 2001,2002,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. +# + +------------------------------------------------------------------------------- + + IMPORTANT + +------------------------------------------------------------------------------- + +GNU Radio is now broken up into several packages. You're looking at +the gnuradio-core. You'll probably want some or all of these too. +Build and install them in the order listed here: + + gnuradio-core # main library + gnuradio-examples # examples + gr-audio-alsa # support for sounds cards using ALSA (prefered under GNU/Linux) + gr-audio-oss # support for sounds cards using OSS + gr-audio-jack # support for JACK Audio Connection Kit + gr-audio-windows # support for sounds cards using Windows Wave + gr-comedi # support for DAQ cards using COMEDI + gr-wxgui # GUI framework built on wxPython + usrp # non-GNU Radio specific portion of usrp + gr-usrp # glues usrp into GNU Radio + mc4020 # GNU/Linux driver for Measurement Computing PCI-DAS4020/12 A/D board + gr-mc4020 # the glue that ties the mc4020 driver into GNU Radio + + +------------------------------------------------------------------------------- + + KNOWN INCOMPATIBILITIES + + + GNU Radio triggers bugs in g++ 3.3 for X86. DO NOT USE GCC 3.3. + gcc 3.2 and 3.4 are known to work well. + +------------------------------------------------------------------------------- + +Prerequisites (you may already have these): + +(1) pkgconfig 0.15.0 or later http://www.freedesktop.org/Software/pkgconfig + +From the web site: + +pkgconfig is a system for managing library compile/link flags that +works with automake and autoconf. It replaces the ubiquitous *-config +scripts you may have seen with a single tool. + + +(2) FFTW 3.0 or later http://www.fftw.org + +IMPORTANT!!! When building FFTW, you MUST use the --enable-single and +--enable-shared configure options. This builds the single precision +floating point version which we use. You should also use either the +--enable-3dnow or --enable-sse options if you're on an Athlon or Pentium +respectively. + + +(3) Python 2.3 or later http://www.python.org + +Python 2.3 or later is now required. If your distribution splits +python into a bunch of separate RPMS including python-devel or +libpython you'll most likely need those too. + + +(4) Numeric python library http://numeric.scipy.org + +Provides a high performance array type for Python. + + +(5) The Boost C++ Libraries http://www.boost.org + +We use the Smart Pointer library. Fedore Core 2 has a package for +this, boost-devel-1.31.0-7. Otherwise download the source and follow +the build instructions. They're a bit different from the normal +./configure && make + + +(6) cppunit 1.9.14 or later. http://cppunit.sourceforge.net + +Unit testing framework for C++. + + +(7) Simple Wrapper Interface Generator. http://www.swig.org + +These versions are known to work: + 1.3.23, 1.3.24, 1.3.25, 1.3.27, 1.3.28, 1.3.29 + +---------------------------------------------------------------- + +For the impatient, just do the following: + + $ ./configure + $ make + $ make check + $ make install + +If it doesn't work, fix it and send us a patch... + + +See http://www.gnu.org/software/gnuradio/ for an overview. +The project is hosted at http://savannah.gnu.org/projects/gnuradio/ + + +If you've got doxygen installed and provide the --enable-doxygen +configure option, the build process creates documentation for the +class hierarchy etc. Point your browser at +gnuradio-core/doc/html/index.html + + +To run the examples you'll need to set PYTHONPATH. +Note that the python version number in the path needs to match your +installed version of python. + + $ export PYTHONPATH=/usr/local/lib/python2.3/site-packages + +You may want to add this to your ~/.bash_profile + + + +---------------------------------------------------------------- + + Notes on building GNU Radio from the CVS repository + +---------------------------------------------------------------- + +If you're building from the CVS repository YOU MUST BE PLAYING BY THE +RULES THAT THE OTHER DEVELOPERS ARE USING. This is especially true +with regard to the versions of the tools below... + +Ensure that you've got THESE VERSIONS of the following tools: + + autoconf 2.57 or later + automake 1.7.4 or later + libtool 1.5 or later + swig 1.3.{23,24,25,27,28,29} + +If you're using earlier versions than these, don't expect the system +to build. Get these versions or something later. They're available +at any of the GNU mirrors. + +Then, check out a copy of GNU Radio. + +See http://www.gnu.org/software/gnuradio for directions on anonymous +access to the CVS repository. + +Then in the top level directory, execute + + $ ./bootstrap + +This builds configure from configure.ac and also builds all the +Makefile.in's from the Makefile.am's. + +Then carry on as usual: + + $ ./configure + $ make + $ make check + $ make install + + +For the easiest way to build from CVS, see +http://comsec.com/wiki?HowtoBuildFromCVS + + + +Another handy trick if for example your fftw includes and libs are +installed in, say ~/local/include and ~/local/lib, instead of +/usr/local is this: + + $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/local/lib + $ make CPPFLAGS="-I$HOME/local/include" + diff --git a/bootstrap b/bootstrap new file mode 100755 index 00000000..7df375ee --- /dev/null +++ b/bootstrap @@ -0,0 +1,29 @@ +#!/bin/sh + +# Copyright 2001,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + + +rm -fr config.cache autom4te*.cache + +aclocal -I config +autoconf +autoheader +libtoolize --automake +automake --add-missing diff --git a/config.guess b/config.guess new file mode 100755 index 00000000..52c01be4 --- /dev/null +++ b/config.guess @@ -0,0 +1,1465 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +timestamp='2005-11-11' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner . +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d -q "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerppc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep __LP64__ >/dev/null + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + x86:Interix*:[345]*) + echo i586-pc-interix${UNAME_RELEASE}|sed -e 's/\..*//' + exit ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips64 + #undef mips64el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mips64el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips64 + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #ifdef __INTEL_COMPILER + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + test x"${LIBC}" != x && { + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit + } + test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config.sub b/config.sub new file mode 100755 index 00000000..a4aba165 --- /dev/null +++ b/config.sub @@ -0,0 +1,1587 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + +timestamp='2005-11-13' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-dietlibc | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | \ + kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | m32r | m32rle | m68000 | m68k | m88k | maxq | mcore \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | ms1 \ + | msp430 \ + | ns16k | ns32k \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b \ + | strongarm \ + | tahoe | thumb | tic4x | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xscalee[bl] | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m32c) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | ms1-* \ + | msp430-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \ + | xstormy16-* | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + m32c-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16c) + basic_machine=cr16c-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tic55x | c55x*) + basic_machine=tic55x-unknown + os=-coff + ;; + tic6x | c6x*) + basic_machine=tic6x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* | -openbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-uclibc* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/config/Makefile.am b/config/Makefile.am new file mode 100644 index 00000000..fd33c622 --- /dev/null +++ b/config/Makefile.am @@ -0,0 +1,66 @@ +# +# Copyright 2001,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 + +# Install m4 macros in this directory +m4datadir = $(datadir)/aclocal + +# List your m4 macros here +m4macros = \ + acx_pthread.m4 \ + bnv_have_qt.m4 \ + cppunit.m4 \ + gr_as.m4 \ + gr_boost.m4 \ + gr_check_createfilemapping.m4 \ + gr_check_usrp.m4 \ + gr_check_mc4020.m4 \ + gr_check_shm_open.m4 \ + gr_doxygen.m4 \ + gr_gprof.m4 \ + gr_libgnuradio_core_extra_ldflags.m4 \ + gr_no_undefined.m4 \ + gr_omnithread.m4 \ + gr_pwin32.m4 \ + gr_python.m4 \ + gr_require_mc4020.m4 \ + gr_scripting.m4 \ + gr_set_md_cpu.m4 \ + gr_swig.m4 \ + gr_sysv_shm.m4 \ + gr_x86_64.m4 \ + lf_cc.m4 \ + lf_cxx.m4 \ + lf_warnings.m4 \ + lf_x11.m4 \ + mkstemp.m4 \ + onceonly.m4 \ + pkg.m4 \ + usrp_fusb_tech.m4 \ + usrp_libusb.m4 \ + usrp_sdcc.m4 + + +# Don't install m4 macros anymore +# m4data_DATA = $(m4macros) + +EXTRA_DIST = $(m4macros) diff --git a/config/acx_pthread.m4 b/config/acx_pthread.m4 new file mode 100644 index 00000000..d318ab01 --- /dev/null +++ b/config/acx_pthread.m4 @@ -0,0 +1,190 @@ +dnl Available from the GNU Autoconf Macro Archive at: +dnl http://www.gnu.org/software/ac-archive/htmldoc/acx_pthread.html +dnl +AC_DEFUN([ACX_PTHREAD], [ +AC_REQUIRE([AC_CANONICAL_HOST]) +AC_LANG_SAVE +AC_LANG_C +acx_pthread_ok=no + +# We used to check for pthread.h first, but this fails if pthread.h +# requires special compiler flags (e.g. on True64 or Sequent). +# It gets checked for in the link test anyway. + +# First of all, check if the user has set any of the PTHREAD_LIBS, +# etcetera environment variables, and if threads linking works using +# them: +if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) + AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes) + AC_MSG_RESULT($acx_pthread_ok) + if test x"$acx_pthread_ok" = xno; then + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" + fi + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" +fi + +# We must check for the threads library under a number of different +# names; the ordering is very important because some systems +# (e.g. DEC) have both -lpthread and -lpthreads, where one of the +# libraries is broken (non-POSIX). + +# Create a list of thread flags to try. Items starting with a "-" are +# C compiler flags, and other items are library names, except for "none" +# which indicates that we try without any flags at all. + +acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt" + +# The ordering *is* (sometimes) important. Some notes on the +# individual items follow: + +# pthreads: AIX (must check this before -lpthread) +# none: in case threads are in libc; should be tried before -Kthread and +# other compiler flags to prevent continual compiler warnings +# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) +# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) +# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) +# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) +# -pthreads: Solaris/gcc +# -mthreads: Mingw32/gcc, Lynx/gcc +# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it +# doesn't hurt to check since this sometimes defines pthreads too; +# also defines -D_REENTRANT) +# pthread: Linux, etcetera +# --thread-safe: KAI C++ + +case "${host_cpu}-${host_os}" in + *solaris*) + + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (We need to link with -pthread or + # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather + # a function called by this macro, so we could check for that, but + # who knows whether they'll stub that too in a future libc.) So, + # we'll just look for -pthreads and -lpthread first: + + acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags" + ;; +esac + +if test x"$acx_pthread_ok" = xno; then +for flag in $acx_pthread_flags; do + + case $flag in + none) + AC_MSG_CHECKING([whether pthreads work without any flags]) + ;; + + -*) + AC_MSG_CHECKING([whether pthreads work with $flag]) + PTHREAD_CFLAGS="$flag" + ;; + + *) + AC_MSG_CHECKING([for the pthreads library -l$flag]) + PTHREAD_LIBS="-l$flag" + ;; + esac + + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS="$PTHREAD_LIBS $LIBS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Check for various functions. We must include pthread.h, + # since some functions may be macros. (On the Sequent, we + # need a special flag -Kthread to make this header compile.) + # We check for pthread_join because it is in -lpthread on IRIX + # while pthread_create is in libc. We check for pthread_attr_init + # due to DEC craziness with -lpthreads. We check for + # pthread_cleanup_push because it is one of the few pthread + # functions on Solaris that doesn't have a non-functional libc stub. + # We try pthread_create on general principles. + AC_TRY_LINK([#include ], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0); ], + [acx_pthread_ok=yes]) + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + AC_MSG_RESULT($acx_pthread_ok) + if test "x$acx_pthread_ok" = xyes; then + break; + fi + + PTHREAD_LIBS="" + PTHREAD_CFLAGS="" +done +fi + +# Various other checks: +if test "x$acx_pthread_ok" = xyes; then + save_LIBS="$LIBS" + LIBS="$PTHREAD_LIBS $LIBS" + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $PTHREAD_CFLAGS" + + # Detect AIX lossage: threads are created detached by default + # and the JOINABLE attribute has a nonstandard name (UNDETACHED). + AC_MSG_CHECKING([for joinable pthread attribute]) + AC_TRY_LINK([#include ], + [int attr=PTHREAD_CREATE_JOINABLE;], + ok=PTHREAD_CREATE_JOINABLE, ok=unknown) + if test x"$ok" = xunknown; then + AC_TRY_LINK([#include ], + [int attr=PTHREAD_CREATE_UNDETACHED;], + ok=PTHREAD_CREATE_UNDETACHED, ok=unknown) + fi + if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then + AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok, + [Define to the necessary symbol if this constant + uses a non-standard name on your system.]) + fi + AC_MSG_RESULT(${ok}) + if test x"$ok" = xunknown; then + AC_MSG_WARN([we do not know how to create joinable pthreads]) + fi + + AC_MSG_CHECKING([if more special flags are required for pthreads]) + flag=no + case "${host_cpu}-${host_os}" in + *-aix* | *-freebsd*) flag="-D_THREAD_SAFE";; + *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";; + esac + AC_MSG_RESULT(${flag}) + if test "x$flag" != xno; then + PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" + fi + + LIBS="$save_LIBS" + CFLAGS="$save_CFLAGS" + + # More AIX lossage: must compile with cc_r + AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC}) +else + PTHREAD_CC="$CC" +fi + +AC_SUBST(PTHREAD_LIBS) +AC_SUBST(PTHREAD_CFLAGS) +AC_SUBST(PTHREAD_CC) + +# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: +if test x"$acx_pthread_ok" = xyes; then + ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) + : +else + acx_pthread_ok=no + $2 +fi +AC_LANG_RESTORE +])dnl ACX_PTHREAD diff --git a/config/bnv_have_qt.m4 b/config/bnv_have_qt.m4 new file mode 100644 index 00000000..1469bfbf --- /dev/null +++ b/config/bnv_have_qt.m4 @@ -0,0 +1,404 @@ +dnl Available from the GNU Autoconf Macro Archive at: +dnl http://www.gnu.org/software/ac-archive/htmldoc/bnv_have_qt.html +dnl +AC_DEFUN([BNV_HAVE_QT], +[ + dnl THANKS! This code includes bug fixes by: + dnl Tim McClarren. + + AC_REQUIRE([AC_PROG_CXX]) + AC_REQUIRE([AC_PATH_X]) + AC_REQUIRE([AC_PATH_XTRA]) + + AC_MSG_CHECKING(for Qt) + + AC_ARG_WITH([Qt-dir], + [ --with-Qt-dir=DIR DIR is equal to \$QTDIR if you have followed the + installation instructions of Trolltech. Header + files are in DIR/include, binary utilities are + in DIR/bin and the library is in DIR/lib]) + AC_ARG_WITH([Qt-include-dir], + [ --with-Qt-include-dir=DIR + Qt header files are in DIR]) + AC_ARG_WITH([Qt-bin-dir], + [ --with-Qt-bin-dir=DIR Qt utilities such as moc and uic are in DIR]) + AC_ARG_WITH([Qt-lib-dir], + [ --with-Qt-lib-dir=DIR The Qt library is in DIR]) + AC_ARG_WITH([Qt-lib], + [ --with-Qt-lib=LIB Use -lLIB to link with the Qt library]) + if test x"$with_Qt_dir" = x"no" || + test x"$with_Qt_include-dir" = x"no" || + test x"$with_Qt_bin_dir" = x"no" || + test x"$with_Qt_lib_dir" = x"no" || + test x"$with_Qt_lib" = x"no"; then + # user disabled Qt. Leave cache alone. + have_qt="User disabled Qt." + else + # "yes" is a bogus option + if test x"$with_Qt_dir" = xyes; then + with_Qt_dir= + fi + if test x"$with_Qt_include_dir" = xyes; then + with_Qt_include_dir= + fi + if test x"$with_Qt_bin_dir" = xyes; then + with_Qt_bin_dir= + fi + if test x"$with_Qt_lib_dir" = xyes; then + with_Qt_lib_dir= + fi + if test x"$with_Qt_lib" = xyes; then + with_Qt_lib= + fi + # No Qt unless we discover otherwise + have_qt=no + # Check whether we are requested to link with a specific version + if test x"$with_Qt_lib" != x; then + bnv_qt_lib="$with_Qt_lib" + fi + # Check whether we were supplied with an answer already + if test x"$with_Qt_dir" != x; then + have_qt=yes + bnv_qt_dir="$with_Qt_dir" + bnv_qt_include_dir="$with_Qt_dir/include" + bnv_qt_bin_dir="$with_Qt_dir/bin" + bnv_qt_lib_dir="$with_Qt_dir/lib" + # Only search for the lib if the user did not define one already + if test x"$bnv_qt_lib" = x; then + bnv_qt_lib="`ls $bnv_qt_lib_dir/libqt* | sed -n 1p | + sed s@$bnv_qt_lib_dir/lib@@ | [sed s@[.].*@@]`" + fi + bnv_qt_LIBS="-L$bnv_qt_lib_dir -l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS" + else + # Use cached value or do search, starting with suggestions from + # the command line + AC_CACHE_VAL(bnv_cv_have_qt, + [ + # We are not given a solution and there is no cached value. + bnv_qt_dir=NO + bnv_qt_include_dir=NO + bnv_qt_lib_dir=NO + if test x"$bnv_qt_lib" = x; then + bnv_qt_lib=NO + fi + BNV_PATH_QT_DIRECT + if test "$bnv_qt_dir" = NO || + test "$bnv_qt_include_dir" = NO || + test "$bnv_qt_lib_dir" = NO || + test "$bnv_qt_lib" = NO; then + # Problem with finding complete Qt. Cache the known absence of Qt. + bnv_cv_have_qt="have_qt=no" + else + # Record where we found Qt for the cache. + bnv_cv_have_qt="have_qt=yes \ + bnv_qt_dir=$bnv_qt_dir \ + bnv_qt_include_dir=$bnv_qt_include_dir \ + bnv_qt_bin_dir=$bnv_qt_bin_dir \ + bnv_qt_LIBS=\"$bnv_qt_LIBS\"" + fi + ])dnl + eval "$bnv_cv_have_qt" + fi # all $bnv_qt_* are set + fi # $have_qt reflects the system status + if test x"$have_qt" = xyes; then + QT_CXXFLAGS="-I$bnv_qt_include_dir" + QT_DIR="$bnv_qt_dir" + QT_LIBS="$bnv_qt_LIBS" + # If bnv_qt_dir is defined, utilities are expected to be in the + # bin subdirectory + if test x"$bnv_qt_dir" != x; then + if test -x "$bnv_qt_dir/bin/uic"; then + QT_UIC="$bnv_qt_dir/bin/uic" + else + # Old versions of Qt don't have uic + QT_UIC= + fi + QT_MOC="$bnv_qt_dir/bin/moc" + else + # Or maybe we are told where to look for the utilities + if test x"$bnv_qt_bin_dir" != x; then + if test -x "$bnv_qt_bin_dir/uic"; then + QT_UIC="$bnv_qt_bin_dir/uic" + else + # Old versions of Qt don't have uic + QT_UIC= + fi + QT_MOC="$bnv_qt_bin_dir/moc" + else + # Last possibility is that they are in $PATH + QT_UIC="`which uic`" + QT_MOC="`which moc`" + fi + fi + # All variables are defined, report the result + AC_MSG_RESULT([$have_qt: + QT_CXXFLAGS=$QT_CXXFLAGS + QT_DIR=$QT_DIR + QT_LIBS=$QT_LIBS + QT_UIC=$QT_UIC + QT_MOC=$QT_MOC]) + else + # Qt was not found + QT_CXXFLAGS= + QT_DIR= + QT_LIBS= + QT_UIC= + QT_MOC= + AC_MSG_RESULT($have_qt) + fi + AC_SUBST(QT_CXXFLAGS) + AC_SUBST(QT_DIR) + AC_SUBST(QT_LIBS) + AC_SUBST(QT_UIC) + AC_SUBST(QT_MOC) + + #### Being paranoid: + if test x"$have_qt" = xyes; then + AC_MSG_CHECKING(correct functioning of Qt installation) + AC_CACHE_VAL(bnv_cv_qt_test_result, + [ + cat > bnv_qt_test.h << EOF +#include +class Test : public QObject +{ +Q_OBJECT +public: + Test() {} + ~Test() {} +public slots: + void receive() {} +signals: + void send(); +}; +EOF + + cat > bnv_qt_main.$ac_ext << EOF +#include "bnv_qt_test.h" +#include +int main( int argc, char **argv ) +{ + QApplication app( argc, argv ); + Test t; + QObject::connect( &t, SIGNAL(send()), &t, SLOT(receive()) ); +} +EOF + + bnv_cv_qt_test_result="failure" + bnv_try_1="$QT_MOC bnv_qt_test.h -o moc_bnv_qt_test.$ac_ext >/dev/null 2>bnv_qt_test_1.out" + AC_TRY_EVAL(bnv_try_1) + bnv_err_1=`grep -v '^ *+' bnv_qt_test_1.out | grep -v "^bnv_qt_test.h\$"` + if test x"$bnv_err_1" != x; then + echo "$bnv_err_1" >&AC_FD_CC + echo "configure: could not run $QT_MOC on:" >&AC_FD_CC + cat bnv_qt_test.h >&AC_FD_CC + else + bnv_try_2="$CXX $QT_CXXFLAGS -c $CXXFLAGS -o moc_bnv_qt_test.o moc_bnv_qt_test.$ac_ext >/dev/null 2>bnv_qt_test_2.out" + AC_TRY_EVAL(bnv_try_2) + bnv_err_2=`grep -v '^ *+' bnv_qt_test_2.out | grep -v "^bnv_qt_test.{$ac_ext}\$"` + if test x"$bnv_err_2" != x; then + echo "$bnv_err_2" >&AC_FD_CC + echo "configure: could not compile:" >&AC_FD_CC + cat bnv_qt_test.$ac_ext >&AC_FD_CC + else + bnv_try_3="$CXX $QT_CXXFLAGS -c $CXXFLAGS -o bnv_qt_main.o bnv_qt_main.$ac_ext >/dev/null 2>bnv_qt_test_3.out" + AC_TRY_EVAL(bnv_try_3) + bnv_err_3=`grep -v '^ *+' bnv_qt_test_3.out | grep -v "^bnv_qt_main.{$ac_ext}\$"` + if test x"$bnv_err_3" != x; then + echo "$bnv_err_3" >&AC_FD_CC + echo "configure: could not compile:" >&AC_FD_CC + cat bnv_qt_main.$ac_ext >&AC_FD_CC + else + bnv_try_4="$CXX $QT_LIBS $LIBS -o bnv_qt_main bnv_qt_main.o moc_bnv_qt_test.o >/dev/null 2>bnv_qt_test_4.out" + AC_TRY_EVAL(bnv_try_4) + bnv_err_4=`grep -v '^ *+' bnv_qt_test_4.out` + if test x"$bnv_err_4" != x; then + echo "$bnv_err_4" >&AC_FD_CC + else + bnv_cv_qt_test_result="success" + fi + fi + fi + fi + ])dnl AC_CACHE_VAL bnv_cv_qt_test_result + AC_MSG_RESULT([$bnv_cv_qt_test_result]); + if test x"$bnv_cv_qt_test_result" = "xfailure"; then + # working Qt was not found + QT_CXXFLAGS= + QT_DIR= + QT_LIBS= + QT_UIC= + QT_MOC= + have_qt=no + AC_MSG_WARN([Failed to find matching components of a complete + Qt installation. Try using more options, + see ./configure --help.]) + fi + + rm -f bnv_qt_test.h moc_bnv_qt_test.$ac_ext moc_bnv_qt_test.o \ + bnv_qt_main.$ac_ext bnv_qt_main.o bnv_qt_main \ + bnv_qt_test_1.out bnv_qt_test_2.out bnv_qt_test_3.out bnv_qt_test_4.out + fi +]) + +dnl Internal subroutine of BNV_HAVE_QT +dnl Set bnv_qt_dir bnv_qt_include_dir bnv_qt_bin_dir bnv_qt_lib_dir bnv_qt_lib +dnl Copyright 2001 Bastiaan N. Veelo +AC_DEFUN([BNV_PATH_QT_DIRECT], +[ + ## Binary utilities ## + if test x"$with_Qt_bin_dir" != x; then + bnv_qt_bin_dir=$with_Qt_bin_dir + fi + ## Look for header files ## + if test x"$with_Qt_include_dir" != x; then + bnv_qt_include_dir="$with_Qt_include_dir" + else + # The following header file is expected to define QT_VERSION. + qt_direct_test_header=qglobal.h + # Look for the header file in a standard set of common directories. + bnv_include_path_list=" + /usr/include + `ls -dr /usr/include/qt* 2>/dev/null` + `ls -dr /usr/lib/qt*/include 2>/dev/null` + `ls -dr /usr/local/qt*/include 2>/dev/null` + `ls -dr /opt/qt*/include 2>/dev/null` + " + for bnv_dir in $bnv_include_path_list; do + if test -r "$bnv_dir/$qt_direct_test_header"; then + bnv_dirs="$bnv_dirs $bnv_dir" + fi + done + # Now look for the newest in this list + bnv_prev_ver=0 + for bnv_dir in $bnv_dirs; do + bnv_this_ver=`egrep -w '#define QT_VERSION' $bnv_dir/$qt_direct_test_header | sed s/'#define QT_VERSION'//` + if expr $bnv_this_ver '>' $bnv_prev_ver > /dev/null; then + bnv_qt_include_dir=$bnv_dir + bnv_prev_ver=$bnv_this_ver + fi + done + fi dnl Found header files. + + # Are these headers located in a traditional Trolltech installation? + # That would be $bnv_qt_include_dir stripped from its last element: + bnv_possible_qt_dir=`dirname $bnv_qt_include_dir` + if test -x $bnv_possible_qt_dir/bin/moc && + ls $bnv_possible_qt_dir/lib/libqt* > /dev/null; then + # Then the rest is a piece of cake + bnv_qt_dir=$bnv_possible_qt_dir + bnv_qt_bin_dir="$bnv_qt_dir/bin" + bnv_qt_lib_dir="$bnv_qt_dir/lib" + # Only look for lib if the user did not supply it already + if test x"$bnv_qt_lib" = xNO; then + bnv_qt_lib="`ls $bnv_qt_lib_dir/libqt* | sed -n 1p | + sed s@$bnv_qt_lib_dir/lib@@ | [sed s@[.].*@@]`" + fi + bnv_qt_LIBS="-L$bnv_qt_lib_dir -l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS" + else + # There is no valid definition for $QTDIR as Trolltech likes to see it + bnv_qt_dir= + ## Look for Qt library ## + if test x"$with_Qt_lib_dir" != x; then + bnv_qt_lib_dir="$with_Qt_lib_dir" + # Only look for lib if the user did not supply it already + if test x"$bnv_qt_lib" = xNO; then + bnv_qt_lib="`ls $bnv_qt_lib_dir/libqt* | sed -n 1p | + sed s@$bnv_qt_lib_dir/lib@@ | [sed s@[.].*@@]`" + fi + bnv_qt_LIBS="-L$bnv_qt_lib_dir -l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS" + else + # Normally, when there is no traditional Trolltech installation, + # the library is installed in a place where the linker finds it + # automatically. + # If the user did not define the library name, try with qt + if test x"$bnv_qt_lib" = xNO; then + bnv_qt_lib=qt + fi + qt_direct_test_header=qapplication.h + qt_direct_test_main=" + int argc; + char ** argv; + QApplication app(argc,argv); + " + # See if we find the library without any special options. + # Don't add top $LIBS permanently yet + bnv_save_LIBS="$LIBS" + LIBS="-l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS" + bnv_qt_LIBS="$LIBS" + bnv_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="-I$bnv_qt_include_dir" + AC_TRY_LINK([#include <$qt_direct_test_header>], + $qt_direct_test_main, + [ + # Success. + # We can link with no special library directory. + bnv_qt_lib_dir= + ], [ + # That did not work. Try the multi-threaded version + echo "Non-critical error, please neglect the above." >&AC_FD_CC + bnv_qt_lib=qt-mt + LIBS="-l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS" + AC_TRY_LINK([#include <$qt_direct_test_header>], + $qt_direct_test_main, + [ + # Success. + # We can link with no special library directory. + bnv_qt_lib_dir= + ], [ + # That did not work. Try the OpenGL version + echo "Non-critical error, please neglect the above." >&AC_FD_CC + bnv_qt_lib=qt-gl + LIBS="-l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS" + AC_TRY_LINK([#include <$qt_direct_test_header>], + $qt_direct_test_main, + [ + # Succes. + # We can link with no special library directory. + bnv_qt_lib_dir= + ], [ + # That did not work. Maybe a library version I don't know about? + echo "Non-critical error, please neglect the above." >&AC_FD_CC + # Look for some Qt lib in a standard set of common directories. + bnv_dir_list=" + `echo $bnv_qt_includes | sed ss/includess` + /lib + /usr/lib + /usr/local/lib + /opt/lib + `ls -dr /usr/lib/qt* 2>/dev/null` + `ls -dr /usr/local/qt* 2>/dev/null` + `ls -dr /opt/qt* 2>/dev/null` + " + for bnv_dir in $bnv_dir_list; do + if ls $bnv_dir/libqt*; then + # Gamble that it's the first one... + bnv_qt_lib="`ls $bnv_dir/libqt* | sed -n 1p | + sed s@$bnv_dir/lib@@ | sed s/[.].*//`" + bnv_qt_lib_dir="$bnv_dir" + break + fi + done + # Try with that one + LIBS="-l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS" + AC_TRY_LINK([#include <$qt_direct_test_header>], + $qt_direct_test_main, + [ + # Succes. + # We can link with no special library directory. + bnv_qt_lib_dir= + ], [ + # Leave bnv_qt_lib_dir defined + ]) + ]) + ]) + ]) + if test x"$bnv_qt_lib_dir" != x; then + bnv_qt_LIBS="-l$bnv_qt_lib_dir $LIBS" + else + bnv_qt_LIBS="$LIBS" + fi + LIBS="$bnv_save_LIBS" + CXXFLAGS="$bnv_save_CXXFLAGS" + fi dnl $with_Qt_lib_dir was not given + fi dnl Done setting up for non-traditional Trolltech installation +]) diff --git a/config/cppunit.m4 b/config/cppunit.m4 new file mode 100644 index 00000000..0991d51e --- /dev/null +++ b/config/cppunit.m4 @@ -0,0 +1,80 @@ +dnl +dnl AM_PATH_CPPUNIT(MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) +dnl +AC_DEFUN([AM_PATH_CPPUNIT], +[ + +AC_ARG_WITH(cppunit-prefix,[ --with-cppunit-prefix=PFX Prefix where CppUnit is installed (optional)], + cppunit_config_prefix="$withval", cppunit_config_prefix="") +AC_ARG_WITH(cppunit-exec-prefix,[ --with-cppunit-exec-prefix=PFX Exec prefix where CppUnit is installed (optional)], + cppunit_config_exec_prefix="$withval", cppunit_config_exec_prefix="") + + if test x$cppunit_config_exec_prefix != x ; then + cppunit_config_args="$cppunit_config_args --exec-prefix=$cppunit_config_exec_prefix" + if test x${CPPUNIT_CONFIG+set} != xset ; then + CPPUNIT_CONFIG=$cppunit_config_exec_prefix/bin/cppunit-config + fi + fi + if test x$cppunit_config_prefix != x ; then + cppunit_config_args="$cppunit_config_args --prefix=$cppunit_config_prefix" + if test x${CPPUNIT_CONFIG+set} != xset ; then + CPPUNIT_CONFIG=$cppunit_config_prefix/bin/cppunit-config + fi + fi + + AC_PATH_PROG(CPPUNIT_CONFIG, cppunit-config, no) + cppunit_version_min=$1 + + AC_MSG_CHECKING(for Cppunit - version >= $cppunit_version_min) + no_cppunit="" + if test "$CPPUNIT_CONFIG" = "no" ; then + no_cppunit=yes + else + CPPUNIT_CFLAGS=`$CPPUNIT_CONFIG --cflags` + CPPUNIT_LIBS=`$CPPUNIT_CONFIG --libs` + cppunit_version=`$CPPUNIT_CONFIG --version` + + cppunit_major_version=`echo $cppunit_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + cppunit_minor_version=`echo $cppunit_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + cppunit_micro_version=`echo $cppunit_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + + cppunit_major_min=`echo $cppunit_version_min | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + cppunit_minor_min=`echo $cppunit_version_min | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + cppunit_micro_min=`echo $cppunit_version_min | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + + cppunit_version_proper=`expr \ + $cppunit_major_version \> $cppunit_major_min \| \ + $cppunit_major_version \= $cppunit_major_min \& \ + $cppunit_minor_version \> $cppunit_minor_min \| \ + $cppunit_major_version \= $cppunit_major_min \& \ + $cppunit_minor_version \= $cppunit_minor_min \& \ + $cppunit_micro_version \>= $cppunit_micro_min ` + + if test "$cppunit_version_proper" = "1" ; then + AC_MSG_RESULT([$cppunit_major_version.$cppunit_minor_version.$cppunit_micro_version]) + else + AC_MSG_RESULT(no) + no_cppunit=yes + fi + fi + + if test "x$no_cppunit" = x ; then + ifelse([$2], , :, [$2]) + else + CPPUNIT_CFLAGS="" + CPPUNIT_LIBS="" + ifelse([$3], , :, [$3]) + fi + + AC_SUBST(CPPUNIT_CFLAGS) + AC_SUBST(CPPUNIT_LIBS) +]) + + + diff --git a/config/gr_as.m4 b/config/gr_as.m4 new file mode 100644 index 00000000..a0695473 --- /dev/null +++ b/config/gr_as.m4 @@ -0,0 +1,34 @@ +# Figure out how to run the assembler. -*- Autoconf -*- + +# serial 2 + +# Copyright 2001 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, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# I just copy and renamed this from automake-1.6.3 so we should work +# under both 1.4-p6 and later. -eb + +# GR_PROG_AS +# ---------- +AC_DEFUN([GR_PROG_AS], +[# By default we simply use the C compiler to build assembly code. +AC_REQUIRE([AC_PROG_CC]) +: ${CCAS='$(CC)'} +# Set ASFLAGS if not already set. +: ${CCASFLAGS='$(CFLAGS)'} +AC_SUBST(CCAS) +AC_SUBST(CCASFLAGS)]) diff --git a/config/gr_atsc.m4 b/config/gr_atsc.m4 new file mode 100644 index 00000000..e409667a --- /dev/null +++ b/config/gr_atsc.m4 @@ -0,0 +1,36 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_ATSC],[ + AC_CONFIG_SRCDIR([gr-atsc/src/lib/atsc.i]) + + AC_CONFIG_FILES([\ + gr-atsc/Makefile \ + gr-atsc/doc/Makefile \ + gr-atsc/src/Makefile \ + gr-atsc/src/lib/Makefile \ + gr-atsc/src/python/Makefile \ + gr-atsc/src/python/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_atsc], [chmod +x gr-atsc/src/python/run_tests]) + + subdirs="$subdirs gr-atsc" +]) diff --git a/config/gr_audio_alsa.m4 b/config/gr_audio_alsa.m4 new file mode 100644 index 00000000..2675ec9c --- /dev/null +++ b/config/gr_audio_alsa.m4 @@ -0,0 +1,41 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_AUDIO_ALSA],[ + AC_CONFIG_SRCDIR([gr-audio-alsa/src/audio_alsa.i]) + + succeeded=yes + PKG_CHECK_MODULES(ALSA, alsa >= 0.9,[],[succeeded=no]) + if test $succeeded = yes; then + LIBS="$LIBS $ALSA_LIBS" + + AC_CONFIG_FILES([\ + gr-audio-alsa/Makefile \ + gr-audio-alsa/src/Makefile \ + gr-audio-alsa/src/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_alsa], [chmod +x gr-audio-alsa/src/run_tests]) + subdirs="$subdirs gr-audio-alsa" + else + AC_MSG_RESULT([failed: $ALSA_PKG_ERRORS]) + failed="$failed gr-audio-alsa" + fi +]) diff --git a/config/gr_audio_jack.m4 b/config/gr_audio_jack.m4 new file mode 100644 index 00000000..628ce034 --- /dev/null +++ b/config/gr_audio_jack.m4 @@ -0,0 +1,41 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_AUDIO_JACK],[ + AC_CONFIG_SRCDIR([gr-audio-jack/src/audio_jack.i]) + + succeeded=yes + PKG_CHECK_MODULES(JACK, jack >= 0.8,[],[succeeded=no]) + if test $succeeded = yes; then + LIBS="$LIBS $JACK_LIBS" + + AC_CONFIG_FILES([\ + gr-audio-jack/Makefile \ + gr-audio-jack/src/Makefile \ + gr-audio-jack/src/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_jack], [chmod +x gr-audio-jack/src/run_tests]) + subdirs="$subdirs gr-audio-jack" + else + AC_MSG_RESULT([failed: $JACK_PKG_ERRORS]) + failed="$failed gr-audio-jack" + fi +]) diff --git a/config/gr_audio_oss.m4 b/config/gr_audio_oss.m4 new file mode 100644 index 00000000..c8dfebeb --- /dev/null +++ b/config/gr_audio_oss.m4 @@ -0,0 +1,45 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_AUDIO_OSS],[ + AC_CONFIG_SRCDIR([gr-audio-oss/src/audio_oss.i]) + + succeeded=yes + + dnl needed for NetBSD + dnl FIXME: conditionalize on NetBSD platform + dnl AC_HAVE_LIBRARY(ossaudio,[],[succeeded=no]) + + AC_CHECK_HEADER(sys/soundcard.h,[],[succeeded=no]) + if test $succeeded = yes; then + + AC_CONFIG_FILES([\ + gr-audio-oss/Makefile \ + gr-audio-oss/src/Makefile \ + gr-audio-oss/src/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_oss], [chmod +x gr-audio-oss/src/run_tests]) + subdirs="$subdirs gr-audio-oss" + else + AC_MSG_RESULT([failed: $OSS_PKG_ERRORS]) + failed="$failed gr-audio-oss" + fi +]) diff --git a/config/gr_audio_osx.m4 b/config/gr_audio_osx.m4 new file mode 100644 index 00000000..2ddb4b38 --- /dev/null +++ b/config/gr_audio_osx.m4 @@ -0,0 +1,38 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_AUDIO_OSX],[ + AC_CONFIG_SRCDIR([gr-audio-osx/src/audio_osx.i]) + + succeeded=yes + MACOSX_AUDIOUNIT([],[succeeded=no]) + if test $succeeded = yes; then + AC_CONFIG_FILES([\ + gr-audio-osx/Makefile \ + gr-audio-osx/src/Makefile \ + gr-audio-osx/src/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_osx], [chmod +x gr-audio-osx/src/run_tests]) + subdirs="$subdirs gr-audio-osx" + else + failed="$failed gr-audio-osx" + fi +]) diff --git a/config/gr_audio_portaudio.m4 b/config/gr_audio_portaudio.m4 new file mode 100644 index 00000000..2ad3719c --- /dev/null +++ b/config/gr_audio_portaudio.m4 @@ -0,0 +1,43 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_AUDIO_PORTAUDIO],[ + AC_CONFIG_SRCDIR([gr-audio-portaudio/src/audio_portaudio.i]) + + succeeded=yes + #PKG_CHECK_MODULES(PORTAUDIO, portaudio-2.0 >= 19,[],[succeeded=no]) + AC_HAVE_LIBRARY([portaudio], [], [succeeded=no]) + AC_CHECK_HEADER([portaudio.h], [], [succeeded=no]) + if test $succeeded = yes; then + LIBS="$LIBS -lportaudio" + + AC_CONFIG_FILES([\ + gr-audio-portaudio/Makefile \ + gr-audio-portaudio/src/Makefile \ + gr-audio-portaudio/src/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_portaudio], [chmod +x gr-audio-portaudio/src/run_tests]) + subdirs="$subdirs gr-audio-portaudio" + else + AC_MSG_RESULT([failed: $PORTAUDIO_PKG_ERRORS]) + failed="$failed gr-audio-portaudio" + fi +]) diff --git a/config/gr_audio_windows.m4 b/config/gr_audio_windows.m4 new file mode 100644 index 00000000..d0a445e9 --- /dev/null +++ b/config/gr_audio_windows.m4 @@ -0,0 +1,39 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_AUDIO_WINDOWS],[ + AC_CONFIG_SRCDIR([gr-audio-windows/src/audio_windows.i]) + + succeeded=yes + AC_HAVE_LIBRARY(winmm,[],[succeeded=no]) + + if test $succeeded = yes; then + AC_CONFIG_FILES([\ + gr-audio-windows/Makefile \ + gr-audio-windows/src/Makefile \ + gr-audio-windows/src/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_windows], [chmod +x gr-audio-windows/src/run_tests]) + subdirs="$subdirs gr-audio-windows" + else + failed="$failed gr-audio-windows" + fi +]) diff --git a/config/gr_boost.m4 b/config/gr_boost.m4 new file mode 100644 index 00000000..b1751c06 --- /dev/null +++ b/config/gr_boost.m4 @@ -0,0 +1,111 @@ +dnl +dnl Copyright 2004,2005 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +dnl This tries to do the "right thing" to locate the boost include files. +dnl If the user explicitly specified --with-boost-include-dir= +dnl we believe them and use it. Otherwise, +dnl +dnl We look for boost/shared_ptr.hpp in the "normal places". That is, +dnl wherever AC_CHECK_HEADER looks. If the boost includes are in /usr/local/include +dnl this step will find them. +dnl +dnl Otherwise, we check to see if the boost stuff was installed in a version-specific +dnl directory under /usr/local/include. These look like: /usr/local/include/boost-1_33_1 +dnl If there's more than one version installed, we select the +dnl lexicographically greatest one. +dnl +dnl If none of these work, we bail. + +AC_DEFUN([GR_REQUIRE_BOOST_INCLUDES], +[ + AC_LANG_PUSH(C++) + gr_boost_include_dir= + AC_ARG_WITH([boost-include-dir], + AC_HELP_STRING([--with-boost-include-dir=], + [path to boost c++ include files]), + [ + # "yes" and "no" are bogus answers + if test x"$with_boost_include_dir" == xyes || + test x"$with_boost_include_dir" == xno; then + gr_boost_include_dir= + else + gr_boost_include_dir=$with_boost_include_dir + fi + ]) + echo "gr_boost_include_dir = $gr_boost_include_dir" + if test x$gr_boost_include_dir != x; then + # + # If the user specified a directory, then we use it + # + OLD_CPPFLAGS=$CPPFLAGS + CPPFLAGS="$CPPFLAGS -I$gr_boost_include_dir" + AC_CHECK_HEADER([boost/shared_ptr.hpp], + [BOOST_CFLAGS="-I$gr_boost_include_dir"], + [AC_MSG_ERROR( + [Failed to locate boost/shared_ptr.hpp. +Try using --with-boost-include-dir=, +E.g., --with-boost-include-dir=/usr/local/include/boost-1_33_1])]) + CPPFLAGS=$OLD_CPPFLAGS + else + # + # Otherwise we check in the default places + # + AC_CHECK_HEADER([boost/shared_ptr.hpp], + [BOOST_CFLAGS=""], + [ # Nope, look for latest version if any in $prefix/include/boost-* + + # Wipe out cached value. KLUDGE: AC should have API for this + unset AS_TR_SH([ac_cv_header_boost/shared_ptr.hpp]) + + boost_last_match(){ + #echo "boost_last_match: [$]*" + pattern="[$]1" + shift + if test "[$]pattern" = "[$]1" + then + LM='' + else + shift `expr [$]# - 1` + LM=[$]1 + fi + #echo "LM(1)='[$]LM'" + } + + pattern="/usr/local/include/boost-*" + boost_last_match "$pattern" $pattern + #echo "LM(2)='$LM'" + + OLD_CPPFLAGS=$CPP_FLAGS + CPPFLAGS="$CPPFLAGS -I$LM" + AC_CHECK_HEADER([boost/shared_ptr.hpp], + [BOOST_CFLAGS="-I$LM"], + [AC_MSG_ERROR( + [Failed to locate boost/shared_ptr.hpp. +Try using --with-boost-include-dir=, +E.g., --with-boost-include-dir=/usr/local/include/boost-1_33_1])]) + CPPFLAGS=$OLD_CPPFLAGS + ]) + + fi + unset boost_last_match LM + AC_LANG_POP + AC_SUBST(BOOST_CFLAGS) +]) diff --git a/config/gr_check_createfilemapping.m4 b/config/gr_check_createfilemapping.m4 new file mode 100644 index 00000000..9cb94f57 --- /dev/null +++ b/config/gr_check_createfilemapping.m4 @@ -0,0 +1,52 @@ +dnl +dnl Copyright 2005 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +dnl AC_DEFUN([GR_CHECK_CREATEFILEMAPPING], +dnl [ +dnl AC_CHECK_FUNCS([CreateFileMapping]) +dnl ]) + +AC_DEFUN([GR_CHECK_CREATEFILEMAPPING],[ + AC_MSG_CHECKING([for CreateFileMapping function]) + AC_COMPILE_IFELSE([ +#include +int main (int argc, char **argv) +{ + HANDLE handle; + int size; + char seg_name[[1024]]; + 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 + return 0; +} +],[HAVE_CREATEFILEMAPPING=yes + AC_DEFINE(HAVE_CREATEFILEMAPPING,[1],[Define if you have the CreateFilemapping function(win32).])], + [HAVE_CREATEFILEMAPPING=no]) + + AC_MSG_RESULT($HAVE_CREATEFILEMAPPING) + AM_CONDITIONAL(HAVE_CREATEFILEMAPPING, test x$HAVE_CREATEFILEMAPPING = xyes) +]) + + diff --git a/config/gr_check_mc4020.m4 b/config/gr_check_mc4020.m4 new file mode 100644 index 00000000..0c4318ef --- /dev/null +++ b/config/gr_check_mc4020.m4 @@ -0,0 +1,37 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +AC_DEFUN([GR_CHECK_MC4020],[ + AC_MSG_CHECKING([for mc4020 A/D driver include file]) + AC_COMPILE_IFELSE([ +#include +int main (int argc, char **argv) +{ + return 0; +} +],[HAVE_MC4020=yes + AC_DEFINE(HAVE_MC4020,[1],[Define if you have a Measurement Computing PCI-DAS4020/12 A/D])], + [HAVE_MC4020=no]) + + AC_MSG_RESULT($HAVE_MC4020) + AM_CONDITIONAL(HAVE_MC4020, test x$HAVE_MC4020 = xyes) +]) + diff --git a/config/gr_check_shm_open.m4 b/config/gr_check_shm_open.m4 new file mode 100644 index 00000000..27c9ee6c --- /dev/null +++ b/config/gr_check_shm_open.m4 @@ -0,0 +1,29 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_CHECK_SHM_OPEN], +[ + SHM_OPEN_LIBS="" + save_LIBS="$LIBS" + AC_SEARCH_LIBS([shm_open], [rt], [SHM_OPEN_LIBS="$LIBS"]) + AC_CHECK_FUNCS([shm_open]) + LIBS="$save_LIBS" + AC_SUBST(SHM_OPEN_LIBS) +]) diff --git a/config/gr_check_usrp.m4 b/config/gr_check_usrp.m4 new file mode 100644 index 00000000..b818a690 --- /dev/null +++ b/config/gr_check_usrp.m4 @@ -0,0 +1,32 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +dnl Check for Universal Software Radio Peripheral + +AC_DEFUN([GR_CHECK_USRP],[ + PKG_CHECK_MODULES(USRP, usrp >= 0.2, + [HAVE_USRP=yes + AC_DEFINE(HAVE_USRP,[1],[Define if you have a USRP])], + [HAVE_USRP=no]) + + AM_CONDITIONAL(HAVE_USRP, test x$HAVE_USRP = xyes) +]) + diff --git a/config/gr_comedi.m4 b/config/gr_comedi.m4 new file mode 100644 index 00000000..89ee30fd --- /dev/null +++ b/config/gr_comedi.m4 @@ -0,0 +1,41 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_COMEDI],[ + AC_CONFIG_SRCDIR([gr-comedi/src/comedi.i]) + + succeeded=yes + PKG_CHECK_MODULES(COMEDI, comedilib >= 0.7,[],[succeeded=no]) + if test $succeeded = yes; then + LIBS="$LIBS $COMEDI_LIBS" + + AC_CONFIG_FILES([\ + gr-comedi/Makefile \ + gr-comedi/src/Makefile \ + gr-comedi/src/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_comedi], [chmod +x gr-comedi/src/run_tests]) + subdirs="$subdirs gr-comedi" + else + AC_MSG_WARN([$COMEDI_PKG_ERRORS]) + failed="$failed gr-comedi" + fi +]) diff --git a/config/gr_doxygen.m4 b/config/gr_doxygen.m4 new file mode 100644 index 00000000..82aea350 --- /dev/null +++ b/config/gr_doxygen.m4 @@ -0,0 +1,59 @@ +dnl +dnl Copyright 2003,2005 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +AC_DEFUN([GR_CHECK_DOXYGEN],[ + AC_ARG_ENABLE(doxygen, [ --enable-doxygen enable documentation generation with doxygen (no)]) + AC_ARG_ENABLE(dot, [ --enable-dot use 'dot' to generate graphs in doxygen (auto)]) + AC_ARG_ENABLE(html-docs, [ --enable-html-docs enable HTML generation with doxygen (yes)], [], [ enable_html_docs=yes]) + AC_ARG_ENABLE(latex-docs, [ --enable-latex-docs enable LaTeX doc generation with doxygen (no)], [], [ enable_latex_docs=no]) + + if test "x$enable_doxygen" = xyes; then + AC_PATH_PROG(DOXYGEN, doxygen, , $PATH) + if test x$DOXYGEN = x; then + if test "x$enable_doxygen" = xyes; then + AC_MSG_ERROR([could not find doxygen]) + fi + enable_doc=no + generate_docs= + else + enable_doc=yes + generate_docs=docs + AC_PATH_PROG(DOT, dot, , $PATH) + fi + else + enable_doc=no + fi + + AM_CONDITIONAL(DOC, test x$enable_doc = xyes) + + if test x$DOT = x; then + if test "x$enable_dot" = xyes; then + AC_MSG_ERROR([could not find dot]) + fi + enable_dot=no + else + enable_dot=yes + fi + AC_SUBST(enable_dot) + AC_SUBST(enable_html_docs) + AC_SUBST(enable_latex_docs) + AC_SUBST(generate_docs) +]) diff --git a/config/gr_error_correcting_codes.m4 b/config/gr_error_correcting_codes.m4 new file mode 100644 index 00000000..84d5560e --- /dev/null +++ b/config/gr_error_correcting_codes.m4 @@ -0,0 +1,38 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_ERROR_CORRECTING_CODES],[ + AC_CONFIG_SRCDIR([gr-error-correcting-codes/src/lib/ecc.i]) + + AC_CONFIG_FILES([\ + gr-error-correcting-codes/Makefile \ + gr-error-correcting-codes/src/Makefile \ + gr-error-correcting-codes/src/lib/Makefile \ + gr-error-correcting-codes/src/lib/libecc/Makefile \ + gr-error-correcting-codes/src/lib/libecc/mld/Makefile \ + gr-error-correcting-codes/src/lib/libecc/tests/Makefile \ + gr-error-correcting-codes/src/python/Makefile \ + gr-error-correcting-codes/src/python/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_error_correcting_codes], [chmod +x gr-error-correcting-codes/src/python/run_tests]) + + subdirs="$subdirs gr-error-correcting-codes" +]) diff --git a/config/gr_fortran.m4 b/config/gr_fortran.m4 new file mode 100644 index 00000000..345936fa --- /dev/null +++ b/config/gr_fortran.m4 @@ -0,0 +1,31 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_FORTRAN],[ + dnl if you want to generate a different table of interpolator taps, you need fortran. + dnl we default to off, since almost no one wants to do this. + AC_ARG_ENABLE(fortran, [ --enable-fortran enable fortran (no)], [], [enable_fortran=no]) + AM_CONDITIONAL(ENABLE_FORTRAN, test "x$enable_fortran" = xyes) + + if test "x$enable_fortran" = xyes + then + AC_PROG_F77 + AC_F77_LIBRARY_LDFLAGS + fi +]) diff --git a/config/gr_gnuradio_core.m4 b/config/gr_gnuradio_core.m4 new file mode 100644 index 00000000..661555ea --- /dev/null +++ b/config/gr_gnuradio_core.m4 @@ -0,0 +1,63 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_GNURADIO_CORE],[ + AC_CONFIG_SRCDIR([gnuradio-core/src/lib/runtime/gr_vmcircbuf.cc]) + + AC_CONFIG_FILES([ \ + gnuradio-core/Makefile + gnuradio-core/gnuradio-core.pc \ + gnuradio-core/doc/Doxyfile \ + gnuradio-core/doc/Makefile \ + gnuradio-core/doc/other/Makefile \ + gnuradio-core/doc/xml/Makefile \ + gnuradio-core/src/Makefile \ + gnuradio-core/src/gen_interpolator_taps/Makefile \ + gnuradio-core/src/lib/Makefile \ + gnuradio-core/src/lib/filter/Makefile \ + gnuradio-core/src/lib/g72x/Makefile \ + gnuradio-core/src/lib/general/Makefile \ + gnuradio-core/src/lib/general/gr_prefix.cc \ + gnuradio-core/src/lib/io/Makefile \ + gnuradio-core/src/lib/missing/Makefile \ + gnuradio-core/src/lib/omnithread/Makefile \ + gnuradio-core/src/lib/reed-solomon/Makefile \ + gnuradio-core/src/lib/runtime/Makefile \ + gnuradio-core/src/lib/swig/Makefile \ + gnuradio-core/src/python/Makefile \ + gnuradio-core/src/python/bin/Makefile \ + gnuradio-core/src/python/gnuradio/Makefile \ + gnuradio-core/src/python/gnuradio/blks/Makefile \ + gnuradio-core/src/python/gnuradio/blksimpl/Makefile \ + gnuradio-core/src/python/gnuradio/gr/Makefile \ + gnuradio-core/src/python/gnuradio/gr/run_tests \ + gnuradio-core/src/python/gnuradio/gru/Makefile \ + gnuradio-core/src/python/gnuradio/gruimpl/Makefile \ + gnuradio-core/src/tests/Makefile \ + gnuradio-core/src/utils/Makefile \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_core], [chmod +x gnuradio-core/src/python/gnuradio/gr/run_tests]) + + dnl kludge up initial swig dependency file + AC_CONFIG_COMMANDS([swig_deps], [touch gnuradio-core/src/lib/swig/gnuradio_swig_python.d]) + + subdirs="$subdirs gnuradio-core" +]) diff --git a/config/gr_gnuradio_examples.m4 b/config/gr_gnuradio_examples.m4 new file mode 100644 index 00000000..6ab51a20 --- /dev/null +++ b/config/gr_gnuradio_examples.m4 @@ -0,0 +1,35 @@ +# Copyright 2001,2002,2003,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. + +AC_DEFUN([GR_GNURADIO_EXAMPLES],[ + AC_CONFIG_SRCDIR([gnuradio-examples/README]) + + AC_CONFIG_FILES([\ + gnuradio-examples/Makefile \ + gnuradio-examples/python/Makefile \ + gnuradio-examples/python/audio/Makefile \ + gnuradio-examples/python/digital_voice/Makefile \ + gnuradio-examples/python/gmsk2/Makefile \ + gnuradio-examples/python/mc4020/Makefile \ + gnuradio-examples/python/usrp/Makefile \ + gnuradio-examples/python/multi_usrp/Makefile \ + ]) + + subdirs="$subdirs gnuradio-examples" +]) diff --git a/config/gr_gprof.m4 b/config/gr_gprof.m4 new file mode 100644 index 00000000..cc505088 --- /dev/null +++ b/config/gr_gprof.m4 @@ -0,0 +1,72 @@ +dnl +dnl Copyright 2002 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +dnl FIXME probably need to add linker flag too... + +AC_DEFUN([GR_SET_GPROF],[ + dnl Check for --with-gprof + AC_MSG_CHECKING([whether user wants gprof]) + AC_ARG_WITH(gprof, + [ --with-gprof Turn on gprof profiling], + [], [ with_gprof=no ]) + AC_MSG_RESULT($with_gprof) + + dnl gprof profiling flags for the two main compilers + cc_profiling_flags="-pg" + cxx_profiling_flags="-pg" + ld_profiling_flags="-pg" + if test $with_gprof = yes + then + if test -n "${CC}" + then + LF_CHECK_CC_FLAG($cc_profiling_flags) + fi + if test -n "${CXX}" + then + LF_CHECK_CXX_FLAG($cxx_profiling_flags) + fi + fi +]) + +AC_DEFUN([GR_SET_PROF],[ + dnl Check for --with-prof + AC_MSG_CHECKING([whether user wants prof]) + AC_ARG_WITH(prof, + [ --with-prof Turn on prof profiling], + [], [ with_prof=no ]) + AC_MSG_RESULT($with_prof) + + dnl prof profiling flags for the two main compilers + cc_profiling_flags="-p" + cxx_profiling_flags="-p" + ld_profiling_flags="-p" + if test $with_prof = yes + then + if test -n "${CC}" + then + LF_CHECK_CC_FLAG($cc_profiling_flags) + fi + if test -n "${CXX}" + then + LF_CHECK_CXX_FLAG($cxx_profiling_flags) + fi + fi +]) diff --git a/config/gr_gsm_fr_vocoder.m4 b/config/gr_gsm_fr_vocoder.m4 new file mode 100644 index 00000000..97408e9d --- /dev/null +++ b/config/gr_gsm_fr_vocoder.m4 @@ -0,0 +1,36 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_GSM_FR_VOCODER],[ + AC_CONFIG_SRCDIR([gr-gsm-fr-vocoder/src/lib/gsm_full_rate.i]) + + AC_CONFIG_FILES([\ + gr-gsm-fr-vocoder/Makefile \ + gr-gsm-fr-vocoder/src/Makefile \ + gr-gsm-fr-vocoder/src/lib/Makefile \ + gr-gsm-fr-vocoder/src/lib/gsm/Makefile \ + gr-gsm-fr-vocoder/src/python/Makefile \ + gr-gsm-fr-vocoder/src/python/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_gsm], [chmod +x gr-gsm-fr-vocoder/src/python/run_tests]) + + subdirs="$subdirs gr-gsm-fr-vocoder" +]) diff --git a/config/gr_libgnuradio_core_extra_ldflags.m4 b/config/gr_libgnuradio_core_extra_ldflags.m4 new file mode 100644 index 00000000..491f7a04 --- /dev/null +++ b/config/gr_libgnuradio_core_extra_ldflags.m4 @@ -0,0 +1,40 @@ +# Check for (MinGW)win32 extra ld options. -*- Autoconf -*- + +# 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. + +dnl +AC_DEFUN([GR_LIBGNURADIO_CORE_EXTRA_LDFLAGS], [ +AC_REQUIRE([AC_PROG_LD]) +# on Mingw32 extra LDFLAGS are required to ease global variable linking +LIBGNURADIO_CORE_EXTRA_LDFLAGS="" + +AC_MSG_CHECKING([whether $LD accepts --enable-runtime-pseudo-reloc]) +if ${LD} --enable-runtime-pseudo-reloc --version >/dev/null 2>&1 +then + # libtool requires the quotes + LIBGNURADIO_CORE_EXTRA_LDFLAGS="\"-Wl,--enable-runtime-pseudo-reloc\"" + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) +fi + +AC_SUBST(LIBGNURADIO_CORE_EXTRA_LDFLAGS) + +]) diff --git a/config/gr_no_undefined.m4 b/config/gr_no_undefined.m4 new file mode 100644 index 00000000..8780fab3 --- /dev/null +++ b/config/gr_no_undefined.m4 @@ -0,0 +1,44 @@ +dnl +dnl Copyright 2005 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +# GR_NO_UNDEFINED() +# +# Detemine whether we need to use the -no-undefined linker flag +# when building shared libraries. +# Sets NO_UNDEFINED to "" or "-no-undefined" +# +# As far as I can tell, we need -no-undefined only when building +# windows DLLs. This occurs when using MinGW and Cygwin. +# +# For now, we stub this out. + +AC_DEFUN([GR_NO_UNDEFINED],[ + AC_REQUIRE([AC_CANONICAL_HOST]) + no_undefined="" + case "${host_os}" in + *mingw* | *cygwin*) + + # on MinGW/Cygwin extra LDFLAGS are required + no_undefined="-no-undefined" + ;; + esac + AC_SUBST(NO_UNDEFINED,[$no_undefined]) +]) diff --git a/config/gr_omnithread.m4 b/config/gr_omnithread.m4 new file mode 100644 index 00000000..7c3150ba --- /dev/null +++ b/config/gr_omnithread.m4 @@ -0,0 +1,51 @@ +# Check for Omnithread (pthread/NT) thread support. -*- Autoconf -*- + +# Copyright 2003 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, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +AC_DEFUN([GR_OMNITHREAD], +[ + # Check first for POSIX + ACX_PTHREAD( + [ ot_posix="yes" + AC_DEFINE(OMNITHREAD_POSIX,[1],[Define to 1 to enable pthread]) + ],[ + # If no POSIX support found, then check for NT threads + AC_MSG_CHECKING([for NT threads]) + + AC_LINK_IFELSE([ + #include + #include + int main() { InitializeCriticalSection(NULL); return 0; } + ], + [ + ot_nt="yes" + AC_DEFINE(OMNITHREAD_NT,[1],[Define to 1 to enable NT thread]) + ], + [AC_MSG_FAILURE([GNU Radio requires POSIX threads. pthreads not found.])] + ) + AC_MSG_RESULT(yes) + ]) + AM_CONDITIONAL(OMNITHREAD_POSIX, test "x$ot_posix" = xyes) + AM_CONDITIONAL(OMNITHREAD_NT, test "x$ot_nt" = xyes) + + save_LIBS="$LIBS" + AC_SEARCH_LIBS([clock_gettime], [rt], [PTHREAD_LIBS="$PTHREAD_LIBS $LIBS"]) + AC_CHECK_FUNCS([clock_gettime gettimeofday nanosleep]) + LIBS="$save_LIBS" +]) + diff --git a/config/gr_pmt.m4 b/config/gr_pmt.m4 new file mode 100644 index 00000000..573f07dc --- /dev/null +++ b/config/gr_pmt.m4 @@ -0,0 +1,34 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_PMT],[ + AC_CONFIG_SRCDIR([pmt/src/lib/pmt.h]) + + AC_CONFIG_FILES([\ + pmt/Makefile \ + pmt/doc/Makefile \ + pmt/src/Makefile \ + pmt/src/lib/Makefile + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + dnl AC_CONFIG_COMMANDS([run_tests_pmt], [chmod +x pmt/src/python/run_tests]) + + subdirs="$subdirs pmt" +]) diff --git a/config/gr_pwin32.m4 b/config/gr_pwin32.m4 new file mode 100644 index 00000000..5f748afc --- /dev/null +++ b/config/gr_pwin32.m4 @@ -0,0 +1,146 @@ +# Check for (mingw)win32 POSIX replacements. -*- Autoconf -*- + +# 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. + + +AC_DEFUN([GR_PWIN32], +[ +AC_REQUIRE([AC_HEADER_TIME]) +AC_CHECK_HEADERS([sys/types.h fcntl.h io.h]) +AC_CHECK_HEADERS([windows.h]) +AC_CHECK_HEADERS([winioctl.h winbase.h], [], [], [ + #if HAVE_WINDOWS_H + #include + #endif +]) + +AC_CHECK_FUNCS([getopt usleep gettimeofday nanosleep rand srand random srandom sleep sigaction]) +AC_CHECK_TYPES([struct timezone, struct timespec, ssize_t],[],[],[ + #if HAVE_SYS_TYPES_H + # include + #endif + #if TIME_WITH_SYS_TIME + # include + # include + #else + # if HAVE_SYS_TIME_H + # include + # else + # include + # endif + #endif +]) + +dnl Checks for replacements +AC_REPLACE_FUNCS([getopt usleep gettimeofday]) + + +AC_MSG_CHECKING(for Sleep) +AC_TRY_LINK([ #include + #include + ], [ Sleep(0); ], + [AC_DEFINE(HAVE_SSLEEP,1,[Define to 1 if you have win32 Sleep]) + AC_MSG_RESULT(yes)], + AC_MSG_RESULT(no) + ) + +dnl Under Win32, mkdir prototype in io.h has only one arg +AC_MSG_CHECKING(whether mkdir accepts only one arg) +AC_TRY_COMPILE([#include + #include + #include ], [ + mkdir("") + ], [ AC_MSG_RESULT(yes) + AC_DEFINE(MKDIR_TAKES_ONE_ARG,[],[Define if mkdir accepts only one arg]) ], + [ AC_MSG_RESULT(no) + ]) + +AH_BOTTOM( +[ +/* Define missing prototypes, implemented in replacement lib */ +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef HAVE_GETOPT +int getopt (int argc, char * const argv[], const char * optstring); +extern char * optarg; +extern int optind, opterr, optopt; +#endif + +#ifndef HAVE_USLEEP +int usleep(unsigned long usec); /* SUSv2 */ +#endif + +#ifndef HAVE_NANOSLEEP +#ifndef HAVE_STRUCT_TIMESPEC +#if HAVE_SYS_TYPES_H +# include /* need time_t */ +#endif +struct timespec { + time_t tv_sec; + long tv_nsec; +}; +#endif +static inline int nanosleep(const struct timespec *req, struct timespec *rem) { return usleep(req->tv_sec*1000000+req->tv_nsec/1000); } +#endif + +#if defined(HAVE_SSLEEP) && !defined(HAVE_SLEEP) +#ifdef HAVE_WINBASE_H +#include +#include +#endif +/* TODO: what about SleepEx? */ +static inline unsigned int sleep (unsigned int nb_sec) { Sleep(nb_sec*1000); return 0; } +#endif + +#ifndef HAVE_GETTIMEOFDAY +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifndef HAVE_STRUCT_TIMEZONE +struct timezone { + int tz_minuteswest; + int tz_dsttime; +}; +#endif +int gettimeofday(struct timeval *tv, struct timezone *tz); +#endif + +#if !defined(HAVE_RANDOM) && defined(HAVE_RAND) +#include +static inline long int random (void) { return rand(); } +#endif + +#if !defined(HAVE_SRANDOM) && defined(HAVE_SRAND) +static inline void srandom (unsigned int seed) { srand(seed); } +#endif + +#ifndef HAVE_SSIZE_T +typedef size_t ssize_t; +#endif + +#ifdef __cplusplus +} +#endif +]) + + +]) diff --git a/config/gr_python.m4 b/config/gr_python.m4 new file mode 100644 index 00000000..760a0f74 --- /dev/null +++ b/config/gr_python.m4 @@ -0,0 +1,116 @@ +dnl +dnl Copyright 2003,2004,2005 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +# PYTHON_DEVEL() +# +# Checks for Python and tries to get the include path to 'Python.h'. +# It provides the $(PYTHON_CPPFLAGS) and $(PYTHON_LDFLAGS) output variables. +# +AC_DEFUN([PYTHON_DEVEL],[ + AC_REQUIRE([AM_PATH_PYTHON]) + AC_REQUIRE([AC_CANONICAL_HOST]) + + # Check for Python include path + AC_MSG_CHECKING([for Python include path]) + if test -z "$PYTHON" ; then + AC_MSG_ERROR([cannot find Python path]) + fi + + # ask distutils which include path we should use + python_cmd=' +import distutils.sysconfig +import os +path = distutils.sysconfig.get_python_inc(plat_specific=False) +if os.sep == "\\": + path = path.replace("\\", "/") +print path +' + python_path=`$PYTHON -c "$python_cmd"` + AC_MSG_RESULT([$python_path]) + if test -z "$python_path" ; then + AC_MSG_ERROR([cannot find Python include path]) + fi + + AC_SUBST(PYTHON_CPPFLAGS,[-I$python_path]) + + # Check for Python headers usability + python_save_CPPFLAGS=$CPPFLAGS + CPPFLAGS="$CPPFLAGS $PYTHON_CPPFLAGS" + AC_CHECK_HEADERS([Python.h], [], + [AC_MSG_ERROR([cannot find usable Python headers])]) + CPPFLAGS="$python_save_CPPFLAGS" + + # Only set this on mingw and cygwin hosts, (only implemented + # for mingw host, for crosscompiling you need to trick this) + + PYTHON_LDFLAGS="" + case $host_os in + *mingw* | *cygwin* ) + AC_MSG_CHECKING([for Python LDFLAGS]) + + python_cmd=' +import distutils.sysconfig +import os +path = distutils.sysconfig.get_config_var("LIBPL") +if path == None: + path = distutils.sysconfig.PREFIX + "/libs" +if os.sep == "\\": + path = path.replace("\\", "/") +print path +' + python_stdlib_path=`$PYTHON -c "$python_cmd"` + + python_version_nodot=`echo $PYTHON_VERSION | sed "s,\.,,"` + libpython_name="python$PYTHON_VERSION" + + # Standard install of python for win32 has libpython24.a + # instead of libpython2.4.a so we check for the library + # without the dot in the version number. + + python_stdlib_filename=`find $python_stdlib_path -type f -name libpython$python_version_nodot.* -print | sed "1q"` + if test -n "$python_stdlib_filename" ; then + libpython_name="python$python_version_nodot" + fi + + PYTHON_LDFLAGS="-L$python_stdlib_path -l$libpython_name" + AC_MSG_RESULT($PYTHON_LDFLAGS) + # Replace all backslashes in PYTHON Paths with forward slashes + AC_MSG_CHECKING([for pythondir]) + pythondir=`echo $pythondir |sed 's,\\\\,/,g'` + AC_MSG_RESULT($pythondir) + AC_SUBST([pythondir]) + AC_MSG_CHECKING([for pkgpythondir]) + pkgpythondir=`echo $pkgpythondir |sed 's,\\\\,/,g'` + AC_MSG_RESULT($pkgpythondir) + AC_SUBST([pkgpythondir]) + AC_MSG_CHECKING([for pyexecdir]) + pyexecdir=`echo $pyexecdir |sed 's,\\\\,/,g'` + AC_MSG_RESULT($pyexecdir) + AC_SUBST([pyexecdir]) + AC_MSG_CHECKING([for pkgpyexecdir]) + pkgpyexecdir=`echo $pkgpyexecdir |sed 's,\\\\,/,g'` + AC_MSG_RESULT($pkgpyexecdir) + AC_SUBST([pkgpyexecdir]) + ;; + esac + + AC_SUBST([PYTHON_LDFLAGS]) +]) diff --git a/config/gr_radar.m4 b/config/gr_radar.m4 new file mode 100644 index 00000000..b9a42d65 --- /dev/null +++ b/config/gr_radar.m4 @@ -0,0 +1,36 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_RADAR],[ + AC_CONFIG_SRCDIR([gr-radar/src/python/usrp_rx_radar.py]) + + AC_CONFIG_FILES([\ + gr-radar/Makefile \ + gr-radar/doc/Makefile \ + gr-radar/src/Makefile \ + gr-radar/src/lib/Makefile \ + gr-radar/src/python/Makefile \ + gr-radar/src/python/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_radar], [chmod +x gr-radar/src/python/run_tests]) + + subdirs="$subdirs gr-radar" +]) diff --git a/config/gr_radio_astronomy.m4 b/config/gr_radio_astronomy.m4 new file mode 100644 index 00000000..db0ca61f --- /dev/null +++ b/config/gr_radio_astronomy.m4 @@ -0,0 +1,35 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_RADIO_ASTRONOMY],[ + AC_CONFIG_SRCDIR([gr-radio-astronomy/src/lib/ra.i]) + + AC_CONFIG_FILES([\ + gr-radio-astronomy/Makefile \ + gr-radio-astronomy/src/Makefile \ + gr-radio-astronomy/src/lib/Makefile \ + gr-radio-astronomy/src/python/Makefile \ + gr-radio-astronomy/src/python/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_astronomy], [chmod +x gr-radio-astronomy/src/python/run_tests]) + + subdirs="$subdirs gr-radio-astronomy" +]) diff --git a/config/gr_require_mc4020.m4 b/config/gr_require_mc4020.m4 new file mode 100644 index 00000000..8a03eeb6 --- /dev/null +++ b/config/gr_require_mc4020.m4 @@ -0,0 +1,33 @@ +dnl +dnl Copyright 2003,2004 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +AC_DEFUN([GR_REQUIRE_MC4020],[ + AC_MSG_CHECKING([for mc4020 A/D driver include file]) + AC_COMPILE_IFELSE([ +#include +int main (int argc, char **argv) +{ + return 0; +} +],[AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no]) + AC_MSG_ERROR([mc4020.h not found.])]) +]) diff --git a/config/gr_scripting.m4 b/config/gr_scripting.m4 new file mode 100644 index 00000000..7f3abdee --- /dev/null +++ b/config/gr_scripting.m4 @@ -0,0 +1,30 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +AC_DEFUN([GR_SCRIPTING],[ + AC_REQUIRE([AC_PROG_LN_S]) + AC_REQUIRE([AC_PROG_CXX]) + AC_REQUIRE([AC_PROG_LIBTOOL]) + + SWIG_PROG(1.3.23) + SWIG_ENABLE_CXX + SWIG_PYTHON +]) diff --git a/config/gr_set_md_cpu.m4 b/config/gr_set_md_cpu.m4 new file mode 100644 index 00000000..1bb2f341 --- /dev/null +++ b/config/gr_set_md_cpu.m4 @@ -0,0 +1,44 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +AC_DEFUN([GR_SET_MD_CPU],[ + AC_REQUIRE([AC_CANONICAL_HOST]) + AC_ARG_WITH(md-cpu, + [ --with-md-cpu=ARCH set machine dependent speedups (auto)], + [cf_with_md_cpu="$withval"], + [cf_with_md_cpu="$host_cpu"]) + + AC_MSG_CHECKING([for machine dependent speedups]) + case "$cf_with_md_cpu" in + x86 | i[[3-7]]86) MD_CPU=x86 MD_SUBCPU=x86 ;; + x86_64) MD_CPU=x86 MD_SUBCPU=x86_64 ;; +# sparc) MD_CPU=sparc ;; + *) MD_CPU=generic ;; + esac + AC_MSG_RESULT($MD_CPU) + AC_SUBST(MD_CPU) + AC_SUBST(MD_SUBCPU) + + AM_CONDITIONAL(MD_CPU_x86, test $MD_CPU = x86) + AM_CONDITIONAL(MD_SUBCPU_x86_64, test $MD_SUBCPU = x86_64) + AM_CONDITIONAL(MD_CPU_generic, test $MD_CPU = generic) +]) + diff --git a/config/gr_swig.m4 b/config/gr_swig.m4 new file mode 100644 index 00000000..a587c6df --- /dev/null +++ b/config/gr_swig.m4 @@ -0,0 +1,85 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +# SWIG_PROG([required-version]) +# +# Checks for the SWIG program. If found you can (and should) call SWIG via $(SWIG). +# You can use the optional first argument to check if the version of the available SWIG +# is greater or equal to the value of the argument. It should have the format: +# N[.N[.N]] (N is a number between 0 and 999. Only the first N is mandatory.) +AC_DEFUN([SWIG_PROG],[ + AC_REQUIRE([AC_PROG_MAKE_SET]) + AC_CHECK_PROG(SWIG,swig,[`which swig`]) + if test -z "$SWIG" ; then + AC_MSG_ERROR([Cannot find 'swig' program. SWIG version >= $1 required]) + SWIG=false + elif test -n "$1" ; then + AC_MSG_CHECKING([for SWIG version]) + swig_version=`$SWIG -version 2>&1 | \ + awk '/^SWIG Version [[0-9]+\.[0-9]+\.[0-9]]+.*$/ { split($[3],a,"[[^.0-9]]"); print a[[1]] }'` + AC_MSG_RESULT([$swig_version]) + if test -n "$swig_version" ; then + swig_version=`echo $swig_version | \ + awk '{ split($[1],a,"\."); print [a[1]*1000000+a[2]*1000+a[3]] }' 2>/dev/null` + swig_required_version=`echo $1 | \ + awk '{ split($[1],a,"\."); print [a[1]*1000000+a[2]*1000+a[3]] }' 2>/dev/null` + if test $swig_required_version -gt $swig_version ; then + AC_MSG_ERROR([SWIG version >= $1 required]) + fi + else + AC_MSG_ERROR([cannot determine SWIG version]) + fi + fi +]) + +# SWIG_ENABLE_CXX() +# +# Enable swig C++ support. This effects all invocations of $(SWIG). +AC_DEFUN([SWIG_ENABLE_CXX],[ + AC_REQUIRE([SWIG_PROG]) + AC_REQUIRE([AC_PROG_CXX]) + if test "$SWIG" != "false" ; then + SWIG="$SWIG -c++" + fi +]) + +# SWIG_PYTHON([use-shadow-classes]) +# +# Checks for Python and provides the $(SWIG_PYTHON_CPPFLAGS), +# $(SWIG_PYTHON_LIB) and $(SWIG_PYTHON_OPT) output variables. +# $(SWIG_PYTHON_OPT) contains all necessary swig options to generate +# code for Python. If you need multi module support use +# $(SWIG_PYTHON_LIB) (provided by the SWIG_MULTI_MODULE_SUPPORT() +# macro) to link against the appropriate library. It contains the +# SWIG Python runtime library that is needed by the type check system +# for example. + +AC_DEFUN([SWIG_PYTHON],[ + AC_REQUIRE([SWIG_PROG]) + AC_REQUIRE([PYTHON_DEVEL]) + if test "$SWIG" != "false" ; then + AC_SUBST(SWIG_PYTHON_LIB,[-lswigpy]) +dnl test ! "x$1" = "xno" && swig_shadow=" -shadow" || swig_shadow="" +dnl AC_SUBST(SWIG_PYTHON_OPT,[-python$swig_shadow]) + AC_SUBST(SWIG_PYTHON_OPT,[-python]) + fi + AC_SUBST(SWIG_PYTHON_CPPFLAGS,[$PYTHON_CPPFLAGS]) +]) diff --git a/config/gr_sysv_shm.m4 b/config/gr_sysv_shm.m4 new file mode 100644 index 00000000..5e11e496 --- /dev/null +++ b/config/gr_sysv_shm.m4 @@ -0,0 +1,36 @@ +# Check for IPC System V shm support. -*- Autoconf -*- + +# Copyright 2003 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, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +AC_DEFUN([GR_SYSV_SHM], +[ + AC_LANG_SAVE + AC_LANG_C + + AC_CHECK_HEADERS([sys/ipc.h sys/shm.h]) + + save_LIBS="$LIBS" + AC_SEARCH_LIBS(shmat, [cygipc ipc], + [ IPC_LIBS="$LIBS" ], + [ AC_MSG_WARN([SystemV IPC support not found. ]) ] + ) + LIBS="$save_LIBS" + + AC_LANG_RESTORE + AC_SUBST(IPC_LIBS) +]) diff --git a/config/gr_usrp.m4 b/config/gr_usrp.m4 new file mode 100644 index 00000000..a51d77ca --- /dev/null +++ b/config/gr_usrp.m4 @@ -0,0 +1,113 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_USRP_HW],[ + AC_CONFIG_SRCDIR([usrp/host/lib/usrp_prims.h]) + + AC_CHECK_PROG([XMLTO],[xmlto],[yes],[]) + AM_CONDITIONAL(HAS_XMLTO, test x$XMLTO = xyes) + + # gnulib. + # FIXME: this needs to fail gracefully and continue, not implemented yet + UTILS_FUNC_MKSTEMP + + succeeded=yes + dnl Checks for library functions. + USRP_LIBUSB([],[succeeded=no]) + USRP_SET_FUSB_TECHNIQUE([],[succeeded=no]) + + dnl check for firmware cross compilation tools + dnl check for SDCC 2.4.0 + USRP_SDCC([2.4.0],[],[succeeded=no]) + + AC_CHECK_FUNCS([getrusage sched_setscheduler],[],[succeeded=no]) + AC_CHECK_FUNCS([sigaction snprintf],[],[succeeded=no]) + + dnl we use these to handle possible byteswapping to and from the USRP. + AC_CHECK_HEADERS([byteswap.h],[],[succeeeded=no]) + AC_C_BIGENDIAN + + if test $succeeded = yes; then + dnl Define where to look for USRP includes + USRP_INCLUDES='-I$(top_srcdir)/host/lib -I$(top_srcdir)/firmware/include' + AC_SUBST(USRP_INCLUDES) + + USRP_DEFINES='' + AC_SUBST(USRP_DEFINES) + + DEFINES="$USRP_DEFINES" + AC_SUBST(DEFINES) + + AC_CONFIG_FILES([ \ + usrp/Makefile \ + usrp/usrp.pc \ + usrp/usrp.iss \ + usrp/doc/Doxyfile \ + usrp/doc/Makefile \ + usrp/doc/other/Makefile \ + usrp/host/Makefile \ + usrp/host/misc/Makefile \ + usrp/host/lib/Makefile \ + usrp/host/lib/std_paths.h \ + usrp/host/swig/Makefile \ + usrp/host/apps/Makefile \ + usrp/firmware/Makefile \ + usrp/firmware/include/Makefile \ + usrp/firmware/lib/Makefile \ + usrp/firmware/src/Makefile \ + usrp/firmware/src/common/Makefile \ + usrp/firmware/src/usrp2/Makefile \ + usrp/fpga/Makefile \ + usrp/fpga/rbf/Makefile \ + ]) + + subdirs="$subdirs usrp" + else + failed="$failed usrp" + fi +]) + +AC_DEFUN([GR_USRP],[ + AC_CONFIG_SRCDIR([gr-usrp/src/usrp1.i]) + + # Don't do gr-usrp if usrp failed + # There *has* to be a better way to check if a value is in a string + succeeded=yes + for dir in $failed + do + if test $dir = usrp; then + succeeded=no + fi + done + + if test $succeeded = yes; then + AC_CONFIG_FILES([\ + gr-usrp/Makefile \ + gr-usrp/src/Makefile \ + gr-usrp/src/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_usrp], [chmod +x gr-usrp/src/run_tests]) + + subdirs="$subdirs gr-usrp" + else + failed="$failed gr-usrp" + fi +]) diff --git a/config/gr_video_sdl.m4 b/config/gr_video_sdl.m4 new file mode 100644 index 00000000..2f524986 --- /dev/null +++ b/config/gr_video_sdl.m4 @@ -0,0 +1,45 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_VIDEO_SDL],[ + AC_CONFIG_SRCDIR([gr-video-sdl/src/video_sdl.i]) + + succeeded=yes + + dnl Check for SDL + SDL_VERSION=1.2.0 + AM_PATH_SDL($SDL_VERSION,[],[succeeded=no]) + + if test $succeeded = yes; then + AM_CFLAGS="$AM_CFLAGS $SDL_CFLAGS" + AM_LDFLAGS="$AM_LDFLAGS $SDL_LIBS" + + AC_CONFIG_FILES([\ + gr-video-sdl/Makefile \ + gr-video-sdl/src/Makefile \ + gr-video-sdl/src/run_tests \ + ]) + + dnl run_tests is created from run_tests.in. Make it executable. + AC_CONFIG_COMMANDS([run_tests_sdl], [chmod +x gr-video-sdl/src/run_tests]) + subdirs="$subdirs gr-video-sdl" + else + failed="$failed gr-video-sdl" + fi +]) diff --git a/config/gr_wxgui.m4 b/config/gr_wxgui.m4 new file mode 100644 index 00000000..4ff56509 --- /dev/null +++ b/config/gr_wxgui.m4 @@ -0,0 +1,33 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_DEFUN([GR_WXGUI],[ + AC_CONFIG_SRCDIR([gr-wxgui/src/python/stdgui.py]) + + # FIXME: Should we actually check for wxPython, even though + # this is a runtime requirement, not a compile/install time one? + + AC_CONFIG_FILES([ \ + gr-wxgui/Makefile \ + gr-wxgui/src/Makefile \ + gr-wxgui/src/python/Makefile \ + ]) + + subdirs="$subdirs gr-wxgui" +]) diff --git a/config/gr_x86_64.m4 b/config/gr_x86_64.m4 new file mode 100644 index 00000000..3d6f5eae --- /dev/null +++ b/config/gr_x86_64.m4 @@ -0,0 +1,39 @@ +dnl +dnl Copyright 2005 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +# GR_X86_64() +# +# Checks to see if we're on a x86_64 machine, and if so, ensure +# that libdir ends in "64" +# +AC_DEFUN([GR_X86_64],[ + AC_REQUIRE([AC_CANONICAL_HOST]) + if test "$host_cpu" = "x86_64"; then + AC_MSG_CHECKING([libdir for lib64 suffix]) + t=${libdir##*/lib} + if test "$t" != 64 && test -d /lib64 && ! test -L /lib64; then + libdir=${libdir}64 + AC_MSG_RESULT([no. Setting libdir to $libdir]) + else + AC_MSG_RESULT([yes]) + fi + fi +]) diff --git a/config/lf_cc.m4 b/config/lf_cc.m4 new file mode 100644 index 00000000..f9bd7155 --- /dev/null +++ b/config/lf_cc.m4 @@ -0,0 +1,42 @@ +dnl Autoconf support for C++ +dnl Copyright (C) 1988 Eleftherios Gkioulekas +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a configuration +dnl script generated by Autoconf, you may include it under the same +dnl distribution terms that you use for the rest of that program. + +# ------------------------------------------------------------------------- +# Use this macro to configure your C compiler +# When called the macro does the following things: +# 1. It finds an appropriate C compiler. +# If you passed the flag --with-cc=foo then it uses that +# particular compiler +# 2. Check whether the compiler works. +# 3. Checks whether the compiler accepts the -g +# ------------------------------------------------------------------------- + +AC_DEFUN([LF_CONFIGURE_CC],[ + dnl Sing the song + AC_REQUIRE([AC_PROG_CC])dnl + AC_REQUIRE([AC_PROG_CPP])dnl + AC_REQUIRE([AC_AIX])dnl + AC_REQUIRE([AC_ISC_POSIX])dnl + AC_REQUIRE([AC_MINIX])dnl + AC_REQUIRE([AC_HEADER_STDC])dnl +]) + diff --git a/config/lf_cxx.m4 b/config/lf_cxx.m4 new file mode 100644 index 00000000..8ade1fb2 --- /dev/null +++ b/config/lf_cxx.m4 @@ -0,0 +1,121 @@ +dnl Autoconf support for C++ +dnl Copyright (C) 1988 Eleftherios Gkioulekas +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a configuration +dnl script generated by Autoconf, you may include it under the same +dnl distribution terms that you use for the rest of that program. + +# ----------------------------------------------------------------- +# This macro should be called to configure your C++ compiler. +# When called, the macro does the following things: +# 1. It finds an appropriate C++ compiler +# If you passed the flag --with-cxx=foo, then it uses that +# particular compiler +# 2. Checks whether the compiler accepts the -g +# ------------------------------------------------------------------ + +AC_DEFUN([LF_CONFIGURE_CXX],[ + AC_REQUIRE([AC_PROG_CXX])dnl + AC_REQUIRE([AC_PROG_CXXCPP])dnl + LF_CXX_PORTABILITY +]) + +# ----------------------------------------------------------------------- +# This macro tests the C++ compiler for various portability problem. +# 1. Defines CXX_HAS_NO_BOOL if the compiler does not support the bool +# data type +# 2. Defines CXX_HAS_BUGGY_FOR_LOOPS if the compiler has buggy +# scoping for the for-loop +# 3. Defines USE_ASSERT if the user wants to use assertions +# ----------------------------------------------------------------------- + + +AC_DEFUN([LF_CXX_PORTABILITY],[ + + dnl + dnl Check for common C++ portability problems + dnl + + dnl AC_LANG_PUSH + dnl AC_LANG_CPLUSPLUS + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + + dnl Check whether we have bool + AC_MSG_CHECKING(whether C++ has bool) + AC_TRY_RUN([main() { bool b1=true; bool b2=false; }], + [ AC_MSG_RESULT(yes) ], + [ AC_MSG_RESULT(no) + AC_DEFINE(CXX_HAS_NO_BOOL,[],[Define if C++ is missing bool type]) ], + [ AC_MSG_WARN(Don't cross-compile)] + ) + + dnl Test whether C++ has buggy for-loops + AC_MSG_CHECKING(whether C++ has buggy scoping in for-loops) + AC_TRY_COMPILE([#include ], [ + for (int i=0;i<10;i++) { } + for (int i=0;i<10;i++) { } +], [ AC_MSG_RESULT(no) ], + [ AC_MSG_RESULT(yes) + AC_DEFINE(CXX_HAS_BUGGY_FOR_LOOPS,[],[Define if for loop scoping is broken]) ]) + + dnl Test whether the user wants to enable assertions + AC_MSG_CHECKING(whether user wants assertions) + AC_ARG_ENABLE(assert, + [ --disable-assert don't use cpp.h assert], + [ AC_DEFINE(NDEBUG,[],[Define to disable asserts (don't doit!)]) + AC_MSG_RESULT(no) ], + [ AC_MSG_RESULT(yes) ], + ) + + dnl Test whether C++ has std::isnan + AC_MSG_CHECKING(whether C++ has std::isnan) + AC_TRY_COMPILE([#include ], [ + std::isnan(0); +], [ AC_MSG_RESULT(yes) + AC_DEFINE(CXX_HAS_STD_ISNAN,[],[Define if has std::isnan]) ], + [ AC_MSG_RESULT(no) ]) + + dnl Done with the portability checks + dnl AC_LANG_POP([C++]) + AC_LANG_RESTORE +]) + +AH_BOTTOM([// Workaround for compilers with buggy for-loop scoping +// That's quite a few compilers actually including recent versions of +// Dec Alpha cxx, HP-UX CC and SGI CC. +// The trivial "if" statement provides the correct scoping to the +// for loop + +#ifdef CXX_HAS_BUGGY_FOR_LOOPS +#undef for +#define for if(1) for +#endif +]) + +AH_BOTTOM([// If the C++ compiler we use doesn't have bool, then +// the following is a near-perfect work-around. +// You must make sure your code does not depend on "int" and "bool" +// being two different types, in overloading for instance. + +#ifdef CXX_HAS_NO_BOOL +#define bool int +#define true 1 +#define false 0 +#endif +]) diff --git a/config/lf_warnings.m4 b/config/lf_warnings.m4 new file mode 100644 index 00000000..0ebb97ef --- /dev/null +++ b/config/lf_warnings.m4 @@ -0,0 +1,128 @@ +dnl Copyright (C) 1988 Eleftherios Gkioulekas +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a configuration +dnl script generated by Autoconf, you may include it under the same +dnl distribution terms that you use for the rest of that program. + +# -------------------------------------------------------------------------- +# Check whether the C++ compiler accepts a certain flag +# If it does it adds the flag to CXXFLAGS +# If it does not then it returns an error to lf_ok +# Usage: +# LF_CHECK_CXX_FLAG(-flag1 -flag2 -flag3 ...) +# ------------------------------------------------------------------------- + +AC_DEFUN([LF_CHECK_CXX_FLAG],[ + echo 'void f(){}' > conftest.cc + for i in $1 + do + AC_MSG_CHECKING([whether $CXX accepts $i]) + if test -z "`${CXX} $i -c conftest.cc 2>&1`" + then + CXXFLAGS="${CXXFLAGS} $i" + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi + done + rm -f conftest.cc conftest.o +]) + +# -------------------------------------------------------------------------- +# Check whether the C compiler accepts a certain flag +# If it does it adds the flag to CFLAGS +# If it does not then it returns an error to lf_ok +# Usage: +# LF_CHECK_CC_FLAG(-flag1 -flag2 -flag3 ...) +# ------------------------------------------------------------------------- + +AC_DEFUN([LF_CHECK_CC_FLAG],[ + echo 'void f(){}' > conftest.c + for i in $1 + do + AC_MSG_CHECKING([whether $CC accepts $i]) + if test -z "`${CC} $i -c conftest.c 2>&1`" + then + CFLAGS="${CFLAGS} $i" + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi + done + rm -f conftest.c conftest.o +]) + +# -------------------------------------------------------------------------- +# Check whether the Fortran compiler accepts a certain flag +# If it does it adds the flag to FFLAGS +# If it does not then it returns an error to lf_ok +# Usage: +# LF_CHECK_F77_FLAG(-flag1 -flag2 -flag3 ...) +# ------------------------------------------------------------------------- + +AC_DEFUN([LF_CHECK_F77_FLAG],[ + cat << EOF > conftest.f +c....:++++++++++++++++++++++++ + PROGRAM MAIN + PRINT*,'Hello World!' + END +EOF + for i in $1 + do + AC_MSG_CHECKING([whether $F77 accepts $i]) + if test -z "`${F77} $i -c conftest.f 2>&1`" + then + FFLAGS="${FFLAGS} $i" + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) + fi + done + rm -f conftest.f conftest.o +]) + +# ---------------------------------------------------------------------- +# Provide the configure script with an --with-warnings option that +# turns on warnings. Call this command AFTER you have configured ALL your +# compilers. +# ---------------------------------------------------------------------- + +AC_DEFUN([LF_SET_WARNINGS],[ + dnl Check for --with-warnings + AC_MSG_CHECKING([whether user wants warnings]) + AC_ARG_WITH(warnings, + [ --with-warnings Turn on warnings], + [ lf_warnings=yes ], [ lf_warnings=no ]) + lf_warnings=yes # hard code for now -eb + AC_MSG_RESULT($lf_warnings) + + dnl Warnings for the two main compilers + cc_warning_flags="-Wall" + cxx_warning_flags="-Wall -Woverloaded-virtual" + if test $lf_warnings = yes + then + if test -n "${CC}" + then + LF_CHECK_CC_FLAG($cc_warning_flags) + fi + if test -n "${CXX}" + then + LF_CHECK_CXX_FLAG($cxx_warning_flags) + fi + fi +]) diff --git a/config/lf_x11.m4 b/config/lf_x11.m4 new file mode 100644 index 00000000..3bd19f24 --- /dev/null +++ b/config/lf_x11.m4 @@ -0,0 +1,39 @@ +dnl Copyright (C) 1988 Eleftherios Gkioulekas +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a configuration +dnl script generated by Autoconf, you may include it under the same +dnl distribution terms that you use for the rest of that program. + + +#----------------------------------------------------------------------- +# This macro searches for Xlib and when it finds it it adds the +# appropriate flags to CXXFLAGS and export the link sequence to +# the variable XLIB. +# In your configure.in file add: +# LF_PATH_XLIB +# In your Makefile.am add +# program_LDADD = .... $(XLIB) +#------------------------------------------------------------------------ + +AC_DEFUN([LF_PATH_XLIB],[ + AC_PATH_XTRA + CXXFLAGS="$CXXFLAGS $X_CFLAGS" + XLIB="$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS" + AC_SUBST(XLIB) +]) + diff --git a/config/macosx_audiounit.m4 b/config/macosx_audiounit.m4 new file mode 100644 index 00000000..313feb3b --- /dev/null +++ b/config/macosx_audiounit.m4 @@ -0,0 +1,49 @@ +# Copyright 2006 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, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +AC_DEFUN([MACOSX_AUDIOUNIT], +[ + audiounitok=yes + case "$host_os" in + darwin*);; + *) + audiounitok=no + AC_MSG_WARN([gr-audio-osx requires darwin or MacOS X.]) + esac + + AC_CHECK_HEADERS([AudioUnit/AudioUnit.h], + [], + [ + audiounitok=no, + AC_MSG_WARN([gr-audio-osx requires AudioUnit/AudioUnit.h, which is available on MacOS X.]) + ] + ) + + AC_CHECK_HEADERS([AudioToolbox/AudioToolbox.h], + [], + [ + audiounitok=no, + AC_MSG_WARN([gr-audio-osx requires AudioToolbox/AudioToolbox.h, which is available on MacOS X.]) + ] + ) + + if test $audiounitok = yes; then + ifelse([$1], , :, [$1]) + else + ifelse([$2], , :, [$2]) + fi +]) diff --git a/config/mkstemp.m4 b/config/mkstemp.m4 new file mode 100644 index 00000000..4af0f0a9 --- /dev/null +++ b/config/mkstemp.m4 @@ -0,0 +1,89 @@ +#serial 4 + +# On some hosts (e.g., HP-UX 10.20, SunOS 4.1.4, Solaris 2.5.1), mkstemp has a +# silly limit that it can create no more than 26 files from a given template. +# Other systems lack mkstemp altogether. +# On OSF1/Tru64 V4.0F, the system-provided mkstemp function can create +# only 32 files per process. +# On systems like the above, arrange to use the replacement function. +AC_DEFUN([UTILS_FUNC_MKSTEMP], +[dnl + AC_REPLACE_FUNCS(mkstemp) + if test $ac_cv_func_mkstemp = no; then + utils_cv_func_mkstemp_limitations=yes + else + AC_CACHE_CHECK([for mkstemp limitations], + utils_cv_func_mkstemp_limitations, + [ + AC_TRY_RUN([ +# include + int main () + { + int i; + for (i = 0; i < 70; i++) + { + char template[] = "conftestXXXXXX"; + int fd = mkstemp (template); + if (fd == -1) + exit (1); + close (fd); + } + exit (0); + } + ], + utils_cv_func_mkstemp_limitations=no, + utils_cv_func_mkstemp_limitations=yes, + utils_cv_func_mkstemp_limitations=yes + ) + ] + ) + fi + + if test $utils_cv_func_mkstemp_limitations = yes; then + AC_LIBOBJ(mkstemp) + AC_LIBOBJ(tempname) + AC_DEFINE(mkstemp, rpl_mkstemp, + [Define to rpl_mkstemp if the replacement function should be used.]) + gl_PREREQ_MKSTEMP + jm_PREREQ_TEMPNAME + fi +]) + +# Prerequisites of lib/mkstemp.c. +AC_DEFUN([gl_PREREQ_MKSTEMP], +[ + AH_BOTTOM( + [ + #ifndef HAVE_MKSTEMP + #ifdef __cplusplus + extern "C" { + #endif + int rpl_mkstemp (char *templ); + #ifdef __cplusplus + } + #endif + #endif + ]) +]) + +# Prerequisites of lib/tempname.c. +AC_DEFUN([jm_PREREQ_TEMPNAME], +[ + AC_REQUIRE([AC_HEADER_STAT]) + AC_CHECK_HEADERS_ONCE(fcntl.h sys/time.h unistd.h) + AC_CHECK_HEADERS(stdint.h) + AC_CHECK_FUNCS(__secure_getenv gettimeofday lstat) + AC_CHECK_DECLS_ONCE(getenv) + # AC_REQUIRE([jm_AC_TYPE_UINTMAX_T]) + + dnl Under Win32, mkdir prototype in io.h has only one arg + AC_MSG_CHECKING(whether mkdir accepts only one arg) + AC_TRY_COMPILE([#include + #include + #include ], [ + mkdir("") + ], [ AC_MSG_RESULT(yes) + AC_DEFINE(MKDIR_TAKES_ONE_ARG,[],[Define if mkdir accepts only one arg]) ], + [ AC_MSG_RESULT(no) + ]) +]) diff --git a/config/onceonly.m4 b/config/onceonly.m4 new file mode 100644 index 00000000..f6fec37c --- /dev/null +++ b/config/onceonly.m4 @@ -0,0 +1,63 @@ +# onceonly.m4 serial 3 +dnl Copyright (C) 2002, 2003 Free Software Foundation, Inc. +dnl This file is free software, distributed under the terms of the GNU +dnl General Public License. As a special exception to the GNU General +dnl Public License, this file may be distributed as part of a program +dnl that contains a configuration script generated by Autoconf, under +dnl the same distribution terms as the rest of that program. + +dnl This file defines some "once only" variants of standard autoconf macros. +dnl AC_CHECK_HEADERS_ONCE like AC_CHECK_HEADERS +dnl AC_CHECK_FUNCS_ONCE like AC_CHECK_FUNCS +dnl AC_CHECK_DECLS_ONCE like AC_CHECK_DECLS +dnl AC_REQUIRE([AC_HEADER_STDC]) like AC_HEADER_STDC +dnl The advantage is that the check for each of the headers/functions/decls +dnl will be put only once into the 'configure' file. It keeps the size of +dnl the 'configure' file down, and avoids redundant output when 'configure' +dnl is run. +dnl The drawback is that the checks cannot be conditionalized. If you write +dnl if some_condition; then gl_CHECK_HEADERS(stdlib.h); fi +dnl inside an AC_DEFUNed function, the gl_CHECK_HEADERS macro call expands to +dnl empty, and the check will be inserted before the body of the AC_DEFUNed +dnl function. + +dnl Autoconf version 2.57 or newer is recommended. +AC_PREREQ(2.54) + +# AC_CHECK_HEADERS_ONCE(HEADER1 HEADER2 ...) is a once-only variant of +# AC_CHECK_HEADERS(HEADER1 HEADER2 ...). +AC_DEFUN([AC_CHECK_HEADERS_ONCE], [ + : + AC_FOREACH([gl_HEADER_NAME], [$1], [ + AC_DEFUN([gl_CHECK_HEADER_]m4_quote(translit(defn([gl_HEADER_NAME]), + [-./], [___])), [ + AC_CHECK_HEADERS(gl_HEADER_NAME) + ]) + AC_REQUIRE([gl_CHECK_HEADER_]m4_quote(translit(gl_HEADER_NAME, + [-./], [___]))) + ]) +]) + +# AC_CHECK_FUNCS_ONCE(FUNC1 FUNC2 ...) is a once-only variant of +# AC_CHECK_FUNCS(FUNC1 FUNC2 ...). +AC_DEFUN([AC_CHECK_FUNCS_ONCE], [ + : + AC_FOREACH([gl_FUNC_NAME], [$1], [ + AC_DEFUN([gl_CHECK_FUNC_]defn([gl_FUNC_NAME]), [ + AC_CHECK_FUNCS(defn([gl_FUNC_NAME])) + ]) + AC_REQUIRE([gl_CHECK_FUNC_]defn([gl_FUNC_NAME])) + ]) +]) + +# AC_CHECK_DECLS_ONCE(DECL1 DECL2 ...) is a once-only variant of +# AC_CHECK_DECLS(DECL1, DECL2, ...). +AC_DEFUN([AC_CHECK_DECLS_ONCE], [ + : + AC_FOREACH([gl_DECL_NAME], [$1], [ + AC_DEFUN([gl_CHECK_DECL_]defn([gl_DECL_NAME]), [ + AC_CHECK_DECLS(defn([gl_DECL_NAME])) + ]) + AC_REQUIRE([gl_CHECK_DECL_]defn([gl_DECL_NAME])) + ]) +]) diff --git a/config/pkg.m4 b/config/pkg.m4 new file mode 100644 index 00000000..770f0629 --- /dev/null +++ b/config/pkg.m4 @@ -0,0 +1,68 @@ +dnl PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not) +dnl defines GSTUFF_LIBS, GSTUFF_CFLAGS, see pkg-config man page +dnl also defines GSTUFF_PKG_ERRORS on error +AC_DEFUN([PKG_CHECK_MODULES], [ + succeeded=no + + if test -z "$PKG_CONFIG"; then + AC_PATH_PROG(PKG_CONFIG, pkg-config, no) + fi + + if test "$PKG_CONFIG" = "no" ; then + echo "*** The pkg-config script could not be found. Make sure it is" + echo "*** in your path, or set the PKG_CONFIG environment variable" + echo "*** to the full path to pkg-config." + echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config." + else + dnl If PKG_CONFIG_PATH is not already set, add /usr/local/lib/pkgconfig. + dnl If it's set, assume the user knows what they're doing. + dnl This should help avoid failures while looking for fftw3f + if test -z "$PKG_CONFIG_PATH"; then + export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig" + fi + + PKG_CONFIG_MIN_VERSION=0.9.0 + if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then + AC_MSG_CHECKING(for $2) + + if $PKG_CONFIG --exists "$2" ; then + AC_MSG_RESULT(yes) + succeeded=yes + + AC_MSG_CHECKING($1_CFLAGS) + $1_CFLAGS=`$PKG_CONFIG --cflags "$2"` + AC_MSG_RESULT($$1_CFLAGS) + + AC_MSG_CHECKING($1_LIBS) + $1_LIBS=`$PKG_CONFIG --libs "$2"` + AC_MSG_RESULT($$1_LIBS) + + AC_MSG_CHECKING($1_INCLUDEDIR) + $1_INCLUDEDIR=`$PKG_CONFIG --variable=includedir "$2"` + AC_MSG_RESULT($$1_INCLUDEDIR) + else + $1_CFLAGS="" + $1_LIBS="" + ## If we have a custom action on failure, don't print errors, but + ## do set a variable so people can do so. + $1_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` + ifelse([$4], ,echo $$1_PKG_ERRORS,) + fi + + AC_SUBST($1_CFLAGS) + AC_SUBST($1_LIBS) + AC_SUBST($1_INCLUDEDIR) + else + echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer." + echo "*** See http://www.freedesktop.org/software/pkgconfig" + fi + fi + + if test $succeeded = yes; then + ifelse([$3], , :, [$3]) + else + ifelse([$4], , AC_MSG_ERROR([Library requirements ($2) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them.]), [$4]) + fi +]) + + diff --git a/config/sdl.m4 b/config/sdl.m4 new file mode 100644 index 00000000..ada3a416 --- /dev/null +++ b/config/sdl.m4 @@ -0,0 +1,175 @@ +# Configure paths for SDL +# Sam Lantinga 9/21/99 +# stolen from Manish Singh +# stolen back from Frank Belew +# stolen from Manish Singh +# Shamelessly stolen from Owen Taylor + +dnl AM_PATH_SDL([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) +dnl Test for SDL, and define SDL_CFLAGS and SDL_LIBS +dnl +AC_DEFUN([AM_PATH_SDL], +[dnl +dnl Get the cflags and libraries from the sdl-config script +dnl +AC_ARG_WITH(sdl-prefix,[ --with-sdl-prefix=PFX Prefix where SDL is installed (optional)], + sdl_prefix="$withval", sdl_prefix="") +AC_ARG_WITH(sdl-exec-prefix,[ --with-sdl-exec-prefix=PFX Exec prefix where SDL is installed (optional)], + sdl_exec_prefix="$withval", sdl_exec_prefix="") +AC_ARG_ENABLE(sdltest, [ --disable-sdltest Do not try to compile and run a test SDL program], + , enable_sdltest=yes) + + if test x$sdl_exec_prefix != x ; then + sdl_args="$sdl_args --exec-prefix=$sdl_exec_prefix" + if test x${SDL_CONFIG+set} != xset ; then + SDL_CONFIG=$sdl_exec_prefix/bin/sdl-config + fi + fi + if test x$sdl_prefix != x ; then + sdl_args="$sdl_args --prefix=$sdl_prefix" + if test x${SDL_CONFIG+set} != xset ; then + SDL_CONFIG=$sdl_prefix/bin/sdl-config + fi + fi + + AC_REQUIRE([AC_CANONICAL_TARGET]) + PATH="$prefix/bin:$prefix/usr/bin:$PATH" + AC_PATH_PROG(SDL_CONFIG, sdl-config, no, [$PATH]) + min_sdl_version=ifelse([$1], ,0.11.0,$1) + AC_MSG_CHECKING(for SDL - version >= $min_sdl_version) + no_sdl="" + if test "$SDL_CONFIG" = "no" ; then + no_sdl=yes + else + SDL_CFLAGS=`$SDL_CONFIG $sdlconf_args --cflags` + SDL_LIBS=`$SDL_CONFIG $sdlconf_args --libs` + + sdl_major_version=`$SDL_CONFIG $sdl_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + sdl_minor_version=`$SDL_CONFIG $sdl_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + sdl_micro_version=`$SDL_CONFIG $sdl_config_args --version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + if test "x$enable_sdltest" = "xyes" ; then + ac_save_CFLAGS="$CFLAGS" + ac_save_LIBS="$LIBS" + CFLAGS="$CFLAGS $SDL_CFLAGS" + LIBS="$LIBS $SDL_LIBS" +dnl +dnl Now check if the installed SDL is sufficiently new. (Also sanity +dnl checks the results of sdl-config to some extent +dnl + rm -f conf.sdltest + AC_TRY_RUN([ +#include +#include +#include +#include "SDL.h" + +char* +my_strdup (char *str) +{ + char *new_str; + + if (str) + { + new_str = (char *)malloc ((strlen (str) + 1) * sizeof(char)); + strcpy (new_str, str); + } + else + new_str = NULL; + + return new_str; +} + +int main (int argc, char *argv[]) +{ + int major, minor, micro; + char *tmp_version; + + /* This hangs on some systems (?) + system ("touch conf.sdltest"); + */ + { FILE *fp = fopen("conf.sdltest", "a"); if ( fp ) fclose(fp); } + + /* HP/UX 9 (%@#!) writes to sscanf strings */ + tmp_version = my_strdup("$min_sdl_version"); + if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { + printf("%s, bad version string\n", "$min_sdl_version"); + exit(1); + } + + if (($sdl_major_version > major) || + (($sdl_major_version == major) && ($sdl_minor_version > minor)) || + (($sdl_major_version == major) && ($sdl_minor_version == minor) && ($sdl_micro_version >= micro))) + { + return 0; + } + else + { + printf("\n*** 'sdl-config --version' returned %d.%d.%d, but the minimum version\n", $sdl_major_version, $sdl_minor_version, $sdl_micro_version); + printf("*** of SDL required is %d.%d.%d. If sdl-config is correct, then it is\n", major, minor, micro); + printf("*** best to upgrade to the required version.\n"); + printf("*** If sdl-config was wrong, set the environment variable SDL_CONFIG\n"); + printf("*** to point to the correct copy of sdl-config, and remove the file\n"); + printf("*** config.cache before re-running configure\n"); + return 1; + } +} + +],, no_sdl=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + if test "x$no_sdl" = x ; then + AC_MSG_RESULT(yes) + ifelse([$2], , :, [$2]) + else + AC_MSG_RESULT(no) + if test "$SDL_CONFIG" = "no" ; then + echo "*** The sdl-config script installed by SDL could not be found" + echo "*** If SDL was installed in PREFIX, make sure PREFIX/bin is in" + echo "*** your path, or set the SDL_CONFIG environment variable to the" + echo "*** full path to sdl-config." + else + if test -f conf.sdltest ; then + : + else + echo "*** Could not run SDL test program, checking why..." + CFLAGS="$CFLAGS $SDL_CFLAGS" + LIBS="$LIBS $SDL_LIBS" + AC_TRY_LINK([ +#include +#include "SDL.h" + +int main(int argc, char *argv[]) +{ return 0; } +#undef main +#define main K_and_R_C_main +], [ return 0; ], + [ echo "*** The test program compiled, but did not run. This usually means" + echo "*** that the run-time linker is not finding SDL or finding the wrong" + echo "*** version of SDL. If it is not finding SDL, you'll need to set your" + echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" + echo "*** to the installed location Also, make sure you have run ldconfig if that" + echo "*** is required on your system" + echo "***" + echo "*** If you have an old version installed, it is best to remove it, although" + echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], + [ echo "*** The test program failed to compile or link. See the file config.log for the" + echo "*** exact error that occured. This usually means SDL was incorrectly installed" + echo "*** or that you have moved SDL since it was installed. In the latter case, you" + echo "*** may want to edit the sdl-config script: $SDL_CONFIG" ]) + CFLAGS="$ac_save_CFLAGS" + LIBS="$ac_save_LIBS" + fi + fi + SDL_CFLAGS="" + SDL_LIBS="" + ifelse([$3], , :, [$3]) + fi + AC_SUBST(SDL_CFLAGS) + AC_SUBST(SDL_LIBS) + rm -f conf.sdltest +]) diff --git a/config/usrp_fusb_tech.m4 b/config/usrp_fusb_tech.m4 new file mode 100644 index 00000000..78b5af55 --- /dev/null +++ b/config/usrp_fusb_tech.m4 @@ -0,0 +1,55 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. +dnl + +AC_DEFUN([USRP_SET_FUSB_TECHNIQUE],[ + AC_ARG_WITH(fusb-tech, + [ --with-fusb-tech=OS set fast usb technique (auto)], + [cf_with_fusb_tech="$withval"], + [cf_with_fusb_tech="$host_os"]) + + + AC_CHECK_HEADER([linux/usbdevice_fs.h], + [x_have_usbdevice_fs_h=yes], + [x_have_usbdevice_fs_h=no]) + + AC_MSG_CHECKING([for fast usb technique to use]) + case "$cf_with_fusb_tech" in + linux*) if test x${x_have_usbdevice_fs_h} = xyes; + then + FUSB_TECH=linux + else + FUSB_TECH=generic + fi ;; + + darwin*) FUSB_TECH=darwin ;; + cygwin*|win*|mingw*) FUSB_TECH=win32 ;; + *) FUSB_TECH=generic ;; + esac + + AC_MSG_RESULT($FUSB_TECH) + AC_SUBST(FUSB_TECH) + + AM_CONDITIONAL(FUSB_TECH_darwin, test $FUSB_TECH = darwin) + AM_CONDITIONAL(FUSB_TECH_win32, test $FUSB_TECH = win32) + AM_CONDITIONAL(FUSB_TECH_generic, test $FUSB_TECH = generic) + AM_CONDITIONAL(FUSB_TECH_linux, test $FUSB_TECH = linux) +]) + diff --git a/config/usrp_libusb.m4 b/config/usrp_libusb.m4 new file mode 100644 index 00000000..9f670144 --- /dev/null +++ b/config/usrp_libusb.m4 @@ -0,0 +1,51 @@ +# Check for libusb support. -*- Autoconf -*- + +# Copyright 2003 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, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +AC_DEFUN([USRP_LIBUSB], +[ + AC_LANG_PUSH(C) + + libusbok=yes + AC_CHECK_HEADERS([usb.h], + [], + [libusbok=no, + AC_MSG_RESULT([USRP requires libusb. usb.h not found. See http://libusb.sf.net])] + ) + + save_LIBS="$LIBS" + case "$host_os" in + darwin*) LIBS="$LIBS -lIOKit" ;; + *) ;; + esac + AC_SEARCH_LIBS(usb_bulk_write, [usb], + [USB_LIBS="$LIBS"], + [libusbok=no, + AC_MSG_RESULT([USRP requires libusb. usb_bulk_write not found. See http://libusb.sf.net])] + ) + LIBS="$save_LIBS" + + AC_LANG_POP + + if test $libusbok = yes; then + AC_SUBST(USB_LIBS) + ifelse([$1], , :, [$1]) + else + ifelse([$2], , :, [$2]) + fi +]) diff --git a/config/usrp_sdcc.m4 b/config/usrp_sdcc.m4 new file mode 100644 index 00000000..eaf7fdd5 --- /dev/null +++ b/config/usrp_sdcc.m4 @@ -0,0 +1,75 @@ +# Check for sdcc support. -*- Autoconf -*- + +# Copyright 2004 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, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +AC_DEFUN([USRP_SDCC], +[ + sdccok=yes + AC_CHECK_PROG(XCC, sdcc, sdcc -mmcs51 --no-xinit-opt,no) + AC_CHECK_PROG(XAS, asx8051, asx8051 -plosgff,no) + + if test "$XCC" = "no" -o "$XAS" = "no" ; then + AC_MSG_RESULT([USRP requires sdcc. sdcc not found. See http://sdcc.sf.net]) + sdccok=no + else + sdcc_version_min=$1 + + sdcc_version=`sdcc --version 2>&1 | \ + sed 's/\(SDCC.* \)\([[0-9]]*\.[[0-9]]*\.[[0-9]]*\)\( .*$\)/\2/'` + + AC_MSG_CHECKING([sdcc_version "$sdcc_version"]) + + sdcc_major_version=`echo $sdcc_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + sdcc_minor_version=`echo $sdcc_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + sdcc_micro_version=`echo $sdcc_version | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + + sdcc_major_min=`echo $sdcc_version_min | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` + sdcc_minor_min=`echo $sdcc_version_min | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` + sdcc_micro_min=`echo $sdcc_version_min | \ + sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` + + sdcc_version_proper=`expr \ + "$sdcc_major_version" \> "$sdcc_major_min" \| \ + "$sdcc_major_version" \= "$sdcc_major_min" \& \ + "$sdcc_minor_version" \> "$sdcc_minor_min" \| \ + "$sdcc_major_version" \= "$sdcc_major_min" \& \ + "$sdcc_minor_version" \= "$sdcc_minor_min" \& \ + "$sdcc_micro_version" \>= "$sdcc_micro_min" ` + + if test "$sdcc_version_proper" = "1" ; then + AC_MSG_RESULT([$sdcc_major_version.$sdcc_minor_version.$sdcc_micro_version]) + else + sdccok=no + AC_MSG_RESULT([USRP requires sdcc >= $sdcc_version_min. sdcc not found. See http://sdcc.sf.net"]) + fi + + AC_SUBST(XCC) + AC_SUBST(XAS) + fi + + if test $sdccok = yes; then + ifelse([$2], , :, [$2]) + else + ifelse([$3], , :, [$3]) + fi +]) diff --git a/configure.ac b/configure.ac new file mode 100644 index 00000000..410567fc --- /dev/null +++ b/configure.ac @@ -0,0 +1,200 @@ +dnl Copyright 2001,2002,2003,2004,2005,2006 Free Software Foundation, Inc. +dnl +dnl This file is part of GNU Radio +dnl +dnl GNU Radio is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2, or (at your option) +dnl any later version. +dnl +dnl GNU Radio is distributed in the hope that it will be useful, +dnl but WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +dnl GNU General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with GNU Radio; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +dnl Boston, MA 02111-1307, USA. + +AC_INIT +AC_PREREQ(2.57) +AM_CONFIG_HEADER(config.h) +AC_CANONICAL_HOST +AC_CANONICAL_TARGET([]) +AM_INIT_AUTOMAKE(gnuradio,2.8svn) + +GR_X86_64 dnl check for lib64 suffix +LF_CONFIGURE_CC +LF_CONFIGURE_CXX +LF_SET_WARNINGS +GR_SET_GPROF +GR_SET_PROF +GR_PROG_AS +AC_PROG_LN_S +AC_PROG_MAKE_SET +AC_PROG_INSTALL + +AC_LIBTOOL_WIN32_DLL +dnl AC_DISABLE_SHARED dnl don't build shared libraries +AC_ENABLE_SHARED dnl do build shared libraries +AC_DISABLE_STATIC dnl don't build static libraries +AC_PROG_LIBTOOL +GR_FORTRAN + +GR_NO_UNDEFINED dnl do we need the -no-undefined linker flag +GR_SCRIPTING + +dnl Checks for libraries. +AC_CHECK_LIB(socket,socket) + +dnl check for threads (mandatory) +GR_OMNITHREAD + +CFLAGS="${CFLAGS} $PTHREAD_CFLAGS" +CXXFLAGS="${CXXFLAGS} $PTHREAD_CFLAGS" + +if test "x$CXX_FOR_BUILD" = x +then + CXX_FOR_BUILD=${CXX} +fi +AC_SUBST(CXX_FOR_BUILD) + +dnl Check for SysV shm (mandatory) +dnl FIXME this is no longer mandatory. Check the macro. +GR_SYSV_SHM + +dnl Checks for header files. +AC_HEADER_STDC +AC_HEADER_SYS_WAIT +AC_CHECK_HEADERS(fcntl.h limits.h strings.h time.h sys/ioctl.h sys/time.h unistd.h) +AC_CHECK_HEADERS(linux/ppdev.h sys/mman.h sys/select.h sys/types.h) +AC_CHECK_HEADERS(sys/resource.h stdint.h sched.h) + +dnl Checks for typedefs, structures, and compiler characteristics. +AC_C_CONST +AC_C_INLINE +AC_TYPE_SIZE_T +AC_HEADER_TIME +AC_C_BIGENDIAN + +dnl Checks for library functions. +AC_FUNC_ALLOCA +AC_FUNC_SETVBUF_REVERSED +AC_FUNC_VPRINTF +AC_CHECK_FUNCS([mmap select socket strcspn strerror strspn getpagesize sysconf]) +AC_CHECK_FUNCS([snprintf gettimeofday nanosleep sched_setscheduler]) + +AC_CHECK_LIB(m, sincos, [AC_DEFINE([HAVE_SINCOS],[1],[Define to 1 if your system has `sincos'.])]) +AC_CHECK_LIB(m, sincosf,[AC_DEFINE([HAVE_SINCOSF],[1],[Define to 1 if your system has `sincosf'.])]) +AC_CHECK_LIB(m, sinf, [AC_DEFINE([HAVE_SINF],[1],[Define to 1 if your system has `sinf'.])]) +AC_CHECK_LIB(m, cosf, [AC_DEFINE([HAVE_COSF],[1],[Define to 1 if your system has `cosf'.])]) +AC_CHECK_LIB(m, trunc, [AC_DEFINE([HAVE_TRUNC],[1],[Define to 1 if your system has `trunc'.])]) +AH_BOTTOM([ +#ifndef HAVE_TRUNC +#include +inline static double trunc(double x) +{ + return x >= 0 ? floor(x) : ceil(x); +} +#endif +]) + +GR_CHECK_SHM_OPEN +GR_LIBGNURADIO_CORE_EXTRA_LDFLAGS +GR_CHECK_CREATEFILEMAPPING + +dnl Check for Mingw support +GR_PWIN32 + +dnl Do we have "dot", part of the graphviz package from AT&T? +dnl Doxgen will use it to draw pretty diagrams ;-) +AC_CHECK_PROG(HAVE_DOT, [dot],[YES],[NO]) + +PKG_CHECK_MODULES(FFTW3F, fftw3f >= 3.0) +AC_SUBST(FFTW3F_LIBS) + +dnl conditional build stuff +GR_CHECK_DOXYGEN +GR_SET_MD_CPU + +dnl Define where to look for GNURADIO includes +GNURADIO_INCLUDES='-I$(top_srcdir)/gnuradio-core/src/lib/runtime -I$(top_srcdir)/gnuradio-core/src/lib/general -I$(top_srcdir)/gnuradio-core/src/lib/filter -I$(top_srcdir)/gnuradio-core/src/lib/io -I$(top_srcdir)/gnuradio-core/src/lib/g72x -I$(top_srcdir)/gnuradio-core/src/lib/atsc -I$(top_srcdir)/gnuradio-core/src/lib/omnithread -I$(top_builddir)/gnuradio-core/src/lib/general -I$(top_builddir)/gnuradio-core/src/lib/filter -I$(top_builddir)/gnuradio-core/src/lib/reed-solomon -I$(top_builddir)/gnuradio-core/src/lib/swig $(FFTW3F_CFLAGS)' +AC_SUBST(GNURADIO_INCLUDES) + +dnl Define where to look for cppunit includes and libs +dnl sets CPPUNIT_CFLAGS and CPPUNIT_LIBS +AM_PATH_CPPUNIT([1.9.14],[], + [AC_MSG_ERROR([GNU Radio requires cppunit. Stop])]) + +CPPUNIT_INCLUDES=$CPPUNIT_CFLAGS +AC_SUBST(CPPUNIT_INCLUDES) + +dnl Define where to find boost includes +dnl defines BOOST_CFLAGS +GR_REQUIRE_BOOST_INCLUDES + +DEFINES="" +AC_SUBST(DEFINES) + +STD_DEFINES_AND_INCLUDES="$DEFINES $GNURADIO_INCLUDES $BOOST_CFLAGS" +AC_SUBST(STD_DEFINES_AND_INCLUDES) + +dnl Component specific configuration +dnl The order of the GR_ macros determines the order of compilation +subdirs="config" +GR_GNURADIO_CORE +GR_GNURADIO_EXAMPLES +GR_USRP_HW +GR_USRP dnl this must come after GR_USRP_HW +GR_AUDIO_ALSA +GR_AUDIO_JACK +GR_AUDIO_OSS +#GR_AUDIO_PORTAUDIO dnl Disabled until portaudio patch figured out +GR_AUDIO_OSX dnl ***NOT TESTED*** +GR_AUDIO_WINDOWS dnl ***NOT TESTED*** +GR_ATSC +GR_COMEDI +#GR_ERROR_CORRECTING_CODES dnl Disabled until compile error fixed from CVS +GR_GSM_FR_VOCODER +GR_RADAR +GR_RADIO_ASTRONOMY +GR_PMT +GR_VIDEO_SDL +GR_WXGUI + +dnl Has list of successfully configured components +AC_SUBST([subdirs],$subdirs) + +AC_CONFIG_FILES([\ + Makefile \ + config/Makefile +]) + +AC_OUTPUT + +echo +echo "*******************************************************************" +echo The following GNU Radio components have been successfully configured: +echo +for dir in $subdirs +do + echo $dir +done +echo +if test "$failed" != ""; then + echo However, the following components did not configure successfully due to + echo missing dependencies: + echo + for dir in $failed + do + echo $dir + done + echo + echo You may still run the 'make' command to build the successfully configured + echo components. + echo + exit 1 +fi +echo You my now run the 'make' command to build these packages. +echo diff --git a/docs/COPYING b/docs/COPYING new file mode 100644 index 00000000..2b7b643f --- /dev/null +++ b/docs/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) 19yy + + 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 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/docs/ChangeLog b/docs/ChangeLog new file mode 100644 index 00000000..f63303f1 --- /dev/null +++ b/docs/ChangeLog @@ -0,0 +1,24 @@ +2004-11-29 Eric Blossom + + * exploring-gnuradio/exploring-gnuradio.xml: new. revision 1.1 + +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/docs/exploring-gnuradio/Makefile b/docs/exploring-gnuradio/Makefile new file mode 100644 index 00000000..837c2c63 --- /dev/null +++ b/docs/exploring-gnuradio/Makefile @@ -0,0 +1,30 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +TARGETS = exploring-gnuradio.html + +all: $(TARGETS) + +clean: + -rm -f $(TARGETS) + +%.html : %.xml + xmlto html-nochunks $< diff --git a/docs/exploring-gnuradio/ddc.eps b/docs/exploring-gnuradio/ddc.eps new file mode 100644 index 00000000..8931a16a --- /dev/null +++ b/docs/exploring-gnuradio/ddc.eps @@ -0,0 +1,3105 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 755 575 +%%Pages: 0 +%%Creator: Sun Microsystems, Inc. +%%Title: none +%%CreationDate: none +%%LanguageLevel: 2 +%%EndComments +%%BeginPreview: 760 575 1 1725 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000010008000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000300FE001800C100000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000701CF001800C300000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000F03830018000300000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000003F03000018000300000000000 +%00000000000000001F800000000000031800000000000000000000000000780000000000000000 +%000000000000000000000000000000000000000000F00019C03000000000000000000000000000 +%0000000007303000019E0CFC0000000000 +%00000000000000007FE00000000000031800000000000000C00000000000F80000000000000000 +%000000000000000000000000000000000000000001E00019C03000000000000000000000000000 +%000000000030638001FF0C7C0000000000 +%000000000000000060700000000000030000000000000000C00000000000C00000000000000000 +%000000000000000000000000000000000000000003000019E03000000000000000000000000000 +%0000000000307FE001C38C300000000000 +%0000000000000000E0380000000000030000000000000000C00000000000C00000000000000000 +%000000000000000000000000000000000000000003000031F03000000000000000000000000000 +%000000000030787001C18C300000000000 +%0000000000000000E0000C04202002030842002100110181F01000000001F02000000000000000 +%000000000000000000000000000000000000000007C08031B03000000000000000000000000000 +%000000000030703001818C300000000000 +%0000000000000000E0007F86FDF87FC3187FC0FF803F8FF1F8FE001FFC03F9FC00000000000000 +%00000000000000000000000000000000000000000FE7F031B83000000000000000000000000000 +%0000000000307033F181CC300000000000 +%00000000000000007C00E3879FBC78C31879C1CF803F9C70E1C7001FFC00C38E00000000000000 +%0000000000000000000000000000000000000000030E38219C3000000000000000000000000000 +%0000000000307033F981CC300000000000 +%00000000000000003FC0C1C70E0C70631860E30780381838C38300000000C30600000000000000 +%0000000000000000000000000000000000000000030C18618C3000000000000000000000000000 +%00000000003070300181CC300000000000 +%000000000000000007E000C60E0C60631860630380380038C30180000000C30000000000000000 +%0000000000000000000000000000000000000000030C00618E3000000000000000000000000000 +%000000000030303001818C300000000000 +%000000000000000000F001C60E0C60731860670380380038C30380000000C3C000000000000000 +%0000000000000000000000000000000000000000030F804187300001B6DBFFFB6DB00000000000 +%000000000030303001C18C300000000000 +%000000000000000000383FC60E0C60331860670380380FF8C3FF801FFC00C1FC00000000000000 +%00000000000000000000000000000000000000000307F041833000000000000000000000000000 +%0000000000301C6001E30C300000000000 +%0000000000000001C018F8C60E0C60731860670380381E38C300001FFC00C03E00000000000000 +%00000000000000000000000000000000000000000300F8C183B000000000000000000000000000 +%0000000000300FC001FF0C3C0000000000 +%0000000000000001C019C0C60E0C60731860670380383838C30000000000C00700000000000000 +%000000000000000000000000000000000000000003001CC181F000000000000000000000000000 +%0000000000300780019C0C1C0000000000 +%0000000000000000E039C1C60E0C70631860630380383038C30180000000C30700000000000000 +%0000000000000000000000000000000000000000030C0C8180F000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000F071C1C60E0C70E31860638780383078E38380000000C30600000000000000 +%0000000000000000000000000000000000000000030C1D8180F000000000000000080000000000 +%0000000000000000000000000000000000 +%00000000000000007FE0E7C60E0C7FC3186061FF80381CF8F9FF00000000C3DE00000000000000 +%00000000000000000000000000000000000000000307F981807000000000000000040000000000 +%0000000000000000000000000000000000 +%00000000000000001FC07CC60E0C7F83186060FB80380F98787C00000000C0FC00000000000000 +%00000000000000000000000000000000000000000303F181803000000000000000020000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000060000000000300000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000060000000030300000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000060000000038700000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000006000000001FE00000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000060000000007800000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000008000000000 +%0008000000000000000018000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000004000000000 +%000C000180000060000018000000001000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000C000380000060000018000000003000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000004000000000 +%000C000380000060000018000000003000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000C000380000060000018000000003000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%03DC1F87E1F001F87E0019E01F00F87E00 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000001000000000 +%0FFC7FC7C7FC00F0FF001FF83FC3FC7C00 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%1C3C60C38E0C0061C3801C1870E30E3000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000001000000000 +%181C60E38C0C006181801C1CE063043000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000800000000 +%181C00E3800C006300C0181CC033803000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%381C0FE381FC006300C0181CC033F03000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000400000000 +%380C7FE387FC006300C0181CC030FC3000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%181C60E38E0C006300C0181CC0300E3000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%181CC0E38C0C006381C0181CC072063000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%1C1CC0E38C1C00618180181C6067063800 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0E3CE1E38E3C0071C380181C70E38E3800 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000100000000 +%07FC7F61E7EC0078FF00181C3FC1FC1E00 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000100000000 +%01881C60E3C600383C0018080F00F00E00 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000080000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000080000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000040000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000040000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000020000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000020000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000003000000C01803C03FC00000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000003000000C0180FF03FF00000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000003000000C0181E7C38F80000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000C018301C301C0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000008000000 +%000000000000000C018300C301C0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000004000000 +%00000603307E000C0183000301C0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000070330FF800C0183C0030180000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000002000000 +%0000030631C1800C0181FC030380000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000002000000 +%000003063181800C01807F03FF00000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000001863001800C018007C3FF80000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000001000000 +%0000018C303F800C018001C301C0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000018C30FD800C018000E300C0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000800000 +%000000DC31C1800C018600E300E0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000800000 +%000000D83181800E038700E300E0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000F83183800E038380C300C0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000400000 +%0000007031C78007FF03FF83FFC0000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000007030FD8003FE00FF03FF80000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000203070800070003C03FC00000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000200000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000100000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000040000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000020000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000010000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000010000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000004000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000004000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000002600 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000003E00 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000000003FE00 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF0000001FE00 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%00000000000000000000020000000000000000000000000000000000000000000010000000FE00 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000007E00 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000003E00 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000001E00 +%0000000000000000000000000000000000 +%000007000000000004003C00000000000000000000000000000000000F00000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000001E00 +%0000000000000000000000000000000000 +%00000700000000000C007C00000000000000000000000000000000007FE0000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000E00 +%0000000000000000000000000000000000 +%00000700000000000C00600000000000000000000000000000000007FFFE000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000600 +%0000000000000000000000000000000000 +%00000700000000000C0060000000000000000000000000000000001F801F800000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000200 +%0000000000000000000000000000000000 +%00000719E06F03033F01FCDC1E06787800000000000000000000007C0003E00000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000071FF87FC3031F01F8FC7F87FDFC0000000000000000000000F80001F00000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000071E1870E3030C0060E0E1C78F0C0000000000000000000001C00000380000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000071C1C6063030C0060C0C0E7060E00000000000000000000038000001C0000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000071C0C6063030C0060C18067060E00000000000000000000078000000E0000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000007180C6063030C0060C18067060E000000000000000000000CC000001B0000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000007180C6063030C0060C18067060E0000000000000000000018600000318000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000007180C6063030C0060C18067060E0000000000000000000018300000618000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000007180C6063070C0060C1C067060E0000000000000000000030180000C0C000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000001800000000000000000 +%000007180C60E3070C0060C0C0C7060E00000000000000000000300C000180C000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000001800000000000000000 +%000007180C71C38F0C0060C0E1C7060E0000000000000000000060060003006000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000001800000000000000000 +%000007180C7F81FB0F0060C07F87060E0000000000000000000040030006002000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000001800000000000000000 +%000006180C6700F3070060C01E07060600000000000000000000C001800C003000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000001800000000000000000 +%0000000000600000000000000000000000000000000000000000C000C01C003000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000001800000000000000000 +%0000000000600000000000000000000000000000000000000001C0006038003800000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000001800000000000000000 +%0000000000600000000000000000000000000000000000000601C0003070003800000000000000 +%000000000000000000700200000000000000000000000000000000000000000000100000000000 +%0000000060000001800000000000000000 +%00000000006000000000000000000000000000000000000007E1800018E0001800000000000000 +%0000000000000000007F0200000000000000000000000000000000000000000000100000000000 +%000000007E000001800000000000000000 +%00000000000000000000000000000000000000000000000007FD80000DC0001800000000000000 +%0000000000000000007FC200000000000000000000000000000000000000000000100000000000 +%000000007FC00001800000000000000000 +%00000000000000000000000000000000000000000000000007FF80000780001800000000000000 +%0000000000000000007FFA00000003FF0000000060000000000300000000000000100000000000 +%000000007FF00001800000000000000000 +%0000000000000000000000000000000000000000000000000FFF80000700001C00000000000000 +%0000000000000000007FFA00000003FF800000006000000000C300000000000000100000000000 +%00000000FFF00001800000000000000000 +%00000000000000000000000000000000000000000000000007FD80000780001800000000000000 +%0000000000000000007FC20000000301C00000000000000000C000000000000000100000000000 +%000000007FC00001800000000000000000 +%00000000000000000000000000000000000000000000000007F180000DC0001800000000000000 +%0000000000000000007F020000000300E00000000000000000C000000000000000100000000000 +%000000007E000001800000000000000000 +%00000000000001007F0000200000000000000000000000000601800018E0001800000000000000 +%00000000000000000070020000000300601800404210100301E200400420000000100000000000 +%0000000060000001800000000000000000 +%00000000000003807FF003FC0000000000000000000000000001C0003070003800000000000000 +%00000000000000000000020000000300707F03F8637EFC1FE3F31BF03F60000000100000000000 +%0000000000000001800000000000000000 +%00000000000007807FF807FF0000000000000000000000000001C0006038003800000000000000 +%0000000000000000000002000000030030E7871C63CFDE1CF0C31F3879E0000000100000000000 +%0000000000000001800000000000000000 +%00000000000006C0601C0E070000000000000000000000000000C000C018003000000000000000 +%000000000000000000000200000003003181860C6387063030C31C1C60E0000000100000000000 +%0000000000000000000000000000000000 +%00000000000006C0600C1C038000000000000000000000000000C001800C003000000000000000 +%000000000000000000000200000003003181CC006307060030C31C1CE060000000100000000000 +%0000000000000000000000000000000000 +%0000000000000C60600E18018000000000000000000000000000C0030006003000000000000000 +%000000000000000000000200000003003381CC006303060070C3181CC060000000100000000000 +%0000000000000000000000000000000000 +%0000000000000C6060063800000000000000000000000000000040060003002000000000000000 +%0000000000000000000002000000030033FFCC006303060FF0C3181CC060000000100000000000 +%0000000000000000000000000000000000 +%0000000000001C70600638000000000000000000000000000000600C0001806000000000000000 +%0000000000000000000002000000030073800C006303063E30C3181CC060000000100000000000 +%0000000000000000000000000000000000 +%000000000000183060063800000000000000000000000000000020180000C04000000000000000 +%0000000000000000000002000000030063800C006303063030C3181CC060000000100000000000 +%0000000000000000000000000000000000 +%00000000000018306006380000000000000000000000000000003070000060C000000000000000 +%00000000000000000000020000000300E1818E0E6303063030C3181C60E0000000100000000000 +%0000000000000000000000000000000000 +%000000000000383860063800000000000000000000000000000038E0000031C000000000000000 +%00000000000000000000020000000301C1C1860C6303063070C3181C60E0000000100000000000 +%0000000000000000000000000000000000 +%0000000000003FF86006180000000000000000000000000000001CC000001B8000000000000000 +%000000000000000000000200000003FFC0FF87BC63030639F0F3181C3FE0000000100000000000 +%0000000000000000000000000000000000 +%000000000000301C600E180180000000000000000000000000000F8000000F0000000000000000 +%000000000000000000000200000003FF007E01F06303061FB873181C1F60000000100000000000 +%0000000000000000000000000000000000 +%000000000000600C600C1C038000000000000000000000000000070000000E0000000000000000 +%000000000000000000000200000000000000000000000000000000000060000000100000000000 +%0000000000000000000000000000000000 +%000000000000600C601C0E038000000000000000000000000000038000001C0000000000000000 +%000000000000000000000200000000000000000000000000000000004060000000100000000000 +%0000000000000000000000000000000000 +%000000000000E00E6078078F000000000000000000000000000001E00000780000000000000000 +%0000000000000000000002000000000000000000000000000000000061C0000000100000000000 +%0000000000000000000000000000000000 +%000000000000C0067FF003FE000000000000000000000000000000F80001F00000000000000000 +%000000000000000000000200000000000000000000000000000000003F80000000100000000000 +%0000000000000000000000000000000000 +%000000000000C0067FC000F00000000000000000000000000000003E0007C00000000000000000 +%000000000000000000000200000000000000000000000000000000000F00000000100000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000007F07E000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000003FFFC000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000007FE0000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000600000000000000000000 +%00000000000000000000020000000000C000000000007FE0000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000600000000000000000000 +%00000000000000000000020000000000C000000000007FF8000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000600000000000000000000 +%00000000000000000000020000000000C00000000000701C000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000F00000000000000000000 +%00000000000000000000020000000000C00000000000701C000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000F00000000000000000000 +%00000000000000000000020000000000C000E040C080700C0700E00C0000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000F00000000000000000000 +%00000000000000000000020000000000C003F860C180700C3FC3F83F8000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000001F00000000000000000000 +%00000000000000000000020000000000C0071C61E180700C71E31C738000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000001F80000000000000000000 +%00000000000000000000020000000000C00E0E61E180701C60660C61C000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000003F80000000000000000000 +%00000000000000000000020000000000C00C0631E3007FF8006700600000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000003FC0000000000000000000 +%00000000000000000000020000000000C00C0731B3007FF000E3C0780000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000020000000000C00C0733330070003FE1F83F8000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000020000000000C00C071B360070007C607C07C000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000020000000000C00C061B3600700060600E01C000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000020000000000C00C061E1E007000E0E606C0C000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000020000000000C00E0E1E1E007000E0E70E60C000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000020000000000FFC7FC0E1C00700077E3FC7F8000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000020000000000FFC1F00E1C0070003E61F83F0000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000003 +%C00000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000007000000000000003C0000000000000000000000000000000000040000000000000000001F +%FC0000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%00000700000000000C007C000000000000000000000000000000000004000000000000000001FC +%7FC000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%00000700000000000C0060000000000000000000000000000000000004000000000000000007E0 +%07E000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%00000700000000000C006000000000000000000000000000000000000400000000000000001F00 +%00F80000000000000000020000000000000000FFE3180000000000000000000000100000000000 +%0000000000000000000000000000000000 +%00000718E04703021F01F89C1E0238700000000000000000000000000400000000000000007800 +%001C0000000000000000020000000000000000FFE3186000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000071BF07F83033F01FCFC7F87FCFC000000000000000000000000040000000000000000E000 +%000E0000000000000000020000000000000000C000186000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000071F3879C3030C0060FCF1C7CF9C000000000000000000000000040000000000000000E000 +%00070000000000000000020000000000000000C000186000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000071C1C70E3030C0060C0C0C7070E000000000000000000000000040000000000000001E000 +%00038000000000000000020000000000000000C00318F81C046000000000000000100000000000 +%0000000000000000000000000000000000 +%0000071C0C6063030C0060C1C067060E0000000000000000000000000400000000000000033000 +%0007C000000000000000020000000000000000C00318FC7F07F000000000000000100000000000 +%0000000000000000000000000000000000 +%000007180C6063030C0060C18067060E0000000000000000000000000400000000000000061800 +%000CE000000000000000020000000000000000C0031870E387E000000000000000100000000000 +%0000000000000000000000000000000000 +%000007180C6063030C0060C18067060E0000000000000000000000000400000000000000061C00 +%00187000000000000000020000000000000000FFC3186181870000000000000000100000000000 +%0000000000000000000000000000000000 +%000007180C6063030C0060C18067060E0000000000000000000000000400000000000000040E00 +%00307000000000000000020000000000000000FFC3186180C60000000000000000100000000000 +%0000000000000007C00000000000000000 +%000007180C6063030C0060C18067060E00000000000000000000000004000000000000000C0700 +%00603800000000000000020000000000000000C0031861FFC60000000000000000100000000000 +%000000000000001FF00000000000000000 +%000007180C6063070C0060C0C0E7060E0000000000000000000000000400000000000000180380 +%00C03800000000000000020000000000000000C0031861FFC60000000000000000100000000000 +%00000000000000383C0000000000000000 +%000007180C70C3070C0060C0E1C7060E00000000000000000000000004000000000000001801C0 +%01801800000000000000020000000000000000C003186180060000000000000000100000000000 +%00000000000000701C0000000000000000 +%000007180C7FC3FF0F0060C07F87060E00000000000000000000000004000000000000003000E0 +%03001C00000000000000020000000000000000C003186180060000000000000000100000000000 +%00000000000000E00E0000000000000000 +%000007180C6F00F3070060C03F07060E0000000000000000000000000400000000000000300060 +%06000C00000000000000020000000000000000C003186180C60000000000000000100000000000 +%00000000000000C0060000000000000000 +%000000000060000000000000000000000000000000000000000000000400000000000000300030 +%0C000C00000000000000020000000000000000C0031871C1860000000000000000100000000000 +%00000000000001C0070000000000000000 +%000000000060000000000000000000000000000000000000000000000400000000000C00300018 +%18000400000000000070020000000000000000C003187CFF860000000000000000100000000000 +%00000000600001C0070000000000000000 +%000000000060000000000000000000000000000000000000000000000400000000000FE060000E +%3000060000000000007F020000000000000000C003183C3E060000000000000000100000000000 +%000000007E0001C0070000000000000000 +%000000000060000000000000000000000000000000000000000000000400000000000FF8600006 +%6000060000000000007FC200000000000000000000000000000000000000000000100000000000 +%000000007FC001C0070000000000000000 +%000000000060000000000000000000000000000000000000000000000400000000000FFF600003 +%C000060000000000007FFA00000000000000000000000000000000000000000000100000000000 +%00000000FFF001C0070000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000FFE600001 +%C000060000000000007FFA00000000000000000000000000000000000000000000100000000000 +%00000000FFF000C0060000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000FF8600003 +%C000060000000000007FC200000000000000000000000000000000000000000000100000000000 +%000000007FC000C0060000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000FE0600006 +%6000060000000000007F0200000000000000000000000000000000000000000000100000000000 +%000000007E000060EC0000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000C0060000C +%380006000000000000700200000000000000000000000000000000000000000000100000000000 +%00000000600000707C0000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000700018 +%180006000000000000000200000000000000000000000000000000000000000000100000000000 +%000000000000003FFC0000000000000000 +%00000000000003807FE001FC000000000000000000000000000000000400000000000000300030 +%0C000C000000000000000200000000000000000000000000000000000000000000100000000000 +%000000000000000FEE0000000000000000 +%00000000000003807FF807FE000000000000000000000000000000000400000000000000300070 +%07000C000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000030000000000000000 +%00000000000006C0603C0E070000000000000000000000000000000004000000000000003000E0 +%03000C000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%00000000000006C0600C0C038000000000000000000000000000000004000000000000003001C0 +%01801C000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000000000000EE0600E1801800000000000000000000000000000000400000000000000180380 +%00E018000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000000000000C60600E1800000000000000000000000000000000000400000000000000180700 +%007038000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000000000000C60600638000000000000000000000000000000000004000000000000000C0E00 +%003838000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000000000001C70600638000000000000000000000000000000000004000000000000000C1C00 +%001C70000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000183060063800000000000000000000000000000000000400000000000000061800 +%000E70000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000183860063800000000000000000000000000000000000400000000000000033000 +%0007E0000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000000000003FF86006380000000000000000000000000000000000040000000000000001A000 +%000380000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000000000003FF8600E180180000000000000000000000000000000040000000000000000C000 +%000300000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000701C600E1C0180000000000000000000000000000000040000000000000000E000 +%000700000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000600C601C0C03800000000000000000000000000000000400000000000000007C00 +%003E00000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000E00E603C0F07000000000000000000000000000000000400000000000000003E00 +%00FC00000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000E00E7FF807FE000000000000000000000000000000000400000000000000000F80 +%01F000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000C0067FE001F80000000000000000000000000000000004000000000000000003FC +%3F8000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000004000000000000000000FF +%FF0000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000040000000000000000001F +%F80000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000001 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000200000000000000000000000000000000000000000000100000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000003 +%0000000000000000000003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE00000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000003 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000007 +%00000000000000000000000000000000000000000000C000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000007 +%80000000000000000000000000000000000000000000C000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000040000000000000000000F +%80000000000000000000000000000000000000000001E000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000040000000000000000000F +%80000000000000000000000000000000000000000001E000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000040000000000000000000F +%C0000000000000000000000000000000000000000001E000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000040000000000000000000F +%C0000000000000000000000000000000000000000003F000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000040000000000000000000F +%C0000000000000000000000000000000000000000003F000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000040000000000000000001F +%C0000000000000000000000000000000000000000003F000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000000000000000000000000003F000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000000000000000000000000007F800000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%00000000000000000000000000000000000000000000C000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000C00000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000C00000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000800000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000007E0C6FC00400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000E70C7FE00400000000000000000000 +%0007807807C0000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000C38C70600400000000000000000000 +%001FC1FE0FE0000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000C00C60600400000000000000000000 +%003863871870000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000F00C60600400000000000000000000 +%003033039830000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000007E0C60600400000000000000000000 +%007007019800000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000001F8C60600400000000000000000000 +%006007019F80000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000038C60600400000000000000000000 +%0060060187E0000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000818C60600400000000000000000000 +%0060070180F0000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000C18C60600400000000000000000000 +%007037018038000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000E38C60600400000000000000000000 +%003033039838000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000007F0C60600400000000000000000000 +%003863871830000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%001FE1FE0FF0000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%0007807C07C0000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000400000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +%FFFFFFFFFFFFFFFFC0000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000000000001803003E000F800000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000000000001C0300FF803FE00000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000000000001E0303C1C070780000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000000000001E030300C0E0380000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000000000001F030700E1C01C0000 +%00000000000000004000000000000001FF00000000006000018006086000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000000000001B83060001800C0000 +%00000000000000004000000000000001FFC0000000006000018006186000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000000000019C30E0003800E0000 +%0000000000000000400000000000000180C0000000006000000006186000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000000000019C30E0003800E0000 +%0000000000000000400000000000000180E0000000006000000006186000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000000000018E30C0003800E0000 +%0000000000000000400000000000000180603C08E00E66060D80C67E6700000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000000000018630E0003800E0000 +%000000000000000040000000000000018060FF1FF83FE30E0D83F67E6FC0000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000000000018330E0003800E0000 +%0000000000000000400000000000000180C1C71F3871E30E0D871E1878E0000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000183B060061800C0000 +%00000000000000004000000000000001FF83831C1C60E30F198E0E187060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000181B060061800C0000 +%00000000000000004000000000000001FF80031C0CE0630B198C0E186060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000181F0700E0C01C0000 +%0000000000000000400000000000000181E0071C0CE0619B198C06186060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000180F0381C0E0380000 +%000000000000000040000000000000018060FF1C0CC0619B318C06186060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000180701FF807FF00000 +%000000000000000040000000000000018071E31C0CC06199B18C06186060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000180700FF001FC00000 +%000000000000000040000000000000018073831C0CE060F1B18C06186060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000018073031C0C6060F1E18E0E186060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%0000000000000000400000000000000180E3071C0C70E0F0E1861E186060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%00000000000000004000000000000001FFC1FF9C0C3FE070E187FE1E6060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%00000000000000004000000000000001FF80F99C0C0F6060E181E60E6060000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000003E0300000000006000FC00000003 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000FF830000000000C003FF00000003 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000001C1C00000000000C0070780000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000380E00000000000C00E0180000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000380400000000000800C01C0000000 +%000000000000000040000000000000000C000000180000000010C0000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000380031BF81F8001801C0001FC1FC3 +%1BF03F800000000040000000000000000C000000180000000030C0000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000001F0031F3839C001801800039E38E3 +%1F3879C00000000040000000000000000C00000000000000003000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000FE031C1C60600100180007073063 +%1C1860E00000000040000000000000000C00000000000000003000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000001FC31C0C60700300180006033003 +%1C1CC060000000004000000000000001CC07001C18CF0E01F07CC07819E0000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000003C31C0CE070030018000E033C03 +%181CE060000000004000000000000007EC1FC07F18FFBF83FC7CC0FE1BF0000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000E31C0CFFF0030018000E031FC3 +%181CFFE000000000400000000000000E3C38E0E398F1F3861C30C1C71E38000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000300631C0CE00006001C00CE0303E3 +%181CC00000000000400000000000000C1C6070C198E0C18E0C30C3839C18000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000300631C0CE00006000C01CE030073 +%181CC0000000000040000000000000180C60318018E0C1800C30C3019818000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000380631C0C606006000E0186073073 +%181CE0600000000040000000000000180C7FF18018C0C1803C30C301981C000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000003C0C31C0C70600400070387063073 +%181C70E00000000040000000000000180C7FF18018C0C183FC30C701981C000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000001FFC31C0C3DE00C0003FF03DE3DE3 +%181C3BC00000000040000000000000180C60018018C0C1878C30C701981C000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000007F031C0C1F800C0001FC01F80FC3 +%181C1F800000000040000000000000180C60018098C0C18C0C30C301981C000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%0000000000000000400000000000000C1C7031C1D8C0C18C0C30C301981C000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%0000000000000000400000000000000E1C7060C198C0C18C1C30C383981C000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%00000000000000004000000000000007FC3FE07F18C0C187FE3EC1FF181C000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%00000000000000004000000000000003CC0F803E18C0C183E61EC07C181C000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000007E000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000001FF800000000000000006000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000381C00000000000000006000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000700E00000000000000006000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000060060300860030110180F818 +%088000000000000040000000000000001E00000010000000000000380700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000E0001FC0DF81FC3F8FF0F8FE +%0FE000000000000040000000000000003E000000300000000000003C0700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000C0003CE0F9C38E3F9C7061C7 +%0FC0000000000000400000000000000030000000300000000000003C0700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000C0003030E0C3073818386383 +%8E00000000000000400000000000000030000000300000000000003E0700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000C0FE6030C0E6033800386301 +%8C000000000000004000000000000000FE1F00F07E1F037007FF00360700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000C0FF7030C0E7033800386301 +%CC000000000000004000000000000000FE7FC1FC7C3F83F007FF00330700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000C0077FF0C0E7FF380FF86301 +%CC0000000000000040000000000000003061C38E3071C3D0000000338700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000E0076000C0E600381E386301 +%CC00000000000000400000000000000030E0C70630C0E38000000031C700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000E0076000C0E6003838386301 +%CC0000000000000040000000000000003000C60030C0630000000030C700000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000070077030C0E7033830386301 +%8C0000000000000040000000000000003007C60030C0630000000030E700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000381E3870C0E3073830786383 +%8C000000000000004000000000000000303FC60031C0730007FF00307700000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000800000000000001FFC1FE0C0E3FE381CF879FF +%0C0000000000000040000000000000003070C60030C0630007FF00303700000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000008000000000000007F00FC0C0E0FC380F983C7C +%0C00000000000000400000000000000030C0C60230C06300000000303F00000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%0000000000000000400000000000000030C0C60630C06300000000301F00000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%0000000000000000400000000000000030E1C30E38E0E300000000300F00000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%00000000000000004000000000000000307FE3FC3E7FC300000000300F00000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%00000000000000004000000000000000303C60F01E1F0300000000300700000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000080000000000000000000000000000000000000 +%000000000000000040000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF +%FFFFFFFFFFFFFFFFC0000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000018000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000018000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000003C000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000003C000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000003C000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000007C000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000007C000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000FE000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000FE000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000FF000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000FF000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000010000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000001F800000000000000000F000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000007FE00000000C00000001F000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000E0F00000000C000000018000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000001C0300000000C000000018000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000180380000000E000000038000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000380003F837E3F0FC0FC07F7F1FC07EC606 +%0FE0DF81FC60700000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000003800073C3CF0C1CE0FC0187F3CE0E7C606 +%1C70FBC38E70600000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000030000C0C3870C3030E0018703071C1C606 +%3830E0C30630600000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000030000C0E3030C3038C001870603181C606 +%3018C0C60030E00000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000030001C0E3030C7038C001870703181C606 +%3038C0C60038C00000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000030001FFE3030C7FF8C0018707FF180C606 +%3FF8C0C60018C00000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000038019C003030C7000C001870600180C606 +%3000C0C60019800000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000018019C003030C7000C001870600181C606 +%3000C0C6000D800000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000001C030C0C3030C3030C001870703181C606 +%3018C0C6060D000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000E070E0C3030C3830C0018703871C3C70E +%3838C0C3060F000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000007FE07BC3030F1EF0C0018703FE0F7C3FE +%1EF0C0C3DE07000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000003F803F0303070FC0C0018700FC07DC1F6 +%07E0C0C0F806000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000000001C000 +%000000000006000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000000001C000 +%000000000006000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000000001C000 +%00000000001C000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000000001C000 +%000000000038000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000008000 +%000000000030000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000001E000187C00000000000003C0 +%0060F8000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000003E00011FF000C0000000007C0 +%0063FC000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000300003183001C000000000E00 +%00670E000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000300003303801C000000380C00 +%004606000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000FC1802301803E030000381F03 +%00C607000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000FC7F06001803F1FC000381F9F +%C0C006000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000070E706003801C38E000380C18 +%E08006000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000031C386007001C707003FF8C30 +%60800E000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000031C00C00E001C603003FF8C38 +%01801C000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000030F00C01C001C603800380C1E +%018038000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000FE307E0C038001C603800380C0F +%C10070000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000FE300F88070001C603800380C03 +%E300E0000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000003003980E0001C603800380C00 +%7303C0000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000003181981C0001C703000380C30 +%330300000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000031C190380001C307000000C38 +%760600000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000030FF103FF800F3FE000000C1F +%E60FFE000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000307E303FF800F0FC000000C0F +%C60FFF000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%%EndPreview +%%BeginProlog +%%BeginResource: SDRes +/b4_inc_state save def +/dict_count countdictstack def +/op_count count 1 sub def +userdict begin +0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit[] 0 setdash newpath +/languagelevel where {pop languagelevel 1 ne {false setstrokeadjust false setoverprint} if} if +/bdef {bind def} bind def +/c {setgray} bdef +/l {neg lineto} bdef +/rl {neg rlineto} bdef +/lc {setlinecap} bdef +/lj {setlinejoin} bdef +/lw {setlinewidth} bdef +/ml {setmiterlimit} bdef +/ld {setdash} bdef +/m {neg moveto} bdef +/ct {6 2 roll neg 6 2 roll neg 6 2 roll neg curveto} bdef +/r {rotate} bdef +/t {neg translate} bdef +/s {scale} bdef +/sw {show} bdef +/gs {gsave} bdef +/gr {grestore} bdef +/f {findfont dup length dict begin +{1 index /FID ne {def} {pop pop} ifelse} forall /Encoding ISOLatin1Encoding def +currentdict end /NFont exch definefont pop /NFont findfont} bdef +/p {closepath} bdef +/sf {scalefont setfont} bdef +/ef {eofill}bdef +/pc {closepath stroke}bdef +/ps {stroke}bdef +/pum {matrix currentmatrix}bdef +/pom {setmatrix}bdef +/bs {/aString exch def /nXOfs exch def /nWidth exch def currentpoint nXOfs 0 rmoveto pum nWidth aString stringwidth pop div 1 scale aString show pom moveto} bdef +%%EndResource +%%EndProlog +%%BeginSetup +%%EndSetup +%%Page: 1 1 +%%BeginPageSetup +%%EndPageSetup +pum +0.02834 0.02833 s +0 -20290 t +/tm matrix currentmatrix def +gs +tm setmatrix +-635 -635 t +1 1 s +635 635 m 27274 635 l 27274 20924 l 635 20924 l 635 635 l eoclip newpath +0 lw 1 lj 0.000 c 17781 10461 m 14606 10461 l 14606 6016 l 20956 6016 l +20956 10461 l 17781 10461 l pc +gs +pum +15663 7567 t +65 0 m 65 -606 l 274 -606 l 321 -606 357 -603 382 -597 ct 416 -589 446 -575 471 -554 ct +503 -527 526 -492 542 -450 ct 558 -408 566 -360 566 -306 ct 566 -260 561 -219 550 -184 ct +539 -148 525 -119 509 -95 ct 492 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +353 -3 320 0 284 0 ct p +145 -71 m 275 -71 l 315 -71 346 -75 369 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 457 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -371 473 -419 452 -453 ct +431 -487 406 -510 376 -522 ct 355 -530 320 -534 272 -534 ct 145 -534 l p ef +965 -141 m 1042 -131 l 1030 -86 1007 -52 975 -27 ct 942 -2 900 9 849 9 ct +785 9 734 -9 696 -49 ct 658 -88 640 -144 640 -215 ct 640 -289 659 -347 697 -387 ct +735 -428 784 -449 845 -449 ct 903 -449 951 -429 989 -389 ct 1026 -349 1044 -292 1044 -220 ct +1044 -216 1044 -209 1044 -200 ct 716 -200 l 719 -152 733 -115 757 -89 ct 782 -64 813 -51 849 -51 ct +877 -51 900 -58 919 -72 ct 938 -87 l 954 -110 l p +721 -261 m 966 -261 l 963 -298 953 -326 938 -344 ct 914 -373 883 -387 845 -387 ct +811 -387 783 -376 759 -353 ct 736 -330 l 723 -300 l p ef +1427 -160 m 1500 -151 l 1492 -100 1472 -61 1439 -32 ct 1406 -4 1365 9 1317 9 ct +1257 9 1209 -9 1172 -49 ct 1136 -88 1118 -144 1118 -217 ct 1118 -265 1125 -306 1141 -342 ct +1157 -378 1181 -404 1213 -422 ct 1245 -440 1280 -449 1318 -449 ct 1365 -449 1404 -437 1435 -412 ct +1465 -388 1485 -354 1493 -310 ct 1421 -299 l 1414 -328 1402 -350 1384 -365 ct +1367 -380 1345 -387 1321 -387 ct 1283 -387 1253 -374 1229 -347 ct 1206 -320 1194 -278 1194 -220 ct +1194 -161 1205 -118 1228 -91 ct 1251 -64 1280 -51 1317 -51 ct 1346 -51 1370 -60 1390 -78 ct +1409 -96 l 1422 -123 l p ef +1564 -520 m 1564 -606 l 1638 -606 l 1638 -520 l p +1564 0 m 1564 -439 l 1638 -439 l 1638 0 l p ef +1748 0 m 1748 -439 l 1815 -439 l 1815 -377 l 1829 -399 1847 -416 1870 -429 ct +1893 -442 1919 -449 1948 -449 ct 1981 -449 2007 -442 2028 -428 ct 2049 -415 2064 -396 2072 -372 ct +2107 -423 2152 -449 2208 -449 ct 2251 -449 2285 -437 2308 -412 ct 2332 -388 2343 -351 2343 -301 ct +2343 0 l 2269 0 l 2269 -276 l 2269 -306 2267 -327 2262 -340 ct 2257 -354 2249 -364 2236 -372 ct +2223 -380 2208 -384 2191 -384 ct 2160 -384 2135 -374 2114 -353 ct 2094 -333 2084 -300 2084 -255 ct +2084 0 l 2009 0 l 2009 -285 l 2009 -318 2003 -343 1991 -359 ct 1979 -376 1959 -384 1932 -384 ct +1911 -384 1891 -379 1873 -368 ct 1856 -357 1843 -340 1835 -319 ct 1827 -298 1823 -267 1823 -227 ct +1823 0 l p ef +2750 -54 m 2722 -30 2696 -14 2670 -4 ct 2645 5 2617 9 2588 9 ct 2540 9 2503 -1 2477 -25 ct +2451 -49 2438 -79 2438 -115 ct 2438 -137 2443 -156 2453 -174 ct 2463 -192 2475 -206 2491 -217 ct +2507 -228 2525 -236 2545 -241 ct 2559 -245 2581 -249 2611 -253 ct 2671 -260 2715 -268 2744 -278 ct +2744 -288 2744 -295 2744 -298 ct 2744 -328 2737 -349 2723 -362 ct 2704 -379 2676 -387 2638 -387 ct +2603 -387 2577 -381 2561 -369 ct 2544 -356 2532 -335 2524 -303 ct 2451 -313 l +2458 -345 2468 -370 2484 -389 ct 2499 -408 2521 -423 2549 -433 ct 2578 -443 2611 -449 2649 -449 ct +2687 -449 2717 -444 2740 -435 ct 2764 -427 2781 -415 2792 -402 ct 2803 -389 2811 -372 2815 -351 ct +2818 -339 2819 -316 2819 -283 ct 2819 -184 l 2819 -114 2821 -71 2824 -52 ct +2827 -34 2833 -16 2843 0 ct 2765 0 l 2757 -15 l 2752 -33 l p +2744 -220 m 2717 -209 2676 -200 2622 -192 ct 2592 -187 2570 -182 2557 -177 ct +2545 -171 2535 -163 2528 -153 ct 2521 -142 2518 -130 2518 -117 ct 2518 -98 2525 -81 2540 -68 ct +2555 -55 2577 -48 2606 -48 ct 2635 -48 2660 -54 2683 -67 ct 2705 -79 2721 -96 2732 -118 ct +2740 -135 2744 -160 2744 -193 ct p ef +3076 -66 m 3087 0 l 3066 3 3047 5 3030 5 ct 3003 5 2982 1 2968 -7 ct 2953 -15 2942 -26 2936 -40 ct +2930 -54 2927 -83 2927 -128 ct 2927 -381 l 2872 -381 l 2872 -439 l 2927 -439 l +2927 -547 l 3001 -592 l 3001 -439 l 3076 -439 l 3076 -381 l 3001 -381 l +3001 -124 l 3001 -103 3002 -89 3005 -83 ct 3008 -77 3012 -72 3018 -69 ct 3024 -65 3032 -63 3043 -63 ct +3051 -63 l 3062 -64 l p ef +3152 -520 m 3152 -606 l 3226 -606 l 3226 -520 l p +3152 0 m 3152 -439 l 3226 -439 l 3226 0 l p ef +3336 0 m 3336 -439 l 3403 -439 l 3403 -376 l 3436 -425 3482 -449 3543 -449 ct +3570 -449 3594 -444 3616 -434 ct 3638 -425 3655 -412 3666 -397 ct 3677 -382 3685 -363 3689 -342 ct +3692 -328 3693 -304 3693 -270 ct 3693 0 l 3619 0 l 3619 -267 l 3619 -297 3616 -320 3610 -335 ct +3604 -350 3594 -362 3579 -371 ct 3565 -380 3547 -384 3527 -384 ct 3496 -384 3468 -374 3445 -354 ct +3422 -334 3411 -296 3411 -239 ct 3411 0 l p ef +3799 36 m 3871 47 l 3874 69 3883 85 3896 95 ct 3915 109 3940 116 3972 116 ct +4006 116 4033 109 4052 95 ct 4071 82 4083 62 4090 38 ct 4094 22 4095 -8 4095 -57 ct +4063 -19 4022 0 3974 0 ct 3913 0 3867 -21 3833 -65 ct 3800 -108 3784 -161 3784 -222 ct +3784 -264 3791 -302 3807 -338 ct 3822 -373 3844 -400 3873 -420 ct 3901 -439 3935 -449 3974 -449 ct +4026 -449 4069 -428 4102 -386 ct 4102 -439 l 4171 -439 l 4171 -59 l 4171 8 4164 57 4150 85 ct +4136 114 4114 136 4084 153 ct 4054 169 4017 178 3972 178 ct 3920 178 3878 166 3845 142 ct +3813 119 l 3798 83 l p +3860 -227 m 3860 -169 3872 -127 3895 -101 ct 3918 -74 3946 -61 3981 -61 ct +4015 -61 4044 -74 4067 -101 ct 4090 -127 4101 -168 4101 -224 ct 4101 -278 4090 -319 4066 -346 ct +4042 -373 4013 -387 3979 -387 ct 3946 -387 3918 -374 3895 -347 ct 3872 -320 l +3860 -280 l p ef +pom +pum +16007 8520 t +62 0 m 62 -606 l 142 -606 l 142 -71 l 440 -71 l 440 0 l p ef +478 -219 m 478 -300 500 -361 545 -400 ct 583 -432 629 -449 684 -449 ct 744 -449 793 -429 832 -389 ct +870 -350 889 -295 889 -225 ct 889 -169 881 -124 864 -92 ct 847 -60 822 -34 790 -16 ct +757 0 722 9 684 9 ct 622 9 572 -9 534 -49 ct 497 -88 l 478 -145 l p +554 -219 m 554 -163 566 -121 591 -93 ct 615 -65 646 -51 684 -51 ct 721 -51 751 -65 776 -93 ct +800 -121 813 -164 813 -222 ct 813 -276 800 -317 776 -345 ct 751 -373 720 -387 684 -387 ct +646 -387 615 -373 591 -345 ct 566 -317 l 554 -275 l p ef +1062 0 m 928 -439 l 1005 -439 l 1075 -185 l 1101 -91 l 1102 -96 1110 -126 1124 -181 ct +1194 -439 l 1270 -439 l 1336 -184 l 1358 -100 l 1383 -185 l 1458 -439 l +1531 -439 l 1393 0 l 1316 0 l 1246 -263 l 1229 -337 l 1140 0 l p ef +1811 0 m 1811 -606 l 2040 -606 l 2080 -606 2111 -604 2132 -600 ct 2162 -595 2187 -586 2207 -572 ct +2227 -558 2243 -538 2255 -513 ct 2268 -488 2274 -461 2274 -430 ct 2274 -379 2257 -335 2224 -300 ct +2192 -264 2132 -246 2047 -246 ct 1891 -246 l 1891 0 l p +1891 -318 m 2048 -318 l 2100 -318 2136 -327 2158 -346 ct 2180 -366 2191 -393 2191 -428 ct +2191 -453 2185 -475 2172 -493 ct 2159 -511 2142 -523 2121 -529 ct 2108 -532 2083 -534 2046 -534 ct +1891 -534 l p ef +2644 -54 m 2616 -30 2590 -14 2564 -4 ct 2539 5 2511 9 2482 9 ct 2434 9 2397 -1 2371 -25 ct +2345 -49 2332 -79 2332 -115 ct 2332 -137 2337 -156 2347 -174 ct 2357 -192 2369 -206 2385 -217 ct +2401 -228 2419 -236 2439 -241 ct 2453 -245 2475 -249 2505 -253 ct 2565 -260 2609 -268 2638 -278 ct +2638 -288 2638 -295 2638 -298 ct 2638 -328 2631 -349 2617 -362 ct 2598 -379 2570 -387 2532 -387 ct +2497 -387 2471 -381 2455 -369 ct 2438 -356 2426 -335 2418 -303 ct 2345 -313 l +2352 -345 2362 -370 2378 -389 ct 2393 -408 2415 -423 2443 -433 ct 2472 -443 2505 -449 2543 -449 ct +2581 -449 2611 -444 2634 -435 ct 2658 -427 2675 -415 2686 -402 ct 2697 -389 2705 -372 2709 -351 ct +2712 -339 2713 -316 2713 -283 ct 2713 -184 l 2713 -114 2715 -71 2718 -52 ct +2721 -34 2727 -16 2737 0 ct 2659 0 l 2651 -15 l 2646 -33 l p +2638 -220 m 2611 -209 2570 -200 2516 -192 ct 2486 -187 2464 -182 2451 -177 ct +2439 -171 2429 -163 2422 -153 ct 2415 -142 2412 -130 2412 -117 ct 2412 -98 2419 -81 2434 -68 ct +2449 -55 2471 -48 2500 -48 ct 2529 -48 2554 -54 2577 -67 ct 2599 -79 2615 -96 2626 -118 ct +2634 -135 2638 -160 2638 -193 ct p ef +2778 -131 m 2851 -142 l 2855 -113 2867 -90 2886 -74 ct 2905 -59 2931 -51 2965 -51 ct +2999 -51 3024 -58 3041 -72 ct 3058 -86 3066 -102 3066 -121 ct 3066 -138 3059 -151 3044 -160 ct +3034 -167 3008 -175 2968 -186 ct 2913 -199 2875 -211 2854 -221 ct 2833 -231 2817 -245 2806 -263 ct +2795 -281 2790 -301 2790 -322 ct 2790 -342 2794 -360 2803 -376 ct 2812 -393 2825 -407 2840 -418 ct +2852 -427 2867 -434 2887 -440 ct 2907 -446 2929 -449 2952 -449 ct 2986 -449 3016 -444 3042 -434 ct +3069 -424 3088 -410 3100 -393 ct 3113 -376 3121 -354 3126 -325 ct 3053 -315 l +3050 -338 3040 -356 3024 -368 ct 3008 -381 2986 -387 2957 -387 ct 2923 -387 2898 -382 2884 -370 ct +2869 -359 2862 -346 2862 -331 ct 2862 -321 2865 -312 2871 -305 ct 2877 -297 2887 -290 2900 -285 ct +2907 -282 2929 -276 2965 -266 ct 3018 -252 3055 -240 3076 -231 ct 3096 -222 3113 -209 3125 -192 ct +3136 -175 3142 -154 3142 -129 ct 3142 -104 3135 -80 3121 -58 ct 3106 -37 3085 -20 3058 -8 ct +3031 3 3000 9 2965 9 ct 2908 9 2865 -1 2835 -25 ct 2805 -49 l 2786 -84 l p ef +3175 -131 m 3248 -142 l 3252 -113 3264 -90 3283 -74 ct 3302 -59 3328 -51 3362 -51 ct +3396 -51 3421 -58 3438 -72 ct 3455 -86 3463 -102 3463 -121 ct 3463 -138 3456 -151 3441 -160 ct +3431 -167 3405 -175 3365 -186 ct 3310 -199 3272 -211 3251 -221 ct 3230 -231 3214 -245 3203 -263 ct +3192 -281 3187 -301 3187 -322 ct 3187 -342 3191 -360 3200 -376 ct 3209 -393 3222 -407 3237 -418 ct +3249 -427 3264 -434 3284 -440 ct 3304 -446 3326 -449 3349 -449 ct 3383 -449 3413 -444 3439 -434 ct +3466 -424 3485 -410 3497 -393 ct 3510 -376 3518 -354 3523 -325 ct 3450 -315 l +3447 -338 3437 -356 3421 -368 ct 3405 -381 3383 -387 3354 -387 ct 3320 -387 3295 -382 3281 -370 ct +3266 -359 3259 -346 3259 -331 ct 3259 -321 3262 -312 3268 -305 ct 3274 -297 3284 -290 3297 -285 ct +3304 -282 3326 -276 3362 -266 ct 3415 -252 3452 -240 3473 -231 ct 3493 -222 3510 -209 3522 -192 ct +3533 -175 3539 -154 3539 -129 ct 3539 -104 3532 -80 3518 -58 ct 3503 -37 3482 -20 3455 -8 ct +3428 3 3397 9 3362 9 ct 3305 9 3262 -1 3232 -25 ct 3202 -49 l 3183 -84 l p ef +pom +pum +16827 9473 t +69 0 m 69 -606 l 478 -606 l 478 -534 l 149 -534 l 149 -346 l 434 -346 l +434 -275 l 149 -275 l 149 0 l p ef +585 -520 m 585 -606 l 659 -606 l 659 -520 l p +585 0 m 585 -439 l 659 -439 l 659 0 l p ef +768 0 m 768 -606 l 842 -606 l 842 0 l p ef +1118 -66 m 1129 0 l 1108 3 1089 5 1072 5 ct 1045 5 1024 1 1010 -7 ct 995 -15 984 -26 978 -40 ct +972 -54 969 -83 969 -128 ct 969 -381 l 914 -381 l 914 -439 l 969 -439 l +969 -547 l 1043 -592 l 1043 -439 l 1118 -439 l 1118 -381 l 1043 -381 l +1043 -124 l 1043 -103 1044 -89 1047 -83 ct 1050 -77 1054 -72 1060 -69 ct 1066 -65 1074 -63 1085 -63 ct +1093 -63 l 1104 -64 l p ef +1494 -141 m 1571 -131 l 1559 -86 1536 -52 1504 -27 ct 1471 -2 1429 9 1378 9 ct +1314 9 1263 -9 1225 -49 ct 1187 -88 1169 -144 1169 -215 ct 1169 -289 1188 -347 1226 -387 ct +1264 -428 1313 -449 1374 -449 ct 1432 -449 1480 -429 1518 -389 ct 1555 -349 1573 -292 1573 -220 ct +1573 -216 1573 -209 1573 -200 ct 1245 -200 l 1248 -152 1262 -115 1286 -89 ct +1311 -64 1342 -51 1378 -51 ct 1406 -51 1429 -58 1448 -72 ct 1467 -87 l 1483 -110 l +p +1250 -261 m 1495 -261 l 1492 -298 1482 -326 1467 -344 ct 1443 -373 1412 -387 1374 -387 ct +1340 -387 1312 -376 1288 -353 ct 1265 -330 l 1252 -300 l p ef +1669 0 m 1669 -439 l 1736 -439 l 1736 -372 l 1753 -403 1768 -424 1783 -434 ct +1797 -444 1813 -449 1831 -449 ct 1856 -449 1881 -441 1907 -425 ct 1882 -356 l +1863 -366 1845 -372 1827 -372 ct 1811 -372 1796 -367 1783 -357 ct 1770 -347 1761 -334 1755 -316 ct +1747 -290 1743 -261 1743 -229 ct 1743 0 l p ef +pom +gr +11317 10321 m 11312 10318 l 11099 10206 l 11093 10203 l 10924 10032 l +10921 10026 l 10811 9811 l 10808 9805 l 10769 9556 l 10769 9549 l +10808 9299 l 10811 9293 l 10921 9078 l 10924 9072 l 11093 8901 l 11099 8898 l +11312 8786 l 11317 8784 l 11564 8744 l 11571 8744 l 11817 8784 l 11823 8786 l +12036 8898 l 12041 8901 l 12210 9072 l 12213 9078 l 12324 9293 l 12326 9299 l +12366 9549 l 12366 9556 l 12326 9805 l 12324 9811 l 12213 10026 l +12210 10032 l 12041 10203 l 12036 10206 l 11823 10318 l 11817 10321 l +11571 10361 l 11564 10361 l 11317 10321 l p +11567 10319 m 11806 10279 l 12013 10171 l 12178 10004 l 12285 9794 l +12324 9552 l 12285 9310 l 12178 9100 l 12013 8933 l 11806 8825 l 11567 8786 l +11328 8825 l 11121 8933 l 10956 9100 l 10849 9310 l 10811 9552 l 10849 9794 l +10956 10004 l 11121 10171 l 11328 10279 l 11567 10319 l p +11049 9029 m 11079 8998 l 11286 9208 l 11493 9417 l 11700 9627 l 11907 9837 l +12115 10048 l 12085 10078 l 11877 9868 l 11670 9658 l 11463 9448 l +11255 9238 l 11049 9029 l p +11079 10078 m 11049 10049 l 11255 9838 l 11463 9628 l 11670 9418 l +11878 9208 l 12086 8998 l 12115 9029 l 11907 9239 l 11700 9449 l 11493 9659 l +11286 9869 l 11079 10078 l p ef +1 lw 0 lj 11317 10321 m 11312 10318 l 11099 10206 l 11093 10203 l 10924 10032 l +10921 10026 l 10811 9811 l 10808 9805 l 10769 9556 l 10769 9549 l +10808 9299 l 10811 9293 l 10921 9078 l 10924 9072 l 11093 8901 l 11099 8898 l +11312 8786 l 11317 8784 l 11564 8744 l 11571 8744 l 11817 8784 l 11823 8786 l +12036 8898 l 12041 8901 l 12210 9072 l 12213 9078 l 12324 9293 l 12326 9299 l +12366 9549 l 12366 9556 l 12326 9805 l 12324 9811 l 12213 10026 l +12210 10032 l 12041 10203 l 12036 10206 l 11823 10318 l 11817 10321 l +11571 10361 l 11564 10361 l 11317 10321 l pc +11567 10319 m 11806 10279 l 12013 10171 l 12178 10004 l 12285 9794 l +12324 9552 l 12285 9310 l 12178 9100 l 12013 8933 l 11806 8825 l 11567 8786 l +11328 8825 l 11121 8933 l 10956 9100 l 10849 9310 l 10811 9552 l 10849 9794 l +10956 10004 l 11121 10171 l 11328 10279 l 11567 10319 l pc +11049 9029 m 11079 8998 l 11286 9208 l 11493 9417 l 11700 9627 l 11907 9837 l +12115 10048 l 12085 10078 l 11877 9868 l 11670 9658 l 11463 9448 l +11255 9238 l 11049 9029 l pc +11079 10078 m 11049 10049 l 11255 9838 l 11463 9628 l 11670 9418 l +11878 9208 l 12086 8998 l 12115 9029 l 11907 9239 l 11700 9449 l 11493 9659 l +11286 9869 l 11079 10078 l pc +7989 6986 m 7538 6836 l 7539 7136 l 7989 6986 l p ef +5716 6986 m 7629 6986 l ps +14606 6986 m 14155 6836 l 14156 7136 l 14606 6986 l p ef +9526 6986 m 14246 6986 l ps +10769 9526 m 10318 9376 l 10319 9676 l 10769 9526 l p ef +5716 9526 m 10409 9526 l ps +14606 9526 m 14155 9376 l 14156 9676 l 14606 9526 l p ef +12426 9526 m 14246 9526 l ps +0 lw 1 lj 10061 16546 m 6251 16546 l 6251 12736 l 13871 12736 l 13871 16546 l +10061 16546 l pc +gs +pum +9102 13970 t +64 0 m 64 -606 l 146 -606 l 465 -130 l 465 -606 l 542 -606 l 542 0 l +459 0 l 141 -476 l 141 0 l p ef +1106 -212 m 1187 -192 l 1170 -126 1140 -76 1096 -41 ct 1052 -6 999 10 936 10 ct +870 10 817 -2 776 -29 ct 735 -56 704 -94 683 -145 ct 661 -195 651 -249 651 -307 ct +651 -370 663 -425 687 -472 ct 711 -519 745 -555 790 -580 ct 834 -604 883 -616 937 -616 ct +998 -616 1049 -601 1090 -570 ct 1131 -539 1160 -496 1176 -440 ct 1097 -421 l +1083 -465 1063 -497 1036 -517 ct 1009 -537 976 -547 935 -547 ct 889 -547 850 -536 818 -514 ct +787 -492 765 -462 752 -424 ct 740 -386 733 -348 733 -308 ct 733 -256 741 -211 756 -173 ct +771 -134 794 -105 826 -86 ct 858 -67 892 -58 929 -58 ct 974 -58 1012 -71 1043 -97 ct +1074 -123 l 1095 -161 l p ef +1284 -295 m 1284 -395 1311 -474 1366 -531 ct 1420 -588 1489 -617 1575 -617 ct +1631 -617 1681 -603 1726 -576 ct 1771 -550 1805 -512 1829 -465 ct 1852 -417 1864 -362 1864 -302 ct +1864 -240 1852 -185 1827 -137 ct 1802 -88 1767 -52 1722 -27 ct 1676 -2 1627 10 1574 10 ct +1517 10 1466 -3 1421 -31 ct 1376 -58 1342 -96 1319 -143 ct 1296 -191 l 1284 -242 l +p +1367 -294 m 1367 -220 1387 -163 1426 -121 ct 1465 -79 1515 -58 1574 -58 ct +1634 -58 1684 -79 1723 -122 ct 1762 -164 1782 -224 1782 -302 ct 1782 -352 1773 -395 1757 -431 ct +1740 -468 1715 -497 1683 -517 ct 1651 -537 1615 -547 1575 -547 ct 1518 -547 1470 -528 1429 -489 ct +1388 -450 l 1367 -385 l p ef +pom +pum +7514 14923 t +38 -194 m 113 -201 l 117 -171 125 -146 138 -126 ct 151 -107 172 -91 199 -79 ct +227 -67 258 -61 292 -61 ct 323 -61 350 -66 373 -75 ct 397 -84 414 -96 426 -112 ct +437 -128 443 -145 443 -164 ct 443 -183 437 -200 426 -214 ct 415 -228 397 -240 372 -250 ct +355 -256 319 -266 264 -279 ct 208 -293 169 -305 147 -317 ct 118 -332 96 -351 82 -374 ct +68 -396 61 -421 61 -449 ct 61 -480 69 -508 87 -535 ct 104 -561 130 -582 163 -595 ct +196 -609 233 -616 274 -616 ct 319 -616 359 -609 393 -594 ct 427 -580 454 -559 472 -531 ct +491 -502 501 -471 502 -435 ct 425 -429 l 421 -468 407 -496 383 -516 ct 359 -536 324 -545 277 -545 ct +229 -545 194 -537 171 -519 ct 149 -501 138 -480 138 -454 ct 138 -433 146 -415 162 -401 ct +177 -387 217 -372 283 -357 ct 348 -343 393 -330 417 -319 ct 452 -303 478 -282 495 -257 ct +512 -232 520 -203 520 -171 ct 520 -138 511 -108 492 -80 ct 474 -51 447 -29 413 -13 ct +378 2 339 10 296 10 ct 241 10 195 2 158 -13 ct 121 -29 92 -53 71 -85 ct 50 -117 l +39 -154 l p ef +638 -520 m 638 -606 l 712 -606 l 712 -520 l p +638 0 m 638 -439 l 712 -439 l 712 0 l p ef +822 0 m 822 -439 l 889 -439 l 889 -376 l 922 -425 968 -449 1029 -449 ct +1056 -449 1080 -444 1102 -434 ct 1124 -425 1141 -412 1152 -397 ct 1163 -382 1171 -363 1175 -342 ct +1178 -328 1179 -304 1179 -270 ct 1179 0 l 1105 0 l 1105 -267 l 1105 -297 1102 -320 1096 -335 ct +1090 -350 1080 -362 1065 -371 ct 1051 -380 1033 -384 1013 -384 ct 982 -384 954 -374 931 -354 ct +908 -334 897 -296 897 -239 ct 897 0 l p ef +1600 -141 m 1677 -131 l 1665 -86 1642 -52 1610 -27 ct 1577 -2 1535 9 1484 9 ct +1420 9 1369 -9 1331 -49 ct 1293 -88 1275 -144 1275 -215 ct 1275 -289 1294 -347 1332 -387 ct +1370 -428 1419 -449 1480 -449 ct 1538 -449 1586 -429 1624 -389 ct 1661 -349 1679 -292 1679 -220 ct +1679 -216 1679 -209 1679 -200 ct 1351 -200 l 1354 -152 1368 -115 1392 -89 ct +1417 -64 1448 -51 1484 -51 ct 1512 -51 1535 -58 1554 -72 ct 1573 -87 l 1589 -110 l +p +1356 -261 m 1601 -261 l 1598 -298 1588 -326 1573 -344 ct 1549 -373 1518 -387 1480 -387 ct +1446 -387 1418 -376 1394 -353 ct 1371 -330 l 1358 -300 l p ef +1958 10 m 2133 -616 l 2193 -616 l 2017 10 l p ef +2931 -212 m 3012 -192 l 2995 -126 2965 -76 2921 -41 ct 2877 -6 2824 10 2761 10 ct +2695 10 2642 -2 2601 -29 ct 2560 -56 2529 -94 2508 -145 ct 2486 -195 2476 -249 2476 -307 ct +2476 -370 2488 -425 2512 -472 ct 2536 -519 2570 -555 2615 -580 ct 2659 -604 2708 -616 2762 -616 ct +2823 -616 2874 -601 2915 -570 ct 2956 -539 2985 -496 3001 -440 ct 2922 -421 l +2908 -465 2888 -497 2861 -517 ct 2834 -537 2801 -547 2760 -547 ct 2714 -547 2675 -536 2643 -514 ct +2612 -492 2590 -462 2577 -424 ct 2565 -386 2558 -348 2558 -308 ct 2558 -256 2566 -211 2581 -173 ct +2596 -134 2619 -105 2651 -86 ct 2683 -67 2717 -58 2754 -58 ct 2799 -58 2837 -71 2868 -97 ct +2899 -123 l 2920 -161 l p ef +3097 -219 m 3097 -300 3119 -361 3164 -400 ct 3202 -432 3248 -449 3303 -449 ct +3363 -449 3412 -429 3451 -389 ct 3489 -350 3508 -295 3508 -225 ct 3508 -169 3500 -124 3483 -92 ct +3466 -60 3441 -34 3409 -16 ct 3376 0 3341 9 3303 9 ct 3241 9 3191 -9 3153 -49 ct +3116 -88 l 3097 -145 l p +3173 -219 m 3173 -163 3185 -121 3210 -93 ct 3234 -65 3265 -51 3303 -51 ct 3340 -51 3370 -65 3395 -93 ct +3419 -121 3432 -164 3432 -222 ct 3432 -276 3419 -317 3395 -345 ct 3370 -373 3339 -387 3303 -387 ct +3265 -387 3234 -373 3210 -345 ct 3185 -317 l 3173 -275 l p ef +3571 -131 m 3644 -142 l 3648 -113 3660 -90 3679 -74 ct 3698 -59 3724 -51 3758 -51 ct +3792 -51 3817 -58 3834 -72 ct 3851 -86 3859 -102 3859 -121 ct 3859 -138 3852 -151 3837 -160 ct +3827 -167 3801 -175 3761 -186 ct 3706 -199 3668 -211 3647 -221 ct 3626 -231 3610 -245 3599 -263 ct +3588 -281 3583 -301 3583 -322 ct 3583 -342 3587 -360 3596 -376 ct 3605 -393 3618 -407 3633 -418 ct +3645 -427 3660 -434 3680 -440 ct 3700 -446 3722 -449 3745 -449 ct 3779 -449 3809 -444 3835 -434 ct +3862 -424 3881 -410 3893 -393 ct 3906 -376 3914 -354 3919 -325 ct 3846 -315 l +3843 -338 3833 -356 3817 -368 ct 3801 -381 3779 -387 3750 -387 ct 3716 -387 3691 -382 3677 -370 ct +3662 -359 3655 -346 3655 -331 ct 3655 -321 3658 -312 3664 -305 ct 3670 -297 3680 -290 3693 -285 ct +3700 -282 3722 -276 3758 -266 ct 3811 -252 3848 -240 3869 -231 ct 3889 -222 3906 -209 3918 -192 ct +3929 -175 3935 -154 3935 -129 ct 3935 -104 3928 -80 3914 -58 ct 3899 -37 3878 -20 3851 -8 ct +3824 3 3793 9 3758 9 ct 3701 9 3658 -1 3628 -25 ct 3598 -49 l 3579 -84 l p ef +3998 -520 m 3998 -606 l 4072 -606 l 4072 -520 l p +3998 0 m 3998 -439 l 4072 -439 l 4072 0 l p ef +4183 0 m 4183 -439 l 4250 -439 l 4250 -376 l 4283 -425 4329 -449 4390 -449 ct +4417 -449 4441 -444 4463 -434 ct 4485 -425 4502 -412 4513 -397 ct 4524 -382 4532 -363 4536 -342 ct +4539 -328 4540 -304 4540 -270 ct 4540 0 l 4466 0 l 4466 -267 l 4466 -297 4463 -320 4457 -335 ct +4451 -350 4441 -362 4426 -371 ct 4412 -380 4394 -384 4374 -384 ct 4343 -384 4315 -374 4292 -354 ct +4269 -334 4258 -296 4258 -239 ct 4258 0 l p ef +4960 -141 m 5037 -131 l 5025 -86 5002 -52 4970 -27 ct 4937 -2 4895 9 4844 9 ct +4780 9 4729 -9 4691 -49 ct 4653 -88 4635 -144 4635 -215 ct 4635 -289 4654 -347 4692 -387 ct +4730 -428 4779 -449 4840 -449 ct 4898 -449 4946 -429 4984 -389 ct 5021 -349 5039 -292 5039 -220 ct +5039 -216 5039 -209 5039 -200 ct 4711 -200 l 4714 -152 4728 -115 4752 -89 ct +4777 -64 4808 -51 4844 -51 ct 4872 -51 4895 -58 4914 -72 ct 4933 -87 l 4949 -110 l +p +4716 -261 m 4961 -261 l 4958 -298 4948 -326 4933 -344 ct 4909 -373 4878 -387 4840 -387 ct +4806 -387 4778 -376 4754 -353 ct 4731 -330 l 4718 -300 l p ef +pom +pum +8136 15876 t +349 -237 m 349 -308 l 605 -309 l 605 -84 l 566 -52 525 -29 483 -13 ct +441 2 398 10 354 10 ct 295 10 241 -2 192 -27 ct 143 -53 107 -90 82 -138 ct 57 -186 45 -240 45 -300 ct +45 -359 57 -414 82 -465 ct 106 -516 142 -554 188 -579 ct 234 -604 288 -616 348 -616 ct +392 -616 432 -609 467 -595 ct 502 -581 530 -561 550 -535 ct 571 -510 586 -477 596 -436 ct +524 -416 l 515 -447 504 -472 490 -489 ct 476 -507 457 -521 432 -532 ct 407 -542 379 -547 349 -547 ct +312 -547 280 -542 253 -531 ct 227 -520 205 -505 189 -487 ct 172 -468 160 -449 150 -427 ct +135 -389 127 -349 127 -305 ct 127 -251 137 -205 155 -169 ct 174 -133 201 -106 236 -88 ct +272 -70 310 -62 350 -62 ct 385 -62 418 -68 452 -82 ct 485 -95 510 -109 527 -124 ct +527 -237 l p ef +1017 -141 m 1094 -131 l 1082 -86 1059 -52 1027 -27 ct 994 -2 952 9 901 9 ct +837 9 786 -9 748 -49 ct 710 -88 692 -144 692 -215 ct 692 -289 711 -347 749 -387 ct +787 -428 836 -449 897 -449 ct 955 -449 1003 -429 1041 -389 ct 1078 -349 1096 -292 1096 -220 ct +1096 -216 1096 -209 1096 -200 ct 768 -200 l 771 -152 785 -115 809 -89 ct 834 -64 865 -51 901 -51 ct +929 -51 952 -58 971 -72 ct 990 -87 l 1006 -110 l p +773 -261 m 1018 -261 l 1015 -298 1005 -326 990 -344 ct 966 -373 935 -387 897 -387 ct +863 -387 835 -376 811 -353 ct 788 -330 l 775 -300 l p ef +1193 0 m 1193 -439 l 1260 -439 l 1260 -376 l 1293 -425 1339 -449 1400 -449 ct +1427 -449 1451 -444 1473 -434 ct 1495 -425 1512 -412 1523 -397 ct 1534 -382 1542 -363 1546 -342 ct +1549 -328 1550 -304 1550 -270 ct 1550 0 l 1476 0 l 1476 -267 l 1476 -297 1473 -320 1467 -335 ct +1461 -350 1451 -362 1436 -371 ct 1422 -380 1404 -384 1384 -384 ct 1353 -384 1325 -374 1302 -354 ct +1279 -334 1268 -296 1268 -239 ct 1268 0 l p ef +1970 -141 m 2047 -131 l 2035 -86 2012 -52 1980 -27 ct 1947 -2 1905 9 1854 9 ct +1790 9 1739 -9 1701 -49 ct 1663 -88 1645 -144 1645 -215 ct 1645 -289 1664 -347 1702 -387 ct +1740 -428 1789 -449 1850 -449 ct 1908 -449 1956 -429 1994 -389 ct 2031 -349 2049 -292 2049 -220 ct +2049 -216 2049 -209 2049 -200 ct 1721 -200 l 1724 -152 1738 -115 1762 -89 ct +1787 -64 1818 -51 1854 -51 ct 1882 -51 1905 -58 1924 -72 ct 1943 -87 l 1959 -110 l +p +1726 -261 m 1971 -261 l 1968 -298 1958 -326 1943 -344 ct 1919 -373 1888 -387 1850 -387 ct +1816 -387 1788 -376 1764 -353 ct 1741 -330 l 1728 -300 l p ef +2145 0 m 2145 -439 l 2212 -439 l 2212 -372 l 2229 -403 2244 -424 2259 -434 ct +2273 -444 2289 -449 2307 -449 ct 2332 -449 2357 -441 2383 -425 ct 2358 -356 l +2339 -366 2321 -372 2303 -372 ct 2287 -372 2272 -367 2259 -357 ct 2246 -347 2237 -334 2231 -316 ct +2223 -290 2219 -261 2219 -229 ct 2219 0 l p ef +2723 -54 m 2695 -30 2669 -14 2643 -4 ct 2618 5 2590 9 2561 9 ct 2513 9 2476 -1 2450 -25 ct +2424 -49 2411 -79 2411 -115 ct 2411 -137 2416 -156 2426 -174 ct 2436 -192 2448 -206 2464 -217 ct +2480 -228 2498 -236 2518 -241 ct 2532 -245 2554 -249 2584 -253 ct 2644 -260 2688 -268 2717 -278 ct +2717 -288 2717 -295 2717 -298 ct 2717 -328 2710 -349 2696 -362 ct 2677 -379 2649 -387 2611 -387 ct +2576 -387 2550 -381 2534 -369 ct 2517 -356 2505 -335 2497 -303 ct 2424 -313 l +2431 -345 2441 -370 2457 -389 ct 2472 -408 2494 -423 2522 -433 ct 2551 -443 2584 -449 2622 -449 ct +2660 -449 2690 -444 2713 -435 ct 2737 -427 2754 -415 2765 -402 ct 2776 -389 2784 -372 2788 -351 ct +2791 -339 2792 -316 2792 -283 ct 2792 -184 l 2792 -114 2794 -71 2797 -52 ct +2800 -34 2806 -16 2816 0 ct 2738 0 l 2730 -15 l 2725 -33 l p +2717 -220 m 2690 -209 2649 -200 2595 -192 ct 2565 -187 2543 -182 2530 -177 ct +2518 -171 2508 -163 2501 -153 ct 2494 -142 2491 -130 2491 -117 ct 2491 -98 2498 -81 2513 -68 ct +2528 -55 2550 -48 2579 -48 ct 2608 -48 2633 -54 2656 -67 ct 2678 -79 2694 -96 2705 -118 ct +2713 -135 2717 -160 2717 -193 ct p ef +3049 -66 m 3060 0 l 3039 3 3020 5 3003 5 ct 2976 5 2955 1 2941 -7 ct 2926 -15 2915 -26 2909 -40 ct +2903 -54 2900 -83 2900 -128 ct 2900 -381 l 2845 -381 l 2845 -439 l 2900 -439 l +2900 -547 l 2974 -592 l 2974 -439 l 3049 -439 l 3049 -381 l 2974 -381 l +2974 -124 l 2974 -103 2975 -89 2978 -83 ct 2981 -77 2985 -72 2991 -69 ct 2997 -65 3005 -63 3016 -63 ct +3024 -63 l 3035 -64 l p ef +3097 -219 m 3097 -300 3119 -361 3164 -400 ct 3202 -432 3248 -449 3303 -449 ct +3363 -449 3412 -429 3451 -389 ct 3489 -350 3508 -295 3508 -225 ct 3508 -169 3500 -124 3483 -92 ct +3466 -60 3441 -34 3409 -16 ct 3376 0 3341 9 3303 9 ct 3241 9 3191 -9 3153 -49 ct +3116 -88 l 3097 -145 l p +3173 -219 m 3173 -163 3185 -121 3210 -93 ct 3234 -65 3265 -51 3303 -51 ct 3340 -51 3370 -65 3395 -93 ct +3419 -121 3432 -164 3432 -222 ct 3432 -276 3419 -317 3395 -345 ct 3370 -373 3339 -387 3303 -387 ct +3265 -387 3234 -373 3210 -345 ct 3185 -317 l 3173 -275 l p ef +3600 0 m 3600 -439 l 3667 -439 l 3667 -372 l 3684 -403 3699 -424 3714 -434 ct +3728 -444 3744 -449 3762 -449 ct 3787 -449 3812 -441 3838 -425 ct 3813 -356 l +3794 -366 3776 -372 3758 -372 ct 3742 -372 3727 -367 3714 -357 ct 3701 -347 3692 -334 3686 -316 ct +3678 -290 3674 -261 3674 -229 ct 3674 0 l p ef +pom +gr +gs +pum +1284 9366 t +79 0 m 79 -606 l 159 -606 l 159 0 l p ef +293 0 m 293 -439 l 360 -439 l 360 -376 l 393 -425 439 -449 500 -449 ct +527 -449 551 -444 573 -434 ct 595 -425 612 -412 623 -397 ct 634 -382 642 -363 646 -342 ct +649 -328 650 -304 650 -270 ct 650 0 l 576 0 l 576 -267 l 576 -297 573 -320 567 -335 ct +561 -350 551 -362 536 -371 ct 522 -380 504 -384 484 -384 ct 453 -384 425 -374 402 -354 ct +379 -334 368 -296 368 -239 ct 368 0 l p ef +769 168 m 769 -439 l 837 -439 l 837 -382 l 853 -404 871 -421 891 -432 ct +911 -443 936 -449 965 -449 ct 1002 -449 1035 -439 1064 -420 ct 1092 -400 1114 -373 1129 -338 ct +1143 -303 1151 -264 1151 -222 ct 1151 -177 1143 -137 1126 -101 ct 1110 -65 1087 -37 1056 -18 ct +1025 0 993 9 959 9 ct 934 9 912 4 892 -5 ct 873 -16 856 -29 844 -45 ct 844 168 l +p +837 -217 m 837 -160 848 -118 871 -91 ct 894 -64 922 -51 954 -51 ct 987 -51 1016 -65 1039 -93 ct +1063 -121 1075 -164 1075 -223 ct 1075 -279 1063 -321 1040 -349 ct 1017 -376 990 -390 958 -390 ct +926 -390 898 -376 873 -346 ct 849 -316 l 837 -273 l p ef +1507 0 m 1507 -64 l 1473 -14 1427 9 1368 9 ct 1342 9 1318 4 1295 -4 ct 1273 -14 1256 -27 1245 -42 ct +1234 -57 1227 -75 1222 -97 ct 1219 -112 1218 -135 1218 -167 ct 1218 -439 l 1292 -439 l +1292 -195 l 1292 -156 1294 -130 1297 -117 ct 1301 -97 1311 -82 1326 -70 ct +1342 -59 1360 -54 1383 -54 ct 1405 -54 1426 -59 1446 -71 ct 1465 -82 1479 -98 1487 -118 ct +1495 -137 1499 -166 1499 -203 ct 1499 -439 l 1574 -439 l 1574 0 l p ef +1858 -66 m 1869 0 l 1848 3 1829 5 1812 5 ct 1785 5 1764 1 1750 -7 ct 1735 -15 1724 -26 1718 -40 ct +1712 -54 1709 -83 1709 -128 ct 1709 -381 l 1654 -381 l 1654 -439 l 1709 -439 l +1709 -547 l 1783 -592 l 1783 -439 l 1858 -439 l 1858 -381 l 1783 -381 l +1783 -124 l 1783 -103 1784 -89 1787 -83 ct 1790 -77 1794 -72 1800 -69 ct 1806 -65 1814 -63 1825 -63 ct +1833 -63 l 1844 -64 l p ef +2190 0 m 2190 -381 l 2124 -381 l 2124 -439 l 2190 -439 l 2190 -485 l +2190 -515 2193 -537 2198 -551 ct 2205 -571 2218 -586 2236 -598 ct 2254 -610 2279 -616 2312 -616 ct +2333 -616 2356 -614 2381 -609 ct 2370 -544 l 2355 -547 2340 -548 2326 -548 ct +2304 -548 2288 -543 2278 -533 ct 2269 -524 2264 -506 2264 -479 ct 2264 -439 l +2350 -439 l 2350 -381 l 2264 -381 l 2264 0 l p ef +2410 0 m 2410 -439 l 2477 -439 l 2477 -372 l 2494 -403 2509 -424 2524 -434 ct +2538 -444 2554 -449 2572 -449 ct 2597 -449 2622 -441 2648 -425 ct 2623 -356 l +2604 -366 2586 -372 2568 -372 ct 2552 -372 2537 -367 2524 -357 ct 2511 -347 2502 -334 2496 -316 ct +2488 -290 2484 -261 2484 -229 ct 2484 0 l p ef +2674 -219 m 2674 -300 2696 -361 2741 -400 ct 2779 -432 2825 -449 2880 -449 ct +2940 -449 2989 -429 3028 -389 ct 3066 -350 3085 -295 3085 -225 ct 3085 -169 3077 -124 3060 -92 ct +3043 -60 3018 -34 2986 -16 ct 2953 0 2918 9 2880 9 ct 2818 9 2768 -9 2730 -49 ct +2693 -88 l 2674 -145 l p +2750 -219 m 2750 -163 2762 -121 2787 -93 ct 2811 -65 2842 -51 2880 -51 ct 2917 -51 2947 -65 2972 -93 ct +2996 -121 3009 -164 3009 -222 ct 3009 -276 2996 -317 2972 -345 ct 2947 -373 2916 -387 2880 -387 ct +2842 -387 2811 -373 2787 -345 ct 2762 -317 l 2750 -275 l p ef +3177 0 m 3177 -439 l 3244 -439 l 3244 -377 l 3258 -399 3276 -416 3299 -429 ct +3322 -442 3348 -449 3377 -449 ct 3410 -449 3436 -442 3457 -428 ct 3478 -415 3493 -396 3501 -372 ct +3536 -423 3581 -449 3637 -449 ct 3680 -449 3714 -437 3737 -412 ct 3761 -388 3772 -351 3772 -301 ct +3772 0 l 3698 0 l 3698 -276 l 3698 -306 3696 -327 3691 -340 ct 3686 -354 3678 -364 3665 -372 ct +3652 -380 3637 -384 3620 -384 ct 3589 -384 3564 -374 3543 -353 ct 3523 -333 3513 -300 3513 -255 ct +3513 0 l 3438 0 l 3438 -285 l 3438 -318 3432 -343 3420 -359 ct 3408 -376 3388 -384 3361 -384 ct +3340 -384 3320 -379 3302 -368 ct 3285 -357 3272 -340 3264 -319 ct 3256 -298 3252 -267 3252 -227 ct +3252 0 l p ef +pom +pum +2302 10319 t +-1 0 m 231 -606 l 318 -606 l 566 0 l 474 0 l 404 -183 l 150 -183 l +83 0 l p +173 -248 m 379 -248 l 315 -416 l 296 -467 282 -509 272 -542 ct 265 -503 254 -465 240 -426 ct +p ef +621 0 m 621 -606 l 830 -606 l 877 -606 913 -603 938 -597 ct 972 -589 1002 -575 1027 -554 ct +1059 -527 1082 -492 1098 -450 ct 1114 -408 1122 -360 1122 -306 ct 1122 -260 1117 -219 1106 -184 ct +1095 -148 1081 -119 1065 -95 ct 1048 -72 1029 -54 1009 -40 ct 989 -27 965 -17 937 -10 ct +909 -3 876 0 840 0 ct p +701 -71 m 831 -71 l 871 -71 902 -75 925 -82 ct 947 -90 965 -100 979 -114 ct +998 -133 1013 -158 1023 -190 ct 1034 -222 1039 -261 1039 -307 ct 1039 -371 1029 -419 1008 -453 ct +987 -487 962 -510 932 -522 ct 911 -530 876 -534 828 -534 ct 701 -534 l p ef +1661 -212 m 1742 -192 l 1725 -126 1695 -76 1651 -41 ct 1607 -6 1554 10 1491 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -555 1345 -580 ct 1389 -604 1438 -616 1492 -616 ct +1553 -616 1604 -601 1645 -570 ct 1686 -539 1715 -496 1731 -440 ct 1652 -421 l +1638 -465 1618 -497 1591 -517 ct 1564 -537 1531 -547 1490 -547 ct 1444 -547 1405 -536 1373 -514 ct +1342 -492 1320 -462 1307 -424 ct 1295 -386 1288 -348 1288 -308 ct 1288 -256 1296 -211 1311 -173 ct +1326 -134 1349 -105 1381 -86 ct 1413 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -123 l 1650 -161 l p ef +pom +gr +gs +pum +1284 6773 t +79 0 m 79 -606 l 159 -606 l 159 0 l p ef +293 0 m 293 -439 l 360 -439 l 360 -376 l 393 -425 439 -449 500 -449 ct +527 -449 551 -444 573 -434 ct 595 -425 612 -412 623 -397 ct 634 -382 642 -363 646 -342 ct +649 -328 650 -304 650 -270 ct 650 0 l 576 0 l 576 -267 l 576 -297 573 -320 567 -335 ct +561 -350 551 -362 536 -371 ct 522 -380 504 -384 484 -384 ct 453 -384 425 -374 402 -354 ct +379 -334 368 -296 368 -239 ct 368 0 l p ef +769 168 m 769 -439 l 837 -439 l 837 -382 l 853 -404 871 -421 891 -432 ct +911 -443 936 -449 965 -449 ct 1002 -449 1035 -439 1064 -420 ct 1092 -400 1114 -373 1129 -338 ct +1143 -303 1151 -264 1151 -222 ct 1151 -177 1143 -137 1126 -101 ct 1110 -65 1087 -37 1056 -18 ct +1025 0 993 9 959 9 ct 934 9 912 4 892 -5 ct 873 -16 856 -29 844 -45 ct 844 168 l +p +837 -217 m 837 -160 848 -118 871 -91 ct 894 -64 922 -51 954 -51 ct 987 -51 1016 -65 1039 -93 ct +1063 -121 1075 -164 1075 -223 ct 1075 -279 1063 -321 1040 -349 ct 1017 -376 990 -390 958 -390 ct +926 -390 898 -376 873 -346 ct 849 -316 l 837 -273 l p ef +1507 0 m 1507 -64 l 1473 -14 1427 9 1368 9 ct 1342 9 1318 4 1295 -4 ct 1273 -14 1256 -27 1245 -42 ct +1234 -57 1227 -75 1222 -97 ct 1219 -112 1218 -135 1218 -167 ct 1218 -439 l 1292 -439 l +1292 -195 l 1292 -156 1294 -130 1297 -117 ct 1301 -97 1311 -82 1326 -70 ct +1342 -59 1360 -54 1383 -54 ct 1405 -54 1426 -59 1446 -71 ct 1465 -82 1479 -98 1487 -118 ct +1495 -137 1499 -166 1499 -203 ct 1499 -439 l 1574 -439 l 1574 0 l p ef +1858 -66 m 1869 0 l 1848 3 1829 5 1812 5 ct 1785 5 1764 1 1750 -7 ct 1735 -15 1724 -26 1718 -40 ct +1712 -54 1709 -83 1709 -128 ct 1709 -381 l 1654 -381 l 1654 -439 l 1709 -439 l +1709 -547 l 1783 -592 l 1783 -439 l 1858 -439 l 1858 -381 l 1783 -381 l +1783 -124 l 1783 -103 1784 -89 1787 -83 ct 1790 -77 1794 -72 1800 -69 ct 1806 -65 1814 -63 1825 -63 ct +1833 -63 l 1844 -64 l p ef +2190 0 m 2190 -381 l 2124 -381 l 2124 -439 l 2190 -439 l 2190 -485 l +2190 -515 2193 -537 2198 -551 ct 2205 -571 2218 -586 2236 -598 ct 2254 -610 2279 -616 2312 -616 ct +2333 -616 2356 -614 2381 -609 ct 2370 -544 l 2355 -547 2340 -548 2326 -548 ct +2304 -548 2288 -543 2278 -533 ct 2269 -524 2264 -506 2264 -479 ct 2264 -439 l +2350 -439 l 2350 -381 l 2264 -381 l 2264 0 l p ef +2410 0 m 2410 -439 l 2477 -439 l 2477 -372 l 2494 -403 2509 -424 2524 -434 ct +2538 -444 2554 -449 2572 -449 ct 2597 -449 2622 -441 2648 -425 ct 2623 -356 l +2604 -366 2586 -372 2568 -372 ct 2552 -372 2537 -367 2524 -357 ct 2511 -347 2502 -334 2496 -316 ct +2488 -290 2484 -261 2484 -229 ct 2484 0 l p ef +2674 -219 m 2674 -300 2696 -361 2741 -400 ct 2779 -432 2825 -449 2880 -449 ct +2940 -449 2989 -429 3028 -389 ct 3066 -350 3085 -295 3085 -225 ct 3085 -169 3077 -124 3060 -92 ct +3043 -60 3018 -34 2986 -16 ct 2953 0 2918 9 2880 9 ct 2818 9 2768 -9 2730 -49 ct +2693 -88 l 2674 -145 l p +2750 -219 m 2750 -163 2762 -121 2787 -93 ct 2811 -65 2842 -51 2880 -51 ct 2917 -51 2947 -65 2972 -93 ct +2996 -121 3009 -164 3009 -222 ct 3009 -276 2996 -317 2972 -345 ct 2947 -373 2916 -387 2880 -387 ct +2842 -387 2811 -373 2787 -345 ct 2762 -317 l 2750 -275 l p ef +3177 0 m 3177 -439 l 3244 -439 l 3244 -377 l 3258 -399 3276 -416 3299 -429 ct +3322 -442 3348 -449 3377 -449 ct 3410 -449 3436 -442 3457 -428 ct 3478 -415 3493 -396 3501 -372 ct +3536 -423 3581 -449 3637 -449 ct 3680 -449 3714 -437 3737 -412 ct 3761 -388 3772 -351 3772 -301 ct +3772 0 l 3698 0 l 3698 -276 l 3698 -306 3696 -327 3691 -340 ct 3686 -354 3678 -364 3665 -372 ct +3652 -380 3637 -384 3620 -384 ct 3589 -384 3564 -374 3543 -353 ct 3523 -333 3513 -300 3513 -255 ct +3513 0 l 3438 0 l 3438 -285 l 3438 -318 3432 -343 3420 -359 ct 3408 -376 3388 -384 3361 -384 ct +3340 -384 3320 -379 3302 -368 ct 3285 -357 3272 -340 3264 -319 ct 3256 -298 3252 -267 3252 -227 ct +3252 0 l p ef +pom +pum +2302 7726 t +-1 0 m 231 -606 l 318 -606 l 566 0 l 474 0 l 404 -183 l 150 -183 l +83 0 l p +173 -248 m 379 -248 l 315 -416 l 296 -467 282 -509 272 -542 ct 265 -503 254 -465 240 -426 ct +p ef +621 0 m 621 -606 l 830 -606 l 877 -606 913 -603 938 -597 ct 972 -589 1002 -575 1027 -554 ct +1059 -527 1082 -492 1098 -450 ct 1114 -408 1122 -360 1122 -306 ct 1122 -260 1117 -219 1106 -184 ct +1095 -148 1081 -119 1065 -95 ct 1048 -72 1029 -54 1009 -40 ct 989 -27 965 -17 937 -10 ct +909 -3 876 0 840 0 ct p +701 -71 m 831 -71 l 871 -71 902 -75 925 -82 ct 947 -90 965 -100 979 -114 ct +998 -133 1013 -158 1023 -190 ct 1034 -222 1039 -261 1039 -307 ct 1039 -371 1029 -419 1008 -453 ct +987 -487 962 -510 932 -522 ct 911 -530 876 -534 828 -534 ct 701 -534 l p ef +1661 -212 m 1742 -192 l 1725 -126 1695 -76 1651 -41 ct 1607 -6 1554 10 1491 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -555 1345 -580 ct 1389 -604 1438 -616 1492 -616 ct +1553 -616 1604 -601 1645 -570 ct 1686 -539 1715 -496 1731 -440 ct 1652 -421 l +1638 -465 1618 -497 1591 -517 ct 1564 -537 1531 -547 1490 -547 ct 1444 -547 1405 -536 1373 -514 ct +1342 -492 1320 -462 1307 -424 ct 1295 -386 1288 -348 1288 -308 ct 1288 -256 1296 -211 1311 -173 ct +1326 -134 1349 -105 1381 -86 ct 1413 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -123 l 1650 -161 l p ef +pom +gr +8442 7781 m 8437 7778 l 8224 7666 l 8218 7663 l 8049 7492 l 8046 7486 l +7936 7271 l 7933 7265 l 7894 7016 l 7894 7009 l 7933 6759 l 7936 6753 l +8046 6538 l 8049 6532 l 8218 6361 l 8224 6358 l 8437 6246 l 8442 6244 l +8689 6204 l 8696 6204 l 8942 6244 l 8948 6246 l 9161 6358 l 9166 6361 l +9335 6532 l 9338 6538 l 9449 6753 l 9451 6759 l 9491 7009 l 9491 7016 l +9451 7265 l 9449 7271 l 9338 7486 l 9335 7492 l 9166 7663 l 9161 7666 l +8948 7778 l 8942 7781 l 8696 7821 l 8689 7821 l 8442 7781 l p +8692 7779 m 8931 7739 l 9138 7631 l 9303 7464 l 9410 7254 l 9449 7012 l +9410 6770 l 9303 6560 l 9138 6393 l 8931 6285 l 8692 6246 l 8453 6285 l +8246 6393 l 8081 6560 l 7974 6770 l 7936 7012 l 7974 7254 l 8081 7464 l +8246 7631 l 8453 7739 l 8692 7779 l p +8174 6489 m 8204 6458 l 8411 6668 l 8618 6877 l 8825 7087 l 9032 7297 l +9240 7508 l 9210 7538 l 9002 7328 l 8795 7118 l 8588 6908 l 8380 6698 l +8174 6489 l p +8204 7538 m 8174 7509 l 8380 7298 l 8588 7088 l 8795 6878 l 9003 6668 l +9211 6458 l 9240 6489 l 9032 6699 l 8825 6909 l 8618 7119 l 8411 7329 l +8204 7538 l p ef +1 lw 0 lj 8442 7781 m 8437 7778 l 8224 7666 l 8218 7663 l 8049 7492 l +8046 7486 l 7936 7271 l 7933 7265 l 7894 7016 l 7894 7009 l 7933 6759 l +7936 6753 l 8046 6538 l 8049 6532 l 8218 6361 l 8224 6358 l 8437 6246 l +8442 6244 l 8689 6204 l 8696 6204 l 8942 6244 l 8948 6246 l 9161 6358 l +9166 6361 l 9335 6532 l 9338 6538 l 9449 6753 l 9451 6759 l 9491 7009 l +9491 7016 l 9451 7265 l 9449 7271 l 9338 7486 l 9335 7492 l 9166 7663 l +9161 7666 l 8948 7778 l 8942 7781 l 8696 7821 l 8689 7821 l 8442 7781 l +pc +8692 7779 m 8931 7739 l 9138 7631 l 9303 7464 l 9410 7254 l 9449 7012 l +9410 6770 l 9303 6560 l 9138 6393 l 8931 6285 l 8692 6246 l 8453 6285 l +8246 6393 l 8081 6560 l 7974 6770 l 7936 7012 l 7974 7254 l 8081 7464 l +8246 7631 l 8453 7739 l 8692 7779 l pc +8174 6489 m 8204 6458 l 8411 6668 l 8618 6877 l 8825 7087 l 9032 7297 l +9240 7508 l 9210 7538 l 9002 7328 l 8795 7118 l 8588 6908 l 8380 6698 l +8174 6489 l pc +8204 7538 m 8174 7509 l 8380 7298 l 8588 7088 l 8795 6878 l 9003 6668 l +9211 6458 l 9240 6489 l 9032 6699 l 8825 6909 l 8618 7119 l 8411 7329 l +8204 7538 l pc +8691 7821 m 8541 8271 l 8841 8270 l 8691 7821 l p ef +8691 8181 m 8691 12701 l ps +11531 10361 m 11381 10811 l 11681 10810 l 11531 10361 l p ef +11531 10721 m 11531 12701 l ps +gs +pum +7329 12171 t +26 -131 m 99 -142 l 103 -113 115 -90 134 -74 ct 153 -59 179 -51 213 -51 ct +247 -51 272 -58 289 -72 ct 306 -86 314 -102 314 -121 ct 314 -138 307 -151 292 -160 ct +282 -167 256 -175 216 -186 ct 161 -199 123 -211 102 -221 ct 81 -231 65 -245 54 -263 ct +43 -281 38 -301 38 -322 ct 38 -342 42 -360 51 -376 ct 60 -393 73 -407 88 -418 ct +100 -427 115 -434 135 -440 ct 155 -446 177 -449 200 -449 ct 234 -449 264 -444 290 -434 ct +317 -424 336 -410 348 -393 ct 361 -376 369 -354 374 -325 ct 301 -315 l 298 -338 288 -356 272 -368 ct +256 -381 234 -387 205 -387 ct 171 -387 146 -382 132 -370 ct 117 -359 110 -346 110 -331 ct +110 -321 113 -312 119 -305 ct 125 -297 135 -290 148 -285 ct 155 -282 177 -276 213 -266 ct +266 -252 303 -240 324 -231 ct 344 -222 361 -209 373 -192 ct 384 -175 390 -154 390 -129 ct +390 -104 383 -80 369 -58 ct 354 -37 333 -20 306 -8 ct 279 3 248 9 213 9 ct 156 9 113 -1 83 -25 ct +53 -49 l 34 -84 l p ef +453 -520 m 453 -606 l 527 -606 l 527 -520 l p +453 0 m 453 -439 l 527 -439 l 527 0 l p ef +637 0 m 637 -439 l 704 -439 l 704 -376 l 737 -425 783 -449 844 -449 ct +871 -449 895 -444 917 -434 ct 939 -425 956 -412 967 -397 ct 978 -382 986 -363 990 -342 ct +993 -328 994 -304 994 -270 ct 994 0 l 920 0 l 920 -267 l 920 -297 917 -320 911 -335 ct +905 -350 895 -362 880 -371 ct 866 -380 848 -384 828 -384 ct 797 -384 769 -374 746 -354 ct +723 -334 712 -296 712 -239 ct 712 0 l p ef +pom +gr +gs +pum +11880 12223 t +342 -160 m 415 -151 l 407 -100 387 -61 354 -32 ct 321 -4 280 9 232 9 ct 172 9 124 -9 87 -49 ct +51 -88 33 -144 33 -217 ct 33 -265 40 -306 56 -342 ct 72 -378 96 -404 128 -422 ct +160 -440 195 -449 233 -449 ct 280 -449 319 -437 350 -412 ct 380 -388 400 -354 408 -310 ct +336 -299 l 329 -328 317 -350 299 -365 ct 282 -380 260 -387 236 -387 ct 198 -387 168 -374 144 -347 ct +121 -320 109 -278 109 -220 ct 109 -161 120 -118 143 -91 ct 166 -64 195 -51 232 -51 ct +261 -51 285 -60 305 -78 ct 324 -96 l 337 -123 l p ef +451 -219 m 451 -300 473 -361 518 -400 ct 556 -432 602 -449 657 -449 ct 717 -449 766 -429 805 -389 ct +843 -350 862 -295 862 -225 ct 862 -169 854 -124 837 -92 ct 820 -60 795 -34 763 -16 ct +730 0 695 9 657 9 ct 595 9 545 -9 507 -49 ct 470 -88 l 451 -145 l p +527 -219 m 527 -163 539 -121 564 -93 ct 588 -65 619 -51 657 -51 ct 694 -51 724 -65 749 -93 ct +773 -121 786 -164 786 -222 ct 786 -276 773 -317 749 -345 ct 724 -373 693 -387 657 -387 ct +619 -387 588 -373 564 -345 ct 539 -317 l 527 -275 l p ef +926 -131 m 999 -142 l 1003 -113 1015 -90 1034 -74 ct 1053 -59 1079 -51 1113 -51 ct +1147 -51 1172 -58 1189 -72 ct 1206 -86 1214 -102 1214 -121 ct 1214 -138 1207 -151 1192 -160 ct +1182 -167 1156 -175 1116 -186 ct 1061 -199 1023 -211 1002 -221 ct 981 -231 965 -245 954 -263 ct +943 -281 938 -301 938 -322 ct 938 -342 942 -360 951 -376 ct 960 -393 973 -407 988 -418 ct +1000 -427 1015 -434 1035 -440 ct 1055 -446 1077 -449 1100 -449 ct 1134 -449 1164 -444 1190 -434 ct +1217 -424 1236 -410 1248 -393 ct 1261 -376 1269 -354 1274 -325 ct 1201 -315 l +1198 -338 1188 -356 1172 -368 ct 1156 -381 1134 -387 1105 -387 ct 1071 -387 1046 -382 1032 -370 ct +1017 -359 1010 -346 1010 -331 ct 1010 -321 1013 -312 1019 -305 ct 1025 -297 1035 -290 1048 -285 ct +1055 -282 1077 -276 1113 -266 ct 1166 -252 1203 -240 1224 -231 ct 1244 -222 1261 -209 1273 -192 ct +1284 -175 1290 -154 1290 -129 ct 1290 -104 1283 -80 1269 -58 ct 1254 -37 1233 -20 1206 -8 ct +1179 3 1148 9 1113 9 ct 1056 9 1013 -1 983 -25 ct 953 -49 l 934 -84 l p ef +pom +gr +24131 6986 m 23680 6836 l 23681 7136 l 24131 6986 l p ef +20956 6986 m 23771 6986 l ps +24131 9526 m 23680 9376 l 23681 9676 l 24131 9526 l p ef +20956 9526 m 23771 9526 l ps +gs +pum +24646 7223 t +79 0 m 79 -606 l 159 -606 l 159 0 l p ef +pom +gr +gs +pum +24435 9763 t +524 -64 m 562 -39 596 -20 627 -8 ct 604 47 l 560 31 517 6 473 -27 ct 429 -2 379 10 325 10 ct +270 10 220 -2 175 -29 ct 131 -55 96 -93 72 -141 ct 48 -189 36 -243 36 -303 ct 36 -362 48 -417 72 -466 ct +97 -515 131 -552 176 -578 ct 221 -604 271 -617 326 -617 ct 382 -617 433 -603 478 -577 ct +523 -550 557 -513 580 -465 ct 604 -417 616 -363 616 -303 ct 616 -253 608 -208 593 -168 ct +578 -129 l 555 -94 l p +348 -167 m 394 -154 432 -135 462 -109 ct 509 -152 533 -217 533 -303 ct 533 -352 525 -395 508 -432 ct +491 -468 467 -497 435 -517 ct 403 -537 367 -547 327 -547 ct 267 -547 217 -527 178 -486 ct +138 -445 119 -384 119 -303 ct 119 -224 138 -163 177 -121 ct 216 -79 266 -58 327 -58 ct +355 -58 382 -63 408 -74 ct 383 -90 356 -102 328 -109 ct p ef +pom +gr +gs +pum +23747 3307 t +315 0 m 241 0 l 241 -474 l 223 -457 199 -440 170 -423 ct 141 -405 115 -393 92 -384 ct +92 -456 l 133 -476 170 -499 201 -527 ct 232 -555 254 -582 267 -608 ct 315 -608 l +p ef +897 -457 m 823 -452 l 816 -481 807 -502 795 -515 ct 775 -536 750 -547 720 -547 ct +697 -547 676 -540 658 -527 ct 634 -510 616 -485 602 -452 ct 589 -420 582 -373 581 -312 ct +599 -339 621 -360 647 -373 ct 673 -386 700 -393 729 -393 ct 778 -393 820 -375 855 -338 ct +890 -301 908 -254 908 -196 ct 908 -158 899 -123 883 -90 ct 867 -58 844 -33 815 -15 ct +787 1 754 10 718 10 ct 656 10 605 -12 566 -58 ct 527 -103 507 -178 507 -283 ct +507 -400 529 -486 572 -539 ct 610 -585 661 -608 725 -608 ct 773 -608 812 -595 842 -568 ct +873 -541 l 891 -504 l p +593 -196 m 593 -170 598 -146 609 -122 ct 620 -99 635 -81 655 -69 ct 675 -57 695 -50 717 -50 ct +748 -50 775 -63 798 -88 ct 820 -114 832 -148 832 -192 ct 832 -234 820 -267 798 -291 ct +776 -315 748 -327 714 -327 ct 680 -327 652 -315 628 -291 ct 605 -267 l 593 -235 l +p ef +952 -181 m 952 -256 l 1181 -256 l 1181 -181 l p ef +1341 0 m 1272 0 l 1272 -606 l 1346 -606 l 1346 -390 l 1378 -429 1418 -449 1467 -449 ct +1494 -449 1519 -443 1543 -432 ct 1568 -421 1587 -406 1603 -386 ct 1619 -367 1631 -343 1640 -315 ct +1648 -287 1653 -257 1653 -226 ct 1653 -150 1634 -92 1597 -51 ct 1560 -10 1515 9 1463 9 ct +1411 9 1370 -11 1341 -55 ct p +1340 -222 m 1340 -170 1347 -132 1362 -108 ct 1385 -70 1417 -51 1457 -51 ct +1489 -51 1517 -65 1541 -93 ct 1565 -121 1577 -164 1577 -220 ct 1577 -277 1565 -319 1543 -346 ct +1520 -374 1492 -387 1460 -387 ct 1428 -387 1399 -373 1376 -345 ct 1352 -317 l +1340 -276 l p ef +1723 -520 m 1723 -606 l 1797 -606 l 1797 -520 l p +1723 0 m 1723 -439 l 1797 -439 l 1797 0 l p ef +2070 -66 m 2081 0 l 2060 3 2041 5 2024 5 ct 1997 5 1976 1 1962 -7 ct 1947 -15 1936 -26 1930 -40 ct +1924 -54 1921 -83 1921 -128 ct 1921 -381 l 1866 -381 l 1866 -439 l 1921 -439 l +1921 -547 l 1995 -592 l 1995 -439 l 2070 -439 l 2070 -381 l 1995 -381 l +1995 -124 l 1995 -103 1996 -89 1999 -83 ct 2002 -77 2006 -72 2012 -69 ct 2018 -65 2026 -63 2037 -63 ct +2045 -63 l 2056 -64 l p ef +pom +pum +22596 4260 t +340 0 m 340 -55 l 312 -11 272 9 217 9 ct 182 9 150 0 121 -19 ct 92 -38 69 -65 53 -99 ct +37 -134 28 -174 28 -219 ct 28 -263 36 -302 50 -338 ct 65 -374 87 -401 116 -420 ct +145 -439 178 -449 214 -449 ct 241 -449 264 -443 285 -432 ct 306 -421 322 -406 335 -388 ct +335 -606 l 409 -606 l 409 0 l p +105 -219 m 105 -162 117 -120 141 -93 ct 164 -65 192 -51 224 -51 ct 257 -51 285 -64 307 -91 ct +330 -117 342 -158 342 -212 ct 342 -273 330 -317 307 -345 ct 284 -373 255 -387 221 -387 ct +188 -387 160 -374 138 -346 ct 116 -319 l 105 -277 l p ef +818 -54 m 790 -30 764 -14 738 -4 ct 713 5 685 9 656 9 ct 608 9 571 -1 545 -25 ct +519 -49 506 -79 506 -115 ct 506 -137 511 -156 521 -174 ct 531 -192 543 -206 559 -217 ct +575 -228 593 -236 613 -241 ct 627 -245 649 -249 679 -253 ct 739 -260 783 -268 812 -278 ct +812 -288 812 -295 812 -298 ct 812 -328 805 -349 791 -362 ct 772 -379 744 -387 706 -387 ct +671 -387 645 -381 629 -369 ct 612 -356 600 -335 592 -303 ct 519 -313 l 526 -345 536 -370 552 -389 ct +567 -408 589 -423 617 -433 ct 646 -443 679 -449 717 -449 ct 755 -449 785 -444 808 -435 ct +832 -427 849 -415 860 -402 ct 871 -389 879 -372 883 -351 ct 886 -339 887 -316 887 -283 ct +887 -184 l 887 -114 889 -71 892 -52 ct 895 -34 901 -16 911 0 ct 833 0 l 825 -15 l +820 -33 l p +812 -220 m 785 -209 744 -200 690 -192 ct 660 -187 638 -182 625 -177 ct 613 -171 603 -163 596 -153 ct +589 -142 586 -130 586 -117 ct 586 -98 593 -81 608 -68 ct 623 -55 645 -48 674 -48 ct +703 -48 728 -54 751 -67 ct 773 -79 789 -96 800 -118 ct 808 -135 812 -160 812 -193 ct +p ef +1144 -66 m 1155 0 l 1134 3 1115 5 1098 5 ct 1071 5 1050 1 1036 -7 ct 1021 -15 1010 -26 1004 -40 ct +998 -54 995 -83 995 -128 ct 995 -381 l 940 -381 l 940 -439 l 995 -439 l +995 -547 l 1069 -592 l 1069 -439 l 1144 -439 l 1144 -381 l 1069 -381 l +1069 -124 l 1069 -103 1070 -89 1073 -83 ct 1076 -77 1080 -72 1086 -69 ct 1092 -65 1100 -63 1111 -63 ct +1119 -63 l 1130 -64 l p ef +1506 -54 m 1478 -30 1452 -14 1426 -4 ct 1401 5 1373 9 1344 9 ct 1296 9 1259 -1 1233 -25 ct +1207 -49 1194 -79 1194 -115 ct 1194 -137 1199 -156 1209 -174 ct 1219 -192 1231 -206 1247 -217 ct +1263 -228 1281 -236 1301 -241 ct 1315 -245 1337 -249 1367 -253 ct 1427 -260 1471 -268 1500 -278 ct +1500 -288 1500 -295 1500 -298 ct 1500 -328 1493 -349 1479 -362 ct 1460 -379 1432 -387 1394 -387 ct +1359 -387 1333 -381 1317 -369 ct 1300 -356 1288 -335 1280 -303 ct 1207 -313 l +1214 -345 1224 -370 1240 -389 ct 1255 -408 1277 -423 1305 -433 ct 1334 -443 1367 -449 1405 -449 ct +1443 -449 1473 -444 1496 -435 ct 1520 -427 1537 -415 1548 -402 ct 1559 -389 1567 -372 1571 -351 ct +1574 -339 1575 -316 1575 -283 ct 1575 -184 l 1575 -114 1577 -71 1580 -52 ct +1583 -34 1589 -16 1599 0 ct 1521 0 l 1513 -15 l 1508 -33 l p +1500 -220 m 1473 -209 1432 -200 1378 -192 ct 1348 -187 1326 -182 1313 -177 ct +1301 -171 1291 -163 1284 -153 ct 1277 -142 1274 -130 1274 -117 ct 1274 -98 1281 -81 1296 -68 ct +1311 -55 1333 -48 1362 -48 ct 1391 -48 1416 -54 1439 -67 ct 1461 -79 1477 -96 1488 -118 ct +1496 -135 1500 -160 1500 -193 ct p ef +2070 -66 m 2081 0 l 2060 3 2041 5 2024 5 ct 1997 5 1976 1 1962 -7 ct 1947 -15 1936 -26 1930 -40 ct +1924 -54 1921 -83 1921 -128 ct 1921 -381 l 1866 -381 l 1866 -439 l 1921 -439 l +1921 -547 l 1995 -592 l 1995 -439 l 2070 -439 l 2070 -381 l 1995 -381 l +1995 -124 l 1995 -103 1996 -89 1999 -83 ct 2002 -77 2006 -72 2012 -69 ct 2018 -65 2026 -63 2037 -63 ct +2045 -63 l 2056 -64 l p ef +2118 -219 m 2118 -300 2140 -361 2185 -400 ct 2223 -432 2269 -449 2324 -449 ct +2384 -449 2433 -429 2472 -389 ct 2510 -350 2529 -295 2529 -225 ct 2529 -169 2521 -124 2504 -92 ct +2487 -60 2462 -34 2430 -16 ct 2397 0 2362 9 2324 9 ct 2262 9 2212 -9 2174 -49 ct +2137 -88 l 2118 -145 l p +2194 -219 m 2194 -163 2206 -121 2231 -93 ct 2255 -65 2286 -51 2324 -51 ct 2361 -51 2391 -65 2416 -93 ct +2440 -121 2453 -164 2453 -222 ct 2453 -276 2440 -317 2416 -345 ct 2391 -373 2360 -387 2324 -387 ct +2286 -387 2255 -373 2231 -345 ct 2206 -317 l 2194 -275 l p ef +2860 0 m 2860 -606 l 2935 -606 l 2935 -388 l 2970 -429 3013 -449 3066 -449 ct +3099 -449 3127 -442 3151 -429 ct 3175 -417 3192 -399 3203 -376 ct 3213 -354 3218 -321 3218 -278 ct +3218 0 l 3144 0 l 3144 -278 l 3144 -315 3136 -342 3119 -359 ct 3103 -376 3081 -385 3051 -385 ct +3029 -385 3008 -379 2989 -367 ct 2969 -356 2955 -340 2947 -321 ct 2939 -301 2935 -274 2935 -240 ct +2935 0 l p ef +3309 -219 m 3309 -300 3331 -361 3376 -400 ct 3414 -432 3460 -449 3515 -449 ct +3575 -449 3624 -429 3663 -389 ct 3701 -350 3720 -295 3720 -225 ct 3720 -169 3712 -124 3695 -92 ct +3678 -60 3653 -34 3621 -16 ct 3588 0 3553 9 3515 9 ct 3453 9 3403 -9 3365 -49 ct +3328 -88 l 3309 -145 l p +3385 -219 m 3385 -163 3397 -121 3422 -93 ct 3446 -65 3477 -51 3515 -51 ct 3552 -51 3582 -65 3607 -93 ct +3631 -121 3644 -164 3644 -222 ct 3644 -276 3631 -317 3607 -345 ct 3582 -373 3551 -387 3515 -387 ct +3477 -387 3446 -373 3422 -345 ct 3397 -317 l 3385 -275 l p ef +3783 -131 m 3856 -142 l 3860 -113 3872 -90 3891 -74 ct 3910 -59 3936 -51 3970 -51 ct +4004 -51 4029 -58 4046 -72 ct 4063 -86 4071 -102 4071 -121 ct 4071 -138 4064 -151 4049 -160 ct +4039 -167 4013 -175 3973 -186 ct 3918 -199 3880 -211 3859 -221 ct 3838 -231 3822 -245 3811 -263 ct +3800 -281 3795 -301 3795 -322 ct 3795 -342 3799 -360 3808 -376 ct 3817 -393 3830 -407 3845 -418 ct +3857 -427 3872 -434 3892 -440 ct 3912 -446 3934 -449 3957 -449 ct 3991 -449 4021 -444 4047 -434 ct +4074 -424 4093 -410 4105 -393 ct 4118 -376 4126 -354 4131 -325 ct 4058 -315 l +4055 -338 4045 -356 4029 -368 ct 4013 -381 3991 -387 3962 -387 ct 3928 -387 3903 -382 3889 -370 ct +3874 -359 3867 -346 3867 -331 ct 3867 -321 3870 -312 3876 -305 ct 3882 -297 3892 -290 3905 -285 ct +3912 -282 3934 -276 3970 -266 ct 4023 -252 4060 -240 4081 -231 ct 4101 -222 4118 -209 4130 -192 ct +4141 -175 4147 -154 4147 -129 ct 4147 -104 4140 -80 4126 -58 ct 4111 -37 4090 -20 4063 -8 ct +4036 3 4005 9 3970 9 ct 3913 9 3870 -1 3840 -25 ct 3810 -49 l 3791 -84 l p ef +4372 -66 m 4383 0 l 4362 3 4343 5 4326 5 ct 4299 5 4278 1 4264 -7 ct 4249 -15 4238 -26 4232 -40 ct +4226 -54 4223 -83 4223 -128 ct 4223 -381 l 4168 -381 l 4168 -439 l 4223 -439 l +4223 -547 l 4297 -592 l 4297 -439 l 4372 -439 l 4372 -381 l 4297 -381 l +4297 -124 l 4297 -103 4298 -89 4301 -83 ct 4304 -77 4308 -72 4314 -69 ct 4320 -65 4328 -63 4339 -63 ct +4347 -63 l 4358 -64 l p ef +pom +pum +23257 5213 t +177 0 m 10 -439 l 89 -439 l 183 -176 l 193 -147 203 -118 211 -87 ct 218 -110 227 -138 239 -171 ct +337 -439 l 413 -439 l 247 0 l p ef +479 -520 m 479 -606 l 553 -606 l 553 -520 l p +479 0 m 479 -439 l 553 -439 l 553 0 l p ef +951 -54 m 923 -30 897 -14 871 -4 ct 846 5 818 9 789 9 ct 741 9 704 -1 678 -25 ct +652 -49 639 -79 639 -115 ct 639 -137 644 -156 654 -174 ct 664 -192 676 -206 692 -217 ct +708 -228 726 -236 746 -241 ct 760 -245 782 -249 812 -253 ct 872 -260 916 -268 945 -278 ct +945 -288 945 -295 945 -298 ct 945 -328 938 -349 924 -362 ct 905 -379 877 -387 839 -387 ct +804 -387 778 -381 762 -369 ct 745 -356 733 -335 725 -303 ct 652 -313 l 659 -345 669 -370 685 -389 ct +700 -408 722 -423 750 -433 ct 779 -443 812 -449 850 -449 ct 888 -449 918 -444 941 -435 ct +965 -427 982 -415 993 -402 ct 1004 -389 1012 -372 1016 -351 ct 1019 -339 1020 -316 1020 -283 ct +1020 -184 l 1020 -114 1022 -71 1025 -52 ct 1028 -34 1034 -16 1044 0 ct 966 0 l +958 -15 l 953 -33 l p +945 -220 m 918 -209 877 -200 823 -192 ct 793 -187 771 -182 758 -177 ct 746 -171 736 -163 729 -153 ct +722 -142 719 -130 719 -117 ct 719 -98 726 -81 741 -68 ct 756 -55 778 -48 807 -48 ct +836 -48 861 -54 884 -67 ct 906 -79 922 -96 933 -118 ct 941 -135 945 -160 945 -193 ct +p ef +1759 -606 m 1839 -606 l 1839 -256 l 1839 -195 1832 -146 1818 -110 ct 1804 -75 1780 -45 1744 -23 ct +1708 0 1660 10 1602 10 ct 1545 10 1499 0 1463 -19 ct 1426 -38 1401 -66 1385 -104 ct +1370 -141 1362 -191 1362 -256 ct 1362 -606 l 1442 -606 l 1442 -256 l 1442 -203 1447 -164 1457 -139 ct +1467 -115 1484 -95 1507 -82 ct 1531 -68 1560 -62 1595 -62 ct 1654 -62 1696 -75 1721 -102 ct +1746 -128 1759 -180 1759 -256 ct p ef +1969 -194 m 2044 -201 l 2048 -171 2056 -146 2069 -126 ct 2082 -107 2103 -91 2130 -79 ct +2158 -67 2189 -61 2223 -61 ct 2254 -61 2281 -66 2304 -75 ct 2328 -84 2345 -96 2357 -112 ct +2368 -128 2374 -145 2374 -164 ct 2374 -183 2368 -200 2357 -214 ct 2346 -228 2328 -240 2303 -250 ct +2286 -256 2250 -266 2195 -279 ct 2139 -293 2100 -305 2078 -317 ct 2049 -332 2027 -351 2013 -374 ct +1999 -396 1992 -421 1992 -449 ct 1992 -480 2000 -508 2018 -535 ct 2035 -561 2061 -582 2094 -595 ct +2127 -609 2164 -616 2205 -616 ct 2250 -616 2290 -609 2324 -594 ct 2358 -580 2385 -559 2403 -531 ct +2422 -502 2432 -471 2433 -435 ct 2356 -429 l 2352 -468 2338 -496 2314 -516 ct +2290 -536 2255 -545 2208 -545 ct 2160 -545 2125 -537 2102 -519 ct 2080 -501 2069 -480 2069 -454 ct +2069 -433 2077 -415 2093 -401 ct 2108 -387 2148 -372 2214 -357 ct 2279 -343 2324 -330 2348 -319 ct +2383 -303 2409 -282 2426 -257 ct 2443 -232 2451 -203 2451 -171 ct 2451 -138 2442 -108 2423 -80 ct +2405 -51 2378 -29 2344 -13 ct 2309 2 2270 10 2227 10 ct 2172 10 2126 2 2089 -13 ct +2052 -29 2023 -53 2002 -85 ct 1981 -117 l 1970 -154 l p ef +2576 0 m 2576 -606 l 2803 -606 l 2849 -606 2886 -600 2914 -587 ct 2942 -575 2964 -556 2980 -531 ct +2996 -505 3004 -479 3004 -451 ct 3004 -425 2997 -400 2983 -378 ct 2969 -355 2948 -336 2919 -322 ct +2956 -311 2984 -293 3004 -267 ct 3024 -241 3033 -211 3033 -175 ct 3033 -147 3027 -120 3015 -96 ct +3003 -72 2989 -53 2971 -40 ct 2953 -26 2931 -16 2905 -10 ct 2878 -3 2845 0 2807 0 ct +p +2656 -351 m 2787 -351 l 2822 -351 2848 -353 2863 -358 ct 2884 -364 2899 -374 2909 -388 ct +2920 -402 2925 -420 2925 -441 ct 2925 -461 2920 -479 2911 -494 ct 2901 -510 2887 -520 2869 -526 ct +2851 -531 2821 -534 2777 -534 ct 2656 -534 l p +2656 -71 m 2807 -71 l 2833 -71 2851 -72 2861 -74 ct 2880 -77 2895 -83 2908 -90 ct +2920 -98 2930 -109 2938 -124 ct 2946 -139 2950 -156 2950 -175 ct 2950 -198 2944 -218 2933 -234 ct +2921 -251 2905 -263 2885 -269 ct 2864 -276 2835 -279 2796 -279 ct 2656 -279 l +p ef +pom +gr +gs +pum +6825 19235 t +497 -212 m 578 -192 l 561 -126 531 -76 487 -41 ct 443 -6 390 10 327 10 ct +261 10 208 -2 167 -29 ct 126 -56 95 -94 74 -145 ct 52 -195 42 -249 42 -307 ct 42 -370 54 -425 78 -472 ct +102 -519 136 -555 181 -580 ct 225 -604 274 -616 328 -616 ct 389 -616 440 -601 481 -570 ct +522 -539 551 -496 567 -440 ct 488 -421 l 474 -465 454 -497 427 -517 ct 400 -537 367 -547 326 -547 ct +280 -547 241 -536 209 -514 ct 178 -492 156 -462 143 -424 ct 131 -386 124 -348 124 -308 ct +124 -256 132 -211 147 -173 ct 162 -134 185 -105 217 -86 ct 249 -67 283 -58 320 -58 ct +365 -58 403 -71 434 -97 ct 465 -123 l 486 -161 l p ef +991 -141 m 1068 -131 l 1056 -86 1033 -52 1001 -27 ct 968 -2 926 9 875 9 ct +811 9 760 -9 722 -49 ct 684 -88 666 -144 666 -215 ct 666 -289 685 -347 723 -387 ct +761 -428 810 -449 871 -449 ct 929 -449 977 -429 1015 -389 ct 1052 -349 1070 -292 1070 -220 ct +1070 -216 1070 -209 1070 -200 ct 742 -200 l 745 -152 759 -115 783 -89 ct 808 -64 839 -51 875 -51 ct +903 -51 926 -58 945 -72 ct 964 -87 l 980 -110 l p +747 -261 m 992 -261 l 989 -298 979 -326 964 -344 ct 940 -373 909 -387 871 -387 ct +837 -387 809 -376 785 -353 ct 762 -330 l 749 -300 l p ef +1166 0 m 1166 -439 l 1233 -439 l 1233 -376 l 1266 -425 1312 -449 1373 -449 ct +1400 -449 1424 -444 1446 -434 ct 1468 -425 1485 -412 1496 -397 ct 1507 -382 1515 -363 1519 -342 ct +1522 -328 1523 -304 1523 -270 ct 1523 0 l 1449 0 l 1449 -267 l 1449 -297 1446 -320 1440 -335 ct +1434 -350 1424 -362 1409 -371 ct 1395 -380 1377 -384 1357 -384 ct 1326 -384 1298 -374 1275 -354 ct +1252 -334 1241 -296 1241 -239 ct 1241 0 l p ef +1806 -66 m 1817 0 l 1796 3 1777 5 1760 5 ct 1733 5 1712 1 1698 -7 ct 1683 -15 1672 -26 1666 -40 ct +1660 -54 1657 -83 1657 -128 ct 1657 -381 l 1602 -381 l 1602 -439 l 1657 -439 l +1657 -547 l 1731 -592 l 1731 -439 l 1806 -439 l 1806 -381 l 1731 -381 l +1731 -124 l 1731 -103 1732 -89 1735 -83 ct 1738 -77 1742 -72 1748 -69 ct 1754 -65 1762 -63 1773 -63 ct +1781 -63 l 1792 -64 l p ef +2182 -141 m 2259 -131 l 2247 -86 2224 -52 2192 -27 ct 2159 -2 2117 9 2066 9 ct +2002 9 1951 -9 1913 -49 ct 1875 -88 1857 -144 1857 -215 ct 1857 -289 1876 -347 1914 -387 ct +1952 -428 2001 -449 2062 -449 ct 2120 -449 2168 -429 2206 -389 ct 2243 -349 2261 -292 2261 -220 ct +2261 -216 2261 -209 2261 -200 ct 1933 -200 l 1936 -152 1950 -115 1974 -89 ct +1999 -64 2030 -51 2066 -51 ct 2094 -51 2117 -58 2136 -72 ct 2155 -87 l 2171 -110 l +p +1938 -261 m 2183 -261 l 2180 -298 2170 -326 2155 -344 ct 2131 -373 2100 -387 2062 -387 ct +2028 -387 2000 -376 1976 -353 ct 1953 -330 l 1940 -300 l p ef +2357 0 m 2357 -439 l 2424 -439 l 2424 -372 l 2441 -403 2456 -424 2471 -434 ct +2485 -444 2501 -449 2519 -449 ct 2544 -449 2569 -441 2595 -425 ct 2570 -356 l +2551 -366 2533 -372 2515 -372 ct 2499 -372 2484 -367 2471 -357 ct 2458 -347 2449 -334 2443 -316 ct +2435 -290 2431 -261 2431 -229 ct 2431 0 l p ef +2904 0 m 2904 -381 l 2838 -381 l 2838 -439 l 2904 -439 l 2904 -485 l +2904 -515 2907 -537 2912 -551 ct 2919 -571 2932 -586 2950 -598 ct 2968 -610 2993 -616 3026 -616 ct +3047 -616 3070 -614 3095 -609 ct 3084 -544 l 3069 -547 3054 -548 3040 -548 ct +3018 -548 3002 -543 2992 -533 ct 2983 -524 2978 -506 2978 -479 ct 2978 -439 l +3064 -439 l 3064 -381 l 2978 -381 l 2978 0 l p ef +3124 0 m 3124 -439 l 3191 -439 l 3191 -372 l 3208 -403 3223 -424 3238 -434 ct +3252 -444 3268 -449 3286 -449 ct 3311 -449 3336 -441 3362 -425 ct 3337 -356 l +3318 -366 3300 -372 3282 -372 ct 3266 -372 3251 -367 3238 -357 ct 3225 -347 3216 -334 3210 -316 ct +3202 -290 3198 -261 3198 -229 ct 3198 0 l p ef +3716 -141 m 3793 -131 l 3781 -86 3758 -52 3726 -27 ct 3693 -2 3651 9 3600 9 ct +3536 9 3485 -9 3447 -49 ct 3409 -88 3391 -144 3391 -215 ct 3391 -289 3410 -347 3448 -387 ct +3486 -428 3535 -449 3596 -449 ct 3654 -449 3702 -429 3740 -389 ct 3777 -349 3795 -292 3795 -220 ct +3795 -216 3795 -209 3795 -200 ct 3467 -200 l 3470 -152 3484 -115 3508 -89 ct +3533 -64 3564 -51 3600 -51 ct 3628 -51 3651 -58 3670 -72 ct 3689 -87 l 3705 -110 l +p +3472 -261 m 3717 -261 l 3714 -298 3704 -326 3689 -344 ct 3665 -373 3634 -387 3596 -387 ct +3562 -387 3534 -376 3510 -353 ct 3487 -330 l 3474 -300 l p ef +4171 168 m 4171 -46 l 4160 -30 4144 -16 4123 -6 ct 4102 4 4080 9 4056 9 ct +4004 9 3959 -10 3922 -52 ct 3884 -94 3865 -151 3865 -223 ct 3865 -267 3873 -307 3888 -342 ct +3904 -377 3926 -404 3955 -422 ct 3984 -440 4016 -449 4051 -449 ct 4105 -449 4148 -426 4179 -380 ct +4179 -439 l 4246 -439 l 4246 168 l p +3942 -220 m 3942 -164 3954 -121 3977 -93 ct 4001 -65 4029 -51 4063 -51 ct 4094 -51 4122 -64 4144 -91 ct +4167 -118 4179 -159 4179 -214 ct 4179 -272 4167 -316 4143 -346 ct 4118 -375 4090 -390 4058 -390 ct +4025 -390 3998 -376 3975 -349 ct 3953 -321 l 3942 -279 l p ef +4656 0 m 4656 -64 l 4622 -14 4576 9 4517 9 ct 4491 9 4467 4 4444 -4 ct 4422 -14 4405 -27 4394 -42 ct +4383 -57 4376 -75 4371 -97 ct 4368 -112 4367 -135 4367 -167 ct 4367 -439 l 4441 -439 l +4441 -195 l 4441 -156 4443 -130 4446 -117 ct 4450 -97 4460 -82 4475 -70 ct +4491 -59 4509 -54 4532 -54 ct 4554 -54 4575 -59 4595 -71 ct 4614 -82 4628 -98 4636 -118 ct +4644 -137 4648 -166 4648 -203 ct 4648 -439 l 4723 -439 l 4723 0 l p ef +5145 -141 m 5222 -131 l 5210 -86 5187 -52 5155 -27 ct 5122 -2 5080 9 5029 9 ct +4965 9 4914 -9 4876 -49 ct 4838 -88 4820 -144 4820 -215 ct 4820 -289 4839 -347 4877 -387 ct +4915 -428 4964 -449 5025 -449 ct 5083 -449 5131 -429 5169 -389 ct 5206 -349 5224 -292 5224 -220 ct +5224 -216 5224 -209 5224 -200 ct 4896 -200 l 4899 -152 4913 -115 4937 -89 ct +4962 -64 4993 -51 5029 -51 ct 5057 -51 5080 -58 5099 -72 ct 5118 -87 l 5134 -110 l +p +4901 -261 m 5146 -261 l 5143 -298 5133 -326 5118 -344 ct 5094 -373 5063 -387 5025 -387 ct +4991 -387 4963 -376 4939 -353 ct 4916 -330 l 4903 -300 l p ef +5320 0 m 5320 -439 l 5387 -439 l 5387 -376 l 5420 -425 5466 -449 5527 -449 ct +5554 -449 5578 -444 5600 -434 ct 5622 -425 5639 -412 5650 -397 ct 5661 -382 5669 -363 5673 -342 ct +5676 -328 5677 -304 5677 -270 ct 5677 0 l 5603 0 l 5603 -267 l 5603 -297 5600 -320 5594 -335 ct +5588 -350 5578 -362 5563 -371 ct 5549 -380 5531 -384 5511 -384 ct 5480 -384 5452 -374 5429 -354 ct +5406 -334 5395 -296 5395 -239 ct 5395 0 l p ef +6083 -160 m 6156 -151 l 6148 -100 6128 -61 6095 -32 ct 6062 -4 6021 9 5973 9 ct +5913 9 5865 -9 5828 -49 ct 5792 -88 5774 -144 5774 -217 ct 5774 -265 5781 -306 5797 -342 ct +5813 -378 5837 -404 5869 -422 ct 5901 -440 5936 -449 5974 -449 ct 6021 -449 6060 -437 6091 -412 ct +6121 -388 6141 -354 6149 -310 ct 6077 -299 l 6070 -328 6058 -350 6040 -365 ct +6023 -380 6001 -387 5977 -387 ct 5939 -387 5909 -374 5885 -347 ct 5862 -320 5850 -278 5850 -220 ct +5850 -161 5861 -118 5884 -91 ct 5907 -64 5936 -51 5973 -51 ct 6002 -51 6026 -60 6046 -78 ct +6065 -96 l 6078 -123 l p ef +6217 169 m 6209 99 l 6225 103 6239 105 6251 105 ct 6268 105 6281 103 6291 97 ct +6301 92 6309 84 6315 74 ct 6320 66 6328 48 6338 19 ct 6340 14 6342 8 6345 0 ct +6178 -439 l 6258 -439 l 6350 -184 l 6362 -152 6372 -118 6382 -83 ct 6390 -117 6400 -150 6412 -183 ct +6506 -439 l 6581 -439 l 6413 7 l 6396 55 6382 88 6372 107 ct 6358 131 6343 149 6326 161 ct +6309 172 6289 178 6265 178 ct 6251 178 l 6235 175 l p ef +pom +pum +7778 20188 t +26 -181 m 26 -256 l 255 -256 l 255 -181 l p ef +364 0 m 364 -381 l 298 -381 l 298 -439 l 364 -439 l 364 -485 l 364 -515 367 -537 372 -551 ct +379 -571 392 -586 410 -598 ct 428 -610 453 -616 486 -616 ct 507 -616 530 -614 555 -609 ct +544 -544 l 529 -547 514 -548 500 -548 ct 478 -548 462 -543 452 -533 ct 443 -524 438 -506 438 -479 ct +438 -439 l 524 -439 l 524 -381 l 438 -381 l 438 0 l p ef +555 -131 m 628 -142 l 632 -113 644 -90 663 -74 ct 682 -59 708 -51 742 -51 ct +776 -51 801 -58 818 -72 ct 835 -86 843 -102 843 -121 ct 843 -138 836 -151 821 -160 ct +811 -167 785 -175 745 -186 ct 690 -199 652 -211 631 -221 ct 610 -231 594 -245 583 -263 ct +572 -281 567 -301 567 -322 ct 567 -342 571 -360 580 -376 ct 589 -393 602 -407 617 -418 ct +629 -427 644 -434 664 -440 ct 684 -446 706 -449 729 -449 ct 763 -449 793 -444 819 -434 ct +846 -424 865 -410 877 -393 ct 890 -376 898 -354 903 -325 ct 830 -315 l 827 -338 817 -356 801 -368 ct +785 -381 763 -387 734 -387 ct 700 -387 675 -382 661 -370 ct 646 -359 639 -346 639 -331 ct +639 -321 642 -312 648 -305 ct 654 -297 664 -290 677 -285 ct 684 -282 706 -276 742 -266 ct +795 -252 832 -240 853 -231 ct 873 -222 890 -209 902 -192 ct 913 -175 919 -154 919 -129 ct +919 -104 912 -80 898 -58 ct 883 -37 862 -20 835 -8 ct 808 3 777 9 742 9 ct 685 9 642 -1 612 -25 ct +582 -49 l 563 -84 l p ef +926 10 m 1101 -616 l 1161 -616 l 985 10 l p ef +1590 -71 m 1590 0 l 1189 0 l 1189 -17 1191 -35 1198 -51 ct 1208 -79 1224 -105 1247 -132 ct +1269 -158 1302 -189 1344 -224 ct 1410 -278 1455 -321 1478 -352 ct 1501 -384 1513 -413 1513 -442 ct +1513 -471 1502 -496 1481 -516 ct 1460 -537 1432 -547 1398 -547 ct 1363 -547 1334 -536 1312 -514 ct +1291 -493 1280 -463 1280 -425 ct 1203 -433 l 1208 -490 1228 -533 1262 -563 ct +1297 -593 1342 -608 1400 -608 ct 1458 -608 1504 -592 1538 -560 ct 1572 -528 1589 -488 1589 -440 ct +1589 -416 1584 -392 1574 -368 ct 1564 -345 1548 -320 1525 -294 ct 1502 -268 1463 -233 1410 -188 ct +1365 -150 1337 -125 1324 -111 ct 1311 -98 1301 -85 1293 -71 ct p ef +2097 -66 m 2108 0 l 2087 3 2068 5 2051 5 ct 2024 5 2003 1 1989 -7 ct 1974 -15 1963 -26 1957 -40 ct +1951 -54 1948 -83 1948 -128 ct 1948 -381 l 1893 -381 l 1893 -439 l 1948 -439 l +1948 -547 l 2022 -592 l 2022 -439 l 2097 -439 l 2097 -381 l 2022 -381 l +2022 -124 l 2022 -103 2023 -89 2026 -83 ct 2029 -77 2033 -72 2039 -69 ct 2045 -65 2053 -63 2064 -63 ct +2072 -63 l 2083 -64 l p ef +2145 -219 m 2145 -300 2167 -361 2212 -400 ct 2250 -432 2296 -449 2351 -449 ct +2411 -449 2460 -429 2499 -389 ct 2537 -350 2556 -295 2556 -225 ct 2556 -169 2548 -124 2531 -92 ct +2514 -60 2489 -34 2457 -16 ct 2424 0 2389 9 2351 9 ct 2289 9 2239 -9 2201 -49 ct +2164 -88 l 2145 -145 l p +2221 -219 m 2221 -163 2233 -121 2258 -93 ct 2282 -65 2313 -51 2351 -51 ct 2388 -51 2418 -65 2443 -93 ct +2467 -121 2480 -164 2480 -222 ct 2480 -276 2467 -317 2443 -345 ct 2418 -373 2387 -387 2351 -387 ct +2313 -387 2282 -373 2258 -345 ct 2233 -317 l 2221 -275 l p ef +3043 -98 m 3043 -264 l 2878 -264 l 2878 -333 l 3043 -333 l 3043 -498 l +3113 -498 l 3113 -333 l 3278 -333 l 3278 -264 l 3113 -264 l 3113 -98 l +p ef +3407 0 m 3407 -381 l 3341 -381 l 3341 -439 l 3407 -439 l 3407 -485 l +3407 -515 3410 -537 3415 -551 ct 3422 -571 3435 -586 3453 -598 ct 3471 -610 3496 -616 3529 -616 ct +3550 -616 3573 -614 3598 -609 ct 3587 -544 l 3572 -547 3557 -548 3543 -548 ct +3521 -548 3505 -543 3495 -533 ct 3486 -524 3481 -506 3481 -479 ct 3481 -439 l +3567 -439 l 3567 -381 l 3481 -381 l 3481 0 l p ef +3598 -131 m 3671 -142 l 3675 -113 3687 -90 3706 -74 ct 3725 -59 3751 -51 3785 -51 ct +3819 -51 3844 -58 3861 -72 ct 3878 -86 3886 -102 3886 -121 ct 3886 -138 3879 -151 3864 -160 ct +3854 -167 3828 -175 3788 -186 ct 3733 -199 3695 -211 3674 -221 ct 3653 -231 3637 -245 3626 -263 ct +3615 -281 3610 -301 3610 -322 ct 3610 -342 3614 -360 3623 -376 ct 3632 -393 3645 -407 3660 -418 ct +3672 -427 3687 -434 3707 -440 ct 3727 -446 3749 -449 3772 -449 ct 3806 -449 3836 -444 3862 -434 ct +3889 -424 3908 -410 3920 -393 ct 3933 -376 3941 -354 3946 -325 ct 3873 -315 l +3870 -338 3860 -356 3844 -368 ct 3828 -381 3806 -387 3777 -387 ct 3743 -387 3718 -382 3704 -370 ct +3689 -359 3682 -346 3682 -331 ct 3682 -321 3685 -312 3691 -305 ct 3697 -297 3707 -290 3720 -285 ct +3727 -282 3749 -276 3785 -266 ct 3838 -252 3875 -240 3896 -231 ct 3916 -222 3933 -209 3945 -192 ct +3956 -175 3962 -154 3962 -129 ct 3962 -104 3955 -80 3941 -58 ct 3926 -37 3905 -20 3878 -8 ct +3851 3 3820 9 3785 9 ct 3728 9 3685 -1 3655 -25 ct 3625 -49 l 3606 -84 l p ef +3969 10 m 4144 -616 l 4204 -616 l 4028 10 l p ef +4633 -71 m 4633 0 l 4232 0 l 4232 -17 4234 -35 4241 -51 ct 4251 -79 4267 -105 4290 -132 ct +4312 -158 4345 -189 4387 -224 ct 4453 -278 4498 -321 4521 -352 ct 4544 -384 4556 -413 4556 -442 ct +4556 -471 4545 -496 4524 -516 ct 4503 -537 4475 -547 4441 -547 ct 4406 -547 4377 -536 4355 -514 ct +4334 -493 4323 -463 4323 -425 ct 4246 -433 l 4251 -490 4271 -533 4305 -563 ct +4340 -593 4385 -608 4443 -608 ct 4501 -608 4547 -592 4581 -560 ct 4615 -528 4632 -488 4632 -440 ct +4632 -416 4627 -392 4617 -368 ct 4607 -345 4591 -320 4568 -294 ct 4545 -268 4506 -233 4453 -188 ct +4408 -150 4380 -125 4367 -111 ct 4354 -98 4344 -85 4336 -71 ct p ef +pom +gr +10161 16546 m 10011 16996 l 10311 16995 l 10161 16546 l p ef +10161 18381 m 10161 16906 l ps +gs +pum +2805 3466 t +38 -194 m 113 -201 l 117 -171 125 -146 138 -126 ct 151 -107 172 -91 199 -79 ct +227 -67 258 -61 292 -61 ct 323 -61 350 -66 373 -75 ct 397 -84 414 -96 426 -112 ct +437 -128 443 -145 443 -164 ct 443 -183 437 -200 426 -214 ct 415 -228 397 -240 372 -250 ct +355 -256 319 -266 264 -279 ct 208 -293 169 -305 147 -317 ct 118 -332 96 -351 82 -374 ct +68 -396 61 -421 61 -449 ct 61 -480 69 -508 87 -535 ct 104 -561 130 -582 163 -595 ct +196 -609 233 -616 274 -616 ct 319 -616 359 -609 393 -594 ct 427 -580 454 -559 472 -531 ct +491 -502 501 -471 502 -435 ct 425 -429 l 421 -468 407 -496 383 -516 ct 359 -536 324 -545 277 -545 ct +229 -545 194 -537 171 -519 ct 149 -501 138 -480 138 -454 ct 138 -433 146 -415 162 -401 ct +177 -387 217 -372 283 -357 ct 348 -343 393 -330 417 -319 ct 452 -303 478 -282 495 -257 ct +512 -232 520 -203 520 -171 ct 520 -138 511 -108 492 -80 ct 474 -51 447 -29 413 -13 ct +378 2 339 10 296 10 ct 241 10 195 2 158 -13 ct 121 -29 92 -53 71 -85 ct 50 -117 l +39 -154 l p ef +924 -54 m 896 -30 870 -14 844 -4 ct 819 5 791 9 762 9 ct 714 9 677 -1 651 -25 ct +625 -49 612 -79 612 -115 ct 612 -137 617 -156 627 -174 ct 637 -192 649 -206 665 -217 ct +681 -228 699 -236 719 -241 ct 733 -245 755 -249 785 -253 ct 845 -260 889 -268 918 -278 ct +918 -288 918 -295 918 -298 ct 918 -328 911 -349 897 -362 ct 878 -379 850 -387 812 -387 ct +777 -387 751 -381 735 -369 ct 718 -356 706 -335 698 -303 ct 625 -313 l 632 -345 642 -370 658 -389 ct +673 -408 695 -423 723 -433 ct 752 -443 785 -449 823 -449 ct 861 -449 891 -444 914 -435 ct +938 -427 955 -415 966 -402 ct 977 -389 985 -372 989 -351 ct 992 -339 993 -316 993 -283 ct +993 -184 l 993 -114 995 -71 998 -52 ct 1001 -34 1007 -16 1017 0 ct 939 0 l +931 -15 l 926 -33 l p +918 -220 m 891 -209 850 -200 796 -192 ct 766 -187 744 -182 731 -177 ct 719 -171 709 -163 702 -153 ct +695 -142 692 -130 692 -117 ct 692 -98 699 -81 714 -68 ct 729 -55 751 -48 780 -48 ct +809 -48 834 -54 857 -67 ct 879 -79 895 -96 906 -118 ct 914 -135 918 -160 918 -193 ct +p ef +1087 0 m 1087 -439 l 1154 -439 l 1154 -377 l 1168 -399 1186 -416 1209 -429 ct +1232 -442 1258 -449 1287 -449 ct 1320 -449 1346 -442 1367 -428 ct 1388 -415 1403 -396 1411 -372 ct +1446 -423 1491 -449 1547 -449 ct 1590 -449 1624 -437 1647 -412 ct 1671 -388 1682 -351 1682 -301 ct +1682 0 l 1608 0 l 1608 -276 l 1608 -306 1606 -327 1601 -340 ct 1596 -354 1588 -364 1575 -372 ct +1562 -380 1547 -384 1530 -384 ct 1499 -384 1474 -374 1453 -353 ct 1433 -333 1423 -300 1423 -255 ct +1423 0 l 1348 0 l 1348 -285 l 1348 -318 1342 -343 1330 -359 ct 1318 -376 1298 -384 1271 -384 ct +1250 -384 1230 -379 1212 -368 ct 1195 -357 1182 -340 1174 -319 ct 1166 -298 1162 -267 1162 -227 ct +1162 0 l p ef +1801 168 m 1801 -439 l 1869 -439 l 1869 -382 l 1885 -404 1903 -421 1923 -432 ct +1943 -443 1968 -449 1997 -449 ct 2034 -449 2067 -439 2096 -420 ct 2124 -400 2146 -373 2161 -338 ct +2175 -303 2183 -264 2183 -222 ct 2183 -177 2175 -137 2158 -101 ct 2142 -65 2119 -37 2088 -18 ct +2057 0 2025 9 1991 9 ct 1966 9 1944 4 1924 -5 ct 1905 -16 1888 -29 1876 -45 ct +1876 168 l p +1869 -217 m 1869 -160 1880 -118 1903 -91 ct 1926 -64 1954 -51 1986 -51 ct 2019 -51 2048 -65 2071 -93 ct +2095 -121 2107 -164 2107 -223 ct 2107 -279 2095 -321 2072 -349 ct 2049 -376 2022 -390 1990 -390 ct +1958 -390 1930 -376 1905 -346 ct 1881 -316 l 1869 -273 l p ef +2250 0 m 2250 -606 l 2324 -606 l 2324 0 l p ef +2437 -520 m 2437 -606 l 2511 -606 l 2511 -520 l p +2437 0 m 2437 -439 l 2511 -439 l 2511 0 l p ef +2621 0 m 2621 -439 l 2688 -439 l 2688 -376 l 2721 -425 2767 -449 2828 -449 ct +2855 -449 2879 -444 2901 -434 ct 2923 -425 2940 -412 2951 -397 ct 2962 -382 2970 -363 2974 -342 ct +2977 -328 2978 -304 2978 -270 ct 2978 0 l 2904 0 l 2904 -267 l 2904 -297 2901 -320 2895 -335 ct +2889 -350 2879 -362 2864 -371 ct 2850 -380 2832 -384 2812 -384 ct 2781 -384 2753 -374 2730 -354 ct +2707 -334 2696 -296 2696 -239 ct 2696 0 l p ef +3085 36 m 3157 47 l 3160 69 3169 85 3182 95 ct 3201 109 3226 116 3258 116 ct +3292 116 3319 109 3338 95 ct 3357 82 3369 62 3376 38 ct 3380 22 3381 -8 3381 -57 ct +3349 -19 3308 0 3260 0 ct 3199 0 3153 -21 3119 -65 ct 3086 -108 3070 -161 3070 -222 ct +3070 -264 3077 -302 3093 -338 ct 3108 -373 3130 -400 3159 -420 ct 3187 -439 3221 -449 3260 -449 ct +3312 -449 3355 -428 3388 -386 ct 3388 -439 l 3457 -439 l 3457 -59 l 3457 8 3450 57 3436 85 ct +3422 114 3400 136 3370 153 ct 3340 169 3303 178 3258 178 ct 3206 178 3164 166 3131 142 ct +3099 119 l 3084 83 l p +3146 -227 m 3146 -169 3158 -127 3181 -101 ct 3204 -74 3232 -61 3267 -61 ct +3301 -61 3330 -74 3353 -101 ct 3376 -127 3387 -168 3387 -224 ct 3387 -278 3376 -319 3352 -346 ct +3328 -373 3299 -387 3265 -387 ct 3232 -387 3204 -374 3181 -347 ct 3158 -320 l +3146 -280 l p ef +3812 0 m 3812 -439 l 3879 -439 l 3879 -372 l 3896 -403 3911 -424 3926 -434 ct +3940 -444 3956 -449 3974 -449 ct 3999 -449 4024 -441 4050 -425 ct 4025 -356 l +4006 -366 3988 -372 3970 -372 ct 3954 -372 3939 -367 3926 -357 ct 3913 -347 3904 -334 3898 -316 ct +3890 -290 3886 -261 3886 -229 ct 3886 0 l p ef +4390 -54 m 4362 -30 4336 -14 4310 -4 ct 4285 5 4257 9 4228 9 ct 4180 9 4143 -1 4117 -25 ct +4091 -49 4078 -79 4078 -115 ct 4078 -137 4083 -156 4093 -174 ct 4103 -192 4115 -206 4131 -217 ct +4147 -228 4165 -236 4185 -241 ct 4199 -245 4221 -249 4251 -253 ct 4311 -260 4355 -268 4384 -278 ct +4384 -288 4384 -295 4384 -298 ct 4384 -328 4377 -349 4363 -362 ct 4344 -379 4316 -387 4278 -387 ct +4243 -387 4217 -381 4201 -369 ct 4184 -356 4172 -335 4164 -303 ct 4091 -313 l +4098 -345 4108 -370 4124 -389 ct 4139 -408 4161 -423 4189 -433 ct 4218 -443 4251 -449 4289 -449 ct +4327 -449 4357 -444 4380 -435 ct 4404 -427 4421 -415 4432 -402 ct 4443 -389 4451 -372 4455 -351 ct +4458 -339 4459 -316 4459 -283 ct 4459 -184 l 4459 -114 4461 -71 4464 -52 ct +4467 -34 4473 -16 4483 0 ct 4405 0 l 4397 -15 l 4392 -33 l p +4384 -220 m 4357 -209 4316 -200 4262 -192 ct 4232 -187 4210 -182 4197 -177 ct +4185 -171 4175 -163 4168 -153 ct 4161 -142 4158 -130 4158 -117 ct 4158 -98 4165 -81 4180 -68 ct +4195 -55 4217 -48 4246 -48 ct 4275 -48 4300 -54 4323 -67 ct 4345 -79 4361 -96 4372 -118 ct +4380 -135 4384 -160 4384 -193 ct p ef +4716 -66 m 4727 0 l 4706 3 4687 5 4670 5 ct 4643 5 4622 1 4608 -7 ct 4593 -15 4582 -26 4576 -40 ct +4570 -54 4567 -83 4567 -128 ct 4567 -381 l 4512 -381 l 4512 -439 l 4567 -439 l +4567 -547 l 4641 -592 l 4641 -439 l 4716 -439 l 4716 -381 l 4641 -381 l +4641 -124 l 4641 -103 4642 -89 4645 -83 ct 4648 -77 4652 -72 4658 -69 ct 4664 -65 4672 -63 4683 -63 ct +4691 -63 l 4702 -64 l p ef +5092 -141 m 5169 -131 l 5157 -86 5134 -52 5102 -27 ct 5069 -2 5027 9 4976 9 ct +4912 9 4861 -9 4823 -49 ct 4785 -88 4767 -144 4767 -215 ct 4767 -289 4786 -347 4824 -387 ct +4862 -428 4911 -449 4972 -449 ct 5030 -449 5078 -429 5116 -389 ct 5153 -349 5171 -292 5171 -220 ct +5171 -216 5171 -209 5171 -200 ct 4843 -200 l 4846 -152 4860 -115 4884 -89 ct +4909 -64 4940 -51 4976 -51 ct 5004 -51 5027 -58 5046 -72 ct 5065 -87 l 5081 -110 l +p +4848 -261 m 5093 -261 l 5090 -298 5080 -326 5065 -344 ct 5041 -373 5010 -387 4972 -387 ct +4938 -387 4910 -376 4886 -353 ct 4863 -330 l 4850 -300 l p ef +5897 -356 m 5497 -356 l 5497 -425 l 5897 -425 l p +5897 -172 m 5497 -172 l 5497 -241 l 5897 -241 l p ef +6264 0 m 6264 -381 l 6198 -381 l 6198 -439 l 6264 -439 l 6264 -485 l +6264 -515 6267 -537 6272 -551 ct 6279 -571 6292 -586 6310 -598 ct 6328 -610 6353 -616 6386 -616 ct +6407 -616 6430 -614 6455 -609 ct 6444 -544 l 6429 -547 6414 -548 6400 -548 ct +6378 -548 6362 -543 6352 -533 ct 6343 -524 6338 -506 6338 -479 ct 6338 -439 l +6424 -439 l 6424 -381 l 6338 -381 l 6338 0 l p ef +6455 -131 m 6528 -142 l 6532 -113 6544 -90 6563 -74 ct 6582 -59 6608 -51 6642 -51 ct +6676 -51 6701 -58 6718 -72 ct 6735 -86 6743 -102 6743 -121 ct 6743 -138 6736 -151 6721 -160 ct +6711 -167 6685 -175 6645 -186 ct 6590 -199 6552 -211 6531 -221 ct 6510 -231 6494 -245 6483 -263 ct +6472 -281 6467 -301 6467 -322 ct 6467 -342 6471 -360 6480 -376 ct 6489 -393 6502 -407 6517 -418 ct +6529 -427 6544 -434 6564 -440 ct 6584 -446 6606 -449 6629 -449 ct 6663 -449 6693 -444 6719 -434 ct +6746 -424 6765 -410 6777 -393 ct 6790 -376 6798 -354 6803 -325 ct 6730 -315 l +6727 -338 6717 -356 6701 -368 ct 6685 -381 6663 -387 6634 -387 ct 6600 -387 6575 -382 6561 -370 ct +6546 -359 6539 -346 6539 -331 ct 6539 -321 6542 -312 6548 -305 ct 6554 -297 6564 -290 6577 -285 ct +6584 -282 6606 -276 6642 -266 ct 6695 -252 6732 -240 6753 -231 ct 6773 -222 6790 -209 6802 -192 ct +6813 -175 6819 -154 6819 -129 ct 6819 -104 6812 -80 6798 -58 ct 6783 -37 6762 -20 6735 -8 ct +6708 3 6677 9 6642 9 ct 6585 9 6542 -1 6512 -25 ct 6482 -49 l 6463 -84 l p ef +pom +gr +gs +pum +15981 14102 t +62 0 m 62 -606 l 289 -606 l 335 -606 372 -600 400 -587 ct 428 -575 450 -556 466 -531 ct +482 -505 490 -479 490 -451 ct 490 -425 483 -400 469 -378 ct 455 -355 434 -336 405 -322 ct +442 -311 470 -293 490 -267 ct 510 -241 519 -211 519 -175 ct 519 -147 513 -120 501 -96 ct +489 -72 475 -53 457 -40 ct 439 -26 417 -16 391 -10 ct 364 -3 331 0 293 0 ct p +142 -351 m 273 -351 l 308 -351 334 -353 349 -358 ct 370 -364 385 -374 395 -388 ct +406 -402 411 -420 411 -441 ct 411 -461 406 -479 397 -494 ct 387 -510 373 -520 355 -526 ct +337 -531 307 -534 263 -534 ct 142 -534 l p +142 -71 m 293 -71 l 319 -71 337 -72 347 -74 ct 366 -77 381 -83 394 -90 ct +406 -98 416 -109 424 -124 ct 432 -139 436 -156 436 -175 ct 436 -198 430 -218 419 -234 ct +407 -251 391 -263 371 -269 ct 350 -276 321 -279 282 -279 ct 142 -279 l p ef +898 -54 m 870 -30 844 -14 818 -4 ct 793 5 765 9 736 9 ct 688 9 651 -1 625 -25 ct +599 -49 586 -79 586 -115 ct 586 -137 591 -156 601 -174 ct 611 -192 623 -206 639 -217 ct +655 -228 673 -236 693 -241 ct 707 -245 729 -249 759 -253 ct 819 -260 863 -268 892 -278 ct +892 -288 892 -295 892 -298 ct 892 -328 885 -349 871 -362 ct 852 -379 824 -387 786 -387 ct +751 -387 725 -381 709 -369 ct 692 -356 680 -335 672 -303 ct 599 -313 l 606 -345 616 -370 632 -389 ct +647 -408 669 -423 697 -433 ct 726 -443 759 -449 797 -449 ct 835 -449 865 -444 888 -435 ct +912 -427 929 -415 940 -402 ct 951 -389 959 -372 963 -351 ct 966 -339 967 -316 967 -283 ct +967 -184 l 967 -114 969 -71 972 -52 ct 975 -34 981 -16 991 0 ct 913 0 l 905 -15 l +900 -33 l p +892 -220 m 865 -209 824 -200 770 -192 ct 740 -187 718 -182 705 -177 ct 693 -171 683 -163 676 -153 ct +669 -142 666 -130 666 -117 ct 666 -98 673 -81 688 -68 ct 703 -55 725 -48 754 -48 ct +783 -48 808 -54 831 -67 ct 853 -79 869 -96 880 -118 ct 888 -135 892 -160 892 -193 ct +p ef +1060 0 m 1060 -439 l 1127 -439 l 1127 -376 l 1160 -425 1206 -449 1267 -449 ct +1294 -449 1318 -444 1340 -434 ct 1362 -425 1379 -412 1390 -397 ct 1401 -382 1409 -363 1413 -342 ct +1416 -328 1417 -304 1417 -270 ct 1417 0 l 1343 0 l 1343 -267 l 1343 -297 1340 -320 1334 -335 ct +1328 -350 1318 -362 1303 -371 ct 1289 -380 1271 -384 1251 -384 ct 1220 -384 1192 -374 1169 -354 ct +1146 -334 1135 -296 1135 -239 ct 1135 0 l p ef +1822 0 m 1822 -55 l 1794 -11 1754 9 1699 9 ct 1664 9 1632 0 1603 -19 ct 1574 -38 1551 -65 1535 -99 ct +1519 -134 1510 -174 1510 -219 ct 1510 -263 1518 -302 1532 -338 ct 1547 -374 1569 -401 1598 -420 ct +1627 -439 1660 -449 1696 -449 ct 1723 -449 1746 -443 1767 -432 ct 1788 -421 1804 -406 1817 -388 ct +1817 -606 l 1891 -606 l 1891 0 l p +1587 -219 m 1587 -162 1599 -120 1623 -93 ct 1646 -65 1674 -51 1706 -51 ct 1739 -51 1767 -64 1789 -91 ct +1812 -117 1824 -158 1824 -212 ct 1824 -273 1812 -317 1789 -345 ct 1766 -373 1737 -387 1703 -387 ct +1670 -387 1642 -374 1620 -346 ct 1598 -319 l 1587 -277 l p ef +2094 0 m 1960 -439 l 2037 -439 l 2107 -185 l 2133 -91 l 2134 -96 2142 -126 2156 -181 ct +2226 -439 l 2302 -439 l 2368 -184 l 2390 -100 l 2415 -185 l 2490 -439 l +2563 -439 l 2425 0 l 2348 0 l 2278 -263 l 2261 -337 l 2172 0 l p ef +2596 -520 m 2596 -606 l 2670 -606 l 2670 -520 l p +2596 0 m 2596 -439 l 2670 -439 l 2670 0 l p ef +3065 0 m 3065 -55 l 3037 -11 2997 9 2942 9 ct 2907 9 2875 0 2846 -19 ct 2817 -38 2794 -65 2778 -99 ct +2762 -134 2753 -174 2753 -219 ct 2753 -263 2761 -302 2775 -338 ct 2790 -374 2812 -401 2841 -420 ct +2870 -439 2903 -449 2939 -449 ct 2966 -449 2989 -443 3010 -432 ct 3031 -421 3047 -406 3060 -388 ct +3060 -606 l 3134 -606 l 3134 0 l p +2830 -219 m 2830 -162 2842 -120 2866 -93 ct 2889 -65 2917 -51 2949 -51 ct 2982 -51 3010 -64 3032 -91 ct +3055 -117 3067 -158 3067 -212 ct 3067 -273 3055 -317 3032 -345 ct 3009 -373 2980 -387 2946 -387 ct +2913 -387 2885 -374 2863 -346 ct 2841 -319 l 2830 -277 l p ef +3419 -66 m 3430 0 l 3409 3 3390 5 3373 5 ct 3346 5 3325 1 3311 -7 ct 3296 -15 3285 -26 3279 -40 ct +3273 -54 3270 -83 3270 -128 ct 3270 -381 l 3215 -381 l 3215 -439 l 3270 -439 l +3270 -547 l 3344 -592 l 3344 -439 l 3419 -439 l 3419 -381 l 3344 -381 l +3344 -124 l 3344 -103 3345 -89 3348 -83 ct 3351 -77 3355 -72 3361 -69 ct 3367 -65 3375 -63 3386 -63 ct +3394 -63 l 3405 -64 l p ef +3495 0 m 3495 -606 l 3570 -606 l 3570 -388 l 3605 -429 3648 -449 3701 -449 ct +3734 -449 3762 -442 3786 -429 ct 3810 -417 3827 -399 3838 -376 ct 3848 -354 3853 -321 3853 -278 ct +3853 0 l 3779 0 l 3779 -278 l 3779 -315 3771 -342 3754 -359 ct 3738 -376 3716 -385 3686 -385 ct +3664 -385 3643 -379 3624 -367 ct 3604 -356 3590 -340 3582 -321 ct 3574 -301 3570 -274 3570 -240 ct +3570 0 l p ef +pom +pum +15888 15055 t +340 0 m 340 -55 l 312 -11 272 9 217 9 ct 182 9 150 0 121 -19 ct 92 -38 69 -65 53 -99 ct +37 -134 28 -174 28 -219 ct 28 -263 36 -302 50 -338 ct 65 -374 87 -401 116 -420 ct +145 -439 178 -449 214 -449 ct 241 -449 264 -443 285 -432 ct 306 -421 322 -406 335 -388 ct +335 -606 l 409 -606 l 409 0 l p +105 -219 m 105 -162 117 -120 141 -93 ct 164 -65 192 -51 224 -51 ct 257 -51 285 -64 307 -91 ct +330 -117 342 -158 342 -212 ct 342 -273 330 -317 307 -345 ct 284 -373 255 -387 221 -387 ct +188 -387 160 -374 138 -346 ct 116 -319 l 105 -277 l p ef +832 -141 m 909 -131 l 897 -86 874 -52 842 -27 ct 809 -2 767 9 716 9 ct 652 9 601 -9 563 -49 ct +525 -88 507 -144 507 -215 ct 507 -289 526 -347 564 -387 ct 602 -428 651 -449 712 -449 ct +770 -449 818 -429 856 -389 ct 893 -349 911 -292 911 -220 ct 911 -216 911 -209 911 -200 ct +583 -200 l 586 -152 600 -115 624 -89 ct 649 -64 680 -51 716 -51 ct 744 -51 767 -58 786 -72 ct +805 -87 l 821 -110 l p +588 -261 m 833 -261 l 830 -298 820 -326 805 -344 ct 781 -373 750 -387 712 -387 ct +678 -387 650 -376 626 -353 ct 603 -330 l 590 -300 l p ef +1295 -160 m 1368 -151 l 1360 -100 1340 -61 1307 -32 ct 1274 -4 1233 9 1185 9 ct +1125 9 1077 -9 1040 -49 ct 1004 -88 986 -144 986 -217 ct 986 -265 993 -306 1009 -342 ct +1025 -378 1049 -404 1081 -422 ct 1113 -440 1148 -449 1186 -449 ct 1233 -449 1272 -437 1303 -412 ct +1333 -388 1353 -354 1361 -310 ct 1289 -299 l 1282 -328 1270 -350 1252 -365 ct +1235 -380 1213 -387 1189 -387 ct 1151 -387 1121 -374 1097 -347 ct 1074 -320 1062 -278 1062 -220 ct +1062 -161 1073 -118 1096 -91 ct 1119 -64 1148 -51 1185 -51 ct 1214 -51 1238 -60 1258 -78 ct +1277 -96 l 1290 -123 l p ef +1432 -520 m 1432 -606 l 1506 -606 l 1506 -520 l p +1432 0 m 1432 -439 l 1506 -439 l 1506 0 l p ef +1616 0 m 1616 -439 l 1683 -439 l 1683 -377 l 1697 -399 1715 -416 1738 -429 ct +1761 -442 1787 -449 1816 -449 ct 1849 -449 1875 -442 1896 -428 ct 1917 -415 1932 -396 1940 -372 ct +1975 -423 2020 -449 2076 -449 ct 2119 -449 2153 -437 2176 -412 ct 2200 -388 2211 -351 2211 -301 ct +2211 0 l 2137 0 l 2137 -276 l 2137 -306 2135 -327 2130 -340 ct 2125 -354 2117 -364 2104 -372 ct +2091 -380 2076 -384 2059 -384 ct 2028 -384 2003 -374 1982 -353 ct 1962 -333 1952 -300 1952 -255 ct +1952 0 l 1877 0 l 1877 -285 l 1877 -318 1871 -343 1859 -359 ct 1847 -376 1827 -384 1800 -384 ct +1779 -384 1759 -379 1741 -368 ct 1724 -357 1711 -340 1703 -319 ct 1695 -298 1691 -267 1691 -227 ct +1691 0 l p ef +2617 -54 m 2589 -30 2563 -14 2537 -4 ct 2512 5 2484 9 2455 9 ct 2407 9 2370 -1 2344 -25 ct +2318 -49 2305 -79 2305 -115 ct 2305 -137 2310 -156 2320 -174 ct 2330 -192 2342 -206 2358 -217 ct +2374 -228 2392 -236 2412 -241 ct 2426 -245 2448 -249 2478 -253 ct 2538 -260 2582 -268 2611 -278 ct +2611 -288 2611 -295 2611 -298 ct 2611 -328 2604 -349 2590 -362 ct 2571 -379 2543 -387 2505 -387 ct +2470 -387 2444 -381 2428 -369 ct 2411 -356 2399 -335 2391 -303 ct 2318 -313 l +2325 -345 2335 -370 2351 -389 ct 2366 -408 2388 -423 2416 -433 ct 2445 -443 2478 -449 2516 -449 ct +2554 -449 2584 -444 2607 -435 ct 2631 -427 2648 -415 2659 -402 ct 2670 -389 2678 -372 2682 -351 ct +2685 -339 2686 -316 2686 -283 ct 2686 -184 l 2686 -114 2688 -71 2691 -52 ct +2694 -34 2700 -16 2710 0 ct 2632 0 l 2624 -15 l 2619 -33 l p +2611 -220 m 2584 -209 2543 -200 2489 -192 ct 2459 -187 2437 -182 2424 -177 ct +2412 -171 2402 -163 2395 -153 ct 2388 -142 2385 -130 2385 -117 ct 2385 -98 2392 -81 2407 -68 ct +2422 -55 2444 -48 2473 -48 ct 2502 -48 2527 -54 2550 -67 ct 2572 -79 2588 -96 2599 -118 ct +2607 -135 2611 -160 2611 -193 ct p ef +2943 -66 m 2954 0 l 2933 3 2914 5 2897 5 ct 2870 5 2849 1 2835 -7 ct 2820 -15 2809 -26 2803 -40 ct +2797 -54 2794 -83 2794 -128 ct 2794 -381 l 2739 -381 l 2739 -439 l 2794 -439 l +2794 -547 l 2868 -592 l 2868 -439 l 2943 -439 l 2943 -381 l 2868 -381 l +2868 -124 l 2868 -103 2869 -89 2872 -83 ct 2875 -77 2879 -72 2885 -69 ct 2891 -65 2899 -63 2910 -63 ct +2918 -63 l 2929 -64 l p ef +3019 -520 m 3019 -606 l 3093 -606 l 3093 -520 l p +3019 0 m 3019 -439 l 3093 -439 l 3093 0 l p ef +3177 -219 m 3177 -300 3199 -361 3244 -400 ct 3282 -432 3328 -449 3383 -449 ct +3443 -449 3492 -429 3531 -389 ct 3569 -350 3588 -295 3588 -225 ct 3588 -169 3580 -124 3563 -92 ct +3546 -60 3521 -34 3489 -16 ct 3456 0 3421 9 3383 9 ct 3321 9 3271 -9 3233 -49 ct +3196 -88 l 3177 -145 l p +3253 -219 m 3253 -163 3265 -121 3290 -93 ct 3314 -65 3345 -51 3383 -51 ct 3420 -51 3450 -65 3475 -93 ct +3499 -121 3512 -164 3512 -222 ct 3512 -276 3499 -317 3475 -345 ct 3450 -373 3419 -387 3383 -387 ct +3345 -387 3314 -373 3290 -345 ct 3265 -317 l 3253 -275 l p ef +3680 0 m 3680 -439 l 3747 -439 l 3747 -376 l 3780 -425 3826 -449 3887 -449 ct +3914 -449 3938 -444 3960 -434 ct 3982 -425 3999 -412 4010 -397 ct 4021 -382 4029 -363 4033 -342 ct +4036 -328 4037 -304 4037 -270 ct 4037 0 l 3963 0 l 3963 -267 l 3963 -297 3960 -320 3954 -335 ct +3948 -350 3938 -362 3923 -371 ct 3909 -380 3891 -384 3871 -384 ct 3840 -384 3812 -374 3789 -354 ct +3766 -334 3755 -296 3755 -239 ct 3755 0 l p ef +pom +pum +16087 16008 t +73 0 m 73 -381 l 7 -381 l 7 -439 l 73 -439 l 73 -485 l 73 -515 76 -537 81 -551 ct +88 -571 101 -586 119 -598 ct 137 -610 162 -616 195 -616 ct 216 -616 239 -614 264 -609 ct +253 -544 l 238 -547 223 -548 209 -548 ct 187 -548 171 -543 161 -533 ct 152 -524 147 -506 147 -479 ct +147 -439 l 233 -439 l 233 -381 l 147 -381 l 147 0 l p ef +580 -54 m 552 -30 526 -14 500 -4 ct 475 5 447 9 418 9 ct 370 9 333 -1 307 -25 ct +281 -49 268 -79 268 -115 ct 268 -137 273 -156 283 -174 ct 293 -192 305 -206 321 -217 ct +337 -228 355 -236 375 -241 ct 389 -245 411 -249 441 -253 ct 501 -260 545 -268 574 -278 ct +574 -288 574 -295 574 -298 ct 574 -328 567 -349 553 -362 ct 534 -379 506 -387 468 -387 ct +433 -387 407 -381 391 -369 ct 374 -356 362 -335 354 -303 ct 281 -313 l 288 -345 298 -370 314 -389 ct +329 -408 351 -423 379 -433 ct 408 -443 441 -449 479 -449 ct 517 -449 547 -444 570 -435 ct +594 -427 611 -415 622 -402 ct 633 -389 641 -372 645 -351 ct 648 -339 649 -316 649 -283 ct +649 -184 l 649 -114 651 -71 654 -52 ct 657 -34 663 -16 673 0 ct 595 0 l 587 -15 l +582 -33 l p +574 -220 m 547 -209 506 -200 452 -192 ct 422 -187 400 -182 387 -177 ct 375 -171 365 -163 358 -153 ct +351 -142 348 -130 348 -117 ct 348 -98 355 -81 370 -68 ct 385 -55 407 -48 436 -48 ct +465 -48 490 -54 513 -67 ct 535 -79 551 -96 562 -118 ct 570 -135 574 -160 574 -193 ct +p ef +1030 -160 m 1103 -151 l 1095 -100 1075 -61 1042 -32 ct 1009 -4 968 9 920 9 ct +860 9 812 -9 775 -49 ct 739 -88 721 -144 721 -217 ct 721 -265 728 -306 744 -342 ct +760 -378 784 -404 816 -422 ct 848 -440 883 -449 921 -449 ct 968 -449 1007 -437 1038 -412 ct +1068 -388 1088 -354 1096 -310 ct 1024 -299 l 1017 -328 1005 -350 987 -365 ct +970 -380 948 -387 924 -387 ct 886 -387 856 -374 832 -347 ct 809 -320 797 -278 797 -220 ct +797 -161 808 -118 831 -91 ct 854 -64 883 -51 920 -51 ct 949 -51 973 -60 993 -78 ct +1012 -96 l 1025 -123 l p ef +1329 -66 m 1340 0 l 1319 3 1300 5 1283 5 ct 1256 5 1235 1 1221 -7 ct 1206 -15 1195 -26 1189 -40 ct +1183 -54 1180 -83 1180 -128 ct 1180 -381 l 1125 -381 l 1125 -439 l 1180 -439 l +1180 -547 l 1254 -592 l 1254 -439 l 1329 -439 l 1329 -381 l 1254 -381 l +1254 -124 l 1254 -103 1255 -89 1258 -83 ct 1261 -77 1265 -72 1271 -69 ct 1277 -65 1285 -63 1296 -63 ct +1304 -63 l 1315 -64 l p ef +1377 -219 m 1377 -300 1399 -361 1444 -400 ct 1482 -432 1528 -449 1583 -449 ct +1643 -449 1692 -429 1731 -389 ct 1769 -350 1788 -295 1788 -225 ct 1788 -169 1780 -124 1763 -92 ct +1746 -60 1721 -34 1689 -16 ct 1656 0 1621 9 1583 9 ct 1521 9 1471 -9 1433 -49 ct +1396 -88 l 1377 -145 l p +1453 -219 m 1453 -163 1465 -121 1490 -93 ct 1514 -65 1545 -51 1583 -51 ct 1620 -51 1650 -65 1675 -93 ct +1699 -121 1712 -164 1712 -222 ct 1712 -276 1699 -317 1675 -345 ct 1650 -373 1619 -387 1583 -387 ct +1545 -387 1514 -373 1490 -345 ct 1465 -317 l 1453 -275 l p ef +1881 0 m 1881 -439 l 1948 -439 l 1948 -372 l 1965 -403 1980 -424 1995 -434 ct +2009 -444 2025 -449 2043 -449 ct 2068 -449 2093 -441 2119 -425 ct 2094 -356 l +2075 -366 2057 -372 2039 -372 ct 2023 -372 2008 -367 1995 -357 ct 1982 -347 1973 -334 1967 -316 ct +1959 -290 1955 -261 1955 -229 ct 1955 0 l p ef +2802 -356 m 2402 -356 l 2402 -425 l 2802 -425 l p +2802 -172 m 2402 -172 l 2402 -241 l 2802 -241 l p ef +3160 0 m 3160 -606 l 3242 -606 l 3561 -130 l 3561 -606 l 3638 -606 l +3638 0 l 3555 0 l 3237 -476 l 3237 0 l p ef +pom +gr +17781 10461 m 17631 10911 l 17931 10910 l 17781 10461 l p ef +17781 13336 m 17781 10821 l ps +gs +pum +17357 3466 t +73 0 m 73 -381 l 7 -381 l 7 -439 l 73 -439 l 73 -485 l 73 -515 76 -537 81 -551 ct +88 -571 101 -586 119 -598 ct 137 -610 162 -616 195 -616 ct 216 -616 239 -614 264 -609 ct +253 -544 l 238 -547 223 -548 209 -548 ct 187 -548 171 -543 161 -533 ct 152 -524 147 -506 147 -479 ct +147 -439 l 233 -439 l 233 -381 l 147 -381 l 147 0 l p ef +264 -131 m 337 -142 l 341 -113 353 -90 372 -74 ct 391 -59 417 -51 451 -51 ct +485 -51 510 -58 527 -72 ct 544 -86 552 -102 552 -121 ct 552 -138 545 -151 530 -160 ct +520 -167 494 -175 454 -186 ct 399 -199 361 -211 340 -221 ct 319 -231 303 -245 292 -263 ct +281 -281 276 -301 276 -322 ct 276 -342 280 -360 289 -376 ct 298 -393 311 -407 326 -418 ct +338 -427 353 -434 373 -440 ct 393 -446 415 -449 438 -449 ct 472 -449 502 -444 528 -434 ct +555 -424 574 -410 586 -393 ct 599 -376 607 -354 612 -325 ct 539 -315 l 536 -338 526 -356 510 -368 ct +494 -381 472 -387 443 -387 ct 409 -387 384 -382 370 -370 ct 355 -359 348 -346 348 -331 ct +348 -321 351 -312 357 -305 ct 363 -297 373 -290 386 -285 ct 393 -282 415 -276 451 -266 ct +504 -252 541 -240 562 -231 ct 582 -222 599 -209 611 -192 ct 622 -175 628 -154 628 -129 ct +628 -104 621 -80 607 -58 ct 592 -37 571 -20 544 -8 ct 517 3 486 9 451 9 ct 394 9 351 -1 321 -25 ct +291 -49 l 272 -84 l p ef +635 10 m 810 -616 l 870 -616 l 694 10 l p ef +937 0 m 937 -606 l 1019 -606 l 1338 -130 l 1338 -606 l 1415 -606 l +1415 0 l 1332 0 l 1014 -476 l 1014 0 l p ef +pom +gr +22227 6350 m 22199 5876 l 21920 5987 l 22227 6350 l p ef +19422 3175 m 19475 3175 l ps +19528 3175 m 19581 3175 l ps +19634 3175 m 19687 3175 l ps +19740 3175 m 19793 3175 l ps +19846 3175 m 19899 3175 l ps +19952 3175 m 20006 3175 l ps +20059 3175 m 20112 3175 l ps +20165 3175 m 20218 3175 l ps +20271 3175 m 20324 3175 l ps +20377 3175 m 20430 3175 l ps +20483 3175 m 20536 3175 l ps +20590 3175 m 20643 3175 l ps +20696 3175 m 20749 3175 l ps +20802 3175 m 20855 3175 l ps +20908 3175 m 20956 3175 l ps +20956 3175 m 20958 3180 l ps +20977 3229 m 20997 3278 l ps +21017 3328 m 21037 3377 l ps +21056 3426 m 21076 3475 l ps +21096 3525 m 21115 3574 l ps +21135 3623 m 21155 3673 l ps +21175 3722 m 21194 3771 l ps +21214 3821 m 21234 3870 l ps +21254 3919 m 21273 3968 l ps +21293 4018 m 21313 4067 l ps +21332 4116 m 21352 4166 l ps +21372 4215 m 21392 4264 l ps +21411 4313 m 21431 4363 l ps +21451 4412 m 21471 4461 l ps +21490 4511 m 21510 4560 l ps +21530 4609 m 21550 4658 l ps +21569 4708 m 21589 4757 l ps +21609 4806 m 21628 4856 l ps +21648 4905 m 21668 4954 l ps +21688 5003 m 21707 5053 l ps +21727 5102 m 21747 5151 l ps +21767 5201 m 21786 5250 l ps +21806 5299 m 21826 5348 l ps +21845 5398 m 21865 5447 l ps +21885 5496 m 21905 5546 l ps +21924 5595 m 21944 5644 l ps +21964 5693 m 21984 5743 l ps +22003 5792 m 22023 5841 l ps +22043 5891 m 22063 5940 l ps +22082 5989 m 22093 6015 l ps +gr +0 20290 t +pom +count op_count sub {pop} repeat countdictstack dict_count sub {end} repeat b4_inc_state restore +%%PageTrailer +%%Trailer +%%EOF diff --git a/docs/exploring-gnuradio/ddc.png b/docs/exploring-gnuradio/ddc.png new file mode 100644 index 0000000000000000000000000000000000000000..ce35bc2a9ea89e42d75a3c46881fda8f73823a66 GIT binary patch literal 42199 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 N^r^F~E?PQ={11aUo7(^Y literal 0 HcmV?d00001 diff --git a/docs/exploring-gnuradio/dial_tone.py b/docs/exploring-gnuradio/dial_tone.py new file mode 100755 index 00000000..3139ba3a --- /dev/null +++ b/docs/exploring-gnuradio/dial_tone.py @@ -0,0 +1,43 @@ +#!/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 gnuradio import gr +from gnuradio import audio + +def build_graph (): + sampling_freq = 32000 + ampl = 0.1 + + fg = gr.flow_graph () + src0 = gr.sig_source_f (sampling_freq, gr.GR_SIN_WAVE, 350, ampl) + src1 = gr.sig_source_f (sampling_freq, gr.GR_SIN_WAVE, 440, ampl) + dst = audio.sink (sampling_freq) + fg.connect (src0, (dst, 0)) + fg.connect (src1, (dst, 1)) + + return fg + +if __name__ == '__main__': + fg = build_graph () + fg.start () + raw_input ('Press Enter to quit: ') + fg.stop () diff --git a/docs/exploring-gnuradio/dial_tone_example.xml b/docs/exploring-gnuradio/dial_tone_example.xml new file mode 100644 index 00000000..14ea6803 --- /dev/null +++ b/docs/exploring-gnuradio/dial_tone_example.xml @@ -0,0 +1,28 @@ + +Dial Tone Output + +#!/usr/bin/env python + +from gnuradio import gr +from gnuradio import audio + +def build_graph (): + sampling_freq = 48000 + ampl = 0.1 + + fg = gr.flow_graph () + src0 = gr.sig_source_f (sampling_freq, gr.GR_SIN_WAVE, 350, ampl) + src1 = gr.sig_source_f (sampling_freq, gr.GR_SIN_WAVE, 440, ampl) + dst = audio.sink (sampling_freq) + fg.connect ((src0, 0), (dst, 0)) + fg.connect ((src1, 0), (dst, 1)) + + return fg + +if __name__ == '__main__': + fg = build_graph () + fg.start () + raw_input ('Press Enter to quit: ') + fg.stop () + + diff --git a/docs/exploring-gnuradio/exploring-gnuradio.xml b/docs/exploring-gnuradio/exploring-gnuradio.xml new file mode 100644 index 00000000..9d471f66 --- /dev/null +++ b/docs/exploring-gnuradio/exploring-gnuradio.xml @@ -0,0 +1,460 @@ + + + +]> + +
+ + Exploring GNU Radio + + Eric + Blossom + +
+ eb@comsec.com +
+
+
+ + + + v1.1 + 2004-11-29 + + Revised and expanded. Examples now use 2.x code base. + + + + + v1.0 + 2004-02-29 + + Initial version published in Linux Journal, Issue 122, June 2004, as + GNU Radio: Tools for Exploring the RF Spectrum. + + + + +This article provides an overview of the GNU Radio +toolkit for building software radios. + + +
+ +Introduction + +Software radio is the technique of getting code as close to the +antenna as possible. It turns radio hardware problems into software +problems. The fundamental characteristic of software radio is that +software defines the transmitted waveforms, and software demodulates +the received waveforms. This is in contrast to most radios in which +the processing is done with either analog circuitry or analog +circuitry combined with digital chips. GNU Radio is a free software +toolkit for building software radios. + +Software radio is a revolution in radio design due to its ability to +create radios that change on the fly, creating new choices for +users. At the baseline, software radios can do pretty much anything a +traditional radio can do. The exciting part is the flexibility that +software provides you. Instead of a bunch of fixed function gadgets, +in the next few years we'll see a move to universal communication +devices. Imagine a device that can morph into a cell phone and get you +connectivity using GPRS, 802.11 Wi-Fi, 802.16 WiMax, a satellite +hookup or the emerging standard of the day. You could determine your +location using GPS, GLONASS or both. + +Perhaps most exciting of all is the potential to build decentralized +communication systems. If you look at today's systems, the vast +majority are infrastructure-based. Broadcast radio and TV provide a +one-way channel, are tightly regulated and the content is controlled +by a handful of organizations. Cell phones are a great convenience, +but the features your phone supports are determined by the operator's +interests, not yours. + +A centralized system limits the rate of innovation. We could take some +lessons from the Internet and push the smarts out to the +edges. Instead of cell phones being second-class citizens, usable only +if infrastructure is in place and limited to the capabilities +determined worthwhile by the operator, we could build smarter +devices. These user-owned devices would generate the network. They'd +create a mesh among themselves, negotiate for backhaul and be free to +evolve new solutions, features and applications. + + + +The Block Diagram + + shows a typical block +diagram for a software radio. To understand the software part of the +radio, we first need to understand a bit about the associated +hardware. Examining the receive path in the figure, +we see an antenna, a mysterious RF front end, an analog-to-digital +converter (ADC) and a bunch of code. The analog-to-digital converter +is the bridge between the physical world of continuous analog signals +and the world of discrete digital samples manipulated by +software. + +
Typical software radio block diagram + + + + + +
+ +ADCs have two primary characteristics, sampling rate and dynamic +range. Sampling rate is the number of times per second that the ADC +measures the analog signal. Dynamic range refers to the difference +between the smallest and largest signal that can be distinguished; +it's a function of the number of bits in the ADC's digital output and +the design of the converter. For example, an 8-bit converter at most +can represent 256 (28) signal levels, while +a 16-bit converter represents up to 65,536 levels. Generally speaking, +device physics and cost impose trade-offs between the sample rate and +dynamic range. + +Before we dive into the software, we need to talk about a bit of +theory. In 1927, a Swedish-born physicist and electrical engineer +named Harry Nyquist determined that to avoid aliasing when converting +from analog to digital, the ADC sampling frequency must be at least +twice the bandwidth of the signal of interest. Aliasing is what makes +the wagon wheels look like they're going backward in the old westerns: +the sampling rate of the movie camera is not fast enough to represent +the position of the spokes unambiguously. + +Assuming we're dealing with low pass signals - signals where the +bandwidth of interest goes from 0 to fMAX, the +Nyquist criterion states that our sampling frequency needs to be at +least 2 * fMAX. But if our ADC runs at 20 MHz, +how can we listen to broadcast FM radio at 92.1 MHz? The answer is the +RF front end. The receive RF front end translates a range of +frequencies appearing at its input to a lower range at its output. For +example, we could imagine an RF front end that translated the signals +occurring in the 90 - 100 MHz range down to the 0 - 10 MHz +range. + +Mostly, we can treat the RF front end as a black box with a single +control, the center of the input range that's to be translated. As a +concrete example, a cable modem tuner module that we've employed +successfully has the following characteristics. It translates a 6 MHz +chunk of the spectrum centered between about 50 MHz and 800 MHz down to +an output range centered at 5.75 MHz. The center frequency of the +output range is called the intermediate frequency, or IF. + +In the simplest-thing-that-possibly-could-work category, the RF front +end may be eliminated altogether. One GNU Radio experimenter has +listened to AM and shortwave broadcasts by connecting a 100-foot piece +of wire directly to his 20M sample/sec ADC. + +
+ +On to the Software + +GNU Radio provides a library of signal processing blocks and the +glue to tie it all together. The programmer builds a radio by creating +a graph (as in graph theory) where the vertices are signal processing +blocks and the edges represent the data flow between them. The +signal processing blocks are implemented in C++. Conceptually, +blocks process infinite streams of data flowing from their input +ports to their output ports. Blocks' attributes include the number +of input and output ports they have as well as the type of data that +flows through each. The most frequently used types are short, float +and complex. + +Some blocks have only output ports or input ports. These serve as +data sources and sinks in the graph. There are sources that read from +a file or ADC, and sinks that write to a file, digital-to-analog +converter (DAC) or graphical display. About 100 blocks come with +GNU Radio. Writing new blocks is not difficult. + +Graphs are constructed and run in Python. + +Example 1 +is the "Hello World" of GNU Radio. It generates two sine waves and outputs +them to the sound card, one on the left channel, one on the +right. + +&dial_tone_example; + +We start by creating a flow graph to hold the blocks and +connections between them. The two sine waves are generated by the +gr.sig_source_f calls. The f suffix indicates that the source produces +floats. One sine wave is at 350 Hz, and the other is at +440 Hz. Together, they sound like the US dial tone. + +audio.sink is a sink that writes its input to the sound card. It +takes one or more streams of floats in the range -1 to +1 as its +input. We connect the three blocks together using the +connect method of the flow graph. + +connect takes two parameters, the +source endpoint and the destination endpoint, and creates a connection +from the source to the destination. An endpoint has two components: a +signal processing block and a port number. The port number specifies +which input or output port of the specified block is to be connected. +In the most general form, an endpoint is represented as a python tuple +like this: (block, port_number). When +port_number is zero, the block may be used alone. + + +These two expressions are equivalent: + +fg.connect ((src1, 0), (dst, 1)) +fg.connect (src1, (dst, 1)) + + +Once the graph is built, we start it. Calling +start forks one or more threads to run the +computation described by the graph and returns control immediately to +the caller. In this case, we simply wait for any keystroke. + + + +A Complete FM Receiver + + + +Example 2 +shows a somewhat simplified but +complete broadcast FM receiver. It includes control of the RF front +end and all required signal processing. This example uses an RF front +end built from a cable modem tuner and a 20M sample/sec +analog-to-digital converter. + +&fm_demod_example; + +Like the Hello World example, we build a graph, connect the +blocks together and start it. In this case, our source, mc4020.source, +is an interface to the Measurement Computing PCI-DAS 4020/12 +high-speed ADC. We follow it with gr.freq_xlating_fir_filter_scf, a +finite impulse response (FIR) filter that selects the FM station we're +looking for and translates it to baseband (0Hz, DC). With the 20M +sample/sec converter and cable modem tuner, we're really grabbing +something in the neighborhood of a 6 MHz chunk of the spectrum. This +single chunk may contain ten or more FM stations, and +gr.freq_xlating_fir_filter_scf allows us to select the one we +want. + +In this case, we select the one at the exact center of the IF of +the RF front end (5.75 MHz). The output of +gr.freq_xlating_fir_filter_scf is a stream of complex samples at +160,000 samples/second. We feed the complex baseband signal into +gr.quadrature_demod_cf, the block that does the actual FM +demodulation. + +gr.quadrature_demod_cf works by subtracting the angle of +each adjacent complex sample, effectively differentiating the +frequency. The output of gr.quadrature_demod_cf contains the +left-plus-right FM mono audio signal, the stereo pilot tone at 19kHz, +the left-minus-right stereo information centered at 38kHz and any +other sub-carriers above that. For this simplified receiver, we finish +off by low pass filtering and decimating the stream, keeping only the +left-plus-right audio information, and send that to the sound card at +32,000 samples/sec. + +For a more indepth look at how the FM receiver +works, please see "Listening to FM, Step by Step." + + + +Graphical User Interfaces + +Graphical interfaces for GNU Radio applications are built in +Python. Interfaces may be built using any toolkit you can access from +Python; we recommend wxPython to maximize cross-platform +portability. GNU Radio provides blocks that use interprocess +communication to transfer chunks of data from the real-time C++ flow +graph to Python-land. + + + + + +Hardware Requirements + +GNU Radio is reasonably hardware-independent. Today's commodity +multi-gigahertz, super-scalar CPUs with single-cycle floating-point +units mean that serious digital signal processing is possible on the +desktop. A 3 GHz Pentium or Athlon can evaluate 3 billion +floating-point FIR taps/s. We now can build, virtually all in +software, communication systems unthinkable only a few years ago. + +Your computational requirements depend on what you're trying to do, +but generally speaking, a 1 or 2 GHz machine with at least 256 MB of RAM +should suffice. You also need some way to connect the analog world to +your computer. Low-cost options include built-in sound cards and +audiophile quality 96 kHz, 24-bit, add-in cards. With either of these +options, you are limited to processing relatively narrow band signals +and need to use some kind of narrow-band RF front end. + +Another possible solution is an off-the-shelf, high-speed PCI +analog-to-digital board. These are available in the 20M sample/sec +range, but they are expensive, about the cost of a complete PC. For +these high-speed boards, cable modem tuners make reasonable RF front +ends. + +Finding none of these alternatives completely satisfactory, we +designed the Universal Software Radio Peripheral, or USRP for short. + + + + +The Universal Software Radio Peripheral + +Our preferred hardware solution is the Universal Software Radio +Peripheral (USRP). shows the +block diagram of the USRP. The brainchild of Matt Ettus, the USRP is +an extremely flexible USB device that connects your PC to the RF +world. The USRP consists of a small motherboard containing up to four +12-bit 64M sample/sec ADCs, four 14-bit, 128M sample/sec DACs, a +million gate-field programmable gate array (FPGA) and a programmable +USB 2.0 controller. Each fully populated USRP motherboard supports +four daughterboards, two for receive and two for transmit. RF front +ends are implemented on the daughterboards. A variety of +daughterboards is available to handle different frequency bands. For +amateur radio use, low-power daughterboards are available that receive +and transmit in the 440 MHz band and the 1.24 GHz band. A receive-only +daughterboard based on a cable modem tuner is available that covers +the range from 50 MHz to 800 MHz. Daughterboards are designed to be easy +to prototype by hand in order to facilitate experimentation. + +
Universal Software Radio Peripheral + + + + + +
+ +The flexibility of the USRP comes from the two programmable components +on the board and their interaction with the host-side library. To get +a feel for the USRP, let's look at its boot sequence. The USRP itself +contains no ROM-based firmware, merely a few bytes that specify the +vendor ID (VID), product ID (PID) and revision. When the USRP is +plugged in to the USB for the first time, the host-side library sees +an unconfigured USRP. It can tell it's unconfigured by reading the +VID, PID and revision. The first thing the library code does is +download the 8051 code that defines the behavior of the USB peripheral +controller. When this code boots, the USRP simulates a USB disconnect +and reconnect. When it reconnects, the host sees a different device: +the VID, PID and revision are different. The firmware now running +defines the USB endpoints, interfaces and command handlers. One of the +commands the USB controller now understands is load the FPGA. The +library code, after seeing the USRP reconnect as the new device, goes +to the next stage of the boot process and downloads the FPGA +configuration bitstream. + +FPGAs are generic hardware chips whose behavior is determined by the +configuration bitstream that's loaded into them. You can think of the +bitstream as object code. The bitstream is the output of compiling a +high-level description of the design. In our case, the design is coded +in the Verilog hardware description language. This is source code and, +like the rest of the code in GNU Radio, is licensed under the GNU +General Public License. + +
+ +What Goes in the FPGA? + +An FPGA is like a small, massively parallel computer that you design +to do exactly what you want. Programming the FPGA takes a bit of +skill, and mistakes can fry the board permanently. That said, we +provide a standard configuration that is useful for a wide variety of +applications. + +Using a good USB host controller, the USRP can sustain 32 MB/sec across +the USB. The USB is half-duplex. Based on your needs, you partition +the 32 MB/sec between the transmit and the receive directions. In the +receive direction, the standard configuration allows you to select the +part or parts of the digitized spectrum you're interested in, +translate them to baseband and decimate as required. This is exactly +equivalent to what's happening in the RF front end, only now we're +doing it on digitized samples. The block of code that performs this +function is called a digital down converter (). +One advantage of performing this function in the digital domain is we can change the +center frequency instantaneously, which is handy for frequency hopping +spread spectrum systems. + +
Digital Down Converter Block Diagram + + + + + +
+ + +In the transmit direction, the exact inverse is performed. The FPGA +contains multiple instances of the digital up and down +converters. These instances can be connected to the same or different +ADCs, depending on your needs. We don't have room here to cover all +the theory behind them; see the GNU Radio Wiki for more information. + +
+ +GNU Radio Applications + +In addition to the examples discussed above, GNU Radio comes with a +complete HDTV transmitter and receiver, a spectrum analyzer, an +oscilloscope, concurrent multichannel receiver and an ever-growing +collection of modulators and demodulators. + +Projects under investigation or in progress include: + + +A TiVo equivalent for radio, capable of recording multiple stations simultaneously. +Time Division Multiple Access (TDMA) waveforms. +A passive radar system that takes advantage of +broadcast TV for its signal source. For those of you with old TVs +hooked to antennas, think about the flutter you see when airplanes fly +over. +Radio astronomy. +TETRA transceiver. +Digital Radio Mundial (DRM). +Software GPS. +Distributed sensor networks. +Distributed measurement of spectrum utilization. +Amateur radio transceivers. +Ad hoc mesh networks. +RFID detector/reader. +Multiple input multiple output (MIMO) processing. + + + + +Politics + +Every revolution has its political issues. Free software for building +radios is troublesome to some people. In the US, we've run into +opposition from the Motion Picture Association of America and its +attempt with the Broadcast Flag to restrict the kinds of receivers +that can be built for over-the-air digital TV. + +The US Federal Communications Commission has issued a Notice of +Proposed Rule Making (NPRM) concerning Cognitive Radio +Technologies and Software Defined Radios. Several troublesome +issues are raised in the NPRM, including restricting the sale of +high-speed digital-to-analog converters, requirements for digital +signatures or similar methods to keep unauthorized software out of +software radio hardware and new restrictions on radios built for the +amateur radio market. + + + +Summary + +Software radio is an exciting field, and GNU Radio provides the tools +to start exploring. A deep understanding of software radio requires +knowledge from many domains. We're doing our best to lower the +barriers to entry. + + + + +
diff --git a/docs/exploring-gnuradio/fm_demod.py b/docs/exploring-gnuradio/fm_demod.py new file mode 100755 index 00000000..e58407f7 --- /dev/null +++ b/docs/exploring-gnuradio/fm_demod.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python + +from gnuradio import gr +from gnuradio import audio +from gnuradio import mc4020 +import sys + +def high_speed_adc (fg, input_rate): + # return gr.file_source (gr.sizeof_short, "dummy.dat", False) + return mc4020.source (input_rate, mc4020.MCC_CH3_EN | mc4020.MCC_ALL_1V) + +# +# return a gr.flow_graph +# +def build_graph (freq1, freq2): + input_rate = 20e6 + cfir_decimation = 125 + audio_decimation = 5 + + quad_rate = input_rate / cfir_decimation + audio_rate = quad_rate / audio_decimation + + fg = gr.flow_graph () + + # use high speed ADC as input source + src = high_speed_adc (fg, input_rate) + + # compute FIR filter taps for channel selection + channel_coeffs = \ + gr.firdes.low_pass (1.0, # gain + input_rate, # sampling rate + 250e3, # low pass cutoff freq + 8*100e3, # width of trans. band + gr.firdes.WIN_HAMMING) + + # input: short; output: complex + chan_filter1 = \ + gr.freq_xlating_fir_filter_scf (cfir_decimation, + channel_coeffs, + freq1, # 1st station freq + input_rate) + + (head1, tail1) = build_pipeline (fg, quad_rate, audio_decimation) + + # sound card as final sink + audio_sink = audio.sink (int (audio_rate)) + + # now wire it all together + fg.connect (src, chan_filter1) + fg.connect (chan_filter1, head1) + fg.connect (tail1, (audio_sink, 0)) + + # two stations at once? + if freq2: + # Extract the second station and connect + # it to a second pipeline... + + # input: short; output: complex + chan_filter2 = \ + gr.freq_xlating_fir_filter_scf (cfir_decimation, + channel_coeffs, + freq2, # 2nd station freq + input_rate) + + (head2, tail2) = build_pipeline (fg, quad_rate, audio_decimation) + + fg.connect (src, chan_filter2) + fg.connect (chan_filter2, head2) + fg.connect (tail2, (audio_sink, 1)) + + return fg + +def build_pipeline (fg, quad_rate, audio_decimation): + '''Given a flow_graph, fg, construct a pipeline + for demodulating a broadcast FM signal. The + input is the downconverteed complex baseband + signal. The output is the demodulated audio. + + build_pipeline returns a two element tuple + containing the input and output endpoints. + ''' + fm_demod_gain = 2200.0/32768.0 + audio_rate = quad_rate / audio_decimation + volume = 1.0 + + # input: complex; output: float + fm_demod = gr.quadrature_demod_cf (volume*fm_demod_gain) + + # compute FIR filter taps for audio filter + width_of_transition_band = audio_rate / 32 + audio_coeffs = gr.firdes.low_pass (1.0, # gain + quad_rate, # sampling rate + audio_rate/2 - width_of_transition_band, + width_of_transition_band, + gr.firdes.WIN_HAMMING) + + # input: float; output: float + audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs) + + fg.connect (fm_demod, audio_filter) + return ((fm_demod, 0), (audio_filter, 0)) + + +def main (args): + nargs = len (args) + if nargs == 1: + freq1 = float (args[0]) * 1e6 + freq2 = None + elif nargs == 2: + freq1 = float (args[0]) * 1e6 + freq2 = float (args[1]) * 1e6 + else: + sys.stderr.write ('usage: fm_demod freq1 [freq2]\n') + sys.exit (1) + + # connect to RF front end + rf_front_end = gr.microtune_4937_eval_board () + if not rf_front_end.board_present_p (): + raise IOError, 'RF front end not found' + + # set front end gain + rf_front_end.set_AGC (300) + IF_freq = rf_front_end.get_output_freq () + IF_freq = 5.75e6 + + if not freq2: # one station + + rf_front_end.set_RF_freq (freq1) + fg = build_graph (IF_freq, None) + + else: # two stations + + if abs (freq1 - freq2) > 5.5e6: + raise IOError, 'freqs too far apart' + + target_freq = (freq1 + freq2) / 2 + actual_freq = rf_front_end.set_RF_freq (target_freq) + #actual_freq = target_freq + + fg = build_graph (IF_freq + freq1 - actual_freq, + IF_freq + freq2 - actual_freq) + + fg.start () # fork thread(s) and return + raw_input ('Press Enter to quit: ') + fg.stop () + +if __name__ == '__main__': + main (sys.argv[1:]) + + diff --git a/docs/exploring-gnuradio/fm_demod_example.xml b/docs/exploring-gnuradio/fm_demod_example.xml new file mode 100644 index 00000000..3036f88b --- /dev/null +++ b/docs/exploring-gnuradio/fm_demod_example.xml @@ -0,0 +1,123 @@ + +Broadcast FM Receiver + +#!/usr/bin/env python + +from gnuradio import gr +from gnuradio import audio +from gnuradio import mc4020 +import sys + +def high_speed_adc (fg, input_rate): + # return gr.file_source (gr.sizeof_short, "dummy.dat", False) + return mc4020.source (input_rate, mc4020.MCC_CH3_EN | mc4020.MCC_ALL_1V) + +# +# return a gr.flow_graph +# +def build_graph (freq1, freq2): + input_rate = 20e6 + cfir_decimation = 125 + audio_decimation = 5 + + quad_rate = input_rate / cfir_decimation + audio_rate = quad_rate / audio_decimation + + fg = gr.flow_graph () + + # use high speed ADC as input source + src = high_speed_adc (fg, input_rate) + + # compute FIR filter taps for channel selection + channel_coeffs = \ + gr.firdes.low_pass (1.0, # gain + input_rate, # sampling rate + 250e3, # low pass cutoff freq + 8*100e3, # width of trans. band + gr.firdes.WIN_HAMMING) + + # input: short; output: complex + chan_filter1 = \ + gr.freq_xlating_fir_filter_scf (cfir_decimation, + channel_coeffs, + freq1, # 1st station freq + input_rate) + + (head1, tail1) = build_pipeline (fg, quad_rate, audio_decimation) + + # sound card as final sink + audio_sink = audio.sink (int (audio_rate)) + + # now wire it all together + fg.connect (src, chan_filter1) + fg.connect (chan_filter1, head1) + fg.connect (tail1, (audio_sink, 0)) + + return fg + +def build_pipeline (fg, quad_rate, audio_decimation): + '''Given a flow_graph, fg, construct a pipeline + for demodulating a broadcast FM signal. The + input is the downconverted complex baseband + signal. The output is the demodulated audio. + + build_pipeline returns a two element tuple + containing the input and output endpoints. + ''' + fm_demod_gain = 2200.0/32768.0 + audio_rate = quad_rate / audio_decimation + volume = 1.0 + + # input: complex; output: float + fm_demod = gr.quadrature_demod_cf (volume*fm_demod_gain) + + # compute FIR filter taps for audio filter + width_of_transition_band = audio_rate / 32 + audio_coeffs = gr.firdes.low_pass (1.0, # gain + quad_rate, # sampling rate + audio_rate/2 - width_of_transition_band, + width_of_transition_band, + gr.firdes.WIN_HAMMING) + + # input: float; output: float + audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs) + + fg.connect (fm_demod, audio_filter) + return ((fm_demod, 0), (audio_filter, 0)) + + +def main (args): + nargs = len (args) + if nargs == 1: + # get station frequency from command line + freq1 = float (args[0]) * 1e6 + else: + sys.stderr.write ('usage: fm_demod freq\n') + sys.exit (1) + + # connect to RF front end + rf_front_end = gr.microtune_4937_eval_board () + if not rf_front_end.board_present_p (): + raise IOError, 'RF front end not found' + + # set front end gain + rf_front_end.set_AGC (300) + + # determine the front end's "Intermediate Frequency" + IF_freq = rf_front_end.get_output_freq () # 5.75e6 + + # Tell the front end to tune to freq1. + # I.e., freq1 is translated down to the IF frequency + rf_front_end.set_RF_freq (freq1) + + # build the flow graph + fg = build_graph (IF_freq, None) + + fg.start () # fork thread(s) and return + raw_input ('Press Enter to quit: ') + fg.stop () + +if __name__ == '__main__': + main (sys.argv[1:]) + + diff --git a/docs/exploring-gnuradio/swr-block-diagram.eps b/docs/exploring-gnuradio/swr-block-diagram.eps new file mode 100644 index 00000000..dd029f35 --- /dev/null +++ b/docs/exploring-gnuradio/swr-block-diagram.eps @@ -0,0 +1,2399 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 755 575 +%%Pages: 0 +%%Creator: Sun Microsystems, Inc. +%%Title: none +%%CreationDate: none +%%LanguageLevel: 2 +%%EndComments +%%BeginPreview: 760 575 1 1725 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000800000000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000400000000800000000800000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000001000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000002000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000002000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000080000000800000004000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000080000000800000004000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000040000000800000008000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000010000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000020000000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000010000000800000020000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000008000000800000040000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000080000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000080000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000002000000800000100000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000002000000800000100000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000001000000800000200000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000400000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000800000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFF +%FFFF000000000000000000000000000000 +%000000000000400000800000800000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000030000000000000000000000 +%0000E00000000000000000000000000000 +%000000000000200000800001000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000080000000000000000000000 +%0000080000000000000000000000000000 +%000000000000000000800002000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000040000000000000000000000000000 +%000000000000100000800002000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000020000000000000000000000000000 +%000000000000080000800004000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000080000800004000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000040000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000001000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800010000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000002000000000000000000000000 +%0000004000000000000000000000000000 +%000000000000020000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000002000000000000000000000000000 +%000000000000010000800020000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000008000800040000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800080000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000004000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000002000800100000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000002000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800400000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000400800800000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000200801000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000802000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000100800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000080804000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000080800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000810000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000010820000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000008840000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000880000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000004800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000002900000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000002800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000C00000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000C00000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%0000000000000000008000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000 +%0000000000000000FFFFFFFFFFFFFFFFFF80000000000000000000000000000380180000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000180380000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%0000000000000002000000000000000000000000000000000000000000000001C0700000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%0000000000000004000000000000000000000000000000000000000000000000C0E00000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000E1C07008184600 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%000000000000001000000000000000000000000000000000000000000000000061C1FC1818FE00 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%000000000000002000000000000000000000000000000000000000000000000073838E1818FC00 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000003707061838E000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000000000800000000000000000000000000000000000000000000000003E0E073030E000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000000001000000000000000000000000000000000000000000000000001C0C033030C000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000001C0C073030C000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%0000000000000400000000000000000000000000000000000000000000000000180C0630318000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%0000000000000800000000000000000000000000000000000000000000000000180C0670718000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400FFC00000000000C000000001FF00FFE00000000 +%0000000000000000000000000000000000000000000000000000000000000000180C0E70618000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400FFF00000000000C000000003FFC0FFE00000000 +%0000000000002000000000000000000000000000000000000000000000000000180E1C70E18000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400E0780000000000C00000000381E0FFE00000000 +%00000000000040000000000000000000000000000000000000000000000000003807783F630000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C01C000000000000000000038070C0000000000 +%00000000000000000000000000000000000000000000000000000000000000003003F01E630000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C01C000000000000000000038030C0000000000 +%000000000001000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C01C1F007C07C0CE060F80038030C0000000000 +%000000000002000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C01C3FC1FE1FE0C6063FC0038070C0000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C03860E3873830C60C70600380E0C0000000000 +%000000000008000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400FFF06063033018C60C607003FFC0FFC00000000 +%000000000010000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400FFC0C063003018C30C603003FF00FFC00000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C1C0FFE3003FF8C3187FF0038300C0000000000 +%000000000040000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C0E0FFE3003FF8C1987FF0038180C0000000000 +%000000000080000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C070C003003000C19860000381C0C0000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C038C063033018C1B060200380E0C0000000000 +%000000000200000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C0386063833838C0F07070038060C0000000000 +%0000000004000001C03FF000FE00000000000000000000000000000000000001F8000000300000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C01C71E1C61C70C0E038E0038070C0000000000 +%0000000000000001C03FFC03FF00000000000000000000000000000000000007FE000000300000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C00E3FC0FE0FE0C0E01FC0038038C0000000000 +%0000000010000003E0301E07838000000000000000000000000000000000000E0E000000300000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400C00E0E00380380C0400700010018C0000000000 +%00000000200000036030060601C000000000000000000000000000000000001C07000000700000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000000000077030070E00C00000000000000000000000000000000000380301C00C603800 +%0000001000000000000000000000000000 +%000000000000000000800000000000000C00400000000000000000000000000000000000000000 +%0001C000800000063030030C00000000000000000000000000C00000000000300007F03F60FE00 +%0000001000000000000000000000000000 +%000000000000000000800000000000000F80400000000000000000000000000000000000000000 +%0001F001000000063830031C00000000000000000000000000F8000000000070000C3871E1C700 +%0000001000000000000000000000000000 +%000000000000000000800000000000000FF8400000000000000000000000000000000000000000 +%0001FF000000000E1830031C00000000000000000000000000FF800000000060001818E0E30300 +%0000001000000000000000000000000000 +%000000000000000000800000000000000FFE400000000000000000000000000000000000000000 +%0001FFE40000000C1830031C00000000000000000000000000FFE00000000060003018C0C70300 +%0000001000000000000000000000000000 +%0000000000000000007FFFFFFFFFFFFFFFFFC000000000000000000000000000000000003FFFFF +%FFFFFFF80000000C1C30031C00000000007FFFFFFFFFFFFFFFFFF80000000060003019C0C70300 +%0000001000000000000000000000000000 +%000000000000000000000000000000000FF8400000000000000000000000000000000000000000 +%0001FF000000001FFC30030C00000000000000000000000000FF80000000006000301980C7FF00 +%0000001000000000000000000000000000 +%000000000000000000000000000000000FE0400000000000000000000000000000000000000000 +%0001FC020000001FFC30030C00C00000000000000000000000FE00000000006006701980C60000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000F00400000000000000000000000000000000000000000 +%0001F001000000380E30070E00C00000000000000000000000F00000000000700E701981C60000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003FF80000000000003FFC00000080000000000 +%00000000000000300630060601C00000000000000000000000000000000000300C303181860600 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003FFC0000000006003FFE000000C0000000000 +%000000004000003007301E0783800000000000000000000000000000000000381C3071C3870E00 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003800000000000E003800000000C0000000000 +%0000000020000070033FFC03FF0000000000000000000000000000000000001FF81FE0FF83FC00 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003000000000000E003000000000C0000000000 +%000000000000006003BFF000FC00000000000000000000000000000000000007E00F807981F000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003000000000000E003000000000C0000000000 +%000000000800000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003000DE1F833E1F80300037C03CC0000000000 +%000000000400000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003000FE7FC3FF0E0030003FF0FFC0000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003000E060E3830E0030003871C3C0000000000 +%000000000100000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003FF0E0E063838E003FFC303181C0000000000 +%000000000080000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003FF0E0C073038E003FFC303180C0000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003000C0C033038E003000303180C0000000000 +%000000000020000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003000C0C033038E003000303180C0000000000 +%000000000010000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003000C0C033038E003000303180C0000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003000C0C063038E003000303181C0000000000 +%000000000004000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003000C06063038E0030003031C1C0000000000 +%0000000000020000000000000000000000000000000000000000000000000038030000000001C0 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003000C071C30387003FFE3030E7C0000000000 +%0000000000000000000000000000000000000000000000000000000000000038070000000001C0 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400003000C03F830387803FFE30307EC0000000000 +%000000000000800000000000000000000000000000000000000000000000003006000000000180 +%0000001000000000000000000000000000 +%0000000000000000000000000000000000004000030004006030103803FFE30301880000000000 +%000000000000400000000000000000000000000000000000000000000000003006000000000180 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000030060380CC0E0380 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%0000000000001000000000000000000000000000000000000000000000000070060FE0DE3F8380 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000008000000000000000000000000000000000000000000000000700E1C70F061C300 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000007FFC3030E0C0C300 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%000000000000020000000000000000000000000000000000000000000000007FFC7039C1C0C300 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000001000000000000000000000000000000000000000000000000E00C7FF981FFC200 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000C01C7FF181FFC200 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000400000000000000000000000000000000000000000000000C01C600181800200 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000C018600381800000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000C018606301818000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000001C01870E301C38000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000001C0183FC300FF0E00 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000180380F03007C0C00 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000400000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%0000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000 +%00000000000000007FFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000002000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000002000000000000000000000000 +%0000004000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000001000000000000000000000000 +%0000004000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000001000000000000000000000000 +%0000008000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000800000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000400000000000000000000000 +%0000010000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000300000000000000000000000 +%0000060000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000080000000000000000000000 +%0000180000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000020000000000000000000000 +%0000200000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000001C000000000000000000000 +%0001800000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000007FF00000 +%0000006000000001FF800000300000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000007FFC0000 +%0000006000000001FFC0000C300000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000000700C0000 +%000000000000000180E0000C300000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000000700E0000 +%00000000000000018060000C300000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000070060300 +%1C01C062010380018070381F318000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000000700E1FC0 +%7F07F063030FE0018070FE1F3FE000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000000700E38E0 +%E38E3863031C70018061C70C3E7000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000007FFC3031 +%C19C1C630638300180E3830C383000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000007FF06031 +%80180C6186301801FFC0030C303800000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000071E07FF1 +%801FFC61863FF801FF80070C303800000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000070707FF9 +%801FFC618C3FF8018000FF0C303800000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000070386001 +%80180060CC3000018001E30C303800000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000070386001 +%80180060CC3000018003830C303800000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000000701C3031 +%819C0C60783018018003030C303800000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000000700E3871 +%C18C1C60783830018003070C303800000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000000700E1FE0 +%FF0FF860701FF0018003DF0F303800000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000070070FC0 +%3E03E0603007C0018001F987B03800000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000400000000800000000800000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000400000000800000000800000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000200000000800000001000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000002000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000100000000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000080000000800000004000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000008000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000010000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000010000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000010000000800000020000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000010000000800000020000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000008000000800000040000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000080000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000004000000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000002000000800000100000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000200000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000400000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800000400000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000400000800000800000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000038000000000000000000000 +%0000E00000000000000000000000000000 +%000000000000400000800000800000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000C0000000000000000000000 +%0000180000000000000000000000000000 +%000000000000200000800001000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000100000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800002000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000400000000000000000000000 +%0000000000000000000000000000000000 +%000000000000100000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000800000000000000000000000 +%0000000000000000000000000000000000 +%000000000000080000800004000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800008000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000001000000000000000000000000 +%0000004000000000000000000000000000 +%000000000000000000800010000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000002000000000000000000000000 +%0000004000000000000000000000000000 +%000000000000000000800010000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000002000000000000000000000000000 +%000000000000010000800020000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000002000000000000000000000000000 +%000000000000010000800020000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000008000800040000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000800080000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000004000800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000002000800100000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000001000800200000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800400000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800400000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000400800800000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000400800800000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000200801000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000802000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000100800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000080804000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000040808000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000810000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000810000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000010820000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000010800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000008840000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000880000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000004900000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000002800000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000001A00000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000C00000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000C00000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000400000 +%000000000000000000000000000000000080000000000000000000000000000380380000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000180700000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000C0700000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000C0E00000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000E1C0F818186E00 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000006383FC1818FE00 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000007307061818F000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000003706061838E000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000001E0E073030C000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000001C0C033030C000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000001C0C073030C000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000180C0630718000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000180C0670718000 +%0000001000000000000000000000000000 +%0000000000000000008000000000000000004000000180380000180001FFC0FFF0000000000000 +%0000000000000000000000000000000000000000000000000000000000000000180C0C70E18000 +%0000001000000000000000000000000000 +%00000000000000000080000000000000000040000001C0700000186001FFE0FFF0000000000000 +%0000000000000000000000000000000000000000000000000000000000000000380E1C71E18000 +%0000001000000000000000000000000000 +%00000000000000000080000000000000000040000000E06000000060018070C000000000000000 +%00000000000080000000000000000000000000000000000000000000000000003007F83F630000 +%0000001000000000000000000000000000 +%0000000000000000008000000000000000004000000070C000000060018030C000000000000000 +%00000000000000000000000000000000000000000000000000000000000000003001E01C630000 +%0000001000000000000000000000000000 +%0000000000000000008000000000000000004000000031C000000070018030C000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000003B81BE7E18FC018030C000000000000000 +%000000000004000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000001F01E7EF1860018070C000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000E01C383186001C3E0E000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000E018383186001FFC0FFE0000000000000 +%000000000020000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000001F018383186001FF00FFC0000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000001B8183831860018380C000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000003181838318600181C0C000000000000000 +%000000000100000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%0000000000000000008000000000000000004000000071C1838318600180E0C000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%00000000000000000080000000000000000040000000E0E183831860018070C000000000000000 +%000000000400001F80006000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%00000000000000000080000000000000000040000000C07183831860018070C000000000000000 +%000000000800003FF800F001FE00000000000000000000000000000000000003FC000000300000 +%0000001000000000000000000000000000 +%00000000000000000080000000000000000040000001C07183831878018038C000000000000000 +%000000000000003FFC00F003FF8000000000000000000000000000000000000F9E000000300000 +%0000001000000000000000000000000000 +%0000000000000000008000000000000000004000000380398383183C018018C000000000000000 +%00000000200000300E01F007018000000000000000000000000000000000001C07000000300000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000400000300701B80E01C000000000000000000000000000000000001803000000600000 +%0000001000000000000000000000000000 +%000000000000000000800000000000000000400000000000000000000000000000000000000000 +%00000000000000300301980C00C00000000000000000000000000000000000380303E01E607C00 +%0000001000000000000000000000000000 +%000000000000000000800800000000000000400000000000000000000000000000000000000400 +%00000001000000300303980C0000000000000080000000000000000000000030000FF03F61FE00 +%0000001000000000000000000000000000 +%000000000000000000803800000000000000400000000000000000000000000000000000001C00 +%000000020000003003030C1C0000000000000780000000000000000000000070001C3861E38300 +%0000001000000000000000000000000000 +%00000000000000000081F80000000000000040000000000000000000000000000000000000FC00 +%000000000000003003830C1C0000000000001F80000000000000000000000060003818C0E30300 +%0000001000000000000000000000000000 +%0000000000000000009FF8000000000000004000000000000000000000000000000000000FFC00 +%000000080000003003860E1C000000000001FF80000000000000000000000060003018C0C70300 +%0000001000000000000000000000000000 +%000000000000000000FFFFFFFFFFFFFFFFFFC000000000000000000000000000000000003FFFFF +%FFFFFFFC0000003003070E1C00000000000FFFFFFFFFFFFFFFFFF8000000006000301980C7FF00 +%0000001000000000000000000000000000 +%0000000000000000001FF8000000000000004000000000000000000000000000000000000FFC00 +%0000000000000030030FFF0C000000000001FF8000000000000000000000006000301980C7FF00 +%0000001000000000000000000000000000 +%00000000000000000001F80000000000000040000000000000000000000000000000000000FC00 +%0000000100000030030E070C00C0000000001F8000000000000000000000006006701980C60000 +%0000001000000000000000000000000000 +%000000000000000000007800000000000000400000000000000000000000000000000000001C00 +%0000000080000030070C030E00C00000000007800000000000000000000000700E703981C60600 +%0000001000000000000000000000000000 +%000000000000000000000800000000000000400007FF80000000004007FFC00000180000000400 +%00000000000000300E1C038701C00000000000800000000000000000000000381C303181860600 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400007FF8000000000C007FFC00000180000000000 +%00000000200000383C180183C78000000000000000000000000000000000003C3838E0C7871C00 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400007000000000000C00700000000180000000000 +%000000001000003FF83801C1FF0000000000000000000000000000000000000FF01FC0FF83F800 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400006000000000000C00700000000180000000000 +%000000000000003FE03000C07C00000000000000000000000000000000000003C007003980E000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400006000880C02303E00700043003180000000000 +%000000000400000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400006000FC7F86FE3F0070006FC0FD80000000000 +%000000000200000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400006000FCF3C7CE0C0070007CE1C780000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400007FE0C0C0C7070C007FF870618380000000000 +%000000000080000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400007FF0C1C0E7030C007FF860730180000000000 +%000000000040000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400007FE0C18067030C007FF060730180000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400006000C18067030C00700060730180000000000 +%000000000010000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400006000C18067030C00700060730180000000000 +%000000000008000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400006000C18067030C00700060730180000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400006000C1C0E7030C00700060738380000000000 +%000000000002000000000000000000000000000000000000000000000000001003000000000080 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400006000C0E1C7030C00700060718380000000000 +%0000000000010000000000000000000000000000000000000000000000000038030000000001C0 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400006000C07F87030F007FFC6071FF80000000000 +%000000000000000000000000000000000000000000000000000000000000003007000000000180 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400006000C03F070307007FFC60707D80000000000 +%000000000000400000000000000000000000000000000000000000000000003006000000000180 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%000000000000200000000000000000000000000000000000000000000000003006000000000180 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000300607C0CE1F0380 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000008000000000000000000000000000000000000000000000000700E1FE0FC7F8380 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%000000000000040000000000000000000000000000000000000000000000007FFE3830E0E0C300 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000007FFC3031C0C0C300 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000001000000000000000000000000000000000000000000000000601C7039C1C0C300 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000800000000000000000000000000000000000000000000000E00C7FF981FFC200 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000C01C7FF181FFC200 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000200000000000000000000000000000000000000000000000C01C600181800600 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000100000000000000000000000000000000000000000000000C018602381818000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000001C018606301818000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000040000000000000000000000000000000000000000000001C01831C301C70400 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%00000000000000020000000000000000000000000000000000000000000001C0383F8300FE0E00 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000400000000000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000180300E0300380C00 +%0000001000000000000000000000000000 +%0000000000000000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000 +%0000000000000000FFFFFFFFFFFFFFFFFF80000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000001000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000004000000000000000000000000 +%0000002000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000002000000000000000000000000 +%0000004000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000001000000000000000000000000 +%0000004000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000400000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000100000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000C0000000000000000000000 +%0000180000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000020000000000000000000000 +%0000200000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000003FFFFFFFFFFFFFFFFFFFFF +%FFFE000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000007FFC00000 +%00000000000182003FF80000860000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000007FFC00000 +%00000000000186003FFC0001860000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000018000000 +%0000000000000600301C0001860000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000018000000 +%0000000000000600300E0001860000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000001806E1F8 +%33C07813C3C19F80300E0F83E67800000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000001807E3FC +%3FE1FE1FFFE18F80300E3FE3E7FE00000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000001807060E +%3871871C78618600300C3061878600000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000001806060E +%3033821838318600303C6061870700000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000001806000E +%30318018303186003FF80061860700000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000000180600FE +%3031F818303186003FE007E1860700000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000000180603FE +%30307E183031860030003FE1860700000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%00000000000000000000000000000000000000000000000000000000000000000000001806070E +%30300F183031860030007861860700000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000018060E0E +%303003183031860030006061860700000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000018060C0E +%303383183031860030006061860700000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000018060E1E +%3031871830318600300070E1C60700000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000000180607FE +%3031FE183031878030003FF1F60700000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%0000000000000000000000000000000000000000000000000000000000000000000000180603C6 +%303078183031838030001E30F60300000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%%EndPreview +%%BeginProlog +%%BeginResource: SDRes +/b4_inc_state save def +/dict_count countdictstack def +/op_count count 1 sub def +userdict begin +0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit[] 0 setdash newpath +/languagelevel where {pop languagelevel 1 ne {false setstrokeadjust false setoverprint} if} if +/bdef {bind def} bind def +/c {setgray} bdef +/l {neg lineto} bdef +/rl {neg rlineto} bdef +/lc {setlinecap} bdef +/lj {setlinejoin} bdef +/lw {setlinewidth} bdef +/ml {setmiterlimit} bdef +/ld {setdash} bdef +/m {neg moveto} bdef +/ct {6 2 roll neg 6 2 roll neg 6 2 roll neg curveto} bdef +/r {rotate} bdef +/t {neg translate} bdef +/s {scale} bdef +/sw {show} bdef +/gs {gsave} bdef +/gr {grestore} bdef +/f {findfont dup length dict begin +{1 index /FID ne {def} {pop pop} ifelse} forall /Encoding ISOLatin1Encoding def +currentdict end /NFont exch definefont pop /NFont findfont} bdef +/p {closepath} bdef +/sf {scalefont setfont} bdef +/ef {eofill}bdef +/pc {closepath stroke}bdef +/ps {stroke}bdef +/pum {matrix currentmatrix}bdef +/pom {setmatrix}bdef +/bs {/aString exch def /nXOfs exch def /nWidth exch def currentpoint nXOfs 0 rmoveto pum nWidth aString stringwidth pop div 1 scale aString show pom moveto} bdef +%%EndResource +%%EndProlog +%%BeginSetup +%%EndSetup +%%Page: 1 1 +%%BeginPageSetup +%%EndPageSetup +pum +0.02834 0.02833 s +0 -20290 t +/tm matrix currentmatrix def +gs +tm setmatrix +-635 -635 t +1 1 s +635 635 m 27274 635 l 27274 20924 l 635 20924 l 635 635 l eoclip newpath +0 lw 1 lj 0.000 c 1905 1905 m 3175 3810 l ps +3175 3810 m 4445 1905 l ps +3175 1905 m 3175 5080 l ps +0.996 c 12565 5080 m 13835 3810 l 16375 3810 l 16375 6350 l 13835 6350 l +12565 5080 l p ef +0.000 c 12565 5080 m 13835 3810 l 16375 3810 l 16375 6350 l 13835 6350 l +12565 5080 l pc +gs +pum +13573 5371 t +-1 0 m 231 -606 l 318 -606 l 566 0 l 474 0 l 404 -183 l 150 -183 l +83 0 l p +173 -248 m 379 -248 l 315 -416 l 296 -467 282 -509 272 -542 ct 265 -503 254 -465 240 -426 ct +p ef +621 0 m 621 -606 l 830 -606 l 877 -606 913 -603 938 -597 ct 972 -589 1002 -575 1027 -554 ct +1059 -527 1082 -492 1098 -450 ct 1114 -408 1122 -360 1122 -306 ct 1122 -260 1117 -219 1106 -184 ct +1095 -148 1081 -119 1065 -95 ct 1048 -72 1029 -54 1009 -40 ct 989 -27 965 -17 937 -10 ct +909 -3 876 0 840 0 ct p +701 -71 m 831 -71 l 871 -71 902 -75 925 -82 ct 947 -90 965 -100 979 -114 ct +998 -133 1013 -158 1023 -190 ct 1034 -222 1039 -261 1039 -307 ct 1039 -371 1029 -419 1008 -453 ct +987 -487 962 -510 932 -522 ct 911 -530 876 -534 828 -534 ct 701 -534 l p ef +1661 -212 m 1742 -192 l 1725 -126 1695 -76 1651 -41 ct 1607 -6 1554 10 1491 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -555 1345 -580 ct 1389 -604 1438 -616 1492 -616 ct +1553 -616 1604 -601 1645 -570 ct 1686 -539 1715 -496 1731 -440 ct 1652 -421 l +1638 -465 1618 -497 1591 -517 ct 1564 -537 1531 -547 1490 -547 ct 1444 -547 1405 -536 1373 -514 ct +1342 -492 1320 -462 1307 -424 ct 1295 -386 1288 -348 1288 -308 ct 1288 -256 1296 -211 1311 -173 ct +1326 -134 1349 -105 1381 -86 ct 1413 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -123 l 1650 -161 l p ef +pom +gr +8255 6350 m 5715 6350 l 5715 3810 l 10795 3810 l 10795 6350 l 8255 6350 l +pc +gs +pum +6033 4895 t +66 0 m 66 -606 l 335 -606 l 389 -606 430 -600 458 -589 ct 486 -579 509 -559 526 -532 ct +542 -504 551 -474 551 -440 ct 551 -397 537 -361 509 -332 ct 481 -302 438 -283 380 -275 ct +401 -265 417 -255 428 -245 ct 452 -224 474 -197 495 -165 ct 600 0 l 500 0 l +419 -126 l 396 -162 377 -190 361 -209 ct 346 -228 333 -242 321 -250 ct 309 -257 296 -263 284 -266 ct +275 -268 260 -269 239 -269 ct 146 -269 l 146 0 l p +146 -338 m 319 -338 l 355 -338 384 -342 405 -350 ct 425 -357 441 -369 452 -386 ct +463 -403 468 -421 468 -440 ct 468 -469 458 -493 437 -511 ct 416 -530 383 -539 338 -539 ct +146 -539 l p ef +965 -141 m 1042 -131 l 1030 -86 1007 -52 975 -27 ct 942 -2 900 9 849 9 ct +785 9 734 -9 696 -49 ct 658 -88 640 -144 640 -215 ct 640 -289 659 -347 697 -387 ct +735 -428 784 -449 845 -449 ct 903 -449 951 -429 989 -389 ct 1026 -349 1044 -292 1044 -220 ct +1044 -216 1044 -209 1044 -200 ct 716 -200 l 719 -152 733 -115 757 -89 ct 782 -64 813 -51 849 -51 ct +877 -51 900 -58 919 -72 ct 938 -87 l 954 -110 l p +721 -261 m 966 -261 l 963 -298 953 -326 938 -344 ct 914 -373 883 -387 845 -387 ct +811 -387 783 -376 759 -353 ct 736 -330 l 723 -300 l p ef +1427 -160 m 1500 -151 l 1492 -100 1472 -61 1439 -32 ct 1406 -4 1365 9 1317 9 ct +1257 9 1209 -9 1172 -49 ct 1136 -88 1118 -144 1118 -217 ct 1118 -265 1125 -306 1141 -342 ct +1157 -378 1181 -404 1213 -422 ct 1245 -440 1280 -449 1318 -449 ct 1365 -449 1404 -437 1435 -412 ct +1465 -388 1485 -354 1493 -310 ct 1421 -299 l 1414 -328 1402 -350 1384 -365 ct +1367 -380 1345 -387 1321 -387 ct 1283 -387 1253 -374 1229 -347 ct 1206 -320 1194 -278 1194 -220 ct +1194 -161 1205 -118 1228 -91 ct 1251 -64 1280 -51 1317 -51 ct 1346 -51 1370 -60 1390 -78 ct +1409 -96 l 1422 -123 l p ef +1864 -141 m 1941 -131 l 1929 -86 1906 -52 1874 -27 ct 1841 -2 1799 9 1748 9 ct +1684 9 1633 -9 1595 -49 ct 1557 -88 1539 -144 1539 -215 ct 1539 -289 1558 -347 1596 -387 ct +1634 -428 1683 -449 1744 -449 ct 1802 -449 1850 -429 1888 -389 ct 1925 -349 1943 -292 1943 -220 ct +1943 -216 1943 -209 1943 -200 ct 1615 -200 l 1618 -152 1632 -115 1656 -89 ct +1681 -64 1712 -51 1748 -51 ct 1776 -51 1799 -58 1818 -72 ct 1837 -87 l 1853 -110 l +p +1620 -261 m 1865 -261 l 1862 -298 1852 -326 1837 -344 ct 1813 -373 1782 -387 1744 -387 ct +1710 -387 1682 -376 1658 -353 ct 1635 -330 l 1622 -300 l p ef +2040 -520 m 2040 -606 l 2114 -606 l 2114 -520 l p +2040 0 m 2040 -439 l 2114 -439 l 2114 0 l p ef +2347 0 m 2180 -439 l 2259 -439 l 2353 -176 l 2363 -147 2373 -118 2381 -87 ct +2388 -110 2397 -138 2409 -171 ct 2507 -439 l 2583 -439 l 2417 0 l p ef +2949 -141 m 3026 -131 l 3014 -86 2991 -52 2959 -27 ct 2926 -2 2884 9 2833 9 ct +2769 9 2718 -9 2680 -49 ct 2642 -88 2624 -144 2624 -215 ct 2624 -289 2643 -347 2681 -387 ct +2719 -428 2768 -449 2829 -449 ct 2887 -449 2935 -429 2973 -389 ct 3010 -349 3028 -292 3028 -220 ct +3028 -216 3028 -209 3028 -200 ct 2700 -200 l 2703 -152 2717 -115 2741 -89 ct +2766 -64 2797 -51 2833 -51 ct 2861 -51 2884 -58 2903 -72 ct 2922 -87 l 2938 -110 l +p +2705 -261 m 2950 -261 l 2947 -298 2937 -326 2922 -344 ct 2898 -373 2867 -387 2829 -387 ct +2795 -387 2767 -376 2743 -353 ct 2720 -330 l 2707 -300 l p ef +3373 0 m 3373 -606 l 3642 -606 l 3696 -606 3737 -600 3765 -589 ct 3793 -579 3816 -559 3833 -532 ct +3849 -504 3858 -474 3858 -440 ct 3858 -397 3844 -361 3816 -332 ct 3788 -302 3745 -283 3687 -275 ct +3708 -265 3724 -255 3735 -245 ct 3759 -224 3781 -197 3802 -165 ct 3907 0 l 3807 0 l +3726 -126 l 3703 -162 3684 -190 3668 -209 ct 3653 -228 3640 -242 3628 -250 ct +3616 -257 3603 -263 3591 -266 ct 3582 -268 3567 -269 3546 -269 ct 3453 -269 l +3453 0 l p +3453 -338 m 3626 -338 l 3662 -338 3691 -342 3712 -350 ct 3732 -357 3748 -369 3759 -386 ct +3770 -403 3775 -421 3775 -440 ct 3775 -469 3765 -493 3744 -511 ct 3723 -530 3690 -539 3645 -539 ct +3453 -539 l p ef +3985 0 m 3985 -606 l 4394 -606 l 4394 -534 l 4065 -534 l 4065 -346 l +4350 -346 l 4350 -275 l 4065 -275 l 4065 0 l p ef +pom +pum +6364 5848 t +69 0 m 69 -606 l 478 -606 l 478 -534 l 149 -534 l 149 -346 l 434 -346 l +434 -275 l 149 -275 l 149 0 l p ef +584 0 m 584 -439 l 651 -439 l 651 -372 l 668 -403 683 -424 698 -434 ct +712 -444 728 -449 746 -449 ct 771 -449 796 -441 822 -425 ct 797 -356 l 778 -366 760 -372 742 -372 ct +726 -372 711 -367 698 -357 ct 685 -347 676 -334 670 -316 ct 662 -290 658 -261 658 -229 ct +658 0 l p ef +848 -219 m 848 -300 870 -361 915 -400 ct 953 -432 999 -449 1054 -449 ct 1114 -449 1163 -429 1202 -389 ct +1240 -350 1259 -295 1259 -225 ct 1259 -169 1251 -124 1234 -92 ct 1217 -60 1192 -34 1160 -16 ct +1127 0 1092 9 1054 9 ct 992 9 942 -9 904 -49 ct 867 -88 l 848 -145 l p +924 -219 m 924 -163 936 -121 961 -93 ct 985 -65 1016 -51 1054 -51 ct 1091 -51 1121 -65 1146 -93 ct +1170 -121 1183 -164 1183 -222 ct 1183 -276 1170 -317 1146 -345 ct 1121 -373 1090 -387 1054 -387 ct +1016 -387 985 -373 961 -345 ct 936 -317 l 924 -275 l p ef +1351 0 m 1351 -439 l 1418 -439 l 1418 -376 l 1451 -425 1497 -449 1558 -449 ct +1585 -449 1609 -444 1631 -434 ct 1653 -425 1670 -412 1681 -397 ct 1692 -382 1700 -363 1704 -342 ct +1707 -328 1708 -304 1708 -270 ct 1708 0 l 1634 0 l 1634 -267 l 1634 -297 1631 -320 1625 -335 ct +1619 -350 1609 -362 1594 -371 ct 1580 -380 1562 -384 1542 -384 ct 1511 -384 1483 -374 1460 -354 ct +1437 -334 1426 -296 1426 -239 ct 1426 0 l p ef +1991 -66 m 2002 0 l 1981 3 1962 5 1945 5 ct 1918 5 1897 1 1883 -7 ct 1868 -15 1857 -26 1851 -40 ct +1845 -54 1842 -83 1842 -128 ct 1842 -381 l 1787 -381 l 1787 -439 l 1842 -439 l +1842 -547 l 1916 -592 l 1916 -439 l 1991 -439 l 1991 -381 l 1916 -381 l +1916 -124 l 1916 -103 1917 -89 1920 -83 ct 1923 -77 1927 -72 1933 -69 ct 1939 -65 1947 -63 1958 -63 ct +1966 -63 l 1977 -64 l p ef +2316 0 m 2316 -606 l 2754 -606 l 2754 -534 l 2396 -534 l 2396 -349 l +2731 -349 l 2731 -277 l 2396 -277 l 2396 -71 l 2768 -71 l 2768 0 l +p ef +2886 0 m 2886 -439 l 2953 -439 l 2953 -376 l 2986 -425 3032 -449 3093 -449 ct +3120 -449 3144 -444 3166 -434 ct 3188 -425 3205 -412 3216 -397 ct 3227 -382 3235 -363 3239 -342 ct +3242 -328 3243 -304 3243 -270 ct 3243 0 l 3169 0 l 3169 -267 l 3169 -297 3166 -320 3160 -335 ct +3154 -350 3144 -362 3129 -371 ct 3115 -380 3097 -384 3077 -384 ct 3046 -384 3018 -374 2995 -354 ct +2972 -334 2961 -296 2961 -239 ct 2961 0 l p ef +3647 0 m 3647 -55 l 3619 -11 3579 9 3524 9 ct 3489 9 3457 0 3428 -19 ct 3399 -38 3376 -65 3360 -99 ct +3344 -134 3335 -174 3335 -219 ct 3335 -263 3343 -302 3357 -338 ct 3372 -374 3394 -401 3423 -420 ct +3452 -439 3485 -449 3521 -449 ct 3548 -449 3571 -443 3592 -432 ct 3613 -421 3629 -406 3642 -388 ct +3642 -606 l 3716 -606 l 3716 0 l p +3412 -219 m 3412 -162 3424 -120 3448 -93 ct 3471 -65 3499 -51 3531 -51 ct 3564 -51 3592 -64 3614 -91 ct +3637 -117 3649 -158 3649 -212 ct 3649 -273 3637 -317 3614 -345 ct 3591 -373 3562 -387 3528 -387 ct +3495 -387 3467 -374 3445 -346 ct 3423 -319 l 3412 -277 l p ef +pom +gr +21272 7620 m 19550 7620 l 19274 7620 19050 7396 19050 7120 ct 19050 3040 l +19050 2764 19274 2540 19550 2540 ct 22995 2540 l 23271 2540 23495 2764 23495 3040 ct +23495 7120 l 23495 7396 23271 7620 22995 7620 ct 21272 7620 l pc +gs +pum +20360 4418 t +236 0 m 285 -234 l 98 -606 l 185 -606 l 275 -429 l 294 -390 313 -349 332 -305 ct +352 -342 380 -383 415 -428 ct 557 -606 l 654 -606 l 365 -228 l 317 0 l +p ef +597 -166 m 597 -252 622 -323 673 -379 ct 714 -425 769 -449 836 -449 ct 889 -449 932 -432 964 -399 ct +997 -366 1013 -321 1013 -265 ct 1013 -215 1003 -168 982 -124 ct 962 -81 933 -47 895 -24 ct +858 -1 818 9 776 9 ct 742 9 711 2 683 -11 ct 655 -26 634 -47 619 -74 ct 604 -100 l +597 -131 l p +672 -174 m 672 -132 682 -101 701 -80 ct 721 -58 747 -47 777 -47 ct 793 -47 809 -51 825 -57 ct +840 -64 855 -74 869 -87 ct 882 -100 894 -115 903 -132 ct 913 -149 920 -167 926 -187 ct +935 -214 939 -240 939 -265 ct 939 -305 929 -336 909 -358 ct 889 -380 864 -391 833 -391 ct +810 -391 789 -385 769 -374 ct 750 -363 733 -346 717 -325 ct 701 -303 690 -278 683 -250 ct +675 -221 l 672 -196 l p ef +1359 -79 m 1307 -19 1253 9 1198 9 ct 1164 9 1136 0 1116 -19 ct 1095 -38 1084 -62 1084 -90 ct +1084 -109 1089 -140 1099 -185 ct 1151 -439 l 1226 -439 l 1168 -158 l 1163 -134 1160 -116 1160 -103 ct +1160 -87 1165 -74 1175 -65 ct 1185 -55 1200 -51 1220 -51 ct 1241 -51 1261 -56 1281 -66 ct +1301 -76 1318 -90 1333 -107 ct 1347 -125 1359 -145 1368 -169 ct 1374 -184 1381 -211 1389 -249 ct +1429 -439 l 1504 -439 l 1412 0 l 1343 0 l p ef +1536 0 m 1627 -439 l 1694 -439 l 1675 -349 l 1698 -383 1720 -408 1741 -424 ct +1763 -441 1785 -449 1808 -449 ct 1823 -449 1841 -443 1863 -433 ct 1832 -363 l +1819 -372 1805 -377 1790 -377 ct 1763 -377 1736 -362 1709 -333 ct 1681 -304 1660 -252 1644 -176 ct +1607 0 l p ef +pom +pum +20241 5371 t +510 -213 m 591 -202 l 565 -132 528 -79 480 -43 ct 431 -7 377 10 316 10 ct +243 10 184 -12 141 -57 ct 98 -102 76 -166 76 -250 ct 76 -359 109 -449 175 -521 ct +233 -584 306 -616 393 -616 ct 457 -616 509 -599 549 -564 ct 589 -530 612 -484 618 -425 ct +543 -418 l 535 -462 518 -495 493 -517 ct 468 -538 436 -549 397 -549 ct 322 -549 262 -516 217 -450 ct +177 -394 157 -326 157 -248 ct 157 -186 172 -138 203 -105 ct 234 -73 273 -56 323 -56 ct +364 -56 402 -70 436 -97 ct 470 -124 l 495 -163 l p ef +650 -166 m 650 -252 675 -323 726 -379 ct 767 -425 822 -449 889 -449 ct 942 -449 985 -432 1017 -399 ct +1050 -366 1066 -321 1066 -265 ct 1066 -215 1056 -168 1035 -124 ct 1015 -81 986 -47 948 -24 ct +911 -1 871 9 829 9 ct 795 9 764 2 736 -11 ct 708 -26 687 -47 672 -74 ct 657 -100 l +650 -131 l p +725 -174 m 725 -132 735 -101 754 -80 ct 774 -58 800 -47 830 -47 ct 846 -47 862 -51 878 -57 ct +893 -64 908 -74 922 -87 ct 935 -100 947 -115 956 -132 ct 966 -149 973 -167 979 -187 ct +988 -214 992 -240 992 -265 ct 992 -305 982 -336 962 -358 ct 942 -380 917 -391 886 -391 ct +863 -391 842 -385 822 -374 ct 803 -363 786 -346 770 -325 ct 754 -303 743 -278 736 -250 ct +728 -221 l 725 -196 l p ef +1409 -63 m 1366 -14 1321 9 1275 9 ct 1233 9 1198 -5 1171 -36 ct 1143 -66 1129 -111 1129 -169 ct +1129 -223 1140 -272 1162 -316 ct 1184 -360 1211 -394 1244 -416 ct 1277 -438 1310 -449 1343 -449 ct +1398 -449 1439 -422 1467 -370 ct 1517 -606 l 1591 -606 l 1465 0 l 1396 0 l +p +1204 -184 m 1204 -153 1207 -129 1213 -111 ct 1219 -94 1229 -79 1244 -67 ct +1258 -55 1276 -50 1296 -50 ct 1330 -50 1361 -67 1388 -102 ct 1425 -149 1444 -207 1444 -276 ct +1444 -311 1435 -338 1417 -358 ct 1398 -377 1376 -387 1348 -387 ct 1330 -387 1314 -383 1299 -375 ct +1284 -367 1270 -353 1255 -334 ct 1241 -315 1228 -291 1219 -261 ct 1209 -232 l +1204 -206 l p ef +1911 -149 m 1984 -141 l 1974 -105 1949 -71 1912 -38 ct 1874 -6 1829 9 1777 9 ct +1745 9 1715 2 1688 -12 ct 1661 -27 1640 -49 1626 -78 ct 1611 -106 1604 -139 1604 -176 ct +1604 -224 1615 -270 1638 -315 ct 1660 -360 1689 -394 1724 -416 ct 1759 -438 1797 -449 1838 -449 ct +1891 -449 1933 -432 1964 -400 ct 1995 -367 2011 -323 2011 -267 ct 2011 -245 2009 -223 2005 -201 ct +1682 -201 l 1681 -192 1680 -184 1680 -177 ct 1680 -136 1689 -105 1708 -83 ct +1727 -62 1750 -51 1778 -51 ct 1803 -51 1829 -59 1853 -76 ct 1878 -93 l 1897 -117 l +p +1694 -258 m 1940 -258 l 1940 -265 1941 -271 1941 -274 ct 1941 -312 1931 -340 1912 -360 ct +1894 -380 1870 -390 1840 -390 ct 1808 -390 1779 -379 1753 -357 ct 1726 -335 l +1707 -302 l p ef +pom +pum +20214 6324 t +35 0 m 162 -606 l 243 -606 l 190 -354 l 504 -354 l 557 -606 l 638 -606 l +512 0 l 430 0 l 490 -285 l 176 -285 l 116 0 l p ef +959 -149 m 1032 -141 l 1022 -105 997 -71 960 -38 ct 922 -6 877 9 825 9 ct +793 9 763 2 736 -12 ct 709 -27 688 -49 674 -78 ct 659 -106 652 -139 652 -176 ct +652 -224 663 -270 686 -315 ct 708 -360 737 -394 772 -416 ct 807 -438 845 -449 886 -449 ct +939 -449 981 -432 1012 -400 ct 1043 -367 1059 -323 1059 -267 ct 1059 -245 1057 -223 1053 -201 ct +730 -201 l 729 -192 728 -184 728 -177 ct 728 -136 737 -105 756 -83 ct 775 -62 798 -51 826 -51 ct +851 -51 877 -59 901 -76 ct 926 -93 l 945 -117 l p +742 -258 m 988 -258 l 988 -265 989 -271 989 -274 ct 989 -312 979 -340 960 -360 ct +942 -380 918 -390 888 -390 ct 856 -390 827 -379 801 -357 ct 774 -335 l 755 -302 l +p ef +1113 0 m 1204 -439 l 1271 -439 l 1252 -349 l 1275 -383 1297 -408 1318 -424 ct +1340 -441 1362 -449 1385 -449 ct 1400 -449 1418 -443 1440 -433 ct 1409 -363 l +1396 -372 1382 -377 1367 -377 ct 1340 -377 1313 -362 1286 -333 ct 1258 -304 1237 -252 1221 -176 ct +1184 0 l p ef +1726 -149 m 1799 -141 l 1789 -105 1764 -71 1727 -38 ct 1689 -6 1644 9 1592 9 ct +1560 9 1530 2 1503 -12 ct 1476 -27 1455 -49 1441 -78 ct 1426 -106 1419 -139 1419 -176 ct +1419 -224 1430 -270 1453 -315 ct 1475 -360 1504 -394 1539 -416 ct 1574 -438 1612 -449 1653 -449 ct +1706 -449 1748 -432 1779 -400 ct 1810 -367 1826 -323 1826 -267 ct 1826 -245 1824 -223 1820 -201 ct +1497 -201 l 1496 -192 1495 -184 1495 -177 ct 1495 -136 1504 -105 1523 -83 ct +1542 -62 1565 -51 1593 -51 ct 1618 -51 1644 -59 1668 -76 ct 1693 -93 l 1712 -117 l +p +1509 -258 m 1755 -258 l 1755 -265 1756 -271 1756 -274 ct 1756 -312 1746 -340 1727 -360 ct +1709 -380 1685 -390 1655 -390 ct 1623 -390 1594 -379 1568 -357 ct 1541 -335 l +1522 -302 l p ef +1946 -153 m 1992 -482 l 2018 -606 l 2109 -606 l 2081 -471 l 1993 -153 l +p +1899 0 m 1917 -84 l 2001 -84 l 1983 0 l p ef +pom +gr +5715 5080 m 5264 4930 l 5265 5230 l 5715 5080 l p ef +1 lw 0 lj 3175 5080 m 5355 5080 l ps +12565 5080 m 12114 4930 l 12115 5230 l 12565 5080 l p ef +10795 5080 m 12205 5080 l ps +19050 5080 m 18599 4930 l 18600 5230 l 19050 5080 l p ef +16375 5080 m 18690 5080 l ps +gs +pum +10425 8413 t +66 0 m 66 -606 l 335 -606 l 389 -606 430 -600 458 -589 ct 486 -579 509 -559 526 -532 ct +542 -504 551 -474 551 -440 ct 551 -397 537 -361 509 -332 ct 481 -302 438 -283 380 -275 ct +401 -265 417 -255 428 -245 ct 452 -224 474 -197 495 -165 ct 600 0 l 500 0 l +419 -126 l 396 -162 377 -190 361 -209 ct 346 -228 333 -242 321 -250 ct 309 -257 296 -263 284 -266 ct +275 -268 260 -269 239 -269 ct 146 -269 l 146 0 l p +146 -338 m 319 -338 l 355 -338 384 -342 405 -350 ct 425 -357 441 -369 452 -386 ct +463 -403 468 -421 468 -440 ct 468 -469 458 -493 437 -511 ct 416 -530 383 -539 338 -539 ct +146 -539 l p ef +965 -141 m 1042 -131 l 1030 -86 1007 -52 975 -27 ct 942 -2 900 9 849 9 ct +785 9 734 -9 696 -49 ct 658 -88 640 -144 640 -215 ct 640 -289 659 -347 697 -387 ct +735 -428 784 -449 845 -449 ct 903 -449 951 -429 989 -389 ct 1026 -349 1044 -292 1044 -220 ct +1044 -216 1044 -209 1044 -200 ct 716 -200 l 719 -152 733 -115 757 -89 ct 782 -64 813 -51 849 -51 ct +877 -51 900 -58 919 -72 ct 938 -87 l 954 -110 l p +721 -261 m 966 -261 l 963 -298 953 -326 938 -344 ct 914 -373 883 -387 845 -387 ct +811 -387 783 -376 759 -353 ct 736 -330 l 723 -300 l p ef +1427 -160 m 1500 -151 l 1492 -100 1472 -61 1439 -32 ct 1406 -4 1365 9 1317 9 ct +1257 9 1209 -9 1172 -49 ct 1136 -88 1118 -144 1118 -217 ct 1118 -265 1125 -306 1141 -342 ct +1157 -378 1181 -404 1213 -422 ct 1245 -440 1280 -449 1318 -449 ct 1365 -449 1404 -437 1435 -412 ct +1465 -388 1485 -354 1493 -310 ct 1421 -299 l 1414 -328 1402 -350 1384 -365 ct +1367 -380 1345 -387 1321 -387 ct 1283 -387 1253 -374 1229 -347 ct 1206 -320 1194 -278 1194 -220 ct +1194 -161 1205 -118 1228 -91 ct 1251 -64 1280 -51 1317 -51 ct 1346 -51 1370 -60 1390 -78 ct +1409 -96 l 1422 -123 l p ef +1864 -141 m 1941 -131 l 1929 -86 1906 -52 1874 -27 ct 1841 -2 1799 9 1748 9 ct +1684 9 1633 -9 1595 -49 ct 1557 -88 1539 -144 1539 -215 ct 1539 -289 1558 -347 1596 -387 ct +1634 -428 1683 -449 1744 -449 ct 1802 -449 1850 -429 1888 -389 ct 1925 -349 1943 -292 1943 -220 ct +1943 -216 1943 -209 1943 -200 ct 1615 -200 l 1618 -152 1632 -115 1656 -89 ct +1681 -64 1712 -51 1748 -51 ct 1776 -51 1799 -58 1818 -72 ct 1837 -87 l 1853 -110 l +p +1620 -261 m 1865 -261 l 1862 -298 1852 -326 1837 -344 ct 1813 -373 1782 -387 1744 -387 ct +1710 -387 1682 -376 1658 -353 ct 1635 -330 l 1622 -300 l p ef +2040 -520 m 2040 -606 l 2114 -606 l 2114 -520 l p +2040 0 m 2040 -439 l 2114 -439 l 2114 0 l p ef +2347 0 m 2180 -439 l 2259 -439 l 2353 -176 l 2363 -147 2373 -118 2381 -87 ct +2388 -110 2397 -138 2409 -171 ct 2507 -439 l 2583 -439 l 2417 0 l p ef +2949 -141 m 3026 -131 l 3014 -86 2991 -52 2959 -27 ct 2926 -2 2884 9 2833 9 ct +2769 9 2718 -9 2680 -49 ct 2642 -88 2624 -144 2624 -215 ct 2624 -289 2643 -347 2681 -387 ct +2719 -428 2768 -449 2829 -449 ct 2887 -449 2935 -429 2973 -389 ct 3010 -349 3028 -292 3028 -220 ct +3028 -216 3028 -209 3028 -200 ct 2700 -200 l 2703 -152 2717 -115 2741 -89 ct +2766 -64 2797 -51 2833 -51 ct 2861 -51 2884 -58 2903 -72 ct 2922 -87 l 2938 -110 l +p +2705 -261 m 2950 -261 l 2947 -298 2937 -326 2922 -344 ct 2898 -373 2867 -387 2829 -387 ct +2795 -387 2767 -376 2743 -353 ct 2720 -330 l 2707 -300 l p ef +3372 0 m 3372 -606 l 3601 -606 l 3641 -606 3672 -604 3693 -600 ct 3723 -595 3748 -586 3768 -572 ct +3788 -558 3804 -538 3816 -513 ct 3829 -488 3835 -461 3835 -430 ct 3835 -379 3818 -335 3785 -300 ct +3753 -264 3693 -246 3608 -246 ct 3452 -246 l 3452 0 l p +3452 -318 m 3609 -318 l 3661 -318 3697 -327 3719 -346 ct 3741 -366 3752 -393 3752 -428 ct +3752 -453 3746 -475 3733 -493 ct 3720 -511 3703 -523 3682 -529 ct 3669 -532 3644 -534 3607 -534 ct +3452 -534 l p ef +4205 -54 m 4177 -30 4151 -14 4125 -4 ct 4100 5 4072 9 4043 9 ct 3995 9 3958 -1 3932 -25 ct +3906 -49 3893 -79 3893 -115 ct 3893 -137 3898 -156 3908 -174 ct 3918 -192 3930 -206 3946 -217 ct +3962 -228 3980 -236 4000 -241 ct 4014 -245 4036 -249 4066 -253 ct 4126 -260 4170 -268 4199 -278 ct +4199 -288 4199 -295 4199 -298 ct 4199 -328 4192 -349 4178 -362 ct 4159 -379 4131 -387 4093 -387 ct +4058 -387 4032 -381 4016 -369 ct 3999 -356 3987 -335 3979 -303 ct 3906 -313 l +3913 -345 3923 -370 3939 -389 ct 3954 -408 3976 -423 4004 -433 ct 4033 -443 4066 -449 4104 -449 ct +4142 -449 4172 -444 4195 -435 ct 4219 -427 4236 -415 4247 -402 ct 4258 -389 4266 -372 4270 -351 ct +4273 -339 4274 -316 4274 -283 ct 4274 -184 l 4274 -114 4276 -71 4279 -52 ct +4282 -34 4288 -16 4298 0 ct 4220 0 l 4212 -15 l 4207 -33 l p +4199 -220 m 4172 -209 4131 -200 4077 -192 ct 4047 -187 4025 -182 4012 -177 ct +4000 -171 3990 -163 3983 -153 ct 3976 -142 3973 -130 3973 -117 ct 3973 -98 3980 -81 3995 -68 ct +4010 -55 4032 -48 4061 -48 ct 4090 -48 4115 -54 4138 -67 ct 4160 -79 4176 -96 4187 -118 ct +4195 -135 4199 -160 4199 -193 ct p ef +4531 -66 m 4542 0 l 4521 3 4502 5 4485 5 ct 4458 5 4437 1 4423 -7 ct 4408 -15 4397 -26 4391 -40 ct +4385 -54 4382 -83 4382 -128 ct 4382 -381 l 4327 -381 l 4327 -439 l 4382 -439 l +4382 -547 l 4456 -592 l 4456 -439 l 4531 -439 l 4531 -381 l 4456 -381 l +4456 -124 l 4456 -103 4457 -89 4460 -83 ct 4463 -77 4467 -72 4473 -69 ct 4479 -65 4487 -63 4498 -63 ct +4506 -63 l 4517 -64 l p ef +4606 0 m 4606 -606 l 4681 -606 l 4681 -388 l 4716 -429 4759 -449 4812 -449 ct +4845 -449 4873 -442 4897 -429 ct 4921 -417 4938 -399 4949 -376 ct 4959 -354 4964 -321 4964 -278 ct +4964 0 l 4890 0 l 4890 -278 l 4890 -315 4882 -342 4865 -359 ct 4849 -376 4827 -385 4797 -385 ct +4775 -385 4754 -379 4735 -367 ct 4715 -356 4701 -340 4693 -321 ct 4685 -301 4681 -274 4681 -240 ct +4681 0 l p ef +pom +gr +0 lw 1 lj 1905 12030 m 3175 13935 l ps +3175 13935 m 4445 12030 l ps +3175 12030 m 3175 15205 l ps +0.996 c 12565 15205 m 13835 13935 l 16375 13935 l 16375 16475 l 13835 16475 l +12565 15205 l p ef +0.000 c 12565 15205 m 13835 13935 l 16375 13935 l 16375 16475 l 13835 16475 l +12565 15205 l pc +gs +pum +13573 15504 t +65 0 m 65 -606 l 274 -606 l 321 -606 357 -603 382 -597 ct 416 -589 446 -575 471 -554 ct +503 -527 526 -492 542 -450 ct 558 -408 566 -360 566 -306 ct 566 -260 561 -219 550 -184 ct +539 -148 525 -119 509 -95 ct 492 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +353 -3 320 0 284 0 ct p +145 -71 m 275 -71 l 315 -71 346 -75 369 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 457 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -371 473 -419 452 -453 ct +431 -487 406 -510 376 -522 ct 355 -530 320 -534 272 -534 ct 145 -534 l p ef +608 0 m 840 -606 l 927 -606 l 1175 0 l 1083 0 l 1013 -183 l 759 -183 l +692 0 l p +782 -248 m 988 -248 l 924 -416 l 905 -467 891 -509 881 -542 ct 874 -503 863 -465 849 -426 ct +p ef +1661 -212 m 1742 -192 l 1725 -126 1695 -76 1651 -41 ct 1607 -6 1554 10 1491 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -555 1345 -580 ct 1389 -604 1438 -616 1492 -616 ct +1553 -616 1604 -601 1645 -570 ct 1686 -539 1715 -496 1731 -440 ct 1652 -421 l +1638 -465 1618 -497 1591 -517 ct 1564 -537 1531 -547 1490 -547 ct 1444 -547 1405 -536 1373 -514 ct +1342 -492 1320 -462 1307 -424 ct 1295 -386 1288 -348 1288 -308 ct 1288 -256 1296 -211 1311 -173 ct +1326 -134 1349 -105 1381 -86 ct 1413 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -123 l 1650 -161 l p ef +pom +gr +8255 16475 m 5715 16475 l 5715 13935 l 10795 13935 l 10795 16475 l +8255 16475 l pc +gs +pum +6708 15028 t +3 0 m 238 -315 l 31 -606 l 126 -606 l 236 -450 l 259 -418 276 -393 285 -376 ct +299 -398 315 -421 333 -445 ct 455 -606 l 543 -606 l 330 -320 l 559 0 l +460 0 l 307 -216 l 299 -228 290 -242 281 -256 ct 267 -234 258 -219 252 -211 ct +100 0 l p ef +611 0 m 611 -439 l 678 -439 l 678 -377 l 692 -399 710 -416 733 -429 ct +756 -442 782 -449 811 -449 ct 844 -449 870 -442 891 -428 ct 912 -415 927 -396 935 -372 ct +970 -423 1015 -449 1071 -449 ct 1114 -449 1148 -437 1171 -412 ct 1195 -388 1206 -351 1206 -301 ct +1206 0 l 1132 0 l 1132 -276 l 1132 -306 1130 -327 1125 -340 ct 1120 -354 1112 -364 1099 -372 ct +1086 -380 1071 -384 1054 -384 ct 1023 -384 998 -374 977 -353 ct 957 -333 947 -300 947 -255 ct +947 0 l 872 0 l 872 -285 l 872 -318 866 -343 854 -359 ct 842 -376 822 -384 795 -384 ct +774 -384 754 -379 736 -368 ct 719 -357 706 -340 698 -319 ct 690 -298 686 -267 686 -227 ct +686 0 l p ef +1326 -520 m 1326 -606 l 1400 -606 l 1400 -520 l p +1326 0 m 1326 -439 l 1400 -439 l 1400 0 l p ef +1673 -66 m 1684 0 l 1663 3 1644 5 1627 5 ct 1600 5 1579 1 1565 -7 ct 1550 -15 1539 -26 1533 -40 ct +1527 -54 1524 -83 1524 -128 ct 1524 -381 l 1469 -381 l 1469 -439 l 1524 -439 l +1524 -547 l 1598 -592 l 1598 -439 l 1673 -439 l 1673 -381 l 1598 -381 l +1598 -124 l 1598 -103 1599 -89 1602 -83 ct 1605 -77 1609 -72 1615 -69 ct 1621 -65 1629 -63 1640 -63 ct +1648 -63 l 1659 -64 l p ef +1997 0 m 1997 -606 l 2266 -606 l 2320 -606 2361 -600 2389 -589 ct 2417 -579 2440 -559 2457 -532 ct +2473 -504 2482 -474 2482 -440 ct 2482 -397 2468 -361 2440 -332 ct 2412 -302 2369 -283 2311 -275 ct +2332 -265 2348 -255 2359 -245 ct 2383 -224 2405 -197 2426 -165 ct 2531 0 l 2431 0 l +2350 -126 l 2327 -162 2308 -190 2292 -209 ct 2277 -228 2264 -242 2252 -250 ct +2240 -257 2227 -263 2215 -266 ct 2206 -268 2191 -269 2170 -269 ct 2077 -269 l +2077 0 l p +2077 -338 m 2250 -338 l 2286 -338 2315 -342 2336 -350 ct 2356 -357 2372 -369 2383 -386 ct +2394 -403 2399 -421 2399 -440 ct 2399 -469 2389 -493 2368 -511 ct 2347 -530 2314 -539 2269 -539 ct +2077 -539 l p ef +2609 0 m 2609 -606 l 3018 -606 l 3018 -534 l 2689 -534 l 2689 -346 l +2974 -346 l 2974 -275 l 2689 -275 l 2689 0 l p ef +pom +pum +6350 15981 t +69 0 m 69 -606 l 478 -606 l 478 -534 l 149 -534 l 149 -346 l 434 -346 l +434 -275 l 149 -275 l 149 0 l p ef +584 0 m 584 -439 l 651 -439 l 651 -372 l 668 -403 683 -424 698 -434 ct +712 -444 728 -449 746 -449 ct 771 -449 796 -441 822 -425 ct 797 -356 l 778 -366 760 -372 742 -372 ct +726 -372 711 -367 698 -357 ct 685 -347 676 -334 670 -316 ct 662 -290 658 -261 658 -229 ct +658 0 l p ef +848 -219 m 848 -300 870 -361 915 -400 ct 953 -432 999 -449 1054 -449 ct 1114 -449 1163 -429 1202 -389 ct +1240 -350 1259 -295 1259 -225 ct 1259 -169 1251 -124 1234 -92 ct 1217 -60 1192 -34 1160 -16 ct +1127 0 1092 9 1054 9 ct 992 9 942 -9 904 -49 ct 867 -88 l 848 -145 l p +924 -219 m 924 -163 936 -121 961 -93 ct 985 -65 1016 -51 1054 -51 ct 1091 -51 1121 -65 1146 -93 ct +1170 -121 1183 -164 1183 -222 ct 1183 -276 1170 -317 1146 -345 ct 1121 -373 1090 -387 1054 -387 ct +1016 -387 985 -373 961 -345 ct 936 -317 l 924 -275 l p ef +1351 0 m 1351 -439 l 1418 -439 l 1418 -376 l 1451 -425 1497 -449 1558 -449 ct +1585 -449 1609 -444 1631 -434 ct 1653 -425 1670 -412 1681 -397 ct 1692 -382 1700 -363 1704 -342 ct +1707 -328 1708 -304 1708 -270 ct 1708 0 l 1634 0 l 1634 -267 l 1634 -297 1631 -320 1625 -335 ct +1619 -350 1609 -362 1594 -371 ct 1580 -380 1562 -384 1542 -384 ct 1511 -384 1483 -374 1460 -354 ct +1437 -334 1426 -296 1426 -239 ct 1426 0 l p ef +1991 -66 m 2002 0 l 1981 3 1962 5 1945 5 ct 1918 5 1897 1 1883 -7 ct 1868 -15 1857 -26 1851 -40 ct +1845 -54 1842 -83 1842 -128 ct 1842 -381 l 1787 -381 l 1787 -439 l 1842 -439 l +1842 -547 l 1916 -592 l 1916 -439 l 1991 -439 l 1991 -381 l 1916 -381 l +1916 -124 l 1916 -103 1917 -89 1920 -83 ct 1923 -77 1927 -72 1933 -69 ct 1939 -65 1947 -63 1958 -63 ct +1966 -63 l 1977 -64 l p ef +2316 0 m 2316 -606 l 2754 -606 l 2754 -534 l 2396 -534 l 2396 -349 l +2731 -349 l 2731 -277 l 2396 -277 l 2396 -71 l 2768 -71 l 2768 0 l +p ef +2886 0 m 2886 -439 l 2953 -439 l 2953 -376 l 2986 -425 3032 -449 3093 -449 ct +3120 -449 3144 -444 3166 -434 ct 3188 -425 3205 -412 3216 -397 ct 3227 -382 3235 -363 3239 -342 ct +3242 -328 3243 -304 3243 -270 ct 3243 0 l 3169 0 l 3169 -267 l 3169 -297 3166 -320 3160 -335 ct +3154 -350 3144 -362 3129 -371 ct 3115 -380 3097 -384 3077 -384 ct 3046 -384 3018 -374 2995 -354 ct +2972 -334 2961 -296 2961 -239 ct 2961 0 l p ef +3647 0 m 3647 -55 l 3619 -11 3579 9 3524 9 ct 3489 9 3457 0 3428 -19 ct 3399 -38 3376 -65 3360 -99 ct +3344 -134 3335 -174 3335 -219 ct 3335 -263 3343 -302 3357 -338 ct 3372 -374 3394 -401 3423 -420 ct +3452 -439 3485 -449 3521 -449 ct 3548 -449 3571 -443 3592 -432 ct 3613 -421 3629 -406 3642 -388 ct +3642 -606 l 3716 -606 l 3716 0 l p +3412 -219 m 3412 -162 3424 -120 3448 -93 ct 3471 -65 3499 -51 3531 -51 ct 3564 -51 3592 -64 3614 -91 ct +3637 -117 3649 -158 3649 -212 ct 3649 -273 3637 -317 3614 -345 ct 3591 -373 3562 -387 3528 -387 ct +3495 -387 3467 -374 3445 -346 ct 3423 -319 l 3412 -277 l p ef +pom +gr +21272 17745 m 19550 17745 l 19274 17745 19050 17521 19050 17245 ct 19050 13165 l +19050 12889 19274 12665 19550 12665 ct 22995 12665 l 23271 12665 23495 12889 23495 13165 ct +23495 17245 l 23495 17521 23271 17745 22995 17745 ct 21272 17745 l pc +gs +pum +20360 14552 t +236 0 m 285 -234 l 98 -606 l 185 -606 l 275 -429 l 294 -390 313 -349 332 -305 ct +352 -342 380 -383 415 -428 ct 557 -606 l 654 -606 l 365 -228 l 317 0 l +p ef +597 -166 m 597 -252 622 -323 673 -379 ct 714 -425 769 -449 836 -449 ct 889 -449 932 -432 964 -399 ct +997 -366 1013 -321 1013 -265 ct 1013 -215 1003 -168 982 -124 ct 962 -81 933 -47 895 -24 ct +858 -1 818 9 776 9 ct 742 9 711 2 683 -11 ct 655 -26 634 -47 619 -74 ct 604 -100 l +597 -131 l p +672 -174 m 672 -132 682 -101 701 -80 ct 721 -58 747 -47 777 -47 ct 793 -47 809 -51 825 -57 ct +840 -64 855 -74 869 -87 ct 882 -100 894 -115 903 -132 ct 913 -149 920 -167 926 -187 ct +935 -214 939 -240 939 -265 ct 939 -305 929 -336 909 -358 ct 889 -380 864 -391 833 -391 ct +810 -391 789 -385 769 -374 ct 750 -363 733 -346 717 -325 ct 701 -303 690 -278 683 -250 ct +675 -221 l 672 -196 l p ef +1359 -79 m 1307 -19 1253 9 1198 9 ct 1164 9 1136 0 1116 -19 ct 1095 -38 1084 -62 1084 -90 ct +1084 -109 1089 -140 1099 -185 ct 1151 -439 l 1226 -439 l 1168 -158 l 1163 -134 1160 -116 1160 -103 ct +1160 -87 1165 -74 1175 -65 ct 1185 -55 1200 -51 1220 -51 ct 1241 -51 1261 -56 1281 -66 ct +1301 -76 1318 -90 1333 -107 ct 1347 -125 1359 -145 1368 -169 ct 1374 -184 1381 -211 1389 -249 ct +1429 -439 l 1504 -439 l 1412 0 l 1343 0 l p ef +1536 0 m 1627 -439 l 1694 -439 l 1675 -349 l 1698 -383 1720 -408 1741 -424 ct +1763 -441 1785 -449 1808 -449 ct 1823 -449 1841 -443 1863 -433 ct 1832 -363 l +1819 -372 1805 -377 1790 -377 ct 1763 -377 1736 -362 1709 -333 ct 1681 -304 1660 -252 1644 -176 ct +1607 0 l p ef +pom +pum +20241 15505 t +510 -213 m 591 -202 l 565 -132 528 -79 480 -43 ct 431 -7 377 10 316 10 ct +243 10 184 -12 141 -57 ct 98 -102 76 -166 76 -250 ct 76 -359 109 -449 175 -521 ct +233 -584 306 -616 393 -616 ct 457 -616 509 -599 549 -564 ct 589 -530 612 -484 618 -425 ct +543 -418 l 535 -462 518 -495 493 -517 ct 468 -538 436 -549 397 -549 ct 322 -549 262 -516 217 -450 ct +177 -394 157 -326 157 -248 ct 157 -186 172 -138 203 -105 ct 234 -73 273 -56 323 -56 ct +364 -56 402 -70 436 -97 ct 470 -124 l 495 -163 l p ef +650 -166 m 650 -252 675 -323 726 -379 ct 767 -425 822 -449 889 -449 ct 942 -449 985 -432 1017 -399 ct +1050 -366 1066 -321 1066 -265 ct 1066 -215 1056 -168 1035 -124 ct 1015 -81 986 -47 948 -24 ct +911 -1 871 9 829 9 ct 795 9 764 2 736 -11 ct 708 -26 687 -47 672 -74 ct 657 -100 l +650 -131 l p +725 -174 m 725 -132 735 -101 754 -80 ct 774 -58 800 -47 830 -47 ct 846 -47 862 -51 878 -57 ct +893 -64 908 -74 922 -87 ct 935 -100 947 -115 956 -132 ct 966 -149 973 -167 979 -187 ct +988 -214 992 -240 992 -265 ct 992 -305 982 -336 962 -358 ct 942 -380 917 -391 886 -391 ct +863 -391 842 -385 822 -374 ct 803 -363 786 -346 770 -325 ct 754 -303 743 -278 736 -250 ct +728 -221 l 725 -196 l p ef +1409 -63 m 1366 -14 1321 9 1275 9 ct 1233 9 1198 -5 1171 -36 ct 1143 -66 1129 -111 1129 -169 ct +1129 -223 1140 -272 1162 -316 ct 1184 -360 1211 -394 1244 -416 ct 1277 -438 1310 -449 1343 -449 ct +1398 -449 1439 -422 1467 -370 ct 1517 -606 l 1591 -606 l 1465 0 l 1396 0 l +p +1204 -184 m 1204 -153 1207 -129 1213 -111 ct 1219 -94 1229 -79 1244 -67 ct +1258 -55 1276 -50 1296 -50 ct 1330 -50 1361 -67 1388 -102 ct 1425 -149 1444 -207 1444 -276 ct +1444 -311 1435 -338 1417 -358 ct 1398 -377 1376 -387 1348 -387 ct 1330 -387 1314 -383 1299 -375 ct +1284 -367 1270 -353 1255 -334 ct 1241 -315 1228 -291 1219 -261 ct 1209 -232 l +1204 -206 l p ef +1911 -149 m 1984 -141 l 1974 -105 1949 -71 1912 -38 ct 1874 -6 1829 9 1777 9 ct +1745 9 1715 2 1688 -12 ct 1661 -27 1640 -49 1626 -78 ct 1611 -106 1604 -139 1604 -176 ct +1604 -224 1615 -270 1638 -315 ct 1660 -360 1689 -394 1724 -416 ct 1759 -438 1797 -449 1838 -449 ct +1891 -449 1933 -432 1964 -400 ct 1995 -367 2011 -323 2011 -267 ct 2011 -245 2009 -223 2005 -201 ct +1682 -201 l 1681 -192 1680 -184 1680 -177 ct 1680 -136 1689 -105 1708 -83 ct +1727 -62 1750 -51 1778 -51 ct 1803 -51 1829 -59 1853 -76 ct 1878 -93 l 1897 -117 l +p +1694 -258 m 1940 -258 l 1940 -265 1941 -271 1941 -274 ct 1941 -312 1931 -340 1912 -360 ct +1894 -380 1870 -390 1840 -390 ct 1808 -390 1779 -379 1753 -357 ct 1726 -335 l +1707 -302 l p ef +pom +pum +20214 16458 t +35 0 m 162 -606 l 243 -606 l 190 -354 l 504 -354 l 557 -606 l 638 -606 l +512 0 l 430 0 l 490 -285 l 176 -285 l 116 0 l p ef +959 -149 m 1032 -141 l 1022 -105 997 -71 960 -38 ct 922 -6 877 9 825 9 ct +793 9 763 2 736 -12 ct 709 -27 688 -49 674 -78 ct 659 -106 652 -139 652 -176 ct +652 -224 663 -270 686 -315 ct 708 -360 737 -394 772 -416 ct 807 -438 845 -449 886 -449 ct +939 -449 981 -432 1012 -400 ct 1043 -367 1059 -323 1059 -267 ct 1059 -245 1057 -223 1053 -201 ct +730 -201 l 729 -192 728 -184 728 -177 ct 728 -136 737 -105 756 -83 ct 775 -62 798 -51 826 -51 ct +851 -51 877 -59 901 -76 ct 926 -93 l 945 -117 l p +742 -258 m 988 -258 l 988 -265 989 -271 989 -274 ct 989 -312 979 -340 960 -360 ct +942 -380 918 -390 888 -390 ct 856 -390 827 -379 801 -357 ct 774 -335 l 755 -302 l +p ef +1113 0 m 1204 -439 l 1271 -439 l 1252 -349 l 1275 -383 1297 -408 1318 -424 ct +1340 -441 1362 -449 1385 -449 ct 1400 -449 1418 -443 1440 -433 ct 1409 -363 l +1396 -372 1382 -377 1367 -377 ct 1340 -377 1313 -362 1286 -333 ct 1258 -304 1237 -252 1221 -176 ct +1184 0 l p ef +1726 -149 m 1799 -141 l 1789 -105 1764 -71 1727 -38 ct 1689 -6 1644 9 1592 9 ct +1560 9 1530 2 1503 -12 ct 1476 -27 1455 -49 1441 -78 ct 1426 -106 1419 -139 1419 -176 ct +1419 -224 1430 -270 1453 -315 ct 1475 -360 1504 -394 1539 -416 ct 1574 -438 1612 -449 1653 -449 ct +1706 -449 1748 -432 1779 -400 ct 1810 -367 1826 -323 1826 -267 ct 1826 -245 1824 -223 1820 -201 ct +1497 -201 l 1496 -192 1495 -184 1495 -177 ct 1495 -136 1504 -105 1523 -83 ct +1542 -62 1565 -51 1593 -51 ct 1618 -51 1644 -59 1668 -76 ct 1693 -93 l 1712 -117 l +p +1509 -258 m 1755 -258 l 1755 -265 1756 -271 1756 -274 ct 1756 -312 1746 -340 1727 -360 ct +1709 -380 1685 -390 1655 -390 ct 1623 -390 1594 -379 1568 -357 ct 1541 -335 l +1522 -302 l p ef +1946 -153 m 1992 -482 l 2018 -606 l 2109 -606 l 2081 -471 l 1993 -153 l +p +1899 0 m 1917 -84 l 2001 -84 l 1983 0 l p ef +pom +gr +3175 15240 m 3625 15389 l 3624 15089 l 3175 15240 l p ef +1 lw 0 lj 5715 15240 m 3535 15240 l ps +10795 15240 m 11245 15389 l 11244 15089 l 10795 15240 l p ef +12565 15240 m 11155 15240 l ps +16510 15240 m 16960 15389 l 16959 15089 l 16510 15240 l p ef +19050 15240 m 16870 15240 l ps +gs +pum +10319 18547 t +219 0 m 219 -534 l 19 -534 l 19 -606 l 500 -606 l 500 -534 l 299 -534 l +299 0 l p ef +584 0 m 584 -439 l 651 -439 l 651 -372 l 668 -403 683 -424 698 -434 ct +712 -444 728 -449 746 -449 ct 771 -449 796 -441 822 -425 ct 797 -356 l 778 -366 760 -372 742 -372 ct +726 -372 711 -367 698 -357 ct 685 -347 676 -334 670 -316 ct 662 -290 658 -261 658 -229 ct +658 0 l p ef +1162 -54 m 1134 -30 1108 -14 1082 -4 ct 1057 5 1029 9 1000 9 ct 952 9 915 -1 889 -25 ct +863 -49 850 -79 850 -115 ct 850 -137 855 -156 865 -174 ct 875 -192 887 -206 903 -217 ct +919 -228 937 -236 957 -241 ct 971 -245 993 -249 1023 -253 ct 1083 -260 1127 -268 1156 -278 ct +1156 -288 1156 -295 1156 -298 ct 1156 -328 1149 -349 1135 -362 ct 1116 -379 1088 -387 1050 -387 ct +1015 -387 989 -381 973 -369 ct 956 -356 944 -335 936 -303 ct 863 -313 l 870 -345 880 -370 896 -389 ct +911 -408 933 -423 961 -433 ct 990 -443 1023 -449 1061 -449 ct 1099 -449 1129 -444 1152 -435 ct +1176 -427 1193 -415 1204 -402 ct 1215 -389 1223 -372 1227 -351 ct 1230 -339 1231 -316 1231 -283 ct +1231 -184 l 1231 -114 1233 -71 1236 -52 ct 1239 -34 1245 -16 1255 0 ct 1177 0 l +1169 -15 l 1164 -33 l p +1156 -220 m 1129 -209 1088 -200 1034 -192 ct 1004 -187 982 -182 969 -177 ct +957 -171 947 -163 940 -153 ct 933 -142 930 -130 930 -117 ct 930 -98 937 -81 952 -68 ct +967 -55 989 -48 1018 -48 ct 1047 -48 1072 -54 1095 -67 ct 1117 -79 1133 -96 1144 -118 ct +1152 -135 1156 -160 1156 -193 ct p ef +1325 0 m 1325 -439 l 1392 -439 l 1392 -376 l 1425 -425 1471 -449 1532 -449 ct +1559 -449 1583 -444 1605 -434 ct 1627 -425 1644 -412 1655 -397 ct 1666 -382 1674 -363 1678 -342 ct +1681 -328 1682 -304 1682 -270 ct 1682 0 l 1608 0 l 1608 -267 l 1608 -297 1605 -320 1599 -335 ct +1593 -350 1583 -362 1568 -371 ct 1554 -380 1536 -384 1516 -384 ct 1485 -384 1457 -374 1434 -354 ct +1411 -334 1400 -296 1400 -239 ct 1400 0 l p ef +1772 -131 m 1845 -142 l 1849 -113 1861 -90 1880 -74 ct 1899 -59 1925 -51 1959 -51 ct +1993 -51 2018 -58 2035 -72 ct 2052 -86 2060 -102 2060 -121 ct 2060 -138 2053 -151 2038 -160 ct +2028 -167 2002 -175 1962 -186 ct 1907 -199 1869 -211 1848 -221 ct 1827 -231 1811 -245 1800 -263 ct +1789 -281 1784 -301 1784 -322 ct 1784 -342 1788 -360 1797 -376 ct 1806 -393 1819 -407 1834 -418 ct +1846 -427 1861 -434 1881 -440 ct 1901 -446 1923 -449 1946 -449 ct 1980 -449 2010 -444 2036 -434 ct +2063 -424 2082 -410 2094 -393 ct 2107 -376 2115 -354 2120 -325 ct 2047 -315 l +2044 -338 2034 -356 2018 -368 ct 2002 -381 1980 -387 1951 -387 ct 1917 -387 1892 -382 1878 -370 ct +1863 -359 1856 -346 1856 -331 ct 1856 -321 1859 -312 1865 -305 ct 1871 -297 1881 -290 1894 -285 ct +1901 -282 1923 -276 1959 -266 ct 2012 -252 2049 -240 2070 -231 ct 2090 -222 2107 -209 2119 -192 ct +2130 -175 2136 -154 2136 -129 ct 2136 -104 2129 -80 2115 -58 ct 2100 -37 2079 -20 2052 -8 ct +2025 3 1994 9 1959 9 ct 1902 9 1859 -1 1829 -25 ct 1799 -49 l 1780 -84 l p ef +2198 0 m 2198 -439 l 2265 -439 l 2265 -377 l 2279 -399 2297 -416 2320 -429 ct +2343 -442 2369 -449 2398 -449 ct 2431 -449 2457 -442 2478 -428 ct 2499 -415 2514 -396 2522 -372 ct +2557 -423 2602 -449 2658 -449 ct 2701 -449 2735 -437 2758 -412 ct 2782 -388 2793 -351 2793 -301 ct +2793 0 l 2719 0 l 2719 -276 l 2719 -306 2717 -327 2712 -340 ct 2707 -354 2699 -364 2686 -372 ct +2673 -380 2658 -384 2641 -384 ct 2610 -384 2585 -374 2564 -353 ct 2544 -333 2534 -300 2534 -255 ct +2534 0 l 2459 0 l 2459 -285 l 2459 -318 2453 -343 2441 -359 ct 2429 -376 2409 -384 2382 -384 ct +2361 -384 2341 -379 2323 -368 ct 2306 -357 2293 -340 2285 -319 ct 2277 -298 2273 -267 2273 -227 ct +2273 0 l p ef +2914 -520 m 2914 -606 l 2988 -606 l 2988 -520 l p +2914 0 m 2914 -439 l 2988 -439 l 2988 0 l p ef +3261 -66 m 3272 0 l 3251 3 3232 5 3215 5 ct 3188 5 3167 1 3153 -7 ct 3138 -15 3127 -26 3121 -40 ct +3115 -54 3112 -83 3112 -128 ct 3112 -381 l 3057 -381 l 3057 -439 l 3112 -439 l +3112 -547 l 3186 -592 l 3186 -439 l 3261 -439 l 3261 -381 l 3186 -381 l +3186 -124 l 3186 -103 3187 -89 3190 -83 ct 3193 -77 3197 -72 3203 -69 ct 3209 -65 3217 -63 3228 -63 ct +3236 -63 l 3247 -64 l p ef +3584 0 m 3584 -606 l 3813 -606 l 3853 -606 3884 -604 3905 -600 ct 3935 -595 3960 -586 3980 -572 ct +4000 -558 4016 -538 4028 -513 ct 4041 -488 4047 -461 4047 -430 ct 4047 -379 4030 -335 3997 -300 ct +3965 -264 3905 -246 3820 -246 ct 3664 -246 l 3664 0 l p +3664 -318 m 3821 -318 l 3873 -318 3909 -327 3931 -346 ct 3953 -366 3964 -393 3964 -428 ct +3964 -453 3958 -475 3945 -493 ct 3932 -511 3915 -523 3894 -529 ct 3881 -532 3856 -534 3819 -534 ct +3664 -534 l p ef +4417 -54 m 4389 -30 4363 -14 4337 -4 ct 4312 5 4284 9 4255 9 ct 4207 9 4170 -1 4144 -25 ct +4118 -49 4105 -79 4105 -115 ct 4105 -137 4110 -156 4120 -174 ct 4130 -192 4142 -206 4158 -217 ct +4174 -228 4192 -236 4212 -241 ct 4226 -245 4248 -249 4278 -253 ct 4338 -260 4382 -268 4411 -278 ct +4411 -288 4411 -295 4411 -298 ct 4411 -328 4404 -349 4390 -362 ct 4371 -379 4343 -387 4305 -387 ct +4270 -387 4244 -381 4228 -369 ct 4211 -356 4199 -335 4191 -303 ct 4118 -313 l +4125 -345 4135 -370 4151 -389 ct 4166 -408 4188 -423 4216 -433 ct 4245 -443 4278 -449 4316 -449 ct +4354 -449 4384 -444 4407 -435 ct 4431 -427 4448 -415 4459 -402 ct 4470 -389 4478 -372 4482 -351 ct +4485 -339 4486 -316 4486 -283 ct 4486 -184 l 4486 -114 4488 -71 4491 -52 ct +4494 -34 4500 -16 4510 0 ct 4432 0 l 4424 -15 l 4419 -33 l p +4411 -220 m 4384 -209 4343 -200 4289 -192 ct 4259 -187 4237 -182 4224 -177 ct +4212 -171 4202 -163 4195 -153 ct 4188 -142 4185 -130 4185 -117 ct 4185 -98 4192 -81 4207 -68 ct +4222 -55 4244 -48 4273 -48 ct 4302 -48 4327 -54 4350 -67 ct 4372 -79 4388 -96 4399 -118 ct +4407 -135 4411 -160 4411 -193 ct p ef +4742 -66 m 4753 0 l 4732 3 4713 5 4696 5 ct 4669 5 4648 1 4634 -7 ct 4619 -15 4608 -26 4602 -40 ct +4596 -54 4593 -83 4593 -128 ct 4593 -381 l 4538 -381 l 4538 -439 l 4593 -439 l +4593 -547 l 4667 -592 l 4667 -439 l 4742 -439 l 4742 -381 l 4667 -381 l +4667 -124 l 4667 -103 4668 -89 4671 -83 ct 4674 -77 4678 -72 4684 -69 ct 4690 -65 4698 -63 4709 -63 ct +4717 -63 l 4728 -64 l p ef +4818 0 m 4818 -606 l 4893 -606 l 4893 -388 l 4928 -429 4971 -449 5024 -449 ct +5057 -449 5085 -442 5109 -429 ct 5133 -417 5150 -399 5161 -376 ct 5171 -354 5176 -321 5176 -278 ct +5176 0 l 5102 0 l 5102 -278 l 5102 -315 5094 -342 5077 -359 ct 5061 -376 5039 -385 5009 -385 ct +4987 -385 4966 -379 4947 -367 ct 4927 -356 4913 -340 4905 -321 ct 4897 -301 4893 -274 4893 -240 ct +4893 0 l p ef +pom +gr +gr +0 20290 t +pom +count op_count sub {pop} repeat countdictstack dict_count sub {end} repeat b4_inc_state restore +%%PageTrailer +%%Trailer +%%EOF diff --git a/docs/exploring-gnuradio/swr-block-diagram.png b/docs/exploring-gnuradio/swr-block-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..580aa687dec873681fa4b2181c1437dedf2ef488 GIT binary patch literal 24686 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 VuxDLC4$kv=&Rcgl6+8OI{|8e{(bWI| literal 0 HcmV?d00001 diff --git a/docs/exploring-gnuradio/usrp-block-diagram.eps b/docs/exploring-gnuradio/usrp-block-diagram.eps new file mode 100644 index 00000000..190b9dee --- /dev/null +++ b/docs/exploring-gnuradio/usrp-block-diagram.eps @@ -0,0 +1,2785 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%BoundingBox: 0 0 755 575 +%%Pages: 0 +%%Creator: Sun Microsystems, Inc. +%%Title: none +%%CreationDate: none +%%LanguageLevel: 2 +%%EndComments +%%BeginPreview: 760 575 1 1725 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000FFE300707800000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000FFE380E1FE00000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C001C0C30700000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C000E1830300000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C000E3820300000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C00077000300000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C0003E000300000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C0001C000700000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000FFC01C000E00000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000FFC03E001C00000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C00037003800000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C0006700F000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C000E381C000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C001C1C18000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C00180C30000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C00380E7FF00000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000C0070077FF00000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%08000000300701F80FF80007C00000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%08000000300707FE0FFE000FF00000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%08000000300706070C060018380000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800000030070E038C030010180000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800000030070C000C030030180000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800000030070E000C030000180000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%08000000300707C00C070000380000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%08000000300703FC0FFE0000300000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000003007007E0FFC0000700000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000003007000F0FFF0000E00000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%08000000300700038C030003C00000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800000030071C018C038007000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800000038061C018C01800E000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800000018060E038C03801C000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000001C0E0F070C070018000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000FFC07FE0FFF003FF80000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800000007F001FC0FFC003FF80000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080007E00000000000000031800000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%08001FF80000000300000031800000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800381C0000000300000031800000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800700C0000000300000031800000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800600E03808E07C8C0E03180E023000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800E0000FE0FF8FCFE3F83183F83F800000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800E0001C70F3C30FC71C31871C3F000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800C0003038E0C30E0E0E318E0E38000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800C0003018C0C30C0C06318C0630000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800C0007018C0C30C0C06318FFE30000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800C0007018C0C30C0C07318FFE30000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800E0067018C0C30C0C07318C0030000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800600E7018C0C30C0C06318C0030000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800700C3038C0C30C0C06318C0630000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0800381C3830C0C30C0E0E318E0E30000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%08001FF81FF0C0C3CC07FC3187FC30000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080007E00FC0C0C1CC01F03181F030000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%080000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000018000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000000000000000000000000000 +%007FFFFFFFFFFFFFFFFFFFFFFFFFFFFE00000000000000000000000000000000FFFFFFFFFFFFFF +%FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000010000 +%004000000000000000000000000000020000040000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000020000000000000000000 +%004000000000000000000000000000020000000000000000000020000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000040000000000000000000 +%004000000000000000000000000000020000000000000000000010000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000100000000000000000000 +%004000000000000000000000000000020000000000000000000004000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000200000000000000000000 +%004000000000000000000000000000020000000000000000000002000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000400000000000000000000 +%004000000000000000000000000000020000000000000000000001000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000800000000000000000000 +%004000000000000000000000000000020000000000000000000000800000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000001000000000000000000000 +%004000000000000000000000000000020000000000000000000000400000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000002000000000000000000000 +%004000000000000000000000000000020000000000000000000000200000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000C000000000000000000000 +%004000000000000000000000000000020000000000000000000000180000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000010000000000000000000000 +%004000000000000000000000000000020000000000000000000000040000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000020000000000000000000000 +%004000000000000000000000000000020000000000000000000000020000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000040000000000000000000000 +%004000000000000000000000000000020000000000000000000000010000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000080000000000000000000000 +%004000000000000000000000000000020000000000000000000000008000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000100000000000000000000000 +%004000000000000000000000000000020000000000000000000000004000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000200000000000000000000000 +%004000000000000000000000000000020000000000000000000000002000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000C00000000000000000000000 +%004000000000000000000000000000020000000000000000000000001800000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000020001C03FF800FE0000000000 +%00400000000000000000000000000002000000000003C03FF001FE000200000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000040001E03FFC03FF8000000000 +%00400000000000000000000000000002000000000003C03FFC03FF000100000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000360300E07038000000000 +%00400000000000000000000000000002000000000003C0301C0703800000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040001000036030060601C000000000 +%0040000000000000000000000000000200000000000760300E0E01800040000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040002000073030070C00C000000000 +%004000000000000000000000000000020000000000066030060C01C00020000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040004000063030030C000000000000 +%004000000000000000000000000000020000000000067030071C00000010000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000063830031C000000000000 +%0040000000000000000000000000000200000000000C3030071800000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000E1830031C00000000FFFF +%FFC0000000000000000000000000000200000000000C3030031800000001FFFF80000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400200000C1830031C00000000FFFF +%FFC0000000000000000000000000000200000000001C1830031800000003FFFF80000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000007FF800000C1C30031C000000000000 +%00400000000000000000000000000003FFFFF800001C1830031800000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000001FFC30030C000000000000 +%0040000000000000000000000000000200000000001FFC30071800000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000001FFE30070C00C000000000 +%0040000000000000000000000000000200000000003FFC30061C00C00000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000380630070E00C000000000 +%004000000000000000000000000000020000000000300E30060C01C00000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400020003006300E0701C000000000 +%004000000000000000000000000000020000000000300E300E0E03800020000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400010003007301E07838000000000 +%0040000000000000000000000000000200000000006006301C0707800040000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000000070033FF801FF0000000000 +%00400000000000000000000000000002000000000060073FF803FE000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400004006003BFE0007C0000000000 +%004000000000000000000000000000020000000000E0033FE000FC000100000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400002000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000200000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000800000000000000000000000 +%004000000000000000000000000000020000000000000000000000000800000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000400000000000000000000000 +%004000000000000000000000000000020000000000000000000000001000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000200000000000000000000000 +%004000000000000000000000000000020000000000000000000000002000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000100000000000000000000000 +%004000000000000000000000000000020000000000000000000000004000000080000000000000 +%0000000000000000000000000000000400 +%0008000000000003FF800000000003000000000000000000400000080000000000000000000000 +%00400000000000000000000000000002000000000000000000000000800000008000000000003F +%F800000000003000000000000000000400 +%0008000000000003FFC00000000003000000000000000000400000040000000000000000000000 +%00400000000000000000000000000002000000000000000000000001000000008000000000003F +%FC00000000003000000000000000000400 +%000800000000000300E00000000002000000000000000000400000020000000000000000000000 +%004000000000000000000000000000020000000000000000000000020000000080000000000038 +%0E00000000002000000000000000000400 +%000800000000000300600000000000000000000000000000400000018000000000000000000000 +%0040000000000000000000000000000200000000000000000000000C0000000080000000000030 +%0700000000000000000000000000000400 +%000800000000000300700000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000100000000080000000000030 +%0700000000000000000000000000000400 +%00080000000000030070FE03F03F0330187E000000000000400000002000000000000000000000 +%004000000000000000000000000000020000000000000000000000200000000080000000000030 +%0707E03F03F8338187F000000000000400 +%00080000000000030061EF073873833838E7000000000000400000001000000000000000000000 +%004000000000000000000000000000020000000000000000000000400000000080000000000030 +%070E7073873C31818E7800000000000400 +%000800000000000301E1830E1CE0C3183181800000000000400000000800000000000000000000 +%004000000000000000000000000000020000000000000000000000800000000080000000000038 +%1E1838E0CE0C31831C1800000000000400 +%0008000000000003FF83018C0CC0E3183181C00000000000400000000400000000000000000000 +%00400000000000000000000000000002000000000000000000000100000000008000000000003F +%FC3018C0CC0631C3180C00000000000400 +%0008000000000003FE03019C01C0E30C6381C00000000000400000000200000000000000000000 +%00400000000000000000000000000002000000000000000000000200000000008000000000003F +%F03018C00C0630C3181C00000000000400 +%00080000000000030703FF9C01FFE30C63FFC00000000000400000000100000000000000000000 +%004000000000000000000000000000020000000000000000000004000000000080000000000030 +%383FF8C00FFE30C61FFC00000000000400 +%00080000000000030383001C01C0030C6380000000000000400000000040000000000000000000 +%004000000000000000000000000000020000000000000000000010000000000080000000000030 +%183000C00C003066180000000000000400 +%000800000000000301C3001C01C00306C380000000000000400000000020000000000000000000 +%004000000000000000000000000000020000000000000000000020000000000080000000000030 +%1C3000C00C003066180000000000000400 +%000800000000000300E3018C0CC04306C181800000000000400000000000000000000000010000 +%004000000000000000000000000000020000040000000000000000000000000080000000000030 +%0E3818C0CC06306C180C00000000000400 +%000800000000000300E1838E1CE0C307C1C1800000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000030 +%071838E0CE0E303C1C1C00000000000400 +%00080000000000030071E7073873C30380E7800000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000030 +%071E707387BC30380F7800000000000400 +%00080000000000030030FE03F03F8303807F000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000030 +%0387E03F03F8303807F000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800FFC0000000000030000000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800FFC00000000 +%00030000000000C0000000000000C00400 +%000800FFF000000000003000C000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800FFF00000000 +%0003000C000000C0000000000000C00400 +%000800E07800000000003000C000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E0780000000 +%0003000C000000C0000000000000C00400 +%000800E01800000000003000C000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E01C0000000 +%0003000C000000C0000000000000C00400 +%000800E01C00000000003000C000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E00C0000000 +%0003000E000000C0000000000000C00400 +%000800E00C1FC38183FC37E3F0FC1FCDF03F81FE1FC7FC00400000000000000000000000010000 +%0040000000000000000000000000000200000400000000000000000000000000800E00C1FE1818 +%3FE37E1F0FC0FCDF01FC0FE1FC7EC00400 +%000800E00C39E381873C3CE0C1CE1FCF3879C3CF1F8E7C00400000000020000000000000000000 +%0040000000000000000000000000000200000000000000000000200000000000800E00E38E1818 +%73E3EF0C1CF0FCFB879E1CF1F8E7C00400 +%000800E00E7063818C1C3870C3031C0E1C60E3031C1C3C00400000000040000000000000000000 +%0040000000000000000000000000000200000000000000000000100000000000800E00E3071818 +%E1E3830C3030E0E1C6063831C1C1C00400 +%000800E00E0063818C0C3030C7031C0C0CC0600318181C00400000000100000000000000000000 +%0040000000000000000000000000000200000000000000000000040000000000800E00E0071818 +%C0E3030C3038C0C0CE070031C181C00400 +%000800E00E006381980C3030C7039C0C0CC0700718181C00400000000200000000000000000000 +%0040000000000000000000000000000200000000000000000000020000000000800E00E0071818 +%C0E3030C7038C0C0CC0300718180C00400 +%000800E00C1FE381980C3030C7FF9C0C0CC030FF18381C00400000000400000000000000000000 +%0040000000000000000000000000000200000000000000000000010000000000800E00E0FF1819 +%C0E3030C7FF8C0C0EC030FF18180C00400 +%000800E00C3E6381980C3030C7001C0C0CC033E318381C00400000000800000000000000000000 +%0040000000000000000000000000000200000000000000000000008000000000800E00E3E71819 +%C0E3030C7000C0C0EC031E318180C00400 +%000800E00C7063839C0C3030C6001C0C0CC0730318181C00400000001000000000000000000000 +%0040000000000000000000000000000200000000000000000000004000000000800E00C7071818 +%C0E3030C7000C0C0CC0330318180C00400 +%000800E01C6063838C0C3030C7031C0C0CE0670318181C00400000002000000000000000000000 +%0040000000000000000000000000000200000000000000000000002000000000800E01C6071838 +%C0E3030C3030C0C0CE0730318181C00400 +%000800E03860E1878C1C3030C3871C0E1860E707181C3C00400000008000000000000000000000 +%0040000000000000000000000000000200000000000000000000001800000000800E0386071838 +%E1E3030C3830C0E1C706307180C1C00400 +%000800FFF071E1FF877C3030F1CE1C0F3879C39F180E7C00400000010000000000000000000000 +%0040000000000000000000000000000200000000000000000000000400000000800FFF039F1FF8 +%73E3030F1EF0C0FB839E39F180F7C00400 +%000800FFE03F30F983EC303070FC1C0DF01F81FB1807FC00400000020000000000000000000000 +%0040000000000000000000000000000200000000000000000000000200000000800FFE03F30FD8 +%3FE303078FE0C0DF01F81FB9807EC00400 +%0008000000000000000C0000000000000000000000000000400000040000000000000000000000 +%004000000000000000000000000000020000000000000000000000010000000080000000000000 +%00E0000000000000000000000000000400 +%0008000000000000080C0000000000000000000000000000400000080000000000000000000000 +%004000000000000000000000000000020000000000000000000000008000000080000000000000 +%C0C0000000000000000000000000000400 +%00080000000000000C1C0000000000000000000000000000400000100000000000000000000000 +%004000000000000000000000000000020000000000000000000000004000000080000000000000 +%E1C0000000000000000000000000000400 +%000800000000000007F80000000000000000000000000000400000200000000000000000000000 +%004000000000000000000000000000020000000000000000000000002000000080000000000000 +%7F80000000000000000000000000000400 +%000800000000000003E00000000000000000000000000000400000C00000000000000000000000 +%004000000000000000000000000000020000000000000000000000001800000080000000000000 +%1E00000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000020001C03FF801FE0000000000 +%00400000000000000000000000000002000000000003C03FF801FE000200000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000040001E03FFC03FF8000000000 +%00400000000000000000000000000002000000000003C03FFC03FF000100000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000360300E07018000000000 +%00400000000000000000000000000002000000000003E0301C0703800000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040001000036030070E01C000000000 +%0040000000000000000000000000000200000000000660300E0E01800040000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040002000073030070C00C000000000 +%004000000000000000000000000000020000000000066030060C00800020000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040004000063030030C000000000000 +%004000000000000000000000000000020000000000067030071C00000010000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040010000063830031C000000000000 +%0040000000000000000000000000000200000000000C3030031800000000000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000007FF800000E1830031C00000000FFFF +%FFC0000000000000000000000000000200000000000C3830031800000001FFFF80000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000007FF800000C1C30031C00000000FFFF +%FFC0000000000000000000000000000200000800001C1830031800000001FFFF80000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400200000C1C30031C000000000000 +%00400000000000000000000000000003FFFFF800001C1830031800000002000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000001FFC30030C000000000000 +%0040000000000000000000000000000200000000001FFC30071C00000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000001FFE30070C00C000000000 +%0040000000000000000000000000000200000000003FFC30060C00C00000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000380630070E00C000000000 +%004000000000000000000000000000020000000000300E30060C01C00000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400020003007300E0701C000000000 +%004000000000000000000000000000020000000000300E300E0E03800020000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000003007383C03C78000000000 +%0040000000000000000000000000000200000000006006303C0787000000000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000000070033FF801FF0000000000 +%00400000000000000000000000000002000000000060073FF803FE000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400004006003BFE0007C0000000000 +%004000000000000000000000000000020000000000E0033FE000F8000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000800000000000000000000000 +%004000000000000000000000000000020000000000000000000000000800000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000400000000000000000000000 +%004000000000000000000000000000020000000000000000000000001000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000100000000000000000000000 +%004000000000000000000000000000020000000000000000000000004000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000080000000000000000000000 +%004000000000000000000000000000020000000000000000000000008000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000020000000000000000000000 +%004000000000000000000000000000020000000000000000000000020000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000018000000000000000000000 +%0040000000000000000000000000000200000000000000000000000C0000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000004000000000000000000000 +%004000000000000000000000000000020000000000000000000000100000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000002000000000000000000000 +%004000000000000000000000000000020000000000000000000000200000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000001000000000000000000000 +%004000000000000000000000000000020000000000000000000000400000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000800000000000000000000 +%004000000000000000000000000000020000000000000000000000800000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000400000000000000000000 +%004000000000000000000000000000020000000000000000000001000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000200000000000000000000 +%004000000000000000000000000000020000000000000000000002000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000080000000000000000000 +%004000000000000000000000000000020000000000000000000008000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000040000000000000000000 +%004000000000000000000000000000020000000000000000000010000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000020000000000000000000 +%004000000000000000000000000000020000000000000000000020000000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000001FFFFFFFFFFFFFFF0000 +%00400000000000000000000000000002000007FFFFFFFFFFFFFFC0000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000FFFFFFFFFFFFFF +%FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000007FF9FF8007C001C000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000007FF9FFE01FF801C000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000007001C0F0383C03E000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C070700C036000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C030E00C036000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C030C000063000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C031C000063000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000007001C071C0000E3800000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000007FF1FFE1C0FE0C1800000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000007FE1FFC1C0FE0C1800000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C001C00E1FFC00000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C000C0061FFC00000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C000C006380E00000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C000E006300600000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C000781E300700000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C0003FFC700700000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0040000006001C0000FF0600300000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000007FFFFFFFFFFFFF +%FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000001FFFFFFFFFFFFFFF0000 +%00400000000000000000000000000002000007FFFFFFFFFFFFFFC0000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000080000000000000000000 +%004000000000000000000000000000020000000000000000000008000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000002000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000008000000000000000000000 +%004000000000000000000000000000020000000000000000000000080000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000010000000000000000000000 +%004000000000000000000000000000020000000000000000000000040000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000040000000000000000000000 +%004000000000000000000000000000020000000000000000000000010000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000080000000000000000000000 +%004000000000000000000000000000020000000000000000000000008000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000200000000000000000000000 +%004000000000000000000000000000020000000000000000000000002000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000C00000000000000000000000 +%004000000000000000000000000000020000000000000000000000001800000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400001003FE00060007C0000000000 +%0040000000000000000000000000000200000000003FE000E00078000400000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400002003FF800F001FF0000000000 +%0040000000000000000000000000000200000000003FF800E001FE000200000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000400383E00F003C78000000000 +%004000000000000000000000000000020000000000303C01E00787000100000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000800380E01F80701C000000000 +%004000000000000000000000000000020000000000300E01B00E03800080000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040001000380701980E00C000000000 +%004000000000000000000000000000020000000000300601B00C01C00040000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040002000380301980C008000000000 +%004000000000000000000000000000020000000000300703181C00800020000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400080003803039C0C000000000000 +%004000000000000000000000000000020000000000300303181C00000008000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400100003803830C1C000000000000 +%0040000000000000000000000000000200000000003003071C1800000004000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000003803830C1C000000008000 +%0040000000000000000000000000000200000800003003060C1800000000000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000007FFC0000380386061C00000000FFFF +%FFC00000000000000000000000000003FFFFF800003003060C1800000001FFFF80000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040020000380387FE1C000000000000 +%00400000000000000000000000000002000000000030030FFE1800000002000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000000038030FFF0C000000000000 +%00400000000000000000000000000002000000000030070FFE1C00000004000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000C00038030C030C00C000000000 +%00400000000000000000000000000002000000000030061C070C00C00018000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000000038070C030E01C000000000 +%004000000000000000000000000000020000000000300618030E01C00000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000380E1C038701C000000000 +%004000000000000000000000000000020000000000300E18038703800000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400008003FFC180183FF8000000000 +%0040000000000000000000000000000200000000003FFC380387FF000080000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000003FF83801C1FE0000000000 +%0040000000000000000000000000000200000000003FF8300181FE000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400002000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000200000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400001000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000400000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000800000000000000000000000 +%004000000000000000000000000000020000000000000000000000000800000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000007FFE00000000000000000C100000000000400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800000000003FF +%E00000000000000000C100000000000400 +%000800000000003FFE00000000000000000C300000000000400000004000000000000000000000 +%0040000000000000000000000000000200000000000000000000001000000000800000000003FF +%E00000000000000000C300000000000400 +%0008000000000001C0000000000000000000300000000000400000002000000000000000000000 +%00400000000000000000000000000002000000000000000000000020000000008000000000000C +%0000000000000000000300000000000400 +%0008000000000001C0000000000000000000300000000000400000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%0000000000000000000300000000000400 +%0008000000000001C0670F833C03C19E1C0CFC0000000000400000000800000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%0270F811C03C09E1C0CFC0000000000400 +%0008000000000001C07F3FE3FF0FE1FF7F0CFC0000000000400000000400000000000000000000 +%00400000000000000000000000000002000000000000000000000100000000008000000000000C +%07F1FE1FF0FF1FF3F0CFC0000000000400 +%0008000000000001C07A30E3C31C31E3C70C300000000000400000000100000000000000000000 +%00400000000000000000000000000002000000000000000000000400000000008000000000000C +%0783061C38C31E3E30C300000000000400 +%0008000000000001C0707063839831C1830C300000000000400000000080000000000000000000 +%00400000000000000000000000000002000000000000000000000800000000008000000000000C +%0703071819C11C1C38C300000000000400 +%0008000000000001C0700063819C01C1830C300000000000400000000040000000000000000000 +%00400000000000000000000000000002000000000000000000001000000000008000000000000C +%0700071819C01C1818C300000000000400 +%0008000000000001C06003E3818F8181830C300000000000400000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%07001F1818F81C1818C300000000000400 +%0008000000000001C0603FE38187F181830C30000000000040000000001FFFFFFFFFFFFFFF0000 +%00400000000000000000000000000002000007FFFFFFFFFFFFFFC000000000008000000000000C +%0701FF18187F1C1818C300000000000400 +%0008000000000001C06078638180F181830C300000000000400000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%0703C718180F9C1818C300000000000400 +%0008000000000001C060606381803981830C300000000000400000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%0707071818019C1818C300000000000400 +%0008000000000001C060606381981981830C300000000000400000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%0706071819819C1818C300000000000400 +%0008000000000001C06060E3819C3981830C300000000000400000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%07070F1819C39C1818C300000000000400 +%0008000000000001C0607FE3818FF181830C3C0000000000400000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%0703FF1818FF1C1818C3C0000000000400 +%0008000000000001C0601E338187C181830C1C0000000000400000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000008000000000000C +%0701F318183E1C1818C1C0000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800FFE0000000000030004000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800FFE00000000 +%00030004000000C0000000000000C00400 +%000800FFF000000000003000C000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800FFF00000000 +%0003000C000000C0000000000000C00400 +%000800E03800000000003000C000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E0380000000 +%0003000C000000C0000000000000C00400 +%000800E01C00000000003000C000000C0000000000000C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E01C0000000 +%0003000C000000C0000000000000C00400 +%000800E00C0F838181EC33C3F07819CCE00F007C1B83CC0040000000001FFFFFFFFFFFFFFF0000 +%00400000000000000000000000000002000007FFFFFFFFFFFFFFC00000000000800E00C0F81818 +%1E633C1F0780DCCE00F007C1BC3CC00400 +%000800E00C3FE38187FC3FE3F1FE1FCFF83FC1FE1F8FFC00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E00E1FE1818 +%7FE3FE1F1FE0FCFF83FC1FE1FC7FC00400 +%000800E00E30E3818E1C3870C3871E0E1870E3871E9C3C00400000000040000000000000000000 +%0040000000000000000000000000000200000000000000000000100000000000800E00E3061818 +%61E3870C3870E0F1C70E3871E0C3C00400 +%000800E00E7063818C0C3030C3031C0E1CE063031C181C00400000000080000000000000000000 +%0040000000000000000000000000000200000000000000000000080000000000800E00E3071818 +%C0E3030C3030C0E0C6063031C1C1C00400 +%000800E00E0063819C0C3030C6031C0C0CC0700318181C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E00E0071818 +%C0E3030C3038C0C0CC0300318181C00400 +%000800E00E03E381980C3030C7FF9C0C0CC0303F18381C00400000000400000000000000000000 +%0040000000000000000000000000000200000000000000000000010000000000800E00E03F1819 +%C0E3030C7FF8C0C0EC0301F18180C00400 +%000800E00C3FE381980C3030C7FF9C0C0CC031FF18381C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E00E1FF1819 +%C0E3030C7FF8C0C0EC031FF18180C00400 +%000800E00C786383980C3030C6001C0C0CC033C318381C00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E00C3871819 +%C0E3030C7000C0C0EC033C318180C00400 +%000800E01C6063839C0C3030C7001C0C0CC0770318181C00400000002000000000000000000000 +%0040000000000000000000000000000200000000000000000000002000000000800E00C7071818 +%C0E3030C7000C0C0CC0330318180C00400 +%000800E0186063838C0C3030C3031C0C1CE0670718181C00400000004000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800E01C6071838 +%C0E3030C3038C0E0C606303181C1C00400 +%000800E07870E1878E1C3030C3871C0E1870E70F180C3C00400000008000000000000000000000 +%0040000000000000000000000000000200000000000000000000000800000000800E07870F1C78 +%E1E3030C3870C0E1C70E307180C3C00400 +%000800FFF03FF1FD87FC3030F1FE1C0FF03FC3FF180FFC00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800FFF03FF0FD8 +%7FE3030F1FE0C0FF83FC3FF1807FC00400 +%000800FFC01E307981EC303070781C0DE01F01F39803CC00400000000000000000000000000000 +%0040000000000000000000000000000200000000000000000000000000000000800FFC01F30798 +%1EE3030787C0C0CE00F00F19803CC00400 +%0008000000000000000C0000000000000000000000000000400000040000000000000000000000 +%004000000000000000000000000000020000000000000000000000010000000080000000000000 +%00C0000000000000000000000000000400 +%00080000000000000C0C0000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%C0C0000000000000000000000000000400 +%00080000000000000E380000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%F3C0000000000000000000000000000400 +%000800000000000007F00000000000000000000000000000400000200000000000000000000000 +%004000000000000000000000000000020000000000000000000000002000000080000000000000 +%7F80000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400001003FF00060007C0000000000 +%0040000000000000000000000000000200000000003FE000E000FC000400000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400002003FFC00F001FF0000000000 +%0040000000000000000000000000000200000000003FF800E003FE000200000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000381E00F003838000000000 +%004000000000000000000000000000020000000000301C01F00787800000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000800380601F80701C000000000 +%004000000000000000000000000000020000000000300E01B00E03800080000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040001000380701980E00C000000000 +%004000000000000000000000000000020000000000300603B00C01C00040000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040004000380301980C000000000000 +%004000000000000000000000000000020000000000300703181C00000010000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400080003803031C0C000000000000 +%004000000000000000000000000000020000000000300303181800000008000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400100003803830C1C000000000000 +%0040000000000000000000000000000200000000003003071C1800000004000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000007FFA00003803870E1C00000000FFFF +%FFC00000000000000000000000000003FFFFF800003003060C1800000003FFFF80000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000007FFC0000380386061C00000000FFFF +%FFC00000000000000000000000000003FFFFF800003003060C1800000001FFFF80000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040020000380307FE0C000000000000 +%00400000000000000000000000000002000000000030030FFE1800000002000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004001000038030FFF0C00C000000000 +%00400000000000000000000000000002000000000030070FFE1C00800004000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000C00038030C030C00C000000000 +%00400000000000000000000000000002000000000030061C070C01C00018000080000000000000 +%0000000000000000000000000000000400 +%0008000000000000000000000000000000000000000000004000000038070C038601C000000000 +%004000000000000000000000000000020000000000300E18030E01800000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040001000380E1C0387038000000000 +%004000000000000000000000000000020000000000301E18038703800040000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400008003FFC180183FF8000000000 +%0040000000000000000000000000000200000000003FFC380387FF000080000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000003FF83801C1FE0000000000 +%0040000000000000000000000000000200000000003FF0300181FE000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400002000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000200000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400001000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000400000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000800000000000000000000000 +%004000000000000000000000000000020000000000000000000000000800000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000200000000000000000000000 +%004000000000000000000000000000020000000000000000000000002000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000040000000000000000000000 +%004000000000000000000000000000020000000000000000000000010000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000100000000000000000000 +%004000000000000000000000000000020000000000000000000004000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000080000000000000000000 +%004000000000000000000000000000020000000000000000000008000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000040000000000000000000 +%004000000000000000000000000000020000000000000000000010000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%00080000000000000000000000000000000000000000000040000000001FFFFFFFFFFFFFFF0000 +%00400000000000000000000000000002000007FFFFFFFFFFFFFFC0000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000800000000000000000000000000000000000000000000400000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000080000000000000 +%0000000000000000000000000000000400 +%000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00000000000000000000000000000 +%00400000000000000000000000000002000000000000000000000000000000007FFFFFFFFFFFFF +%FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC00 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%004000000000000000000000000000020000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%007FFFFFFFFFFFFFFFFFFFFFFFFFFFFE0000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%000000000000000000000000000000000000000000000000000000000000000000000000000000 +%0000000000000000000000000000000000 +%%EndPreview +%%BeginProlog +%%BeginResource: SDRes +/b4_inc_state save def +/dict_count countdictstack def +/op_count count 1 sub def +userdict begin +0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin 10 setmiterlimit[] 0 setdash newpath +/languagelevel where {pop languagelevel 1 ne {false setstrokeadjust false setoverprint} if} if +/bdef {bind def} bind def +/c {setgray} bdef +/l {neg lineto} bdef +/rl {neg rlineto} bdef +/lc {setlinecap} bdef +/lj {setlinejoin} bdef +/lw {setlinewidth} bdef +/ml {setmiterlimit} bdef +/ld {setdash} bdef +/m {neg moveto} bdef +/ct {6 2 roll neg 6 2 roll neg 6 2 roll neg curveto} bdef +/r {rotate} bdef +/t {neg translate} bdef +/s {scale} bdef +/sw {show} bdef +/gs {gsave} bdef +/gr {grestore} bdef +/f {findfont dup length dict begin +{1 index /FID ne {def} {pop pop} ifelse} forall /Encoding ISOLatin1Encoding def +currentdict end /NFont exch definefont pop /NFont findfont} bdef +/p {closepath} bdef +/sf {scalefont setfont} bdef +/ef {eofill}bdef +/pc {closepath stroke}bdef +/ps {stroke}bdef +/pum {matrix currentmatrix}bdef +/pom {setmatrix}bdef +/bs {/aString exch def /nXOfs exch def /nWidth exch def currentpoint nXOfs 0 rmoveto pum nWidth aString stringwidth pop div 1 scale aString show pom moveto} bdef +%%EndResource +%%EndProlog +%%BeginSetup +%%EndSetup +%%Page: 1 1 +%%BeginPageSetup +%%EndPageSetup +pum +0.02834 0.02833 s +0 -20290 t +/tm matrix currentmatrix def +gs +tm setmatrix +-635 -635 t +1 1 s +635 635 m 27274 635 l 27274 20924 l 635 20924 l 635 635 l eoclip newpath +0.996 c 7835 7938 m 8893 6985 l 11010 6985 l 11010 8890 l 8893 8890 l +7835 7938 l p ef +0 lw 1 lj 0.000 c 7835 7938 m 8893 6985 l 11010 6985 l 11010 8890 l 8893 8890 l +7835 7938 l pc +gs +pum +8520 8228 t +-1 0 m 231 -605 l 317 -605 l 565 0 l 474 0 l 403 -183 l 150 -183 l +83 0 l p +173 -248 m 378 -248 l 315 -416 l 296 -467 282 -509 272 -541 ct 264 -503 254 -464 240 -426 ct +p ef +621 0 m 621 -605 l 829 -605 l 876 -605 912 -602 937 -596 ct 972 -588 1001 -574 1026 -553 ct +1058 -526 1082 -492 1098 -450 ct 1114 -408 1121 -360 1121 -306 ct 1121 -260 1116 -219 1105 -183 ct +1095 -148 1081 -118 1064 -95 ct 1047 -72 1029 -54 1009 -40 ct 989 -27 965 -17 937 -10 ct +908 -3 876 0 839 0 ct p +701 -71 m 830 -71 l 870 -71 901 -75 924 -82 ct 947 -90 965 -100 979 -114 ct +998 -133 1012 -158 1023 -190 ct 1034 -222 1039 -261 1039 -307 ct 1039 -370 1028 -419 1008 -453 ct +987 -487 962 -510 932 -521 ct 910 -530 876 -534 828 -534 ct 701 -534 l p ef +1661 -212 m 1741 -192 l 1724 -126 1694 -76 1650 -41 ct 1607 -6 1553 10 1490 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -554 1345 -579 ct 1389 -603 1438 -615 1491 -615 ct +1552 -615 1603 -600 1644 -569 ct 1686 -538 1714 -495 1731 -439 ct 1652 -420 l +1638 -465 1617 -497 1591 -517 ct 1564 -537 1530 -547 1490 -547 ct 1443 -547 1404 -536 1373 -513 ct +1342 -491 1320 -461 1307 -424 ct 1295 -386 1288 -347 1288 -307 ct 1288 -256 1296 -211 1311 -172 ct +1326 -134 1349 -105 1381 -86 ct 1412 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -122 l 1650 -161 l p ef +pom +gr +13955 5080 m 11733 5080 l 11733 1270 l 16178 1270 l 16178 5080 l 13955 5080 l +pc +gs +pum +13176 2513 t +69 0 m 69 -605 l 477 -605 l 477 -534 l 149 -534 l 149 -346 l 433 -346 l +433 -275 l 149 -275 l 149 0 l p ef +532 0 m 766 -315 l 560 -605 l 655 -605 l 765 -450 l 788 -418 804 -393 814 -375 ct +827 -397 843 -420 862 -444 ct 984 -605 l 1071 -605 l 858 -320 l 1087 0 l +988 0 l 836 -216 l 827 -228 818 -241 809 -256 ct 796 -234 786 -219 780 -211 ct +628 0 l p ef +1510 -71 m 1510 0 l 1110 0 l 1110 -17 1112 -35 1119 -51 ct 1129 -78 1145 -105 1168 -132 ct +1190 -158 1223 -189 1265 -223 ct 1331 -277 1375 -320 1398 -352 ct 1422 -383 1433 -413 1433 -441 ct +1433 -471 1423 -495 1402 -516 ct 1380 -536 1353 -546 1319 -546 ct 1283 -546 1255 -535 1233 -514 ct +1212 -492 1201 -463 1201 -425 ct 1124 -432 l 1129 -489 1149 -533 1183 -563 ct +1217 -593 1263 -608 1321 -608 ct 1379 -608 1425 -591 1459 -559 ct 1493 -527 1510 -487 1510 -439 ct +1510 -415 1505 -391 1495 -368 ct 1485 -345 1468 -320 1445 -294 ct 1422 -268 1384 -233 1331 -187 ct +1286 -150 1257 -125 1245 -111 ct 1232 -98 1222 -84 1213 -71 ct p ef +pom +pum +12713 3466 t +462 -605 m 542 -605 l 542 -255 l 542 -194 535 -146 522 -110 ct 508 -74 483 -45 447 -23 ct +411 0 364 10 306 10 ct 249 10 202 0 166 -19 ct 130 -38 105 -66 89 -103 ct 74 -140 66 -191 66 -255 ct +66 -605 l 146 -605 l 146 -256 l 146 -203 151 -164 161 -139 ct 171 -114 187 -95 211 -82 ct +235 -68 264 -61 299 -61 ct 358 -61 400 -75 425 -102 ct 450 -128 462 -180 462 -256 ct +p ef +673 -194 m 748 -201 l 752 -170 760 -146 773 -126 ct 786 -107 806 -91 834 -79 ct +862 -67 893 -61 927 -61 ct 958 -61 985 -66 1008 -75 ct 1031 -84 1049 -96 1060 -112 ct +1072 -128 1077 -145 1077 -164 ct 1077 -183 1072 -200 1061 -214 ct 1050 -228 1032 -240 1006 -249 ct +990 -256 954 -266 898 -279 ct 843 -292 804 -305 782 -317 ct 753 -332 731 -351 717 -373 ct +703 -396 696 -421 696 -449 ct 696 -479 704 -508 722 -534 ct 739 -561 764 -581 798 -595 ct +831 -609 868 -615 909 -615 ct 954 -615 993 -608 1028 -594 ct 1062 -579 1088 -558 1107 -530 ct +1125 -502 1135 -470 1136 -434 ct 1060 -429 l 1055 -467 1041 -496 1018 -515 ct +994 -535 959 -545 912 -545 ct 864 -545 828 -536 806 -518 ct 784 -500 773 -479 773 -454 ct +773 -432 781 -414 796 -400 ct 812 -386 852 -372 917 -357 ct 982 -342 1027 -329 1051 -318 ct +1087 -302 1113 -282 1129 -257 ct 1146 -232 1155 -203 1155 -171 ct 1155 -138 1145 -108 1127 -79 ct +1108 -51 1082 -29 1047 -13 ct 1013 2 974 10 931 10 ct 876 10 830 2 793 -13 ct 756 -29 727 -53 706 -85 ct +685 -117 l 674 -154 l p ef +1278 0 m 1278 -605 l 1506 -605 l 1552 -605 1589 -599 1617 -587 ct 1645 -574 1667 -556 1683 -530 ct +1699 -505 1706 -478 1706 -450 ct 1706 -424 1699 -400 1685 -377 ct 1671 -354 1650 -336 1622 -322 ct +1658 -311 1687 -293 1706 -267 ct 1726 -241 1736 -210 1736 -175 ct 1736 -147 1730 -120 1718 -96 ct +1706 -72 1691 -53 1673 -40 ct 1656 -26 1634 -16 1607 -10 ct 1580 -3 1548 0 1509 0 ct +p +1359 -351 m 1490 -351 l 1525 -351 1551 -353 1566 -358 ct 1586 -364 1602 -374 1612 -388 ct +1622 -402 1628 -419 1628 -441 ct 1628 -461 1623 -478 1613 -494 ct 1603 -509 1590 -520 1572 -525 ct +1554 -531 1523 -534 1480 -534 ct 1359 -534 l p +1359 -71 m 1509 -71 l 1535 -71 1553 -72 1564 -74 ct 1582 -77 1598 -83 1610 -90 ct +1623 -98 1633 -109 1641 -124 ct 1649 -139 1653 -156 1653 -175 ct 1653 -198 1647 -217 1635 -234 ct +1624 -251 1608 -262 1587 -269 ct 1567 -276 1537 -279 1499 -279 ct 1359 -279 l +p ef +2436 -71 m 2436 0 l 2036 0 l 2036 -17 2038 -35 2045 -51 ct 2055 -78 2071 -105 2094 -132 ct +2116 -158 2149 -189 2191 -223 ct 2257 -277 2301 -320 2324 -352 ct 2348 -383 2359 -413 2359 -441 ct +2359 -471 2349 -495 2328 -516 ct 2306 -536 2279 -546 2245 -546 ct 2209 -546 2181 -535 2159 -514 ct +2138 -492 2127 -463 2127 -425 ct 2050 -432 l 2055 -489 2075 -533 2109 -563 ct +2143 -593 2189 -608 2247 -608 ct 2305 -608 2351 -591 2385 -559 ct 2419 -527 2436 -487 2436 -439 ct +2436 -415 2431 -391 2421 -368 ct 2411 -345 2394 -320 2371 -294 ct 2348 -268 2310 -233 2257 -187 ct +2212 -150 2183 -125 2171 -111 ct 2158 -98 2148 -84 2139 -71 ct p ef +pom +pum +12091 4419 t +497 -212 m 577 -192 l 560 -126 530 -76 486 -41 ct 443 -6 389 10 326 10 ct +261 10 208 -2 167 -29 ct 126 -56 95 -94 74 -145 ct 52 -195 42 -249 42 -307 ct 42 -370 54 -425 78 -472 ct +102 -519 136 -554 181 -579 ct 225 -603 274 -615 327 -615 ct 388 -615 439 -600 480 -569 ct +522 -538 550 -495 567 -439 ct 488 -420 l 474 -465 453 -497 427 -517 ct 400 -537 366 -547 326 -547 ct +279 -547 240 -536 209 -513 ct 178 -491 156 -461 143 -424 ct 131 -386 124 -347 124 -307 ct +124 -256 132 -211 147 -172 ct 162 -134 185 -105 217 -86 ct 248 -67 283 -58 320 -58 ct +365 -58 403 -71 434 -97 ct 465 -122 l 486 -161 l p ef +663 -219 m 663 -300 685 -360 730 -399 ct 768 -432 814 -448 868 -448 ct 929 -448 978 -428 1016 -389 ct +1054 -349 1074 -295 1074 -225 ct 1074 -169 1065 -124 1048 -92 ct 1031 -59 1007 -34 974 -16 ct +942 0 907 9 868 9 ct 807 9 757 -9 719 -49 ct 682 -88 l 663 -145 l p +739 -219 m 739 -163 751 -121 776 -93 ct 800 -65 831 -51 868 -51 ct 905 -51 936 -65 960 -93 ct +985 -121 997 -164 997 -221 ct 997 -276 985 -317 960 -345 ct 936 -373 905 -387 868 -387 ct +831 -387 800 -373 776 -345 ct 751 -317 l 739 -275 l p ef +1166 0 m 1166 -438 l 1233 -438 l 1233 -376 l 1265 -424 1312 -448 1373 -448 ct +1399 -448 1424 -443 1446 -434 ct 1468 -424 1484 -412 1495 -396 ct 1507 -381 1514 -363 1519 -342 ct +1521 -328 1523 -304 1523 -269 ct 1523 0 l 1448 0 l 1448 -266 l 1448 -297 1446 -319 1440 -334 ct +1434 -349 1424 -361 1409 -370 ct 1394 -379 1377 -384 1357 -384 ct 1325 -384 1298 -374 1275 -354 ct +1252 -333 1241 -295 1241 -239 ct 1241 0 l p ef +1806 -66 m 1816 0 l 1795 3 1777 5 1760 5 ct 1733 5 1712 1 1697 -7 ct 1683 -15 1672 -26 1666 -40 ct +1660 -54 1657 -83 1657 -128 ct 1657 -380 l 1602 -380 l 1602 -438 l 1657 -438 l +1657 -547 l 1731 -591 l 1731 -438 l 1806 -438 l 1806 -380 l 1731 -380 l +1731 -124 l 1731 -103 1732 -89 1735 -83 ct 1737 -77 1742 -72 1748 -68 ct 1753 -65 1762 -63 1773 -63 ct +1781 -63 l 1792 -64 l p ef +1880 0 m 1880 -438 l 1947 -438 l 1947 -372 l 1964 -403 1980 -423 1995 -433 ct +2009 -443 2025 -448 2042 -448 ct 2067 -448 2093 -440 2119 -424 ct 2093 -355 l +2075 -366 2057 -371 2039 -371 ct 2022 -371 2008 -366 1995 -357 ct 1982 -347 1973 -333 1967 -316 ct +1959 -289 1955 -261 1955 -229 ct 1955 0 l p ef +2145 -219 m 2145 -300 2167 -360 2212 -399 ct 2250 -432 2296 -448 2350 -448 ct +2411 -448 2460 -428 2498 -389 ct 2536 -349 2556 -295 2556 -225 ct 2556 -169 2547 -124 2530 -92 ct +2513 -59 2489 -34 2456 -16 ct 2424 0 2389 9 2350 9 ct 2289 9 2239 -9 2201 -49 ct +2164 -88 l 2145 -145 l p +2221 -219 m 2221 -163 2233 -121 2258 -93 ct 2282 -65 2313 -51 2350 -51 ct 2387 -51 2418 -65 2442 -93 ct +2467 -121 2479 -164 2479 -221 ct 2479 -276 2467 -317 2442 -345 ct 2418 -373 2387 -387 2350 -387 ct +2313 -387 2282 -373 2258 -345 ct 2233 -317 l 2221 -275 l p ef +2647 0 m 2647 -605 l 2721 -605 l 2721 0 l p ef +2832 0 m 2832 -605 l 2906 -605 l 2906 0 l p ef +3319 -141 m 3395 -131 l 3383 -86 3361 -52 3328 -27 ct 3295 -2 3253 9 3203 9 ct +3138 9 3087 -9 3050 -49 ct 3012 -88 2993 -144 2993 -215 ct 2993 -289 3012 -346 3050 -387 ct +3089 -428 3138 -448 3198 -448 ct 3257 -448 3305 -428 3342 -388 ct 3379 -348 3398 -292 3398 -220 ct +3398 -215 3398 -209 3397 -200 ct 3070 -200 l 3073 -152 3087 -115 3111 -89 ct +3136 -64 3166 -51 3203 -51 ct 3230 -51 3253 -58 3273 -72 ct 3292 -87 l 3307 -109 l +p +3074 -261 m 3319 -261 l 3316 -298 3307 -326 3291 -344 ct 3268 -373 3237 -387 3199 -387 ct +3165 -387 3136 -376 3113 -353 ct 3090 -330 l 3077 -299 l p ef +3494 0 m 3494 -438 l 3561 -438 l 3561 -372 l 3578 -403 3594 -423 3609 -433 ct +3623 -443 3639 -448 3656 -448 ct 3681 -448 3707 -440 3733 -424 ct 3707 -355 l +3689 -366 3671 -371 3653 -371 ct 3636 -371 3622 -366 3609 -357 ct 3596 -347 3587 -333 3581 -316 ct +3573 -289 3569 -261 3569 -229 ct 3569 0 l p ef +pom +gr +13956 19115 m 11900 19115 l 11900 6350 l 16013 6350 l 16013 19115 l +13956 19115 l pc +gs +pum +12806 13017 t +69 0 m 69 -605 l 477 -605 l 477 -534 l 149 -534 l 149 -346 l 433 -346 l +433 -275 l 149 -275 l 149 0 l p ef +594 0 m 594 -605 l 822 -605 l 862 -605 893 -603 914 -599 ct 944 -594 969 -585 989 -571 ct +1009 -557 1025 -538 1038 -513 ct 1050 -488 1056 -460 1056 -430 ct 1056 -378 1040 -335 1007 -299 ct +974 -264 915 -246 829 -246 ct 674 -246 l 674 0 l p +674 -317 m 830 -317 l 882 -317 919 -327 941 -346 ct 963 -365 973 -392 973 -427 ct +973 -453 967 -474 954 -493 ct 941 -511 925 -522 904 -528 ct 890 -532 865 -534 829 -534 ct +674 -534 l p ef +1433 -237 m 1433 -308 l 1690 -308 l 1690 -84 l 1650 -52 1610 -29 1568 -13 ct +1526 2 1483 10 1439 10 ct 1379 10 1325 -2 1277 -27 ct 1228 -53 1191 -90 1167 -138 ct +1142 -186 1130 -240 1130 -299 ct 1130 -358 1142 -413 1167 -464 ct 1191 -516 1227 -553 1273 -578 ct +1319 -603 1372 -615 1433 -615 ct 1477 -615 1516 -608 1551 -594 ct 1587 -580 1615 -560 1635 -535 ct +1655 -510 1670 -476 1681 -436 ct 1608 -416 l 1599 -447 1588 -471 1574 -489 ct +1561 -506 1542 -520 1517 -531 ct 1492 -542 1464 -547 1433 -547 ct 1397 -547 1365 -541 1338 -530 ct +1311 -519 1290 -504 1273 -486 ct 1257 -468 1244 -448 1235 -426 ct 1220 -389 1212 -348 1212 -304 ct +1212 -250 1221 -205 1240 -169 ct 1259 -133 1286 -106 1321 -88 ct 1357 -70 1394 -61 1434 -61 ct +1469 -61 1503 -68 1536 -82 ct 1569 -95 1594 -109 1611 -124 ct 1611 -237 l p ef +1745 0 m 1977 -605 l 2063 -605 l 2311 0 l 2220 0 l 2149 -183 l 1896 -183 l +1829 0 l p +1919 -248 m 2124 -248 l 2061 -416 l 2042 -467 2028 -509 2018 -541 ct 2010 -503 2000 -464 1986 -426 ct +p ef +pom +gr +0.996 c 7835 17258 m 8893 16305 l 11010 16305 l 11010 18210 l 8893 18210 l +7835 17258 l p ef +0.000 c 7835 17258 m 8893 16305 l 11010 16305 l 11010 18210 l 8893 18210 l +7835 17258 l pc +gs +pum +8520 17542 t +65 0 m 65 -605 l 273 -605 l 320 -605 356 -602 381 -596 ct 416 -588 445 -574 470 -553 ct +502 -526 526 -492 542 -450 ct 558 -408 565 -360 565 -306 ct 565 -260 560 -219 549 -183 ct +539 -148 525 -118 508 -95 ct 491 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +352 -3 320 0 283 0 ct p +145 -71 m 274 -71 l 314 -71 345 -75 368 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 456 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -370 472 -419 452 -453 ct +431 -487 406 -510 376 -521 ct 354 -530 320 -534 272 -534 ct 145 -534 l p ef +608 0 m 840 -605 l 926 -605 l 1174 0 l 1083 0 l 1012 -183 l 759 -183 l +692 0 l p +782 -248 m 987 -248 l 924 -416 l 905 -467 891 -509 881 -541 ct 873 -503 863 -464 849 -426 ct +p ef +1661 -212 m 1741 -192 l 1724 -126 1694 -76 1650 -41 ct 1607 -6 1553 10 1490 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -554 1345 -579 ct 1389 -603 1438 -615 1491 -615 ct +1552 -615 1603 -600 1644 -569 ct 1686 -538 1714 -495 1731 -439 ct 1652 -420 l +1638 -465 1617 -497 1591 -517 ct 1564 -537 1530 -547 1490 -547 ct 1443 -547 1404 -536 1373 -513 ct +1342 -491 1320 -461 1307 -424 ct 1295 -386 1288 -347 1288 -307 ct 1288 -256 1296 -211 1311 -172 ct +1326 -134 1349 -105 1381 -86 ct 1412 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -122 l 1650 -161 l p ef +pom +gr +0.996 c 7835 10478 m 8893 9525 l 11010 9525 l 11010 11430 l 8893 11430 l +7835 10478 l p ef +0.000 c 7835 10478 m 8893 9525 l 11010 9525 l 11010 11430 l 8893 11430 l +7835 10478 l pc +gs +pum +8520 10768 t +-1 0 m 231 -605 l 317 -605 l 565 0 l 474 0 l 403 -183 l 150 -183 l +83 0 l p +173 -248 m 378 -248 l 315 -416 l 296 -467 282 -509 272 -541 ct 264 -503 254 -464 240 -426 ct +p ef +621 0 m 621 -605 l 829 -605 l 876 -605 912 -602 937 -596 ct 972 -588 1001 -574 1026 -553 ct +1058 -526 1082 -492 1098 -450 ct 1114 -408 1121 -360 1121 -306 ct 1121 -260 1116 -219 1105 -183 ct +1095 -148 1081 -118 1064 -95 ct 1047 -72 1029 -54 1009 -40 ct 989 -27 965 -17 937 -10 ct +908 -3 876 0 839 0 ct p +701 -71 m 830 -71 l 870 -71 901 -75 924 -82 ct 947 -90 965 -100 979 -114 ct +998 -133 1012 -158 1023 -190 ct 1034 -222 1039 -261 1039 -307 ct 1039 -370 1028 -419 1008 -453 ct +987 -487 962 -510 932 -521 ct 910 -530 876 -534 828 -534 ct 701 -534 l p ef +1661 -212 m 1741 -192 l 1724 -126 1694 -76 1650 -41 ct 1607 -6 1553 10 1490 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -554 1345 -579 ct 1389 -603 1438 -615 1491 -615 ct +1552 -615 1603 -600 1644 -569 ct 1686 -538 1714 -495 1731 -439 ct 1652 -420 l +1638 -465 1617 -497 1591 -517 ct 1564 -537 1530 -547 1490 -547 ct 1443 -547 1404 -536 1373 -513 ct +1342 -491 1320 -461 1307 -424 ct 1295 -386 1288 -347 1288 -307 ct 1288 -256 1296 -211 1311 -172 ct +1326 -134 1349 -105 1381 -86 ct 1412 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -122 l 1650 -161 l p ef +pom +gr +0.996 c 7835 14618 m 8893 13665 l 11010 13665 l 11010 15570 l 8893 15570 l +7835 14618 l p ef +0.000 c 7835 14618 m 8893 13665 l 11010 13665 l 11010 15570 l 8893 15570 l +7835 14618 l pc +gs +pum +8520 14896 t +65 0 m 65 -605 l 273 -605 l 320 -605 356 -602 381 -596 ct 416 -588 445 -574 470 -553 ct +502 -526 526 -492 542 -450 ct 558 -408 565 -360 565 -306 ct 565 -260 560 -219 549 -183 ct +539 -148 525 -118 508 -95 ct 491 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +352 -3 320 0 283 0 ct p +145 -71 m 274 -71 l 314 -71 345 -75 368 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 456 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -370 472 -419 452 -453 ct +431 -487 406 -510 376 -521 ct 354 -530 320 -534 272 -534 ct 145 -534 l p ef +608 0 m 840 -605 l 926 -605 l 1174 0 l 1083 0 l 1012 -183 l 759 -183 l +692 0 l p +782 -248 m 987 -248 l 924 -416 l 905 -467 891 -509 881 -541 ct 873 -503 863 -464 849 -426 ct +p ef +1661 -212 m 1741 -192 l 1724 -126 1694 -76 1650 -41 ct 1607 -6 1553 10 1490 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -554 1345 -579 ct 1389 -603 1438 -615 1491 -615 ct +1552 -615 1603 -600 1644 -569 ct 1686 -538 1714 -495 1731 -439 ct 1652 -420 l +1638 -465 1617 -497 1591 -517 ct 1564 -537 1530 -547 1490 -547 ct 1443 -547 1404 -536 1373 -513 ct +1342 -491 1320 -461 1307 -424 ct 1295 -386 1288 -347 1288 -307 ct 1288 -256 1296 -211 1311 -172 ct +1326 -134 1349 -105 1381 -86 ct 1412 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -122 l 1650 -161 l p ef +pom +gr +0.996 c 19984 7938 m 18926 6985 l 16809 6985 l 16809 8890 l 18926 8890 l +19984 7938 l p ef +0.000 c 19984 7938 m 18926 6985 l 16809 6985 l 16809 8890 l 18926 8890 l +19984 7938 l pc +gs +pum +17489 8228 t +-1 0 m 231 -605 l 317 -605 l 565 0 l 474 0 l 403 -183 l 150 -183 l +83 0 l p +173 -248 m 378 -248 l 315 -416 l 296 -467 282 -509 272 -541 ct 264 -503 254 -464 240 -426 ct +p ef +621 0 m 621 -605 l 829 -605 l 876 -605 912 -602 937 -596 ct 972 -588 1001 -574 1026 -553 ct +1058 -526 1082 -492 1098 -450 ct 1114 -408 1121 -360 1121 -306 ct 1121 -260 1116 -219 1105 -183 ct +1095 -148 1081 -118 1064 -95 ct 1047 -72 1029 -54 1009 -40 ct 989 -27 965 -17 937 -10 ct +908 -3 876 0 839 0 ct p +701 -71 m 830 -71 l 870 -71 901 -75 924 -82 ct 947 -90 965 -100 979 -114 ct +998 -133 1012 -158 1023 -190 ct 1034 -222 1039 -261 1039 -307 ct 1039 -370 1028 -419 1008 -453 ct +987 -487 962 -510 932 -521 ct 910 -530 876 -534 828 -534 ct 701 -534 l p ef +1661 -212 m 1741 -192 l 1724 -126 1694 -76 1650 -41 ct 1607 -6 1553 10 1490 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -554 1345 -579 ct 1389 -603 1438 -615 1491 -615 ct +1552 -615 1603 -600 1644 -569 ct 1686 -538 1714 -495 1731 -439 ct 1652 -420 l +1638 -465 1617 -497 1591 -517 ct 1564 -537 1530 -547 1490 -547 ct 1443 -547 1404 -536 1373 -513 ct +1342 -491 1320 -461 1307 -424 ct 1295 -386 1288 -347 1288 -307 ct 1288 -256 1296 -211 1311 -172 ct +1326 -134 1349 -105 1381 -86 ct 1412 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -122 l 1650 -161 l p ef +pom +gr +0.996 c 19984 17258 m 18926 16305 l 16809 16305 l 16809 18210 l 18926 18210 l +19984 17258 l p ef +0.000 c 19984 17258 m 18926 16305 l 16809 16305 l 16809 18210 l 18926 18210 l +19984 17258 l pc +gs +pum +17489 17542 t +65 0 m 65 -605 l 273 -605 l 320 -605 356 -602 381 -596 ct 416 -588 445 -574 470 -553 ct +502 -526 526 -492 542 -450 ct 558 -408 565 -360 565 -306 ct 565 -260 560 -219 549 -183 ct +539 -148 525 -118 508 -95 ct 491 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +352 -3 320 0 283 0 ct p +145 -71 m 274 -71 l 314 -71 345 -75 368 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 456 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -370 472 -419 452 -453 ct +431 -487 406 -510 376 -521 ct 354 -530 320 -534 272 -534 ct 145 -534 l p ef +608 0 m 840 -605 l 926 -605 l 1174 0 l 1083 0 l 1012 -183 l 759 -183 l +692 0 l p +782 -248 m 987 -248 l 924 -416 l 905 -467 891 -509 881 -541 ct 873 -503 863 -464 849 -426 ct +p ef +1661 -212 m 1741 -192 l 1724 -126 1694 -76 1650 -41 ct 1607 -6 1553 10 1490 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -554 1345 -579 ct 1389 -603 1438 -615 1491 -615 ct +1552 -615 1603 -600 1644 -569 ct 1686 -538 1714 -495 1731 -439 ct 1652 -420 l +1638 -465 1617 -497 1591 -517 ct 1564 -537 1530 -547 1490 -547 ct 1443 -547 1404 -536 1373 -513 ct +1342 -491 1320 -461 1307 -424 ct 1295 -386 1288 -347 1288 -307 ct 1288 -256 1296 -211 1311 -172 ct +1326 -134 1349 -105 1381 -86 ct 1412 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -122 l 1650 -161 l p ef +pom +gr +0.996 c 19984 10478 m 18926 9525 l 16809 9525 l 16809 11430 l 18926 11430 l +19984 10478 l p ef +0.000 c 19984 10478 m 18926 9525 l 16809 9525 l 16809 11430 l 18926 11430 l +19984 10478 l pc +gs +pum +17489 10768 t +-1 0 m 231 -605 l 317 -605 l 565 0 l 474 0 l 403 -183 l 150 -183 l +83 0 l p +173 -248 m 378 -248 l 315 -416 l 296 -467 282 -509 272 -541 ct 264 -503 254 -464 240 -426 ct +p ef +621 0 m 621 -605 l 829 -605 l 876 -605 912 -602 937 -596 ct 972 -588 1001 -574 1026 -553 ct +1058 -526 1082 -492 1098 -450 ct 1114 -408 1121 -360 1121 -306 ct 1121 -260 1116 -219 1105 -183 ct +1095 -148 1081 -118 1064 -95 ct 1047 -72 1029 -54 1009 -40 ct 989 -27 965 -17 937 -10 ct +908 -3 876 0 839 0 ct p +701 -71 m 830 -71 l 870 -71 901 -75 924 -82 ct 947 -90 965 -100 979 -114 ct +998 -133 1012 -158 1023 -190 ct 1034 -222 1039 -261 1039 -307 ct 1039 -370 1028 -419 1008 -453 ct +987 -487 962 -510 932 -521 ct 910 -530 876 -534 828 -534 ct 701 -534 l p ef +1661 -212 m 1741 -192 l 1724 -126 1694 -76 1650 -41 ct 1607 -6 1553 10 1490 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -554 1345 -579 ct 1389 -603 1438 -615 1491 -615 ct +1552 -615 1603 -600 1644 -569 ct 1686 -538 1714 -495 1731 -439 ct 1652 -420 l +1638 -465 1617 -497 1591 -517 ct 1564 -537 1530 -547 1490 -547 ct 1443 -547 1404 -536 1373 -513 ct +1342 -491 1320 -461 1307 -424 ct 1295 -386 1288 -347 1288 -307 ct 1288 -256 1296 -211 1311 -172 ct +1326 -134 1349 -105 1381 -86 ct 1412 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -122 l 1650 -161 l p ef +pom +gr +0.996 c 19984 14618 m 18926 13665 l 16809 13665 l 16809 15570 l 18926 15570 l +19984 14618 l p ef +0.000 c 19984 14618 m 18926 13665 l 16809 13665 l 16809 15570 l 18926 15570 l +19984 14618 l pc +gs +pum +17489 14896 t +65 0 m 65 -605 l 273 -605 l 320 -605 356 -602 381 -596 ct 416 -588 445 -574 470 -553 ct +502 -526 526 -492 542 -450 ct 558 -408 565 -360 565 -306 ct 565 -260 560 -219 549 -183 ct +539 -148 525 -118 508 -95 ct 491 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +352 -3 320 0 283 0 ct p +145 -71 m 274 -71 l 314 -71 345 -75 368 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 456 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -370 472 -419 452 -453 ct +431 -487 406 -510 376 -521 ct 354 -530 320 -534 272 -534 ct 145 -534 l p ef +608 0 m 840 -605 l 926 -605 l 1174 0 l 1083 0 l 1012 -183 l 759 -183 l +692 0 l p +782 -248 m 987 -248 l 924 -416 l 905 -467 891 -509 881 -541 ct 873 -503 863 -464 849 -426 ct +p ef +1661 -212 m 1741 -192 l 1724 -126 1694 -76 1650 -41 ct 1607 -6 1553 10 1490 10 ct +1425 10 1372 -2 1331 -29 ct 1290 -56 1259 -94 1238 -145 ct 1216 -195 1206 -249 1206 -307 ct +1206 -370 1218 -425 1242 -472 ct 1266 -519 1300 -554 1345 -579 ct 1389 -603 1438 -615 1491 -615 ct +1552 -615 1603 -600 1644 -569 ct 1686 -538 1714 -495 1731 -439 ct 1652 -420 l +1638 -465 1617 -497 1591 -517 ct 1564 -537 1530 -547 1490 -547 ct 1443 -547 1404 -536 1373 -513 ct +1342 -491 1320 -461 1307 -424 ct 1295 -386 1288 -347 1288 -307 ct 1288 -256 1296 -211 1311 -172 ct +1326 -134 1349 -105 1381 -86 ct 1412 -67 1447 -58 1484 -58 ct 1529 -58 1567 -71 1598 -97 ct +1629 -122 l 1650 -161 l p ef +pom +gr +23767 18828 m 20592 18828 l 20592 13113 l 26942 13113 l 26942 18828 l +23767 18828 l pc +gs +pum +22133 15795 t +219 0 m 219 -534 l 19 -534 l 19 -605 l 499 -605 l 499 -534 l 299 -534 l +299 0 l p ef +583 0 m 583 -438 l 650 -438 l 650 -372 l 667 -403 683 -423 698 -433 ct +712 -443 728 -448 745 -448 ct 770 -448 796 -440 822 -424 ct 796 -355 l 778 -366 760 -371 742 -371 ct +725 -371 711 -366 698 -357 ct 685 -347 676 -333 670 -316 ct 662 -289 658 -261 658 -229 ct +658 0 l p ef +1162 -54 m 1134 -30 1108 -14 1082 -4 ct 1057 5 1029 9 1000 9 ct 952 9 915 -1 889 -25 ct +863 -48 850 -79 850 -115 ct 850 -137 855 -156 865 -174 ct 875 -192 887 -206 903 -217 ct +919 -228 937 -236 957 -241 ct 971 -245 993 -249 1023 -252 ct 1083 -259 1127 -268 1155 -278 ct +1156 -288 1156 -295 1156 -297 ct 1156 -328 1149 -349 1135 -361 ct 1116 -378 1087 -387 1050 -387 ct +1015 -387 989 -380 973 -368 ct 956 -356 944 -334 936 -303 ct 863 -313 l 869 -344 880 -369 896 -388 ct +911 -408 933 -422 961 -433 ct 990 -443 1023 -448 1061 -448 ct 1098 -448 1129 -444 1152 -435 ct +1175 -426 1193 -415 1204 -402 ct 1215 -388 1222 -371 1227 -351 ct 1229 -338 1231 -316 1231 -282 ct +1231 -183 l 1231 -114 1232 -70 1235 -52 ct 1238 -34 1245 -16 1254 0 ct 1176 0 l +1169 -15 l 1164 -33 l p +1155 -220 m 1128 -209 1088 -199 1034 -192 ct 1003 -187 982 -182 969 -177 ct +956 -171 947 -163 940 -153 ct 933 -142 929 -130 929 -117 ct 929 -97 937 -81 952 -68 ct +967 -54 989 -48 1018 -48 ct 1046 -48 1072 -54 1094 -67 ct 1117 -79 1133 -96 1143 -118 ct +1151 -135 1155 -160 1155 -192 ct p ef +1325 0 m 1325 -438 l 1392 -438 l 1392 -376 l 1424 -424 1471 -448 1532 -448 ct +1558 -448 1583 -443 1605 -434 ct 1627 -424 1643 -412 1654 -396 ct 1666 -381 1673 -363 1678 -342 ct +1680 -328 1682 -304 1682 -269 ct 1682 0 l 1607 0 l 1607 -266 l 1607 -297 1605 -319 1599 -334 ct +1593 -349 1583 -361 1568 -370 ct 1553 -379 1536 -384 1516 -384 ct 1484 -384 1457 -374 1434 -354 ct +1411 -333 1400 -295 1400 -239 ct 1400 0 l p ef +1772 -130 m 1845 -142 l 1849 -113 1861 -90 1880 -74 ct 1898 -59 1925 -51 1959 -51 ct +1993 -51 2018 -58 2035 -72 ct 2051 -85 2059 -102 2059 -121 ct 2059 -137 2052 -151 2038 -160 ct +2027 -167 2002 -175 1962 -185 ct 1907 -199 1869 -211 1848 -221 ct 1827 -231 1811 -245 1800 -263 ct +1789 -281 1784 -300 1784 -322 ct 1784 -341 1788 -359 1797 -376 ct 1806 -393 1818 -407 1834 -418 ct +1845 -426 1861 -433 1881 -439 ct 1901 -445 1923 -448 1945 -448 ct 1980 -448 2010 -443 2036 -433 ct +2062 -423 2081 -410 2094 -393 ct 2106 -376 2115 -353 2119 -325 ct 2047 -315 l +2043 -338 2034 -355 2018 -368 ct 2002 -381 1980 -387 1951 -387 ct 1917 -387 1892 -381 1878 -370 ct +1863 -359 1856 -346 1856 -330 ct 1856 -321 1859 -312 1865 -304 ct 1871 -296 1880 -290 1893 -285 ct +1901 -282 1923 -275 1959 -266 ct 2012 -251 2048 -240 2069 -231 ct 2090 -222 2106 -209 2118 -192 ct +2130 -175 2136 -154 2136 -128 ct 2136 -104 2129 -80 2114 -58 ct 2100 -36 2079 -20 2052 -8 ct +2024 3 1993 9 1959 9 ct 1902 9 1859 -1 1829 -25 ct 1799 -49 l 1780 -84 l p ef +2198 0 m 2198 -438 l 2265 -438 l 2265 -377 l 2279 -398 2297 -415 2320 -428 ct +2343 -442 2369 -448 2398 -448 ct 2430 -448 2457 -441 2478 -428 ct 2499 -414 2513 -396 2522 -371 ct +2556 -423 2602 -448 2657 -448 ct 2701 -448 2734 -436 2758 -412 ct 2781 -388 2793 -351 2793 -301 ct +2793 0 l 2719 0 l 2719 -276 l 2719 -306 2716 -327 2712 -340 ct 2707 -353 2698 -364 2685 -372 ct +2673 -380 2658 -384 2641 -384 ct 2610 -384 2584 -373 2564 -353 ct 2543 -332 2533 -300 2533 -254 ct +2533 0 l 2459 0 l 2459 -285 l 2459 -318 2453 -342 2441 -359 ct 2429 -375 2409 -384 2381 -384 ct +2360 -384 2341 -378 2323 -367 ct 2305 -356 2293 -340 2285 -319 ct 2277 -298 2273 -267 2273 -227 ct +2273 0 l p ef +2914 -520 m 2914 -605 l 2988 -605 l 2988 -520 l p +2914 0 m 2914 -438 l 2988 -438 l 2988 0 l p ef +3261 -66 m 3271 0 l 3250 3 3232 5 3215 5 ct 3188 5 3167 1 3152 -7 ct 3138 -15 3127 -26 3121 -40 ct +3115 -54 3112 -83 3112 -128 ct 3112 -380 l 3057 -380 l 3057 -438 l 3112 -438 l +3112 -547 l 3186 -591 l 3186 -438 l 3261 -438 l 3261 -380 l 3186 -380 l +3186 -124 l 3186 -103 3187 -89 3190 -83 ct 3192 -77 3197 -72 3203 -68 ct 3208 -65 3217 -63 3228 -63 ct +3236 -63 l 3247 -64 l p ef +pom +pum +20955 16748 t +65 0 m 65 -605 l 273 -605 l 320 -605 356 -602 381 -596 ct 416 -588 445 -574 470 -553 ct +502 -526 526 -492 542 -450 ct 558 -408 565 -360 565 -306 ct 565 -260 560 -219 549 -183 ct +539 -148 525 -118 508 -95 ct 491 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +352 -3 320 0 283 0 ct p +145 -71 m 274 -71 l 314 -71 345 -75 368 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 456 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -370 472 -419 452 -453 ct +431 -487 406 -510 376 -521 ct 354 -530 320 -534 272 -534 ct 145 -534 l p ef +951 -54 m 923 -30 897 -14 871 -4 ct 846 5 818 9 789 9 ct 741 9 704 -1 678 -25 ct +652 -48 639 -79 639 -115 ct 639 -137 644 -156 654 -174 ct 664 -192 676 -206 692 -217 ct +708 -228 726 -236 746 -241 ct 760 -245 782 -249 812 -252 ct 872 -259 916 -268 944 -278 ct +945 -288 945 -295 945 -297 ct 945 -328 938 -349 924 -361 ct 905 -378 876 -387 839 -387 ct +804 -387 778 -380 762 -368 ct 745 -356 733 -334 725 -303 ct 652 -313 l 658 -344 669 -369 685 -388 ct +700 -408 722 -422 750 -433 ct 779 -443 812 -448 850 -448 ct 887 -448 918 -444 941 -435 ct +964 -426 982 -415 993 -402 ct 1004 -388 1011 -371 1016 -351 ct 1018 -338 1020 -316 1020 -282 ct +1020 -183 l 1020 -114 1021 -70 1024 -52 ct 1027 -34 1034 -16 1043 0 ct 965 0 l +958 -15 l 953 -33 l p +944 -220 m 917 -209 877 -199 823 -192 ct 792 -187 771 -182 758 -177 ct 745 -171 736 -163 729 -153 ct +722 -142 718 -130 718 -117 ct 718 -97 726 -81 741 -68 ct 756 -54 778 -48 807 -48 ct +835 -48 861 -54 883 -67 ct 906 -79 922 -96 932 -118 ct 940 -135 944 -160 944 -192 ct +p ef +1401 0 m 1401 -64 l 1367 -14 1320 9 1262 9 ct 1236 9 1212 4 1189 -4 ct 1167 -14 1150 -27 1139 -42 ct +1128 -57 1121 -75 1116 -97 ct 1113 -112 1112 -135 1112 -166 ct 1112 -438 l 1186 -438 l +1186 -195 l 1186 -156 1187 -130 1191 -116 ct 1195 -97 1205 -82 1220 -70 ct +1235 -59 1254 -54 1276 -54 ct 1299 -54 1320 -59 1339 -71 ct 1359 -82 1373 -98 1381 -117 ct +1389 -137 1393 -166 1393 -203 ct 1393 -438 l 1467 -438 l 1467 0 l p ef +1577 36 m 1649 47 l 1652 69 1660 85 1674 95 ct 1693 109 1718 116 1750 116 ct +1784 116 1811 109 1829 95 ct 1848 82 1861 62 1867 38 ct 1871 22 1873 -8 1873 -57 ct +1840 -19 1800 0 1751 0 ct 1691 0 1644 -21 1611 -65 ct 1578 -108 1562 -160 1562 -221 ct +1562 -263 1569 -302 1584 -337 ct 1600 -373 1622 -400 1650 -419 ct 1679 -438 1713 -448 1752 -448 ct +1804 -448 1846 -427 1880 -385 ct 1880 -438 l 1948 -438 l 1948 -59 l 1948 8 1941 57 1928 85 ct +1914 114 1892 136 1861 153 ct 1831 169 1794 178 1750 178 ct 1698 178 1656 166 1623 142 ct +1591 119 l 1576 83 l p +1638 -227 m 1638 -169 1650 -127 1672 -101 ct 1695 -74 1724 -61 1758 -61 ct +1793 -61 1821 -74 1844 -101 ct 1867 -127 1879 -168 1879 -224 ct 1879 -278 1867 -318 1843 -346 ct +1819 -373 1791 -387 1757 -387 ct 1724 -387 1696 -373 1673 -346 ct 1650 -319 l +1638 -280 l p ef +2066 0 m 2066 -605 l 2141 -605 l 2141 -388 l 2175 -428 2219 -448 2272 -448 ct +2304 -448 2333 -442 2357 -429 ct 2381 -416 2398 -398 2408 -376 ct 2418 -353 2424 -320 2424 -278 ct +2424 0 l 2349 0 l 2349 -278 l 2349 -315 2341 -342 2325 -359 ct 2309 -376 2286 -384 2257 -384 ct +2235 -384 2214 -378 2195 -367 ct 2175 -356 2161 -340 2153 -320 ct 2145 -301 2141 -274 2141 -240 ct +2141 0 l p ef +2705 -66 m 2715 0 l 2694 3 2676 5 2659 5 ct 2632 5 2611 1 2596 -7 ct 2582 -15 2571 -26 2565 -40 ct +2559 -54 2556 -83 2556 -128 ct 2556 -380 l 2501 -380 l 2501 -438 l 2556 -438 l +2556 -547 l 2630 -591 l 2630 -438 l 2705 -438 l 2705 -380 l 2630 -380 l +2630 -124 l 2630 -103 2631 -89 2634 -83 ct 2636 -77 2641 -72 2647 -68 ct 2652 -65 2661 -63 2672 -63 ct +2680 -63 l 2691 -64 l p ef +3081 -141 m 3157 -131 l 3145 -86 3123 -52 3090 -27 ct 3057 -2 3015 9 2965 9 ct +2900 9 2849 -9 2812 -49 ct 2774 -88 2755 -144 2755 -215 ct 2755 -289 2774 -346 2812 -387 ct +2851 -428 2900 -448 2960 -448 ct 3019 -448 3067 -428 3104 -388 ct 3141 -348 3160 -292 3160 -220 ct +3160 -215 3160 -209 3159 -200 ct 2832 -200 l 2835 -152 2849 -115 2873 -89 ct +2898 -64 2928 -51 2965 -51 ct 2992 -51 3015 -58 3035 -72 ct 3054 -87 l 3069 -109 l +p +2836 -261 m 3081 -261 l 3078 -298 3069 -326 3053 -344 ct 3030 -373 2999 -387 2961 -387 ct +2927 -387 2898 -376 2875 -353 ct 2852 -330 l 2839 -299 l p ef +3255 0 m 3255 -438 l 3322 -438 l 3322 -372 l 3339 -403 3355 -423 3370 -433 ct +3384 -443 3400 -448 3417 -448 ct 3442 -448 3468 -440 3494 -424 ct 3468 -355 l +3450 -366 3432 -371 3414 -371 ct 3397 -371 3383 -366 3370 -357 ct 3357 -347 3348 -333 3342 -316 ct +3334 -289 3330 -261 3330 -229 ct 3330 0 l p ef +3617 0 m 3548 0 l 3548 -605 l 3622 -605 l 3622 -389 l 3654 -428 3694 -448 3742 -448 ct +3769 -448 3795 -443 3819 -432 ct 3843 -421 3863 -406 3879 -386 ct 3894 -366 3906 -343 3915 -315 ct +3924 -287 3928 -257 3928 -225 ct 3928 -150 3910 -92 3873 -51 ct 3835 -10 3791 9 3739 9 ct +3687 9 3646 -11 3617 -54 ct p +3616 -222 m 3616 -170 3623 -132 3638 -108 ct 3661 -70 3693 -51 3733 -51 ct +3765 -51 3793 -65 3817 -93 ct 3840 -121 3852 -163 3852 -219 ct 3852 -277 3841 -319 3818 -346 ct +3796 -373 3768 -387 3736 -387 ct 3703 -387 3675 -373 3652 -345 ct 3628 -316 l +3616 -276 l p ef +3970 -219 m 3970 -300 3992 -360 4037 -399 ct 4075 -432 4121 -448 4175 -448 ct +4236 -448 4285 -428 4323 -389 ct 4361 -349 4381 -295 4381 -225 ct 4381 -169 4372 -124 4355 -92 ct +4338 -59 4314 -34 4281 -16 ct 4249 0 4214 9 4175 9 ct 4114 9 4064 -9 4026 -49 ct +3989 -88 l 3970 -145 l p +4046 -219 m 4046 -163 4058 -121 4083 -93 ct 4107 -65 4138 -51 4175 -51 ct 4212 -51 4243 -65 4267 -93 ct +4292 -121 4304 -164 4304 -221 ct 4304 -276 4292 -317 4267 -345 ct 4243 -373 4212 -387 4175 -387 ct +4138 -387 4107 -373 4083 -345 ct 4058 -317 l 4046 -275 l p ef +4761 -54 m 4733 -30 4707 -14 4681 -4 ct 4656 5 4628 9 4599 9 ct 4551 9 4514 -1 4488 -25 ct +4462 -48 4449 -79 4449 -115 ct 4449 -137 4454 -156 4464 -174 ct 4474 -192 4486 -206 4502 -217 ct +4518 -228 4536 -236 4556 -241 ct 4570 -245 4592 -249 4622 -252 ct 4682 -259 4726 -268 4754 -278 ct +4755 -288 4755 -295 4755 -297 ct 4755 -328 4748 -349 4734 -361 ct 4715 -378 4686 -387 4649 -387 ct +4614 -387 4588 -380 4572 -368 ct 4555 -356 4543 -334 4535 -303 ct 4462 -313 l +4468 -344 4479 -369 4495 -388 ct 4510 -408 4532 -422 4560 -433 ct 4589 -443 4622 -448 4660 -448 ct +4697 -448 4728 -444 4751 -435 ct 4774 -426 4792 -415 4803 -402 ct 4814 -388 4821 -371 4826 -351 ct +4828 -338 4830 -316 4830 -282 ct 4830 -183 l 4830 -114 4831 -70 4834 -52 ct +4837 -34 4844 -16 4853 0 ct 4775 0 l 4768 -15 l 4763 -33 l p +4754 -220 m 4727 -209 4687 -199 4633 -192 ct 4602 -187 4581 -182 4568 -177 ct +4555 -171 4546 -163 4539 -153 ct 4532 -142 4528 -130 4528 -117 ct 4528 -97 4536 -81 4551 -68 ct +4566 -54 4588 -48 4617 -48 ct 4645 -48 4671 -54 4693 -67 ct 4716 -79 4732 -96 4742 -118 ct +4750 -135 4754 -160 4754 -192 ct p ef +4922 0 m 4922 -438 l 4989 -438 l 4989 -372 l 5006 -403 5022 -423 5037 -433 ct +5051 -443 5067 -448 5084 -448 ct 5109 -448 5135 -440 5161 -424 ct 5135 -355 l +5117 -366 5099 -371 5081 -371 ct 5064 -371 5050 -366 5037 -357 ct 5024 -347 5015 -333 5009 -316 ct +5001 -289 4997 -261 4997 -229 ct 4997 0 l p ef +5499 0 m 5499 -55 l 5471 -11 5430 9 5376 9 ct 5341 9 5309 0 5280 -19 ct 5250 -38 5228 -65 5212 -99 ct +5195 -134 5187 -174 5187 -218 ct 5187 -262 5195 -302 5209 -338 ct 5224 -373 5246 -401 5275 -420 ct +5304 -439 5337 -448 5373 -448 ct 5399 -448 5423 -443 5444 -431 ct 5464 -420 5481 -406 5494 -388 ct +5494 -605 l 5568 -605 l 5568 0 l p +5264 -218 m 5264 -162 5276 -120 5299 -92 ct 5323 -65 5351 -51 5383 -51 ct 5416 -51 5443 -64 5466 -91 ct +5489 -117 5500 -158 5500 -212 ct 5500 -272 5489 -316 5465 -344 ct 5442 -373 5414 -387 5380 -387 ct +5347 -387 5319 -373 5297 -346 ct 5275 -319 l 5264 -277 l p ef +pom +gr +23767 12065 m 20592 12065 l 20592 6350 l 26942 6350 l 26942 12065 l +23767 12065 l pc +gs +pum +22239 9022 t +66 0 m 66 -605 l 335 -605 l 389 -605 430 -600 458 -589 ct 486 -578 508 -559 525 -531 ct +542 -504 550 -473 550 -440 ct 550 -397 536 -361 508 -331 ct 481 -302 438 -283 380 -275 ct +401 -265 417 -255 428 -245 ct 451 -223 473 -197 494 -164 ct 600 0 l 499 0 l +419 -125 l 395 -162 376 -190 361 -209 ct 346 -228 332 -242 320 -249 ct 308 -257 296 -263 284 -266 ct +275 -267 260 -268 239 -268 ct 146 -268 l 146 0 l p +146 -338 m 318 -338 l 355 -338 384 -342 404 -349 ct 425 -357 441 -369 451 -386 ct +462 -402 468 -420 468 -440 ct 468 -468 457 -492 436 -510 ct 416 -529 383 -538 338 -538 ct +146 -538 l p ef +965 -141 m 1041 -131 l 1029 -86 1007 -52 974 -27 ct 941 -2 899 9 849 9 ct +784 9 733 -9 696 -49 ct 658 -88 639 -144 639 -215 ct 639 -289 658 -346 696 -387 ct +735 -428 784 -448 844 -448 ct 903 -448 951 -428 988 -388 ct 1025 -348 1044 -292 1044 -220 ct +1044 -215 1044 -209 1043 -200 ct 716 -200 l 719 -152 733 -115 757 -89 ct 782 -64 812 -51 849 -51 ct +876 -51 899 -58 919 -72 ct 938 -87 l 953 -109 l p +720 -261 m 965 -261 l 962 -298 953 -326 937 -344 ct 914 -373 883 -387 845 -387 ct +811 -387 782 -376 759 -353 ct 736 -330 l 723 -299 l p ef +1427 -160 m 1500 -151 l 1492 -100 1471 -61 1438 -32 ct 1405 -4 1365 9 1317 9 ct +1257 9 1209 -9 1172 -48 ct 1136 -88 1118 -144 1118 -217 ct 1118 -265 1125 -306 1141 -342 ct +1157 -377 1181 -404 1213 -421 ct 1245 -439 1280 -448 1317 -448 ct 1365 -448 1404 -436 1434 -412 ct +1465 -388 1484 -354 1493 -309 ct 1420 -298 l 1413 -328 1401 -350 1384 -365 ct +1366 -380 1345 -387 1320 -387 ct 1283 -387 1252 -374 1229 -347 ct 1206 -320 1194 -277 1194 -219 ct +1194 -160 1205 -118 1228 -91 ct 1250 -64 1280 -51 1316 -51 ct 1345 -51 1370 -60 1389 -78 ct +1409 -95 l 1421 -123 l p ef +1864 -141 m 1940 -131 l 1928 -86 1906 -52 1873 -27 ct 1840 -2 1798 9 1748 9 ct +1683 9 1632 -9 1595 -49 ct 1557 -88 1538 -144 1538 -215 ct 1538 -289 1557 -346 1595 -387 ct +1634 -428 1683 -448 1743 -448 ct 1802 -448 1850 -428 1887 -388 ct 1924 -348 1943 -292 1943 -220 ct +1943 -215 1943 -209 1942 -200 ct 1615 -200 l 1618 -152 1632 -115 1656 -89 ct +1681 -64 1711 -51 1748 -51 ct 1775 -51 1798 -58 1818 -72 ct 1837 -87 l 1852 -109 l +p +1619 -261 m 1864 -261 l 1861 -298 1852 -326 1836 -344 ct 1813 -373 1782 -387 1744 -387 ct +1710 -387 1681 -376 1658 -353 ct 1635 -330 l 1622 -299 l p ef +2040 -520 m 2040 -605 l 2114 -605 l 2114 -520 l p +2040 0 m 2040 -438 l 2114 -438 l 2114 0 l p ef +2347 0 m 2180 -438 l 2259 -438 l 2353 -175 l 2363 -147 2372 -118 2381 -87 ct +2388 -110 2397 -138 2409 -171 ct 2506 -438 l 2583 -438 l 2417 0 l p ef +2949 -141 m 3025 -131 l 3013 -86 2991 -52 2958 -27 ct 2925 -2 2883 9 2833 9 ct +2768 9 2717 -9 2680 -49 ct 2642 -88 2623 -144 2623 -215 ct 2623 -289 2642 -346 2680 -387 ct +2719 -428 2768 -448 2828 -448 ct 2887 -448 2935 -428 2972 -388 ct 3009 -348 3028 -292 3028 -220 ct +3028 -215 3028 -209 3027 -200 ct 2700 -200 l 2703 -152 2717 -115 2741 -89 ct +2766 -64 2796 -51 2833 -51 ct 2860 -51 2883 -58 2903 -72 ct 2922 -87 l 2937 -109 l +p +2704 -261 m 2949 -261 l 2946 -298 2937 -326 2921 -344 ct 2898 -373 2867 -387 2829 -387 ct +2795 -387 2766 -376 2743 -353 ct 2720 -330 l 2707 -299 l p ef +pom +pum +20955 9975 t +65 0 m 65 -605 l 273 -605 l 320 -605 356 -602 381 -596 ct 416 -588 445 -574 470 -553 ct +502 -526 526 -492 542 -450 ct 558 -408 565 -360 565 -306 ct 565 -260 560 -219 549 -183 ct +539 -148 525 -118 508 -95 ct 491 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +352 -3 320 0 283 0 ct p +145 -71 m 274 -71 l 314 -71 345 -75 368 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 456 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -370 472 -419 452 -453 ct +431 -487 406 -510 376 -521 ct 354 -530 320 -534 272 -534 ct 145 -534 l p ef +951 -54 m 923 -30 897 -14 871 -4 ct 846 5 818 9 789 9 ct 741 9 704 -1 678 -25 ct +652 -48 639 -79 639 -115 ct 639 -137 644 -156 654 -174 ct 664 -192 676 -206 692 -217 ct +708 -228 726 -236 746 -241 ct 760 -245 782 -249 812 -252 ct 872 -259 916 -268 944 -278 ct +945 -288 945 -295 945 -297 ct 945 -328 938 -349 924 -361 ct 905 -378 876 -387 839 -387 ct +804 -387 778 -380 762 -368 ct 745 -356 733 -334 725 -303 ct 652 -313 l 658 -344 669 -369 685 -388 ct +700 -408 722 -422 750 -433 ct 779 -443 812 -448 850 -448 ct 887 -448 918 -444 941 -435 ct +964 -426 982 -415 993 -402 ct 1004 -388 1011 -371 1016 -351 ct 1018 -338 1020 -316 1020 -282 ct +1020 -183 l 1020 -114 1021 -70 1024 -52 ct 1027 -34 1034 -16 1043 0 ct 965 0 l +958 -15 l 953 -33 l p +944 -220 m 917 -209 877 -199 823 -192 ct 792 -187 771 -182 758 -177 ct 745 -171 736 -163 729 -153 ct +722 -142 718 -130 718 -117 ct 718 -97 726 -81 741 -68 ct 756 -54 778 -48 807 -48 ct +835 -48 861 -54 883 -67 ct 906 -79 922 -96 932 -118 ct 940 -135 944 -160 944 -192 ct +p ef +1401 0 m 1401 -64 l 1367 -14 1320 9 1262 9 ct 1236 9 1212 4 1189 -4 ct 1167 -14 1150 -27 1139 -42 ct +1128 -57 1121 -75 1116 -97 ct 1113 -112 1112 -135 1112 -166 ct 1112 -438 l 1186 -438 l +1186 -195 l 1186 -156 1187 -130 1191 -116 ct 1195 -97 1205 -82 1220 -70 ct +1235 -59 1254 -54 1276 -54 ct 1299 -54 1320 -59 1339 -71 ct 1359 -82 1373 -98 1381 -117 ct +1389 -137 1393 -166 1393 -203 ct 1393 -438 l 1467 -438 l 1467 0 l p ef +1577 36 m 1649 47 l 1652 69 1660 85 1674 95 ct 1693 109 1718 116 1750 116 ct +1784 116 1811 109 1829 95 ct 1848 82 1861 62 1867 38 ct 1871 22 1873 -8 1873 -57 ct +1840 -19 1800 0 1751 0 ct 1691 0 1644 -21 1611 -65 ct 1578 -108 1562 -160 1562 -221 ct +1562 -263 1569 -302 1584 -337 ct 1600 -373 1622 -400 1650 -419 ct 1679 -438 1713 -448 1752 -448 ct +1804 -448 1846 -427 1880 -385 ct 1880 -438 l 1948 -438 l 1948 -59 l 1948 8 1941 57 1928 85 ct +1914 114 1892 136 1861 153 ct 1831 169 1794 178 1750 178 ct 1698 178 1656 166 1623 142 ct +1591 119 l 1576 83 l p +1638 -227 m 1638 -169 1650 -127 1672 -101 ct 1695 -74 1724 -61 1758 -61 ct +1793 -61 1821 -74 1844 -101 ct 1867 -127 1879 -168 1879 -224 ct 1879 -278 1867 -318 1843 -346 ct +1819 -373 1791 -387 1757 -387 ct 1724 -387 1696 -373 1673 -346 ct 1650 -319 l +1638 -280 l p ef +2066 0 m 2066 -605 l 2141 -605 l 2141 -388 l 2175 -428 2219 -448 2272 -448 ct +2304 -448 2333 -442 2357 -429 ct 2381 -416 2398 -398 2408 -376 ct 2418 -353 2424 -320 2424 -278 ct +2424 0 l 2349 0 l 2349 -278 l 2349 -315 2341 -342 2325 -359 ct 2309 -376 2286 -384 2257 -384 ct +2235 -384 2214 -378 2195 -367 ct 2175 -356 2161 -340 2153 -320 ct 2145 -301 2141 -274 2141 -240 ct +2141 0 l p ef +2705 -66 m 2715 0 l 2694 3 2676 5 2659 5 ct 2632 5 2611 1 2596 -7 ct 2582 -15 2571 -26 2565 -40 ct +2559 -54 2556 -83 2556 -128 ct 2556 -380 l 2501 -380 l 2501 -438 l 2556 -438 l +2556 -547 l 2630 -591 l 2630 -438 l 2705 -438 l 2705 -380 l 2630 -380 l +2630 -124 l 2630 -103 2631 -89 2634 -83 ct 2636 -77 2641 -72 2647 -68 ct 2652 -65 2661 -63 2672 -63 ct +2680 -63 l 2691 -64 l p ef +3081 -141 m 3157 -131 l 3145 -86 3123 -52 3090 -27 ct 3057 -2 3015 9 2965 9 ct +2900 9 2849 -9 2812 -49 ct 2774 -88 2755 -144 2755 -215 ct 2755 -289 2774 -346 2812 -387 ct +2851 -428 2900 -448 2960 -448 ct 3019 -448 3067 -428 3104 -388 ct 3141 -348 3160 -292 3160 -220 ct +3160 -215 3160 -209 3159 -200 ct 2832 -200 l 2835 -152 2849 -115 2873 -89 ct +2898 -64 2928 -51 2965 -51 ct 2992 -51 3015 -58 3035 -72 ct 3054 -87 l 3069 -109 l +p +2836 -261 m 3081 -261 l 3078 -298 3069 -326 3053 -344 ct 3030 -373 2999 -387 2961 -387 ct +2927 -387 2898 -376 2875 -353 ct 2852 -330 l 2839 -299 l p ef +3255 0 m 3255 -438 l 3322 -438 l 3322 -372 l 3339 -403 3355 -423 3370 -433 ct +3384 -443 3400 -448 3417 -448 ct 3442 -448 3468 -440 3494 -424 ct 3468 -355 l +3450 -366 3432 -371 3414 -371 ct 3397 -371 3383 -366 3370 -357 ct 3357 -347 3348 -333 3342 -316 ct +3334 -289 3330 -261 3330 -229 ct 3330 0 l p ef +3617 0 m 3548 0 l 3548 -605 l 3622 -605 l 3622 -389 l 3654 -428 3694 -448 3742 -448 ct +3769 -448 3795 -443 3819 -432 ct 3843 -421 3863 -406 3879 -386 ct 3894 -366 3906 -343 3915 -315 ct +3924 -287 3928 -257 3928 -225 ct 3928 -150 3910 -92 3873 -51 ct 3835 -10 3791 9 3739 9 ct +3687 9 3646 -11 3617 -54 ct p +3616 -222 m 3616 -170 3623 -132 3638 -108 ct 3661 -70 3693 -51 3733 -51 ct +3765 -51 3793 -65 3817 -93 ct 3840 -121 3852 -163 3852 -219 ct 3852 -277 3841 -319 3818 -346 ct +3796 -373 3768 -387 3736 -387 ct 3703 -387 3675 -373 3652 -345 ct 3628 -316 l +3616 -276 l p ef +3970 -219 m 3970 -300 3992 -360 4037 -399 ct 4075 -432 4121 -448 4175 -448 ct +4236 -448 4285 -428 4323 -389 ct 4361 -349 4381 -295 4381 -225 ct 4381 -169 4372 -124 4355 -92 ct +4338 -59 4314 -34 4281 -16 ct 4249 0 4214 9 4175 9 ct 4114 9 4064 -9 4026 -49 ct +3989 -88 l 3970 -145 l p +4046 -219 m 4046 -163 4058 -121 4083 -93 ct 4107 -65 4138 -51 4175 -51 ct 4212 -51 4243 -65 4267 -93 ct +4292 -121 4304 -164 4304 -221 ct 4304 -276 4292 -317 4267 -345 ct 4243 -373 4212 -387 4175 -387 ct +4138 -387 4107 -373 4083 -345 ct 4058 -317 l 4046 -275 l p ef +4761 -54 m 4733 -30 4707 -14 4681 -4 ct 4656 5 4628 9 4599 9 ct 4551 9 4514 -1 4488 -25 ct +4462 -48 4449 -79 4449 -115 ct 4449 -137 4454 -156 4464 -174 ct 4474 -192 4486 -206 4502 -217 ct +4518 -228 4536 -236 4556 -241 ct 4570 -245 4592 -249 4622 -252 ct 4682 -259 4726 -268 4754 -278 ct +4755 -288 4755 -295 4755 -297 ct 4755 -328 4748 -349 4734 -361 ct 4715 -378 4686 -387 4649 -387 ct +4614 -387 4588 -380 4572 -368 ct 4555 -356 4543 -334 4535 -303 ct 4462 -313 l +4468 -344 4479 -369 4495 -388 ct 4510 -408 4532 -422 4560 -433 ct 4589 -443 4622 -448 4660 -448 ct +4697 -448 4728 -444 4751 -435 ct 4774 -426 4792 -415 4803 -402 ct 4814 -388 4821 -371 4826 -351 ct +4828 -338 4830 -316 4830 -282 ct 4830 -183 l 4830 -114 4831 -70 4834 -52 ct +4837 -34 4844 -16 4853 0 ct 4775 0 l 4768 -15 l 4763 -33 l p +4754 -220 m 4727 -209 4687 -199 4633 -192 ct 4602 -187 4581 -182 4568 -177 ct +4555 -171 4546 -163 4539 -153 ct 4532 -142 4528 -130 4528 -117 ct 4528 -97 4536 -81 4551 -68 ct +4566 -54 4588 -48 4617 -48 ct 4645 -48 4671 -54 4693 -67 ct 4716 -79 4732 -96 4742 -118 ct +4750 -135 4754 -160 4754 -192 ct p ef +4922 0 m 4922 -438 l 4989 -438 l 4989 -372 l 5006 -403 5022 -423 5037 -433 ct +5051 -443 5067 -448 5084 -448 ct 5109 -448 5135 -440 5161 -424 ct 5135 -355 l +5117 -366 5099 -371 5081 -371 ct 5064 -371 5050 -366 5037 -357 ct 5024 -347 5015 -333 5009 -316 ct +5001 -289 4997 -261 4997 -229 ct 4997 0 l p ef +5499 0 m 5499 -55 l 5471 -11 5430 9 5376 9 ct 5341 9 5309 0 5280 -19 ct 5250 -38 5228 -65 5212 -99 ct +5195 -134 5187 -174 5187 -218 ct 5187 -262 5195 -302 5209 -338 ct 5224 -373 5246 -401 5275 -420 ct +5304 -439 5337 -448 5373 -448 ct 5399 -448 5423 -443 5444 -431 ct 5464 -420 5481 -406 5494 -388 ct +5494 -605 l 5568 -605 l 5568 0 l p +5264 -218 m 5264 -162 5276 -120 5299 -92 ct 5323 -65 5351 -51 5383 -51 ct 5416 -51 5443 -64 5466 -91 ct +5489 -117 5500 -158 5500 -212 ct 5500 -272 5489 -316 5465 -344 ct 5442 -373 5414 -387 5380 -387 ct +5347 -387 5319 -373 5297 -346 ct 5275 -319 l 5264 -277 l p ef +pom +gr +4245 18828 m 1070 18828 l 1070 13113 l 7420 13113 l 7420 18828 l 4245 18828 l +pc +gs +pum +2607 15795 t +219 0 m 219 -534 l 19 -534 l 19 -605 l 499 -605 l 499 -534 l 299 -534 l +299 0 l p ef +583 0 m 583 -438 l 650 -438 l 650 -372 l 667 -403 683 -423 698 -433 ct +712 -443 728 -448 745 -448 ct 770 -448 796 -440 822 -424 ct 796 -355 l 778 -366 760 -371 742 -371 ct +725 -371 711 -366 698 -357 ct 685 -347 676 -333 670 -316 ct 662 -289 658 -261 658 -229 ct +658 0 l p ef +1162 -54 m 1134 -30 1108 -14 1082 -4 ct 1057 5 1029 9 1000 9 ct 952 9 915 -1 889 -25 ct +863 -48 850 -79 850 -115 ct 850 -137 855 -156 865 -174 ct 875 -192 887 -206 903 -217 ct +919 -228 937 -236 957 -241 ct 971 -245 993 -249 1023 -252 ct 1083 -259 1127 -268 1155 -278 ct +1156 -288 1156 -295 1156 -297 ct 1156 -328 1149 -349 1135 -361 ct 1116 -378 1087 -387 1050 -387 ct +1015 -387 989 -380 973 -368 ct 956 -356 944 -334 936 -303 ct 863 -313 l 869 -344 880 -369 896 -388 ct +911 -408 933 -422 961 -433 ct 990 -443 1023 -448 1061 -448 ct 1098 -448 1129 -444 1152 -435 ct +1175 -426 1193 -415 1204 -402 ct 1215 -388 1222 -371 1227 -351 ct 1229 -338 1231 -316 1231 -282 ct +1231 -183 l 1231 -114 1232 -70 1235 -52 ct 1238 -34 1245 -16 1254 0 ct 1176 0 l +1169 -15 l 1164 -33 l p +1155 -220 m 1128 -209 1088 -199 1034 -192 ct 1003 -187 982 -182 969 -177 ct +956 -171 947 -163 940 -153 ct 933 -142 929 -130 929 -117 ct 929 -97 937 -81 952 -68 ct +967 -54 989 -48 1018 -48 ct 1046 -48 1072 -54 1094 -67 ct 1117 -79 1133 -96 1143 -118 ct +1151 -135 1155 -160 1155 -192 ct p ef +1325 0 m 1325 -438 l 1392 -438 l 1392 -376 l 1424 -424 1471 -448 1532 -448 ct +1558 -448 1583 -443 1605 -434 ct 1627 -424 1643 -412 1654 -396 ct 1666 -381 1673 -363 1678 -342 ct +1680 -328 1682 -304 1682 -269 ct 1682 0 l 1607 0 l 1607 -266 l 1607 -297 1605 -319 1599 -334 ct +1593 -349 1583 -361 1568 -370 ct 1553 -379 1536 -384 1516 -384 ct 1484 -384 1457 -374 1434 -354 ct +1411 -333 1400 -295 1400 -239 ct 1400 0 l p ef +1772 -130 m 1845 -142 l 1849 -113 1861 -90 1880 -74 ct 1898 -59 1925 -51 1959 -51 ct +1993 -51 2018 -58 2035 -72 ct 2051 -85 2059 -102 2059 -121 ct 2059 -137 2052 -151 2038 -160 ct +2027 -167 2002 -175 1962 -185 ct 1907 -199 1869 -211 1848 -221 ct 1827 -231 1811 -245 1800 -263 ct +1789 -281 1784 -300 1784 -322 ct 1784 -341 1788 -359 1797 -376 ct 1806 -393 1818 -407 1834 -418 ct +1845 -426 1861 -433 1881 -439 ct 1901 -445 1923 -448 1945 -448 ct 1980 -448 2010 -443 2036 -433 ct +2062 -423 2081 -410 2094 -393 ct 2106 -376 2115 -353 2119 -325 ct 2047 -315 l +2043 -338 2034 -355 2018 -368 ct 2002 -381 1980 -387 1951 -387 ct 1917 -387 1892 -381 1878 -370 ct +1863 -359 1856 -346 1856 -330 ct 1856 -321 1859 -312 1865 -304 ct 1871 -296 1880 -290 1893 -285 ct +1901 -282 1923 -275 1959 -266 ct 2012 -251 2048 -240 2069 -231 ct 2090 -222 2106 -209 2118 -192 ct +2130 -175 2136 -154 2136 -128 ct 2136 -104 2129 -80 2114 -58 ct 2100 -36 2079 -20 2052 -8 ct +2024 3 1993 9 1959 9 ct 1902 9 1859 -1 1829 -25 ct 1799 -49 l 1780 -84 l p ef +2198 0 m 2198 -438 l 2265 -438 l 2265 -377 l 2279 -398 2297 -415 2320 -428 ct +2343 -442 2369 -448 2398 -448 ct 2430 -448 2457 -441 2478 -428 ct 2499 -414 2513 -396 2522 -371 ct +2556 -423 2602 -448 2657 -448 ct 2701 -448 2734 -436 2758 -412 ct 2781 -388 2793 -351 2793 -301 ct +2793 0 l 2719 0 l 2719 -276 l 2719 -306 2716 -327 2712 -340 ct 2707 -353 2698 -364 2685 -372 ct +2673 -380 2658 -384 2641 -384 ct 2610 -384 2584 -373 2564 -353 ct 2543 -332 2533 -300 2533 -254 ct +2533 0 l 2459 0 l 2459 -285 l 2459 -318 2453 -342 2441 -359 ct 2429 -375 2409 -384 2381 -384 ct +2360 -384 2341 -378 2323 -367 ct 2305 -356 2293 -340 2285 -319 ct 2277 -298 2273 -267 2273 -227 ct +2273 0 l p ef +2914 -520 m 2914 -605 l 2988 -605 l 2988 -520 l p +2914 0 m 2914 -438 l 2988 -438 l 2988 0 l p ef +3261 -66 m 3271 0 l 3250 3 3232 5 3215 5 ct 3188 5 3167 1 3152 -7 ct 3138 -15 3127 -26 3121 -40 ct +3115 -54 3112 -83 3112 -128 ct 3112 -380 l 3057 -380 l 3057 -438 l 3112 -438 l +3112 -547 l 3186 -591 l 3186 -438 l 3261 -438 l 3261 -380 l 3186 -380 l +3186 -124 l 3186 -103 3187 -89 3190 -83 ct 3192 -77 3197 -72 3203 -68 ct 3208 -65 3217 -63 3228 -63 ct +3236 -63 l 3247 -64 l p ef +pom +pum +1429 16748 t +65 0 m 65 -605 l 273 -605 l 320 -605 356 -602 381 -596 ct 416 -588 445 -574 470 -553 ct +502 -526 526 -492 542 -450 ct 558 -408 565 -360 565 -306 ct 565 -260 560 -219 549 -183 ct +539 -148 525 -118 508 -95 ct 491 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +352 -3 320 0 283 0 ct p +145 -71 m 274 -71 l 314 -71 345 -75 368 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 456 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -370 472 -419 452 -453 ct +431 -487 406 -510 376 -521 ct 354 -530 320 -534 272 -534 ct 145 -534 l p ef +951 -54 m 923 -30 897 -14 871 -4 ct 846 5 818 9 789 9 ct 741 9 704 -1 678 -25 ct +652 -48 639 -79 639 -115 ct 639 -137 644 -156 654 -174 ct 664 -192 676 -206 692 -217 ct +708 -228 726 -236 746 -241 ct 760 -245 782 -249 812 -252 ct 872 -259 916 -268 944 -278 ct +945 -288 945 -295 945 -297 ct 945 -328 938 -349 924 -361 ct 905 -378 876 -387 839 -387 ct +804 -387 778 -380 762 -368 ct 745 -356 733 -334 725 -303 ct 652 -313 l 658 -344 669 -369 685 -388 ct +700 -408 722 -422 750 -433 ct 779 -443 812 -448 850 -448 ct 887 -448 918 -444 941 -435 ct +964 -426 982 -415 993 -402 ct 1004 -388 1011 -371 1016 -351 ct 1018 -338 1020 -316 1020 -282 ct +1020 -183 l 1020 -114 1021 -70 1024 -52 ct 1027 -34 1034 -16 1043 0 ct 965 0 l +958 -15 l 953 -33 l p +944 -220 m 917 -209 877 -199 823 -192 ct 792 -187 771 -182 758 -177 ct 745 -171 736 -163 729 -153 ct +722 -142 718 -130 718 -117 ct 718 -97 726 -81 741 -68 ct 756 -54 778 -48 807 -48 ct +835 -48 861 -54 883 -67 ct 906 -79 922 -96 932 -118 ct 940 -135 944 -160 944 -192 ct +p ef +1401 0 m 1401 -64 l 1367 -14 1320 9 1262 9 ct 1236 9 1212 4 1189 -4 ct 1167 -14 1150 -27 1139 -42 ct +1128 -57 1121 -75 1116 -97 ct 1113 -112 1112 -135 1112 -166 ct 1112 -438 l 1186 -438 l +1186 -195 l 1186 -156 1187 -130 1191 -116 ct 1195 -97 1205 -82 1220 -70 ct +1235 -59 1254 -54 1276 -54 ct 1299 -54 1320 -59 1339 -71 ct 1359 -82 1373 -98 1381 -117 ct +1389 -137 1393 -166 1393 -203 ct 1393 -438 l 1467 -438 l 1467 0 l p ef +1577 36 m 1649 47 l 1652 69 1660 85 1674 95 ct 1693 109 1718 116 1750 116 ct +1784 116 1811 109 1829 95 ct 1848 82 1861 62 1867 38 ct 1871 22 1873 -8 1873 -57 ct +1840 -19 1800 0 1751 0 ct 1691 0 1644 -21 1611 -65 ct 1578 -108 1562 -160 1562 -221 ct +1562 -263 1569 -302 1584 -337 ct 1600 -373 1622 -400 1650 -419 ct 1679 -438 1713 -448 1752 -448 ct +1804 -448 1846 -427 1880 -385 ct 1880 -438 l 1948 -438 l 1948 -59 l 1948 8 1941 57 1928 85 ct +1914 114 1892 136 1861 153 ct 1831 169 1794 178 1750 178 ct 1698 178 1656 166 1623 142 ct +1591 119 l 1576 83 l p +1638 -227 m 1638 -169 1650 -127 1672 -101 ct 1695 -74 1724 -61 1758 -61 ct +1793 -61 1821 -74 1844 -101 ct 1867 -127 1879 -168 1879 -224 ct 1879 -278 1867 -318 1843 -346 ct +1819 -373 1791 -387 1757 -387 ct 1724 -387 1696 -373 1673 -346 ct 1650 -319 l +1638 -280 l p ef +2066 0 m 2066 -605 l 2141 -605 l 2141 -388 l 2175 -428 2219 -448 2272 -448 ct +2304 -448 2333 -442 2357 -429 ct 2381 -416 2398 -398 2408 -376 ct 2418 -353 2424 -320 2424 -278 ct +2424 0 l 2349 0 l 2349 -278 l 2349 -315 2341 -342 2325 -359 ct 2309 -376 2286 -384 2257 -384 ct +2235 -384 2214 -378 2195 -367 ct 2175 -356 2161 -340 2153 -320 ct 2145 -301 2141 -274 2141 -240 ct +2141 0 l p ef +2705 -66 m 2715 0 l 2694 3 2676 5 2659 5 ct 2632 5 2611 1 2596 -7 ct 2582 -15 2571 -26 2565 -40 ct +2559 -54 2556 -83 2556 -128 ct 2556 -380 l 2501 -380 l 2501 -438 l 2556 -438 l +2556 -547 l 2630 -591 l 2630 -438 l 2705 -438 l 2705 -380 l 2630 -380 l +2630 -124 l 2630 -103 2631 -89 2634 -83 ct 2636 -77 2641 -72 2647 -68 ct 2652 -65 2661 -63 2672 -63 ct +2680 -63 l 2691 -64 l p ef +3081 -141 m 3157 -131 l 3145 -86 3123 -52 3090 -27 ct 3057 -2 3015 9 2965 9 ct +2900 9 2849 -9 2812 -49 ct 2774 -88 2755 -144 2755 -215 ct 2755 -289 2774 -346 2812 -387 ct +2851 -428 2900 -448 2960 -448 ct 3019 -448 3067 -428 3104 -388 ct 3141 -348 3160 -292 3160 -220 ct +3160 -215 3160 -209 3159 -200 ct 2832 -200 l 2835 -152 2849 -115 2873 -89 ct +2898 -64 2928 -51 2965 -51 ct 2992 -51 3015 -58 3035 -72 ct 3054 -87 l 3069 -109 l +p +2836 -261 m 3081 -261 l 3078 -298 3069 -326 3053 -344 ct 3030 -373 2999 -387 2961 -387 ct +2927 -387 2898 -376 2875 -353 ct 2852 -330 l 2839 -299 l p ef +3255 0 m 3255 -438 l 3322 -438 l 3322 -372 l 3339 -403 3355 -423 3370 -433 ct +3384 -443 3400 -448 3417 -448 ct 3442 -448 3468 -440 3494 -424 ct 3468 -355 l +3450 -366 3432 -371 3414 -371 ct 3397 -371 3383 -366 3370 -357 ct 3357 -347 3348 -333 3342 -316 ct +3334 -289 3330 -261 3330 -229 ct 3330 0 l p ef +3617 0 m 3548 0 l 3548 -605 l 3622 -605 l 3622 -389 l 3654 -428 3694 -448 3742 -448 ct +3769 -448 3795 -443 3819 -432 ct 3843 -421 3863 -406 3879 -386 ct 3894 -366 3906 -343 3915 -315 ct +3924 -287 3928 -257 3928 -225 ct 3928 -150 3910 -92 3873 -51 ct 3835 -10 3791 9 3739 9 ct +3687 9 3646 -11 3617 -54 ct p +3616 -222 m 3616 -170 3623 -132 3638 -108 ct 3661 -70 3693 -51 3733 -51 ct +3765 -51 3793 -65 3817 -93 ct 3840 -121 3852 -163 3852 -219 ct 3852 -277 3841 -319 3818 -346 ct +3796 -373 3768 -387 3736 -387 ct 3703 -387 3675 -373 3652 -345 ct 3628 -316 l +3616 -276 l p ef +3970 -219 m 3970 -300 3992 -360 4037 -399 ct 4075 -432 4121 -448 4175 -448 ct +4236 -448 4285 -428 4323 -389 ct 4361 -349 4381 -295 4381 -225 ct 4381 -169 4372 -124 4355 -92 ct +4338 -59 4314 -34 4281 -16 ct 4249 0 4214 9 4175 9 ct 4114 9 4064 -9 4026 -49 ct +3989 -88 l 3970 -145 l p +4046 -219 m 4046 -163 4058 -121 4083 -93 ct 4107 -65 4138 -51 4175 -51 ct 4212 -51 4243 -65 4267 -93 ct +4292 -121 4304 -164 4304 -221 ct 4304 -276 4292 -317 4267 -345 ct 4243 -373 4212 -387 4175 -387 ct +4138 -387 4107 -373 4083 -345 ct 4058 -317 l 4046 -275 l p ef +4761 -54 m 4733 -30 4707 -14 4681 -4 ct 4656 5 4628 9 4599 9 ct 4551 9 4514 -1 4488 -25 ct +4462 -48 4449 -79 4449 -115 ct 4449 -137 4454 -156 4464 -174 ct 4474 -192 4486 -206 4502 -217 ct +4518 -228 4536 -236 4556 -241 ct 4570 -245 4592 -249 4622 -252 ct 4682 -259 4726 -268 4754 -278 ct +4755 -288 4755 -295 4755 -297 ct 4755 -328 4748 -349 4734 -361 ct 4715 -378 4686 -387 4649 -387 ct +4614 -387 4588 -380 4572 -368 ct 4555 -356 4543 -334 4535 -303 ct 4462 -313 l +4468 -344 4479 -369 4495 -388 ct 4510 -408 4532 -422 4560 -433 ct 4589 -443 4622 -448 4660 -448 ct +4697 -448 4728 -444 4751 -435 ct 4774 -426 4792 -415 4803 -402 ct 4814 -388 4821 -371 4826 -351 ct +4828 -338 4830 -316 4830 -282 ct 4830 -183 l 4830 -114 4831 -70 4834 -52 ct +4837 -34 4844 -16 4853 0 ct 4775 0 l 4768 -15 l 4763 -33 l p +4754 -220 m 4727 -209 4687 -199 4633 -192 ct 4602 -187 4581 -182 4568 -177 ct +4555 -171 4546 -163 4539 -153 ct 4532 -142 4528 -130 4528 -117 ct 4528 -97 4536 -81 4551 -68 ct +4566 -54 4588 -48 4617 -48 ct 4645 -48 4671 -54 4693 -67 ct 4716 -79 4732 -96 4742 -118 ct +4750 -135 4754 -160 4754 -192 ct p ef +4922 0 m 4922 -438 l 4989 -438 l 4989 -372 l 5006 -403 5022 -423 5037 -433 ct +5051 -443 5067 -448 5084 -448 ct 5109 -448 5135 -440 5161 -424 ct 5135 -355 l +5117 -366 5099 -371 5081 -371 ct 5064 -371 5050 -366 5037 -357 ct 5024 -347 5015 -333 5009 -316 ct +5001 -289 4997 -261 4997 -229 ct 4997 0 l p ef +5499 0 m 5499 -55 l 5471 -11 5430 9 5376 9 ct 5341 9 5309 0 5280 -19 ct 5250 -38 5228 -65 5212 -99 ct +5195 -134 5187 -174 5187 -218 ct 5187 -262 5195 -302 5209 -338 ct 5224 -373 5246 -401 5275 -420 ct +5304 -439 5337 -448 5373 -448 ct 5399 -448 5423 -443 5444 -431 ct 5464 -420 5481 -406 5494 -388 ct +5494 -605 l 5568 -605 l 5568 0 l p +5264 -218 m 5264 -162 5276 -120 5299 -92 ct 5323 -65 5351 -51 5383 -51 ct 5416 -51 5443 -64 5466 -91 ct +5489 -117 5500 -158 5500 -212 ct 5500 -272 5489 -316 5465 -344 ct 5442 -373 5414 -387 5380 -387 ct +5347 -387 5319 -373 5297 -346 ct 5275 -319 l 5264 -277 l p ef +pom +gr +4245 12065 m 1070 12065 l 1070 6350 l 7420 6350 l 7420 12065 l 4245 12065 l +pc +gs +pum +2713 9022 t +66 0 m 66 -605 l 335 -605 l 389 -605 430 -600 458 -589 ct 486 -578 508 -559 525 -531 ct +542 -504 550 -473 550 -440 ct 550 -397 536 -361 508 -331 ct 481 -302 438 -283 380 -275 ct +401 -265 417 -255 428 -245 ct 451 -223 473 -197 494 -164 ct 600 0 l 499 0 l +419 -125 l 395 -162 376 -190 361 -209 ct 346 -228 332 -242 320 -249 ct 308 -257 296 -263 284 -266 ct +275 -267 260 -268 239 -268 ct 146 -268 l 146 0 l p +146 -338 m 318 -338 l 355 -338 384 -342 404 -349 ct 425 -357 441 -369 451 -386 ct +462 -402 468 -420 468 -440 ct 468 -468 457 -492 436 -510 ct 416 -529 383 -538 338 -538 ct +146 -538 l p ef +965 -141 m 1041 -131 l 1029 -86 1007 -52 974 -27 ct 941 -2 899 9 849 9 ct +784 9 733 -9 696 -49 ct 658 -88 639 -144 639 -215 ct 639 -289 658 -346 696 -387 ct +735 -428 784 -448 844 -448 ct 903 -448 951 -428 988 -388 ct 1025 -348 1044 -292 1044 -220 ct +1044 -215 1044 -209 1043 -200 ct 716 -200 l 719 -152 733 -115 757 -89 ct 782 -64 812 -51 849 -51 ct +876 -51 899 -58 919 -72 ct 938 -87 l 953 -109 l p +720 -261 m 965 -261 l 962 -298 953 -326 937 -344 ct 914 -373 883 -387 845 -387 ct +811 -387 782 -376 759 -353 ct 736 -330 l 723 -299 l p ef +1427 -160 m 1500 -151 l 1492 -100 1471 -61 1438 -32 ct 1405 -4 1365 9 1317 9 ct +1257 9 1209 -9 1172 -48 ct 1136 -88 1118 -144 1118 -217 ct 1118 -265 1125 -306 1141 -342 ct +1157 -377 1181 -404 1213 -421 ct 1245 -439 1280 -448 1317 -448 ct 1365 -448 1404 -436 1434 -412 ct +1465 -388 1484 -354 1493 -309 ct 1420 -298 l 1413 -328 1401 -350 1384 -365 ct +1366 -380 1345 -387 1320 -387 ct 1283 -387 1252 -374 1229 -347 ct 1206 -320 1194 -277 1194 -219 ct +1194 -160 1205 -118 1228 -91 ct 1250 -64 1280 -51 1316 -51 ct 1345 -51 1370 -60 1389 -78 ct +1409 -95 l 1421 -123 l p ef +1864 -141 m 1940 -131 l 1928 -86 1906 -52 1873 -27 ct 1840 -2 1798 9 1748 9 ct +1683 9 1632 -9 1595 -49 ct 1557 -88 1538 -144 1538 -215 ct 1538 -289 1557 -346 1595 -387 ct +1634 -428 1683 -448 1743 -448 ct 1802 -448 1850 -428 1887 -388 ct 1924 -348 1943 -292 1943 -220 ct +1943 -215 1943 -209 1942 -200 ct 1615 -200 l 1618 -152 1632 -115 1656 -89 ct +1681 -64 1711 -51 1748 -51 ct 1775 -51 1798 -58 1818 -72 ct 1837 -87 l 1852 -109 l +p +1619 -261 m 1864 -261 l 1861 -298 1852 -326 1836 -344 ct 1813 -373 1782 -387 1744 -387 ct +1710 -387 1681 -376 1658 -353 ct 1635 -330 l 1622 -299 l p ef +2040 -520 m 2040 -605 l 2114 -605 l 2114 -520 l p +2040 0 m 2040 -438 l 2114 -438 l 2114 0 l p ef +2347 0 m 2180 -438 l 2259 -438 l 2353 -175 l 2363 -147 2372 -118 2381 -87 ct +2388 -110 2397 -138 2409 -171 ct 2506 -438 l 2583 -438 l 2417 0 l p ef +2949 -141 m 3025 -131 l 3013 -86 2991 -52 2958 -27 ct 2925 -2 2883 9 2833 9 ct +2768 9 2717 -9 2680 -49 ct 2642 -88 2623 -144 2623 -215 ct 2623 -289 2642 -346 2680 -387 ct +2719 -428 2768 -448 2828 -448 ct 2887 -448 2935 -428 2972 -388 ct 3009 -348 3028 -292 3028 -220 ct +3028 -215 3028 -209 3027 -200 ct 2700 -200 l 2703 -152 2717 -115 2741 -89 ct +2766 -64 2796 -51 2833 -51 ct 2860 -51 2883 -58 2903 -72 ct 2922 -87 l 2937 -109 l +p +2704 -261 m 2949 -261 l 2946 -298 2937 -326 2921 -344 ct 2898 -373 2867 -387 2829 -387 ct +2795 -387 2766 -376 2743 -353 ct 2720 -330 l 2707 -299 l p ef +pom +pum +1429 9975 t +65 0 m 65 -605 l 273 -605 l 320 -605 356 -602 381 -596 ct 416 -588 445 -574 470 -553 ct +502 -526 526 -492 542 -450 ct 558 -408 565 -360 565 -306 ct 565 -260 560 -219 549 -183 ct +539 -148 525 -118 508 -95 ct 491 -72 473 -54 453 -40 ct 433 -27 409 -17 381 -10 ct +352 -3 320 0 283 0 ct p +145 -71 m 274 -71 l 314 -71 345 -75 368 -82 ct 391 -90 409 -100 423 -114 ct +442 -133 456 -158 467 -190 ct 478 -222 483 -261 483 -307 ct 483 -370 472 -419 452 -453 ct +431 -487 406 -510 376 -521 ct 354 -530 320 -534 272 -534 ct 145 -534 l p ef +951 -54 m 923 -30 897 -14 871 -4 ct 846 5 818 9 789 9 ct 741 9 704 -1 678 -25 ct +652 -48 639 -79 639 -115 ct 639 -137 644 -156 654 -174 ct 664 -192 676 -206 692 -217 ct +708 -228 726 -236 746 -241 ct 760 -245 782 -249 812 -252 ct 872 -259 916 -268 944 -278 ct +945 -288 945 -295 945 -297 ct 945 -328 938 -349 924 -361 ct 905 -378 876 -387 839 -387 ct +804 -387 778 -380 762 -368 ct 745 -356 733 -334 725 -303 ct 652 -313 l 658 -344 669 -369 685 -388 ct +700 -408 722 -422 750 -433 ct 779 -443 812 -448 850 -448 ct 887 -448 918 -444 941 -435 ct +964 -426 982 -415 993 -402 ct 1004 -388 1011 -371 1016 -351 ct 1018 -338 1020 -316 1020 -282 ct +1020 -183 l 1020 -114 1021 -70 1024 -52 ct 1027 -34 1034 -16 1043 0 ct 965 0 l +958 -15 l 953 -33 l p +944 -220 m 917 -209 877 -199 823 -192 ct 792 -187 771 -182 758 -177 ct 745 -171 736 -163 729 -153 ct +722 -142 718 -130 718 -117 ct 718 -97 726 -81 741 -68 ct 756 -54 778 -48 807 -48 ct +835 -48 861 -54 883 -67 ct 906 -79 922 -96 932 -118 ct 940 -135 944 -160 944 -192 ct +p ef +1401 0 m 1401 -64 l 1367 -14 1320 9 1262 9 ct 1236 9 1212 4 1189 -4 ct 1167 -14 1150 -27 1139 -42 ct +1128 -57 1121 -75 1116 -97 ct 1113 -112 1112 -135 1112 -166 ct 1112 -438 l 1186 -438 l +1186 -195 l 1186 -156 1187 -130 1191 -116 ct 1195 -97 1205 -82 1220 -70 ct +1235 -59 1254 -54 1276 -54 ct 1299 -54 1320 -59 1339 -71 ct 1359 -82 1373 -98 1381 -117 ct +1389 -137 1393 -166 1393 -203 ct 1393 -438 l 1467 -438 l 1467 0 l p ef +1577 36 m 1649 47 l 1652 69 1660 85 1674 95 ct 1693 109 1718 116 1750 116 ct +1784 116 1811 109 1829 95 ct 1848 82 1861 62 1867 38 ct 1871 22 1873 -8 1873 -57 ct +1840 -19 1800 0 1751 0 ct 1691 0 1644 -21 1611 -65 ct 1578 -108 1562 -160 1562 -221 ct +1562 -263 1569 -302 1584 -337 ct 1600 -373 1622 -400 1650 -419 ct 1679 -438 1713 -448 1752 -448 ct +1804 -448 1846 -427 1880 -385 ct 1880 -438 l 1948 -438 l 1948 -59 l 1948 8 1941 57 1928 85 ct +1914 114 1892 136 1861 153 ct 1831 169 1794 178 1750 178 ct 1698 178 1656 166 1623 142 ct +1591 119 l 1576 83 l p +1638 -227 m 1638 -169 1650 -127 1672 -101 ct 1695 -74 1724 -61 1758 -61 ct +1793 -61 1821 -74 1844 -101 ct 1867 -127 1879 -168 1879 -224 ct 1879 -278 1867 -318 1843 -346 ct +1819 -373 1791 -387 1757 -387 ct 1724 -387 1696 -373 1673 -346 ct 1650 -319 l +1638 -280 l p ef +2066 0 m 2066 -605 l 2141 -605 l 2141 -388 l 2175 -428 2219 -448 2272 -448 ct +2304 -448 2333 -442 2357 -429 ct 2381 -416 2398 -398 2408 -376 ct 2418 -353 2424 -320 2424 -278 ct +2424 0 l 2349 0 l 2349 -278 l 2349 -315 2341 -342 2325 -359 ct 2309 -376 2286 -384 2257 -384 ct +2235 -384 2214 -378 2195 -367 ct 2175 -356 2161 -340 2153 -320 ct 2145 -301 2141 -274 2141 -240 ct +2141 0 l p ef +2705 -66 m 2715 0 l 2694 3 2676 5 2659 5 ct 2632 5 2611 1 2596 -7 ct 2582 -15 2571 -26 2565 -40 ct +2559 -54 2556 -83 2556 -128 ct 2556 -380 l 2501 -380 l 2501 -438 l 2556 -438 l +2556 -547 l 2630 -591 l 2630 -438 l 2705 -438 l 2705 -380 l 2630 -380 l +2630 -124 l 2630 -103 2631 -89 2634 -83 ct 2636 -77 2641 -72 2647 -68 ct 2652 -65 2661 -63 2672 -63 ct +2680 -63 l 2691 -64 l p ef +3081 -141 m 3157 -131 l 3145 -86 3123 -52 3090 -27 ct 3057 -2 3015 9 2965 9 ct +2900 9 2849 -9 2812 -49 ct 2774 -88 2755 -144 2755 -215 ct 2755 -289 2774 -346 2812 -387 ct +2851 -428 2900 -448 2960 -448 ct 3019 -448 3067 -428 3104 -388 ct 3141 -348 3160 -292 3160 -220 ct +3160 -215 3160 -209 3159 -200 ct 2832 -200 l 2835 -152 2849 -115 2873 -89 ct +2898 -64 2928 -51 2965 -51 ct 2992 -51 3015 -58 3035 -72 ct 3054 -87 l 3069 -109 l +p +2836 -261 m 3081 -261 l 3078 -298 3069 -326 3053 -344 ct 3030 -373 2999 -387 2961 -387 ct +2927 -387 2898 -376 2875 -353 ct 2852 -330 l 2839 -299 l p ef +3255 0 m 3255 -438 l 3322 -438 l 3322 -372 l 3339 -403 3355 -423 3370 -433 ct +3384 -443 3400 -448 3417 -448 ct 3442 -448 3468 -440 3494 -424 ct 3468 -355 l +3450 -366 3432 -371 3414 -371 ct 3397 -371 3383 -366 3370 -357 ct 3357 -347 3348 -333 3342 -316 ct +3334 -289 3330 -261 3330 -229 ct 3330 0 l p ef +3617 0 m 3548 0 l 3548 -605 l 3622 -605 l 3622 -389 l 3654 -428 3694 -448 3742 -448 ct +3769 -448 3795 -443 3819 -432 ct 3843 -421 3863 -406 3879 -386 ct 3894 -366 3906 -343 3915 -315 ct +3924 -287 3928 -257 3928 -225 ct 3928 -150 3910 -92 3873 -51 ct 3835 -10 3791 9 3739 9 ct +3687 9 3646 -11 3617 -54 ct p +3616 -222 m 3616 -170 3623 -132 3638 -108 ct 3661 -70 3693 -51 3733 -51 ct +3765 -51 3793 -65 3817 -93 ct 3840 -121 3852 -163 3852 -219 ct 3852 -277 3841 -319 3818 -346 ct +3796 -373 3768 -387 3736 -387 ct 3703 -387 3675 -373 3652 -345 ct 3628 -316 l +3616 -276 l p ef +3970 -219 m 3970 -300 3992 -360 4037 -399 ct 4075 -432 4121 -448 4175 -448 ct +4236 -448 4285 -428 4323 -389 ct 4361 -349 4381 -295 4381 -225 ct 4381 -169 4372 -124 4355 -92 ct +4338 -59 4314 -34 4281 -16 ct 4249 0 4214 9 4175 9 ct 4114 9 4064 -9 4026 -49 ct +3989 -88 l 3970 -145 l p +4046 -219 m 4046 -163 4058 -121 4083 -93 ct 4107 -65 4138 -51 4175 -51 ct 4212 -51 4243 -65 4267 -93 ct +4292 -121 4304 -164 4304 -221 ct 4304 -276 4292 -317 4267 -345 ct 4243 -373 4212 -387 4175 -387 ct +4138 -387 4107 -373 4083 -345 ct 4058 -317 l 4046 -275 l p ef +4761 -54 m 4733 -30 4707 -14 4681 -4 ct 4656 5 4628 9 4599 9 ct 4551 9 4514 -1 4488 -25 ct +4462 -48 4449 -79 4449 -115 ct 4449 -137 4454 -156 4464 -174 ct 4474 -192 4486 -206 4502 -217 ct +4518 -228 4536 -236 4556 -241 ct 4570 -245 4592 -249 4622 -252 ct 4682 -259 4726 -268 4754 -278 ct +4755 -288 4755 -295 4755 -297 ct 4755 -328 4748 -349 4734 -361 ct 4715 -378 4686 -387 4649 -387 ct +4614 -387 4588 -380 4572 -368 ct 4555 -356 4543 -334 4535 -303 ct 4462 -313 l +4468 -344 4479 -369 4495 -388 ct 4510 -408 4532 -422 4560 -433 ct 4589 -443 4622 -448 4660 -448 ct +4697 -448 4728 -444 4751 -435 ct 4774 -426 4792 -415 4803 -402 ct 4814 -388 4821 -371 4826 -351 ct +4828 -338 4830 -316 4830 -282 ct 4830 -183 l 4830 -114 4831 -70 4834 -52 ct +4837 -34 4844 -16 4853 0 ct 4775 0 l 4768 -15 l 4763 -33 l p +4754 -220 m 4727 -209 4687 -199 4633 -192 ct 4602 -187 4581 -182 4568 -177 ct +4555 -171 4546 -163 4539 -153 ct 4532 -142 4528 -130 4528 -117 ct 4528 -97 4536 -81 4551 -68 ct +4566 -54 4588 -48 4617 -48 ct 4645 -48 4671 -54 4693 -67 ct 4716 -79 4732 -96 4742 -118 ct +4750 -135 4754 -160 4754 -192 ct p ef +4922 0 m 4922 -438 l 4989 -438 l 4989 -372 l 5006 -403 5022 -423 5037 -433 ct +5051 -443 5067 -448 5084 -448 ct 5109 -448 5135 -440 5161 -424 ct 5135 -355 l +5117 -366 5099 -371 5081 -371 ct 5064 -371 5050 -366 5037 -357 ct 5024 -347 5015 -333 5009 -316 ct +5001 -289 4997 -261 4997 -229 ct 4997 0 l p ef +5499 0 m 5499 -55 l 5471 -11 5430 9 5376 9 ct 5341 9 5309 0 5280 -19 ct 5250 -38 5228 -65 5212 -99 ct +5195 -134 5187 -174 5187 -218 ct 5187 -262 5195 -302 5209 -338 ct 5224 -373 5246 -401 5275 -420 ct +5304 -439 5337 -448 5373 -448 ct 5399 -448 5423 -443 5444 -431 ct 5464 -420 5481 -406 5494 -388 ct +5494 -605 l 5568 -605 l 5568 0 l p +5264 -218 m 5264 -162 5276 -120 5299 -92 ct 5323 -65 5351 -51 5383 -51 ct 5416 -51 5443 -64 5466 -91 ct +5489 -117 5500 -158 5500 -212 ct 5500 -272 5489 -316 5465 -344 ct 5442 -373 5414 -387 5380 -387 ct +5347 -387 5319 -373 5297 -346 ct 5275 -319 l 5264 -277 l p ef +pom +gr +51 lw 13970 5080 m 13970 6350 l ps +11010 7920 m 11900 7920 l ps +11010 10460 m 11900 10460 l ps +11010 14605 m 11900 14605 l ps +11010 17245 m 11900 17245 l ps +7835 7955 m 7420 7955 l ps +7835 10460 m 7420 10460 l ps +7835 14605 m 7420 14605 l ps +7835 17245 m 7420 17245 l ps +16013 7955 m 16809 7955 l ps +19984 7920 m 20592 7920 l ps +19984 10460 m 20592 10460 l ps +16013 10495 m 16809 10495 l ps +16013 14605 m 16809 14605 l ps +16013 17245 m 16809 17245 l ps +19984 14605 m 20592 14605 l ps +19984 17245 m 20592 17245 l ps +gr +0 20290 t +pom +count op_count sub {pop} repeat countdictstack dict_count sub {end} repeat b4_inc_state restore +%%PageTrailer +%%Trailer +%%EOF diff --git a/docs/exploring-gnuradio/usrp-block-diagram.png b/docs/exploring-gnuradio/usrp-block-diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..55a0f0b38637603cf006a0a88d500ce7a482077c GIT binary patch literal 35729 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 + Copyright (C) 19yy + + 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 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) 19yy name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/dtools/README b/dtools/README new file mode 100644 index 00000000..e0c76588 --- /dev/null +++ b/dtools/README @@ -0,0 +1,25 @@ +# +# 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. +# + +This is a collection of tools that are useful for building tarball +distributions of GNU Radio. They're probably not of general interest. + +To use, add dtools/bin to PATH and dtools/python to PYTHONPATH diff --git a/dtools/bin/check-config-files b/dtools/bin/check-config-files new file mode 100755 index 00000000..7111c951 --- /dev/null +++ b/dtools/bin/check-config-files @@ -0,0 +1,72 @@ +#!/usr/bin/env python +# usage: takes list of directories on command line + +import sys +import os +import os.path +from itertools import ifilter, ifilterfalse, imap, izip +import md5 +from pprint import pprint +from sets import Set + +class info(object): + def __init__(self, dir, name, md5sum): + self.dir = dir + self.name = name + self.md5sum = md5sum + def __repr__(self): + return '<%r, %r, %r>' % (self.dir, self.name, self.md5sum) + + +def md5sum_file(filename): + f = open(filename, 'r') + m = md5.new(f.read()) + return m.hexdigest() + +def process_dir(dir): + files = list(ifilterfalse(lambda s: s.endswith('~'), + _filter(os.listdir(dir), ('CVS','Makefile', 'Makefile.in', '.svn')))) + return [info(dir, f, md5sum_file(os.path.join(dir, f))) for f in files] + + +# Return a copy with items that occur in skip removed. +# +def _filter(flist, skip): + return list(ifilterfalse(skip.__contains__, flist)) + +def main(): + dirs = sys.argv[1:] + r = [] + for d in dirs: + r += process_dir(d) + + names = Set([x.name for x in r]) + #pprint(names) + + # check for missing files across the union of names + for d in dirs: + names_in_dir = Set([x.name for x in r if x.dir == d]) + diff = names.difference(names_in_dir) + if len(diff) != 0: + print "%s is missing %r" % (d, diff) + + # check for different versions of files + name_list = [n for n in names] + name_list.sort() + + for name in name_list: + vers = {} + pairs = [(x.dir, x.md5sum) for x in r if x.name == name] + for (dir, sum) in pairs: + if vers.has_key(sum): + vers[sum].append(dir) + else: + vers[sum] = [ dir ] + if len(vers) != 1: # multiple versions + print "Multiple versions of %s:" % (name,) + pprint(vers) + + # pprint(r) + +if __name__ == '__main__': + main() diff --git a/dtools/bin/check-imports b/dtools/bin/check-imports new file mode 100755 index 00000000..75ca547d --- /dev/null +++ b/dtools/bin/check-imports @@ -0,0 +1,4 @@ +#!/bin/bash + +find . -name '*.py' | xargs grep -h -E '^(from|import)' | sort -u + diff --git a/dtools/bin/check-tarball-h-files b/dtools/bin/check-tarball-h-files new file mode 100755 index 00000000..f94832c2 --- /dev/null +++ b/dtools/bin/check-tarball-h-files @@ -0,0 +1,23 @@ +#!/bin/bash + +tarball=$1 +if [ "x$tarball" == "x" ] +then + echo "usage: $0 tarball" 1>&2 + exit 1 +fi + +path=${tarball%%.tar.gz} + +tar tzf $tarball \ + | grep -E '\.(h|py|v)$' \ + | sed -e "s/$path/./" \ + | sort >/tmp/tarball-h-files + +find . \( -name '*.h' -o -name '*.py' \) -print | grep -v ./$path | sort >/tmp/build-h-files + +comm -23 /tmp/build-h-files /tmp/tarball-h-files + +# rm /tmp/tarball-h-files /tmp/build-h-files + + diff --git a/dtools/bin/get-config-files b/dtools/bin/get-config-files new file mode 100755 index 00000000..9bdffc12 --- /dev/null +++ b/dtools/bin/get-config-files @@ -0,0 +1,6 @@ +#!/bin/bash + +# fetch latest config.guess and config.sub + +wget http://savannah.gnu.org/cgi-bin/viewcvs/config/config/config.guess?rev=HEAD&content-type=text/plain +wget http://savannah.gnu.org/cgi-bin/viewcvs/config/config/config.sub?rev=HEAD&content-type=text/plain diff --git a/dtools/bin/incr_release b/dtools/bin/incr_release new file mode 100755 index 00000000..167192e2 --- /dev/null +++ b/dtools/bin/incr_release @@ -0,0 +1,37 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 optparse import OptionParser +import release_tools +import os.path + +def main(): + parser = OptionParser() + parser.add_option('-f', '--final', action='store_true', default=False) + (options, args) = parser.parse_args() + + for f in args: + release_tools.incr_release(os.path.join(f, 'configure.ac'), options.final) + +if __name__ == '__main__': + main() + diff --git a/dtools/bin/make-upload b/dtools/bin/make-upload new file mode 100755 index 00000000..73a0feb6 --- /dev/null +++ b/dtools/bin/make-upload @@ -0,0 +1,12 @@ +#!/bin/bash + +read -s -p "GPG Passphrase: " passphrase + +for file in "$@" +do + echo "directory: gnuradio" > $file.directive + echo "$passphrase" | gpg --passphrase-fd 0 --clearsign $file.directive + rm $file.directive + echo "$passphrase" | gpg --passphrase-fd 0 -b $file +done +passphrase="XYZabcdefhghakdsj;lasjdf;ajfdiuiwjr;lajv;laoisfuaoieurlkajdsflkajsdfoiuew" diff --git a/dtools/bin/show_release b/dtools/bin/show_release new file mode 100755 index 00000000..a4eff605 --- /dev/null +++ b/dtools/bin/show_release @@ -0,0 +1,36 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 optparse import OptionParser +import release_tools +import os.path + +def main(): + parser = OptionParser() + (options, args) = parser.parse_args() + + for f in args: + print release_tools.get_release(os.path.join(f, 'configure.ac')) + +if __name__ == '__main__': + main() + diff --git a/dtools/bin/tag_release b/dtools/bin/tag_release new file mode 100755 index 00000000..883b94b4 --- /dev/null +++ b/dtools/bin/tag_release @@ -0,0 +1,47 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 optparse import OptionParser +import release_tools +import os +import os.path +import sys + +def main(): + parser = OptionParser() + (options, args) = parser.parse_args() + + exit_code = 0 + for d in args: + f = os.path.join(d, 'configure.ac') + rel = release_tools.get_release(f) + if rel is None: + raise ValueError, "%s: couldn't find version" % (f,) + tag = release_tools.make_tag(rel) + cmd = '(cd %s; cvs tag %s)' % (d, tag) + print cmd + exit_code = exit_code | os.system(cmd) + + sys.exit(exit_code) + +if __name__ == '__main__': + main() diff --git a/dtools/python/release_tools.py b/dtools/python/release_tools.py new file mode 100644 index 00000000..788ede55 --- /dev/null +++ b/dtools/python/release_tools.py @@ -0,0 +1,87 @@ +# +# 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. +# + +import re +import os + +def get_release(configure_ac_filename): + f = open(configure_ac_filename,'r') + contents = f.read() + pat = re.compile('^AM_INIT_AUTOMAKE\((.*),(\d+)\.(\d+)(.*)\)', re.M) + mo = pat.search(contents) + if mo: + return mo.groups() + +def set_release(configure_ac_filename, new_release): + f = open(configure_ac_filename,'r') + contents = f.read() + pat = re.compile('^AM_INIT_AUTOMAKE\(((.*),(\d+)\.(\d+)(.*))\)', re.M) + repl = ''.join(('AM_INIT_AUTOMAKE(', + new_release[0], + ',', + new_release[1], + '.', + new_release[2],new_release[3],')')) + new = pat.sub(repl, contents) + return new + +def incr_release(configure_ac_filename, final=False): + cur = get_release(configure_ac_filename) + if cur is None: + raise ValueError, "%s: couldn't find version" % (configure_ac_filename,) + new = set_release(configure_ac_filename, up_rev(cur, final)) + os.rename(configure_ac_filename, configure_ac_filename + '.bak') + f = open(configure_ac_filename,'w') + f.write(new) + f.close() + +def up_rev(current_rev, final=False): + """ + X.Y -> X.Ycvs + if final: + X.Ycvs -> X.(Y+1)rc1 + else: + X.Ycvs -> X.(Y+1) + if final: + X.YrcN -> X.Y + else + X.YrcN -> X.Yrc(N+1) + """ + pkg, major, minor, suffix = current_rev + + if len(suffix) == 0: + if final: + raise RuntimeError, ("Can't go from current to final. current = " + str(current_rev)) + return (pkg, major, minor, "cvs") + if suffix == "cvs": + if final: + return (pkg, major, str(int(minor)+1), "") + return (pkg, major, str(int(minor)+1), "rc1") + elif suffix.startswith('rc'): + if final: + return (pkg, major, minor, "") + return (pkg, major, minor, "rc" + (str(int(suffix[2:]) + 1))) + +def make_tag(current_rev): + pkg, major, minor, suffix = current_rev + if suffix == "cvs": + raise ValueError, "You tried to tag a X.Ycvs release..." + return 'REL_%s_%s%s' % (major, minor, suffix) diff --git a/gnuradio-core/ChangeLog b/gnuradio-core/ChangeLog new file mode 100644 index 00000000..776ab8ca --- /dev/null +++ b/gnuradio-core/ChangeLog @@ -0,0 +1,1893 @@ +2006-07-06 Tom Rondeau + + * src/python/gnuradio/blksimpl/gmsk2.py: + Added AGC to GMSK code. + +2006-07-06 Tom Rondeau + + * src/python/gnuradio/blksimpl/Makefile.am: + Call to gmsk.py was causing error after removal of gmsk.py file. + Removed call in Makefile.am to this. + +2006-07-05 Eric Blossom + + * src/python/gnuradio/blksimpl/gmsk.py: Removed long deprecated + code. We'll give this a week or so for the dust to settle, then + we'll rename gmsk2.py to gmsk.py + +2006-06-29 Tom Rondeau + + * src/lib/general/gr_correlate_access_code_bb.cc (work): + Removed branches; cleaned up code to only deal with a 180 degree phase shift in + BPSK. + +2006-06-28 Tom Rondeau + + * src/python/gnuradio/gr/qa_correlate_access_code.py (test_correlate_access_code.test_001): + Changes to access code correlator to handle BPSK phase reversal + killed qa_correlate_access_code. Modified the access code search in + test_001 to all the test to pass properly. + +2006-06-28 Tom Rondeau + + * src/lib/general/gr_constellation_decoder_cb.cc: + Set Compute_EVN=false by default (to clean up the output) + +2006-06-20 Tom Rondeau + + * src/lib/general/gr_costas_loop_cc.{h,cc,i}: modified to support + both BPSK and QPSK via "order" constructor argument. Removed + unused ref_phase ctor arg. + +2006-06-20 Eric Blossom + + * src/lib/general/gr_probe_avg_mag_sqrd_{f,c}.{h,cc,i}: added accessor + for threshold. + + * src/python/gnuradio/blksimpl/pkt.py: result of refactoring + gmsk2_pkt.py. This is the common packet handling framework, and + is modulation independent. gmsk2_pkt is now deprecated. + + * src/python/gnuradio/blksimpl/gmsk2_pkt.py: added deprecation warning. + + * src/python/gnuradio/packet_utils.py (make_packet): added + bits_per_baud parameter to handle QPSK, etc in the future. + +2006-06-17 Eric Blossom + + * src/lib/runtime/gr_realtime.{h,cc,i}: new function to enable + realtime scheduling. + +2006-06-15 Eric Blossom + + * src/lib/io/gr_oscope_guts.{h,cc,i}, + src/lib/io/gr_oscope_sink_x.{h,cc}: added set_sample_rate method. + + * src/lib/general/gr_keep_one_in_n.{h,cc,i}: added set_n method. + +2006-06-13 Eric Blossom + + * src/lib/general/gr_binary_slicer_fb.h: corrected calling sequence. + +2006-06-08 Eric Blossom + + * src/lib/general/gr_feval.{h,cc,i}, + src/python/gnuradio/gr/qa_feval.py: new C++/python helper that + allows C++ code to evaluate a function defined in Python. Uses + SWIG directors. + +2006-06-06 Eric Blossom + + * src/lib/general/gr_unpack_k_bits_bb.cc (work): bug fix. Was + computing the wrong answer and writing *way* too much data if k was > 1. + * src/python/gnuradio/gr/qa_unpack_k_bits.py: new ;) + + * src/lib/general/gr_diff_decoder_bb.{h,cc,i}: new. differential + decoder. constellation index in / constellation index out. + + * src/lib/general/gr_map_bb.{h,cc,i}: new. map any byte into any + other byte. + +2006-06-01 Eric Blossom + + * src/lib/filter/ccomplex_dotprod_3dnow64.S, + src/lib/filter/3dnow_float_dotprod_really_simple.S, + src/lib/filter/3dnow_float_dotprod_simple.S, + src/lib/filter/assembly.h, + src/lib/filter/ccomplex_dotprod_3dnow.S, + src/lib/filter/ccomplex_dotprod_3dnow64.S, + src/lib/filter/ccomplex_dotprod_3dnowext.S, + src/lib/filter/ccomplex_dotprod_3dnowext64.S, + src/lib/filter/ccomplex_dotprod_sse.S, + src/lib/filter/ccomplex_dotprod_sse64.S, + src/lib/filter/complex_dotprod_3dnow.S, + src/lib/filter/complex_dotprod_3dnow64.S, + src/lib/filter/complex_dotprod_3dnowext.S, + src/lib/filter/complex_dotprod_3dnowext64.S, + src/lib/filter/complex_dotprod_sse.S, + src/lib/filter/complex_dotprod_sse64.S, + src/lib/filter/fcomplex_dotprod_3dnow.S, + src/lib/filter/fcomplex_dotprod_3dnow64.S, + src/lib/filter/fcomplex_dotprod_sse.S, + src/lib/filter/fcomplex_dotprod_sse64.S, + src/lib/filter/float_dotprod_3dnow.S, + src/lib/filter/float_dotprod_3dnow64.S, + src/lib/filter/float_dotprod_sse.S, + src/lib/filter/float_dotprod_sse64.S, + src/lib/filter/short_dotprod_mmx.S, + src/lib/filter/short_dotprod_mmx64.S: changed all occurrences of + .align 16 to .p2align 4 to avoid ambiguous interpretation of .align + argument. + + +2006-05-29 Eric Blossom + + * src/python/gnuradio/blksimpl/gmsk2_pkt.py: now uses string of 1's + and 0's for access_code representation. Refactored to use + correlate_access_code_bb and frame_sink_1 instead of packet_sink. + + * src/lib/general/gr_binary_slicer_fb.{h,cc,i}: new + * src/lib/general/gr_qpsk_slicer_cb.{h,cc,i}: deleted. Use + gr_constellation_decoder_cb instead. + +2006-05-29 Eric Blossom + + * src/lib/general/gr_clock_recovery_mm_cc.cc: revised + implementation based on 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. + Thanks Tom! + + * src/utils/cool.m, src/utils/db_width.m, src/utils/filter_tools.m, + src/utils/read_char_binary.m, src/utils/read_complex_binary.m, + src/utils/read_float_binary.m, src/utils/read_int_binary.m, + src/utils/read_short_binary.m: modified to be compatible with + MATLAB. + +2006-05-26 Eric Blossom + + * src/lib/general/gr_framer_sink_1.{h,cc,i}: new. Refactored from + gr_packet_sink. Use in combination with gr_correlate_access_code_bb. + +2006-05-24 Eric Blossom + + * src/lib/general/gr_diff_encoder_bb.{h,cc,i}: new. differential encoder. + + * src/lib/general/gr_constellation_decoder_cb.{h,cc,i}: new. + Maps i/q value to closest constellation point and return value + associated with the point. This probably obsoletes + gr_qpsk_slicer_cb. + + * src/lib/general/gr_qpsk_slicer_cb.{h,cc,i}: new. + * src/lib/general/gr_unpack_k_bits_bb.{h,cc,i}: unpack bytes + containing k valid bits, into bytes, 1 bit per byte. + + * src/lib/general/gr_correlate_access_code_bb.{h,cc,i}: new. + General purpose block for searching for access codes (sync + vectors). Can handle any sync vector between 1 and 64 bits. + +2006-05-23 Eric Blossom + + * src/lib/general/gr_diff_phasor_cc.{h,cc,i}: new. Compute phase + difference as a complex number between adjacent complex items in + stream. This is useful for demodulating differentially encoded PSK. + + * src/python/gnuradio/gruimpl/mathmisc.py (log2): new function. + + * src/lib/general/gr_firdes.cc (root_raised_cosine): force ntaps + to be odd. + +2006-05-21 Martin Dudok van Heel + + Added generic test class gr_test. + gr_test is a gnuradio block meant to be used in a flow_graph. + It doesn't do much processing, but you can specify from python every parameter you need to for testing. + For example history, output_multiple, input and output signature, decimation and such. + Especially handy for testing setting up the buffers. + It also touches every available input and output to check for segfaults. + You can also instruct it to not consume all ninput_items or not produce all noutput_items. + + There is also a new script test_buffers.py in src/tests which uses gr_test to test setting up the buffers. + It is NOT automatically run by make check yet, because it will fail with an assert when it reaches circbuf memory limit of the system. + (On linux: Trying to setup a buffer >shmmax + Note that you can set the smmax limit manually on a linux 2.6 system in the following way in a root console) + #set shmmax limit manually to 300MB + echo 300000000 >/proc/sys/kernel/shmmax + + * src/lib/general/Makefile.am: added gr_test + * src/lib/general/general.i: added gr_test + * src/lib/general/gr_test.cc: new + * src/lib/general/gr_test.h: new + * src/lib/general/gr_test.i: new + * src/lib/general/gr_test_types.h: new + * src/tests/test_buffers.py: new script to test setting up the buffers using gr_test + +2006-05-21 Martin Dudok van Heel + + Solved the following bugs which result from incorrect buffersize setup: + sched: is requesting more input data + than we can provide. + ninput_items_required = 8192 + max_possible_items_available = 8191 + If this is a filter, consider reducing the number of taps. + + python: src/lib/runtime/gr_buffer.h:108: unsigned int gr_buffer::index_sub(unsigned int, unsigned int): + Assertion `(unsigned) s < d_bufsize' failed. + Aborted + + * src/python/gnuradio/gr/flow_graph.py: resolved above bugs by adding + mdown.history() to nitems when appropriate + +2006-04-24 Eric Blossom + + * src/lib/general/gr_chunks_to_symbols_XX.{h,cc,i}.t, + src/lib/general/gr_packed_to_unpacked_XX.{h,cc,i}.t, + src/lib/general/gr_unpacked_to_packed_XX.{h,cc,i}.t: + new pseudo-templates for generating family of blocks. Patch + submitted by Achilleas Anastasopoulos , touched + up by Eric. + +2006-04-24 Martin Dudok van Heel + + * src/python/gnuradio/gr/flow_graph.py (buffer_sizes.allocate): + increase buffer size allocation for blocks with a large + output_multiple, not just those that are decimators. + +2006-04-05 Eric Blossom + + * src/lib/general/gr_pll_carriertracking_cc.i: added + squelch_enable and set_lock_threshold methods. + + * src/lib/general/gr_clock_recovery_mm_cc.h: removed erroneous + class prefix to method. GCC 4.1.0 complains ;) + +2006-04-03 Eric Blossom + + * src/lib/general/gr_pll_carriertracking_cc.cc (phase_detector): + fixed typo. + + * src/python/gnuradio/gr/prefs.py: don't load prefs if + GR_DONT_LOAD_PREFS environment variable is set. run_tests sets + this to avoid interactions with system and user prefs during + make check. + + * src/python/gnuradio/gr/qa_rational_resampler.py: disabled two + tests that were causing hangs on SuSE 10.0. Should be investigated. + +2006-03-30 Eric Blossom + + * src/lib/filter/gr_fft_filter_ccc.{h,cc}, + src/lib/filter/gr_fft_filter_fff.{h,cc}: reworked to allow + safer setting of new taps after instantiation. + +2006-03-29 Eric Blossom + + * src/lib/general/gr_prefix.{h,cc,i}: new function that returns + installation prefix directory (--prefix argument to configure). + + * src/lib/general/gr_prefs.{h,cc,i}: reworked implementation to + use python ConfigParser. + * src/python/gnuradio/gr/prefs.py: moved from + src/python/gnuradio/prefs.py to solve initialization problem. + + * src/lib/general/gr_stream_to_vector.{h,cc,i}: renamed from gr_serial_to_parallel + * src/lib/general/gr_vector_to_stream.{h,cc,i}: renamed from gr_parallel_to_serial + * src/lib/python/gnuradio/gr/__init__.py: new aliases for + backwards compatibility with rename. + + * src/lib/swig/Makefile.am: cleanup for make distcheck. + + * src/lib/atsc/GrAtscBitTimingLoop.cc, GrAtscBitTimingLoop.h, + GrAtscBitTimingLoop2.cc, GrAtscBitTimingLoop2.h, + GrAtscBitTimingLoop3.cc, GrAtscBitTimingLoop3.h, + GrAtscConvert2xTo20.cc, GrAtscConvert2xTo20.h, + GrAtscDataSegToSoftDataSeg.cc, GrAtscDataSegToSoftDataSeg.h, + GrAtscDeinterleaver.cc, GrAtscDeinterleaver.h, + GrAtscDerandomizer.cc, GrAtscDerandomizer.h, + GrAtscEqualizer.cc, GrAtscEqualizer.h, GrAtscFPLL.cc, + GrAtscFPLL.h, GrAtscFieldSyncChecker.cc, + GrAtscFieldSyncChecker.h, GrAtscFieldSyncCorrelator.cc, + GrAtscFieldSyncCorrelator.h, GrAtscFieldSyncDemux.cc, + GrAtscFieldSyncDemux.h, GrAtscFieldSyncMux.cc, + GrAtscFieldSyncMux.h, GrAtscInterleaver.cc, + GrAtscInterleaver.h, GrAtscRSDecoder.cc, GrAtscRSDecoder.h, + GrAtscRSEncoder.cc, GrAtscRSEncoder.h, GrAtscRandomizer.cc, + GrAtscRandomizer.h, GrAtscSegSymSync.cc, GrAtscSegSymSync.h, + GrAtscSegSymSyncImpl.cc, GrAtscSegSymSyncImpl.h, + GrAtscSegSymSyncImpl_export.h, GrAtscSymbolMapper.h, + GrAtscTrellisEncoder.cc, GrAtscTrellisEncoder.h, + GrAtscViterbiDecoder.cc, GrAtscViterbiDecoder.h, Makefile.am, + README, atsc_basic_trellis_encoder.cc, + atsc_basic_trellis_encoder.h, atsc_consts.h, + atsc_data_interleaver.cc, atsc_data_interleaver.h, + atsc_diag_output.h, atsc_equalizer.cc, atsc_equalizer.h, + atsc_equalizer_lms.cc, atsc_equalizer_lms.h, + atsc_equalizer_lms2.cc, atsc_equalizer_lms2.h, + atsc_equalizer_nop.cc, atsc_equalizer_nop.h, atsc_exp2_lp.cc, + atsc_exp2_lp.h, atsc_exp2_lp20.dat, atsc_exp2_lp2x.dat, + atsc_fake_single_viterbi.cc, atsc_fake_single_viterbi.h, + atsc_fs_checker.cc, atsc_fs_checker.h, + atsc_fs_checker_naive.cc, atsc_fs_checker_naive.h, + atsc_fs_correlator.cc, atsc_fs_correlator.h, + atsc_fs_correlator_naive.cc, atsc_fs_correlator_naive.h, + atsc_pnXXX.cc, atsc_pnXXX.h, atsc_randomizer.cc, + atsc_randomizer.h, atsc_reed_solomon.cc, atsc_reed_solomon.h, + atsc_root_raised_cosine.cc, atsc_root_raised_cosine.h, + atsc_root_raised_cosine_bandpass.cc, + atsc_root_raised_cosine_bandpass.h, atsc_single_viterbi.cc, + atsc_single_viterbi.h, atsc_slicer_agc.h, + atsc_sliding_correlator.cc, atsc_sliding_correlator.h, + atsc_sssr.cc, atsc_sssr.h, atsc_syminfo.h, atsc_sync_tag.h, + atsc_trellis_encoder.cc, atsc_trellis_encoder.h, atsc_types.h, + atsc_viterbi_decoder.cc, atsc_viterbi_decoder.h, + atsc_viterbi_gen.cc, atsc_vsbtx_lp.cc, atsc_vsbtx_lp.dat, + atsc_vsbtx_lp.h, convolutional_interleaver.h, + create_atsc_equalizer.cc, create_atsc_equalizer.h, + create_atsc_fs_checker.cc, create_atsc_fs_checker.h, + create_atsc_fs_correlator.cc, create_atsc_fs_correlator.h, + fpll_btloop_coupling.h, gen_encoder.py, interleaver_fifo.h, + plinfo.cc, qa_atsc.cc, qa_atsc.h, + qa_atsc_basic_trellis_encoder.cc, + qa_atsc_basic_trellis_encoder.h, qa_atsc_data_interleaver.cc, + qa_atsc_data_interleaver.h, qa_atsc_equalizer_nop.cc, + qa_atsc_equalizer_nop.h, qa_atsc_fake_single_viterbi.cc, + qa_atsc_fake_single_viterbi.h, qa_atsc_fs_correlator.cc, + qa_atsc_fs_correlator.h, qa_atsc_randomizer.cc, + qa_atsc_randomizer.h, qa_atsc_reed_solomon.cc, + qa_atsc_reed_solomon.h, qa_atsc_single_viterbi.cc, + qa_atsc_single_viterbi.h, qa_atsc_sliding_correlator.cc, + qa_atsc_sliding_correlator.h, qa_atsc_trellis_encoder.cc, + qa_atsc_trellis_encoder.h, + qa_atsc_trellis_encoder_t1_input.dat, + qa_atsc_trellis_encoder_t1_output.dat, + qa_atsc_viterbi_decoder.cc, qa_atsc_viterbi_decoder.h, + qa_atsc_viterbi_decoder_t1_input.dat, + qa_atsc_viterbi_decoder_t1_output.dat, + qa_convolutional_interleaver.cc, + qa_convolutional_interleaver.h, qa_interleaver_fifo.cc, + qa_interleaver_fifo.h: Moved all atsc code from src/lib/atsc to + new gr-atsc CVS module. + + * src/lib/general/gri_ringbuffer.{h,cc}: removed. Use + gr_buffer/gr_buffer_reader instead. + +2006-03-27 Eric Blossom + + * src/lib/general/gr_prefs.{h,cc,i}: renamed parameter from "val" to + "v" to work around issue in SWIG 1.3.{28,29} and/or g++ 4.0.2. + + * src/lib/general/gr_prefs.{h,cc,i}, src/python/gnuradio/prefs.py: + new class for user preferences. This uses SWIG directors (serious + magic), to have the actual implementation be in python, but + callable transparently from C++. We'll use this for user prefs + such as audio module, audio module options, etc. + +2006-03-25 Eric Blossom + + * src/lib/io/gri_logger.h (class gri_logger): new class that can + safely log to a file from within a JACK or portaudio callback. + Uses a ringbuffer to communicate with a separate thread that + writes the file. + +2006-03-17 Eric Blossom + + * src/lib/runtime/gr_buffer.cc (gr_buffer_reader): added missing + drop_reader call to destructor. Fixed latent bug. + +2006-03-15 Eric Blossom + + * src/lib/omnithread.h, + src/lib/omnithread/ot_posix.h, src/lib/omnithread/posix.cc, + src/lib/omnithread/nt.cc: mods to + allow specifying a max count on semaphores. This allows the + construction of binary semaphores by passing max_count=1 to the ctor. + The default behavior is unchanged. + +2006-03-13 Eric Blossom + + * src/lib/general/gr_pll_carriertracking_cc.cc (work): refactored + loop control. + +2006-03-12 Stephane Fillod + * src/lib/general/gri_ringbuffer.{cc,h}, + src/lib/general/Makefile.am: new lockless ringbuffer (single + reader/single writer) taken from JACK software (GPL). + * * src/lib/omnithread/omnithread.h: add omni_mutex::trylock + * * src/lib/omnithread/ot_posix.h: POSIX trylock implementation + * * src/lib/omnithread/ot_nt.h: Win32 trylock implementation + +2006-03-12 Eric Blossom + + * src/lib/general/gr_firdes.h, src/lib/io/gr_file_source.h: Fix + for g++ 4.1. Removed extra class:: qualification. Patch + submitted by Martin Michlmayr + +2006-03-10 Eric Blossom + + * src/lib/general/gr_dd_mpsk_sync_cc.cc: doc fixes. reworked + delay line handling. + * src/lib/general/gr_dd_mpsk_sync_cc.h: doc fixes. Added DLLEN const. + * src/lib/general/gr_costas_loop_cc.h: doc fixes. + * src/lib/general/gr_costas_loop_cc.cc (work): cosmetic tweak to + loop control. + +2006-03-07 Eric Blossom + + * src/lib/general/gr_multiply_const_XX.h.t, + src/lib/general/gr_quadrature_demod_cf.h, + src/lib/general/gr_frequency_modulator_fc.h, + src/lib/general/gr_packed_to_unpacked_bb.h, + src/lib/general/gr_unpacked_to_packed_bb.h, + src/lib/general/gr_chunks_to_symbols_bf.h, + src/lib/general/gr_chunks_to_symbols_bc.h: doc fixs. + +2006-02-22 Martin Dudok van Heel + + Addded new blocks gr_single_pole_iir_filter_cc + gr_agc_cc + gr_phase_modulator_fc + Changed gr_single_pole_iir.h to make this work + Bugfix, to make make_check work again. + + * src/lib/filter/Makefile.am: Added gr_single_pole_iir_filter_cc + Added missing gr_single_pole_avg.h and gr_single_pole_rec.h (fix make check bug) + * src/lib/filter/filter.i: changed. Added gr_single_pole_iir_filter_cc + * src/lib/filter/gr_single_pole_iir.h: changed template to have + partial specialization for . Needed + because calculations and temporary variables have to be + gr_complexd in this special case + * src/lib/filter/gr_single_pole_iir_filter_cc.cc: new + * src/lib/filter/gr_single_pole_iir_filter_cc.h: new + * src/lib/filter/gr_single_pole_iir_filter_cc.i: new + * src/lib/general/Makefile.am: changed. Added gr_agc_cc, gr_phase_modulator_fc,gri_agc_cc + * src/lib/general/general.i: changed. Added gr_agc_cc, gr_phase_modulator_fc + * src/lib/general/gr_agc_cc.cc: new + * src/lib/general/gr_agc_cc.h: new + * src/lib/general/gr_agc_cc.i: new + * src/lib/general/gr_phase_modulator_fc.cc: new + * src/lib/general/gr_phase_modulator_fc.h: new + * src/lib/general/gr_phase_modulator_fc.i: new + * src/lib/general/gri_agc_cc.h: new + * src/lib/general/gri_agc_cc.i: new + * src/python/gnuradio/gr/Makefile.am: changed. Added qa_single_pole_iir_cc.py + * src/python/gnuradio/gr/qa_single_pole_iir_cc.py: new + +2006-02-17 Stephane Fillod + + * configure.ac, src/lib/filter/ccomplex_dotprod_generic.cc, + src/lib/filter/complex_dotprod_generic.cc, + src/lib/filter/generate_gr_fir_sysconfig.py, + src/lib/filter/generate_gr_fir_sysconfig_generic.py, + src/lib/filter/generate_gr_fir_util.py, + src/lib/filter/gr_fir_XXX.cc.t, + src/lib/filter/gr_fir_XXX_generic.cc.t, + src/lib/filter/gr_fir_ccc_simd.cc, + src/lib/filter/gr_fir_ccc_x86.cc, + src/lib/filter/gr_fir_ccf_simd.cc, + src/lib/filter/gr_fir_ccf_x86.cc, + src/lib/filter/gr_fir_fcc_simd.cc, + src/lib/filter/gr_fir_fcc_x86.cc, + src/lib/filter/gr_fir_fff_simd.cc, + src/lib/filter/gr_fir_fff_x86.cc, + src/lib/filter/gr_fir_fsf_simd.cc, + src/lib/filter/gr_fir_fsf_x86.cc, + src/lib/filter/gr_fir_scc_simd.cc, + src/lib/filter/gr_fir_scc_x86.cc, + src/lib/filter/gr_fir_sysconfig_x86.cc, + src/lib/filter/gri_mmse_fir_interpolator.cc, + src/lib/filter/gri_mmse_fir_interpolator_cc.cc, + src/lib/filter/sysconfig_x86.cc, + src/lib/general/gr_align_on_samplenumbers_ss.cc, + src/lib/general/gr_crc32.cc, + src/lib/general/gr_head.cc, + src/lib/general/gr_lfsr_32k_source_s.cc, + src/lib/general/gr_noise_source_X.cc.t, + src/lib/general/gr_nop.cc, + src/lib/general/gr_reverse.cc, + src/lib/general/gr_sig_source_X.cc.t, + src/lib/general/gr_simple_correlator.cc, + src/lib/general/gr_simple_framer.cc, + src/lib/general/gr_skiphead.cc, + src/lib/general/gr_vector_sink_X.cc.t, + src/lib/general/gr_vector_source_X.cc.t, + src/lib/general/qa_gr_fxpt.cc, + src/lib/general/qa_gr_fxpt_nco.cc, + src/lib/general/qa_gr_fxpt_vco.cc, + src/lib/io/gr_oscope_guts.cc, + src/lib/runtime/gr_io_signature.cc, + src/lib/runtime/gr_types.h, + src/lib/runtime/qa_gr_block.cc, + src/lib/runtime/qa_gr_buffer.cc, + src/lib/runtime/qa_gr_io_signature.cc: added proper config check + for stdint.h to define gr_int* types. + +2006-02-16 Eric Blossom + + * src/lib/runtime/gr_types.h: added typedef for gr_int64 and + gr_uint64. Need proper autoconf fix for these. + +2006-02-08 Eric Blossom + + * src/lib/io/gr_file_sink.{h,cc,i}: added new methods: enable & + disable. Thanks Marcus! + +2006-02-06 Eric Blossom + + * src/lib/general/gr_kludge_copy.{h,cc,i}: new. Copies input to output. + * src/python/gnuradio/gr/qa_kludge_copy.py: new QA code. + +2006-02-05 Eric Blossom + + * src/python/gnuradio/gr/qa_iir.py (test_iir.test_iir_direct_008): + accept either RuntimeError or ValueError in test case. The return + value changed in swig 1.3.28. + + * src/lib/swig/gnuradio.i: now use anonymous templates for + std::vector's. This was a tip from one of the SWIG developers. + It generates less code. + +2006-02-02 Eric Blossom + + * src/python/gnuradio/gruimpl/seq_with_cursor.py: added method to + select closest index by value. + +2006-01-30 Eric Blossom + + * src/lib/general/gr_packet_sink.{h,i}: Added new "carrier_sensed" + method. Naive implementation, but it just might work ;) + * src/python/gnuradio/blksimpl/gmsk2_pkt.py (carrier_sensed): new method. + +2006-01-28 Eric Blossom + + * src/lib/general/gr_pa_2x2_phase_combiner.{h,cc,i}: new. + four antenna phase combiner for phased array experiments. + + * src/lib/general/gr_simple_squelch_cc.{h,cc,i}: added threshold + and squelch_range methods. + +2006-01-24 Eric Blossom + + * src/lib/general/gr_sync_block.cc (forecast): removed duplicated code. + * src/lib/general/gr_sync_interpolator.cc (forecast): removed duplicated code. + * src/lib/general/gr_sync_decimation.cc (forecast): removed duplicated code. + * src/lib/runtime/gr_single_threaded_scheduler.cc (main_loop): + take advantage of fixed_rate() method so that we can consume all + available input. Fixed bad audio sound with encdec. + +2005-12-23 Eric Blossom + + * src/lib/general/gr_interleaved_short_to_complex.i (class + gr_interleaved_short_to_complex): corrected superclass spec. + +2005-12-19 Martin Dudok van Heel + + Addded a new blocks to convert from unsigned char to float and for char to float. + Added new agc block gr_agc_ff based on existing gr_agc block + (which can't be directly used in a flowgraph). All needed for + tv-reception. + + * src/lib/general/gr_uchar_to_float.{cc,h,i}: new + * src/lib/general/gri_uchar_to_float.{cc,h}: new + * src/lib/general/gr_char_to_float.{cc,h,i}: new + * src/lib/general/gri_char_to_float.{cc,h}: new + * src/lib/general/gr_agc_ff.cc: new + * src/lib/general/gr_agc_ff.h: new + * src/lib/general/gr_agc_ff.i: new + * src/lib/general/Makefile.am: changed. Added gr_agc_ff, + gr_(u)char_to_float and gri_(u)char_to_float. + * src/lib/general/general.i: changed. Added + gr_agc_ff,gr_(u)char_to_float and gri_(u)char_to_float. + +2005-12-17 Eric Blossom + + * src/lib/general/gr_quadrature_demod_cf.cc: use fast arctan code. + +2005-12-17 Bob McGwier N4HY + + * src/lib/general/gr_lms_dfe_cc.{h,cc,i}: new. + * src/lib/general/gr_fast_atan2f.cc: new. Fast arc tangent using + table lookup and interpolation. Declaration added to gr_math.h + +2005-12-17 Eric Blossom + + * src/lib/general/gr_lms_dfe_ff.h: doc fix. + * src/lib/general/gr_lms_dfe_ff.cc: refactored. Moved common + functions to gr_misc + * src/lib/general/gr_misc.{h,cc}: new. Collect misc functions in + one place. + * doc/Makefile.am: --enable-doxygen default is now "no" + +2005-12-16 Eric Blossom + + * src/lib/swig/gnuradio_swig_bug_workaround.h: removed from CVS. + It's generated when it's needed. + +2005-12-09 Eric Blossom + + made 2.6 release. + +2005-12-08 Chuck Swiger + + * src/lib/general/gr_probe_signal_f.{h,cc,i}: new. Return a + single sample from the stream. + +2005-12-07 Chuck Swiger + + * src/lib/general/gr_probe_avg_mag_sqrd_{f,c}.{h,cc,i}: new. + Sinks that measure the average magnitude squared and allow the + value to be retrieved via accessors. + +2005-12-06 Eric Blossom + + * src/lib/general/gr_clock_recovery_mm_ff.cc: doc fix: added reference to book. + +2005-12-01 Eric Blossom + + * src/lib/general/gr_packet_sink.h (class gr_packet_sink): changed + d_threshold to unsigned to eliminate warning. + * src/lib/general/gr_simple_correlator.cc: removed duplicate + definition of slice. + +2005-12-01 Stephane Fillod + + * src/lib/general/gr_count_bits.cc (gr_count_bits32): faster + implementation. No branching. + +2005-11-22 Ramakrishnan Muthukrishnan + + * src/python/gnuradio/gr/qa_filter_delay_fc.py, + src/python/gnuradio/gr/qa_hilbert.py: updated QA code to reflect + change in delay line handling. + +2005-11-21 Eric Blossom + + * config/gr_boost.m4: reworked to look for latest version if + installed in version-specific subdir of /usr/local/include. + * src/lib/swig/Makefile.am (DISTCLEANFILES): added gnuradio_swig_python.d + +2005-11-19 Eric Blossom + + * config/usrp_libusb.m4 (USRP_LIBUSB): add -lIOKit under darwin. + * config/gr_no_undefinedm4, config/gr_set_md_cpu.m4, + config/gr_x86_64.m3, config/usrp_fusb_tech.m4, + config/usrp_libusb.m4: changed incorrect use of + AC_CANONICAL_TARGET to HOST. + +2005-11-18 Eric Blossom + + These changes enabled discontinous transmission of usrp packets. + The treatment of history was slightly changed. Now we provide + zeros for the initial delay lines and produce N outputs for N + inputs. In the past we would produce N-history-1 outputs for N inputs. + + * src/python/gnuradio/packet_utils.py: ensure at least a single + byte of padding to flush filters. + * src/lib/runtime/gr_block.{h,cc,i}, + src/lib/general/gr_sync_block.{h,cc,i}, + src/lib/general/gr_sync_decimator.{h,cc,i}, + src/lib/general/gr_sync_interpolator.{h,cc,i}: moved history into + gr_block from gr_sync_block. Added new methods to support fast + path through scheduler: fixed_rate, fixed_rate_ninput_to_output + and fixed_rate_noutput_to_input. + + * src/python/gnuradio/gr/flow_graph.py (flow_graph._connect_inputs): + account for initial history when attaching buffer reader. + * src/lib/runtime/gr_buffer.{h,cc,i} (gr_buffer_add_reader): modified to + provide zeros for initial history. + + * src/python/gnuradio/gr/qa_fft_filter.py, + src/python/gnuradio/gr/qa_filter_delay_fc.py, + src/python/gnuradio/gr/qa_hilbert.py, + src/python/gnuradio/gr/qa_interp_fir_filter.py, + src/python/gnuradio/gr/qa_rational_resampler.py: tweaked QA code + to work with new history behavior. + + +2005-11-17 Eric Blossom + + * src/lib/filter/gr_interp_fir_filter_XXX.cc.t, + gr_rational_resampler_base_XXX.cc.t: ensure that history is set in + constructor. + + * src/lib/runtime/gr_msg_queue.i: more evil hackery to release + Python global interpreter lock around blocking msg_queue methods. + + * src/python/gnuradio/packet_utils.py (make_packet): conditionally + add padding such that final packet is a multiple of 512 bytes on the USB. + +2005-11-16 Eric Blossom + + * src/lib/io/gr_message_source.h (class gr_message_source): added + msgq limit to constructor args. + + * src/lib/general/gr_packet_sink.{h,cc,i}: added access code + detection threshold to ctor args. + + * src/lib/filter/gri_mmse_fir_interpolator.{h,cc}: declared interpolate const. + + * src/lib/general/gr_clock_recovery_mm_ff.cc: limit excursions of + omega using omega_relative_limit. Added conditional diagnostic logging. + + * src/lib/runtime/gr_msg_queue.{h,cc}: block when inserting into a + full msg queue. + + * src/lib/filter/gr_fractional_interpolator.cc (general_work): + 1.0 - d_mu -> d_mu to match revised filter defs. + +2005-11-15 Eric Blossom + + * src/lib/io/gr_oscope_guts.{h,cc}, + src/lib/io/gr_oscope_sink_f.{h,cc,i}: Refactored to use messages + and message queues to communicate to Python. This code will never + block waiting for the gui. + * src/lib/io/gr_message_sink.{h,cc,i}: new. A sink that packages up its + input and puts it in a message queue. + +2005-11-14 Eric Blossom + + * doc/Doxyfile.in: updated to latest version. Turned off serveral + options to reduce documentation generation time. + +2005-11-13 Eric Blossom + + * src/python/gnuradio/blksimpl/gmsk2.py, + src/python/gnuradio/blksimpl/gmsk2_pkt.py: new GMSK mod/demod. + * src/python/gnuradio/gruimpl/mathmisc.py: new: gcd, lcm. + * src/python/gnuradio/blksimpl/rational_resampler.py: If neither + taps nor fractional_bw is supplied, provide a reasonable default. + +2005-11-11 Eric Blossom + + * src/lib/filter/qa_gri_mmse_fir_interpolator.cc (t1): revised sign. + + * src/lib/filter/gr_fir_filter_XXX.cc.t (work): if taps updated, return 0. + * src/lib/filter/gr_interp_fir_filter_XXX.cc.t (work): if taps updated, return 0. + +2005-11-09 Matt Ettus + + * src/lib/general/gr_packet_sink.cc (gr_make_packet_sink): new. + slices, correlates for packet access code, checks header and + assembles packets. + +2005-11-09 Eric Blossom + + * src/lib/io/gr_message_source.h: new class. Messages sent to + this class are streamed to its single output. + + * src/lib/runtime/gr_message.{h,cc,i}: removed unused methods; new + constructor from string; get contents as string. + + * src/lib/filter/gri_mmse_fir_interpolator.{h,cc}: renamed from gr_mmse_fir_interpolator. + * src/lib/filter/gr_fractional_interpolator.{h,cc,i}: new. + +2005-11-08 Eric Blossom + + * src/lib/general/gr_crc32.{h,cc,i}: new. ISO 3309 CRC-32 generator. + +2005-11-08 Matt Ettus + + * src/lib/general/gr_threshold_ff.{h,cc,i}: new. + * src/python/gnuradio/blksimpl/standard_squelch.py: new + * src/python/gnuradio/blksimpl/nbfm_rx.py: removed squelch from + block. + +2005-11-07 Eric Blossom + + * src/python/gnuradio/blksimpl/rational_resampler.py + (design_filter): added code to automatically design filter. + + * src/lib/general/gr_firdes.cc (window): fixed Kaiser window. + +2005-10-28 Eric Blossom + + * src/lib/io/gr_oscope_sink_f.cc (gr_oscope_sink_f): fixed del of + unowned variable that was causing double-free. + +2005-10-23 Eric Blossom + + * src/lib/general/gr_nco.h (gr_nco): removed unused local var. + +2005-10-17 Eric Blossom + + * src/lib/general/gr_fxpt_vco.h: use floats instead of double. + Gives 30% speedup on Opteron under gcc 3.3.5 + +2005-10-17 Stephane Fillod + + * src/lib/general/gr_fxpt_nco.h, src/lib/general/gr_nco.h, + src/lib/general/gr_sig_source_X.cc.t: set primitives in shape + for an eventual simd speedup. fix bug in sincos() of gr_nco.h. + + * src/lib/general/Makefile.am, src/lib/general/gr_vco.h, + src/lib/general/gr_vco_f.cc, src/lib/general/gr_vco_f.h, + src/lib/general/qa_gr_fxpt_vco.h, src/lib/general/qa_gr_fxpt_vco.cc, + src/lib/general/qa_general.cc, src/tests/benchmark_vco.cc, + src/lib/general/gr_fxpt_vco.h: make use of fixed point cosine for VCO, + with appropriate QA code, set primitives in shape for an eventual + simd speedup. + * src/lib/general/qa_gr_fxpt_vco.cc, src/lib/general/gr_vco.h, + src/lib/general/qa_gr_fxpt_vco.h, src/lib/general/gr_fxpt_vco.h: new + + * README: reference gr-audio-jack, gr-audio-windows and gr-comedi + +2005-10-12 Eric Blossom + + * src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.{h,cc}: resurrected + rev 1.1 then added check for contiguous mapping. + * src/lib/runtime/gr_vmcircbuf.cc: enable gr_vmcircbuf_mmap_tmpfile. + +2005-10-11 Eric Blossom + + * src/lib/runtime/gr_vmcircbuf_mmap_shm_open.cc + (gr_vmcircbuf_mmap_shm_open): corrected error message. + +2005-10-10 Eric Blossom + + * src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.{h,cc}: removed. + +2005-10-10 Stephane Fillod + + * src/lib/general/gr_check_counting_s.cc, + src/lib/general/gr_check_lfsr_32k_s.cc, + src/lib/general/gr_vector_source_X.cc.t, + src/lib/runtime/gr_vmcircbuf_createfilemapping.cc, + src/lib/runtime/gr_vmcircbuf_mmap_shm_open.cc: compiler warning + silencing. + + * src/lib/general/gr_sig_source_X.cc.t, + src/lib/general/gr_fxpt_nco.h, + src/lib/general/gr_nco.h: added sincos block primitive. + * src/lib/general/qa_gr_fxpt_nco.cc: qa code for new sincos + block primitive. cleanup. + * src/tests/benchmark_nco.cc: benchmark the new sincos block + + * src/tests/Makefile.am: added benchmark_vco + src/tests/benchmark_vco.cc: new + +2005-10-05 Eric Blossom + + * src/python/gnuradio/gr/hier_block.py (hier_block_base.__init__): + reenabled weakref to break circular graph. + * src/python/gnuradio/gr/basic_flow_graph.py (basic_flow_graph), + src/python/gnuradio/gr/flow_graph.py (flow_graph): + removed __slots__ class attribute so we can create weakrefs to + flow graphs. + + * src/python/gnuradio/gr/gr_threading.py: New. Load appropriate bug fix. + * src/python/gnuradio/gr/gr_threading_23.py (Thread.join): bug fixed + version of python 2.3 threading.py. + * src/python/gnuradio/gr/gr_threading_24.py (Thread.join): bug fixed + version of python 2.4 threading.py. + + * src/lib/general/gr_vco_f.{h,cc,i}: new VCO block. + +2005-10-03 Eric Blossom + + * src/python/gnuradio/gr/hier_block.py (hier_block_base.__init__): + backed out use of weakref. + * src/python/gnuradio/gr/scheduler.py (scheduler.wait): backed out + "Control-C fix". + +2005-10-02 Eric Blossom + + * src/python/gnuradio/blksimpl/wfm_tx.py: New. Wide band FM tx block. + +2005-09-29 Eric Blossom + + * src/python/gnuradio/gr/hier_block.py (hier_block_base.__init__): + store weakref to flow_graph to break circular graph so that flow + graph can be reclaimed right away. + + * src/python/gnuradio/gr/flow_graph.py (flow_graph.__del__): call + self.stop() to ensure that i/o devices get shutdown gracefully. + + * src/python/gnuradio/gr/scheduler.py (scheduler.wait): calling + thread.join was keeping us from seeing SIGINT. Replaced with + alternate implementation. + +2005-09-27 Eric Blossom + + * src/python/gnuradio/eng_option.py (check_subdev): removed the + (0, None) and (1, None) results. + +2005-09-21 Eric Blossom + + * src/python/gnuradio/eng_option.py (check_subdev): added new + command line parser type, "subdev", for selecting usrp daughterboards. + +2005-09-17 Krzysztof Kamieniecki + + * src/lib/filter/qa_gr_fir_ccf.cc: alignment fix for gcc 4.x + +2005-08-28 Stephane Fillod + + * config/gr_set_md_cpu.m4, src/lib/filter/Makefile.am: add simd + support for x86_64 platform. + + * src/lib/filter/ccomplex_dotprod_3dnow64.S, + src/lib/filter/ccomplex_dotprod_3dnowext64.S, + src/lib/filter/ccomplex_dotprod_sse64.S, + src/lib/filter/complex_dotprod_3dnow64.S, + src/lib/filter/complex_dotprod_3dnowext64.S, + src/lib/filter/complex_dotprod_sse64.S, + src/lib/filter/fcomplex_dotprod_3dnow64.S, + src/lib/filter/fcomplex_dotprod_sse64.S, + src/lib/filter/float_dotprod_3dnow64.S, + src/lib/filter/float_dotprod_sse64.S, + src/lib/filter/short_dotprod_mmx64.S, + src/lib/filter/cpuid_x86_64.S: new + + * src/lib/filter/ccomplex_dotprod_3dnow.S, + src/lib/filter/ccomplex_dotprod_3dnowext.S, + src/lib/filter/ccomplex_dotprod_sse.S, + src/lib/filter/complex_dotprod_3dnow.S, + src/lib/filter/complex_dotprod_3dnowext.S, + src/lib/filter/complex_dotprod_sse.S, + src/lib/filter/fcomplex_dotprod_3dnow.S, + src/lib/filter/fcomplex_dotprod_sse.S, + src/lib/filter/float_dotprod_3dnow.S, + src/lib/filter/float_dotprod_sse.S, + src/lib/filter/short_dotprod_mmx.S + src/lib/filter/cpuid_x86.S: filename debug info fix, + removed useless emms instruction in pure SSE. + * src/lib/filter/qa_gr_fir_ccc.cc: comment fix + +2005-08-28 Eric Blossom + + * src/lib/general/malloc16.c: fixed 64-bit pointer to int cast problem. + +2005-08-26 Eric Blossom + + * src/python/gnuradio/gr/qa_rational_resampler.py + (test_rational_resampler.test_002_interp): reduced random test + from 10k cases to 1000 cases. The 10k case turns up a single + failure. FIXME figure out why! + + * src/python/gnuradio/gr/qa_fsk_stuff.py + (test_bytes_to_syms.test_simple_framer): fixed test case to + reflect 0x55 trailing tail. + + * src/lib/filter/qa_gr_fir_ccc.cc (test_random_io): Ensure 16-byte + input alignment to meet contract with SIMD ccc kernel. + +2005-08-25 Eric Blossom + + * src/lib/general/gr_simple_correlator.cc: average the samples in + the sync field and use this to set the slicing level for the + payload. This helps account for frequency offsets between the Tx + and Rx sides. + +2005-08-24 Eric Blossom + + * src/lib/general/gr_simple_framer_sync.h: include GRSF_TAIL_PAD + in GRSF_OVERHEAD. + + * src/lib/runtime/gr_single_threaded_scheduler.cc (main_loop): now + only invoke sources if we are not making progress. This avoids + blocking (in most cases) unless we've got nothing better to do. + + * src/lib/filter/gr_freq_xlating_fir_filter_XXX.cc.t + (build_composite_fir): reversed taps to fix problem introduced + when we "rationalized" the tap ordering a while ago. [We are + missing a unit test for this...] + +2005-08-22 Matt Ettus + + * src/python/gnuradio/blksimpl/gmsk.py: + made several changes to the filters on both TX and RX. + The demod filter (integrate_taps) should not average + over multiple samples. In reality, a few samples should + work, so I'm not sure why it doesn't here. + +2005-08-22 Eric Blossom + + * src/lib/general/gr_simple_correlator.cc (general_work): removed + incorrect magic number and replaced with constant expression. + [Almost as embarrassing as a buffer overflow] + +2005-08-21 Eric Blossom + + * src/lib/general/gr_simple_framer_sync.h: added one byte tail + padding to ensure that correlator has a chance to get synced in + case it was later on the previous packet. + + * src/lib/general/gr_simple_correlator.cc (general_work): + corrected to use count_bits64. + +2005-08-19 Eric Blossom + + * doc/Makefile.am: clean-local now uses $(RM) -fr + +2005-08-18 Eric Blossom + + * src/lib/general/gr_count_bits.{h,cc}: new gr_count_bits64. + + * src/lib/general/gr_simple_correlator.{h,cc}, + src/lib/general/gr_simple_framer.{h,cc}, + src/lib/general/gr_simple_framer_sync.h, + src/python/gnuradio/gr/qa_fsk_stuff.py: changed length of SYNC + code from 32 to 64 bits. + +2005-08-16 Andrew Thomas Beck + + * src/lib/runtime/gr_vmcircbuf_createfilemapping.cc (gr_vmcircbuf_createfilemapping): fixes. + +2005-08-15 Eric Blossom + + * src/lib/runtime/gr_single_threaded_scheduler.i, + src/lib/runtime/gr_block_detail.i, src/lib/runtime/gr_buffer.i: + fixes for SWIG 1.3.25. Thanks to Job de Haas for a big clue! + +2005-08-08 Martin Dudok van Heel + + Addded a new block to convert from float to unsigned char. Needed for new tv-reception example. + + * src/lib/general/gr_float_to_uchar.{cc,h,i}: new + * src/lib/general/gri_float_to_uchar.{cc,h}: new + * src/lib/general/Makefile.am: changed. Added gr_float_to_uchar and gri_float_to_uchar. (Also added gr_float_to_char.h which was + forgotten in previous patch to add gr_float_to_char) + * src/lib/general/general.i: changed. Added gr_float_to_uchar and gri_float_to_uchar. + +2005-07-28 Eric Blossom + + * src/lib/general/qa_gr_circular_file.cc (t1): conditionalized + base on HAVE_MMAP. + +2005-07-24 Stephane Fillod + + * src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.cc: get correct + granularity under Cygwin. + + * src/lib/filter/Makefile.am: renamed .s files to .S in order + to enable preprocessor support in assembly source + * src/lib/general/README: misc status update + * src/lib/filter/assembly.h: new + * src/lib/filter/3dnow_float_dotprod_really_simple.S, + src/lib/filter/3dnow_float_dotprod_simple.S, + src/lib/filter/ccomplex_dotprod_3dnow.S, + src/lib/filter/ccomplex_dotprod_3dnowext.S, + src/lib/filter/ccomplex_dotprod_sse.S, + src/lib/filter/complex_dotprod_3dnow.S, + src/lib/filter/complex_dotprod_3dnowext.S, + src/lib/filter/complex_dotprod_sse.S, + src/lib/filter/fcomplex_dotprod_3dnow.S, + src/lib/filter/fcomplex_dotprod_sse.S, + src/lib/filter/float_dotprod_3dnow.S, + src/lib/filter/float_dotprod_sse.S, + src/lib/filter/short_dotprod_mmx.S, + src/lib/filter/cpuid_x86.S: new, moved from .s files with + added preprocessor macros to handle both ELF and Windows + x86 assembly. + * src/lib/filter/3dnow_float_dotprod_really_simple.s, + src/lib/filter/3dnow_float_dotprod_simple.s, + src/lib/filter/ccomplex_dotprod_3dnow.s, + src/lib/filter/ccomplex_dotprod_3dnowext.s, + src/lib/filter/ccomplex_dotprod_sse.s, + src/lib/filter/complex_dotprod_3dnow.s, + src/lib/filter/complex_dotprod_3dnowext.s, + src/lib/filter/complex_dotprod_sse.s, + src/lib/filter/fcomplex_dotprod_3dnow.s, + src/lib/filter/fcomplex_dotprod_sse.s, + src/lib/filter/float_dotprod_3dnow.s, + src/lib/filter/float_dotprod_sse.s, + src/lib/filter/short_dotprod_mmx.s, + src/lib/filter/cpuid_x86.s: removed (renamed) + + +2005-07-21 Eric Blossom + + * src/lib/filter/gr_fft_filter_fff.cc (compute_sizes): turned off + debugging output. + +2005-07-20 Eric Blossom + + * src/python/gnuradio/blksimpl/filterbank.py: documented channel + number to frequency mapping. Fixed a couple of problems related + to reversing filter tap order. + +2005-07-20 Martin Dvh + + * src/lib/runtime/gr_vmcircbuf_createfilemapping.{h,cc}: new. + Native implementation for Windows NT/W2K/XP. + * config/gr_python.m4: MinGW mods. + +2005-07-19 Eric Blossom + + * src/lib/filter/gr_fft_filter_fff.{h,cc,i}: new. Work in + progress. Not yet ready for prime time. + + * src/lib/runtime/gr_single_threaded_scheduler.cc: fixed spinning when + sink's upstream was done, but there was a non-zero but too small + amount of data left in the sink's input buffer. + +2005-07-18 Stephane Fillod + + * config/gr_libgnuradio_core_extra_ldflags.m4, + config/gr_no_undefined.m4, config/gr_python.m4: mods for MinGW. + +2005-07-17 Eric Blossom + + * src/lib/filter/gr_rational_resampler_base_XXX.{h,cc,i}: new. + + * src/python/gnuradio/blksimpl/rational_resampler.py + (rational_resampler_ccc.__init__): new. High-level wrapper for + gr.rational_resampler_base_??? + +2005-07-15 Eric Blossom + + * src/lib/filter/gr_fft_filter_ccc.cc, src/lib/filter/gr_fir_XXX.h.t, + src/lib/filter/gr_fir_ccc_simd.cc, src/lib/filter/gr_fir_ccc_simd.h, + src/lib/filter/gr_fir_ccf_simd.cc, src/lib/filter/gr_fir_ccf_simd.h, + src/lib/filter/gr_fir_fcc_simd.cc, src/lib/filter/gr_fir_fcc_simd.h, + src/lib/filter/gr_fir_fff_simd.cc, src/lib/filter/gr_fir_fsf_simd.cc, + src/lib/filter/gr_fir_scc_simd.cc, src/lib/filter/gr_fir_scc_simd.h, + src/lib/filter/gr_hilbert_fc.cc, src/lib/filter/gr_interp_fir_filter_XXX.cc.t, + src/lib/filter/gr_mmse_fir_interpolator.cc, src/lib/filter/qa_ccomplex_dotprod_x86.cc, + src/lib/filter/qa_gr_fir_ccc.cc, src/lib/filter/qa_gr_fir_ccf.cc, + src/lib/filter/qa_gr_fir_fcc.cc, src/lib/filter/qa_gr_fir_fff.cc, + src/lib/filter/qa_gr_fir_scc.cc, src/lib/general/Makefile.am, + src/lib/general/gr_firdes.cc, src/lib/general/gr_firdes.h, + src/lib/general/gr_firdes.i, src/python/gnuradio/gr/qa_filter_delay_fc.py, + src/python/gnuradio/gr/qa_interp_fir_filter.py: reversed order of + "taps" arguments constructors and set_taps, fixed taps() so it + returns the right order. We now require the "right" order for + taps, instead of the reversed order ("dot product order") we used to + require. + +2005-07-13 Martin Dvh + + * config/gr_check_createfilemapping.m4, + config/gr_libgnuradio_core_extra_ldflags.m4: new files + * configure.ac, config/Makefile.am, src/lib/Makefile.am: added + support for extra ld flags and future createfilemapping + factory. + * src/lib/io/gr_file_source.cc, src/lib/io/gr_file_sink.cc: + binary mode support under Windows. + +2005-07-02 Eric Blossom + + * config/gr_no_undefined.m4, config/gr_x86_64.m4: new, x86_64 support. + * config/gr_python.m4: backed out search for libpython, making + x86_64 work and breaking Cygwin/MinGW. + * configure.ac, src/lib/Makefile.am: mods for x86_64, $(NO_UNDEFINED) + + * src/python/gnuradio/gr/qa_complex_to_xxx.py: loosened up passing + threshold so that we pass on x86_64. + +2005-06-23 Eric Blossom + + * src/lib/runtime/gr_error_handler.cc: added #include + +2005-06-19 Eric Blossom + + * src/lib/runtime/gr_single_threaded_scheduler.cc (main_loop): + added diagnostic logging. Fixed problem where data was dribbling + through pipeline. + + * src/lib/general/gr_fxpt.cc: gcc 4.x fix. + +2005-06-16 Eric Blossom + + * src/lib/general/gr_nco.h: increase precision: float->double. + * src/lib/general/qa_gr_fxpt_nco.h: changed initial test frequency + +2005-06-16 Stephane Fillod + + * gnuradio-core.pc.in, src/lib/Makefile.am, src/lib/atsc/Makefile.am, + src/lib/filter/Makefile.am, src/lib/general/Makefile.am, + src/lib/runtime/Makefile.am, src/tests/Makefile.am: put qa code + in separate library. + +2005-06-12 Eric Blossom + + * src/python/gnuradio/blksimpl/filterbank.py: new. DFT filterbank. + * src/lib/general/gr_vector_to_streams.{h,cc,i}: new. + * src/lib/general/gr_streams_to_vector.{h,cc,i}: new. + * src/lib/general/gr_streams_to_stream.{h,cc,i}: new. Convert + streams of 1 item into a stream of N items. + * src/lib/general/gr_stream_to_streams.{h,cc,i}: new. Convert + a stream of N items into N streams of 1 items. + +2005-06-11 Eric Blossom + + * src/lib/general/gr_nlog10_ff.{h,cc,i}: added addition constructor arg, + k, that is added to the return value. Handy for normalizing FFTs. + + * src/lib/filter/gr_fft_filter_ccc.{h,cc,i}: new. FFT based FIR filtering. + +2005-06-10 Eric Blossom + + * src/python/gnuradio/gr/flow_graph.py (buffer_sizes.allocate), + src/python/gnuradio/gr/basic_flow_graph.py (downstream_verticies_port): + modified to take into account downstream block decimation ratio. + This allows us to compute big FFTs, FIRs with lots of taps, etc. + +2005-05-18 Eric Blossom + + * src/lib/runtime/gr_block.{h,cc,i}: new start/stop methods. These are + useful for minimizing latency due to startup overhead. + * src/lib/runtime/gr_single_threaded_scheduler.cc: call new methods. + +2005-05-18 John Gilmore + + * src/python/gnuradio/gruimpl/hexint.py: new. Convert hex + constants to negative ints for long ints >= 2**31. + +2005-05-11 Eric Blossom + + * src/lib/runtime/gr_vmcircbuf_sysv_shm.cc + (gr_vmcircbuf_sysv_shm): add read-only guard page on either side + of buffer. + + * src/lib/general/gr_throttle.{h,cc,i}: new block to rate-limit + samples. Mostly useful where there's nothing stopping us from + sucking down all CPU. E.g., reading from files, gr.sig_source, etc. + +2005-05-09 Stephane Fillod + + * src/lib/filter/fcomplex_dotprod_{3dnow,sse}.s, + src/lib/filter/fcomplex_dotprod_x86.h, + src/lib/filter/gr_fir_ccf_simd.{cc,h}, + src/lib/filter/gr_fir_ccf_x86.{cc,h}, + src/lib/filter/gr_fir_fcc_simd.{cc,h}, + src/lib/filter/gr_fir_fcc_x86.{cc,h}, + src/tests/benchmark_dotprod_ccf.cc, + src/tests/benchmark_dotprod_fsf.cc: new files + * src/lib/filter/Makefile.am, src/tests/Makefile.am, + src/lib/filter/gr_fir_sysconfig_x86.{cc,h}: support for FCC and + CCF filter speedup + * src/tests/benchmark_dotprod_{ccc,fcc,scc}.cc: copy/paste fixes + which should not change benchmark results + +2005-05-09 Stephane Fillod + + * config/gr_sysv_shm.m4: SysV shared memory not mandatory + * config/gr_pwin32.m4, config/gr_python.m4, config/lf_cxx.m4: + fixes for Cygwin, MinGW + * src/lib/runtime/gr_error_handler.cc, src/lib/runtime/gr_local_sighandler.{h,cc}, + src/lib/runtime/gr_vmcircbuf.cc, src/lib/runtime/gr_vmcircbuf_mmap_tmpfile.cc: + modifications for Cygin, MinGW + +2005-04-27 Eric Blossom + + * src/lib/general/gr_fake_channel_coder_pp.{h,cc,i}: new classes + the pretend to do channel encoding and decoding, but really only + add and strip padding... + + * src/lib/runtime/gr_buffer.cc (allocate_buffer): cleaned up formatting + on allocation warning message. + + * src/python/gnuradio/blksimpl/digital_voice.py: GSM vocoder + GMSK. + +2005-04-03 Eric Blossom + + * src/lib/io/gr_oscope_guts.cc (found_trigger): fixed trigger + problem where value was exactly equal to trigger value. + +2005-03-29 Eric Blossom + + * src/python/gnuradio/blksimpl/gmsk.py: new GMSK mod and demod + from Joshua Lackey + +2005-03-29 Ramakrishnan Muthukrishnan + + * src/lib/filter/gr_filter_delay_fc.{h,cc,i}, + src/python/gnuradio/gr/qa_filter_delay_fc.py: New block that + pairs a filter with a delay. + +2005-03-26 Eric Blossom + + * src/lib/runtime/gr_dispatcher.{h,cc,i}, + src/lib/runtime/gr_select_handler.{h,cc,i}: new. Framework for + callbacks based on select(2). + + * src/lib/runtime/gr_error_handler.{h,cc,i}: new. + +2005-03-14 Eric Blossom + + * src/lib/general/gr_complex_to_xxx.{h,cc,i}: now support + vector length argument, vlen. + * src/lib/general/gr_nlog10_ff.{h,cc,i}: new. + * src/lib/general/gr_parallel_to_serial.{h,cc,i}: new. + * src/lib/filter/gr_single_pole_iir_filter_ff.{h,cc,i}: new + * src/python/gnuradio/gr/qa_single_pole_iir.py: new + * src/python/gnuradio/gr/qa_nlog10.py: new + +2005-03-08 Eric Blossom + + * src/python/gnuradio/gr/qa_fsk_stuff.py: enabled simple_framer qa code. + * src/lib/general/gr_simple_framer.{h,cc}: added forecast method. + +2005-03-07 Eric Blossom + + * configure.ac: test for trunc and work around if missing. + +2005-03-02 Eric Blossom + + * src/python/gnuradio/blks/__init__.py, src/python/gnuradio/blksimpl/__init__.py, + src/python/gnuradio/gru/__init__.py, + src/python/gnuradio/gruimpl/__init__.py: refactored organization + so that hierarchical blocks are physically contained in the + blkimpl directory, but that for convenience in naming, all blocks + appear in the gnuradio.blks package. Same story for gruimpl vs gru. + + Rearranged a bunch of stuff under src/python. CVS sucks! + +2005-02-28 Eric Blossom + + * src/lib/general/gr_frequency_modulator_fc.cc (work): fixed + floating point loss of precision. + * src/lib/general/gr_simple_correlator.cc (general_work): fixed + bug that had it processing only a single sample at a time. + +2005-02-25 Matt Ettus + + * lib/general/Makefile.am, lib/general/general.i, + lib/general/gr_rms_[ff,cf].[cc,h,i]: new rms measuring block + +2005-02-25 Eric Blossom + + * python/gnuradio/gr/qa_mute.py, lib/general/gr_mute_XX.cc.t, + lib/general/gr_mute_XX.h.t, lib/general/gr_mute_XX.i.t: new block. + * lib/general/Makefile.am, lib/general/Makefile.gen, + lib/general/general_generated.i, lib/general/generate_common.py: + mods to generate new block. + +2005-02-23 Eric Blossom + + * src/python/gnuradio/gr/hier_block.py: new. support for + hierarchical signal processing blocks. + * src/python/gnuradio/gr/basic_flow_graph.py, + src/python/gnuradio/gr/qa_basic_flow_graph.py: modified to support + hierarchical signal processing blocks. + +2005-02-22 Eric Blossom + + * src/lib/general/gr_simple_squelch_cc.{h,cc,i}: new. + + * src/lib/runtime/gr_message.{h,cc,i}, + src/lib/runtime/gr_msg_handler.{h,cc,i}, + src/lib/runtime/gr_msg_queue.{h,cc,i}, + src/lib/runtime/gr_timer.h: new. work-in-progress. + +2005-02-09 Eric Blossom + + * src/lib/io/gr_file_descriptor_source.{h,cc}(work): reworked to + return as soon as any data is available. This make it much more + friendly for reading sockets, named pipes, etc. + +2005-02-07 Eric Blossom + + * src/python/gnuradio/gr/basic_flow_graph.py (coerce_endpoint): + fix exception message. + +2005-02-06 Eric Blossom + + * src/python/gnuradio/gr/basic_flow_graph.py + (basic_flow_graph.connect): connect now takes >= 2 args, per + Thomas Traber's suggestion. + * src/python/gnuradio/gr/qa_flow_graph.py, + src/python/gnuradio/gr/qa_basic_flow_grapy.py: additional test code. + +2005-02-05 Eric Blossom + + * src/python/gnuradio/gr/basic_flow_graph.py + (basic_flow_graph.connect): removed unnecessary None + +2005-02-02 Chuck Swiger + + * src/lib/io/gr_file_source.{h,cc,i}: added seek method. + +2005-01-29 Eric Blossom + + * src/lib/runtime/gr_io_signature.i: mods for SWIG 1.3.24 + +2005-01-24 Eric Blossom + + * src/python/gnuradio/freqz.py (freqz): New. Compute frequency + response of filter. + * src/python/gnuradio/gnuplot_freqz.py: New. Plot output of freqz. + +2005-01-17 Eric Blossom + + * src/lib/runtime/gr_single_threaded_scheduler.cc (main_loop): + Make better initial estimate of noutput_items when current block + is a decimator. Removed old diagnostic code. + + * src/lib/general/gr_vector_source_X.cc.t (work): reorganized the + repeat case so that we always return the number of items requested. + This fixes the excessive latency we were seeing in + spectrum_inversion.py + + * src/python/gnuradio/gr/flow_graph.py: Set noutputs correctly. + * src/python/gnuradio/gr/qa_flow_graph.py: Test value of noutputs. + +2005-01-16 Eric Blossom + + * src/lib/runtime/gr_single_threaded_scheduler.cc (main_loop): + check for situation where block is requesting more input data than + we will ever provide. + + * src/python/gnuradio/gr/flow_graph.py (buffer_sizes.allocate): + set minimum buffersize to 2 * output_multiple() + + * src/lib/runtime/gr_buffer.cc (space_available): fixed degenerate + case to be consistent with normal case. + +2005-01-01 Eric Blossom + + * src/lib/io/sdr_1000.i (class sdr_1000_base): removed default arg + to work around SWIG 1.3.23 bug. + +2004-12-22 Eric Blossom + + * src/lib/general/qa_gr_fxpt.cc (t0): disabled float_to_fixed test + to avoid spurious failures. + +2004-12-21 Eric Blossom + + * src/lib/general/gr_fxpt.h (class gr_fxpt): added explicit float cast. + * src/lib/general/Makefile.am (grinclude_HEADERS): added gr_fxpt_nco.h + +2004-12-18 Eric Blossom + + * src/lib/general/gr_fxpt.{h,cc},src/lib/general/gr_fxpt_nco.{h,cc}, + src/lib/general/qa_gr_fxpt.{h,cc},src/lib/general/qa_gr_fxpt_nco.{h,cc}, + src/tests/benchmark_nco.cc: new. Faster sine and cosine + calculation. Uses table lookup with linear interpolation. This + is about 3x faster than the original code. + +2004-12-17 Eric Blossom + + * src/lib/general/Makefile.am (swiginclude_HEADERS): fixed typo. + * src/lib/general/gr_deinterleave.{h,cc,i}: new. + +2004-12-11 Eric Blossom + + * src/lib/general/gr_interleave.{h,cc,i}: new. + +2004-12-10 Eric Blossom + + * src/python/gnuradio/eng_option.py (check_intx): now parses hex + numbers too. + +2004-12-09 Eric Blossom + + * src/lib/filter/Makefile.am: fixed problem with gr_hilbert_fc on + OS/X (it was in the wrong place in the makefile). Now builds and + checks on OS/X. + +2004-12-06 Ramakrishnan Muthukrishnan + + * src/lib/filter/Makefile.am, src/lib/general/Makefile.am, + src/python/gnuradio/Makefile.am, + src/python/gnuradio/gr/Makefile.am: added *.pyc to CLEANFILES + +2004-11-30 Eric Blossom + + * src/python/gnuradio/gr/Makefile.am, configure.ac: modified to + no longer require run_test_trampoline. Now uses AC_CONFIG_COMMANDS to + set execute bit on run_tests. + * src/python/gnuradio/gr/run_test_trampoline: removed. + + * src/lib/filter/Makefile.am (swiginclude_HEADERS): fix typo in gr_hilbert_fc.i + +2004-11-27 Eric Blossom + + * src/python/gnuradio/gr/qa_hilbert.py: new + * src/lib/general/gr_firdes.i: moved from filter to general. + * src/lib/general/gr_firdes.{h,cc}: new method: reverse. + * src/lib/filter/gr_hilbert_fc.i: new. + * src/lib/filter/gr_hilbert_fc.cc: ensure ntaps is odd. + +2004-11-08 Stephane Fillod + + * src/lib/filter/Makefile.am, src/tests/Makefile.am, + src/lib/filter/complex_dotprod_generic.cc, + src/lib/filter/gr_fir_sysconfig_x86.{cc,h}, + src/lib/filter/qa_dotprod_x86.cc, src/lib/filter/qa_filter.cc: + added support for x86 SIMD CCC dotproduct. + * src/lib/filter/ccomplex_dotprod_3dnow.s, + src/lib/filter/ccomplex_dotprod_3dnowext.s, + src/lib/filter/ccomplex_dotprod_generic.{cc,h}, + src/lib/filter/ccomplex_dotprod_sse.s, + src/lib/filter/ccomplex_dotprod_x86.h, + src/lib/filter/gr_fir_ccc_simd.{cc,h}, + src/lib/filter/gr_fir_ccc_x86.{cc,h}, + src/lib/filter/qa_ccomplex_dotprod_x86.{cc,h}, + src/lib/filter/qa_gr_fir_ccc.{cc,h}, + src/tests/benchmark_dotprod.cc, + src/tests/benchmark_dotprod_{ccc,fcc,scc}.cc: new + +2004-11-08 Eric Blossom + + * src/lib/runtime/gr_block.h: new methods: set_input_signature and + set_output_signature. + +2004-11-04 Eric Blossom + + * configure.ac: upped version to 2.3cvs + + * configure.ac: set version to 2.3. Made release. + * src/python/gnuradio/audio.py (__init__): raise error if no audio + module found. + +2004-11-02 Eric Blossom + + * src/lib/runtime/gr_local_sighandler.cc (name): conditionalized + based on signal names. + +2004-10-30 Eric Blossom + + * src/lib/runtime/gr_local_sighandler.{h,cc}: new. get and set + signal handlers. + * src/lib/runtime/gr_vmcircbuf.cc (test_factory): install handlers + for SIGBUS and SIGSEGV while running tests. + +2004-10-18 Stephane Fillod + + * config/gr_pwin32.m4, src/lib/runtime/gr_preferences.cc: proper + detect Sleep() support, check for mkdir that takes only one arg + under win32. + * src/lib/runtime/gr_io_signature.cc, + src/lib/runtime/gr_io_signature.h, + src/lib/runtime/gr_io_signature.i, + src/lib/runtime/qa_gr_io_signature.cc: resolve a clash with + INFINITE already defined. + * src/lib/runtime/gr_pagesize.cc: declare missing prototype of + getpagesize() under win32. + +2004-10-18 Eric Blossom + + * src/python/gnuradio/gr/run_tests.in: allow VPATH building. + +2004-10-18 Stephane Fillod + + * configure.ac, src/lib/filter/Makefile.am, + src/lib/general/Makefile.am: allow VPATH building. + +2004-10-17 Eric Blossom + + * doc/Makefile.am (install-data-local): install html documentation. + * src/lib/filter/gr_iir_filter_ffd.cc (gr_iir_filter_ffd): removed + debug message. + * src/python/gnuradio/gr/run_tests.in: changed == to = for POSIX + compatibility. + * src/python/gnuradio/gr/qa_basic_flow_graph.py: use /usr/bin/env + to find python. + +2004-10-13 Eric Blossom + + * configure.ac: upped rev to 2.2cvs + +2004-10-11 Eric Blossom + + * configure.ac: bumped rev to 2.2, make release + * Makefile.am (EXTRA_DIST): added config.h.in + +2004-10-07 Eric Blossom + + * src/python/gnuradio/lmx2306.py: now works! + +2004-09-29 Eric Blossom + + * src/lib/filter/gri_iir.h: renamed from gr_iir.h. Also, changed + the sign back. We're consistent with Oppenheim and Schafer, + "Discrete-Time Signal Processing." Documented exactly what we + compute. Faster delay line implementation. + * src/lib/filter/gr_iir_filter_ffd.{h,cc,i}: new direct form IIR block. + +2004-09-23 Eric Blossom + + * config/usrp_fusb_tech.m4, config/bnv_have_qt.m4, config/cppunit.m4, + config/gr_check_mc4020.m4, config/gr_check_usrp.m4, config/gr_doxygen.m4, + config/gr_gprof.m4, config/gr_scripting.m4, config/gr_set_md_cpu.m4, + config/pkg.m4, config/usrp_fusb_tech.m4: added additional quoting + to first arg of AC_DEFUN to silence automake warning. + +2004-09-22 Eric Blossom + + * src/lib/io/gr_file_descriptor_sink.cc: added missing #include + * src/lib/io/gr_file_descriptor_source.cc: added missing #include + +2004-09-21 Matthew Hall + + * src/gnu/lib/gr/gr_iir.h: rewrote ctor docs. Fixed sign error + in filter method. Now gr_iir uses Direct Form I of IIR. + +2004-09-19 Eric Blossom + + * src/lib/general/gr_complex_to_xxx.{h,cc,i}: new blocks. + * src/python/gnuradio/gr/qa_complex_xxx.py: new qa code. + + * src/lib/general/gr_simple_correlator.{h,cc,i}: payload size is + now in bytes, not bits. + * src/lib/general/gr_simple_framer.{h,cc,i}: payload size is + now in bytes, not bits. + + * src/lib/swig/Makefile.am: now tracks swig .i file dependencies. + * src/lib/swig/gnuradio.i: simplification and cleanup. + +2004-09-18 Eric Blossom + + These modifications happened sometime between 2004-09-08 and 2004-09-18. + The details are lost in the swirl around preparing the TAPR DCC. + + * src/lib/filter/gr_interp_fir_filter_XXX.{h,cc,i}.t: new + * src/lib/filter/generate_gr_interp_fir_filter_XXX.py: new + * src/lib/filter/generate_all.py: modified for to generate interpolating fir filter + * src/lib/general/gr_bytes_to_syms.{h,cc,i}: new + * src/lib/general/gr_frequency_modulator_fc.{h,cc,i}: new + * src/lib/general/gr_simple_framer.{h,cc,i}: new + * src/lib/general/gr_simple_framer_sync.h: new + * src/lib/general/gr_simple_correlator.{h,cc,i}: new + * src/lib/io/gr_oscope_guts.{h,cc}: new + * src/lib/io/gr_oscope_sink_{f,x}.{h,cc}: new + * src/lib/io/gr_trigger_mode.h: new + * src/lib/io/ppio.i: new + + The following changes are related to moving from SWIG 1.3.21 to 1.3.22 + + * src/lib/runtime/gr_block_detail.i: removed unneccesary global decl of friend. + * src/lib/runtime/gr_buffer.i: removed unneccesary global decl of friend. + * src/lib/runtime/gr_io_signature.i: removed unneccesary global decl of friend. + * src/lib/runtime/gr_single_threaded_scheduler.i: removed unneccesary global decl of friend. + * src/lib/swig/gnuradio.i: mods for improved STL support + + * src/lib/runtime/gr_types.h: new typedefs + * src/lib/swig/gen-swig-bug-fix: new. generate gnuradio_swig_bug_workaround.h + + * src/python/gnuradio/eng_notation.py: new + * src/python/gnuradio/grutil.py: new + * src/python/gnuradio/gr_unittest.py: new subclass of unittest + * src/python/gnuradio/lmx2306.py: new. Control National PLL synthesizer + * src/python/gnuradio/microtune.py: new. Command line interface + to microtune boards. + * src/python/gnuradio/gr/qa_frequency_modulator.py: new + * src/python/gnuradio/gr/qa_fsk_stuff.py: new + * src/python/gnuradio/gr/qa_head.py: new + * src/python/gnuradio/gr/qa_interp_fir_filter.py: new + * src/python/gnuradio/gr/qa_sig_source.py: new + +2004-09-08 Eric Blossom + + * src/python/gnuradio/gr/basic_flow_graph.py + (basic_flow_graph.validate): now calls check_topology. + * src/lib/runtime/gr_block.{h,cc,i} (check_topology): new method. + + * src/lib/general/gr_short_to_float.{h,cc,i}: new + * src/lib/general/gr_float_to_short.{h,cc,i}: new + +2004-08-26 Eric Blossom + + * src/lib/general/gr_fft_vfc.{h,cc,i}: new + * src/lib/general/gr_fft_vcc.{h,cc,i}: new + * src/lib/general/gri_fft.{h,cc}: renamed from gr_fft.{h,cc} + * src/lib/general/gr_serial_to_parallel.{h,cc,i}: new + * src/lib/general/gr_keep_one_in_n.{h,cc,i}: new + +2004-08-25 Eric Blossom + + * src/lib/io/gr_file_descriptor_source.{h,cc,i}: new + * src/lib/io/gr_file_descriptor_sink.{h,cc,i}: new + +2004-08-19 Eric Blossom + + * src/lib/general/gr_sig_source_X.cc.t (work): performance tweak + for constant case. + + * src/python/gnuradio/eng_option.py (check_eng_float): support + engineering notation in option parsing. E.g., 32k, 106.5M + +2004-08-18 Eric Blossom + + * src/python/gnuradio/gr/scheduler.py, + src/python/gnuradio/gr/basic_flow_graph.py, + src/python/gnuradio/gr/flow_graph.py, + src/python/gnuradio/gr/qa_flowgraph.py: modified to partition + graphs and assign separate threads to each disjoint set of + verticies. + + +2004-08-05 Eric Blossom + + * src/lib/general/gr_lfsr_32k_source_s.{h,cc,i}: new. + + * src/lib/general/gr_check_counting_s.{h,cc,i}: renamed from gr_counting_sink. + * src/lib/general/gri_lfsr_15_1_0.h: new LFSR generator with + period 32K-1 bits. + * src/lib/general/gri_lfsr_32k.h: new LFSR generator with period + 32K bits. + * src/lib/general/gr_counting_sink_s.{h,cc,i}: new. checks that + it's input is a counting sequence. + * src/lib/filter/Makefile.am: added missing .t files + +2004-07-31 Eric Blossom + + * src/lib/general/gr_vector_source_X.{h,cc,i}.t: added repeat + argument to constructor. + +2004-07-30 Eric Blossom + + * src/lib/general/gr_sig_source_X.cc.t (work): now use gr_sincos + to compute both at same time. + + * src/lib/general/gr_nco.h (gr_nco): renamed method cossin -> sincos + and use gr_sincos to compute value. + + * configure.ac: upped rev to 2.1cvs. + +2004-07-21 Eric Blossom + + * configure.ac: upped rev to 2.1. Made release. + +2004-07-20 Eric Blossom + + * src/python/gnuradio/optfir.py: new. High level routines for optimal FIR design. + * src/lib/general/gr_remez.{h,cc}: new. Parks-McClellan method + for optimal FIR design. + +2004-07-19 Eric Blossom + + * src/lib/general/gri_add_const_ss_generic.cc: new. + * src/lib/general/gri_add_const_ss.h: new. + +2004-07-17 Eric Blossom + + * src/python/gnuradio/gr/flow_graph.py (buffer_sizes.allocate): + take into account output_multiple when computing buffer size. + + * src/lib/runtime/gr_block.i: added output_multiple and + relative_rate to swig interface. + +2004-07-12 Eric Blossom + + * configure.ac: upped rev to 2.0cvs + + * src/python/gnuradio/sdr_1000.py: added back in. + * src/lib/io/sdr_1000.{h,cc}: added back in. + +2004-07-11 Eric Blossom + + * config/gr_boost.m4 (GR_REQUIRE_BOOST_INCLUDES): new m4 macro. + +2004-07-09 Eric Blossom + + * src/lib/audio-oss: removed all files and moved to gr-audio-oss package. + +2004-07-04 Eric Blossom + + * src/lib/general/gr_{add,sub,multiply,divide}_XX.{h,i,cc}.t: new + * src/lib/general/gr_multiply_const_XX.{h,i,cc}.t: new + * src/lib/runtime/gr_block.{h,cc} (class gr_block): renamed + basic_work method to general_work + * src/lib/general/gr_sync_block.{h,cc} (class gr_sync_block): + renamed sync_work method to work. + +2004-07-03 Eric Blossom + + * src/python/gnuradio/gr/scheduler.py: new. Now run graph in + separate thread. + * src/lib/runtime/gr_single_threaded_scheduler.{h,i,cc}: added + stop method. + * src/lib/general/gr_noise_source_X.{h,i,cc}.t: new random noise source. + * config/gr_swig.m4: fail, not warn, if the right version isn't found. + * src/lib/general/gr_random.{h,cc}: moved implementation specific + defines out of header and into implementation. Also moved statics + into class and cleaned up a couple of other annoyances. + +2004-07-01 Eric Blossom + + * src/python/gnuradio/gr/run_tests.in: new. Sets PYTHONPATH + for sucessful testing in build tree; runs all tests. + * src/lib/runtime/{gr_block.i,gr_swig_block_magic.i}: revised to + use lambda expression for repr printing instead of referencing global. + * src/lib/swig/Makefile.am: now generate standalone swig runtime + library that all other swig modules link against. + +2004-06-21 Eric Blossom + + Cleaned up interface to microtune modules and eval boards. + Now uses boost::shared_ptr's. Refactored all uses 4937 and 4702, + and corresponding eval board classes. + + * src/lib/io/i2c.{h,cc}: split into i2c.{h,cc} and i2c_bitbang.{h,cc} + * src/lib/io/eval_board_4702_defs.h: deleted. + * src/lib/io/i2cio.{h,cc}: renamed to i2c_bbio.{h,cc} + * src/lib/io/i2cio_pp.{h,cc}: renamed to i2c_bbio_pp.{h,cc} + +2004-06-13 Eric Blossom + + * src/lib/general/gr_quadrature_demod_cf.{i,h,cc}: new. + + * src/lib/audio-oss/gr_audio_sink_oss.{i,h,cc}: new. + FIXME: should be moved into a different build tree to decouple oss + dependency. + + * src/lib/io/gr_file_{sink,source}.{i,h,cc} io.i: new. + +2004-06-12 Eric Blossom + + * src/lib/general/gr_sig_source_X.{h,cc,i}.t: new + * src/lib/general/gr_sig_source_waveform.h: new + * src/lib/general/gr_head.{h,cc,i}: new + + * src/lib/runtime/gr_block_detail.cc (set_done), gr_buffer.h: + propagate "done" upstream + + +2004-XX-XX Eric Blossom + + Months of changes... This was whatever it took to get + the beginning of the new code base working... + +2004-03-11 Eric Blossom + + * src/lib/runtime/io_signature.{h,cc}, + * src/lib/runtime/qa_io_signature.{h,cc}: new. + +2004-03-08 Eric Blossom + + Removed cppunit from our build tree and updated qa code to work + with cppunit-1.9.12 + + * Makefile.am + * bootstrap + * configure.ac + * config/Makefile.am + * config/cppunit.m4 + * src/lib/Makefile.am + * src/lib/atsc/convolutional_interleaver.h + * src/lib/atsc/qa_atsc_basic_trellis_encoder.cc + * src/lib/atsc/qa_atsc_data_interleaver.cc + * src/lib/atsc/qa_atsc_equalizer_nop.cc + * src/lib/atsc/qa_atsc_fake_single_viterbi.cc + * src/lib/atsc/qa_atsc_fs_correlator.cc + * src/lib/atsc/qa_atsc_randomizer.cc + * src/lib/atsc/qa_atsc_reed_solomon.cc + * src/lib/atsc/qa_atsc_single_viterbi.cc + * src/lib/atsc/qa_atsc_trellis_encoder.cc + * src/lib/atsc/qa_atsc_viterbi_decoder.cc + * src/lib/atsc/qa_convolutional_interleaver.cc + * src/lib/atsc/qa_interleaver_fifo.cc + * src/lib/filter/qa_complex_dotprod_x86.cc + * src/lib/filter/qa_float_dotprod_x86.cc + * src/lib/filter/qa_gr_fir_CCF.cc + * src/lib/filter/qa_gr_fir_FCC.cc + * src/lib/filter/qa_gr_fir_FFF.cc + * src/lib/filter/qa_gr_fir_SCC.cc + * src/lib/filter/qa_gr_mmse_fir_interpolator.cc + * src/lib/filter/qa_sse_float_dotprod.cc + * src/lib/general/qa_gr_circular_file.cc + * src/lib/general/qa_gr_firdes.cc + * src/lib/general/old/qa_gr_fir_SSS.cc + * src/lib/general/old/qa_gr_fir_sse.cc + * src/lib/runtime/qa_gr_vmcircbuf.cc + * src/lib/vrx/VrComplex.h + * src/tests/GrTestSink.cc + * src/tests/GrTestSkippingSink.cc + * src/tests/GrTestSource.cc + + + +This code was derived from gnuradio-0.9 with a massive amount of hacking. + +# +# Copyright 2001,2002,2003,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. +# diff --git a/gnuradio-core/Makefile.am b/gnuradio-core/Makefile.am new file mode 100644 index 00000000..b4b619b8 --- /dev/null +++ b/gnuradio-core/Makefile.am @@ -0,0 +1,36 @@ +# +# Copyright 2001,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 + +EXTRA_DIST = \ + gnuradio-core.conf \ + gnuradio-core.pc.in \ + README.hacking \ + README-win32-mingw-short.txt + +SUBDIRS = src doc + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = gnuradio-core.pc + +etcdir = $(sysconfdir)/gnuradio/conf.d +etc_DATA = gnuradio-core.conf diff --git a/gnuradio-core/NEWS b/gnuradio-core/NEWS new file mode 100644 index 00000000..bd9ab537 --- /dev/null +++ b/gnuradio-core/NEWS @@ -0,0 +1,35 @@ +GNU Radio -- History of visible changes. + +Copyright (C) 2001, Free Software Foundation, Inc. +See the end for copying conditions. + +Please send GNU Radio bug reports to bug-gnuradio@fsf.org + +Version 0.2 + +* This the first "real release" + + +Version 0.1 + +* We're working toward the first alpha distribution + +* The build strategy is in the processes of being converted to use + automake. It is mostly complete, but there are still some untested directories + which still contain Makefile.in's + +------------------------------------------------------- +Copying information: + +Copyright (C) 2001, Free Software Foundation, Inc. + + Permission is granted to anyone to make or distribute verbatim copies + of this document as received, in any medium, provided that the + copyright notice and this permission notice are preserved, + thus giving the recipient permission to redistribute in turn. + + Permission is granted to distribute modified versions + of this document, or of portions of it, + under the above conditions, provided also that they + carry prominent notices stating who last changed them. + diff --git a/gnuradio-core/README b/gnuradio-core/README new file mode 100644 index 00000000..dfc0ac8d --- /dev/null +++ b/gnuradio-core/README @@ -0,0 +1,190 @@ +# +# Copyright 2001,2002,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. +# + +------------------------------------------------------------------------------- + + IMPORTANT + +------------------------------------------------------------------------------- + +GNU Radio is now broken up into several packages. You're looking at +the gnuradio-core. You'll probably want some or all of these too. +Build and install them in the order listed here: + + gnuradio-core # main library + gnuradio-examples # examples + gr-audio-alsa # support for sounds cards using ALSA (prefered under GNU/Linux) + gr-audio-oss # support for sounds cards using OSS + gr-audio-jack # support for JACK Audio Connection Kit + gr-audio-windows # support for sounds cards using Windows Wave + gr-comedi # support for DAQ cards using COMEDI + gr-wxgui # GUI framework built on wxPython + usrp # non-GNU Radio specific portion of usrp + gr-usrp # glues usrp into GNU Radio + mc4020 # GNU/Linux driver for Measurement Computing PCI-DAS4020/12 A/D board + gr-mc4020 # the glue that ties the mc4020 driver into GNU Radio + + +------------------------------------------------------------------------------- + + KNOWN INCOMPATIBILITIES + + + GNU Radio triggers bugs in g++ 3.3 for X86. DO NOT USE GCC 3.3. + gcc 3.2 and 3.4 are known to work well. + +------------------------------------------------------------------------------- + +Prerequisites (you may already have these): + +(1) pkgconfig 0.15.0 or later http://www.freedesktop.org/Software/pkgconfig + +From the web site: + +pkgconfig is a system for managing library compile/link flags that +works with automake and autoconf. It replaces the ubiquitous *-config +scripts you may have seen with a single tool. + + +(2) FFTW 3.0 or later http://www.fftw.org + +IMPORTANT!!! When building FFTW, you MUST use the --enable-single and +--enable-shared configure options. This builds the single precision +floating point version which we use. You should also use either the +--enable-3dnow or --enable-sse options if you're on an Athlon or Pentium +respectively. + + +(3) Python 2.3 or later http://www.python.org + +Python 2.3 or later is now required. If your distribution splits +python into a bunch of separate RPMS including python-devel or +libpython you'll most likely need those too. + + +(4) Numeric python library http://numeric.scipy.org + +Provides a high performance array type for Python. + + +(5) The Boost C++ Libraries http://www.boost.org + +We use the Smart Pointer library. Fedore Core 2 has a package for +this, boost-devel-1.31.0-7. Otherwise download the source and follow +the build instructions. They're a bit different from the normal +./configure && make + + +(6) cppunit 1.9.14 or later. http://cppunit.sourceforge.net + +Unit testing framework for C++. + + +(7) Simple Wrapper Interface Generator. http://www.swig.org + +These versions are known to work: + 1.3.23, 1.3.24, 1.3.25, 1.3.27, 1.3.28, 1.3.29 + +---------------------------------------------------------------- + +For the impatient, just do the following: + + $ ./configure + $ make + $ make check + $ make install + +If it doesn't work, fix it and send us a patch... + + +See http://www.gnu.org/software/gnuradio/ for an overview. +The project is hosted at http://savannah.gnu.org/projects/gnuradio/ + + +If you've got doxygen installed and provide the --enable-doxygen +configure option, the build process creates documentation for the +class hierarchy etc. Point your browser at +gnuradio-core/doc/html/index.html + + +To run the examples you'll need to set PYTHONPATH. +Note that the python version number in the path needs to match your +installed version of python. + + $ export PYTHONPATH=/usr/local/lib/python2.3/site-packages + +You may want to add this to your ~/.bash_profile + + + +---------------------------------------------------------------- + + Notes on building GNU Radio from the CVS repository + +---------------------------------------------------------------- + +If you're building from the CVS repository YOU MUST BE PLAYING BY THE +RULES THAT THE OTHER DEVELOPERS ARE USING. This is especially true +with regard to the versions of the tools below... + +Ensure that you've got THESE VERSIONS of the following tools: + + autoconf 2.57 or later + automake 1.7.4 or later + libtool 1.5 or later + swig 1.3.{23,24,25,27,28,29} + +If you're using earlier versions than these, don't expect the system +to build. Get these versions or something later. They're available +at any of the GNU mirrors. + +Then, check out a copy of GNU Radio. + +See http://www.gnu.org/software/gnuradio for directions on anonymous +access to the CVS repository. + +Then in the top level directory, execute + + $ ./bootstrap + +This builds configure from configure.ac and also builds all the +Makefile.in's from the Makefile.am's. + +Then carry on as usual: + + $ ./configure + $ make + $ make check + $ make install + + +For the easiest way to build from CVS, see +http://comsec.com/wiki?HowtoBuildFromCVS + + + +Another handy trick if for example your fftw includes and libs are +installed in, say ~/local/include and ~/local/lib, instead of +/usr/local is this: + + $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$HOME/local/lib + $ make CPPFLAGS="-I$HOME/local/include" + diff --git a/gnuradio-core/README-win32-mingw-short.txt b/gnuradio-core/README-win32-mingw-short.txt new file mode 100644 index 00000000..88338e3b --- /dev/null +++ b/gnuradio-core/README-win32-mingw-short.txt @@ -0,0 +1,92 @@ +Building and using gnuradio on windows (win32) using mingw + +Required tools and libraries + +MingW and Msys +Download the latest stable version from the mingw site oand follow their installation instructions) + +Python for windows version 2.4 (or higher) +You do not need to build this yourself. +You can just install the windows executable which you can find on the python site. +I am not sure if it will work if you have speces in your python pathname. +I recommend installing it in C:\Python24 or D:\Python24 + +Libtool +If you are building from cvs you need a recent libtool +msys comes with libtool, but the version distributed with current mingw doesn't work with gnuradio. +download, build and install a recent libtool + +cppunit +Build and install cppunit + +boost +build and install boost (maybe you can get away with only unpacking the source, we only use the boost header files) +If you build boost, you first have to download jam (boost jam) for win32. (Do not use build and use the cygwin version) + +build environment: +You need to have the following files on your PATH: +python.exe python24.dll libcppunit-1-10-2.dll libfftw3f-3.dll fftwf-wisdom.exe cppunit-config +If you have cygwin installed Make sure that NO cygwin executables are on your path. + +needed on PATH: +/usr/local/bin +/mingw/bin +/bin +/c/Python24/ python.exe +/c/Python24/libs python24.dll +/c/Python24/DLLs +/usr/local/bin or /mingw/bin or /my/special/installed/lib/folder/bin + libcppunit-1-10-2.dll + libfftw3f-3.dll + fftw-wisdom-to-conf + fftwf-wisdom.exe + cppunit-config +/c/WINNT/system32 +/c/WINNT + + +I made a little script set_clean_path.sh to set my path for building gnuradio where I just discard the original PATH (to get rid of the cygwin executables on my default path) and just include what is needed: + +#!/bin/sh +export PATH=".:/usr/local/bin:/mingw/bin:/bin:/c/Python24:/c/Python24/DLLs:/c/Python24/libs:/my/special/installed/lib/folder/bin:/c/WINNT/system32:/c/WINNT:/c/WINNT/System32/Wbem:. + +You need to source this script to set the PATH. +. ./set_clean_path.sh +(notice the extra dot and space in the beginning of the line, this means source this file. Sourcing means execute it and remember all environment variables set in this script) + +If you are building from cvs it is recommended that you edit bootstrap to your needs and use it +If you built a recent libtool and didn't overwrite the original libtool +(because you installed the new version in /usr/local) then you have to tell aclocal to use the more recent libtool m4 macros. +You can do this by appending -I /usr/local/share/aclocal to the aclocal commandline +I also changed the aclocal and automake invocations to use the most recent version in my bootstrap script +Here follows the bootstrap script I use + +#!/bin/sh +rm -fr config.cache autom4te*.cache + +aclocal-1.8 -I config -I /usr/local/share/aclocal +autoconf +autoheader +libtoolize --automake +automake-1.8 --add-missing + +If you run this script it will convert a clean cvs checkout to a version which you can configure, build and install + +So now you can configure gnuradio. +On win32 /mingw you need to give it a few parameters +You need to tell it where cppunit is installed +where boost include files are to be found +where the pkg-config of libfftw is to be found +to use a generic cpu (no 3Dnow,SSE,MMX) (This option will not be needed anymore soon) +If you have boost installed in C:\boost_1_32_0 and cppunit and fftw in /usr/local then you would need the following configur commandline +$ ./configure --with-md-cpu=generic --with-cppunit-prefix=/usr/local --with-boost-include-dir=/c/boost_1_32_0/include/boost-1_32 PKG_CONFIG_PATH=/usr/local/lib/pkgconfig + +If everything went well you cannow do +make +make install + +Now you have a working gnuradio-core +Now you can go on building and installing gr-audio-windows and windows usrp and wxgui +remember that all gnuradio and python dlls need to be on your path to use gnuradio +The gnuradio dlls are installed at +/c/Python24/Lib/site-packages:/c/Python24/Lib/site-packages/gnuradio:/c/Python24/Lib/site-packages/gnuradio/gr diff --git a/gnuradio-core/README.hacking b/gnuradio-core/README.hacking new file mode 100644 index 00000000..7e211e0b --- /dev/null +++ b/gnuradio-core/README.hacking @@ -0,0 +1,178 @@ +# -*- Outline -*- +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + + +Random notes on coding conventions, some explanations about why things +aren't done differently, etc, etc, + + +* C++ and Python + +GNU Radio is now a hybrid system. Some parts of the system are built +in C++ and some of it in Python. In general, prefer Python to C++. +Signal processing primitives are still built in C++ for performance. + +It is no longer possible to build user applications entirely in C++. +Essential parts of the runtime system have been moved into Python. + + +* C++ namespaces + +In the cleanup process, I considered putting everything in the +gnuradio namespace and dropping the Gr|gr prefix. In fact, I think +it's probably the right idea, but when I tested it out, I ran into +problems with SWIG's handling of namespaces. Bottom line, SWIG +(1.3.21) got confused and generated bad code when I started playing +around with namespaces in a not particularly convoluted way. I saw +problems using the boost::shared_ptr template in combination with +classes defined in the gnuradio namespace. It wasn't pretty... + + +* Naming conventions + +Death to CamelCaseNames! We've returned to a kinder, gentler era. +We're now using the "STL style" naming convention with a couple of +modifications since we're not using namespaces. + +With the exception of macros and other constant values, all +identifiers shall be lower case with words_separated_like_this. + +Macros and constant values (e.g., enumerated values, +static const int FOO = 23) shall be in UPPER_CASE. + + +** Global names + +All globally visible names (types, functions, variables, consts, etc) +shall begin with a "package prefix", followed by an '_'. The bulk of +the code in GNU Radio logically belongs to the "gr" package, hence +names look like gr_open_file (...). + +Large coherent bodies of code may use other package prefixes, but +let's try to keep them to a well thought out list. See the list +below. + +*** Package prefixes + +These are the current package prefixes: + + gr_ Almost everything + + gri_ Implementation primitives. Sometimes we + have both a gr_ and a gri_. In that case, + gr_ would be derived from gr_block and gri_ + would be the low level guts of the function. + + atsc_ Code related to the Advanced Television + Standards Committee HDTV implementation + + usrp_ Universal Software Radio Peripheral + + qa_ Quality Assurance. Test code. + + +** Class data members (instance variables) + +All class data members shall begin with d_. + +The big win is when you're staring at a block of code it's obvious +which of the things being assigned to persist outside of the block. +This also keeps you from having to be creative with parameter names +for methods and constructors. You just use the same name as the +instance variable, without the d_. + +class gr_wonderfulness { + std::string d_name; + double d_wonderfulness_factor; + +public: + gr_wonderfulness (std::string name, double wonderfulness_factor) + : d_name (name), d_wonderfulness_factor (wonderfulness_factor) + { + ... + } + ... +}; + + +** Class static data members (class variables) + +All class static data members shall begin with s_. + + +** File names + +Each significant class shall be contained in it's own file. The +declaration of class gr_foo shall be in gr_foo.h, the definition in +gr_foo.cc. + + + +* Storage management + +Strongly consider using the boost smart pointer templates, scoped_ptr +and shared_ptr. scoped_ptr should be used for locals that contain +pointers to objects that we need to delete when we exit the current +scope. shared_ptr implements transparent reference counting and is a +major win. You never have to worry about calling delete. The right +thing happens. + +See http://www.boost.org/libs/smart_ptr/smart_ptr.htm + + +* Unit tests + +Build unit tests for everything non-trivial and run them after every +change. Check out Extreme Programming: +http://c2.com/cgi/wiki?ExtremeProgrammingRoadmap + +Unit tests should also be written for all examples. This should kill +off the bit rot we've been plagued with. + +** C++ unit tests + +For C++ we're using the cppunit framework. cppunit has its bad +smells, but it's mostly workable. http://cppunit.sf.net + +Currently each directory contains files qa_.{h,cc} +that bring together all the qa_ test suites in the directory. +We ought to be able to automate this without too much trouble. + +The directory gnuradio-core/src/tests contains programs that run +the tests. test_all runs all of the registered C++ unit tests. + +As far as I can tell, the cppunit TestFactoryRegistry maybe able to be +tricked into doing what we want. As is, I don't think it's enough by +itself, since there's nothing dragging the qa* files out of the +library and into the program. I haven't tested out this idea. + +** Python unit tests + +We use the standard unittest package for unit testing of Python code. + + +* Misc tips + +ccache, a compiler cache, can really speed up your builds. +See http://ccache.samba.org/ + +Be sure to create links for gcc and g++ diff --git a/gnuradio-core/THANKS b/gnuradio-core/THANKS new file mode 100644 index 00000000..00e44886 --- /dev/null +++ b/gnuradio-core/THANKS @@ -0,0 +1,7 @@ +GNU Radio THANKS file + +GNU Radio has originally been written by Free Software Foundation, Inc. +Many people have further contributed to GNU Radio by reporting problems, +suggesting various improvements, or submitting actual code. Here is +a list of these people. Help me keep it complete and exempt of errors. + diff --git a/gnuradio-core/TODO b/gnuradio-core/TODO new file mode 100644 index 00000000..f9521c29 --- /dev/null +++ b/gnuradio-core/TODO @@ -0,0 +1,14 @@ +Have configure check for correct version of SWIG. +gr_swig checks, but doesn't set any variable that can be checked +afterwards. + +Failure to find SWIG should disable build of scripting directory + + +Have configure search for FFTW includes and libraries (use pkg-config +to find them) + +Come up with a consistent naming strategy and implement it! + +make o'scope display fast enough + diff --git a/gnuradio-core/doc/Doxyfile.in b/gnuradio-core/doc/Doxyfile.in new file mode 100644 index 00000000..7283a7b2 --- /dev/null +++ b/gnuradio-core/doc/Doxyfile.in @@ -0,0 +1,1224 @@ +# Doxyfile 1.4.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project +# +# All text after a hash (#) is considered a comment and will be ignored +# The format is: +# TAG = value [value, ...] +# For lists items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (" ") + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded +# by quotes) that should identify the project. + +PROJECT_NAME = "GNU Radio 2.x" + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. +# This could be handy for archiving the generated documentation or +# if some version control system is used. + +PROJECT_NUMBER = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) +# base path where the generated documentation will be put. +# If a relative path is entered, it will be relative to the location +# where doxygen was started. If left blank the current directory will be used. + +OUTPUT_DIRECTORY = + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create +# 4096 sub-directories (in 2 levels) under the output directory of each output +# format and will distribute the generated files over these directories. +# Enabling this option can be useful when feeding doxygen a huge amount of +# source files, where putting all generated files in the same directory would +# otherwise cause performance problems for the file system. + +CREATE_SUBDIRS = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# The default language is English, other supported languages are: +# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, +# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese, +# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian, +# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, +# Swedish, and Ukrainian. + +OUTPUT_LANGUAGE = English + +# This tag can be used to specify the encoding used in the generated output. +# The encoding is not always determined by the language that is chosen, +# but also whether or not the output is meant for Windows or non-Windows users. +# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES +# forces the Windows encoding (this is the default for the Windows binary), +# whereas setting the tag to NO uses a Unix-style encoding (the default for +# all platforms other than Windows). + +USE_WINDOWS_ENCODING = NO + +# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will +# include brief member descriptions after the members that are listed in +# the file and class documentation (similar to JavaDoc). +# Set to NO to disable this. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend +# the brief description of a member or function before the detailed description. +# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator +# that is used to form the text in various listings. Each string +# in this list, if found as the leading text of the brief description, will be +# stripped from the text and the result after processing the whole list, is +# used as the annotated text. Otherwise, the brief description is used as-is. +# If left blank, the following values are used ("$name" is automatically +# replaced with the name of the entity): "The $name class" "The $name widget" +# "The $name file" "is" "provides" "specifies" "contains" +# "represents" "a" "an" "the" + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# Doxygen will generate a detailed section even if there is only a brief +# description. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full +# path before files name in the file list and in the header files. If set +# to NO the shortest path that makes the file name unique will be used. + +FULL_PATH_NAMES = NO + +# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag +# can be used to strip a user-defined part of the path. Stripping is +# only done if one of the specified strings matches the left-hand part of +# the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the +# path to strip. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of +# the path mentioned in the documentation of a class, which tells +# the reader which header file to include in order to use a class. +# If left blank only the name of the header file containing the class +# definition is used. Otherwise one should specify the include paths that +# are normally passed to the compiler using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter +# (but less readable) file names. This can be useful is your file systems +# doesn't support long names like on DOS, Mac, or CD-ROM. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen +# will interpret the first line (until the first dot) of a JavaDoc-style +# comment as the brief description. If set to NO, the JavaDoc +# comments will behave just like the Qt-style comments (thus requiring an +# explicit @brief command for a brief description. + +JAVADOC_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen +# treat a multi-line C++ special comment block (i.e. a block of //! or /// +# comments) as a brief description. This used to be the default behaviour. +# The new default is to treat a multi-line C++ comment block as a detailed +# description. Set this tag to YES if you prefer the old behaviour instead. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the DETAILS_AT_TOP tag is set to YES then Doxygen +# will output the detailed description near the top, like JavaDoc. +# If set to NO, the detailed description appears after the member +# documentation. + +DETAILS_AT_TOP = YES + +# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented +# member inherits the documentation from any documented member that it +# re-implements. + +INHERIT_DOCS = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. + +DISTRIBUTE_GROUP_DOC = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. +# Doxygen uses this value to replace tabs by spaces in code fragments. + +TAB_SIZE = 8 + +# This tag can be used to specify a number of aliases that acts +# as commands in the documentation. An alias has the form "name=value". +# For example adding "sideeffect=\par Side Effects:\n" will allow you to +# put the command \sideeffect (or @sideeffect) in the documentation, which +# will result in a user-defined paragraph with heading "Side Effects:". +# You can put \n's in the value part of an alias to insert newlines. + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C +# sources only. Doxygen will then generate output that is more tailored for C. +# For instance, some of the names that are used will be different. The list +# of all members will be omitted, etc. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources +# only. Doxygen will then generate output that is more tailored for Java. +# For instance, namespaces will be presented as packages, qualified scopes +# will look different, etc. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the SUBGROUPING tag to YES (the default) to allow class member groups of +# the same type (for instance a group of public functions) to be put as a +# subgroup of that type (e.g. under the Public Functions section). Set it to +# NO to prevent subgrouping. Alternatively, this can be done per class using +# the \nosubgrouping command. + +SUBGROUPING = YES + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. +# Private class members and static file members will be hidden unless +# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class +# will be included in the documentation. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file +# will be included in the documentation. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) +# defined locally in source files will be included in the documentation. +# If set to NO only classes defined in header files are included. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local +# methods, which are defined in the implementation section but not in +# the interface are included in the documentation. +# If set to NO (the default) only methods in the interface are included. + +EXTRACT_LOCAL_METHODS = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all +# undocumented members of documented classes, files or namespaces. +# If set to NO (the default) these members will be included in the +# various overviews, but no documentation section is generated. +# This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. +# If set to NO (the default) these classes will be included in the various +# overviews. This option has no effect if EXTRACT_ALL is enabled. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all +# friend (class|struct|union) declarations. +# If set to NO (the default) these declarations will be included in the +# documentation. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any +# documentation blocks found inside the body of a function. +# If set to NO (the default) these blocks will be appended to the +# function's detailed documentation block. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation +# that is typed after a \internal command is included. If the tag is set +# to NO (the default) then the documentation will be excluded. +# Set it to YES to include the internal documentation. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate +# file names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen +# will show members with their full class and namespace scopes in the +# documentation. If set to YES the scope will be hidden. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen +# will put a list of the files that are included by a file in the documentation +# of that file. + +SHOW_INCLUDE_FILES = YES + +# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] +# is inserted in the documentation for inline members. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen +# will sort the (detailed) documentation of file and class members +# alphabetically by member name. If set to NO the members will appear in +# declaration order. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the +# brief documentation of file, namespace and class members alphabetically +# by member name. If set to NO (the default) the members will appear in +# declaration order. + +SORT_BRIEF_DOCS = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be +# sorted by fully-qualified names, including namespaces. If set to +# NO (the default), the class list will be sorted only by class name, +# not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the +# alphabetical list. + +SORT_BY_SCOPE_NAME = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or +# disable (NO) the todo list. This list is created by putting \todo +# commands in the documentation. + +GENERATE_TODOLIST = YES + +# The GENERATE_TESTLIST tag can be used to enable (YES) or +# disable (NO) the test list. This list is created by putting \test +# commands in the documentation. + +GENERATE_TESTLIST = YES + +# The GENERATE_BUGLIST tag can be used to enable (YES) or +# disable (NO) the bug list. This list is created by putting \bug +# commands in the documentation. + +GENERATE_BUGLIST = YES + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or +# disable (NO) the deprecated list. This list is created by putting +# \deprecated commands in the documentation. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional +# documentation sections, marked by \if sectionname ... \endif. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines +# the initial value of a variable or define consists of for it to appear in +# the documentation. If the initializer consists of more lines than specified +# here it will be hidden. Use a value of 0 to hide initializers completely. +# The appearance of the initializer of individual variables and defines in the +# documentation can be controlled using \showinitializer or \hideinitializer +# command in the documentation regardless of this setting. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated +# at the bottom of the documentation of classes and structs. If set to YES the +# list will mention the files that were used to generate the documentation. + +SHOW_USED_FILES = YES + +# If the sources in your project are distributed over multiple directories +# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy +# in the documentation. + +# -eb +SHOW_DIRECTORIES = NO + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from the +# version control system). Doxygen will invoke the program by executing (via +# popen()) the command , where is the value of +# the FILE_VERSION_FILTER tag, and is the name of an input file +# provided by doxygen. Whatever the progam writes to standard output +# is used as the file version. See the manual for examples. + +FILE_VERSION_FILTER = + +#--------------------------------------------------------------------------- +# configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated +# by doxygen. Possible values are YES and NO. If left blank NO is used. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated by doxygen. Possible values are YES and NO. If left blank +# NO is used. + +WARNINGS = YES + +# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings +# for undocumented members. If EXTRACT_ALL is set to YES then this flag will +# automatically be disabled. + +WARN_IF_UNDOCUMENTED = YES + +# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some +# parameters in a documented function, or documenting parameters that +# don't exist or using markup commands wrongly. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be abled to get warnings for +# functions that are documented, but have no documentation for their parameters +# or return value. If set to NO (the default) doxygen will only warn about +# wrong or incomplete parameter documentation, but not about the absence of +# documentation. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that +# doxygen can produce. The string should contain the $file, $line, and $text +# tags, which will be replaced by the file and line number from which the +# warning originated and the warning text. Optionally the format may contain +# $version, which will be replaced by the version of the file (if it could +# be obtained via FILE_VERSION_FILTER) + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning +# and error messages should be written. If left blank the output is written +# to stderr. + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag can be used to specify the files and/or directories that contain +# documented source files. You may enter file names like "myfile.cpp" or +# directories like "/usr/src/myproject". Separate the files or directories +# with spaces. + +INPUT = @top_srcdir@/src/lib \ + @top_srcdir@/src/tests \ + @top_srcdir@/doc/other + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank the following patterns are tested: +# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx +# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm + +FILE_PATTERNS = *.h \ + *.cc \ + *.dox + +# The RECURSIVE tag can be used to turn specify whether or not subdirectories +# should be searched for input files as well. Possible values are YES and NO. +# If left blank NO is used. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. + +EXCLUDE = CVS \ + @top_srcdir@/src/lib/swig/gnuradio_swig_python.cc \ + @top_srcdir@/src/lib/atsc \ + @top_srcdir@/src/lib/io-orig \ + @top_srcdir@/src/lib/vrx + +# The EXCLUDE_SYMLINKS tag can be used select whether or not files or +# directories that are symbolic links (a Unix filesystem feature) are excluded +# from the input. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. + +EXCLUDE_PATTERNS = moc_*.cc + +# The EXAMPLE_PATH tag can be used to specify one or more files or +# directories that contain example code fragments that are included (see +# the \include command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp +# and *.h) to filter out the source-files in the directories. If left +# blank all files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude +# commands irrespective of the value of the RECURSIVE tag. +# Possible values are YES and NO. If left blank NO is used. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or +# directories that contain image that are included in the documentation (see +# the \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command , where +# is the value of the INPUT_FILTER tag, and is the name of an +# input file. Doxygen will then use the output that the filter program writes +# to standard output. If FILTER_PATTERNS is specified, this tag will be +# ignored. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: +# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further +# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER +# is applied to all files. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will be used to filter the input files when producing source +# files to browse (i.e. when SOURCE_BROWSER is set to YES). + +FILTER_SOURCE_FILES = NO + +#--------------------------------------------------------------------------- +# configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will +# be generated. Documented entities will be cross-referenced with these sources. +# Note: To get rid of all source code in the generated output, make sure also +# VERBATIM_HEADERS is set to NO. + +SOURCE_BROWSER = NO + +# Setting the INLINE_SOURCES tag to YES will include the body +# of functions and classes directly in the documentation. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct +# doxygen to hide any special comment blocks from generated source code +# fragments. Normal C and C++ comments will always remain visible. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES (the default) +# then for each documented function all documented +# functions referencing it will be listed. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES (the default) +# then for each documented function all documented entities +# called/used by that function will be listed. + +REFERENCES_RELATION = YES + +# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen +# will generate a verbatim copy of the header file for each class for +# which an include is specified. Set to NO to disable this. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index +# of all compounds will be generated. Enable this if the project +# contains a lot of classes, structs, unions or interfaces. + +ALPHABETICAL_INDEX = NO + +# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then +# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns +# in which this list will be split (can be a number in the range [1..20]) + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all +# classes will be put under the same header in the alphabetical index. +# The IGNORE_PREFIX tag can be used to specify one or more prefixes that +# should be ignored while generating the index headers. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES (the default) Doxygen will +# generate HTML output. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `html' will be used as the default path. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for +# each generated HTML page (for example: .htm,.php,.asp). If it is left blank +# doxygen will generate files with .html extension. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a personal HTML header for +# each generated HTML page. If it is left blank doxygen will generate a +# standard header. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a personal HTML footer for +# each generated HTML page. If it is left blank doxygen will generate a +# standard footer. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading +# style sheet that is used by each HTML page. It can be used to +# fine-tune the look of the HTML output. If the tag is left blank doxygen +# will generate a default style sheet. Note that doxygen will try to copy +# the style sheet file to the HTML output directory, so don't put your own +# stylesheet in the HTML output directory as well, or it will be erased! + +HTML_STYLESHEET = + +# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, +# files or namespaces will be aligned in HTML using tables. If set to +# NO a bullet list will be used. + +HTML_ALIGN_MEMBERS = YES + +# If the GENERATE_HTMLHELP tag is set to YES, additional index files +# will be generated that can be used as input for tools like the +# Microsoft HTML help workshop to generate a compressed HTML help file (.chm) +# of the generated HTML documentation. + +GENERATE_HTMLHELP = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can +# be used to specify the file name of the resulting .chm file. You +# can add a path in front of the file if the result should not be +# written to the html output directory. + +CHM_FILE = + +# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can +# be used to specify the location (absolute path including file name) of +# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run +# the HTML help compiler on the generated index.hhp. + +HHC_LOCATION = + +# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag +# controls if a separate .chi index file is generated (YES) or that +# it should be included in the master .chm file (NO). + +GENERATE_CHI = NO + +# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag +# controls whether a binary table of contents is generated (YES) or a +# normal table of contents (NO) in the .chm file. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members +# to the contents of the HTML help documentation and to the tree view. + +TOC_EXPAND = NO + +# The DISABLE_INDEX tag can be used to turn on/off the condensed index at +# top of each HTML page. The value NO (the default) enables the index and +# the value YES disables it. + +DISABLE_INDEX = NO + +# This tag can be used to set the number of enum values (range [1..20]) +# that doxygen will group on one line in the generated HTML documentation. + +ENUM_VALUES_PER_LINE = 4 + +# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be +# generated containing a tree-like index structure (just like the one that +# is generated for HTML Help). For this to work a browser that supports +# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+, +# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are +# probably better off using the HTML help feature. + +GENERATE_TREEVIEW = NO + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be +# used to set the initial width (in pixels) of the frame in which the tree +# is shown. + +TREEVIEW_WIDTH = 250 + +#--------------------------------------------------------------------------- +# configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will +# generate Latex output. + +# -eb +GENERATE_LATEX = NO + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `latex' will be used as the default path. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. If left blank `latex' will be used as the default command name. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to +# generate index for LaTeX. If left blank `makeindex' will be used as the +# default command name. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact +# LaTeX documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used +# by the printer. Possible values are: a4, a4wide, letter, legal and +# executive. If left blank a4wide will be used. + +PAPER_TYPE = letter + +# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX +# packages that should be included in the LaTeX output. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for +# the generated latex document. The header should contain everything until +# the first chapter. If it is left blank doxygen will generate a +# standard header. Notice: only use this tag if you know what you are doing! + +LATEX_HEADER = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated +# is prepared for conversion to pdf (using ps2pdf). The pdf file will +# contain links (just like the HTML output) instead of page references +# This makes the output suitable for online browsing using a pdf viewer. + +PDF_HYPERLINKS = YES + +# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of +# plain latex in the generated Makefile. Set this option to YES to get a +# higher quality PDF documentation. + +USE_PDFLATEX = NO + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. +# command to the generated LaTeX files. This will instruct LaTeX to keep +# running if errors occur, instead of asking the user for help. +# This option is also used when generating formulas in HTML. + +LATEX_BATCHMODE = NO + +# If LATEX_HIDE_INDICES is set to YES then doxygen will not +# include the index chapters (such as File Index, Compound Index, etc.) +# in the output. + +LATEX_HIDE_INDICES = NO + +#--------------------------------------------------------------------------- +# configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output +# The RTF output is optimized for Word 97 and may not look very pretty with +# other RTF readers or editors. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `rtf' will be used as the default path. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES Doxygen generates more compact +# RTF documents. This may be useful for small projects and may help to +# save some trees in general. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated +# will contain hyperlink fields. The RTF file will +# contain links (just like the HTML output) instead of page references. +# This makes the output suitable for online browsing using WORD or other +# programs which support those fields. +# Note: wordpad (write) and others do not support links. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's +# config file, i.e. a series of assignments. You only have to provide +# replacements, missing definitions are set to their default value. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an rtf document. +# Syntax is similar to doxygen's config file. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES (the default) Doxygen will +# generate man pages + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `man' will be used as the default path. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to +# the generated man pages (default is the subroutine's section .3) + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and Doxygen generates man output, +# then it will generate one additional man file for each entity +# documented in the real man page(s). These additional files +# only source the real man page, but without them the man command +# would be unable to find the correct page. The default is NO. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES Doxygen will +# generate an XML file that captures the structure of +# the code including all documentation. + +GENERATE_XML = YES + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be +# put in front of it. If left blank `xml' will be used as the default path. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify an XML schema, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify an XML DTD, +# which can be used by a validating XML parser to check the +# syntax of the XML files. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES Doxygen will +# dump the program listings (including syntax highlighting +# and cross-referencing information) to the XML output. Note that +# enabling this will significantly increase the size of the XML output. + +# -eb +XML_PROGRAMLISTING = NO + +#--------------------------------------------------------------------------- +# configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will +# generate an AutoGen Definitions (see autogen.sf.net) file +# that captures the structure of the code including all +# documentation. Note that this feature is still experimental +# and incomplete at the moment. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES Doxygen will +# generate a Perl module file that captures the structure of +# the code including all documentation. Note that this +# feature is still experimental and incomplete at the +# moment. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES Doxygen will generate +# the necessary Makefile rules, Perl scripts and LaTeX code to be able +# to generate PDF and DVI output from the Perl module output. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be +# nicely formatted so it can be parsed by a human reader. This is useful +# if you want to understand what is going on. On the other hand, if this +# tag is set to NO the size of the Perl module output will be much smaller +# and Perl will parse it just the same. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file +# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. +# This is useful so different doxyrules.make files included by the same +# Makefile don't overwrite each other's variables. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will +# evaluate all C-preprocessor directives found in the sources and include +# files. + +ENABLE_PREPROCESSING = YES + +# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro +# names in the source code. If set to NO (the default) only conditional +# compilation will be performed. Macro expansion can be done in a controlled +# way by setting EXPAND_ONLY_PREDEF to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES +# then the macro expansion is limited to the macros specified with the +# PREDEFINED and EXPAND_AS_PREDEFINED tags. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files +# in the INCLUDE_PATH (see below) will be search if a #include is found. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by +# the preprocessor. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will +# be used. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that +# are defined before the preprocessor is started (similar to the -D option of +# gcc). The argument of the tag is a list of macros of the form: name +# or name=definition (no spaces). If the definition and the = are +# omitted =1 is assumed. To prevent a macro definition from being +# undefined via #undef or recursively expanded use the := operator +# instead of the = operator. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then +# this tag can be used to specify a list of macro names that should be expanded. +# The macro definition that is found in the sources will be used. +# Use the PREDEFINED tag if you want to use a different macro definition. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then +# doxygen's preprocessor will remove all function-like macros that are alone +# on a line, have an all uppercase name, and do not end with a semicolon. Such +# function macros are typically used for boiler-plate code, and will confuse +# the parser if not removed. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES option can be used to specify one or more tagfiles. +# Optionally an initial location of the external documentation +# can be added for each tagfile. The format of a tag file without +# this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where "loc1" and "loc2" can be relative or absolute paths or +# URLs. If a location is present for each tag, the installdox tool +# does not have to be run to correct the links. +# Note that each tag file must have a unique name +# (where the name does NOT include the path) +# If a tag file is not located in the directory in which doxygen +# is run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create +# a tag file that is based on the input files it reads. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external classes will be listed +# in the class index. If set to NO only the inherited external classes +# will be listed. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will +# be listed. + +EXTERNAL_GROUPS = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of `which perl'). + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will +# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base +# or super classes. Setting the tag to NO turns the diagrams off. Note that +# this option is superseded by the HAVE_DOT option below. This is only a +# fallback. It is recommended to install and use dot, since it yields more +# powerful graphs. + +CLASS_DIAGRAMS = YES + +# If set to YES, the inheritance and collaboration graphs will hide +# inheritance and usage relations if the target is undocumented +# or is not a class. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz, a graph visualization +# toolkit from AT&T and Lucent Bell Labs. The other options in this section +# have no effect if this option is set to NO (the default) + +HAVE_DOT = @HAVE_DOT@ + +# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect inheritance relations. Setting this tag to YES will force the +# the CLASS_DIAGRAMS tag to NO. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for each documented class showing the direct and +# indirect implementation dependencies (inheritance, containment, and +# class references variables) of the class with other documented classes. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen +# will generate a graph for groups, showing the direct groups dependencies + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. + +UML_LOOK = NO + +# If set to YES, the inheritance and collaboration graphs will show the +# relations between templates and their instances. + +TEMPLATE_RELATIONS = NO + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT +# tags are set to YES then doxygen will generate a graph for each documented +# file showing the direct and indirect include dependencies of the file with +# other documented files. + +INCLUDE_GRAPH = YES + +# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and +# HAVE_DOT tags are set to YES then doxygen will generate a graph for each +# documented header file showing the documented files that directly or +# indirectly include this file. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will +# generate a call dependency graph for every global function or class method. +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. + +CALL_GRAPH = NO + +# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen +# will graphical hierarchy of all classes instead of a textual one. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES +# then doxygen will show the dependencies a directory has on other directories +# in a graphical way. The dependency relations are determined by the #include +# relations between the files in the directories. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. Possible values are png, jpg, or gif +# If left blank png will be used. + +DOT_IMAGE_FORMAT = png + +# The tag DOT_PATH can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the +# \dotfile command). + +DOTFILE_DIRS = + +# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_WIDTH = 1024 + +# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height +# (in pixels) of the graphs generated by dot. If a graph becomes larger than +# this value, doxygen will try to truncate the graph, so that it fits within +# the specified constraint. Beware that most browsers cannot cope with very +# large images. + +MAX_DOT_GRAPH_HEIGHT = 1024 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the +# graphs generated by dot. A depth value of 3 means that only nodes reachable +# from the root by following a path via at most 3 edges will be shown. Nodes +# that lay further from the root node will be omitted. Note that setting this +# option to 1 or 2 may greatly reduce the computation time needed for large +# code bases. Also note that a graph may be further truncated if the graph's +# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH +# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default), +# the graph is not depth-constrained. + +MAX_DOT_GRAPH_DEPTH = 0 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, which results in a white background. +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) +# support this, this feature is disabled by default. + +# -eb +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will +# generate a legend page explaining the meaning of the various boxes and +# arrows in the dot generated graphs. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will +# remove the intermediate dot files that are used to generate +# the various graphs. + +DOT_CLEANUP = YES + +#--------------------------------------------------------------------------- +# Configuration::additions related to the search engine +#--------------------------------------------------------------------------- + +# The SEARCHENGINE tag specifies whether or not a search engine should be +# used. If set to NO the values of all tags below this one will be ignored. + +SEARCHENGINE = NO diff --git a/gnuradio-core/doc/Makefile.am b/gnuradio-core/doc/Makefile.am new file mode 100644 index 00000000..562b3665 --- /dev/null +++ b/gnuradio-core/doc/Makefile.am @@ -0,0 +1,71 @@ +# +# Copyright 2001,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 + +SUBDIRS = other xml + +man3dir = $(mandir)/man3 +docdir = $(prefix)/share/doc/@PACKAGE@-@VERSION@ + +EXTRA_DIST = + +all-local: prep @generate_docs@ +doc: docs # alias + +docs: prep html/index.html +html/index.html: + @DOXYGEN@ + +prep: + mkdir -p html + +#install-data-local: +# $(mkinstalldirs) $(DESTDIR)$(man3dir) +# @for i in ./man/man3/*.3; do \ +# inst=`basename $$i | sed 's/_/:/g'`; \ +# echo "$(INSTALL_DATA) $$i $(DESTDIR)$(man3dir)/$$inst"; \ +# $(INSTALL_DATA) $$i $(DESTDIR)$(man3dir)/$$inst; \ +# done +# $(mkinstalldirs) $(DESTDIR)$(docdir) +## @for i in ../README ../ChangeLog @PACKAGE@.ps @PACKAGE@.pdf; do \ +## echo "$(INSTALL_DATA) $$i $(DESTDIR)$(docdir)"; \ +## $(INSTALL_DATA) $$i $(DESTDIR)$(docdir); \ +## done +# cp -r html $(docdir) + +install-data-local: + $(mkinstalldirs) $(DESTDIR)$(docdir) + @for i in $(top_srcdir)/README $(top_srcdir)/README.hacking $(top_srcdir)/ChangeLog; do \ + echo "$(INSTALL_DATA) $$i $(DESTDIR)$(docdir)"; \ + $(INSTALL_DATA) $$i $(DESTDIR)$(docdir); \ + done + cp -r html $(DESTDIR)$(docdir) + +uninstall-local: + @for i in README README.hacking ChangeLog; do \ + echo "$(RM) $(DESTDIR)$(docdir)/$$i;"; \ + $(RM) $(DESTDIR)$(docdir)/$$i; \ + done + $(RM) -fr $(DESTDIR)$(docdir)/html + +clean-local: + $(RM) -fr latex html man diff --git a/gnuradio-core/doc/other/Makefile.am b/gnuradio-core/doc/other/Makefile.am new file mode 100644 index 00000000..25685eda --- /dev/null +++ b/gnuradio-core/doc/other/Makefile.am @@ -0,0 +1,31 @@ +# +# 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 + +EXTRA_DIST = \ + tv-channel-frequencies \ + vector_docstub.h \ + shared_ptr_docstub.h \ + omnithread.html \ + omnithread.pdf \ + omnithread.ps \ + group_defs.dox diff --git a/gnuradio-core/doc/other/group_defs.dox b/gnuradio-core/doc/other/group_defs.dox new file mode 100644 index 00000000..47cce21c --- /dev/null +++ b/gnuradio-core/doc/other/group_defs.dox @@ -0,0 +1,31 @@ +/*! + * \defgroup block Signal Processing Blocks + * These are the signal processing blocks, blah, blah blah... + * @{ + */ + +/*! + * \defgroup source Signal Sources + * signal sources docs... + */ + +/*! + * \defgroup sink Signal Sinks + * docs for sinks... + */ + +/*! + * \defgroup filter Filters + */ + +/*! + * \defgroup converter Type Conversions + */ + +/*! @} */ + +/*! \defgroup filter_design Filter Design */ +/*! \defgroup filter_primitive Filter Primitives */ +/*! \defgroup internal Implementation Details */ +/*! \defgroup qa Quality Assurance */ + diff --git a/gnuradio-core/doc/other/main_page.dox b/gnuradio-core/doc/other/main_page.dox new file mode 100644 index 00000000..5c37905f --- /dev/null +++ b/gnuradio-core/doc/other/main_page.dox @@ -0,0 +1,5 @@ +/*! \mainpage + +Welcome to GNU Radio! + +*/ diff --git a/gnuradio-core/doc/other/omnithread.html b/gnuradio-core/doc/other/omnithread.html new file mode 100644 index 00000000..5682d1d0 --- /dev/null +++ b/gnuradio-core/doc/other/omnithread.html @@ -0,0 +1,411 @@ + + +The OMNI Thread Abstraction + + + + + + + + + + + + +

The OMNI Thread Abstraction

+ +

Tristan Richardson
+AT&T Laboratories Cambridge
+

+ +

Revised November 2001

+ + +
+ +The OMNI thread abstraction is designed to provide a common set of +thread operations for use in programs written in C++. Programs +written using the abstraction should be much easier to port between +different architectures with different underlying threads primitives.
+
+The programming interface is designed to be similar to the C language +interface to POSIX threads (IEEE draft standard 1003.1c --- previously +1003.4a, often known as ``pthreads'' [POSIX94]).
+
+Much of the abstraction consists of simple C++ object wrappers around +pthread calls. However for some features such as thread-specific +data, a better interface can be offered because of the use of C++.
+
+Some of the more complex features of pthreads are not supported +because of the difficulty of ensuring the same features can be offered +on top of other thread systems. Such features include thread +cancellation and complex scheduling control (though simple thread +priorities are supported).
+
+The abstraction layer is currently implemented for the following +architectures / thread systems: +
  • Solaris 2.x using pthreads draft 10 +
  • Solaris 2.x using solaris threads (but pthreads version is now standard) +
  • Alpha OSF1 using pthreads draft 4 +
  • Windows NT using NT threads +
  • Linux 2.x using Linuxthread 0.5 (which is based on pthreads draft 10) +
  • Linux 2.x using MIT pthreads (which is based on draft 8) +
  • ATMos using pthreads draft 6 (but not Virata ATMos)
+See the omnithread.h header file for full details of the API. +The descriptions below assume you have some previous knowledge of +threads, mutexes, condition variables and semaphores. Also refer to +other documentation ([Birrell89], [POSIX94]) for further +explanation of these ideas (particularly condition variables, the use +of which may not be particularly intuitive when first encountered).
+
+ + +

2  Synchronisation objects

+ +Synchronisation objects are used to synchronise threads within the +same process. There is no inter-process synchronisation provided. +The synchronisation objects provided are mutexes, condition variables +and counting semaphores.
+
+ + +

2.1  Mutex

+ +An object of type omni_mutex is used for mutual exclusion. +It provides two operations, lock() and unlock(). +The alternative names acquire() and release() can be +used if preferred. Behaviour is undefined when a thread attempts to +lock the same mutex again or when a mutex is locked by one thread and +unlocked by a different thread.
+
+ + +

2.2  Condition Variable

+ +A condition variable is represented by an omni_condition and +is used for signalling between threads. A call to wait() +causes a thread to wait on the condition variable. A call to +signal() wakes up at least one thread if any are waiting. A +call to broadcast() wakes up all threads waiting on the +condition variable.
+
+When constructed, a pointer to an omni_mutex must be given. +A condition variable wait() has an implicit mutex +unlock() and lock() around it. The link between +condition variable and mutex lasts for the lifetime of the condition +variable (unlike pthreads where the link is only for the duration of +the wait). The same mutex may be used with several condition +variables.
+
+A wait with a timeout can be achieved by calling +timed_wait(). This is given an absolute time to wait until. +The routine omni_thread::get_time() can be used to turn a +relative time into an absolute time. timed_wait() returns +true if the condition was signalled, false if the +time expired before the condition variable was signalled.
+
+ + +

2.3  Counting semaphores

+ +An omni_semaphore is a counting semaphore. When created it +is given an initial unsigned integer value. When wait() is +called, the value is decremented if non-zero. If the value is zero +then the thread blocks instead. When post() is called, if +any threads are blocked in wait(), exactly one thread is +woken. If no threads were blocked then the value of the semaphore is +incremented.
+
+If a thread calls try_wait(), then the thread won't block if +the semaphore's value is 0, returning false instead.
+
+There is no way of querying the value of the semaphore.
+
+ + +

3  Thread object

+ +A thread is represented by an omni_thread object. There are +broadly two different ways in which it can be used.
+
+The first way is simply to create an omni_thread object, +giving a particular function which the thread should execute. This is +like the POSIX (or any other) C language interface.
+
+The second method of use is to create a new class which inherits from +omni_thread. In this case the thread will execute the +run() member function of the new class. One advantage of +this scheme is that thread-specific data can be implemented simply by +having data members of the new class.
+
+When constructed a thread is in the "new" state and has not actually +started. A call to start() causes the thread to begin +executing. A static member function create() is provided to +construct and start a thread in a single call. A thread exits by +calling exit() or by returning from the thread function.
+
+Threads can be either detached or undetached. Detached threads are +threads for which all state will be lost upon exit. Other threads +cannot determine when a detached thread will disappear, and therefore +should not attempt to access the thread object unless some explicit +synchronisation with the detached thread guarantees that it still +exists.
+
+Undetached threads are threads for which storage is not reclaimed +until another thread waits for its termination by calling +join(). An exit value can be passed from an undetached +thread to the thread which joins it.
+
+Detached / undetached threads are distinguished on creation by the +type of function they execute. Undetached threads execute a function +which has a void* return type, whereas detached threads +execute a function which has a void return type. +Unfortunately C++ member functions are not allowed to be distinguished +simply by their return type. Thus in the case of a derived class of +omni_thread which needs an undetached thread, the member +function executed by the thread is called run_undetached() +rather than run(), and it is started by calling +start_undetached() instead of start().
+
+The abstraction currently supports three priorities of thread, but no +guarantee is made of how this will affect underlying thread +scheduling. The three priorities are PRIORITY_LOW, +PRIORITY_NORMAL and PRIORITY_HIGH. By default all +threads run at PRIORITY_NORMAL. A different priority can be +specified on thread creation, or while the thread is running using +set_priority(). A thread's current priority is returned by +priority().
+
+Other functions provided are self() which returns the calling +thread's omni_thread object, yield() which +requests that other threads be allowed to run, id() which +returns an integer id for the thread for use in debugging, +state(), sleep() and get_time().
+
+ + +

4  Per-thread data

+ +omnithread supports per-thread data, via member functions of the +omni_thread object.
+
+First, you must allocate a key for with the +omni_thread::allocate_key() function. Then, any object +whose class is derived from omni_thread::value_t can be +stored using the set_value() function. Values are retrieved +or removed with get_value() and remove_value() +respectively.
+
+When the thread exits, all per-thread data is deleted (hence the base +class with virtual destructor).
+
+Note that the per-thread data functions are not thread safe, +so although you can access one thread's storage from another thread, +there is no concurrency control. Unless you really know what you are +doing, it is best to only access per-thread data from the thread it is +attached to.
+
+ + +

5  Using OMNI threads in your program

+ +Obviously you need to include the omnithread.h header file in +your source code, and link in the omnithread library with your +executable. Because there is a single omnithread.h for all +platforms, certain preprocessor defines must be given as compiler +options. The easiest way to do this is to study the makefiles given +in the examples provided with this distribution. If you are to +include OMNI threads in your own development environment, these are +the necessary preprocessor defines:
+ + + + + + + + + + + + + + + + + + + + + + + + +
PlatformPreprocessor Defines
Sun Solaris 2.x-D__sunos__ -D__sparc__ -D__OSVERSION__=5
 -DSVR4 -DUsePthread -D_REENTRANT
x86 Linux 2.0-D__linux__ -D__i86__ -D__OSVERSION__=2
with linuxthreads 0.5-D_REENTRANT
Digital Unix 3.2-D__osf1__ -D__alpha__ -D__OSVERSION__=3
 -D_REENTRANT
Windows NT-D__NT__ -MD

+ + +

6  Threaded I/O shutdown for Unix

+ +or, how one thread should tell another thread to shut down when it +might be doing a blocking call on a socket.
+
+If you are using omniORB, you don't need to worry about all +this, since omniORB does it for you. This section is only relevant +if you are using omnithread in your own socket-based programming. It +is also seriously out of date.
+
+Unfortunately there doesn't seem to be a standard way of doing this +which works across all Unix systems. I have investigated the +behaviour of Solaris 2.5 and Digital Unix 3.2. On Digital Unix +everything is fine, as the obvious method using shutdown() seems to +work OK. Unfortunately on Solaris shutdown can only be used on a +connected socket, so we need devious means to get around this +limitation. The details are summarised below:
+
+ + +

6.1  read()

+ +Thread A is in a loop, doing read(sock), processing the data, +then going back into the read.
+
+Thread B comes along and wants to shut it down --- it can't cancel +thread A since (i) working out how to clean up according to where A is +in its loop is a nightmare, and (ii) this isn't available in +omnithread anyway.
+
+On Solaris 2.5 and Digital Unix 3.2 the following strategy works:
+
+Thread B does shutdown(sock,2).
+
+At this point thread A is either blocked inside read(sock), or +is elsewhere in the loop. If the former then read will return 0, +indicating that the socket is closed. If the latter then eventually +thread A will call read(sock) and then this will return 0. +Thread A should close(sock), do any other tidying up, and exit.
+
+If there is another point in the loop that thread A can block then +obviously thread B needs to be aware of this and be able to wake it up +in the appropriate way from that point.
+
+ + +

6.2  accept()

+ +Again thread A is in a loop, this time doing an accept on listenSock, +dealing with a new connection and going back into accept. Thread B +wants to cancel it.
+
+On Digital Unix 3.2 the strategy is identical to that for read:
+
+Thread B does shutdown(listenSock,2). Wherever thread A is in +the loop, eventually it will return ECONNABORTED from the +accept call. It should close(listenSock), tidy up as necessary +and exit.
+
+On Solaris 2.5 thread B can't do shutdown(listenSock,2) --- +this returns ENOTCONN. Instead the following strategy can be +used:
+
+First thread B sets some sort of "shutdown flag" associated with +listenSock. Then it does getsockaddr(listenSock) to find out +which port listenSock is on (or knows already), sets up a socket +dummySock, does connect(dummySock, this host, port) and +finally does close(dummySock).
+
+Wherever thread A is in the loop, eventually it will call +accept(listenSock). This will return successfully with a new +socket, say connSock. Thread A then checks to see if the "shutdown +flag" is set. If not, then it's a normal connection. If it is set, +then thread A closes listenSock and connSock, tidies up and exits.
+
+ + +

6.3  write()

+ +Thread A may be blocked in write, or about to go in to a +potentially-blocking write. Thread B wants to shut it down.
+
+On Solaris 2.5:
+
+Thread B does shutdown(sock,2).
+
+If thread A is already in write(sock) then it will return with +ENXIO. If thread A calls write after thread B calls shutdown +this will return EIO.
+
+On Digital Unix 3.2:
+
+Thread B does shutdown(sock,2).
+
+If thread A is already in write(sock) then it will return the +number of bytes written before it became blocked. A subsequent call +to write will then generate SIGPIPE (or EPIPE will be +returned if SIGPIPE is ignored by the thread).
+
+ + +

6.4  connect()

+ +Thread A may be blocked in connect, or about to go in to a +potentially-blocking connect. Thread B wants to shut it down.
+
+On Digital Unix 3.2:
+
+Thread B does shutdown(sock,2).
+
+If thread A is already in connect(sock) then it will return a +successful connection. Subsequent reading or writing will show that +the socket has been shut down (i.e. read returns 0, write generates +SIGPIPE or returns EPIPE). If thread A calls connect +after thread B calls shutdown this will return EINVAL.
+
+On Solaris 2.5:
+
+There is no way to wake up a thread which is blocked in connect. +Instead Solaris forces us through a ridiculous procedure whichever way +we try it. One way is this:
+
+First thread A creates a pipe in addition to the socket. Instead of +shutting down the socket, thread B simply writes a byte to the pipe.
+
+Thread A meanwhile sets the socket to non-blocking mode using +fcntl(sock, F_SETFL, O_NONBLOCK). Then it calls connect +on the socket --- this will return EINPROGRESS. Then it must +call select(), waiting for either sock to become writable or +for the pipe to become readable. If select returns that just sock is +writable then the connection has succeeded. It then needs to set the +socket back to blocking mode using fcntl(sock, F_SETFL, 0). If +instead select returns that the pipe is readable, thread A closes the +socket, tidies up and exits.
+
+An alternative method is similar but to use polling instead of the +pipe. Thread B justs sets a flag and thread A calls select with a +timeout, periodically waking up to see if the flag has been set.
+
+ + +

References

+
[POSIX94]
+Portable Operating System Interface (POSIX) Threads Extension, +P1003.1c Draft 10, +IEEE, +September 1994.
+
+
[Birrell89]
+An Introduction to Programming with Threads, +Research Report 35, +DEC Systems Research Center, +Palo Alto, CA, +January 1989.
+ + + +
+
This document was translated from LATEX by +HEVEA. +
+ + diff --git a/gnuradio-core/doc/other/omnithread.pdf b/gnuradio-core/doc/other/omnithread.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b54218744874c22560e9092acc19e08d22b6410f GIT binary patch literal 126474 zcmb?@2UrwM)-IAAct{c@jewFFayB3t0m)I20R|Wt(#()E2uPMBNk9}q0a1eFED|Iq zB`3*QP>_6kK>gg^@BX`Y@Be7iJ=G`GIj5@Ls_yEm8gdG}0(^oXAuvDK(cBg+Ee(RG z!W^v8Heg|(NDBl}fFsZ_Bp9NAfTCe?FbhXZ80f|g5DJZiLG3~Aqp$VvJC2JI6C5Nb z`QY6I-N;@vI@zp+$%Mmf`kzT4aH?*!m2Iqbl@Z_RzMALU*!G9I@vEF<<3U&B zSU9&8wG?@1e4AOID?b9P<+q}g&E~t>-{i-;Z5}tU6n%;9HG2JSDes5*80^cBls1Ki)~)&kJvuN{ZPN$d@w%3Lb5j0!!7+Sz^W!UZjb7cl0>fBC;bm0 zbYjoK=rdM-2o&Awz9@Y^|FF}6yD=Q+20@{$)|A|I>QwPHi|eCX_mYw?70F{0T4t;B zC^JaLR$0@E7tt)oTNbeuu8t{U3ozxQM7s&dxOBD;kftlfIm*C zI(8u*S3qQ7nC(Du6T=s!^>1)rV=7`g%4G@1RLvkWiZJh}smiY21;&8~FS?`icPQ{* zxu$U4O(2r7ed7@mA;W)9hu1fXJ}pC3!F5butJsy#)z@={2aEUB@$xcG(92N}9}JG@ zlc3x?qP)s%TM@%dCS|d*I@!_{H?`gU#wFPRLF2f1InWgt^NUdAP6i&Akx8Sy)UEq_}eE&-zZgQKKm(mcpzwq`Es9S&E9zOf5?ba2T#* zG#Qh+$?TBVc=^F@Zj4xx-we{%1bnm}vN8YR1Kvh>Mj@3=P=j82Ha`eAMZ>L57CC+t z!yJi4d7W9#=VmO?lJUC;tRsArtYgQH@=$&`wWWHOOM54>qcrQ@m%Z^6+xsH#!JA*b zd}%Zwz@wII75rLUVvy>avOr>t4tA9%@!s+)sMRUf%A<;PIKg+@XsFqbUh0ZWcVA&f ziPv^mL;ZIy9g5Y#%BxPvdj`e6+BedNqV^cW17cbfOh z`Rj4Lc+6EXw4M{h-s!BU+r2FXyS1$hOY$wQRSVG1a;$6~V&!d(N;gx}vU=I5?i0?M zDt!WDT|aEmQLR`cb$wjJ1PWPO?$uIt618?wYYhzS6QgeAQx50aj-!&TwTsYjrHIJ6 zfh9f^!WJ2)7WR~`!+G+V8{=gr4&)%f&xvO^V#=6}f=RGt)dx!|BphE^eKW6@*%&?VV(-t5lwWEHr*mW0HQ_9OLc& zolV_#()=c)J55TWT^^}|I_%k!gqy{M%@B({8_8%K?8nX5r(61YhSGY8+PU|y?X|>Y0I%d z$Ec{)Ay!3&{=rQB@W#+Q#*Jue-IBd48o!w>Un<0 zkU)~DZ+h5HdxW>&74UcFT5djH;_$wJ%L5iVyeGXs0&hm*FH6xspXz;V-nwVLCG0}+ zV>Qfg#vg?&lH4c3eti)QbFlo`R{~c+7YoAltC+KZkbp4gXPMw1-LH;^6ATQ|fLg;q z5LrhDKmZyA#`MoXXRHN7Il3S%U?{M_d4U?t5)QrX=ngjK2MRPxB>pD55xVdyH@~o0R2AD!wU(6MKFYzOOd}WMZu!KO2xopzb?i9 zA`k?NpOpf`0z?DpXrT>5gN=bI$SHs!Ixu%M*aR3ceyjeou0MwwfuGg;cVkVW!K&l9 zI0?Z)k)Qkx$yN$?!XNIUKuN zk8dlwaCqz5iMYk{?1ahnn>T%q#+Wm2PK?*pN8>np?d%VHZy|lLxBuR;-g|tK;`xVb z^!M>^=w`Q*!}b{3T(St1sa&Q_gL%5+0Y2dj|v?4At`tJ zfsAeWR7#$Ni6c6%reHNB=*qz>x<^~JKD%uuCSUMl*59c}?-+>6DqbgbLFK7BJKB(k zhfX}jmJ;Hwa{HXt5L5HMH*GV-s3=LyMbn|c33-JI6s4W8m;4S^manSVRlxUfsq>1| z2L0?*bc(ufpY zx90bH%EeBVg5L0(1mxj#eWt>7GT~kKuU$AS`e?fl^L+P{8CDKDr0QdnCFA$mjn;zo z4)2%6WuDJW^Ph!%cp2?xXY@QjX|h*9#+9XZpssUIj;WZPWhIB*yfwZ@G&G}lgJAfm zPn<93+KSrPS99&fE{(kqwBA#7Tw`zV7uZ>i5d~vL`YMC{BAF}RQ=%>-61-WR)qZI; zn|kB;$v?7sQ^)%XKbS184%pmtq^D~Sj-nmX(hwWPIjP3G^gbwlNUQatcV)o@SZK8v zr-$9m207qjKCf5i_2ogY`rGWo0}Wgs4>F7vCsnpyy-A?ptfHcONEsX6e(Qnx zrF|)f6C7g=e=FhB+FC|yDb?retc2GYKW|Bf$x&VtsyT7}(Ws}%!a}3-F*;dFJ8tdp zEh!IkakymHUd?4m4T^E~r!U+F2A-tkq-grt8jODl(UinZh>rgNO8I2U=5ahC6G-;# zg_P3J94R3iby^1VRjkKc)0OV}JtO;d4-;oOWskAn_l7Fvc!)BH;_I+$t5QJn8%oKs z>+S0Jf}4iJ5>Kr;j8V`5B_gW26SCLPt`%`g3LZq^2xx1s-&6)$VWBk5 z+Qz!>?xTx-qBu`gN=5x5qsTmH$z?c=xHf|Vlt33s=9d|TUJ~u(xT?~c33O|=;>r(p zA51btuQk&@wkO9X(?uiJ{W*vXl*r8BT{6j%C5ObZAmvhvqj)mcN4_P?)HTW1K~dwb zcWdfI9a@!bI&!ScUyAj-e`Nt!^PyZv{2|>W9WKVU~P?O?&kyVi(?&ruwcj5Kjdo{xT zs%{%?MC5HevBgUdjXz_ODbmxUPjFL819L8UfC0=OkH7bs&Y6y@nN#X1y zNHcbZJ83aWUc75Kavv#p)%<>pI{vI%v!oP_`FP(htMLk4!5QSjlMs6GdWCNd+Q-f3 zVc)CkN%-+kQCHr17E%(cNlIhA2wdQ6wBVRcp*F!*5UU53RAxba(yumLFwc;o`*clN9$XoBv3=;&e0Mm*GT_%xW!lNnKZ|{Y%noF-KZ1W<7BIPOabjR*R z?A>TS{E-;_A~>@`yrNY_R*~9&I@5iA#voCmifp&LyIdzY5Wz!oKb>6ecI(NVJ_%Zp zU1W=3x<3z-U`L=FpO*%LQgipt^a4)BRZqIvj>{HVnd)sJQ4-0rDEx(97A3qUyqjQd zrw7qWfx2Lhs#!A+>x1nEUSq7D&?J4n&zqiKT3_+v$h6PnlwErH@v$$Ckh-=^z@;{e z*@T`jldC-lTjTZ*JX_|j0;PpED&mIGhGuJK@3jaI;DTK4oD!dJ6)K2x^Sfz_eEiBt z#HmjveOukwgpafBGu4d(IU@a5GPX+ur(_e!0^eZY-sjukGrcGUdA^pT4cPIyh)p?u zD0liKXga*n7Ib3+n{u14u6EkP8QTby+e}OJVSUn+7$JX}+|X#qSKx0T@cB)mQ~;Oj zXAvr!WFt$f$F@s7;aH%ELQs%D5+c*vZi-`OrzaGnldZ`gD(P8uu)pXv;P-xl?}>Ks z<=d)nl^#Jm(svY)Y(On&P&bNHr%Gl` zxSh22@M-Durlm6M&raPO$kmByCF z^BcUa!v~R-9zC;KR$x?;o87VQ!97AH zzZAo<*gpBJBKimyn}qz&AY}7)BIgTr88Ew0&Sx&%O!qo8rOlCl zQC^RjIw8IBmFnWZ;LI~ng#ns^LPEcRrof-b?{AT&00y7^Bhbi?om5^dXn;$h%}bhad~+TE64ep8~1$x4pRl%SM(OTjC6-Su17msRu)^yPLGzZ`&ZW=%jA!=%cm@{EPk2z z`fa9Nc;hC^r7g(Co6p#KDAM6Aeni%H@Z3hC9RfzSzu)!Q8}0j+wZ1wnL z3pM<`bnpAE@sIbgk|b37*#;8p_xnm&O%ua(g?c$A`<2or+}Bb!zF@cNCUV3I5Eu`T zxCV4lju0!UiHT3ML6MfRlqz1xJmK%Ods25kx3IZfkGi`c7w>!L%jWaz8IPn-<+Xy^ zBlGM=Q!`UA5nypcN~B=6OZcT;X%1d7?$*>ii9FQ(BA zT}t;)w4qa`cMx7Aeam;+m!{_ROm}Z^;3Iwk=y6%8o7zVm6}DF@tYg?#*WMMeq(xt; z&Y2W=7;F39jfXOL!PEXAIy>Tx#A`j~G)2dhlgpP$7M4;y5i zBmA#r_};pGeRl6&%ny5;rL{{lL$B%Z1M$dbIT_#fi<=I|g>BOCfQK#zwvA(no6QNn z(pkIxCKVr-MfX7{!R2;PQI$MFCiUBPW6n<7An6=<_v9F)`^gROnIA zUS{_;vcy>I-6m7nk&Bp?-*r93avYsPiQcXud?$l8EHjRDC9|ugZR?7i6H<#)Jk(xZ zDJ;PiPE#C^C?o4qH!Pua5*?JPUL3+gNquSJA+)^CfSB;sWtBFzj}-Fe_8{$=#32bN zcl=CLRz-S)+Twy2;ijwmcuFhh(+4|vMAj7)+Q}Z|$@S*D^*??T3UkzkYPd7lJ!9jo zJzg=`Q7IY0sabBSdJ+6)=Hr`-qT-%-SRyC97ZBF?f#_P+hp#3GUveC?j=O!(yznK)yYUk`G25fP?Oj09^{w`~k2}L_%PORPZ<%BL zaAS{ye77V5V0Em-lrq|vK3cY5Wp@6MSYFk-TFGVM5VNFVI(?<%l3_^hJTw2&6LYuI zVT48s;nxS&+XXP<^6=82RZ|^dks6C`$yR0QfFy$Hig&__iCBA;2^oj(C7)Tf>4InP z&V9FXjb7wocYVZ98E@pgc*iL5#)y@oN93D_LQ15m-VR6pEY*s_dJMVYk8G)7F66hH zNOXca+i<3FuVY1*H8#laM7iKgcZSq?hD4kAKbHtYd~c;29bes|(hhvUyfb9iW4-Fw zuU!|UOjFCj+f@C%Lk-Jw_Co%;j}gwJuhSF!of=e1Hk|ryovG9`I<}cg`}#4hSbn<| zj#W;il223auzj}YFiCAEyytdAs|zOA6YVl1As}kvD1CG9(W~gbdrF+;$80>RAH?Mw zkL4J!qEN1WPTu!>8mh|Pli9o_B9ZRS&Xs0Z%fXH+^A&3f_3f!FI7Zu~RY9N33=W~? zrY>+lv73L1S5DMkb#=T%HDhth98aQ$hamdZ11IZsvVyS+@e#%+H0Bft*UDLQ^IcD)DPib*-;ZK?oJ6+$gUef6 z_)BW+2I#>9@7#ni4hsiTvSnE&a<6w9ZIMDlyb=Tj==#6&(LO>0Mou z>f$>h27WQ`rnJ~7e@>c~+7Pp^eKNjp)i07?-qO1K-tf9%o5d93SE7eO^Qdf68wMr1m(R@cvSQkWi2aQj9-U{Yq451ahJoD(%vc z)5NZ3j(DBQbEmYsu3$L0%7AJyIzKMUEbxnu8TB}OKr9j45r>j6Rt-~3cHUF);~gyy zG_ikEX+msoof0J(vU>t&J)^~=(mW^X>+9#Wcd~nOpV_zS5cX=% zps8=fvX4k1_F+wh^s1xV=IOyk?uSOhd>zRJ{1fdo6af{7F z5~n1uKj>Q;3zbEGxS*2tIWTHRus&|{5LandsFe>N*QZ>kHk>V;Wo$8}P=(|1qOet6 zVapX@1yalyPx}Trg;)lgSjJrVWu1f_q2`ZrwwEtz@1I+~oc+*h5^m$=95L$Y`6k z9^aB_`@YDNrJ+1vOM$NTsZ5Cr^QWJ!PhJ#Iy+9Yxmh-T=H{}|&QoAlo&rRIpOf~!T z+mi;SN0UXxye|HP*hM}cbHuvz8u=ZfKG_#BvwD3gUx zwerQ(=uVc!;zi%@xrh3vIBQ)O^#2uaV*utE-WKH-{I#$vfLSm7g+%`zZ=bE5{=?Gl z*>dZDkGC=Gzf}IQxcdj*{yU8Q9|3E@zgfH${0|pzyA16e$HXb{cP;$n>t18a6})t# zsvtFH`>^1YMj1B1Le(-jT%*Bh) za**iP&LohTR`ac`{4swtdo)NI-%#!Cr`Ejw#w~tl^^N}E0oq5ld17e3e!YKYvcJxF zEQaE7ZrDgx;R!w4g(Fm|GuX!9?Vw7r;iviS!5H^Bmt5(+Y^JKR*686&yr99?kBLS! ztxYr+@43h=y~rl7&8BL;qPPaCMHBUv$CW^fUXFbjc_>MK*N|dPug;W+H|8Zp(8qCs z7~VxiJZt&nz!a9p&3Lazl`3zPak)#WujM^^t?&sX@g=xq_V&uFLj6`;wM*3OMf28= zuSm@ZM9e0P6K;HwHy@{ckP=LBVZKDT?0aKNOC4dTij6?ArW5va;sP6Ljr_7nH&t48 z)0+jK^9HV$nLE}RANUg`-INvlzF{X*!(Ewrh0MwOM(K+}-7#(Lt}whA{@Fo(%Vj+u zN?Ti9k3#>=k!jRS5p-d{aF!s z8Be<%w_^!|v>Ar|U%a%t7siiOJl&J{W2P->j2F2NhyT#vrqy_PF>u zYg+hjY^2KQrCLL-NOrakg>RoC-W}@|=WoK~qbk3?G>Te|Q{Wl9eRM0ytB)9&r}&|~ zWcLF^K<$CYLKmBl*K0y$s&}DGEa`2|)yRyu2{e4OR~|+yDOtA*ss zFU@?*D5GQ}5%-?S1!J({? zs7EWj)lcFDr(}2YWoy*qPh+v9wrY1vTxA;MwT2>>THp9f@yn|$5wJ+NEs2AfZ6{bo z2WTzAlNELd_|v{was;VO7g(~sD}DbGf6d?{yH~fIV>Lrn0NS;+#DV5eZ|ksXAjk%x zl~B78LIHj#>X`vqd%_JXmU-0Fa$D*n`s$a<7lMWeUmlMWsD%n_n|nSI1h2PtN4>rr z!Ie>h_L{stQ9^?Xqh5SeMis_>xmM@BxiWFWhJS;&@HLQys`lZsX2OfLt}GIdDj(N- zr-)E~rw_NaEYhS@@Axm>(Z^o13bZ7Dafb%hc5m#vk^IpM+m0;O=rZqYnWe!}d0A5s z2?P4GC>t{FQMhKDkrK`}6MWh@UsSkQz;xU~-8CTQOQPUV2=jcFzH#>`-_7{iYkaR? zD!wa~ttz=E2#Q!l8b@MLxZyWb2Xv5mk%Wkbcq%)Nc`qt~@kyv+WBTiWLl8d9*s>^E!m73)?U(lK5TtXO#rX z>R#6$ug8k%xZqN)JJ$zqdzAU@K1x7HuqZOU6?U`Upr{}VuGqaB#YU&W&7Huw5{u26 zq!+2ByWNRLpp(=N6>Pv=3pHF5aXF0Quz1B&=Fkym!l-NTS?0cWk7VC4OoSmToy_KQp5Rv@>!V{OoUG#J)KB^OGzo19ZE-yXjCmBCdIT@VY4;R)oRGQh3nZjcbbG_IXKlGZG02XBQ zdbNcz9=`DEopP?tHKn~vlEi}iF89-xnp+g4DFQTzw25uUO#3g!du-&dE4>N*sD`vF zY!kqL5rTs2~+mx{O{hMm5lWR}}PPj0Fn5K9_P@*`tf#8zF z@?1NEpPkEYP#ZGb`q~kp&c@fGe|N5I-RJIulYZ$iMC#|@xN+l=TZ8?n&zZb z_QWFC)qCHW2y45CQ*Nz{tT(dtXx_(%37@B-gV_LIrGlJj-9W2C`5L77!As_1{C09Y zpWH0c4`Q9-c?;`iq|wGh54+QKu6WT3*=?Ix`NWOd+&uM`To2XzKCt{Mv#HNY^3yZ! zJ*h&+`g`N!rl$ARa!-{Mc++bv;TEjXKj>T(KDs|Q8%!Px%&6l1rKigZLQ-kz;_mUs8xua3s+`^6tmP&pp1OhE`tG`m7RE9xsJzjR;s z#qZRpOOxc=d+g5Lg55R#JyyH|jT~12MZI_@43RMSR(a(1fx+}%a)GzHD!pt{d!q=4z2HoFYvyI~ zlVWc}y~o?U`bMKx_Fb9HM@;a-Cye>{kUu)G;jkCO`m6iT-&22?Q)SLP;@V?^a>2dh z4I0(mnQ@oy-SAKR=6hqY9}|G%}=Gxq-(+x-V?siOZcYpH^N!pWa&se)&30sQ-S!_p0mW5&uT z@cYY;!sYKj!>TUWNUD*@z4%BQOjOF({T|L-5r-h+jwgyR{al~zSB`ql*B6Lb=l22f>;)(w8!=S6M{Afsbsh4){wG^@PzqYndVYLar?_^JM;?--(s(>h0{f? zcaHky(aYHm4AJWeebh~y>%GQxhr55<%q<2?%dY&?&S;!u@Gj28p7d7!@`;(PI7#6I z2}qBmWSU4w?4S~sC)Be(T_u93gp#Z!(|Fm)6qFn??r2&d{EBKPUA7wyV9&zfN;6J5 zD=`yQsLL)~TyHLEgoSHn<`HgyP=$nLJ?k5Ut}>UPnKy{m=?5mUb*TfWN$fxmd~T%& zSKCjth^lT9+_QSdnz{dWq`HNvbLr+ZnFJ#*lfvV#BiKY;-A@iPDNDMK@mdOIvielo zzD-SM8PP*JN|4{ul3K<{(QLY^5iPob4#5+nmj^y|$B>lyA|`m5_!-J!3t97=Ip59I zRzW!F_W4~66zWz5#;v$g1ruosxNQ*U?9DPK6*n5ROS*_n0tfM9G=(7{GrDS(V8e!4 zewc1|jMpesC+I|WZ0tQj^tfn-AvRTE{)fb@mE7D8#j9dJ?>N=)drSmNoxE!>K zje+!%3S2c|MTcltwy)`(Q3br9@{A{*}w!ocr@S zKR>oVXs%gFcoZIslfh9@_Ix_1keQBo_ATz6a~e;U)uEufIUVk$0I4ycXNgBD24$T#sJ6MWr6$9Zzf;5b>8? z4N=D9HaQgSeSTxnN9No3D^1S9i7Ka!&_pg3ir7W7z<0GqDSHCb`w(mG0fB9r;E!gp z%MR}a2zqd=uV|JR9oAJo^-auwyVb3raGVCZRiJAj@3ZabI+ zo=QdZDxr3`>Q<^=Wi?(j4yYa-9ZAq&V^nMn^aqClRw^?as zflF^pQzKgh!$-SeF&5>oSU3mDT#s^12sApMCsUiY^oHY=GxfjAW)OVmDL+DeX9U0f zoe$FQenld2g`JvFCZkqoC}jkW2Df=CJ?G4H)+J?uoYz|iBz)=% zG@Xn!dIKxIPdu>X>dm;i9t*4oT;v>*vg?*M4VTFCElQ5hUgs9mTT&6eb2(upqFXL! zUoxB;MH6?(Q(iCW(Npr>z+2cq-GB7>UTC~u!J31qZ@2bQ$44PG3 zuj7~A*X`oHmuLw!Bjq(Ai!FXwFD^WsuKG-o-=;oO`jLNwo9FR$(xnTwkD{k?-rjwA zM=%#hLm#yjw0(avlzs3 zZL0`Vk6pdKh4EE|*9zPV|JZ!fOUX*s{@Tt9L0F^5^#{?JvgB`zaBk>b2@9$4b==5z3}+^g**?C?rnze+bSv7rXPPJCV9Uk&(Q29|F}Cd%gntI^=ix45HXZi zwve=Sj|sjsLw&JAv(VB%vt);}%`8bKgpJ_l(7rx0g=h~X{qieSboPW)>}OM(@)ws0 zm$WMtx#z#AIK72@-wPhR7F-_tHqcX94Du+?Hmvtyp|BHbQf)ZgT3FBX2zs zc=k-8a~)KbE2_z-=1u^E#Vq=a9Mmf)-aA1hdG{?f&(&2 z_QnVmm1F|z7Fu1o0=aMF> z`b4A<7h~Boa;gOl3ykZN3@*E&9Zj~ZACbng(h%giecf5TY@JY~T(PkPb1Bp!{3HXW zrIE#De@=c>{Ex|odo-fVrJl0%Y+owFqCeo4f zI@36=R7p8~{EwmdmLAU}*QhC_Zhf}PxK~q(_{dFs*MG{AEZn`2y1Y2-LZ`{+f+zLP zb_tI0+l`oNx@-0BF7lsfk);XhUeZ?GC+11QR9?q)uZLKw38tpS8EZtcUq(rK1>2lpA zM_haFFOm8TI#;-Vze2igZ;mwxpWq3cEwjuKS5H-4W5sPBaL7 z+g#vLfOQE5sXM((6nDc>osUi5Y{(Zw25z4bEgH*vZ6RgKb2$s4=5p=tZ;?EHqH z=;UMc&Fa%F_-^aX`+2R@%5L8Lqitp<<}C85V{2`=IxK?IbiRWut@C)aCLR|KGNFYD zFSMSq>_|GPz0W$>!^S#1g6*y+rG6S#=Tr+)WHHb@%?5#3~zUQptgwPE->D@0? zJx=coz3ojfm)J$Cy6giy^Xke(d;(r%mEv-xUK`uMwCNv>pS=td{w z0yv-Qc!M_h76c@|x=&Z>lcadTi?~jlJGLqz@iK#D0b`HK$4V%^DToQg*#6Zy_;Z&a zlF-2v|EM`;n$d0o9*^@iPM)jdUVVyXX!?bTw}@}gXRvERG6Tz8zNB3Wmc183LCf~m z|I!b=XCF?D%DO&;eiU(``a#d|O56z%~9mxvI}5f~Y`Lc(zE zPUgz`;|}7&buMy_rz!~*P9SzXEFSv3nG-GDCeL`}<=!4%h2AMAG5`0>;ffhEhs=lg z`;8$}5IDihwu>k7slJC6c*Qm29`51KUJRhO=k{QrWBfWnLt-QLI_@&AyEL;;q!)bl zf*N|0ysf|-MEjp{?+5Gh?r(H;9d*@X$tX)b{ug9(HmYM5wge+1ST5Iy~nm3)%Dl zMT4n62iZr)z*m%(v*a&^CKg|>XojT6%qWs}`e>4`UnE_g*Mql3(r~AAV~enAlrdr_)ZGGe^NqvQG^ONf6#^JCA=F@qj7nVx+In@Ftp>O+)TAi#R zGFxdb1Xg0-eG>7l0Q0ZX$OJAX@$s(6l=qSwx_AF zszTytFDrhVbE{vrgyjxd#pU*W7)9eKbaaz`b$S=s7{7co>hQ!_{3v(e1JMM}3C{O~ z4$Xhf@}E#0BrGWQE6Iia-17SON&XY8|F!8#=;yn!|6!5~oj=I`Ywyz;|F0>-Us?Wt z!S6zUy#6Zwa}U;k2H*enr2}~fVB;>_!5RdSgIig_fK6eTO=QMkeh8m~Bia&X1r~r< zI-;Q#7Ql8fh!q@Sg@9Ngp%!SkqXWdo#Q}Ka>0*z7x}YJdC4Ci0%8dP>I1Qc*g)VATZkP50kMZT zKpY`X5N8Myf`XtSE)Z9U8^j&r0r5Q33;U@RdH(AUZD=^c5(X9!6#E@h0U)S9qNT?;u9*VSs zp#DkEIjbX3Ns&J)DIx(ew1fjK52ylIK=hBcA}a7RcP$;=93W>Iib*>JklYXp7bK>w zdO$pY^f5;|+QA&mflNlh&Rga$fj~MrdHmFiw6p@U>MY4HRY$<=F-;1{0feJ9+yaUK z+WW5@M#8M&7*#M!h&|K-(-G$((ltGUs;4{E-AQ=Mj?m?Hw6R{{)edhsgdiN&cK!{+wC<4`%t_T*~J( z%I7r7f6yrZrjbY6K-ACG-90D2drp4$5AwS|34U|gyCBeTCxi#&?s=QkJ!jQDXVv|K zRrfcK;rUG+8%LxA1jv7Tp#L&Qpdc961Dy=?{5JFtUg)`6=x-6wGdDni&gYjKfM{cw zVdu=SKbV2go#!e9eog~Fr}^1ioHaK1ZyFfj28VNXj_2f#=j4umh;;l(@SDpL?h3br zK^)JW;BwCBa?a@T2cyex4v+JjKobX?;PI>YAGR0&>#7`Ppans+UChyEJF78cy#NUE zYeWPC!|d6@)@`8UIUAFKUDqy1p!R=mTK*F@o`Z$|P^tnPi9*ZTK#^cTrz$X>oLviw zh=3saa7(leu(kUqa{jGf_$ThbXpn=UERb*~v?CHMd=69pKodVPGsqY$D8dgGbFggrEPcTu>b2fWQBT;SdC5V&n^o zi37e8IOD_ciVO3D#elN2a)1s)DG{cnu@rL%1O5;b z2CxvI3sWaCehJ`O`0QFl1bCJ$3T$`>kd+V+NQ_P~VA&NzCm}2flmqnQ7&(9p%vlsz z9t9R|MFF2+G6#qJ748~OQ%y1E*GlMV+gvBJzXfQ^Ihzp)M zTM)B{9{7!Mytuf~S-A*ch$uhcI8neU5+Yz>U>R2kV*05}O#F(IJB5)zoi`0L*@lwY^Ei(?#-8&7lN-O{j*0o72gX)$jQ#&4|19)Cj{FM2uR8yE784Oa z3q2<6e;%0j^XGvHHzpm<&Y0^zjp0nR4BXDEM8!+*|Ifi`#6 zS)Km`a`5M>{P}M|Ae?{R2XgiNIe@be=SSFdPj^U44pqB!g8fN%fsOM-Q^^fjQs zKy3+kROQujw1}3YPtaI=~!& z3{Gxtp1(>kBw%xoUv~gb3={`n11?-)2uCM-03`q-{%b~U7z~WIfq|{y2pCvH_qM9C zESN(Es01+00V@C?2CU&?j(}T$Rp9_2LBTk|RzN2T6kvXUEgT&z;h3tS_y8khP+%w+ zPy`s5N5Gsgw|Kw+?y-jhvl2%KFaX+s@d*GnmSD6a817(!Z~ldgFcS$t3?Lih zoxkddVf|Hms1pD_&bS@VsD9f3N26c}D?Sjg2^4rY4h`tGhC2W&BY;iH4pxpp*KuBM z>EiV3o-1aK1vrQUlQW!v5l~A<2ZRS0m{Wov>cE(90RwaVcTwg8|E~r4e<8&GD*^sr z3Ge@3aQ`_*e>GW-KQ8~P_WaMH6@clJI@BIW06-l0S04jb1!FoHhkv1l+QShZe@Fk% zl=^2AX)wp%icv;GfjpPNtPFs8CHO?nGZBtbfV;yiHQ;Cq8?Y4=0rUZ98LEq!^?miJX}Z(ULdRQq<-Cmrj*e8v*nm z_c8G7OtS{i%F$<7@~1j|HQ?K7K=*xi7bEXB=EFW-yaJ-4U|vB0ObGA;uN+DU3;Fzw z?lVCGfAOk8(MUMvvp{_O0Q3Mx4dBd=(fzvsZ1PWHej{RSG%&XSx{}`o7>mwlqUf`3 z0jU13-)G$#4CW5A0F8Wdw2*pWo1B({eoK?t(kW-$)F6P<66};)qLcm1A9(xLFZtoL zM84V4n_#}uZpo8MkD(Q(<2eJ+Y#D8JtPOsA%nY0eQoV|TR>l5lg6)1TG#nLj1lt`mu`MN)ALRSj7w7RB4= zE34Pym-cqqo7-DkKGc83Yn-F!&WO2qRSHVuo49f%0qtRi{8nOdf_LC5^5}kwrjgZ!jGUBR()}?@)&9^I47v02_gnr2Dcy9F@#425St{>~uJ-yJsQzY+nFgW@FWgTCK zYvCTFq%G5TyQtgb8t4(1#`+D3iB!I@ZXF{sx5(OOrbUF#Y-7x+-5<4!doBVm%a-G5 zHd(hDyuorw)#K@nW68UE|IsW6;&vq`@s!GTN+&hw5W4@mW`aaz@z%4J*#{cV#`V&+ zT(_;ZU5o3uJnc!mudYAuH&MA2K?%HGi_B&nwRO;0C%fS~{=K|c&G%8s=EHZdjg(ic zz~zJ?lp9Q=OG^TK`07l!!gwvBUhOiwETQxh`K-8x zJh?ZCylLT$I}M@&x>m?5j}F)+)?s;cD)M#oovDE5^^ctu-(h@j=gbmGUbN3Hn{`$` zo+sgc{~kzmWiKeJU8b$Pm~f`Tgw1X+@u{~ zuPfdrv}KVuV@vET52kPKO%}hC^A^t7WxdFkWF-Ux+YxGDonptdW=LA#Cw&~>E3kD;u7q{mf_>(1T<;t9?R3i zm{W->PprdQLAMkis@fkkq4;a@?yJZuxBJ-Oe@ESkeWKSzYA-OEtCr|`hpXnFI>cOAWNnAnG8N?oTvTv|7D zhWXSK4KrXlL?>xX4$4pyiS(J|;~SVj3pRMW7rst@!Adm|>b~5mk+z2A?c`xAe<$jh z%kf>+(^PT&%*DmZXX)D;8_+$U+=)E)3&bNFAkk0BD1&m{m0=2VDNT`=V@YN8yLLUc z!Fd9W6%9pbA+^7PLHb6q-Wh%|MW9V> z!{X5j4^LK0ishW}8(MNzJ|k4VH@=Rupx@psxm*@lyFB)ke9Pzh#N@4}!k&<$(5NJp zUKO{C-&z&AYzsT+*A_;MxIN{nUPY;q80V9&mU}5LP0Xabn_bhFAzIAKG1}I?pVjw* z@NnRRo5arOT^s?EdC;ovz{yDW(cLkEMRjMYI(c`{ z#a&T3kK|f2{tp02K(@bh0P$rVKw#-?X^La?XM0`*7oWroy=U*8mcre}$e+=$ta`5-8a1Dq3>lLRsl{ zfg4nRGB;JZYHW*n5z^6`(&=D}R!?QO!FGxnsaXnAnFY`&et=s_=viqF0xF@SKbk#^ zo#oYLR8$i;OK1}+Fjv(?e%2M9mfr#nHt^$WveN~c`7w&DQHRi4d+Y!IyL4m#K3A`H z3Nh7NzuF3mAaeU+vP(VdrG#eQSc3pAV8ZUjhtV!5)N&jQ-ks+PjwL<7{l-krWB!Q$ zsvzLps>UGTsZe(Vxy$B^|A6ib$L9LCjn^k=T<(lzX7Ae4fVmgHTFUo_$U>rB46wQ8 zl-*~%zLwWa(!a?m3$UzviSgrV*0yf`+eIaw<#L?l^)N>i8RXwSBG!zV`mi7VAXbQ7 zobcJE^qqzK94PgTqjH>63W?t{mWm2<;j5CrwE#<0sAKIe$+8$#kC;OqVqBE!Ej|PT6sL{GHh9)#{_SnO%Ee zTuX(9{KAK#%Uq@X6#RF^SR&V{iHR3GQ77|IB9{)HdGf27rLpqX&R{WdeQEJBzVGA!l z`S5_j`hANzOe((~nEEI4ubH*dK1XL^U?yyr#L4GFh7cbpgSaV!}F0l?D z+7A_f3%ajhC2J%5o9Sh9MT75Of?8jiKM<=j0!iW9s9_FyL}Rqz(ZtmRetWgi7t`)s6|feCQfE26pfg7HHGS4O)+X}9zz^? zSeXHsUun2gW62Z_OtQ##PelWVcbsKOyy24EpwUn++5L-ZafZGtJ}9O?O5=U`CF>KgHJLByx2{S zr&>L4|16g@{TZ+i#hBSEtosAQoZv?z-!r%IZls};Y)QU0BKGQ6P$fyQu+p#0nyRU? ze|RXVaC@KpH9)zI)$J1j76p~Ckzqh&@G6*~BqY4nxt>gy)9>=WzmbahC-~8p{Ty_Z z)(mz9p4ys>z?~<{(?FDzX2xv z6kYd?dIA}^pxudaQc25wk4WAJ#)ss>K=j8;}g1YrmXa3(9DR@L|uvJTkd><6>w-T>|C z($D|s<<_bkZ-G5%Km=Q|i_>-vV9aulYCvQXnVY(>0(l%l=$=4sMOy*JPq?0d_zy^e z*$&?6tfx)Wam)V$CXKf}6?*~bu^X^20LYK1SzxDGZ|jaC99>Fqo|1Est!MzSz7Y(~ z%9VXkR0A-Zc_APxtsRPEXM*pvpa%kwrfeV zONj%NnAbWhlN;L@cVJ@WCb`ggpw@-z zJVa$q-2+g%R7690rS12q0ORHnO&+HaNa0K+c+}DlN|I)p*FXK#@ZJFUQySosADVsZ zVo%~wGvzHvYYO1IC<)7*MRKD%3Vd1-X`ujjYZ{TGb8HsV&-E3Ug38=ctJlH-M#r4_ zZ(^9_M8L~*;p|^SKy^?selA^9g3G!+Z_%uMmoKn`B?wqxd}q@O5RJG+iI%zIjrCHS z&1RG7Xh`U>cqr!HN`fPr&NM1!q{4g;vgg9-jOX`_+ms0x^)Gu%=&2{tN^%~)*Vc|f z@Q1uT=SpR6?>AwZ^?ss*?g_glkySf0TO^8EKo$dIvBM+}cm(@1agiT2*o`uu#}=)| z5EH(Flf@rZs|-t0={sw%$jVI|p@)a*pk@QK1a$VKxk|5@HfLfe>(~-#F^(ZFi^wEC zxi{#m28Ygh8fy+NAkNzgST$Kxfomeqn+zwplNSA?+be|f^2No36v^w6oD%oj0rTE8 zav&iexTb%vMOs-f>jBQ1!dPela0@SobIOK_IV~+lRnTP+%a_;5lA}$G1)q})U;Ki+ zPWcl(RFm7t(}OVwFqbx(q|-Ksuhpg29GgG<#G88s(ilH-+JL_LvK4dbL3B{9f*>#B zL&Xmn&_FgoyLkvW?})fiyPeT}PG9ge&ZY#-`IxyrYcrQm z0}`y!VAPy{p|e8IXB&#Lw$cMYdzlzx=$Z`3KenQ%-9!qSqsS`cOgcAA+gkAo5@(;2 z?A(D2uEk`y{R*+>wl*p`Au;=w!Awg(O{gY9_sBE3jC8S7ASC@~bwxBrKPA`8C}J#Z zKK((UO|Q!j7^AxG8lW+)nZL}IwG~`-m{u$MGydy5y%$gn-Urc&N+7|LcoNJv3(F)q zlpPPQss&M_ppAT#ISy_4di_ObTyb0cHmm9}Tg~EwhmP3~1(v*4&p_5#OC1lKF*9b_*9FhyI>S#*E z)XbJqFrQO|p#gL!@rhp|*WPtb<0!7Op|lU0(}&DndK+BKbEV*Y1KsW&IvYWK3nf%4 z5u-#m`*6&q?GLd}41f{5QirImg5Ke{4h)fK{UZV{b=7?&6v-&i-E$1Dhhpj>H}Q1@ zbv`zcJQ$guSiZYwo0G`q$2GieFM2qnHZ{aM@p*|}8bHSK5JZW{-lE zr$8t$FD0!dJ&)+s$aD{OZIP0-Z|%9(o4t+AZiRgOTI#5hikh9OEIjlQS z*gjd8U%KK_9f6pimg6ZXLqdLr6f~QO=dW1MdUva_r;iw8KSuOu1YsKLRps4u=(Ooh zgqghI8tWOs3X4(jzaSPuAYerFaK|I}p+g${CKr=vuP^=^?@>{ZUq*epjsDNH*CjfC z*eek@Lcd&ost5`q6DHM9hX|?g5(zs7ZWp>c z_Si|(_j{{@B^o^K(K6bnnT`*7h z{3bxHjTEGtGkSBk$5B@KPO)2}P(s2UPdMS7CZ|Rh3Mot6^RF~<@o)Fqtr4Vbs99v@ zgpi;QXFVD^3b&h_2Qcx4&3?Su>9(r&J+m*({6X|*y{~Luhb52(fHJu!CoW=K%_?0S zZv@(Qh8+60_)c0i|UgQr=mP0Y|H_6s@JBeahgT z!x18jCwbIU_7sGy*-@Y38$P0^=)~7OJo*(Ux{l^GL;}p;XlGOgX_=)PI3{YgC zTvtLm6WhdgwLS+R4A;8PL*KFgXhc~^t&cJ6dHN~v@R6>1tvntA{-X5uV&M@>VH@CL zMbUQJ#*Odd;PXFJWt2V$t2yUA-})`3muWu|FT*)UHe-ITn5AW$)=RE4A|i?=urnYK z%_x8PBDx;TlR1!4bS#({jC(2WD`PGX%t)@YWv}Ndi}b-VU^0tB6$dQo^=!I-Yfgj# zAXBr@coA}PUvB}%#|oNuS~$4YnTxx1dqd%Ba_Yb(unr;viJK_yv2X-^ne)ikN_%ej0<6i>h%+X@?chElT%!%W3CdxJeNaz4I_xSe?|X$nMD zhHsD_zcKi+KreIWBUURPK7qewWWTF&67KDF6^GK{vt{9n9!Q1PaBw$jUEj4v4j8M` z*sWVfOx$wjjPad?TrX0J1~G=;K{sP*ggawG8jT80Wf6{U1PTT8zpCta9_7XE!&<(g zAiO%F?DI2lhE|pFMyL`5fKf}U%ko#U$a(8+23F@_WO;Fx87G-}Ojhk(pi63-WoKnV zC#f=PdTA1mCi9lV*ZoPLRJW24HJ7v%hi{CoY6l^aSy@cH%V8H>O28gsOLp~!)hlM& zNgNaTK{Ln}^czR&>0rerw!e;n`%>47mT=-3hnro!fAjsy>26Nmgj{FkGTy7QSb=Wc za!$#nk2pc)kXM-aWz@Azucvu2*$tt&$#4+_DfE}?>RG&aP~ z_etGqUTog#sb4cW3wux%ObLVG*$kuErn_>KhO$U~2y@fqy1Vr^88R)~7!3PcK94$a z2_#AF$>V%^(hE~P&7xrIa~Mb<;-5sYuRNZ;$!j^~_D@c%%>kg{=rt8%15=OxiW zar%-A?RcMz>|HW{c>yXeto$$5Fgdu1@{7DRud==2<-kzk;)6!aS3?NT@v2h(SgFCk z$546LHNctC90@BY~)JM1S4Rdi%e<8q-$-B1v9zI8DvHQgq zhZ|ND!hhsqU>mfB(?kaY*N&dgf?umrFn|{|<~#7%ElUpVKpOKrir!$+?mBV|+Y_n( z>19K*4_*7TfC6SJ1(bzPybe%0=TKZfq0#TOp>KV+O7_^dR$V}ml;XML=gFob+S6~w zMX$eCV|S#0tF3m(T@h5N>$sSkY^vQ)#yxdeL@K7qo=7*dNiLkI1?aKHIn`3Tf zWh$BUrbN+reQCv0p9t+7RQBl+hWE|VE|+O?#~!|~Fk96MU%5sz$m*C)1NOgAeqv%G zZ0Ea%I_0xtE&s`N$^#}s`@v*ts!f;C(Y1_;mDmJ+F1r^rY9<6Bx8VY z=4lv4o2~ofYzP1L5>eWWD)jSdaO4PFDq9msyV=NF`C~L)w5A=rqF5=>YQ~{2Tlr0h-_hfPP|Ja% z?ke+YG~Fq@e(qarv1Fag_w~{pkZiB4%}1;p_PTcCmDh=}lrR&@GT8f_bu1OvE}d}- zNi4}D3-W`u60gz1v*7dvn|4gA;(~YC$r=_AyYBP7+qL{v0BAxf=(T``3*`C7Vx#Gpg4TA6Y3uYehSvq3bsoNLM`#%ek}I^Qzw6~2;xj#3LqoF zbC0o_)Lc~JPIIlriblpnQJ6ekU6CILdY8PgzX(vM&ghat-eL?#uX>i}R8+F!7euEE zCx|G^_-WVW7!jaLgZguaeB)(~SZyAqetRX&E-cn&Dd&AWsS&+W{3!?gefo&_;RQ_d zcLYOP-fj*fxOgHWukZfjL&!L0TLG{muAqX(Z$#)LLdg^_gfQxh#<#kbfJs>sekR=c zKb^wI=gK7bESwgHKH7P^@{syvch$&x2)1x03gwuNLM9AKDnWEVDDng(M|P28ocWy1=jX>Yr8^Uj|#>*jKq zELJxOClD9=7qXL5jib?gpSl3^M+_&5#6FkNG93J))28bWf4n$(zpGFG5ZDwa=y*nU?-~l~81(T6!q55v%OhR&RHhR$f9J58 zZck1W=~E|Z*H-r`UD)*xe_YQfGRYDv?R?VXG(=TOPTRPPem%5VBZZ~Z)wM8Ko#6+%oO7B`9 zx2;s^79o*+71h`?lSeO2|XK1RK=V@7@p-lw0{WB5wJLuT$zMC(ud@gG%qq@?1 zg@Rq!MMP`gxC}cb&}p*Q2pG$hekWr`{GFrU7FT%+i;e!2@*ej;J}93Q-5l+9QdyY{ zmL*mUh#3LTKo|y1CT-Pw$F@^R$idLxizK;|Bsw73sm;_BSVZl6DsF^8aV^A{f&qzo zVj?t<*v$FFTtGhgJ+*`x_b=J)S)5V|qW#(eXB?SX){+C{M5=?R7Daj%7AHG>T>O_L zi{Lk7)RL_jkIG)v%<3qcDL|*_c)~8PiR@A6DM(y)DPFF^LJG=mST<8vaXC$^WNO_o z5Btv;@mNNN>E5QuCwYMU8``LtojvFvYghK2D`>Ue_%(O6K^)o6Y(AJ|OYDJZrPY8(;^#?vO{|CaBJk zj0{J6+H<~YR#bF7W!mg=4{ErdVd!F(Ls`nb-)kGM(nTr?JHQ!~kkWDRiqwD#qPb$- zHp1WL`(aP`SarDZq%H$wBdsj0&8h_HK;bn!*YNqIwS$>z?%f&j4U>lJcRE--U#l= z6pLy5CRT%X*arCZp~2C0caj*Icoo5YEetcrBvnYWF8_tpb>s(ITJDFV%l zKYSBl-JIUAX`XL9wqmjKvp6=*xD=1|d@6@x%>g^8Vi;}EY70*C`KYQzNU1#qQuzDf ze@%yRJQF6XHwA((62mb+fFl^70+fpWpBnDIB~QeDa&P*stnTC?6`0(`+S!u=oP!z& zaj5z7=sQ_#C&2j>=4I*FQz+B^alp9sM}VG3x7}|)u8{vD>&esHj-{*_AoSyvpNCSa zY@xZ)$8`fA)?@M{ShhcCZ_t@h1xfa33KTzmiS?(DZ7%nOzWxE*WSI(&reRW2Yxi`S zKNt9H$N0Yq&Xq6wb^BsMLlD8o$$7lj(qPiZV1&TAS-qVt&@E-aw=-TovvTOYT1j?i z50H#k3XFY+*!75-!*6L?Uy(Q)Qs#Js$+wwQHG1%fA!7Rr;+MJ(sGG6Je^hmdjI)Vg z%hcRsqM6`K+%q^8$Eixg;@@1LvFc7q_qvy0Qn90{6K%+aD6Nqz$^I^LDIWf{J{g1v zMQc4y*L0*i?gZxY3B{vu@NlGjM7?g8Lt*g)x}c3YI-t6CXrue;gMHg|ENo<-X=xW6 zA=hx!qXp@ZZWIyT?ljzd>^aZD1&S{ne&$H8U^PP;MtKUygcT2E9Rz~+JIvB(LJy0P z-))`+CW(l!cBBH7mylbbsY~};26p_zUVj(qGf2E~-dV5T@^ncYi@Aff@Lm!+QS^($ zE~#*uv}XbDyg-LKaOE%Dx9r1iejyq4vMQN@C6&?T zAdSSebp;DhXPa{~6iGYez^B5l=%j8*&cvW_k~d7lU*DT$e}r%8L|Q&|e%2`F5$J^$ z>Xv6Gqwi0Y%m3}M~7r$bl#qa$whR_Hnz_*>q*pDMmqTqG8{_d%R zBX1FA)t{MRVk8$L?|n0_QdJTL&uPiRW=9&Syabs&fn-5FA!Pc$FpD?ww98?$d@{hZ zD%|W^qDJeh8Y}ewxcZ_#D$fy=G-bPnv)4nf@7ekfprMFK znoKBiBbJ=`K0S163=?H&zPw0oaeV2a*)#Y;4uj<34HiT5*+z;EL#7{tbb4_~bC}fym}abXpV5Ob3oN~@6H{F91vx$@GTu%3=qb&0 zJ~_=sdL@$X+*Fh`Y8r~*ffsvfOCc;EMi|DUROv_UNUI)0-2w+`pk94RX03Wb?L3V& z6p&4^yK(dFy)OY4_{ctrP;F?5DM!*~_Zmj`=zeBFfD% zXA$Cu1g6bL@28gXPzj~l6&4!_I=BI&{0;DOM(Rq=2NN! zathwxwS2?)y;3C{Vi+lnMW_jobfK&qr(kg8d^?fvukx#Qi3oBCpnHt^n&e;8s7xAW zJHH)CVC#J6fMfYGY&Q_k3dA)1Mer&4IFbAr7?!2~gL3d5_YcP`<&v5hPBA zr+BR9vbkASYITKX^{-;fqmXE1p}^}?mfsG+`F0kwaNuFXXyaGqcqm1L_;i0<@anWl zj)n9sey8_e#(3C(CxNX#SLNh*)P%j3F$lRb%KBycTxPJk?|6$nmZ4AtN0revxhhR6 z1+~HWDOwMG4rlnI%B92K^5FaHoU*yn?rI26qLAmRbN4Y@-f(k@tO0~JK8)>yP1J_X z5>nvFhPymy#wm==qr@i8f1V*{PN^|vrNJJrOO;!mmzsH3%lQ52iWkqqFialMZuX`djRR;*w!E{a(XQeOvW z`vI`9LY`NlzTGliwm3}2gO9=2U%G!w%#VuYl#M#!L3Eo(iwD)?QXPJ{~NcB#_HPH0Q zI6smkIVgk*RrP#Q#c%Bs!FCYZV@bo@-p$ugj63?*HpjAKgzKQZi6l-EW?(k430nMt zE;#ntI@)~BEo+>KHkJJJE7#CUh;Nr)QuA2qMkgxJ{UKhP?%)#{+uA{BUqiP;_2~=! zjax2Y7PS~h-eD3mL)6hlnmRa}gbcnii2_>EUaZNk0~|3)X-ce%%d8$_xUd@qotAo( z7$v@|X*9p}JnXMM?vXb^7759i_!b@uVc>*?`c8v-MMNG;zRbt$!12CjQQMWeJ-{)CuNb_ zKAhcC{W2=>$$&{`Kl(Zf$x$oMM0AALtG%E zPk1^)fQ5^#+hM|yy)pJ$v^{+Wi83;xwr|;_pem=ES#^5Oo+1!N(KYMV=dE?cA769X zDr$!V$kZENy)T*@XiXhR$ds?ih#G0Z;a7-t%BNFlzmLdV0w*=>)UPpDZ93l-p;k(T z{~u=sy>WYL;&kRTyF@lOcZ8rmKX8k(dqI~jS!2#~P zg00^YazyOoqjoKW9PP{2ozV0#d5`uXHuR6oS~-_|;Ox~JF;pFoNz*x8~m1s+z zda*r5&I*jjge zy@(yZSl5(oSPE-=IW&0+K`4_JOn| zPDm&6$$C{6OyXdN2qwsvq2>a#;_9!FJBpCkGQYL*3XD{XZynm$CR#VW!J-m@N}piy?Arqv zpSAM{jf&~mnaKP&Q3q?mTc|zCQ6PCMp;JhQ0E#45zXidEUh>C1ov6^|+3k6* z1NWI3_&NJQwI0yK`csVqha+|H@Uk!7uV#lpJYE&Nuy|dq8Yva*$N)GIyIx_H9k24E zX*@aq;O^lXf3Vy&35Lc5govEH3jXI5E`8k^lXnkD_YVMU!D3TKYm{Ne3J&G@u>3^3 zOQL@f3{T|;8Q}^p$QCG2)dtesuJor~!*Z?~Tn>c#bHVGFfzvdD&UrS;`MvHcK>zRS z6XSqY+cP=Px|eOj3l~&TX%-Ysub!JinAox%nY=lK`eqI|Q|o~D!p^d#W~_9%TxWyB zN)d;{$S~VYuIdwtUdEiV$8eQne7{+{wl$bZNEwOT@3+e7Qv)68MEVrk{9CVQZu?{r z@d_kc$$XBsby`D-rGZ>kd^1bd{}{7+6hFzDq0dFnc8jY6+;HQSq^{{W*U{Mug6{lX z&DdP&br{s~eqhti;Bw;P&TgABzQI&^zXi5Fe_6py9ZnqiJ3rS9R|Xv!w~hSHrV2Px z8gZ?|6Ih%2!>K4*EHNnRXwp7bp%-kzW>(qcDAYR)U*B+->>;oce%)ccu?gt=Ljs!J zoKaV?U6gZso?WJI)~(4`jeI~9vCl`Rq)8%i@a{LXvWAO&Z+FvC-;qv}IK$f|r9(~m zULd#ybJ8Z|@}t2a9=0<&maQPm)7{jU>lu@3Vd^ogrcWp1hqZL`tA%5myl>ziRf#q! z0?JC3_RT7geA&54%0v(Fm!nYUmX{h?P}$ah)(m=87$^eC+lRHpIe2pI9tsy#XJJxb zZ#&G3-rx6t9YG43u6qZi?j-v`WK>N6aE%!?>Mm))P9OL3#B?j>s~~7mt-?KO!o8yw z?$OPdBwbx{A##$f?FvLhZD@h?ltpWE}xYwd5KAD1Ptvc4*ENyMvpfOXgDM?AHO%uOSLK~1Zou! zC@41WH?FW$&a@cv$uJ}w1k-(^9Bh~u5rH7?l0|o$pBy8<5G8ctMjbD%u7lJ8nR#V{ z1;lLX`Aqb>AfYbpB=E-7`KY^Ds1rt`+geHY^%S|EZp!r%?yL6u>nS$%)B{n7alhVq zq<$ECw!cbYZADxcOD;2cza08U{wPThM8!k1%-}@Vj-&Rn8if6*FvXQ2@T3I*( z$5IS92zrQ=Aj)LSZ!7`bv=YREyh?u5)Q-8_ncmxgBBL0f@VF6-CKODI4z5tO;%lEC z--Td}Wy=>lPl!2qxBH4l0mU0tX(jOJ0E0;VTt6?^qH&&Gr3|T+CuN^+p5xB8evWg( z7h9&W)krS!7LZICI$A2n=BwLSL!Z9xB0$4&``VE26VFYagn7AiO_A5jgJKfpc?HseDxBLpaXo@c%(DYgzFeY3FZzng__PYv3IE z3Mncn7BnQIM>Z5{doR#`l*m&~b_yDHMM(pk`&Dm4uHGinqwaqiKsqEz^We3bumq<^ zKZ7`|VhV-Aw7|y4exxg?aw-TjPPu39WZ4zVKla%7C=LKY(JTt`Awv9~jc&hYbZpu_ zC9UzKPVgUoq}+OH+r`WQ4qJscH$E4F>7z(biXOXKrEm_5t2~*!rIC^ZUrak{j-_^< z$y(>nB&;f{vHlN-307ioOB5^VW!f%q51^+ZbdLXElG8T}evg!4Pr45Z-`@h^UuK}I zR{KExJsa_QA{+a7yYeHZ1|+h#-35l>`rf)BS?*1*(M*@bRX6AFHc~1bt-CZbBu}C; zVaVnt!)^&+h=HleED5noLTyCwWRh6_aD-tM#F(-iia7Hqs((QI)l^i#K8jSZQ3PrikME#DaFg;yVINnXCoOsjdN5hvTMwq$HO%J z`+L#o^5VaS4w}mB3;9xq*YLjBb1ICjLsrp6_I{MW$mLX(`;9GjE~T{Otu0b`q;k^2 zEmcpoL#z;U&jOlTv7Xx2eT~>732(Jng}N2CwC0nc(OB&pFx4ireG&lde>X4w9Cga7 zyW%D?o&+}941W#CIHa7DSz4Zs|v*O+MQ0# zyaa;ZiY|`KK07ziepeY+KSR$9QA{WRETB!@i68mAr#s3xAA~eL+ZP>K1LOVKp6Nsd zkV1wNc~ccOb*6KdY<<%w%o865d*~~AgOBeN;$llJNZF+v#e{kF zF|lVDh(6tjDtc-LKZP|Dpz$S{A;i_eq$K6n3mA2$44D-*$_@j3eI!!Oxj`}R7uKw# z=TEOssgUCbT*#b0Ae9ha?>i&oin6fJIsM^; zuaf4*N&%^L#;&pjVy7Q1p>RMs+WcAJc-=cq_tXIzt}QFK6b==HOlheS9Cq4rB;}>s z++*b`gA>|5imx_;zQg)(qi%050eLV(UO_W%j&sgE{v9g29ypb7zN-pwg95(vtDs;^ zE^?mJ3m4zD;qru^L zvn?D^;oUDlGU29h_)s?o56a(RJA-*?XfXSxSpZ(sKSbIt9(_UCvHvWc){9M1&BH~hO;Hn~O&Lr~WJt{) zQr^6s{gx}19sXY1h=pgt!Et?h4oTf-ADqR$&D(iEs+h8wRPy zYH0}7!w_nD?SgC8Su&;bOWANYlfk%%djgbuDTpa-_u~Le73ag{hSh|fz z_M04fQ{s3%o~`srly>c`Hg?6dK1}oSB6AGJW6hYg{};t$=d!&TwUpxui-jk+o1nrz zry?u;myJUXtT2nuV6I} zPtxr#@5L-$j#M#xy2e#yxc@X{ahWF+CD6*AAQ=0;o8Qr@3krB`O-;(~jGIRN3y3yv zlC9deUGByYHZuxGhq+yPx}VQwT|IT2b`H4 zKzL{I@}%=aE;R2tybmFt`m{))2=jK!6Go|e>2}j?w9=Ob(yvAIE#%zH%7m`o+@2Yn z%NGl`T}uG+8~D8KO#ou?gzAc~YO#42-WvuxU3^N{Vn$gxJ4vUVz5Lxk}4!9M1QJLntB+ zEZJL|5dz4m#`xK^2}`;oX@XQcsrC!q#%nYItbz27ej;cQigAfY075Yzv z0$GM)9qY9)L_V7A%5hXcfYBPS|4;L^UG*Mc=r(Nrx$1v$VXwOObGSN*$UPAwzYIme z=e6@Fa=9Dg8lJNADcug7R%41QxXw3JkhMp zuMP}cH`)62w7cw77EqER{~BVs=w!{2V5yRYO@;u-2i?c;r;E^T(yw88sf>LOdOIXo zG(MG=jA;T0kQi*Le_Uizw(dni5N4dMr)Im}?(}L&ZhUtaIt*G`e%r*RSf%hO?-y~3 z3b6Td+m@ZTamqU{!7dz)L02$Zc%@_tNUOU%blyw~1Oe!pMnEkCr+$EXg-_QHCuh)= zU{#O0U*;C$KB9Dzi7q|1!6AtN@picaF&a^>NKnT8*1B7E0kxUAYGrpIo?z!f!%r}y znpx_cz$0mWo~@_|lEz3;Lj3dRIvY#E*OAy) z>eS-4;S6gF@TNfWS>_u{E@pxJE4o5w+ybFy+RE zXTaU1b;zF6g3i>d^aVnza2T02e*HVo#oo&!M(E?Z9!@Wvj*)isWGQkJb~ZP*pPAUm z75X=bnKt+%+LngsEa=zH4zDi8cE5aQTR(*Kg>$|{PR^g|`dzswAoxwmsU*wlNB_s4 z1(2&m6dtZ}$Oapb8~`YtFc95|g|F55NnskWO^5l=4NG7vu>wTqi^+Fc=Dta0j<0<~?FJTJKxEYr`=-A3dcr zuzH^qbh!b&2l?C6w0X)mfDdEz)^k8_ z@`}n!&hr;WETYYJ7ij`BXd$Vlvm<)W(du%ayYtyX!*!y2fV)z-bvwx#g{gK^Q49Vix!Zo?tnvDY~tr<4hgKLl41 zuee5Ke9n~95%n6%KpITzBN}&MIYgp_F{w8XiZ*T$vt#7eT8bq|s%8*N`CSGopa!y_ z?2r-G`bVx^1e_6L1qY}cZ1r&r1Fh*}Aj_s3mxxp5J5wdJNCM!goa(1vy02+t^;@1Dhe*rE;Pp-t}T4Z zmA3X(0uCwUYq!hQ)^+SP`Kq5n!7~YT8}S@HoiC)f^#Ocb`O115nxd|plJ%QEQ~fe3 z@X3Hn-!d5r?|Ma!wqg&$bjcNc%yVmfl~FhHA-Hyh{~_~YQMu7Z#zRZ`gbUs@%Eq<&^ew1`1>HBQ-dk3jUN=Lx6)vXX(ssk3Zgi*7#Q1T?C2d`_Me>~aAL zIZ5bh6;R{pja87_Ho#J^ZnbAr+@xaLiSBH3WNf?(kWqwB~O$O{MiX zWK*y!A|y}M1-9IUQC<+1u_O-M7@!qGj~pD&6eK;`T{dh6A;6S&=Ak7s`_LeM)us*u z-v{D-7=-=Z!Vju|ft($df;h_E(2UDZXg#08kiA(u6cbfacvM02|@`O;N8$ zQOkYpBn9qC0+e7f=q z)tZ}!@~}3N$6N^`r5s;cvZyp~{qa%2^tzK?EdbxT9go|DvnzrAT2bfq1BJw)o!4xN z_bt|rF=MC|m_*6H7ZXHwZ>!=DGdZ9!jG^~hYTDwgYl_Yx}##ipTQj_s* zfv)v>oY*MgVHIcz&4UP`Q7zX=f^fV9qyrpLo)uc*ikw9zmO${9inEpY2NzRApJeT( z&SBH^L_-eKvGBXzOd;dk;M2aiB&9<$_E2`G!1sSJ^`5bOh8D6&Kw$rPVl#WRqC$QV zhJ(2_tAx4$>_2wATxX?JV_YVJ@6Q1PgGZT_S8cLgH03t1zGVyvOmWY46>kunbg_qc zv&K%ofdtL2#ocA;mMsrO9~Li0F3t$M*;hP!hC^|O7umVrC+%vEPOr;!GquaN<8%0& zT@cH{BX~gY1_sQ@r~1mbS$F`JKN$uNYeV0(9R`%11G!?i;)-*=3)|oy zcs!mUZps+5MmSqGi|^tR3EdOBN?J4LC@U7tTCACHfT&)nSRmkQU_$`8rKT?LZA*fc z6AXlJGdkBGAPkE|eqm!H8h{|HDW0o$%nnJtE>}x6Yji&@hqqO+Fgp^V!TDN}#5E?i z%DQvV4^~0=?@wL!EW8L`)trUi9S|?mX!<~d{q_d99x!UE<}uyCk^~vc@m$q04Zp$EpIsX7ocP_DBlWx>85i zqEo4-SdGiQk8P#N-0|jeTnf&DVj^#eh%jwt7w;=MZC_vu?=|~xaWD(J{{{knsToQx zwm|aY6S;F>sb2)ZPu^mUhb1A6r&1GWhw^u1s2cERwz?vlxO90B^45t;>2Oy>>kp2Z zlhU#1-({1`-}EZ8ho72SShyB!$h@R9r6x{f@OnT1w;%%%@CzgU0FU;4Zqk9dck64V z#a-d2*H=g=k#S#I9LeZw2=PtWn6R>6Uy7jI9O_gpas%z=Ze>^Jy*^e7TcrIu zjGq=JLdZiZsq_aMRD-6goYySrh9@zs|KD&J%SYK49;n#oz=xPZawV;>ccTlR&ahbpZeCJN^g(E+*ly{HO;q71DP#2 zR+q~>(ug6o5g(|SYk!Zcq#VE0?o)C1mp?`3LCA8QA)=Xl{{U6WVKEK%x(bY_fQ2Z` zbk3F+l`p5D;T-;)GWQJ8wj)#%&hJA@k14>OMdpe>PrHPsOyKfZ{1Zu_b8Jd1Oj$x7 z2~{9gmVoDW$SHnu%^50XT#|KqENju6ih(5LqdG3ms;71;`RJR<7B0u$ak)tX&X&RE zOyh zFZd@MyInJ$v@)+7pp*fyC~pGBM5m#1*$p`sy-U%J|{qvb)q!06T3Z zV!u+0JX_M$4tJVDW7)SDS={r}eRmzjBO|yeV_U7t^> zlUY8qB-X`s3f>UCm#K{aRoY>3b{{rpkx2oxNw+UCvuIGoGR!fnG?(=ODubW&l~ccS zF*cD5u7??S$>K@*@w2YR-=kkNd(xM2zB%X(9g>&oVI|$Hjd|pKohw)?FGXssr^t{| zvf8s!#gLu12fp0~u{IUiAChQ03?Z-)B}8ZFJsMa8{39D|$ECw)Z&v})cG5|zCzYCr zUSzrcNM#0|@90w!u$fezZ6DZw=n0=*P@nEXoh6V|rv#W3Exdwe!xMJBn(|Fw%xRGiGYZ%aM{^OYxJ?!>6uaGF`0joRMP* z+avLk!F#Pw+B!>UJ9TL&X<5EAl^abV)C$qXErVE+32vo=SrPwnR zON^b}juexG2TfZE#>Zg!*V-%g6M96AzzFg^r{tpB(!L-DA@ijk`o_i7 z9xU&l)-o%uSnNajNrVt+!5bO&w1b8cZuodf5wP@`>}}sGkF?=*d@jbiaA{gP6|y<%B>!i;9KFy^2A2$l;FWRACsvs!}?J|crYTjY`pJ(Vv+1R#Wb__5?1_AQMCxu#8LnbX~M z-VCEiztAf02j72cl^4OT3WoRKt$1j$A(Aoeb2mG3BR0EQCw}!0<_69LVnGDFW+KE&20HLrP{yNf=RISohN4~mq(SwGTmNt z7A^WbZLTNFunawk>)6;-{M1|-+vAX=_pb~i_uWWh4`Z6ddACc~2KE=;7fCh@YQG)l zF?L`UReP*J0PAs!Tv#Su4DHBO$xE~kIzz6?tp4Q2_~ClI!?pFIT`GRWZ1m~?ArvFD zIZQluP*|s#?CZD8pf4qvgr{aQtT><3qCHSM_udwO*=!nNnPApYHEz-Wlm{fam91-R z-ZuJ&05b0**qKq>&#EAE<&@t07PeGizcZt{2j^}Nt|e0+D)FjEc;~r}R$V;%nXPdK z%gf6^Z>B`rnb+R&y)a(qbmwFPesBXlv1YrR#0YnbEQ8_rW-gn39<*igE>kDtO)BCk(=%Z? zWB*aUU_hXNL6BIIre%$TQfUXBeZoG5U;jZ=l20MR1SUNRp1B9l2T|@Tt08t9 z8(dh99p;6E8B^St>k_7zO+E#)uy3;4^WPM($MW?~SACV?9x7=r7hY(9&lLXUQU*9K zt{8J%9J32FF>vv-xU>>wlbgRhlF3E!Qm$NC9f`c}(q$+JlK0t6$Uzt!LRuFlsTs8l zSn5YI3HGc@8Kr_Bstm6dgapJ1rX4xjuh)+62WH;~M&2W68ziFn8U!450o{ zy2oGWP;IPHV6J@2R_n6u*-zOihj_k1#RKKxzWh!+nBcT3VHsG9>L5)tn~}nR6@^`9b3m=9G=c zZ}LtE-*JMx9~~DrwS1Ryq1H-8u(< zofKZeh7KlQ+0`lu5Cfd|q#`#)Ef)u{)RZf~6HOLk;Y8Fw@eg9HtOpZ$#f*P&p_gwZ zk}bT3Y^j?8x#=z(=7aGxHYc-0J=;z+q;=TxR(_(?PCChSNZ*=2TU85VF!6kgXWvFl z6MOK0@RJ$OJKcHW$GW6%sfnNLtHn7@Z@+)&$(ErKDmwxGZl>5ZP1^ZHy;AEk+E<$^ zpUFre1|#jSQj2~1p(E3p^3?Jk^HIHGdF^)CZn?Temon?EiE|KBE{xFMnd8&Ewc2Or z_F{sKxUxkFba?PAu%@N@=N?|YLzA(*UM_7_C9@vh74Z=mLcQr*auIk?Ol?NyIZ1*o zc9c5WIIj02xT4!kMFk|$hKKm4Vy%SNBHwLVlteYSZo_uX)n9}G9AD=`X&u0oILKqY zr=i~vwaCC){1tU)&T1M3QBKx;Tk z<0pM<;R~cX{vZ7S{*Oun3;(Br|4*C)eG5aNIRS`OwKE6tqyMBm1GhkOr)O$3XoHEF zf$=YY`7=BE+5N=!w-)CaApN{60|)D0uFGePG$@so`S0Q&Og$*=e?UBaL0UgE?15#T z%~AsPAX5Y(J0p;V|6b2V><_3b8wUeWQUk=^gYtmbQ>H)g!_REh7c%}oB3^-Pe+NTL z6(EovK(F>^Ei7!Df0TP>sA>YCuKx^C1#-6OMJ)7;?FoU!Ku~@~LkB|2f3Jag_FufX zUS2dWAg#;qT9!YgEFc}ri;CqB5sTilKE>|sAMF9^GYx?h_-9J@-zfjz?N`qv*JtGN zze)@Kwg~`F(qA?KpiJd2n*b0t{*N{T)<22hAfPPhwEk%m0CMa>`~BU7=YpWisrgJt z2jS*Hl=Npp`)})iCa1r={s$!eOXB}@{apC@zn2n!r@SE8|4#X9$G?+ac<_Ix{IwGk zJ1Y>J3q<<9;Qcv(jsnmEBB?*~-a+j3KYa)wAHehSXYWDvvIBAYY^*?E0+5i;4)PxW zIri*~oP?}Els^aXhGqpWY@q$wm-l9RSp5P(CQ_8FmkZ z7K7F-z;?XU`*NOtuk*RHe|G#O|1TIl5cvPM?e+ym|EIa)FBttFw>A9>j2?L0-(dAX zTfiT%`u_$-&&WmiURqHdh#3dc#Qz0A4@Al{5(+p1O;bP>20IrM0~aeh5Ow|=wfg;A z5SpHyP{0ysXVTZRA_QWPO@NjjAcY)Ac2@-2NDLiZ=?DcZEC>}qE+%_Ipxn#Q&dJaK z$UFzqlm8v_9EfWMCI1)5^M6KDzYx#=A8FJ-SN=Co`;W8qFZsU_wBK7>+5iPTc7!0R zwB5hJwqFq1AeEV;uBzL)jv?DSj#z&i+NEny{eX9NQI4GdjCSbr13zr0VtQ{xE|0sugl6?i+* z|6zI}1f~P*{sCeC0^)Y3W#R<##DNYEMn<5lgPon#^B;FqwlW18yTpY+?>z?4`~UwE zH9M&>u*6F^Z?Y7c9`V{w zu_9!`wSVNIlsANC7pg`3uy)WbDq^_$hb96ZsVNS{du&yb(?4zEaCO*irG}8uEd3zy z9)!;{*ca5uYrkHdheM`Ph@~RNW?w3X`38=T;reY4II-I7oixCse>%1-B`$|yFA_>I zWyA~j@rT~kHsFJi)6^8T{H{RP?Ea=Rrola;Y#vq;Lnfm`(1m2dQNeQH>c^nIUR-o3TdB zwv}tD7=xbnVXzCleiiDOr#Hpp2_3uH7PawQD`P}>(n&TZtDoh!^}x-yp)sQH%`Ux< zy2*l-8GRMXB<y7E~qocuuF?iqWq1#T0LeX{~SO2BmS zsk#eE1)1C+V(QVDMET@Xk$7h;(TrO#1md~K{-q`?bv@I2K8rDukgvpzSas3u%7^-6 z(7rk;$f|kzml+QknfW&m{+ze}iRk|`C;<)3{`(=pi#&>vgOlU0@cd8X41k^euQ31l zL;N}P=VW==@A-rLIqmP^z;m1lN~8aW2mW70e%EcjME37hEhPC?q3Qp;HS)U0;ngy1?_Av0Tkh%1H0#fe+2E%nx#LZ#b*T= zNV^1l{j6I8DVKoDi;U@?6<~klfsXmF|3G<6z|i+a0mi}rR2u=KOVIKhN`vx&QRB;T zKoKP<(*0cl#srLlU&{RN*8f`t7%)l(h3KG&_Bql8e&mC;LCZ@t42oVsdCzhGOC~4* zv<)f@+6INfFJbOK3=lvWpx%Ib@v;WB`X$B&6@Km|a1BZa9ran@1bqE+7C`%ewn1kI zwEdF*oDNI_m4B}L&pc4Wp3e-hH_vqfL*VD*|GEC-x`0YN?*%;SbCX|QfHMB*1L(NG z`k!C?elcJ6d>(|n6bBUp*}|S%11tq<1*j0{4E){Sm!hEcOL0(1knoEIWN7{~{Ur^w z{0j0_SN-3u zL7f1l|8wQfgQGv|`@Pe@Z-dH!8u)t}XdBe&-92;{!tqC&wIYiVEnsUevcG^!mB^DSpV-Sz?20f zWmN?KQ33Y+ME&=(AOEHJ3mEv)0%z?1_%!EaX8pe*{sML$bOQdge*LlaUrwL=Tk#kD zZxb6#K+z~r4fy{j9hegofIQ5{HWP z3JkA4d|Uy9sKrr%1J3DAT+}$PbBY;_%2B04tqtDMkTx4{ipKcK1MaVr0Sc1@%ug)= zzlh1|+9DH(_X4ooL%;Lb)Q%zXIf9SHF(0K;j%BF$$)s|bBnix_Iy)QdqS^6aK=M$c zAyYHGB9-6xFm2mv!g$xBc+OJ~jS`K!lRElfL2C`Y**I7_aGEsRXC9^Sxnk(6|J*>Y zj+T|~T2{R6EH$3B@LBTFHda#m^_;11RO)_mRgP{*3A$26btO5YV(iD>cYTDG7EK(+ zHJNKS5VGmqp02PWm!g7&!5vfnISfwXdDbqpm8Gc10EbTJ4o)SY)Vk;YxxgH_1@)Z3Z@tM7$$ zs7lOvdb&uc{HyP02QPe3T)KQ z{scHPNQ4Rbj(n6 zqOO5m{UH1nYc&YV1GN}^HwoUrX)ynLJLT@(*u3*BduB#riOWfe8v>ajOQ8U`hse3U zn@QjV;>OW}O32LctT+BVthJvUTgOhST!GyA{gBJqjxG|{M@HRB&nKKC6Oj^cp;o=b zwey40G6X)BL$Z?4&vL6Yn8>1IprWACy=rg{TD7QZ^!MV&ihZ`Ap+ zL+EH?%*a8MINVdosCV=$Md(*3R>9b4u1{aS$H{6ld39))8je$Y0;DB-(prWIzlCdl z1NNGMv)RGtQcHQ1k9*k&Yc#2r{8!S;k~Y?5c45}mB@EO;%0{Tb_fyhDQw}uSYkV02 z*MLCU3MaCd?^_B-G0C=wv5`UGIG_DTsGjwoZzGi zGZ1lDduLHC^A4)5X)RKa*lf^K{_6I6R(0}UG?o@WESOb~{03|xAV))*L{Z4E-uje@J_whupee*0!Sa>NOQV108%sOm6K9ox@%x+}0E(47 ztu)bX)Aw0{y)T5KwJ-uc+#F`9d3w&X9|-NasPD{$Yte5N30rswO}B(0U04@ZKX}kF z!Mc#{FVQenF)l>Nu5_+MYHNCIq?P#bNaf`cuvPKY@EnOkh0%A(LiZ-hT61wjZ+?3p z%~PL5UM{q)7>YN+%73$qLE$HE9CEFBK+-r&NAx~<4R_D36rmGJ;`r)c(Ks=Nme69CS ze&r$s-TgUHB_hXX1$@?A2F9>& zv#mt?F?_K&$bKX!06J~fZG~j?biA`xKTt5{!B`V0j>A&=6c7uW&XVJE_24=8@-Z&S zyh>SoE$OU0=aHbJGJrhqv(h`%S=^kKcO}3gl!y5q$xNE)GxtjMm*>(nUK3aBrZNvZd3vVY-JC2_UBeL?w8v!lj^5 z-5!q2yKMx#_vVX9^~%oPLZ>H7byd5027a#Tz|HbC+w=7BRqn#wroZ8hv9sRw?j88f}}g6lE?VE6ux7~18&%>~U;4Yn}SmURT{ za(yCDY+A^E&g))=%;+bJ`uq_yw^w8=4#<2$8_o8nHAt?;hv8A}34NJ!;sCo`d_C0uCDA?pfToLG75O9=6=HNI}7K*o!)()$O73iiG& z{aFXYI?my>NAU*vQ{_)yq})_rH<7Z_Z%+io?U<1#)o(4>90%WED}5=^z>4&=zE4aM z8Lcnp_$70iNJ8IhS_6gmQw3GksbF8ziN6Qcsv-k_?A&Bq4AO>HcQtR{$&TMvxl|6V z%C}y}6aYTpYO+le>1gNX3a2~`$8tnj?lr)?LflH&F;itstBknL&*gNA5D9Y^64`Hb zGLz)EqgV&XNkKt1_S%b&$N}^)*(t8IE}YfY4@@597#@|x3~tuKXa zgt4q?$6&&vDYZKiT~?#y z!y_0S3hJb#yX*)mu(+BYT&WZ2+$3kq()Y>({!62+qo|F+)8qDum@`HBT*2Hsu=C{; z>g z#jEq&nm(nW16fM7a#|>k*dG@h-?Zzhcr$of_1ZeROIzpV0BWRFynRg{GTL_7X}JAA zzhfI3q<mbPHCL|(F5qvsa_ z#u~fnKk+gA+9_5(3YU`)Fp_?!YogPerL%q$@P1X8JtFZ5K6cnu;=xEVod_r4k=6am z&ekUhars1-)BIrD=(wb&aslRUrfb8p6z{%w=n2<)aE?++EdHwF#%R{*3PN%w5g^(LAOgnW8$enjCSH+Gl?TO7c||m-~ztn1Xx;fx#;o z$E%fd{|>WooBHokT3_E54ciT5qVbz_k0-mNrs^D&O={y?rqUi-j=V@1Kdw4?8 zbdU_e+s`U+sW#M}HZP^en^M%|gSuqd+tiFThE31l(|TaOmc}0HcNdz9_RJVUjP|vo zb{Tw@Rimh2Qi?x{6{0E`A7>qiisI}b&Rl-j@3|WLjGnfz9#CSXE%23ne_N!-6kD-r zOP`L7B1>=ieNAqGlwbqBIe^E9?j6z2=;kc2PqR+)*~cZg`A zpeSU>0MVz6zdUCyO*$@_iWJrSS@~*|V9TQYxfAYWdp@TZZjb9$lOjPFSZ+c_@@af9 zI{B3iGuVes)=z4-#^C!sArBh2>U=c$F^=+9Gi&Fg;t`y!LBU%@K0Q5y_NOIGSGhZN z@#5sKNP@B7CIvr6SE;g=X_Lp&-Gt?7(NT7dXtfJC8pYG=0Dqsm=QUpVW@|Z`?>Q4w zJd~7(uqHOP?wfCRhVESXU88`LyYjl4NZzgPphrn%zdM>XfH&_zSiYv*tRTZ%TS&*H zbA4vp+91=!SP{!y5+9CHR9iutVsL--$>nYyeIo-+Ya?dMstvvRb$FpDa`yR|RiMq3;Jo&)JK+&97O2WY3}hb>7wk7)f%zWD#p~29ggWRFy4DTo zk6)tO>?n(WDkZ)rZHp!9Yt0;jgFN^Dw23EYTfd29a5t~VhB9)uUuwEO=rdn=Po|I_C*CEM-r=;@aGJV zLO9XWu7Ox$#EA8LzbZH01+G(AmJv4-^8B2Cozjv?fji~ zw^Ar+&&ETS77~wNRR9CkdIQKzP&4XeZtJ>#G@7XR)?ZTj{qz7@g#owM{|$zRO%#Io ze4#q#NlwVmG#>R2Goo%b=QN%eTuz26L5PJhAMa$E+9LzUMCgK9Y)|w0jjB5@eIFif z)w?cqkpr^sT~%hRy0m{TJE5~CbQw#3SmWP>qgplQc!gASdNTWI{%SM@4epqB8ct(8 z>PJY1!wHeJhB(-bjvXTllKi{L*ZNculY*y#eo3`aJBHtqmX{A2ERpcvgH!F%m#d2EH-0YaO$i&g;#URvGr*>LCJI5=02Z;}yGmxU#=8oc_ zdKK!;t^>g$T`lZy&&zIqJs*eDsl^V-r+SIQYM$gHLu3n?mnU(p-j}@jlQ75n*u3xk zF71iup?)L_)@$RD;654C$EUM$O3c$L>TlL+l52MtuSxC=RsP1;3&Y1c*!71~Srb(JRR2<|D7M?kZ zZ36MSC+x{ecB2c7`Fp4k=&)BI?sMdsVvCHADgkTt>Mez|9h$!B34m|TQ!JvKd(+bQn+$igRftxIY?(6|iT zpL|X4b&{m4*dNeCBb=^%SLfIxdw_Zj@R3OI_43{_gIOM`jy$`B)*_Cd>i#*8lk4mj zf>p+qNaP4TWWzH9A3AlCe>ZMOIrOxX$Zg*EhENhcJ~{{wPb8J~!F;1pRI~!155etj zEb~b09mB%|1_kYYGiM#cn;*C%f}&J*8>Vos0dsBry3HAkD4E^@F7_+)oTT^DNU71Q z{n%P#Vn>R?pySyJuod3y9=j+)7Ki3{Hzuub0w3to;co|n5;%5pUDPY0=L;$+@v)Sq ze2J_i$$q*O5R$i&M+4e3l7pMQiKxo$#Y^@0THn=Pq-{s12~$@gP_y3AdSSVL9SrGr z)HWVUnX2n$*1$ba?06T2ZDbr3903DHG-gPFcfoaV8RcXNSU0FE7Wt{=%zXbdsO9u~ zxk+Dzf_%DKx%zyb1hVdYmIU-M%CueoLBCP9sM9svw{#1QaTV^5p=pS}I$S?xmVL^- z3U162^IbyXDorMeGPaRsG*w|oMCB3LduX;_X7q;&o}#MO9K3C(_7ntwDOy|#wRnUc zPUAr##^%uaI(vUY`Hl*n|E3r?MNv7qHJGLNYlLdSJghPA3`Bfhc*Q2494bLBJ+h{6uA0{?-)Cb;KKNfZuKlv*1Uo zUnu+X5Vi_7^1NOyI6 zP4*uNZ>}0Y%tzl*wrky2#wils*on{_nGj5EkX@WOn?!Hz5CBC@4<_T#fU7xz=f3&oXOCYyEB8k4Y0qe zD@FWR&}Ryh-@pAjrCZ7w@))4ZPC?TkvfJRE%7%JsAd;;+L_*h%dIMi(kAZ zT;4LA@*0cd9nUkF>%X4GVc(2T1`DZg-cM@IQ6#A{DTns)G{y*5l_--vUA87{Nbt6H z06eBpT#81R=p@n1t(SfL%<&7sp|PETX=MLH(GJRMZ)99;e=c8#*ZF0OuOw}^sjvG@ zk7C&$e_(5cC=Tk*7sWfnXyD%%3fE*aEOv6Di;T+>xgF?nUcu@XcXe6bA#dg`k0O3j z`6fJ?K)e`4a>XmUcOpKGu+quyget5zEb*Y@;*vF2W6lsR7MndsV()#Q5eR$eg;yF) z0jM2f>I{_}Mls3SF8k8{3(MT`oaxh=csoW_<3lY1#8<~%SeJ^0>yb?sX7n>FEZ-|f0GKCVf9dm9Gb;TXob4u{Eb zO`G^2TsbvS{|)Pu5_ztXX~hzofme}~U0cD#*dadS=)SEZBLq?HEE)Ujj~mIK!bolU z9^`ibi~+$Ii7#a}i^GsTsy)UzC^zi=Bba`8D7LHqngTw^o}7~Bj7Yt~wG``{7u?as zwS|u9@v0A*w+E<0&dRTlI5BrF(noLc*F7GHa-{F>1lfvDnD$z=bFyWkJMDR*e(I3> z%lSM|4Mdp79u|-oOi4lGycDF8i$K$@0pJQ3Nv+&Cu1W zkA2gshEzokWoIxPeTWo%#FURem5@9S>?`}giC=iIS)>$g3wB{q_ikT#4Lw8bDE_ro zy|IAhQtro47=>)pnh|C(pCW9@A2JJW1XySUAiM2>#`!u z7W#mNkn_jN@gXbOoC%kL|CyB8Pwc&jSxX6-!9pbgSa44SfV!Utq@q z&oMMUF_P&y(9mSh?R#RgP3{b>3Llb5-l-FM1#8_00Su500+~OPa$aB{6!daeC+8!g z_oY3uyEn|!ueR(yxi$|k+g+0lLsGHkkZTkxs5gCO#fH0P^lIt_j7@|KJc*8n*Z7nk zvlI)UdwTe~eH4bpO66NzGC@=kx|=##FxMr(^T!0j@4 zzo0aCd@Z|K;J*C3Z4MKQw~icLTuh>15rpBa}W^|%g# zWi}Tdlkp&d?1M$9N+oB-&PT@XJ9hWL_U&oS5JX;%Guz2Xb$W2C@-_vko&jM43ld0U zhmhOm@7{KsEn)*u60_OvR|*ThB^nANg6J-a)nIlXrg(KJOE!}9)u0By+Um+;4^Ktd zR9nZ6D}I}AVEv^S;(@wrf*=uCA;|rBH}mt-5nv?3u4&c9AFJko!fv_DwX_&R$701p zq+48Y+YpF`@#$~2IecxcmQW1^EO;hXbOY#>?9qxgYy$M-VU4bO~0cOh+1 zoO3ZySW=T)H?e3IW#d}HeV(#Cuh_-YxAfkW$*uG|+#aOR?RJ3`%Yau3uc1+!@wU8s z1HjSpC$GtXr5)kx$X(0y5vU{ePnjI^22k&!NU0hIpRIp9D{nhc)g22HC6Z32(BWll!P?!Z5mJgUpJ&(xE3 z$77_pkH2>B-8l}2;zsAy9GOW4dx1m`&6V2;xS4$`oTkGyqBR&Lqlfh)7cJ{$Wn6+O z-`o~4+3Hz5Iq*9*0iyD1wei~GFpf}i=Z0aKO{I^6uOau>65vy~%5P{Kn9fx%RV5+O z+bg?LmMDeyIa{{k;VgkZDxULb`je_B>_7cVW1Wd}TqM!{;` z!(}BbQ{(*^;2?-cW24M@i`BujvH1&$&eTs`yz)Yvexnd2cC$>x$%)#dnHYz-oSrG= zkeeSX5Y4IuDbya~bB!5EltTowUN|N1;N9`uwiaV}*AEe#%8J(d6e*4;)O#NfvZowB zA6_QgLYzwiJnhnv(JXx-3{qqz=7_UKuD75M0&X3b62-rS23VQT$j#KTnR{U9pdQ8U zWHPqFKtF~0*HgM2glx6tvny$dIt3w01Sc*rEx=k6_@3*_1y8Me9^|re)}<`pXqkuB zb;d$M(2nHr7Viu-!6qv+6?wU}8yTWw?ob3_zF{lJWF3QBq^C&dW7JDcMrHJ1_Ra%1AqhCM1%gk}BV6kT&1iU|z>tqalRQ*Y$eKwOW!?*V& z7X3rpW__iP43CyWj8)(Kw{JoM$}HwJ)h_bGdS~<5IR`BIs7_X|?{byQ*yu)vLdD*p z(iGpRx~kc`V^hA88z)=34|Om2!0e6Oq(9voY>7cpK=$26Fq3y!*I6et%xQZ_eNEI& z*m=Gi3iVh&-e|mg7hG-^CyaSixAs#MWfc_$z|Y;vh4%YmKw;?{1e|wzUaybR z{TNrxp1RYr?@M(lrE09F?sVv-TSu-wL?ZZ~sn2!@eE8|>FI4*;t)x%`Y@U2nbXs(D z)6kxdqg(1Yg5oD@I#th!d|sU?o4dJXEKwC5p$&ak zKNIa%-|tg-9pTZoAtvX;wjTjoa-3hwUv1o;RrNsQH9|9Ft{!%$wWefY7>67?u$(Fw|z~h4=hIQv$iw4h^aqOBP z3V*=0td%V9)0qdBC=yPw8Vk8l7Ec`)A?)H<_8jqocf(6+@ zLBdIl5)ME7ybr8wDe0KVJ>*1*;PThAG!Vr=5n7FQXLnn1Xql%uYXdW2d|I9!|%% zoZH5FscAEz4xh)919JP(;t3~I-t|HV^GrpE(G+#s=&DH`;h{{;OPy=cG=D5YVeDU_ zLx)aJV{Sp#+9irXX+zoL1+6_tCo{gujzJXIUIWAtG}$;v4)AHFPO7$QYb1PgaIM$oxRZm zO!iVf01vM{Cze4|c1Scsh-jVSq&7){fpl^EwXTE*5lndb6m<3aYcG8TqwNW^N)F2Y zi=w`Uhn=~hEx}aD1fRwfT1O&ypk$HG~_(CMPumn%;O=*MbG2CPfufNza*2kVQ(0S|*yasWy#idd%kZ zMH_^iIB?e3A51vjzrHk;Ru%nbSlFO@8*Ay6Ln71F&M4s2!AqVgXRH$u2-6YY^UYjG zLRu*Q5gp&-wN^_CQqIXT`!sg!d+=)BiV4ElR1CC4VkaWY82Ha&@_HFsdvMrp7nPbgG6;4wsh@fiSIQHYS%hTWguuyM zJaQv=-qs-_h%kghM_48@zf{_%k5f=OOt1`j3F)CiTm&uS&SGRZgd~wRH3TpBtrp-o zcpu`2iXYLQmsGavgUNfU{u6-(r#&)DAqrtYQ5-Kvl|<?ctU>W!ul>;NDw zX-iW1fsW{w4d5jb)3AkYvj)DH<~ZY}YvWsqK;kTB7JeHsv5-n>YfEE!umXsVw`m1H z_!D=1YR_Av31Ta5O?nX0O046VNhE6s)(y?u^v`5F78hWx1Q=6ZDAWNbZu|e*@z=sUA(;rnDVP(+I~S zV)zgkS-g952Bw5jqwM1ZE%#-jkp+2AUpg%je|!`mj6P_ZIIT2iXx!h#wPCF>DHbOh z$%VU6=A$0?iWtflL#JcfagjWrN$9Y8*-6fagK^b0bPmU*l0&jAJ{Hwm^JWwv#gM#~ z4lXv^bi&a6+1J-b1$Acc*TOrL*Itb%G5XTLZ|Jdtt0i)$Y)0QGA*Ec=5iJfRtJvLr zS+WTB^-AB~8l;}`@}W2NOBlw&kLG>U(C!c8-bo3kh|_VFxZ=|1s^x%)(6klac$!#g zhTfM^+=J5!G5iqSk?s}|BD&bD&$mL(CK&-XtA^9lh z(6Fp71Pmp8C(hk(sDv^BaN8Pdtm$Lww}|4kl>NgKdB(>jk9Z>}xTpSB7jbo+0n#4> zIIk_dv#%*uO!Y$Jutw+{-wL1_7g0I(+LyyPsA!fib~((No6zAwwtmQjk0S~!@E@Pj zOHZD|yPa0-?3_gm8S^bPvAT&``PQ_^(cV1?%c_?+93xwWcp)}1)^aF5Xv^HUt(4fm z+b?f|8%l((qb^MOGLUF&p#dC6*2$)q|56_%sdbSaVXqP`jz5x~FW}ePJJZuvAuy1K zTD!!(QnHV{rb4(JZDqNSpiN3qWIIoExwI0QVh;?l<1$=Yo9L1Hj*R3AMI;+5Fk}+` zOTYnE);<>Qx^D^>IQuMW1e3=@MBaIH9yO}B@`-pp^;3c%ba!yS(JRwyVTfQXR2|Pt zrVm{^H-n5C(4udKf^xXHl5C;HtCbs%Nax~AGh>ys(4Ys9mrI0Ax^x1IkbSpy!IJym z#IveN)SC_Bm6$dxU3Cfj;V7+9YO9sqEsGdh?$Hiz1zOoT3waBV2Z=2g%OD9X&FOi+D?8 zKgsNC-l1`tL@FPDXzv8C=T1nr>ZKZNh`DHX)?tvk3G=P?`;yNbN&`_h@wF-iGyY-9 zH{y!uiu4OHgA31L5kpQh^Tr?^o9~Z$QgNYokxq8LIwW?`0$O?r8NKOy8dDM=;Lm-g-I;t zh$5|&P_m&~kq>>Ml9SAEEFjEM4AnBVXYb*{faA_27SGP>#6Q?g=I7}OZHcX71T(mM zDRbI_0~)%;`5dG(1mOhEVab^BWrr+ZC%cKV#WW2*m&8MpTq@QC5Y|hu*T~^-vG&Er z96CKPqKiFq=vN1u#f^H{O5Y;h9gW^a?82jf3cuI;eSdp~Y#dCHReqR6g6QtS664}2~_eB|TFuAm8+U_@No zLplhCdzzPoDteE6_1ZE}OC0~T8X~U*36?b40hpg;iGJl;f13rg2Q*F*{5P@pFli!@ zhPI#GzSFL0WGS<7z8%TAVyN}5Cv&+g6K-n7bNDJ!*+#~o$T6TLaT(AYQx%AUuuJgJ zL(!9eZ_+@cdwOmDFi7@Ihl8)&=G~y?n+P=I@(Y~F9!OS4lq72_asIWuDX{r3wmtFKvW#8imJjbcW0Q)OnL=DFV|$a5kHddXdMy43t=mYTSV7c77LYf7 z47}Xzui(^9=)$-*5UgH9`m$1^a!AtkD*rU=;_oWFvdaxdm=Y~|E+hT8|%8=o;H91u_c3hFUyas~YEKVml^iUJCh>U8U%7dR3tvlK( z_lDV3M1+*KX^X7Ah2=hcrd<`H85}3 z@<*0edxDQaZv%ksP~40!ougQ_eqkQ!AK4yA`j}=pbGT@@v*5M6P5uMs`+u=_mqC#-5K27-JJmj zcXxMpcXt^ESa|Q5bKiTud%uk@c7JSaoF5t0U6opymEF|VFb67*cF~CA*>WVW&y%?m^WgR?ZIkoS2kN{CRDd? z&RO^NK0;7U{CrxzO&k?P%)_?pr+3nbieRaD-X9McUmw(Yv?|lgK$i-yoPW9AU%Qs9 zdfvu8(}C~Ry0K!KK@RN|27p9*bx9J~8@hWrhqh}%x?VOKb`Dv+aqSV*nHD&x=~v6e z&yV|!rgVdzf^;i~2R~NrB$vOW%<|VOCQ>oh8D}fwBd>9xa0SnfH&v03$z?RDe6`7* z4e%C289@lclWh##4f{6b+60llnkJ*Hn}js3`GxnmmYXz~8F4)TQ5_VNq; z5WpFJgyP|6#ih2#&kJN-Ebw&FeIdq(7zLu*^DNTBjSk@N3i=Cgf}=~nGy|*e6yA3YMq!UbG>YXVK}oEA|ESu z78MRgUKuV*d)!w|d1{c-YW8!U2F+nFV#L%_X)f%Ky{)4Cr3#cguU*F%YG|*~anO&w zhc=|fc|W(Ju$-wLw0{G9$keRea2!%Jt9P{iJ-H|Us5lq0Cr;~34@VA%^prP4k}ZBy zhJZgfiNL+|%0RWq6}zh|%PW^be6Z}M?2_CDN6&26RII)c>= zzY~qjJ7f)=84ZCe?qnh&w&X%;g=9f}^OAZ&4_sav$VihPo`KZmOKx@BNVPM;U zo$VK%6Z%`VtPFcZk8CubW3wfi2;w&lWzCC*Rq*`7(D1=Y#*3_`)ct#;rZ`6l<^bq3 zPBG8}Qd-dp$t^hS?3CNm9rCy!MBtR9BAaLTeH9**v$es+v^_v@|vSI3+}pHJU1=onT#Y=tUm|bOc1n9d~Y^4l?{J)fb{Fr=Uh@iP+-PGTSc(*J`~1u^(CEt zMQFmBqL3?|Em}-u^| z%M&l<87ZZxUM4LS;e9LJXyXKPSrE!o}z{P35csryQ zKWvZ42RmD&?JB;nGk}M+88@NFn^CcHvYn~n=tqb=3&B=R$>6ltM{th8H*g zrXlb2LemNrDOuhxjeQtqD^QfPKvo*9J*w0qW~bPggz|70K8{+nfC>EBl1|b;qD9;cOl6=2So7b)X8FYXx-6NR7SNJVkWelW6HEtHiiiT$sIndlw{*VHSNOP|dQs2eC zXG{8%nL=LX4I(;lwD2^G9#P}vRQ!p=gS9-_L+wXplR*h*Q#%WzCdkP#f*YqF0kYl0 z&7h$H)=7b7b>5lINZ$1SxS!mc;^!V@vP-7O*`0rJ&uNs@ySlo1XN)O4pYmoW*Zr~@ z6a9d{Xj*PfwF7%XLInox!blN?;}iC*R$hQ|Weh+ARoQ~Yse(dRb_Qr8K0p*8W#7P- zURoHjlE};dd>>&i%HgJwMs6+ozV6TiNC4_@qLXhEfw1ul<&T)YVUj|Z%Y`7s91f3) zl}NjoPM@K*hR(%24@WsW9%s3|!lUOSBc@KFWE5phw*)|V5Z`7YTfbE1P>4oeNP6_l z&dnuWJ)ol+fhF|V$*yf@xicdS>VPDzR-Qj1Ggu?t_m2+W$lZs78v$XLIkv_L8irx* zC}Y#5lO^ie-!CXU)qT~KB@&FSLS&~Gnzz`Vf5j00Hb0d0J=&^HyB#-g(&dIMs@QeY zquH5PRM_gcu~P}n8>1*hHA<7f@}gu{Xg)g!kMmxE)zBi82d>;?z3;j$o62NF z_kMpE#}Nw^tFjY41|SzL7~$i#?zm>8WoS1;h{ZWIg%uTm*mVse6R3RkUc;cdeEuqa z6cZzgY=@rpXnBT}uqpTDN(*@d{J4pXTH?&#K7=*4x@m(yR$FP)1bfq#kW{goYeQ|+ zCar`mRSpxQ9paKvJ;oY5g14@ay8qIP`MTlDWSEu(UvonOtgPn~KuG^LhB*!$tP()c zp6%HeN-Av>qH+V7+?^o??#|fd*55n1I-u45anxnLEAcW*AUe^^UE>QKzqK}q49jxA zH_sR67XmZ?O+AWCQg{JYfM%mRW7keq6oy~D-zfyu8#bhCE7Ql#MiVFk@gX|1UerF4&~%%;pJm6o|4aifY2GPO#F}7gpqjDUM(Ux%nvJ#k z>#H0}?8k_-m*imfUqP?a*owSfi9deOhmj8kq^&1#5+J@|g8d|FOhFzFv<(VePlYO$ zScr)#YzRULD+o6njZG($DPER^NF`BasTquTS)?v=(OP-8VOt3q^h>W|b=y&pMG_hP zkx~G(qdc)-aG$nzh_?T*HZ68lkP9dTu*p?9_S;f zz548w#IudKcS^H+h&S8Pk#+iT5I(sw}$J@exM)?duS!E)$?Nko4Mecw_aZ_TfcT|Y;p3l1K=dsJ}h<0_! zO&dOPgbAsct|t(<&M25#W9{1a=$pt-RZ!OPcucVG@e1Fe8a>>NMaA-rlx>DPTFJZ} zuBMOD%LHANGw#g@40fMxw*M>xTMvK0N7UkkvdW;H=xA9M9-7qN0#sFiNzK7sX$G?o z>z%R`P_JdCgfFA+aiRLrT`WMpNlK9-NIXp-wnVg56o}RHk#q@VyHV1h^|ZjNIVI6A z_`W+7tO=l>hxa>Omr~UM7!;=M z?S=2l3HL0wz1Ltj;0bYQG8^I!Mam^X1e`XA>uB4wm1W(Y_#$T@SqU-x?K@PmUVK!j zNG$LZo^8-Eiv{st%%HeS3ELTZiiy|1j92LS_=;4OG z$pqZMi^NX4R68@?@6knR@*xU`rWi5)bY{HrK-YXscw5&T9M>4!Qwft)bHt}iCJxls z?n3)fD=U_K>i1Y&=JVD#n z0Q$C3;6wyyx;OsHiZM#t*jLS0NQ(nvV32faT>|n;M_5EV;7n;xq(GIWO~T$syc+cy z>SMv>&-_S2qCR`ymhUdUyW<=A7;NY|I2Q`@D&^^KM4Uf6a5(~4crNIY=c|bZXMez> z!s@Bll$B@xE?-*f+DJlGJl0h2?)D;xTZj`DN`jW5gLiG&#ES%N9;8odS00g>wos`m*+9cP;UD>8+?ToelIcX(mW~W$1zpZS4a~Pgz3L z=e|Mx=CKkLV(a7?Yrk0D+pllF4(}d5_bO()=anm{(HdxKSie3Z!P4|7=;!g*lJ-;n zTAosOZ_OT-ZBl^I9SXC5w@_ z4Nizj(5=4Z$klqa_KmV(1vX!l(4@pF3;@k({zcic88V5K`)Z=|+sj*5vf)U6`` zr|blEP?Dr4u+>;vw9#H((6&B@%f||Al}_|tdphDBj*@`(M;Fmn8q~t8_=BN@yG1$n zbOQaDGuwu@TTmnv4d_asscLBWA{`1^ijT#BCTWt?IAO=YOUt#xY4UpdQNFGk^6E4c zqKWQ5^2-8)G;Ub&4t>1+{eD_$ycdkMn$JHY&-mpzPSjLr7|N9n?~*z^Vn8V=R&KOc zS44-BqzYA&EyrxGY=<-FsHTidl^?RglyDWu^(KQ=XAyf5PlBdH)Yb9v7rCQJ?3oh`tg?55dq>gbz6m0KdI5TfF63%j3TIzKU_?p=t5w-4J zrpx$jg-x805Smzl%xsS$+te>y89qzlsLWzdTm(^Ol#@lz;*kp zhU?X7{woxAdZ->As;f=%Jd%LB9NR{{42M30`&{te7%SJ7s<1UI3fiR@cx`j3Gq3Xd z`!PgE>caR~C^r)0CH;HrMooaOd+-r5f^(&u~;Sg-~4g>%`9Q=Dvp@wqLeYRy9 z6txv&s&&<)0@6VTbtMKTk7Z`ApqOMh$^EjWmIL*(y(JlUJytPdF~gndq$;WcDtcH} zbR%D3$iWXXaOpBQBMdSv=f+!L1ImQ}jAk$gc5^iUcRAIW4vIH;TGB-~4UWF_tr;5c zJK($M-&@0|wF3_ov|2TUr|5?kF}7Ag6NPh|*})qew7%cJ?AUts%3^Pn9X@HX!DlBI z7hT{a2JiWqC=?tlBxtuY!Noo5iAF3Cdu6}t0+N4Gji@*Jix^a&Pa_9byu%1!!u9=P zQa_*7;F7AMS-vYL)MZnT846m)Sf`||?^P`_yo`snACVrhN#O}UrBRWtA%`K_#HKjK zk3_X;1E|xs^aJXC@LvFz-#nVRBd`ZRmM;1sve)f9-!*!|Q!f8xx6bu~7h3`1!*>?@upUb5NNn>s z6aZR|cg`pf8^w{*8F=|D805u3vat<2wE>gfV5mNsI5#Fv4IVQ z)MY#XESTd26AiGU6dc%sKd#<$Q}e=DH6E50{Q>{-;SmBK8OivXCwEjCG01A6Doa*Q zBBHKxARrAr^p}xk&xf^%PEtf8zSCZ^lP@9>5kVLgS}~y`wLj;@zXx2IL-TOhN@QWa zh(t9^iHp?!SXzq>&L;wY#lP9~dxuQWm@E_9<;+TEIHtM@#ba9(ra@_J~2q)ewKD9LbR8x^53NE}5DRuJ?vXQrXlje-DP@9>Iaw-T-_dT>|Q z{X1q2zf>OOkaaWWJ$p;WFl-`RQlZ8E`?P%WILRh~+gSFRu5#GHwhO;ZXjai4W=LvN zD4E;*C6<@mt|sxArW_lYO*p;buQDdBr)PnAq;#lKCd4RQy=$I<-$hjAOg(nk<5XX4 zNc(XB%Y)|yFe~<~QISA2?RmoGbos7@t)cS2)M2eJpHw=&<`akkrV zC3U}a=!i*M*+ApV(_`==P~mAXr8-mxImIX%Xksb9>Wifq*`kKwxz@%8oWCJHOPnb}p@kV{9u7gmUP*exd!vFRfgYPvJ1Ru;re@PylKOOo>ox zq-|s-H!ng^d6A*xZ1ek|_)hG#*8vX+yd}C*HTC^rg;+BWm0a?~qdohEmUknca7|KL zt;z2mA(BMgg3`IDe?*`^<$B*4Gt!W^iu`Pq zxowoU`Qccy#ApM=KD9G0Qy*#y)0AmTF)c|EDws$Fs1m13+FnOg-vMsP`6>QD>j5ay3OrUN|*o~!DjK6$uU2p zaa<~p;x108lVq*TyMVf-3V0aoESa}pwGz{<9!sO-JH>vN_9Y@5h;PEl@aB_wl#hrO zv1^m`sZ}vu+)aU$Fp<=QG8gDmsz9bPwR?wTmD8W*L1&=i8O1)BJG0Xcgi(;; z*U61odjq>4YsE@~$?=`Z^u^cjvsQ7#*R7y-E2k>H9^?!@TMIOqN+65f&7Eiv%@zso zl$!VC?ZFph=#G|wV|eB(6=uvj;U(tY7|guvtb_-&h6`1e*Y}KH zq?18c6`P;E13p_hT%7$*xLL4AmwgAoE=_|nL(rbFJmqp@9>24|!_ z{pr@E`bL2szhBgKZQKd)?8Br_kunX3_E?)ASYsagpR&LoggbFs?2VZN4RC|bJ)D5B$?!oyE$RzA;f~lPv(x-4 zzpCT5&|W{Wm@~bb2pAkI)~rTYxZPNs74_tF>if^ie%)j=A%v%d@VshaEGL274mcHH zv?X&mp4FN;Zj+V|EcpaD*ic0lVa1ff?Xgg5qpXY)ZlY z!Sp|9END*9e#Uq{59a#X%N@d1I8A!03~gPNMP7QiX?zX87AU6Pt~|C4fC6WUIH9SPxu7$Yecx3 zgpBw5vQfE#0f}AMqredfKfg+N)|SYuG29n;GFPq|1`AIbuEI*t-QFu$7u{)7QVm5V zMzH!pc*x{h)aH$=Bx2E}!U~wdL~gq)po(2PDG2xGDl16XKq6j<;6C(%tW?=L6(**B zb1|-xLztE5LloHKv1UMAr)`oR5JD5*6rhDLX^A^aK576M#Ub1kZLzLPn(b@zZi~}CjSugC zKcWU!q5`8Zz8(SB*^0ande!IIR$xv7pA|qW@%tGu=i?fI-o}(W%Oyk&6X$qm9M9co zM@hfE;T+J1Xl9m1Ksw8`c?4B*O9fuel$*pAB6ePZqC43Efo}wOg7KiFPr~gvq-OzF zuu#wr+Tt(TScY{QfEI*psGFw6l76qBa* z%?D_pS7jWXeQOz!Qn@4e&SHHb%qR)aK(&B1ihf}3Miy8kmi-C&u8@!4=PNV9bvWx* z{ZFjW6}<(N0AXHI^c8QYuu-!HI=MBjNrmqn%qb1bU4$e!PtJPd>8YWx&Qc?{YZF@@ z3Ja#9S&4Lqmm94L!drUJn29P}E65R=5@-F%+`SF=`S3Hd$agi^Sb1TGJhM*diA zM!HCFeFJ1#`wcLq9AgaMKVeIsC40WJ#X2Q*a^BY`>VO=}?iM)w(nfGWEp`bC8bKOn z+PqgT5mq(if;kAO=9YZ>kbbHo??9QX7m(igu7tz(O4oYuxL-QLb@SQ^+hfqZ`@eFR72q)FiOT$~+UFa~Y;r3QDd|8d zbD%3MId^CIP)H}~Yhcmku>eLVniD%Rf*4EGo5h**S9M_OR}LFIZ?5WN9rk!)?N{F* zlOwwVqLhh_QgZaa^yn%|?hD+@XF-=e7eyb;XBp8?y-}qnG#PZu^EQ)@lmt_geA!Cq zDJ?ApHqZ?Wt%DDW3W!}sH$=cq$t?}G>fDCiDO_{T*D>QgjiFoOQppb-& zQ9jBJM|ndBWJ$l%Ui>JQ^+%o8;*&#@6pF4YjjHprBl`UdW~5)iA;$1FPaST8kG^sa zcx`-Ly>jK_lai&T1&0)Dc+jt11a4r6ok}Ligv|pC?0U|Lh=r3euIM}Csr|bSYXGQf zA@l?klJwRUsx7Oa16SH7Vdlhl*xnG%IHy)|8lcRcEdyWfL)>yR83IZs z8T2S!Z?=#ko5UpSCDLeO8n$TSiDkbMA%QUo1B1k1S>Lx2` zzgy>5Z7jjbeMddGUAf$La!r+&0ThUG4*+i&ez_~dDNH?bOO0T1^ z6Lacd)>x7h<_g$8HHOkmeP%pgA)y?L&UpxN(1oX7qhMQ8Z7X$s+_iQGZOSW<%+Spt zIAVR$Dxq^8HXU##>lzU1r4!^!9SfVE*sAcyLoTkt_#UTU!WYR~#DLs}JMOfHT*u zE|n~T-zkSuujCJZ2av&x-=%ydxC1FdJKNwKfZ`D48CNB&mS6X;ei$qY@k)vuB|77? z40$Q*yh~oM+c@3T5uDza!&WB+d!ayPRw&>CY-a~Jf5C@b&41k&`kpdwKnJD0_8Xl9 zLfC>Gnm%)oXr8KZn{8?hkY0PWDU3?cP<>`ETFi*|a2uW!s8GQ;3@0a4Orxa|D7*Ay zGXES(Z@QnxHj3N}t~p%DY8CD&Tgbl3#+S`xV*^$!UsC11M~nsj^%_JgRM^yh+0o%g zQr&h9!xW4APT$H#J2{}kll8$ZU1xq<#>eC!ZR+|A>EmAy?p)DbeD7@2tYEN|T?zuQ zrb~6as(5Br7B7LTeZ^^)C&b8p=E)3^%#^@}ZAO0F^7HX$j`w!Q(n8}rAR?k*Em&%@ z1M+sT->vOs$_Zm_w{Ts~PGZqEMmU06TNP!-o+ASdbH(+DsU$J{3#Zu9+3C};*nF_< zEuz2IblvLjFm!gsJug@d|6x}LWlrNis6RB>|f%ZQ=s(ZT6C)bf3w%~LB~^U zWNh3p%M1z`r_xDVfJbAefN;KbF=N1qTfc_HmgzKPD;XKbJAg;d5h4HKy6{q>d?2|B zM1=GWw16)`r?H1JcYEP%;nf2uX5ff;8WEDhCeTArjXT{VkiegD>uau|KWae^5GNG+ z>2%P%G1!2zLQl~7UO))J!W7C4XLk4;Sm4lMa>-($D&!bdXbLc_RD4(Tcn-zTaMNTZ z;^G&eB#K)Y$pNdgvY5uc2~P2^X_n>CAtNJsQX?oD4@fI$+`2p+#ZF8&QK;$;xx5lW z%0&{ij|$6X<=iy7=;6FCYTqKvwjIe)a_-SG*r9v)R=}}&@Jt}>WyVHuyWMl21~_=gpCCto{F z48k>_TpWYDt=@(-UstG8?s$hX-EimWd?>+plB%7HZO1tc^}`Dm7IX$GBA8Wt6&)(Y zw~xC5WD$ZFyCFGz>1S?9{YOXE#K+4OZBtsn8-w1U;%)2r?VUGVz z)cl*M`M)J<{!$J;aT5k6R)+tyXa3=^0O(m5S^lZZ{LyR}KFqKG-1~>K`I}n#m#p#^ zQ}aJPr29{ve_<;hG5?EINyqkI#F`H#=WkZ!Cuj3dwB`@t@?RcB{)eogXZWCQ{%O{* z{)<^d|F6&e{vXg9J13hD;O*0~`|sIG0~;$VJz7&YTT>%z+W*$DbTqX$GNLuMak8g1 zHgh(j{WL8FXa#A-X{BjDB}=(~T9(SRdbIkq27g(W#Jco=^i zoxc)(jtY&x5RXsd@l$I2X9Dg@%{?*a>%TM_LKtALA9bNhR>pwWiAN}O-fXJs3 z^9hUmy^K%DEb~)s`6rQ$E`Ix&O~O`F#B+ z-skqSyw7_4fmc4${()XT^Zq>cSKB_y{*%X_KKXn3|Ir_RFX_KmbUyR@%$J_-V<7y! z6aQrXXZu(3|A_gIX8hGume29^htc_~f*(i!r1{)_R_b&6dF-=8{>1rH*+2XKJ4WYE zWB&|{Pe$iY`oA+epZWjQp`V@lFM<7o;rXkR{zahq%;)dn^Thv8;j^y)-LXIUewP1N zM}KzqzXX;KHt4hS|JjKj1K`gf_|y4+2Ed<=|6lU>DF1WcU+3d<0Q?Cb<$jj^8UCs0 zd<>ZXoOS-em$Ljr-TK3qvV2NAe^Ycm#NfZZ{}{>tq3rx`_) zhZXaI4O^O78_C%?n0;ROAM*OgJp7k?^Uq^Sre+2f)DeHCKyP_Jk+h60C$%7o19R7?=*BwjXzpCFNmVjOq!8s>vtjpr?>&=pTF?zH6 zAtwOvOXy^&(1?4J_Q)c9(}WCSrgYG9*STkS-?~|cZrrJQ7qP>|>!;IY9s)9>Jl%S~ zT6uS_kP^FFzyk3_9min1X%ra{NxnoZdB7%{i;xJ7tg&t?zYfWhS!yj7Scr;#l1jE2 zb0QhBFtsn1W7+|>zL6d7)fXxA8tpgSkl#;XIrfPWP7kQdc9pfu2-cvuhYgnOD?+|M zoS-(`yOl=;`%At7ALtqG|JHjRklAJ%0i;1fc7O^_^0rKK8C)FhX5+A_3-kCSuF~Ge zO6cJtw60f4+w^P6SNW@6+AF3<;q4gdjcfie#*Upatn~%3cCd0j*o=O`6@p;Z9(m|k zL(y9VE)3BTKs{5VP#pp^H?e3Lmuxwe1pD>1>FGVx6WfSa%g8|5Ov3`7pJ*lKJa}eX zp?1ZOr65=sQR#vrf&v#BiKV|c61uITPnXHk8 z!-H0#=X4Z^m)^AeWVOe!P8VL1A>W;OD@xBoO7&cFh&l&zJDc(qrpR_~98p9xWU!Kp zu=Jp&!Moj_(9U4r$^r-`Ck||XUUf?*1xOIJ-MCvEgv6P;g(Bb-$$CURC-}`sQ6r8Q zXek&vnp`qc)HnX z_~Q$q%V5a2PQ$bGK}EYCJ}(Kx(1PJ6Ej;CC+XQC-YTsDLBGuA8{|3~~2pZ)xDg`(| z8|t>1o%mwQ#AKh#ups3AP1aspwp~yBuZDR2R0|ZvQ>9#EpHrecIMPw&<2uA*szlWU zM$;ePBy~$e<>^PgtTwm40?US z70SXX7f99Iln6=eIL(@M{*+p*!9CSs?l0D`747sq(0JeozKo}diwbi+uhK=t7Sra> zf`Hsga3;$_vtP)&GGcmTmlBu&t?z(AhNZ5n*KEhP|7s?~=DSq%v2O!HlZVI=e0iX; z(HnVb(&S4DuZl4LPp2dloV&vtgXnMUzz%H!VwIbFK(g>>%C5T?IRXdCK7bSL1HtWx zd5X6hw)G{17O9HF==kh=#}^SZ{XQvS9LC^KE}!mi9AHSXSHy=oc*{w|N@A?*gJG{M z`rC|cqCb)zOp25%=yONaDRa~IN^_aMecOJqm|?W8JC6w^N+pXnoencjT%G+6o6r?^ z5hR#(%iV27;-WU*PJV!*T9Fg=O%(st9zYNSw`eK6Q$ zU@jZ8;+J@f5yQkRjosC~SB&{?4o@giOO;hVND_VC2dfqn~3=Tqs9 ztlcr#cceg3`x#)h$Ka}Xqs#SeTwUri%=40dAqHnRH zNEmr9u9A6Wt(#j|a&<3Kn+bxpG}AN>oo?VE=RW)*y~1JMO|;y!wKoKdQ=p=2>Ru;P z?AndS%)I?QBtSNPB5R{RAHzD`(q>1@3fN3EsJfgJ(&DmDmM;(WdP5>-GTetot6zs&6_tCK-Vrge>@A& zhFd+X(fLaW7DG@Uz?-mBT+}pwfl(ruerXa|f{Dd|oXWaiLvJI7q@xdNw8^77h&m_L zXos35=L~NsAA;ayJVQ2=syxOZC}bVj24xkgJdBBu)2O9#PtttMJ zKT9Ix1EA!8rs+hE8d*6{g1>HrLh$D@!-^ICN1ly%HJ}yrmZSsWY``P}$H>^=7DG&B>_% z*KWl(y}=JKZq`%J4WXZ=HQVFr++TNTAhHflAzAd)J)x^0-Za8-#Csl&FIHCQ#_jVN z@y|tdVVXua6r)gl$rv6{4DS3wf*Y*`3rHoC)`uhuyk;$KwPL2qMmPno5wdtGD0&Vc z16geRqEny3IMl_yyPOtEnGmmWePK5|0cflUa#5Ug*)ao8P6k6mXl6tyr8ETYz0wUcrO}yd8~&`z!gB<|u;?$69a$Ft9yU59X|Y$1q^3Npx^n%g?Ex$`njOPtABqewn=;%oo;|&oq9ws zH269XaqjmD)VMLf2%^|uk6NkW=zz%gw%Ryql^JHyS&Z{zwc+GeaQQBziZkW!(fE3Z za>;W=D(z-R5qd}08UsT}8nVAV0YoicVvukv`u}KzFzYd5n&fn zxSG`{5enD3+Nkd^5lGpu;L3c}8H4N5ER~08_5Q&edlN^H zV4G{i2fE-H%#viBu+zz=)ddG_=Sjw(rnc`^+|mk&yDq&&JZylmZNP18G|0kOc5>{Y zjWVono4m5QK_odtwo$gPvg<-Oig<1~c3ACplfY5B_i(<11F4OX@ z5MqAv&@oB2J21bEvnUJj9lynyI$iUN5}0T{XT*(!-XX5n7!(ocmtevTu36faS}fF4 zJligARZII&(s|`s-&qX~ZniZ4ZXs$v60}%`!E9o#MDIcx3h2Ps1)b!p^|gg8c5mc& zSJEvL=?5fa@IEbX(PZbPdj@2Ygd^d*P&1gUDFG{KZo>si*SVGgTw z8H~6kg|dDVqTMIqrsmw*uTtxTZiL)&0a!P?yurWS-;wnih0~H|Zh_t*lLYnL=#2^8U}`XU;Xrc|Gd262z|NMqs3)3GNJ0*o%QuHwyLlhsh&+NT|j#DB$Ka8z5~w z#3N!YeiDH!6^($hOQb-waFIS>eV2|ezfX>aAcyHd@(kf1KCA}@fr#Y#bBP=>>nbSH zhRd$>nM?ubh7)&0i}S){&mp}jUypweN{L-5eYSu1%2yaOu(cy(#}Q4HU6yS3d(S&K zcAa^H|8Bmumk0N4eaJaHKVCp^8s+dRVDvC?a!9x>vut=UNx4408JqL9bB%)JYoyJf z0ZW+>eyE4p*y-$Da}aZWqGm^Pp}DR1Qi|m-*;**<%nQmqncpXJUxiGCSzkJ-j?3jq z>PEDJFPLxGp|@E?FNA3P4h?sV71^cscMH&Mqzk;-yY|qbzAHc`w2_kJR4ApqrJ*%< z@4()N)pBo>#%bN#+IUR#0eex6H6L3U%2JUXUB|dFywyjhBV3Md{|OwsC9Mu0%e8OUvJNxJgPWi=M$o_2 z^o-V#EK!lUfqXBPQOX~4bULRSnnJP6xyDg{+`$v^j@oObn5v+wDOb{E_o`3`+k+`B zE(beF9dR-1xlPHL^EKhcht<070mv^S&-dJsQh}vdX_dns3OSvY__wHFe`%p0td&seOWWrvocQMC9X-XE9^H67I>b(Kq<|;;umq zF`W|g8a zZ`ve^FUP7o?+wWF#M6=>L~xpo=iSs1{e(?3Tl&@0hPx0d`056mm-#Y<6yzGu2EL?0OH?j`MvU$ZGXpPiFhH+URsEP21LhyduE++|4DOZ$NKG>3O0!f z@(Sov`ms&rLDutQ_+?te`nlsX8=>fphB zbf}ne5p-KT-<)bJ5@butq9XRS=72(_RFG;so1^>1AE-XIvMnKcL7UeM*^4J`C08gd z?Q2b5Rq5m@1iY6;e1lI6R^kV=B7@n)0jIO}Eui_CKZ8A%>(Y?5y3u9W%~Gk@>@3?R zc{Ge~wW?$JYY*s>(TU(~8pn-T-kqrDG0txo-?E){FRiugp9z>7ejbZSy+=C(Y{`5h z+s8(d($eerqdBzeMW+2hZfg21^C^{zcVG)$a#!r7=MI9mr{^4Pj;|Oz$KP{c9nv2q zwh&Fc%wm`Dm}61HC4LCB#1gfO(r|cyy-Kodua-2LU8()1bd6et$FR8u^m5F>c${@$ zTeot+sYf5=ZUm={NSba!8~vQgxWp1k-pS!(+2fct7tbxSktAZRx239U;+kGaT*08d zc#!XdB1%_6;a*(A-ASc#@FSb^6?k`p>0w>_m?&E~-*TKoX7#K^XX@WLDQ^^|VKr8- zC=!p8nx=Zs0I)4MWy31i;{}Xxgq4-H4!Ed*TNYckQDaAtYc_#-B{yWpe5qcW_WOOT zc~ZtTon6;@UHsJtz=Bw@VP^zxhHzlriqc6aMGb7DA@TOF^j-F*Z(eJ z2wJMh%vjQZ1`>>K0S3Dx2o zl_O{Yt&P#k%(u9PVm#q=)Ly|>NxIPz0sjqq<)gF+#RdVvz14OhdM>7|ytgj1baEG~ z9apNEeMjVutfBz7Goa=l+s2oJ5vS>$_GAG}r%-I!iqy8f&-=%a5{sz9{_w+dh0#+E zlgz_|L=wn{G|c<E zdFm8BBn&1M-jAk1(FPy0L(q=+WH&qsATsT6oiDoF~Fc!F4f0 zTS_#s{9o+dWl$we+8}IPP7}DhySuwXU#(74mMH}3B4?(XicjZ5PW3;oP9J3BkO z8ym4dzWCw|BBQ7}WLD;V*QqE@)wz3y#`5w@e6d7W?uN)DnF^bj_?wJ8)s)DutsP`c~Pz;J;&}0c>#Hzs3Yj zT(Q0RhtTgf-I<>Ym}9S%>EV-DkXS&?LgvI=P;IfL|cpxAhh3{I1)#DXe8g{Qd10_t@qI(v7ec8Us7>^vYjd z<2XbNF`Llg<@iZ=Pi2oP*H~sv7IOLDvqL*^xffkDQ+?b`d$I>x>9?7GNvf=UiMk&I zIvB=8YhQYbDdm_xyBIlenyRqyB)-dcvs_9cGrq9*6vTDvD9JXn89X~t&iZ)b)iGR? z-|DQKsAKiq?a2*NSS0dd5k+zHs6PAnOUm3l{agTQ8g)R9pe*TndEf;#84p;A&IWTjPq%lFh8gUed4LRCTC%%B+)=bHccasf~zh=z;PdfZ;*+<+p#FlE_D z`4UbTWA9PZUCORfrYZ!WwF)F;W_O(H9p0OGME3cH?vJapKf$4}WBUVxJzP7Slx3Px zdD*d{39~ZrQd=qAf(qnRsY%{PRChXhi;T#l{xLbN!G)K8G5`rZ-R$@A{`ByI23Jr< z5OvTrU;1q2nmUl{nS~tu7a93ClEQf9rJ8oTkP0qMhPQ;IA%=-;Cy-U@#CcQZz(7d6 z8{M0bGo;A?d7}m0)o!Q095ec>g;WWpUm#Kg)an)5Sz>p@N-Kr+vKi>ei_#QkT65$z zu1qdq2=MVYV~J2F>zQP|#9=23`!x0SvvhaY(^bZSCd&Is8^}Ft?>3^0FC0S7*I}t7 zgSR1-Ic4e|Es*kBLdQy^AOwhAYKU}QNo93jybrCI4|`ej_0=CN2S;;4kVBO0o^O%u zc8VAiPj8Pu@C-O0E%|67+gpVCl?PW>eX50+P8UlpcQh5N`tCdUY>q-;@B&Ht&;hfU z_ChU{YOjK<^HP#MmDur;6%jXzsPC$JV;P=pPbiNxxU{##@enl8Ihq|KH9ZgH$xyQd>5vCY5fJ)EuZ@ub~}2B^GOI=5|J_o=5h z1ZU?gPBdoA!&m9py$se?#WL$&--nQ$RKbamR=8JPD(3l;P&2JKSKI0a8ra{qQf5;N zP`xg?C7*25cL3$%7}(#r&977^aBNPL>1#Vm;}+nR=MmN^3CVZ@gz-w0Y&5-?Sn&X$ zutFwDkOL+Z-;5#;YIl=NA}H~;Q?fd zG|5GovF?sDas_%6cywikg=<$iraU_f)!*}`FW&Ns z@5E(#<0RS-J7c*vE9SE>lj%Q@$2`sNkr3GQO!MA!1n~jut}<{JZuDQI#jX<&nG!Lu zz5xbaYK%GR#zx-$ZH&#OZ`$E~b!AI&SHkH&?HVKy`h!FB>@E5ER68n&a*=nsP!16<9O3Q3z_}aZNif{>b1)GF0GAeUE8VzTxMM;jA3{@~`;#Tis_r4J2 zF?;p2DvKuL41<&y3mg_}rw32n}DU{Xl&1rwlk~OtjW#uek!2f%e>2m{6XabjFv|f z(Sij0?8?5{QLcXS-yHf77q=yz&}{Yt@9;e8BWiuwzU+KOq{#8YyP(Mo6aShC=7VU# zaN+MXG^bd(b@q@w7v%k3Cb7g*bP(!mNRzBb>lLzsXDBaupU}1*5Jxx)(^+-YYvr;F zGd3aPk?^&5>ZB1_p$}S*cQeGC&Xi{NCmdD*Ab@1Ip{fVU6FVums-x+aec;1fcIji< za$RSY@!<{ZOtPOrJ~xIwzgM7|__;W(LqArH6}w5>DIaWSkqXc;-=pv_r{terB}H9^ zhj$DVY-=_kb4uUy3;3$-`5ShOmOT5Y?KjmJeYbT~Fhd6kd?douh#t zvo%R)_1J^7@W2k?wGE0-*~bkx$)r};YGK8giV#`suXWfY=!)(Y4)yb6Z8hh|G29y{ zCL@7jE@|&SKowd*DZrj)Lthe}9wWQmBvX6`U!JFENf>*T-a(=?P>(}A(2xwT@*mGN z6p?`_94q(Gj~~ZXV=-!G5A#S;-lR@YiQpY{( zZd8!(v^%C%CzQ7^r9Lw65)7%^@4OB~bZ@WcA&H^mAy*$?tmYSP(Z!#hk#AZWZm1|G z!!c##w~JmA1Ov9@7CA=GY5<0P&Gah{27g;cD5-Cpjl5Cdq*ZGa5!B^I0=?h*Wyh6Z z1_oOzBahxG;^!Ba@Ki~YS8QM9u4A3W-n#!Q+bpa`ZBo=(13!`us-Yth$W*uu)iN4b zt^T@WT?%RirZ`nzSk)%7AaseH#)V}Qrh&QWhoo`1n=bz$Dj=|vw)bZk!UghnN**VT za-2-W6OD~Oo!O5%#1(yQN)SbHl6t}ke&FGd9M=n{4R#0)qJ;L2FTl8}bZOx#-gcFi zsc+QCf;~2Q=l0$_<=$j^zbA0^*G zy*zC!TYwgCz0_=FYl-s{ru53!m}6rZ0{Zk-dQNH)(GX?p6UyCXS;_28bC!Cq(gIlT zWMaPf5n9E_ZYidWN!xbfaycbAS5r%HaFf<2iZ>pg{4`akx{{m|N++~AMW*p>fwa#e z;heyZ%Ij;0aTYSDYY(Q2{tUISMcV*(L3eF zs>H}}^z$luNyHO}|8?bo+K1UXd3UT$>vgsCBKBkXeyNG3ACl$xm$4Q|LhlJqYsV-4Sa5}spH%0O~6Ut$zoJ{8YZqqmeSHENC@6B@Pc?N-X z(52)6UJd0qzE+_|F@IiV_sj>6_0%cx1>gqQWQkPC41F|W$Q*LW?|{M=)4nO{EE0Jq zB~ZvUubZU> zOqK*?uP25*sXvKY$UE+5Ku&~t;pmV|!ZQv2ZlSTI`5DvMOuo{h(muR$?QlV^o+vs8my^O5A!}vTCRDVWJuzNL}I& z)(aZ`>Q$lV=-}o!TrNTmPV49@7;;69BarrdjFzv)c>981a31SnyzmdSs0Y+@E5Lq! z4PBrr#0>BGvEPP+l6iPYh)6FAFFG0Sy61(B(pzR%m@I{H#9*E(Tx{fNiucthO7Fpf zMj$E{AE&}3Z|+#4%P$pDY6w}x?Z-THne6Bf%q{K?G)i(L2>qOQvwccT13MKcApJ(H zDB?2$fSr?1*ALp_lG>KUpxINDn(}n&6GGdlO2}MX19sw}O(_~#K)}A0o~7l(*;?Yj znu<6*Dh}iw2y;B%9k5py7CeYOO(o~vETogz(v2C&3t?mF8i&`WMdO=^miDYQwMdYI zLxfIr-}Dovg^Cv)c#s}sd5{)GT3O2qya+^jl);x52%N@WLt0W=&MQw&I96wZ!8c7@ zY^Pa+ce$?1wmOM4R&EQ>dCJyNQvUPoOt@PY`Gxs+hro^l{n6k#C~_fJ_0v~VZbB4s zy5%XqChqghSe6!6<-It)6b1wfgmt5{OnZ5Xq%p`+i-W!UhyDFvJ9Ew4%RR4qYlRsQ zgs>^0uWlJ(y56PMP--k7LR;Eq`^&#U{JuzWxqP@Rdy=XM+CNyf(T~Nj%v+TZ0Xg}J zb|RClzAf*gNV$fsVeq2{v|qus!5Jnb%1XMjE~W3w!>q15ANt1Y1#nezI%vpzY!#H) z^AxII)Yq3+@=377W?8BPciXGH+hzz)8R?+Wr{#qXOb0)_SK<IPU zYBLUeJ$ox}c9PMe*tj9nU3PeMLN4zH%*-wFKJG$&xg2|XgBD}Hk`^QnNY-%YP7uxY zQ>to&FhHS_E@pBPj{OWZ7sB+lFFc8dqOgwecg#+w-?U3&;>1iyRd(x?GN4tIpsQ>~b=ia}QvNA+LND9~r?iG5`$ zRo@x&DMoAJi`V)Mo&as686~~19dS7QTY-1-4lHOIPe=Lyp<(ljD`K~E;ZwpU>pJj@ zC81L3Gm6(yTGcD=@6yuxW7(e!4=Af>4$r!H1*LB1Ksxy4hqrc~C8U!I$vodChwt}6 zb}eHv2|_t>aGnp6c@Bx((WqKA4e)<|7ml?Dva=KGZTIyt0GGi_d0(zfRmj}E2B^rS z(_4RUIOX@^gfJ}9`dS1c6HuHud9s|iaKn8m+aAMq=3r19U(`GOlT8uv%KP_1f+JKv z=~~zKJecb8Kq>GwmTN|H%~)$zF*5AqXCETkJ;0P6e#-t$vU<+$1>2#Pi%Cr*zJgD)_Cl$EH247q6EpzV(Jso`!Y(6-7 zN^4=#uY30}%|w%@)UR9h9q|6Z6w}ys1t1zxUv(M;R1oJFW>A;=-Q8(KdGQXI87yki z;JO4Kv&Dwun&NJ6EuUmi+6Nr{zq^P^9;+7nqS!(137VO3+C=s=v<@k z-|EeZ*tndm?HaCIX&+aBtMo))kG-INs%m#wr%7^s%m$f#s!41v=~lDB>CqD=iAoen zplYA|^aveNv6-(-_K77x8$<(M-y^=(=uyG!&Ru5aJp@63>2ihNEn@aUTUp)WhW8jpI*Iq`<_6lA z8;a+ssjOJCfuu77N2q_}EjzLqX7)0vFY?f#aK{aK=);79$az8VChq1amFoc?k9zez z`Z8{ZhZIm$hGEN$S9osgZZPnRGL7T`8hgZ{xxDX~>D!~f;KUkvA(!DSBe;kprc}B3 z$>C_p=n_R}b$b8Dtapl!83{nz{I!bvhp6~Jfk}2nwfR%|Zpg5}t$k|s?|PObLgvrk zxjjfQ?f4wFr_3O9E01c3!+rWAnKyZ}uBJsPBS?au6;8X1e&%q@6=JIYR;l%d9JZ}B z9^1^2+$hq{36_@_E`es+yG)<|E}2$Ys=x{e==5cC7+B5c%C%Uk?BJ`EG!l0(fGW=ohz_7)-k; zyZJ7(4o8gD*yfEGzV;y<9%;fhe1Z%3-t0Dn%7Xg_6P~OjHe8ROG6Lel?NXdopw31I z2zd~r(su9MP7TXwPI&%S#)d0MzxkV3qpFW4m+5SfwAnp^zq8Lhc%s1(fhLHbn-I8!RI(i39}@a|IJ#GpTzdEJ$;PfrYwkgJKEnu$zOSMN z*>fDecO(%h{RcI<5E)`Ja9lxiQ}d7^kmK>Z`9a46)^CEo!eI{Z^}Va%1(!ngB310xB;Mu7aU1IsDPLi~_g4vn6QDiMD}^}A(e3ds zo(-IgFB6U~=Pp%tAY@qaP8UAReki%TlM=Sy{;z{PCScb;aS@$dkJXBW`y zb3jMJRh@7fD5#557R`T6z#6Eziv!d*t_mc+hhy+Vb?)gyM6hT^F~BpZ-)Z;ucm=|a zZm01^?R`<~hmEHgt3p7El}sa^9j<*05a{23ZWOmXngfB0eXe5}JZ`wh=;m-z$3vPm zwbJP)d;lfVv>@bxon86HxQzS`jA9j&1MJ z{mJ)oa4&$9GXkv_Vn?_-K(Xr_T zU22%VZ~;?wDvABx_~pQ_mP*TxN{lXvoQBxtqwZw&&2(h2Y@&ed*v!%b9dbEwI#Ny^ z%+-z_jd?84Hm71KBAAO8motDIKy;vnoNf19y9+b3c=ouE69Ip}7b-G#F|;J2>ad`C z(hyt`sMy(e4Oqy+;J%HFy3up9(F0 zvj`429jfUiDE- zCQUcdO_iWm)#*gX!$j|IqVU79Kw7ki?5l|^`=8KiBs95-{bnPkEqdw9A57K>@z?hl zuCwi=v;UndDI0vt@Vr-U7^pgYMRZrO4p;`c-^oNz@uI$1Y7-(fD_f_J4>#sCZVN?Q zVp8)MwcDw@*9w#j)4U^TahohC9vic4!QnZaNyF0E)wUzNJgo}45WrTM{HoHRGfu9< zu_-6_t+;O^X%4mNCwpR>LPLG&3fm(FjP!5UX5L-rZeeu{|K$@mf&uTs-oRS`b>`sJ z37AZhJZj1FBeul*mvogIZjUz2jd$Ai8}OA$n+de6g)_%>Zg zZdfUHOb^~wqanZd_p-4UWc3Bfh+EK_C+VK`X%;uO`3=vgzE>s0`p~k?vTmr&ylrf@k8}+~BSrvqV=@IU~#m!e>wo*{JWJ&s< z#PDkoqoHo6q1`PBtH*)lgHse`HbV!0NnV!VB9VomAGj5KWz|H@jOd<&5C{SA2%pEo zPeCYkoJz38v8Ozs< zf_p|yf2$%OoFl?iC68E6XlyE`GrHclQe6n?;H5$;nquOr<8)ulkLt5|)lH6g5E z5DP&>XiZf_-%1ZmoEZ&m6?-j*9BCtBK*abgjU0w`{gl_x*F`k!lOa%!wRc6)C5@v& zz_OBpt_zEQRJ-lWvUeq&y6<}#WQydfR5C-{Ts6qv21VwuQyCzCbA}V1xhhk*ZrB3V zQcMVuJfloA>F$6?Is>CoT9zAhKVd>|m865nVO|&erbe7bR8wu({DmyCza>m+4NL;N zGyByI$e-(ii>J1K`1pPI*()VTei}$AFi5{y2}$@@ChQ*Z^d{>1(SZzgvXjIY(e@@! z)O3LhK~sm!_FG-i1cgR@_#;ufG^+;I2;-Uhl6Jv#M!k&7zI-ykKmdgR+QLvfgQyIf zk)Pla5x-aKjzSQU0I!<3sZ$j!N$WeC%35B5iF*yT|M8Q|1nC*?L|hl!^myuxtQWx) ztwDBYVAU7X5k&CbMXqB;UVdo*33uZNeQS)=;j8E!*&B+s}zyeB!r#XXLf@?hiefQ zRS1-aAJ$9Y;P6$yvVT0i?_KgO1)*dsK^sis^akN^%?&X-EYy8xfWN=CQkQqA9Q|d zGZ_dYY~m*&lM~liQr#Xj_;DPm&s|8A`;L8TJePTBnd6Wo31mN|pw1d_a&l#WCYw5= zwq3&{(zSe8__bl3r4ti%B?_()WFo(dZX7=MDs6k+l+i4^5n2F>L)+6s0|BMRZzn#J z7fBV_x1TP$mqd4&8Wd$U-pPROdf3Wr?mdMxmZBP(T=J=Qq8D5S^ra%re;E(A+lCC9 zgk5f>ACefLz-weJ1@)3rDF`zpP9-Vn(9p_0T&W%hL-CtL6Zg?Al(j{s=F%%KU^b%9 zfI;44H3jdf303B8t#7Mitzx(q8H=BWZIaVn_V z`Bqs(L4)7kbzAgZ8vB?*OdWuft`W={<6T%X`v7KeoSEC3?+~Pu67{~vTM`ttDbb7@ zTNo*=F{NV6>em|^TfGg6UZ#90Ax>?Y@`OjX-c{#+BqT=`jc0p@&Ym&}VdIKmCd%{m z>vWDo#3mZO_1kcyK<|vYTbwxZs%<2shxc2~O#K{2_J8;xF|w*FHrI1glH(Ow*gd{e z>)|6Sx5QbN2#{H%Fw%In@;jt4Hk7nPEwg&z`R>*;&=FS5w&I#%Du$WwA8Y`uaxF`7 z0^4%e8svkXv*N@{J#-4SG9c-eWd8NkuqLnkj1lNc8b51#c&~YL;(|-G1_iM1t-l=> z6FEZr4yRWfs&k}=V>vw;vynxzSRIo8-R6#Xwj5BW!|mujan~JfwX$gJPeuZy4|gm@ z@8NI4$R%QN9*wtg{sie6mw5aHM|LzkFuH`&tfKs4hYxLm-AhrRtQz}8J5dz|JN_z5 z0b0*qShjaDQ;L%|nG|ke0b=5O4>?)d&~lpVYTNT`BC59V^-=}MwdAJmR7*BlL*Oege zI264A(h1DfwTVz|ncIP>J4=1EzEBZ#i;hW`ng<9yYi_jDV>Z8amV=`!P+yG*qw$qh zuFy3R#|QIMj{42e4c&E;h{dwo3k>s}k$W++w(l^d(WBlrs3 z;qwa&HFYlsm=p+#RLq*w%a4oLS@`~_VT7-8x3vcbskk^0!2+Q48oKfv2MfjY$U?HW zy<0tU*Ef}Va!KeVQb!xyuH_jp(-aBKWKF9CSSozSCk~~Slgd*IAeB~Qm0^LryVz9t z5y*?MrLIEo9i90m$)(qDZ{lM{g(n;IFNhjP!ahIEsdKfZ4wHHl+NY^0-OLA-L6oye z6|-puFqr)EH|r(zdKP(G*H0R71x@6Xh8D%t$Clm{V&a`{pG;58P8Jn?kG6o3jNhT9 z3-BvhTfY5j2q1Ig7A$vN42JBJf&jL;^}L)i8K}UV{g0XT+s!-QeZKQk|M-{J377=40(r{;ZG>+h~!u6H%*$g@5DtFzlBi z#b+mmj#1rIUN8DZlFgkaMmKWPvBOf9nm;-a2xO(vRd9sE14Q#juf8iKc?Lj>530j3 zV``xq9P0YQH%VFpkgna3L8eIc%;9a1IOO5r`=&df{NHXNN^MahrPo{T6Lu}f8wP7f zp4JRMzE1jhUN6c|O$zIrzOixcTA`0KgsG=kyUM6I8fZoO3jcWKZRIQREduja9qFX))HbtIe5^3H zX)=&He3aVzgV-GeE1UAc4AnKVNC-D`3-?OJ1BZ3g2fhjbM?4 z?4)ZyOgop|>4M4H=v0ckO(Vzj)(A7+&!pBHBkIL?{062Q>y&uvl%*b=MK^m(!DWI8 z6u&xA$It}a|WO6u6d!co)6-67%Tj0*TyzDQl9S>T$2N7~Gcgr4tvhz)> zgS?SyWvl&93~B)Q``es_eI>3}3-#HBA^Yi&MQ#;G0SN+mSkGcpX`$K~5e*-4pC8zy zB4nlEO7axSui%2V7e2@=|KjU{$C{z*T1ud)D^^?Jc(Rp%nmzi?$ntunm^x%^yio(ozssF| zfz_OAXOGjeiB@Q|g8AJ!k0_=oppD@^K8{9vI@LwKDsIEegs(C($*7G3v=74~ zPL(r<^QVOnhlJ=$d%EPNawo%#ZGSUjVOnYePF?ExroBgDeAi^!)%l5KMGh%SKw<$+ zb_sqD?8@^P$khmg$zdQ_GMXR4w+J08)yJBsu7}oq?%GRFd~Garjo`xIB0_l<6be$2 ztB7zrG*nK~FSTnQr?^@ZDR0qxR~tGTHc;BtR1yEB3f)G`EXc`@a!2`E0;O<0h_fbP z!`V%s&5i^^O(o&vIY5ECOEp2zVolL@hk|yMa4X0@EHQ@BV9atv>lhW&UC1(_1ShfL zw!EN~l0I~sD$=Pq+zv|k5a_P1;eDK6H~qe{!#g4lGhXNhF>xT27Rm{376cM$dFb|+K>h<=8 zfb3$~Y^;-MCX=v`%PuBa?_mCcF!@dS{wY3aiVua@uQVf0^2{U)mreAbi4NDP`_+35 z!c@lmn~ln|+~z})k}YxDo7QOJAuv}$jFx%i7Z68#5Bu75%<27608kHX`p?Pj=kG3d zD~mIWLEm5F^vu&5~ zP)gvzyWJMIJ}enQO0%V@NMxX=#MQ;Y{R^y!RcUQz}jrZmyMoHebr;4QBb-uL$U zU8rY++}C+O17AvUV@>i1K8OOPX5GxUCEY0g7w*h?5db%4tY@EyLT(cHEoI^F7=R3ZC+zdh5mvdby zJlX}Ea9e`vUC)tNu$y@-@Vfjn>8cAog_APxjbj~oERE<>k2xDfU2T>Y{g3OczEp;U zbUQ=0fXKJ`^KYtnPhVTjk#$ooD1fNb=*QclH(V&KTR>VoFd&Bo;*bLGXwczzMc$pN zj7Q_-$^~3sro!C)`yU`iYQJ%(aGS@3c@MmZeo2CxM&mO;ovChyF0bi258m00_B-?G zZjx1^$NxD^=a1=c!WCroek6H7p&Pbd>D&_SERc7gPao~n{d8!$pQprRxawz5LwJNa zrF$50TR;m*Jwnq5fH3a-xV=K^mp*(Lp;7^@ehdUVWNrUo3=ykZ#@T)EzocXdv%tRA z&lE~evu5Z}Ig~olvRHv`VG!YjnR&OyR~fcqF+O#KlwaykL$XK&zO96W-w?suaXUcx zJ!Y2*whk6^)vqU8S|WyCt`K>&P2VpDy4es_amr7;ax5GS7JrWZ^%-;aA?&7H2dI#_ zL>kMS*N+QlZ!D$*6*2>8R&xKp7L*$Qgq4_!-mR0aQu2E*8E{ zKT38T(li*2c-{T_jc+6nt$O_3D$!@_a2EdB0OgPfN{I!U z3=n9et>X|Dyx;H)PB9;o<(%v1R|za6hG0K|xy=e9aH} z>)*|-|Ak}wP2b+w#>&{_AB^o^qOAa($Ol9F-w9f^{{Ybb&-|>@{|wOnp&$Php#5YX zKO*-h9{-O4+K&PMj{q&(KMcu#18CX)rX>FcX#Z6FOsD1_@RjugDr2Q*{|lgH|L{UT zoK8j#27D%lzkJTW#LrKG^Dkxe)4Ke0I~mzO8~)Efe_sD+^A9BZ;d(N$G5piXWM}@c zLO-^Bnw$UhKmP+j`?p*Ax3BrXTmIS42k`b;=kN0Ab^ZZpKlbwnj-~&EZ<+u6{^@tJ zeI$#WiSeTkf0?Lkj30GB#{ThX*2ne_c$WRMt&cW7mmfza3*$$eK4S96A^k8;|9Gr_ z0Mh@1K>MfTEFS{xM~6Olz|8gmkbVU442`pMhs*|9I_VJIhB$Sm{3k z_rW_eaj@VsGcw~deRh)mh1s|GhxV@QIp!42vIhM1ZX)v2JojdAC=e{|2hgj1MwHQ`|o-ByZUFh{;2sQpX%eEi?xZ z`yq+bFn(M?e0cJo*D_51pRi{c{(o)HHmWr3bZW90c!{pOO3FH52Bg;CFAjPSmL!~8 z40A(_{7ChEW7wrpAK0kw}fS7vz-`tD3qNJsMA&XE25SXvoaG9NY$G)VG_LQ*<=&Rd zl+=PFXK{~qvckI)49}HBSw8dIsLb8!fqs2gXbV2?~dp8Gab-F9N5+Qfoi-?whgx*EQ5x0f0sJi^eQ8T50U z?@a9yohD^qt!7bE+_#Q?z_Zc3&Os+%kZJr?1*nxW0YAm>6|9>_GOvPcW7(4=_U<+R zP7LAHjXb$5sXZdtwIElVRE;rNnycJrdzvtM6g)-+bA?IQf9h7*vE6B zn;_H%c!9qRm^A_dns+a5MV86hzBrHpXMu&6hl7vvhlE z8;$#iG7e&D1y~Ia%Mv#XR|ZJ=IitFCRn-mTEq7^bnE&b$O$?I1#G#xrEaZonrAj2N z`eCHVqe$d6M;Xz+$*h1R(_ULw!+>n#G|b%Or$)CN*hYfbQl4msea~ZU;G{iUs673s z!()ihH`|)T1r9UOKZIi@3}m=f2hkqIHS1LXHOp3lE0z_m!Cwv4(~unKRSo3XVtUwt zCXC2A)O8~<@c8CtC zuuRJBtWWK`R}J!XHbACYeqZ|GG>W4?#gGB6#>HqmMBH>ll!IcDOcp=0i? zm|ujN%^5V`QFZStw8&ZVYz&}kWSBHFaQaPd-@(E_32h4xPj<|EjSIlE zBZi1#__lHk>V;+_XcO!@_66Tx_j>>=#-WeUNP| zOA}I*bbToK0{uadRHPSdSZZ;xKu3=uqFkX@=gfJm$1^J(*myRXFp8pwZ$2Y2;)R#!h%r;z+lxJS|2}We^YNh6phY7~D7Va8^ulnG`!t3?Z?RDt z;}l$SJ(#iQu}1{wl%vYT%4U+OUZAalVMvWJ8uQXzU?oQZlj0>#b#7!DujDD+% zC7MGAboYa;hDZ6EW*}iqM@+3-J!^@d6;I8M3WiL8N&L%x`?{j z26z4TFfm$XWT+YOmNwVEmJuohju){TtN#M`yDl=~&!{5?i=UQ7d|dIvW2o8$qzZ@y zE+J3Hp62AGq=An~tdSt-!thdZ5HLI^bW3yWCiG%6Z;@ch>1L|0+dBc9u8LbY+p7oT zg6^z{7zHpaB%BM(;7lz9E6Y4Zc+)ZRyo!Unf?Ji;b%H70QB;I#M$?VcZ{=E>sgNoH z65z?4o-ZPrucEm`YO;Z~flGd9Q+BH2s^Ffh)UgC!3Bqy74+}T-KH@*q;`|heX>Kr! zZ4vME#x|W6cX;;E+RH+-Z1fm>5<-~=gvBCbokfT=W1p`ooj|d-AQAJjF5BrkUiuQl zqqZ|?_M)6C=p#0)l@~141|XM($iA41jaLh^y*kLoiH=FL?Y~RF=eK;t3~#!Y^!2&i z`0fQ%V#elL>g&q4qi0cjabfF&`^ZfWyI^wvW><31f<3YfP^E}EwE4=L+}2gFYb9?V zkXg*qp|~1AfY4xagB%jwtN0jle@RtL_@bsHg=@#dwy+WwZ`YkuZK9 znO%)2TQp|2UY{^Ui826bwzbD$gVoxzk-iIPuPrh=K9X(shq2$&K!(>ME0;Gl{o60>a|hvRf0gR{r)RA!Kxr!ROXQ4mrg|P?7s4fp`izYA)(`>z0b(w< zU!;7UGW9(R20zNk7^o~~Co4>qPfO}0_M-;t-nSAXq*gGr+ksR)*#+HXv2pvJE>_?a z=bL1kgsHu4Dvxh%od}HIT8izc3-iH)p##>$GYp%27 zY!e`ny!LfasGT0yw)s^f!>N+FZmdPD_od@I0*4p5CV;>7R+E9{xM}3!#6Vr4nZMVcva5Lc zqr6vk}^78L88 z&HXVqv}`V6N<2F3VHzp=o7f0cKep9-R8bRyzEZFUrfC+}0#8%sL(&!;MI&CU{#Aqo z|07?16O&CL)X#xyJlX9k=1?f2s{-XjDVU49n;y^a$%{9AJr>JN4TrpOX713;b6hFJ zw@~VuClG>Uduf(QH@Q*2cWqb>38#)YJ zDr$mW$Rqc^yIm3LLLs_5*k4x&F6-OxKUBwymreAisxk!BB(mx>$W5mm9A+XPnTV&6 ze`ASJq(8N%52D(cd0fl$=RnIg$QS}z?=#wH8j^=m5O1f#l#3IG+M)_?<(u9?+8Nk; z$}_*cqk6=uR;Fst&gjUXNlRS>Og`{CT+7{hIxCCT6VLt9V)4;*C5@0JrvFkhEc?Ep zdBv-WBBKe`@MW9s0d80`uRqv|%cg~4ohNp_7Bpg94}LH`(o<*+a}o7kgWAxyFMjfO zWrSj5=B+S3UVd7=qNPFj<1b;Sx^W#=0X7t>l|*mqZ4G6ai zN}l*obF96R(YhqyGsgKT_s0s98jgkab-W&X=kTp~n>EmmZ9F~ko``Vt{p!Nz1j0Qr zF(IQG-@3Cf+J?!>AW0#fs;&>ZRKyQ)(fZR16~QF_E-Xu;uS7Q-sJW!Yj-V^#2Zv`7 zt>eexD^LiIejjrJ(u#S*OQH1T6+p9&oLF_-k;tnX2(B~3yW6hmqn2moVBh5rryb$1WcT9R4>%BhaQASzsuMrRL=Kfnw!FT zJ$1dqMU9}C(Bj1|fo8uO4wTGpUN=y~bI;&H`!}2NK^X?KB}yobOSJ=7J($TI|GGW~ zF*wkBsPKEs7N0}i2~OL+Asu7Ty219rwnj3t{R+I5J%SPHjVreW@&o*+A^-8i0Ws%k zpKcyzX)L}Mq(FF1Pf&9k8P_t2qNpCGwP)>T-i}+|MUth;<}=z6o$4O=hvQ+8>wuxa z1xptZ0mk?U#OwTG=S{Mny*A>ROFHN}*EaKp}Tfw%n^>7a#4X z4zSiPn{uXmq_R~=XyMD8HIdy+DTEgp7uH~k--fmL+Rm00pns|<5?crn!uoyz&y~-g ziMQC$jVr-kA4ANlP|<3I$ovJJxq7z&2c_!*d{Fl+?50XLtXEFvDYgo7;FO7*%`a`m zHuK{B+5=}83!0JM)&0iKX~B$Y+*M!6RG+Z~;6%Nnw;;(Lowl$x7Ff9g!w0;Gx??~SO9Ez9x+)Gn?;~)Yay`BMLZ!@RcvqScw ztFYOf$0%#wghq@pY_> zFO7`cAi>r3R=LXNe#pQpwW1s6Q8RzoNDuIM7FVKxFD^9yQJ?O5{!9IcfBG! za;qTrK^02($QM_2G!+Yr-R^s|DLf`50a1lnQoe+CZXf3`psRjWuCW{j*50VtkgY5uoVavRTM~wVEG35F`r5-7}l!Kezfe!d+<3n&eA4%RiYOCmw!_;s4s}wQtKHWQ^tW_1w5DA<2Cf*@JcK0Fng3~ ztx;zI7Wi+7r|D*P^uZ=+k;y*%+P7FEj?+Jk8e2o`6`m4i=0zw~qCN%zhwOK?vmP%q)r~j`+fdc|gS*Eis6@Q(sJLe>X~fBH9|+T;#OJ z1&e)9i_d36!($=mKaOQamibF{;qbE4{~Cy{#(1(;9V)Ddu`l@N9Rr>8@&;lK+;-aAbvz1=FexTHpRNQ$k=FL_&dvX46Bn9Tgst(~?# znOLI|M{by5Ulhd=&aq)Y)%j?Vfs2g@?>(;ob5wgqza6Q^5F>vxW$MzdS|;kBnk|w6MmC86=J2{NJ}!F}|5LlbO&>;bH>U8X z(KI^k;vuPPJqK399)1p0$xSG}27ELVP$2sO@uoWi;+D)zWxg5 zHRw}r-q+c$LcpDkQ^2n$0e*hfXMz{BTJ*2Mff<>adQng}M2bN3&AdfGBri%-9e;;* zs3P*?e=~Y}tx}10)10mU9mlPMiwdQQH`z$3!?-j=xk>s!UzP=z1rj% zx@OI=s%r?RD;;)pu~W%ZJzSw!?FD?B`IW$-**=Vj%Rmffv7<|0Tk2g!WL0%1e6YXB zQbj~YMSAiSha#jNMU1=ABO0hl{~(n+E>9G=nsnXd9^2+?3fQ#La5W|(f^+Z4ji29u zU9vv3Zi@7uQZnq$e<-LW=T~szY@8?IovSfk?%4ui-_l`jHHu3n;!h=w)MW zT>5o-SCaRJu5CGt4&abq-SdVZhK~MCNZl$#7kqKCavs$QGB3Wp3k$mff5)~+PMQ4y}_ zFnfg@L1c$+W9Z|yJN&e;LzUI0LK>J-v8JYq|M2pVKL2t7FKz#;^D^CVD#U~4qTeX( zEL2#o*k9ONL{@AG>8FH;%f(>K&#+Hl_m{s|#S)eQwfY|W>zC4wS<*1vVC)so&AI1X ze9rcYU5*~v0;=;Cp>e!)bkON1?@i%=2n$jms)3y1Kh{e}_Sl^MSz4(tOWGv4p<`&uSEx9TZa=#nY0xz=iQE2_VBM5?Pxe?gY_etqF z;nb(CxghNR0?USML+`ChHj(uk7Ydf+s_c@K0Dmgr~(rrtc~@w2@>>sT2<=UJ!9 ze7&t%w?RyV$HQrA*gR_BiFgJ4eP5CND9RYkkQ2Uq{hxGxyx0Kl@?v|hR4A)_TNn6L z9_bv*c5%14>(xBORU-%uEE@L7Kr1aCoHXWj8g__jH{-!0=oYc{f65{hj z;usv3G4<)Ku?veV+iC-+k{h{u_%r-Gb`IcmpckkI3>Mblif=Z~7v-z_%@BA~VJx$I zJ0QmfkVukjD53FXd@<9rn&#!f zs(zRR$OrPKac;P2OE_eX-8{vV7j<}ovGDz6yIk{+n*laZBUrl6i4ZUCKWND8`({Fl ziPpDbnH*!#RE(NLmC^<+q1bg4TF#_46cAnN{$6e|jHBD@BR*ARi2HU?c>&9K1^TCJ z{qEIcP5HL|=N-4DhJ(1q_<@QjzjC(lcb$Jp)U`P1()`V)_$f24LbEn4KIMHoviqT3 z0^RVSJhAB^nv4qN&I`mATE@^zoNsz+Ee=(SsExUlWu%Jzk#Q;464ci@P%<2_N!xoPVuV%$b<^c%!y zxg#)F|PC!E{Fk;_fJ8YRDZ6&lXqJ%W*`+X}vuQ7>}k*0nK_b>#h z3nz2h7Q$w7=Y0Ho;1=Zj{k`I2ePRIlKME-;y9VS>)r0i;e=L&)aoetLm zh1rdAAQ+m73I>USC3tzTzm1tr3aA0kZSa(B+Gog8&pu3cGd+K~AmeMLH{<_g+UWR>3dbp*< zqPuj?8zPo8_RqQMu6cpn_{1m)KM<4~qHFCITJdi2x-4CZ4+y*Kt;kA#0K_z21eP?_ z*doB77fY>T+w09YS;@s~+G1skZn@1?5v3H)lprx0lNRy0a!Si4S=T{7aSs=T_k? zYMpM|$xKy>MT9?1dk8XcE(v7(*|EYd`FL<`fu;7gZNm?{SEP;@s9mLTLPSdwvM{Mp z+xZZsM>@HO&-M>1;p7{O&CN&McNgo&kKz-j#t;-HUj32=-Gt2wM#+RchXQZWr0a=5 zYdn4_+!NO!CJc{KjusLN8%XOt7zz?;!c!+JF;vZlw_%p!P)UtmJcx(Ub-#$$;rRbI z&dVI}qs2*XZKN>>lUlbC-eh}oqX93M&}6onoeX>C>0eND)q*8LU=E^MHUS)^q&9qC zi_D(igE#l<^{+BwFwEGiSO!)L?gu2}U)aE0EttOEy(c&6399@*XF`R=_QH>0xoA5g7t;Cpx641}p$@J@vJi~n49of(0I0Og zjXIVkNZj8)EB~~cOE>uOcbif{zujH!29qsZ3&UuxU~=qB$q5=fX73zU%^C-|%P8$a z?b;K5T>}ul18E^0pS{C05TAh`dc!(_lz*C*cz6ZRQgx5B=-Sqc<1E-rQndxHED#zBB5l1%GJF} z1yoy?Pem-p{tTmA7L{Luo>8Hpoc<~{TN0BL)=2fO)jTo;v9cxeLqL~+DZ<#l3BX=G z8=pkE=?2F`=T|KO(i;y-_-SsiIs;JT%hYY4;Nh;Wuy3>=0^=oTyHM#f1?;|Xf4;~) zokZkeO;imr?_Kw8u z%(k<(1Q9ro*ZBE31cA?Ke&z0i0iv!K-MA`4Vd1v5EE~%SE)HHgj&J5NhvKsyn*01%?z1_ zl`_<@aXW8}USpS1FJV}?PNMD|IP&UPU9%8YiXF;E+&CF~OinX*SCJ>*OrF2}w8Dm# z3T#H^sHmLBrj8i0Z|2*79J($b`4MIBNg4C17j$i*W-7q93N}ieCG?I6&on$?cK8y; z-Y}8#rsjn}KHEU8HN~^3kVUyMK&w`>%c#$XCr72dKB4n{nC}Wck4GFlG_A(IeERti zU(#7yep>0iST?P#N~vGc6sO?8v_3q1A#QF9n9h^vxT6$zkLH!tNB#V>v zPiAWCrfXP`Wd(S)n)u#D)KG_~PTq>(#vEFVNaoPrxNEwduwn5Kus8|e_23|8RQvjS zQ0PVaiavuv=3l+@e1`D08Md^S)1Hw-U#<=ahe95)c)IwvRL58(<+7WzVF6bVA>Z~#LfeFw*FE#k+RA3KVAu7bDc`3CG>Ura{>#UIQsC%;)? z9_ynz-3J5FN%f(q@Hkt3jdQm?VAV)~3Jm!iGAeQJ86jU#W51^mTj*EYeTpqwef9t{ zYD=_}j+a@mz@bxm94RubviH*JExa^;Sz(lF-%@?rI#DWSx|Dynei~ucpeH)2=W6_M z^%AUed5o55W7q<`|Dsn06_xuZ$+2-$burTU6!6I}2yg{Rn{F;2wC|Y40k!Ft|IXfX zsG??KYh8e%3D`s=s+ii0$ceA1IfR~0%;<3~q_OmJwL)VHQB_oMDdv%PhCs?cs_n$L zo~HS77(kp>aPOKfgMvyJ(us$=pjY}ztd&}{GnjiKl`>{wAhJYMsQu#Qi6tN%TX(t! z5Z6;qNWd8HfZ?}jPqAEbUOf9a5YM}v72b_OPbD=t#o*9qDjS!T-<4YO@BNlaxb6ej zqbm`59e-H+b;6iYv#`0)CNyYO%KwK3ny3*n*#czdo_q*2-v5b4E=D}7{io&9bxct1 z%f?-m0o3;Vgaho7%`4(m$dBT#hyvyMNEIb8Y>Co|pj-q9RBk&C&UjB_J~3hX?fY69 z7_x82{Do)c?V17HM86aJZLg^mfj7(exa2Pd7f}hDHHfA#@-6Zf0cw0|NcE$CH<_1GV;|V0F$)rh5;O~5R!DXo`6bL z;v+kQA#gt)6*sv8JH?p&3m_u) z^sy`LX@l35*np%Q^jm>VoBWJhX%622^ZrVE6Z1D)&nWjQ#L6zeratpU*3s?oyu%&* z!=lAs>?;N&ky-zdBB!c&Q$@>@l^{o#n_B4M@T2NDRTva`dxSCy5T#HDnl0{u#lI^I z&tqQ${I->aRs1T@?pThst)&G-<Ji?B($W*9xMhqr*cTrWl+w@)7lsRsUx&dZ zL90s`b2dD+%7s_dsqWg`i-F8B1jGs*$$jKjoXv4xEjeG<$`wBF71L?-{G$-_Z(M zh0-_@(LE8cc(YbM;^15LF$&P@erQ86nbbenUqfq?105T4y%#@&!s7FN zJz`g}3GEdkLD^`}&-2U+1tLPdR9b82Xe)cs_uxB`L1f!w^IEo|)mh8ml$$QnMCFKi#(4`CHRGy|Fc|8vyZCo ztsh!Ed(Txk-*5^z9T3*x`Axwr4&I-n$D`R*F&wEMJIyQ#_uK;LJWlXHgszfU+-9Gv z6XBe+amXY3>)-m<<7P1 zC*@V9K)U2h>wMMLmV6a}=_&B{122{Gb)wK@3N~&Xrcicvrse(aDAW_GGmrsOsB38V zd=?9~M{fsmf!fH{M;D|#o4|=MYi6c&6+fsy+sZxBxLDzG2#80Ri^qbSvtLT`+22Ot z<+B>xsQ$A9O8CGBihz|_-*vC8_rD7UdC5V;ErjiMoQ$rLS1Y8jRV)gx8nuXD5?10r zqcXC^78=eX9Ey~ZIGKMB(4V+v?WEqZ197UUYK}w@ZtooF*ZBoiw!qA&f5{5hh#PqI zYU$KT@7mU;(QjnK&xF!&Ee`g6EL{^58N#rOpM}af0zpA7%JEqN0b>GfU-$RJPT1!V zvY))H2o6X4)RAIrBDh3j0jq-M>5*88`}Pxy`OWJO02(>k0rPRP!;@bD%M0L^Ltv#EEM>PjY2J z|976mQiPZy93Dvam5_T>*!J;A_p)?7w+e)91sUbE`10h<0Nx1r7T{; zny#fe-~-_6(kDF|NbDnseevD{0(AKc32{Q#F*dceCUTq!wFK~TxL%GzqlKy&N*qyg z=Frzq^e~Y`G9Pw8f_=RcgxlpnK(zYh_k7otMabAEH=z91$0Br2Uej{vODL9pM{VFa z+?tKRj2_&+B2WxU5@wAU7L_cy#~l}0*4tZ_fpqlAhShjgb!ROgkkJdEa^I=oXxl^2 zq^Bk#)%=g1FEaFEvV?Dph;Lq7{CuDbU_KxOtZj(-I)Rs=+6^&yILuW8~Vip+@~Sr1djcB;<5* z8R2vVIr>DhMfPQYi;OWxcxx$mtfj}}8pFDG{>WAJfe#A#NOOn;9nPkLDaz$|wfBJY zm=OU_HQu@>;>#1Gm2zkT?M#^ojH8pxLyGAgCF}s$>yJ5>j`P3(R``E(DlCa1C^Ext z*tEnG>0YR|-8vO;$sQ+l9^bn@i*l6I0rXA&8pE!>u$gV{EoUaVM4Oy)M5{cq7Nx>{ zWh_C;AO82LLzMkdd2@$JRDaVp@xxD!!cUgVX=}0q?zxPcV}Q!#=UwwVn=Fy!vV)(} z@KxzXZ7yhk)w!Q{nTq?Jn}*-rFa`6jQYIF&`$1isI?^=&SXnuK7}_v*_aVE?Cd;&X zu_Z7Y5)&ahyJ(U`@<{M*0&n#6AL*&Uxta`u7&xp#Qs*wT2tc69HX>6YFq+YRIHIRU za7Hep2{ViVFOW>g%JL*ti_pe6OezQkw|Qu|t{ckUYY-Xn@NRWnb~1Tw35r|?Vx?!g zNwA|$&v{$L6-G};5%L(xhkc^pdU5So7Hf>y%7h?Rx#l9r6hLSO7PNU5hew&I{oP;C zSM96E=N|d(Ms|hPa)%ES?1YcbmQT-$5adqfEbg48FVO1;h>O1Q)?F{^XdywfaK|If z^z5FKRtm+*<_u0VZiGN(r)fE0q>anReipc+2x=VCbBf+n=Kylr1{6NTdx(KL;WhaKIUPMBH2w%&wj)FX64{u@;EJQr3)PQzyd z2(2=kF|_BrNybO++-B*ECvE`$(2j}e)8;TAjhz105Z?VFWugCTu<}vtm%ySf&}~fE zgwQv&|E}^c)oU{Ory0q2>}H0W+#a$zMHx5$6Ro0$D1cXh7F`q|;BqyKikHJ7<^n}v) zG0DlaEFtS1o1~6kmBj4dGV%wqUZVT$hVIyqPUU~V9W|V>w{(s*kiN^s2-NGVM{X*Y z|6lKm_Kjg?WgSP31n?vfjT>nXoth?Ht<(eK$@bQZE>YX+BO~Zhk^XrgWUfpv1+4fB;Dg!{XhedZk^W-wrQ3J=??(`{nQ(WoJs_hb(A_9P6_0tYD(OW}v zyH)Axd0jte?rh&WVT|SoIi4sl4!v`G(1jwL*T#f)9!VB@fA{%1y_Itc>(Epj&O zW-l*@lZdBm!3Dg}63-6z@H8^^uwr-E(rU~ZuO}j2{Cn{>$n5Lds*(I_2i8=sbf@^S z98K~LRL_YN>+@mL+;2Leo`lCf_-hF)DG16jUzMS#p)_ZC%u_A8#j3~cKM;u;p!&aP z63r?`^${JZTN-8a7Bj_vX%jire}yKTmxfYYStSk$pmHg2HKobbE)|0m+2z4to&w+; z<3v-}w*yc986+@cTXf2ZkZ9c-{V~317I`*)Y?p@_1Dh3Cr4+h6v<`!Z!VW{G5ALJP zJrSjCoPYM9*aE|5>~NxM1yi;&fU7@LHFc1+g3gx1Qg^i=35MO90=1vByE%AsDe)mC zR*wVs4gqzzeD1y($lP2+C%2@3F$R)ojr1osJC+ors8(crGC-rTUdbhMS&|p^iM9j; zCL$bRQ8U>ifkOsJgmd0evE&zx8~RJc6tkjekwPydT#{`)MA3@n-Lvn*wfGYi$Nbz^ z+qIH=<#TO^Zi8wbU?U4wMuy&*Zl$VfOp`&e> z(fVPnikjBP+y<~T(C=LWKrWVCGa?er1}bZoc)@>W=jE|jz^QZ-RQN2>6=>5GTT;n} za~YGl`xqU(__6h>5>8Dn_^4nrPh|WW3~_5!nv?ltE(iw)ELYKpEcJo&(W6Ik<7Wlw zBk$Y^!J+slvLd*pX#9~AoyQeKSd+EKkW>_BWx7RKb7b4FS_q`-$=5Zh>eR*x=tvJ% z`jOJY0*}^CY_;#`f#+4$EA(GC5A)ORg&C9aw7n87e7_PSme2qt*h)8hww3C*I)t9I zK+JVXZ*1h+yBzG~75z~)xuC{bQ{ycCs>gN;MBcH`FhR4MMF{#B%(*?^Hv|=9Y+N5h zboekYxV7B;F44KOR-?S}g3BN27*?it@=yMOB+<+lNn=68>kEQ@t)7*kuZexf(-^B@ z#Ixv)f^wFVfjQaJ^FpkYpMU}t&Ls{^+hiyE!BBVMe79KbYDu|SdA)MC)$m}^r&6|S z2Q@C))yOtI47>(OmttCFhlky8nj@M(zPj+=MO`&}yS6H>kXD?hGv>pS^nl>GlF^u@ zSA?yQgm6)dwJMR)K6Z(=NXYpYDmq4JNB*whuDC7^=NOjCZ9_f=Oz~)`#)`db#C}Cg zk};XQ;Tr21!3nprv=C505d0_(t0@?Chy~sq03`G((9&zJ==3yMIrDhRV^srG14bME zoag49_e-=zDU4Nnfc0gM@Q%;~ZJZi2t}5!L-0-ErVmK4>%K!=r5{o0>93tqmB7w69 zibVorTdQ54vw?EDj?ORz!W#KIP0U)M9rI=IB?Ju7Fg$@s5hP-&&u5-rEaw%sW$v&# zf8?Rw7(+@(>4OQeNh)-WJ^!$lTYxHFbKh_U6ek8S3a@T!U_1(&0OuQ!4yqsw8@UGz z{8~Uj%Soei=0|kN*nQR-^@<6wg{ibufcm4)hZD8MZsD|#z;@!P*@?zF%M>GduB>MJ zHfR1qARw!aWKTV?1t9-MS9cZTM5V0GM5JvB{rA9YM! zqQ9-^N!o=HO%ZxmxI}mQDl@?AL9vU}Z2mWW&{W0=<7TldiZ%*jSzI^Cz(BD{j()GR zS?#c#8zTl-3;HLpz(lDRTlsu!QlQYCxpQ|qqQ~!q|tCWdMOG|(Xnpnfs9^u^eJvI-tS%- zioMcPrJ)L}G|B1Ga=z69YNZ(~-QEk#bgsgaByGjkz~%iGRUp#|?q(|>ow+JLvX(gNwr3??JuG)HuP1JAB8I9PCHX4+pe!UtP-tuyh5gsSKZTK? zELr>=)$pgnt^4(`0-r6IzR9Nh#lJV7ii<%P_!`2C1iwA3kFKs&i+Q}SuSd@|h5%?j zQM^qBR%3GdaFC1}Z7;XTp5(*fF%9pmZ4;@Q{{R~;;!Yta1 z__({h@y-(6nO?o}(}^@Yrnv*icOUUA{|ec;SbwA-lxp4n4EC2nfN6sH zmtHFZzOXfJyY&MrXJCVo=4TS})nIdrMhrEjnb1DMxIKNaJ&M*`N{qkUAdr|xd?4=U z2Bo0Y{!Ch~L1wqtVT%^rVkcdXFtQksoUtu}t?u!mILH^81v_Srqx>eZ@R98!A~d&H zLjK%yROKmIYr0Wm(>#MHFKZWQnNhb)>ZkTWC8SxIh`-_N9+PiYv2$lzknFq2z0Mz!}N{FnzeJ@3zV5s{IGBz`gc!PR1zRgw2+&rdye}G5u*~0}uq` zoR$d%a|I@{54B&v7X>vPJ-QF!@4q#W0d5WrOPhXs{{fplg5Om|T9Mfez^o)Ch z&wd^WT(NO){8`_KBUPP4mpxNle9iIPoe~ju>rVuB<5xGz7u@)1~P1-b1QNAHa#!!#}`RAY% zkRdn6Nw{9VCqrp9Ostyqi3=LcMknC}z?LBc&QFly$xO^dql~XJ>jR!^9HIBNdEmfN zk(kj2O}_&K40RMTZfb+cQS)euF z2mmnkw4wxjWNC(_mdf>)cmE(f20TTY1_C{U!rS|_?b3SPMd|t^EmQ6 zA~EKT?z{>56Jny4NB99WlJTdjZ5 zb()g%+8e>kH>7Y`qfMIy=(f4fY;ytCAmot<}^rn(ErLp_@pj@;|WiN%hr7#X8a;ON0W+?3x(jj1s-LTj3=YB|Mm_)!AROmQ-}opjmuz`-*vR% zBo3b(ObPT%BwinTI8^=^O`-478-!5%x;Pg*{UXS5RPt}5s5vPAexh*!ojKXyZFj;g zo!Gvy>IG~dxOr*?lXkx%9mnP@g&;O28~7@E^^gZ|37YPT7M;fI+g`XeUyFZzG%AdC z@;YD~~gC%g)vDWq8!$+D`UK>u?$&I=>Gv@0n<< z7g3=`QJu0DDO&ixJx%P!5qW;Xlks)CRE|lArGO+Rf{j;xRGhtGu`|6G(qD?dw#=o; z0NLqqi`g%aw`mA6`2bc#>>PPi29K%?Hq*NY1Ri33+P~D}2?N<-bLZ3;B{O3f+5q$n z?cXd`0I4brQLX?ChLEL(hFKVCC6^Invs9L(C}5~UIK$ika>Qj*i~zd|wi>1peP%v1 z<)>bG_vul>uu4tx6G_P7(wa=>Kp^D(yV5JHMD1!NO#t;@T=qa<@%9tXY30z&$b7%& zzSie)UfNxEgzDnE^N1+x5iLfL!aN5+m0+^CbA1EDu?l;Fx3mtge+2Q&7?ntPa#&m! zG)y>2R#LDA{XwgKBmODxdL&sC)s&P~Ly)0#3Sl@AqS|{8=lOaI0fi3^Z(IsyE0Cni z9h;~RO7%=e5ka5_a4$-E+JIuPCqyYu{F(+!heU_&-8-=GBqJFF(QUkEPF4}G)09 zum}7W@d;yr%KC(MGT&xh3Y3e^JPP-S)1`EP&$e31_lL+rqFoN!iS~{Bp}fVNiUl*E zw+_Kk89gbgZU#?s{e_lvOUO~`J*M5g*lB}j)3Mzf*qvOT zVP42Erjz>+(9%e^B=}j!7ge^(V?|gn30(N;_NchqJ5!}X$)`6wIz;Tnw&#gCdS`ty z-tC*awxZIk*)Gj9LBxi3G%Or{5VCkKch$FbibMI2O*d$2Qu&bPHR5Mt1*6xLx6m{Z zDiKzdC>@Qp<`R>s75AW!MR~?lC=ka$WbXniRgRzCR?&Vwu&Ao^cjpD>hyqz-GbSab z34w6SSgRK8dI9Q8wL)fuA#M!$``| znF;Pv&)MBo3l$5(JXXUzKeLNAn0VHtYpY6q&U|VB2@01w#YN)t#P-31i~at(ohvpg z%oj~S>mdA45hbqZ@doHs>H!;KdwP$q$o6(!;d$AT|NQr|)^tq#kFJ0&=j8(Ar_NsP zL?y%y)i zZEc)gy^C?<*EOApAA0=H-uUWjj@*)qvhM&`hr|j~) z%uiA0ctzNfSd9lv3g6sk_`FjG)2)nkCNB2HHd~v6WRluU_avXji=uPFAF|$=-7Fmh z%fa)IoHliU+8n%!OJJr}_QEU}o8!E|;uOpxRdAz*Shr0j9$vXJ{ zup`xqNgBBzmg{=*XD%leKa88N?7VX5mduypX1=7IMZh?;AZK1X%iP)NqQA5xLLSxx zcpj|x+458OWo|%>-HN{+GT6CfDxmJQoQsEj{^~+e0iB(*=N6uB<_`>|R4NFd@(c`( zQF<`HX4)j4kvK(u>qUz~sltXAJu(N4A8|A)mtZmzoG6C6f^7(a=KGalAIUDf$NgJH zoj6QS60n|ljE*9R>?h}Pp13KM9Vrnuv@HHsuG-nx&bm39O-imk&$k;2LM*@15crRC z??-1%@j8aJO@(TjyV>Bq3OEpF53^McR)eacL|;{e>1UWAONx0L+XNv-{x%S)zT|bt z$KeYmH9kA4Yvwg<`rQHLNV`~0hV;RJo~3%Do56?j6+`=ucWOV_ZpcQz-z&GxGFRy6 z%VAdryDaN?P@=)j^0P9e21r? zvr6fhM}9)pYm=e=(U39=03lw(O$*v0c|<`Y~wIwJ^@8 zt4lfdya4OJ;|LB^qaz>PKrMYe6&;CNx_e-Nhhh(wB-1$8veW8^oYNohG9z*HeasFm znT=m8_Vf1(tMA^dkkVR;=-0!{P_|i>Bk`#3vjgxEs%IG?nf_+YP)0$&a33yFe}AR& z>A`~pPpPr4CWaQLl)FH;Incz#vCzxSNiVyHhVLA)@;BtrktD_C*_rP*{yI zd7y^zN!}qi-Cs3W64Lzi39Na!@ACcN1r)X+xFC_!3ql|)rg-(<%;BE%I`G1j*P?)) zyj*=i(0J(O$V+(Zs%<%9^_@6)gg41_0b*_SIW-!|x8Lr{?9rhu__T~uE?va;Q*5cF za1p??4jGe4!lQVV{gNplmeZOPpxYf5XIRQ!Gv|}^oihBBnfy+ng`WiW z?Hd4C}@5&BCVS+{UREL zvGw)`B5OTiDta;z8PdRMk+C{y_S`G;GK@s}br*){qn=RDjB;y$c@HCUYneb%L^4nk zZSa3?m+Xx~{WBJWrzbexZFK!;?Zm=igz;z#ws!GD1OjA4FENO;WciFpKDKoOgO{4n zUaleQo2?i4-Mo>zDOFsq?R}8^KT{_N>geVp_3d&4dr6E69Gwii`iyWqg!S*>!kCS) zIU<4%bB7Q2G6Tx(HY23=YP+851lk!H$|NTPmLo!*ZSl0z^WG*WMw)<4xGqHr@wKny-bkg60s-!*zkM8#h zq`YMLMnXi?$?^5@06=k;CWQ*IG!$LTl%T%-rI#OMor|+K6c47;9MPmC+Chw0yN&>l>9f5x5S zgbfUPD2H~A6`+u;1mE<2$R+LdaQ$D`W+(+L@FFA>-?rYo7d1!Mhl*Z)xA!o+) ze8SJ-auiW=ZWS?758l=$k}NN>B`KqUQ$j&#R8eDHEXpv&0nm6uunCZ&^Ts#1H^5v% zqOUOSHWdzD5gj{BUoGS|li2*p_9x_$cze5<9O3A4|Gn5w+B!QxR4`v%m^S zT4VhGR7+fArf}x>d@4Rm@zLH15q9uKhcjw0jMzG7-mZ)bS%uL)%Ep(zr56T_OA2oo zIHU#R2WLx@SNCuu$q;maZG0NU>#D`CJvnV|WJO8*DX^+1SObEpwr0oA(rl+()r-Y7 z+Y}mq9Htj6-zMdqznN1wGYJ7@z)E1D9Z_YyMc*E~O}R!zuG;WoRLYhZ^rPMh`fDBN zmzHw+f64vX=n^`Tu%k^HC$UQBNVEppU=OW>@|bvN2I&=>pQM>EZmc>b?gb}pebtw} zG(&zkjSGH4teI)ixB5!6jT-z49L{;+3S)I1C(CnmYN&bW6;Q-x7DxMLIgWIO z%!I)32AgQ0%5}1d<;pJI6I<4tDer4)bq4n%HMe<|-en+kJw*J9d~SZNjBqxv-BgA; zcf^-bABc7-u5ElA^9-*e9ZexnrpXXE9#0el(MQow(4l8f6y+mF{FYlYUFi-%U22GN zET*{PL{nH+T>!daafihY;Lz7T zlH3xM)>fvXJJn!A=@>Y@a3GjQYghwB{q4>9#yj}fN&Na4#yBp6bY-s9wNpzRUo-77 z<&~khCudpzk9PJCfqm9iKYx+31r?;|2z-~tLk4p;O)p;vy#u+izI~KN@sWx_lZH9R zXU8yDF62-C_QL9qLrKZhLecM;y;!213Z{I7?HNb<<9`(nJK#9vV0WZn#)M-A)N_t# zRp@{LQX1KxuU3f?Fge)u%3(Rvobak>u`y8LqEc=$c7dRmc%nGZ7Ict_n|O8R?kD>n zXo8lVP>FG0I$ANz_it79mtPy|deF3C1_OpIpoPk+%`#lC>%J7O=Y9WyXMUMEzq9tY_vKRuGz|Pn#%8r6(YdCb4yI)djNso2s;j1 z5-9hUCWWC;zm2C^W*}j-@d0|COfFEl_=5#{%@wh&pdcs-b9F{sa5MJI#_(%Qbxg7Y zY3qab$n(%2P5pQ?4>7RYrq#R8putkcaXnn#xnwR|G&KSNHzN0p@n1Q=dB@=SH0F(( z)T(7V71jYv?~}iA3 zn{+y)YaWK&a?k8Ib8!7UAhI4+sbT1Yu*J_+m@@g0PaI{9v%MswNY-Ia!yEjc4%Fm7 z^_3s?inKFpN1sKLy^$LMc!1nAkKToQ-(h7UR2rk4$~l;`)?e{}Y&HQwU5r4nOO6wWAxrGwZ6$S9w4c*Mm&+{A%1cwHfaJfGPN_D9e%% zef-R$Y%?Wo$p)(}=Gdv+QBsOhQEzrGCRJld5Dl%EX?VulcOX44`lgK_JII!zshJi)^>cZo0PM6D*&G3^U! z_TfgUvO0KDym#y|KAKA@&V6Y30sf}u`kcO~Qqr=tp&LYKJ{BiNCo@OB>Zm2>PVyij z2uDEUy`XjfMooTu(fY%J)IjT7Nu3SzNYxkVGH%6Od33hJ`<^!{a&*s>?`tS(%y5xS z=omI2+w>QuRX>q(EZ?!F8oogrtL3P`T|nwt_;Ypili7>PmFGdO^5H8p^7hZS%N~U! zya;}~`1!?aC#3@6z6|6UFHhi6w$E_MXjAst$gMyS%ZFtX!V15$Nbcle>#vORL~}n` zIM~HG3n^_v0+%YvDRTKIll96MDtm_Kz8MYuq#mO*?SV$^1uU30Y36uLz>BJGhuz6% z;MncrRp5H~Vte9w?O_Jkp>AE8^9vULO_m{oZJ&2tT0AK71z$zKb}UUHY@>TmDo&?v z=NwRs$w+GKEOe3_^Dm%DK#qt)hzQ}IvAjO7Hh`!chWC9ZRrUnGm?&Yf-Zjg;Xsfe9_V znufY7t}RXur^;KTsO8=AS4yw`I^$0Ee05d6I8{V%wUN8`=nYut^I%2}Zjh+3$%2ck zhzHwBGDrTKph1*ESc{dq*TOL0XB>)<+B9GK9Iu*d8j_0poTWTRj)I05ubY=V2A_^> z7Hhn)aU)yUw^{qkEv@V#T6Cd+_WK5C(Q;%%(XCjB|jP)rU3MG7$H=v>W z-FRx0j7s;*D#LV4YyEP~atT2kpjYTC2QA8K5nc(oMvK^%+eqC%mks zf1W5R&&pn1Ya*uD{dC7k`VLH|!=Wkby7Pc-Kox ztF`5}0)^d=b0K;G&*&&@-@SeB&sLK&U$rimF^qOZOruqwgI~Bx3t~zD9`W>cC*pQl zI<0Q$iQbRebX~u##TA2d^+TNNApNt4Uy`?JSW5wfNT&u5ijTffvmJCA0t=!zFht(Q ztm-^h+ZTUcRqfBu#MdHq7~MA;MwfT8uwvTd)Tl}PEo#}}l>Pc_O3{F^Lk|r@2Svt! zM@X#nSR2o#wS_k)_Z=GYR?fh?8}w9qYMj$C4)4meM!rfs%|4M7`9k-NjrP%XZ>sIZ z7r`p`VegI>p^me-Jc~&0&AZ^#?Z;+c%6dYGbb^Qn?4`wQ@G2!A&hClfl7S;o7%|6o znnb6PPYDO_jS~2@fC^XWsg`<2WBA^6^;Z^Ajg~aHxSb#D4vGdHX3bX<4(Glc#!aD8 zbY$5sT1bO%-Dy-mDx$T%z9w;4*^N>ACh{66YY)HenyS*sgOKV6m4!oLBE8p-c&*XH zN*X_zA6TqcL}!*JmqcSw`3!KQJ(wnC?ZhH{v!`ULK0X)ek3uVO7u*okX`_1@L=aBb z2~~GG{N518OBoo>2~D&?YmIeip{HUuN|S3qXl!J3A$0`VH(ltUEY&I+!g0uMhKiN( z5);A|mxA=Cc!uXj3_d~RN;#!O+vzIqbQR1xr8#-y+jxYnhAZ2>3uQ0O@H91@=)M$B z={F1uwprGo?k4aD%-oeo4j>)5Cb3PC#|^Q>a4w}})i->5Za!k%YfY176?_H4L%Z;=t_rGb>81iD(v_D|ONE!m-kKxR-CpLp-7 zEj+!Gp?<5Ya6Yj}6SZDaO{Mbae2 z#G_p);K9dnUzPmWcm68(p1&l$1($JFwC|}n!uY6H*x~XB#&WIk_K$=cAvt5ddZ)qh zp}>vQv043-q7lE_Mr9`~)FF&v?LinROCJQ|oGcxRrxRCXsPZ$U^UTDUYJ0cjZ60vm z50US#pXV=T;sT$lzt42^Yv*?CdzU-2&b9r7(4sVPehwKGbwKuTveIGx!}pMHQTQLU zBEL^fGsPka3{m!H*4HzFY>r+HVcnekxE&ul-P!(aTV4e;naR>t5K^L5COB1f^Gj^% zoR3Osi~l{_nQC9br!>%bB~}^y3SD%5Ia(qd*a%!|)QgwEG#Q!Vo05Ky>>Scx9>7qD zuZb;@`~4v1z9kAT+}|7@7BLmH^6uKe*s(E9ifFvuS*6XX#;#Zw{bS$$I5MwLT1=bl zJ+SD>QuyG3vBLxTI{qYr+1t1+iqQ<&4dO9vPaF4=`p_*~B$kY$UFtL%+X?i$%+y@w zmVb6QdDo2N2ZgH= zL;3Y+%A*VP2@?WAW5*hDSw*{sCDw?Ll3GA9l-(q{-x& zKz)ynv{eQKaoKL+A39O?X*=NJ;iwm7lhS7!lphUO^Ov>oHg|YfDGto=&Lj_Nm33F| ze?hCJ%6b1lo~v{JLsU!1O^vS+$Fb}Tx>%lH*U6Y{Z~7AXNTBs)@@AF{iHkI0DS}9? z1(2au>=NnTKk50aNNj0x^6aDoe|mr-d=|eA787?XXnTKqHD4 z^uz6mt>VlJa%xlm5>Lw!j;x))nmU>k@vzb3jL_r!ZYL6H_MNEM^8`~-KT(slH$8TT zh(Qt@Nq^;~#_qGVvk@%p;l9Bafm3zOjC8pevAf-+xjmH1;Rpo0yiN^e&5Z-tl9&XCM~&w(mPjW(&m~^+lO@ zC(}Eax909^yjL02O|m(y|N1vh_ZmpuNVm+Wm2 zrZH^tx5^;PTk~?x%2Q|(-juGmp!t#@FBBKhc&x8Zvtk6^D6O}4FmeBgN^d2eIjy3 zTk?2#!REM~kJcU!Q((XTPHIWU94VXL2n`EIdV8$z6)CM|`snk&UB)=sz6(*AOY_<# zreRgZ-FfnKWu%?zmIKW0XxP zF86?u(7pKHh%Fe6N?$YbBb~L@*CP)yQS(tRTM(+$lX1ywruCa24{UeQV> z+0XrLN7XkqbM&RJA9Fj@uoA0o+ZgW4X5An?6AV}!C1zXxP&}?u`zUI(v{_fAv@Y4i zQ#q2TeL!Ih_&sl^wMtXlO%NybHh@Omf5ALgUely{?>bE=dDk$3j0J4Ee0e{SPoxQQ zMBjC{ZTl?+tIng9n0U63_RV?w1d3EPY<=CDrTy4I9PRBrZyF)9z=a?axrp5dQM!o* zpbp&ZI^9=Uo+r=bWZ3&fkP7J>uosQG*<_0dMQ%A_SBd#{sl2T+w*p@^BD>hhB%ZE0 z9eNz;@uZs+U83p!pfZ@=*KyAj zS@@Jsy~FW^`?#>rKVxZih>~pV2_hqiL6Buu2h=6`^o70GkIxOfiSx_v^X+OYY_MVJ za6_(0n$uWm5Uw`=;O}RxO-=3X|SfVAmYP|$5&$E8)arL%FNYM3`)cxp^%}7 z3~%}mnafW+W;mdb9q|~k+_Z2Fo;yC7geL0cfygj3|3Up{gSC6*4r}s6*e0AnI*9X|!m8Sbd;n{&A88uw^ zemx+8wJy|n^2CjeCm;gVWu% z8w^hvMD9N!lVaIAAGd4!M$jD@@KWX*>$&XYL9k%YI#%3y@7ETw+=ZTJDYLjU*QAAR zgjG_eB&268me8@qm^b+x(n@*pKRi?4saokNsHpL%qm};NeL}nkjf!V*qQz{;U0+Mk zv)U5o%~D;6)`_~6z*n`>mUZ`@4N6*;8p+h_+-QLvfTj{Jan3c1n4qbmoF z;kt9?i#Bb6ru6d5scW#t(9XE}ryUW387I9||#~vVv|B&DqnM#U$bTcKFc1 zUt~bPsSi~1TIF-9O32(5@WptA_I-rJALonWXG3Z1(nEiP19Hale&iimflQR84fg4X zTc^wz*L=_i5nlx-Y^Bt7=Q3jDh_fplapjoR&c-RZj0w;VGX;}=Vv~m-%g*ETG=qT!< zjR;Tm>}_v3em}I@StFq@0Z9J3puF-;F08x@lViSxAFF8!uO=+9`urb zzfrx@5Nr7mmEB&jwcD97&ZX8U{{%!-4%!Rp>0P8`sx*EZYmhv|EOhG83a%`3J(o+n zryT>TWn?VWSO$lk{z*f1fNjkjZ6l*idFVG0{(fkePD>*gz?mK;9Uat2Rn8o$R`>N!7; zRqt2FDvB4r*p0}2qCymT&>G!ZE0>l#FIzZyzr0pYf0wx1x~9Rf2-HC`+U&vL(ZATC zEhNxHmT6RQS-+NZi zRS(&8SIx9{^Bm2kN@s0Z8(kD~ z-8Kh=l=(A-0%`Vzv8|&CJ!8^ISjjp17r61f_vc{5cgMA9h#Ec{WG8A_380mZP1ZA( z&%dRx0ivH zzd(cU%^RA@%T7<{X=~g*T|Yb31{&Tksr9|h`?Xqzufp*aOaG$VC-lv;I>fY@ zA(*Sa>HRZF`d34B_w_LCiw0nRvB(8uEi5#0gpOnfXfI^5Z0@LOE|j)Rd{P5xN)K&ChA zwCTi6&y^4!9y4J+QI2~2a-;TSFcrq;b|Vuncliq<4|<6FLGryc4uaxlLF$ zPAr?^)X`9>UFdrBt=hVGkAyuYs5UfpnTOYGLuc-XX1v$m zx$F6k^ONS?t~&kbd~aAazEpjKtkQMwBOyHBUxdA5XpAX={6uz6dnG(ROGOuM`u@Hd zWGD@D-gTw>{^ZxH?`BJ6ypt<~+{zBk^kvvAAQ>sNrPe`>HS^B*Ihh)rQ7v~YKcCj_ zm+*2~9heRo(l66}Air!U zZv8G8Le;;At}LA4RnWgtg+%o3Y)}d`I}dkc(_u~IgWjtx`~FyO%Prj$m5i=Du(#5# zrs;=Hi!lvR=Bi*cRDf=>h=^~S7_kYe9`>u{=&FqwCxxs__1?2+U+~#`P>36%rY2SQ zmVJ75 zgmUL|55=1V^qOP^2{g8~CQ&{*-LF4qXS-E8hb5CbI^L&b{BlE%EI+=1f_Y1!14A*x zsZLaHZibSzv#pMy9{qiye)$i>&?ClYNh|JWnoi;FO-81sJ!G~$j~MH|N=#2n;$G7v zJqqMGN*iV&-<`-fY10+8jg!~AI~tx#p^bz@g^s_vwSE^=U>m)e!)^5SL7};@s*Vt* z7agf|44aOm1qFk4yY9LELqeAxbFB#SuWDE=YcfdVH+s7Mk^wqWYR_M4wr7KIG}jkU zGdEE6fsu)6U+q3Xxubj5r!7f!i_mWUG^qpt64iMjSNZc?urCL zL0^3iYS)vkaf0 zM>>>#=Csq-q)OEAi|Ghlq;Q`h+WT9MC5Nf;6A$4Toie_|hJv%?BU(Gf33qNu&&JYa zda=4v>F!5iju>}}Qe%7q{@4+5{yi!6LGdlK`hfiYL;`ZUTV!=ZL_J1_OE0|u^L~?JCW}lj zdMx8pWEXja$B)mbi?3-j#CmkpIwPNJ`;=UJ&_LGhR!Uca;qng5m%aGHF@_jj0FlW@IdXtp zCQcc>KG+)mB`Zz-`q-Mg*>Gtaosq;a6D{OnoW!jR& zU;=~ug80PyJ$-+WyP3=#}L1Ri}=*8fMDZS?A$HO19eHLUsjmvQJyH> zK6UV8#_C?3IPa6Jr1cHHU_Ak;b+%on8}Edh8r$rJN}evgeYqoJ-8nN$!!65bn5|JF zn{QESGa+!pMm_13phHH@|M7tTj|cq!x6lEdSsELk0if0Sf^H;D30)e{+3* z@qqs(+WvuN`x^%=1pf^OEGT>l2YeZW_P^kOZS27|PGEO$S1**cr4!h~*$w64Y2jl1 zm-H7M_+OF1Zcg5wU@KQ=XA7|1T{kBs8SG*Y7+SeHxw?R*!7^Z3upGc6RsbsjOkx$V zDp(Dy4%YaMPJ9cj2i6B0fGs^NtQ=8ZzhK7y`TUo|7GO)T71$aKj0v^{+kx%D4q!*{ zKLBHQum{)^>;?7){|8|V_WN%Le)aZuJpSqqYvkr zNf3b$Krq=b{YQf$0HE%#ubEu_tHA+|@Ffkn1m<_~`pr&2__Cd_033iQ|7nMW!i0eJ z`=c!!E(E`#L4_{RL}UigOwfxw|x#)ZIv5L~u{3L>s(a0tLp{VM0Q72G0f8&NAg;~> zNLwJIE{}n@D8@g>ML;f!<#!EO47l(m4FW|7K(F|R6o6mx58yXno*Nv%Utb;<&@KS! zzmE%~9~|IvU)HX!2OMzb@)`l!)mi|csF&*q4nqiBo(CNMuiBM-2J9}!3Ic} zLIPmY_F0{)rxX=L3{N?_H0CxN(4UV|H9{{x_cyZWXy#C(rFSOtD z%FDw7IQ>09Vq(BOn7tqB;+z3%ySf6$I?(b0C$8*b@czFFflYp*} NNCb$TU0zcG^gpmH(YF8q literal 0 HcmV?d00001 diff --git a/gnuradio-core/doc/other/omnithread.ps b/gnuradio-core/doc/other/omnithread.ps new file mode 100644 index 00000000..9e858f0b --- /dev/null +++ b/gnuradio-core/doc/other/omnithread.ps @@ -0,0 +1,730 @@ +%!PS-Adobe-2.0 +%%Creator: dvipsk 5.86 p1.5d Copyright 1996-2001 ASCII Corp.(www-ptex@ascii.co.jp) +%%based on dvipsk 5.86 Copyright 1999 Radical Eye Software (www.radicaleye.com) +%%Title: omnithread.dvi +%%Pages: 7 +%%PageOrder: Ascend +%%BoundingBox: 0 0 596 842 +%%DocumentFonts: Palatino-Roman Palatino-Italic Palatino-Bold Courier +%%EndComments +%DVIPSWebPage: (www.radicaleye.com) +%DVIPSCommandLine: dvips omnithread +%DVIPSParameters: dpi=600, compressed +%DVIPSSource: TeX output 2002.08.15:1756 +%%BeginProcSet: texc.pro +%! +/TeXDict 300 dict def TeXDict begin/N{def}def/B{bind def}N/S{exch}N/X{S +N}B/A{dup}B/TR{translate}N/isls false N/vsize 11 72 mul N/hsize 8.5 72 +mul N/landplus90{false}def/@rigin{isls{[0 landplus90{1 -1}{-1 1}ifelse 0 +0 0]concat}if 72 Resolution div 72 VResolution div neg scale isls{ +landplus90{VResolution 72 div vsize mul 0 exch}{Resolution -72 div hsize +mul 0}ifelse TR}if Resolution VResolution vsize -72 div 1 add mul TR[ +matrix currentmatrix{A A round sub abs 0.00001 lt{round}if}forall round +exch round exch]setmatrix}N/@landscape{/isls true N}B/@manualfeed{ +statusdict/manualfeed true put}B/@copies{/#copies X}B/FMat[1 0 0 -1 0 0] +N/FBB[0 0 0 0]N/nn 0 N/IEn 0 N/ctr 0 N/df-tail{/nn 8 dict N nn begin +/FontType 3 N/FontMatrix fntrx N/FontBBox FBB N string/base X array +/BitMaps X/BuildChar{CharBuilder}N/Encoding IEn N end A{/foo setfont}2 +array copy cvx N load 0 nn put/ctr 0 N[}B/sf 0 N/df{/sf 1 N/fntrx FMat N +df-tail}B/dfs{div/sf X/fntrx[sf 0 0 sf neg 0 0]N df-tail}B/E{pop nn A +definefont setfont}B/Cw{Cd A length 5 sub get}B/Ch{Cd A length 4 sub get +}B/Cx{128 Cd A length 3 sub get sub}B/Cy{Cd A length 2 sub get 127 sub} +B/Cdx{Cd A length 1 sub get}B/Ci{Cd A type/stringtype ne{ctr get/ctr ctr +1 add N}if}B/id 0 N/rw 0 N/rc 0 N/gp 0 N/cp 0 N/G 0 N/CharBuilder{save 3 +1 roll S A/base get 2 index get S/BitMaps get S get/Cd X pop/ctr 0 N Cdx +0 Cx Cy Ch sub Cx Cw add Cy setcachedevice Cw Ch true[1 0 0 -1 -.1 Cx +sub Cy .1 sub]/id Ci N/rw Cw 7 add 8 idiv string N/rc 0 N/gp 0 N/cp 0 N{ +rc 0 ne{rc 1 sub/rc X rw}{G}ifelse}imagemask restore}B/G{{id gp get/gp +gp 1 add N A 18 mod S 18 idiv pl S get exec}loop}B/adv{cp add/cp X}B +/chg{rw cp id gp 4 index getinterval putinterval A gp add/gp X adv}B/nd{ +/cp 0 N rw exit}B/lsh{rw cp 2 copy get A 0 eq{pop 1}{A 255 eq{pop 254}{ +A A add 255 and S 1 and or}ifelse}ifelse put 1 adv}B/rsh{rw cp 2 copy +get A 0 eq{pop 128}{A 255 eq{pop 127}{A 2 idiv S 128 and or}ifelse} +ifelse put 1 adv}B/clr{rw cp 2 index string putinterval adv}B/set{rw cp +fillstr 0 4 index getinterval putinterval adv}B/fillstr 18 string 0 1 17 +{2 copy 255 put pop}for N/pl[{adv 1 chg}{adv 1 chg nd}{1 add chg}{1 add +chg nd}{adv lsh}{adv lsh nd}{adv rsh}{adv rsh nd}{1 add adv}{/rc X nd}{ +1 add set}{1 add clr}{adv 2 chg}{adv 2 chg nd}{pop nd}]A{bind pop} +forall N/D{/cc X A type/stringtype ne{]}if nn/base get cc ctr put nn +/BitMaps get S ctr S sf 1 ne{A A length 1 sub A 2 index S get sf div put +}if put/ctr ctr 1 add N}B/I{cc 1 add D}B/bop{userdict/bop-hook known{ +bop-hook}if/SI save N @rigin 0 0 moveto/V matrix currentmatrix A 1 get A +mul exch 0 get A mul add .99 lt{/QV}{/RV}ifelse load def pop pop}N/eop{ +SI restore userdict/eop-hook known{eop-hook}if showpage}N/@start{ +userdict/start-hook known{start-hook}if pop/VResolution X/Resolution X +1000 div/DVImag X/IEn 256 array N 2 string 0 1 255{IEn S A 360 add 36 4 +index cvrs cvn put}for pop 65781.76 div/vsize X 65781.76 div/hsize X}N +/dir 0 def/dyy{/dir 0 def}B/dyt{/dir 1 def}B/dty{/dir 2 def}B/dtt{/dir 3 +def}B/p{dir 2 eq{-90 rotate show 90 rotate}{dir 3 eq{-90 rotate show 90 +rotate}{show}ifelse}ifelse}N/RMat[1 0 0 -1 0 0]N/BDot 260 string N/Rx 0 +N/Ry 0 N/V{}B/RV/v{/Ry X/Rx X V}B statusdict begin/product where{pop +false[(Display)(NeXT)(LaserWriter 16/600)]{A length product length le{A +length product exch 0 exch getinterval eq{pop true exit}if}{pop}ifelse} +forall}{false}ifelse end{{gsave TR -.1 .1 TR 1 1 scale Rx Ry false RMat{ +BDot}imagemask grestore}}{{gsave TR -.1 .1 TR Rx Ry scale 1 1 false RMat +{BDot}imagemask grestore}}ifelse B/QV{gsave newpath transform round exch +round exch itransform moveto Rx 0 rlineto 0 Ry neg rlineto Rx neg 0 +rlineto fill grestore}B/a{moveto}B/delta 0 N/tail{A/delta X 0 rmoveto}B +/M{S p delta add tail}B/b{S p tail}B/c{-4 M}B/d{-3 M}B/e{-2 M}B/f{-1 M} +B/g{0 M}B/h{1 M}B/i{2 M}B/j{3 M}B/k{4 M}B/w{0 rmoveto}B/l{p -4 w}B/m{p +-3 w}B/n{p -2 w}B/o{p -1 w}B/q{p 1 w}B/r{p 2 w}B/s{p 3 w}B/t{p 4 w}B/x{ +0 S rmoveto}B/y{3 2 roll p a}B/bos{/SS save N}B/eos{SS restore}B end + +%%EndProcSet +%%BeginProcSet: 8r.enc +% @@psencodingfile@{ +% author = "S. Rahtz, P. MacKay, Alan Jeffrey, B. Horn, K. Berry", +% version = "0.6", +% date = "1 July 1998", +% filename = "8r.enc", +% email = "tex-fonts@@tug.org", +% docstring = "Encoding for TrueType or Type 1 fonts +% to be used with TeX." +% @} +% +% Idea is to have all the characters normally included in Type 1 fonts +% available for typesetting. This is effectively the characters in Adobe +% Standard Encoding + ISO Latin 1 + extra characters from Lucida. +% +% Character code assignments were made as follows: +% +% (1) the Windows ANSI characters are almost all in their Windows ANSI +% positions, because some Windows users cannot easily reencode the +% fonts, and it makes no difference on other systems. The only Windows +% ANSI characters not available are those that make no sense for +% typesetting -- rubout (127 decimal), nobreakspace (160), softhyphen +% (173). quotesingle and grave are moved just because it's such an +% irritation not having them in TeX positions. +% +% (2) Remaining characters are assigned arbitrarily to the lower part +% of the range, avoiding 0, 10 and 13 in case we meet dumb software. +% +% (3) Y&Y Lucida Bright includes some extra text characters; in the +% hopes that other PostScript fonts, perhaps created for public +% consumption, will include them, they are included starting at 0x12. +% +% (4) Remaining positions left undefined are for use in (hopefully) +% upward-compatible revisions, if someday more characters are generally +% available. +% +% (5) hyphen appears twice for compatibility with both +% ASCII and Windows. +% +/TeXBase1Encoding [ +% 0x00 (encoded characters from Adobe Standard not in Windows 3.1) + /.notdef /dotaccent /fi /fl + /fraction /hungarumlaut /Lslash /lslash + /ogonek /ring /.notdef + /breve /minus /.notdef +% These are the only two remaining unencoded characters, so may as +% well include them. + /Zcaron /zcaron +% 0x10 + /caron /dotlessi +% (unusual TeX characters available in, e.g., Lucida Bright) + /dotlessj /ff /ffi /ffl + /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef + % very contentious; it's so painful not having quoteleft and quoteright + % at 96 and 145 that we move the things normally found there to here. + /grave /quotesingle +% 0x20 (ASCII begins) + /space /exclam /quotedbl /numbersign + /dollar /percent /ampersand /quoteright + /parenleft /parenright /asterisk /plus /comma /hyphen /period /slash +% 0x30 + /zero /one /two /three /four /five /six /seven + /eight /nine /colon /semicolon /less /equal /greater /question +% 0x40 + /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O +% 0x50 + /P /Q /R /S /T /U /V /W + /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore +% 0x60 + /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o +% 0x70 + /p /q /r /s /t /u /v /w + /x /y /z /braceleft /bar /braceright /asciitilde + /.notdef % rubout; ASCII ends +% 0x80 + /.notdef /.notdef /quotesinglbase /florin + /quotedblbase /ellipsis /dagger /daggerdbl + /circumflex /perthousand /Scaron /guilsinglleft + /OE /.notdef /.notdef /.notdef +% 0x90 + /.notdef /.notdef /.notdef /quotedblleft + /quotedblright /bullet /endash /emdash + /tilde /trademark /scaron /guilsinglright + /oe /.notdef /.notdef /Ydieresis +% 0xA0 + /.notdef % nobreakspace + /exclamdown /cent /sterling + /currency /yen /brokenbar /section + /dieresis /copyright /ordfeminine /guillemotleft + /logicalnot + /hyphen % Y&Y (also at 45); Windows' softhyphen + /registered + /macron +% 0xD0 + /degree /plusminus /twosuperior /threesuperior + /acute /mu /paragraph /periodcentered + /cedilla /onesuperior /ordmasculine /guillemotright + /onequarter /onehalf /threequarters /questiondown +% 0xC0 + /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla + /Egrave /Eacute /Ecircumflex /Edieresis + /Igrave /Iacute /Icircumflex /Idieresis +% 0xD0 + /Eth /Ntilde /Ograve /Oacute + /Ocircumflex /Otilde /Odieresis /multiply + /Oslash /Ugrave /Uacute /Ucircumflex + /Udieresis /Yacute /Thorn /germandbls +% 0xE0 + /agrave /aacute /acircumflex /atilde + /adieresis /aring /ae /ccedilla + /egrave /eacute /ecircumflex /edieresis + /igrave /iacute /icircumflex /idieresis +% 0xF0 + /eth /ntilde /ograve /oacute + /ocircumflex /otilde /odieresis /divide + /oslash /ugrave /uacute /ucircumflex + /udieresis /yacute /thorn /ydieresis +] def + +%%EndProcSet +%%BeginProcSet: texps.pro +%! +TeXDict begin/rf{findfont dup length 1 add dict begin{1 index/FID ne 2 +index/UniqueID ne and{def}{pop pop}ifelse}forall[1 index 0 6 -1 roll +exec 0 exch 5 -1 roll VResolution Resolution div mul neg 0 0]/Metrics +exch def dict begin 0 1 255{exch dup type/integertype ne{pop pop 1 sub +dup 0 le{pop}{[}ifelse}{FontMatrix 0 get div Metrics 0 get div def} +ifelse}for Metrics/Metrics currentdict end def[2 index currentdict end +definefont 3 -1 roll makefont/setfont cvx]cvx def}def/ObliqueSlant{dup +sin S cos div neg}B/SlantFont{4 index mul add}def/ExtendFont{3 -1 roll +mul exch}def/ReEncodeFont{CharStrings rcheck{/Encoding false def dup[ +exch{dup CharStrings exch known not{pop/.notdef/Encoding true def}if} +forall Encoding{]exch pop}{cleartomark}ifelse}if/Encoding exch def}def +end + +%%EndProcSet +TeXDict begin 39158280 55380996 1000 600 600 (omnithread.dvi) +@start /Fa 134[ 45 45 66 1[ 51 30 35 35 1[ 45 40 51 71 +25 2[ 25 45 45 25 35 45 37 42 40 8[ 66 3[ 56 51 2[ 56 +71 5[ 30 3[ 56 3[ 66 23[ 30 30 40[{ TeXBase1Encoding ReEncodeFont} 31 +90.9091 /Palatino-Italic rf /Fb 134[ 51 1[ 76 1[ 56 30 +40 35 2[ 51 56 81 30 2[ 30 56 51 35 45 56 40 56 45 14[ 66 +2[ 76 5[ 35 6[ 61 19[ 23 30 23 4[ 25 39[{ TeXBase1Encoding ReEncodeFont} +27 90.9091 /Palatino-Bold rf /Fc 135[ 50 83 1[ 61 33 +44 39 1[ 61 55 61 89 33 2[ 33 61 55 1[ 50 61 44 61 50 +10[ 78 8[ 100 9[ 72 12[ 50 1[ 50 50 50 50 2[ 25 4[ 33 +33 40[{ TeXBase1Encoding ReEncodeFont} 30 99.6264 /Palatino-Bold +rf /Fd 134[ 55 55 55 55 55 55 55 55 55 55 55 55 55 55 +55 55 55 55 55 55 55 55 55 55 55 1[ 55 5[ 55 55 55 55 +55 55 55 55 1[ 55 55 55 55 55 55 1[ 55 55 55 55 55 55 +55 55 55 3[ 55 2[ 55 1[ 55 1[ 55 55 55 55 55 55 55 1[ 55 +55 55 1[ 55 55 55 40[{ TeXBase1Encoding ReEncodeFont} 65 +90.9091 /Courier rf /Fe 141[ 36 12[ 44 56 2[ 45 7[ 61 +61 91 1[ 71 56 48 61 2[ 71 76 3[ 30 31 76 1[ 51 56 70 +64 56 71 10[ 45 3[ 45 45 1[ 55 23 4[ 30 30 40[{ +.167 SlantFont TeXBase1Encoding ReEncodeFont} 29 90.9091 +/Palatino-Roman rf +%DVIPSBitmapFont: Ff cmsy10 10.95 1 +/Ff 1 16 df 15 +D E +%EndDVIPSBitmapFont +/Fg 104[ 91 2[ 45 45 24[ 45 51 47 76 51 55 30 39 36 51 +55 50 53 80 26 51 21 26 53 51 30 44 56 40 50 45 3[ 30 +1[ 30 2[ 61 91 66 71 56 48 61 1[ 55 71 76 86 56 66 30 +31 76 1[ 51 56 70 64 56 71 6[ 23 45 45 45 45 45 45 45 +45 45 45 55 23 30 23 55 1[ 30 30 25 4[ 34 30[ 55 55 2[{ +TeXBase1Encoding ReEncodeFont} 75 90.9091 /Palatino-Roman +rf /Fh 134[ 66 60 100 1[ 73 40 53 47 1[ 73 66 73 106 +2[ 40 40 73 66 47 60 73 53 73 60 11[ 93 80 73 86 1[ 73 +100 100 120 3[ 47 18[ 60 60 60 60 60 60 1[ 35 1[ 40 45[{ +TeXBase1Encoding ReEncodeFont} 38 119.552 /Palatino-Bold +rf /Fi 137[ 50 2[ 39 9[ 28 3[ 39 50 17[ 66 82[{ +TeXBase1Encoding ReEncodeFont} 6 99.6264 /Palatino-Italic +rf /Fj 137[ 56 1[ 32 42 39 2[ 54 58 88 3[ 29 58 55 1[ 48 +61 44 55 50 12[ 61 1[ 67 3[ 83 1[ 61 8[ 71 1[ 78 14[ 50 +50 50 9[ 78 38[{ TeXBase1Encoding ReEncodeFont} 25 99.6264 +/Palatino-Roman rf /Fk 139[ 47 61 57 2[ 78 83 4[ 42 83 +2[ 69 88 64 79 72 12[ 88 4[ 113 119 136 3[ 48 7[ 112 +65[{ TeXBase1Encoding ReEncodeFont} 18 143.462 /Palatino-Roman +rf end +%%EndProlog +%%BeginSetup +%%Feature: *Resolution 600dpi +TeXDict begin +%%PaperSize: A4 + +%%EndSetup +%%Page: 1 1 +1 0 bop Fk 728 918 a(The) 36 b(OMNI) g(Thr) m(ead) f(Abstracti) n(on) p +Fj 1293 1176 a(T) -9 b(ristan) 26 b(Richar) n(dson) 1022 +1293 y(A) -7 b(T&T) 24 b(Laboratories) i(Cambridge) p +Fi 1192 1504 a(Revised) p Fj 24 w(November) f(2001) p +Fh 63 1961 a(1) 119 b(Introduction) p Fg 63 2183 a(The) 20 +b(OMNI) h(thr) n(ead) g(abstraction) g(is) h(des) n(igned) f(to) f(pr) n +(ovide) h(a) h(common) f(set) f(of) h(thr) n(ead) g(oper) n(-) 63 +2296 y(ations) h(for) g(use) g(in) h(pr) n(ograms) f(written) f(in) i +(C++.) 29 b(Pr) n(ograms) 22 b(written) g(using) f(the) h(abstraction) +63 2409 y(should) 30 b(be) g(much) i(easier) e(to) g(port) g(betwee) n +(n) h(dif) n(fer) n(ent) g(ar) n(chi) r(tectur) l(es) g(with) g(dif) n +(fer) n(ent) f(un-) 63 2522 y(derlying) 21 b(thr) n(eads) h +(primitives.) 204 2640 y(The) 17 b(pr) n(ogramming) h(interface) g(is) f +(designed) f(to) h(be) h(similar) h(to) e(the) g(C) i(language) e +(interface) 63 2753 y(to) k(POSIX) h(thr) n(eads) f(\(IEEE) g(draft) h +(standar) n(d) f(100) r(3.1c) i(\227) f(pr) n(eviously) g(1003) r(.4a,) +g(often) g(known) 63 2866 y(as) g(\223pthr) n(eads\224) h([POSIX94]\).) +204 2985 y(Much) 18 b(of) f(the) g(abstraction) i(consists) d(of) i +(simple) g(C++) g(object) g(wrappers) e(ar) n(ound) h(pthr) n(ead) 63 +3098 y(calls.) 28 b(Howe) n(ver) 20 b(for) f(some) f(featur) n(es) g +(such) h(as) h(thr) n(ead-spe) n(ci\002c) h(data,) f(a) f(better) f +(interface) i(can) 63 3211 y(be) i(of) n(fer) n(ed) g(because) h(of) f +(the) g(use) g(of) g(C++.) 204 3329 y(Some) 28 b(of) h(the) f(mor) n(e) +h(complex) f(featur) n(es) g(of) h(pthr) n(eads) f(ar) n(e) h(not) f +(suppo) n(rted) g(because) h(of) 63 3442 y(the) e(dif) n(\002culty) i +(of) f(ensuring) g(the) f(same) h(featur) n(es) g(can) h(be) f(of) n +(fer) n(ed) g(on) g(top) g(of) g(other) f(thr) n(ead) 63 +3555 y(sys) n(tems.) f(Such) 17 b(featur) n(es) g(include) h(thr) n +(ead) f(cancell) r(ation) g(and) h(complex) g(schedu) n(ling) h(contr) n +(ol) 63 3668 y(\(thoug) n(h) k(simple) g(thr) n(ead) f(priorities) g +(ar) n(e) h(supp) n(orted\).) 204 3787 y(The) i(abstraction) h(layer) h +(is) f(curr) n(ently) f(implemented) g(for) h(the) f(following) i(ar) n +(chitectur) n(es) 63 3900 y(/) 22 b(thr) n(ead) h(sys) n(tems:) p +Ff 199 4141 a(\017) p Fg 46 w(Solaris) g(2.x) g(using) f(pthr) n(eads) f +(draft) h(10) p Ff 199 4351 a(\017) p Fg 46 w(Solaris) h(2.x) g(using) f +(solaris) g(thr) n(eads) g(\(but) h(pthr) n(eads) e(version) h(is) h +(now) f(standar) n(d\)) p Ff 199 4561 a(\017) p Fg 46 +w(Alpha) h(OSF1) g(using) f(pthr) n(eads) f(draft) i(4) p +Ff 199 4772 a(\017) p Fg 46 w(W) -5 b(indows) 21 b(NT) h(using) g(NT) g +(thr) n(eads) p Ff 199 4982 a(\017) p Fg 46 w(Linux) g(2.x) h(using) f +(Linuxthr) n(ead) g(0.5) h(\(which) h(is) e(based) g(on) h(pthr) n +(eads) e(draft) i(10\)) p Ff 199 5193 a(\017) p Fg 46 +w(Linux) f(2.x) h(using) f(MIT) g(pthr) n(eads) f(\(which) j(is) f +(based) f(on) g(draft) h(8\)) p Ff 199 5403 a(\017) p +Fg 46 w(A) -7 b(TMos) 22 b(using) g(pthr) n(eads) f(draft) h(6) i +(\(but) e(not) g(V) -5 b(irata) 23 b(A) -7 b(TMos\)) 1684 +5652 y(1) p 90 rotate dyy eop +%%Page: 2 2 +2 1 bop Fg 221 249 a(2) p Fe 1797 w(2) 91 b(SYNCHRONI) n(SA) -7 +b(TION) 22 b(OBJECTS) p Fg 362 548 a(See) h(the) p Fd +22 w(omni) n(thre) n(ad.h) p Fg 22 w(header) f(\002le) i(for) f(full) i +(det) n(ail) r(s) e(of) g(the) g(API.) f(The) h(des) n(criptions) 221 +661 y(below) 35 b(assume) g(you) g(have) h(some) e(pr) n(evious) h +(knowled) n(ge) g(of) h(thr) n(eads) n(,) j(mutexes) n(,) g(condi-) 221 +774 y(tion) f(varia) r(bles) g(and) g(semaphor) n(es) n(.) 75 +b(Also) 38 b(r) n(efer) f(to) h(other) f(document) n(ation) i(\([Birr) n +(ell89) r(],) 221 887 y([POSIX94) q(]\)) 22 b(for) g(further) f +(explanation) i(of) f(thes) n(e) g(ideas) g(\(particularly) h +(condition) f(variab) r(les,) 221 1000 y(the) g(use) g(of) g(which) h +(may) g(not) f(be) h(particularly) h(intuitive) f(when) f(\002rst) f +(encounter) n(ed) n(\).) p Fh 221 1299 a(2) 119 b(Synchronisation) 31 +b(objects) p Fg 221 1510 a(Synchr) n(onisation) 26 b(objects) h(ar) n +(e) g(used) e(to) h(synchr) n(onise) g(thr) n(eads) g(within) h(the) f +(same) h(pr) n(ocess) n(.) 221 1623 y(Ther) n(e) j(is) i(no) f(inter) n +(-pr) n(ocess) f(synchr) n(onisation) g(pr) n(ovided.) 53 +b(The) 30 b(synchr) n(onisation) h(objects) 221 1735 +y(pr) n(ovided) 22 b(ar) n(e) h(mutexes) n(,) g(condition) f(variab) r +(les) g(and) h(counting) f(semaphor) n(e) n(s.) p Fc +221 1991 a(2.1) 99 b(Mutex) p Fg 221 2168 a(An) 26 b(object) g(of) h +(typ) n(e) p Fd 26 w(omni) n(_mute) n(x) p Fg 26 w(is) g(use) n(d) f +(for) h(mutual) f(exclusion.) 39 b(It) 26 b(pr) n(ovides) f(two) g(op-) +221 2281 y(erations,) p Fd 37 w(lock\() n(\)) p Fg 35 +w(and) p Fd 35 w(unloc) n(k\(\)) p Fg(.) 64 b(The) 35 +b(alternative) h(names) p Fd 35 w(acq) n(uire\() n(\)) p +Fg 35 w(and) p Fd 35 w(re-) 221 2393 y(leas) n(e\(\)) p +Fg 19 w(can) 21 b(be) f(used) f(if) i(pr) n(eferr) n(ed) n(.) 27 +b(Behaviour) 20 b(is) g(unde\002ne) n(d) g(when) f(a) i(thr) n(ead) f +(attempt) n(s) 221 2506 y(to) 30 b(lock) h(the) e(same) i(mutex) f +(again) h(or) f(when) g(a) h(mutex) f(is) h(locked) e(by) i(one) e(thr) +n(ead) h(and) h(un-) 221 2619 y(locked) 22 b(by) h(a) g(dif) n(fer) n +(ent) f(thr) n(ead.) p Fc 221 2874 a(2.2) 99 b(Condition) 26 +b(V) -11 b(ariable) p Fg 221 3051 a(A) 28 b(condition) f(varia) r(ble) h +(is) g(r) n(epr) n(ese) n(nted) f(by) h(an) p Fd 28 w(omn) n(i_con) n +(diti) n(on) p Fg 27 w(and) g(is) g(used) e(for) i(sig-) 221 +3164 y(nalli) r(ng) 20 b(betwee) n(n) g(thr) n(eads.) 26 +b(A) 21 b(call) h(to) p Fd 19 w(wait\() n(\)) p Fg 20 +w(causes) e(a) h(thr) n(ead) e(to) h(wait) h(on) f(the) f(condition) 221 +3277 y(varia) r(ble.) 45 b(A) 28 b(call) i(to) p Fd 27 +w(sign) n(al\(\)) p Fg 27 w(wakes) d(up) h(at) g(least) g(one) f(thr) n +(ead) h(if) h(any) f(ar) n(e) g(waiting.) 45 b(A) 221 +3390 y(call) 25 b(to) p Fd 22 w(bro) n(adca) n(st\(\)) p +Fg 21 w(wakes) d(up) g(all) i(thr) n(eads) e(waiting) h(on) f(the) g +(condition) g(varia) r(ble.) 362 3503 y(When) 30 b(constr) o(ucte) n +(d,) i(a) e(pointer) f(to) h(an) p Fd 30 w(omni) n(_mute) n(x) p +Fg 30 w(must) f(be) h(given.) 50 b(A) 30 b(condition) 221 +3616 y(varia) r(ble) p Fd 33 w(wait\() n(\)) p Fg 33 +w(has) j(an) h(implic) r(it) f(mutex) p Fd 33 w(unlo) n(ck\(\)) p +Fg 32 w(and) p Fd 33 w(lock) n(\(\)) p Fg 33 w(ar) n(ound) g(it.) 60 +b(The) 221 3729 y(link) 30 b(between) f(condition) g(varia) r(ble) h +(and) g(mutex) f(lasts) g(for) h(the) f(lifetime) i(of) e(the) g +(condition) 221 3842 y(varia) r(ble) c(\(unlike) h(pthr) n(eads) e +(wher) n(e) g(the) h(link) h(is) f(only) g(for) g(the) g(duration) f +(of) i(the) e(wait\).) 37 b(The) 221 3955 y(same) 23 +b(mutex) f(may) h(be) f(used) f(with) i(several) f(condition) h(variab) +r(les.) 362 4068 y(A) c(wait) g(with) g(a) g(timeout) f(can) i(be) e +(achieved) h(by) g(call) r(ing) p Fd 19 w(tim) n(ed_w) n(ait\(\)) p +Fg -2 w(.) 27 b(This) 18 b(is) h(given) 221 4181 y(an) 27 +b(absolute) e(time) h(to) f(wait) h(until.) 38 b(The) 26 +b(r) n(outine) p Fd 25 w(omn) n(i_thr) n(ead:) n(:get_) n(time) n(\(\)) +p Fg 25 w(can) h(be) 221 4293 y(used) 21 b(to) h(turn) g(a) h(r) n +(elativ) r(e) f(time) g(into) h(an) g(absolute) f(time.) p +Fd 28 w(tim) n(ed_wa) n(it\(\)) p Fg 21 w(r) n(eturns) p +Fd 21 w(true) p Fg 21 w(if) 221 4406 y(the) 27 b(condition) h(was) g +(signalled,) p Fd 29 w(false) p Fg 26 w(if) h(the) f(time) g(expir) n +(ed) f(befor) n(e) g(the) h(condition) f(vari) r(-) 221 +4519 y(able) d(was) e(signalled.) p Fc 221 4774 a(2.3) 99 +b(Counting) 26 b(semaphores) p Fg 221 4951 a(An) p Fd +21 w(omn) n(i_sem) n(apho) n(re) p Fg 20 w(is) 21 b(a) h(counting) e +(semaphor) n(e) n(.) 28 b(When) 20 b(cr) n(eated) g(it) h(is) g(given) g +(an) g(initial) 221 5064 y(unsigned) j(intege) n(r) i(value.) 36 +b(When) p Fd 25 w(wai) n(t\(\)) p Fg 24 w(is) 26 b(called,) g(the) f +(value) h(is) f(decr) n(emente) n(d) g(if) h(non-) 221 +5177 y(zer) n(o.) 43 b(If) 27 b(the) g(value) h(is) f(zer) n(o) h(then) +f(the) f(thr) n(ead) h(blocks) h(instead.) 41 b(When) p +Fd 27 w(post) n(\(\)) p Fg 27 w(is) 27 b(cal) r(led,) 221 +5290 y(if) h(any) g(thr) n(eads) e(ar) n(e) i(blocked) f(in) p +Fd 27 w(wait\() n(\)) p Fg(,) h(exactly) f(one) g(thr) n(ead) g(is) g +(woken.) 41 b(If) 27 b(no) g(thr) n(eads) 221 5403 y(wer) n(e) 22 +b(blocked) g(then) g(the) g(value) h(of) g(the) e(semaphor) n(e) h(is) h +(incr) n(emented.) p 90 rotate dyy eop +%%Page: 3 3 +3 2 bop Fg 3306 249 a(3) 204 548 y(If) 27 b(a) h(thr) n(ead) e(cal) r +(ls) p Fd 27 w(try) n(_wait) n(\(\)) p Fg(,) h(then) g(the) f(thr) n +(ead) g(won't) h(block) h(if) f(the) g(semaphor) n(e's) 63 +661 y(value) c(is) g(0,) g(r) n(eturning) p Fd 21 w(false) p +Fg 21 w(instead.) 204 777 y(Ther) n(e) f(is) g(no) h(way) f(of) h +(query) n(ing) g(the) f(value) h(of) g(the) f(semaphor) n(e) n(.) p +Fh 63 1095 a(3) 119 b(Thread) 29 b(object) p Fg 63 1313 +a(A) 23 b(thr) n(ead) g(is) h(r) n(epr) n(ese) n(nted) e(by) i(an) p +Fd 24 w(omni) n(_thr) n(ead) p Fg 23 w(object.) 30 b(Ther) n(e) 23 +b(ar) n(e) h(br) n(oadly) g(two) e(dif) n(fer) n(-) 63 +1426 y(ent) f(ways) i(in) g(which) g(it) g(can) g(be) g(used) n(.) 204 +1542 y(The) 28 b(\002rst) g(way) h(is) h(simply) f(to) f(cr) n(eate) h +(an) p Fd 30 w(omn) n(i_thr) n(ead) p Fg 28 w(object,) h(giving) g(a) f +(particula) r(r) 63 1655 y(function) c(which) h(the) e(thr) n(ead) h +(should) f(execute) n(.) 36 b(This) 25 b(is) g(like) g(the) g(POSIX) f +(\(or) i(any) f(other) n(\)) h(C) 63 1768 y(language) c(interface.) 204 +1884 y(The) k(second) f(method) h(of) h(use) e(is) i(to) f(cr) n(eate) h +(a) g(new) g(class) g(which) g(inherits) f(fr) n(om) p +Fd 28 w(omn) n(i_) 63 1997 y(thr) n(ead) p Fg(.) 50 b(In) 31 +b(this) f(case) g(the) g(thr) n(ead) g(will) i(execute) d(the) p +Fd 29 w(run\(\)) p Fg 29 w(member) h(function) h(of) f(the) 63 +2109 y(new) 22 b(class.) 29 b(One) 23 b(advantage) g(of) g(this) g +(scheme) f(is) h(that) g(thr) n(ead-speci\002c) g(data) g(can) h(be) f +(imple-) 63 2222 y(mented) e(simply) h(by) h(having) g(data) g(members) +f(of) h(the) f(new) g(class.) 204 2339 y(When) f(constr) o(ucted) g(a) i +(thr) n(ead) f(is) g(in) h(the) e("new") h(state) f(and) h(has) g(not) g +(actuall) r(y) g(starte) n(d.) 28 b(A) 63 2451 y(call) j(to) p +Fd 29 w(sta) n(rt\(\)) p Fg 28 w(causes) e(the) g(thr) n(ead) g(to) g +(begin) g(executing.) 47 b(A) 29 b(static) h(member) f(function) p +Fd 63 2564 a(cre) n(ate\() n(\)) p Fg 32 w(is) j(pr) n(ovided) f(to) g +(constr) o(uct) g(and) g(start) g(a) i(thr) n(ead) e(in) h(a) g(single) +g(call.) 57 b(A) 31 b(thr) n(ead) 63 2677 y(exits) 21 +b(by) i(call) r(ing) p Fd 22 w(exit\() n(\)) p Fg 22 +w(or) g(by) f(r) n(eturning) g(fr) n(om) h(the) f(thr) n(ead) g +(function.) 204 2793 y(Thr) n(eads) 27 b(can) j(be) e(either) g +(detached) f(or) h(undetached) n(.) 46 b(Detached) 28 +b(thr) n(eads) g(ar) n(e) h(thr) n(eads) 63 2906 y(for) h(which) i(all) +g(state) e(will) i(be) f(lost) f(upon) g(exit.) 52 b(Other) 30 +b(thr) n(eads) g(cannot) h(dete) n(rmine) g(when) 63 +3019 y(a) e(detached) f(thr) n(ead) h(will) h(disappear) -7 +b(,) 31 b(and) e(ther) n(efor) n(e) f(should) g(not) h(attempt) f(to) g +(access) h(the) 63 3132 y(thr) n(ead) 23 b(object) g(unless) f(some) h +(explicit) h(synchr) n(onisation) f(with) g(the) g(detached) f(thr) n +(ead) h(guar) n(-) 63 3245 y(antees) e(that) h(it) h(still) g(exists.) +204 3361 y(Undet) n(ached) 33 b(thr) n(eads) f(ar) n(e) i(thr) n(eads) e +(for) h(which) g(storage) f(is) h(not) f(r) n(eclai) r(med) g(until) i +(an-) 63 3474 y(othe) n(r) g(thr) n(ead) g(waits) g(for) g(its) g +(termination) g(by) g(call) r(ing) p Fd 34 w(joi) n(n\(\)) p +Fg(.) 61 b(An) 34 b(exit) g(value) h(can) g(be) 63 3587 +y(passe) n(d) 23 b(fr) n(om) g(an) g(undet) n(ached) g(thr) n(ead) f +(to) g(the) g(thr) n(ead) g(which) h(joins) g(it.) 204 +3703 y(Detached) 31 b(/) h(undetached) e(thr) n(eads) h(ar) n(e) i +(distinguish) n(ed) f(on) f(cr) n(eation) h(by) g(the) f(type) g(of) 63 +3816 y(function) 24 b(they) e(execute.) 30 b(Undetached) 22 +b(thr) n(eads) h(execute) g(a) h(function) g(which) g(has) g(a) p +Fd 25 w(voi) n(d*) p Fg 63 3929 a(r) n(eturn) c(typ) n(e,) h(wher) n +(eas) f(detached) f(thr) n(eads) h(execute) f(a) j(function) f(which) g +(has) g(a) p Fd 21 w(void) p Fg 19 w(r) n(eturn) 63 4042 +y(typ) n(e.) 52 b(Unfortunate) n(ly) 31 b(C++) g(member) g(functions) f +(ar) n(e) h(not) f(allowed) g(to) g(be) h(distingu) n(ished) 63 +4155 y(simply) 26 b(by) h(their) f(r) n(eturn) g(type) n(.) 40 +b(Thus) 26 b(in) h(the) f(case) h(of) g(a) g(derived) f(class) h(of) p +Fd 26 w(omni_) n(thre) n(ad) p Fg 63 4268 a(which) 20 +b(needs) e(an) j(undet) n(ached) f(thr) n(ead,) g(the) f(member) h +(function) g(execute) n(d) g(by) g(the) f(thr) n(ead) g(is) 63 +4380 y(called) p Fd 19 w(run_u) n(ndet) n(ache) n(d\(\)) p +Fg 18 w(rather) f(than) p Fd 19 w(run\() n(\)) p Fg(,) h(and) g(it) g +(is) g(started) e(by) i(calli) r(ng) p Fd 18 w(star) n(t_) 63 +4493 y(und) n(etac) n(hed\(\)) p Fg 21 w(instead) j(of) p +Fd 22 w(start) n(\(\)) p Fg(.) 204 4610 y(The) i(abstraction) i(curr) n +(ently) e(suppo) n(rts) h(thr) n(ee) f(priorities) g(of) h(thr) n(ead,) +g(but) g(no) g(guarantee) 63 4722 y(is) 33 b(made) g(of) h(how) f(this) +g(will) h(af) n(f) r(ect) f(underlying) f(thr) n(ead) h(scheduling.) 59 +b(The) 33 b(thr) n(ee) f(priori-) 63 4835 y(ties) 18 +b(ar) n(e) p Fd 20 w(PRIO) n(RITY) n(_LOW) p Fg(,) p +Fd 18 w(PRIO) n(RITY) n(_NOR) n(MAL) p Fg 19 w(and) p +Fd 19 w(PRIO) n(RITY) n(_HIG) n(H) p Fg(.) h(By) g(default) g(all) 63 +4948 y(thr) n(eads) i(r) o(un) i(at) p Fd 23 w(PRIO) n(RITY) n(_NORM) n +(AL) p Fg(.) f(A) g(dif) n(fer) n(ent) h(priority) f(can) i(be) e +(speci\002ed) g(on) g(thr) n(ead) 63 5061 y(cr) n(eation,) h(or) f +(while) h(the) f(thr) n(ead) g(is) h(r) o(unning) g(using) p +Fd 22 w(set_) n(prio) n(rity\() n(\).) p Fg 28 w(A) g(thr) n(ead's) f +(cur) n(-) 63 5174 y(r) n(ent) g(priority) g(is) g(r) n(eturned) f(by) p +Fd 23 w(pri) n(ority) n(\(\)) p Fg(.) 204 5290 y(Other) d(functions) g +(pr) n(ovided) g(ar) n(e) p Fd 19 w(sel) n(f\(\)) p Fg +18 w(which) h(r) n(eturns) e(the) h(calli) r(ng) g(thr) n(ead's) p +Fd 18 w(omn) n(i_) 63 5403 y(thr) n(ead) p Fg 36 w(object,) p +Fd 40 w(yie) n(ld\(\)) p Fg 35 w(which) 38 b(r) n(eques) n(ts) e(that) h +(other) e(thr) n(eads) h(be) h(allowed) g(to) f(r) o(un,) p +90 rotate dyy eop +%%Page: 4 4 +4 3 bop Fg 221 249 a(4) p Fe 1367 w(6) 91 b(THRE) n(ADED) 23 +b(I/O) g(SHUTDOWN) f(FOR) g(UNIX) p Fd 221 548 a(id\(\)) p +Fg 27 w(which) 29 b(r) n(eturns) e(an) i(intege) n(r) g(id) f(for) h +(the) e(thr) n(ead) h(for) g(use) g(in) h(debug) n(ging,) p +Fd 29 w(state) n(\(\)) p Fg(,) p Fd 221 661 a(slee) n(p\(\)) p +Fg 22 w(and) p Fd 22 w(get_t) n(ime\() n(\)) p Fg(.) p +Fh 221 953 a(4) 119 b(Per) n(-threa) n(d) 30 b(data) p +Fg 221 1164 a(omnithr) n(ead) 22 b(suppo) n(rts) g(per) n(-thr) n(ead) f +(data,) h(via) i(member) e(functions) f(of) i(the) p +Fd 21 w(omni) n(_thr) n(ead) p Fg 221 1277 a(object.) 362 +1390 y(First,) d(you) g(must) h(allocate) h(a) f(key) f(for) g(with) h +(the) p Fd 20 w(omni) n(_thre) n(ad::) n(allo) n(cate_) n(key\() n(\)) p +Fg 221 1502 a(function.) 28 b(Then,) 21 b(any) h(object) g(whose) f +(class) h(is) g(derived) f(fr) n(om) p Fd 23 w(omni) n(_thr) n(ead::) n +(valu) n(e_t) p Fg 221 1615 a(can) 27 b(be) f(stor) n(e) n(d) g(using) f +(the) p Fd 26 w(set) n(_val) n(ue\(\)) p Fg 25 w(function.) 38 +b(V) -8 b(alues) 25 b(ar) n(e) h(r) n(etrieved) f(or) h(r) n(emoved) 221 +1728 y(with) p Fd 23 w(get) n(_valu) n(e\(\)) p Fg 21 +w(and) p Fd 23 w(remo) n(ve_v) n(alue\() n(\)) p Fg 22 +w(r) n(espectively) -10 b(.) 362 1841 y(When) 23 b(the) g(thr) n(ead) g +(exits,) g(all) i(per) n(-thr) n(ead) e(data) h(is) g(delet) n(ed) f +(\(hence) h(the) e(base) i(class) g(with) 221 1954 y(virtual) g(dest) n +(r) o(uctor\).) 362 2067 y(Note) 17 b(that) i(the) f(per) n(-thr) n +(ead) f(data) i(functions) f(ar) n(e) p Fb 19 w(not) p +Fg 18 w(thr) n(ead) g(safe,) i(so) d(although) i(you) e(can) 221 +2180 y(access) 29 b(one) e(thr) n(ead's) h(storage) f(fr) n(om) i +(another) f(thr) n(ead,) h(ther) n(e) e(is) i(no) f(concurr) n(ency) g +(contr) n(ol.) 221 2293 y(Unless) j(you) g(r) n(eall) r(y) h(know) f +(what) h(you) f(ar) n(e) i(doing,) g(it) g(is) f(best) f(to) h(only) g +(access) g(per) n(-thr) n(ead) 221 2406 y(data) 23 b(fr) n(om) g(the) f +(thr) n(ead) g(it) h(is) g(attached) f(to.) p Fh 221 +2698 a(5) 119 b(Using) 31 b(OMNI) d(threads) h(in) h(your) g(program) p +Fg 221 2909 a(Obvi) r(ously) 16 b(you) h(need) g(to) g(include) h(the) p +Fd 16 w(omnit) n(hrea) n(d.h) p Fg 17 w(header) e(\002le) i(in) g(your) +f(sour) n(ce) g(code,) 221 3021 y(and) 25 b(link) g(in) h(the) e +(omnithr) n(ead) g(libra) r(ry) g(with) h(your) f(execut) n(abl) r(e.) +34 b(Because) 23 b(ther) n(e) h(is) h(a) g(single) p +Fd 221 3134 a(omni) n(threa) n(d.h) p Fg 30 w(for) 32 +b(all) h(platforms,) h(certain) e(pr) n(epr) n(oces) n(sor) f +(de\002nes) f(must) h(be) g(given) h(as) 221 3247 y(compiler) 25 +b(options) n(.) 33 b(The) 23 b(easiest) g(way) h(to) g(do) f(this) h +(is) g(to) g(stud) n(y) g(the) g(make\002les) f(given) h(in) h(the) 221 +3360 y(examples) i(pr) n(ovided) g(with) g(this) g(distribution.) 42 +b(If) 27 b(you) g(ar) n(e) g(to) g(include) h(OMNI) f(thr) n(eads) g +(in) 221 3473 y(your) 18 b(own) g(development) g(envir) n(onment,) h +(thes) n(e) g(ar) n(e) g(the) f(necessary) g(pr) n(epr) n(oce) n(ssor) g +(de\002nes) n(:) p 362 3567 3287 4 v 360 3680 4 113 v +412 3646 a(Platform) p 1312 3680 V 599 w(Pr) n(epr) n(ocess) n(or) 23 +b(De\002nes) p 3648 3680 V 362 3683 3287 4 v 362 3700 +V 360 3813 4 113 v 412 3779 a(Sun) f(Solaris) h(2.x) p +1312 3813 V Fd 365 w(-D__) n(suno) n(s__) 54 b(-D_) n(_spa) n(rc__) f +(-D__) n(OSVER) n(SION) n(__=5) p 3648 3813 V 360 3926 +V 1312 3926 V 1363 3892 a(-DSV) n(R4) h(-DUs) n(ePth) n(read) f(-D_R) n +(EENT) n(RANT) p 3648 3926 V 362 3929 3287 4 v 360 4042 +4 113 v Fg 412 4008 a(x86) 24 b(Linux) e(2.0) p 1312 +4042 V Fd 418 w(-D__) n(linu) n(x__) 54 b(-D_) n(_i86) n(__) g(-D__) n +(OSVE) n(RSION) n(__=2) p 3648 4042 V 360 4155 V Fg 412 +4121 a(with) 23 b(linuxthr) n(eads) f(0.5) p 1312 4155 +V Fd 100 w(-D_R) n(EENT) n(RANT) p 3648 4155 V 362 4158 +3287 4 v 360 4271 4 113 v Fg 412 4237 a(Digital) i(Unix) f(3.2) p +1312 4271 V Fd 320 w(-D__) n(osf1) n(__) 54 b(-D__) n(alph) n(a__) g +(-D_) n(_OSV) n(ERSIO) n(N__=) n(3) p 3648 4271 V 360 +4384 V 1312 4384 V 1363 4350 a(-D_R) n(EENT) n(RANT) p +3648 4384 V 362 4387 3287 4 v 360 4500 4 113 v Fg 412 +4466 a(W) -5 b(indows) 22 b(NT) p 1312 4500 V Fd 411 +w(-D__) n(NT__) 53 b(-MD) p 3648 4500 V 362 4503 3287 +4 v Fh 221 4740 a(6) 119 b(Threaded) 29 b(I/O) g(shutdown) h(for) g +(Unix) p Fg 221 4951 a(or) -7 b(,) 20 b(how) e(one) g(thr) n(ead) h +(shou) n(ld) h(tell) f(another) f(thr) n(ead) g(to) h(shut) f(down) g +(when) g(it) h(might) g(be) g(doing) 221 5064 y(a) k(blocking) g(cal) r +(l) g(on) f(a) h(socket) n(.) p Fb 362 5177 a(If) h(you) e(are) i +(using) e(omniOR) n(B,) h(you) e(don') n(t) i(need) g(to) g(worry) f +(about) g(all) i(this,) f(since) h(om-) 221 5290 y(niORB) i(does) h(it) +h(for) f(you) n(.) p Fg 41 w(This) g(section) f(is) h(only) g(r) n +(elevant) g(if) h(you) e(ar) n(e) h(using) f(omnithr) n(ead) 221 +5403 y(in) d(your) f(own) g(socket) n(-based) h(pr) n(ogramming.) k(It) +22 b(is) h(also) g(serious) n(ly) g(out) f(of) h(date.) p +90 rotate dyy eop +%%Page: 5 5 +5 4 bop Fe 63 249 a(6.1) 91 b(r) n(ead\(\)) p Fg 2800 +w(5) 204 548 y(Unfortunate) n(ly) 35 b(ther) n(e) e(doe) n(sn't) h +(seem) f(to) h(be) g(a) h(standar) n(d) e(way) i(of) f(doing) f(this) h +(which) 63 661 y(works) 19 b(acr) n(oss) i(all) i(Unix) e(syst) n(ems.) +27 b(I) 21 b(have) g(investigated) f(the) h(behaviour) g(of) g(Solaris) +h(2.5) g(and) 63 774 y(Digital) k(Unix) g(3.2.) 36 b(On) 26 +b(Digital) h(Unix) e(everyth) n(ing) h(is) f(\002ne,) g(as) h(the) e +(obvious) h(method) f(using) 63 887 y(shutd) n(own\(\)) 32 +b(seems) f(to) h(work) f(OK.) h(Unfortunately) f(on) h(Solaris) h(shut) +n(down) f(can) h(only) f(be) 63 1000 y(used) 25 b(on) h(a) h(connected) +e(socke) n(t,) i(so) f(we) g(need) f(devious) h(means) g(to) g(get) f +(ar) n(ound) h(this) g(lim) r(ita-) 63 1112 y(tion.) h(The) 22 +b(details) g(ar) n(e) h(summarised) g(below:) p Fc 63 +1429 a(6.1) 99 b(read\(\)) p Fg 63 1627 a(Thr) n(ead) 28 +b(A) h(is) g(in) h(a) g(loop,) g(doing) p Fd 28 w(rea) n(d\(soc) n(k\)) +p Fg(,) g(pr) n(ocess) n(ing) f(the) g(data,) h(then) f(going) f(back) +63 1739 y(into) 22 b(the) g(r) n(ead.) 204 1862 y(Thr) n(ead) 30 +b(B) h(comes) f(along) h(and) g(wants) f(to) g(shut) g(it) h(down) f +(\227) h(it) g(can't) g(cancel) h(thr) n(ead) f(A) 63 +1975 y(since) 21 b(\(i\)) h(working) e(out) g(how) g(to) h(clean) h(up) +e(accor) n(ding) i(to) e(wher) n(e) g(A) h(is) g(in) h(its) f(loop) f +(is) h(a) h(night-) 63 2088 y(mar) n(e,) h(and) f(\(ii\)) i(this) f +(isn't) f(ava) r(ilabl) r(e) g(in) h(omnithr) n(ead) f(anyway) -10 +b(.) 204 2211 y(On) 23 b(Solaris) g(2.5) g(and) g(Digital) h(Unix) f +(3.2) g(the) f(following) h(strate) n(gy) f(works:) 204 +2334 y(Thr) n(ead) g(B) g(does) p Fd 21 w(shut) n(down\() n(sock) n +(,2\)) p Fg(.) 204 2457 y(At) g(this) g(point) h(thr) n(ead) f(A) g(is) +h(either) f(blocked) g(inside) p Fd 23 w(rea) n(d\(so) n(ck\)) p +Fg(,) g(or) g(is) h(elsewhe) n(r) n(e) g(in) 63 2570 +y(the) 18 b(loop.) 26 b(If) 18 b(the) g(former) h(then) f(r) n(ead) h +(will) h(r) n(eturn) e(0,) i(indicating) f(that) g(the) f(socke) n(t) h +(is) g(closed.) 26 b(If) 63 2683 y(the) 21 b(latter) h(then) f +(eventually) h(thr) n(ead) g(A) g(will) i(call) p Fd +24 w(rea) n(d\(so) n(ck\)) p Fg 21 w(and) f(then) e(this) h(will) h(r) n +(eturn) 63 2796 y(0.) 28 b(Thr) n(ead) 22 b(A) h(should) p +Fd 21 w(clos) n(e\(soc) n(k\)) p Fg(,) f(do) g(any) g(other) g(tidying) +f(up,) h(and) h(exit.) 204 2919 y(If) 34 b(ther) n(e) g(is) h(another) f +(point) g(in) h(the) e(loop) i(that) f(thr) n(ead) g(A) h(can) g(block) +g(then) f(obviously) 63 3032 y(thr) n(ead) 19 b(B) h(needs) f(to) h(be) +g(awar) n(e) h(of) f(this) g(and) g(be) h(able) g(to) e(wake) h(it) h +(up) f(in) g(the) g(appr) n(opriate) g(way) 63 3145 y(fr) n(om) j(that) +f(point.) p Fc 63 3462 a(6.2) 99 b(accept\(\)) p Fg 63 +3659 a(Again) 25 b(thr) n(ead) g(A) h(is) f(in) h(a) g(loop,) g(this) f +(time) h(doing) e(an) i(acc) r(ept) e(on) h(listenSock,) g(dealing) h +(with) 63 3772 y(a) d(new) f(connection) g(and) h(going) e(back) j +(into) e(accept.) 28 b(Thr) n(ead) 22 b(B) g(wants) h(to) f(cancel) h +(it.) 204 3895 y(On) g(Digital) h(Unix) f(3.2) g(the) f(strateg) n(y) g +(is) h(identical) h(to) e(that) g(for) h(r) n(ead:) 204 +4018 y(Thr) n(ead) 39 b(B) g(does) p Fd 38 w(shut) n(down) n(\(list) n +(enSo) n(ck,2) n(\)) p Fg(.) 79 b(Wher) n(ever) 38 b(thr) n(ead) h(A) h +(is) f(in) h(the) 63 4131 y(loop,) i(eventually) c(it) h(will) h(r) n +(eturn) p Fd 38 w(ECONN) n(ABOR) n(TED) p Fg 38 w(fr) n(om) f(the) f +(accept) h(call) r(.) 76 b(It) 39 b(shou) n(ld) p Fd +63 4244 a(clo) n(se\(l) n(isten) n(Sock) n(\)) p Fg(,) 22 +b(tidy) g(up) g(as) h(necessary) e(and) i(exit.) 204 +4367 y(On) 30 b(Solaris) f(2.5) i(thr) n(ead) e(B) g(can't) h(do) p +Fd 29 w(shu) n(tdow) n(n\(lis) n(tenS) n(ock,2) n(\)) p +Fg 29 w(\227) g(this) f(r) n(eturns) p Fd 63 4480 a(ENO) n(TCON) n(N) p +Fg(.) 22 b(Instead) f(the) h(following) h(strateg) n(y) g(can) g(be) g +(used) n(:) 204 4603 y(First) 35 b(thr) n(ead) h(B) g(set) n(s) g(some) +f(sort) g(of) h("shutdo) n(wn) g(\003ag") g(associated) g(with) g +(listenSock.) 63 4716 y(Then) 31 b(it) h(does) p Fd 30 +w(gets) n(ocka) n(ddr\(l) n(iste) n(nSock) n(\)) p Fg +32 w(to) f(\002nd) g(out) g(which) i(port) e(listenSock) f(is) 63 +4828 y(on) 18 b(\(or) h(knows) e(alr) n(eady\),) j(sets) d(up) h(a) h +(socket) e(dummySock,) i(doe) n(s) p Fd 19 w(con) n(nect) n(\(dumm) n +(ySoc) n(k,) 63 4941 y(thi) n(s) 54 b(host,) f(por) n(t\)) p +Fg 22 w(and) 23 b(\002nally) g(does) p Fd 21 w(clos) n(e\(dum) n(mySo) n +(ck\)) p Fg(.) 204 5064 y(Wher) n(ever) 16 b(thr) n(ead) h(A) g(is) g +(in) h(the) e(loop,) h(eventually) g(it) h(will) g(call) p +Fd 19 w(acce) n(pt\(li) n(sten) n(Sock) n(\)) p Fg(.) 63 +5177 y(This) 35 b(will) j(r) n(eturn) d(successfully) g(with) h(a) h +(new) e(socket,) j(say) e(connSock.) 67 b(Thr) n(ead) 36 +b(A) f(then) 63 5290 y(checks) 20 b(to) h(see) f(if) i(the) f("shutd) n +(own) g(\003ag") h(is) f(set.) 26 b(If) c(not,) e(then) h(it's) g(a) h +(normal) g(connection.) 27 b(If) 21 b(it) 63 5403 y(is) h(set,) g(then) +f(thr) n(ead) h(A) h(closes) f(listenSock) f(and) i(connSock,) e +(tidies) h(up) g(and) h(exits.) p 90 rotate dyy eop +%%Page: 6 6 +6 5 bop Fg 221 249 a(6) p Fe 1367 w(6) 91 b(THRE) n(ADED) 23 +b(I/O) g(SHUTDOWN) f(FOR) g(UNIX) p Fc 221 548 a(6.3) 99 +b(write\(\)) p Fg 221 768 a(Thr) n(ead) 19 b(A) f(may) h(be) g(blocked) +f(in) i(write,) f(or) f(about) h(to) f(go) g(in) h(to) g(a) g(poten) n +(tiall) r(y-blocking) g(write.) 221 881 y(Thr) n(ead) j(B) h(wants) f +(to) g(shut) f(it) i(down.) 362 1016 y(On) g(Solaris) g(2.5:) 362 +1150 y(Thr) n(ead) f(B) h(doe) n(s) p Fd 23 w(shu) n(tdown) n(\(soc) n +(k,2\)) p Fg -2 w(.) 362 1285 y(If) c(thr) n(ead) f(A) h(is) g(alr) n +(eady) g(in) p Fd 20 w(wri) n(te\(s) n(ock\)) p Fg 17 +w(then) f(it) h(will) i(r) n(eturn) d(with) p Fd 18 w(ENXIO) p +Fg -2 w(.) h(If) g(thr) n(ead) 221 1398 y(A) k(calls) h(write) e(after) +g(thr) n(ead) g(B) h(calls) h(shut) n(down) e(this) g(will) i(r) n +(eturn) p Fd 22 w(EIO) p Fg(.) 362 1532 y(On) f(Digital) h(Unix) f +(3.2:) 362 1666 y(Thr) n(ead) f(B) h(doe) n(s) p Fd 23 +w(shu) n(tdown) n(\(soc) n(k,2\)) p Fg -2 w(.) 362 1801 +y(If) h(thr) n(ead) f(A) g(is) h(alr) n(eady) g(in) p +Fd 24 w(writ) n(e\(so) n(ck\)) p Fg 23 w(then) e(it) i(will) h(r) n +(eturn) e(the) f(number) i(of) f(bytes) 221 1914 y(written) 31 +b(befor) n(e) h(it) g(became) g(blocked.) 55 b(A) 32 +b(subseq) n(uent) f(cal) r(l) h(to) f(write) h(will) h(then) e(gene) n +(rate) p Fd 221 2027 a(SIGP) n(IPE) p Fg 22 w(\(or) p +Fd 22 w(EPIP) n(E) p Fg 23 w(will) 24 b(be) e(r) n(eturned) f(if) p +Fd 24 w(SIG) n(PIPE) p Fg 21 w(is) i(ignor) n(ed) e(by) i(the) f(thr) n +(ead\).) p Fc 221 2413 a(6.4) 99 b(connect\(\)) p Fg +221 2634 a(Thr) n(ead) 30 b(A) f(may) h(be) g(blocked) f(in) i +(connect,) g(or) e(about) h(to) f(go) g(in) i(to) e(a) h(poten) n +(tiall) r(y-blocking) 221 2747 y(connect.) d(Thr) n(ead) c(B) f(wants) g +(to) g(shut) g(it) g(down.) 362 2881 y(On) h(Digital) h(Unix) f(3.2:) +362 3016 y(Thr) n(ead) f(B) h(doe) n(s) p Fd 23 w(shu) n(tdown) n +(\(soc) n(k,2\)) p Fg -2 w(.) 362 3150 y(If) j(thr) n(ead) f(A) g(is) h +(alr) n(eady) g(in) p Fd 26 w(conn) n(ect\() n(sock) n(\)) p +Fg 26 w(then) e(it) i(will) h(r) n(eturn) e(a) h(successful) f(con-) 221 +3263 y(nection.) 54 b(Subsequ) n(ent) 31 b(r) n(eading) g(or) g +(writing) g(will) i(show) d(that) i(the) e(socket) g(has) h(been) g +(shut) 221 3376 y(down) 22 b(\(i.e.) 28 b(r) n(ead) 23 +b(r) n(eturns) e(0,) i(write) f(generate) n(s) p Fd 23 +w(SIG) n(PIPE) p Fg 21 w(or) g(r) n(eturns) p Fd 22 w(EPI) n(PE) p +Fg(\).) g(If) h(thr) n(ead) f(A) 221 3489 y(call) r(s) g(connect) g +(after) h(thr) n(ead) f(B) g(call) r(s) g(shutdo) n(wn) h(this) f(will) +i(r) n(eturn) p Fd 22 w(EIN) n(VAL) p Fg(.) 362 3623 +y(On) f(Solaris) g(2.5:) 362 3758 y(Ther) n(e) 35 b(is) h(no) f(way) g +(to) g(wake) g(up) g(a) h(thr) n(ead) f(which) h(is) g(blocked) f(in) h +(connect.) 66 b(Inst) n(ead) 221 3871 y(Solaris) 33 b(for) n(ces) g(us) +f(thr) n(ough) g(a) i(ridiculous) f(pr) n(oced) n(ur) n(e) g(whichever) +g(way) g(we) f(try) g(it.) 59 b(One) 221 3984 y(way) 23 +b(is) f(this:) 362 4118 y(First) d(thr) n(ead) h(A) g(cr) n(eates) f(a) +h(pipe) g(in) g(addition) g(to) f(the) g(socket) n(.) 27 +b(Instead) 19 b(of) h(shut) n(ting) g(down) 221 4231 +y(the) i(socket) n(,) h(thr) n(ead) f(B) g(simply) h(writes) e(a) i +(byte) f(to) g(the) g(pipe.) 362 4365 y(Thr) n(ead) 17 +b(A) g(meanwhile) h(set) n(s) f(the) g(socke) n(t) g(to) g +(non-blocking) g(mode) f(using) p Fd 17 w(fcn) n(tl\(s) n(ock,) 221 +4478 y(F_SE) n(TFL,) 53 b(O_NO) n(NBLO) n(CK\)) p Fg(.) 26 +b(Then) h(it) g(cal) r(ls) g(connect) g(on) g(the) f(socket) g(\227) h +(this) g(will) i(r) n(eturn) p Fd 221 4591 a(EINP) n(ROGRE) n(SS) p +Fg(.) k(Then) h(it) h(must) e(cal) r(l) p Fd 35 w(sel) n(ect\() n(\)) p +Fg(,) k(waiting) e(for) f(either) g(sock) g(to) f(become) 221 +4704 y(writable) 39 b(or) f(for) h(the) e(pipe) h(to) g(become) g(r) n +(eadable.) 75 b(If) 39 b(select) e(r) n(eturns) g(that) i(just) e(sock) +h(is) 221 4817 y(writable) 30 b(then) f(the) g(connection) g(has) h +(succeede) n(d.) 49 b(It) 29 b(then) g(need) n(s) h(to) f(set) f(the) h +(socket) f(back) 221 4930 y(to) i(blocking) h(mode) f(using) p +Fd 30 w(fcnt) n(l\(so) n(ck,) 54 b(F_S) n(ETFL) n(,) h(0\)) p +Fg(.) c(If) 31 b(instead) e(select) h(r) n(eturns) 221 +5043 y(that) 23 b(the) e(pipe) h(is) h(r) n(eadable,) g(thr) n(ead) f +(A) h(closes) e(the) h(socket) n(,) h(tidies) f(up) g(and) h(exits.) 362 +5177 y(An) g(alternative) h(method) e(is) i(similar) h(but) e(to) g +(use) f(polling) i(instead) e(of) i(the) e(pipe.) 29 +b(Thr) n(ead) 221 5290 y(B) 24 b(justs) e(sets) g(a) j(\003ag) f(and) g +(thr) n(ead) f(A) h(calls) h(select) e(with) g(a) i(timeout,) e(period) +n(ica) r(lly) h(waking) f(up) 221 5403 y(to) f(see) g(if) h(the) f +(\003ag) h(has) f(been) g(set.) p 90 rotate dyy eop +%%Page: 7 7 +7 6 bop Fe 63 249 a(REF) n(ERENCES) p Fg 2660 w(7) p +Fh 63 548 a(Refere) n(nces) p Fg 63 759 a([POSIX94]) p +Fa 46 w(Portable) 29 b(Operat) r(ing) f(System) g(Interface) h +(\(POSIX\)) e(Thr) n(ea) r(ds) h(Extension) p Fg(,) h(P1003) r(.1c) 245 +872 y(Draft) 23 b(10,) g(IEEE,) e(Septe) n(mber) i(1994) r(.) 63 +1059 y([Birr) n(ell89]) p Fa 47 w(An) 28 b(Intr) n(od) r(uction) g(to) h +(Pr) n(ogr) r(amming) g(with) g(Thr) n(ead) r(s) p Fg(,) h(Rese) n(ar) n +(ch) g(Repo) n(rt) e(35,) j(DEC) 245 1172 y(Syst) n(ems) 22 +b(Resear) n(ch) g(Center) -7 b(,) 22 b(Palo) h(Alto,) f(CA,) h(January) +g(1989) r(.) p 90 rotate dyy eop +%%Trailer +end +userdict /end-hook known{end-hook}if +%%EOF diff --git a/gnuradio-core/doc/other/shared_ptr_docstub.h b/gnuradio-core/doc/other/shared_ptr_docstub.h new file mode 100755 index 00000000..428dd03f --- /dev/null +++ b/gnuradio-core/doc/other/shared_ptr_docstub.h @@ -0,0 +1,24 @@ +namespace boost +{ + /*! + * \brief shared_ptr documentation stub + * + * \warning + * This isn't the real shared_ptr template. It's just enough to get doxygen + * to draw pretty collaboration diagrams. + * + * 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. + */ + +template class shared_ptr +{ +public: + + T * px; // contained pointer + +}; // shared_ptr + + +} // namespace boost diff --git a/gnuradio-core/doc/other/tv-channel-frequencies b/gnuradio-core/doc/other/tv-channel-frequencies new file mode 100644 index 00000000..e2780eca --- /dev/null +++ b/gnuradio-core/doc/other/tv-channel-frequencies @@ -0,0 +1,79 @@ +# These are the center frequencies in MHz for North American broadcast +# TV channels. Each channel is 6 MHz wide, hence the bottom edge of the +# channel is 3 MHz below the value in this table. +# +# For NTSC (Analog) TV, the picture carrier is 1.25 MHz up from the +# bottom edge. NTSC has the FM audio at bottom + 5.75 and the spike is easily +# visible. +# +# For ATSC, the pilot tone is 0.31 MHz up from the bottom. +# +# + 2 57.00 + 3 63.00 + 4 69.00 + 5 79.00 + 6 85.00 + 7 177.00 + 8 183.00 + 9 189.00 + 10 195.00 + 11 201.00 + 12 207.00 + 13 213.00 + 14 473.00 + 15 479.00 + 16 485.00 + 17 491.00 + 18 497.00 + 19 503.00 + 20 509.00 + 21 515.00 + 22 521.00 + 23 527.00 + 24 533.00 + 25 539.00 + 26 545.00 + 27 551.00 + 28 557.00 + 29 563.00 + 30 569.00 + 31 575.00 + 32 581.00 + 33 587.00 + 34 593.00 + 35 599.00 + 36 605.00 + 37 611.00 + 38 617.00 + 39 623.00 + 40 629.00 + 41 635.00 + 42 641.00 + 43 647.00 + 44 653.00 + 45 659.00 + 46 665.00 + 47 671.00 + 48 677.00 + 49 683.00 + 50 689.00 + 51 695.00 + 52 701.00 + 53 707.00 + 54 713.00 + 55 719.00 + 56 725.00 + 57 731.00 + 58 737.00 + 59 743.00 + 60 749.00 + 61 755.00 + 62 761.00 + 63 767.00 + 64 773.00 + 65 779.00 + 66 785.00 + 67 791.00 + 68 797.00 + 69 803.00 diff --git a/gnuradio-core/doc/other/vector_docstub.h b/gnuradio-core/doc/other/vector_docstub.h new file mode 100644 index 00000000..139ce651 --- /dev/null +++ b/gnuradio-core/doc/other/vector_docstub.h @@ -0,0 +1,16 @@ +namespace std +{ + /*! + * \brief vector documentation stub + * + * \warning + * This isn't the real vector template. It's just enough to get doxygen + * to draw pretty collaboration diagrams. + */ + template class vector + { + public: + T *p; + }; + +} // namespace std diff --git a/gnuradio-core/doc/xml/Makefile.am b/gnuradio-core/doc/xml/Makefile.am new file mode 100644 index 00000000..848a4685 --- /dev/null +++ b/gnuradio-core/doc/xml/Makefile.am @@ -0,0 +1,25 @@ +# +# 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. +# + +EXTRA_DIST = README doxy2swig.py swig.xsl + +CLEANFILES = *.xml combine.xslt compound.xsd index.xsd + diff --git a/gnuradio-core/doc/xml/README b/gnuradio-core/doc/xml/README new file mode 100644 index 00000000..317dbb4e --- /dev/null +++ b/gnuradio-core/doc/xml/README @@ -0,0 +1,129 @@ +# +# 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. +# + +# +# Generating Python docstrings from C++ code using doxygen +# + +There are at least two strategies for this: + - use xsltproc as described below + - use doxy2swig.py (included in this directory) + +FIXME: get one of these working (probably doxy2swig since it doesn't +add any additional dependencies). + +---------------------------------------------------------------- + +Note: Robin's patch is in SWIG >= 1.3.23 + +-------------------------------------------------------------------------------- +From: http://mailman.cs.uchicago.edu/pipermail/swig/2004-October/010604.html + +> I applied the docstring patch. '%feature("autodoc",1");' is working as +> expected ... + +[problem solved. ...] + +> I can not agree more with the doxygen idea. I am using doxygen for +> documentation and I have been trying to put doxygen output to the +> python interface. Automatic generation of %feature("docstring") lines +> from doxygen output is the closest solution I can think of but the +> workload is still pretty big. How I wish this feature can be +> implemented in the near future. + +I have successfully extracted function/class description from doxygen +generated xml files, using an xslt script. To add doxygen generated +description to each class/function, you will need to (tested under +linux, note that this works only for Python, using Robin's docstring +patch) + +1. download swig source, apply Robin's docstring patch from + https://sourceforge.net/tracker/index.php?func=detail&aid=1023309&group_id=1645&atid=301645 + compile and install + +2. generate doxygen document with option "GENERATE_XML = YES" + +3. copy the attached script (save as swig.xsl) to the doc/xml directory + and run + + > xsltproc swig.xsl index.xml > temp_doc.i + > cat temp_doc.i | sed 's/"/\\"/g' | sed 's/__QuOtE__/"/g' > swig_doc.i + + you will get an interface file with lines like + %feature("docstring") class "class description"; + %feature("docstring") class::function "member function + description"; + + the second step is necessary since there might be " in descriptions + and I need to backquote them before I replace __QuOtE__ by real + quotes. (xslt experts may know how to post-process and + make the script easier to use.) + +4. in your interface file, add + %include "siwg_doc.i" + %feature("autodoc","1") ; + +Hope this helps. + +swig.xsl: +========================================================= + + + + + + + + + + + + + + %feature(__QuOtE__docstring__QuOtE__) + + __QuOtE__ + + + + see also: + + __QuOtE__; + + + + %feature(__QuOtE__docstring__QuOtE__) :: + __QuOtE__ + + + + + __QuOtE__; + + + + + +-- +Bo Peng \ No newline at end of file diff --git a/gnuradio-core/doc/xml/doxy2swig.py b/gnuradio-core/doc/xml/doxy2swig.py new file mode 100644 index 00000000..1e379d94 --- /dev/null +++ b/gnuradio-core/doc/xml/doxy2swig.py @@ -0,0 +1,371 @@ +#!/usr/bin/env python +"""Doxygen XML to SWIG docstring converter. + +Converts Doxygen generated XML files into a file containing docstrings +that can be used by SWIG-1.3.x. Note that you need to get SWIG +version > 1.3.23 or use Robin Dunn's docstring patch to be able to use +the resulting output. + +Usage: + + doxy2swig.py input.xml output.i + +input.xml is your doxygen generated XML file and output.i is where the +output will be written (the file will be clobbered). + +""" + +# This code is implemented using Mark Pilgrim's code as a guideline: +# http://www.faqs.org/docs/diveintopython/kgp_divein.html +# +# Author: Prabhu Ramachandran +# License: BSD style + + +from xml.dom import minidom +import re +import textwrap +import sys +import types +import os.path + + +def my_open_read(source): + if hasattr(source, "read"): + return source + else: + return open(source) + +def my_open_write(dest): + if hasattr(dest, "write"): + return dest + else: + return open(dest, 'w') + + +class Doxy2SWIG: + """Converts Doxygen generated XML files into a file containing + docstrings that can be used by SWIG-1.3.x that have support for + feature("docstring"). Once the data is parsed it is stored in + self.pieces. + + """ + + def __init__(self, src): + """Initialize the instance given a source object (file or + filename). + + """ + f = my_open_read(src) + self.my_dir = os.path.dirname(f.name) + self.xmldoc = minidom.parse(f).documentElement + f.close() + + self.pieces = [] + self.pieces.append('\n// File: %s\n'%\ + os.path.basename(f.name)) + + self.space_re = re.compile(r'\s+') + self.lead_spc = re.compile(r'^(%feature\S+\s+\S+\s*?)"\s+(\S)') + self.multi = 0 + self.ignores = ('inheritancegraph', 'param', 'listofallmembers', + 'innerclass', 'name', 'declname', 'incdepgraph', + 'invincdepgraph', 'programlisting', 'type', + 'references', 'referencedby', 'location', + 'collaborationgraph', 'reimplements', + 'reimplementedby', 'derivedcompoundref', + 'basecompoundref') + #self.generics = [] + + def generate(self): + """Parses the file set in the initialization. The resulting + data is stored in `self.pieces`. + + """ + self.parse(self.xmldoc) + + def parse(self, node): + """Parse a given node. This function in turn calls the + `parse_` functions which handle the respective + nodes. + + """ + pm = getattr(self, "parse_%s"%node.__class__.__name__) + pm(node) + + def parse_Document(self, node): + self.parse(node.documentElement) + + def parse_Text(self, node): + txt = node.data + txt = txt.replace('\\', r'\\\\') + txt = txt.replace('"', r'\"') + # ignore pure whitespace + m = self.space_re.match(txt) + if m and len(m.group()) == len(txt): + pass + else: + self.add_text(textwrap.fill(txt)) + + def parse_Element(self, node): + """Parse an `ELEMENT_NODE`. This calls specific + `do_` handers for different elements. If no handler + is available the `generic_parse` method is called. All + tagNames specified in `self.ignores` are simply ignored. + + """ + name = node.tagName + ignores = self.ignores + if name in ignores: + return + attr = "do_%s" % name + if hasattr(self, attr): + handlerMethod = getattr(self, attr) + handlerMethod(node) + else: + self.generic_parse(node) + #if name not in self.generics: self.generics.append(name) + + def add_text(self, value): + """Adds text corresponding to `value` into `self.pieces`.""" + if type(value) in (types.ListType, types.TupleType): + self.pieces.extend(value) + else: + self.pieces.append(value) + + def get_specific_nodes(self, node, names): + """Given a node and a sequence of strings in `names`, return a + dictionary containing the names as keys and child + `ELEMENT_NODEs`, that have a `tagName` equal to the name. + + """ + nodes = [(x.tagName, x) for x in node.childNodes \ + if x.nodeType == x.ELEMENT_NODE and \ + x.tagName in names] + return dict(nodes) + + def generic_parse(self, node, pad=0): + """A Generic parser for arbitrary tags in a node. + + Parameters: + + - node: A node in the DOM. + - pad: `int` (default: 0) + + If 0 the node data is not padded with newlines. If 1 it + appends a newline after parsing the childNodes. If 2 it + pads before and after the nodes are processed. Defaults to + 0. + + """ + npiece = 0 + if pad: + npiece = len(self.pieces) + if pad == 2: + self.add_text('\n') + for n in node.childNodes: + self.parse(n) + if pad: + if len(self.pieces) > npiece: + self.add_text('\n') + + def space_parse(self, node): + self.add_text(' ') + self.generic_parse(node) + + do_ref = space_parse + do_emphasis = space_parse + do_bold = space_parse + do_computeroutput = space_parse + do_formula = space_parse + + def do_compoundname(self, node): + self.add_text('\n\n') + data = node.firstChild.data + self.add_text('%%feature("docstring") %s "\n'%data) + + def do_compounddef(self, node): + kind = node.attributes['kind'].value + if kind in ('class', 'struct'): + prot = node.attributes['prot'].value + if prot <> 'public': + return + names = ('compoundname', 'briefdescription', + 'detaileddescription', 'includes') + first = self.get_specific_nodes(node, names) + for n in names: + if first.has_key(n): + self.parse(first[n]) + self.add_text(['";','\n']) + for n in node.childNodes: + if n not in first.values(): + self.parse(n) + elif kind in ('file', 'namespace'): + nodes = node.getElementsByTagName('sectiondef') + for n in nodes: + self.parse(n) + + def do_includes(self, node): + self.add_text('C++ includes: ') + self.generic_parse(node, pad=1) + + def do_parameterlist(self, node): + self.add_text(['\n', '\n', 'Parameters:', '\n']) + self.generic_parse(node, pad=1) + + def do_para(self, node): + self.add_text('\n') + self.generic_parse(node, pad=1) + + def do_parametername(self, node): + self.add_text('\n') + self.add_text("%s: "%node.firstChild.data) + + def do_parameterdefinition(self, node): + self.generic_parse(node, pad=1) + + def do_detaileddescription(self, node): + self.generic_parse(node, pad=1) + + def do_briefdescription(self, node): + self.generic_parse(node, pad=1) + + def do_memberdef(self, node): + prot = node.attributes['prot'].value + id = node.attributes['id'].value + kind = node.attributes['kind'].value + tmp = node.parentNode.parentNode.parentNode + compdef = tmp.getElementsByTagName('compounddef')[0] + cdef_kind = compdef.attributes['kind'].value + + if prot == 'public': + first = self.get_specific_nodes(node, ('definition', 'name')) + name = first['name'].firstChild.data + if name[:8] == 'operator': # Don't handle operators yet. + return + + defn = first['definition'].firstChild.data + self.add_text('\n') + self.add_text('%feature("docstring") ') + + anc = node.parentNode.parentNode + if cdef_kind in ('file', 'namespace'): + ns_node = anc.getElementsByTagName('innernamespace') + if not ns_node and cdef_kind == 'namespace': + ns_node = anc.getElementsByTagName('compoundname') + if ns_node: + ns = ns_node[0].firstChild.data + self.add_text(' %s::%s "\n%s'%(ns, name, defn)) + else: + self.add_text(' %s "\n%s'%(name, defn)) + elif cdef_kind in ('class', 'struct'): + # Get the full function name. + anc_node = anc.getElementsByTagName('compoundname') + cname = anc_node[0].firstChild.data + self.add_text(' %s::%s "\n%s'%(cname, name, defn)) + + for n in node.childNodes: + if n not in first.values(): + self.parse(n) + self.add_text(['";', '\n']) + + def do_definition(self, node): + data = node.firstChild.data + self.add_text('%s "\n%s'%(data, data)) + + def do_sectiondef(self, node): + kind = node.attributes['kind'].value + if kind in ('public-func', 'func'): + self.generic_parse(node) + + def do_simplesect(self, node): + kind = node.attributes['kind'].value + if kind in ('date', 'rcs', 'version'): + pass + elif kind == 'warning': + self.add_text(['\n', 'WARNING: ']) + self.generic_parse(node) + elif kind == 'see': + self.add_text('\n') + self.add_text('See: ') + self.generic_parse(node) + else: + self.generic_parse(node) + + def do_argsstring(self, node): + self.generic_parse(node, pad=1) + + def do_member(self, node): + kind = node.attributes['kind'].value + refid = node.attributes['refid'].value + if kind == 'function' and refid[:9] == 'namespace': + self.generic_parse(node) + + def do_doxygenindex(self, node): + self.multi = 1 + comps = node.getElementsByTagName('compound') + for c in comps: + refid = c.attributes['refid'].value + fname = refid + '.xml' + if not os.path.exists(fname): + fname = os.path.join(self.my_dir, fname) + print "parsing file: %s"%fname + p = Doxy2SWIG(fname) + p.generate() + self.pieces.extend(self.clean_pieces(p.pieces)) + + def write(self, fname): + o = my_open_write(fname) + if self.multi: + o.write("".join(self.pieces)) + else: + o.write("".join(self.clean_pieces(self.pieces))) + o.close() + + def clean_pieces(self, pieces): + """Cleans the list of strings given as `pieces`. It replaces + multiple newlines by a maximum of 2 and returns a new list. + It also wraps the paragraphs nicely. + + """ + ret = [] + count = 0 + for i in pieces: + if i == '\n': + count = count + 1 + else: + if i == '";': + if count: + ret.append('\n') + elif count > 2: + ret.append('\n\n') + elif count: + ret.append('\n'*count) + count = 0 + ret.append(i) + + _data = "".join(ret) + ret = [] + for i in _data.split('\n\n'): + if i == 'Parameters:': + ret.extend(['Parameters:\n-----------', '\n\n']) + elif i.find('// File:') > -1: # leave comments alone. + ret.extend([i, '\n']) + else: + _tmp = textwrap.fill(i.strip()) + _tmp = self.lead_spc.sub(r'\1"\2', _tmp) + ret.extend([_tmp, '\n\n']) + return ret + + +def main(input, output): + p = Doxy2SWIG(input) + p.generate() + p.write(output) + + +if __name__ == '__main__': + if len(sys.argv) != 3: + print __doc__ + sys.exit(1) + main(sys.argv[1], sys.argv[2]) diff --git a/gnuradio-core/doc/xml/swig.xsl b/gnuradio-core/doc/xml/swig.xsl new file mode 100644 index 00000000..6163c2d9 --- /dev/null +++ b/gnuradio-core/doc/xml/swig.xsl @@ -0,0 +1,38 @@ + + + + + + + + + + + + + %feature(__QuOtE__docstring__QuOtE__) + + __QuOtE__ + + + + see also: + + __QuOtE__; + + + + %feature(__QuOtE__docstring__QuOtE__) :: + __QuOtE__ + + + + + __QuOtE__; + + + + diff --git a/gnuradio-core/gnuradio-core.conf b/gnuradio-core/gnuradio-core.conf new file mode 100644 index 00000000..d64f5840 --- /dev/null +++ b/gnuradio-core/gnuradio-core.conf @@ -0,0 +1,19 @@ +# This file contains system wide configuration data for GNU Radio. +# You may override any setting on a per-user basis by editing +# ~/.gnuradio/config.conf + +[DEFAULT] + +verbose = False + + +[audio] + +# specify which audio module to load, or use "auto" to have the system +# select one. Valid choices depend on your OS and which modules +# you've installed, but typically include: auto, audio_alsa, +# audio_oss, audio_portaudio, audio_jack, audio_osx, audio_windows + +audio_module = auto + + diff --git a/gnuradio-core/gnuradio-core.pc.in b/gnuradio-core/gnuradio-core.pc.in new file mode 100644 index 00000000..cc6c03ac --- /dev/null +++ b/gnuradio-core/gnuradio-core.pc.in @@ -0,0 +1,11 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@/gnuradio + +Name: gnuradio-core +Description: GNU Software Radio toolkit +Requires: +Version: @VERSION@ +Libs: -L${libdir} -lgnuradio-core @FFTW3F_LIBS@ +Cflags: -I${includedir} @DEFINES@ @PTHREAD_CFLAGS@ diff --git a/gnuradio-core/src/Makefile.am b/gnuradio-core/src/Makefile.am new file mode 100644 index 00000000..8d00ccae --- /dev/null +++ b/gnuradio-core/src/Makefile.am @@ -0,0 +1,26 @@ +# +# 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 + +SUBDIRS = gen_interpolator_taps lib tests python + +DIST_SUBDIRS = gen_interpolator_taps lib tests python utils diff --git a/gnuradio-core/src/gen_interpolator_taps/Makefile.am b/gnuradio-core/src/gen_interpolator_taps/Makefile.am new file mode 100644 index 00000000..fff6372c --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/Makefile.am @@ -0,0 +1,33 @@ +# +# 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 + +EXTRA_DIST = praxis.txt simpson.h + +if ENABLE_FORTRAN +noinst_PROGRAMS = gen_interpolator_taps +noinst_HEADERS = simpson.h + +gen_interpolator_taps_SOURCES = gen_interpolator_taps.c objective_fct.c simpson.c praxis.f +gen_interpolator_taps_LDADD = $(FLIBS) -lm + +endif diff --git a/gnuradio-core/src/gen_interpolator_taps/README b/gnuradio-core/src/gen_interpolator_taps/README new file mode 100644 index 00000000..cc2f1ac8 --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/README @@ -0,0 +1,47 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 file contains the source for gen_interpolator_taps, a program +which generates optimal interpolator taps for a fractional +interpolator. + +The ideal interpolator requires an infinite tap FIR filter to +realize. We design a separate 8 tap filter for each value of mu, +the fractional delay, that we are interested in. The taps are +selected such that the mean squared error between the ideal frequency +response and the approximation is mininimized over all frequencies of +interest. In this implementation we define ``frequencies of +interest'' as those from -B to +B, where B = 1/(4*Ts), where Ts is the +sampling period. + +For a detailed look at what this is all about, please see Chapter 9 of +"Digital Communication Receivers: Synchronization, Channel Estimation +and Signal Processing" by Meyr, Moeneclaey and Fechtel, ISBN 0-471-50275-8 + +NOTE, if you're running gen_interpolator_taps and it seg faults in +RANDOM, you're probably using g77-2.96. The fix is to use g77 3.0 or later + + cd + rm config.cache + export F77=g77-3.0.4 + ./configure + make diff --git a/gnuradio-core/src/gen_interpolator_taps/gen_interpolator_taps.c b/gnuradio-core/src/gen_interpolator_taps/gen_interpolator_taps.c new file mode 100644 index 00000000..0dd05651 --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/gen_interpolator_taps.c @@ -0,0 +1,186 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU 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 +#include +#include + +#define NSTEPS 10 // how many steps of mu are in the generated table +#define MAX_NSTEPS 256 +#define NTAPS 8 // # of taps in the interpolator +#define MAX_NTAPS 128 + +extern void initpt (double x[], int ntaps); +extern double objective (double x[], int *ntaps); +extern double global_mu; +extern double global_B; + +// fortran +extern double prax2_ (double (fct)(double x[], int *ntaps), + double initv[], int *ntaps, double result[]); + +static void +usage (char *name) +{ + fprintf (stderr, "usage: %s [-v] [-n ] [-t ] [-B ]\n", name); + exit (1); +} + +static void +printline (double x[], int ntaps, int imu, int nsteps) +{ + int i; + + printf (" { "); + for (i = 0; i < ntaps; i++){ + printf ("%12.5e", x[i]); + if (i != ntaps - 1) + printf (", "); + else + printf (" }, // %3d/%d\n", imu, nsteps); + } +} + +int +main (int argc, char **argv) +{ + double xx[MAX_NSTEPS+1][MAX_NTAPS]; + int ntaps = NTAPS; + int nsteps = NSTEPS; + int i, j; + double result; + double step_size; + int c; + int verbose = 0; + + global_B = 0.25; + + while ((c = getopt (argc, argv, "n:t:B:v")) != EOF){ + switch (c){ + case 'n': + nsteps = strtol (optarg, 0, 0); + break; + + case 't': + ntaps = strtol (optarg, 0, 0); + break; + + case 'B': + global_B = strtod (optarg, 0); + break; + + case 'v': + verbose = 1; + break; + + default: + usage (argv[0]); + break; + } + } + + if ((nsteps & 1) != 0){ + fprintf (stderr, "%s: nsteps must be even\n", argv[0]); + exit (1); + } + + if (nsteps > MAX_NSTEPS){ + fprintf (stderr, "%s: nsteps must be < %d\n", argv[0], MAX_NSTEPS); + exit (1); + } + + if ((ntaps & 1) != 0){ + fprintf (stderr, "%s: ntaps must be even\n", argv[0]); + exit (1); + } + + if (nsteps > MAX_NTAPS){ + fprintf (stderr, "%s: ntaps must be < %d\n", argv[0], MAX_NTAPS); + exit (1); + } + + if (global_B < 0 || global_B > 0.5){ + fprintf (stderr, "%s: bandwidth must be in the range (0, 0.5)\n", argv[0]); + exit (1); + } + + step_size = 1.0/nsteps; + + // the optimizer chokes on the two easy cases (0/N and N/N). We do them by hand... + + for (i = 0; i < ntaps; i++) + xx[0][i] = 0.0; + xx[0][ntaps/2] = 1.0; + + + // compute optimal values for mu <= 0.5 + + for (j = 1; j <= nsteps/2; j++){ + + global_mu = j * step_size; // this determines the MU for which we're computing the taps + + // initialize X to a reasonable starting value + + initpt (&xx[j][0], ntaps); + + // find the value of X that minimizes the value of OBJECTIVE + + result = prax2_ (objective, &xx[j][0], &ntaps, &xx[j][0]); + + if (verbose){ + fprintf (stderr, "Mu: %10.8f\t", global_mu); + fprintf (stderr, "Objective: %g\n", result); + } + } + + // now compute remaining values via symmetry + + for (j = 0; j < nsteps/2; j++){ + for (i = 0; i < ntaps; i++){ + xx[nsteps - j][i] = xx[j][ntaps-i-1]; + } + } + + // now print out the table + + printf ("\ +/*\n\ + * This file was machine generated by gen_interpolator_taps.\n\ + * DO NOT EDIT BY HAND.\n\ + */\n\n"); + + + printf ("static const int NTAPS = %4d;\n", ntaps); + printf ("static const int NSTEPS = %4d;\n", nsteps); + printf ("static const double BANDWIDTH = %g;\n\n", global_B); + + printf ("static const float taps[NSTEPS+1][NTAPS] = {\n"); + printf (" // -4 -3 -2 -1 0 1 2 3 mu\n"); + + + for (i = 0; i <= nsteps; i++) + printline (xx[i], ntaps, i, nsteps); + + printf ("};\n\n"); + + return 0; +} diff --git a/gnuradio-core/src/gen_interpolator_taps/objective_fct.c b/gnuradio-core/src/gen_interpolator_taps/objective_fct.c new file mode 100644 index 00000000..aab0008e --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/objective_fct.c @@ -0,0 +1,124 @@ +/* -*- c -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU 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 MMSE FIR interpolation table values + */ + +#include +#include +#include "simpson.h" + +#define MU 0.5 /* the MU for which we're computing coeffs */ + +#define Ts (1.0) /* sampling period */ +#define B (1.0/(4*Ts)) /* one-sided signal bandwidth */ +//#define B (1.0/(8./3*Ts)) /* one-sided signal bandwidth */ + +static unsigned global_n; +static double *global_h; +double global_mu = MU; +double global_B = B; + +/* + * This function computes the difference squared between the ideal + * interpolator frequency response at frequency OMEGA and the + * approximation defined by the FIR coefficients in global_h[] + * + * See eqn (9-7), "Digital Communication Receivers", Meyr, Moeneclaey + * and Fechtel, Wiley, 1998. + */ + +static double +integrand (double omega) +{ + double real_ideal; + double real_approx; + double real_diff; + double imag_ideal; + double imag_approx; + double imag_diff; + + int i, n; + int I1; + double *h; + + real_ideal = cos (omega * Ts * global_mu); + imag_ideal = sin (omega * Ts * global_mu); + + n = global_n; + h = global_h; + I1 = -(n / 2); + + real_approx = 0; + imag_approx = 0; + + for (i = 0; i < n; i++){ + real_approx += h[i] * cos (-omega * Ts * (i + I1)); + imag_approx += h[i] * sin (-omega * Ts * (i + I1)); + } + + real_diff = real_ideal - real_approx; + imag_diff = imag_ideal - imag_approx; + + return real_diff * real_diff + imag_diff * imag_diff; +} + +/* + * Integrate the difference squared over all frequencies of interest. + */ +double +c_fcn (double *x, int n) +{ + assert ((n & 1) == 0); /* assert n is even */ + global_n = n; + global_h = x; + return qsimp (integrand, -2 * M_PI * global_B, 2 * M_PI * global_B); +} + +/* this is the interface expected by the calling fortran code */ + +double +objective (double x[], int *ndim) +{ + return c_fcn (x, *ndim); +} + +static double +si (double x) +{ + if (fabs (x) < 1e-9) + return 1.0; + + return sin(x) / x; +} + +/* + * starting guess for optimization + */ +void initpt (double x[], int ndim) +{ + int i; + for (i = 0; i < ndim; i++){ + x[i] = si (M_PI * ((double) (i - ndim/2) + global_mu)); + } +} diff --git a/gnuradio-core/src/gen_interpolator_taps/praxis.f b/gnuradio-core/src/gen_interpolator_taps/praxis.f new file mode 100644 index 00000000..1b648b9b --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/praxis.f @@ -0,0 +1,1705 @@ +C +C Copyright 2002 Free Software Foundation, Inc. +C +C This file is part of GNU Radio +C +C GNU Radio is free software; you can redistribute it and/or modify +C it under the terms of the GNU General Public License as published by +C the Free Software Foundation; either version 2, or (at your option) +C any later version. +C +C GNU Radio is distributed in the hope that it will be useful, +C but WITHOUT ANY WARRANTY; without even the implied warranty of +C MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +C GNU General Public License for more details. +C +C You should have received a copy of the GNU General Public License +C along with GNU Radio; see the file COPYING. If not, write to +C the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +C Boston, MA 02111-1307, USA. +C + DOUBLE PRECISION FUNCTION PRAX2(F,INITV,NDIM,OUT) + DOUBLE PRECISION INITV(128),OUT(128), F + INTEGER NDIM + EXTERNAL F +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + +C + N=NDIM + do 10 I=1,N + 10 X(I) = INITV(I) + +C + call praset + +C -1 produces no diagnostic output + jprint = -1 + nfmax = 3000 +C tighter tolerance + T=1.0D-6 +C + call praxis(f) +C + do 30 I=1,N + 30 OUT(I) = X(I) +C + prax2 = fx + return + end + + + SUBROUTINE PRASET +C +C PRASET 1.0 JUNE 1995 +C +C SET INITIAL VALUES FOR SOME QUANTITIES USED IN SUBROUTINE PRAXIS. +C THE USER CAN RESET THESE, IF DESIRED, +C AFTER CALLING PRASET AND BEFORE CALLING PRAXIS. +C +C J. P. CHANDLER, COMPUTER SCIENCE DEPARTMENT, +C OKLAHOMA STATE UNIVERSITY +C +C ON MANY MACHINES, SUBROUTINE PRAXIS WILL CAUSE UNDERFLOW AND/OR +C DIVIDE CHECK WHEN COMPUTING EPSMCH**4 AND EPSMCH**(-4). +C IN THAT CASE, SET EPSMCH=1.0D-9 (OR POSSIBLY EPSMCH=1.0D-8) +C AFTER CALLING SUBROUTINE PRASET. +C + INTEGER N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + INTEGER J +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD + DOUBLE PRECISION A,B,XMID,XPLUS,RZERO,UNITR,RTWO +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH +C + RZERO=0.0D0 + UNITR=1.0D0 + RTWO=2.0D0 +C +C NMAX IS THE DIMENSION OF THE ARRAYS V(*,*), X(*), D(*), +C Q0(*), AND Q1(*). +C + NMAX=128 +C +C NFMAX IS THE MAXIMUM NUMBER OF FUNCTION EVALUATIONS PERMITTED. +C + NFMAX=100000 +C +C LP IS THE LOGICAL UNIT NUMBER FOR PRINTED OUTPUT. +C + LP=6 +C +C T IS A CONVERGENCE TOLERANCE USED IN SUBROUTINE PRAXIS. +C + T=1.0D-5 +C +C JPRINT CONTROLS PRINTED OUTPUT IN PRAXIS. +C + JPRINT=4 +C +C H IS AN ESTIMATE OF THE DISTANCE FROM THE INITIAL POINT +C TO THE SOLUTION. +C + H=1.0D0 +C +C USE BISECTION TO COMPUTE THE VALUE OF EPSMCH, "MACHINE EPSILON". +C EPSMCH IS THE SMALLEST FLOATING POINT (REAL OR DOUBLE PRECISION) +C NUMBER WHICH, WHEN ADDED TO ONE, GIVES A RESULT GREATER THAN ONE. +C + A=RZERO + B=UNITR + 10 XMID=A+(B-A)/RTWO + IF(XMID.LE.A .OR. XMID.GE.B) GO TO 20 + XPLUS=UNITR+XMID + IF(XPLUS.GT.UNITR) THEN + B=XMID + ELSE + A=XMID + ENDIF + GO TO 10 +C + 20 EPSMCH=B +C + DO 30 J=1,NMAX + X(J)=RZERO + 30 CONTINUE +C +C JRANCH = 1 TO USE BRENT'S RANDOM, +C JRANCH = 2 TO USE FUNCTION DRANDM. +C + JRANCH=1 +C + CALL RANINI(4.0D0) +C +C DSEED IS AN INITIAL SEED FOR DRANDM, +C A SUBROUTINE THAT GENERATES PSEUDORANDOM NUMBERS +C UNIFORMLY DISTRIBUTED ON (0,1). +C + DSEED=1234567.0D0 +C +C SCBD IS AN UPPER BOUND ON THE SCALE FACTORS IN PRAXIS. +C IF THE AXES MAY BE BADLY SCALED (WHICH IS TO BE AVOIDED IF +C POSSIBLE) THEN SET SCBD = 10, OTHERWISE 1. +C + SCBD=1.0D0 +C +C ILLCIN IS THE INITIAL VALUE OF ILLC, +C THE FLAG THAT SIGNALS AN ILL-CONDITIONED PROBLEM. +C IF THE PROBLEM IS KNOWN TO BE ILL-CONDITIONED SET ILLCIN=1, +C OTHERWISE 0. +C + ILLCIN=0 +C +C KTM IS A CONVERGENCE SWITCH USED IN PRAXIS. +C KTM+1 IS THE NUMBER OF ITERATIONS WITHOUT IMPROVEMENT +C BEFORE THE ALGORITHM TERMINATES. +C KTM=4 IS VERY CAUTIOUS. +C USUALLY KTM=1 IS SATISFACTORY. +C + KTM=1 +C + RETURN +C +C END PRASET +C + END + SUBROUTINE PRAXIS(F) +C +C PRAXIS 2.0 JUNE 1995 +C +C THE PRAXIS PACKAGE MINIMIZES THE FUNCTION F(X,N) OF N +C VARIABLES X(1),...,X(N), USING THE PRINCIPAL AXIS METHOD. +C F MUST BE A SMOOTH (CONTINUOUSLY DIFFERENTIABLE) FUNCTION. +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973 (ISBN 0-13-022335-2), +C PAGES 156-167 +C +C TRANSLATED FROM ALGOL W TO A.N.S.I. 1966 STANDARD BASIC FORTRAN +C BY ROSALEE TAYLOR AND SUE PINSKI, COMPUTER SCIENCE DEPARTMENT, +C OKLAHOMA STATE UNIVERSITY (DECEMBER 1973). +C +C UPDATED TO A.N.S.I. STANDARD FORTRAN 77 BY J. P. CHANDLER +C COMPUTER SCIENCE DEPARTMENT, OKLAHOMA STATE UNIVERSITY +C +C +C SUBROUTINE PRAXIS CALLS SUBPROGRAMS +C F, MINX, RANDOM (OR DRANDM), QUAD, MINFIT, SORT. +C +C SUBROUTINE QUAD CALLS MINX. +C +C SUBROUTINE MINX CALLS FLIN. +C +C SUBROUTINE FLIN CALLS F. +C +C +C INPUT QUANTITIES (SET IN THE CALLING PROGRAM)... +C +C F FUNCTION F(X,N) TO BE MINIMIZED +C +C X(*) INITIAL GUESS OF MINIMUM +C +C N DIMENSION OF X (NOTE... N MUST BE .GE. 2) +C +C H MAXIMUM STEP SIZE +C +C T TOLERANCE +C +C EPSMCH MACHINE PRECISION +C +C JPRINT PRINT SWITCH +C +C +C OUTPUT QUANTITIES... +C +C X(*) ESTIMATED POINT OF MINIMUM +C +C FX VALUE OF F AT X +C +C NL NUMBER OF LINEAR SEARCHES +C +C NF NUMBER OF FUNCTION EVALUATIONS +C +C V(*,*) EIGENVECTORS OF A +C NEW DIRECTIONS +C +C D(*) EIGENVALUES OF A +C NEW D +C +C Z(*) SCALE FACTORS +C +C +C ON ENTRY X(*) HOLDS A GUESS. ON RETURN IT HOLDS THE ESTIMATED +C POINT OF MINIMUM, WITH (HOPEFULLY) +C ABS(ERROR) LESS THAN SQRT(EPSMCH)*ABS(X) + T, WHERE +C EPSMCH IS THE MACHINE PRECISION, THE SMALLEST NUMBER SUCH THAT +C (1 + EPSMCH) IS GREATER THAN 1. +C +C T IS A TOLERANCE. +C +C H IS THE MAXIMUM STEP SIZE, SET TO ABOUT THE MAXIMUM EXPECTED +C DISTANCE FROM THE GUESS TO THE MINIMUM. IF H IS SET TOO +C SMALL OR TOO LARGE THEN THE INITIAL RATE OF CONVERGENCE WILL +C BE SLOW. +C +C THE USER SHOULD OBSERVE THE COMMENT ON HEURISTIC NUMBERS +C AT THE BEGINNING OF THE SUBROUTINE. +C +C JPRINT CONTROLS THE PRINTING OF INTERMEDIATE RESULTS. +C IT USES SUBROUTINES FLIN, MINX, QUAD, SORT, AND MINFIT. +C IF JPRINT = 1, F IS PRINTED AFTER EVERY N+1 OR N+2 LINEAR +C MINIMIZATIONS, AND FINAL X IS PRINTED, BUT INTERMEDIATE +C X ONLY IF N IS LESS THAN OR EQUAL TO 4. +C IF JPRINT = 2, EIGENVALUES OF A AND SCALE FACTORS ARE ALSO PRINTED. +C IF JPRINT = 3, F AND X ARE PRINTED AFTER EVERY FEW LINEAR +C MINIMIZATIONS. +C IF JPRINT = 4, EIGENVECTORS ARE ALSO PRINTED. +C IF JPRINT = 5, ADDITIONAL DEBUGGING INFORMATION IS ALSO PRINTED. +C +C RANDOM RETURNS A RANDOM NUMBER UNIFORMLY DISTRIBUTED IN (0, 1). +C +C THIS SUBROUTINE IS MACHINE-INDEPENDENT, APART FROM THE +C SPECIFICATION OF EPSMCH. WE ASSUME THAT EPSMCH**(-4) DOES NOT +C OVERFLOW (IF IT DOES THEN EPSMCH MUST BE INCREASED), AND THAT ON +C FLOATING-POINT UNDERFLOW THE RESULT IS SET TO ZERO. +C + INTEGER N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + INTEGER ILLC,I,IK,IM,IMU,J,K,KL,KM1,KT,K2 +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD + DOUBLE PRECISION F, Y,Z,E, DABS,DSQRT,ZABS,ZSQRT,DRANDM, + * HUNDRD,HUNDTH,ONE,PT9,RHALF,TEN,TENTH,TWO,ZERO, + * DF,DLDFAC,DN,F1,XF,XL,T2,RANVAL,ARG, + * VLARGE,VSMALL,XLARGE,XLDS,FXVALU,F1VALU,S,SF,SL +C + EXTERNAL F +C + DIMENSION Y(128),Z(128),E(128) +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH +C + ZABS(ARG)=DABS(ARG) + ZSQRT(ARG)=DSQRT(ARG) +C +C INITIALIZATION... +C + RHALF=0.5D0 + ONE=1.0D0 + TENTH=0.1D0 + HUNDTH=0.01D0 + HUNDRD=100.0D0 + ZERO=0.0D0 + PT9=0.9D0 + TEN=10.0D0 + TWO=2.0D0 +C +C MACHINE DEPENDENT NUMBERS... +C +C ON MANY COMPUTERS, VSMALL WILL UNDERFLOW, +C AND COMPUTING XLARGE MAY CAUSE A DIVISION BY ZERO. +C IN THAT CASE, EPSMCH SHOULD BE SET EQUAL TO 1.0D-9 +C (OR POSSIBLY 1.0D-8) BEFORE CALLING PRAXIS. +C + SMALL=EPSMCH*EPSMCH + VSMALL=SMALL*SMALL + XLARGE=ONE/SMALL + VLARGE=ONE/VSMALL + XM2=ZSQRT(EPSMCH) + XM4=ZSQRT(XM2) +C +C HEURISTIC NUMBERS... +C +C IF THE AXES MAY BE BADLY SCALED (WHICH IS TO BE AVOIDED IF +C POSSIBLE) THEN SET SCBD = 10, OTHERWISE 1. +C +C IF THE PROBLEM IS KNOWN TO BE ILL-CONDITIONED SET ILLC = 1, +C OTHERWISE 0. +C +C KTM+1 IS THE NUMBER OF ITERATIONS WITHOUT IMPROVEMENT +C BEFORE THE ALGORITHM TERMINATES. +C KTM=4 IS VERY CAUTIOUS. +C USUALLY KTM=1 IS SATISFACTORY. +C +C BRENT RECOMMENDED THE FOLLOWING VALUES FOR MOST PROBLEMS... +C +C SCBD=1.0 +C ILLC=0 +C KTM=1 +C +C SCBD, ILLCIN, AND KTM ARE NOW IN COMMON. +C THEY ARE INITIALIZED IN SUBROUTINE PRASET, +C AND CAN BE RESET BY THE USER AFTER CALLING PRASET. +C + ILLC=ILLCIN +C + IF(ILLC.EQ.1) THEN + DLDFAC=TENTH + ELSE + DLDFAC=HUNDTH + ENDIF +C + KT=0 + NL=0 + NF=1 + FX=F(X,N) + QF1=FX + T=SMALL+ZABS(T) + T2=T + DMIN=SMALL + IF(H.LT.HUNDRD*T) H=HUNDRD*T + XLDT=H +C + DO 20 I=1,N + DO 10 J=1,N + V(I,J)=ZERO + 10 CONTINUE + V(I,I)=ONE + 20 CONTINUE +C + QD0=ZERO + D(1)=ZERO +C +C Q0(*) AND Q1(*) ARE PREVIOUS X(*) POINTS, +C INITIALIZED IN PRAXIS, USED IN FLIN, +C AND CHANGED IN QUAD. +C + DO 30 I=1,N + Q1(I)=X(I) +C +C Q0(*) WAS NOT INITIALIZED IN BRENT'S ALGOL PROCEDURE. +C + Q0(I)=X(I) + 30 CONTINUE +C + IF(JPRINT.GT.0) THEN + WRITE(LP,40)NL,NF,FX + 40 FORMAT(/' NL =',I10,5X,'NF =',I10/5X,'FX =',1PG15.7) +C + IF(N.LE.4 .OR. JPRINT.GT.2) THEN + WRITE(LP,50)(X(I),I=1,N) + 50 FORMAT(/8X,'X'/(1X,1PG15.7,4G15.7)) + ENDIF + ENDIF +C +C MAIN LOOP... +C LABEL L0... +C + 60 SF=D(1) + S=ZERO + D(1)=ZERO +C +C MINIMIZE ALONG THE FIRST DIRECTION. +C + IF(JPRINT.GE.5) WRITE(LP,70)D(1),S,FX + 70 FORMAT(/' CALL NO. 1 TO MINX.'/ + * 5X,'D(1) =',1PG15.7,5X,'S =',G15.7,5X,'FX =',G15.7) +C + FXVALU=FX + CALL MINX(1,2,D(1),S,FXVALU,0,F) +C + IF(S.LE.ZERO) THEN + DO 80 I=1,N + V(I,1)=-V(I,1) + 80 CONTINUE + ENDIF +C + IF(SF.LE.PT9*D(1) .OR. PT9*SF.GE.D(1)) THEN +C + IF(N.GE.2) THEN + DO 90 I=2,N + D(I)=ZERO + 90 CONTINUE + ENDIF +C + ENDIF +C + IF(N.LT.2) GO TO 320 + DO 310 K=2,N +C + DO 100 I=1,N + Y(I)=X(I) + 100 CONTINUE +C + SF=FX + IF(KT.GT.0) ILLC=1 +C +C LABEL L1... +C + 110 KL=K + DF=ZERO +C + IF(ILLC.EQ.1) THEN +C +C TAKE A RANDOM STEP TO GET OUT OF A RESOLUTION VALLEY. +C +C PRAXIS ASSUMES THAT RANDOM (OR DRANDM) RETURNS +C A PSEUDORANDOM NUMBER UNIFORMLY DISTRIBUTED IN (0,1), +C AND THAT ANY INITIALIZATION OF THE RANDOM NUMBER GENERATOR +C HAS ALREADY BEEN DONE. +C + DO 130 I=1,N +C + IF(JRANCH.EQ.1) THEN + CALL RANDOM(RANVAL) + ELSE + RANVAL=DRANDM(DSEED) + ENDIF +C + S=(TENTH*XLDT+T2*TEN**KT)*(RANVAL-RHALF) + Z(I)=S +C + DO 120 J=1,N + X(J)=X(J)+S*V(J,I) + 120 CONTINUE + 130 CONTINUE +C + FX=F(X,N) + NF=NF+1 +C + IF(JPRINT.GE.1) WRITE(LP,140)NF,SF,FX + 140 FORMAT(/' ***** RANDOM STEP IN PRAXIS. NF =',I11/ + * 5X,'SF =',1PG15.7,5X,'FX =',G15.7) + ENDIF +C + IF(K.GT.N) GO TO 170 + DO 160 K2=K,N + SL=FX + S=ZERO +C +C MINIMIZE ALONG NON-CONJUGATE DIRECTIONS. +C + IF(JPRINT.GE.5) WRITE(LP,150)K2,D(K2),S,FX + 150 FORMAT(/' CALL NO. 2 TO MINX.'/ + * 5X,'K2 =',I4,5X,'D(K2) =',1PG15.7,5X, + * 'S =',G15.7/5X,'FX =',G15.7) +C + FXVALU=FX + CALL MINX(K2,2,D(K2),S,FXVALU,0,F) +C + IF(ILLC.EQ.1) THEN + S=D(K2)*(S+Z(K2))**2 + ELSE + S=SL-FX + ENDIF +C + IF(DF.LT.S) THEN + DF=S + KL=K2 + ENDIF + 160 CONTINUE +C + 170 IF(ILLC.EQ.0 .AND. DF.LT.ZABS(HUNDRD*EPSMCH*FX)) THEN +C +C NO SUCCESS WITH ILLC=0, SO TRY ONCE WITH ILLC=1 . +C + ILLC=1 +C +C GO TO L1. +C + GO TO 110 + ENDIF +C + IF(K.EQ.2 .AND. JPRINT.GT.1) THEN + WRITE(LP,180)(D(I),I=1,N) + 180 FORMAT(/' NEW D'/(1X,1PG15.7,4G15.7)) + ENDIF +C + KM1=K-1 + IF(KM1.LT.1) GO TO 210 + DO 200 K2=1,KM1 +C +C MINIMIZE ALONG CONJUGATE DIRECTIONS. +C + IF(JPRINT.GE.5) WRITE(LP,190)K2,D(K2),S,FX + 190 FORMAT(/' CALL NO. 3 TO MINX.'/ + * 5X,'K2 =',I4,5X,'D(K2) =',1PG15.7,5X, + * 'S =',G15.7/5X,'FX =',G15.7) +C + S=ZERO + FXVALU=FX + CALL MINX(K2,2,D(K2),S,FXVALU,0,F) + 200 CONTINUE +C + 210 F1=FX + FX=SF +C + XLDS=ZERO + DO 220 I=1,N + SL=X(I) + X(I)=Y(I) + SL=SL-Y(I) + Y(I)=SL + XLDS=XLDS+SL*SL + 220 CONTINUE +C + XLDS=ZSQRT(XLDS) + IF(XLDS.GT.SMALL) THEN +C +C THROW AWAY THE DIRECTION KL AND MINIMIZE ALONG +C THE NEW CONJUGATE DIRECTION. +C + IK=KL-1 + IF(K.GT.IK) GO TO 250 + DO 240 IM=K,IK + I=IK-IM+K +C + DO 230 J=1,N + V(J,I+1)=V(J,I) + 230 CONTINUE +C + D(I+1)=D(I) + 240 CONTINUE +C + 250 D(K)=ZERO +C + DO 260 I=1,N + V(I,K)=Y(I)/XLDS + 260 CONTINUE +C + IF(JPRINT.GE.5) WRITE(LP,270)K,D(K),XLDS,F1 + 270 FORMAT(/' CALL NO. 4 TO MINX.'/ + * 5X,'K =',I4,5X,'D(K) =',1PG15.7,5X, + * 'XLDS =',G15.7/5X,'F1 =',G15.7) +C + F1VALU=F1 + CALL MINX(K,4,D(K),XLDS,F1VALU,1,F) +C + IF(XLDS.LE.ZERO) THEN + XLDS=-XLDS +C + DO 280 I=1,N + V(I,K)=-V(I,K) + 280 CONTINUE + ENDIF + ENDIF +C + XLDT=DLDFAC*XLDT + IF(XLDT.LT.XLDS) XLDT=XLDS +C + IF(JPRINT.GT.0) THEN + WRITE(LP,40)NL,NF,FX + IF(N.LE.4 .OR. JPRINT.GT.2) THEN + WRITE(LP,50)(X(I),I=1,N) + ENDIF + ENDIF +C + T2=ZERO + DO 290 I=1,N + T2=T2+X(I)**2 + 290 CONTINUE + T2=XM2*ZSQRT(T2)+T +C +C SEE IF THE STEP LENGTH EXCEEDS HALF THE TOLERANCE. +C + IF(XLDT.GT.RHALF*T2) THEN + KT=0 + ELSE + KT=KT+1 + ENDIF +C +C IF(...) GO TO L2 +C + IF(KT.GT.KTM) GO TO 550 +C + IF(NF.GE.NFMAX) THEN + WRITE(LP,300)NFMAX + 300 FORMAT(/' IN PRAXIS, NF REACHED THE LIMIT NFMAX =',I11/ + * 5X,'THIS IS AN ABNORMAL TERMINATION.'/ + * 5X,'THE FUNCTION HAS NOT BEEN MINIMIZED AND', + * ' THE RESULTING X(*) VECTOR SHOULD NOT BE USED.') + GO TO 550 + ENDIF +C + 310 CONTINUE +C +C TRY QUADRATIC EXTRAPOLATION IN CASE WE ARE STUCK IN A CURVED VALLEY. +C + 320 CALL QUAD(F) +C + DN=ZERO + DO 330 I=1,N + D(I)=ONE/ZSQRT(D(I)) + IF(DN.LT.D(I)) DN=D(I) + 330 CONTINUE +C + IF(JPRINT.GT.3) THEN +C + WRITE(LP,340) + 340 FORMAT(/' NEW DIRECTIONS') +C + DO 360 I=1,N + WRITE(LP,350)I,(V(I,J),J=1,N) + 350 FORMAT(1X,I5,4X,1PG15.7,4G15.7/(10X,5G15.7)) + 360 CONTINUE + ENDIF +C + DO 380 J=1,N +C + S=D(J)/DN + DO 370 I=1,N + V(I,J)=S*V(I,J) + 370 CONTINUE + 380 CONTINUE +C + IF(SCBD.GT.ONE) THEN +C +C SCALE THE AXES TO TRY TO REDUCE THE CONDITION NUMBER. +C + S=VLARGE + DO 400 I=1,N +C + SL=ZERO + DO 390 J=1,N + SL=SL+V(I,J)**2 + 390 CONTINUE +C + Z(I)=ZSQRT(SL) + IF(Z(I).LT.XM4) Z(I)=XM4 + IF(S.GT.Z(I)) S=Z(I) + 400 CONTINUE +C + DO 410 I=1,N + SL=S/Z(I) + Z(I)=ONE/SL +C + IF(Z(I).GT.SCBD) THEN + SL=ONE/SCBD + Z(I)=SCBD + ENDIF +C +C IT APPEARS THAT THERE ARE TWO MISSING END; STATEMENTS +C AT THIS POINT IN BRENT'S LISTING. +C + 410 CONTINUE + ENDIF +C +C TRANSPOSE V FOR MINFIT. +C + IF(N.LT.2) GO TO 440 + DO 430 I=2,N +C + IMU=I-1 + DO 420 J=1,IMU + S=V(I,J) + V(I,J)=V(J,I) + V(J,I)=S + 420 CONTINUE + 430 CONTINUE +C +C FIND THE SINGULAR VALUE DECOMPOSITION OF V. +C THIS GIVES THE EIGENVALUES AND PRINCIPAL AXES +C OF THE APPROXIMATING QUADRATIC FORM +C WITHOUT SQUARING THE CONDITION NUMBER. +C + 440 CALL MINFIT(N,EPSMCH,VSMALL,V,D,E,NMAX,LP) +C + IF(SCBD.GT.ONE) THEN +C +C UNSCALING... +C + DO 460 I=1,N +C + S=Z(I) + DO 450 J=1,N + V(I,J)=S*V(I,J) + 450 CONTINUE + 460 CONTINUE +C + DO 490 I=1,N +C + S=ZERO + DO 470 J=1,N + S=S+V(J,I)**2 + 470 CONTINUE + S=ZSQRT(S) +C + D(I)=S*D(I) +C + S=ONE/S + DO 480 J=1,N + V(J,I)=S*V(J,I) + 480 CONTINUE + 490 CONTINUE + ENDIF +C + DO 500 I=1,N +C + IF(DN*D(I).GT.XLARGE) THEN + D(I)=VSMALL + ELSE IF(DN*D(I).LT.SMALL) THEN + D(I)=VLARGE + ELSE + D(I)=ONE/(DN*D(I))**2 + ENDIF + 500 CONTINUE +C +C SORT THE NEW EIGENVALUES AND EIGENVECTORS. +C + CALL SORT +C + DMIN=D(N) + IF(DMIN.LT.SMALL) DMIN=SMALL +C + IF(XM2*D(1).GT.DMIN) THEN + ILLC=1 + ELSE + ILLC=0 + ENDIF +C + IF(JPRINT.GT.1 .AND. SCBD.GT.ONE) THEN + WRITE(LP,510)(Z(I),I=1,N) + 510 FORMAT(/' SCALE FACTORS'/(1X,1PG15.7,4G15.7)) + ENDIF +C + IF(JPRINT.GT.1) THEN + WRITE(LP,520)(D(I),I=1,N) + 520 FORMAT(/' EIGENVALUES OF A'/(1X,1PG15.7,4G15.7)) + ENDIF +C + IF(JPRINT.GT.3) THEN +C + WRITE(LP,530) + 530 FORMAT(/' EIGENVECTORS OF A') +C + DO 540 I=1,N + WRITE(LP,350)I,(V(I,J),J=1,N) + 540 CONTINUE + ENDIF +C +C GO BACK TO THE MAIN LOOP. +C GO TO L0 +C +C HANDLE THE CASE N .EQ. 1 IN AN AD HOC WAY. +C (BRENT DID NOT PROVIDE FOR THIS CASE.) +C + IF(N.GE.2) GO TO 60 +C +C LABEL L2... +C + 550 IF(JPRINT.GT.0) THEN + WRITE(LP,560)(X(I),I=1,N) + 560 FORMAT(//7X,'X'/(1X,1PG15.7,4G15.7)) + ENDIF +C + FX=F(X,N) +C + IF(JPRINT.GE.0) WRITE(LP,570)FX,NL,NF + 570 FORMAT(/' EXIT PRAXIS. FX =',1PG25.17,5X,'NL =',I8, + * 5X,'NF =',I9) +C + RETURN +C +C END PRAXIS +C + END + SUBROUTINE QUAD(F) +C +C THIS SUBROUTINE LOOKS FOR THE MINIMUM ALONG +C A CURVE DEFINED BY Q0, Q1, AND X. +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGE 161 +C +C SUBROUTINE QUAD IS CALLED BY SUBROUTINE PRAXIS. +C + INTEGER N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + INTEGER I +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD + DOUBLE PRECISION F, DSQRT,ZSQRT,ARG, + * ONE,QA,QB,QC,S,TWO,XL,ZERO,QF1VAL +C + EXTERNAL F +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH +C + ZSQRT(ARG)=DSQRT(ARG) +C + ZERO=0.0D0 + ONE=1.0D0 +C + S=FX + FX=QF1 + QF1=S + QD1=ZERO +C + DO 10 I=1,N + S=X(I) + XL=Q1(I) + X(I)=XL + Q1(I)=S + QD1=QD1+(S-XL)**2 + 10 CONTINUE +C + QD1=ZSQRT(QD1) + XL=QD1 + S=ZERO +C + IF(QD0.GT.ZERO .AND. QD1.GT.ZERO .AND. NL.GE.3*N*N) THEN +C + IF(JPRINT.GE.1) WRITE(LP,20)NF,QD0,QD1,FX,QF1 + 20 FORMAT(/' ***** CALL MINX FROM QUAD. NF =',I11/ + * 5X,'QD0 =',1PG15.7,5X,'QD1 =',G15.7/ + * 5X,'FX =',G15.7,5X,'QF1 =',G15.7) +C + QF1VAL=QF1 + CALL MINX(0,2,S,XL,QF1VAL,1,F) + QA=XL*(XL-QD1)/(QD0*(QD0+QD1)) + QB=(XL+QD0)*(QD1-XL)/(QD0*QD1) + QC=XL*(XL+QD0)/(QD1*(QD0+QD1)) + ELSE + FX=QF1 + QA=ZERO + QB=ZERO + QC=ONE + ENDIF +C + QD0=QD1 +C + DO 30 I=1,N + S=Q0(I) + Q0(I)=X(I) + X(I)=QA*S+QB*X(I)+QC*Q1(I) + 30 CONTINUE +C + RETURN +C +C END QUAD +C + END + SUBROUTINE MINX(J,NITS,D2,X1,F1,IFK,F) +C +C SUBROUTINE MINX MINIMIZES F FROM X IN THE DIRECTION V(*,J) +C UNLESS J IS LESS THAN 1, WHEN A QUADRATIC SEARCH IS DONE IN +C THE PLANE DEFINED BY Q0, Q1, AND X. +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGES 159-160 +C +C SUBROUTINE MINX IS CALLED BY SUBROUTINES PRAXIS AND QUAD. +C +C D2 AND X1 RETURN RESULTS. +C J, NITS, F1 AND IFK ARE VALUE PARAMETERS THAT RETURN NOTHING. +C DO NOT SEND A COMMON VARIABLE TO MINX FOR PARAMETER F1. +C +C +C D2 IS AN APPROXIMATION TO HALF OF +C THE SECOND DERIVATIVE OF F (OR ZERO). +C +C X1 IS AN ESTIMATE OF DISTANCE TO MINIMUM, +C RETURNED AS THE DISTANCE FOUND. +C +C IF IFK = 1 THEN F1 IS FLIN(X1), OTHERWISE X1 AND F1 ARE +C IGNORED ON ENTRY UNLESS FINAL FX IS GREATER THAN F1. +C +C NITS CONTROLS THE NUMBER OF TIMES AN ATTEMPT IS MADE TO +C HALVE THE INTERVAL. +C + EXTERNAL F +C + INTEGER N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + INTEGER IFK,J,NITS, I,IDZ,K +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD + DOUBLE PRECISION D2,X1, + * DABS,DSQRT,ZABS,ZSQRT,ARG, + * HUNDTH,RHALF,TWO,ZERO, + * DENOM,D1,FM,F0,F1,F2,S,SF1,SX1,T2,XM,X2 +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH +C + ZSQRT(ARG)=DSQRT(ARG) + ZABS(ARG)=DABS(ARG) +C + HUNDTH=0.01D0 + ZERO=0.0D0 + TWO=2.0D0 + RHALF=0.5D0 +C + SF1=F1 + SX1=X1 + K=0 + XM=ZERO + FM=FX + F0=FX +C + IF(D2.LT.EPSMCH) THEN + IDZ=1 + ELSE + IDZ=0 + ENDIF +C +C FIND THE STEP SIZE. +C + S=ZERO + DO 10 I=1,N + S=S+X(I)**2 + 10 CONTINUE + S=ZSQRT(S) +C + IF(IDZ.EQ.1) THEN + DENOM=DMIN + ELSE + DENOM=D2 + ENDIF +C + T2=XM4*ZSQRT(ZABS(FX)/DENOM+S*XLDT)+XM2*XLDT + S=XM4*S+T + IF(IDZ.EQ.1 .AND. T2.GT.S) T2=S + IF(T2.LT.SMALL) T2=SMALL + IF(T2.GT.HUNDTH*H) T2=HUNDTH*H +C + IF(IFK.EQ.1 .AND. F1.LE.FM) THEN + XM=X1 + FM=F1 + ENDIF +C + IF(IFK.EQ.0 .OR. ZABS(X1).LT.T2) THEN +C + IF(X1.GE.ZERO) THEN + X1=T2 + ELSE + X1=-T2 + ENDIF +C + CALL FLIN(X1,J,F,F1) + ENDIF +C + IF(F1.LT.FM) THEN + XM=X1 + FM=F1 + ENDIF +C +C LABEL L0... +C + 20 IF(IDZ.EQ.1) THEN +C +C EVALUATE FLIN AT ANOTHER POINT, +C AND ESTIMATE THE SECOND DERIVATIVE. +C + IF(F0.LT.F1) THEN + X2=-X1 + ELSE + X2=TWO*X1 + ENDIF +C + CALL FLIN(X2,J,F,F2) +C + IF(F2.LE.FM) THEN + XM=X2 + FM=F2 + ENDIF +C + D2=(X2*(F1-F0)-X1*(F2-F0))/(X1*X2*(X1-X2)) +C + IF(JPRINT.GE.5) WRITE(LP,30)X1,X2,F0,F1,F2,D2 + 30 FORMAT(/' COMPUTE D2 IN SUBROUTINE MINX.'/ + * 5X,'X1 =',1PG15.7,5X,'X2 =',G15.7/ + * 5X,'F0 =',G15.7,5X,'F1 =',G15.7,5X,'F2 =',G15.7/ + * 5X,'D2 =',G15.7) + ENDIF +C +C ESTIMATE THE FIRST DERIVATIVE AT 0. +C + D1=(F1-F0)/X1-X1*D2 + IDZ=1 +C +C PREDICT THE MINIMUM. +C + IF(D2.LE.SMALL) THEN +C + IF(D1.LT.ZERO) THEN + X2=H + ELSE + X2=-H + ENDIF +C + ELSE + X2=-RHALF*D1/D2 + ENDIF +C + IF(ZABS(X2).GT.H) THEN +C + IF(X2.GT.ZERO) THEN + X2=H + ELSE + X2=-H + ENDIF + ENDIF +C +C EVALUATE F AT THE PREDICTED MINIMUM. +C LABEL L1... +C + 40 CALL FLIN(X2,J,F,F2) +C + IF(K.LT.NITS .AND. F2.GT.F0) THEN +C +C NO SUCCESS, SO TRY AGAIN. +C + K=K+1 +C +C IF(...) GO TO L0 +C + IF(F0.LT.F1 .AND. X1*X2.GT.ZERO) GO TO 20 + X2=X2/TWO +C +C GO TO L1 +C + GO TO 40 +C + ENDIF +C +C INCREMENT THE ONE-DIMENSIONAL SEARCH COUNTER. +C + NL=NL+1 +C + IF(F2.GT.FM) THEN + X2=XM + ELSE + FM=F2 + ENDIF +C +C GET A NEW ESTIMATE OF THE SECOND DERIVATIVE. +C + IF(ZABS(X2*(X2-X1)).GT.SMALL) THEN + D2=(X2*(F1-F0)-X1*(FM-F0))/(X1*X2*(X1-X2)) +C + IF(JPRINT.GE.5) WRITE(LP,50)X1,X2,F0,FM,F1,D2 + 50 FORMAT(/' RECOMPUTE D2 IN SUBROUTINE MINX.'/ + * 5X,'X1 =',1PG15.7,5X,'X2 =',G15.7/ + * 5X,'F0 =',G15.7,5X,'FM =',G15.7,5X,'F1 =',G15.7/ + * 5X,'D2 =',G15.7) +C + ELSE IF(K.GT.0) THEN + D2=ZERO +C + IF(JPRINT.GE.5) WRITE(LP,60) + 60 FORMAT(/' SET D2=0 IN SUBROUTINE MINX.') + ELSE + D2=D2 + ENDIF +C + IF(D2.LE.SMALL) THEN + D2=SMALL +C + IF(JPRINT.GE.5) WRITE(LP,70)D2 + 70 FORMAT(/' SET D2=SMALL=',1PG15.7,' IN SUBROUTINE MINX.') + ENDIF +C + IF(JPRINT.GE.5) WRITE(LP,80)X1,X2,FX,FM,SF1 + 80 FORMAT(/' SUBROUTINE MINX. X1 =',1PG15.7,5X,'X2 =',G15.7/ + * 5X,'FX =',G15.7,5X,'FM =',G15.7,5X,'SF1 =',G15.7) +C + X1=X2 + FX=FM + IF(SF1.LT.FX) THEN + FX=SF1 + X1=SX1 + ENDIF +C +C UPDATE X FOR A LINEAR SEARCH BUT NOT FOR A PARABOLIC SEARCH. +C + IF(J.GT.0) THEN +C + DO 90 I=1,N + X(I)=X(I)+X1*V(I,J) + 90 CONTINUE + ENDIF +C + IF(JPRINT.GE.5) WRITE(LP,100)D2,X1,F1,FX + 100 FORMAT(/' LEAVE SUBROUTINE MINX.'/ + * 5X,'D2 =',1PG15.7,5X,'X1 =',G15.7,5X,'F1 =',G15.7/ + * 5X,'FX =',G15.7) +C + RETURN +C +C END MINX +C + END + SUBROUTINE FLIN(XL,J,F,FLN) +C +C FLIN IS A FUNCTION OF ONE VARIABLE XL WHICH IS MINIMIZED BY +C SUBROUTINE MINX. +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGES 159-160 +C +C SUBROUTINE FLIN IS CALLED BY SUBROUTINE MINX. +C + INTEGER N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + INTEGER J, I +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD + DOUBLE PRECISION XL,F,FLN, TT, QA,QB,QC +C + DIMENSION TT(128) +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH +C + IF(J.GT.0) THEN +C +C LINEAR SEARCH... +C + DO 10 I=1,N + TT(I)=X(I)+XL*V(I,J) + 10 CONTINUE +C + ELSE +C +C SEARCH ALONG A PARABOLIC SPACE CURVE. +C + QA=XL*(XL-QD1)/(QD0*(QD0+QD1)) + QB=(XL+QD0)*(QD1-XL)/(QD0*QD1) + QC=XL*(XL+QD0)/(QD1*(QD0+QD1)) +C + DO 20 I=1,N + TT(I)=QA*Q0(I)+QB*X(I)+QC*Q1(I) + 20 CONTINUE + ENDIF +C +C INCREMENT FUNCTION EVALUATION COUNTER. +C + NF=NF+1 + FLN=F(TT,N) +C + RETURN +C +C END FLIN +C + END + SUBROUTINE MINFIT(N,EPS,TOL,AB,Q,E,NMAX,LP) +C +C AN IMPROVED VERSION OF MINFIT, RESTRICTED TO M=N, P=0. +C SEE GOLUB AND REINSCH (1970). +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGES 156-158 +C +C G. H. GOLUB AND C. REINSCH, +C "SINGULAR VALUE DECOMPOSITION AND LEAST SQUARES SOLUTIONS', +C NUMERISCHE MATHEMATIK 14 (1970) PAGES 403-420 +C +C THE SINGULAR VALUES OF THE ARRAY AB ARE RETURNED IN Q, +C AND AB IS OVERWRITTEN WITH THE ORTHOGONAL MATRIX V SUCH THAT +C U.DIAG(Q)=AB.V, WHERE U IS ANOTHER ORTHOGONAL MATRIX. +C +C SUBROUTINE MINFIT IS CALLED BY SUBROUTINE PRAXIS. +C + INTEGER N,NMAX,LP, + * I,II,J,JTHIRT,K,KK,KT,L,LL2,LPI,L2 +C + DOUBLE PRECISION EPS,TOL,AB,Q,E, + * DABS,DSQRT,ZABS,ZSQRT,ARG, + * C,DENOM,F,G,H,ONE,X,Y,Z,ZERO,S,TWO +C + DIMENSION AB(NMAX,N),Q(N),E(N) +C + ZABS(ARG)=DABS(ARG) + ZSQRT(ARG)=DSQRT(ARG) +C + JTHIRT=30 +C + ZERO=0.0D0 + ONE=1.0D0 + TWO=2.0D0 +C +C HOUSEHOLDER'S REDUCTION TO BIDIAGONAL FORM... +C + X=ZERO + G=ZERO +C + DO 140 I=1,N + E(I)=G + S=ZERO + L=I+1 +C + DO 10 J=I,N + S=S+AB(J,I)**2 + 10 CONTINUE +C + IF(S.LT.TOL) THEN + G=ZERO + ELSE + F=AB(I,I) +C + IF(F.LT.ZERO) THEN + G=ZSQRT(S) + ELSE + G=-ZSQRT(S) + ENDIF +C + H=F*G-S + AB(I,I)=F-G +C + IF(L.GT.N) GO TO 60 + DO 50 J=L,N +C + F=ZERO + IF(I.GT.N) GO TO 30 + DO 20 K=I,N + F=F+AB(K,I)*AB(K,J) + 20 CONTINUE + 30 F=F/H +C + IF(I.GT.N) GO TO 50 + DO 40 K=I,N + AB(K,J)=AB(K,J)+F*AB(K,I) + 40 CONTINUE + 50 CONTINUE + ENDIF +C + 60 Q(I)=G + S=ZERO +C + IF(I.LE.N) THEN +C + IF(L.GT.N) GO TO 80 + DO 70 J=L,N + S=S+AB(I,J)**2 + 70 CONTINUE + ENDIF +C + 80 IF(S.LT.TOL) THEN + G=ZERO + ELSE + F=AB(I,I+1) +C + IF(F.LT.ZERO) THEN + G=ZSQRT(S) + ELSE + G=-ZSQRT(S) + ENDIF +C + H=F*G-S + AB(I,I+1)=F-G + IF(L.GT.N) GO TO 130 + DO 90 J=L,N + E(J)=AB(I,J)/H + 90 CONTINUE +C + DO 120 J=L,N +C + S=ZERO + DO 100 K=L,N + S=S+AB(J,K)*AB(I,K) + 100 CONTINUE +C + DO 110 K=L,N + AB(J,K)=AB(J,K)+S*E(K) + 110 CONTINUE + 120 CONTINUE + ENDIF +C + 130 Y=ZABS(Q(I))+ZABS(E(I)) +C + IF(Y.GT.X) X=Y + 140 CONTINUE +C +C ACCUMULATION OF RIGHT-HAND TRANSFORMATIONS... +C + DO 210 II=1,N + I=N-II+1 +C + IF(G.NE.ZERO) THEN + H=AB(I,I+1)*G +C + IF(L.GT.N) GO TO 200 + DO 150 J=L,N + AB(J,I)=AB(I,J)/H + 150 CONTINUE +C + DO 180 J=L,N +C + S=ZERO + DO 160 K=L,N + S=S+AB(I,K)*AB(K,J) + 160 CONTINUE +C + DO 170 K=L,N + AB(K,J)=AB(K,J)+S*AB(K,I) + 170 CONTINUE + 180 CONTINUE + ENDIF +C + IF(L.GT.N) GO TO 200 + DO 190 J=L,N + AB(J,I)=ZERO + AB(I,J)=ZERO + 190 CONTINUE +C + 200 AB(I,I)=ONE + G=E(I) + L=I + 210 CONTINUE +C +C DIAGONALIZATION OF THE BIDIAGONAL FORM... +C + EPS=EPS*X + DO 330 KK=1,N + K=N-KK+1 + KT=0 +C +C LABEL TESTFSPLITTING... +C + 220 KT=KT+1 +C + IF(KT.GT.JTHIRT) THEN + E(K)=ZERO + WRITE(LP,230) + 230 FORMAT(' QR FAILED.') + ENDIF +C + DO 240 LL2=1,K + L2=K-LL2+1 + L=L2 +C +C IF(...) GO TO TESTFCONVERGENCE +C + IF(ZABS(E(L)).LE.EPS) GO TO 270 +C +C IF(...) GO TO CANCELLATION +C + IF(ZABS(Q(L-1)).LE.EPS) GO TO 250 + 240 CONTINUE +C +C CANCELLATION OF E(L) IF L IS GREATER THAN 1... +C LABEL CANCELLATION... +C + 250 C=ZERO + S=ONE + IF(L.GT.K) GO TO 270 + DO 260 I=L,K + F=S*E(I) + E(I)=C*E(I) +C +C IF(...) GO TO TESTFCONVERGENCE +C + IF(ZABS(F).LE.EPS) GO TO 270 + G=Q(I) +C + IF(ZABS(F).LT.ZABS(G)) THEN + H=ZABS(G)*ZSQRT(ONE+(F/G)**2) + ELSE IF(F.NE.ZERO) THEN + H=ZABS(F)*ZSQRT(ONE+(G/F)**2) + ELSE + H=ZERO + ENDIF +C + Q(I)=H +C + IF(H.EQ.ZERO) THEN + H=ONE + G=ONE + ENDIF +C +C THE ABOVE REPLACES Q(I) AND H BY SQUARE ROOT OF (G*G+F*F) +C WHICH MAY GIVE INCORRECT RESULTS IF THE SQUARES UNDERFLOW OR IF +C F = G = 0 . +C + C=G/H + S=-F/H + 260 CONTINUE +C +C LABEL TESTFCONVERGENCE... +C + 270 Z=Q(K) +C +C IF(...) GO TO CONVERGENCE +C + IF(L.EQ.K) GO TO 310 +C +C SHIFT FROM BOTTOM 2*2 MINOR. +C + X=Q(L) + Y=Q(K-1) + G=E(K-1) + H=E(K) + F=((Y-Z)*(Y+Z)+(G-H)*(G+H))/(TWO*H*Y) + G=ZSQRT(F*F+ONE) +C + IF(F.LT.ZERO) THEN + DENOM=F-G + ELSE + DENOM=F+G + ENDIF +C + F=((X-Z)*(X+Z)+H*(Y/DENOM-H))/X +C +C NEXT QR TRANSFORMATION... +C + S=ONE + C=ONE + LPI=L+1 + IF(LPI.GT.K) GO TO 300 + DO 290 I=LPI,K + G=E(I) + Y=Q(I) + H=S*G + G=G*C +C + IF(ZABS(F).LT.ZABS(H)) THEN + Z=ZABS(H)*ZSQRT(ONE+(F/H)**2) + ELSE IF(F.NE.ZERO) THEN + Z=ZABS(F)*ZSQRT(ONE+(H/F)**2) + ELSE + Z=ZERO + ENDIF +C + E(I-1)=Z +C + IF(Z.EQ.ZERO) THEN + F=ONE + Z=ONE + ENDIF +C + C=F/Z + S=H/Z + F=X*C+G*S + G=-X*S+G*C + H=Y*S + Y=Y*C +C + DO 280 J=1,N + X=AB(J,I-1) + Z=AB(J,I) + AB(J,I-1)=X*C+Z*S + AB(J,I)=-X*S+Z*C + 280 CONTINUE +C + IF(ZABS(F).LT.ZABS(H)) THEN + Z=ZABS(H)*ZSQRT(ONE+(F/H)**2) + ELSE IF(F.NE.ZERO) THEN + Z=ZABS(F)*ZSQRT(ONE+(H/F)**2) + ELSE + Z=ZERO + ENDIF +C + Q(I-1)=Z +C + IF(Z.EQ.ZERO) THEN + F=ONE + Z=ONE + ENDIF +C + C=F/Z + S=H/Z + F=C*G+S*Y + X=-S*G+C*Y + 290 CONTINUE +C + 300 E(L)=ZERO + E(K)=F + Q(K)=X +C +C GO TO TESTFSPLITTING +C + GO TO 220 +C +C LABEL CONVERGENCE... +C + 310 IF(Z.LT.ZERO) THEN +C +C Q(K) IS MADE NON-NEGATIVE. +C + Q(K)=-Z + DO 320 J=1,N + AB(J,K)=-AB(J,K) + 320 CONTINUE + ENDIF + 330 CONTINUE +C + RETURN +C +C END MINFIT +C + END + SUBROUTINE SORT +C +C THIS SUBROUTINE SORTS THE ELEMENTS OF D +C AND THE CORRESPONDING COLUMNS OF V INTO DESCENDING ORDER. +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGES 158-159 +C + INTEGER N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH + INTEGER I,IPI,J,K,NMI +C + DOUBLE PRECISION V,X,D,Q0,Q1,DMIN,EPSMCH,FX,H,QD0,QD1,QF1, + * SMALL,T,XLDT,XM2,XM4,DSEED,SCBD + DOUBLE PRECISION S +C + COMMON /CPRAX/ V(128,128),X(128),D(128),Q0(128),Q1(128), + * DMIN,EPSMCH,FX,H,QD0,QD1,QF1,SMALL,T,XLDT,XM2,XM4,DSEED,SCBD, + * N,NL,NF,LP,JPRINT,NMAX,ILLCIN,KTM,NFMAX,JRANCH +C + NMI=N-1 + IF(NMI.LT.1) GO TO 50 + DO 40 I=1,NMI + K=I + S=D(I) + IPI=I+1 + IF(IPI.GT.N) GO TO 20 +C + DO 10 J=IPI,N +C + IF(D(J).GT.S) THEN + K=J + S=D(J) + ENDIF + 10 CONTINUE +C + 20 IF(K.GT.I) THEN + D(K)=D(I) + D(I)=S +C + DO 30 J=1,N + S=V(J,I) + V(J,I)=V(J,K) + V(J,K)=S + 30 CONTINUE + ENDIF + 40 CONTINUE +C + 50 RETURN +C +C END SORT +C + END + SUBROUTINE RANINI(RVALUE) +C +C SUBROUTINE RANINI PERFORMS INITIALIZATION FOR SUBROUTINE RANDOM. +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGES 163-164 +C + INTEGER JRAN2,I +C + DOUBLE PRECISION RVALUE,R,RAN3,DMOD,DABS,RAN1 +C + COMMON /COMRAN/ RAN3(127),RAN1,JRAN2 +C + R=DMOD(DABS(RVALUE),8190.0D0)+1 + JRAN2=127 +C + 10 IF(JRAN2.GT.0) THEN + JRAN2=JRAN2-1 + RAN1=-2.0D0**55 +C + DO 20 I=1,7 + R=DMOD(1756.0D0*R,8191.0D0) + RAN1=(RAN1+(R-DMOD(R,32.0D0))/32.0D0)/256.0D0 + 20 CONTINUE +C + RAN3(JRAN2+1)=RAN1 + GO TO 10 + ENDIF +C + RETURN +C +C END RANINI +C + END + SUBROUTINE RANDOM(RANVAL) +C +C SUBROUTINE RANDOM RETURNS A DOUBLE PRECISION PSEUDORANDOM NUMBER +C UNIFORMLY DISTRIBUTED IN (0,1) (INCLUDING 0 BUT NOT 1). +C +C "ALGORITHMS FOR MINIMIZATION WITHOUT DERIVATIVES", +C RICHARD P. BRENT, PRENTICE-HALL 1973, PAGES 163-164 +C +C BEFORE THE FIRST CALL TO RANDOM, THE USER MUST +C CALL RANINI(R) ONCE (ONLY) WITH R A DOUBLE PRECISION NUMBER +C EQUAL TO ANY INTEGER VALUE. +C BRENT (PAGE 166) USED THE EQUIVALENT OF +C CALL RANINI(4.0D0) . +C +C THE ALGORITHM USED IN SUBROUTINE RANDOM RETURNS X(N)/2**56, +C WHERE X(N) = X(N-1) + X(N-127) (MOD 2**56) . +C SINCE (1 + X + X**127) IS PRIMITIVE (MOD 2), +C THE PERIOD IS AT LEAST (2**127 - 1), WHICH EXCEEDS 10**38. +C +C SEE "SEMINUMERICAL ALGORITHMS", VOLUME 2 OF +C "THE ART OF COMPUTER PROGRAMMING" BY DONALD E. KNUTH, +C ADDISON-WESLEY 1969, PAGES 26, 34, AND 464. +C +C X(N) IS STORED IN DOUBLE PRECISION AS RAN3 = X(N)/2**56 - 1/2, +C AND ALL DOUBLE PRECISION ARITHMETIC IS EXACT. +C + INTEGER JRAN2 +C + DOUBLE PRECISION RANVAL,RAN3,RAN1 +C + COMMON /COMRAN/ RAN3(127),RAN1,JRAN2 +C + IF(JRAN2.EQ.0) THEN + JRAN2=126 + ELSE + JRAN2=JRAN2-1 + ENDIF +C + RAN1=RAN1+RAN3(JRAN2+1) + IF(RAN1.LT.0.0D0) THEN + RAN1=RAN1+0.5D0 + ELSE + RAN1=RAN1-0.5D0 + ENDIF +C + RAN3(JRAN2+1)=RAN1 + RANVAL=RAN1+0.5D0 +C + RETURN +C +C END RANDOM +C + END + DOUBLE PRECISION FUNCTION DRANDM(DL) +C +C SIMPLE PORTABLE PSEUDORANDOM NUMBER GENERATOR. +C +C DRANDM RETURNS FUNCTION VALUES THAT ARE PSEUDORANDOM +C NUMBERS UNIFORMLY DISTRIBUTED ON THE INTERVAL (0,1). +C +C 'NUMERICAL MATHEMATICS AND COMPUTING' BY WARD CHENEY AND +C DAVID KINCAID, BROOKS/COLE PUBLISHING COMPANY +C (FIRST EDITION, 1980), PAGE 203 +C +C AT THE BEGINNING OF EXECUTION, OR WHENEVER A NEW SEQUENCE IS +C TO BE INITIATED, SET DL EQUAL TO AN INTEGER VALUE BETWEEN +C 1.0D0 AND 2147483646.0D0, INCLUSIVE. DO THIS ONLY ONCE. +C THEREAFTER, DO NOT SET OR ALTER DL IN ANY WAY. +C FUNCTION DRANDM WILL MODIFY DL FOR ITS OWN PURPOSES. +C +C DRANDM USES A MULTIPLICATIVE CONGRUENTIAL METHOD. +C THE NUMBERS GENERATED BY DRANDM SUFFER FROM THE PARALLEL +C PLANES DEFECT DISCOVERED BY G. MARSAGLIA, AND SHOULD NOT BE +C USED WHEN HIGH-QUALITY RANDOMNESS IS REQUIRED. IN THAT +C CASE, USE A "SHUFFLING" METHOD. +C + DOUBLE PRECISION DL,DMOD +C + 10 DL=DMOD(16807.0D0*DL,2147483647.0D0) + DRANDM=DL/2147483647.0D0 + IF(DRANDM.LE.0.0D0 .OR. DRANDM.GE.1.0D0) GO TO 10 + RETURN + END diff --git a/gnuradio-core/src/gen_interpolator_taps/praxis.txt b/gnuradio-core/src/gen_interpolator_taps/praxis.txt new file mode 100644 index 00000000..5c4b8155 --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/praxis.txt @@ -0,0 +1,176 @@ +Brent's PRAXIS minimizer is available in FORTRAN 77. July 1995 + +"Algorithms for Minimization Without Derivatives" +by Richard P. Brent, Prentice-Hall, 1973 +ISBN: 0-13-022335-2 + +This book by Brent was a groundbreaking effort. +(I believe that it was his Ph.D. thesis at Stanford.) +His algorithms for finding roots and minima in +one dimension have good performance for typical problems +and guaranteed performance in the worst case. +(A later rootfinder by J. Bus and Dekker gave +a much lower bound for the worst case, +but no better performance in typical problems.) +These algorithms were implemented in both ALGOL W +and FORTRAN by Brent, and have been used fairly widely. + +Brent also gave a multi-dimensional minimization algorithm, +PRAXIS, but only shows an implementation in ALGOL W. +This routine has not been widely used, at least in the U.S. +The PRAXIS package has been translated into FORTRAN +by Rosalee Taylor, Sue Pinski, and me, and +I am making it available via anonymous ftp for use as +freeware (please do not remove our names). + + ftp a.cs.okstate.edu + anonymous + [enter your userid as password] + cd /pub/jpc + get praxis.f + quit + + +Brent's method and its performance + +Newton's method for minimization can find the minimum of a +quadratic function in one iteration, but is sometimes not +convenient to use. In the 1960s, several researchers found +iterative methods that solve quadratic problems exactly in a +finite number of steps. C. S. Smith (1962) and +M. J. D. Powell (1964) devised methods +that had this property and did not require derivatives. +G. W. Stewart modified the Davidon-Fletcher-Powell quasi-Newton +method to use finite difference approximations to approximate +the gradient. Powell's method, or later versions by Zangwill, +were the most successful of the early direct search methods +having the property of finite convergence on quadratic functions. + +Powell's method was programmed at Harwell as subroutine VA04A, +and is available as file va04a.f in the same directory as praxis.f. +VA04A is not extremely robust, and can give underflow, overflow, +or division by zero. va04a.f has several documented patches in it +where I tried to get around various abnormal terminations. +I do not recommend VA04A very strongly. + +Brent's PRAXIS added orthogonalization and several other features +to Powell's method. Brent also dealt carefully with roundoff. + +William H. Press et al. in their book "Numerical Recipes" +comment that +"Brent has a number of other cute tricks up his sleeve, +and his modification of Powell's method is probably +the best presently known." + +Roger Fletcher was less enthusiastic in his review of Brent's book +in The Computer Journal 16 (1973) 314: +"... I am not convinced that the modifications to Powell's +method are the best. Use of eigenvector directions +is not independent of scale changes to the variables, +and the use of searches in random directions is hardly +appealing. Nonetheless all the algorithms are demonstrated +to be competitive by numerical examples." + +The methods of Powell, Brent, et al. require that the function +for which a local minimum is sought must be smooth; +that is, the function and all of its first partial derivatives +must be continuous. + +Brent compared his method to the methods of Powell, of Stewart, +and of Davies, Swann, and Campey. Indirectly, he compared it +also to the Davidon-Fletcher-Powell quasi-Newton method. +He found that his method was about as efficient as the best +of these in most cases, and that it was more robust than others +in some cases. (Pages 139-155 in Brent's book give fair +comparisons to other methods. The results in Table 7.1 on +page 138 are correct, but do not include progress all the way +to convergence, and are therefore not too useful.) + +On least squares problems, all of these general minimization +methods are likely to be inefficient compared to least squares +methods such as the Gauss-Newton or Marquardt methods. + +In addition to the scale dependence that Fletcher deplored, +PRAXIS also had the disadvantage that it required N, the number +of parameters, to be greater than or equal to two. +The failure to handle N=1 is an unnecessary and pointless limitation. + + +The FORTRAN version + +We have followed Brent's PRAXIS rather closely. +I have added a patch to try to handle the case N=1, +and an option to use a simpler pseudorandom number generator, +DRANDM. The handling of N=1 is not guaranteed. + +The user writes a main program and a function subprogram +to compute the function to be minimized. +All communication between the user's main program and PRAXIS +is done via COMMON, except for an EXTERNAL parameter giving +the name of the function subprogram. +The disadvantages of using COMMON are at least two-fold: + + 1) Arrays cannot have adjustable dimensions. + + 2) Because some actual parameters are COMMON variables, + the FORTRAN version of PRAXIS probably will not pass + the Bell Labs PFORT package as being 100% standard FORTRAN. + Nevertheless, this usage will not cause any conflict in + any commercial FORTRAN compiler ever written. + (If it does, I will apologize and rewrite PRAXIS.) + +The advantage of using COMMON is that it is not necessary to pass +about fifteen more parameters every time the user calls PRAXIS. +At present all arrays are dimensioned (20) or (20,20), +and this can easily be increased using two simple global editing +commands. (In this case, increase the value of NMAX.) + +There are no DATA statements in PRAXIS, and it was not necessary +to use any SAVE statements. + +We have used DOUBLE PRECISION for all floating point computations, +as Brent did. We recommend using DOUBLE PRECISION on all computers +except possibly Cray computers, in which REAL is reasonably precise. +The value of "machine epsilon" is computed in subroutine PRASET +using bisection, and is called EPSMCH. +Brent computes EPSMCH**4 and 1/EPSMCH**4 in PRAXIS, +and uses these quantities later. +Because EPSMCH in DOUBLE PRECISION is less than 1E-16, +these fourth powers of EPSMCH and 1/EPSMCH will underflow +and overflow on such machines as VAXs and PCs, +which have a range of only about 1E38, grossly insufficient +for scientific computation. For such machines, Brent recommends +increasing the value of EPSMCH. +EPSMCH=1E-9 or possibly even 1E-8 might be necessary. +A better solution would be to eliminate the explicit use of +these fourth powers, accomplishing the same result implicitly. + +A "bug bounty" of $10 U.S. will be paid by me for the first +notification of any error in PRAXIS. +The same bounty also applies to any substantive poor design +choice (having no redeeming advantages whatever) in the FORTRAN +package. (The patch for N=1 is not included, although any +suggested improvements in that will be considered carefully.) + +praxis.f includes test software to run any of the test problems +that Brent ran, and is set to run at least one case of each problem. +I have run these on an IBM 3090, essentially the same +architecture that Brent used, and obtained essentially the same +results that Brent shows on pages 140-155. The Hilbert problem with +N=12, for which Brent shows no termination results and for which +the results in Table 7.1 are correct but not relevant, +runs a long time; I cut it off at 3000 function evaluations. +I don't particularly like Brent's convergence criterion, +which allows this sort of extremely slow creeping progress, +but have not modified it. + +Please notify me of any problems with this software, +or of any suggested modifications. + +John Chandler +Computer Science Department +Oklahoma State University +Stillwater, Oklahoma 74078, U.S.A. +(405) 744-5676 +jpc@a.cs.okstate.edu + diff --git a/gnuradio-core/src/gen_interpolator_taps/simpson.c b/gnuradio-core/src/gen_interpolator_taps/simpson.c new file mode 100644 index 00000000..fc6dd6c2 --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/simpson.c @@ -0,0 +1,76 @@ +/* -*- c -*- */ +#include +#include + +#define EPS (1.0e-5) +#define JMAX 16 + +/* + * Compute the Nth stage of refinement of an extended trapezoidal + * rule. FUNC is input as a pointer to a function to be integrated + * between limits A and B. When called with N = 1, the routine + * returns the crudest estimate of the integral from A to B of f(x) + * dx. Subsequent calls with N=2,3,... (in that sequential order) + * will improve the accuracy by adding 2**(N-2) additional interior + * points. + * + * N.B., this function contains static state and IS NEITHER RENTRANT + * NOR THREAD SAFE! + */ + +double +trapzd (double (*func)(double), + double a, double b, + int n) +{ + long double x, tnm, sum, del; + static long double s; + static int it; + int j; + + if (n == 1){ + it = 1; /* # of points to add on the next call */ + s = 0.5 * (b - a) * (func(a) + func(b)); + return s; + } + else { + tnm = it; + del = (b-a)/tnm; /* this is the spacing of the points to be added */ + x = a + 0.5*del; + for (sum = 0.0, j = 1; j <= it; j++, x += del) + sum += func(x); + it *= 2; + s = 0.5 * (s + (b-a) * sum/tnm); /* replace s by it's refined value */ + return s; + } +} + +/* + * Returns the integral of the function FUNC from A to B. The + * parameters EPS can be set to the desired fractional accuracy and + * JMAX so that 2**(JMAX-1) is the maximum allowed number of steps. + * Integration is performed by Simpson's rule. + */ + +double +qsimp (double (*func)(double), + double a, /* lower limit */ + double b) /* upper limit */ +{ + int j; + long double s, st, ost, os; + + ost = os = -1.0e30; + for (j = 1; j <= JMAX; j++){ + st = trapzd (func, a, b, j); + s = (4.0 * st - ost)/3.0; + if (fabs (s - os) < EPS * fabs(os)) + return s; + os = s; + ost = st; + } + fprintf (stderr, "Too many steps in routine QSIMP\n"); + // exit (1); + return s; +} + diff --git a/gnuradio-core/src/gen_interpolator_taps/simpson.h b/gnuradio-core/src/gen_interpolator_taps/simpson.h new file mode 100644 index 00000000..68774f9a --- /dev/null +++ b/gnuradio-core/src/gen_interpolator_taps/simpson.h @@ -0,0 +1,3 @@ +double qsimp (double (*func)(double), + double a, double b); + diff --git a/gnuradio-core/src/lib/Makefile.am b/gnuradio-core/src/lib/Makefile.am new file mode 100644 index 00000000..2b31b3fc --- /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 00000000..929c7f81 --- /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 00000000..5aee102f --- /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 00000000..4c4936d3 --- /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 00000000..01885a84 --- /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" + +# +# _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 _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 00000000..6809274f --- /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 00000000..00730f83 --- /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, 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 00000000..9398a0a1 --- /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 00000000..79826e8a --- /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 00000000..bff045e1 --- /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 00000000..39057e46 --- /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 00000000..c6f907c9 --- /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 00000000..edd5b1b0 --- /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 +#endif +#include +#include "gr_fir_ccc_simd.h" +#include "ccomplex_dotprod_generic.h" + +#include + +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 00000000..70d3b6bd --- /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 00000000..a16d0535 --- /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 00000000..216df6e5 --- /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 00000000..0a8c7363 --- /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 00000000..37608ece --- /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 00000000..1413c6ce --- /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 00000000..443949ed --- /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 00000000..195dc377 --- /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 00000000..300f4700 --- /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 +#endif +#include +#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 00000000..44a4ea55 --- /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 00000000..acafb1a3 --- /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 00000000..0fb95db0 --- /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 00000000..86ac0e78 --- /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 00000000..3152b91d --- /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 00000000..98137db1 --- /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 00000000..20dc5b2d --- /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 00000000..32772bf4 --- /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 00000000..2d8b4ccb --- /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 00000000..cba03579 --- /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 00000000..d9f7eaca --- /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 00000000..2d434699 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +%} + +%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 00000000..784fa0b5 --- /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 00000000..0f6a9480 --- /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 00000000..21912afd --- /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 00000000..4f4d4ebf --- /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 00000000..0e59f5e3 --- /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 00000000..c7f821a3 --- /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 00000000..7a101920 --- /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 00000000..dcbe75df --- /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 00000000..e55ff854 --- /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 ' + 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 00000000..e3c0ec7a --- /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 00000000..3c78daa2 --- /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 + +''') + + # for sig in fir_signatures: + # out.write ('class gr_fir_' + sig + ';\n') + + out.write ('#include \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 *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 +#endif +#include + +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 00000000..78cf3773 --- /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 + +''') + + 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 *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 *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 +#endif +#include + +''') + + for sig in fir_signatures: + out.write ('#include \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 00000000..80d91863 --- /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 *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 + +''') + + 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 *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 +#endif +#include +#include + +// +// 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 00000000..4a34556f --- /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 00000000..00b3c788 --- /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 00000000..0f96451a --- /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 00000000..2eeb38e7 --- /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 00000000..f2ab319b --- /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 +#include + +gr_adaptive_fir_ccf::gr_adaptive_fir_ccf(char *name, int decimation, const std::vector &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 &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 00000000..57a95a33 --- /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 + +/*! + * \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 d_new_taps; + bool d_updated; + +protected: + float d_error; + std::vector 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 &taps); + void set_taps(const std::vector &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 00000000..896fb42c --- /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 &taps); + +public: + void set_taps(const std::vector &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 00000000..29b8a3e4 --- /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_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(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 00000000..25c99689 --- /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 + +class gr_cma_equalizer_cc; +typedef boost::shared_ptr 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 00000000..c64bfc3a --- /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_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 00000000..7e926f34 --- /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 + +/* + * 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 00000000..563b60cb --- /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 00000000..c90e3a0f --- /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 +#include +#include +#include +#include +#include +#include + +#include + +gr_fft_filter_ccc_sptr gr_make_fft_filter_ccc (int decimation, const std::vector &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 &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 &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 &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 &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 00000000..06bc7c1b --- /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 + +class gr_fft_filter_ccc; +typedef boost::shared_ptr gr_fft_filter_ccc_sptr; +gr_fft_filter_ccc_sptr gr_make_fft_filter_ccc (int decimation, const std::vector &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 &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 d_tail; // state carried between blocks for overlap-add + std::vector d_xformed_taps; // Fourier xformed taps + std::vector 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 &taps); + + void compute_sizes(int ntaps); + int tailsize() const { return d_ntaps - 1; } + void actual_set_taps (const std::vector &taps); + + public: + ~gr_fft_filter_ccc (); + + void set_taps (const std::vector &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 00000000..65cbb362 --- /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 &taps + ) throw (std::invalid_argument); + +class gr_fft_filter_ccc : public gr_sync_decimator +{ + private: + gr_fft_filter_ccc (int decimation, const std::vector &taps); + + public: + ~gr_fft_filter_ccc (); + + void set_taps (const std::vector &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 00000000..ceb2e828 --- /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 +#include +#include +#include +#include +#include +#include + +#include + +gr_fft_filter_fff_sptr gr_make_fft_filter_fff (int decimation, const std::vector &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 &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 &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 &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 &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 &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 00000000..bdd29b70 --- /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 + +class gr_fft_filter_fff; +typedef boost::shared_ptr gr_fft_filter_fff_sptr; +gr_fft_filter_fff_sptr gr_make_fft_filter_fff (int decimation, const std::vector &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 &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 d_tail; // state carried between blocks for overlap-add + std::vector d_xformed_taps; // Fourier xformed taps + std::vector 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 &taps); + + void compute_sizes(int ntaps); + int tailsize() const { return d_ntaps - 1; } + void actual_set_taps (const std::vector &taps); + + public: + ~gr_fft_filter_fff (); + + void set_taps (const std::vector &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 00000000..5ee30ebb --- /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 &taps + ) throw (std::invalid_argument); + +class gr_fft_filter_fff : public gr_sync_decimator +{ + private: + gr_fft_filter_fff (int decimation, const std::vector &taps); + + public: + ~gr_fft_filter_fff (); + + void set_taps (const std::vector &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 00000000..09f181ea --- /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 +#include +#include + +// public constructor +gr_filter_delay_fc_sptr +gr_make_filter_delay_fc (const std::vector &taps) +{ + return gr_filter_delay_fc_sptr (new gr_filter_delay_fc (taps)); +} + +gr_filter_delay_fc::gr_filter_delay_fc (const std::vector &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 00000000..2b65c672 --- /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 +#include +#include + +class gr_filter_delay_fc; +typedef boost::shared_ptr gr_filter_delay_fc_sptr; + +// public constructor +gr_filter_delay_fc_sptr gr_make_filter_delay_fc (const std::vector &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 &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 &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 00000000..85603ce2 --- /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 &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 00000000..1f786622 --- /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 +#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 00000000..a5bf3ed0 --- /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 +@VRCOMPLEX_INCLUDE@ +#include + +/*! + * \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 00000000..7bc7a5eb --- /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 +#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 00000000..b1b2f402 --- /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 00000000..6d5cba3b --- /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 +#endif +#include + +#include +#include +#include + +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 &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 &inew_taps) +{ + gr_fir_ccc::set_taps (inew_taps); // call superclass + + const std::vector 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 00000000..89888871 --- /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 + +/*! + * \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 &taps); + ~gr_fir_ccc_simd (); + + // MANIPULATORS + virtual void set_taps (const std::vector &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 00000000..8b96c23d --- /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 +#endif +#include +#include + +/* + * --- 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 &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 &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 &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 00000000..ee2fe9b1 --- /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 + +/*! + * \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 &taps); +}; + +class gr_fir_ccc_3dnowext : public gr_fir_ccc_simd +{ +public: + gr_fir_ccc_3dnowext (); + gr_fir_ccc_3dnowext (const std::vector &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 &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 00000000..d1992d7c --- /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 +#endif +#include + +#include +#include +#include + +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 &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 &inew_taps) +{ + gr_fir_ccf::set_taps (inew_taps); // call superclass + const std::vector 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 00000000..60898b43 --- /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 + + +/*! + * \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 &taps); + ~gr_fir_ccf_simd (); + + // MANIPULATORS + virtual void set_taps (const std::vector &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 00000000..9f288fc2 --- /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 +#endif +#include +#include + +/* + * --- 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 &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 &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 00000000..5c51a5f9 --- /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 + +/*! + * \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 &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 &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 00000000..c17d29f7 --- /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 +#endif +#include + +#include +#include +#include + +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 &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 &inew_taps) +{ + gr_fir_fcc::set_taps (inew_taps); // call superclass + const std::vector 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 00000000..56248209 --- /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 + + +/*! + * \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 &taps); + ~gr_fir_fcc_simd (); + + // MANIPULATORS + virtual void set_taps (const std::vector &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 00000000..e80dfe1f --- /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 +#endif +#include +#include + +/* + * --- 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 &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 &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 00000000..500f4fb5 --- /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 + +/*! + * \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 &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 &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 00000000..92c4256e --- /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 +#endif +#include + +#include +#include +#include + +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 &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 &inew_taps) +{ + gr_fir_fff::set_taps (inew_taps); // call superclass + const std::vector 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 00000000..375b1191 --- /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 + +/*! + * \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 &taps); + ~gr_fir_fff_simd (); + + // MANIPULATORS + virtual void set_taps (const std::vector &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 00000000..494a0f7e --- /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 +#endif +#include +#include + +/* + * --- 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 &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 &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 00000000..407ae3ff --- /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 + +/*! + * \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 &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 &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 00000000..91b3111e --- /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 +#include + +@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 00000000..b6e5d1aa --- /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 + +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 00000000..13c919d1 --- /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 00000000..00b4e609 --- /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 +#endif +#include + +#include +#include +#include + +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 &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 &inew_taps) +{ + gr_fir_fsf::set_taps (inew_taps); // call superclass + const std::vector 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 00000000..77e093ca --- /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 + +/*! + * \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 &taps); + ~gr_fir_fsf_simd (); + + // MANIPULATORS + virtual void set_taps (const std::vector &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 00000000..c407789d --- /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 +#endif +#include +#include + +/* + * --- 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 &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 &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 00000000..e8ae763f --- /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 + +/*! + * \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 &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 &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 00000000..b6f91a74 --- /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 +#endif +#include + +#include +#include +#include + +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 &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 &inew_taps) +{ + gr_fir_scc::set_taps (inew_taps); // call superclass + + const std::vector 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 00000000..098b02a5 --- /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 + + +/*! + * \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 &taps); + ~gr_fir_scc_simd (); + + // MANIPULATORS + virtual void set_taps (const std::vector &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 00000000..c654fce1 --- /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 +#endif +#include +#include + +/* + * --- 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 &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 &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 &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 00000000..bbdf5eb7 --- /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 + +/*! + * \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 &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 &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 &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 00000000..7d576e8b --- /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 +#endif +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +// #include +// #include +// #include +// #include + +#include +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 &taps) +{ + return new gr_fir_ccf_3dnow(taps); +} + +static gr_fir_ccf * +make_gr_fir_ccf_sse(const std::vector &taps) +{ + return new gr_fir_ccf_sse(taps); +} + +static gr_fir_fcc * +make_gr_fir_fcc_3dnow(const std::vector &taps) +{ + return new gr_fir_fcc_3dnow(taps); +} + +static gr_fir_fcc * +make_gr_fir_fcc_sse(const std::vector &taps) +{ + return new gr_fir_fcc_sse(taps); +} + +static gr_fir_ccc * +make_gr_fir_ccc_3dnow (const std::vector &taps) +{ + return new gr_fir_ccc_3dnow (taps); +} + +static gr_fir_ccc * +make_gr_fir_ccc_3dnowext (const std::vector &taps) +{ + return new gr_fir_ccc_3dnowext (taps); +} + +static gr_fir_ccc * +make_gr_fir_ccc_sse (const std::vector &taps) +{ + return new gr_fir_ccc_sse (taps); +} + +static gr_fir_fff * +make_gr_fir_fff_3dnow (const std::vector &taps) +{ + return new gr_fir_fff_3dnow (taps); +} + +static gr_fir_fff * +make_gr_fir_fff_sse (const std::vector &taps) +{ + return new gr_fir_fff_sse (taps); +} + +static gr_fir_fsf * +make_gr_fir_fsf_3dnow (const std::vector &taps) +{ + return new gr_fir_fsf_3dnow (taps); +} + +static gr_fir_fsf * +make_gr_fir_fsf_sse (const std::vector &taps) +{ + return new gr_fir_fsf_sse (taps); +} + +#if 0 +static gr_fir_sss * +make_gr_fir_sss_mmx (const std::vector &taps) +{ + return new gr_fir_sss_mmx (taps); +} + +static gr_fir_sss * +make_gr_fir_sss_sse2 (const std::vector &taps) +{ + return new gr_fir_sss_sse2 (taps); +} +#endif + +static gr_fir_scc * +make_gr_fir_scc_3dnow(const std::vector &taps) +{ + return new gr_fir_scc_3dnow(taps); +} + +static gr_fir_scc * +make_gr_fir_scc_3dnowext(const std::vector &taps) +{ + return new gr_fir_scc_3dnowext(taps); +} + +static gr_fir_scc * +make_gr_fir_scc_sse(const std::vector &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 &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 &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 &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 &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 &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 &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 &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 *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 *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 *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 *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 *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 *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 *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 00000000..2f1d48ef --- /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 + +class gr_fir_sysconfig_x86 : public gr_fir_sysconfig_generic { +public: + virtual gr_fir_ccf *create_gr_fir_ccf (const std::vector &taps); + virtual gr_fir_fcc *create_gr_fir_fcc (const std::vector &taps); + virtual gr_fir_fff *create_gr_fir_fff (const std::vector &taps); + virtual gr_fir_fsf *create_gr_fir_fsf (const std::vector &taps); + virtual gr_fir_scc *create_gr_fir_scc (const std::vector &taps); + virtual gr_fir_ccc *create_gr_fir_ccc (const std::vector &taps); +//virtual gr_fir_sss *create_gr_fir_sss (const std::vector &taps); + + virtual void get_gr_fir_ccf_info (std::vector *info); + virtual void get_gr_fir_fcc_info (std::vector *info); + virtual void get_gr_fir_fff_info (std::vector *info); + virtual void get_gr_fir_fsf_info (std::vector *info); + virtual void get_gr_fir_scc_info (std::vector *info); + virtual void get_gr_fir_ccc_info (std::vector *info); +//virtual void get_gr_fir_sss_info (std::vector *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 00000000..6abb963d --- /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 +#include +#include +#include + +// 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 00000000..b024c441 --- /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 + +class gri_mmse_fir_interpolator; + +class gr_fractional_interpolator; +typedef boost::shared_ptr 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 00000000..4592e754 --- /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 +#include + +@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 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 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 00000000..d1351e20 --- /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 +#include + +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 00000000..0a4f8b31 --- /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 00000000..264b96e6 --- /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 +#include + +// 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 00000000..c8363bc4 --- /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 +#include + +class gr_goertzel_fc; +typedef boost::shared_ptr 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 00000000..6d5efd23 --- /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 00000000..371363c3 --- /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 +#include +#include +#include + +// 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 00000000..54082a95 --- /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 +#include +#include + +class gr_hilbert_fc; +typedef boost::shared_ptr 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 00000000..f69f624a --- /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 00000000..4e825e7a --- /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 +#include +#include + + +gr_iir_filter_ffd_sptr +gr_make_iir_filter_ffd (const std::vector &fftaps, + const std::vector &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 &fftaps, + const std::vector &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 &fftaps, + const std::vector &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 00000000..5ef36349 --- /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 +#include +#include + +class gr_iir_filter_ffd; +typedef boost::shared_ptr gr_iir_filter_ffd_sptr; +gr_iir_filter_ffd_sptr +gr_make_iir_filter_ffd (const std::vector &fftaps, + const std::vector &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 &fftaps, + const std::vector &fbtaps) throw (std::invalid_argument); + + gri_iir d_iir; + std::vector d_new_fftaps; + std::vector d_new_fbtaps; + bool d_updated; + + /*! + * Construct an IIR filter with the given taps + */ + gr_iir_filter_ffd (const std::vector &fftaps, + const std::vector &fbtaps) throw (std::invalid_argument); + + public: + ~gr_iir_filter_ffd (); + + void set_taps (const std::vector &fftaps, + const std::vector &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 00000000..bab8310f --- /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 &fftaps, + const std::vector &fbtaps) throw (std::invalid_argument); + +class gr_iir_filter_ffd : public gr_sync_block +{ + private: + gr_iir_filter_ffd (const std::vector &fftaps, + const std::vector &fbtaps) throw (std::invalid_argument); + + public: + ~gr_iir_filter_ffd (); + + void set_taps (const std::vector &fftaps, + const std::vector &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 00000000..f382a7cd --- /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 +#include +#include +#include + +@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 00000000..866c43ab --- /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 + +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 00000000..d58c823f --- /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 00000000..a07b739e --- /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 +#include +#include +#include + +@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 00000000..01172693 --- /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 + +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 00000000..2411d034 --- /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 00000000..930b1cc2 --- /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 + +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 00000000..44c85740 --- /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 +#include + +// ---------------------------------------------------------------- + +#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 00000000..2e8f3ff7 --- /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 00000000..adf871ae --- /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 + +/*! + * \brief class template for single pole moving average filter + */ +template +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 +o_type +gr_single_pole_avg::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 +void +gr_single_pole_avg::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 00000000..99f8b110 --- /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 +#include +#include + + +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 00000000..cc3640f6 --- /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 +#include +#include + +class gr_single_pole_avg_filter_ff; +typedef boost::shared_ptr 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 > 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 00000000..f0ffe6ce --- /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 00000000..c1d3f748 --- /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 +#include +/*! + * \brief class template for single pole IIR filter + */ +template +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 +o_type +gr_single_pole_iir::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 +void +gr_single_pole_iir::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 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 (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::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 +void +gr_single_pole_iir::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 00000000..0218452c --- /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 +#include +#include + + +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 00000000..38caa614 --- /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 +#include +#include +#include + +class gr_single_pole_iir_filter_cc; +typedef boost::shared_ptr 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 > 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 00000000..683bbe99 --- /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 00000000..03e27484 --- /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 +#include +#include + + +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 00000000..ff6bae3b --- /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 +#include +#include + +class gr_single_pole_iir_filter_ff; +typedef boost::shared_ptr 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 > 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 00000000..6680c84e --- /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 00000000..f443678d --- /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 + +/*! + * \brief class template for single pole recursive filter + */ +template +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 +o_type +gr_single_pole_rec::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 +void +gr_single_pole_rec::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 00000000..7c0a9aa9 --- /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 +#include +#include + + +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 00000000..d1861e75 --- /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 +#include +#include + +class gr_single_pole_rec_filter_ff; +typedef boost::shared_ptr 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 > 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 00000000..06da737b --- /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 00000000..def340a0 --- /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 + +/*! + * \brief class template for single zero moving average filter + */ +template +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 +o_type +gr_single_zero_avg::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 +void +gr_single_zero_avg::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 00000000..62feb4ca --- /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 +#include +#include + + +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 00000000..4a283d3c --- /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 +#include +#include + +class gr_single_zero_avg_filter_ff; +typedef boost::shared_ptr 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 > 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 00000000..0e6d84fa --- /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 00000000..f91640c5 --- /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 + +/*! + * \brief class template for single zero recursive filter + */ +template +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 +o_type +gr_single_zero_rec::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 +void +gr_single_zero_rec::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 00000000..fe704f45 --- /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 +#include +#include + + +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 00000000..98215e90 --- /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 +#include +#include + +class gr_single_zero_rec_filter_ff; +typedef boost::shared_ptr 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 > 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 00000000..e2cbbfc9 --- /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 00000000..571de616 --- /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 + +#include + +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 00000000..6baf94e9 --- /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 + +/*! + * \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 00000000..7de8c69a --- /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 +#include + +/*! + * \brief base class template for Infinite Impulse Response filter (IIR) + */ +template +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& fftaps, + const std::vector& 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 &fftaps, + const std::vector &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 d_fftaps; + std::vector d_fbtaps; + int d_latest; + std::vector d_prev_output; + std::vector d_prev_input; +}; + + +// +// general case. We may want to specialize this +// +template +o_type +gri_iir::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 +void +gri_iir::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 00000000..ff7eca89 --- /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 +#endif +#include +#include +#include +#include +#include +#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 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 00000000..e2fb8f79 --- /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 + +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 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 00000000..3f75aedc --- /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 +#endif +#include +#include +#include +#include +#include +#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 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 00000000..d0c14117 --- /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 +#include + +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 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 00000000..76702b63 --- /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 00000000..ad6f6c6e --- /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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 00000000..f10f0060 --- /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 +#include + +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 00000000..91c8e9e2 --- /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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 00000000..53509ea6 --- /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 +#include + +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 00000000..3fbbdc3d --- /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 *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 00000000..d0f66cc9 --- /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 00000000..6aeb4932 --- /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 00000000..75415a79 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include + +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 00000000..71371ae1 --- /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 + +//! 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 00000000..a1697797 --- /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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 00000000..00568129 --- /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 +#include + +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 00000000..9c70a167 --- /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 +#endif + +#include + +typedef gr_complex i_type; +typedef gr_complex o_type; +typedef gr_complex tap_type; +typedef gr_complex acc_type; + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 &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 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 info; + gr_fir_util::get_gr_fir_ccc_info (&info); // get all known ccc implementations + + for (std::vector::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 00000000..46fa9b0e --- /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 +#include + +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 00000000..c45e0853 --- /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 +#endif + +#include + +typedef gr_complex i_type; +typedef gr_complex o_type; +typedef float tap_type; +typedef gr_complex acc_type; + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 &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 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 info; + gr_fir_util::get_gr_fir_ccf_info (&info); // get all known ccf implementations + + for (std::vector::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 00000000..bf87136d --- /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 +#include + +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 00000000..0706b585 --- /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 +#endif + +#include + +typedef float i_type; +typedef gr_complex o_type; +typedef gr_complex tap_type; +typedef gr_complex acc_type; + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 &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 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 info; + gr_fir_util::get_gr_fir_fcc_info (&info); // get all known fcc implementations + + for (std::vector::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 00000000..145f72f0 --- /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 +#include + +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 00000000..1ba3bee5 --- /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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +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 &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 t1a (&taps_1a[0], &taps_1a[NELEM (taps_1a)]); + vector 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 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 info; + gr_fir_util::get_gr_fir_fff_info (&info); // get all known fff implementations + + for (std::vector::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 00000000..34d86f9d --- /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 +#include + +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 00000000..38a76924 --- /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 +#endif + +#include + +typedef short i_type; +typedef gr_complex o_type; +typedef gr_complex tap_type; +typedef gr_complex acc_type; + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 &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 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 info; + gr_fir_util::get_gr_fir_scc_info (&info); // get all known scc implementations + + for (std::vector::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 00000000..2662d02b --- /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 +#include + +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 00000000..a756bbc4 --- /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 +#include +#include +#include +#include + +#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 00000000..85be45e8 --- /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 +#include + +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 00000000..4fca2e5d --- /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 00000000..6e3709ff --- /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 00000000..7c9ae078 --- /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 00000000..4c46e0ea --- /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 00000000..03b47489 --- /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 00000000..f27d3930 --- /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 +#include +#include + +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 00000000..f356a0e0 --- /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 00000000..1cecf49f --- /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 * +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 00000000..d2c31612 --- /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 +#endif +#include + +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 00000000..c8ba3e8d --- /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 00000000..23b0e7dd --- /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] outfile + decode [-3|4|5] [-a|u|l] 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 g721file + + # Read 40Kbps G.723 and output A-law + decode -5 -a alawfile + + # Compress and then decompress u-law data using 24Kbps G.723 + encode -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 00000000..cf8c739c --- /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 +#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 00000000..e7448286 --- /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 +#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 00000000..d4d60a5c --- /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 00000000..445f177e --- /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 00000000..452f4dae --- /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 00000000..4858baf4 --- /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 00000000..9a823c75 --- /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 +/* + * 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 00000000..33807171 --- /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 00000000..a240cc91 --- /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 00000000..f0c477e3 --- /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 00000000..26d829f1 --- /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), 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 + + // 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 00000000..3466412f --- /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 00000000..94445e96 --- /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 00000000..ca7812cb --- /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 00000000..06a5e7c8 --- /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 00000000..3f410a9e --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +%} + +%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 00000000..a41f30a3 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +%} + +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include 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 00000000..1b33abb9 --- /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 00000000..4616f4a9 --- /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 00000000..f743d873 --- /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 + +@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 00000000..1fa42e36 --- /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 + +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 00000000..8479aad6 --- /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 00000000..1a2cf08d --- /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 + +@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 00000000..c965df3a --- /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 + +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 00000000..c2c814b5 --- /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 00000000..7966331b --- /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 + +@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 00000000..b42bc2d9 --- /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 + +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 00000000..38c39943 --- /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 00000000..480b4a45 --- /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 + +@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 00000000..29a0b03b --- /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 + +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 00000000..08109610 --- /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 00000000..7249ee15 --- /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 +#include +#include + +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 00000000..c7676a51 --- /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 +#include +class gr_agc_cc; +typedef boost::shared_ptr 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 00000000..79ebf19d --- /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 + +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 00000000..6b0d01e7 --- /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 +#include +#include + +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 00000000..da7edb7a --- /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 +#include +class gr_agc_ff; +typedef boost::shared_ptr 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 00000000..9b631271 --- /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 + +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 00000000..005b575b --- /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 +#include +#include +#include + +//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;i200) + { + 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::max(); + int noutput_items_produced=0; + for(unsigned int i=0;i=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;i256000000 || 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 0x00000000) + if(!d_in_presync) + { +#ifdef DEBUG_TOCONSUME + printf("presync START with %i\n",i); +#endif + for(unsigned int k=0;k10) + { + 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;i2000) + { + 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 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;i0x4000000) + { + 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;i10) + { + 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 00000000..69d68b2a --- /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 + +class gr_align_on_samplenumbers_ss; +typedef boost::shared_ptr 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: 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 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 00000000..00d31749 --- /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 00000000..a74746d3 --- /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 +#include +#include + +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 00000000..ce755718 --- /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 + +class gr_binary_slicer_fb; +typedef boost::shared_ptr 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 00000000..0d66429b --- /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 00000000..3b492cdb --- /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 +#include +#include + +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 00000000..72f844d4 --- /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 + +class gr_bytes_to_syms; +typedef boost::shared_ptr 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 00000000..33ef089d --- /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 00000000..c4151eee --- /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 +#include +#include + +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 00000000..d2b287ff --- /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 + +class gr_char_to_float; +typedef boost::shared_ptr 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 00000000..3f1c7e19 --- /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 00000000..59e740c1 --- /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 +#include +#include +#include + +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 00000000..3037e9f0 --- /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 + +class gr_check_counting_s; +typedef boost::shared_ptr 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 00000000..f52f8724 --- /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 00000000..72051cf5 --- /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 +#include +#include +#include + +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 00000000..4b7eb8a1 --- /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 +#include + + +class gr_check_lfsr_32k_s; +typedef boost::shared_ptr 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 00000000..422b7cd2 --- /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 00000000..a4887335 --- /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 +#include +#include + +@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 + +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 00000000..e67e4804 --- /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 00000000..8aa8af08 --- /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 +#endif + +#include + +#include +#ifdef HAVE_SYS_MMAN_H +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#include + +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 00000000..33407457 --- /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 00000000..0d8c7f38 --- /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 +#include +#include +#include +#include + +// 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 00000000..8a65ae4d --- /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 +#include + +class gri_mmse_fir_interpolator_cc; + +class gr_clock_recovery_mm_cc; +typedef boost::shared_ptr 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 00000000..4db01aff --- /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 00000000..1219df7b --- /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 +#include +#include +#include + +#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 00000000..e970bcce --- /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 +#include + +class gri_mmse_fir_interpolator; + +class gr_clock_recovery_mm_ff; +typedef boost::shared_ptr 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 00000000..5b7bd45d --- /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 00000000..65fbbe93 --- /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 +#include +#include + +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 00000000..1afca560 --- /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 + +class gr_complex_to_interleaved_short; +typedef boost::shared_ptr + 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 00000000..1b4b6baa --- /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 00000000..727f44f0 --- /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 +#include + +// ---------------------------------------------------------------- + +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 00000000..02a9fc8f --- /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 +#include + +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_sptr; +typedef boost::shared_ptr gr_complex_to_real_sptr; +typedef boost::shared_ptr gr_complex_to_imag_sptr; +typedef boost::shared_ptr gr_complex_to_mag_sptr; +typedef boost::shared_ptr 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 00000000..06f1020a --- /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 00000000..50e25efa --- /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 +#include + +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 00000000..f1551b86 --- /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 + +class gr_conjugate_cc; +typedef boost::shared_ptr 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 00000000..efafa84c --- /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 00000000..5b4f719d --- /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 +#include +#include + +#include +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 &sym_position, + const std::vector &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 &sym_position, + const std::vector &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 &sym_position, + const std::vector &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 00000000..2cc16c57 --- /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 +#include + +class gr_constellation_decoder_cb; +typedef boost::shared_ptr gr_constellation_decoder_cb_sptr; + +gr_constellation_decoder_cb_sptr + gr_make_constellation_decoder_cb (const std::vector &sym_position, + const std::vector &sym_value_out); + + +class gr_constellation_decoder_cb : public gr_sync_block +{ + + private: + std::vector d_sym_position; + std::vector d_sym_value_out; + + friend gr_constellation_decoder_cb_sptr + gr_make_constellation_decoder_cb (const std::vector &sym_position, const std::vector &sym_value_out); + + gr_constellation_decoder_cb (const std::vector &sym_position, + const std::vector &sym_value_out); //constructor + + public: + bool set_constellation(const std::vector &sym_position, + const std::vector &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 00000000..ba1e38f6 --- /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 &sym_position, + const std::vector &sym_value_out); + +class gr_constellation_decoder_cb : public gr_sync_block +{ + private: + gr_constellation_decoder_cb (const std::vector &sym_position, + const std::vector &sym_value_out); + + friend gr_constellation_decoder_cb_sptr + gr_make_constellation_decoder_cb (const std::vector &sym_position, + const std::vector &sym_value_out); + + public: + int set_constellation(const std::vector &sym_position, + const std::vector &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 00000000..0f259860 --- /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 +#include +#include +#include + +#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 00000000..519258ca --- /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 +#include + +class gr_correlate_access_code_bb; +typedef boost::shared_ptr 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 00000000..688f3f69 --- /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 00000000..4ad627f0 --- /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 +#include +#include +#include +#include + +#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 00000000..4672c094 --- /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 +#include + +class gr_costas_loop_cc; +typedef boost::shared_ptr 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 00000000..85d2ada5 --- /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 00000000..cd51ce8a --- /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 + +/* + * 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 00000000..b0e83c83 --- /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 00000000..3b0ebd40 --- /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 +#endif +#include + + +// 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 00000000..2d6fdc85 --- /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 +#include + +/*! + * \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 00000000..79e1d086 --- /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 00000000..7ad31cbd --- /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 + +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 gr_ctcss_squelch_ff::squelch_range() const +{ + std::vector 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 00000000..337e5cab --- /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 +#include + +class gr_ctcss_squelch_ff; +typedef boost::shared_ptr 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 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 00000000..6d32c7d0 --- /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 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 00000000..1f0bc015 --- /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 +#include +#include +#include +#include +#include + +#include + +#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 00000000..fdc25614 --- /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 + +class gri_mmse_fir_interpolator_cc; + +class gr_dd_mpsk_sync_cc; +typedef boost::shared_ptr 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 00000000..3bab9e2f --- /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 00000000..375a40d2 --- /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 +#include +#include + + +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 00000000..0eb9874e --- /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 + +class gr_deinterleave; +typedef boost::shared_ptr 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 00000000..f1eac5ca --- /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 00000000..5ab88a9c --- /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 +#include + +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 00000000..c88e0e25 --- /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 + +class gr_diff_decoder_bb; +typedef boost::shared_ptr 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 00000000..b4ad5f6a --- /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 00000000..bd4135c4 --- /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 +#include + +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 00000000..c839d399 --- /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 + +class gr_diff_encoder_bb; +typedef boost::shared_ptr 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 00000000..890779c4 --- /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 00000000..c5eae5f3 --- /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 +#include + +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 00000000..64a3f291 --- /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 + +class gr_diff_phasor_cc; +typedef boost::shared_ptr 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 00000000..773d276b --- /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 00000000..e85f7b0a --- /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 + +@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 00000000..193d6f82 --- /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 + +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 00000000..8479aad6 --- /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 00000000..e33af166 --- /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 00000000..d05b06a0 --- /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 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 00000000..502bfe9e --- /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 +#include + +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 00000000..0ef4c46d --- /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 +#include +#include +#include + +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 00000000..03b651e8 --- /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 + +class gr_fake_channel_encoder_pp; +typedef boost::shared_ptr 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_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 00000000..3bf394e2 --- /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 00000000..ebbece57 --- /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 // declaration is in here +#include + +#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 00000000..b30930ec --- /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 +#endif + +#include + +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 00000000..e9f3ae35 --- /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 + +/*! + * \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 00000000..f7d8c221 --- /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 00000000..e5291590 --- /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 +#include +#include +#include + +gr_fft_vcc_sptr +gr_make_fft_vcc (int fft_size, bool forward,const std::vector 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 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 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 00000000..784471a3 --- /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 + +class gri_fft_complex; + +class gr_fft_vcc; +typedef boost::shared_ptr gr_fft_vcc_sptr; + +gr_fft_vcc_sptr +gr_make_fft_vcc (int fft_size, bool forward, const std::vector 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 window); + + unsigned int d_fft_size; + std::vector d_window; + gri_fft_complex *d_fft; + + gr_fft_vcc (int fft_size, bool forward, const std::vector 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 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 00000000..a171d122 --- /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 window); + +class gr_fft_vcc : public gr_sync_block +{ + protected: + gr_fft_vcc (int fft_size, bool forward, const std::vector window); + + public: + bool set_window(const std::vector 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 00000000..d6d24791 --- /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 +#include +#include +#include +#include + + +// 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 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 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 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 00000000..a30495d8 --- /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 + +class gri_fft_complex; + +class gr_fft_vfc; +typedef boost::shared_ptr gr_fft_vfc_sptr; + +gr_fft_vfc_sptr +gr_make_fft_vfc (int fft_size, bool forward, const std::vector); + +/*! + * \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 window); + + unsigned int d_fft_size; + std::vector d_window; + gri_fft_complex *d_fft; + + gr_fft_vfc (int fft_size, bool forward, const std::vector 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 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 00000000..f30606d8 --- /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 window); + +class gr_fft_vfc : public gr_sync_block +{ + protected: + gr_fft_vfc (int fft_size, bool forward, const std::vector window); + + public: + bool set_window(const std::vector 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 00000000..d09d68d6 --- /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 +#include + + +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 +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 taps(ntaps); + vector 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 +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 taps(ntaps); + vector 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 +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 taps(ntaps); + vector 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_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 taps(ntaps); + vector lptaps(ntaps); + vector 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 +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 taps(ntaps); + vector 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 +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 taps(ntaps); + vector 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 +gr_firdes::gaussian (double gain, + double spb, + double bt, + int ntaps) +{ + + vector 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 +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 taps(ntaps); + double scale = 0; + for(int i=0;i= 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 +gr_firdes::window (win_type type, int ntaps, double beta) +{ + vector 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 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 00000000..734f8ee9 --- /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 +#include +#include + +/*! + * \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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + gaussian (double gain, + double spb, + double bt, // Bandwidth to bitrate ratio + int ntaps); + + // window functions ... + static std::vector 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 00000000..a0ea2f45 --- /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 + 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 + 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 + 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 + 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 + 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 + 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 + 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 + gaussian (double gain, + double spb, + double bt, // Bandwidth to bitrate ratio + int ntaps); + + /*! + * Return window given type, ntaps and optional beta. + */ + static std::vector 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 00000000..ed9538fc --- /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 +#include +#include + +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 00000000..e1d0f9f0 --- /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 + +class gr_float_to_char; +typedef boost::shared_ptr 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 00000000..139439c3 --- /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 00000000..547d9173 --- /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 +#include + +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 00000000..8c285217 --- /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 +#include + +class gr_float_to_complex; +typedef boost::shared_ptr 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 00000000..4a6ea324 --- /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 00000000..171726b8 --- /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 +#include +#include + +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 00000000..75fdd943 --- /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 + +class gr_float_to_short; +typedef boost::shared_ptr 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 00000000..10726bc8 --- /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 00000000..d9402427 --- /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 +#include +#include + +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 00000000..bab00c42 --- /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 + +class gr_float_to_uchar; +typedef boost::shared_ptr 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 00000000..8c0ee584 --- /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 00000000..c1afc434 --- /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 +#include +#include +#include + +#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 00000000..3e38aeed --- /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 +#include + +class gr_framer_sink_1; +typedef boost::shared_ptr 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 00000000..fbc55696 --- /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 00000000..271b8d33 --- /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 +#include +#include +#include + + +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 00000000..6080adb9 --- /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 + +class gr_frequency_modulator_fc; +typedef boost::shared_ptr 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 00000000..04a8b536 --- /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 00000000..62ed8bd6 --- /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 + +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 00000000..fc8432d6 --- /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 + +/*! + * \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 00000000..c779bdfe --- /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 +#include + +/*! + * \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 00000000..c57a577b --- /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 +#include + +/*! + * \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 00000000..7771ed51 --- /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 +#endif +#include +#include + +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 00000000..125ee14b --- /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 +#include // 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 00000000..0a34214d --- /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 00000000..cae0cd9d --- /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 +#include +#include + + +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 00000000..128ed7ce --- /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 + +class gr_interleave; +typedef boost::shared_ptr 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 00000000..f082531f --- /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 00000000..c43e7254 --- /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 +#include +#include + +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 00000000..0eb1a32f --- /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 + +class gr_interleaved_short_to_complex; +typedef boost::shared_ptr + 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 00000000..02d1ec01 --- /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 00000000..e3020708 --- /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 +#include + +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 00000000..44a84740 --- /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 + +class gr_keep_one_in_n; +typedef boost::shared_ptr 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 00000000..13ed9a38 --- /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 00000000..bf980d23 --- /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 +#include +#include + +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 00000000..d1cf54ee --- /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 + +class gr_kludge_copy; +typedef boost::shared_ptr 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 00000000..828ec212 --- /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 00000000..8a0b8768 --- /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 +#endif +#include +#include +#include + + +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 00000000..d3d72a98 --- /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 +#include + +class gr_lfsr_32k_source_s; +typedef boost::shared_ptr 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 00000000..60b62679 --- /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 00000000..874ad84f --- /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 +#include +#include +#include + +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 + +class gr_lms_dfe_cc; +typedef boost::shared_ptr 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 d_ff_delayline; + std::vector d_fb_delayline; + std::vector d_ff_taps; + std::vector 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 00000000..4ea4a6ae --- /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 00000000..017c90a2 --- /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 +#include +#include +#include + +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 + +class gr_lms_dfe_ff; +typedef boost::shared_ptr 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 d_ff_delayline; + std::vector d_fb_delayline; + std::vector d_ff_taps; + std::vector 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 00000000..6b9e439d --- /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 00000000..fe255045 --- /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 + +template 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 00000000..891ff02c --- /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 +#include + +gr_map_bb_sptr +gr_make_map_bb (const std::vector &map) +{ + return gr_map_bb_sptr (new gr_map_bb (map)); +} + +gr_map_bb::gr_map_bb (const std::vector &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 00000000..f5f7fa8d --- /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 + +class gr_map_bb; +typedef boost::shared_ptr gr_map_bb_sptr; + +gr_map_bb_sptr gr_make_map_bb(const std::vector &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 &map); + + unsigned char d_map[0x100]; + + gr_map_bb(const std::vector &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 00000000..a4282a3e --- /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 &map); + +class gr_map_bb : public gr_sync_block +{ + private: + gr_map_bb (const std::vector &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 00000000..e2e7249e --- /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 +#endif + +#include +#include + +/* + * 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 00000000..5ce8fb78 --- /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 00000000..d1520227 --- /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 + +unsigned int +gr_rounduppow2(unsigned int n) +{ + int i; + for (i=0;((n-1)>>i) != 0;i++) + ; + return 1< &v) +{ + for(unsigned int i=0; i < v.size(); i++) + v[i] = 0; +} + +void +gr_zero_vector(std::vector &v) +{ + for(unsigned int i=0; i < v.size(); i++) + v[i] = 0; +} + +void +gr_zero_vector(std::vector &v) +{ + for(unsigned int i=0; i < v.size(); i++) + v[i] = 0; +} + +void +gr_zero_vector(std::vector &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 00000000..177df964 --- /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 + +unsigned int +gr_rounduppow2(unsigned int n); + +// FIXME should be template +void gr_zero_vector(std::vector &v); +void gr_zero_vector(std::vector &v); +void gr_zero_vector(std::vector &v); +void gr_zero_vector(std::vector &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 00000000..a9c43224 --- /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 + +@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 00000000..cfa416f1 --- /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 + +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 00000000..8479aad6 --- /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 00000000..b312b9c0 --- /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 + +@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 00000000..6e771e0b --- /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 + +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 00000000..c2c814b5 --- /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 00000000..9b723a3e --- /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 + +@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 00000000..dba875c3 --- /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 + +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 00000000..38c39943 --- /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 00000000..cc242dda --- /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 + +@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 00000000..c6388d93 --- /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 + +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 00000000..08109610 --- /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 00000000..740821e5 --- /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 +#include + + +@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 00000000..88915322 --- /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 + +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 00000000..413e5298 --- /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 00000000..2cf41fd7 --- /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 +#include +#include +#include + +/*! + * \brief base class template for Numerically Controlled Oscillator (NCO) + */ + + +//FIXME Eventually generalize this to fixed point + +template +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 +void +gr_nco::sincos (float *sinx, float *cosx) const +{ + gr_sincosf (phase, sinx, cosx); +} + +template +void +gr_nco::sin (float *output, int noutput_items, double ampl) +{ + for (int i = 0; i < noutput_items; i++){ + output[i] = (float)(sin () * ampl); + step (); + } +} + +template +void +gr_nco::cos (float *output, int noutput_items, double ampl) +{ + for (int i = 0; i < noutput_items; i++){ + output[i] = (float)(cos () * ampl); + step (); + } +} + +template +void +gr_nco::sin (short *output, int noutput_items, double ampl) +{ + for (int i = 0; i < noutput_items; i++){ + output[i] = (short)(sin() * ampl); + step (); + } +} + +template +void +gr_nco::cos (short *output, int noutput_items, double ampl) +{ + for (int i = 0; i < noutput_items; i++){ + output[i] = (short)(cos () * ampl); + step (); + } +} + +template +void +gr_nco::sin (int *output, int noutput_items, double ampl) +{ + for (int i = 0; i < noutput_items; i++){ + output[i] = (int)(sin () * ampl); + step (); + } +} + +template +void +gr_nco::cos (int *output, int noutput_items, double ampl) +{ + for (int i = 0; i < noutput_items; i++){ + output[i] = (int)(cos () * ampl); + step (); + } +} + +template +void +gr_nco::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 00000000..71e8279a --- /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 +#include +#include + +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 00000000..04a6f80d --- /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 + +class gr_nlog10_ff; +typedef boost::shared_ptr 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 00000000..3dbd12d8 --- /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 00000000..401bed19 --- /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 +#endif +#include <@NAME@.h> +#include +#include + + +@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 00000000..bc016aff --- /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 +#include +#include + + +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 00000000..0a3ad96a --- /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 00000000..886d5f44 --- /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 00000000..0a3f4f33 --- /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 +#endif +#include +#include + +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 00000000..faf93862 --- /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 +#include // 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 00000000..556ad573 --- /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 00000000..7e9c7a79 --- /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 +#include + +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 00000000..55b61aac --- /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 +#include // 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 00000000..145be901 --- /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 00000000..65923cf7 --- /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 +#include + +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 00000000..9fc43a07 --- /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 + +/*! + * \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 00000000..8a88f359 --- /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 00000000..7f470af9 --- /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 +#include + +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 00000000..e8634968 --- /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 + +class gr_pa_2x2_phase_combiner; +typedef boost::shared_ptr 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 00000000..a19413af --- /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 00000000..f585c4a6 --- /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 +#include +#include + +static const unsigned int BITS_PER_TYPE = sizeof(@I_TYPE@) * 8; +static const unsigned int LOG2_L_TYPE = gr_log2_const(); + + +@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= (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 00000000..1c9d2a0d --- /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 +#include + +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 00000000..9517a8ac --- /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 00000000..f88758b9 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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& 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& 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 (countmsg(), 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 00000000..3c468afd --- /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 +#include + +class gr_packet_sink; +typedef boost::shared_ptr gr_packet_sink_sptr; + +gr_packet_sink_sptr +gr_make_packet_sink (const std::vector& 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& 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& 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 00000000..fb960729 --- /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& 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& 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 00000000..95631f09 --- /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 +#include +#include +#include + + +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 00000000..ea274275 --- /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 + +class gr_phase_modulator_fc; +typedef boost::shared_ptr 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 00000000..0ce25fd1 --- /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 00000000..4736e77c --- /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 +#include +#include +#include + +#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 00000000..679eb24d --- /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 + +class gr_pll_carriertracking_cc; +typedef boost::shared_ptr 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 00000000..2653f8e8 --- /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 00000000..f15f160d --- /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 +#include +#include + +#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 00000000..3d05a1c2 --- /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 + +class gr_pll_freqdet_cf; +typedef boost::shared_ptr 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 00000000..8a27c4fd --- /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 00000000..e5356118 --- /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 +#include +#include +#include + +#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 00000000..c46a65ee --- /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 + +class gr_pll_refout_cc; +typedef boost::shared_ptr 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 00000000..8cb4fde8 --- /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 00000000..25c6960c --- /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 + +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 00000000..a521b619 --- /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 + +/*! + * \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 00000000..04e1899a --- /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 00000000..c9721f0f --- /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 +#endif + +#include + +/* + * 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 00000000..eaf74870 --- /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 + +/*! + * \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 00000000..d11da173 --- /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 00000000..73c7343b --- /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 +#include +#include + +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 00000000..85e2244b --- /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 +#include + +class gr_probe_avg_mag_sqrd_c; +typedef boost::shared_ptr 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 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 00000000..0b8000c5 --- /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 00000000..439138f0 --- /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 +#include +#include + +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 00000000..5f20a5ca --- /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 +#include + +class gr_probe_avg_mag_sqrd_f; +typedef boost::shared_ptr 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 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 00000000..f58caa2d --- /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 00000000..8c94b036 --- /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 +#include + +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 00000000..72811b20 --- /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 + +class gr_probe_signal_f; +typedef boost::shared_ptr 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 00000000..14fc6f19 --- /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 00000000..33c12872 --- /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_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 gr_pwr_squelch_cc::squelch_range() const +{ + std::vector 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 00000000..2822ee59 --- /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 +#include +#include + +class gr_pwr_squelch_cc; +typedef boost::shared_ptr 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 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 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 00000000..41832ab7 --- /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 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 00000000..8bc3aad6 --- /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_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 gr_pwr_squelch_ff::squelch_range() const +{ + std::vector 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 00000000..1eb61b16 --- /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 +#include +#include + +class gr_pwr_squelch_ff; +typedef boost::shared_ptr 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 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 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 00000000..4bc16b10 --- /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 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 00000000..eb1fae85 --- /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 +#include +#include + +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 00000000..7e625e7a --- /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 + +class gr_quadrature_demod_cf; +typedef boost::shared_ptr 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 00000000..685b278f --- /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 00000000..a56f2875 --- /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 +#include + +#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 00000000..9726ee9b --- /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 + +/*! + * \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 00000000..10039000 --- /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 +#include +#include +#include + + +#ifndef LOCAL_BUFFER +#include +#define LOCAL_BUFFER(T, buf, size) \ + std::vector 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 (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; j0.0) && (E[0]>E[1])) || + ((E[0]<0.0) && (E[0]=E[i-1]) && (E[i]>E[i+1]) && (E[i]>0.0)) || + ((E[i]<=E[i-1]) && (E[i]= 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]= 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 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 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 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 +gr_remez (int order, + const std::vector &arg_bands, + const std::vector &arg_response, + const std::vector &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 (&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) 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 00000000..c910803b --- /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 +#include +#include + +/*! + * \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 +gr_remez (int order, + const std::vector &bands, + const std::vector &l, + const std::vector &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 00000000..2e2471e2 --- /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 +gr_remez (int order, + const std::vector &bands, + const std::vector &l, + const std::vector &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 00000000..099deb60 --- /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 + + +std::vector +gr_reverse (const std::vector &taps) +{ + int size = taps.size (); + std::vector 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_reverse (const std::vector &taps) +{ + int size = taps.size (); + std::vector 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 00000000..cff53255 --- /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 +#include + +// reverse the order of taps +std::vector gr_reverse (const std::vector &taps); +std::vector gr_reverse (const std::vector &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 00000000..7abfefd1 --- /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 +#include +#include + +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 00000000..bc16c23e --- /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 +#include + +class gr_rms_cf; +typedef boost::shared_ptr 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 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 00000000..0d7b05c8 --- /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 00000000..187be638 --- /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 +#include +#include + +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 00000000..3f276eb2 --- /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 +#include + +class gr_rms_ff; +typedef boost::shared_ptr 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 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 00000000..bf9dbe2d --- /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 00000000..3ca79373 --- /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 +#include +#include + +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 00000000..ee5a4ee1 --- /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 + +class gr_short_to_float; +typedef boost::shared_ptr 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 00000000..724165d5 --- /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 00000000..079864b2 --- /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 +#endif +#include <@NAME@.h> +#include +#include +#include +#include + + +@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 00000000..2cdeb326 --- /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 +#include +#include + +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 00000000..3e769d42 --- /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 00000000..2d0dc567 --- /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 00000000..09c81239 --- /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 +#include +#include +#include +#include +#include + + +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 00000000..5697e170 --- /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 +#include + +//#define DEBUG_SIMPLE_CORRELATOR + +class gr_simple_correlator; +typedef boost::shared_ptr 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 00000000..d143648f --- /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 00000000..797b1f3b --- /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 +#include +#include +#include +#include + + +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 00000000..33813741 --- /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 + +class gr_simple_framer; +typedef boost::shared_ptr 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 00000000..4083ce16 --- /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 00000000..c7f65528 --- /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 00000000..e34f9a13 --- /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 +#include +#include + +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 +gr_simple_squelch_cc::squelch_range() const +{ + std::vector 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 00000000..31fde128 --- /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 +#include + +class gr_simple_squelch_cc; +typedef boost::shared_ptr 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 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 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 00000000..5e3339a2 --- /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 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 00000000..599d00bf --- /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 +#endif +#include +#include + +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 00000000..e87f8a4e --- /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 +#include // 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 00000000..deedeb3b --- /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 00000000..b3e61fcc --- /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 +#include + +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 00000000..4e331284 --- /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 + +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 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 00000000..0ef674c4 --- /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 + +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 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 00000000..a457c5f6 --- /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 +#include + +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 00000000..4128735a --- /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 + +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 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 00000000..d749d498 --- /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 + +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 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 00000000..d4627964 --- /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 +#include + +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 00000000..3775e79b --- /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 + +class gr_stream_to_streams; +typedef boost::shared_ptr 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 00000000..59b93da0 --- /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 00000000..3d815cf5 --- /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 +#include + +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 00000000..a0a318b6 --- /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 + +class gr_stream_to_vector; +typedef boost::shared_ptr 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 00000000..16550ac0 --- /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 00000000..9d05fbf7 --- /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 +#include + +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 00000000..86d39094 --- /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 + +class gr_streams_to_stream; +typedef boost::shared_ptr 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 00000000..0f9e46fc --- /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 00000000..794254dd --- /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 +#include + +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 00000000..d3a89035 --- /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 + +class gr_streams_to_vector; +typedef boost::shared_ptr 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 00000000..a69c2e5a --- /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 00000000..2cfdc6e9 --- /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 + +@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 00000000..025c077a --- /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 + +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 00000000..8479aad6 --- /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 00000000..57b6c556 --- /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::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 00000000..b4a2d008 --- /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 + +/*! + * \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 00000000..c078a8b8 --- /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 00000000..4b168a5d --- /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::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 00000000..6cdd35a4 --- /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 + +/*! + * \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 00000000..d9f6483a --- /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 00000000..024d7e78 --- /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::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 00000000..914ea8e5 --- /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 + +/*! + * \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 00000000..9b69d334 --- /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 00000000..17263f49 --- /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 +#include +#include +#include + +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 +#include +#include "gr_test_types.h" + +class gr_test; +typedef boost::shared_ptr 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 00000000..e6f922c0 --- /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_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 00000000..92fe3f74 --- /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 00000000..4041f467 --- /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 +#include + +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 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 00000000..30ca67f5 --- /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 + +class gr_threshold_ff; +typedef boost::shared_ptr 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 00000000..2fcf1dea --- /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 00000000..9fbf23ed --- /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 +#include +#include +#include +#include +#ifdef HAVE_TIME_H +#include +#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 00000000..c926a405 --- /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 +#ifdef HAVE_SYS_TIME_H +#include +#endif + +class gr_throttle; +typedef boost::shared_ptr 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 00000000..eb237b35 --- /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 00000000..e162d777 --- /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 +#include +#include + +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 00000000..7de55726 --- /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 + +class gr_uchar_to_float; +typedef boost::shared_ptr 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 00000000..4b7e8bce --- /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 00000000..399bc111 --- /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 +#include +#include +#include + +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 00000000..38a8bc1a --- /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 + +class gr_unpack_k_bits_bb; +typedef boost::shared_ptr 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 00000000..eb6bda9d --- /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 00000000..7d5d72e6 --- /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 +#include + +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>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 00000000..8d8c14d2 --- /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 +#include + +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 00000000..7fdcb5d7 --- /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 00000000..3c35bdff --- /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 +#include +#include +#include + +/*! + * \brief base class template for Voltage Controlled Oscillator (VCO) + */ + +//FIXME Eventually generalize this to fixed point + +template +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 +void +gr_vco::sincos (float *sinx, float *cosx) const +{ + gr_sincosf (d_phase, sinx, cosx); +} + +template +void +gr_vco::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 00000000..7421e4ec --- /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 +#include +#include + +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 00000000..2872d387 --- /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 +#include + +class gr_vco_f; +typedef boost::shared_ptr 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 00000000..d3447450 --- /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 00000000..5e99a928 --- /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 +#endif +#include <@NAME@.h> +#include +#include + + +@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 00000000..e549f1fb --- /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 + +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 00000000..d10636cf --- /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 00000000..4ec2dd8b --- /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 +#endif +#include <@NAME@.h> +#include +#include + + +@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 00000000..631ab867 --- /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 + +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 00000000..f3b98c62 --- /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 00000000..130f9613 --- /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 +#include + +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 00000000..5efff733 --- /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 + +class gr_vector_to_stream; +typedef boost::shared_ptr 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 00000000..66ae1739 --- /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 00000000..4a3f110e --- /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 +#include + +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 00000000..ae13fae4 --- /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 + +class gr_vector_to_streams; +typedef boost::shared_ptr 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 00000000..7444d0d6 --- /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 00000000..49fddb68 --- /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 00000000..f94db30e --- /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 + +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 00000000..eaaed8c3 --- /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 + +/*! + * \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 00000000..0bdbd404 --- /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 + +/*! + * \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 00000000..5cdd4e46 --- /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 + +/*! + * \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 00000000..70c1baa7 --- /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 + +/*! + * \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 00000000..ca02ca27 --- /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 + +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 00000000..7aa38d02 --- /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 00000000..35e138aa --- /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 + +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 00000000..612b7c59 --- /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 00000000..30b01271 --- /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 +#include +#include +#include +#include +#include +#include +#include + +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(d_inbuf), + reinterpret_cast(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(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(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 00000000..50347748 --- /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 + +/*! + * \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 00000000..b94c5344 --- /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 +#include + +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 00000000..8891ac1a --- /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 00000000..b2910616 --- /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 +#include + +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 00000000..e13b61d5 --- /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 00000000..8281a967 --- /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 +#include + +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 00000000..fbde8c51 --- /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 00000000..56e3c39a --- /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 +#include + +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 00000000..3a0fc3de --- /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 + +/* + * 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 00000000..561ba6c5 --- /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 00000000..653223e6 --- /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 + +/*! + * \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 00000000..f6beb456 --- /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 + +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 00000000..1abd0dd5 --- /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 00000000..8a5f87a5 --- /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 + +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 00000000..50646e46 --- /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 00000000..2cc6135e --- /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 + +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 00000000..0376ec56 --- /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 + +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 00000000..1fa2b935 --- /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 +#include +#include +#include +#include +#include + +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 00000000..6bf57df6 --- /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 + +//! 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 00000000..adfa33cb --- /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 +#include +#include +#include +#include +#include + +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 00000000..45ebfd8e --- /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 +#include + +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 00000000..072bcb68 --- /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 +#include +#include +#include +#include +#include +#include +#include + +#define NELEM(x) (sizeof (x) / sizeof (x[0])) + +using std::vector; + +static void +print_taps (std::ostream &s, vector &v) +{ + + for (unsigned int i = 0; i < v.size (); i++){ + printf ("tap[%2d] = %16.7e\n", i, v[i]); + } +} + +static void +check_symmetry (vector &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 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 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 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 00000000..8fb4d5a3 --- /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 +#include + +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 00000000..6cd582ad --- /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 +#endif +#include +#include +#include +#include +#include +#include +#include + +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 00000000..a21be5cc --- /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 +#include + +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 00000000..5b774fb8 --- /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 +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +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 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 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 00000000..3d0c84a0 --- /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 +#include + +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 00000000..70c2da36 --- /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 +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +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 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 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 00000000..80ea0253 --- /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 +#include + +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 00000000..816aca34 --- /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 + +#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 00000000..69834943 --- /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 00000000..e390e134 --- /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 00000000..6a0b1ca4 --- /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 +#include +#include +#include +#include +#include +#include +#include + + +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 00000000..a811ce70 --- /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 + +class gr_file_descriptor_sink; +typedef boost::shared_ptr 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 00000000..e0581865 --- /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 00000000..38b9da01 --- /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 +#include +#include +#include +#include +#include +#include +#include + + +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 00000000..9f678dcf --- /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 + +class gr_file_descriptor_source; +typedef boost::shared_ptr 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 00000000..ba9b3894 --- /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 00000000..d22488bf --- /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 +#include +#include +#include +#include +#include +#include + +// win32 (mingw/msvc) specific +#ifdef HAVE_IO_H +#include +#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 00000000..9c11bf72 --- /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 +#include + +class gr_file_sink; +typedef boost::shared_ptr 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 00000000..ffcf02aa --- /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 00000000..2573a37e --- /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 +#include +#include +#include +#include +#include +#include + +// win32 (mingw/msvc) specific +#ifdef HAVE_IO_H +#include +#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 00000000..6b635c53 --- /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 + +class gr_file_source; +typedef boost::shared_ptr 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 00000000..08fdfaf9 --- /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 00000000..8a0784ec --- /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 +#include +#include +#include +#include +#include +#include +#include + + +// 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 00000000..8011ab29 --- /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 +#include +#include + +class gr_message_sink; +typedef boost::shared_ptr 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 00000000..ca73479c --- /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 00000000..797433be --- /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 +#include +#include +#include +#include +#include +#include +#include + + +// 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 00000000..02060124 --- /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 +#include +#include + +class gr_message_source; +typedef boost::shared_ptr 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 00000000..369112ef --- /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 00000000..6636fff1 --- /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 +#endif +#include +#include +#include +#include +#include +#include +#include + +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 00000000..4094a653 --- /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 +#include + +/*! + * \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 00000000..ea841990 --- /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 00000000..b505381d --- /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 +#include +#include + + +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 00000000..7b92a785 --- /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 +#include + +class gr_oscope_sink_f; +typedef boost::shared_ptr 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 00000000..51c28678 --- /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 +#include +#include + + +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 00000000..45cccc0d --- /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 +#include + +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 00000000..0928c6a3 --- /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 00000000..a1bdfb0e --- /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 +#endif + +#include +#include +#include +#include +#include + + +/* + * 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 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 00000000..ecbd3141 --- /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 +#include +#include + +class gri_log_poster; +class gri_logger; +typedef boost::shared_ptr 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 00000000..9b9fbcd1 --- /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 00000000..88b3c913 --- /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 + +class i2c; +typedef boost::shared_ptr 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 00000000..8f383976 --- /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 00000000..f0ea3b66 --- /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 + +class i2c_bbio; +typedef boost::shared_ptr 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 00000000..125f01c3 --- /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 00000000..25af0cf4 --- /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 00000000..6bf37b60 --- /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 00000000..5196cd23 --- /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 +#include + +/*! + * \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 00000000..ae4ca268 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +%} + +%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 00000000..9b180ff8 --- /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 +#include +#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 00000000..b5890774 --- /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 + +/*! + * \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 00000000..88cf2b6a --- /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 00000000..9fc2914e --- /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 00000000..6205c930 --- /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 00000000..c05f63c1 --- /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 +#include +#include + +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 00000000..84c8d611 --- /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 + +/*! + * \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 00000000..82a03740 --- /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 00000000..8a8f46b0 --- /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 00000000..106832e3 --- /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 00000000..7c673e3a --- /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 00000000..5245fd5c --- /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 00000000..8633b111 --- /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 00000000..8fac06d8 --- /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 + +class i2c; +typedef boost::shared_ptr 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 00000000..a7ea98d6 --- /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 + +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 00000000..3a817b69 --- /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 + +class microtune_xxxx; + +class ppio; +typedef boost::shared_ptr ppio_sptr; + +class i2c; +typedef boost::shared_ptr 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 00000000..2e43f27a --- /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 00000000..86f402bb --- /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 +#include + +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 00000000..41813870 --- /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 + +class ppio; +typedef boost::shared_ptr 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 00000000..2eaddc20 --- /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_sptr; + +%template(ppio_sptr) boost::shared_ptr; + +/*! + * \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 00000000..bfdaa3de --- /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 +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_LINUX_PPDEV_H +#include +#include +#include +#include +#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 00000000..8ac4a35d --- /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 + +class ppio_ppdev; +typedef boost::shared_ptr 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 00000000..1cb9b9af --- /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 +#include + +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 00000000..f9ddb35c --- /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 + +class ppio; +typedef boost::shared_ptr 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 00000000..46690e0c --- /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 00000000..7985fb3e --- /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 00000000..b7970227 --- /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 00000000..93fb6ea5 --- /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 +#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 . */ +#ifndef _NO_PROTO +#define _NO_PROTO +#endif + +#include + +/* 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 +#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 +#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 00000000..45541f5a --- /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 00000000..4ed15e21 --- /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 + +#ifdef HAVE_WINDOWS_H +#include +#endif +#ifdef HAVE_WINBASE_H +# include +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#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 00000000..4a0f75ea --- /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 + +#ifndef HAVE_USLEEP + +#include +#include + +#ifdef HAVE_SYS_SELECT_H +# include +#endif + +#ifdef HAVE_WINDOWS_H +#include +#endif +#ifdef HAVE_WINBASE_H +# include +#endif + +#ifdef apollo +# include +# include + 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 00000000..f2234468 --- /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 00000000..d5380341 --- /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 00000000..06f8a11e --- /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 +#include +#include +#include +#include "omnithread.h" + +#define DB(x) // x +// #include or #include 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 00000000..09be4229 --- /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 +#endif + +#include +#include +#include +#include + +#define DB(x) // x +//#include or #include 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 00000000..f63adc4f --- /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 +#endif + +#if defined(OMNITHREAD_POSIX) +#include + +#elif defined(OMNITHREAD_NT) +#include + +#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 + +#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 +#else +#include +#endif + +#elif defined(__rtems__) +#include +#include + +#elif defined(__macos__) +#include +#include + +#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 00000000..e96c036c --- /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 +#include +#include + + +/////////////////////////////////////////////////////////////////////////// +// 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 00000000..483f600f --- /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 + +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 00000000..3ed173f2 --- /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 + +#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 00000000..1e5bf9d2 --- /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 +#else +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN +# define OMNI_DEFINED_WIN32_LEAN_AND_MEAN +# endif +# include +# 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 00000000..cf3d8794 --- /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 + + 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 + +#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 00000000..aaef036f --- /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 + +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 00000000..5fda14fc --- /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 +#include +#include +#include +#include + +#ifdef HAVE_NANOSLEEP +#undef NoNanoSleep +#else +#define NoNanoSleep +#endif + +#ifdef HAVE_SYS_TIME_H +// typedef of struct timeval and gettimeofday(); +#include +#include +#endif + +#if defined(__linux__) && defined(_MIT_POSIX_THREADS) +#include +#endif + +#if defined(__irix__) && defined(PthreadSupportThreadPriority) +#if _POSIX_THREAD_PRIORITY_SCHEDULING +#include +#endif +#endif + +#define DB(x) // x +//#include or #include 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 00000000..827a645f --- /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 +#include +#include + +#define DB(x) // x +// #include or #include 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 00000000..3d007714 --- /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 00000000..25634ce9 --- /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 +#include +#include +#include +#include +#include + +#include // assert +#include // 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 + #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()<mutexID<<" tid:"<<(int)taskIdSelf()<mutexID<<" tid:"<<(int)taskIdSelf()< count. + + STATUS status = semTake(waiters_lock_,WAIT_FOREVER); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::wait"<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"< count. + status = semTake(waiters_lock_,WAIT_FOREVER); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::wait"<, 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 count. + STATUS status = semTake(waiters_lock_, WAIT_FOREVER); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::timedwait"<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"<id()<<" SemID:"<<(int)sema_<<" errno:"<, 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()< 0; + + status = semGive(waiters_lock_); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::signal"<mutexID<<" tid:"<<(int)taskIdSelf()< must be locked before this call is made. + // This is needed to ensure that and 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"< 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 held. + have_waiters = 1; + } + + status = semGive(waiters_lock_); + + DBG_ASSERT(assert(status == OK)); + + if(status != OK) + { + DBG_TRACE(cout<<"Exception: omni_condition::signal"<id()<<" SemID:"<<(int)sema_<<" errno:"<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 "<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 "<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 "<id()<<" detached "<detached<<" return value "<<(int)return_value<detached) + delete me; + } + else + DBG_TRACE(cout<<"omni_thread::exit: called with a non-omnithread. Exit quietly."<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 00000000..71af7664 --- /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 00000000..8550b415 --- /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 00000000..341832db --- /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 00000000..f30644ff --- /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 00000000..0f2bde61 --- /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 00000000..2fbcb504 --- /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<= 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 00000000..ca409782 --- /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 +#endif + +#include + +#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 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 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 0){ + /* Convert from conventional to dual basis */ + for(i=0;i + +#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 +#endif + +#include +#include +#include + +#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= 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 00000000..1e4e4f53 --- /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 +#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 00000000..9dde1891 --- /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 +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< + +#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<= (1<= (1<mm = symsize; + rs->nn = (1<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;inn;i++){ + rs->index_of[sr] = i; + rs->alpha_to[i] = sr; + sr <<= 1; + if(sr & (1<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 00000000..2b0405ae --- /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<= 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 00000000..c3953ce5 --- /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 00000000..9e731d9d --- /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 00000000..d8fc5448 --- /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 +#endif + +#include +#include +#include +#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< +#include +#include + +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 00000000..df72e1a3 --- /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 +#include + +/*! + * \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 00000000..f1f0332e --- /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_sptr; +%template(gr_block_sptr) boost::shared_ptr; + +// support vectors of these... +namespace std { + %template(x_vector_gr_block_sptr) vector; +}; + +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: "" % (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 00000000..0ad5da49 --- /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 +#include + +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 00000000..90c912c2 --- /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 +#include + +/*! + * \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 d_input; + std::vector 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 00000000..9d3843eb --- /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_sptr; +%template(gr_block_detail_sptr) boost::shared_ptr; +%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 00000000..d3d12309 --- /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 +#include +#include +#include +#include +#include +#include + +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::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 00000000..6f85f275 --- /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 + +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 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 00000000..80f92ece --- /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_sptr; +%template(gr_buffer_sptr) boost::shared_ptr; +%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_sptr; +%template(gr_buffer_reader_sptr) boost::shared_ptr; +%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 00000000..242b2f54 --- /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 +typedef std::complex gr_complex; +typedef std::complex 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 00000000..c2a1eb50 --- /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 +#include +#include + +#ifdef HAVE_SELECT +# ifdef HAVE_SYS_SELECT_H +# include +# else +# ifdef HAVE_SYS_TIME_H +# include +# endif +# ifdef HAVE_SYS_TYPES_H +# include +# endif +# ifdef HAVE_UNISTD_H +# include +# 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 00000000..a3d85797 --- /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 +#include + +class gr_dispatcher; +typedef boost::shared_ptr 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 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 00000000..5feca757 --- /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_sptr; +%template(gr_dispatcher_sptr) boost::shared_ptr; + +%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 00000000..a3148cfd --- /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 +#include +#include +#include + +#ifdef HAVE_IO_H +#include +#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 00000000..275db64c --- /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 +#include + +/*! + * \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 00000000..d0e61496 --- /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 00000000..7277108c --- /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 +#endif +#include +#include +#include + +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 00000000..e0d97907 --- /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 + +/*! + * \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 00000000..601142e2 --- /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_sptr; +%template(gr_io_signature_sptr) boost::shared_ptr; + +%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 00000000..c6da0978 --- /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 +#include +#include + + +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 00000000..69eb65d8 --- /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 +#include + +/*! + * \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 00000000..e9427e64 --- /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 +#include + +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 00000000..272a82ee --- /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 +#include + +class gr_message; +typedef boost::shared_ptr 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 00000000..19d5d1cd --- /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_sptr; +%template(gr_message_sptr) boost::shared_ptr; + +%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 00000000..98007e23 --- /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::~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 00000000..15aab338 --- /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 + +class gr_msg_handler; +typedef boost::shared_ptr 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 00000000..5571665a --- /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 00000000..6b53fc7e --- /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 +#include + + +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 00000000..6a9147ee --- /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 +#include + +class gr_msg_queue; +typedef boost::shared_ptr 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 00000000..28292d66 --- /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_sptr; +%template(gr_msg_queue_sptr) boost::shared_ptr; + +%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 00000000..dec40678 --- /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 +#include +#include + +#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 00000000..a5cadb70 --- /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 00000000..85431444 --- /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 +#include +#include +#include +#include +#include +#include + + +#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 00000000..5a7cad45 --- /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 00000000..4f23ea0c --- /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 +#endif +#include + +#ifdef HAVE_SCHED_H +#include +#endif + +#include +#include +#include + +#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 00000000..3aeafa53 --- /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 00000000..cb43e051 --- /dev/null +++ b/gnuradio-core/src/lib/runtime/gr_realtime.i @@ -0,0 +1,4 @@ +%rename(enable_realtime_scheduling) gr_enable_realtime_scheduling; + +%include + 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 00000000..f138e6ac --- /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 + +/* + * 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_sptr; +typedef boost::shared_ptr gr_block_detail_sptr; +typedef boost::shared_ptr gr_io_signature_sptr; +typedef boost::shared_ptr gr_buffer_sptr; +typedef boost::shared_ptr 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 00000000..d85883a6 --- /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::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 00000000..d07ff007 --- /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 + +class gr_select_handler; +typedef boost::shared_ptr 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 00000000..3d401557 --- /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 +#include +#include +#include +#include +#include +#include +#include + +// 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 << "name() << " (" << m->unique_id() << ")>"; + return os; +} + +gr_single_threaded_scheduler_sptr +gr_make_single_threaded_scheduler (const std::vector &blocks) +{ + return + gr_single_threaded_scheduler_sptr (new gr_single_threaded_scheduler (blocks)); +} + +gr_single_threaded_scheduler::gr_single_threaded_scheduler ( + const std::vector &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::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: 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 00000000..1272831e --- /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 +#include + +class gr_single_threaded_scheduler; +typedef boost::shared_ptr 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 d_blocks; + volatile bool d_enabled; + std::ofstream *d_log; + + gr_single_threaded_scheduler (const std::vector &blocks); + + void main_loop (); + + friend gr_single_threaded_scheduler_sptr + gr_make_single_threaded_scheduler (const std::vector &blocks); +}; + +gr_single_threaded_scheduler_sptr +gr_make_single_threaded_scheduler (const std::vector &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 00000000..40058228 --- /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 + +class gr_single_threaded_scheduler; +typedef boost::shared_ptr gr_single_threaded_scheduler_sptr; +%template(gr_single_threaded_scheduler_sptr) boost::shared_ptr; +%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 &modules); + +class gr_single_threaded_scheduler { + public: + ~gr_single_threaded_scheduler (); + + // void run (); + void stop (); + + private: + gr_single_threaded_scheduler (const std::vector &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 00000000..ca4f6e60 --- /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 ## _sptr; +%template(NAME ## _sptr) boost::shared_ptr; +%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: "" % (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 00000000..709b9847 --- /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 + +class gr_timer; + +typedef boost::shared_ptr 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 00000000..7eb03b5d --- /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 +#include +#include +#include + +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 00000000..742ce056 --- /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 00000000..370ca564 --- /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 +#include +#include // size_t + +#include + +typedef std::vector gr_vector_int; +typedef std::vector gr_vector_float; +typedef std::vector gr_vector_double; +typedef std::vector gr_vector_void_star; +typedef std::vector gr_vector_const_void_star; + +/* + * #include must be placed beforehand + * in the source file including gr_types.h for + * the following to work correctly + */ +#ifdef HAVE_STDINT_H +#include +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 00000000..3586c4c7 --- /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 +#include +#include +#include +#include +#include + +// all the factories we know about +#include +#include +#include +#include + +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 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_sysconfig::all_factories () +{ + std::vector 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 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 00000000..e2af9358 --- /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 + +/*! + * \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 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 00000000..8f3540b4 --- /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 +#include +#include +#include +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_MMAN_H +#include +#endif +#include +#include +#include +#include +#include + + +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 00000000..f7113cf4 --- /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 + +#ifdef HAVE_CREATEFILEMAPPING +#include +#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 00000000..65fa1183 --- /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 +#include +#include +#include +#include +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_MMAN_H +#include +#endif +#include +#include +#include +#include + + +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 00000000..4b1feaff --- /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 + +/*! + * \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 00000000..a07df779 --- /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 +#include +#include +#include +#include +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_MMAN_H +#include +#endif +#include +#include +#include +#include +#include +#include + + +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 00000000..3b9f5dba --- /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 + +/*! + * \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 00000000..4b6fcfe3 --- /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 +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_IPC_H +#include +#endif +#ifdef HAVE_SYS_SHM_H +#include +#endif +#include +#include +#include + + +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 00000000..9a8c128a --- /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 + +/*! + * \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 00000000..e3a21be3 --- /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 +#endif +#include +#include +#include +#include +#include +#include + + +// ---------------------------------------------------------------- + + +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 00000000..6e308251 --- /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 +#include +#include + +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 00000000..5c549d0b --- /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 +#endif +#include +#include +#include +#include +#include + +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 00000000..700629cc --- /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 +#include + +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 00000000..c180e7b7 --- /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 +#endif +#include +#include + +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 00000000..225ce806 --- /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 +#include +#include + +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 00000000..f3c815a0 --- /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 +#endif + +#include +#include +#include +#include + +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 00000000..41f69c35 --- /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 +#include + +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 00000000..668628f2 --- /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 +#include +#include +#include +#include + +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 00000000..5862b1ea --- /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 + +//! 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 00000000..d8dd34f1 --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +%} + +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include +%include 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 00000000..26bfa6d2 --- /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 +#include + +gr_block_sptr +foo (gr_vector_source_i_sptr s) +{ + return gr_block_sptr (s); +} + +typedef gr_shared_block_sptr gr_vector_source_i_ptrX; +//typedef boost::shared_ptr 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 00000000..77bd0308 --- /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.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 00000000..4e8bf48f --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +%} + +// 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 + + +// leave out the VrHistoryProc and pretend we're directly derived from VrSigProc + +// %template(VrHistoryProc_1) VrHistoryProc; + +class GrAtscRandomizer : public VrSigProc +// class GrAtscRandomizer : public VrHistoryProc +{ +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 GrAtscSymbolMapper : public VrSigProc +{ +public: + GrAtscSymbolMapper (); + ~GrAtscSymbolMapper (); +}; + +%template(GrAtscSymbolMapperF) GrAtscSymbolMapper; + +template +class GrWeaverModHead : public VrSigProc +{ +public: + GrWeaverModHead (int interp_factor); + ~GrWeaverModHead (); +}; + +%template(GrWeaverModHeadFF) GrWeaverModHead; + +template +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; + +class GrAtscConvert2xTo20 : public VrSigProc +{ +public: + GrAtscConvert2xTo20 (); + ~GrAtscConvert2xTo20 (); +}; + + +#if 0 // FIXME +%template(VrSource_mpeg_packet) VrSource; +%template(VrFileSource_mpeg_packet) VrFileSource; + +%template(VrSink_mpeg_packet) VrSink; +%template(VrFileSink_mpeg_packet) VrFileSink; +#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 00000000..36332cc5 --- /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 00000000..b8c58538 --- /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 +#include // size_t +%} + +%feature("autodoc","1"); + +%include +%include +%include + + +typedef std::complex gr_complex; +typedef std::complex gr_complexd; + + +// instantiate the required template specializations + +namespace std { + %template() vector; + %template() vector; + %template() vector; + %template() vector; + %template() vector; + %template() vector; + %template() vector >; +}; + +//////////////////////////////////////////////////////////////////////// + +%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 +%include +%include +%include + +// %include + +//////////////////////////////////////////////////////////////////////// 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 00000000..9663033a --- /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 shared_ptr +{ +public: + + shared_ptr() + { + } + + shared_ptr (T * p) + { + } + + + T * operator-> () // never throws + { + return px; + } + + +private: + + T * px; // contained pointer + int pn; + +}; // shared_ptr + +}; \ No newline at end of file diff --git a/gnuradio-core/src/python/Makefile.am b/gnuradio-core/src/python/Makefile.am new file mode 100644 index 00000000..99f86026 --- /dev/null +++ b/gnuradio-core/src/python/Makefile.am @@ -0,0 +1,29 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 + +SUBDIRS = gnuradio bin + +noinst_PYTHON = \ + build_utils.py \ + build_utils_codes.py + diff --git a/gnuradio-core/src/python/bin/Makefile.am b/gnuradio-core/src/python/bin/Makefile.am new file mode 100644 index 00000000..3e9b9076 --- /dev/null +++ b/gnuradio-core/src/python/bin/Makefile.am @@ -0,0 +1,30 @@ +# +# 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 $(top_srcdir)/Makefile.common + + +EXTRA_DIST = microtune.py + +bin_SCRIPTS = \ + microtune.py + +CLEANFILES = *.pyc diff --git a/gnuradio-core/src/python/bin/microtune.py b/gnuradio-core/src/python/bin/microtune.py new file mode 100755 index 00000000..0e799c93 --- /dev/null +++ b/gnuradio-core/src/python/bin/microtune.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python +# -*- Python -*- + +from gnuradio import gr +from gnuradio.eng_option import eng_option +from gnuradio.wxgui import stdgui, fftsink +from optparse import OptionParser +from gnuradio import eng_notation + + +def main (): + parser = OptionParser (option_class=eng_option) + parser.add_option ("-g", "--gain", type="eng_float", default=-1, + help="set front end gain to GAIN [0,1000]") + parser.add_option ("-f", "--freq", type="eng_float", default=-1, + help="set front end center frequency to FREQ") + parser.add_option ("-t", "--type", type="string", default="4937", + help="select eval board type {4937 or 4702}") + parser.add_option ("-p", "--port", type="int", default=0, + help="parallel port eval board is attached to") + (options, args) = parser.parse_args () + + if options.type == "4937": + front_end = gr.microtune_4937_eval_board (options.port) + elif options.type == "4702": + front_end = gr.microtune_4702_eval_board (options.port) + else: + raise RuntimeError, "Invalid board type. Must be either -t 4937 or -t 4702" + + if options.gain != -1: + front_end.set_AGC (options.gain) + + if options.freq != -1: + if options.freq < 1e6: + options.freq = options.freq * 1e6 + + actual = front_end.set_RF_freq (options.freq) + print "microtune: actual freq = %s" % (eng_notation.num_to_str (actual),) + + +if __name__ == '__main__': + main () diff --git a/gnuradio-core/src/python/build_utils.py b/gnuradio-core/src/python/build_utils.py new file mode 100644 index 00000000..18cfc2e7 --- /dev/null +++ b/gnuradio-core/src/python/build_utils.py @@ -0,0 +1,163 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +"""Misc utilities used at build time +""" + +import re, os, os.path +from build_utils_codes import * + + +# set srcdir to the directory that contains Makefile.am +try: + srcdir = os.environ['srcdir'] +except KeyError, e: + srcdir = "." +srcdir = srcdir + '/' + + +name_dict = {} + +def log_output_name (name): + (base, ext) = os.path.splitext (name) + ext = ext[1:] # drop the leading '.' + + entry = name_dict.setdefault (ext, []) + entry.append (name) + +def open_and_log_name (name, dir): + f = open (name, dir) + log_output_name (name) + return f + +def expand_template (d, template_filename, extra = ""): + '''Given a dictionary D and a TEMPLATE_FILENAME, expand template into output file + ''' + output_extension = extract_extension (template_filename) + template = open_src (template_filename, 'r') + output_name = d['NAME'] + extra + '.' + output_extension + log_output_name (output_name) + output = open (output_name, 'w') + do_substitution (d, template, output) + template.close () + output.close () + +def output_glue (dirname): + output_makefile_fragment () + output_ifile_include (dirname) + +def output_makefile_fragment (): + f = open ('Makefile.gen', 'w') + f.write ('#\n# This file is machine generated. All edits will be overwritten\n#\n') + output_subfrag (f, 'h') + output_subfrag (f, 'i') + output_subfrag (f, 'cc') + f.close () + +def output_ifile_include (dirname): + f = open ('%s_generated.i' % (dirname,), 'w') + f.write ('//\n// This file is machine generated. All edits will be overwritten\n//\n') + files = name_dict.setdefault ('i', []) + files.sort () + f.write ('%{\n') + for file in files: + f.write ('#include <%s>\n' % (file[0:-1] + 'h',)) + f.write ('%}\n\n') + for file in files: + f.write ('%%include <%s>\n' % (file,)) + +def output_subfrag (f, ext): + files = name_dict.setdefault (ext, []) + files.sort () + f.write ("GENERATED_%s =" % (ext.upper ())) + for file in files: + f.write (" \\\n\t%s" % (file,)) + f.write ("\n\n") + + +def extract_extension (template_name): + # template name is something like: GrFIRfilterXXX.h.t + # we return everything between the penultimate . and .t + mo = re.search (r'\.([a-z]+)\.t$', template_name) + if not mo: + raise ValueError, "Incorrectly formed template_name '%s'" % (template_name,) + return mo.group (1) + +def open_src (name, mode): + global srcdir + return open (os.path.join (srcdir, name), mode) + +def do_substitution (d, in_file, out_file): + def repl (match_obj): + key = match_obj.group (1) + # print key + return d[key] + + inp = in_file.read () + out = re.sub (r"@([a-zA-Z0-9_]+)@", repl, inp) + out_file.write (out) + + + +copyright = '''/* -*- c++ -*- */ +/* + * Copyright 2003,2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +''' + +def is_complex (code3): + if i_code (code3) == 'c' or o_code (code3) == 'c': + return '1' + else: + return '0' + + +def standard_dict (name, code3): + d = {} + d['NAME'] = name + d['GUARD_NAME'] = 'INCLUDED_%s_H' % name.upper () + d['BASE_NAME'] = re.sub ('^gr_', '', name) + d['SPTR_NAME'] = '%s_sptr' % name + d['WARNING'] = 'WARNING: this file is machine generated. Edits will be over written' + d['COPYRIGHT'] = copyright + d['TYPE'] = i_type (code3) + d['I_TYPE'] = i_type (code3) + d['O_TYPE'] = o_type (code3) + d['TAP_TYPE'] = tap_type (code3) + d['IS_COMPLEX'] = is_complex (code3) + return d diff --git a/gnuradio-core/src/python/build_utils_codes.py b/gnuradio-core/src/python/build_utils_codes.py new file mode 100644 index 00000000..f4215f2b --- /dev/null +++ b/gnuradio-core/src/python/build_utils_codes.py @@ -0,0 +1,52 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +def i_code (code3): + return code3[0] + +def o_code (code3): + if len (code3) >= 2: + return code3[1] + else: + return code3[0] + +def tap_code (code3): + if len (code3) >= 3: + return code3[2] + else: + return code3[0] + +def i_type (code3): + return char_to_type[i_code (code3)] + +def o_type (code3): + return char_to_type[o_code (code3)] + +def tap_type (code3): + return char_to_type[tap_code (code3)] + + +char_to_type = {} +char_to_type['s'] = 'short' +char_to_type['i'] = 'int' +char_to_type['f'] = 'float' +char_to_type['c'] = 'gr_complex' +char_to_type['b'] = 'unsigned char' diff --git a/gnuradio-core/src/python/gnuradio/Makefile.am b/gnuradio-core/src/python/gnuradio/Makefile.am new file mode 100644 index 00000000..3222c5db --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/Makefile.am @@ -0,0 +1,36 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 + +SUBDIRS = gr gru gruimpl blks blksimpl + +grpython_PYTHON = \ + __init__.py \ + audio.py \ + eng_notation.py \ + eng_option.py \ + packet_utils.py \ + gr_unittest.py \ + optfir.py \ + window.py + +CLEANFILES = *.pyc diff --git a/gnuradio-core/src/python/gnuradio/__init__.py b/gnuradio-core/src/python/gnuradio/__init__.py new file mode 100644 index 00000000..a4917cf6 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/__init__.py @@ -0,0 +1 @@ +# make this a package diff --git a/gnuradio-core/src/python/gnuradio/audio.py b/gnuradio-core/src/python/gnuradio/audio.py new file mode 100644 index 00000000..5a9d09c7 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/audio.py @@ -0,0 +1,88 @@ +# +# 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. +# + +""" +This is the 'generic' audio or soundcard interface. + +The behavior of this module is controlled by the [audio] audio_module +configuration parameter. If it is 'auto' we attempt to import modules +from the known_modules list, using the first one imported successfully. + +If [audio] audio_module is not 'auto', we assume it's the name of +an audio module and attempt to import it. +""" + +__all__ = ['source', 'sink'] + +from gnuradio import gr +import sys + +source = None +sink = None + + +known_modules = ( + 'audio_alsa', 'audio_oss', 'audio_osx', 'audio_jack', 'audio_portaudio') + + +def try_import(name): + """ + Build a blob of code and try to execute it. + If it succeeds we will have set the globals source and sink + as side effects. + + returns True or False + """ + global source, sink + full_name = "gnuradio." + name + code = """ +import %s +source = %s.source +sink = %s.sink +""" % (full_name, full_name, full_name) + try: + exec code in globals() + return True + except ImportError: + return False + + +def __init__ (): + p = gr.prefs() # get preferences (config file) object + verbose = p.get_bool('audio', 'verbose', False) + module = p.get_string('audio', 'audio_module', 'auto') + + if module == 'auto': # search our list for the first one that we can import + for m in known_modules: + if try_import(m): + if verbose: sys.stderr.write('audio: using %s\n' % (m,)) + return + raise ImportError, 'Unable to locate an audio module.' + + else: # use the one the user specified + if try_import(module): + if verbose: sys.stderr.write('audio: using %s\n' % (module,)) + else: + msg = 'Failed to import user-specified audio module %s' % (module,) + if verbose: sys.stderr.write('audio: %s\n' % (msg,)) + raise ImportError, msg + +__init__() diff --git a/gnuradio-core/src/python/gnuradio/blks/Makefile.am b/gnuradio-core/src/python/gnuradio/blks/Makefile.am new file mode 100644 index 00000000..17574d77 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks/Makefile.am @@ -0,0 +1,35 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 = run_tests.in +# TESTS = run_tests + +grblkspythondir = $(grpythondir)/blks + +grblkspython_PYTHON = \ + __init__.py + + +noinst_PYTHON = + +CLEANFILES = *.pyc *.pyo diff --git a/gnuradio-core/src/python/gnuradio/blks/__init__.py b/gnuradio-core/src/python/gnuradio/blks/__init__.py new file mode 100644 index 00000000..4cc10ebb --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blks/__init__.py @@ -0,0 +1,37 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 glob +import os.path + +# Semi-hideous kludge to import everything in the blksimpl directory +# into the gnuradio.blks namespace. This keeps us from having to remember +# to manually update this file. + +for p in __path__: + filenames = glob.glob (os.path.join (p, "..", "blksimpl", "*.py")) + for f in filenames: + f = os.path.basename(f).lower() + f = f[:-3] + if f == '__init__': + continue + # print f + exec "from gnuradio.blksimpl.%s import *" % (f,) diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am b/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am new file mode 100644 index 00000000..415920b2 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/Makefile.am @@ -0,0 +1,49 @@ +# +# 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 $(top_srcdir)/Makefile.common + +# EXTRA_DIST = run_tests.in +# TESTS = run_tests + +grblkspythondir = $(grpythondir)/blksimpl + +grblkspython_PYTHON = \ + __init__.py \ + am_demod.py \ + filterbank.py \ + fm_demod.py \ + fm_emph.py \ + gmsk2.py \ + gmsk2_pkt.py \ + nbfm_rx.py \ + nbfm_tx.py \ + pkt.py \ + rational_resampler.py \ + standard_squelch.py \ + wfm_rcv.py \ + wfm_rcv_pll.py \ + wfm_tx.py + + +noinst_PYTHON = + +CLEANFILES = *.pyc *.pyo diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/__init__.py b/gnuradio-core/src/python/gnuradio/blksimpl/__init__.py new file mode 100644 index 00000000..a4917cf6 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/__init__.py @@ -0,0 +1 @@ +# make this a package diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/am_demod.py b/gnuradio-core/src/python/gnuradio/blksimpl/am_demod.py new file mode 100644 index 00000000..309f5e65 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/am_demod.py @@ -0,0 +1,75 @@ +# +# 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. +# + +from gnuradio import gr, optfir + +class am_demod_cf(gr.hier_block): + """ + Generalized AM demodulation block with audio filtering. + + This block demodulates a band-limited, complex down-converted AM + channel into the the original baseband signal, applying low pass + filtering to the audio output. It produces a float stream in the + range [-1.0, +1.0]. + + @param fg: flowgraph + @param channel_rate: incoming sample rate of the AM baseband + @type sample_rate: integer + @param audio_decim: input to output decimation rate + @type audio_decim: integer + @param audio_pass: audio low pass filter passband frequency + @type audio_pass: float + @param audio_stop: audio low pass filter stop frequency + @type audio_stop: float + """ + def __init__(self, fg, channel_rate, audio_decim, audio_pass, audio_stop): + MAG = gr.complex_to_mag() + DCR = gr.add_const_ff(-1.0) + + audio_taps = optfir.low_pass(0.5, # Filter gain + channel_rate, # Sample rate + audio_pass, # Audio passband + audio_stop, # Audio stopband + 0.1, # Passband ripple + 60) # Stopband attenuation + LPF = gr.fir_filter_fff(audio_decim, audio_taps) + + fg.connect(MAG, DCR, LPF) + gr.hier_block.__init__(self, fg, MAG, LPF) + +class demod_10k0a3e_cf(am_demod_cf): + """ + AM demodulation block, 10 KHz channel. + + This block demodulates an AM channel conformant to 10K0A3E emission + standards, such as broadcast band AM transmissions. + + @param fg: flowgraph + @param channel_rate: incoming sample rate of the AM baseband + @type sample_rate: integer + @param audio_decim: input to output decimation rate + @type audio_decim: integer + """ + def __init__(self, fg, channel_rate, audio_decim): + am_demod_cf.__init__(self, fg, channel_rate, audio_decim, + 5000, # Audio passband + 5500) # Audio stopband + \ No newline at end of file diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/digital_voice.py.real b/gnuradio-core/src/python/gnuradio/blksimpl/digital_voice.py.real new file mode 100644 index 00000000..1b3a14f3 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/digital_voice.py.real @@ -0,0 +1,102 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +""" +Digital voice Tx and Rx using GSM 13kbit vocoder and GMSK. + +Runs channel at 32kbit/sec. Currently uses fake channel coding, +but there's room for a rate 1/2 coder. +""" + +from gnuradio import gr, gru +from gnuradio.blksimpl.gmsk import gmsk_mod, gmsk_demod + +from gnuradio.vocoder import gsm_full_rate + +# Size of gsm full rate speech encoder output packet in bytes + +GSM_FRAME_SIZE = 33 + +# Size of packet in bytes that we send to GMSK modulator: +# +# Target: 256kS/sec air rate. +# +# 256kS 1 sym 1 bit 1 byte 0.020 sec 80 bytes +# ---- * ----- * ----- * ------ * --------- = -------- +# sec 8 S 1 sym 8 bits frame frame +# +# gr_simple_framer add 10 bytes of overhead. + +AIR_FRAME_SIZE = 70 + + +class digital_voice_tx(gr.hier_block): + """ + Hierarchical block for digital voice tranmission. + + The input is 8kS/sec floating point audio in the range [-1,+1] + The output is 256kS/sec GMSK modulated complex baseband signal in the range [-1,+1]. + """ + def __init__(self, fg): + samples_per_symbol = 8 + symbol_rate = 32000 + bt = 0.3 # Gaussian filter bandwidth * symbol time + + src_scale = gr.multiply_const_ff(32767) + f2s = gr.float_to_short() + voice_coder = gsm_full_rate.encode_sp() + + channel_coder = gr.fake_channel_encoder_pp(GSM_FRAME_SIZE, AIR_FRAME_SIZE) + p2s = gr.parallel_to_serial(gr.sizeof_char, AIR_FRAME_SIZE) + + mod = gmsk_mod(fg, sps=samples_per_symbol, + symbol_rate=symbol_rate, bt=bt, + p_size=AIR_FRAME_SIZE) + + fg.connect(src_scale, f2s, voice_coder, channel_coder, p2s, mod) + gr.hier_block.__init__(self, fg, src_scale, mod) + + +class digital_voice_rx(gr.hier_block): + """ + Hierarchical block for digital voice reception. + + The input is 256kS/sec GMSK modulated complex baseband signal. + The output is 8kS/sec floating point audio in the range [-1,+1] + """ + def __init__(self, fg): + samples_per_symbol = 8 + symbol_rate = 32000 + + demod = gmsk_demod(fg, sps=samples_per_symbol, + symbol_rate=symbol_rate, + p_size=AIR_FRAME_SIZE) + + s2p = gr.serial_to_parallel(gr.sizeof_char, AIR_FRAME_SIZE) + channel_decoder = gr.fake_channel_decoder_pp(AIR_FRAME_SIZE, GSM_FRAME_SIZE) + + voice_decoder = gsm_full_rate.decode_ps() + s2f = gr.short_to_float () + sink_scale = gr.multiply_const_ff(1.0/32767.) + + fg.connect(demod, s2p, channel_decoder, voice_decoder, s2f, sink_scale) + gr.hier_block.__init__(self, fg, demod, sink_scale) diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/filterbank.py b/gnuradio-core/src/python/gnuradio/blksimpl/filterbank.py new file mode 100644 index 00000000..bd23f793 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/filterbank.py @@ -0,0 +1,160 @@ +# +# 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. +# + +import sys +from gnuradio import gr, gru + +def _generate_synthesis_taps(mpoints): + return [] # FIXME + + +def _split_taps(taps, mpoints): + assert (len(taps) % mpoints) == 0 + result = [list() for x in range(mpoints)] + for i in xrange(len(taps)): + (result[i % mpoints]).append(taps[i]) + return [tuple(x) for x in result] + + +class synthesis_filterbank(gr.hier_block): + """ + Uniformly modulated polyphase DFT filter bank: synthesis + + See http://cnx.rice.edu/content/m10424/latest + """ + def __init__(self, fg, mpoints, taps=None): + """ + Takes M complex streams in, produces single complex stream out + that runs at M times the input sample rate + + @param fg: flow_graph + @param mpoints: number of freq bins/interpolation factor/subbands + @param taps: filter taps for subband filter + + The channel spacing is equal to the input sample rate. + The total bandwidth and output sample rate are equal the input + sample rate * nchannels. + + Output stream to frequency mapping: + + channel zero is at zero frequency. + + if mpoints is odd: + + Channels with increasing positive frequencies come from + channels 1 through (N-1)/2. + + Channel (N+1)/2 is the maximum negative frequency, and + frequency increases through N-1 which is one channel lower + than the zero frequency. + + if mpoints is even: + + Channels with increasing positive frequencies come from + channels 1 through (N/2)-1. + + Channel (N/2) is evenly split between the max positive and + negative bins. + + Channel (N/2)+1 is the maximum negative frequency, and + frequency increases through N-1 which is one channel lower + than the zero frequency. + + Channels near the frequency extremes end up getting cut + off by subsequent filters and therefore have diminished + utility. + """ + item_size = gr.sizeof_gr_complex + + if taps is None: + taps = _generate_synthesis_taps(mpoints) + + # pad taps to multiple of mpoints + r = len(taps) % mpoints + if r != 0: + taps = taps + (mpoints - r) * (0,) + + # split in mpoints separate set of taps + sub_taps = _split_taps(taps, mpoints) + + self.ss2v = gr.streams_to_vector(item_size, mpoints) + self.ifft = gr.fft_vcc(mpoints, False, []) + self.v2ss = gr.vector_to_streams(item_size, mpoints) + # mpoints filters go in here... + self.ss2s = gr.streams_to_stream(item_size, mpoints) + + fg.connect(self.ss2v, self.ifft, self.v2ss) + + # build mpoints fir filters... + for i in range(mpoints): + f = gr.fft_filter_ccc(1, sub_taps[i]) + fg.connect((self.v2ss, i), f) + fg.connect(f, (self.ss2s, i)) + + gr.hier_block.__init__(self, fg, self.ss2v, self.ss2s) + + +class analysis_filterbank(gr.hier_block): + """ + Uniformly modulated polyphase DFT filter bank: analysis + + See http://cnx.rice.edu/content/m10424/latest + """ + def __init__(self, fg, mpoints, taps=None): + """ + Takes 1 complex stream in, produces M complex streams out + that runs at 1/M times the input sample rate + + @param fg: flow_graph + @param mpoints: number of freq bins/interpolation factor/subbands + @param taps: filter taps for subband filter + + Same channel to frequency mapping as described above. + """ + item_size = gr.sizeof_gr_complex + + if taps is None: + taps = _generate_synthesis_taps(mpoints) + + # pad taps to multiple of mpoints + r = len(taps) % mpoints + if r != 0: + taps = taps + (mpoints - r) * (0,) + + # split in mpoints separate set of taps + sub_taps = _split_taps(taps, mpoints) + + # print >> sys.stderr, "mpoints =", mpoints, "len(sub_taps) =", len(sub_taps) + + self.s2ss = gr.stream_to_streams(item_size, mpoints) + # filters here + self.ss2v = gr.streams_to_vector(item_size, mpoints) + self.fft = gr.fft_vcc(mpoints, True, []) + self.v2ss = gr.vector_to_streams(item_size, mpoints) + + # build mpoints fir filters... + for i in range(mpoints): + f = gr.fft_filter_ccc(1, sub_taps[mpoints-i-1]) + fg.connect((self.s2ss, i), f) + fg.connect(f, (self.ss2v, i)) + + fg.connect(self.ss2v, self.fft, self.v2ss) + gr.hier_block.__init__(self, fg, self.s2ss, self.v2ss) diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/fm_demod.py b/gnuradio-core/src/python/gnuradio/blksimpl/fm_demod.py new file mode 100644 index 00000000..9487e0f0 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/fm_demod.py @@ -0,0 +1,122 @@ +# +# 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. +# + +from gnuradio import gr, optfir +from gnuradio.blksimpl.fm_emph import fm_deemph +from math import pi + +class fm_demod_cf(gr.hier_block): + """ + Generalized FM demodulation block with deemphasis and audio + filtering. + + This block demodulates a band-limited, complex down-converted FM + channel into the the original baseband signal, optionally applying + deemphasis. Low pass filtering is done on the resultant signal. It + produces an output float strem in the range of [-1.0, +1.0]. + + @param fg: flowgraph + @param channel_rate: incoming sample rate of the FM baseband + @type sample_rate: integer + @param deviation: maximum FM deviation (default = 5000) + @type deviation: float + @param audio_decim: input to output decimation rate + @type audio_decim: integer + @param audio_pass: audio low pass filter passband frequency + @type audio_pass: float + @param audio_stop: audio low pass filter stop frequency + @type audio_stop: float + @param gain: gain applied to audio output (default = 1.0) + @type gain: float + @param tau: deemphasis time constant (default = 75e-6), specify 'None' + to prevent deemphasis + """ + def __init__(self, fg, channel_rate, audio_decim, deviation, + audio_pass, audio_stop, gain=1.0, tau=75e-6): + + """ + # Equalizer for ~100 us delay + delay = 100e-6 + num_taps = int(channel_rate*delay) + + mu = 1e-4/num_taps + print "CMA: delay =", delay, "n =", num_taps, "mu =", mu + CMA = gr.cma_equalizer_cc(num_taps, 1.0, mu) + """ + k = channel_rate/(2*pi*deviation) + QUAD = gr.quadrature_demod_cf(k) + + audio_taps = optfir.low_pass(gain, # Filter gain + channel_rate, # Sample rate + audio_pass, # Audio passband + audio_stop, # Audio stopband + 0.1, # Passband ripple + 60) # Stopband attenuation + LPF = gr.fir_filter_fff(audio_decim, audio_taps) + + if tau is not None: + DEEMPH = fm_deemph(fg, channel_rate, tau) + fg.connect(QUAD, DEEMPH, LPF) + else: + fg.connect(QUAD, LPF) + + gr.hier_block.__init__(self, fg, QUAD, LPF) + +class demod_20k0f3e_cf(fm_demod_cf): + """ + NBFM demodulation block, 20 KHz channels + + This block demodulates a complex, downconverted, narrowband FM + channel conforming to 20K0F3E emission standards, outputting + floats in the range [-1.0, +1.0]. + + @param fg: flowgraph + @param sample_rate: incoming sample rate of the FM baseband + @type sample_rate: integer + @param audio_decim: input to output decimation rate + @type audio_decim: integer + """ + def __init__(self, fg, channel_rate, audio_decim): + fm_demod_cf.__init__(self, fg, channel_rate, audio_decim, + 5000, # Deviation + 3000, # Audio passband frequency + 4000) # Audio stopband frequency + +class demod_200kf3e_cf(fm_demod_cf): + """ + WFM demodulation block, mono. + + This block demodulates a complex, downconverted, wideband FM + channel conforming to 200KF3E emission standards, outputting + floats in the range [-1.0, +1.0]. + + @param fg: flowgraph + @param sample_rate: incoming sample rate of the FM baseband + @type sample_rate: integer + @param audio_decim: input to output decimation rate + @type audio_decim: integer + """ + def __init__(self, fg, channel_rate, audio_decim): + fm_demod_cf.__init__(self, fg, channel_rate, audio_decim, + 75000, # Deviation + 15000, # Audio passband + 16000, # Audio stopband + 20.0) # Audio gain diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/fm_emph.py b/gnuradio-core/src/python/gnuradio/blksimpl/fm_emph.py new file mode 100644 index 00000000..5c256f5d --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/fm_emph.py @@ -0,0 +1,145 @@ +# +# 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. +# + +from gnuradio import gr +import math + + +# +# 1 +# H(s) = ------- +# 1 + s +# +# tau is the RC time constant. +# critical frequency: w_p = 1/tau +# +# We prewarp and use the bilinear z-transform to get our IIR coefficients. +# See "Digital Signal Processing: A Practical Approach" by Ifeachor and Jervis +# + +class fm_deemph(gr.hier_block): + """ + FM Deemphasis IIR filter. + """ + def __init__(self, fg, fs, tau=75e-6): + """ + @param fg: flow graph + @type fg: gr.flow_graph + @param fs: sampling frequency in Hz + @type fs: float + @param tau: Time constant in seconds (75us in US, 50us in EUR) + @type tau: float + """ + w_p = 1/tau + w_pp = math.tan (w_p / (fs * 2)) # prewarped analog freq + + a1 = (w_pp - 1)/(w_pp + 1) + b0 = w_pp/(1 + w_pp) + b1 = b0 + + btaps = [b0, b1] + ataps = [1, a1] + + if 0: + print "btaps =", btaps + print "ataps =", ataps + global plot1 + plot1 = gru.gnuplot_freqz (gru.freqz (btaps, ataps), fs, True) + + deemph = gr.iir_filter_ffd(btaps, ataps) + gr.hier_block.__init__(self, fg, deemph, deemph) + +# +# 1 + s*t1 +# H(s) = ---------- +# 1 + s*t2 +# +# I think this is the right transfer function. +# +# +# This fine ASCII rendition is based on Figure 5-15 +# in "Digital and Analog Communication Systems", Leon W. Couch II +# +# +# R1 +# +-----||------+ +# | | +# o------+ +-----+--------o +# | C1 | | +# +----/\/\/\/--+ \ +# / +# \ R2 +# / +# \ +# | +# o--------------------------+--------o +# +# f1 = 1/(2*pi*t1) = 1/(2*pi*R1*C) +# +# 1 R1 + R2 +# f2 = ------- = ------------ +# 2*pi*t2 2*pi*R1*R2*C +# +# t1 is 75us in US, 50us in EUR +# f2 should be higher than our audio bandwidth. +# +# +# The Bode plot looks like this: +# +# +# /---------------- +# / +# / <-- slope = 20dB/decade +# / +# -------------/ +# f1 f2 +# +# We prewarp and use the bilinear z-transform to get our IIR coefficients. +# See "Digital Signal Processing: A Practical Approach" by Ifeachor and Jervis +# + +class fm_preemph(gr.hier_block): + """ + FM Preemphasis IIR filter. + """ + def __init__(self, fg, fs, tau=75e-6): + """ + @param fg: flow graph + @type fg: gr.flow_graph + @param fs: sampling frequency in Hz + @type fs: float + @param tau: Time constant in seconds (75us in US, 50us in EUR) + @type tau: float + """ + + # FIXME make this compute the right answer + + btaps = [1] + ataps = [1] + + if 0: + print "btaps =", btaps + print "ataps =", ataps + global plot2 + plot2 = gru.gnuplot_freqz (gru.freqz (btaps, ataps), fs, True) + + preemph = gr.iir_filter_ffd(btaps, ataps) + gr.hier_block.__init__(self, fg, preemph, preemph) diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/gmsk2.py b/gnuradio-core/src/python/gnuradio/blksimpl/gmsk2.py new file mode 100644 index 00000000..68d18967 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/gmsk2.py @@ -0,0 +1,159 @@ +# +# GMSK modulation and demodulation. +# +# +# 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. +# + +# See gnuradio-examples/python/gmsk2 for examples + +from gnuradio import gr +from math import pi +import Numeric + +# ///////////////////////////////////////////////////////////////////////////// +# GMSK mod/demod with steams of bytes as data i/o +# ///////////////////////////////////////////////////////////////////////////// + +class gmsk2_mod(gr.hier_block): + + def __init__(self, fg, spb = 2, bt = 0.3): + """ + Hierarchical block for Gaussian Minimum Shift Key (GMSK) + modulation. + + The input is a byte stream (unsigned char) and the + output is the complex modulated signal at baseband. + + @param fg: flow graph + @type fg: flow graph + @param spb: samples per baud >= 2 + @type spb: integer + @param bt: Gaussian filter bandwidth * symbol time + @type bt: float + """ + if not isinstance(spb, int) or spb < 2: + raise TypeError, "sbp must be an integer >= 2" + self.spb = spb + + ntaps = 4 * spb # up to 3 bits in filter at once + sensitivity = (pi / 2) / spb # phase change per bit = pi / 2 + + # Turn it into NRZ data. + self.nrz = gr.bytes_to_syms() + + # Form Gaussian filter + + # Generate Gaussian response (Needs to be convolved with window below). + self.gaussian_taps = gr.firdes.gaussian( + 1, # gain + spb, # symbol_rate + bt, # bandwidth * symbol time + ntaps # number of taps + ) + + self.sqwave = (1,) * spb # rectangular window + self.taps = Numeric.convolve(Numeric.array(self.gaussian_taps),Numeric.array(self.sqwave)) + self.gaussian_filter = gr.interp_fir_filter_fff(spb, self.taps) + + # FM modulation + self.fmmod = gr.frequency_modulator_fc(sensitivity) + + # Connect + fg.connect(self.nrz, self.gaussian_filter, self.fmmod) + + # Initialize base class + gr.hier_block.__init__(self, fg, self.nrz, self.fmmod) + + def samples_per_baud(self): + return self.spb + + def bits_per_baud(self=None): # staticmethod that's also callable on an instance + return 1 + bits_per_baud = staticmethod(bits_per_baud) # make it a static method. RTFM + + +class gmsk2_demod(gr.hier_block): + + def __init__(self, fg, spb=2, omega=None, gain_mu=0.03, mu=0.5, + omega_relative_limit=0.000200, freq_error=0.0): + """ + Hierarchical block for Gaussian Minimum Shift Key (GMSK) + demodulation. + + The input is the complex modulated signal at baseband. + The output is a stream of symbols ready to be sliced at zero. + + @param fg: flow graph + @type fg: flow graph + @param spb: samples per baud + @type spb: integer + + Clock recovery parameters. These all have reasonble defaults. + + @param omega: nominal relative freq (defaults to spb) + @type omega: float + @param gain_mu: controls rate of mu adjustment + @type gain_mu: float + @param mu: fractional delay [0.0, 1.0] + @type mu: float + @param omega_relative_limit: sets max variation in omega + @type omega_relative_limit: float, typically 0.000200 (200 ppm) + @param freq_error: bit rate error as a fraction + @param float + """ + if spb < 2: + raise TypeError, "sbp >= 2" + self.spb = spb + + if omega is None: + omega = spb*(1+freq_error) + + gain_omega = .25*gain_mu*gain_mu # critically damped + + # Automatic gain control + self.preamp = gr.multiply_const_cc(10e-5) + self.agc = gr.agc_cc(1e-3, 1, 1, 1000) + + # Demodulate FM + sensitivity = (pi / 2) / spb + self.fmdemod = gr.quadrature_demod_cf(1.0 / sensitivity) + + alpha = 0.0008 + + # the clock recovery block tracks the symbol clock and resamples as needed. + # the output of the block is a stream of soft symbols (float) + self.clock_recovery = gr.clock_recovery_mm_ff(omega, gain_omega, mu, gain_mu, + omega_relative_limit) + + # slice the floats at 0, outputting 1 bit (the LSB of the output byte) per sample + self.slicer = gr.binary_slicer_fb() + + fg.connect(self.preamp, self.agc, self.fmdemod, self.clock_recovery, self.slicer) + + # Initialize base class + gr.hier_block.__init__(self, fg, self.preamp, self.slicer) + + def samples_per_baud(self): + return self.spb + + def bits_per_baud(self=None): # staticmethod that's also callable on an instance + return 1 + bits_per_baud = staticmethod(bits_per_baud) # make it a static method. RTFM diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/gmsk2_pkt.py b/gnuradio-core/src/python/gnuradio/blksimpl/gmsk2_pkt.py new file mode 100644 index 00000000..af586239 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/gmsk2_pkt.py @@ -0,0 +1,174 @@ +# +# 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. +# + +from math import pi +import Numeric + +from gnuradio import gr, packet_utils +import gnuradio.gr.gr_threading as _threading +import gmsk2 + + +def _deprecation_warning(old_name, new_name): + print '#' + print '# Warning: %s is deprecated and will be removed soon.' % (old_name,) + print '# Please use the modulation independent block, %s.' % (new_name,) + print "#" + + +# ///////////////////////////////////////////////////////////////////////////// +# GMSK mod/demod with packets as i/o +# ///////////////////////////////////////////////////////////////////////////// + +class gmsk2_mod_pkts(gr.hier_block): + """ + GSM modulator that is a GNU Radio source. + + Send packets by calling send_pkt + """ + def __init__(self, fg, access_code=None, msgq_limit=2, pad_for_usrp=True, *args, **kwargs): + """ + Hierarchical block for Gaussian Minimum Shift Key (GMSK) modulation. + + Packets to be sent are enqueued by calling send_pkt. + The output is the complex modulated signal at baseband. + + @param fg: flow graph + @type fg: flow graph + @param access_code: AKA sync vector + @type access_code: string of 1's and 0's between 1 and 64 long + @param msgq_limit: maximum number of messages in message queue + @type msgq_limit: int + @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples + + See gmsk_mod for remaining parameters + """ + _deprecation_warning('gmsk2_mod_pkts', 'mod_pkts') + + self.pad_for_usrp = pad_for_usrp + if access_code is None: + access_code = packet_utils.default_access_code + if not packet_utils.is_1_0_string(access_code): + raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,) + self._access_code = access_code + + # accepts messages from the outside world + self.pkt_input = gr.message_source(gr.sizeof_char, msgq_limit) + self.gmsk_mod = gmsk2.gmsk2_mod(fg, *args, **kwargs) + fg.connect(self.pkt_input, self.gmsk_mod) + gr.hier_block.__init__(self, fg, None, self.gmsk_mod) + + def send_pkt(self, payload='', eof=False): + """ + Send the payload. + + @param payload: data to send + @type payload: string + """ + if eof: + msg = gr.message(1) # tell self.pkt_input we're not sending any more packets + else: + # print "original_payload =", string_to_hex_list(payload) + pkt = packet_utils.make_packet(payload, + self.gmsk_mod.samples_per_baud(), + self.gmsk_mod.bits_per_baud(), + self._access_code, + self.pad_for_usrp) + #print "pkt =", string_to_hex_list(pkt) + msg = gr.message_from_string(pkt) + self.pkt_input.msgq().insert_tail(msg) + + + +class gmsk2_demod_pkts(gr.hier_block): + """ + GSM demodulator that is a GNU Radio sink. + + The input is complex baseband. When packets are demodulated, they are passed to the + app via the callback. + """ + + def __init__(self, fg, access_code=None, callback=None, threshold=-1, *args, **kwargs): + """ + Hierarchical block for Gaussian Minimum Shift Key (GMSK) + demodulation. + + The input is the complex modulated signal at baseband. + Demodulated packets are sent to the handler. + + @param fg: flow graph + @type fg: flow graph + @param access_code: AKA sync vector + @type access_code: string of 1's and 0's + @param callback: function of two args: ok, payload + @type callback: ok: bool; payload: string + @param threshold: detect access_code with up to threshold bits wrong (-1 -> use default) + @type threshold: int + + See gmsk_demod for remaining parameters. + """ + + _deprecation_warning('gmsk2_demod_pkts', 'demod_pkts') + + if access_code is None: + access_code = packet_utils.default_access_code + if not packet_utils.is_1_0_string(access_code): + raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,) + self._access_code = access_code + + if threshold == -1: + threshold = 12 # FIXME raise exception + + self._rcvd_pktq = gr.msg_queue() # holds packets from the PHY + self.gmsk_demod = gmsk2.gmsk2_demod(fg, *args, **kwargs) + self.correlator = gr.correlate_access_code_bb(access_code, threshold) + + self.framer_sink = gr.framer_sink_1(self._rcvd_pktq) + fg.connect(self.gmsk_demod, self.correlator, self.framer_sink) + + gr.hier_block.__init__(self, fg, self.gmsk_demod, None) + self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback) + + def carrier_sensed(self): + """ + Return True if we detect carrier. + """ + return False # FIXME + + +class _queue_watcher_thread(_threading.Thread): + def __init__(self, rcvd_pktq, callback): + _threading.Thread.__init__(self) + self.setDaemon(1) + self.rcvd_pktq = rcvd_pktq + self.callback = callback + self.keep_running = True + self.start() + + #def stop(self): + # self.keep_running = False + + def run(self): + while self.keep_running: + msg = self.rcvd_pktq.delete_head() + ok, payload = packet_utils.unmake_packet(msg.to_string()) + if self.callback: + self.callback(ok, payload) diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/nbfm_rx.py b/gnuradio-core/src/python/gnuradio/blksimpl/nbfm_rx.py new file mode 100644 index 00000000..39059ec9 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/nbfm_rx.py @@ -0,0 +1,87 @@ +# +# 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. +# + +import math +from gnuradio import gr, optfir +from gnuradio.blksimpl.fm_emph import fm_deemph +from gnuradio.blksimpl.standard_squelch import standard_squelch + +class nbfm_rx(gr.hier_block): + def __init__(self, fg, audio_rate, quad_rate, tau=75e-6, max_dev=5e3): + """ + Narrow Band FM Receiver. + + Takes a single complex baseband input stream and produces a single + float output stream of audio sample in the range [-1, +1]. + + @param fg: flow graph + @param audio_rate: sample rate of audio stream, >= 16k + @type audio_rate: integer + @param quad_rate: sample rate of output stream + @type quad_rate: integer + @param tau: preemphasis time constant (default 75e-6) + @type tau: float + @param max_dev: maximum deviation in Hz (default 5e3) + @type max_dev: float + + quad_rate must be an integer multiple of audio_rate. + + Exported sub-blocks (attributes): + squelch + quad_demod + deemph + audio_filter + """ + + # FIXME audio_rate and quad_rate ought to be exact rationals + audio_rate = int(audio_rate) + quad_rate = int(quad_rate) + + if quad_rate % audio_rate != 0: + raise ValueError, "quad_rate is not an integer multiple of audio_rate" + + squelch_threshold = 20 # dB + #self.squelch = gr.simple_squelch_cc(squelch_threshold, 0.001) + + # FM Demodulator input: complex; output: float + k = quad_rate/(2*math.pi*max_dev) + self.quad_demod = gr.quadrature_demod_cf(k) + + # FM Deemphasis IIR filter + self.deemph = fm_deemph (fg, quad_rate, tau=tau) + + # compute FIR taps for audio filter + audio_decim = quad_rate // audio_rate + audio_taps = gr.firdes.low_pass (1.0, # gain + quad_rate, # sampling rate + 4.5e3, # Audio LPF cutoff + 2.5e3, # Transition band + gr.firdes.WIN_HAMMING) # filter type + + print "len(audio_taps) =", len(audio_taps) + + # Decimating audio filter + # input: float; output: float; taps: float + self.audio_filter = gr.fir_filter_fff(audio_decim, audio_taps) + + fg.connect(self.quad_demod, self.deemph, self.audio_filter) + + gr.hier_block.__init__(self, fg, self.quad_demod, self.audio_filter) diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/nbfm_tx.py b/gnuradio-core/src/python/gnuradio/blksimpl/nbfm_tx.py new file mode 100644 index 00000000..2f636b67 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/nbfm_tx.py @@ -0,0 +1,95 @@ +# +# 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. +# + +import math +from gnuradio import gr, optfir +from gnuradio.blksimpl.fm_emph import fm_preemph + +#from gnuradio import ctcss + +class nbfm_tx(gr.hier_block): + def __init__(self, fg, audio_rate, quad_rate, tau=75e-6, max_dev=5e3): + """ + Narrow Band FM Transmitter. + + Takes a single float input stream of audio samples in the range [-1,+1] + and produces a single FM modulated complex baseband output. + + @param fg: flow graph + @param audio_rate: sample rate of audio stream, >= 16k + @type audio_rate: integer + @param quad_rate: sample rate of output stream + @type quad_rate: integer + @param tau: preemphasis time constant (default 75e-6) + @type tau: float + @param max_dev: maximum deviation in Hz (default 5e3) + @type max_dev: float + + quad_rate must be an integer multiple of audio_rate. + """ + + # FIXME audio_rate and quad_rate ought to be exact rationals + audio_rate = int(audio_rate) + quad_rate = int(quad_rate) + + if quad_rate % audio_rate != 0: + raise ValueError, "quad_rate is not an integer multiple of audio_rate" + + + do_interp = audio_rate != quad_rate + + if do_interp: + interp_factor = quad_rate / audio_rate + interp_taps = optfir.low_pass (interp_factor, # gain + quad_rate, # Fs + 4500, # passband cutoff + 7000, # stopband cutoff + 0.1, # passband ripple dB + 40) # stopband atten dB + + #print "len(interp_taps) =", len(interp_taps) + self.interpolator = gr.interp_fir_filter_fff (interp_factor, interp_taps) + + self.preemph = fm_preemph (fg, quad_rate, tau=tau) + + k = 2 * math.pi * max_dev / quad_rate + self.modulator = gr.frequency_modulator_fc (k) + + if do_interp: + fg.connect (self.interpolator, self.preemph, self.modulator) + gr.hier_block.__init__(self, fg, self.interpolator, self.modulator) + else: + fg.connect(self.preemph, self.modulator) + gr.hier_block.__init__(self, fg, self.preemph, self.modulator) + + +#class ctcss_gen_f(gr.sig_source_f): +# def __init__(self, sample_rate, tone_freq): +# gr.sig_source_f.__init__(self, sample_rate, gr.SIN_WAVE, tone_freq, 0.1, 0.0) +# +# def set_tone (self, tone): +# gr.sig_source_f.set_frequency(self,tone) + +class ctcss_gen_f(gr.hier_block): + def __init__(self, fg, sample_rate, tone_freq): + self.plgen = gr.sig_source_f(sample_rate, gr.GR_SIN_WAVE, tone_freq, 0.1, 0.0) + + gr.hier_block.__init__(self, fg, self.plgen, self.plgen) diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/pkt.py b/gnuradio-core/src/python/gnuradio/blksimpl/pkt.py new file mode 100644 index 00000000..3ebb7229 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/pkt.py @@ -0,0 +1,156 @@ +# +# 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. +# + +from math import pi +import Numeric + +from gnuradio import gr, packet_utils +import gnuradio.gr.gr_threading as _threading + + +# ///////////////////////////////////////////////////////////////////////////// +# mod/demod with packets as i/o +# ///////////////////////////////////////////////////////////////////////////// + +class mod_pkts(gr.hier_block): + """ + Wrap an arbitrary digital modulator in our packet handling framework. + + Send packets by calling send_pkt + """ + def __init__(self, fg, modulator, access_code=None, msgq_limit=2, pad_for_usrp=True): + """ + Hierarchical block for sending packets + + Packets to be sent are enqueued by calling send_pkt. + The output is the complex modulated signal at baseband. + + @param fg: flow graph + @type fg: flow graph + @param modulator: instance of modulator class (gr_block or hier_block) + @type modulator: complex baseband out + @param access_code: AKA sync vector + @type access_code: string of 1's and 0's between 1 and 64 long + @param msgq_limit: maximum number of messages in message queue + @type msgq_limit: int + @param pad_for_usrp: If true, packets are padded such that they end up a multiple of 128 samples + + See gmsk_mod for remaining parameters + """ + self._modulator = modulator + self._pad_for_usrp = pad_for_usrp + + if access_code is None: + access_code = packet_utils.default_access_code + if not packet_utils.is_1_0_string(access_code): + raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,) + self._access_code = access_code + + # accepts messages from the outside world + self._pkt_input = gr.message_source(gr.sizeof_char, msgq_limit) + fg.connect(self._pkt_input, self._modulator) + gr.hier_block.__init__(self, fg, None, self._modulator) + + def send_pkt(self, payload='', eof=False): + """ + Send the payload. + + @param payload: data to send + @type payload: string + """ + if eof: + msg = gr.message(1) # tell self._pkt_input we're not sending any more packets + else: + # print "original_payload =", string_to_hex_list(payload) + pkt = packet_utils.make_packet(payload, + self._modulator.samples_per_baud(), + self._modulator.bits_per_baud(), + self._access_code, + self._pad_for_usrp) + #print "pkt =", string_to_hex_list(pkt) + msg = gr.message_from_string(pkt) + self._pkt_input.msgq().insert_tail(msg) + + + +class demod_pkts(gr.hier_block): + """ + Wrap an arbitrary digital demodulator in our packet handling framework. + + The input is complex baseband. When packets are demodulated, they are passed to the + app via the callback. + """ + + def __init__(self, fg, demodulator, access_code=None, callback=None, threshold=-1): + """ + Hierarchical block for demodulating and deframing packets. + + The input is the complex modulated signal at baseband. + Demodulated packets are sent to the handler. + + @param fg: flow graph + @type fg: flow graph + @param demodulator: instance of demodulator class (gr_block or hier_block) + @type demodulator: complex baseband in + @param access_code: AKA sync vector + @type access_code: string of 1's and 0's + @param callback: function of two args: ok, payload + @type callback: ok: bool; payload: string + @param threshold: detect access_code with up to threshold bits wrong (-1 -> use default) + @type threshold: int + """ + + self._demodulator = demodulator + if access_code is None: + access_code = packet_utils.default_access_code + if not packet_utils.is_1_0_string(access_code): + raise ValueError, "Invalid access_code %r. Must be string of 1's and 0's" % (access_code,) + self._access_code = access_code + + if threshold == -1: + threshold = 12 # FIXME raise exception + + self._rcvd_pktq = gr.msg_queue() # holds packets from the PHY + self.correlator = gr.correlate_access_code_bb(access_code, threshold) + + self.framer_sink = gr.framer_sink_1(self._rcvd_pktq) + fg.connect(self._demodulator, self.correlator, self.framer_sink) + + gr.hier_block.__init__(self, fg, self._demodulator, None) + self._watcher = _queue_watcher_thread(self._rcvd_pktq, callback) + + +class _queue_watcher_thread(_threading.Thread): + def __init__(self, rcvd_pktq, callback): + _threading.Thread.__init__(self) + self.setDaemon(1) + self.rcvd_pktq = rcvd_pktq + self.callback = callback + self.keep_running = True + self.start() + + + def run(self): + while self.keep_running: + msg = self.rcvd_pktq.delete_head() + ok, payload = packet_utils.unmake_packet(msg.to_string()) + if self.callback: + self.callback(ok, payload) diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/rational_resampler.py b/gnuradio-core/src/python/gnuradio/blksimpl/rational_resampler.py new file mode 100644 index 00000000..8b928b10 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/rational_resampler.py @@ -0,0 +1,137 @@ +# +# 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. +# + +from gnuradio import gr, gru + +_plot = None + +def design_filter(interpolation, decimation, fractional_bw): + """ + Given the interpolation rate, decimation rate and a fractional bandwidth, + design a set of taps. + + @param interpolation: interpolation factor + @type interpolation: integer > 0 + @param decimation: decimation factor + @type decimation: integer > 0 + @param fractional_bw: fractional bandwidth in (0, 0.5) 0.4 works well. + @type fractional_bw: float + @returns: sequence of numbers + """ + + global _plot + + if fractional_bw >= 0.5 or fractional_bw <= 0: + raise ValueError, "Invalid fractional_bandwidth, must be in (0, 0.5)" + + beta = 5.0 + trans_width = 0.5 - fractional_bw + mid_transition_band = 0.5 - trans_width/2 + + taps = gr.firdes.low_pass(interpolation, # gain + 1, # Fs + mid_transition_band/interpolation, # trans mid point + trans_width/interpolation, # transition width + gr.firdes.WIN_KAISER, + beta # beta + ) + # print "len(resampler_taps) =", len(taps) + # _plot = gru.gnuplot_freqz(gru.freqz(taps, 1), 1) + + return taps + + + +class _rational_resampler_base(gr.hier_block): + """ + base class for all rational resampler variants. + """ + def __init__(self, resampler_base, fg, + interpolation, decimation, taps=None, fractional_bw=None): + """ + Rational resampling polyphase FIR filter. + + Either taps or fractional_bw may be specified, but not both. + If neither is specified, a reasonable default, 0.4, is used as + the fractional_bw. + + @param fg: flow graph + @param interpolation: interpolation factor + @type interpolation: integer > 0 + @param decimation: decimation factor + @type decimation: integer > 0 + @param taps: optional filter coefficients + @type taps: sequence + @param fractional_bw: fractional bandwidth in (0, 0.5), measured at final freq (use 0.4) + @type fractional_bw: float + """ + + if not isinstance(interpolation, int) or interpolation < 1: + raise ValueError, "interpolation must be an integer >= 1" + + if not isinstance(decimation, int) or decimation < 1: + raise ValueError, "decimation must be an integer >= 1" + + if taps is None and fractional_bw is None: + fractional_bw = 0.4 + + d = gru.gcd(interpolation, decimation) + interpolation = interpolation // d + decimation = decimation // d + + if taps is None: + taps = design_filter(interpolation, decimation, fractional_bw) + + resampler = resampler_base(interpolation, decimation, taps) + gr.hier_block.__init__(self, fg, resampler, resampler) + + + +class rational_resampler_fff(_rational_resampler_base): + def __init__(self, fg, interpolation, decimation, taps=None, fractional_bw=None): + """ + Rational resampling polyphase FIR filter with + float input, float output and float taps. + """ + _rational_resampler_base.__init__(self, gr.rational_resampler_base_fff, fg, + interpolation, decimation, + taps, fractional_bw) + +class rational_resampler_ccf(_rational_resampler_base): + def __init__(self, fg, interpolation, decimation, taps=None, fractional_bw=None): + """ + Rational resampling polyphase FIR filter with + complex input, complex output and float taps. + """ + _rational_resampler_base.__init__(self, gr.rational_resampler_base_ccf, fg, + interpolation, decimation, + taps, fractional_bw) + +class rational_resampler_ccc(_rational_resampler_base): + def __init__(self, fg, interpolation, decimation, taps=None, fractional_bw=None): + """ + Rational resampling polyphase FIR filter with + complex input, complex output and complex taps. + """ + _rational_resampler_base.__init__(self, gr.rational_resampler_base_ccc, fg, + interpolation, decimation, + taps, fractional_bw) + diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/standard_squelch.py b/gnuradio-core/src/python/gnuradio/blksimpl/standard_squelch.py new file mode 100644 index 00000000..2c80dd5a --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/standard_squelch.py @@ -0,0 +1,73 @@ +# +# 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. +# + +import math +from gnuradio import gr, optfir + +class standard_squelch(gr.hier_block): + def __init__(self, fg, audio_rate): + + self.input_node = gr.add_const_ff(0) # FIXME kludge + + self.low_iir = gr.iir_filter_ffd((0.0193,0,-0.0193),(1,1.9524,-0.9615)) + self.low_square = gr.multiply_ff() + self.low_smooth = gr.single_pole_iir_filter_ff(1/(0.01*audio_rate)) # 100ms time constant + + self.hi_iir = gr.iir_filter_ffd((0.0193,0,-0.0193),(1,1.3597,-0.9615)) + self.hi_square = gr.multiply_ff() + self.hi_smooth = gr.single_pole_iir_filter_ff(1/(0.01*audio_rate)) + + self.sub = gr.sub_ff(); + self.add = gr.add_ff(); + self.gate = gr.threshold_ff(0.3,0.43,0) + self.squelch_lpf = gr.single_pole_iir_filter_ff(1/(0.01*audio_rate)) + + self.div = gr.divide_ff() + self.squelch_mult = gr.multiply_ff() + + fg.connect (self.input_node, (self.squelch_mult, 0)) + + fg.connect (self.input_node,self.low_iir) + fg.connect (self.low_iir,(self.low_square,0)) + fg.connect (self.low_iir,(self.low_square,1)) + fg.connect (self.low_square,self.low_smooth,(self.sub,0)) + fg.connect (self.low_smooth, (self.add,0)) + + fg.connect (self.input_node,self.hi_iir) + fg.connect (self.hi_iir,(self.hi_square,0)) + fg.connect (self.hi_iir,(self.hi_square,1)) + fg.connect (self.hi_square,self.hi_smooth,(self.sub,1)) + fg.connect (self.hi_smooth, (self.add,1)) + + fg.connect (self.sub, (self.div, 0)) + fg.connect (self.add, (self.div, 1)) + fg.connect (self.div, self.gate, self.squelch_lpf, (self.squelch_mult,1)) + + gr.hier_block.__init__(self, fg, self.input_node, self.squelch_mult) + + def set_threshold(self, threshold): + self.gate.set_hi(threshold) + + def threshold(self): + return self.gate.hi() + + def squelch_range(self): + return (0.0, 1.0, 1.0/100) diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/wfm_rcv.py b/gnuradio-core/src/python/gnuradio/blksimpl/wfm_rcv.py new file mode 100644 index 00000000..55dbbaa0 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/wfm_rcv.py @@ -0,0 +1,72 @@ +# +# 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. +# + +from gnuradio import gr +from gnuradio.blksimpl.fm_emph import fm_deemph +import math + +class wfm_rcv(gr.hier_block): + def __init__ (self, fg, quad_rate, audio_decimation): + """ + Hierarchical block for demodulating a broadcast FM signal. + + The input is the downconverted complex baseband signal (gr_complex). + The output is the demodulated audio (float). + + @param fg: flow graph. + @type fg: flow graph + @param quad_rate: input sample rate of complex baseband input. + @type quad_rate: float + @param audio_decimation: how much to decimate quad_rate to get to audio. + @type audio_decimation: integer + """ + volume = 20. + + max_dev = 75e3 + fm_demod_gain = quad_rate/(2*math.pi*max_dev) + audio_rate = quad_rate / audio_decimation + + + # We assign to self so that outsiders can grab the demodulator + # if they need to. E.g., to plot its output. + # + # input: complex; output: float + self.fm_demod = gr.quadrature_demod_cf (fm_demod_gain) + + # input: float; output: float + self.deemph = fm_deemph (fg, audio_rate) + + # compute FIR filter taps for audio filter + width_of_transition_band = audio_rate / 32 + audio_coeffs = gr.firdes.low_pass (1.0, # gain + quad_rate, # sampling rate + audio_rate/2 - width_of_transition_band, + width_of_transition_band, + gr.firdes.WIN_HAMMING) + # input: float; output: float + self.audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs) + + fg.connect (self.fm_demod, self.audio_filter, self.deemph) + + gr.hier_block.__init__(self, + fg, + self.fm_demod, # head of the pipeline + self.deemph) # tail of the pipeline diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/wfm_rcv_pll.py b/gnuradio-core/src/python/gnuradio/blksimpl/wfm_rcv_pll.py new file mode 100644 index 00000000..d116090e --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/wfm_rcv_pll.py @@ -0,0 +1,206 @@ +# +# 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. +# + +from gnuradio import gr +from gnuradio.blksimpl.fm_emph import fm_deemph +import math + +class wfm_rcv_pll(gr.hier_block): + def __init__ (self, fg, demod_rate, audio_decimation): + """ + Hierarchical block for demodulating a broadcast FM signal. + + The input is the downconverted complex baseband signal (gr_complex). + The output is two streams of the demodulated audio (float) 0=Left, 1=Right. + + @param fg: flow graph. + @type fg: flow graph + @param demod_rate: input sample rate of complex baseband input. + @type demod_rate: float + @param audio_decimation: how much to decimate demod_rate to get to audio. + @type audio_decimation: integer + """ + + bandwidth = 200e3 + audio_rate = demod_rate / audio_decimation + + + # We assign to self so that outsiders can grab the demodulator + # if they need to. E.g., to plot its output. + # + # input: complex; output: float + alpha = 0.25*bandwidth * math.pi / demod_rate + beta = alpha * alpha / 4.0 + max_freq = 2.0*math.pi*100e3/demod_rate + + self.fm_demod = gr.pll_freqdet_cf (alpha,beta,max_freq,-max_freq) + + # input: float; output: float + self.deemph_Left = fm_deemph (fg, audio_rate) + self.deemph_Right = fm_deemph (fg, audio_rate) + + # compute FIR filter taps for audio filter + width_of_transition_band = audio_rate / 32 + audio_coeffs = gr.firdes.low_pass (1.0 , # gain + demod_rate, # sampling rate + 15000 , + width_of_transition_band, + gr.firdes.WIN_HAMMING) + # input: float; output: float + self.audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs) + if 1: + # Pick off the stereo carrier/2 with this filter. It attenuated 10 dB so apply 10 dB gain + # We pick off the negative frequency half because we want to base band by it! + ## NOTE THIS WAS HACKED TO OFFSET INSERTION LOSS DUE TO DEEMPHASIS + + stereo_carrier_filter_coeffs = gr.firdes.complex_band_pass(10.0, + demod_rate, + -19020, + -18980, + width_of_transition_band, + gr.firdes.WIN_HAMMING) + + #print "len stereo carrier filter = ",len(stereo_carrier_filter_coeffs) + #print "stereo carrier filter ", stereo_carrier_filter_coeffs + #print "width of transition band = ",width_of_transition_band, " audio rate = ", audio_rate + + # Pick off the double side band suppressed carrier Left-Right audio. It is attenuated 10 dB so apply 10 dB gain + + stereo_dsbsc_filter_coeffs = gr.firdes.complex_band_pass(20.0, + demod_rate, + 38000-15000/2, + 38000+15000/2, + width_of_transition_band, + gr.firdes.WIN_HAMMING) + #print "len stereo dsbsc filter = ",len(stereo_dsbsc_filter_coeffs) + #print "stereo dsbsc filter ", stereo_dsbsc_filter_coeffs + # construct overlap add filter system from coefficients for stereo carrier + + self.stereo_carrier_filter = gr.fir_filter_fcc(audio_decimation, stereo_carrier_filter_coeffs) + + # carrier is twice the picked off carrier so arrange to do a commplex multiply + + self.stereo_carrier_generator = gr.multiply_cc(); + + # Pick off the rds signal + + stereo_rds_filter_coeffs = gr.firdes.complex_band_pass(30.0, + demod_rate, + 57000 - 1500, + 57000 + 1500, + width_of_transition_band, + gr.firdes.WIN_HAMMING) + #print "len stereo dsbsc filter = ",len(stereo_dsbsc_filter_coeffs) + #print "stereo dsbsc filter ", stereo_dsbsc_filter_coeffs + # construct overlap add filter system from coefficients for stereo carrier + + self.stereo_carrier_filter = gr.fir_filter_fcc(audio_decimation, stereo_carrier_filter_coeffs) + self.rds_signal_filter = gr.fir_filter_fcc(audio_decimation, stereo_rds_filter_coeffs) + + + + + + + self.rds_carrier_generator = gr.multiply_cc(); + self.rds_signal_generator = gr.multiply_cc(); + self_rds_signal_processor = gr.null_sink(gr.sizeof_gr_complex); + + + + alpha = 5 * 0.25 * math.pi / (audio_rate) + beta = alpha * alpha / 4.0 + max_freq = -2.0*math.pi*18990/audio_rate; + min_freq = -2.0*math.pi*19010/audio_rate; + + self.stereo_carrier_pll_recovery = gr.pll_carriertracking_cc(alpha,beta,max_freq,min_freq); + self.stereo_carrier_pll_recovery.squelch_enable(False); + + + # set up mixer (multiplier) to get the L-R signal at baseband + + self.stereo_basebander = gr.multiply_cc(); + + # pick off the real component of the basebanded L-R signal. The imaginary SHOULD be zero + + self.LmR_real = gr.complex_to_real(); + self.Make_Left = gr.add_ff(); + self.Make_Right = gr.sub_ff(); + + self.stereo_dsbsc_filter = gr.fir_filter_fcc(audio_decimation, stereo_dsbsc_filter_coeffs) + + + if 1: + + # send the real signal to complex filter to pick off the carrier and then to one side of a multiplier + fg.connect (self.fm_demod,self.stereo_carrier_filter,self.stereo_carrier_pll_recovery, (self.stereo_carrier_generator,0)) + # send the already filtered carrier to the otherside of the carrier + fg.connect (self.stereo_carrier_pll_recovery, (self.stereo_carrier_generator,1)) + # the resulting signal from this multiplier is the carrier with correct phase but at -38000 Hz. + + # send the new carrier to one side of the mixer (multiplier) + fg.connect (self.stereo_carrier_generator, (self.stereo_basebander,0)) + # send the demphasized audio to the DSBSC pick off filter, the complex + # DSBSC signal at +38000 Hz is sent to the other side of the mixer/multiplier + fg.connect (self.fm_demod,self.stereo_dsbsc_filter, (self.stereo_basebander,1)) + # the result is BASEBANDED DSBSC with phase zero! + + # Pick off the real part since the imaginary is theoretically zero and then to one side of a summer + fg.connect (self.stereo_basebander, self.LmR_real, (self.Make_Left,0)) + #take the same real part of the DSBSC baseband signal and send it to negative side of a subtracter + fg.connect (self.LmR_real,(self.Make_Right,1)) + + # Make rds carrier by taking the squared pilot tone and multiplying by pilot tone + fg.connect (self.stereo_basebander,(self.rds_carrier_generator,0)) + fg.connect (self.stereo_carrier_pll_recovery,(self.rds_carrier_generator,1)) + # take signal, filter off rds, send into mixer 0 channel + fg.connect (self.fm_demod,self.rds_signal_filter,(self.rds_signal_generator,0)) + # take rds_carrier_generator output and send into mixer 1 channel + fg.connect (self.rds_carrier_generator,(self.rds_signal_generator,1)) + # send basebanded rds signal and send into "processor" which for now is a null sink + fg.connect (self.rds_signal_generator,self_rds_signal_processor) + + + if 1: + # pick off the audio, L+R that is what we used to have and send it to the summer + fg.connect(self.fm_demod, self.audio_filter, (self.Make_Left, 1)) + # take the picked off L+R audio and send it to the PLUS side of the subtractor + fg.connect(self.audio_filter,(self.Make_Right, 0)) + # The result of Make_Left gets (L+R) + (L-R) and results in 2*L + # The result of Make_Right gets (L+R) - (L-R) and results in 2*R + + + # kludge the signals into a stereo channel + kludge = gr.kludge_copy(gr.sizeof_float) + fg.connect(self.Make_Left , self.deemph_Left, (kludge, 0)) + fg.connect(self.Make_Right, self.deemph_Right, (kludge, 1)) + + #send it to the audio system + gr.hier_block.__init__(self, + fg, + self.fm_demod, # head of the pipeline + kludge) # tail of the pipeline + else: + fg.connect (self.fm_demod, self.audio_filter) + gr.hier_block.__init__(self, + fg, + self.fm_demod, # head of the pipeline + self.audio_filter) # tail of the pipeline diff --git a/gnuradio-core/src/python/gnuradio/blksimpl/wfm_tx.py b/gnuradio-core/src/python/gnuradio/blksimpl/wfm_tx.py new file mode 100644 index 00000000..50545557 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/blksimpl/wfm_tx.py @@ -0,0 +1,79 @@ +# +# 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. +# + +import math +from gnuradio import gr, optfir +from gnuradio.blksimpl.fm_emph import fm_preemph + +class wfm_tx(gr.hier_block): + def __init__(self, fg, audio_rate, quad_rate, tau=75e-6, max_dev=75e3): + """ + Wide Band FM Transmitter. + + Takes a single float input stream of audio samples in the range [-1,+1] + and produces a single FM modulated complex baseband output. + + @param fg: flow graph + @param audio_rate: sample rate of audio stream, >= 16k + @type audio_rate: integer + @param quad_rate: sample rate of output stream + @type quad_rate: integer + @param tau: preemphasis time constant (default 75e-6) + @type tau: float + @param max_dev: maximum deviation in Hz (default 75e3) + @type max_dev: float + + quad_rate must be an integer multiple of audio_rate. + """ + + # FIXME audio_rate and quad_rate ought to be exact rationals + audio_rate = int(audio_rate) + quad_rate = int(quad_rate) + + if quad_rate % audio_rate != 0: + raise ValueError, "quad_rate is not an integer multiple of audio_rate" + + + do_interp = audio_rate != quad_rate + + if do_interp: + interp_factor = quad_rate / audio_rate + interp_taps = optfir.low_pass (interp_factor, # gain + quad_rate, # Fs + 16000, # passband cutoff + 18000, # stopband cutoff + 0.1, # passband ripple dB + 40) # stopband atten dB + + print "len(interp_taps) =", len(interp_taps) + self.interpolator = gr.interp_fir_filter_fff (interp_factor, interp_taps) + + self.preemph = fm_preemph (fg, quad_rate, tau=tau) + + k = 2 * math.pi * max_dev / quad_rate + self.modulator = gr.frequency_modulator_fc (k) + + if do_interp: + fg.connect (self.interpolator, self.preemph, self.modulator) + gr.hier_block.__init__(self, fg, self.interpolator, self.modulator) + else: + fg.connect(self.preemph, self.modulator) + gr.hier_block.__init__(self, fg, self.preemph, self.modulator) diff --git a/gnuradio-core/src/python/gnuradio/eng_notation.py b/gnuradio-core/src/python/gnuradio/eng_notation.py new file mode 100644 index 00000000..72cd8931 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/eng_notation.py @@ -0,0 +1,71 @@ +# +# Copyright 2003 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +scale_factor = {} +scale_factor['E'] = 1e18 +scale_factor['P'] = 1e15 +scale_factor['T'] = 1e12 +scale_factor['G'] = 1e9 +scale_factor['M'] = 1e6 +scale_factor['k'] = 1e3 +scale_factor['m'] = 1e-3 +scale_factor['u'] = 1e-6 +scale_factor['n'] = 1e-9 +scale_factor['p'] = 1e-12 +scale_factor['f'] = 1e-15 +scale_factor['a'] = 1e-18 + +def num_to_str (n): + '''Convert a number to a string in engineering notation. E.g., 5e-9 -> 5n''' + m = abs(n) + if m >= 1e9: + return "%gG" % (n * 1e-9) + elif m >= 1e6: + return "%gM" % (n * 1e-6) + elif m >= 1e3: + return "%gk" % (n * 1e-3) + elif m >= 1: + return "%g" % (n) + elif m >= 1e-3: + return "%gm" % (n * 1e3) + elif m >= 1e-6: + return "%gu" % (n * 1e6) # where's that mu when you need it (unicode?) + elif m >= 1e-9: + return "%gn" % (n * 1e9) + elif m >= 1e-12: + return "%gp" % (n * 1e12) + elif m >= 1e-15: + return "%gf" % (n * 1e15) + else: + return "%g" % (n) + + +def str_to_num (value): + '''Convert a string in engineering notation to a number. E.g., '15m' -> 15e-3''' + try: + scale = 1.0 + suffix = value[-1] + if scale_factor.has_key (suffix): + return float (value[0:-1]) * scale_factor[suffix] + return float (value) + except: + raise RuntimeError ( + "Invalid engineering notation value: %r" % (value,)) diff --git a/gnuradio-core/src/python/gnuradio/eng_option.py b/gnuradio-core/src/python/gnuradio/eng_option.py new file mode 100644 index 00000000..3e25c578 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/eng_option.py @@ -0,0 +1,80 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +'''Add support for engineering notation to optparse.OptionParser''' + +from copy import copy +from optparse import Option, OptionValueError + +scale_factor = {} +scale_factor['E'] = 1e18 +scale_factor['P'] = 1e15 +scale_factor['T'] = 1e12 +scale_factor['G'] = 1e9 +scale_factor['M'] = 1e6 +scale_factor['k'] = 1e3 +scale_factor['m'] = 1e-3 +scale_factor['u'] = 1e-6 +scale_factor['n'] = 1e-9 +scale_factor['p'] = 1e-12 +scale_factor['f'] = 1e-15 +scale_factor['a'] = 1e-18 + + +def check_eng_float (option, opt, value): + try: + scale = 1.0 + suffix = value[-1] + if scale_factor.has_key (suffix): + return float (value[0:-1]) * scale_factor[suffix] + return float (value) + except: + raise OptionValueError ( + "option %s: invalid engineering notation value: %r" % (opt, value)) + +def check_intx (option, opt, value): + try: + return int (value, 0) + except: + raise OptionValueError ( + "option %s: invalid integer value: %r" % (opt, value)) + +def check_subdev (option, opt, value): + """ + Value has the form: (A|B)(:0|1)? + + @returns a 2-tuple (0|1, 0|1) + """ + d = { 'A' : (0, 0), 'A:0' : (0, 0), 'A:1' : (0, 1), + 'B' : (1, 0), 'B:0' : (1, 0), 'B:1' : (1, 1) } + try: + return d[value.upper()] + except: + raise OptionValueError( + "option %s: invalid subdev: '%r', must be one of A, B, A:0, A:1, B:0, B:1" % (opt, value)) + +class eng_option (Option): + TYPES = Option.TYPES + ("eng_float", "intx", "subdev") + TYPE_CHECKER = copy (Option.TYPE_CHECKER) + TYPE_CHECKER["eng_float"] = check_eng_float + TYPE_CHECKER["intx"] = check_intx + TYPE_CHECKER["subdev"] = check_subdev + diff --git a/gnuradio-core/src/python/gnuradio/gr/Makefile.am b/gnuradio-core/src/python/gnuradio/gr/Makefile.am new file mode 100644 index 00000000..05dee29f --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/Makefile.am @@ -0,0 +1,77 @@ +# +# 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 $(top_srcdir)/Makefile.common + +EXTRA_DIST = run_tests.in + + +TESTS = \ + run_tests + + +grgrpythondir = $(grpythondir)/gr + +grgrpython_PYTHON = \ + __init__.py \ + basic_flow_graph.py \ + exceptions.py \ + flow_graph.py \ + gr_threading.py \ + gr_threading_23.py \ + gr_threading_24.py \ + hier_block.py \ + prefs.py \ + scheduler.py + +noinst_PYTHON = \ + qa_add_and_friends.py \ + qa_basic_flow_graph.py \ + qa_complex_to_xxx.py \ + qa_correlate_access_code.py \ + qa_diff_encoder.py \ + qa_diff_phasor_cc.py \ + qa_feval.py \ + qa_fft_filter.py \ + qa_filter_delay_fc.py \ + qa_flow_graph.py \ + qa_frequency_modulator.py \ + qa_fsk_stuff.py \ + qa_head.py \ + qa_hilbert.py \ + qa_iir.py \ + qa_interleave.py \ + qa_interp_fir_filter.py \ + qa_kludge_copy.py \ + qa_kludged_imports.py \ + qa_message.py \ + qa_mute.py \ + qa_nlog10.py \ + qa_packed_to_unpacked.py \ + qa_pipe_fittings.py \ + qa_rational_resampler.py \ + qa_sig_source.py \ + qa_single_pole_iir.py \ + qa_single_pole_iir_cc.py \ + qa_unpack_k_bits.py + + +CLEANFILES = *.pyc diff --git a/gnuradio-core/src/python/gnuradio/gr/__init__.py b/gnuradio-core/src/python/gnuradio/gr/__init__.py new file mode 100644 index 00000000..5583c412 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/__init__.py @@ -0,0 +1,40 @@ +# +# Copyright 2003,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. +# + +# The presence of this file turns this directory into a Python package + +# This is the main GNU Radio python module. +# We pull the swig output and the other modules into the gnuradio.gr namespace + +from gnuradio_swig_python import * +from basic_flow_graph import * +from flow_graph import * +from exceptions import * +from hier_block import * + + +# create a couple of aliases +serial_to_parallel = stream_to_vector +parallel_to_serial = vector_to_stream + +# Force the preference database to be initialized +from prefs import prefs + diff --git a/gnuradio-core/src/python/gnuradio/gr/basic_flow_graph.py b/gnuradio-core/src/python/gnuradio/gr/basic_flow_graph.py new file mode 100644 index 00000000..1afc9629 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/basic_flow_graph.py @@ -0,0 +1,267 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 gnuradio_swig_python import gr_block_sptr +import types +import hier_block + +def remove_duplicates (seq): + new = [] + for x in seq: + if not x in new: + new.append (x) + return new + + +class endpoint (object): + __slots__ = ['block', 'port'] + def __init__ (self, block, port): + self.block = block + self.port = port + + def __cmp__ (self, other): + if self.block == other.block and self.port == other.port: + return 0 + return 1 + + def __str__ (self): + return '' % (self.block, self.port) + +def expand_src_endpoint (src_endpoint): + # A src_endpoint is an output of a block + src_endpoint = coerce_endpoint (src_endpoint) + if isinstance (src_endpoint.block, hier_block.hier_block_base): + return expand_src_endpoint ( + coerce_endpoint (src_endpoint.block.resolve_output_port(src_endpoint.port))) + else: + return src_endpoint + +def expand_dst_endpoint (dst_endpoint): + # a dst_endpoint is the input to a block + dst_endpoint = coerce_endpoint (dst_endpoint) + if isinstance (dst_endpoint.block, hier_block.hier_block_base): + exp = [coerce_endpoint(x) for x in + dst_endpoint.block.resolve_input_port(dst_endpoint.port)] + return expand_dst_endpoints (exp) + else: + return [dst_endpoint] + +def expand_dst_endpoints (endpoint_list): + r = [] + for e in endpoint_list: + r.extend (expand_dst_endpoint (e)) + return r + + +def coerce_endpoint (x): + if isinstance (x, endpoint): + return x + elif isinstance (x, types.TupleType) and len (x) == 2: + return endpoint (x[0], x[1]) + elif hasattr (x, 'block'): # assume it's a block + return endpoint (x, 0) + elif isinstance(x, hier_block.hier_block_base): + return endpoint (x, 0) + else: + raise ValueError, "Not coercible to endpoint: %s" % (x,) + + +class edge (object): + __slots__ = ['src', 'dst'] + def __init__ (self, src_endpoint, dst_endpoint): + self.src = src_endpoint + self.dst = dst_endpoint + + def __cmp__ (self, other): + if self.src == other.src and self.dst == other.dst: + return 0 + return 1 + + def __repr__ (self): + return '' % (self.src, self.dst) + +class basic_flow_graph (object): + '''basic_flow_graph -- describe connections between blocks''' + # __slots__ is incompatible with weakrefs (for some reason!) + # __slots__ = ['edge_list'] + def __init__ (self): + self.edge_list = [] + + def connect (self, *points): + '''connect requires two or more arguments that can be coerced to endpoints. + If more than two arguments are provided, they are connected together successively. + ''' + if len (points) < 2: + raise ValueError, ("connect requires at least two endpoints; %d provided." % (len (points),)) + for i in range (1, len (points)): + self._connect (points[i-1], points[i]) + + def _connect (self, src_endpoint, dst_endpoint): + s = expand_src_endpoint (src_endpoint) + for d in expand_dst_endpoint (dst_endpoint): + self._connect_prim (s, d) + + def _connect_prim (self, src_endpoint, dst_endpoint): + src_endpoint = coerce_endpoint (src_endpoint) + dst_endpoint = coerce_endpoint (dst_endpoint) + self._check_valid_src_port (src_endpoint) + self._check_valid_dst_port (dst_endpoint) + self._check_dst_in_use (dst_endpoint) + self._check_type_match (src_endpoint, dst_endpoint) + self.edge_list.append (edge (src_endpoint, dst_endpoint)) + + def disconnect (self, src_endpoint, dst_endpoint): + s = expand_src_endpoint (src_endpoint) + for d in expand_dst_endpoint (dst_endpoint): + self._disconnect_prim (s, d) + + def _disconnect_prim (self, src_endpoint, dst_endpoint): + src_endpoint = coerce_endpoint (src_endpoint) + dst_endpoint = coerce_endpoint (dst_endpoint) + e = edge (src_endpoint, dst_endpoint) + self.edge_list.remove (e) + + def disconnect_all (self): + self.edge_list = [] + + def validate (self): + # check all blocks to ensure: + # (1a) their input ports are contiguously assigned + # (1b) the number of input ports is between min and max + # (2a) their output ports are contiguously assigned + # (2b) the number of output ports is between min and max + # (3) check_topology returns true + + for m in self.all_blocks (): + # print m + + edges = self.in_edges (m) + used_ports = [e.dst.port for e in edges] + ninputs = self._check_contiguity (m, m.input_signature (), used_ports, "input") + + edges = self.out_edges (m) + used_ports = [e.src.port for e in edges] + noutputs = self._check_contiguity (m, m.output_signature (), used_ports, "output") + + if not m.check_topology (ninputs, noutputs): + raise ValueError, ("%s::check_topology (%d, %d) failed" % (m, ninputs, noutputs)) + + + # --- public utilities --- + + def all_blocks (self): + '''return list of all blocks in the graph''' + all_blocks = [] + for edge in self.edge_list: + m = edge.src.block + if not m in all_blocks: + all_blocks.append (m) + m = edge.dst.block + if not m in all_blocks: + all_blocks.append (m) + return all_blocks + + def in_edges (self, m): + '''return list of all edges that have M as a destination''' + return [e for e in self.edge_list if e.dst.block == m] + + def out_edges (self, m): + '''return list of all edges that have M as a source''' + return [e for e in self.edge_list if e.src.block == m] + + def downstream_verticies (self, m): + return [e.dst.block for e in self.out_edges (m)] + + def downstream_verticies_port (self, m, port): + return [e.dst.block for e in self.out_edges(m) if e.src.port == port] + + def upstream_verticies (self, m): + return [e.src.block for e in self.in_edges (m)] + + def adjacent_verticies (self, m): + '''return list of all verticies adjacent to M''' + return self.downstream_verticies (m) + self.upstream_verticies (m) + + def sink_p (self, m): + '''return True iff this block is a sink''' + e = self.out_edges (m) + return len (e) == 0 + + def source_p (self, m): + '''return True iff this block is a source''' + e = self.in_edges (m) + return len (e) == 0 + + # --- internal methods --- + + def _check_dst_in_use (self, dst_endpoint): + '''Ensure that there is not already an endpoint that terminates at dst_endpoint.''' + x = [ep for ep in self.edge_list if ep.dst == dst_endpoint] + if x: # already in use + raise ValueError, ("destination endpoint already in use: %s" % (dst_endpoint)) + + def _check_valid_src_port (self, src_endpoint): + self._check_port (src_endpoint.block.output_signature(), src_endpoint.port) + + def _check_valid_dst_port (self, dst_endpoint): + self._check_port (dst_endpoint.block.input_signature(), dst_endpoint.port) + + def _check_port (self, signature, port): + if port < 0: + raise ValueError, 'port number out of range.' + if signature.max_streams () == -1: # infinite + return # OK + if port >= signature.max_streams (): + raise ValueError, 'port number out of range.' + + def _check_type_match (self, src_endpoint, dst_endpoint): + # for now, we just ensure that the stream item sizes match + src_sig = src_endpoint.block.output_signature () + dst_sig = dst_endpoint.block.input_signature () + src_size = src_sig.sizeof_stream_item (src_endpoint.port) + dst_size = dst_sig.sizeof_stream_item (dst_endpoint.port) + if src_size != dst_size: + raise ValueError, 'source and destination data sizes are different' + + def _check_contiguity (self, m, sig, used_ports, dir): + used_ports.sort () + used_ports = remove_duplicates (used_ports) + min_s = sig.min_streams () + + l = len (used_ports) + if l == 0: + if min_s == 0: + return l + raise ValueError, ("%s requires %d %s connections. It has none." % + (m, min_s, dir)) + + if used_ports[-1] + 1 < min_s: + raise ValueError, ("%s requires %d %s connections. It has %d." % + (m, min_s, dir, used_ports[-1] + 1)) + + if used_ports[-1] + 1 != l: + for i in range (l): + if used_ports[i] != i: + raise ValueError, ("%s %s port %d is not connected" % + (m, dir, i)) + + # print "%s ports: %s" % (dir, used_ports) + return l diff --git a/gnuradio-core/src/python/gnuradio/gr/benchmark_filters.py b/gnuradio-core/src/python/gnuradio/gr/benchmark_filters.py new file mode 100755 index 00000000..7b2f44c4 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/benchmark_filters.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python + +import time +import random +from optparse import OptionParser +from gnuradio import gr +from gnuradio.eng_option import eng_option + +def make_random_complex_tuple(L): + result = [] + for x in range(L): + result.append(complex(random.uniform(-1000,1000), + random.uniform(-1000,1000))) + return tuple(result) + +def benchmark(name, creator, dec, ntaps, total_test_size, block_size): + block_size = 32768 + + fg = gr.flow_graph() + taps = make_random_complex_tuple(ntaps) + src = gr.vector_source_c(make_random_complex_tuple(block_size), True) + head = gr.head(gr.sizeof_gr_complex, int(total_test_size)) + op = creator(dec, taps) + dst = gr.null_sink(gr.sizeof_gr_complex) + fg.connect(src, head, op, dst) + start = time.time() + fg.run() + stop = time.time() + delta = stop - start + print "%16s: taps: %4d input: %4g, time: %6.3f taps/sec: %10.4g" % ( + name, ntaps, total_test_size, delta, ntaps*total_test_size/delta) + +def main(): + parser = OptionParser(option_class=eng_option) + parser.add_option("-n", "--ntaps", type="int", default=256) + parser.add_option("-t", "--total-input-size", type="eng_float", default=40e6) + parser.add_option("-b", "--block-size", type="intx", default=50000) + parser.add_option("-d", "--decimation", type="int", default=1) + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + sys.exit(1) + + ntaps = options.ntaps + total_input_size = options.total_input_size + block_size = options.block_size + dec = options.decimation + + benchmark("gr.fir_filter_ccc", gr.fir_filter_ccc, + dec, ntaps, total_input_size, block_size) + benchmark("gr.fft_filter_ccc", gr.fft_filter_ccc, + dec, ntaps, total_input_size, block_size) + +if __name__ == '__main__': + main() diff --git a/gnuradio-core/src/python/gnuradio/gr/exceptions.py b/gnuradio-core/src/python/gnuradio/gr/exceptions.py new file mode 100644 index 00000000..0cbeb143 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/exceptions.py @@ -0,0 +1,27 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 NotDAG (Exception): + """Not a directed acyclic graph""" + pass + +class CantHappen (Exception): + """Can't happen""" + pass diff --git a/gnuradio-core/src/python/gnuradio/gr/flow_graph.py b/gnuradio-core/src/python/gnuradio/gr/flow_graph.py new file mode 100644 index 00000000..db9c5876 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/flow_graph.py @@ -0,0 +1,234 @@ +# +# 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 gnuradio.gr.basic_flow_graph import remove_duplicates, endpoint, edge, \ + basic_flow_graph + +from gnuradio.gr.exceptions import * +from gnuradio_swig_python import buffer, buffer_add_reader, block_detail, \ + single_threaded_scheduler + +from gnuradio.gr.scheduler import scheduler + +_WHITE = 0 # graph coloring tags +_GRAY = 1 +_BLACK = 2 + +_flow_graph_debug = False + +def set_flow_graph_debug(on): + global _flow_graph_debug + _flow_graph_debug = on + + +class buffer_sizes (object): + """compute buffer sizes to use""" + def __init__ (self, flow_graph): + # We could scan the graph here and determine individual sizes + # based on relative_rate, number of readers, etc. + + # The simplest thing that could possibly work: all buffers same size + self.flow_graph = flow_graph + self.fixed_buffer_size = 32*1024 + + def allocate (self, m, index): + """allocate buffer for output index of block m""" + item_size = m.output_signature().sizeof_stream_item (index) + nitems = self.fixed_buffer_size / item_size + if nitems < 2 * m.output_multiple (): + nitems = 2 * m.output_multiple () + + # if any downstream blocks is a decimator and/or has a large output_multiple, + # ensure that we have a buffer at least 2 * their decimation_factor*output_multiple + for mdown in self.flow_graph.downstream_verticies_port(m, index): + decimation = int(1.0 / mdown.relative_rate()) + nitems = max(nitems, 2 * (decimation * mdown.output_multiple() + mdown.history())) + + return buffer (nitems, item_size) + + +class flow_graph (basic_flow_graph): + """add physical connection info to simple_flow_graph + """ + # __slots__ is incompatible with weakrefs (for some reason!) + # __slots__ = ['blocks', 'scheduler'] + + def __init__ (self): + basic_flow_graph.__init__ (self); + self.blocks = None + self.scheduler = None + + def __del__(self): + # print "\nflow_graph.__del__" + # this ensures that i/o devices such as the USRP get shutdown gracefully + self.stop() + + def start (self): + '''start graph, forking thread(s), return immediately''' + if self.scheduler: + raise RuntimeError, "Scheduler already running" + self._setup_connections () + + # cast down to gr_module_sptr + # t = [x.block () for x in self.topological_sort (self.blocks)] + self.scheduler = scheduler (self) + self.scheduler.start () + + def stop (self): + '''tells scheduler to stop and waits for it to happen''' + if self.scheduler: + self.scheduler.stop () + self.scheduler = None + + def wait (self): + '''waits for scheduler to stop''' + if self.scheduler: + self.scheduler.wait () + self.scheduler = None + + def is_running (self): + return not not self.scheduler + + def run (self): + '''start graph, wait for completion''' + self.start () + self.wait () + + def _setup_connections (self): + """given the basic flow graph, setup all the physical connections""" + self.validate () + self.blocks = self.all_blocks () + self._assign_details () + self._assign_buffers () + self._connect_inputs () + + def _assign_details (self): + for m in self.blocks: + edges = self.in_edges (m) + used_ports = remove_duplicates ([e.dst.port for e in edges]) + ninputs = len (used_ports) + + edges = self.out_edges (m) + used_ports = remove_duplicates ([e.src.port for e in edges]) + noutputs = len (used_ports) + + m.set_detail (block_detail (ninputs, noutputs)) + + def _assign_buffers (self): + """determine the buffer sizes to use, allocate them and attach to detail""" + sizes = buffer_sizes (self) + for m in self.blocks: + d = m.detail () + for index in range (d.noutputs ()): + d.set_output (index, sizes.allocate (m, index)) + + def _connect_inputs (self): + """connect all block inputs to appropriate upstream buffers""" + for m in self.blocks: + d = m.detail () + # print "%r history = %d" % (m, m.history()) + for e in self.in_edges(m): + # FYI, sources don't have any in_edges + our_port = e.dst.port + upstream_block = e.src.block + upstream_port = e.src.port + upstream_buffer = upstream_block.detail().output(upstream_port) + d.set_input(our_port, buffer_add_reader(upstream_buffer, m.history())) + + + def topological_sort (self, all_v): + ''' + Return a topologically sorted list of vertices. + This is basically a depth-first search with checks + for back edges (the non-DAG condition) + + ''' + + # it's correct without this sort, but this + # should give better ordering for cache utilization + all_v = self._sort_sources_first (all_v) + + output = [] + for v in all_v: + v.ts_color = _WHITE + for v in all_v: + if v.ts_color == _WHITE: + self._dfs_visit (v, output) + output.reverse () + return output + + def _dfs_visit (self, u, output): + # print "dfs_visit (enter): ", u + u.ts_color = _GRAY + for v in self.downstream_verticies (u): + if v.ts_color == _WHITE: # (u, v) is a tree edge + self._dfs_visit (v, output) + elif v.ts_color == _GRAY: # (u, v) is a back edge + raise NotDAG, "The graph is not an acyclic graph (It's got a loop)" + elif v.ts_color == _BLACK: # (u, v) is a cross or forward edge + pass + else: + raise CantHappen, "Invalid color on vertex" + u.ts_color = _BLACK + output.append (u) + # print "dfs_visit (exit): ", u, output + + def _sort_sources_first (self, all_v): + # the sort function is not guaranteed to be stable. + # We add the unique_id in to the key so we're guaranteed + # of reproducible results. This is important for the test + # code. There is often more than one valid topological sort. + # We want to force a reproducible choice. + x = [(not self.source_p(v), v.unique_id(), v) for v in all_v] + x.sort () + x = [v[2] for v in x] + # print "sorted: ", x + return x + + def partition_graph (self, all_v): + '''Return a list of lists of nodes that are connected. + The result is a list of disjoint graphs. + The sublists are topologically sorted. + ''' + result = [] + working_v = all_v[:] # make copy + while working_v: + rv = self._reachable_verticies (working_v[0], working_v) + result.append (self.topological_sort (rv)) + for v in rv: + working_v.remove (v) + if _flow_graph_debug: + print "partition_graph:", result + return result + + def _reachable_verticies (self, start, all_v): + for v in all_v: + v.ts_color = _WHITE + + self._reachable_dfs_visit (start) + return [v for v in all_v if v.ts_color == _BLACK] + + def _reachable_dfs_visit (self, u): + u.ts_color = _BLACK + for v in self.adjacent_verticies (u): + if v.ts_color == _WHITE: + self._reachable_dfs_visit (v) + return None diff --git a/gnuradio-core/src/python/gnuradio/gr/gr_threading.py b/gnuradio-core/src/python/gnuradio/gr/gr_threading.py new file mode 100644 index 00000000..6a09a323 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/gr_threading.py @@ -0,0 +1,35 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 sys import version_info as _version_info + +# import patched version of standard threading module + +if _version_info[0:2] == (2, 3): + #print "Importing gr_threading_23" + from gr_threading_23 import * +elif _version_info[0:2] == (2, 4): + #print "Importing gr_threading_24" + from gr_threading_24 import * +else: + # assume the patch was applied... + #print "Importing system provided threading" + from threading import * diff --git a/gnuradio-core/src/python/gnuradio/gr/gr_threading_23.py b/gnuradio-core/src/python/gnuradio/gr/gr_threading_23.py new file mode 100644 index 00000000..dee8034c --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/gr_threading_23.py @@ -0,0 +1,724 @@ +"""Thread module emulating a subset of Java's threading model.""" + +# This started life as the threading.py module of Python 2.3 +# It's been patched to fix a problem with join, where a KeyboardInterrupt +# caused a lock to be left in the acquired state. + +import sys as _sys + +try: + import thread +except ImportError: + del _sys.modules[__name__] + raise + +from StringIO import StringIO as _StringIO +from time import time as _time, sleep as _sleep +from traceback import print_exc as _print_exc + +# Rename some stuff so "from threading import *" is safe +__all__ = ['activeCount', 'Condition', 'currentThread', 'enumerate', 'Event', + 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread', + 'Timer', 'setprofile', 'settrace'] + +_start_new_thread = thread.start_new_thread +_allocate_lock = thread.allocate_lock +_get_ident = thread.get_ident +ThreadError = thread.error +del thread + + +# Debug support (adapted from ihooks.py). +# All the major classes here derive from _Verbose. We force that to +# be a new-style class so that all the major classes here are new-style. +# This helps debugging (type(instance) is more revealing for instances +# of new-style classes). + +_VERBOSE = False + +if __debug__: + + class _Verbose(object): + + def __init__(self, verbose=None): + if verbose is None: + verbose = _VERBOSE + self.__verbose = verbose + + def _note(self, format, *args): + if self.__verbose: + format = format % args + format = "%s: %s\n" % ( + currentThread().getName(), format) + _sys.stderr.write(format) + +else: + # Disable this when using "python -O" + class _Verbose(object): + def __init__(self, verbose=None): + pass + def _note(self, *args): + pass + +# Support for profile and trace hooks + +_profile_hook = None +_trace_hook = None + +def setprofile(func): + global _profile_hook + _profile_hook = func + +def settrace(func): + global _trace_hook + _trace_hook = func + +# Synchronization classes + +Lock = _allocate_lock + +def RLock(*args, **kwargs): + return _RLock(*args, **kwargs) + +class _RLock(_Verbose): + + def __init__(self, verbose=None): + _Verbose.__init__(self, verbose) + self.__block = _allocate_lock() + self.__owner = None + self.__count = 0 + + def __repr__(self): + return "<%s(%s, %d)>" % ( + self.__class__.__name__, + self.__owner and self.__owner.getName(), + self.__count) + + def acquire(self, blocking=1): + me = currentThread() + if self.__owner is me: + self.__count = self.__count + 1 + if __debug__: + self._note("%s.acquire(%s): recursive success", self, blocking) + return 1 + rc = self.__block.acquire(blocking) + if rc: + self.__owner = me + self.__count = 1 + if __debug__: + self._note("%s.acquire(%s): initial succes", self, blocking) + else: + if __debug__: + self._note("%s.acquire(%s): failure", self, blocking) + return rc + + def release(self): + me = currentThread() + assert self.__owner is me, "release() of un-acquire()d lock" + self.__count = count = self.__count - 1 + if not count: + self.__owner = None + self.__block.release() + if __debug__: + self._note("%s.release(): final release", self) + else: + if __debug__: + self._note("%s.release(): non-final release", self) + + # Internal methods used by condition variables + + def _acquire_restore(self, (count, owner)): + self.__block.acquire() + self.__count = count + self.__owner = owner + if __debug__: + self._note("%s._acquire_restore()", self) + + def _release_save(self): + if __debug__: + self._note("%s._release_save()", self) + count = self.__count + self.__count = 0 + owner = self.__owner + self.__owner = None + self.__block.release() + return (count, owner) + + def _is_owned(self): + return self.__owner is currentThread() + + +def Condition(*args, **kwargs): + return _Condition(*args, **kwargs) + +class _Condition(_Verbose): + + def __init__(self, lock=None, verbose=None): + _Verbose.__init__(self, verbose) + if lock is None: + lock = RLock() + self.__lock = lock + # Export the lock's acquire() and release() methods + self.acquire = lock.acquire + self.release = lock.release + # If the lock defines _release_save() and/or _acquire_restore(), + # these override the default implementations (which just call + # release() and acquire() on the lock). Ditto for _is_owned(). + try: + self._release_save = lock._release_save + except AttributeError: + pass + try: + self._acquire_restore = lock._acquire_restore + except AttributeError: + pass + try: + self._is_owned = lock._is_owned + except AttributeError: + pass + self.__waiters = [] + + def __repr__(self): + return "" % (self.__lock, len(self.__waiters)) + + def _release_save(self): + self.__lock.release() # No state to save + + def _acquire_restore(self, x): + self.__lock.acquire() # Ignore saved state + + def _is_owned(self): + # Return True if lock is owned by currentThread. + # This method is called only if __lock doesn't have _is_owned(). + if self.__lock.acquire(0): + self.__lock.release() + return False + else: + return True + + def wait(self, timeout=None): + currentThread() # for side-effect + assert self._is_owned(), "wait() of un-acquire()d lock" + waiter = _allocate_lock() + waiter.acquire() + self.__waiters.append(waiter) + saved_state = self._release_save() + try: # restore state no matter what (e.g., KeyboardInterrupt) + if timeout is None: + waiter.acquire() + if __debug__: + self._note("%s.wait(): got it", self) + else: + # Balancing act: We can't afford a pure busy loop, so we + # have to sleep; but if we sleep the whole timeout time, + # we'll be unresponsive. The scheme here sleeps very + # little at first, longer as time goes on, but never longer + # than 20 times per second (or the timeout time remaining). + endtime = _time() + timeout + delay = 0.0005 # 500 us -> initial delay of 1 ms + while True: + gotit = waiter.acquire(0) + if gotit: + break + remaining = endtime - _time() + if remaining <= 0: + break + delay = min(delay * 2, remaining, .05) + _sleep(delay) + if not gotit: + if __debug__: + self._note("%s.wait(%s): timed out", self, timeout) + try: + self.__waiters.remove(waiter) + except ValueError: + pass + else: + if __debug__: + self._note("%s.wait(%s): got it", self, timeout) + finally: + self._acquire_restore(saved_state) + + def notify(self, n=1): + currentThread() # for side-effect + assert self._is_owned(), "notify() of un-acquire()d lock" + __waiters = self.__waiters + waiters = __waiters[:n] + if not waiters: + if __debug__: + self._note("%s.notify(): no waiters", self) + return + self._note("%s.notify(): notifying %d waiter%s", self, n, + n!=1 and "s" or "") + for waiter in waiters: + waiter.release() + try: + __waiters.remove(waiter) + except ValueError: + pass + + def notifyAll(self): + self.notify(len(self.__waiters)) + + +def Semaphore(*args, **kwargs): + return _Semaphore(*args, **kwargs) + +class _Semaphore(_Verbose): + + # After Tim Peters' semaphore class, but not quite the same (no maximum) + + def __init__(self, value=1, verbose=None): + assert value >= 0, "Semaphore initial value must be >= 0" + _Verbose.__init__(self, verbose) + self.__cond = Condition(Lock()) + self.__value = value + + def acquire(self, blocking=1): + rc = False + self.__cond.acquire() + while self.__value == 0: + if not blocking: + break + if __debug__: + self._note("%s.acquire(%s): blocked waiting, value=%s", + self, blocking, self.__value) + self.__cond.wait() + else: + self.__value = self.__value - 1 + if __debug__: + self._note("%s.acquire: success, value=%s", + self, self.__value) + rc = True + self.__cond.release() + return rc + + def release(self): + self.__cond.acquire() + self.__value = self.__value + 1 + if __debug__: + self._note("%s.release: success, value=%s", + self, self.__value) + self.__cond.notify() + self.__cond.release() + + +def BoundedSemaphore(*args, **kwargs): + return _BoundedSemaphore(*args, **kwargs) + +class _BoundedSemaphore(_Semaphore): + """Semaphore that checks that # releases is <= # acquires""" + def __init__(self, value=1, verbose=None): + _Semaphore.__init__(self, value, verbose) + self._initial_value = value + + def release(self): + if self._Semaphore__value >= self._initial_value: + raise ValueError, "Semaphore released too many times" + return _Semaphore.release(self) + + +def Event(*args, **kwargs): + return _Event(*args, **kwargs) + +class _Event(_Verbose): + + # After Tim Peters' event class (without is_posted()) + + def __init__(self, verbose=None): + _Verbose.__init__(self, verbose) + self.__cond = Condition(Lock()) + self.__flag = False + + def isSet(self): + return self.__flag + + def set(self): + self.__cond.acquire() + try: + self.__flag = True + self.__cond.notifyAll() + finally: + self.__cond.release() + + def clear(self): + self.__cond.acquire() + try: + self.__flag = False + finally: + self.__cond.release() + + def wait(self, timeout=None): + self.__cond.acquire() + try: + if not self.__flag: + self.__cond.wait(timeout) + finally: + self.__cond.release() + +# Helper to generate new thread names +_counter = 0 +def _newname(template="Thread-%d"): + global _counter + _counter = _counter + 1 + return template % _counter + +# Active thread administration +_active_limbo_lock = _allocate_lock() +_active = {} +_limbo = {} + + +# Main class for threads + +class Thread(_Verbose): + + __initialized = False + + def __init__(self, group=None, target=None, name=None, + args=(), kwargs={}, verbose=None): + assert group is None, "group argument must be None for now" + _Verbose.__init__(self, verbose) + self.__target = target + self.__name = str(name or _newname()) + self.__args = args + self.__kwargs = kwargs + self.__daemonic = self._set_daemon() + self.__started = False + self.__stopped = False + self.__block = Condition(Lock()) + self.__initialized = True + + def _set_daemon(self): + # Overridden in _MainThread and _DummyThread + return currentThread().isDaemon() + + def __repr__(self): + assert self.__initialized, "Thread.__init__() was not called" + status = "initial" + if self.__started: + status = "started" + if self.__stopped: + status = "stopped" + if self.__daemonic: + status = status + " daemon" + return "<%s(%s, %s)>" % (self.__class__.__name__, self.__name, status) + + def start(self): + assert self.__initialized, "Thread.__init__() not called" + assert not self.__started, "thread already started" + if __debug__: + self._note("%s.start(): starting thread", self) + _active_limbo_lock.acquire() + _limbo[self] = self + _active_limbo_lock.release() + _start_new_thread(self.__bootstrap, ()) + self.__started = True + _sleep(0.000001) # 1 usec, to let the thread run (Solaris hack) + + def run(self): + if self.__target: + self.__target(*self.__args, **self.__kwargs) + + def __bootstrap(self): + try: + self.__started = True + _active_limbo_lock.acquire() + _active[_get_ident()] = self + del _limbo[self] + _active_limbo_lock.release() + if __debug__: + self._note("%s.__bootstrap(): thread started", self) + + if _trace_hook: + self._note("%s.__bootstrap(): registering trace hook", self) + _sys.settrace(_trace_hook) + if _profile_hook: + self._note("%s.__bootstrap(): registering profile hook", self) + _sys.setprofile(_profile_hook) + + try: + self.run() + except SystemExit: + if __debug__: + self._note("%s.__bootstrap(): raised SystemExit", self) + except: + if __debug__: + self._note("%s.__bootstrap(): unhandled exception", self) + s = _StringIO() + _print_exc(file=s) + _sys.stderr.write("Exception in thread %s:\n%s\n" % + (self.getName(), s.getvalue())) + else: + if __debug__: + self._note("%s.__bootstrap(): normal return", self) + finally: + self.__stop() + try: + self.__delete() + except: + pass + + def __stop(self): + self.__block.acquire() + self.__stopped = True + self.__block.notifyAll() + self.__block.release() + + def __delete(self): + _active_limbo_lock.acquire() + del _active[_get_ident()] + _active_limbo_lock.release() + + def join(self, timeout=None): + assert self.__initialized, "Thread.__init__() not called" + assert self.__started, "cannot join thread before it is started" + assert self is not currentThread(), "cannot join current thread" + if __debug__: + if not self.__stopped: + self._note("%s.join(): waiting until thread stops", self) + self.__block.acquire() + try: + if timeout is None: + while not self.__stopped: + self.__block.wait() + if __debug__: + self._note("%s.join(): thread stopped", self) + else: + deadline = _time() + timeout + while not self.__stopped: + delay = deadline - _time() + if delay <= 0: + if __debug__: + self._note("%s.join(): timed out", self) + break + self.__block.wait(delay) + else: + if __debug__: + self._note("%s.join(): thread stopped", self) + finally: + self.__block.release() + + def getName(self): + assert self.__initialized, "Thread.__init__() not called" + return self.__name + + def setName(self, name): + assert self.__initialized, "Thread.__init__() not called" + self.__name = str(name) + + def isAlive(self): + assert self.__initialized, "Thread.__init__() not called" + return self.__started and not self.__stopped + + def isDaemon(self): + assert self.__initialized, "Thread.__init__() not called" + return self.__daemonic + + def setDaemon(self, daemonic): + assert self.__initialized, "Thread.__init__() not called" + assert not self.__started, "cannot set daemon status of active thread" + self.__daemonic = daemonic + +# The timer class was contributed by Itamar Shtull-Trauring + +def Timer(*args, **kwargs): + return _Timer(*args, **kwargs) + +class _Timer(Thread): + """Call a function after a specified number of seconds: + + t = Timer(30.0, f, args=[], kwargs={}) + t.start() + t.cancel() # stop the timer's action if it's still waiting + """ + + def __init__(self, interval, function, args=[], kwargs={}): + Thread.__init__(self) + self.interval = interval + self.function = function + self.args = args + self.kwargs = kwargs + self.finished = Event() + + def cancel(self): + """Stop the timer if it hasn't finished yet""" + self.finished.set() + + def run(self): + self.finished.wait(self.interval) + if not self.finished.isSet(): + self.function(*self.args, **self.kwargs) + self.finished.set() + +# Special thread class to represent the main thread +# This is garbage collected through an exit handler + +class _MainThread(Thread): + + def __init__(self): + Thread.__init__(self, name="MainThread") + self._Thread__started = True + _active_limbo_lock.acquire() + _active[_get_ident()] = self + _active_limbo_lock.release() + import atexit + atexit.register(self.__exitfunc) + + def _set_daemon(self): + return False + + def __exitfunc(self): + self._Thread__stop() + t = _pickSomeNonDaemonThread() + if t: + if __debug__: + self._note("%s: waiting for other threads", self) + while t: + t.join() + t = _pickSomeNonDaemonThread() + if __debug__: + self._note("%s: exiting", self) + self._Thread__delete() + +def _pickSomeNonDaemonThread(): + for t in enumerate(): + if not t.isDaemon() and t.isAlive(): + return t + return None + + +# Dummy thread class to represent threads not started here. +# These aren't garbage collected when they die, +# nor can they be waited for. +# Their purpose is to return *something* from currentThread(). +# They are marked as daemon threads so we won't wait for them +# when we exit (conform previous semantics). + +class _DummyThread(Thread): + + def __init__(self): + Thread.__init__(self, name=_newname("Dummy-%d")) + self._Thread__started = True + _active_limbo_lock.acquire() + _active[_get_ident()] = self + _active_limbo_lock.release() + + def _set_daemon(self): + return True + + def join(self, timeout=None): + assert False, "cannot join a dummy thread" + + +# Global API functions + +def currentThread(): + try: + return _active[_get_ident()] + except KeyError: + ##print "currentThread(): no current thread for", _get_ident() + return _DummyThread() + +def activeCount(): + _active_limbo_lock.acquire() + count = len(_active) + len(_limbo) + _active_limbo_lock.release() + return count + +def enumerate(): + _active_limbo_lock.acquire() + active = _active.values() + _limbo.values() + _active_limbo_lock.release() + return active + +# Create the main thread object + +_MainThread() + + +# Self-test code + +def _test(): + + class BoundedQueue(_Verbose): + + def __init__(self, limit): + _Verbose.__init__(self) + self.mon = RLock() + self.rc = Condition(self.mon) + self.wc = Condition(self.mon) + self.limit = limit + self.queue = [] + + def put(self, item): + self.mon.acquire() + while len(self.queue) >= self.limit: + self._note("put(%s): queue full", item) + self.wc.wait() + self.queue.append(item) + self._note("put(%s): appended, length now %d", + item, len(self.queue)) + self.rc.notify() + self.mon.release() + + def get(self): + self.mon.acquire() + while not self.queue: + self._note("get(): queue empty") + self.rc.wait() + item = self.queue.pop(0) + self._note("get(): got %s, %d left", item, len(self.queue)) + self.wc.notify() + self.mon.release() + return item + + class ProducerThread(Thread): + + def __init__(self, queue, quota): + Thread.__init__(self, name="Producer") + self.queue = queue + self.quota = quota + + def run(self): + from random import random + counter = 0 + while counter < self.quota: + counter = counter + 1 + self.queue.put("%s.%d" % (self.getName(), counter)) + _sleep(random() * 0.00001) + + + class ConsumerThread(Thread): + + def __init__(self, queue, count): + Thread.__init__(self, name="Consumer") + self.queue = queue + self.count = count + + def run(self): + while self.count > 0: + item = self.queue.get() + print item + self.count = self.count - 1 + + NP = 3 + QL = 4 + NI = 5 + + Q = BoundedQueue(QL) + P = [] + for i in range(NP): + t = ProducerThread(Q, NI) + t.setName("Producer-%d" % (i+1)) + P.append(t) + C = ConsumerThread(Q, NI*NP) + for t in P: + t.start() + _sleep(0.000001) + C.start() + for t in P: + t.join() + C.join() + +if __name__ == '__main__': + _test() diff --git a/gnuradio-core/src/python/gnuradio/gr/gr_threading_24.py b/gnuradio-core/src/python/gnuradio/gr/gr_threading_24.py new file mode 100644 index 00000000..8539bfc0 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/gr_threading_24.py @@ -0,0 +1,793 @@ +"""Thread module emulating a subset of Java's threading model.""" + +# This started life as the threading.py module of Python 2.4 +# It's been patched to fix a problem with join, where a KeyboardInterrupt +# caused a lock to be left in the acquired state. + +import sys as _sys + +try: + import thread +except ImportError: + del _sys.modules[__name__] + raise + +from time import time as _time, sleep as _sleep +from traceback import format_exc as _format_exc +from collections import deque + +# Rename some stuff so "from threading import *" is safe +__all__ = ['activeCount', 'Condition', 'currentThread', 'enumerate', 'Event', + 'Lock', 'RLock', 'Semaphore', 'BoundedSemaphore', 'Thread', + 'Timer', 'setprofile', 'settrace', 'local'] + +_start_new_thread = thread.start_new_thread +_allocate_lock = thread.allocate_lock +_get_ident = thread.get_ident +ThreadError = thread.error +del thread + + +# Debug support (adapted from ihooks.py). +# All the major classes here derive from _Verbose. We force that to +# be a new-style class so that all the major classes here are new-style. +# This helps debugging (type(instance) is more revealing for instances +# of new-style classes). + +_VERBOSE = False + +if __debug__: + + class _Verbose(object): + + def __init__(self, verbose=None): + if verbose is None: + verbose = _VERBOSE + self.__verbose = verbose + + def _note(self, format, *args): + if self.__verbose: + format = format % args + format = "%s: %s\n" % ( + currentThread().getName(), format) + _sys.stderr.write(format) + +else: + # Disable this when using "python -O" + class _Verbose(object): + def __init__(self, verbose=None): + pass + def _note(self, *args): + pass + +# Support for profile and trace hooks + +_profile_hook = None +_trace_hook = None + +def setprofile(func): + global _profile_hook + _profile_hook = func + +def settrace(func): + global _trace_hook + _trace_hook = func + +# Synchronization classes + +Lock = _allocate_lock + +def RLock(*args, **kwargs): + return _RLock(*args, **kwargs) + +class _RLock(_Verbose): + + def __init__(self, verbose=None): + _Verbose.__init__(self, verbose) + self.__block = _allocate_lock() + self.__owner = None + self.__count = 0 + + def __repr__(self): + return "<%s(%s, %d)>" % ( + self.__class__.__name__, + self.__owner and self.__owner.getName(), + self.__count) + + def acquire(self, blocking=1): + me = currentThread() + if self.__owner is me: + self.__count = self.__count + 1 + if __debug__: + self._note("%s.acquire(%s): recursive success", self, blocking) + return 1 + rc = self.__block.acquire(blocking) + if rc: + self.__owner = me + self.__count = 1 + if __debug__: + self._note("%s.acquire(%s): initial succes", self, blocking) + else: + if __debug__: + self._note("%s.acquire(%s): failure", self, blocking) + return rc + + def release(self): + me = currentThread() + assert self.__owner is me, "release() of un-acquire()d lock" + self.__count = count = self.__count - 1 + if not count: + self.__owner = None + self.__block.release() + if __debug__: + self._note("%s.release(): final release", self) + else: + if __debug__: + self._note("%s.release(): non-final release", self) + + # Internal methods used by condition variables + + def _acquire_restore(self, (count, owner)): + self.__block.acquire() + self.__count = count + self.__owner = owner + if __debug__: + self._note("%s._acquire_restore()", self) + + def _release_save(self): + if __debug__: + self._note("%s._release_save()", self) + count = self.__count + self.__count = 0 + owner = self.__owner + self.__owner = None + self.__block.release() + return (count, owner) + + def _is_owned(self): + return self.__owner is currentThread() + + +def Condition(*args, **kwargs): + return _Condition(*args, **kwargs) + +class _Condition(_Verbose): + + def __init__(self, lock=None, verbose=None): + _Verbose.__init__(self, verbose) + if lock is None: + lock = RLock() + self.__lock = lock + # Export the lock's acquire() and release() methods + self.acquire = lock.acquire + self.release = lock.release + # If the lock defines _release_save() and/or _acquire_restore(), + # these override the default implementations (which just call + # release() and acquire() on the lock). Ditto for _is_owned(). + try: + self._release_save = lock._release_save + except AttributeError: + pass + try: + self._acquire_restore = lock._acquire_restore + except AttributeError: + pass + try: + self._is_owned = lock._is_owned + except AttributeError: + pass + self.__waiters = [] + + def __repr__(self): + return "" % (self.__lock, len(self.__waiters)) + + def _release_save(self): + self.__lock.release() # No state to save + + def _acquire_restore(self, x): + self.__lock.acquire() # Ignore saved state + + def _is_owned(self): + # Return True if lock is owned by currentThread. + # This method is called only if __lock doesn't have _is_owned(). + if self.__lock.acquire(0): + self.__lock.release() + return False + else: + return True + + def wait(self, timeout=None): + assert self._is_owned(), "wait() of un-acquire()d lock" + waiter = _allocate_lock() + waiter.acquire() + self.__waiters.append(waiter) + saved_state = self._release_save() + try: # restore state no matter what (e.g., KeyboardInterrupt) + if timeout is None: + waiter.acquire() + if __debug__: + self._note("%s.wait(): got it", self) + else: + # Balancing act: We can't afford a pure busy loop, so we + # have to sleep; but if we sleep the whole timeout time, + # we'll be unresponsive. The scheme here sleeps very + # little at first, longer as time goes on, but never longer + # than 20 times per second (or the timeout time remaining). + endtime = _time() + timeout + delay = 0.0005 # 500 us -> initial delay of 1 ms + while True: + gotit = waiter.acquire(0) + if gotit: + break + remaining = endtime - _time() + if remaining <= 0: + break + delay = min(delay * 2, remaining, .05) + _sleep(delay) + if not gotit: + if __debug__: + self._note("%s.wait(%s): timed out", self, timeout) + try: + self.__waiters.remove(waiter) + except ValueError: + pass + else: + if __debug__: + self._note("%s.wait(%s): got it", self, timeout) + finally: + self._acquire_restore(saved_state) + + def notify(self, n=1): + assert self._is_owned(), "notify() of un-acquire()d lock" + __waiters = self.__waiters + waiters = __waiters[:n] + if not waiters: + if __debug__: + self._note("%s.notify(): no waiters", self) + return + self._note("%s.notify(): notifying %d waiter%s", self, n, + n!=1 and "s" or "") + for waiter in waiters: + waiter.release() + try: + __waiters.remove(waiter) + except ValueError: + pass + + def notifyAll(self): + self.notify(len(self.__waiters)) + + +def Semaphore(*args, **kwargs): + return _Semaphore(*args, **kwargs) + +class _Semaphore(_Verbose): + + # After Tim Peters' semaphore class, but not quite the same (no maximum) + + def __init__(self, value=1, verbose=None): + assert value >= 0, "Semaphore initial value must be >= 0" + _Verbose.__init__(self, verbose) + self.__cond = Condition(Lock()) + self.__value = value + + def acquire(self, blocking=1): + rc = False + self.__cond.acquire() + while self.__value == 0: + if not blocking: + break + if __debug__: + self._note("%s.acquire(%s): blocked waiting, value=%s", + self, blocking, self.__value) + self.__cond.wait() + else: + self.__value = self.__value - 1 + if __debug__: + self._note("%s.acquire: success, value=%s", + self, self.__value) + rc = True + self.__cond.release() + return rc + + def release(self): + self.__cond.acquire() + self.__value = self.__value + 1 + if __debug__: + self._note("%s.release: success, value=%s", + self, self.__value) + self.__cond.notify() + self.__cond.release() + + +def BoundedSemaphore(*args, **kwargs): + return _BoundedSemaphore(*args, **kwargs) + +class _BoundedSemaphore(_Semaphore): + """Semaphore that checks that # releases is <= # acquires""" + def __init__(self, value=1, verbose=None): + _Semaphore.__init__(self, value, verbose) + self._initial_value = value + + def release(self): + if self._Semaphore__value >= self._initial_value: + raise ValueError, "Semaphore released too many times" + return _Semaphore.release(self) + + +def Event(*args, **kwargs): + return _Event(*args, **kwargs) + +class _Event(_Verbose): + + # After Tim Peters' event class (without is_posted()) + + def __init__(self, verbose=None): + _Verbose.__init__(self, verbose) + self.__cond = Condition(Lock()) + self.__flag = False + + def isSet(self): + return self.__flag + + def set(self): + self.__cond.acquire() + try: + self.__flag = True + self.__cond.notifyAll() + finally: + self.__cond.release() + + def clear(self): + self.__cond.acquire() + try: + self.__flag = False + finally: + self.__cond.release() + + def wait(self, timeout=None): + self.__cond.acquire() + try: + if not self.__flag: + self.__cond.wait(timeout) + finally: + self.__cond.release() + +# Helper to generate new thread names +_counter = 0 +def _newname(template="Thread-%d"): + global _counter + _counter = _counter + 1 + return template % _counter + +# Active thread administration +_active_limbo_lock = _allocate_lock() +_active = {} +_limbo = {} + + +# Main class for threads + +class Thread(_Verbose): + + __initialized = False + # Need to store a reference to sys.exc_info for printing + # out exceptions when a thread tries to use a global var. during interp. + # shutdown and thus raises an exception about trying to perform some + # operation on/with a NoneType + __exc_info = _sys.exc_info + + def __init__(self, group=None, target=None, name=None, + args=(), kwargs={}, verbose=None): + assert group is None, "group argument must be None for now" + _Verbose.__init__(self, verbose) + self.__target = target + self.__name = str(name or _newname()) + self.__args = args + self.__kwargs = kwargs + self.__daemonic = self._set_daemon() + self.__started = False + self.__stopped = False + self.__block = Condition(Lock()) + self.__initialized = True + # sys.stderr is not stored in the class like + # sys.exc_info since it can be changed between instances + self.__stderr = _sys.stderr + + def _set_daemon(self): + # Overridden in _MainThread and _DummyThread + return currentThread().isDaemon() + + def __repr__(self): + assert self.__initialized, "Thread.__init__() was not called" + status = "initial" + if self.__started: + status = "started" + if self.__stopped: + status = "stopped" + if self.__daemonic: + status = status + " daemon" + return "<%s(%s, %s)>" % (self.__class__.__name__, self.__name, status) + + def start(self): + assert self.__initialized, "Thread.__init__() not called" + assert not self.__started, "thread already started" + if __debug__: + self._note("%s.start(): starting thread", self) + _active_limbo_lock.acquire() + _limbo[self] = self + _active_limbo_lock.release() + _start_new_thread(self.__bootstrap, ()) + self.__started = True + _sleep(0.000001) # 1 usec, to let the thread run (Solaris hack) + + def run(self): + if self.__target: + self.__target(*self.__args, **self.__kwargs) + + def __bootstrap(self): + try: + self.__started = True + _active_limbo_lock.acquire() + _active[_get_ident()] = self + del _limbo[self] + _active_limbo_lock.release() + if __debug__: + self._note("%s.__bootstrap(): thread started", self) + + if _trace_hook: + self._note("%s.__bootstrap(): registering trace hook", self) + _sys.settrace(_trace_hook) + if _profile_hook: + self._note("%s.__bootstrap(): registering profile hook", self) + _sys.setprofile(_profile_hook) + + try: + self.run() + except SystemExit: + if __debug__: + self._note("%s.__bootstrap(): raised SystemExit", self) + except: + if __debug__: + self._note("%s.__bootstrap(): unhandled exception", self) + # If sys.stderr is no more (most likely from interpreter + # shutdown) use self.__stderr. Otherwise still use sys (as in + # _sys) in case sys.stderr was redefined since the creation of + # self. + if _sys: + _sys.stderr.write("Exception in thread %s:\n%s\n" % + (self.getName(), _format_exc())) + else: + # Do the best job possible w/o a huge amt. of code to + # approximate a traceback (code ideas from + # Lib/traceback.py) + exc_type, exc_value, exc_tb = self.__exc_info() + try: + print>>self.__stderr, ( + "Exception in thread " + self.getName() + + " (most likely raised during interpreter shutdown):") + print>>self.__stderr, ( + "Traceback (most recent call last):") + while exc_tb: + print>>self.__stderr, ( + ' File "%s", line %s, in %s' % + (exc_tb.tb_frame.f_code.co_filename, + exc_tb.tb_lineno, + exc_tb.tb_frame.f_code.co_name)) + exc_tb = exc_tb.tb_next + print>>self.__stderr, ("%s: %s" % (exc_type, exc_value)) + # Make sure that exc_tb gets deleted since it is a memory + # hog; deleting everything else is just for thoroughness + finally: + del exc_type, exc_value, exc_tb + else: + if __debug__: + self._note("%s.__bootstrap(): normal return", self) + finally: + self.__stop() + try: + self.__delete() + except: + pass + + def __stop(self): + self.__block.acquire() + self.__stopped = True + self.__block.notifyAll() + self.__block.release() + + def __delete(self): + "Remove current thread from the dict of currently running threads." + + # Notes about running with dummy_thread: + # + # Must take care to not raise an exception if dummy_thread is being + # used (and thus this module is being used as an instance of + # dummy_threading). dummy_thread.get_ident() always returns -1 since + # there is only one thread if dummy_thread is being used. Thus + # len(_active) is always <= 1 here, and any Thread instance created + # overwrites the (if any) thread currently registered in _active. + # + # An instance of _MainThread is always created by 'threading'. This + # gets overwritten the instant an instance of Thread is created; both + # threads return -1 from dummy_thread.get_ident() and thus have the + # same key in the dict. So when the _MainThread instance created by + # 'threading' tries to clean itself up when atexit calls this method + # it gets a KeyError if another Thread instance was created. + # + # This all means that KeyError from trying to delete something from + # _active if dummy_threading is being used is a red herring. But + # since it isn't if dummy_threading is *not* being used then don't + # hide the exception. + + _active_limbo_lock.acquire() + try: + try: + del _active[_get_ident()] + except KeyError: + if 'dummy_threading' not in _sys.modules: + raise + finally: + _active_limbo_lock.release() + + def join(self, timeout=None): + assert self.__initialized, "Thread.__init__() not called" + assert self.__started, "cannot join thread before it is started" + assert self is not currentThread(), "cannot join current thread" + if __debug__: + if not self.__stopped: + self._note("%s.join(): waiting until thread stops", self) + self.__block.acquire() + try: + if timeout is None: + while not self.__stopped: + self.__block.wait() + if __debug__: + self._note("%s.join(): thread stopped", self) + else: + deadline = _time() + timeout + while not self.__stopped: + delay = deadline - _time() + if delay <= 0: + if __debug__: + self._note("%s.join(): timed out", self) + break + self.__block.wait(delay) + else: + if __debug__: + self._note("%s.join(): thread stopped", self) + finally: + self.__block.release() + + def getName(self): + assert self.__initialized, "Thread.__init__() not called" + return self.__name + + def setName(self, name): + assert self.__initialized, "Thread.__init__() not called" + self.__name = str(name) + + def isAlive(self): + assert self.__initialized, "Thread.__init__() not called" + return self.__started and not self.__stopped + + def isDaemon(self): + assert self.__initialized, "Thread.__init__() not called" + return self.__daemonic + + def setDaemon(self, daemonic): + assert self.__initialized, "Thread.__init__() not called" + assert not self.__started, "cannot set daemon status of active thread" + self.__daemonic = daemonic + +# The timer class was contributed by Itamar Shtull-Trauring + +def Timer(*args, **kwargs): + return _Timer(*args, **kwargs) + +class _Timer(Thread): + """Call a function after a specified number of seconds: + + t = Timer(30.0, f, args=[], kwargs={}) + t.start() + t.cancel() # stop the timer's action if it's still waiting + """ + + def __init__(self, interval, function, args=[], kwargs={}): + Thread.__init__(self) + self.interval = interval + self.function = function + self.args = args + self.kwargs = kwargs + self.finished = Event() + + def cancel(self): + """Stop the timer if it hasn't finished yet""" + self.finished.set() + + def run(self): + self.finished.wait(self.interval) + if not self.finished.isSet(): + self.function(*self.args, **self.kwargs) + self.finished.set() + +# Special thread class to represent the main thread +# This is garbage collected through an exit handler + +class _MainThread(Thread): + + def __init__(self): + Thread.__init__(self, name="MainThread") + self._Thread__started = True + _active_limbo_lock.acquire() + _active[_get_ident()] = self + _active_limbo_lock.release() + import atexit + atexit.register(self.__exitfunc) + + def _set_daemon(self): + return False + + def __exitfunc(self): + self._Thread__stop() + t = _pickSomeNonDaemonThread() + if t: + if __debug__: + self._note("%s: waiting for other threads", self) + while t: + t.join() + t = _pickSomeNonDaemonThread() + if __debug__: + self._note("%s: exiting", self) + self._Thread__delete() + +def _pickSomeNonDaemonThread(): + for t in enumerate(): + if not t.isDaemon() and t.isAlive(): + return t + return None + + +# Dummy thread class to represent threads not started here. +# These aren't garbage collected when they die, +# nor can they be waited for. +# Their purpose is to return *something* from currentThread(). +# They are marked as daemon threads so we won't wait for them +# when we exit (conform previous semantics). + +class _DummyThread(Thread): + + def __init__(self): + Thread.__init__(self, name=_newname("Dummy-%d")) + self._Thread__started = True + _active_limbo_lock.acquire() + _active[_get_ident()] = self + _active_limbo_lock.release() + + def _set_daemon(self): + return True + + def join(self, timeout=None): + assert False, "cannot join a dummy thread" + + +# Global API functions + +def currentThread(): + try: + return _active[_get_ident()] + except KeyError: + ##print "currentThread(): no current thread for", _get_ident() + return _DummyThread() + +def activeCount(): + _active_limbo_lock.acquire() + count = len(_active) + len(_limbo) + _active_limbo_lock.release() + return count + +def enumerate(): + _active_limbo_lock.acquire() + active = _active.values() + _limbo.values() + _active_limbo_lock.release() + return active + +# Create the main thread object + +_MainThread() + +# get thread-local implementation, either from the thread +# module, or from the python fallback + +try: + from thread import _local as local +except ImportError: + from _threading_local import local + + +# Self-test code + +def _test(): + + class BoundedQueue(_Verbose): + + def __init__(self, limit): + _Verbose.__init__(self) + self.mon = RLock() + self.rc = Condition(self.mon) + self.wc = Condition(self.mon) + self.limit = limit + self.queue = deque() + + def put(self, item): + self.mon.acquire() + while len(self.queue) >= self.limit: + self._note("put(%s): queue full", item) + self.wc.wait() + self.queue.append(item) + self._note("put(%s): appended, length now %d", + item, len(self.queue)) + self.rc.notify() + self.mon.release() + + def get(self): + self.mon.acquire() + while not self.queue: + self._note("get(): queue empty") + self.rc.wait() + item = self.queue.popleft() + self._note("get(): got %s, %d left", item, len(self.queue)) + self.wc.notify() + self.mon.release() + return item + + class ProducerThread(Thread): + + def __init__(self, queue, quota): + Thread.__init__(self, name="Producer") + self.queue = queue + self.quota = quota + + def run(self): + from random import random + counter = 0 + while counter < self.quota: + counter = counter + 1 + self.queue.put("%s.%d" % (self.getName(), counter)) + _sleep(random() * 0.00001) + + + class ConsumerThread(Thread): + + def __init__(self, queue, count): + Thread.__init__(self, name="Consumer") + self.queue = queue + self.count = count + + def run(self): + while self.count > 0: + item = self.queue.get() + print item + self.count = self.count - 1 + + NP = 3 + QL = 4 + NI = 5 + + Q = BoundedQueue(QL) + P = [] + for i in range(NP): + t = ProducerThread(Q, NI) + t.setName("Producer-%d" % (i+1)) + P.append(t) + C = ConsumerThread(Q, NI*NP) + for t in P: + t.start() + _sleep(0.000001) + C.start() + for t in P: + t.join() + C.join() + +if __name__ == '__main__': + _test() diff --git a/gnuradio-core/src/python/gnuradio/gr/hier_block.py b/gnuradio-core/src/python/gnuradio/gr/hier_block.py new file mode 100644 index 00000000..d669d717 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/hier_block.py @@ -0,0 +1,132 @@ +# +# 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. +# + +from gnuradio_swig_python import io_signature +import weakref + +class hier_block_base(object): + """ + Abstract base class for hierarchical signal processing blocks. + """ + def __init__(self, fg): + """ + @param fg: The flow graph that contains this hierarchical block. + @type fg: gr.flow_graph + """ + self.fg = weakref.proxy(fg) + + def input_signature(self): + """ + @return input signature of hierarchical block. + @rtype gr.io_signature + """ + raise NotImplemented + + def output_signature(self): + """ + @return output signature of hierarchical block. + @rtype gr.io_signature + """ + raise NotImplemented + + def resolve_input_port(self, port_number): + """ + @param port_number: which input port number to resolve to an endpoint. + @type port_number: int + @return: sequence of endpoints + @rtype: sequence of endpoint + + Note that an input port can resolve to more than one endpoint. + """ + raise NotImplemented + + def resolve_output_port(self, port_number): + """ + @param port_number: which output port number to resolve to an endpoint. + @type port_number: int + @return: endpoint + @rtype: endpoint + + Output ports resolve to a single endpoint. + """ + raise NotImplemented + + +class hier_block(hier_block_base): + """ + Simple concrete class for building hierarchical blocks. + + This class assumes that there is at most a single block at the + head of the chain and a single block at the end of the chain. + Either head or tail may be None indicating a sink or source respectively. + + If you needs something more elaborate than this, derive a new class from + hier_block_base. + """ + def __init__(self, fg, head_block, tail_block): + """ + @param fg: The flow graph that contains this hierarchical block. + @type fg: flow_graph + @param head_block: the first block in the signal processing chain. + @type head_block: None or subclass of gr.block or gr.hier_block_base + @param tail_block: the last block in the signal processing chain. + @type tail_block: None or subclass of gr.block or gr.hier_block_base + """ + hier_block_base.__init__(self, fg) + # FIXME add type checks here for easier debugging of misuse + self.head = head_block + self.tail = tail_block + + def input_signature(self): + if self.head: + return self.head.input_signature() + else: + return io_signature(0,0,0) + + def output_signature(self): + if self.tail: + return self.tail.output_signature() + else: + return io_signature(0,0,0) + + def resolve_input_port(self, port_number): + return ((self.head, port_number),) + + def resolve_output_port(self, port_number): + return (self.tail, port_number) + + +class compose(hier_block): + """ + Compose one or more blocks (primitive or hierarchical) into a new hierarchical block. + """ + def __init__(self, fg, *blocks): + """ + @param fg: flow graph + @type fg: gr.flow_graph + @param *blocks: list of blocks + @type *blocks: list of blocks + """ + if len(blocks) < 1: + raise ValueError, ("compose requires at least one block; none provided.") + if len(blocks) > 1: + fg.connect(*blocks) + hier_block.__init__(self, fg, blocks[0], blocks[-1]) diff --git a/gnuradio-core/src/python/gnuradio/gr/prefs.py b/gnuradio-core/src/python/gnuradio/gr/prefs.py new file mode 100644 index 00000000..fa129127 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/prefs.py @@ -0,0 +1,129 @@ +# +# 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. +# + +import gnuradio_swig_python as gsp +_prefs_base = gsp.gr_prefs + + +import ConfigParser +import os +import os.path +import sys + + +def _user_prefs_filename(): + return os.path.expanduser('~/.gnuradio/config.conf') + +def _sys_prefs_dirname(): + return os.path.join(gsp.prefix(), 'etc/gnuradio/conf.d') + +def _bool(x): + """ + Try to coerce obj to a True or False + """ + if isinstance(x, bool): + return x + if isinstance(x, (float, int)): + return bool(x) + raise TypeError, x + + +class _prefs(_prefs_base): + """ + Derive our 'real class' from the stubbed out base class that has support + for SWIG directors. This allows C++ code to magically and transparently + invoke the methods in this python class. + """ + def __init__(self): + _prefs_base.__init__(self) + self.cp = ConfigParser.RawConfigParser() + + def _sys_prefs_filenames(self): + dir = _sys_prefs_dirname() + try: + fnames = os.listdir(dir) + except (IOError, OSError): + return [] + fnames.sort() + return [os.path.join(dir, f) for f in fnames] + + + def _read_files(self): + filenames = self._sys_prefs_filenames() + filenames.append(_user_prefs_filename()) + #print "filenames: ", filenames + self.cp.read(filenames) + + def __getattr__(self, name): + return getattr(self.cp, name) + + # ---------------------------------------------------------------- + # These methods override the C++ virtual methods of the same name + # ---------------------------------------------------------------- + def has_section(self, section): + return self.cp.has_section(section) + + def has_option(self, section, option): + return self.cp.has_option(section, option) + + def get_string(self, section, option, default_val): + try: + return self.cp.get(section, option) + except: + return default_val + + def get_bool(self, section, option, default_val): + try: + return self.cp.getboolean(section, option) + except: + return default_val + + def get_long(self, section, option, default_val): + try: + return self.cp.getint(section, option) + except: + return default_val + + def get_double(self, section, option, default_val): + try: + return self.cp.getfloat(section, option) + except: + return default_val + # ---------------------------------------------------------------- + # End override of C++ virtual methods + # ---------------------------------------------------------------- + + +_prefs_db = _prefs() + +# if GR_DONT_LOAD_PREFS is set, don't load them. +# (make check uses this to avoid interactions.) +if os.getenv("GR_DONT_LOAD_PREFS", None) is None: + _prefs_db._read_files() + + +_prefs_base.set_singleton(_prefs_db) # tell C++ what instance to use + +def prefs(): + """ + Return the global preference data base + """ + return _prefs_db diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_add_and_friends.py b/gnuradio-core/src/python/gnuradio/gr/qa_add_and_friends.py new file mode 100755 index 00000000..6cb74e9f --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_add_and_friends.py @@ -0,0 +1,129 @@ +#!/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 gnuradio import gr, gr_unittest + +class test_head (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def help_ii (self, src_data, exp_data, op): + for s in zip (range (len (src_data)), src_data): + src = gr.vector_source_i (s[1]) + self.fg.connect (src, (op, s[0])) + dst = gr.vector_sink_i () + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertEqual (exp_data, result_data) + + def help_ff (self, src_data, exp_data, op): + for s in zip (range (len (src_data)), src_data): + src = gr.vector_source_f (s[1]) + self.fg.connect (src, (op, s[0])) + dst = gr.vector_sink_f () + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertEqual (exp_data, result_data) + + def help_cc (self, src_data, exp_data, op): + for s in zip (range (len (src_data)), src_data): + src = gr.vector_source_c (s[1]) + self.fg.connect (src, (op, s[0])) + dst = gr.vector_sink_c () + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertEqual (exp_data, result_data) + + def test_add_const_ii (self): + src_data = (1, 2, 3, 4, 5) + expected_result = (6, 7, 8, 9, 10) + op = gr.add_const_ii (5) + self.help_ii ((src_data,), expected_result, op) + + def test_add_const_cc (self): + src_data = (1, 2, 3, 4, 5) + expected_result = (1+5j, 2+5j, 3+5j, 4+5j, 5+5j) + op = gr.add_const_cc (5j) + self.help_cc ((src_data,), expected_result, op) + + def test_mult_const_ii (self): + src_data = (-1, 0, 1, 2, 3) + expected_result = (-5, 0, 5, 10, 15) + op = gr.multiply_const_ii (5) + self.help_ii ((src_data,), expected_result, op) + + def test_add_ii (self): + src1_data = (1, 2, 3, 4, 5) + src2_data = (8, -3, 4, 8, 2) + expected_result = (9, -1, 7, 12, 7) + op = gr.add_ii () + self.help_ii ((src1_data, src2_data), + expected_result, op) + + def test_mult_ii (self): + src1_data = (1, 2, 3, 4, 5) + src2_data = (8, -3, 4, 8, 2) + expected_result = (8, -6, 12, 32, 10) + op = gr.multiply_ii () + self.help_ii ((src1_data, src2_data), + expected_result, op) + + def test_sub_ii_1 (self): + src1_data = (1, 2, 3, 4, 5) + expected_result = (-1, -2, -3, -4, -5) + op = gr.sub_ii () + self.help_ii ((src1_data,), + expected_result, op) + + def test_sub_ii_2 (self): + src1_data = (1, 2, 3, 4, 5) + src2_data = (8, -3, 4, 8, 2) + expected_result = (-7, 5, -1, -4, 3) + op = gr.sub_ii () + self.help_ii ((src1_data, src2_data), + expected_result, op) + + def test_div_ff_1 (self): + src1_data = (1, 2, 4, -8) + expected_result = (1, 0.5, 0.25, -.125) + op = gr.divide_ff () + self.help_ff ((src1_data,), + expected_result, op) + + def test_div_ff_2 (self): + src1_data = ( 5, 9, -15, 1024) + src2_data = (10, 3, -5, 64) + expected_result = (0.5, 3, 3, 16) + op = gr.divide_ff () + self.help_ff ((src1_data, src2_data), + expected_result, op) + + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_add_v_and_friends.py b/gnuradio-core/src/python/gnuradio/gr/qa_add_v_and_friends.py new file mode 100755 index 00000000..11e69e37 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_add_v_and_friends.py @@ -0,0 +1,353 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 gnuradio import gr, gr_unittest + +class test_add_v_and_friends(gr_unittest.TestCase): + + def setUp(self): + self.fg = gr.flow_graph() + + def tearDown(self): + self.fg = None + + def help_ss(self, size, src_data, exp_data, op): + for s in zip(range (len (src_data)), src_data): + src = gr.vector_source_s(s[1]) + srcv = gr.stream_to_vector(gr.sizeof_short, size) + self.fg.connect(src, srcv) + self.fg.connect(srcv, (op, s[0])) + rhs = gr.vector_to_stream(gr.sizeof_short, size) + dst = gr.vector_sink_s() + self.fg.connect(op, rhs, dst) + self.fg.run() + result_data = dst.data() + self.assertEqual(exp_data, result_data) + + def help_ii(self, size, src_data, exp_data, op): + for s in zip(range (len (src_data)), src_data): + src = gr.vector_source_i(s[1]) + srcv = gr.stream_to_vector(gr.sizeof_int, size) + self.fg.connect(src, srcv) + self.fg.connect(srcv, (op, s[0])) + rhs = gr.vector_to_stream(gr.sizeof_int, size) + dst = gr.vector_sink_i() + self.fg.connect(op, rhs, dst) + self.fg.run() + result_data = dst.data() + self.assertEqual(exp_data, result_data) + + def help_ff(self, size, src_data, exp_data, op): + for s in zip(range (len (src_data)), src_data): + src = gr.vector_source_f(s[1]) + srcv = gr.stream_to_vector(gr.sizeof_float, size) + self.fg.connect(src, srcv) + self.fg.connect(srcv, (op, s[0])) + rhs = gr.vector_to_stream(gr.sizeof_float, size) + dst = gr.vector_sink_f() + self.fg.connect(op, rhs, dst) + self.fg.run() + result_data = dst.data() + self.assertEqual(exp_data, result_data) + + def help_cc(self, size, src_data, exp_data, op): + for s in zip(range (len (src_data)), src_data): + src = gr.vector_source_c(s[1]) + srcv = gr.stream_to_vector(gr.sizeof_gr_complex, size) + self.fg.connect(src, srcv) + self.fg.connect(srcv, (op, s[0])) + rhs = gr.vector_to_stream(gr.sizeof_gr_complex, size) + dst = gr.vector_sink_c() + self.fg.connect(op, rhs, dst) + self.fg.run() + result_data = dst.data() + self.assertEqual(exp_data, result_data) + + def help_const_ss(self, src_data, exp_data, op): + src = gr.vector_source_s(src_data) + srcv = gr.stream_to_vector(gr.sizeof_short, len(src_data)) + rhs = gr.vector_to_stream(gr.sizeof_short, len(src_data)) + dst = gr.vector_sink_s() + self.fg.connect(src, srcv, op, rhs, dst) + self.fg.run() + result_data = dst.data() + self.assertEqual(exp_data, result_data) + + def help_const_ii(self, src_data, exp_data, op): + src = gr.vector_source_i(src_data) + srcv = gr.stream_to_vector(gr.sizeof_int, len(src_data)) + rhs = gr.vector_to_stream(gr.sizeof_int, len(src_data)) + dst = gr.vector_sink_i() + self.fg.connect(src, srcv, op, rhs, dst) + self.fg.run() + result_data = dst.data() + self.assertEqual(exp_data, result_data) + + def help_const_ff(self, src_data, exp_data, op): + src = gr.vector_source_f(src_data) + srcv = gr.stream_to_vector(gr.sizeof_float, len(src_data)) + rhs = gr.vector_to_stream(gr.sizeof_float, len(src_data)) + dst = gr.vector_sink_f() + self.fg.connect(src, srcv, op, rhs, dst) + self.fg.run() + result_data = dst.data() + self.assertEqual(exp_data, result_data) + + def help_const_cc(self, src_data, exp_data, op): + src = gr.vector_source_c(src_data) + srcv = gr.stream_to_vector(gr.sizeof_gr_complex, len(src_data)) + rhs = gr.vector_to_stream(gr.sizeof_gr_complex, len(src_data)) + dst = gr.vector_sink_c() + self.fg.connect(src, srcv, op, rhs, dst) + self.fg.run() + result_data = dst.data() + self.assertEqual(exp_data, result_data) + + + def test_add_vss_one(self): + src1_data = (1,) + src2_data = (2,) + src3_data = (3,) + expected_result = (6,) + op = gr.add_vss(1) + self.help_ss(1, (src1_data, src2_data, src3_data), expected_result, op) + + def test_add_vss_five(self): + src1_data = (1, 2, 3, 4, 5) + src2_data = (6, 7, 8, 9, 10) + src3_data = (11, 12, 13, 14, 15) + expected_result = (18, 21, 24, 27, 30) + op = gr.add_vss(5) + self.help_ss(5, (src1_data, src2_data, src3_data), expected_result, op) + + def test_add_vii_one(self): + src1_data = (1,) + src2_data = (2,) + src3_data = (3,) + expected_result = (6,) + op = gr.add_vii(1) + self.help_ii(1, (src1_data, src2_data, src3_data), expected_result, op) + + def test_add_vii_five(self): + src1_data = (1, 2, 3, 4, 5) + src2_data = (6, 7, 8, 9, 10) + src3_data = (11, 12, 13, 14, 15) + expected_result = (18, 21, 24, 27, 30) + op = gr.add_vii(5) + self.help_ii(5, (src1_data, src2_data, src3_data), expected_result, op) + + def test_add_vff_one(self): + src1_data = (1.0,) + src2_data = (2.0,) + src3_data = (3.0,) + expected_result = (6.0,) + op = gr.add_vff(1) + self.help_ff(1, (src1_data, src2_data, src3_data), expected_result, op) + + def test_add_vff_five(self): + src1_data = (1.0, 2.0, 3.0, 4.0, 5.0) + src2_data = (6.0, 7.0, 8.0, 9.0, 10.0) + src3_data = (11.0, 12.0, 13.0, 14.0, 15.0) + expected_result = (18.0, 21.0, 24.0, 27.0, 30.0) + op = gr.add_vff(5) + self.help_ff(5, (src1_data, src2_data, src3_data), expected_result, op) + + def test_add_vcc_one(self): + src1_data = (1.0+2.0j,) + src2_data = (3.0+4.0j,) + src3_data = (5.0+6.0j,) + expected_result = (9.0+12j,) + op = gr.add_vcc(1) + self.help_cc(1, (src1_data, src2_data, src3_data), expected_result, op) + + def test_add_vcc_five(self): + src1_data = (1.0+2.0j, 3.0+4.0j, 5.0+6.0j, 7.0+8.0j, 9.0+10.0j) + src2_data = (11.0+12.0j, 13.0+14.0j, 15.0+16.0j, 17.0+18.0j, 19.0+20.0j) + src3_data = (21.0+22.0j, 23.0+24.0j, 25.0+26.0j, 27.0+28.0j, 29.0+30.0j) + expected_result = (33.0+36.0j, 39.0+42.0j, 45.0+48.0j, 51.0+54.0j, 57.0+60.0j) + op = gr.add_vcc(5) + self.help_cc(5, (src1_data, src2_data, src3_data), expected_result, op) + + def test_add_const_vss_one(self): + src_data = (1,) + op = gr.add_const_vss((2,)) + exp_data = (3,) + self.help_const_ss(src_data, exp_data, op) + + def test_add_const_vss_five(self): + src_data = (1, 2, 3, 4, 5) + op = gr.add_const_vss((6, 7, 8, 9, 10)) + exp_data = (7, 9, 11, 13, 15) + self.help_const_ss(src_data, exp_data, op) + + def test_add_const_vii_one(self): + src_data = (1,) + op = gr.add_const_vii((2,)) + exp_data = (3,) + self.help_const_ii(src_data, exp_data, op) + + def test_add_const_vii_five(self): + src_data = (1, 2, 3, 4, 5) + op = gr.add_const_vii((6, 7, 8, 9, 10)) + exp_data = (7, 9, 11, 13, 15) + self.help_const_ii(src_data, exp_data, op) + + def test_add_const_vff_one(self): + src_data = (1.0,) + op = gr.add_const_vff((2.0,)) + exp_data = (3.0,) + self.help_const_ff(src_data, exp_data, op) + + def test_add_const_vff_five(self): + src_data = (1.0, 2.0, 3.0, 4.0, 5.0) + op = gr.add_const_vff((6.0, 7.0, 8.0, 9.0, 10.0)) + exp_data = (7.0, 9.0, 11.0, 13.0, 15.0) + self.help_const_ff(src_data, exp_data, op) + + def test_add_const_vcc_one(self): + src_data = (1.0+2.0j,) + op = gr.add_const_vcc((2.0+3.0j,)) + exp_data = (3.0+5.0j,) + self.help_const_cc(src_data, exp_data, op) + + def test_add_const_vcc_five(self): + src_data = (1.0+2.0j, 3.0+4.0j, 5.0+6.0j, 7.0+8.0j, 9.0+10.0j) + op = gr.add_const_vcc((11.0+12.0j, 13.0+14.0j, 15.0+16.0j, 17.0+18.0j, 19.0+20.0j)) + exp_data = (12.0+14.0j, 16.0+18.0j, 20.0+22.0j, 24.0+26.0j, 28.0+30.0j) + self.help_const_cc(src_data, exp_data, op) + + + def test_multiply_vss_one(self): + src1_data = (1,) + src2_data = (2,) + src3_data = (3,) + expected_result = (6,) + op = gr.multiply_vss(1) + self.help_ss(1, (src1_data, src2_data, src3_data), expected_result, op) + + def test_multiply_vss_five(self): + src1_data = (1, 2, 3, 4, 5) + src2_data = (6, 7, 8, 9, 10) + src3_data = (11, 12, 13, 14, 15) + expected_result = (66, 168, 312, 504, 750) + op = gr.multiply_vss(5) + self.help_ss(5, (src1_data, src2_data, src3_data), expected_result, op) + + def test_multiply_vii_one(self): + src1_data = (1,) + src2_data = (2,) + src3_data = (3,) + expected_result = (6,) + op = gr.multiply_vii(1) + self.help_ii(1, (src1_data, src2_data, src3_data), expected_result, op) + + def test_multiply_vii_five(self): + src1_data = (1, 2, 3, 4, 5) + src2_data = (6, 7, 8, 9, 10) + src3_data = (11, 12, 13, 14, 15) + expected_result = (66, 168, 312, 504, 750) + op = gr.multiply_vii(5) + self.help_ii(5, (src1_data, src2_data, src3_data), expected_result, op) + + def test_multiply_vff_one(self): + src1_data = (1.0,) + src2_data = (2.0,) + src3_data = (3.0,) + expected_result = (6.0,) + op = gr.multiply_vff(1) + self.help_ff(1, (src1_data, src2_data, src3_data), expected_result, op) + + def test_multiply_vff_five(self): + src1_data = (1.0, 2.0, 3.0, 4.0, 5.0) + src2_data = (6.0, 7.0, 8.0, 9.0, 10.0) + src3_data = (11.0, 12.0, 13.0, 14.0, 15.0) + expected_result = (66.0, 168.0, 312.0, 504.0, 750.0) + op = gr.multiply_vff(5) + self.help_ff(5, (src1_data, src2_data, src3_data), expected_result, op) + + def test_multiply_vcc_one(self): + src1_data = (1.0+2.0j,) + src2_data = (3.0+4.0j,) + src3_data = (5.0+6.0j,) + expected_result = (-85+20j,) + op = gr.multiply_vcc(1) + self.help_cc(1, (src1_data, src2_data, src3_data), expected_result, op) + + def test_multiply_vcc_five(self): + src1_data = (1.0+2.0j, 3.0+4.0j, 5.0+6.0j, 7.0+8.0j, 9.0+10.0j) + src2_data = (11.0+12.0j, 13.0+14.0j, 15.0+16.0j, 17.0+18.0j, 19.0+20.0j) + src3_data = (21.0+22.0j, 23.0+24.0j, 25.0+26.0j, 27.0+28.0j, 29.0+30.0j) + expected_result = (-1021.0+428.0j, -2647.0+1754.0j, -4945.0+3704.0j, -8011.0+6374.0j, -11941.0+9860.0j) + op = gr.multiply_vcc(5) + self.help_cc(5, (src1_data, src2_data, src3_data), expected_result, op) + + def test_multiply_const_vss_one(self): + src_data = (2,) + op = gr.multiply_const_vss((3,)) + exp_data = (6,) + self.help_const_ss(src_data, exp_data, op) + + def test_multiply_const_vss_five(self): + src_data = (1, 2, 3, 4, 5) + op = gr.multiply_const_vss((6, 7, 8, 9, 10)) + exp_data = (6, 14, 24, 36, 50) + self.help_const_ss(src_data, exp_data, op) + + def test_multiply_const_vii_one(self): + src_data = (2,) + op = gr.multiply_const_vii((3,)) + exp_data = (6,) + self.help_const_ii(src_data, exp_data, op) + + def test_multiply_const_vii_five(self): + src_data = (1, 2, 3, 4, 5) + op = gr.multiply_const_vii((6, 7, 8, 9, 10)) + exp_data = (6, 14, 24, 36, 50) + self.help_const_ii(src_data, exp_data, op) + + def test_multiply_const_vff_one(self): + src_data = (2.0,) + op = gr.multiply_const_vff((3.0,)) + exp_data = (6.0,) + self.help_const_ff(src_data, exp_data, op) + + def test_multiply_const_vff_five(self): + src_data = (1.0, 2.0, 3.0, 4.0, 5.0) + op = gr.multiply_const_vff((6.0, 7.0, 8.0, 9.0, 10.0)) + exp_data = (6.0, 14.0, 24.0, 36.0, 50.0) + self.help_const_ff(src_data, exp_data, op) + + def test_multiply_const_vcc_one(self): + src_data = (1.0+2.0j,) + op = gr.multiply_const_vcc((2.0+3.0j,)) + exp_data = (-4.0+7.0j,) + self.help_const_cc(src_data, exp_data, op) + + def test_multiply_const_vcc_five(self): + src_data = (1.0+2.0j, 3.0+4.0j, 5.0+6.0j, 7.0+8.0j, 9.0+10.0j) + op = gr.multiply_const_vcc((11.0+12.0j, 13.0+14.0j, 15.0+16.0j, 17.0+18.0j, 19.0+20.0j)) + exp_data = (-13.0+34.0j, -17.0+94.0j, -21.0+170.0j, -25.0+262.0j, -29.0+370.0j) + self.help_const_cc(src_data, exp_data, op) + + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_basic_flow_graph.py b/gnuradio-core/src/python/gnuradio/gr/qa_basic_flow_graph.py new file mode 100755 index 00000000..0799c72e --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_basic_flow_graph.py @@ -0,0 +1,190 @@ +#!/usr/bin/env python + +from gnuradio import gr, gr_unittest + + +# ---------------------------------------------------------------- + + +class test_basic_flow_graph (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.basic_flow_graph () + + def tearDown (self): + self.fg = None + + def test_000_create_delete (self): + pass + + def test_001a_insert_1 (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + fg.connect (gr.endpoint (src1, 0), gr.endpoint (dst1, 0)) + + def test_001b_insert_1 (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + fg.connect (src1, gr.endpoint (dst1, 0)) + + def test_001c_insert_1 (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + fg.connect (gr.endpoint (src1, 0), dst1) + + def test_001d_insert_1 (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + fg.connect (src1, dst1) + + def test_001e_insert_1 (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + fg.connect ((src1, 0), (dst1, 0)) + + def test_002_dst_in_use (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + src2 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + fg.connect ((src1, 0), (dst1, 0)) + self.assertRaises (ValueError, + lambda : fg.connect ((src2, 0), + (dst1, 0))) + + def test_003_no_such_src_port (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + self.assertRaises (ValueError, + lambda : fg.connect ((src1, 1), + (dst1, 0))) + + def test_004_no_such_dst_port (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + self.assertRaises (ValueError, + lambda : fg.connect ((src1, 0), + (dst1, 1))) + + def test_005_one_src_two_dst (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + dst2 = gr.null_sink (gr.sizeof_int) + fg.connect ((src1, 0), (dst1, 0)) + fg.connect ((src1, 0), (dst2, 0)) + + def test_006_check_item_sizes (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_char) + self.assertRaises (ValueError, + lambda : fg.connect ((src1, 0), + (dst1, 0))) + + def test_007_validate (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + dst2 = gr.null_sink (gr.sizeof_int) + fg.connect ((src1, 0), (dst1, 0)) + fg.connect ((src1, 0), (dst2, 0)) + fg.validate () + + def test_008_validate (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + dst2 = gr.null_sink (gr.sizeof_int) + fg.connect ((src1, 0), (nop1, 0)) + fg.connect ((src1, 0), (nop1, 1)) + fg.connect ((nop1, 0), (dst1, 0)) + fg.connect ((nop1, 1), (dst2, 0)) + fg.validate () + + def test_009_validate (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + dst2 = gr.null_sink (gr.sizeof_int) + fg.connect ((src1, 0), (nop1, 0)) + fg.connect ((src1, 0), (nop1, 2)) + fg.connect ((nop1, 0), (dst1, 0)) + fg.connect ((nop1, 1), (dst2, 0)) + self.assertRaises (ValueError, + lambda : fg.validate ()) + + + def test_010_validate (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + dst2 = gr.null_sink (gr.sizeof_int) + fg.connect ((src1, 0), (nop1, 0)) + fg.connect ((src1, 0), (nop1, 1)) + fg.connect ((nop1, 0), (dst1, 0)) + fg.connect ((nop1, 2), (dst2, 0)) + self.assertRaises (ValueError, + lambda : fg.validate ()) + + + def test_011_disconnect (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + dst2 = gr.null_sink (gr.sizeof_int) + fg.connect ((src1, 0), (nop1, 0)) + fg.connect ((src1, 0), (nop1, 1)) + fg.connect ((nop1, 0), (dst1, 0)) + fg.connect ((nop1, 1), (dst2, 0)) + fg.validate () + fg.disconnect ((src1, 0), (nop1, 1)) + fg.validate () + self.assertRaises (ValueError, + lambda : fg.disconnect ((src1, 0), + (nop1, 1))) + + def test_012_connect (self): + fg = self.fg + src_data = (0, 1, 2, 3) + expected_result = (2, 3, 4, 5) + src1 = gr.vector_source_i (src_data) + op = gr.add_const_ii (2) + dst1 = gr.vector_sink_i () + fg.connect (src1, op) + fg.connect (op, dst1) + # print "edge_list:", fg.edge_list + fg.validate () + + def test_013_connect_varargs (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + self.assertRaises (ValueError, + lambda : fg.connect ()) + self.assertRaises (ValueError, + lambda : fg.connect (src1)) + + def test_014_connect_varargs (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + fg.connect (src1, nop1, dst1) + fg.validate () + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_cma_equalizer.py b/gnuradio-core/src/python/gnuradio/gr/qa_cma_equalizer.py new file mode 100755 index 00000000..6b3e9aa9 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_cma_equalizer.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python + +from gnuradio import gr, gr_unittest + +class test_cma_equalizer_fir(gr_unittest.TestCase): + + def setUp(self): + self.fg = gr.flow_graph() + + def tearDown(self): + self.fg = None + + def transform(self, src_data): + SRC = gr.vector_source_c(src_data, False) + EQU = gr.cma_equalizer_cc(4, 1.0, .001) + DST = gr.vector_sink_c() + self.fg.connect(SRC, EQU, DST) + self.fg.run() + return DST.data() + + def test_001_identity(self): + # Constant modulus signal so no adjustments + src_data = (1+0j, 0+1j, -1+0j, 0-1j)*1000 + expected_data = src_data + result = self.transform(src_data) + self.assertComplexTuplesAlmostEqual(expected_data, result) + +if __name__ == "__main__": + gr_unittest.main() \ No newline at end of file diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_complex_to_xxx.py b/gnuradio-core/src/python/gnuradio/gr/qa_complex_to_xxx.py new file mode 100755 index 00000000..4bc19335 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_complex_to_xxx.py @@ -0,0 +1,116 @@ +#!/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 gnuradio import gr, gr_unittest +import math + +class test_complex_ops (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_complex_to_float_1 (self): + src_data = (0, 1, -1, 3+4j, -3-4j, -3+4j) + expected_result = (0, 1, -1, 3, -3, -3) + src = gr.vector_source_c (src_data) + op = gr.complex_to_float () + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () # run the graph and wait for it to finish + actual_result = dst.data () # fetch the contents of the sink + self.assertFloatTuplesAlmostEqual (expected_result, actual_result) + + def test_complex_to_float_2 (self): + src_data = (0, 1, -1, 3+4j, -3-4j, -3+4j) + expected_result0 = (0, 1, -1, 3, -3, -3) + expected_result1 = (0, 0, 0, 4, -4, 4) + src = gr.vector_source_c (src_data) + op = gr.complex_to_float () + dst0 = gr.vector_sink_f () + dst1 = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect ((op, 0), dst0) + self.fg.connect ((op, 1), dst1) + self.fg.run () + actual_result = dst0.data () + self.assertFloatTuplesAlmostEqual (expected_result0, actual_result) + actual_result = dst1.data () + self.assertFloatTuplesAlmostEqual (expected_result1, actual_result) + + def test_complex_to_real (self): + src_data = (0, 1, -1, 3+4j, -3-4j, -3+4j) + expected_result = (0, 1, -1, 3, -3, -3) + src = gr.vector_source_c (src_data) + op = gr.complex_to_real () + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + actual_result = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, actual_result) + + def test_complex_to_imag (self): + src_data = (0, 1, -1, 3+4j, -3-4j, -3+4j) + expected_result = (0, 0, 0, 4, -4, 4) + src = gr.vector_source_c (src_data) + op = gr.complex_to_imag () + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + actual_result = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, actual_result,5) + + def test_complex_to_mag (self): + src_data = (0, 1, -1, 3+4j, -3-4j, -3+4j) + expected_result = (0, 1, 1, 5, 5, 5) + src = gr.vector_source_c (src_data) + op = gr.complex_to_mag () + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + actual_result = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, actual_result,5) + + def test_complex_to_arg (self): + pi = math.pi + expected_result = (0, pi/6, pi/4, pi/2, 3*pi/4, 7*pi/8, + -pi/6, -pi/4, -pi/2, -3*pi/4, -7*pi/8) + src_data = tuple ([math.cos (x) + math.sin (x) * 1j for x in expected_result]) + src = gr.vector_source_c (src_data) + op = gr.complex_to_arg () + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + actual_result = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, actual_result, 5) + + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_constellation_decoder_cb.py b/gnuradio-core/src/python/gnuradio/gr/qa_constellation_decoder_cb.py new file mode 100755 index 00000000..95641222 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_constellation_decoder_cb.py @@ -0,0 +1,53 @@ +#!/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 gnuradio import gr, gr_unittest +import math + +class test_head (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_constellation_decoder_cb (self): + symbol_positions = [1 + 0j, 0 + 1j , -1 + 0j, 0 - 1j] + symbol_values_out = [0, 1, 2, 3] + expected_result = ( 0, 3, 2, 1, 0, 0, 3) + src_data = (0.5 + 0j, 0.1 - 1.2j, -0.8 - 0.1j, -0.45 + 0.8j, 0.8 - 0j, 0.5 + 0j, 0.1 - 1.2j) + src = gr.vector_source_c (src_data) + op = gr.constellation_decoder_cb (symbol_positions, symbol_values_out) + dst = gr.vector_sink_b () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () # run the graph and wait for it to finish + actual_result = dst.data () # fetch the contents of the sink + #print "actual result", actual_result + #print "expected result", expected_result + self.assertFloatTuplesAlmostEqual (expected_result, actual_result) + + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_correlate_access_code.py b/gnuradio-core/src/python/gnuradio/gr/qa_correlate_access_code.py new file mode 100755 index 00000000..89b4909e --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_correlate_access_code.py @@ -0,0 +1,83 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 gnuradio import gr, gr_unittest +import math + +default_access_code = '\xAC\xDD\xA4\xE2\xF2\x8C\x20\xFC' + +def string_to_1_0_list(s): + r = [] + for ch in s: + x = ord(ch) + for i in range(8): + t = (x >> i) & 0x1 + r.append(t) + + return r + +def to_1_0_string(L): + return ''.join(map(lambda x: chr(x + ord('0')), L)) + +class test_correlate_access_code(gr_unittest.TestCase): + + def setUp(self): + self.fg = gr.flow_graph() + + def tearDown(self): + self.fg = None + + def test_001(self): + pad = (0,) * 64 + # 0 0 0 1 0 0 0 1 + src_data = (1, 0, 1, 1, 1, 1, 0, 1, 1) + pad + (0,) * 7 + expected_result = pad + (1, 0, 1, 1, 3, 1, 0, 1, 1, 2) + (0,) * 6 + src = gr.vector_source_b (src_data) + op = gr.correlate_access_code_bb("1011", 0) + dst = gr.vector_sink_b () + self.fg.connect (src, op, dst) + self.fg.run () + result_data = dst.data () + self.assertEqual (expected_result, result_data) + + + def test_002(self): + code = tuple(string_to_1_0_list(default_access_code)) + access_code = to_1_0_string(code) + pad = (0,) * 64 + #print code + #print access_code + src_data = code + (1, 0, 1, 1) + pad + expected_result = pad + code + (3, 0, 1, 1) + src = gr.vector_source_b (src_data) + op = gr.correlate_access_code_bb(access_code, 0) + dst = gr.vector_sink_b () + self.fg.connect (src, op, dst) + self.fg.run () + result_data = dst.data () + self.assertEqual (expected_result, result_data) + + + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_diff_encoder.py b/gnuradio-core/src/python/gnuradio/gr/qa_diff_encoder.py new file mode 100755 index 00000000..44840709 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_diff_encoder.py @@ -0,0 +1,86 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 gnuradio import gr, gr_unittest +import math +import random + +def make_random_int_tuple(L, min, max): + result = [] + for x in range(L): + result.append(random.randint(min, max)) + return tuple(result) + + +class test_encoder (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_diff_encdec_000(self): + random.seed(0) + modulus = 2 + src_data = make_random_int_tuple(1000, 0, modulus-1) + expected_result = src_data + src = gr.vector_source_b(src_data) + enc = gr.diff_encoder_bb(modulus) + dec = gr.diff_decoder_bb(modulus) + dst = gr.vector_sink_b() + self.fg.connect(src, enc, dec, dst) + self.fg.run() # run the graph and wait for it to finish + actual_result = dst.data() # fetch the contents of the sink + self.assertEqual(expected_result, actual_result) + + def test_diff_encdec_001(self): + random.seed(0) + modulus = 4 + src_data = make_random_int_tuple(1000, 0, modulus-1) + expected_result = src_data + src = gr.vector_source_b(src_data) + enc = gr.diff_encoder_bb(modulus) + dec = gr.diff_decoder_bb(modulus) + dst = gr.vector_sink_b() + self.fg.connect(src, enc, dec, dst) + self.fg.run() # run the graph and wait for it to finish + actual_result = dst.data() # fetch the contents of the sink + self.assertEqual(expected_result, actual_result) + + def test_diff_encdec_002(self): + random.seed(0) + modulus = 8 + src_data = make_random_int_tuple(40000, 0, modulus-1) + expected_result = src_data + src = gr.vector_source_b(src_data) + enc = gr.diff_encoder_bb(modulus) + dec = gr.diff_decoder_bb(modulus) + dst = gr.vector_sink_b() + self.fg.connect(src, enc, dec, dst) + self.fg.run() # run the graph and wait for it to finish + actual_result = dst.data() # fetch the contents of the sink + self.assertEqual(expected_result, actual_result) + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_diff_phasor_cc.py b/gnuradio-core/src/python/gnuradio/gr/qa_diff_phasor_cc.py new file mode 100755 index 00000000..0b716020 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_diff_phasor_cc.py @@ -0,0 +1,50 @@ +#!/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 gnuradio import gr, gr_unittest +import math + +class test_complex_ops (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_diff_phasor_cc (self): + src_data = (0+0j, 1+0j, -1+0j, 3+4j, -3-4j, -3+4j) + expected_result = (0+0j, 0+0j, -1+0j, -3-4j, -25+0j, -7-24j) + src = gr.vector_source_c (src_data) + op = gr.diff_phasor_cc () + dst = gr.vector_sink_c () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () # run the graph and wait for it to finish + actual_result = dst.data () # fetch the contents of the sink + self.assertComplexTuplesAlmostEqual (expected_result, actual_result) + + + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_feval.py b/gnuradio-core/src/python/gnuradio/gr/qa_feval.py new file mode 100755 index 00000000..1de49369 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_feval.py @@ -0,0 +1,92 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 gnuradio import gr, gr_unittest + +class my_add2_dd(gr.feval_dd): + def eval(self, x): + return x + 2 + +class my_add2_ll(gr.feval_ll): + def eval(self, x): + return x + 2 + +class my_add2_cc(gr.feval_cc): + def eval(self, x): + return x + (2 - 2j) + + +class test_feval(gr_unittest.TestCase): + + def test_dd_1(self): + f = my_add2_dd() + src_data = (0.0, 1.0, 2.0, 3.0, 4.0) + expected_result = (2.0, 3.0, 4.0, 5.0, 6.0) + # this is all in python... + actual_result = tuple([f.eval(x) for x in src_data]) + self.assertEqual(expected_result, actual_result) + + def test_dd_2(self): + f = my_add2_dd() + src_data = (0.0, 1.0, 2.0, 3.0, 4.0) + expected_result = (2.0, 3.0, 4.0, 5.0, 6.0) + # this is python -> C++ -> python and back again... + actual_result = tuple([gr.feval_dd_example(f, x) for x in src_data]) + self.assertEqual(expected_result, actual_result) + + + def test_ll_1(self): + f = my_add2_ll() + src_data = (0, 1, 2, 3, 4) + expected_result = (2, 3, 4, 5, 6) + # this is all in python... + actual_result = tuple([f.eval(x) for x in src_data]) + self.assertEqual(expected_result, actual_result) + + def test_ll_2(self): + f = my_add2_ll() + src_data = (0, 1, 2, 3, 4) + expected_result = (2, 3, 4, 5, 6) + # this is python -> C++ -> python and back again... + actual_result = tuple([gr.feval_ll_example(f, x) for x in src_data]) + self.assertEqual(expected_result, actual_result) + + + def test_cc_1(self): + f = my_add2_cc() + src_data = (0+1j, 2+3j, 4+5j, 6+7j) + expected_result = (2-1j, 4+1j, 6+3j, 8+5j) + # this is all in python... + actual_result = tuple([f.eval(x) for x in src_data]) + self.assertEqual(expected_result, actual_result) + + def test_cc_2(self): + f = my_add2_cc() + src_data = (0+1j, 2+3j, 4+5j, 6+7j) + expected_result = (2-1j, 4+1j, 6+3j, 8+5j) + # this is python -> C++ -> python and back again... + actual_result = tuple([gr.feval_cc_example(f, x) for x in src_data]) + self.assertEqual(expected_result, actual_result) + + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_fft_filter.py b/gnuradio-core/src/python/gnuradio/gr/qa_fft_filter.py new file mode 100755 index 00000000..cb2e76b1 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_fft_filter.py @@ -0,0 +1,268 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr, gr_unittest +import sys +import random + +def make_random_complex_tuple(L): + result = [] + for x in range(L): + result.append(complex(random.uniform(-1000,1000), + random.uniform(-1000,1000))) + return tuple(result) + +def make_random_float_tuple(L): + result = [] + for x in range(L): + result.append(float(int(random.uniform(-1000,1000)))) + return tuple(result) + + +def reference_filter_ccc(dec, taps, input): + """ + compute result using conventional fir filter + """ + fg = gr.flow_graph() + #src = gr.vector_source_c(((0,) * (len(taps) - 1)) + input) + src = gr.vector_source_c(input) + op = gr.fir_filter_ccc(dec, taps) + dst = gr.vector_sink_c() + fg.connect(src, op, dst) + fg.run() + return dst.data() + +def reference_filter_fff(dec, taps, input): + """ + compute result using conventional fir filter + """ + fg = gr.flow_graph() + #src = gr.vector_source_f(((0,) * (len(taps) - 1)) + input) + src = gr.vector_source_f(input) + op = gr.fir_filter_fff(dec, taps) + dst = gr.vector_sink_f() + fg.connect(src, op, dst) + fg.run() + return dst.data() + + +def print_complex(x): + for i in x: + i = complex(i) + sys.stdout.write("(%6.3f,%6.3fj), " % (i.real, i.imag)) + sys.stdout.write('\n') + + +class test_fft_filter(gr_unittest.TestCase): + + def setUp(self): + self.fg = gr.flow_graph () + + def tearDown(self): + self.fg = None + + def assert_fft_ok2(self, expected_result, result_data): + expected_result = expected_result[:len(result_data)] + self.assertComplexTuplesAlmostEqual2 (expected_result, result_data, + abs_eps=1e-9, rel_eps=4e-4) + + def assert_fft_float_ok2(self, expected_result, result_data, abs_eps=1e-9, rel_eps=4e-4): + expected_result = expected_result[:len(result_data)] + self.assertFloatTuplesAlmostEqual2 (expected_result, result_data, + abs_eps, rel_eps) + + #def test_ccc_000(self): + # self.assertRaises (RuntimeError, gr.fft_filter_ccc, 2, (1,)) + + def test_ccc_001(self): + src_data = (0,1,2,3,4,5,6,7) + taps = (1,) + expected_result = tuple([complex(x) for x in (0,1,2,3,4,5,6,7)]) + src = gr.vector_source_c(src_data) + op = gr.fft_filter_ccc(1, taps) + dst = gr.vector_sink_c() + self.fg.connect(src, op, dst) + self.fg.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + + + def test_ccc_002(self): + src_data = (0,1,2,3,4,5,6,7) + taps = (2,) + expected_result = tuple([2 * complex(x) for x in (0,1,2,3,4,5,6,7)]) + src = gr.vector_source_c(src_data) + op = gr.fft_filter_ccc(1, taps) + dst = gr.vector_sink_c() + self.fg.connect(src, op, dst) + self.fg.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + + def test_ccc_004(self): + random.seed(0) + for i in xrange(25): + # sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + src_len = 4*1024 + src_data = make_random_complex_tuple(src_len) + ntaps = int(random.uniform(2, 1000)) + taps = make_random_complex_tuple(ntaps) + expected_result = reference_filter_ccc(1, taps, src_data) + + src = gr.vector_source_c(src_data) + op = gr.fft_filter_ccc(1, taps) + dst = gr.vector_sink_c() + self.fg.connect(src, op, dst) + self.fg.run() + result_data = dst.data() + + self.assert_fft_ok2(expected_result, result_data) + + def test_ccc_005(self): + random.seed(0) + for i in xrange(25): + # sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + dec = i + 1 + src_len = 4*1024 + src_data = make_random_complex_tuple(src_len) + ntaps = int(random.uniform(2, 100)) + taps = make_random_complex_tuple(ntaps) + expected_result = reference_filter_ccc(dec, taps, src_data) + + src = gr.vector_source_c(src_data) + op = gr.fft_filter_ccc(dec, taps) + dst = gr.vector_sink_c() + self.fg.connect(src, op, dst) + self.fg.run() + result_data = dst.data() + + self.assert_fft_ok2(expected_result, result_data) + + # ---------------------------------------------------------------- + # test _fff version + # ---------------------------------------------------------------- + + def test_fff_001(self): + src_data = (0,1,2,3,4,5,6,7) + taps = (1,) + expected_result = tuple([float(x) for x in (0,1,2,3,4,5,6,7)]) + src = gr.vector_source_f(src_data) + op = gr.fft_filter_fff(1, taps) + dst = gr.vector_sink_f() + self.fg.connect(src, op, dst) + self.fg.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + self.assertFloatTuplesAlmostEqual (expected_result, result_data, 5) + + + def test_fff_002(self): + src_data = (0,1,2,3,4,5,6,7) + taps = (2,) + expected_result = tuple([2 * float(x) for x in (0,1,2,3,4,5,6,7)]) + src = gr.vector_source_f(src_data) + op = gr.fft_filter_fff(1, taps) + dst = gr.vector_sink_f() + self.fg.connect(src, op, dst) + self.fg.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + self.assertFloatTuplesAlmostEqual (expected_result, result_data, 5) + + def xtest_fff_003(self): + random.seed(0) + for i in xrange(25): + sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + src_len = 4096 + src_data = make_random_float_tuple(src_len) + ntaps = int(random.uniform(2, 1000)) + taps = make_random_float_tuple(ntaps) + expected_result = reference_filter_fff(1, taps, src_data) + + src = gr.vector_source_f(src_data) + op = gr.fft_filter_fff(1, taps) + dst = gr.vector_sink_f() + self.fg.connect(src, op, dst) + self.fg.run() + result_data = dst.data() + + #print "src_len =", src_len, " ntaps =", ntaps + try: + self.assert_fft_float_ok2(expected_result, result_data, abs_eps=1.0) + except: + expected = open('expected', 'w') + for x in expected_result: + expected.write(`x` + '\n') + actual = open('actual', 'w') + for x in result_data: + actual.write(`x` + '\n') + raise + + def xtest_fff_004(self): + random.seed(0) + for i in xrange(25): + sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + src_len = 4*1024 + src_data = make_random_float_tuple(src_len) + ntaps = int(random.uniform(2, 1000)) + taps = make_random_float_tuple(ntaps) + expected_result = reference_filter_fff(1, taps, src_data) + + src = gr.vector_source_f(src_data) + op = gr.fft_filter_fff(1, taps) + dst = gr.vector_sink_f() + self.fg.connect(src, op, dst) + self.fg.run() + result_data = dst.data() + + self.assert_fft_float_ok2(expected_result, result_data, abs_eps=2.0) + + def xtest_fff_005(self): + random.seed(0) + for i in xrange(25): + sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + dec = i + 1 + src_len = 4*1024 + src_data = make_random_float_tuple(src_len) + ntaps = int(random.uniform(2, 100)) + taps = make_random_float_tuple(ntaps) + expected_result = reference_filter_fff(dec, taps, src_data) + + src = gr.vector_source_f(src_data) + op = gr.fft_filter_fff(dec, taps) + dst = gr.vector_sink_f() + self.fg.connect(src, op, dst) + self.fg.run() + result_data = dst.data() + + self.assert_fft_float_ok2(expected_result, result_data) + + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_filter_delay_fc.py b/gnuradio-core/src/python/gnuradio/gr/qa_filter_delay_fc.py new file mode 100755 index 00000000..191552ca --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_filter_delay_fc.py @@ -0,0 +1,317 @@ +#!/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 gnuradio import gr, gr_unittest +import math + +class qa_filter_delay_fc (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_001_filter_delay_one_input (self): + + # expected result + expected_result = ( -1.4678005338941702e-11j, + -0.0011950774351134896j, + -0.0019336787518113852j, + -0.0034673355985432863j, + -0.0036765895783901215j, + -0.004916108213365078j, + -0.0042778430506587029j, + -0.006028641015291214j, + -0.005476709920912981j, + -0.0092810001224279404j, + -0.0095402700826525688j, + -0.016060983762145042j, + -0.016446959227323532j, + -0.02523401565849781j, + -0.024382550269365311j, + -0.035477779805660248j, + -0.033021725714206696j, + -0.048487484455108643j, + -0.04543270543217659j, + -0.069477587938308716j, + -0.066984444856643677j, + -0.10703597217798233j, + -0.10620346665382385j, + -0.1852707713842392j, + -0.19357112050056458j, + (7.2191945754696007e-09 -0.50004088878631592j), + (0.58778399229049683 -0.6155126690864563j), + (0.95105588436126709 -0.12377222627401352j), + (0.95105588436126709 +0.41524654626846313j), + (0.5877838134765625 +0.91611981391906738j), + (5.8516356205018383e-09 +1.0670661926269531j), + (-0.5877840518951416 +0.87856143712997437j), + (-0.95105588436126709 +0.35447561740875244j), + (-0.95105588436126709 -0.26055556535720825j), + (-0.5877838134765625 -0.77606213092803955j), + (-8.7774534307527574e-09 -0.96460390090942383j), + (0.58778399229049683 -0.78470128774642944j), + (0.95105588436126709 -0.28380891680717468j), + (0.95105588436126709 +0.32548999786376953j), + (0.5877838134765625 +0.82514488697052002j), + (1.4629089051254596e-08 +1.0096219778060913j), + (-0.5877840518951416 +0.81836479902267456j), + (-0.95105588436126709 +0.31451958417892456j), + (-0.95105588436126709 -0.3030143678188324j), + (-0.5877838134765625 -0.80480599403381348j), + (-1.7554906861505515e-08 -0.99516552686691284j), + (0.58778399229049683 -0.80540722608566284j), + (0.95105582475662231 -0.30557557940483093j), + (0.95105588436126709 +0.31097668409347534j), + (0.5877838134765625 +0.81027895212173462j), + (2.3406542482007353e-08 +1.0000816583633423j), + (-0.5877840518951416 +0.80908381938934326j), + (-0.95105588436126709 +0.30904293060302734j), + (-0.95105588436126709 -0.30904296040534973j), + (-0.5877838134765625 -0.80908387899398804j), + (-2.6332360292258272e-08 -1.0000815391540527j), + (0.58778399229049683 -0.80908381938934326j), + (0.95105582475662231 -0.30904299020767212j), + (0.95105588436126709 +0.30904293060302734j), + (0.5877838134765625 +0.80908381938934326j), + (3.218399768911695e-08 +1.0000815391540527j)) + + fg = self.fg + + sampling_freq = 100 + + ntaps = 51 + src1 = gr.sig_source_f (sampling_freq, gr.GR_SIN_WAVE, + sampling_freq * 0.10, 1.0) + head = gr.head (gr.sizeof_float, int (ntaps + sampling_freq * 0.10)) + dst2 = gr.vector_sink_c () + + # calculate taps + taps = gr.firdes_hilbert (ntaps) + hd = gr.filter_delay_fc (taps) + + fg.connect (src1, head) + fg.connect (head, hd) + fg.connect (hd,dst2) + + fg.run () + + # get output + result_data = dst2.data () + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + + def test_002_filter_delay_two_inputs (self): + + # giving the same signal to both the inputs should fetch the same results + # as above + + # expected result + expected_result = ( -1.4678005338941702e-11j, + -0.0011950774351134896j, + -0.0019336787518113852j, + -0.0034673355985432863j, + -0.0036765895783901215j, + -0.004916108213365078j, + -0.0042778430506587029j, + -0.006028641015291214j, + -0.005476709920912981j, + -0.0092810001224279404j, + -0.0095402700826525688j, + -0.016060983762145042j, + -0.016446959227323532j, + -0.02523401565849781j, + -0.024382550269365311j, + -0.035477779805660248j, + -0.033021725714206696j, + -0.048487484455108643j, + -0.04543270543217659j, + -0.069477587938308716j, + -0.066984444856643677j, + -0.10703597217798233j, + -0.10620346665382385j, + -0.1852707713842392j, + -0.19357112050056458j, + (7.2191945754696007e-09 -0.50004088878631592j), + (0.58778399229049683 -0.6155126690864563j), + (0.95105588436126709 -0.12377222627401352j), + (0.95105588436126709 +0.41524654626846313j), + (0.5877838134765625 +0.91611981391906738j), + (5.8516356205018383e-09 +1.0670661926269531j), + (-0.5877840518951416 +0.87856143712997437j), + (-0.95105588436126709 +0.35447561740875244j), + (-0.95105588436126709 -0.26055556535720825j), + (-0.5877838134765625 -0.77606213092803955j), + (-8.7774534307527574e-09 -0.96460390090942383j), + (0.58778399229049683 -0.78470128774642944j), + (0.95105588436126709 -0.28380891680717468j), + (0.95105588436126709 +0.32548999786376953j), + (0.5877838134765625 +0.82514488697052002j), + (1.4629089051254596e-08 +1.0096219778060913j), + (-0.5877840518951416 +0.81836479902267456j), + (-0.95105588436126709 +0.31451958417892456j), + (-0.95105588436126709 -0.3030143678188324j), + (-0.5877838134765625 -0.80480599403381348j), + (-1.7554906861505515e-08 -0.99516552686691284j), + (0.58778399229049683 -0.80540722608566284j), + (0.95105582475662231 -0.30557557940483093j), + (0.95105588436126709 +0.31097668409347534j), + (0.5877838134765625 +0.81027895212173462j), + (2.3406542482007353e-08 +1.0000816583633423j), + (-0.5877840518951416 +0.80908381938934326j), + (-0.95105588436126709 +0.30904293060302734j), + (-0.95105588436126709 -0.30904296040534973j), + (-0.5877838134765625 -0.80908387899398804j), + (-2.6332360292258272e-08 -1.0000815391540527j), + (0.58778399229049683 -0.80908381938934326j), + (0.95105582475662231 -0.30904299020767212j), + (0.95105588436126709 +0.30904293060302734j), + (0.5877838134765625 +0.80908381938934326j), + (3.218399768911695e-08 +1.0000815391540527j)) + + + fg = self.fg + + sampling_freq = 100 + ntaps = 51 + src1 = gr.sig_source_f (sampling_freq, gr.GR_SIN_WAVE, + sampling_freq * 0.10, 1.0) + head = gr.head (gr.sizeof_float, int (ntaps + sampling_freq * 0.10)) + dst2 = gr.vector_sink_c () + + + # calculate taps + taps = gr.firdes_hilbert (ntaps) + hd = gr.filter_delay_fc (taps) + + fg.connect (src1, head) + fg.connect (head, (hd,0)) + fg.connect (head, (hd,1)) + fg.connect (hd,dst2) + fg.run () + + # get output + result_data = dst2.data () + + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + + + def test_003_filter_delay_two_inputs (self): + + # give two different inputs + + # expected result + expected_result = ( -0.0020331963896751404j, + -0.0016448829555884004j, + -0.0032375147566199303j, + -0.0014826074475422502j, + -0.0033034090884029865j, + -0.00051144487224519253j, + -0.0043686260469257832j, + -0.0010198024101555347j, + -0.0082517862319946289j, + -0.003456643782556057j, + -0.014193611219525337j, + -0.005875137634575367j, + -0.020293503999710083j, + -0.0067503536120057106j, + -0.026798896491527557j, + -0.0073488112539052963j, + -0.037041611969470978j, + -0.010557252913713455j, + -0.055669989436864853j, + -0.018332764506340027j, + -0.089904911816120148j, + -0.033361352980136871j, + -0.16902604699134827j, + -0.074318811297416687j, + -0.58429563045501709j, + (7.2191945754696007e-09 -0.35892376303672791j), + (0.58778399229049683 +0.63660913705825806j), + (0.95105588436126709 +0.87681591510772705j), + (0.95105588436126709 +0.98705857992172241j), + (0.5877838134765625 +0.55447429418563843j), + (5.8516356205018383e-09 +0.026006083935499191j), + (-0.5877840518951416 -0.60616838932037354j), + (-0.95105588436126709 -0.9311758279800415j), + (-0.95105588436126709 -0.96169203519821167j), + (-0.5877838134765625 -0.57292771339416504j), + (-8.7774534307527574e-09 -0.0073488391935825348j), + (0.58778399229049683 +0.59720659255981445j), + (0.95105588436126709 +0.94438445568084717j), + (0.95105588436126709 +0.95582199096679688j), + (0.5877838134765625 +0.58196049928665161j), + (1.4629089051254596e-08 +0.0026587247848510742j), + (-0.5877840518951416 -0.59129220247268677j), + (-0.95105588436126709 -0.94841635227203369j), + (-0.95105588436126709 -0.95215457677841187j), + (-0.5877838134765625 -0.58535969257354736j), + (-1.7554906861505515e-08 -0.00051158666610717773j), + (0.58778399229049683 +0.58867418766021729j), + (0.95105582475662231 +0.94965213537216187j), + (0.95105588436126709 +0.95050644874572754j), + (0.5877838134765625 +0.58619076013565063j), + (2.3406542482007353e-08 +1.1920928955078125e-07j), + (-0.5877840518951416 -0.58783555030822754j), + (-0.95105588436126709 -0.95113480091094971j), + (-0.95105588436126709 -0.95113474130630493j), + (-0.5877838134765625 -0.58783555030822754j), + (-2.6332360292258272e-08 -8.1956386566162109e-08j), + (0.58778399229049683 +0.58783555030822754j), + (0.95105582475662231 +0.95113474130630493j), + (0.95105588436126709 +0.95113474130630493j), + (0.5877838134765625 +0.58783560991287231j), + (3.218399768911695e-08 +1.1920928955078125e-07j)) + + fg = self.fg + + sampling_freq = 100 + ntaps = 51 + + src1 = gr.sig_source_f (sampling_freq, gr.GR_SIN_WAVE,sampling_freq * 0.10, 1.0) + src2 = gr.sig_source_f (sampling_freq, gr.GR_COS_WAVE,sampling_freq * 0.10, 1.0) + + head1 = gr.head (gr.sizeof_float, int (ntaps + sampling_freq * 0.10)) + head2 = gr.head (gr.sizeof_float, int (ntaps + sampling_freq * 0.10)) + + taps = gr.firdes_hilbert (ntaps) + hd = gr.filter_delay_fc (taps) + + dst2 = gr.vector_sink_c () + + fg.connect (src1, head1) + fg.connect (src2, head2) + + fg.connect (head1, (hd,0)) + fg.connect (head2, (hd,1)) + fg.connect (hd, dst2) + + fg.run () + + # get output + result_data = dst2.data () + + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_flow_graph.py b/gnuradio-core/src/python/gnuradio/gr/qa_flow_graph.py new file mode 100755 index 00000000..455cc135 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_flow_graph.py @@ -0,0 +1,356 @@ +#!/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 gnuradio import gr, gr_unittest +import qa_basic_flow_graph + + +def all_counts (): + return (gr.block_ncurrently_allocated (), + gr.block_detail_ncurrently_allocated (), + gr.buffer_ncurrently_allocated (), + gr.buffer_reader_ncurrently_allocated ()) + + +class wrap_add(gr.hier_block): + def __init__(self, fg, a): + add = gr.add_const_ii (a) + gr.hier_block.__init__ (self, fg, add, add) + +class mult_add(gr.hier_block): + def __init__(self, fg, m, a): + mult = gr.multiply_const_ii (m) + add = gr.add_const_ii (a) + fg.connect (mult, add) + gr.hier_block.__init__ (self, fg, mult, add) + + +class test_flow_graph (qa_basic_flow_graph.test_basic_flow_graph): + + def setUp (self): + ''' override qa_basic_flow_graph setUp in order to use our class''' + self.fg = gr.flow_graph () + + def tearDown (self): + qa_basic_flow_graph.test_basic_flow_graph.tearDown (self) + + + # we inherit all their tests, so we can be sure we don't break + # any of the underlying code + + + def leak_check (self, fct): + begin = all_counts () + fct () + # tear down early so we can check for leaks + self.tearDown () + end = all_counts () + self.assertEqual (begin, end) + + def test_100_tsort_null (self): + self.assertEqual ([], self.fg.topological_sort (self.fg.all_blocks ())) + + def test_101_tsort_two (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + fg.connect ((src1, 0), (dst1, 0)) + fg.validate () + self.assertEqual ([src1, dst1], fg.topological_sort (fg.all_blocks ())) + + def test_102_tsort_three_a (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + fg.connect (src1, nop1) + fg.connect (nop1, dst1) + fg.validate () + self.assertEqual ([src1, nop1, dst1], fg.topological_sort (fg.all_blocks ())) + + def test_103_tsort_three_b (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + fg.connect (nop1, dst1) + fg.connect (src1, nop1) + fg.validate () + self.assertEqual ([src1, nop1, dst1], fg.topological_sort (fg.all_blocks ())) + + def test_104_trivial_dag_check (self): + fg = self.fg + nop1 = gr.nop (gr.sizeof_int) + fg.connect (nop1, nop1) + fg.validate () + self.assertRaises (gr.NotDAG, + lambda : fg.topological_sort (fg.all_blocks ())) + + def test_105 (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + src2 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + nop2 = gr.nop (gr.sizeof_int) + nop3 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + + fg.connect (src1, nop1) + fg.connect (src2, nop2) + fg.connect (nop1, (nop3, 0)) + fg.connect (nop2, (nop3, 1)) + fg.connect (nop3, dst1) + fg.validate () + ts = fg.topological_sort (fg.all_blocks ()) + self.assertEqual ([src2, nop2, src1, nop1, nop3, dst1], ts) + + + def test_106 (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + src2 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + nop2 = gr.nop (gr.sizeof_int) + nop3 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + + fg.connect (nop3, dst1) + fg.connect (nop2, (nop3, 1)) + fg.connect (nop1, (nop3, 0)) + fg.connect (src2, nop2) + fg.connect (src1, nop1) + fg.validate () + ts = fg.topological_sort (fg.all_blocks ()) + self.assertEqual ([src2, nop2, src1, nop1, nop3, dst1], ts) + + def test_107 (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + src2 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + nop2 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + dst2 = gr.null_sink (gr.sizeof_int) + + fg.connect (src1, nop1) + fg.connect (nop1, dst1) + fg.connect (src2, nop2) + fg.connect (nop2, dst2) + fg.validate () + ts = fg.topological_sort (fg.all_blocks ()) + self.assertEqual ([src2, nop2, dst2, src1, nop1, dst1], ts) + + def test_108 (self): + self.leak_check (self.body_108) + + def body_108 (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + src2 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + nop2 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + dst2 = gr.null_sink (gr.sizeof_int) + + fg.connect (nop2, dst2) + fg.connect (src1, nop1) + fg.connect (src2, nop2) + fg.connect (nop1, dst1) + fg.validate () + ts = fg.topological_sort (fg.all_blocks ()) + self.assertEqual ([src2, nop2, dst2, src1, nop1, dst1], ts) + self.assertEqual ((6,0,0,0), all_counts ()) + + def test_109__setup_connections (self): + self.leak_check (self.body_109) + + def body_109 (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + fg.connect (src1, dst1) + fg._setup_connections () + self.assertEqual ((2,2,1,1), all_counts ()) + + def test_110_scheduler (self): + self.leak_check (self.body_110) + + def body_110 (self): + fg = self.fg + src_data = (0, 1, 2, 3) + src1 = gr.vector_source_i (src_data) + dst1 = gr.vector_sink_i () + fg.connect ((src1, 0), (dst1, 0)) + fg.run () + dst_data = dst1.data () + self.assertEqual (src_data, dst_data) + + def test_111_scheduler (self): + self.leak_check (self.body_111) + + def body_111 (self): + fg = self.fg + src_data = (0, 1, 2, 3) + expected_result = (2, 3, 4, 5) + src1 = gr.vector_source_i (src_data) + op = gr.add_const_ii (2) + dst1 = gr.vector_sink_i () + fg.connect (src1, op) + fg.connect (op, dst1) + fg.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_111v_scheduler (self): + self.leak_check (self.body_111v) + + def body_111v (self): + fg = self.fg + src_data = (0, 1, 2, 3) + expected_result = (2, 3, 4, 5) + src1 = gr.vector_source_i (src_data) + op = gr.add_const_ii (2) + dst1 = gr.vector_sink_i () + fg.connect (src1, op, dst1) + fg.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_112 (self): + fg = self.fg + nop1 = gr.nop (gr.sizeof_int) + nop2 = gr.nop (gr.sizeof_int) + nop3 = gr.nop (gr.sizeof_int) + fg.connect ((nop1, 0), (nop2, 0)) + fg.connect ((nop1, 1), (nop3, 0)) + fg._setup_connections () + self.assertEqual (2, nop1.detail().noutputs()) + + def test_113 (self): + fg = self.fg + nop1 = gr.nop (gr.sizeof_int) + nop2 = gr.nop (gr.sizeof_int) + nop3 = gr.nop (gr.sizeof_int) + fg.connect ((nop1, 0), (nop2, 0)) + fg.connect ((nop1, 0), (nop3, 0)) + fg._setup_connections () + self.assertEqual (1, nop1.detail().noutputs()) + + def test_200_partition (self): + self.leak_check (self.body_200) + + def body_200 (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + fg.connect (nop1, dst1) + fg.connect (src1, nop1) + fg.validate () + p = fg.partition_graph (fg.all_blocks ()) + self.assertEqual ([[src1, nop1, dst1]], p) + self.assertEqual ((3,0,0,0), all_counts ()) + + def test_201_partition (self): + self.leak_check (self.body_201) + + def body_201 (self): + fg = self.fg + src1 = gr.null_source (gr.sizeof_int) + src2 = gr.null_source (gr.sizeof_int) + nop1 = gr.nop (gr.sizeof_int) + nop2 = gr.nop (gr.sizeof_int) + dst1 = gr.null_sink (gr.sizeof_int) + dst2 = gr.null_sink (gr.sizeof_int) + + fg.connect (nop2, dst2) + fg.connect (src1, nop1) + fg.connect (src2, nop2) + fg.connect (nop1, dst1) + fg.validate () + p = fg.partition_graph (fg.all_blocks ()) + self.assertEqual ([[src2, nop2, dst2], [src1, nop1, dst1]], p) + self.assertEqual ((6,0,0,0), all_counts ()) + + def test_300_hier (self): + self.leak_check (self.body_300_hier) + + def body_300_hier (self): + fg = self.fg + src_data = (0, 1, 2, 3) + expected_result = (10, 11, 12, 13) + src1 = gr.vector_source_i (src_data) + op = wrap_add (fg, 10) + dst1 = gr.vector_sink_i () + fg.connect (src1, op, dst1) + fg.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_301_hier (self): + self.leak_check (self.body_301_hier) + + def body_301_hier (self): + fg = self.fg + src_data = (0, 1, 2, 3) + expected_result = (5, 8, 11, 14) + src1 = gr.vector_source_i (src_data) + op = mult_add (fg, 3, 5) + dst1 = gr.vector_sink_i () + fg.connect (src1, op, dst1) + fg.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_302_hier (self): + self.leak_check (self.body_302_hier) + + def body_302_hier (self): + fg = self.fg + src_data = (0, 1, 2, 3) + expected_result = (10, 11, 12, 13) + src1 = gr.vector_source_i (src_data) + op = gr.compose (fg, gr.add_const_ii (10)) + dst1 = gr.vector_sink_i () + fg.connect (src1, op, dst1) + fg.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_303_hier (self): + self.leak_check (self.body_303_hier) + + def body_303_hier (self): + fg = self.fg + src_data = (0, 1, 2, 3) + expected_result = (35, 38, 41, 44) + src1 = gr.vector_source_i (src_data) + op = gr.compose (fg, gr.add_const_ii (10), mult_add (fg, 3, 5)) + dst1 = gr.vector_sink_i () + fg.connect (src1, op, dst1) + fg.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_frequency_modulator.py b/gnuradio-core/src/python/gnuradio/gr/qa_frequency_modulator.py new file mode 100755 index 00000000..cfa34830 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_frequency_modulator.py @@ -0,0 +1,56 @@ +#!/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 gnuradio import gr, gr_unittest +import math + +def sincos(x): + return math.cos(x) + math.sin(x) * 1j + + +class test_frequency_modulator (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_fm_001 (self): + pi = math.pi + sensitivity = pi/4 + src_data = (1.0/4, 1.0/2, 1.0/4, -1.0/4, -1.0/2, -1/4.0) + running_sum = (pi/16, 3*pi/16, pi/4, 3*pi/16, pi/16, 0) + expected_result = tuple ([sincos (x) for x in running_sum]) + src = gr.vector_source_f (src_data) + op = gr.frequency_modulator_fc (sensitivity) + dst = gr.vector_sink_c () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertComplexTuplesAlmostEqual (expected_result, result_data) + + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_fsk_stuff.py b/gnuradio-core/src/python/gnuradio/gr/qa_fsk_stuff.py new file mode 100755 index 00000000..d61ddb1a --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_fsk_stuff.py @@ -0,0 +1,75 @@ +#!/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 gnuradio import gr, gr_unittest +import math + +def sincos(x): + return math.cos(x) + math.sin(x) * 1j + +class test_bytes_to_syms (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_bytes_to_syms_001 (self): + src_data = (0x01, 0x80, 0x03) + expected_result = (-1, -1, -1, -1, -1, -1, -1, +1, + +1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, +1, +1) + src = gr.vector_source_b (src_data) + op = gr.bytes_to_syms () + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertEqual (expected_result, result_data) + + def test_simple_framer (self): + src_data = (0x00, 0x11, 0x22, 0x33, + 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, + 0xcc, 0xdd, 0xee, 0xff) + + expected_result = ( + 0xac, 0xdd, 0xa4, 0xe2, 0xf2, 0x8c, 0x20, 0xfc, 0x00, 0x00, 0x11, 0x22, 0x33, 0x55, + 0xac, 0xdd, 0xa4, 0xe2, 0xf2, 0x8c, 0x20, 0xfc, 0x01, 0x44, 0x55, 0x66, 0x77, 0x55, + 0xac, 0xdd, 0xa4, 0xe2, 0xf2, 0x8c, 0x20, 0xfc, 0x02, 0x88, 0x99, 0xaa, 0xbb, 0x55, + 0xac, 0xdd, 0xa4, 0xe2, 0xf2, 0x8c, 0x20, 0xfc, 0x03, 0xcc, 0xdd, 0xee, 0xff, 0x55) + + src = gr.vector_source_b (src_data) + op = gr.simple_framer (4) + dst = gr.vector_sink_b () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertEqual (expected_result, result_data) + + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_goertzel.py b/gnuradio-core/src/python/gnuradio/gr/qa_goertzel.py new file mode 100755 index 00000000..da9d65f6 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_goertzel.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 gnuradio import gr, gr_unittest +from math import pi, cos + +class test_goertzel(gr_unittest.TestCase): + + def setUp(self): + self.fg = gr.flow_graph() + + def tearDown(self): + self.fg = None + + def make_tone_data(self, rate, freq): + return [cos(2*pi*x*freq/rate) for x in range(rate)] + + def transform(self, src_data, rate, freq): + src = gr.vector_source_f(src_data, False) + dft = gr.goertzel_fc(rate, rate, freq) + dst = gr.vector_sink_c() + self.fg.connect(src, dft, dst) + self.fg.run() + return dst.data() + + def test_001(self): # Measure single tone magnitude + rate = 8000 + freq = 100 + bin = freq + src_data = self.make_tone_data(rate, freq) + expected_result = 0.5 + actual_result = abs(self.transform(src_data, rate, bin)[0]) + self.assertAlmostEqual(expected_result, actual_result, places=5) + + def test_002(self): # Measure off frequency magnitude + rate = 8000 + freq = 100 + bin = freq/2 + src_data = self.make_tone_data(rate, freq) + expected_result = 0.0 + actual_result = abs(self.transform(src_data, rate, bin)[0]) + self.assertAlmostEqual(expected_result, actual_result, places=5) + +if __name__ == '__main__': + gr_unittest.main() diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_head.py b/gnuradio-core/src/python/gnuradio/gr/qa_head.py new file mode 100755 index 00000000..a6fcd7f9 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_head.py @@ -0,0 +1,47 @@ +#!/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 gnuradio import gr, gr_unittest + +class test_head (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_head (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) + expected_result = (1, 2, 3, 4) + src1 = gr.vector_source_i (src_data) + op = gr.head (gr.sizeof_int, 4) + dst1 = gr.vector_sink_i () + self.fg.connect (src1, op) + self.fg.connect (op, dst1) + self.fg.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_hilbert.py b/gnuradio-core/src/python/gnuradio/gr/qa_hilbert.py new file mode 100755 index 00000000..a8f39dd6 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_hilbert.py @@ -0,0 +1,116 @@ +#!/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 gnuradio import gr, gr_unittest +import math + +class test_sig_source (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_hilbert (self): + fg = self.fg + ntaps = 51 + sampling_freq = 100 + + expected_result = ( -1.4678005338941702e-11j, + -0.0011950774351134896j, + -0.0019336787518113852j, + -0.0034673355985432863j, + -0.0036765895783901215j, + -0.004916108213365078j, + -0.0042778430506587029j, + -0.006028641015291214j, + -0.005476709920912981j, + -0.0092810001224279404j, + -0.0095402700826525688j, + -0.016060983762145042j, + -0.016446959227323532j, + -0.02523401565849781j, + -0.024382550269365311j, + -0.035477779805660248j, + -0.033021725714206696j, + -0.048487484455108643j, + -0.04543270543217659j, + -0.069477587938308716j, + -0.066984444856643677j, + -0.10703597217798233j, + -0.10620346665382385j, + -0.1852707713842392j, + -0.19357112050056458j, + (7.2191945754696007e-09 -0.50004088878631592j), + (0.58778399229049683 -0.6155126690864563j), + (0.95105588436126709 -0.12377222627401352j), + (0.95105588436126709 +0.41524654626846313j), + (0.5877838134765625 +0.91611981391906738j), + (5.8516356205018383e-09 +1.0670661926269531j), + (-0.5877840518951416 +0.87856143712997437j), + (-0.95105588436126709 +0.35447561740875244j), + (-0.95105588436126709 -0.26055556535720825j), + (-0.5877838134765625 -0.77606213092803955j), + (-8.7774534307527574e-09 -0.96460390090942383j), + (0.58778399229049683 -0.78470128774642944j), + (0.95105588436126709 -0.28380891680717468j), + (0.95105588436126709 +0.32548999786376953j), + (0.5877838134765625 +0.82514488697052002j), + (1.4629089051254596e-08 +1.0096219778060913j), + (-0.5877840518951416 +0.81836479902267456j), + (-0.95105588436126709 +0.31451958417892456j), + (-0.95105588436126709 -0.3030143678188324j), + (-0.5877838134765625 -0.80480599403381348j), + (-1.7554906861505515e-08 -0.99516552686691284j), + (0.58778399229049683 -0.80540722608566284j), + (0.95105582475662231 -0.30557557940483093j), + (0.95105588436126709 +0.31097668409347534j), + (0.5877838134765625 +0.81027895212173462j), + (2.3406542482007353e-08 +1.0000816583633423j), + (-0.5877840518951416 +0.80908381938934326j), + (-0.95105588436126709 +0.30904293060302734j), + (-0.95105588436126709 -0.30904296040534973j), + (-0.5877838134765625 -0.80908387899398804j), + (-2.6332360292258272e-08 -1.0000815391540527j), + (0.58778399229049683 -0.80908381938934326j), + (0.95105582475662231 -0.30904299020767212j), + (0.95105588436126709 +0.30904293060302734j), + (0.5877838134765625 +0.80908381938934326j), + (3.218399768911695e-08 +1.0000815391540527j)) + + + src1 = gr.sig_source_f (sampling_freq, gr.GR_SIN_WAVE, + sampling_freq * 0.10, 1.0) + + head = gr.head (gr.sizeof_float, int (ntaps + sampling_freq * 0.10)) + hilb = gr.hilbert_fc (ntaps) + dst1 = gr.vector_sink_c () + fg.connect (src1, head) + fg.connect (head, hilb) + fg.connect (hilb, dst1) + fg.run () + dst_data = dst1.data () + self.assertComplexTuplesAlmostEqual (expected_result, dst_data, 5) + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_iir.py b/gnuradio-core/src/python/gnuradio/gr/qa_iir.py new file mode 100755 index 00000000..a1f2aa07 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_iir.py @@ -0,0 +1,135 @@ +#!/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 gnuradio import gr, gr_unittest + +class test_iir (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_iir_direct_001 (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + fftaps = () + fbtaps = () + expected_result = (0, 0, 0, 0, 0, 0, 0, 0) + src = gr.vector_source_f (src_data) + op = gr.iir_filter_ffd (fftaps, fbtaps) + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_iir_direct_002 (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + fftaps = (2,) + fbtaps = (0,) + expected_result = (2, 4, 6, 8, 10, 12, 14, 16) + src = gr.vector_source_f (src_data) + op = gr.iir_filter_ffd (fftaps, fbtaps) + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_iir_direct_003 (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + fftaps = (2, 11) + fbtaps = (0, 0) + expected_result = (2, 15, 28, 41, 54, 67, 80, 93) + src = gr.vector_source_f (src_data) + op = gr.iir_filter_ffd (fftaps, fbtaps) + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_iir_direct_004 (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + fftaps = (2, 11) + fbtaps = (0, -1) + expected_result = (2, 13, 15, 26, 28, 39, 41, 52) + src = gr.vector_source_f (src_data) + op = gr.iir_filter_ffd (fftaps, fbtaps) + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_iir_direct_005 (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + fftaps = (2, 11, 0) + fbtaps = (0, -1, 3) + expected_result = (2, 13, 21, 59, 58, 186, 68, 583) + src = gr.vector_source_f (src_data) + op = gr.iir_filter_ffd (fftaps, fbtaps) + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_iir_direct_006 (self): + fftaps = (2, 11, 0) + fbtaps = (0, -1) + self.assertRaises ((RuntimeError, ValueError), gr.iir_filter_ffd, fftaps, fbtaps) + + def test_iir_direct_007 (self): + src_data = (1, 2, 3, 4, 5, 6, 7, 8) + expected_result = (2, 13, 21, 59, 58, 186, 68, 583) + fftaps = (2, 1) + fbtaps = (0, -1) + src = gr.vector_source_f (src_data) + op = gr.iir_filter_ffd (fftaps, fbtaps) + fftaps = (2, 11, 0) + fbtaps = (0, -1, 3) + op.set_taps (fftaps, fbtaps) + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_iir_direct_008 (self): + fftaps = (2, 1) + fbtaps = (0, -1) + op = gr.iir_filter_ffd (fftaps, fbtaps) + fftaps = (2, 11) + fbtaps = (0, -1, 3) + self.assertRaises ((RuntimeError, ValueError), op.set_taps, fftaps, fbtaps) + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_interleave.py b/gnuradio-core/src/python/gnuradio/gr/qa_interleave.py new file mode 100755 index 00000000..003d12e6 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_interleave.py @@ -0,0 +1,81 @@ +#!/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 gnuradio import gr, gr_unittest +import math + +class test_interleave (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_int_001 (self): + lenx = 64 + src0 = gr.vector_source_f (range (0, lenx, 4)) + src1 = gr.vector_source_f (range (1, lenx, 4)) + src2 = gr.vector_source_f (range (2, lenx, 4)) + src3 = gr.vector_source_f (range (3, lenx, 4)) + op = gr.interleave (gr.sizeof_float) + dst = gr.vector_sink_f () + + self.fg.connect (src0, (op, 0)) + self.fg.connect (src1, (op, 1)) + self.fg.connect (src2, (op, 2)) + self.fg.connect (src3, (op, 3)) + self.fg.connect (op, dst) + self.fg.run () + expected_result = tuple (range (lenx)) + result_data = dst.data () + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_deint_001 (self): + lenx = 64 + src = gr.vector_source_f (range (lenx)) + op = gr.deinterleave (gr.sizeof_float) + dst0 = gr.vector_sink_f () + dst1 = gr.vector_sink_f () + dst2 = gr.vector_sink_f () + dst3 = gr.vector_sink_f () + + self.fg.connect (src, op) + self.fg.connect ((op, 0), dst0) + self.fg.connect ((op, 1), dst1) + self.fg.connect ((op, 2), dst2) + self.fg.connect ((op, 3), dst3) + self.fg.run () + + expected_result0 = tuple (range (0, lenx, 4)) + expected_result1 = tuple (range (1, lenx, 4)) + expected_result2 = tuple (range (2, lenx, 4)) + expected_result3 = tuple (range (3, lenx, 4)) + + self.assertFloatTuplesAlmostEqual (expected_result0, dst0.data ()) + self.assertFloatTuplesAlmostEqual (expected_result1, dst1.data ()) + self.assertFloatTuplesAlmostEqual (expected_result2, dst2.data ()) + self.assertFloatTuplesAlmostEqual (expected_result3, dst3.data ()) + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_interp_fir_filter.py b/gnuradio-core/src/python/gnuradio/gr/qa_interp_fir_filter.py new file mode 100755 index 00000000..4119e3e2 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_interp_fir_filter.py @@ -0,0 +1,54 @@ +#!/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 gnuradio import gr, gr_unittest +import math + +class test_interp_fir_filter (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_fff (self): + taps = [1, 10, 100, 1000, 10000] + src_data = (0, 2, 3, 5, 7, 11, 13, 17) + interpolation = 3 + xr = (0,0,0,0,2,20,200,2003,20030,300,3005,30050,500,5007,50070,700,7011,70110,1100,11013,110130,1300,13017,130170) + expected_result = tuple ([float (x) for x in xr]) + + src = gr.vector_source_f (src_data) + op = gr.interp_fir_filter_fff (interpolation, taps) + dst = gr.vector_sink_f () + self.fg.connect (src, op) + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + L = min(len(result_data), len(expected_result)) + self.assertEqual (expected_result[0:L], result_data[0:L]) + + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_kludge_copy.py b/gnuradio-core/src/python/gnuradio/gr/qa_kludge_copy.py new file mode 100755 index 00000000..f5dee152 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_kludge_copy.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 gnuradio import gr, gr_unittest +import math +import random + + +class test_kludge_copy(gr_unittest.TestCase): + + def setUp(self): + self.fg = gr.flow_graph() + self.rng = random.Random() + self.rng.seed(0) + + def tearDown(self): + self.fg = None + self.rng = None + + def make_random_int_tuple(self, L): + result = [] + for x in range(L): + result.append(self.rng.randint(int(-1e9), int(+1e9))) + return tuple(result) + + + def test_001(self): + # 1 input stream; 1 output stream + src0_data = self.make_random_int_tuple(16000) + src0 = gr.vector_source_i(src0_data) + op = gr.kludge_copy(gr.sizeof_int) + dst0 = gr.vector_sink_i() + self.fg.connect(src0, op, dst0) + self.fg.run() + dst0_data = dst0.data() + self.assertEqual(src0_data, dst0_data) + + def test_002(self): + # 2 input streams; 2 output streams + src0_data = self.make_random_int_tuple(16000) + src1_data = self.make_random_int_tuple(16000) + src0 = gr.vector_source_i(src0_data) + src1 = gr.vector_source_i(src1_data) + op = gr.kludge_copy(gr.sizeof_int) + dst0 = gr.vector_sink_i() + dst1 = gr.vector_sink_i() + self.fg.connect(src0, (op, 0), dst0) + self.fg.connect(src1, (op, 1), dst1) + self.fg.run() + dst0_data = dst0.data() + dst1_data = dst1.data() + self.assertEqual(src0_data, dst0_data) + self.assertEqual(src1_data, dst1_data) + + def test_003(self): + # number of input streams != number of output streams + src0_data = self.make_random_int_tuple(16000) + src1_data = self.make_random_int_tuple(16000) + src0 = gr.vector_source_i(src0_data) + src1 = gr.vector_source_i(src1_data) + op = gr.kludge_copy(gr.sizeof_int) + dst0 = gr.vector_sink_i() + dst1 = gr.vector_sink_i() + self.fg.connect(src0, (op, 0), dst0) + self.fg.connect(src1, (op, 1)) + self.assertRaises(ValueError, self.fg.run) + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_kludged_imports.py b/gnuradio-core/src/python/gnuradio/gr/qa_kludged_imports.py new file mode 100755 index 00000000..b2086772 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_kludged_imports.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 gnuradio import gr, gr_unittest + +class test_head (gr_unittest.TestCase): + + def setUp(self): + pass + + def tearDown(self): + pass + + def test_blks_import(self): + # make sure that this somewhat magic import works + from gnuradio import blks + + def test_gru_import(self): + # make sure that this somewhat magic import works + from gnuradio import gru + + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_message.py b/gnuradio-core/src/python/gnuradio/gr/qa_message.py new file mode 100755 index 00000000..d5d51114 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_message.py @@ -0,0 +1,117 @@ +#!/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 gnuradio import gr, gr_unittest +import qa_basic_flow_graph + + +def all_counts (): + return (gr.block_ncurrently_allocated (), + gr.block_detail_ncurrently_allocated (), + gr.buffer_ncurrently_allocated (), + gr.buffer_reader_ncurrently_allocated (), + gr.message_ncurrently_allocated ()) + + +class test_message (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph() + self.msgq = gr.msg_queue () + + def tearDown (self): + self.fg = None + self.msgq = None + + def leak_check (self, fct): + begin = all_counts () + fct () + # tear down early so we can check for leaks + self.tearDown () + end = all_counts () + self.assertEqual (begin, end) + + def test_100 (self): + msg = gr.message (0, 1.5, 2.3) + self.assertEquals (0, msg.type()) + self.assertAlmostEqual (1.5, msg.arg1()) + self.assertAlmostEqual (2.3, msg.arg2()) + self.assertEquals (0, msg.length()) + + def test_101 (self): + s = 'This is a test' + msg = gr.message_from_string(s) + self.assertEquals(s, msg.to_string()) + + def test_200 (self): + self.leak_check (self.body_200) + + def body_200 (self): + self.msgq.insert_tail (gr.message (0)) + self.assertEquals (1, self.msgq.count()) + self.msgq.insert_tail (gr.message (1)) + self.assertEquals (2, self.msgq.count()) + msg0 = self.msgq.delete_head () + self.assertEquals (0, msg0.type()) + msg1 = self.msgq.delete_head () + self.assertEquals (1, msg1.type()) + self.assertEquals (0, self.msgq.count()) + + def test_201 (self): + self.leak_check (self.body_201) + + def body_201 (self): + self.msgq.insert_tail (gr.message (0)) + self.assertEquals (1, self.msgq.count()) + self.msgq.insert_tail (gr.message (1)) + self.assertEquals (2, self.msgq.count()) + + def test_202 (self): + self.leak_check (self.body_202) + + def body_202 (self): + # global msg + msg = gr.message (666) + + def test_300(self): + input_data = (0,1,2,3,4,5,6,7,8,9) + src = gr.vector_source_b(input_data) + dst = gr.vector_sink_b() + self.fg.connect(src, dst) + self.fg.run() + self.assertEquals(input_data, dst.data()) + + def test_301(self): + src = gr.message_source(gr.sizeof_char) + dst = gr.vector_sink_b() + self.fg.connect(src, dst) + src.msgq().insert_tail(gr.message_from_string('01234')) + src.msgq().insert_tail(gr.message_from_string('5')) + src.msgq().insert_tail(gr.message_from_string('')) + src.msgq().insert_tail(gr.message_from_string('6789')) + src.msgq().insert_tail(gr.message(1)) # send EOF + self.fg.run() + self.assertEquals(tuple(map(ord, '0123456789')), dst.data()) + + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_mute.py b/gnuradio-core/src/python/gnuradio/gr/qa_mute.py new file mode 100755 index 00000000..863c308a --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_mute.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr, gr_unittest + +class test_head (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def help_ii (self, src_data, exp_data, op): + for s in zip (range (len (src_data)), src_data): + src = gr.vector_source_i (s[1]) + self.fg.connect (src, (op, s[0])) + dst = gr.vector_sink_i () + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertEqual (exp_data, result_data) + + def help_ff (self, src_data, exp_data, op): + for s in zip (range (len (src_data)), src_data): + src = gr.vector_source_f (s[1]) + self.fg.connect (src, (op, s[0])) + dst = gr.vector_sink_f () + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertEqual (exp_data, result_data) + + def help_cc (self, src_data, exp_data, op): + for s in zip (range (len (src_data)), src_data): + src = gr.vector_source_c (s[1]) + self.fg.connect (src, (op, s[0])) + dst = gr.vector_sink_c () + self.fg.connect (op, dst) + self.fg.run () + result_data = dst.data () + self.assertEqual (exp_data, result_data) + + def test_unmute_ii(self): + src_data = (1, 2, 3, 4, 5) + expected_result = (1, 2, 3, 4, 5) + op = gr.mute_ii (False) + self.help_ii ((src_data,), expected_result, op) + + def test_mute_ii(self): + src_data = (1, 2, 3, 4, 5) + expected_result = (0, 0, 0, 0, 0) + op = gr.mute_ii (True) + self.help_ii ((src_data,), expected_result, op) + + def test_unmute_cc (self): + src_data = (1+5j, 2+5j, 3+5j, 4+5j, 5+5j) + expected_result = (1+5j, 2+5j, 3+5j, 4+5j, 5+5j) + op = gr.mute_cc (False) + self.help_cc ((src_data,), expected_result, op) + + def test_unmute_cc (self): + src_data = (1+5j, 2+5j, 3+5j, 4+5j, 5+5j) + expected_result = (0+0j, 0+0j, 0+0j, 0+0j, 0+0j) + op = gr.mute_cc (True) + self.help_cc ((src_data,), expected_result, op) + + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_nlog10.py b/gnuradio-core/src/python/gnuradio/gr/qa_nlog10.py new file mode 100755 index 00000000..f056d110 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_nlog10.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 gnuradio import gr, gr_unittest + +class test_single_pole_iir(gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_001(self): + src_data = (-10, 0, 10, 100, 1000, 10000, 100000) + expected_result = (-180, -180, 10, 20, 30, 40, 50) + src = gr.vector_source_f(src_data) + op = gr.nlog10_ff(10) + dst = gr.vector_sink_f() + self.fg.connect (src, op, dst) + self.fg.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_packed_to_unpacked.py b/gnuradio-core/src/python/gnuradio/gr/qa_packed_to_unpacked.py new file mode 100755 index 00000000..d5472c8d --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_packed_to_unpacked.py @@ -0,0 +1,405 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 gnuradio import gr, gr_unittest +import random + +class test_packing(gr_unittest.TestCase): + + def setUp(self): + self.fg = gr.flow_graph () + + def tearDown(self): + self.fg = None + + def test_001(self): + """ + Test stream_to_streams. + """ + src_data = (0x80,) + expected_results = (1,0,0,0,0,0,0,0) + src = gr.vector_source_b(src_data,False) + op = gr.packed_to_unpacked_bb(1, gr.GR_MSB_FIRST) + self.fg.connect(src, op) + + dst = gr.vector_sink_b() + self.fg.connect(op, dst) + + self.fg.run() + + self.assertEqual(expected_results, dst.data()) + + def test_002(self): + """ + Test stream_to_streams. + """ + src_data = (0x80,) + expected_results = (0,0,0,0,0,0,0, 1) + src = gr.vector_source_b(src_data,False) + op = gr.packed_to_unpacked_bb(1, gr.GR_LSB_FIRST) + self.fg.connect(src, op) + + dst = gr.vector_sink_b() + self.fg.connect(op, dst) + + self.fg.run() + + self.assertEqual(expected_results, dst.data()) + + def test_003(self): + """ + Test stream_to_streams. + """ + src_data = (0x11,) + expected_results = (4, 2) + src = gr.vector_source_b(src_data,False) + op = gr.packed_to_unpacked_bb(3, gr.GR_LSB_FIRST) + self.fg.connect(src, op) + + dst = gr.vector_sink_b() + self.fg.connect(op, dst) + + self.fg.run() + + self.assertEqual(expected_results, dst.data()) + + def test_004(self): + """ + Test stream_to_streams. + """ + src_data = (0x11,) + expected_results = (0, 4) + src = gr.vector_source_b(src_data,False) + op = gr.packed_to_unpacked_bb(3, gr.GR_MSB_FIRST) + self.fg.connect(src, op) + + dst = gr.vector_sink_b() + self.fg.connect(op, dst) + + self.fg.run() + + self.assertEqual(expected_results, dst.data()) + + def test_005(self): + """ + Test stream_to_streams. + """ + src_data = (1,0,0,0,0,0,1,0,0,1,0,1,1,0,1,0) + expected_results = (0x82,0x5a) + src = gr.vector_source_b(src_data,False) + op = gr.unpacked_to_packed_bb(1, gr.GR_MSB_FIRST) + self.fg.connect(src, op) + + dst = gr.vector_sink_b() + self.fg.connect(op, dst) + + self.fg.run() + + self.assertEqual(expected_results, dst.data()) + + def test_006(self): + """ + Test stream_to_streams. + """ + src_data = (0,1,0,0,0,0,0,1,0,1,0,1,1,0,1,0) + expected_results = (0x82,0x5a) + src = gr.vector_source_b(src_data,False) + op = gr.unpacked_to_packed_bb(1, gr.GR_LSB_FIRST) + self.fg.connect(src, op) + + dst = gr.vector_sink_b() + self.fg.connect(op, dst) + + self.fg.run() + + self.assertEqual(expected_results, dst.data()) + + + def test_007(self): + """ + Test stream_to_streams. + """ + src_data = (4, 2, 0,0,0) + expected_results = (0x11,) + src = gr.vector_source_b(src_data,False) + op = gr.unpacked_to_packed_bb(3, gr.GR_LSB_FIRST) + self.fg.connect(src, op) + + dst = gr.vector_sink_b() + self.fg.connect(op, dst) + + self.fg.run() + + self.assertEqual(expected_results, dst.data()) + + def test_008(self): + """ + Test stream_to_streams. + """ + src_data = (0, 4, 2,0,0) + expected_results = (0x11,) + src = gr.vector_source_b(src_data,False) + op = gr.unpacked_to_packed_bb(3, gr.GR_MSB_FIRST) + self.fg.connect(src, op) + + dst = gr.vector_sink_b() + self.fg.connect(op, dst) + + self.fg.run() + + self.assertEqual(expected_results, dst.data()) + + def test_009(self): + """ + Test stream_to_streams. + """ + + random.seed(0) + src_data = [] + for i in xrange(202): + src_data.append((random.randint(0,255))) + src_data = tuple(src_data) + expected_results = src_data + + src = gr.vector_source_b(tuple(src_data),False) + op1 = gr.packed_to_unpacked_bb(3, gr.GR_MSB_FIRST) + op2 = gr.unpacked_to_packed_bb(3, gr.GR_MSB_FIRST) + self.fg.connect(src, op1, op2) + + dst = gr.vector_sink_b() + self.fg.connect(op2, dst) + + self.fg.run() + + self.assertEqual(expected_results[0:201], dst.data()) + + def test_010(self): + """ + Test stream_to_streams. + """ + + random.seed(0) + src_data = [] + for i in xrange(56): + src_data.append((random.randint(0,255))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_b(tuple(src_data),False) + op1 = gr.packed_to_unpacked_bb(7, gr.GR_MSB_FIRST) + op2 = gr.unpacked_to_packed_bb(7, gr.GR_MSB_FIRST) + self.fg.connect(src, op1, op2) + dst = gr.vector_sink_b() + self.fg.connect(op2, dst) + + self.fg.run() + self.assertEqual(expected_results[0:201], dst.data()) + + def test_011(self): + """ + Test stream_to_streams. + """ + + random.seed(0) + src_data = [] + for i in xrange(56): + src_data.append((random.randint(0,255))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_b(tuple(src_data),False) + op1 = gr.packed_to_unpacked_bb(7, gr.GR_LSB_FIRST) + op2 = gr.unpacked_to_packed_bb(7, gr.GR_LSB_FIRST) + self.fg.connect(src, op1, op2) + dst = gr.vector_sink_b() + self.fg.connect(op2, dst) + + self.fg.run() + self.assertEqual(expected_results[0:201], dst.data()) + + + # tests on shorts + + def test_100a(self): + """ + test short version + """ + random.seed(0) + src_data = [] + for i in xrange(100): + src_data.append((random.randint(-2**15,2**15-1))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_s(tuple(src_data),False) + op1 = gr.packed_to_unpacked_ss(1, gr.GR_MSB_FIRST) + op2 = gr.unpacked_to_packed_ss(1, gr.GR_MSB_FIRST) + self.fg.connect(src, op1, op2) + dst = gr.vector_sink_s() + self.fg.connect(op2, dst) + + self.fg.run() + self.assertEqual(expected_results, dst.data()) + + def test_100b(self): + """ + test short version + """ + random.seed(0) + src_data = [] + for i in xrange(100): + src_data.append((random.randint(-2**15,2**15-1))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_s(tuple(src_data),False) + op1 = gr.packed_to_unpacked_ss(1, gr.GR_LSB_FIRST) + op2 = gr.unpacked_to_packed_ss(1, gr.GR_LSB_FIRST) + self.fg.connect(src, op1, op2) + dst = gr.vector_sink_s() + self.fg.connect(op2, dst) + + self.fg.run() + self.assertEqual(expected_results, dst.data()) + + def test_101a(self): + """ + test short version + """ + random.seed(0) + src_data = [] + for i in xrange(100): + src_data.append((random.randint(-2**15,2**15-1))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_s(tuple(src_data),False) + op1 = gr.packed_to_unpacked_ss(8, gr.GR_MSB_FIRST) + op2 = gr.unpacked_to_packed_ss(8, gr.GR_MSB_FIRST) + self.fg.connect(src, op1, op2) + dst = gr.vector_sink_s() + self.fg.connect(op2, dst) + + self.fg.run() + self.assertEqual(expected_results, dst.data()) + + def test_101b(self): + """ + test short version + """ + random.seed(0) + src_data = [] + for i in xrange(100): + src_data.append((random.randint(-2**15,2**15-1))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_s(tuple(src_data),False) + op1 = gr.packed_to_unpacked_ss(8, gr.GR_LSB_FIRST) + op2 = gr.unpacked_to_packed_ss(8, gr.GR_LSB_FIRST) + self.fg.connect(src, op1, op2) + dst = gr.vector_sink_s() + self.fg.connect(op2, dst) + + self.fg.run() + self.assertEqual(expected_results, dst.data()) + + # tests on ints + + def test_200a(self): + """ + test int version + """ + random.seed(0) + src_data = [] + for i in xrange(100): + src_data.append((random.randint(-2**31,2**31-1))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_i(tuple(src_data),False) + op1 = gr.packed_to_unpacked_ii(1, gr.GR_MSB_FIRST) + op2 = gr.unpacked_to_packed_ii(1, gr.GR_MSB_FIRST) + self.fg.connect(src, op1, op2) + dst = gr.vector_sink_i() + self.fg.connect(op2, dst) + + self.fg.run() + self.assertEqual(expected_results, dst.data()) + + def test_200b(self): + """ + test int version + """ + random.seed(0) + src_data = [] + for i in xrange(100): + src_data.append((random.randint(-2**31,2**31-1))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_i(tuple(src_data),False) + op1 = gr.packed_to_unpacked_ii(1, gr.GR_LSB_FIRST) + op2 = gr.unpacked_to_packed_ii(1, gr.GR_LSB_FIRST) + self.fg.connect(src, op1, op2) + dst = gr.vector_sink_i() + self.fg.connect(op2, dst) + + self.fg.run() + self.assertEqual(expected_results, dst.data()) + + def test_201a(self): + """ + test int version + """ + random.seed(0) + src_data = [] + for i in xrange(100): + src_data.append((random.randint(-2**31,2**31-1))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_i(tuple(src_data),False) + op1 = gr.packed_to_unpacked_ii(8, gr.GR_MSB_FIRST) + op2 = gr.unpacked_to_packed_ii(8, gr.GR_MSB_FIRST) + self.fg.connect(src, op1, op2) + dst = gr.vector_sink_i() + self.fg.connect(op2, dst) + + self.fg.run() + self.assertEqual(expected_results, dst.data()) + + def test_201b(self): + """ + test int version + """ + random.seed(0) + src_data = [] + for i in xrange(100): + src_data.append((random.randint(-2**31,2**31-1))) + src_data = tuple(src_data) + expected_results = src_data + src = gr.vector_source_i(tuple(src_data),False) + op1 = gr.packed_to_unpacked_ii(8, gr.GR_LSB_FIRST) + op2 = gr.unpacked_to_packed_ii(8, gr.GR_LSB_FIRST) + self.fg.connect(src, op1, op2) + dst = gr.vector_sink_i() + self.fg.connect(op2, dst) + + self.fg.run() + self.assertEqual(expected_results, dst.data()) + + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_pipe_fittings.py b/gnuradio-core/src/python/gnuradio/gr/qa_pipe_fittings.py new file mode 100755 index 00000000..dca18c8e --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_pipe_fittings.py @@ -0,0 +1,143 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 gnuradio import gr, gr_unittest + +if 0: + import os + print "pid =", os.getpid() + raw_input("Attach, then press Enter to continue") + + +def calc_expected_result(src_data, n): + assert (len(src_data) % n) == 0 + result = [list() for x in range(n)] + #print "len(result) =", len(result) + for i in xrange(len(src_data)): + (result[i % n]).append(src_data[i]) + return [tuple(x) for x in result] + + +class test_pipe_fittings(gr_unittest.TestCase): + + def setUp(self): + self.fg = gr.flow_graph () + + def tearDown(self): + self.fg = None + + def test_001(self): + """ + Test stream_to_streams. + """ + n = 8 + src_len = n * 8 + src_data = range(src_len) + + expected_results = calc_expected_result(src_data, n) + #print "expected results: ", expected_results + src = gr.vector_source_i(src_data) + op = gr.stream_to_streams(gr.sizeof_int, n) + self.fg.connect(src, op) + + dsts = [] + for i in range(n): + dst = gr.vector_sink_i() + self.fg.connect((op, i), (dst, 0)) + dsts.append(dst) + + self.fg.run() + + for d in range(n): + self.assertEqual(expected_results[d], dsts[d].data()) + + def test_002(self): + """ + Test streams_to_stream (using stream_to_streams). + """ + n = 8 + src_len = n * 8 + src_data = tuple(range(src_len)) + expected_results = src_data + + src = gr.vector_source_i(src_data) + op1 = gr.stream_to_streams(gr.sizeof_int, n) + op2 = gr.streams_to_stream(gr.sizeof_int, n) + dst = gr.vector_sink_i() + + self.fg.connect(src, op1) + for i in range(n): + self.fg.connect((op1, i), (op2, i)) + self.fg.connect(op2, dst) + + self.fg.run() + self.assertEqual(expected_results, dst.data()) + + def test_003(self): + """ + Test streams_to_vector (using stream_to_streams & vector_to_stream). + """ + n = 8 + src_len = n * 8 + src_data = tuple(range(src_len)) + expected_results = src_data + + src = gr.vector_source_i(src_data) + op1 = gr.stream_to_streams(gr.sizeof_int, n) + op2 = gr.streams_to_vector(gr.sizeof_int, n) + op3 = gr.vector_to_stream(gr.sizeof_int, n) + dst = gr.vector_sink_i() + + self.fg.connect(src, op1) + for i in range(n): + self.fg.connect((op1, i), (op2, i)) + self.fg.connect(op2, op3, dst) + + self.fg.run() + self.assertEqual(expected_results, dst.data()) + + def test_004(self): + """ + Test vector_to_streams. + """ + n = 8 + src_len = n * 8 + src_data = tuple(range(src_len)) + expected_results = src_data + + src = gr.vector_source_i(src_data) + op1 = gr.stream_to_vector(gr.sizeof_int, n) + op2 = gr.vector_to_streams(gr.sizeof_int, n) + op3 = gr.streams_to_stream(gr.sizeof_int, n) + dst = gr.vector_sink_i() + + self.fg.connect(src, op1, op2) + for i in range(n): + self.fg.connect((op2, i), (op3, i)) + self.fg.connect(op3, dst) + + self.fg.run() + self.assertEqual(expected_results, dst.data()) + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_rational_resampler.py b/gnuradio-core/src/python/gnuradio/gr/qa_rational_resampler.py new file mode 100755 index 00000000..2505482d --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_rational_resampler.py @@ -0,0 +1,290 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr, gr_unittest +from gnuradio import blks +import math +import random +import sys + +#import os +#print os.getpid() +#raw_input('Attach with gdb, then press Enter: ') + + +def random_floats(n): + r = [] + for x in xrange(n): + r.append(float(random.randint(-32768, 32768))) + return tuple(r) + + +def reference_dec_filter(src_data, decim, taps): + fg = gr.flow_graph() + src = gr.vector_source_f(src_data) + op = gr.fir_filter_fff(decim, taps) + dst = gr.vector_sink_f() + fg.connect(src, op, dst) + fg.run() + result_data = dst.data() + fg = None + return result_data + +def reference_interp_filter(src_data, interp, taps): + fg = gr.flow_graph() + src = gr.vector_source_f(src_data) + op = gr.interp_fir_filter_fff(interp, taps) + dst = gr.vector_sink_f() + fg.connect(src, op, dst) + fg.run() + result_data = dst.data() + fg = None + return result_data + +def reference_interp_dec_filter(src_data, interp, decim, taps): + fg = gr.flow_graph() + src = gr.vector_source_f(src_data) + up = gr.interp_fir_filter_fff(interp, (1,)) + dn = gr.fir_filter_fff(decim, taps) + dst = gr.vector_sink_f() + fg.connect(src, up, dn, dst) + fg.run() + result_data = dst.data() + fg = None + return result_data + + +class test_rational_resampler (gr_unittest.TestCase): + + def setUp(self): + self.fg = gr.flow_graph() + + def tearDown(self): + self.fg = None + + # + # test the gr.rational_resampler_base primitives... + # + + def test_000_1_to_1(self): + taps = (-4, 5) + src_data = (234, -4, 23, -56, 45, 98, -23, -7) + xr = (-936, 1186, -112, 339, -460, -167, 582) + expected_result = tuple([float(x) for x in xr]) + + src = gr.vector_source_f(src_data) + op = gr.rational_resampler_base_fff(1, 1, taps) + dst = gr.vector_sink_f() + self.fg.connect(src, op) + self.fg.connect(op, dst) + self.fg.run() + result_data = dst.data() + self.assertEqual(expected_result, result_data) + + def test_001_interp(self): + taps = [1, 10, 100, 1000, 10000] + src_data = (0, 2, 3, 5, 7, 11, 13, 17) + interpolation = 3 + xr = (0,0,0,0,2,20,200,2003,20030,300,3005,30050,500,5007,50070,700,7011,70110,1100,11013,110130,1300,13017,130170,1700.0,17000.0,170000.0) + expected_result = tuple([float(x) for x in xr]) + + src = gr.vector_source_f(src_data) + op = gr.rational_resampler_base_fff(interpolation, 1, taps) + dst = gr.vector_sink_f() + self.fg.connect(src, op) + self.fg.connect(op, dst) + self.fg.run() + result_data = dst.data() + self.assertEqual(expected_result, result_data) + + def test_002_interp(self): + taps = random_floats(31) + #src_data = random_floats(10000) # FIXME the 10k case fails! + src_data = random_floats(1000) + interpolation = 3 + + expected_result = reference_interp_filter(src_data, interpolation, taps) + + src = gr.vector_source_f(src_data) + op = gr.rational_resampler_base_fff(interpolation, 1, taps) + dst = gr.vector_sink_f() + self.fg.connect(src, op) + self.fg.connect(op, dst) + self.fg.run() + result_data = dst.data() + + L1 = len(result_data) + L2 = len(expected_result) + L = min(L1, L2) + if False: + sys.stderr.write('delta = %2d: ntaps = %d interp = %d ilen = %d\n' % + (L2 - L1, len(taps), interpolation, len(src_data))) + sys.stderr.write(' len(result_data) = %d len(expected_result) = %d\n' % + (len(result_data), len(expected_result))) + #self.assertEqual(expected_result[0:L], result_data[0:L]) + # FIXME check first 3 answers + self.assertEqual(expected_result[3:L], result_data[3:L]) + + def test_003_interp(self): + taps = random_floats(31) + src_data = random_floats(10000) + decimation = 3 + + expected_result = reference_dec_filter(src_data, decimation, taps) + + src = gr.vector_source_f(src_data) + op = gr.rational_resampler_base_fff(1, decimation, taps) + dst = gr.vector_sink_f() + self.fg.connect(src, op) + self.fg.connect(op, dst) + self.fg.run() + result_data = dst.data() + + L1 = len(result_data) + L2 = len(expected_result) + L = min(L1, L2) + if False: + sys.stderr.write('delta = %2d: ntaps = %d decim = %d ilen = %d\n' % + (L2 - L1, len(taps), decimation, len(src_data))) + sys.stderr.write(' len(result_data) = %d len(expected_result) = %d\n' % + (len(result_data), len(expected_result))) + self.assertEqual(expected_result[0:L], result_data[0:L]) + + # FIXME disabled. Triggers hang on SuSE 10.0 + def xtest_004_decim_random_vals(self): + MAX_TAPS = 9 + MAX_DECIM = 7 + OUTPUT_LEN = 9 + + random.seed(0) # we want reproducibility + + for ntaps in xrange(1, MAX_TAPS + 1): + for decim in xrange(1, MAX_DECIM+1): + for ilen in xrange(ntaps + decim, ntaps + OUTPUT_LEN*decim): + src_data = random_floats(ilen) + taps = random_floats(ntaps) + expected_result = reference_dec_filter(src_data, decim, taps) + + fg = gr.flow_graph() + src = gr.vector_source_f(src_data) + op = gr.rational_resampler_base_fff(1, decim, taps) + dst = gr.vector_sink_f() + fg.connect(src, op, dst) + fg.run() + fg = None + result_data = dst.data() + L1 = len(result_data) + L2 = len(expected_result) + L = min(L1, L2) + if False: + sys.stderr.write('delta = %2d: ntaps = %d decim = %d ilen = %d\n' % (L2 - L1, ntaps, decim, ilen)) + sys.stderr.write(' len(result_data) = %d len(expected_result) = %d\n' % + (len(result_data), len(expected_result))) + self.assertEqual(expected_result[0:L], result_data[0:L]) + + + # FIXME disabled. Triggers hang on SuSE 10.0 + def xtest_005_interp_random_vals(self): + MAX_TAPS = 9 + MAX_INTERP = 7 + INPUT_LEN = 9 + + random.seed(0) # we want reproducibility + + for ntaps in xrange(1, MAX_TAPS + 1): + for interp in xrange(1, MAX_INTERP+1): + for ilen in xrange(ntaps, ntaps + INPUT_LEN): + src_data = random_floats(ilen) + taps = random_floats(ntaps) + expected_result = reference_interp_filter(src_data, interp, taps) + + fg = gr.flow_graph() + src = gr.vector_source_f(src_data) + op = gr.rational_resampler_base_fff(interp, 1, taps) + dst = gr.vector_sink_f() + fg.connect(src, op, dst) + fg.run() + fg = None + result_data = dst.data() + L1 = len(result_data) + L2 = len(expected_result) + L = min(L1, L2) + #if True or abs(L1-L2) > 1: + if False: + sys.stderr.write('delta = %2d: ntaps = %d interp = %d ilen = %d\n' % (L2 - L1, ntaps, interp, ilen)) + #sys.stderr.write(' len(result_data) = %d len(expected_result) = %d\n' % + # (len(result_data), len(expected_result))) + #self.assertEqual(expected_result[0:L], result_data[0:L]) + # FIXME check first ntaps+1 answers + self.assertEqual(expected_result[ntaps+1:L], result_data[ntaps+1:L]) + + + def test_006_interp_decim(self): + taps = (0,1,0,0) + src_data = range(10000) + interp = 3 + decimation = 2 + + expected_result = reference_interp_dec_filter(src_data, interp, decimation, taps) + + src = gr.vector_source_f(src_data) + op = gr.rational_resampler_base_fff(interp, decimation, taps) + dst = gr.vector_sink_f() + self.fg.connect(src, op) + self.fg.connect(op, dst) + self.fg.run() + result_data = dst.data() + + L1 = len(result_data) + L2 = len(expected_result) + L = min(L1, L2) + if False: + sys.stderr.write('delta = %2d: ntaps = %d decim = %d ilen = %d\n' % + (L2 - L1, len(taps), decimation, len(src_data))) + sys.stderr.write(' len(result_data) = %d len(expected_result) = %d\n' % + (len(result_data), len(expected_result))) + self.assertEqual(expected_result[1:L], result_data[1:L]) + + # + # test the blks.rational_resampler_??? primitives... + # + + def test_101_interp(self): + taps = [1, 10, 100, 1000, 10000] + src_data = (0, 2, 3, 5, 7, 11, 13, 17) + interpolation = 3 + xr = (0,0,0,0,2,20,200,2003,20030,300,3005,30050,500,5007,50070,700,7011,70110,1100,11013,110130,1300,13017,130170,1700.0,17000.0,170000.0) + expected_result = tuple([float(x) for x in xr]) + + src = gr.vector_source_f(src_data) + op = blks.rational_resampler_fff(self.fg, interpolation, 1, taps=taps) + dst = gr.vector_sink_f() + self.fg.connect(src, op) + self.fg.connect(op, dst) + self.fg.run() + result_data = dst.data() + self.assertEqual(expected_result, result_data) + + +if __name__ == '__main__': + gr_unittest.main() + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_sig_source.py b/gnuradio-core/src/python/gnuradio/gr/qa_sig_source.py new file mode 100755 index 00000000..39866ac4 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_sig_source.py @@ -0,0 +1,85 @@ +#!/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 gnuradio import gr, gr_unittest +import math + +class test_sig_source (gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_const_f (self): + fg = self.fg + expected_result = (1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5) + src1 = gr.sig_source_f (1e6, gr.GR_CONST_WAVE, 0, 1.5) + op = gr.head (gr.sizeof_float, 10) + dst1 = gr.vector_sink_f () + fg.connect (src1, op) + fg.connect (op, dst1) + fg.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_const_i (self): + fg = self.fg + expected_result = (1, 1, 1, 1) + src1 = gr.sig_source_i (1e6, gr.GR_CONST_WAVE, 0, 1) + op = gr.head (gr.sizeof_int, 4) + dst1 = gr.vector_sink_i () + fg.connect (src1, op) + fg.connect (op, dst1) + fg.run () + dst_data = dst1.data () + self.assertEqual (expected_result, dst_data) + + def test_sine_f (self): + fg = self.fg + sqrt2 = math.sqrt(2) / 2 + expected_result = (0, sqrt2, 1, sqrt2, 0, -sqrt2, -1, -sqrt2, 0) + src1 = gr.sig_source_f (8, gr.GR_SIN_WAVE, 1.0, 1.0) + op = gr.head (gr.sizeof_float, 9) + dst1 = gr.vector_sink_f () + fg.connect (src1, op) + fg.connect (op, dst1) + fg.run () + dst_data = dst1.data () + self.assertFloatTuplesAlmostEqual (expected_result, dst_data, 5) + + def test_cosine_f (self): + fg = self.fg + sqrt2 = math.sqrt(2) / 2 + expected_result = (1, sqrt2, 0, -sqrt2, -1, -sqrt2, 0, sqrt2, 1) + src1 = gr.sig_source_f (8, gr.GR_COS_WAVE, 1.0, 1.0) + op = gr.head (gr.sizeof_float, 9) + dst1 = gr.vector_sink_f () + fg.connect (src1, op) + fg.connect (op, dst1) + fg.run () + dst_data = dst1.data () + self.assertFloatTuplesAlmostEqual (expected_result, dst_data, 5) + +if __name__ == '__main__': + gr_unittest.main () diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_single_pole_iir.py b/gnuradio-core/src/python/gnuradio/gr/qa_single_pole_iir.py new file mode 100755 index 00000000..5898188f --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_single_pole_iir.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 gnuradio import gr, gr_unittest + +class test_single_pole_iir(gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_001(self): + src_data = (0, 1000, 2000, 3000, 4000, 5000) + expected_result = src_data + src = gr.vector_source_f(src_data) + op = gr.single_pole_iir_filter_ff (1.0) + dst = gr.vector_sink_f() + self.fg.connect (src, op, dst) + self.fg.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual (expected_result, result_data) + + def test_002(self): + src_data = (0, 1000, 2000, 3000, 4000, 5000) + expected_result = (0, 125, 359.375, 689.453125, 1103.271484, 1590.36255) + src = gr.vector_source_f(src_data) + op = gr.single_pole_iir_filter_ff (0.125) + dst = gr.vector_sink_f() + self.fg.connect (src, op, dst) + self.fg.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual (expected_result, result_data, 3) + + def test_003(self): + block_size = 2 + src_data = (0, 1000, 2000, 3000, 4000, 5000) + expected_result = (0, 125, 250, 484.375, 718.75, 1048.828125) + src = gr.vector_source_f(src_data) + s2p = gr.serial_to_parallel(gr.sizeof_float, block_size) + op = gr.single_pole_iir_filter_ff (0.125, block_size) + p2s = gr.parallel_to_serial(gr.sizeof_float, block_size) + dst = gr.vector_sink_f() + self.fg.connect (src, s2p, op, p2s, dst) + self.fg.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual (expected_result, result_data, 3) + + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_single_pole_iir_cc.py b/gnuradio-core/src/python/gnuradio/gr/qa_single_pole_iir_cc.py new file mode 100755 index 00000000..a7889d17 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_single_pole_iir_cc.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python +# +# Copyright 2005,2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 gnuradio import gr, gr_unittest + +class test_single_pole_iir_cc(gr_unittest.TestCase): + + def setUp (self): + self.fg = gr.flow_graph () + + def tearDown (self): + self.fg = None + + def test_001(self): + src_data = (0+0j, 1000+1000j, 2000+2000j, 3000+3000j, 4000+4000j, 5000+5000j) + expected_result = src_data + src = gr.vector_source_c(src_data) + op = gr.single_pole_iir_filter_cc (1.0) + dst = gr.vector_sink_c() + self.fg.connect (src, op, dst) + self.fg.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual (expected_result, result_data) + + def test_002(self): + src_data = (complex(0,0), complex(1000,-1000), complex(2000,-2000), complex(3000,-3000), complex(4000,-4000), complex(5000,-5000)) + expected_result = (complex(0,0), complex(125,-125), complex(359.375,-359.375), complex(689.453125,-689.453125), complex(1103.271484,-1103.271484), complex(1590.36255,-1590.36255)) + src = gr.vector_source_c(src_data) + op = gr.single_pole_iir_filter_cc (0.125) + dst = gr.vector_sink_c() + self.fg.connect (src, op, dst) + self.fg.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 3) + + def test_003(self): + block_size = 2 + src_data = (complex(0,0), complex(1000,-1000), complex(2000,-2000), complex(3000,-3000), complex(4000,-4000), complex(5000,-5000)) + expected_result = (complex(0,0), complex(125,-125), complex(250,-250), complex(484.375,-484.375), complex(718.75,-718.75), complex(1048.828125,-1048.828125)) + src = gr.vector_source_c(src_data) + s2p = gr.serial_to_parallel(gr.sizeof_gr_complex, block_size) + op = gr.single_pole_iir_filter_cc (0.125, block_size) + p2s = gr.parallel_to_serial(gr.sizeof_gr_complex, block_size) + dst = gr.vector_sink_c() + self.fg.connect (src, s2p, op, p2s, dst) + self.fg.run() + result_data = dst.data() + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 3) + + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_unpack_k_bits.py b/gnuradio-core/src/python/gnuradio/gr/qa_unpack_k_bits.py new file mode 100755 index 00000000..59f838a4 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_unpack_k_bits.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 gnuradio import gr, gr_unittest +import random + +class test_unpack(gr_unittest.TestCase): + + def setUp(self): + self.fg = gr.flow_graph () + + def tearDown(self): + self.fg = None + + def test_001(self): + src_data = (1,0,1,1,0,1,1,0) + expected_results = (1,0,1,1,0,1,1,0) + src = gr.vector_source_b(src_data,False) + op = gr.unpack_k_bits_bb(1) + dst = gr.vector_sink_b() + self.fg.connect(src, op, dst) + self.fg.run() + self.assertEqual(expected_results, dst.data()) + + def test_002(self): + src_data = ( 2, 3, 0, 1) + expected_results = (1,0,1,1,0,0,0,1) + src = gr.vector_source_b(src_data,False) + op = gr.unpack_k_bits_bb(2) + dst = gr.vector_sink_b() + self.fg.connect(src, op, dst) + self.fg.run() + self.assertEqual(expected_results, dst.data()) + + +if __name__ == '__main__': + gr_unittest.main () + diff --git a/gnuradio-core/src/python/gnuradio/gr/run_tests.in b/gnuradio-core/src/python/gnuradio/gr/run_tests.in new file mode 100755 index 00000000..87d0afda --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/run_tests.in @@ -0,0 +1,33 @@ +#!/bin/sh + +swigbld=@abs_top_builddir@/gnuradio-core/src/lib/swig +swigsrc=@abs_top_srcdir@/gnuradio-core/src/lib/swig +py=@abs_top_srcdir@/gnuradio-core/src/python + +PYTHONPATH="$swigbld:$swigbld/.libs:$swigsrc:$py" +export PYTHONPATH + +# for OS/X +DYLD_LIBRARY_PATH="@abs_top_builddir@/gnuradio-core/src/lib/.libs" +export DYLD_LIBRARY_PATH + +# Don't load user or system prefs +GR_DONT_LOAD_PREFS=1 +export GR_DONT_LOAD_PREFS + +ok=yes +for file in @srcdir@/qa_*.py +do + echo $file + if ! $file + then + ok=no + fi +done + +if [ $ok = yes ] +then + exit 0 +else + exit 1 +fi diff --git a/gnuradio-core/src/python/gnuradio/gr/scheduler.py b/gnuradio-core/src/python/gnuradio/gr/scheduler.py new file mode 100644 index 00000000..919d07f0 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/scheduler.py @@ -0,0 +1,70 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 gnuradio.gr.exceptions import * +from gnuradio_swig_python import single_threaded_scheduler, sts_pyrun +import gr_threading as _threading +#import threading as _threading + +class scheduler_thread(_threading.Thread): + def __init__(self, sts): + _threading.Thread.__init__(self) + self.sts = sts + def run(self): + # Invoke the single threaded scheduler's run method + # + # Note that we're in a new thread, and that sts_pyrun + # releases the global interpreter lock. This has the + # effect of evaluating the graph in parallel to the + # main line control code. + sts_pyrun(self.sts) + self.sts = None + +class scheduler(object): + def __init__(self, fg): + graphs = fg.partition_graph(fg.blocks) + # print "@@@ # graphs = %d" % (len(graphs)) + + self.state = [] + + for g in graphs: + list_of_blocks = [x.block() for x in g] + sts = single_threaded_scheduler(list_of_blocks) + thread = scheduler_thread(sts) + thread.setDaemon(1) + self.state.append((sts, thread)) + + def start(self): + for (sts, thread) in self.state: + thread.start() + + def stop(self): + for (sts, thread) in self.state: + sts.stop() + self.wait() + + def wait(self): + for (sts, thread) in self.state: + timeout = 0.100 + while True: + thread.join(timeout) + if not thread.isAlive(): + break diff --git a/gnuradio-core/src/python/gnuradio/gr_unittest.py b/gnuradio-core/src/python/gnuradio/gr_unittest.py new file mode 100755 index 00000000..a74a0615 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr_unittest.py @@ -0,0 +1,114 @@ +#!/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 unittest +import sys + +class TestCase(unittest.TestCase): + """A subclass of unittest.TestCase that adds additional assertions + + Adds new methods assertComplexAlmostEqual, + assertComplexTuplesAlmostEqual and assertFloatTuplesAlmostEqual + """ + + def assertComplexAlmostEqual (self, first, second, places=7, msg=None): + """Fail if the two complex objects are unequal as determined by their + difference rounded to the given number of decimal places + (default 7) and comparing to zero. + + Note that decimal places (from zero) is usually not the same + as significant digits (measured from the most signficant digit). + """ + if round(second.real-first.real, places) != 0: + raise self.failureException, \ + (msg or '%s != %s within %s places' % (`first`, `second`, `places` )) + if round(second.imag-first.imag, places) != 0: + raise self.failureException, \ + (msg or '%s != %s within %s places' % (`first`, `second`, `places` )) + + def assertComplexAlmostEqual2 (self, ref, x, abs_eps=1e-12, rel_eps=1e-6, msg=None): + """ + Fail if the two complex objects are unequal as determined by... + """ + if abs(ref - x) < abs_eps: + return + + if abs(ref) > abs_eps: + if abs(ref-x)/abs(ref) > rel_eps: + raise self.failureException, \ + (msg or '%s != %s rel_error = %s rel_limit = %s' % ( + `ref`, `x`, abs(ref-x)/abs(ref), `rel_eps` )) + else: + raise self.failureException, \ + (msg or '%s != %s rel_error = %s rel_limit = %s' % ( + `ref`, `x`, abs(ref-x)/abs(ref), `rel_eps` )) + + + + def assertComplexTuplesAlmostEqual (self, a, b, places=7, msg=None): + self.assertEqual (len(a), len(b)) + for i in xrange (len(a)): + self.assertComplexAlmostEqual (a[i], b[i], places, msg) + + def assertComplexTuplesAlmostEqual2 (self, ref, x, + abs_eps=1e-12, rel_eps=1e-6, msg=None): + self.assertEqual (len(ref), len(x)) + for i in xrange (len(ref)): + try: + self.assertComplexAlmostEqual2 (ref[i], x[i], abs_eps, rel_eps, msg) + except self.failureException, e: + #sys.stderr.write("index = %d " % (i,)) + #sys.stderr.write("%s\n" % (e,)) + raise + + def assertFloatTuplesAlmostEqual (self, a, b, places=7, msg=None): + self.assertEqual (len(a), len(b)) + for i in xrange (len(a)): + self.assertAlmostEqual (a[i], b[i], places, msg) + + + def assertFloatTuplesAlmostEqual2 (self, ref, x, + abs_eps=1e-12, rel_eps=1e-6, msg=None): + self.assertEqual (len(ref), len(x)) + for i in xrange (len(ref)): + try: + self.assertComplexAlmostEqual2 (ref[i], x[i], abs_eps, rel_eps, msg) + except self.failureException, e: + #sys.stderr.write("index = %d " % (i,)) + #sys.stderr.write("%s\n" % (e,)) + raise + + +TestResult = unittest.TestResult +TestSuite = unittest.TestSuite +FunctionTestCase = unittest.FunctionTestCase +TestLoader = unittest.TestLoader +TextTestRunner = unittest.TextTestRunner +TestProgram = unittest.TestProgram +main = TestProgram + +############################################################################## +# Executing this module from the command line +############################################################################## + +if __name__ == "__main__": + main(module=None) diff --git a/gnuradio-core/src/python/gnuradio/gru/Makefile.am b/gnuradio-core/src/python/gnuradio/gru/Makefile.am new file mode 100644 index 00000000..44b52b6c --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gru/Makefile.am @@ -0,0 +1,35 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 = run_tests.in +# TESTS = run_tests + +grblkspythondir = $(grpythondir)/gru + +grblkspython_PYTHON = \ + __init__.py + + +noinst_PYTHON = + +CLEANFILES = *.pyc *.pyo diff --git a/gnuradio-core/src/python/gnuradio/gru/__init__.py b/gnuradio-core/src/python/gnuradio/gru/__init__.py new file mode 100644 index 00000000..272c7a5f --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gru/__init__.py @@ -0,0 +1,37 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 glob +import os.path + +# Semi-hideous kludge to import everything in the gruimpl directory +# into the gnuradio.gru namespace. This keeps us from having to remember +# to manually update this file. + +for p in __path__: + filenames = glob.glob (os.path.join (p, "..", "gruimpl", "*.py")) + for f in filenames: + f = os.path.basename(f).lower() + f = f[:-3] + if f == '__init__': + continue + # print f + exec "from gnuradio.gruimpl.%s import *" % (f,) diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/Makefile.am b/gnuradio-core/src/python/gnuradio/gruimpl/Makefile.am new file mode 100644 index 00000000..06eb7a1f --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/Makefile.am @@ -0,0 +1,40 @@ +# +# 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 $(top_srcdir)/Makefile.common + +grupythondir = $(grpythondir)/gruimpl + +grupython_PYTHON = \ + __init__.py \ + crc.py \ + freqz.py \ + gnuplot_freqz.py \ + hexint.py \ + listmisc.py \ + mathmisc.py \ + lmx2306.py \ + os_read_exactly.py \ + sdr_1000.py \ + seq_with_cursor.py \ + socket_stuff.py + +CLEANFILES = *.pyc diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/__init__.py b/gnuradio-core/src/python/gnuradio/gruimpl/__init__.py new file mode 100644 index 00000000..a4917cf6 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/__init__.py @@ -0,0 +1 @@ +# make this a package diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/crc.py b/gnuradio-core/src/python/gnuradio/gruimpl/crc.py new file mode 100644 index 00000000..6a97c81b --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/crc.py @@ -0,0 +1,36 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 gnuradio import gr +from hexint import * +import struct + +def gen_and_append_crc32(s): + crc = gr.crc32(s) + return s + struct.pack(">I", hexint(crc)) + +def check_crc32(s): + msg = s[:-4] + #print "msg = '%s'" % (msg,) + actual = gr.crc32(msg) + (expected,) = struct.unpack(">I", s[-4:]) + # print "actual =", hex(actual), "expected =", hex(expected) + return (actual == expected, msg) diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/freqz.py b/gnuradio-core/src/python/gnuradio/gruimpl/freqz.py new file mode 100644 index 00000000..21704944 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/freqz.py @@ -0,0 +1,344 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 lifted from various parts of www.scipy.org -eb 2005-01-24 + +# Copyright (c) 2001, 2002 Enthought, Inc. +# +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# a. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# b. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# c. Neither the name of the Enthought nor the names of its contributors +# may be used to endorse or promote products derived from this software +# without specific prior written permission. +# +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +# DAMAGE. +# + +__all__ = ['freqz'] + +import Numeric +from Numeric import * +Num=Numeric + +def atleast_1d(*arys): + """ Force a sequence of arrays to each be at least 1D. + + Description: + Force an array to be at least 1D. If an array is 0D, the + array is converted to a single row of values. Otherwise, + the array is unaltered. + Arguments: + *arys -- arrays to be converted to 1 or more dimensional array. + Returns: + input array converted to at least 1D array. + """ + res = [] + for ary in arys: + ary = asarray(ary) + if len(ary.shape) == 0: + result = Numeric.array([ary[0]]) + else: + result = ary + res.append(result) + if len(res) == 1: + return res[0] + else: + return res + + +def polyval(p,x): + """Evaluate the polynomial p at x. If x is a polynomial then composition. + + Description: + + If p is of length N, this function returns the value: + p[0]*(x**N-1) + p[1]*(x**N-2) + ... + p[N-2]*x + p[N-1] + + x can be a sequence and p(x) will be returned for all elements of x. + or x can be another polynomial and the composite polynomial p(x) will be + returned. + """ + p = asarray(p) + if isinstance(x,poly1d): + y = 0 + else: + x = asarray(x) + y = Numeric.zeros(x.shape,x.typecode()) + for i in range(len(p)): + y = x * y + p[i] + return y + +class poly1d: + """A one-dimensional polynomial class. + + p = poly1d([1,2,3]) constructs the polynomial x**2 + 2 x + 3 + + p(0.5) evaluates the polynomial at the location + p.r is a list of roots + p.c is the coefficient array [1,2,3] + p.order is the polynomial order (after leading zeros in p.c are removed) + p[k] is the coefficient on the kth power of x (backwards from + sequencing the coefficient array. + + polynomials can be added, substracted, multplied and divided (returns + quotient and remainder). + asarray(p) will also give the coefficient array, so polynomials can + be used in all functions that accept arrays. + """ + def __init__(self, c_or_r, r=0): + if isinstance(c_or_r,poly1d): + for key in c_or_r.__dict__.keys(): + self.__dict__[key] = c_or_r.__dict__[key] + return + if r: + c_or_r = poly(c_or_r) + c_or_r = atleast_1d(c_or_r) + if len(c_or_r.shape) > 1: + raise ValueError, "Polynomial must be 1d only." + c_or_r = trim_zeros(c_or_r, trim='f') + if len(c_or_r) == 0: + c_or_r = Numeric.array([0]) + self.__dict__['coeffs'] = c_or_r + self.__dict__['order'] = len(c_or_r) - 1 + + def __array__(self,t=None): + if t: + return asarray(self.coeffs,t) + else: + return asarray(self.coeffs) + + def __coerce__(self,other): + return None + + def __repr__(self): + vals = repr(self.coeffs) + vals = vals[6:-1] + return "poly1d(%s)" % vals + + def __len__(self): + return self.order + + def __str__(self): + N = self.order + thestr = "0" + for k in range(len(self.coeffs)): + coefstr ='%.4g' % abs(self.coeffs[k]) + if coefstr[-4:] == '0000': + coefstr = coefstr[:-5] + power = (N-k) + if power == 0: + if coefstr != '0': + newstr = '%s' % (coefstr,) + else: + if k == 0: + newstr = '0' + else: + newstr = '' + elif power == 1: + if coefstr == '0': + newstr = '' + elif coefstr == '1': + newstr = 'x' + else: + newstr = '%s x' % (coefstr,) + else: + if coefstr == '0': + newstr = '' + elif coefstr == '1': + newstr = 'x**%d' % (power,) + else: + newstr = '%s x**%d' % (coefstr, power) + + if k > 0: + if newstr != '': + if self.coeffs[k] < 0: + thestr = "%s - %s" % (thestr, newstr) + else: + thestr = "%s + %s" % (thestr, newstr) + elif (k == 0) and (newstr != '') and (self.coeffs[k] < 0): + thestr = "-%s" % (newstr,) + else: + thestr = newstr + return _raise_power(thestr) + + + def __call__(self, val): + return polyval(self.coeffs, val) + + def __mul__(self, other): + if isscalar(other): + return poly1d(self.coeffs * other) + else: + other = poly1d(other) + return poly1d(polymul(self.coeffs, other.coeffs)) + + def __rmul__(self, other): + if isscalar(other): + return poly1d(other * self.coeffs) + else: + other = poly1d(other) + return poly1d(polymul(self.coeffs, other.coeffs)) + + def __add__(self, other): + other = poly1d(other) + return poly1d(polyadd(self.coeffs, other.coeffs)) + + def __radd__(self, other): + other = poly1d(other) + return poly1d(polyadd(self.coeffs, other.coeffs)) + + def __pow__(self, val): + if not isscalar(val) or int(val) != val or val < 0: + raise ValueError, "Power to non-negative integers only." + res = [1] + for k in range(val): + res = polymul(self.coeffs, res) + return poly1d(res) + + def __sub__(self, other): + other = poly1d(other) + return poly1d(polysub(self.coeffs, other.coeffs)) + + def __rsub__(self, other): + other = poly1d(other) + return poly1d(polysub(other.coeffs, self.coeffs)) + + def __div__(self, other): + if isscalar(other): + return poly1d(self.coeffs/other) + else: + other = poly1d(other) + return map(poly1d,polydiv(self.coeffs, other.coeffs)) + + def __rdiv__(self, other): + if isscalar(other): + return poly1d(other/self.coeffs) + else: + other = poly1d(other) + return map(poly1d,polydiv(other.coeffs, self.coeffs)) + + def __setattr__(self, key, val): + raise ValueError, "Attributes cannot be changed this way." + + def __getattr__(self, key): + if key in ['r','roots']: + return roots(self.coeffs) + elif key in ['c','coef','coefficients']: + return self.coeffs + elif key in ['o']: + return self.order + else: + return self.__dict__[key] + + def __getitem__(self, val): + ind = self.order - val + if val > self.order: + return 0 + if val < 0: + return 0 + return self.coeffs[ind] + + def __setitem__(self, key, val): + ind = self.order - key + if key < 0: + raise ValueError, "Does not support negative powers." + if key > self.order: + zr = Numeric.zeros(key-self.order,self.coeffs.typecode()) + self.__dict__['coeffs'] = Numeric.concatenate((zr,self.coeffs)) + self.__dict__['order'] = key + ind = 0 + self.__dict__['coeffs'][ind] = val + return + + def integ(self, m=1, k=0): + return poly1d(polyint(self.coeffs,m=m,k=k)) + + def deriv(self, m=1): + return poly1d(polyder(self.coeffs,m=m)) + +def freqz(b, a, worN=None, whole=0, plot=None): + """Compute frequency response of a digital filter. + + Description: + + Given the numerator (b) and denominator (a) of a digital filter compute + its frequency response. + + jw -jw -jmw + jw B(e) b[0] + b[1]e + .... + b[m]e + H(e) = ---- = ------------------------------------ + jw -jw -jnw + A(e) a[0] + a[2]e + .... + a[n]e + + Inputs: + + b, a --- the numerator and denominator of a linear filter. + worN --- If None, then compute at 512 frequencies around the unit circle. + If a single integer, the compute at that many frequencies. + Otherwise, compute the response at frequencies given in worN + whole -- Normally, frequencies are computed from 0 to pi (upper-half of + unit-circle. If whole is non-zero compute frequencies from 0 + to 2*pi. + + Outputs: (h,w) + + h -- The frequency response. + w -- The frequencies at which h was computed. + """ + b, a = map(atleast_1d, (b,a)) + if whole: + lastpoint = 2*pi + else: + lastpoint = pi + if worN is None: + N = 512 + w = Num.arange(0,lastpoint,lastpoint/N) + elif isinstance(worN, types.IntType): + N = worN + w = Num.arange(0,lastpoint,lastpoint/N) + else: + w = worN + w = atleast_1d(w) + zm1 = exp(-1j*w) + h = polyval(b[::-1], zm1) / polyval(a[::-1], zm1) + # if not plot is None: + # plot(w, h) + return h, w diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/gnuplot_freqz.py b/gnuradio-core/src/python/gnuradio/gruimpl/gnuplot_freqz.py new file mode 100755 index 00000000..5a117605 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/gnuplot_freqz.py @@ -0,0 +1,82 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +__all__ = ['gnuplot_freqz'] + +import tempfile +import os +import math +import Numeric + +from gnuradio import gr +from gnuradio.gruimpl.freqz import freqz + + +def gnuplot_freqz (hw, Fs=None, logfreq=False): + + """hw is a tuple of the form (h, w) where h is sequence of complex + freq responses, and w is a sequence of corresponding frequency + points. Plot the frequency response using gnuplot. If Fs is + provide, use it as the sampling frequency, else use 2*pi. + + Returns a handle to the gnuplot graph. When the handle is reclaimed + the graph is torn down.""" + + data_file = tempfile.NamedTemporaryFile () + cmd_file = os.popen ('gnuplot', 'w') + + h, w = hw + ampl = 20 * Numeric.log10 (Numeric.absolute (h) + 1e-9) + phase = map (lambda x: math.atan2 (x.imag, x.real), h) + + if Fs: + w *= (Fs/(2*math.pi)) + + for freq, a, ph in zip (w, ampl, phase): + data_file.write ("%g\t%g\t%g\n" % (freq, a, ph)) + + data_file.flush () + + cmd_file.write ("set grid\n") + if logfreq: + cmd_file.write ("set logscale x\n") + else: + cmd_file.write ("unset logscale x\n") + cmd_file.write ("plot '%s' using 1:2 with lines\n" % (data_file.name,)) + cmd_file.flush () + + return (cmd_file, data_file) + + +def test_plot (): + sample_rate = 2.0e6 + taps = gr.firdes.low_pass (1.0, # gain + sample_rate, # sampling rate + 200e3, # low pass cutoff freq + 100e3, # width of trans. band + gr.firdes.WIN_HAMMING) + # print len (taps) + return gnuplot_freqz (freqz (taps, 1), sample_rate) + +if __name__ == '__main__': + handle = test_plot () + raw_input ('Press Enter to continue: ') diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/hexint.py b/gnuradio-core/src/python/gnuradio/gruimpl/hexint.py new file mode 100644 index 00000000..1220755c --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/hexint.py @@ -0,0 +1,32 @@ +# +# 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. +# + +def hexint(mask): + """ + Convert unsigned masks into signed ints. + + This allows us to use hex constants like 0xf0f0f0f2 when talking to + our hardware and not get screwed by them getting treated as python + longs. + """ + if mask >= 2**31: + return int(mask-2**32) + return mask diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/listmisc.py b/gnuradio-core/src/python/gnuradio/gruimpl/listmisc.py new file mode 100644 index 00000000..857e417f --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/listmisc.py @@ -0,0 +1,29 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +def list_reverse(x): + """ + Return a copy of x that is reverse order. + """ + r = list(x) + r.reverse() + return r + diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/lmx2306.py b/gnuradio-core/src/python/gnuradio/gruimpl/lmx2306.py new file mode 100755 index 00000000..b46c896f --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/lmx2306.py @@ -0,0 +1,186 @@ +#!/usr/bin/env python +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +'''Control National LMX2306 based frequency synthesizer''' + +from gnuradio import gr +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +# bottom two bits of 21 bit word select which register to program + +R_REG = 0x0 +AB_REG = 0x1 +F_REG = 0x2 + +F_counter_reset = (1 << 2) +F_phase_detector_polarity = (1 << 7) + +F_LD_tri_state = (0 << 4) +F_LD_R_divider_output = (4 << 4) +F_LD_N_divider_output = (2 << 4) +F_LD_serial_data_output = (6 << 4) +F_LD_digital_lock_detect = (1 << 4) +F_LD_open_drain = (5 << 4) +F_LD_high = (3 << 4) +F_LD_low = (7 << 4) + +# F_default = F_LD_digital_lock_detect | F_phase_detector_polarity +F_default = F_LD_open_drain | F_phase_detector_polarity + +# +# 4 control pins: +# CE always high +# LE load enable. When LE goes high, data stored in the shift register +# is loaded into one of the three registers +# CLK data is clocked in on the rising edge +# DATA single data bit. Entered MSB first + +DB_CLK = (1 << 0) +DB_DATA = (1 << 1) +DB_LE = (1 << 2) +DB_CE = (1 << 3) + +class lmx2306 (object): + '''Control the National LMX2306 PLL''' + __slots__ = ['pp', 'shadow', 'fosc', 'r', 'step_size', 'verbose'] + def __init__ (self, fosc, step_size, which_pp = 0): + '''FOSC is the frequency of the reference oscillator, + STEP_SIZE is the step between valid frequencies, + WHICH_PP specifies which parallel port to use + ''' + self.pp = gr.make_ppio (which_pp) + self.shadow = DB_CE + self.pp.lock () + self.pp.write_data (self.shadow) + self.pp.unlock () + self.verbose = False + self._set_fosc (fosc) + self._set_step (step_size) + + + def program (self, r, a, b): + if self.verbose: + print "lmx2306: r = %d a = %d b = %d" % (r, a, b) + self.pp.lock () + self._write_word (F_REG | F_default | F_counter_reset) + self._write_word (R_REG | ((r & 0x3fff) << 2)) + self._write_word (AB_REG | ((a & 0x1f) << 2) | ((b & 0x1fff) << 7)) + self._write_word (F_REG | F_default) + self.pp.unlock () + + def set_freq (self, freq): + '''Set the PLL frequency to FREQ + + Return the actual freq value set. It will be rounded down to a + multiple of step_size + ''' + divisor = int (freq / self.step_size) + actual = divisor * self.step_size + (a, b) = self._compute_ab (divisor) + self.program (self.r, a, b) + return actual + + # ---------------------------------------------------------------- + + def _set_fosc (self, ref_oscillator_freq): + self.fosc = ref_oscillator_freq + + def _set_step (self, step_size): + r = int (self.fosc / step_size) + if r * step_size != self.fosc: + raise ValueError, "step_size is not a factor of self.fosc" + if r < 3 or r > 16383: + raise ValueError, "r is out of range" + self.r = r + self.step_size = step_size + + def _compute_ab (self, divisor): + b = divisor / 8 + a = divisor - (b * 8) + if b < 3 or b > 8191 or a > b: + raise ValueError, "Invalid divisor" + return (a, b) + + def _write_word (self, w): + for i in range(21): + if w & (1 << 20): + self._set_DATA_1 () + else: + self._set_DATA_0 () + w = (w << 1) & 0x0ffffff + self._set_CLK_1 () + self._set_CLK_0 () + self._set_LE_1 () + self._set_LE_0 () + + def _set_LE_0 (self): + self.shadow = self.shadow & ~DB_LE + self.pp.write_data (self.shadow) + + def _set_LE_1 (self): + self.shadow = self.shadow | DB_LE + self.pp.write_data (self.shadow) + + def _set_CLK_0 (self): + self.shadow = self.shadow & ~DB_CLK + self.pp.write_data (self.shadow) + + def _set_CLK_1 (self): + self.shadow = self.shadow | DB_CLK + self.pp.write_data (self.shadow) + + def _set_DATA_0 (self): + self.shadow = self.shadow & ~DB_DATA + self.pp.write_data (self.shadow) + + def _set_DATA_1 (self): + self.shadow = self.shadow | DB_DATA + self.pp.write_data (self.shadow) + +if __name__ == '__main__': + parser = OptionParser (option_class=eng_option) + parser.add_option ("-o", "--fosc", type="eng_float", default=32e6, + help="set reference oscillator freq to FREQ", metavar="FREQ") + parser.add_option ("-s", "--step-size", type="eng_float", default=10e3, + help="set the frequency step size to STEP_SIZE") + parser.add_option ("-f", "--freq", type="eng_float", default=430e6, + help="set VCO frequency to FREQ") + parser.add_option ("-v", "--verbose", action="store_true", default=False) + (options, args) = parser.parse_args () + + if options.verbose: + print "fosc = %s step = %s fvco = %s" % ( + eng_notation.num_to_str (options.fosc), + eng_notation.num_to_str (options.step_size), + eng_notation.num_to_str (options.freq)) + + lmx = lmx2306 (options.fosc, options.step_size) + lmx.verbose = options.verbose + + actual = lmx.set_freq (options.freq) + + if options.verbose: + print "fvco_actual = %s delta = %s" % ( + eng_notation.num_to_str (actual), + eng_notation.num_to_str (options.freq - actual)) diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/mathmisc.py b/gnuradio-core/src/python/gnuradio/gruimpl/mathmisc.py new file mode 100644 index 00000000..13e6de80 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/mathmisc.py @@ -0,0 +1,33 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 + +def gcd(a,b): + while b: + a,b = b, a % b + return a + +def lcm(a,b): + return a * b / gcd(a, b) + +def log2(x): + return math.log(x)/math.log(2) diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/os_read_exactly.py b/gnuradio-core/src/python/gnuradio/gruimpl/os_read_exactly.py new file mode 100644 index 00000000..afdfb514 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/os_read_exactly.py @@ -0,0 +1,36 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 os + +def os_read_exactly(file_descriptor, nbytes): + """ + Replacement for os.read that blocks until it reads exactly nbytes. + + """ + s = '' + while nbytes > 0: + sbuf = os.read(file_descriptor, nbytes) + if not(sbuf): + return '' + nbytes -= len(sbuf) + s = s + sbuf + return s diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/sdr_1000.py b/gnuradio-core/src/python/gnuradio/gruimpl/sdr_1000.py new file mode 100644 index 00000000..5de23b72 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/sdr_1000.py @@ -0,0 +1,84 @@ +# +# Copyright 2003,2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 gnuradio import gr + +class sdr_1000 (gr.sdr_1000_base): + "Control the DDS on the SDR-1000" + def __init__(self, pport = 0): + gr.sdr_1000_base.__init__(self, pport) + self.write_latch (3, 0x00, 0xC0) # Reset low, WRS/ low + self.write_reg (0x20, 0x40) + + def write_reg(self, addr, data): + self.write_latch (3, addr & 0x3f, 0x3f) + self.write_latch (2, data, 0xff) + self.write_latch (3, 0x40, 0x40) + self.write_latch (3, 0x00, 0x40) + + def set_freq(self, freq): + self.set_band (freq) + ftw = freq / 200e6; + for i in xrange(6): + word = int(ftw * 256) + ftw = ftw*256 - word + # print (('%d [%02x]') % (i, word)) + self.write_reg (4+i, word) + + def set_band (self, freq): + if freq <= 2.25e6: + band = 0 + elif freq <= 5.5e6: + band = 1 + elif freq <= 11e6: + band = 3 # due to wiring mistake on board + elif freq <= 22e6: + band = 2 # due to wiring mistake on board + elif freq <= 37.5e6: + band = 4 + else: + band = 5 + + self.write_latch (1, 1 << band, 0x3f) + + def set_bit (self, reg, bit, state): + val = 0x00 + if state: val = 1< 0), "Out of range 1..7" + self.set_bit(0, pin-1, on) diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/seq_with_cursor.py b/gnuradio-core/src/python/gnuradio/gruimpl/seq_with_cursor.py new file mode 100644 index 00000000..5616dea9 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/seq_with_cursor.py @@ -0,0 +1,77 @@ +# +# Copyright 2003,2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# misc utilities + +import types +import exceptions + +class seq_with_cursor (object): + __slots__ = [ 'items', 'index' ] + + def __init__ (self, items, initial_index = None, initial_value = None): + assert len (items) > 0, "seq_with_cursor: len (items) == 0" + self.items = items + self.set_index (initial_index) + if initial_value is not None: + self.set_index_by_value(initial_value) + + def set_index (self, initial_index): + if initial_index is None: + self.index = len (self.items) / 2 + elif initial_index >= 0 and initial_index < len (self.items): + self.index = initial_index + else: + raise exceptions.ValueError + + def set_index_by_value(self, v): + """ + Set index to the smallest value such that items[index] >= v. + If there is no such item, set index to the maximum value. + """ + self.set_index(0) # side effect! + cv = self.current() + more = True + while cv < v and more: + cv, more = self.next() # side effect! + + def next (self): + new_index = self.index + 1 + if new_index < len (self.items): + self.index = new_index + return self.items[new_index], True + else: + return self.items[self.index], False + + def prev (self): + new_index = self.index - 1 + if new_index >= 0: + self.index = new_index + return self.items[new_index], True + else: + return self.items[self.index], False + + def current (self): + return self.items[self.index] + + def get_seq (self): + return self.items[:] # copy of items + diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/socket_stuff.py b/gnuradio-core/src/python/gnuradio/gruimpl/socket_stuff.py new file mode 100644 index 00000000..05be0d43 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gruimpl/socket_stuff.py @@ -0,0 +1,56 @@ +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +# random socket related stuff + +import socket +import os +import sys + +def tcp_connect_or_die(sock_addr): + """ + @param sock_addr: (host, port) to connect to + @type sock_addr: tuple + @returns: socket or exits + """ + s = socket.socket (socket.AF_INET, socket.SOCK_STREAM) + try: + s.connect(sock_addr) + except socket.error, err: + sys.stderr.write('Failed to connect to %s: %s\n' % + (sock_addr, os.strerror (err.args[0]),)) + sys.exit(1) + return s + +def udp_connect_or_die(sock_addr): + """ + @param sock_addr: (host, port) to connect to + @type sock_addr: tuple + @returns: socket or exits + """ + s = socket.socket (socket.AF_INET, socket.SOCK_DGRAM) + try: + s.connect(sock_addr) + except socket.error, err: + sys.stderr.write('Failed to connect to %s: %s\n' % + (sock_addr, os.strerror (err.args[0]),)) + sys.exit(1) + return s diff --git a/gnuradio-core/src/python/gnuradio/optfir.py b/gnuradio-core/src/python/gnuradio/optfir.py new file mode 100644 index 00000000..eb3f321b --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/optfir.py @@ -0,0 +1,242 @@ +# +# 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. +# + +''' +Routines for designing optimal FIR filters. + +For a great intro to how all this stuff works, see section 6.6 of +"Digital Signal Processing: A Practical Approach", Emmanuael C. Ifeachor +and Barrie W. Jervis, Adison-Wesley, 1993. ISBN 0-201-54413-X. +''' + +import math +from gnuradio import gr + +remez = gr.remez + +# ---------------------------------------------------------------- + +def low_pass (gain, Fs, freq1, freq2, passband_ripple_db, stopband_atten_db, + nextra_taps=0): + passband_dev = passband_ripple_to_dev (passband_ripple_db) + stopband_dev = stopband_atten_to_dev (stopband_atten_db) + desired_ampls = (gain, 0) + (n, fo, ao, w) = remezord ([freq1, freq2], desired_ampls, + [passband_dev, stopband_dev], Fs) + taps = gr.remez (n + nextra_taps, fo, ao, w, "bandpass") + return taps + +# FIXME high_passs is broken... +def high_pass (Fs, freq1, freq2, stopband_atten_db, passband_ripple_db, + nextra_taps=0): + """FIXME: broken""" + passband_dev = passband_ripple_to_dev (passband_ripple_db) + stopband_dev = stopband_atten_to_dev (stopband_atten_db) + desired_ampls = (0, 1) + (n, fo, ao, w) = remezord ([freq1, freq2], desired_ampls, + [stopband_dev, passband_dev], Fs) + taps = gr.remez (n + nextra_taps, fo, ao, w, "bandpass") + return taps + +# ---------------------------------------------------------------- + +def stopband_atten_to_dev (atten_db): + """Convert a stopband attenuation in dB to an absolute value""" + return 10**(-atten_db/20) + +def passband_ripple_to_dev (ripple_db): + """Convert passband ripple spec expressed in dB to an absolute value""" + return (10**(ripple_db/20)-1)/(10**(ripple_db/20)+1) + +# ---------------------------------------------------------------- + +def remezord (fcuts, mags, devs, fsamp = 2): + ''' + FIR order estimator (lowpass, highpass, bandpass, mulitiband). + + (n, fo, ao, w) = remezord (f, a, dev) + (n, fo, ao, w) = remezord (f, a, dev, fs) + + (n, fo, ao, w) = remezord (f, a, dev) finds the approximate order, + normalized frequency band edges, frequency band amplitudes, and + weights that meet input specifications f, a, and dev, to use with + the remez command. + + * f is a sequence of frequency band edges (between 0 and Fs/2, where + Fs is the sampling frequency), and a is a sequence specifying the + desired amplitude on the bands defined by f. The length of f is + twice the length of a, minus 2. The desired function is + piecewise constant. + + * dev is a sequence the same size as a that specifies the maximum + allowable deviation or ripples between the frequency response + and the desired amplitude of the output filter, for each band. + + Use remez with the resulting order n, frequency sequence fo, + amplitude response sequence ao, and weights w to design the filter b + which approximately meets the specifications given by remezord + input parameters f, a, and dev: + + b = remez (n, fo, ao, w) + + (n, fo, ao, w) = remezord (f, a, dev, Fs) specifies a sampling frequency Fs. + + Fs defaults to 2 Hz, implying a Nyquist frequency of 1 Hz. You can + therefore specify band edges scaled to a particular applications + sampling frequency. + + In some cases remezord underestimates the order n. If the filter + does not meet the specifications, try a higher order such as n+1 + or n+2. + ''' + # get local copies + fcuts = fcuts[:] + mags = mags[:] + devs = devs[:] + + for i in range (len (fcuts)): + fcuts[i] = float (fcuts[i]) / fsamp + + nf = len (fcuts) + nm = len (mags) + nd = len (devs) + nbands = nm + + if nm != nd: + raise ValueError, "Length of mags and devs must be equal" + + if nf != 2 * (nbands - 1): + raise ValueError, "Length of f must be 2 * len (mags) - 2" + + for i in range (len (mags)): + if mags[i] != 0: # if not stopband, get relative deviation + devs[i] = devs[i] / mags[i] + + # separate the passband and stopband edges + f1 = fcuts[0::2] + f2 = fcuts[1::2] + + n = 0 + min_delta = 2 + for i in range (len (f1)): + if f2[i] - f1[i] < min_delta: + n = i + min_delta = f2[i] - f1[i] + + if nbands == 2: + # lowpass or highpass case (use formula) + l = lporder (f1[n], f2[n], devs[0], devs[1]) + else: + # bandpass or multipass case + # try different lowpasses and take the worst one that + # goes through the BP specs + l = 0 + for i in range (1, nbands-1): + l1 = lporder (f1[i-1], f2[i-1], devs[i], devs[i-1]) + l2 = lporder (f1[i], f2[i], devs[i], devs[i+1]) + l = max (l, l1, l2) + + n = int (math.ceil (l)) - 1 # need order, not length for remez + + # cook up remez compatible result + ff = [0] + fcuts + [1] + for i in range (1, len (ff) - 1): + ff[i] *= 2 + + aa = [] + for a in mags: + aa = aa + [a, a] + + max_dev = max (devs) + wts = [1] * len(devs) + for i in range (len (wts)): + wts[i] = max_dev / devs[i] + + return (n, ff, aa, wts) + +# ---------------------------------------------------------------- + +def lporder (freq1, freq2, delta_p, delta_s): + ''' + FIR lowpass filter length estimator. freq1 and freq2 are + normalized to the sampling frequency. delta_p is the passband + deviation (ripple), delta_s is the stopband deviation (ripple). + + Note, this works for high pass filters too (freq1 > freq2), but + doesnt work well if the transition is near f == 0 or f == fs/2 + + From Herrmann et al (1973), Practical design rules for optimum + finite impulse response filters. Bell System Technical J., 52, 769-99 + ''' + df = abs (freq2 - freq1) + ddp = math.log10 (delta_p) + dds = math.log10 (delta_s) + + a1 = 5.309e-3 + a2 = 7.114e-2 + a3 = -4.761e-1 + a4 = -2.66e-3 + a5 = -5.941e-1 + a6 = -4.278e-1 + + b1 = 11.01217 + b2 = 0.5124401 + + t1 = a1 * ddp * ddp + t2 = a2 * ddp + t3 = a4 * ddp * ddp + t4 = a5 * ddp + + dinf=((t1 + t2 + a3) * dds) + (t3 + t4 + a6) + ff = b1 + b2 * (ddp - dds) + n = dinf / df - ff * df + 1 + return n + + +def bporder (freq1, freq2, delta_p, delta_s): + ''' + FIR bandpass filter length estimator. freq1 and freq2 are + normalized to the sampling frequency. delta_p is the passband + deviation (ripple), delta_s is the stopband deviation (ripple). + + From Mintzer and Liu (1979) + ''' + df = abs (freq2 - freq1) + ddp = math.log10 (delta_p) + dds = math.log10 (delta_s) + + a1 = 0.01201 + a2 = 0.09664 + a3 = -0.51325 + a4 = 0.00203 + a5 = -0.57054 + a6 = -0.44314 + + t1 = a1 * ddp * ddp + t2 = a2 * ddp + t3 = a4 * ddp * ddp + t4 = a5 * ddp + + cinf = dds * (t1 + t2 + a3) + t3 + t4 + a6 + ginf = -14.6 * math.log10 (delta_p / delta_s) - 16.9 + n = cinf / df + ginf * df + 1 + return n + diff --git a/gnuradio-core/src/python/gnuradio/packet_utils.py b/gnuradio-core/src/python/gnuradio/packet_utils.py new file mode 100644 index 00000000..d7235540 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/packet_utils.py @@ -0,0 +1,433 @@ +# +# 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. +# + +import struct +import Numeric +from gnuradio import gru + + +def conv_packed_binary_string_to_1_0_string(s): + """ + '\xAF' --> '10101111' + """ + r = [] + for ch in s: + x = ord(ch) + for i in range(7,-1,-1): + t = (x >> i) & 0x1 + r.append(t) + + return ''.join(map(lambda x: chr(x + ord('0')), r)) + +def conv_1_0_string_to_packed_binary_string(s): + """ + '10101111' -> ('\xAF', False) + + Basically the inverse of conv_packed_binary_string_to_1_0_string, + but also returns a flag indicating if we had to pad with leading zeros + to get to a multiple of 8. + """ + if not is_1_0_string(s): + raise ValueError, "Input must be a string containing only 0's and 1's" + + # pad to multiple of 8 + padded = False + rem = len(s) % 8 + if rem != 0: + npad = 8 - rem + s = '0' * npad + s + padded = True + + assert len(s) % 8 == 0 + + r = [] + i = 0 + while i < len(s): + t = 0 + for j in range(8): + t = (t << 1) | (ord(s[i + j]) - ord('0')) + r.append(chr(t)) + i += 8 + return (''.join(r), padded) + + +default_access_code = \ + conv_packed_binary_string_to_1_0_string('\xAC\xDD\xA4\xE2\xF2\x8C\x20\xFC') + + +def is_1_0_string(s): + if not isinstance(s, str): + return False + for ch in s: + if not ch in ('0', '1'): + return False + return True + +def string_to_hex_list(s): + return map(lambda x: hex(ord(x)), s) + + +def whiten(s): + sa = Numeric.fromstring(s, Numeric.UnsignedInt8) + z = sa ^ random_mask_vec8[0:len(sa)] + return z.tostring() + +def dewhiten(s): + return whiten(s) # self inverse + + +def make_header(payload_len): + return struct.pack('!HH', payload_len, payload_len) + +def make_packet(payload, spb, bits_per_baud, access_code=default_access_code, pad_for_usrp=True): + """ + Build a packet, given access code and payload. + + @param payload: packet payload, len [0, 4096] + @param spb: samples per baud (needed for padding calculation) + @type spb: int + @param bits_per_baud: (needed for padding calculation) + @type bits_per_baud: int + @param access_code: string of ascii 0's and 1's + + Packet will have access code at the beginning, followed by length, payload + and finally CRC-32. + """ + if not is_1_0_string(access_code): + raise ValueError, "access_code must be a string containing only 0's and 1's (%r)" % (access_code,) + + (packed_access_code, padded) = conv_1_0_string_to_packed_binary_string(access_code) + + payload_with_crc = gru.gen_and_append_crc32(payload) + #print "outbound crc =", string_to_hex_list(payload_with_crc[-4:]) + + L = len(payload_with_crc) + MAXLEN = len(random_mask_tuple) + if L > MAXLEN: + raise ValueError, "len(payload) must be in [0, %d]" % (MAXLEN,) + + pkt = ''.join((packed_access_code, make_header(L), whiten(payload_with_crc), '\x55')) + if pad_for_usrp: + pkt = pkt + (_npadding_bytes(len(pkt), spb, bits_per_baud) * '\x55') + + #print "make_packet: len(pkt) =", len(pkt) + return pkt + +def _npadding_bytes(pkt_byte_len, spb, bits_per_baud): + """ + Generate sufficient padding such that each packet ultimately ends + up being a multiple of 512 bytes when sent across the USB. We + send 4-byte samples across the USB (16-bit I and 16-bit Q), thus + we want to pad so that after modulation the resulting packet + is a multiple of 128 samples. + + @param ptk_byte_len: len in bytes of packet, not including padding. + @param spb: samples per baud == samples per bit (1 bit / baud with GMSK) + @type spb: int + + @returns number of bytes of padding to append. + """ + modulus = 128 + byte_modulus = gru.lcm(modulus/8, spb) * bits_per_baud / spb + r = pkt_byte_len % byte_modulus + if r == 0: + return 0 + return byte_modulus - r + + +def unmake_packet(whitened_payload_with_crc): + """ + Return (ok, payload) + + @param whitened_payload_with_crc: string + """ + payload_with_crc = dewhiten(whitened_payload_with_crc) + ok, payload = gru.check_crc32(payload_with_crc) + + if 0: + print "payload_with_crc =", string_to_hex_list(payload_with_crc) + print "ok = %r, len(payload) = %d" % (ok, len(payload)) + print "payload =", string_to_hex_list(payload) + + return ok, payload + + +# FYI, this PN code is the output of a 15-bit LFSR +random_mask_tuple = ( + 255, 63, 0, 16, 0, 12, 0, 5, 192, 3, 16, 1, 204, 0, 85, 192, + 63, 16, 16, 12, 12, 5, 197, 195, 19, 17, 205, 204, 85, 149, 255, 47, + 0, 28, 0, 9, 192, 6, 208, 2, 220, 1, 153, 192, 106, 208, 47, 28, + 28, 9, 201, 198, 214, 210, 222, 221, 152, 89, 170, 186, 255, 51, 0, 21, + 192, 15, 16, 4, 12, 3, 69, 193, 243, 16, 69, 204, 51, 21, 213, 207, + 31, 20, 8, 15, 70, 132, 50, 227, 85, 137, 255, 38, 192, 26, 208, 11, + 28, 7, 73, 194, 182, 209, 182, 220, 118, 217, 230, 218, 202, 219, 23, 27, + 78, 139, 116, 103, 103, 106, 170, 175, 63, 60, 16, 17, 204, 12, 85, 197, + 255, 19, 0, 13, 192, 5, 144, 3, 44, 1, 221, 192, 89, 144, 58, 236, + 19, 13, 205, 197, 149, 147, 47, 45, 220, 29, 153, 201, 170, 214, 255, 30, + 192, 8, 80, 6, 188, 2, 241, 193, 132, 80, 99, 124, 41, 225, 222, 200, + 88, 86, 186, 190, 243, 48, 69, 212, 51, 31, 85, 200, 63, 22, 144, 14, + 236, 4, 77, 195, 117, 145, 231, 44, 74, 157, 247, 41, 134, 158, 226, 232, + 73, 142, 182, 228, 118, 203, 102, 215, 106, 222, 175, 24, 124, 10, 161, 199, + 56, 82, 146, 189, 173, 177, 189, 180, 113, 183, 100, 118, 171, 102, 255, 106, + 192, 47, 16, 28, 12, 9, 197, 198, 211, 18, 221, 205, 153, 149, 170, 239, + 63, 12, 16, 5, 204, 3, 21, 193, 207, 16, 84, 12, 63, 69, 208, 51, + 28, 21, 201, 207, 22, 212, 14, 223, 68, 88, 51, 122, 149, 227, 47, 9, + 220, 6, 217, 194, 218, 209, 155, 28, 107, 73, 239, 118, 204, 38, 213, 218, + 223, 27, 24, 11, 74, 135, 119, 34, 166, 153, 186, 234, 243, 15, 5, 196, + 3, 19, 65, 205, 240, 85, 132, 63, 35, 80, 25, 252, 10, 193, 199, 16, + 82, 140, 61, 165, 209, 187, 28, 115, 73, 229, 246, 203, 6, 215, 66, 222, + 177, 152, 116, 106, 167, 111, 58, 172, 19, 61, 205, 209, 149, 156, 111, 41, + 236, 30, 205, 200, 85, 150, 191, 46, 240, 28, 68, 9, 243, 70, 197, 242, + 211, 5, 157, 195, 41, 145, 222, 236, 88, 77, 250, 181, 131, 55, 33, 214, + 152, 94, 234, 184, 79, 50, 180, 21, 183, 79, 54, 180, 22, 247, 78, 198, + 180, 82, 247, 125, 134, 161, 162, 248, 121, 130, 162, 225, 185, 136, 114, 230, + 165, 138, 251, 39, 3, 90, 129, 251, 32, 67, 88, 49, 250, 148, 67, 47, + 113, 220, 36, 89, 219, 122, 219, 99, 27, 105, 203, 110, 215, 108, 94, 173, + 248, 125, 130, 161, 161, 184, 120, 114, 162, 165, 185, 187, 50, 243, 85, 133, + 255, 35, 0, 25, 192, 10, 208, 7, 28, 2, 137, 193, 166, 208, 122, 220, + 35, 25, 217, 202, 218, 215, 27, 30, 139, 72, 103, 118, 170, 166, 255, 58, + 192, 19, 16, 13, 204, 5, 149, 195, 47, 17, 220, 12, 89, 197, 250, 211, + 3, 29, 193, 201, 144, 86, 236, 62, 205, 208, 85, 156, 63, 41, 208, 30, + 220, 8, 89, 198, 186, 210, 243, 29, 133, 201, 163, 22, 249, 206, 194, 212, + 81, 159, 124, 104, 33, 238, 152, 76, 106, 181, 239, 55, 12, 22, 133, 206, + 227, 20, 73, 207, 118, 212, 38, 223, 90, 216, 59, 26, 147, 75, 45, 247, + 93, 134, 185, 162, 242, 249, 133, 130, 227, 33, 137, 216, 102, 218, 170, 219, + 63, 27, 80, 11, 124, 7, 97, 194, 168, 81, 190, 188, 112, 113, 228, 36, + 75, 91, 119, 123, 102, 163, 106, 249, 239, 2, 204, 1, 149, 192, 111, 16, + 44, 12, 29, 197, 201, 147, 22, 237, 206, 205, 148, 85, 175, 127, 60, 32, + 17, 216, 12, 90, 133, 251, 35, 3, 89, 193, 250, 208, 67, 28, 49, 201, + 212, 86, 223, 126, 216, 32, 90, 152, 59, 42, 147, 95, 45, 248, 29, 130, + 137, 161, 166, 248, 122, 194, 163, 17, 185, 204, 114, 213, 229, 159, 11, 40, + 7, 94, 130, 184, 97, 178, 168, 117, 190, 167, 48, 122, 148, 35, 47, 89, + 220, 58, 217, 211, 26, 221, 203, 25, 151, 74, 238, 183, 12, 118, 133, 230, + 227, 10, 201, 199, 22, 210, 142, 221, 164, 89, 187, 122, 243, 99, 5, 233, + 195, 14, 209, 196, 92, 83, 121, 253, 226, 193, 137, 144, 102, 236, 42, 205, + 223, 21, 152, 15, 42, 132, 31, 35, 72, 25, 246, 138, 198, 231, 18, 202, + 141, 151, 37, 174, 155, 60, 107, 81, 239, 124, 76, 33, 245, 216, 71, 26, + 178, 139, 53, 167, 87, 58, 190, 147, 48, 109, 212, 45, 159, 93, 168, 57, + 190, 146, 240, 109, 132, 45, 163, 93, 185, 249, 178, 194, 245, 145, 135, 44, + 98, 157, 233, 169, 142, 254, 228, 64, 75, 112, 55, 100, 22, 171, 78, 255, + 116, 64, 39, 112, 26, 164, 11, 59, 71, 83, 114, 189, 229, 177, 139, 52, + 103, 87, 106, 190, 175, 48, 124, 20, 33, 207, 88, 84, 58, 191, 83, 48, + 61, 212, 17, 159, 76, 104, 53, 238, 151, 12, 110, 133, 236, 99, 13, 233, + 197, 142, 211, 36, 93, 219, 121, 155, 98, 235, 105, 143, 110, 228, 44, 75, + 93, 247, 121, 134, 162, 226, 249, 137, 130, 230, 225, 138, 200, 103, 22, 170, + 142, 255, 36, 64, 27, 112, 11, 100, 7, 107, 66, 175, 113, 188, 36, 113, + 219, 100, 91, 107, 123, 111, 99, 108, 41, 237, 222, 205, 152, 85, 170, 191, + 63, 48, 16, 20, 12, 15, 69, 196, 51, 19, 85, 205, 255, 21, 128, 15, + 32, 4, 24, 3, 74, 129, 247, 32, 70, 152, 50, 234, 149, 143, 47, 36, + 28, 27, 73, 203, 118, 215, 102, 222, 170, 216, 127, 26, 160, 11, 56, 7, + 82, 130, 189, 161, 177, 184, 116, 114, 167, 101, 186, 171, 51, 63, 85, 208, + 63, 28, 16, 9, 204, 6, 213, 194, 223, 17, 152, 12, 106, 133, 239, 35, + 12, 25, 197, 202, 211, 23, 29, 206, 137, 148, 102, 239, 106, 204, 47, 21, + 220, 15, 25, 196, 10, 211, 71, 29, 242, 137, 133, 166, 227, 58, 201, 211, + 22, 221, 206, 217, 148, 90, 239, 123, 12, 35, 69, 217, 243, 26, 197, 203, + 19, 23, 77, 206, 181, 148, 119, 47, 102, 156, 42, 233, 223, 14, 216, 4, + 90, 131, 123, 33, 227, 88, 73, 250, 182, 195, 54, 209, 214, 220, 94, 217, + 248, 90, 194, 187, 17, 179, 76, 117, 245, 231, 7, 10, 130, 135, 33, 162, + 152, 121, 170, 162, 255, 57, 128, 18, 224, 13, 136, 5, 166, 131, 58, 225, + 211, 8, 93, 198, 185, 146, 242, 237, 133, 141, 163, 37, 185, 219, 50, 219, + 85, 155, 127, 43, 96, 31, 104, 8, 46, 134, 156, 98, 233, 233, 142, 206, + 228, 84, 75, 127, 119, 96, 38, 168, 26, 254, 139, 0, 103, 64, 42, 176, + 31, 52, 8, 23, 70, 142, 178, 228, 117, 139, 103, 39, 106, 154, 175, 43, + 60, 31, 81, 200, 60, 86, 145, 254, 236, 64, 77, 240, 53, 132, 23, 35, + 78, 153, 244, 106, 199, 111, 18, 172, 13, 189, 197, 177, 147, 52, 109, 215, + 109, 158, 173, 168, 125, 190, 161, 176, 120, 116, 34, 167, 89, 186, 186, 243, + 51, 5, 213, 195, 31, 17, 200, 12, 86, 133, 254, 227, 0, 73, 192, 54, + 208, 22, 220, 14, 217, 196, 90, 211, 123, 29, 227, 73, 137, 246, 230, 198, + 202, 210, 215, 29, 158, 137, 168, 102, 254, 170, 192, 127, 16, 32, 12, 24, + 5, 202, 131, 23, 33, 206, 152, 84, 106, 191, 111, 48, 44, 20, 29, 207, + 73, 148, 54, 239, 86, 204, 62, 213, 208, 95, 28, 56, 9, 210, 134, 221, + 162, 217, 185, 154, 242, 235, 5, 143, 67, 36, 49, 219, 84, 91, 127, 123, + 96, 35, 104, 25, 238, 138, 204, 103, 21, 234, 143, 15, 36, 4, 27, 67, + 75, 113, 247, 100, 70, 171, 114, 255, 101, 128, 43, 32, 31, 88, 8, 58, + 134, 147, 34, 237, 217, 141, 154, 229, 171, 11, 63, 71, 80, 50, 188, 21, + 177, 207, 52, 84, 23, 127, 78, 160, 52, 120, 23, 98, 142, 169, 164, 126, + 251, 96, 67, 104, 49, 238, 148, 76, 111, 117, 236, 39, 13, 218, 133, 155, + 35, 43, 89, 223, 122, 216, 35, 26, 153, 203, 42, 215, 95, 30, 184, 8, + 114, 134, 165, 162, 251, 57, 131, 82, 225, 253, 136, 65, 166, 176, 122, 244, + 35, 7, 89, 194, 186, 209, 179, 28, 117, 201, 231, 22, 202, 142, 215, 36, + 94, 155, 120, 107, 98, 175, 105, 188, 46, 241, 220, 68, 89, 243, 122, 197, + 227, 19, 9, 205, 198, 213, 146, 223, 45, 152, 29, 170, 137, 191, 38, 240, + 26, 196, 11, 19, 71, 77, 242, 181, 133, 183, 35, 54, 153, 214, 234, 222, + 207, 24, 84, 10, 191, 71, 48, 50, 148, 21, 175, 79, 60, 52, 17, 215, + 76, 94, 181, 248, 119, 2, 166, 129, 186, 224, 115, 8, 37, 198, 155, 18, + 235, 77, 143, 117, 164, 39, 59, 90, 147, 123, 45, 227, 93, 137, 249, 166, + 194, 250, 209, 131, 28, 97, 201, 232, 86, 206, 190, 212, 112, 95, 100, 56, + 43, 82, 159, 125, 168, 33, 190, 152, 112, 106, 164, 47, 59, 92, 19, 121, + 205, 226, 213, 137, 159, 38, 232, 26, 206, 139, 20, 103, 79, 106, 180, 47, + 55, 92, 22, 185, 206, 242, 212, 69, 159, 115, 40, 37, 222, 155, 24, 107, + 74, 175, 119, 60, 38, 145, 218, 236, 91, 13, 251, 69, 131, 115, 33, 229, + 216, 75, 26, 183, 75, 54, 183, 86, 246, 190, 198, 240, 82, 196, 61, 147, + 81, 173, 252, 125, 129, 225, 160, 72, 120, 54, 162, 150, 249, 174, 194, 252, + 81, 129, 252, 96, 65, 232, 48, 78, 148, 52, 111, 87, 108, 62, 173, 208, + 125, 156, 33, 169, 216, 126, 218, 160, 91, 56, 59, 82, 147, 125, 173, 225, + 189, 136, 113, 166, 164, 122, 251, 99, 3, 105, 193, 238, 208, 76, 92, 53, + 249, 215, 2, 222, 129, 152, 96, 106, 168, 47, 62, 156, 16, 105, 204, 46, + 213, 220, 95, 25, 248, 10, 194, 135, 17, 162, 140, 121, 165, 226, 251, 9, + 131, 70, 225, 242, 200, 69, 150, 179, 46, 245, 220, 71, 25, 242, 138, 197, + 167, 19, 58, 141, 211, 37, 157, 219, 41, 155, 94, 235, 120, 79, 98, 180, + 41, 183, 94, 246, 184, 70, 242, 178, 197, 181, 147, 55, 45, 214, 157, 158, + 233, 168, 78, 254, 180, 64, 119, 112, 38, 164, 26, 251, 75, 3, 119, 65, + 230, 176, 74, 244, 55, 7, 86, 130, 190, 225, 176, 72, 116, 54, 167, 86, + 250, 190, 195, 48, 81, 212, 60, 95, 81, 248, 60, 66, 145, 241, 172, 68, + 125, 243, 97, 133, 232, 99, 14, 169, 196, 126, 211, 96, 93, 232, 57, 142, + 146, 228, 109, 139, 109, 167, 109, 186, 173, 179, 61, 181, 209, 183, 28, 118, + 137, 230, 230, 202, 202, 215, 23, 30, 142, 136, 100, 102, 171, 106, 255, 111, + 0, 44, 0, 29, 192, 9, 144, 6, 236, 2, 205, 193, 149, 144, 111, 44, + 44, 29, 221, 201, 153, 150, 234, 238, 207, 12, 84, 5, 255, 67, 0, 49, + 192, 20, 80, 15, 124, 4, 33, 195, 88, 81, 250, 188, 67, 49, 241, 212, + 68, 95, 115, 120, 37, 226, 155, 9, 171, 70, 255, 114, 192, 37, 144, 27, + 44, 11, 93, 199, 121, 146, 162, 237, 185, 141, 178, 229, 181, 139, 55, 39, + 86, 154, 190, 235, 48, 79, 84, 52, 63, 87, 80, 62, 188, 16, 113, 204, + 36, 85, 219, 127, 27, 96, 11, 104, 7, 110, 130, 172, 97, 189, 232, 113, + 142, 164, 100, 123, 107, 99, 111, 105, 236, 46, 205, 220, 85, 153, 255, 42, + 192, 31, 16, 8, 12, 6, 133, 194, 227, 17, 137, 204, 102, 213, 234, 223, + 15, 24, 4, 10, 131, 71, 33, 242, 152, 69, 170, 179, 63, 53, 208, 23, + 28, 14, 137, 196, 102, 211, 106, 221, 239, 25, 140, 10, 229, 199, 11, 18, + 135, 77, 162, 181, 185, 183, 50, 246, 149, 134, 239, 34, 204, 25, 149, 202, + 239, 23, 12, 14, 133, 196, 99, 19, 105, 205, 238, 213, 140, 95, 37, 248, + 27, 2, 139, 65, 167, 112, 122, 164, 35, 59, 89, 211, 122, 221, 227, 25, + 137, 202, 230, 215, 10, 222, 135, 24, 98, 138, 169, 167, 62, 250, 144, 67, + 44, 49, 221, 212, 89, 159, 122, 232, 35, 14, 153, 196, 106, 211, 111, 29, + 236, 9, 141, 198, 229, 146, 203, 45, 151, 93, 174, 185, 188, 114, 241, 229, + 132, 75, 35, 119, 89, 230, 186, 202, 243, 23, 5, 206, 131, 20, 97, 207, + 104, 84, 46, 191, 92, 112, 57, 228, 18, 203, 77, 151, 117, 174, 167, 60, + 122, 145, 227, 44, 73, 221, 246, 217, 134, 218, 226, 219, 9, 155, 70, 235, + 114, 207, 101, 148, 43, 47, 95, 92, 56, 57, 210, 146, 221, 173, 153, 189, + 170, 241, 191, 4, 112, 3, 100, 1, 235, 64, 79, 112, 52, 36, 23, 91, + 78, 187, 116, 115, 103, 101, 234, 171, 15, 63, 68, 16, 51, 76, 21, 245, + 207, 7, 20, 2, 143, 65, 164, 48, 123, 84, 35, 127, 89, 224, 58, 200, + 19, 22, 141, 206, 229, 148, 75, 47, 119, 92, 38, 185, 218, 242, 219, 5, + 155, 67, 43, 113, 223, 100, 88, 43, 122, 159, 99, 40, 41, 222, 158, 216, + 104, 90, 174, 187, 60, 115, 81, 229, 252, 75, 1, 247, 64, 70, 176, 50, + 244, 21, 135, 79, 34, 180, 25, 183, 74, 246, 183, 6, 246, 130, 198, 225, + 146, 200, 109, 150, 173, 174, 253, 188, 65, 177, 240, 116, 68, 39, 115, 90, + 165, 251, 59, 3, 83, 65, 253, 240, 65, 132, 48, 99, 84, 41, 255, 94, + 192, 56, 80, 18, 188, 13, 177, 197, 180, 83, 55, 125, 214, 161, 158, 248, + 104, 66, 174, 177, 188, 116, 113, 231, 100, 74, 171, 119, 63, 102, 144, 42, + 236, 31, 13, 200, 5, 150, 131, 46, 225, 220, 72, 89, 246, 186, 198, 243, + 18, 197, 205, 147, 21, 173, 207, 61, 148, 17, 175, 76, 124, 53, 225, 215, + 8, 94, 134, 184, 98, 242, 169, 133, 190, 227, 48, 73, 212, 54, 223, 86, + 216, 62, 218, 144, 91, 44, 59, 93, 211, 121, 157, 226, 233, 137, 142, 230, + 228, 74, 203, 119, 23, 102, 142, 170, 228, 127, 11, 96, 7, 104, 2, 174, + 129, 188, 96, 113, 232, 36, 78, 155, 116, 107, 103, 111, 106, 172, 47, 61, + 220, 17, 153, 204, 106, 213, 239, 31, 12, 8, 5, 198, 131, 18, 225, 205, + 136, 85, 166, 191, 58, 240, 19, 4, 13, 195, 69, 145, 243, 44, 69, 221, + 243, 25, 133, 202, 227, 23, 9, 206, 134, 212, 98, 223, 105, 152, 46, 234, + 156, 79, 41, 244, 30, 199, 72, 82, 182, 189, 182, 241, 182, 196, 118, 211, + 102, 221, 234, 217, 143, 26, 228, 11, 11, 71, 71, 114, 178, 165, 181, 187, + 55, 51, 86, 149, 254, 239, 0, 76, 0, 53, 192, 23, 16, 14, 140, 4, + 101, 195, 107, 17, 239, 76, 76, 53, 245, 215, 7, 30, 130, 136, 97, 166, + 168, 122, 254, 163, 0, 121, 192, 34, 208, 25, 156, 10, 233, 199, 14, 210, + 132, 93, 163, 121, 185, 226, 242, 201, 133, 150, 227, 46, 201, 220, 86, 217, + 254, 218, 192, 91, 16, 59, 76, 19, 117, 205, 231, 21, 138, 143, 39, 36, + 26, 155, 75, 43, 119, 95, 102, 184, 42, 242, 159, 5, 168, 3, 62, 129, + 208, 96, 92, 40, 57, 222, 146, 216, 109, 154, 173, 171, 61, 191, 81, 176, + 60, 116, 17, 231, 76, 74, 181, 247, 55, 6, 150, 130, 238, 225, 140, 72, + 101, 246, 171, 6, 255, 66, 192, 49, 144, 20, 108, 15, 109, 196, 45, 147, + 93, 173, 249, 189, 130, 241, 161, 132, 120, 99, 98, 169, 233, 190, 206, 240, + 84, 68, 63, 115, 80, 37, 252, 27, 1, 203, 64, 87, 112, 62, 164, 16, + 123, 76, 35, 117, 217, 231, 26, 202, 139, 23, 39, 78, 154, 180, 107, 55, + 111, 86, 172, 62, 253, 208, 65, 156, 48, 105, 212, 46, 223, 92, 88, 57, + 250, 146, 195, 45, 145, 221, 172, 89, 189, 250, 241, 131, 4, 97, 195, 104, + 81, 238, 188, 76, 113, 245, 228, 71, 11, 114, 135, 101, 162, 171, 57, 191, + 82, 240, 61, 132, 17, 163, 76, 121, 245, 226, 199, 9, 146, 134, 237, 162, + 205, 185, 149, 178, 239, 53, 140, 23, 37, 206, 155, 20, 107, 79, 111, 116, + 44, 39, 93, 218, 185, 155, 50, 235, 85, 143, 127, 36, 32, 27, 88, 11, + 122, 135, 99, 34, 169, 217, 190, 218, 240, 91, 4, 59, 67, 83, 113, 253, + 228, 65, 139, 112, 103, 100, 42, 171, 95, 63, 120, 16, 34, 140, 25, 165, + 202, 251, 23, 3, 78, 129, 244, 96, 71, 104, 50, 174, 149, 188, 111, 49, + 236, 20, 77, 207, 117, 148, 39, 47, 90, 156, 59, 41, 211, 94, 221, 248, + 89, 130, 186, 225, 179, 8, 117, 198, 167, 18, 250, 141, 131, 37, 161, 219, + 56, 91, 82, 187, 125, 179, 97, 181, 232, 119, 14, 166, 132, 122, 227, 99, + 9, 233, 198, 206, 210, 212, 93, 159, 121, 168, 34, 254, 153, 128, 106, 224, + 47, 8, 28, 6, 137, 194, 230, 209, 138, 220, 103, 25, 234, 138, 207, 39, + 20, 26, 143, 75, 36, 55, 91, 86, 187, 126, 243, 96, 69, 232, 51, 14, + 149, 196, 111, 19, 108, 13, 237, 197, 141, 147, 37, 173, 219, 61, 155, 81, + 171, 124, 127, 97, 224, 40, 72, 30, 182, 136, 118, 230, 166, 202, 250, 215, + 3, 30, 129, 200, 96, 86, 168, 62, 254, 144, 64, 108, 48, 45, 212, 29, + 159, 73, 168, 54, 254, 150, 192, 110, 208, 44, 92, 29, 249, 201, 130, 214, + 225, 158, 200, 104, 86, 174, 190, 252, 112, 65, 228, 48, 75, 84, 55, 127, + 86, 160, 62, 248, 16, 66, 140, 49, 165, 212, 123, 31, 99, 72, 41, 246, + 158, 198, 232, 82, 206, 189, 148, 113, 175, 100, 124, 43, 97, 223, 104, 88, + 46, 186, 156, 115, 41, 229, 222, 203, 24, 87, 74, 190, 183, 48, 118, 148, + 38, 239, 90, 204, 59, 21, 211, 79, 29, 244, 9, 135, 70, 226, 178, 201, + 181, 150, 247, 46, 198, 156, 82, 233, 253, 142, 193, 164, 80, 123, 124, 35, + 97, 217, 232, 90, 206, 187, 20, 115, 79, 101, 244, 43, 7, 95, 66, 184, + 49, 178, 148, 117, 175, 103, 60, 42, 145, 223, 44, 88, 29, 250, 137, 131, + 38, 225, 218, 200, 91, 22, 187, 78, 243, 116, 69, 231, 115, 10, 165, 199, + 59, 18, 147, 77, 173, 245, 189, 135, 49, 162, 148, 121, 175, 98, 252, 41, + 129, 222, 224, 88, 72, 58, 182, 147, 54, 237, 214, 205, 158, 213, 168, 95, + 62, 184, 16, 114, 140, 37, 165, 219, 59, 27, 83, 75, 125, 247, 97, 134, + 168, 98, 254, 169, 128, 126, 224, 32, 72, 24, 54, 138, 150, 231, 46, 202, + 156, 87, 41, 254, 158, 192, 104, 80, 46, 188, 28, 113, 201, 228, 86, 203, + 126, 215, 96, 94, 168, 56, 126, 146, 160, 109, 184, 45, 178, 157, 181, 169, + 183, 62, 246, 144, 70, 236, 50, 205, 213, 149, 159, 47, 40, 28, 30, 137, + 200, 102, 214, 170, 222, 255, 24, 64, 10, 176, 7, 52, 2, 151, 65, 174, + 176, 124, 116, 33, 231, 88, 74, 186, 183, 51, 54, 149, 214, 239, 30, 204, + 8, 85, 198, 191, 18, 240, 13, 132, 5, 163, 67, 57, 241, 210, 196, 93, + 147, 121, 173, 226, 253, 137, 129, 166, 224, 122, 200, 35, 22, 153, 206, 234, + 212, 79, 31, 116, 8, 39, 70, 154, 178, 235, 53, 143, 87, 36, 62, 155, + 80, 107, 124, 47, 97, 220, 40, 89, 222, 186, 216, 115, 26, 165, 203, 59, + 23, 83, 78, 189, 244, 113, 135, 100, 98, 171, 105, 191, 110, 240, 44, 68, + 29, 243, 73, 133, 246, 227, 6, 201, 194, 214, 209, 158, 220, 104, 89, 238, + 186, 204, 115, 21, 229, 207, 11, 20, 7, 79, 66, 180, 49, 183, 84, 118, + 191, 102, 240, 42, 196, 31, 19, 72, 13, 246, 133, 134, 227, 34, 201, 217, + 150, 218, 238, 219, 12, 91, 69, 251, 115, 3, 101, 193, 235, 16, 79, 76, + 52, 53, 215, 87, 30, 190, 136, 112, 102, 164, 42, 251, 95, 3, 120, 1, + 226, 128, 73, 160, 54, 248, 22, 194, 142, 209, 164, 92, 123, 121, 227, 98, + 201, 233, 150, 206, 238, 212, 76, 95, 117, 248, 39, 2, 154, 129, 171, 32, + 127, 88, 32, 58, 152, 19, 42, 141, 223, 37, 152, 27, 42, 139, 95, 39, + 120, 26, 162, 139, 57, 167, 82, 250, 189, 131, 49, 161, 212, 120, 95, 98, + 184, 41, 178, 158, 245, 168, 71, 62, 178, 144, 117, 172, 39, 61, 218, 145, + 155, 44, 107, 93, 239, 121, 140, 34, 229, 217, 139, 26, 231, 75, 10, 183, + 71, 54, 178, 150, 245, 174, 199, 60, 82, 145, 253, 172, 65, 189, 240, 113, + 132, 36, 99, 91, 105, 251, 110, 195, 108, 81, 237, 252, 77, 129, 245, 160, + 71, 56, 50, 146, 149, 173, 175, 61, 188, 17, 177, 204, 116, 85, 231, 127, + 10, 160, 7, 56, 2, 146, 129, 173, 160, 125, 184, 33, 178, 152, 117, 170, + 167, 63, 58, 144, 19, 44, 13, 221, 197, 153, 147, 42, 237, 223, 13, 152, + 5, 170, 131, 63, 33, 208, 24, 92, 10, 185, 199, 50, 210, 149, 157, 175, + 41, 188, 30, 241, 200, 68, 86, 179, 126, 245, 224, 71, 8, 50, 134, 149, + 162, 239, 57, 140, 18, 229, 205, 139, 21, 167, 79, 58, 180, 19, 55, 77, + 214, 181, 158, 247, 40, 70, 158, 178, 232, 117, 142, 167, 36, 122, 155, 99, + 43, 105, 223, 110, 216, 44, 90, 157, 251, 41, 131, 94, 225, 248, 72, 66, + 182, 177, 182, 244, 118, 199, 102, 210, 170, 221, 191, 25, 176, 10, 244, 7, + 7, 66, 130, 177, 161, 180, 120, 119, 98, 166, 169, 186, 254, 243, 0, 69, + 192, 51, 16, 21, 204, 15, 21, 196, 15, 19, 68, 13, 243, 69, 133, 243, + 35, 5, 217, 195, 26, 209, 203, 28, 87, 73, 254, 182, 192, 118, 208, 38, + 220, 26, 217, 203, 26, 215, 75, 30, 183, 72, 118, 182, 166, 246, 250, 198, + 195, 18, 209, 205, 156, 85, 169, 255, 62, 192, 16, 80, 12, 60, 5, 209, + 195, 28, 81, 201, 252, 86, 193, 254, 208, 64, 92, 48, 57, 212, 18, 223, + 77, 152, 53, 170, 151, 63, 46, 144, 28, 108, 9, 237, 198, 205, 146, 213, + 173, 159, 61, 168, 17, 190, 140, 112, 101, 228, 43, 11, 95, 71, 120, 50, + 162, 149, 185, 175, 50, 252, 21, 129, 207, 32, 84, 24, 63, 74, 144, 55, + 44, 22, 157, 206, 233, 148, 78, 239, 116, 76, 39, 117, 218, 167, 27, 58, + 139, 83, 39, 125, 218, 161, 155, 56, 107, 82, 175, 125, 188, 33, 177, 216, + 116, 90, 167, 123, 58, 163, 83, 57, 253, 210, 193, 157, 144, 105, 172, 46, + 253, 220, 65, 153, 240, 106, 196, 47, 19, 92, 13, 249, 197, 130, 211, 33, + 157, 216, 105, 154, 174, 235, 60, 79, 81, 244, 60, 71, 81, 242, 188, 69, + 177, 243, 52, 69, 215, 115, 30, 165, 200, 123, 22, 163, 78, 249, 244, 66, + 199, 113, 146, 164, 109, 187, 109, 179, 109, 181, 237, 183, 13, 182, 133, 182, + 227, 54, 201, 214, 214, 222, 222, 216, 88, 90, 186, 187, 51, 51, 255, 63 ) + +random_mask_vec8 = Numeric.array(random_mask_tuple, Numeric.UnsignedInt8) + diff --git a/gnuradio-core/src/python/gnuradio/window.py b/gnuradio-core/src/python/gnuradio/window.py new file mode 100644 index 00000000..391b83c3 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/window.py @@ -0,0 +1,190 @@ +# +# 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. +# + +''' +Routines for designing window functions. +''' + +import math +from gnuradio import gr + +def izero(x): + izeroepsilon = 1e-21 + halfx = x/2.0 + accum = u = n = 1 + while 1: + temp = halfx/n + n += 1 + temp *= temp + u *= temp + accum += u + if u >= IzeroEPSILON*sum: + break + return accum + +def midm1(fft_size): + return (fft_size - 1)/2 + +def midp1(fft_size): + return (fft_size+1)/2 + +def freq(fft_size): + return 2.0*math.pi/fft_size + +def rate(fft_size): + return 1.0/(fft_size >> 1) + +def expn(fft_size): + math.log(2.0)/(midn(fft_size) + 1.0) + +def hamming(fft_size): + window = [] + for index in xrange(fft_size): + window.append(0.54 - 0.46 * math.cos (2 * math.pi / fft_size * index)) # Hamming window + return window + +def hanning(fft_size): + window = [] + for index in xrange(fft_size): + window.append(0.5 - 0.5 * math.cos (2 * math.pi / fft_size * index)) # von Hann window + return window + +def welch(fft_size): + window = [0 for i in range(fft_size)] + j = fft_size-1 + for index in xrange(midn(fft_size)+1): + window[j] = window[index] = (1.0 - math.sqrt((index - midm1(fft_size)) / midp1(fft_size))) + j -= 1 + return window + +def parzen(fft_size): + window = [0 for i in range(fft_size)] + j = fft_size-1 + for index in xrange(midn(fft_size)+1): + window[j] = window[index] = (1.0 - math.abs((index - midm1(fft_size)) / midp1(fft_size))) + j -= 1 + return window + +def bartlett(fft_size): + mfrq = freq(fft_size) + angle = 0 + window = [0 for i in range(fft_size)] + j = fft_size-1 + for index in xrange(midn(fft_size)+1): + window[j] = window[index] = angle + angle += freq + j -= 1 + return window + +def blackman2(fft_size): + mfrq = freq(fft_size) + angle = 0 + window = [0 for i in range(fft_size)] + j = fft_size-1 + for index in xrange(midn(fft_size)+1): + cx = math.cos(angle) + window[j] = window[index] = (.34401 + (cx * (-.49755 + (cx * .15844)))) + angle += freq + j -= 1 + return window + +def blackman3(fft_size): + mfrq = freq(fft_size) + angle = 0 + window = [0 for i in range(fft_size)] + j = fft_size-1 + for index in xrange(midn(fft_size)+1): + cx = math.cos(angle) + window[j] = window[index] = (.21747 + (cx * (-.45325 + (cx * (.28256 - (cx * .04672)))))) + angle += freq + j -= 1 + return window + +def blackman4(fft_size): + mfrq = freq(fft_size) + angle = 0 + window = [0 for i in range(fft_size)] + j = fft_size-1 + for index in xrange(midn(fft_size)+1): + cx = math.cos(angle) + window[j] = window[index] = (.084037 + (cx * (-.29145 + (cx * (.375696 + (cx * (-.20762 + (cx * .041194)))))))) + angle += freq + j -= 1 + return window + +def exponential(fft_size): + expsum = 1.0 + window = [0 for i in range(fft_size)] + j = fft_size-1 + for index in xrange(midn(fft_size)+1): + window[j] = window[i] = (expsum - 1.0) + expsum *= expn(fft_size) + j -= 1 + return window + +def riemann(fft_size): + sr1 = freq(fft_size) + window = [0 for i in range(fft_size)] + j = fft_size-1 + for index in xrange(midn(fft_size)): + if index == midn(fft_size): + window[index] = window[j] = 1.0 + else: + cx = sr1*midn(fft_size) - index + window[index] = window[j] = math.sin(cx)/cx + j -= 1 + return window + +def blackmanharris(fft_size): + a0 = 0.35875 + a1 = 0.48829 + a2 = 0.14128 + a3 = 0.01168 + window = [0 for i in range(fft_size)] + for index in xrange(fft_size): + window[index] = a0 + window[index] -= a1*math.cos(2.0*math.pi*(index+0.5)/(fft_size - 1)) + window[index] += a2*math.cos(4.0*math.pi*(index+0.5)/(fft_size - 1)) + window[index] -= a3*math.cos(6.0*math.pi*(index+0.5)/(fft_size - 1)) + return window + +def nuttall(fft_size): + a0 = 0.3635819 + a1 = 0.4891775 + a2 = 0.1365995 + a3 = 0.0106411 + window = [0 for i in range(fft_size)] + for index in xrange(fft_size): + window[index] = a0 + window[index] -= a1*math.cos(2.0*math.pi*(index+0.5)/(fft_size - 1)) + window[index] += a2*math.cos(4.0*math.pi*(index+0.5)/(fft_size - 1)) + window[index] -= a3*math.cos(6.0*math.pi*(index+0.5)/(fft_size - 1)) + return window + +def kaiser(fft_size,beta): + ibeta = 1.0/izero(beta) + inm1 = 1.0/(fft_size) + window = [0 for i in range(fft_size)] + for index in xrange(fft_size): + window[index] = izero(beta*math.sqrt(1.0 - (index * inm1)*(index * inm1))) * ibeta + return window + + diff --git a/gnuradio-core/src/tests/Makefile.am b/gnuradio-core/src/tests/Makefile.am new file mode 100644 index 00000000..1dd3dd06 --- /dev/null +++ b/gnuradio-core/src/tests/Makefile.am @@ -0,0 +1,96 @@ +# +# 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 + +INCLUDES = $(STD_DEFINES_AND_INCLUDES) $(CPPUNIT_INCLUDES) + +# list of programs run by "make check" and "make distcheck" + +TESTS = test_all + + +# test_atsc + +#Test program to test setting up buffers using gr_test which can be run manually +EXTRA_DIST = \ + test_buffers.py + +noinst_PROGRAMS = \ + benchmark_dotprod \ + benchmark_dotprod_fsf \ + benchmark_dotprod_fcc \ + benchmark_dotprod_scc \ + benchmark_dotprod_ccc \ + benchmark_dotprod_ccf \ + benchmark_nco \ + benchmark_vco \ + test_runtime \ + test_general \ + test_all \ + test_filter \ + test_vmcircbuf + + +LIBGNURADIO = $(top_builddir)/gnuradio-core/src/lib/libgnuradio-core.la +LIBGNURADIOQA = $(top_builddir)/gnuradio-core/src/lib/libgnuradio-core-qa.la $(LIBGNURADIO) + +benchmark_dotprod_SOURCES = benchmark_dotprod.cc +benchmark_dotprod_LDADD = $(LIBGNURADIO) + +benchmark_dotprod_fsf_SOURCES = benchmark_dotprod_fsf.cc +benchmark_dotprod_fsf_LDADD = $(LIBGNURADIO) + +benchmark_dotprod_ccf_SOURCES = benchmark_dotprod_ccf.cc +benchmark_dotprod_ccf_LDADD = $(LIBGNURADIO) + +benchmark_dotprod_fcc_SOURCES = benchmark_dotprod_fcc.cc +benchmark_dotprod_fcc_LDADD = $(LIBGNURADIO) + +benchmark_dotprod_scc_SOURCES = benchmark_dotprod_scc.cc +benchmark_dotprod_scc_LDADD = $(LIBGNURADIO) + +benchmark_dotprod_ccc_SOURCES = benchmark_dotprod_ccc.cc +benchmark_dotprod_ccc_LDADD = $(LIBGNURADIO) + +benchmark_nco_SOURCES = benchmark_nco.cc +benchmark_nco_LDADD = $(LIBGNURADIO) + +benchmark_vco_SOURCES = benchmark_vco.cc +benchmark_vco_LDADD = $(LIBGNURADIO) + +test_runtime_SOURCES = test_runtime.cc +test_runtime_LDADD = $(LIBGNURADIOQA) + +test_general_SOURCES = test_general.cc +test_general_LDADD = $(LIBGNURADIOQA) + +test_filter_SOURCES = test_filter.cc +test_filter_LDADD = $(LIBGNURADIOQA) + +# test_atsc_SOURCES = test_atsc.cc +#test_atsc_LDADD = $(LIBGNURADIOQA) + +test_vmcircbuf_SOURCES = test_vmcircbuf.cc +test_vmcircbuf_LDADD = $(LIBGNURADIOQA) + +test_all_SOURCES = test_all.cc +test_all_LDADD = $(LIBGNURADIOQA) diff --git a/gnuradio-core/src/tests/benchmark_dotprod.cc b/gnuradio-core/src/tests/benchmark_dotprod.cc new file mode 100644 index 00000000..8986f725 --- /dev/null +++ b/gnuradio-core/src/tests/benchmark_dotprod.cc @@ -0,0 +1,148 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU 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 +#include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif + +#include +#include +#include +#include + +#define TOTAL_TEST_SIZE (40 * 1000 * 1000L) +#define NTAPS 256 +#define BLOCK_SIZE (50 * 1000) /* fits in cache */ + +#if ((TOTAL_TEST_SIZE % BLOCK_SIZE) != 0) +#error "TOTAL_TEST_SIZE % BLOCK_SIZE must equal 0" +#endif + +typedef gr_fir_fff* (*fir_maker_t)(const std::vector &taps); +typedef gr_fir_fff filter_t; + + +static double +timeval_to_double (const struct timeval *tv) +{ + return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6; +} + + +static void +benchmark (fir_maker_t filter_maker, const char *implementation_name) +{ + int i; + float coeffs[NTAPS]; + float input[BLOCK_SIZE + NTAPS]; + long n; + float result; +#ifdef HAVE_SYS_RESOURCE_H + struct rusage rusage_start; + struct rusage rusage_stop; +#else + double clock_start; + double clock_end; +#endif + // setup coefficients and input data + + for (i = 0; i < NTAPS; i++) + coeffs[i] = random() - RANDOM_MAX/2; + + for (i = 0; i < BLOCK_SIZE + NTAPS; i++) + input[i] = random() - RANDOM_MAX/2; + + std::vector taps (&coeffs[0], &coeffs[NTAPS]); + filter_t *f = filter_maker (taps); + + // get starting CPU usage +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_start) < 0){ + perror ("getrusage"); + exit (1); + } +#else + clock_start = (double) clock() * (1000000. / CLOCKS_PER_SEC); +#endif + // do the actual work + + for (n = 0; n < TOTAL_TEST_SIZE; n += BLOCK_SIZE){ + int j; + for (j = 0; j < BLOCK_SIZE; j++){ + result = f->filter (&input[j]); + } + } + + // get ending CPU usage +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_stop) < 0){ + perror ("getrusage"); + exit (1); + } + + // compute results + + double user = + timeval_to_double (&rusage_stop.ru_utime) + - timeval_to_double (&rusage_start.ru_utime); + + double sys = + timeval_to_double (&rusage_stop.ru_stime) + - timeval_to_double (&rusage_start.ru_stime); + + double total = user + sys; +#else + clock_end = (double) clock () * (1000000. / CLOCKS_PER_SEC); + double total = clock_end -clock_start; +#endif + double macs = NTAPS * (double) TOTAL_TEST_SIZE; + + printf ("%10s: taps: %4d input: %4g cpu: %6.3f taps/sec: %10.4g \n", + implementation_name, NTAPS, (double) TOTAL_TEST_SIZE, total, macs / total); + + delete f; +} + +static void +do_all () +{ + std::vector info; + gr_fir_util::get_gr_fir_fff_info (&info); // get all known FFF implementations + + for (std::vector::iterator p = info.begin (); + p != info.end (); + ++p){ + + benchmark (p->create, p->name); + } +} + +int +main (int argc, char **argv) +{ + do_all (); + return 0; +} diff --git a/gnuradio-core/src/tests/benchmark_dotprod_ccc.cc b/gnuradio-core/src/tests/benchmark_dotprod_ccc.cc new file mode 100644 index 00000000..afc24e07 --- /dev/null +++ b/gnuradio-core/src/tests/benchmark_dotprod_ccc.cc @@ -0,0 +1,149 @@ +/* -*- 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 +#include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +#include +#include +#include +#include + +#define TOTAL_TEST_SIZE (40 * 1000 * 1000L) +#define NTAPS 256 +#define BLOCK_SIZE (50 * 1000) /* fits in cache */ + +#if ((TOTAL_TEST_SIZE % BLOCK_SIZE) != 0) +#error "TOTAL_TEST_SIZE % BLOCK_SIZE must equal 0" +#endif + +typedef gr_fir_ccc* (*fir_maker_t)(const std::vector &taps); +typedef gr_fir_ccc filter_t; + + +static double +timeval_to_double (const struct timeval *tv) +{ + return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6; +} + + +static void +benchmark (fir_maker_t filter_maker, const char *implementation_name) +{ + int i; + gr_complex coeffs[NTAPS]; + gr_complex input[BLOCK_SIZE + NTAPS]; + long n; + gr_complex result; +#ifdef HAVE_SYS_RESOURCE_H + struct rusage rusage_start; + struct rusage rusage_stop; +#else + double clock_start; + double clock_end; +#endif + + + // setup coefficients and input data + + for (i = 0; i < NTAPS; i++) + coeffs[i] = gr_complex(random() - RANDOM_MAX/2, random() - RANDOM_MAX/2); + + for (i = 0; i < BLOCK_SIZE + NTAPS; i++) + input[i] = gr_complex(random() - RANDOM_MAX/2, random() - RANDOM_MAX/2); + + std::vector taps (&coeffs[0], &coeffs[NTAPS]); + filter_t *f = filter_maker (taps); + + // get starting CPU usage +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_start) < 0){ + perror ("getrusage"); + exit (1); + } +#else + clock_start= (double) clock() * (1000000. / CLOCKS_PER_SEC); +#endif + // do the actual work + + for (n = 0; n < TOTAL_TEST_SIZE; n += BLOCK_SIZE){ + int j; + for (j = 0; j < BLOCK_SIZE; j++){ + result = f->filter ((gr_complex*)&input[j]); + } + } + + // get ending CPU usage +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_stop) < 0){ + perror ("getrusage"); + exit (1); + } + + // compute results + + double user = + timeval_to_double (&rusage_stop.ru_utime) + - timeval_to_double (&rusage_start.ru_utime); + + double sys = + timeval_to_double (&rusage_stop.ru_stime) + - timeval_to_double (&rusage_start.ru_stime); + + double total = user + sys; +#else + clock_end = (double) clock() * (1000000. / CLOCKS_PER_SEC); + double total = clock_end - clock_start; +#endif + + double macs = NTAPS * (double) TOTAL_TEST_SIZE; + + printf ("%10s: taps: %4d input: %4g cpu: %6.3f taps/sec: %10.4g \n", + implementation_name, NTAPS, (double) TOTAL_TEST_SIZE, total, macs / total); + + delete f; +} + +static void +do_all () +{ + std::vector info; + gr_fir_util::get_gr_fir_ccc_info (&info); // get all known CCC implementations + + for (std::vector::iterator p = info.begin (); + p != info.end () ; + ++p){ + benchmark (p->create, p->name); + } +} + +int +main (int argc, char **argv) +{ + do_all (); + return 0; +} diff --git a/gnuradio-core/src/tests/benchmark_dotprod_ccf.cc b/gnuradio-core/src/tests/benchmark_dotprod_ccf.cc new file mode 100644 index 00000000..866f7f61 --- /dev/null +++ b/gnuradio-core/src/tests/benchmark_dotprod_ccf.cc @@ -0,0 +1,151 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU 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 +#include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +#include +#include +#include +#include + +#define TOTAL_TEST_SIZE (40 * 1000 * 1000L) +#define NTAPS 256 +#define BLOCK_SIZE (50 * 1000) /* fits in cache */ + +#if ((TOTAL_TEST_SIZE % BLOCK_SIZE) != 0) +#error "TOTAL_TEST_SIZE % BLOCK_SIZE must equal 0" +#endif + +typedef gr_fir_ccf* (*fir_maker_t)(const std::vector &taps); +typedef gr_fir_ccf filter_t; + + +static double +timeval_to_double (const struct timeval *tv) +{ + return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6; +} + + +static void +benchmark (fir_maker_t filter_maker, const char *implementation_name) +{ + int i; + float coeffs[NTAPS]; + gr_complex input[BLOCK_SIZE + NTAPS]; + long n; + gr_complex result; +#ifdef HAVE_SYS_RESOURCE_H + struct rusage rusage_start; + struct rusage rusage_stop; +#else + double clock_start; + double clock_end; +#endif + + // setup coefficients and input data + + for (i = 0; i < NTAPS; i++) + coeffs[i] = random() - RANDOM_MAX/2; + + for (i = 0; i < BLOCK_SIZE + NTAPS; i++) + input[i] = gr_complex(random() - RANDOM_MAX/2, random() - RANDOM_MAX/2); + + std::vector taps (&coeffs[0], &coeffs[NTAPS]); + filter_t *f = filter_maker (taps); + + // get starting CPU usage + +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_start) < 0){ + perror ("getrusage"); + exit (1); + } +#else + clock_start= (double) clock() * (1000000. / CLOCKS_PER_SEC); +#endif + + // do the actual work + + for (n = 0; n < TOTAL_TEST_SIZE; n += BLOCK_SIZE){ + int j; + for (j = 0; j < BLOCK_SIZE; j++){ + result = f->filter (&input[j]); + } + } + + // get ending CPU usage + +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_stop) < 0){ + perror ("getrusage"); + exit (1); + } + + // compute results + + double user = + timeval_to_double (&rusage_stop.ru_utime) + - timeval_to_double (&rusage_start.ru_utime); + + double sys = + timeval_to_double (&rusage_stop.ru_stime) + - timeval_to_double (&rusage_start.ru_stime); + + double total = user + sys; +#else + clock_end= (double) clock() * (1000000. / CLOCKS_PER_SEC); + double total = clock_end - clock_start; +#endif + + double macs = NTAPS * (double) TOTAL_TEST_SIZE; + + printf ("%10s: taps: %4d input: %4g cpu: %6.3f taps/sec: %10.4g \n", + implementation_name, NTAPS, (double) TOTAL_TEST_SIZE, total, macs / total); + + delete f; +} + +static void +do_all () +{ + std::vector info; + gr_fir_util::get_gr_fir_ccf_info (&info); // get all known CCF implementations + + for (std::vector::iterator p = info.begin (); + p != info.end () ; + ++p){ + benchmark (p->create, p->name); + } +} + +int +main (int argc, char **argv) +{ + do_all (); + return 0; +} diff --git a/gnuradio-core/src/tests/benchmark_dotprod_fcc.cc b/gnuradio-core/src/tests/benchmark_dotprod_fcc.cc new file mode 100644 index 00000000..af54707b --- /dev/null +++ b/gnuradio-core/src/tests/benchmark_dotprod_fcc.cc @@ -0,0 +1,152 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU 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 +#include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +#include +#include +#include +#include + +#define TOTAL_TEST_SIZE (40 * 1000 * 1000L) +#define NTAPS 256 +#define BLOCK_SIZE (50 * 1000) /* fits in cache */ + +#if ((TOTAL_TEST_SIZE % BLOCK_SIZE) != 0) +#error "TOTAL_TEST_SIZE % BLOCK_SIZE must equal 0" +#endif + +typedef gr_fir_fcc* (*fir_maker_t)(const std::vector &taps); +typedef gr_fir_fcc filter_t; + + +static double +timeval_to_double (const struct timeval *tv) +{ + return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6; +} + + +static void +benchmark (fir_maker_t filter_maker, const char *implementation_name) +{ + int i; + gr_complex coeffs[NTAPS]; + float input[BLOCK_SIZE + NTAPS]; + long n; + gr_complex result; +#ifdef HAVE_SYS_RESOURCE_H + struct rusage rusage_start; + struct rusage rusage_stop; +#else + double clock_start; + double clock_end; +#endif + + + + // setup coefficients and input data + + for (i = 0; i < NTAPS; i++) + coeffs[i] = gr_complex(random() - RANDOM_MAX/2, random() - RANDOM_MAX/2); + + for (i = 0; i < BLOCK_SIZE + NTAPS; i++) + input[i] = random() - RANDOM_MAX/2; + + std::vector taps (&coeffs[0], &coeffs[NTAPS]); + filter_t *f = filter_maker (taps); + + // get starting CPU usage +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_start) < 0){ + perror ("getrusage"); + exit (1); + } +#else + clock_start = (double) clock() * (1000000. / CLOCKS_PER_SEC); +#endif + + // do the actual work + + for (n = 0; n < TOTAL_TEST_SIZE; n += BLOCK_SIZE){ + int j; + for (j = 0; j < BLOCK_SIZE; j++){ + result = f->filter (&input[j]); + } + } + + // get ending CPU usage + +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_stop) < 0){ + perror ("getrusage"); + exit (1); + } + + // compute results + + double user = + timeval_to_double (&rusage_stop.ru_utime) + - timeval_to_double (&rusage_start.ru_utime); + + double sys = + timeval_to_double (&rusage_stop.ru_stime) + - timeval_to_double (&rusage_start.ru_stime); + + double total = user + sys; +#else + clock_end= (double) clock() * (1000000. / CLOCKS_PER_SEC); + double total = clock_end - clock_start; +#endif + + double macs = NTAPS * (double) TOTAL_TEST_SIZE; + + printf ("%10s: taps: %4d input: %4g cpu: %6.3f taps/sec: %10.4g \n", + implementation_name, NTAPS, (double) TOTAL_TEST_SIZE, total, macs / total); + + delete f; +} + +static void +do_all () +{ + std::vector info; + gr_fir_util::get_gr_fir_fcc_info (&info); // get all known FCC implementations + + for (std::vector::iterator p = info.begin (); + p != info.end () ; + ++p){ + benchmark (p->create, p->name); + } +} + +int +main (int argc, char **argv) +{ + do_all (); + return 0; +} diff --git a/gnuradio-core/src/tests/benchmark_dotprod_fsf.cc b/gnuradio-core/src/tests/benchmark_dotprod_fsf.cc new file mode 100644 index 00000000..7317e839 --- /dev/null +++ b/gnuradio-core/src/tests/benchmark_dotprod_fsf.cc @@ -0,0 +1,151 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU 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 +#include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +#include +#include +#include +#include + +#define TOTAL_TEST_SIZE (40 * 1000 * 1000L) +#define NTAPS 256 +#define BLOCK_SIZE (50 * 1000) /* fits in cache */ + +#if ((TOTAL_TEST_SIZE % BLOCK_SIZE) != 0) +#error "TOTAL_TEST_SIZE % BLOCK_SIZE must equal 0" +#endif + +typedef gr_fir_fsf* (*fir_maker_t)(const std::vector &taps); +typedef gr_fir_fsf filter_t; + + +static double +timeval_to_double (const struct timeval *tv) +{ + return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6; +} + + +static void +benchmark (fir_maker_t filter_maker, const char *implementation_name) +{ + int i; + float coeffs[NTAPS]; + float input[BLOCK_SIZE + NTAPS]; + long n; + short result; +#ifdef HAVE_SYS_RESOURCE_H + struct rusage rusage_start; + struct rusage rusage_stop; +#else + double clock_start; + double clock_end; +#endif + + // setup coefficients and input data + + for (i = 0; i < NTAPS; i++) + coeffs[i] = random() - RANDOM_MAX/2; + + for (i = 0; i < BLOCK_SIZE + NTAPS; i++) + input[i] = random() - RANDOM_MAX/2; + + std::vector taps (&coeffs[0], &coeffs[NTAPS]); + filter_t *f = filter_maker (taps); + + // get starting CPU usage +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_start) < 0){ + perror ("getrusage"); + exit (1); + } +#else + clock_start= (double) clock() * (1000000. / CLOCKS_PER_SEC); +#endif + + // do the actual work + + for (n = 0; n < TOTAL_TEST_SIZE; n += BLOCK_SIZE){ + int j; + for (j = 0; j < BLOCK_SIZE; j++){ + result = f->filter (&input[j]); + } + } + + // get ending CPU usage + +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_stop) < 0){ + perror ("getrusage"); + exit (1); + } + + // compute results + + double user = + timeval_to_double (&rusage_stop.ru_utime) + - timeval_to_double (&rusage_start.ru_utime); + + double sys = + timeval_to_double (&rusage_stop.ru_stime) + - timeval_to_double (&rusage_start.ru_stime); + + double total = user + sys; +#else + clock_end= (double) clock() * (1000000. / CLOCKS_PER_SEC); + double total = clock_end - clock_start; +#endif + + double macs = NTAPS * (double) TOTAL_TEST_SIZE; + + printf ("%10s: taps: %4d input: %4g cpu: %6.3f taps/sec: %10.4g \n", + implementation_name, NTAPS, (double) TOTAL_TEST_SIZE, total, macs / total); + + delete f; +} + +static void +do_all () +{ + std::vector info; + gr_fir_util::get_gr_fir_fsf_info (&info); // get all known FFF implementations + + for (std::vector::iterator p = info.begin (); + p != info.end (); + ++p){ + + benchmark (p->create, p->name); + } +} + +int +main (int argc, char **argv) +{ + do_all (); + return 0; +} diff --git a/gnuradio-core/src/tests/benchmark_dotprod_scc.cc b/gnuradio-core/src/tests/benchmark_dotprod_scc.cc new file mode 100644 index 00000000..d67fad55 --- /dev/null +++ b/gnuradio-core/src/tests/benchmark_dotprod_scc.cc @@ -0,0 +1,151 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU 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 +#include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +#include +#include +#include +#include + +#define TOTAL_TEST_SIZE (40 * 1000 * 1000L) +#define NTAPS 256 +#define BLOCK_SIZE (50 * 1000) /* fits in cache */ + +#if ((TOTAL_TEST_SIZE % BLOCK_SIZE) != 0) +#error "TOTAL_TEST_SIZE % BLOCK_SIZE must equal 0" +#endif + +typedef gr_fir_scc* (*fir_maker_t)(const std::vector &taps); +typedef gr_fir_scc filter_t; + + +static double +timeval_to_double (const struct timeval *tv) +{ + return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6; +} + + +static void +benchmark (fir_maker_t filter_maker, const char *implementation_name) +{ + int i; + gr_complex coeffs[NTAPS]; + short input[BLOCK_SIZE + NTAPS]; + long n; + gr_complex result; +#ifdef HAVE_SYS_RESOURCE_H + struct rusage rusage_start; + struct rusage rusage_stop; +#else + double clock_start; + double clock_end; +#endif + + + // setup coefficients and input data + + for (i = 0; i < NTAPS; i++) + coeffs[i] = gr_complex(random() - RANDOM_MAX/2, random() - RANDOM_MAX/2); + + for (i = 0; i < BLOCK_SIZE + NTAPS; i++) + input[i] = random() - RANDOM_MAX/2; + + std::vector taps (&coeffs[0], &coeffs[NTAPS]); + filter_t *f = filter_maker (taps); + + // get starting CPU usage + +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_start) < 0){ + perror ("getrusage"); + exit (1); + } +#else + clock_start = (double) clock() * (1000000. / CLOCKS_PER_SEC); +#endif + + // do the actual work + + for (n = 0; n < TOTAL_TEST_SIZE; n += BLOCK_SIZE){ + int j; + for (j = 0; j < BLOCK_SIZE; j++){ + result = f->filter (&input[j]); + } + } + + // get ending CPU usage +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_stop) < 0){ + perror ("getrusage"); + exit (1); + } + + // compute results + + double user = + timeval_to_double (&rusage_stop.ru_utime) + - timeval_to_double (&rusage_start.ru_utime); + + double sys = + timeval_to_double (&rusage_stop.ru_stime) + - timeval_to_double (&rusage_start.ru_stime); + + double total = user + sys; +#else + clock_end= (double) clock () * (1000000. / CLOCKS_PER_SEC); + double total = clock_end -clock_start; +#endif + + double macs = NTAPS * (double) TOTAL_TEST_SIZE; + + printf ("%10s: taps: %4d input: %4g cpu: %6.3f taps/sec: %10.4g \n", + implementation_name, NTAPS, (double) TOTAL_TEST_SIZE, total, macs / total); + + delete f; +} + +static void +do_all () +{ + std::vector info; + gr_fir_util::get_gr_fir_scc_info (&info); // get all known SCC implementations + + for (std::vector::iterator p = info.begin (); + p != info.end () ; + ++p){ + benchmark (p->create, p->name); + } +} + +int +main (int argc, char **argv) +{ + do_all (); + return 0; +} diff --git a/gnuradio-core/src/tests/benchmark_nco.cc b/gnuradio-core/src/tests/benchmark_nco.cc new file mode 100644 index 00000000..fb0fe687 --- /dev/null +++ b/gnuradio-core/src/tests/benchmark_nco.cc @@ -0,0 +1,219 @@ +/* -*- 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. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +#include +#include +#include + +#define ITERATIONS 20000000 +#define BLOCK_SIZE (10 * 1000) // fits in cache + +#define FREQ 5003.123 + +static double +timeval_to_double (const struct timeval *tv) +{ + return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6; +} + + +static void +benchmark (void test (float *x, float *y), const char *implementation_name) +{ +#ifdef HAVE_SYS_RESOURCE_H + struct rusage rusage_start; + struct rusage rusage_stop; +#else + double clock_start; + double clock_end; +#endif + float output[2*BLOCK_SIZE]; + float *x = &output[0], *y = &output[BLOCK_SIZE]; + + // touch memory + memset(output, 0, 2*BLOCK_SIZE*sizeof(float)); + + // get starting CPU usage +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_start) < 0){ + perror ("getrusage"); + exit (1); + } +#else + clock_start = (double) clock() * (1000000. / CLOCKS_PER_SEC); +#endif + // do the actual work + + test (x, y); + + // get ending CPU usage + +#ifdef HAVE_SYS_RESOURCE_H + if (getrusage (RUSAGE_SELF, &rusage_stop) < 0){ + perror ("getrusage"); + exit (1); + } + + // compute results + + double user = + timeval_to_double (&rusage_stop.ru_utime) + - timeval_to_double (&rusage_start.ru_utime); + + double sys = + timeval_to_double (&rusage_stop.ru_stime) + - timeval_to_double (&rusage_start.ru_stime); + + double total = user + sys; +#else + clock_end = (double) clock () * (1000000. / CLOCKS_PER_SEC); + double total = clock_end - clock_start; +#endif + + printf ("%18s: cpu: %6.3f steps/sec: %10.3e\n", + implementation_name, total, ITERATIONS / total); +} + +// ---------------------------------------------------------------- +// Don't compare the _vec with other functions since memory store's +// are involved. + +void basic_sincos_vec (float *x, float *y) +{ + gr_nco nco; + + nco.set_freq (2 * M_PI / FREQ); + + for (int i = 0; i < ITERATIONS/BLOCK_SIZE; i++){ + for (int j = 0; j < BLOCK_SIZE; j++){ + nco.sincos (&x[2*j+1], &x[2*j]); + nco.step (); + } + } +} + +void native_sincos_vec (float *x, float *y) +{ + gr_nco nco; + + nco.set_freq (2 * M_PI / FREQ); + + for (int i = 0; i < ITERATIONS/BLOCK_SIZE; i++){ + nco.sincos ((gr_complex*)x, BLOCK_SIZE); + } +} + +void fxpt_sincos_vec (float *x, float *y) +{ + gr_fxpt_nco nco; + + nco.set_freq (2 * M_PI / FREQ); + + for (int i = 0; i < ITERATIONS/BLOCK_SIZE; i++){ + nco.sincos ((gr_complex*)x, BLOCK_SIZE); + } +} + +// ---------------------------------------------------------------- + +void native_sincos (float *x, float *y) +{ + gr_nco nco; + + nco.set_freq (2 * M_PI / FREQ); + + for (int i = 0; i < ITERATIONS; i++){ + nco.sincos (x, y); + nco.step (); + } +} + +void fxpt_sincos (float *x, float *y) +{ + gr_fxpt_nco nco; + + nco.set_freq (2 * M_PI / FREQ); + + for (int i = 0; i < ITERATIONS; i++){ + nco.sincos (x, y); + nco.step (); + } +} + +// ---------------------------------------------------------------- + +void native_sin (float *x, float *y) +{ + gr_nco nco; + + nco.set_freq (2 * M_PI / FREQ); + + for (int i = 0; i < ITERATIONS; i++){ + *x = nco.sin (); + nco.step (); + } +} + +void fxpt_sin (float *x, float *y) +{ + gr_fxpt_nco nco; + + nco.set_freq (2 * M_PI / FREQ); + + for (int i = 0; i < ITERATIONS; i++){ + *x = nco.sin (); + nco.step (); + } +} + +// ---------------------------------------------------------------- + +void nop_fct (float *x, float *y) +{ +} + +void nop_loop (float *x, float *y) +{ + for (int i = 0; i < ITERATIONS; i++){ + nop_fct (x, y); + } +} + +int +main (int argc, char **argv) +{ + benchmark (nop_loop, "nop loop"); + benchmark (native_sin, "native sine"); + benchmark (fxpt_sin, "fxpt sine"); + benchmark (native_sincos, "native sin/cos"); + benchmark (fxpt_sincos, "fxpt sin/cos"); + benchmark (basic_sincos_vec, "basic sin/cos vec"); + benchmark (native_sincos_vec, "native sin/cos vec"); + benchmark (fxpt_sincos_vec, "fxpt sin/cos vec"); +} diff --git a/gnuradio-core/src/tests/benchmark_vco.cc b/gnuradio-core/src/tests/benchmark_vco.cc new file mode 100644 index 00000000..1b290dfa --- /dev/null +++ b/gnuradio-core/src/tests/benchmark_vco.cc @@ -0,0 +1,166 @@ +/* -*- 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. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif +#include +#include +#include + +#define ITERATIONS 5000000 +#define BLOCK_SIZE (10 * 1000) // fits in cache + +#define FREQ 5003.123 +#define K 4.9999999 +#define AMPLITUDE 2.444444444 + + +static double +timeval_to_double (const struct timeval *tv) +{ + return (double) tv->tv_sec + (double) tv->tv_usec * 1e-6; +} + + +static void +benchmark (void test (float *x, const float *y), const char *implementation_name) +{ +#ifdef HAVE_SYS_RESOURCE_H + struct rusage rusage_start; + struct rusage rusage_stop; +#else + double clock_start; + double clock_end; +#endif + float output[BLOCK_SIZE]; + float input[BLOCK_SIZE]; + + // touch memory + memset(output, 0, BLOCK_SIZE*sizeof(float)); + for (int i = 0; i 2 * M_PI) + phase -= 2 * M_PI; + + while (phase < -2 * M_PI) + phase += 2 * M_PI; + } + } +} + +void native_vco (float *output, const float *input) +{ + gr_vco vco; + + for (int j = 0; j < ITERATIONS/BLOCK_SIZE; j++){ + vco.cos(output, input, BLOCK_SIZE, K, AMPLITUDE); + } + } + +void fxpt_vco (float *output, const float *input) +{ + gr_fxpt_vco vco; + + for (int j = 0; j < ITERATIONS/BLOCK_SIZE; j++){ + vco.cos(output, input, BLOCK_SIZE, K, AMPLITUDE); + } +} + +// ---------------------------------------------------------------- + +void nop_fct (float *x, const float *y) +{ +} + +void nop_loop (float *x, const float *y) +{ + for (int i = 0; i < ITERATIONS; i++){ + nop_fct (x, y); + } +} + +int +main (int argc, char **argv) +{ + benchmark (nop_loop, "nop loop"); + benchmark (basic_vco, "basic vco"); + benchmark (native_vco, "native vco"); + benchmark (fxpt_vco, "fxpt vco"); +} diff --git a/gnuradio-core/src/tests/nco_results b/gnuradio-core/src/tests/nco_results new file mode 100644 index 00000000..5bdf5dd1 --- /dev/null +++ b/gnuradio-core/src/tests/nco_results @@ -0,0 +1,48 @@ +================================================================ +These are on a 1.4 GHz Pentium M using g++ 3.4.1 +================================================================ + +Default compiler options -O2 + + nop loop: cpu: 0.015 steps/sec: 6.668e+08 + native sine: cpu: 0.900 steps/sec: 1.111e+07 + fxpt sine: cpu: 0.281 steps/sec: 3.559e+07 + native sin/cos: cpu: 1.138 steps/sec: 8.789e+06 + fxpt sin/cos: cpu: 0.550 steps/sec: 1.818e+07 + +-O2 -march=pentium-m -fomit-frame-pointer + + nop loop: cpu: 0.015 steps/sec: 6.668e+08 + native sine: cpu: 0.903 steps/sec: 1.108e+07 + fxpt sine: cpu: 0.271 steps/sec: 3.691e+07 + native sin/cos: cpu: 1.092 steps/sec: 9.159e+06 + fxpt sin/cos: cpu: 0.542 steps/sec: 1.845e+07 + +Inlined fxpt::sin & cos +-O2 -march=pentium-m -fomit-frame-pointer + + nop loop: cpu: 0.015 steps/sec: 6.668e+08 + native sine: cpu: 0.904 steps/sec: 1.106e+07 + fxpt sine: cpu: 0.187 steps/sec: 5.348e+07 + native sin/cos: cpu: 1.091 steps/sec: 9.167e+06 + fxpt sin/cos: cpu: 0.373 steps/sec: 2.681e+07 + +================================================================ +These are on a 1.5 GHz Athon MP 1800+ +================================================================ + +Default compiler options: -O2 + + nop loop: cpu: 0.013 steps/sec: 7.693e+08 + native sine: cpu: 0.733 steps/sec: 1.364e+07 + fxpt sine: cpu: 0.210 steps/sec: 4.763e+07 + native sin/cos: cpu: 1.183 steps/sec: 8.454e+06 + fxpt sin/cos: cpu: 0.420 steps/sec: 2.381e+07 + +-O2 -fomit-frame-pointer -march=athlon-mp + + nop loop: cpu: 0.013 steps/sec: 7.693e+08 + native sine: cpu: 0.679 steps/sec: 1.473e+07 + fxpt sine: cpu: 0.200 steps/sec: 5.001e+07 + native sin/cos: cpu: 1.147 steps/sec: 8.720e+06 + fxpt sin/cos: cpu: 0.444 steps/sec: 2.253e+07 diff --git a/gnuradio-core/src/tests/test_all.cc b/gnuradio-core/src/tests/test_all.cc new file mode 100644 index 00000000..b5e1b461 --- /dev/null +++ b/gnuradio-core/src/tests/test_all.cc @@ -0,0 +1,46 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU 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 + +#include +#include +#include +// #include + +// FIXME add atsc back in. + +int +main (int argc, char **argv) +{ + + CppUnit::TextTestRunner runner; + + runner.addTest (qa_runtime::suite ()); + runner.addTest (qa_general::suite ()); + runner.addTest (qa_filter::suite ()); + // runner.addTest (qa_atsc::suite ()); + + bool was_successful = runner.run ("", false); + + return was_successful ? 0 : 1; +} diff --git a/gnuradio-core/src/tests/test_atsc.cc b/gnuradio-core/src/tests/test_atsc.cc new file mode 100644 index 00000000..cca96d55 --- /dev/null +++ b/gnuradio-core/src/tests/test_atsc.cc @@ -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. + */ + +#include +#include + +int +main (int argc, char **argv) +{ + + CppUnit::TextTestRunner runner; + + runner.addTest (qa_atsc::suite ()); + + bool was_successful = runner.run ("", false); + + return was_successful ? 0 : 1; +} diff --git a/gnuradio-core/src/tests/test_buffers.py b/gnuradio-core/src/tests/test_buffers.py new file mode 100755 index 00000000..b3211329 --- /dev/null +++ b/gnuradio-core/src/tests/test_buffers.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 gnuradio import gr, gru +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +import time +import sys + +# Test script to test setting up the buffers using gr_test +# For very large buffers it will fail when you hit the circbuf memory limit. +# On linux this limit is shmmax, it will fail when it tries to create a buffer > shmmax. +# With a 2.6 or later kernel you can set the shmmax limit manually in a root console +#show current shmmax limit +#$ cat /proc/sys/kernel/shmmax +#33554432 + +#set shmmax limit manually to 300MB +#echo 300000000 >/proc/sys/kernel/shmmax + +#show new shmmax limit +#$ cat /proc/sys/kernel/shmmax +#300000000 + +class my_graph(gr.flow_graph): + + def __init__(self, seconds,history,output_multiple): + gr.flow_graph.__init__(self) + + parser = OptionParser(option_class=eng_option) + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-r", "--sample-rate", type="eng_float", default=48000, + help="set sample rate to RATE (48000)") + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + sample_rate = int(options.sample_rate) + ampl = 0.1 + + src0 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 350, ampl) + + nsamples=int(sample_rate * seconds) #1 seconds + # gr.test (const std::string &name=std::string("gr_test"), + # int min_inputs=1, int max_inputs=1, unsigned int sizeof_input_item=1, + # int min_outputs=1, int max_outputs=1, unsigned int sizeof_output_item=1, + # unsigned int history=1,unsigned int output_multiple=1,double relative_rate=1.0, + # bool fixed_rate=true,gr_consume_type_t cons_type=CONSUME_NOUTPUT_ITEMS, gr_produce_type_t prod_type=PRODUCE_NOUTPUT_ITEMS); + name="gr_test" + min_inputs=1 + max_inputs=1 + sizeof_input_item=gr.sizeof_float + min_outputs=1 + max_outputs=1 + sizeof_output_item=gr.sizeof_float + #history=1 # problems start at 8150 + #output_multiple=1 #problems start at 8000 in combination with large history + relative_rate=1.0 + fixed_rate=True + consume_type=gr.CONSUME_NOUTPUT_ITEMS + produce_type=gr.PRODUCE_NOUTPUT_ITEMS + test = gr.test(name, min_inputs,max_inputs,sizeof_input_item, + min_outputs,max_outputs,sizeof_output_item, + history,output_multiple,relative_rate, + fixed_rate, consume_type,produce_type) + #test = gr.test("gr_test",1,1,gr.sizeof_float, + # 1,1,gr.sizeof_float, + # 1,1,1.0, + # True, gr.CONSUME_NOUTPUT_ITEMS,gr.PRODUCE_NOUTPUT_ITEMS) + #unsigned int history=1,unsigned int output_multiple=1,double relative_rate=1.0, + #bool fixed_rate=false + dst = audio.sink (sample_rate, options.audio_output) + head= gr.head(gr.sizeof_float, nsamples) + + self.connect (src0,test,head,(dst, 0)) + + +if __name__ == '__main__': + + seconds=5.0 + output_multiple=1 + for history in (1,1000,8000,8100,8150,8175,8190,8191,8192,8193,8194,8195,9000,10000,100000,1000000,10000000): #,100000000): + sys.stdout.flush() + sys.stderr.flush() + print 'Test with history=', history, 'output_multiple=',output_multiple + sys.stdout.flush() + sys.stderr.flush() + succeed=True + starttime=time.time() + try: + my_graph(seconds,history,output_multiple).run() + except KeyboardInterrupt: + pass + except: + print "\nAn exception has terminated the graph." + exception=True + succeed=False + sys.stdout.flush() + sys.stderr.flush() + if succeed: + print '' + endtime=time.time() + duration=endtime - starttime + if (duration < 0.5*seconds) and (succeed): + print "A problem has terminated the graph." + succeed=False + if (duration > 1.5*seconds) and (succeed): + print "Something slowed the graph down considerably." + succeed=False + + print 'The test result was:' , succeed + print 'Test duration' , duration + print '' diff --git a/gnuradio-core/src/tests/test_filter.cc b/gnuradio-core/src/tests/test_filter.cc new file mode 100644 index 00000000..1b2c57be --- /dev/null +++ b/gnuradio-core/src/tests/test_filter.cc @@ -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. + */ + +#include +#include + +int +main (int argc, char **argv) +{ + + CppUnit::TextTestRunner runner; + + runner.addTest (qa_filter::suite ()); + + bool was_successful = runner.run ("", false); + + return was_successful ? 0 : 1; +} diff --git a/gnuradio-core/src/tests/test_general.cc b/gnuradio-core/src/tests/test_general.cc new file mode 100644 index 00000000..9f93b9d7 --- /dev/null +++ b/gnuradio-core/src/tests/test_general.cc @@ -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. + */ + +#include +#include + +int +main (int argc, char **argv) +{ + + CppUnit::TextTestRunner runner; + + runner.addTest (qa_general::suite ()); + + bool was_successful = runner.run ("", false); + + return was_successful ? 0 : 1; +} diff --git a/gnuradio-core/src/tests/test_runtime.cc b/gnuradio-core/src/tests/test_runtime.cc new file mode 100644 index 00000000..72290a9b --- /dev/null +++ b/gnuradio-core/src/tests/test_runtime.cc @@ -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. + */ + +#include +#include + +int +main (int argc, char **argv) +{ + + CppUnit::TextTestRunner runner; + + runner.addTest (qa_runtime::suite ()); + + bool was_successful = runner.run ("", false); + + return was_successful ? 0 : 1; +} diff --git a/gnuradio-core/src/tests/test_vmcircbuf.cc b/gnuradio-core/src/tests/test_vmcircbuf.cc new file mode 100644 index 00000000..e00b1706 --- /dev/null +++ b/gnuradio-core/src/tests/test_vmcircbuf.cc @@ -0,0 +1,44 @@ +/* -*- c++ -*- */ +/* + * Copyright 2003 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU 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 +#include + +int +main (int argc, char **argv) +{ + int verbose = 1; // summary + + if (argc > 1) + verbose = 2; // extra chatty + + bool ok = gr_vmcircbuf_sysconfig::test_all_factories (verbose); + + if (ok){ + fprintf (stdout, "test_vmcircbuf: OK. We've got at least one workable solution\n"); + return 0; + } + else { + fprintf (stdout, "test_vmcircbuf: NOT OK. We don't have a workable solution\n"); + return 1; + } +} diff --git a/gnuradio-core/src/utils/Makefile.am b/gnuradio-core/src/utils/Makefile.am new file mode 100644 index 00000000..ee0bd437 --- /dev/null +++ b/gnuradio-core/src/utils/Makefile.am @@ -0,0 +1,43 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 = \ + db_width.m \ + filter_tools.m \ + plot_freq_response.m \ + plot_freq_response_db.m \ + plot_freq_response_phase.m \ + plotfft.m \ + plotfftavgk.m \ + plotfftavgk_db.m \ + plotfftk.m \ + plotfftk_db.m \ + put_markers.m \ + read_char_binary.m \ + read_complex_binary.m \ + read_float_binary.m \ + read_int_binary.m \ + read_short_binary.m \ + single_pole_iir.m \ + write_float_binary.m \ + write_short_binary.m diff --git a/gnuradio-core/src/utils/cool.m b/gnuradio-core/src/utils/cool.m new file mode 100644 index 00000000..eff194d8 --- /dev/null +++ b/gnuradio-core/src/utils/cool.m @@ -0,0 +1,50 @@ +%% Copyright (C) 1999,2000 Kai Habel +%% +%% This program is free software; you can redistribute it and/or modify +%% it under the terms of the GNU General Public License as published by +%% the Free Software Foundation; either version 2 of the License, or +%% (at your option) any later version. +%% +%% This program is distributed in the hope that it will be useful, +%% but WITHOUT ANY WARRANTY; without even the implied warranty of +%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +%% GNU General Public License for more details. +%% +%% You should have received a copy of the GNU General Public License +%% along with this program; if not, write to the Free Software +%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +%% -*- texinfo -*- +%% @deftypefn {Function File} {} cool (@var{n}) +%% Create color colormap. +%% (cyan to magenta) +%% The argument @var{n} should be a scalar. If it +%% is omitted, the length of the current colormap or 64 is assumed. +%% @end deftypefn +%% @seealso{colormap} + +%% Author: Kai Habel + +function map = cool (number) + + if (nargin == 0) + number = rows (colormap); + elseif (nargin == 1) + if (! is_scalar (number)) + error ("cool: argument must be a scalar"); + end + else + usage ("cool (number)"); + end + + if (number == 1) + map = [0, 1, 1]; + elseif (number > 1) + r = (0:number - 1)' ./ (number - 1); + g = 1 - r; + b = ones (number, 1); + map = [r, g, b]; + else + map = []; + end + diff --git a/gnuradio-core/src/utils/db_width.m b/gnuradio-core/src/utils/db_width.m new file mode 100644 index 00000000..c12dfd1c --- /dev/null +++ b/gnuradio-core/src/utils/db_width.m @@ -0,0 +1,35 @@ +% +% Copyright 2001 Free Software Foundation, Inc. +% +% This file is part of GNU Radio +% +% GNU Radio is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2, or (at your option) +% any later version. +% +% GNU Radio is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with GNU Radio; see the file COPYING. If not, write to +% the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +% Boston, MA 02111-1307, USA. + +%% find the N-dB width of the given filter +%% E.g., to find the 3-dB width, use width = db_width (taps, -3.0) +%% the result is normalized to nyquist == 1 + +function width = db_width (taps, db) + [H,w] = freqz (taps, 1, 4096); + Habs = abs(H); + max_H = max(Habs); + min_H = min(Habs); + threshold = max_H * 10^(db/20); + if (min_H > threshold) + error ("The %g dB point is never reached", db); + end + above = Habs >= threshold; + width = sum(above) / length (above); diff --git a/gnuradio-core/src/utils/filter_tools.m b/gnuradio-core/src/utils/filter_tools.m new file mode 100644 index 00000000..78a50b7d --- /dev/null +++ b/gnuradio-core/src/utils/filter_tools.m @@ -0,0 +1,42 @@ +% +% Copyright 2001 Free Software Foundation, Inc. +% +% This file is part of GNU Radio +% +% GNU Radio is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2, or (at your option) +% any later version. +% +% GNU Radio is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with GNU Radio; see the file COPYING. If not, write to +% the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +% Boston, MA 02111-1307, USA. +% +%% equivalent to the C++ code in VrComplexFIRfilter::buildFilterComplex + +1; + +%% hamming window, nothing fancy + +function taps = build_filter_complex_lp (gain, ntaps) + + taps = gain * (0.54 - 0.46 * cos (2 * pi * (0:ntaps-1)' / (ntaps-1))); + +end + +%% old_taps describes a low pass filter, convert it to bandpass +%% centered at center_freq. center_freq is normalized to Fs (sampling freq) + +function new_taps = freq_shift_filter (old_taps, center_freq) + + ntaps = length(old_taps); + + new_taps = exp (j*2*pi*center_freq*(0:ntaps-1)') .* old_taps; + +end diff --git a/gnuradio-core/src/utils/is_complex.m b/gnuradio-core/src/utils/is_complex.m new file mode 100644 index 00000000..a17b8ad4 --- /dev/null +++ b/gnuradio-core/src/utils/is_complex.m @@ -0,0 +1,24 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function p = is_complex (x) + p = any (imag (x) != 0); +endfunction; diff --git a/gnuradio-core/src/utils/lp_to_bp.m b/gnuradio-core/src/utils/lp_to_bp.m new file mode 100644 index 00000000..8718baed --- /dev/null +++ b/gnuradio-core/src/utils/lp_to_bp.m @@ -0,0 +1,27 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +## transform low pass coefficients into bandpass coefficients + +function bp_taps = lp_to_bp (lp_taps, center_freq, sampling_freq) + arg = 2 * pi * center_freq / sampling_freq; + bp_taps = lp_taps .* exp (j*arg*(0:length(lp_taps)-1)'); +endfunction diff --git a/gnuradio-core/src/utils/partition-cascaded-decimating-filters.scm b/gnuradio-core/src/utils/partition-cascaded-decimating-filters.scm new file mode 100644 index 00000000..598f79d8 --- /dev/null +++ b/gnuradio-core/src/utils/partition-cascaded-decimating-filters.scm @@ -0,0 +1,68 @@ +;; Estimate the total work (ntaps * sampling rate) for two cascaded +;; decimating low pass filters. +;; +;; The basic assumption is that the number of taps required in any +;; section is inversely proportional to the normalized transition width +;; for that section. +;; +;; FS is the input sampling frequency +;; F1 is the cutoff frequency +;; F2 is the far edge of the transition band +;; DEC1 is the decimation factor for the first filter +;; DEC2 is the decimation factor for the 2nd filter +;; +;; The total decimation factor is DEC1 * DEC2. Therefore, +;; the output rate of the filter is FS / (DEC1 * DEC2) + +(require 'common-list-functions) +(require 'factor) + + + +(define (work2 fs f1 f2 dec1 dec2) + (+ (work1 fs f1 (/ fs (* 2 dec1)) dec1) + (work1 (/ fs dec1) f1 f2 dec2))) + + +;; work for a single section + +(define (work1 fs f1 f2 dec) + (/ (* fs (/ fs (- f2 f1))) dec)) + + +;; return the max integer dec such that fs/(2*dec) >= f2 + +(define (max-dec fs f2) + (inexact->exact (floor (/ fs (* 2 f2))))) + + +;; `adjoin' returns the adjoint of the element OBJ and the list LST. +;; That is, if OBJ is in LST, `adjoin' returns LST, otherwise, it returns +;; `(cons OBJ LST)'. + +(define (adjoin-equal obj lst) + (if (member obj lst) lst (cons obj lst))) + + +;;; not quite right + +(define (permute lst) + (let ((result '())) + (define (aux set head) + (if (null? set) + (set! result (cons head result)) + (for-each (lambda (x) + (aux (set-difference set (list x)) + (cons x head))) + set))) + (aux lst '()) + result)) + +;; `extract-nth' returns the Nth element of LST consed on to the +;; list resulting from splicing out the Nth element of LST. +;; Indexing is 0 based. + +(define (extract-nth n lst) + lst) + + \ No newline at end of file diff --git a/gnuradio-core/src/utils/permute.scm b/gnuradio-core/src/utils/permute.scm new file mode 100644 index 00000000..23ddfc99 --- /dev/null +++ b/gnuradio-core/src/utils/permute.scm @@ -0,0 +1,27 @@ +(require 'common-list-functions) + + +(define (permute lst) + (define (aux set head) + (cond ((null? set) head) + (else + (map (lambda (x) + (aux (set-difference set (list x)) + (cons x head))) + set)))) + (aux lst '())) + +(define (permute-2 lst) + (let ((result '())) + (define (aux set head) + (if (null? set) + (set! result (cons head result)) + (for-each (lambda (x) + (aux (set-difference set (list x)) + (cons x head))) + set))) + (aux lst '()) + result)) + + + diff --git a/gnuradio-core/src/utils/plot_cic_decimator_response.m b/gnuradio-core/src/utils/plot_cic_decimator_response.m new file mode 100644 index 00000000..e26883c5 --- /dev/null +++ b/gnuradio-core/src/utils/plot_cic_decimator_response.m @@ -0,0 +1,45 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function plot_cic_decimator_response (R, N, M) + ## R = decimation rate + ## N = number of stages (4) + ## M = 1 + gain = (R*M)^N + npoints = 1024; + w = 0:1/npoints:1-1/npoints; + w = w * 1 * pi; + ## w = w * R; + length(w); + num = sin (w*R*M/2); + length (num); + ## H = sin (w*R*M/2) ./ sin (w/2) + denom = sin(w/2); + length (denom); + H = (num ./ denom) .^ N; + H(1) = gain; + H = H ./ gain; + plot (R*w/(2*pi), 10 * log10 (H)); + ## plot (R*w/(2*pi), H); +endfunction + + + \ No newline at end of file diff --git a/gnuradio-core/src/utils/plot_freq_response.m b/gnuradio-core/src/utils/plot_freq_response.m new file mode 100644 index 00000000..bf186fae --- /dev/null +++ b/gnuradio-core/src/utils/plot_freq_response.m @@ -0,0 +1,36 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function plot_freq_response (b,...) + if (nargin == 1) + ## Response of an FIR filter + a = 1; + elseif (nargin == 2) + ## response of an IIR filter + a = va_arg (); + endif + + [H,w] = freqz (b,a); + plot (w/(2*pi), abs(H)); + grid; + xlabel ('Normalized Frequency (Fs == 1)'); + ylabel ('Magnitude (linear)'); +endfunction diff --git a/gnuradio-core/src/utils/plot_freq_response_db.m b/gnuradio-core/src/utils/plot_freq_response_db.m new file mode 100644 index 00000000..d6ebce39 --- /dev/null +++ b/gnuradio-core/src/utils/plot_freq_response_db.m @@ -0,0 +1,39 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function plot_freq_response_db (b,...) + if (nargin == 1) + ## Response of an FIR filter + a = 1; + elseif (nargin == 2) + ## response of an IIR filter + a = va_arg (); + endif + + [H,w] = freqz (b,a); + + grid; + xlabel ('Normalized Frequency (Fs == 1)'); + ylabel ('Magnitude Squared (dB)'); + abs = abs(H); +# plot (w/(2*pi), 20 * log10 (abs/max(abs))); + plot (w/(2*pi), 20 * log10 (abs)); +endfunction diff --git a/gnuradio-core/src/utils/plot_freq_response_phase.m b/gnuradio-core/src/utils/plot_freq_response_phase.m new file mode 100644 index 00000000..f30ff7d3 --- /dev/null +++ b/gnuradio-core/src/utils/plot_freq_response_phase.m @@ -0,0 +1,38 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function plot_freq_response_db (b,...) + if (nargin == 1) + ## Response of an FIR filter + a = 1; + elseif (nargin == 2) + ## response of an IIR filter + a = va_arg (); + endif + + [H,w] = freqz (b,a); + + grid; + xlabel ('Normalized Frequency (Fs == 1)'); + ylabel ('Phase (radians)'); + abs = abs(H); + plot (w/(2*pi), atan2(imag(H), real(H))) +endfunction diff --git a/gnuradio-core/src/utils/plotfft.m b/gnuradio-core/src/utils/plotfft.m new file mode 100644 index 00000000..5af149a1 --- /dev/null +++ b/gnuradio-core/src/utils/plotfft.m @@ -0,0 +1,40 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function plotfft (data, sample_rate) + + if (nargin == 1) + sample_rate = 1.0; + endif; + + if ((m = nargchk (1,2,nargin))) + usage (m); + endif; + + len = length(data); + s = fft (data.*kaiser(len, 5)); + + incr = sample_rate/len; + min_x = -sample_rate/2; + max_x = sample_rate/2 - incr; + plot (min_x:incr:max_x, abs(fftshift(s))); + +endfunction diff --git a/gnuradio-core/src/utils/plotfftavgk.m b/gnuradio-core/src/utils/plotfftavgk.m new file mode 100644 index 00000000..3e19f40c --- /dev/null +++ b/gnuradio-core/src/utils/plotfftavgk.m @@ -0,0 +1,61 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function plotfftavgk_db (all_data, k, sample_rate) + + if (nargin == 2) + sample_rate = 1.0; + endif; + + if ((m = nargchk (2,3,nargin))) + usage (m); + endif; + + ## len = 1024; + len = 8192; + ##window = ones (len, 1); + window = kaiser (len, 5); + + s = zeros (len,1); + + count = min (100, floor (length (all_data)/len)); + + for i = 0:count-1; + data = all_data((k+i)*len + 1 : (k+i+1)*len); + s = s + abs (fft (data.*window)); + endfor; + + s = s ./ count; + + incr = sample_rate/len; + min_x = -sample_rate/2; + max_x = sample_rate/2 - incr; + + x = min_x:incr:max_x; + ## y = 20 * log10(fftshift(s)); + y = (fftshift(s)); + plot (x, y); + + i = find (y == max(y)) + x(i) + y(i) + +endfunction diff --git a/gnuradio-core/src/utils/plotfftavgk_db.m b/gnuradio-core/src/utils/plotfftavgk_db.m new file mode 100644 index 00000000..6dbb0f50 --- /dev/null +++ b/gnuradio-core/src/utils/plotfftavgk_db.m @@ -0,0 +1,73 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function plotfftavgk_db (all_data, k, sample_rate) + + if (nargin == 2) + sample_rate = 1.0; + endif; + + if ((m = nargchk (2,3,nargin))) + usage (m); + endif; + + len = 1024; + ## len = 8192; + ##window = ones (len, 1); + #window = kaiser (len, 5); + window = hanning (len); + + s = zeros (len,1); + + count = min (100, floor (length (all_data)/len)); + + for i = 0:count-1; + data = all_data((k+i)*len + 1 : (k+i+1)*len); + s = s + abs (fft (data.*window)); + endfor; + + s = s ./ count; + + incr = sample_rate/len; + + if is_complex (all_data); + min_x = -sample_rate/2; + max_x = sample_rate/2 - incr; + + x = min_x:incr:max_x; + y = 20 * log10(fftshift(s)); + plot (x, y); + else + min_x = 0 + max_x = sample_rate/2 - incr; + + x = min_x:incr:max_x; + y = 20 * log10(s(1:len/2)); + plot (x, y); + + endif; + + + i = find (y == max(y)) + x(i) + y(i) + +endfunction diff --git a/gnuradio-core/src/utils/plotfftk.m b/gnuradio-core/src/utils/plotfftk.m new file mode 100644 index 00000000..bf93ea5d --- /dev/null +++ b/gnuradio-core/src/utils/plotfftk.m @@ -0,0 +1,41 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function plotfftk (all_data, k, sample_rate) + + if (nargin == 2) + sample_rate = 1.0; + endif; + + if ((m = nargchk (2,3,nargin))) + usage (m); + endif; + + len = 1024; + data = all_data(k*len + 1 : (k+1)*len); + s = fft (data.*kaiser(len, 5)); + + incr = sample_rate/len; + min_x = -sample_rate/2; + max_x = sample_rate/2 - incr; + plot (min_x:incr:max_x, abs(fftshift(s))); + +endfunction diff --git a/gnuradio-core/src/utils/plotfftk_db.m b/gnuradio-core/src/utils/plotfftk_db.m new file mode 100644 index 00000000..498c22fc --- /dev/null +++ b/gnuradio-core/src/utils/plotfftk_db.m @@ -0,0 +1,43 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function plotfftk_db (all_data, k, sample_rate) + + if (nargin == 2) + sample_rate = 1.0; + endif; + + if ((m = nargchk (2,3,nargin))) + usage (m); + endif; + + len = 1024; + data = all_data(k*len + 1 : (k+1)*len); + ## s = fft (data.*kaiser(len, 5)); + ## s = fft (data.*hamming(len)); + s = fft (data.*hanning(len)); + + incr = sample_rate/len; + min_x = -sample_rate/2; + max_x = sample_rate/2 - incr; + plot (min_x:incr:max_x, 20 * log10(abs(fftshift(s)))); + +endfunction diff --git a/gnuradio-core/src/utils/put_markers.m b/gnuradio-core/src/utils/put_markers.m new file mode 100644 index 00000000..e35aee9d --- /dev/null +++ b/gnuradio-core/src/utils/put_markers.m @@ -0,0 +1,32 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function put_markers (y) + + if (nargin == 0) + y = 25; + endif; + + hold on; + plot (3.06e6, y, '@'); + plot (8.44e6, y, '@'); + +endfunction diff --git a/gnuradio-core/src/utils/rainbow.m b/gnuradio-core/src/utils/rainbow.m new file mode 100644 index 00000000..e19bd679 --- /dev/null +++ b/gnuradio-core/src/utils/rainbow.m @@ -0,0 +1,53 @@ +## Copyright (C) 1999,2000 Kai Habel +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, write to the Free Software +## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +## -*- texinfo -*- +## @deftypefn {Function File} {} rainbow (@var{n}) +## Create color colormap. +## (red through yellow, green, cyan,blue,magenta to red) +## The argument @var{n} should be a scalar. If it +## is omitted, the length of the current colormap or 64 is assumed. +## @end deftypefn +## @seealso{colormap} + +## Author: Kai Habel + +## 2001-09-13 Paul Kienzle +## * renamed to rainbow for use with tk_octave +## * remove reference to __current_color_map__ + +function map = rainbow (number) + + if (nargin == 0) + number = length(colormap); + elseif (nargin == 1) + if (! is_scalar (number)) + error ("rainbow: argument must be a scalar"); + endif + else + usage ("rainbow (number)"); + endif + + if (number == 1) + map = [1, 0, 0]; + elseif (number > 1) + h = linspace (0, 1, number)'; + map = hsv2rgb ([h, ones(number, 1), ones(number, 1)]); + else + map = []; + endif + +endfunction diff --git a/gnuradio-core/src/utils/read_char_binary.m b/gnuradio-core/src/utils/read_char_binary.m new file mode 100644 index 00000000..d33bd91a --- /dev/null +++ b/gnuradio-core/src/utils/read_char_binary.m @@ -0,0 +1,45 @@ +% +% Copyright 2001 Free Software Foundation, Inc. +% +% This file is part of GNU Radio +% +% GNU Radio is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2, or (at your option) +% any later version. +% +% GNU Radio is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with GNU Radio; see the file COPYING. If not, write to +% the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +% Boston, MA 02111-1307, USA. +% + +function v = read_char_binary (filename, count) + + %% usage: read_char (filename, [count]) + %% + %% open filename and return the contents, treating them as + %% signed short integers + %% + + m = nargchk (1,2,nargin); + if (m) + usage (m); + end + + if (nargin < 2) + count = Inf; + end + + f = fopen (filename, 'rb'); + if (f < 0) + v = 0; + else + v = fread (f, count, 'char'); + fclose (f); + end diff --git a/gnuradio-core/src/utils/read_complex_binary.m b/gnuradio-core/src/utils/read_complex_binary.m new file mode 100644 index 00000000..6f538f37 --- /dev/null +++ b/gnuradio-core/src/utils/read_complex_binary.m @@ -0,0 +1,48 @@ +% +% Copyright 2001 Free Software Foundation, Inc. +% +% This file is part of GNU Radio +% +% GNU Radio is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2, or (at your option) +% any later version. +% +% GNU Radio is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with GNU Radio; see the file COPYING. If not, write to +% the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +% Boston, MA 02111-1307, USA. +% + +function v = read_complex_binary (filename, count) + + %% usage: read_complex_binary (filename, [count]) + %% + %% open filename and return the contents as a column vector, + %% treating them as 32 bit complex numbers + %% + + m = nargchk (1,2,nargin); + if (m) + usage (m); + end + + if (nargin < 2) + count = Inf; + end + + f = fopen (filename, 'rb'); + if (f < 0) + v = 0; + else + t = fread (f, [2, count], 'float'); + fclose (f); + v = t(1,:) + t(2,:)*i; + [r, c] = size (v); + v = reshape (v, c, r); + end diff --git a/gnuradio-core/src/utils/read_float_binary.m b/gnuradio-core/src/utils/read_float_binary.m new file mode 100644 index 00000000..ac8461ff --- /dev/null +++ b/gnuradio-core/src/utils/read_float_binary.m @@ -0,0 +1,45 @@ +% +% Copyright 2001 Free Software Foundation, Inc. +% +% This file is part of GNU Radio +% +% GNU Radio is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2, or (at your option) +% any later version. +% +% GNU Radio is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with GNU Radio; see the file COPYING. If not, write to +% the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +% Boston, MA 02111-1307, USA. +% + +function v = read_float_binary (filename, count) + + %% usage: read_float_binary (filename, [count]) + %% + %% open filename and return the contents, treating them as + %% 32 bit floats + %% + + m = nargchk (1,2,nargin); + if (m) + usage (m); + end + + if (nargin < 2) + count = Inf; + end + + f = fopen (filename, 'rb'); + if (f < 0) + v = 0; + else + v = fread (f, count, 'float'); + fclose (f); + end diff --git a/gnuradio-core/src/utils/read_int_binary.m b/gnuradio-core/src/utils/read_int_binary.m new file mode 100644 index 00000000..ca4f7339 --- /dev/null +++ b/gnuradio-core/src/utils/read_int_binary.m @@ -0,0 +1,46 @@ +% +% Copyright 2001,2002 Free Software Foundation, Inc. +% +% This file is part of GNU Radio +% +% GNU Radio is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2, or (at your option) +% any later version. +% +% GNU Radio is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with GNU Radio; see the file COPYING. If not, write to +% the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +% Boston, MA 02111-1307, USA. +% + +function v = read_int_binary (filename, count) + + %% usage: read_int_binary (filename, [count]) + %% + %% open filename and return the contents, treating them as + %% signed integers + %% + + m = nargchk (1,2,nargin); + if (m) + usage (m); + end + + if (nargin < 2) + count = Inf; + end + + f = fopen (filename, 'rb'); + if (f < 0) + v = 0; + else + v = fread (f, count, 'int'); + fclose (f); + end +end diff --git a/gnuradio-core/src/utils/read_short_binary.m b/gnuradio-core/src/utils/read_short_binary.m new file mode 100644 index 00000000..361392bf --- /dev/null +++ b/gnuradio-core/src/utils/read_short_binary.m @@ -0,0 +1,45 @@ +% +% Copyright 2001 Free Software Foundation, Inc. +% +% This file is part of GNU Radio +% +% GNU Radio is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2, or (at your option) +% any later version. +% +% GNU Radio is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with GNU Radio; see the file COPYING. If not, write to +% the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +% Boston, MA 02111-1307, USA. +% + +function v = read_short_binary (filename, count) + + %% usage: read_short_binary (filename, [count]) + %% + %% open filename and return the contents, treating them as + %% signed short integers + %% + + m = nargchk (1,2,nargin); + if (m) + usage (m); + end + + if (nargin < 2) + count = Inf; + end + + f = fopen (filename, 'rb'); + if (f < 0) + v = 0; + else + v = fread (f, count, 'short'); + fclose (f); + end diff --git a/gnuradio-core/src/utils/read_xambi.m b/gnuradio-core/src/utils/read_xambi.m new file mode 100644 index 00000000..7533ddac --- /dev/null +++ b/gnuradio-core/src/utils/read_xambi.m @@ -0,0 +1,46 @@ +# +# Copyright 2001,2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function v = read_xambi (filename) + + ## usage: read_xambi (filename) + ## + ## read binary cross-ambiguity data from radar tools. + ## The file has an 8 float header, the first word of which specifies + ## the number of doppler bins. + ## returns a matrix + + if ((m = nargchk (1,1,nargin))) + usage (m); + endif; + + f = fopen (filename, "rb"); + if (f < 0) + v = 0; + else + header = fread(f, 8, "float"); + ndoppler_bins = header(1) + min_doppler = header(2) + max_doppler = header(3) + v = fread (f, [ndoppler_bins, Inf], "float"); + fclose (f); + endif; +endfunction; diff --git a/gnuradio-core/src/utils/runsum.m b/gnuradio-core/src/utils/runsum.m new file mode 100644 index 00000000..0f530b01 --- /dev/null +++ b/gnuradio-core/src/utils/runsum.m @@ -0,0 +1,9 @@ +function r = runsum(x) + len = length(x); + r = zeros (1, len); + r(1) = x(1); + for i = 2:len; + r(i) = r(i-1) + x(i); + endfor; +endfunction; + diff --git a/gnuradio-core/src/utils/single_pole_iir.m b/gnuradio-core/src/utils/single_pole_iir.m new file mode 100644 index 00000000..13d6b4d5 --- /dev/null +++ b/gnuradio-core/src/utils/single_pole_iir.m @@ -0,0 +1,25 @@ +# +# Copyright 2002 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function [b, a] = single_pole_iir (alpha) + b = [alpha]; + a = [1, alpha - 1]; +endfunction \ No newline at end of file diff --git a/gnuradio-core/src/utils/write_float_binary.m b/gnuradio-core/src/utils/write_float_binary.m new file mode 100644 index 00000000..c0d27436 --- /dev/null +++ b/gnuradio-core/src/utils/write_float_binary.m @@ -0,0 +1,40 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function v = write_float_binary (data, filename) + + ## usage: write_float_binary (data, filename) + ## + ## open filename and write data to it as 32 bit floats + ## + + if ((m = nargchk (2,2,nargin))) + usage (m); + endif; + + f = fopen (filename, "wb"); + if (f < 0) + v = 0; + else + v = fwrite (f, data, "float"); + fclose (f); + endif; +endfunction; diff --git a/gnuradio-core/src/utils/write_short_binary.m b/gnuradio-core/src/utils/write_short_binary.m new file mode 100644 index 00000000..ffe502e6 --- /dev/null +++ b/gnuradio-core/src/utils/write_short_binary.m @@ -0,0 +1,40 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +function v = write_short_binary (data, filename) + + ## usage: write_short_binary (data, filename) + ## + ## open filename and write data to it as 16 bit shorts + ## + + if ((m = nargchk (2,2,nargin))) + usage (m); + endif; + + f = fopen (filename, "wb"); + if (f < 0) + v = 0; + else + v = fwrite (f, data, "short"); + fclose (f); + endif; +endfunction; diff --git a/gnuradio-examples/AUTHORS b/gnuradio-examples/AUTHORS new file mode 100644 index 00000000..6bd41174 --- /dev/null +++ b/gnuradio-examples/AUTHORS @@ -0,0 +1,2 @@ +Eric Blossom +Matt Ettus diff --git a/gnuradio-examples/ChangeLog b/gnuradio-examples/ChangeLog new file mode 100644 index 00000000..e2c630eb --- /dev/null +++ b/gnuradio-examples/ChangeLog @@ -0,0 +1,381 @@ +2006-06-20 Eric Blossom + + * python/gmsk2/receive_path.py, python/gmsk2/transmit_path.py, + benchmark_gmsk_{tx,rx}.py: refactored to use modulation + independent pkt.py code. Lays the foundation for a single set of + tools that can exercise all modulations. More work required to + meet that goal, but we're closing in. + + * python/gmsk2/tunnel.py: refactored version of + tunnel_ip_null_mac. This creates a virtual ethernet inteface + using the TAP driver, and then tunnels packets across the air + using GMSK and a simple carrier sense MAC. Fixed problem with + truncation of large packets which was leading to stalls. + + * python/gmsk2/tunnel_ip_null_mac.py: removed. Replaced with + tunnel.py + +2006-06-15 Eric Blossom + + * python/usrp/usrp_fft.py (app_flow_graph.set_decim): added + missing return value. + + * python/usrp/usrp_oscope.py, python/usrp/usrp_fft.py: you can now + change the decimation factor in the GUI. + +2006-06-06 Eric Blossom + + * python/gmsk2/mpsk.py: Lots of rework. QPSK is now + working with mpsk_test.py. Need to confirm it on the air, and then + make BPSK work again. + + +2006-05-30 Eric Blossom + + Standardized on mpsk as the prefix. Renamed a bunch of stuff to + restore sanity: + * python/gmsk2/benchmark_xpsk_rx.py -> python/gmsk2/benchmark_mpsk_rx.py + * python/gmsk2/benchmark_xpsk_tx.py -> python/gmsk2/benchmark_mpsk_tx.py + * python/gmsk2/psk_receive_path.py -> python/gmsk2/mpsk_receive_path.py + * python/gmsk2/psk_transmit_path.py -> python/gmsk2/mpsk_transmit_path.py + * python/gmsk2/xpsk.py -> python/gmsk2/mpsk.py + * python/gmsk2/xpsk_pkt.py -> python/gmsk2/mpsk_pkt.py + * python/gmsk2/xpsk_test.py -> python/gmsk2/mpsk_test.py + +2006-05-29 Eric Blossom + + * python/gmsk2/qpsk_tester.py, python/gmsk2/qpsk_usrp_tester.py: + new. Test benches for qpsk code. Thanks Tom! + +2005-12-19 Martin Dvh + + updated multi_usrp examples which should now work 'out-of-the-box' with current cvs + (you need updated usrp,gr-usrp, gnuradio-core and gnuradio-examples) + + * configure.ac: added python/usrp_multi/Makefile + * python/Makefile.am: added multi_usrp + * python/multi_usrp/.cvsignore: new + * python/multi_usrp/Makefile.am: new + * python/multi_usrp/README: Made this into a real readme + * python/multi_usrp/multi_usrp_oscope.py: changed to work with current usrp_multi code in cvs + * python/multi_usrp/multi_usrp_rx_cfile.py: changed to work with current usrp_multi code in cvs + * python/multi_usrp/multi_usrp.py: removed + * python/multi_usrp/multi_usrp_oscope_showcounters.py: removed + * python/multi_usrp/multi_usrp_oscope_simple.py: removed + * python/multi_usrp/multi_usrp_oscope_standalone.py: removed + * python/multi_usrp/multi_usrp_rx_tofile.py: removed + * python/multi_usrp/multi_usrp_rx_tofile_standalone.py: removed + * python/multi_usrp/multi_usrp_test_counting.py: removed + +2006-05-10 Eric Blossom + + * python/gmsk2/psk_transmit_path.py: add diff=False per Bob Vincent. + +2006-04-06 Eric Blossom + + * python/usrp/usrp_fft.py: removed explicit setting of fft_rate. + The code will now pick it up from config files. + +2006-03-12 Eric Blossom + + * python/usrp/usrp_siggen.py: added daughterboard support. + * python/usrp/usrp_oscope.py, python/usrp/usrp_fft.py: fixed so + frequency can be set even after an invalid frequency is passed on + the command line. + +2006-03-10 Eric Blossom + + * python/gmsk2/xpsk.py: doc fixes. + +2006-03-08 Eric Blossom + + * python/usrp/fm_tx_2_daughterboards.py: example that transmits + different signals out two daughterboards. + +2006-02-02 Eric Blossom + + * python/usrp/usrp_oscope.py: support manual scaling of + Y-axis. Smarter defaulting of rx_subdev_spec if user doesn't pick. + * python/usrp/usrp_fft.py: Smarter defaulting of rx_subdev_spec if user doesn't pick. + +2006-02-01 Eric Blossom + + * python/gmsk2/transmit_path.py: fixed so it works on both A and B sides. + +2006-01-30 Eric Blossom + + * python/gmsk2/receive_path.py (receive_path.set_auto_tr): added + set_auto_tr to the receive path to have it work properly with + changes in auto t/r switching semantics. + + * python/usrp/fm_tx4.py (fm_tx_graph.__init__): changes to have it + work in both A and B sides. + +2005-12-19 Martin Dvh + + * multi_usrp/README, multi_usrp/multi_usrp.py, multi_usrp/multi_usrp_oscope.py, + multi_usrp/multi_usrp_oscope_showcounters.py, multi_usrp/multi_usrp_oscope_simple.py, + multi_usrp/multi_usrp_oscope_standalone.py, multi_usrp/multi_usrp_rx_tofile.py, + multi_usrp/multi_usrp_rx_tofile_standalone.py, multi_usrp/multi_usrp_test_counting.py: + new directory and examples to exercise multiple usrps coherently + connected together. These require additional code that is not yet + in the repository. + +2005-12-13 Eric Blossom + + * python/usrp/usrp_wfm_rcv2_nogui.py: new: receive two FM stations + simultaneously. + +2005-12-09 Eric Blossom + + * python/gmsk2/tunnel_ip_null_mac.py: cleaned up. gathered mac + functions together. + + * python/usrp/usrp_wfm_rcv_pll.py (pick_subdevice), + python/usrp/usrp_wfm_rcv_nogui.py (pick_subdevice): use library version. + * python/usrp/fm_tx4.py: explicity call set_enable(True) to turn + on transmitter (required due to policy change). Also removed + pick_tx_subdevice. Now use version in usrp library. + +2005-12-09 Eric Blossom + + Made release 2.6 + +2005-12-08 Eric Blossom + + * python/gmsk/rx.py, python/gmsk/rx2.py, python/gmsk/tx.py, + python/gmsk/tx2.py, python/gmsk/xcvr.py, python/gmsk/xcvr2.py, + ggmsk-test.py, gmsk-test.py: removed. Use the code in ../gmsk2 instead. + + * python/gmsk2/receive_path.py, python/gmsk2/transmit_path.py: + New. Extracted hierarchical blocks from benchmark_gmsk_{tx,rx}.py + +2005-12-06 Eric Blossom + + * python/gmsk2/benchmark_gmsk_tx.py, + python/gmsk2/benchmark_gmsk_rx.py: now support "--bitrate" command + line arg. + * python/gmsk2/pick_bitrate.py: given a bitrate, determine + samples/baud and interp/decim ratio. + +2005-11-11 Eric Blossom + + * python/usrp/usrp_nbfm_ptt.py, python/usrp/usrp_wfm_rcv.py: moved + pick_xx_subdev to library. + +2005-11-01 Eric Blossom + + * python/usrp/dbs_nbfm.py: removed. Use usrp_nbfm_rcv.py instead. + +2005-10-24 Eric Blossom + + * python/usrp/usrp_oscope.py: basically identical to usrp_fft.py, + but uses oscope sink. + + * python/usrp/usrp_wfm_rcv_nogui.py, python/usr/usrp_wfm_rcv.py: + increased usrp decimation factor to 200 reduce host cpu + requirements. With the half-band in the FPGA, good decimation + factors are even values in [8,256]. + +2005-10-14 Eric Blossom + + * python/usrp/usrp_fft.py: gui mods. + * python/usrp/usrp_wfm_rcv.py: reworked gui. + +2005-10-11 Eric Blossom + + * python/usrp/usrp_waterfall.py: removed. Use usrp_fft.py -W instead. + +2005-10-10 Eric Blossom + + * python/audio/audio_copy.py, python/audio/audio_play.py, + python/audio/audio_to_file.py, python/audio/dial_tone.py, + python/audio/mono_tone.py, python/audio/multi_tone.py, + python/audio/spectrum_inversion.py: revised to use standard + command line args and canonical structure. + +2005-09-21 Eric Blossom + + * python/usrp/usrp_fft.py: extensively reworked to use new + daughterboard auto-instantiation framework. + +2005-07-30 Martin Dvh + + * python/usrp/tvrx_tv_rcv.py: PAL/NTSC TV demod. Work in progress. + +2005-07-21 Eric Blossom + + * python/usrp/benchmark_usb.py, python/usrp/usrp_rx_cfile.py, + python/usrp/usrp_oscope.py, python/usrp/dbs_debug: doc fix. + +2005-07-19 Eric Blossom + + * python/usrp/ayfabtu.py: new. Transmit on 25 frequencies simultaneously! + +2005-07-02 Eric Blossom + + * config/gr_no_undefined.m4, config/gr_x86_64.m4: new, x86_64 support. + * config/gr_python.m4: backed out search for libpython, making + x86_64 work and breaking Cygwin/MinGW. + * configure.ac: mods for x86_64, $(NO_UNDEFINED) + + * python/usrp/usrp_waterfall.py, python/usrp/dbs_debug.py, + python/usrp/flexrf_debug.py, python/usrp/flexrf_siggen.py, + python/usrp/usrp_fft.py, python/usrp/usrp_oscope.py, + python/usrp/usrp_rx_cfile.py, python/usrp/usrp_rx_file.py, + python/usrp/usrp_siggen.py, python/usrp/usrp_waterfall.py: + gru.hexint fix for python 2.4. + +2005-06-17 Eric Blossom + + * python/apps/README: new directory for applications. + +2005-06-16 Eric Blossom + + * python/usrp/tvrx_wfm_rcv_gui.py: add -d audio_device option; fix + volume increment so up == 1.0/down; fix default range of bottom FFT. + +2005-06-13 Eric Blossom + + * python/usrp/tvrx_wfm_rcv_gui.py: removed limit on what frequency + can be set. + +2005-05-09 Stephane Fillod + + * config/gr_sysv_shm.m4: SysV shared memory not mandatory + * config/gr_pwin32.m4, config/gr_python.m4, config/lf_cxx.m4: + fixes for Cygwin, MinGW + +2005-04-27 Eric Blossom + + * python/digital_voice/encdec.py: simulate gsm voice encode / + gmsk mod / gmsk demod / gsm voice decode. + +2005-03-29 Eric Blossom + + * python/gmsk/ggmsk-test.py, python/gmsk/gmsk-test.py: new GMSK + test code from Joshua Lackey + + * python/gmsk/tx.py, python/gmsk/rx.py: new tx and rx modules that + depending on command line options do either FSK or GMSK and use + either files, sockets, named pipes or a USRP for their inputs and + outputs. From Bob Vincent + +2005-03-29 Eric Blossom + + * python/audio/audio_copy.py, python/audio/multi_tone.py, + python/audio/mono_tone.py: replace ALSA specific default argument + with "" + +2005-03-04 Eric Blossom + + * python/usrp/nbfm_ptt_quick_and_dirty.py: simple NBFM + push-to-talk transceiver. (Works, but has a latency problem that + needs to be fixed) + +2005-02-28 Eric Blossom + + * python/usrp/fsk_tx.py: reduced gain, added -N (no gui) flag. + * python/usrp/fsk_rx.py: added -N (no gui) flag. + Running Tx and Rx on same machine (1.4 GHz Pentium M) 100kb/sec + burns up about 70% of CPU with -N options on both. + +2005-02-25 Eric Blossom + + Removed usrp0 directory. + Moved contents of usrp1 directory into usrp directory. + +2005-02-22 Eric Blossom + + * python/usrp1/nbfm_rcv.py: added squelch. + +2004-10-13 Eric Blossom + + * configure.ac: upped rev to 0.2cvs + +2004-10-11 Eric Blossom + + * Makefile.am (EXTRA_DIST): added config.h.in + +2004-10-07 Chuck Swiger + + * python/audio/audio_to_file.py: coerce audio sample rate to int. + +2004-10-07 Eric Blossom + + * python/usrp1/wfm_rcv.py: new. Single channel broadcast FM + receiver for usrp1 + microtune 4937. + +2004-09-23 Eric Blossom + + * config/usrp_fusb_tech.m4, config/bnv_have_qt.m4, config/cppunit.m4, + config/gr_check_mc4020.m4, config/gr_check_usrp.m4, config/gr_doxygen.m4, + config/gr_gprof.m4, config/gr_scripting.m4, config/gr_set_md_cpu.m4, + config/pkg.m4, config/usrp_fusb_tech.m4: added additional quoting + to first arg of AC_DEFUN to silence automake warning. + +2004-09-18 Eric Blossom + + These changes happened somewhere around DCC + + * python/usrp/usrp_fft.py: new + * python/usrp1/dsb_tx.py: new double sideband AM transmitter + * python/usrp1/fm_tx4.py: simultaneous 4 channel narrow band FM transmitter + * python/usrp1/fsk_rx.py: FSK Rx module. Needs some work. + * python/usrp1/fsk_tx.py: FSK Tx module. Needs some work. + +2004-08-19 Eric Blossom + + * python/usrp/usrp_rx_file.py (main): added command line parsing. + * python/usrp/usrp_siggen.py: added command line parsing. + + * python/usrp1/test_digital_loopback_lfsr.py, + python/usrp1/test_digital_loopback_counting.py, + python/usrp1/test_digital_counting.py: new. Take advantage of + scheduler fix to implement both the tx and rx path's in the same + flow graph. + + +2004-07-31 Eric Blossom + + * python/usrp0, python/usrp1: new directories for rev specific examples. + * python/usrp1/loopback.py (main): new. + +2004-07-30 Eric Blossom + + * python/usrp/usrp_siggen.py: now directly queries hardware for dac freq. + * python/usrp/usrp_rx_file.py: now directly queries hardware for dac freq. + +2004-07-17 Eric Blossom + + * python/mc4020/fm_demod.py: updated to use new mc4020 block, formatting + +2004-07-12 Eric Blossom + + * configure.ac: upped rev to 0.1cvs + +2004-07-03 Eric Blossom + + * python/usrp/usrp_siggen.py: Yeah! The first demo program that + reconfigures the flow graph on the fly! + +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# diff --git a/gnuradio-examples/Makefile.am b/gnuradio-examples/Makefile.am new file mode 100644 index 00000000..76111384 --- /dev/null +++ b/gnuradio-examples/Makefile.am @@ -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. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = README.hacking +SUBDIRS = python + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = diff --git a/gnuradio-examples/NEWS b/gnuradio-examples/NEWS new file mode 100644 index 00000000..e69de29b diff --git a/gnuradio-examples/README b/gnuradio-examples/README new file mode 100644 index 00000000..89515bb3 --- /dev/null +++ b/gnuradio-examples/README @@ -0,0 +1,68 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +Welcome! + +This package is a collection of examples for the GNU Radio 2.x toolkit. + +They assume that at a minimum, you've got the gnuradio-core +package installed. In addition, depending on what i/o devices you +have, you may want to consider installing: + + gr-usrp : support for Universal Software Radio Peripheral (Rev 1) + gr-audio-oss : sound card support using OSS + gr-audio-alsa : sound card support using ALSA + gr-audio-osx : sound card support for OS/X + gr-mc4020 : Measurement Computing PCI-DAS 4020/12 A/D card + + +You'll need to set your PYTHONPATH environment variable so that the +GNU Radio toolkit and optional packages can be found by python. + +PYTHONPATH should include the path of the local site-packages +directory. It has the general form: + + ${prefix}/lib/python${pythonversion}/site-packages + +If the above packages were installed using the default prefix +(/usr/local) and you're using python 2.3, this should work: + + $ export PYTHONPATH=/usr/local/lib/python2.3/site-packages + +You may want to add this to your ~/.bash_profile or similar file. + + +Once PYTHONPATH is set, you should be able to run any of the examples +for which you have the required i/o devices. + +To ensure that your setup is sane, try this: + + $ python + >>> from gnuradio import gr + +If this works, your PYTHONPATH is set correctly. + + +Have fun! + +The GNU Radio team + + diff --git a/gnuradio-examples/README.hacking b/gnuradio-examples/README.hacking new file mode 100644 index 00000000..44d42474 --- /dev/null +++ b/gnuradio-examples/README.hacking @@ -0,0 +1,39 @@ +* Standard command line options + +When building applications or examples, if your command has any of +these options, please use the following short and long names: + + + + # General + + parser = OptionParser(option_class=eng_option) + + parser.add_option("-f", "--freq", type="eng_float", default=None, + help="set frequency to FREQ", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=None, + help="set gain in dB (default is midpoint)") + parser.add_option("-F", "--filename", type="string", default=None) + + # Audio devices + + parser.add_option("-I", "--audio-input", type=string, default="", + help="pcm input device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-O", "--audio-output", type=string, default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-r", "--sample-rate", type="eng_float", default=48000, + help="set sample rate to RATE (48000)") + + # USRP specific + + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=(0, 0), + help="select USRP Rx side A or B (default=A)") + parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=(0, 0), + help="select USRP Tx side A or B (default=A)") + parser.add_option("-d", "--decim", type="int", default=16, + help="set fgpa decimation rate to DECIM (default=16)") + parser.add_option("-i", "--interp", type="int", default=32, + help="set fgpa interpolation rate to INTERP (default=32)") + parser.add_option("-n", "--nchannels", type=intx, default=1, + help="set number of channels to NCHANNELS (default=1)") + diff --git a/gnuradio-examples/python/Makefile.am b/gnuradio-examples/python/Makefile.am new file mode 100644 index 00000000..73b7921b --- /dev/null +++ b/gnuradio-examples/python/Makefile.am @@ -0,0 +1,22 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +SUBDIRS = audio mc4020 usrp gmsk2 digital_voice multi_usrp diff --git a/gnuradio-examples/python/apps/README b/gnuradio-examples/python/apps/README new file mode 100644 index 00000000..a3f041bf --- /dev/null +++ b/gnuradio-examples/python/apps/README @@ -0,0 +1,26 @@ +# +# 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 directory servers as the parent directory for various and sundry +applications such as scanners, HF radios, etc. Each subdirectory +shall have a README file that includes a short description of what the +application does, and a list of hardware dependencies. E.g., requires +a USRP with an xyz daughterboard, connected to a footronics magic box. diff --git a/gnuradio-examples/python/apps/hf_explorer/README b/gnuradio-examples/python/apps/hf_explorer/README new file mode 100644 index 00000000..5f780b3d --- /dev/null +++ b/gnuradio-examples/python/apps/hf_explorer/README @@ -0,0 +1,48 @@ +hfx.py is meant to be a full-featured Long Wave / Medium Wave +and Short Wave (250kHz to 30Mhz) AM and Single Sideband receiver. +It uses the USRP with a Basic RX board, and will need an +antenna and some preamps, about 30db gain will work. See the +'Help' menu or hfx_help for more info. + +---------------------------------------------------------- + +hfx2.py is a major revision built about complex fir filter +coeffecients ability and cleaner python script. Inherits +most features from hfx.py - Powermate knob supported but +not required, tooltip frequency display, single click +tuning, AGC, record to disk, play from disk and record audio. +New feature is ability to tailor the audio passband with two +sliders over the spectrum display. The sliders almost align +with the actual frequency. Preset filter settings for LSB +(-3000 to 0kHz), USB (0 to +3000kHz), CW (-400 to -800Hz) +and AM (-5kHz from carrier to +5kHz). + +AM now switches in a synchronous PLL detector with the +carriers at 7.5kHz. The PLL carrier is displayed in the +bottom display and helps show where on the upper spectrum +the demodulated signal lies. Everything gets shifted up +7.5kHz in AM, center frequency, tooltips, etc. The target +AM carrier needs to be closely tuned in, it will have a +hollow sound untill it is locked, and then the PLL carrier +in the bottom display will jump up and remain relatively +constant. There is a slider "AM sync carrier" to play with +different levels to mix with the signal for demodulation. +The filter in AM is preset to 2500/12500 (7.5kHz +/- 5kHz) +and is handy for removing adjacent channel interference. +Change AM_SYNC_DISPLAY in script for whether to show AM +Sync carrier or not. +Run with "-h" for command line help with setting USRP +ddc center frequency, decimation, rf data record, playback +and audio data recording. + +There are some controls for controlling a varactor and +tuning an antenna - just ignore them unless you want +to build a voltage tuned antenna to track frequency. + +There is also code for Web based control of frequency and +volume - so I can tune the radio with an Ipaq from bed. +Disabled by default - it takes a web server, some +directories and scripts to use. + + + diff --git a/gnuradio-examples/python/apps/hf_explorer/hfx2.py b/gnuradio-examples/python/apps/hf_explorer/hfx2.py new file mode 100755 index 00000000..c09f962c --- /dev/null +++ b/gnuradio-examples/python/apps/hf_explorer/hfx2.py @@ -0,0 +1,786 @@ +#!/usr/bin/env python +# -*- coding: ANSI_X3.4-1968 -*- +# generated by wxGlade 0.4 on Tue Mar 14 10:16:06 2006 +# +# 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. +# +#----------------------------------------------------------------- +# +# +-->(fft) +# | +# (src)->(xlate)--+->(audio filter)--+-->(sel_am)-+--------------+ +# | | | +# | (pll) | +# | | | +# | (pll_carrier_scale) | +# | | | +# | (pll_carrier_filter) | +# | | | +# | +--(fft2) | +# | | | +# | +--(c2f3)--+ | +# | | | | +# | (phaser1) (phaser2) | +# | | | | +# | +--(f2c)---+ | +# | | V +# V +---------->(am_det) +# (c2f) | +# | (c2f2) +# | | +# +-->(sel_sb)------------>(combine) +# | +# V +# +--------------------------(scale) +# | | +# | | +# | +++ +# V | | +# (agc)<--(offset)<--(intr)<---(sqr1) +# | +# V +# (dst) +# +#---------------------------------------------------------------------- +# +# Versions 2.2.1 adds loop antenna automatic tuner +# +# 2.3.1 adds web control, made AM Sync display optional, +# added more comments. +# +# 2.4.1 updates usrp interface to support auto subdev + +# Web server control disabled by default. Do not enable +# until directory structure and scripts are in place. +WEB_CONTROL = False + +# Controls display of AM Sync Carrier - turn off for smaller +# window if not needed +AM_SYNC_DISPLAY = False + +import os, wx, sys, math +import wx.lib.evtmgr as em +from gnuradio.wxgui import powermate, fftsink +from gnuradio import gr, audio, eng_notation, usrp, gru +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +ID_BUTTON_1 = wx.NewId() # LSB button +ID_BUTTON_2 = wx.NewId() # USB +ID_BUTTON_3 = wx.NewId() # AM +ID_BUTTON_4 = wx.NewId() # CW +ID_BUTTON_5 = wx.NewId() # Powermate controls: Upper audio freq cutoff +ID_BUTTON_6 = wx.NewId() # " Lower audio freq cutoff +ID_BUTTON_7 = wx.NewId() # " Frequency +ID_BUTTON_8 = wx.NewId() # " Volume +ID_BUTTON_9 = wx.NewId() # " Time +ID_BUTTON_10 = wx.NewId() # Time Seek Forwards +ID_BUTTON_11 = wx.NewId() # Time Seek Backwards +ID_BUTTON_12 = wx.NewId() # Automatic Antenna Tune (AT) enable +ID_BUTTON_13 = wx.NewId() # AT Calibrate point +ID_BUTTON_14 = wx.NewId() # AT Reset +ID_TEXT_1 = wx.NewId() # Band Center, USRP ddc Freq +ID_SPIN_1 = wx.NewId() # Frequency display and control +ID_SLIDER_1 = wx.NewId() # Upper audio freq cutoff +ID_SLIDER_2 = wx.NewId() # Lower audio freq cutoff +ID_SLIDER_3 = wx.NewId() # Frequency +ID_SLIDER_4 = wx.NewId() # Volume +ID_SLIDER_5 = wx.NewId() # Programmable Gain Amp, PGA, RF gain +ID_SLIDER_6 = wx.NewId() # AM Sync carrier level +ID_SLIDER_7 = wx.NewId() # AT control voltage output +ID_EXIT = wx.NewId() # Menu Exit + + +def pick_subdevice(u): + """ + The user didn't specify a subdevice on the command line. + If there's a daughterboard on A, select A. + If there's a daughterboard on B, select B. + Otherwise, select A. + """ + if u.db[0][0].dbid() >= 0: # dbid is < 0 if there's no d'board or a problem + return (0, 0) + if u.db[1][0].dbid() >= 0: + return (1, 0) + return (0, 0) + + +class MyFrame(wx.Frame): + def __init__(self, *args, **kwds): + # begin wxGlade: MyFrame.__init__ + kwds["style"] = wx.DEFAULT_FRAME_STYLE + wx.Frame.__init__(self, *args, **kwds) + + # Menu Bar + self.frame_1_menubar = wx.MenuBar() + self.SetMenuBar(self.frame_1_menubar) + wxglade_tmp_menu = wx.Menu() + self.Exit = wx.MenuItem(wxglade_tmp_menu, ID_EXIT, "Exit", "Exit", wx.ITEM_NORMAL) + wxglade_tmp_menu.AppendItem(self.Exit) + self.frame_1_menubar.Append(wxglade_tmp_menu, "File") + # Menu Bar end + self.panel_1 = wx.Panel(self, -1) + self.button_1 = wx.Button(self, ID_BUTTON_1, "LSB") + self.button_2 = wx.Button(self, ID_BUTTON_2, "USB") + self.button_3 = wx.Button(self, ID_BUTTON_3, "AM") + self.button_4 = wx.Button(self, ID_BUTTON_4, "CW") + self.button_5 = wx.ToggleButton(self, ID_BUTTON_5, "Upper") + self.slider_1 = wx.Slider(self, ID_SLIDER_1, 0, -15799, 15799, style=wx.SL_HORIZONTAL|wx.SL_LABELS) + self.button_6 = wx.ToggleButton(self, ID_BUTTON_6, "Lower") + self.slider_2 = wx.Slider(self, ID_SLIDER_2, 0, -15799, 15799, style=wx.SL_HORIZONTAL|wx.SL_LABELS) + self.panel_5 = wx.Panel(self, -1) + self.label_1 = wx.StaticText(self, -1, " Band\nCenter") + self.text_ctrl_1 = wx.TextCtrl(self, ID_TEXT_1, "") + self.panel_6 = wx.Panel(self, -1) + self.panel_7 = wx.Panel(self, -1) + self.panel_2 = wx.Panel(self, -1) + self.button_7 = wx.ToggleButton(self, ID_BUTTON_7, "Freq") + self.slider_3 = wx.Slider(self, ID_SLIDER_3, 3000, 0, 6000) + self.spin_ctrl_1 = wx.SpinCtrl(self, ID_SPIN_1, "", min=0, max=100) + self.button_8 = wx.ToggleButton(self, ID_BUTTON_8, "Vol") + self.slider_4 = wx.Slider(self, ID_SLIDER_4, 0, 0, 500) + self.slider_5 = wx.Slider(self, ID_SLIDER_5, 0, 0, 20) + self.button_9 = wx.ToggleButton(self, ID_BUTTON_9, "Time") + self.button_11 = wx.Button(self, ID_BUTTON_11, "Rew") + self.button_10 = wx.Button(self, ID_BUTTON_10, "Fwd") + self.panel_3 = wx.Panel(self, -1) + self.label_2 = wx.StaticText(self, -1, "PGA ") + self.panel_4 = wx.Panel(self, -1) + self.panel_8 = wx.Panel(self, -1) + self.panel_9 = wx.Panel(self, -1) + self.label_3 = wx.StaticText(self, -1, "AM Sync\nCarrier") + self.slider_6 = wx.Slider(self, ID_SLIDER_6, 50, 0, 200, style=wx.SL_HORIZONTAL|wx.SL_LABELS) + self.label_4 = wx.StaticText(self, -1, "Antenna Tune") + self.slider_7 = wx.Slider(self, ID_SLIDER_7, 1575, 950, 2200, style=wx.SL_HORIZONTAL|wx.SL_LABELS) + self.panel_10 = wx.Panel(self, -1) + self.button_12 = wx.ToggleButton(self, ID_BUTTON_12, "Auto Tune") + self.button_13 = wx.Button(self, ID_BUTTON_13, "Calibrate") + self.button_14 = wx.Button(self, ID_BUTTON_14, "Reset") + self.panel_11 = wx.Panel(self, -1) + self.panel_12 = wx.Panel(self, -1) + + self.__set_properties() + self.__do_layout() + # end wxGlade + + parser = OptionParser (option_class=eng_option) + parser.add_option ("-c", "--ddc-freq", type="eng_float", default=3.9e6, + help="set Rx DDC frequency to FREQ", metavar="FREQ") + parser.add_option ("-a", "--audio_file", default="", + help="audio output file", metavar="FILE") + parser.add_option ("-r", "--radio_file", default="", + help="radio output file", metavar="FILE") + parser.add_option ("-i", "--input_file", default="", + help="radio input file", metavar="FILE") + parser.add_option ("-d", "--decim", type="int", default=250, + help="USRP decimation") + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, help="select USRP Rx side A or B (default=first one with a daughterboard)") + (options, args) = parser.parse_args () + + self.usrp_center = options.ddc_freq + usb_rate = 64e6 / options.decim + self.slider_range = usb_rate * 0.9375 + self.f_lo = self.usrp_center - (self.slider_range/2) + self.f_hi = self.usrp_center + (self.slider_range/2) + self.af_sample_rate = 32000 + fir_decim = long (usb_rate / self.af_sample_rate) + + # data point arrays for antenna tuner + self.xdata = [] + self.ydata = [] + + self.fg = gr.flow_graph() + + # radio variables, initial conditions + self.frequency = self.usrp_center + # these map the frequency slider (0-6000) to the actual range + self.f_slider_offset = self.f_lo + self.f_slider_scale = 10000/options.decim + self.spin_ctrl_1.SetRange(self.f_lo,self.f_hi) + self.text_ctrl_1.SetValue(str(int(self.usrp_center))) + self.slider_5.SetValue(0) + self.AM_mode = False + + self.slider_3.SetValue((self.frequency-self.f_slider_offset)/self.f_slider_scale) + self.spin_ctrl_1.SetValue(int(self.frequency)) + + POWERMATE = True + try: + self.pm = powermate.powermate(self) + except: + sys.stderr.write("Unable to find PowerMate or Contour Shuttle\n") + POWERMATE = False + + if POWERMATE: + powermate.EVT_POWERMATE_ROTATE(self, self.on_rotate) + powermate.EVT_POWERMATE_BUTTON(self, self.on_pmButton) + self.active_button = 7 + + # command line options + if options.audio_file == "": SAVE_AUDIO_TO_FILE = False + else: SAVE_AUDIO_TO_FILE = True + if options.radio_file == "": SAVE_RADIO_TO_FILE = False + else: SAVE_RADIO_TO_FILE = True + if options.input_file == "": self.PLAY_FROM_USRP = True + else: self.PLAY_FROM_USRP = False + + if self.PLAY_FROM_USRP: + self.src = usrp.source_c(decim_rate=options.decim) + if options.rx_subdev_spec is None: + options.rx_subdev_spec = pick_subdevice(self.src) + self.src.set_mux(usrp.determine_rx_mux_value(self.src, options.rx_subdev_spec)) + self.subdev = usrp.selected_subdev(self.src, options.rx_subdev_spec) + self.src.tune(0, self.subdev, self.usrp_center) + self.tune_offset = 0 # -self.usrp_center - self.src.rx_freq(0) + + else: + self.src = gr.file_source (gr.sizeof_gr_complex,options.input_file) + self.tune_offset = 2200 # 2200 works for 3.5-4Mhz band + + # save radio data to a file + if SAVE_RADIO_TO_FILE: + file = gr.file_sink(gr.sizeof_gr_complex, options.radio_file) + self.fg.connect (self.src, file) + + # 2nd DDC + xlate_taps = gr.firdes.low_pass ( \ + 1.0, usb_rate, 16e3, 4e3, gr.firdes.WIN_HAMMING ) + self.xlate = gr.freq_xlating_fir_filter_ccf ( \ + fir_decim, xlate_taps, self.tune_offset, usb_rate ) + + # Complex Audio filter + audio_coeffs = gr.firdes.complex_band_pass ( + 1.0, # gain + self.af_sample_rate, # sample rate + -3000, # low cutoff + 0, # high cutoff + 100, # transition + gr.firdes.WIN_HAMMING) # window + self.slider_1.SetValue(0) + self.slider_2.SetValue(-3000) + + self.audio_filter = gr.fir_filter_ccc ( 1, audio_coeffs) + + # Main +/- 16Khz spectrum display + self.fft = fftsink.fft_sink_c (self.fg, self.panel_2, fft_size=512, sample_rate=self.af_sample_rate, average=True, size=(640,240)) + + # AM Sync carrier + if AM_SYNC_DISPLAY: + self.fft2 = fftsink.fft_sink_c (self.fg, self.panel_9, y_per_div=20, fft_size=512, sample_rate=self.af_sample_rate, average=True, size=(640,240)) + + c2f = gr.complex_to_float() + + # AM branch + self.sel_am = gr.multiply_const_cc(0) + # the following frequencies turn out to be in radians/sample + # gr.pll_refout_cc(alpha,beta,min_freq,max_freq) + # suggested alpha = X, beta = .25 * X * X + pll = gr.pll_refout_cc(.5,.0625,(2.*math.pi*7.5e3/self.af_sample_rate),(2.*math.pi*6.5e3/self.af_sample_rate)) + self.pll_carrier_scale = gr.multiply_const_cc(complex(10,0)) + am_det = gr.multiply_cc() + # these are for converting +7.5kHz to -7.5kHz + # for some reason gr.conjugate_cc() adds noise ?? + c2f2 = gr.complex_to_float() + c2f3 = gr.complex_to_float() + f2c = gr.float_to_complex() + phaser1 = gr.multiply_const_ff(1) + phaser2 = gr.multiply_const_ff(-1) + + # filter for pll generated carrier + pll_carrier_coeffs = gr.firdes.complex_band_pass ( + 2.0, # gain + self.af_sample_rate, # sample rate + 7400, # low cutoff + 7600, # high cutoff + 100, # transition + gr.firdes.WIN_HAMMING) # window + + self.pll_carrier_filter = gr.fir_filter_ccc ( 1, pll_carrier_coeffs) + + self.sel_sb = gr.multiply_const_ff(1) + combine = gr.add_ff() + + #AGC + sqr1 = gr.multiply_ff() + intr = gr.iir_filter_ffd ( [.004, 0], [0, .999] ) + offset = gr.add_const_ff(1) + agc = gr.divide_ff() + + + self.scale = gr.multiply_const_ff(0.00001) + dst = audio.sink(long(self.af_sample_rate)) + + self.fg.connect(self.src,self.xlate,self.fft) + self.fg.connect(self.xlate,self.audio_filter,self.sel_am,(am_det,0)) + self.fg.connect(self.sel_am,pll,self.pll_carrier_scale,self.pll_carrier_filter,c2f3) + self.fg.connect((c2f3,0),phaser1,(f2c,0)) + self.fg.connect((c2f3,1),phaser2,(f2c,1)) + self.fg.connect(f2c,(am_det,1)) + self.fg.connect(am_det,c2f2,(combine,0)) + self.fg.connect(self.audio_filter,c2f,self.sel_sb,(combine,1)) + if AM_SYNC_DISPLAY: + self.fg.connect(self.pll_carrier_filter,self.fft2) + self.fg.connect(combine,self.scale) + self.fg.connect(self.scale,(sqr1,0)) + self.fg.connect(self.scale,(sqr1,1)) + self.fg.connect(sqr1, intr, offset, (agc, 1)) + self.fg.connect(self.scale,(agc, 0)) + self.fg.connect(agc,dst) + + if SAVE_AUDIO_TO_FILE: + f_out = gr.file_sink(gr.sizeof_short,options.audio_file) + sc1 = gr.multiply_const_ff(64000) + f2s1 = gr.float_to_short() + self.fg.connect(agc,sc1,f2s1,f_out) + + self.fg.start() + + # for mouse position reporting on fft display + em.eventManager.Register(self.Mouse, wx.EVT_MOTION, self.fft.win) + # and left click to re-tune + em.eventManager.Register(self.Click, wx.EVT_LEFT_DOWN, self.fft.win) + + # start a timer to check for web commands + if WEB_CONTROL: + self.timer = UpdateTimer(self, 1000) # every 1000 mSec, 1 Sec + + + wx.EVT_BUTTON(self,ID_BUTTON_1,self.set_lsb) + wx.EVT_BUTTON(self,ID_BUTTON_2,self.set_usb) + wx.EVT_BUTTON(self,ID_BUTTON_3,self.set_am) + wx.EVT_BUTTON(self,ID_BUTTON_4,self.set_cw) + wx.EVT_BUTTON(self,ID_BUTTON_10,self.fwd) + wx.EVT_BUTTON(self,ID_BUTTON_11,self.rew) + wx.EVT_BUTTON(self, ID_BUTTON_13, self.AT_calibrate) + wx.EVT_BUTTON(self, ID_BUTTON_14, self.AT_reset) + wx.EVT_TOGGLEBUTTON(self,ID_BUTTON_5,self.on_button) + wx.EVT_TOGGLEBUTTON(self,ID_BUTTON_6,self.on_button) + wx.EVT_TOGGLEBUTTON(self,ID_BUTTON_7,self.on_button) + wx.EVT_TOGGLEBUTTON(self,ID_BUTTON_8,self.on_button) + wx.EVT_TOGGLEBUTTON(self,ID_BUTTON_9,self.on_button) + wx.EVT_SLIDER(self,ID_SLIDER_1,self.set_filter) + wx.EVT_SLIDER(self,ID_SLIDER_2,self.set_filter) + wx.EVT_SLIDER(self,ID_SLIDER_3,self.slide_tune) + wx.EVT_SLIDER(self,ID_SLIDER_4,self.set_volume) + wx.EVT_SLIDER(self,ID_SLIDER_5,self.set_pga) + wx.EVT_SLIDER(self,ID_SLIDER_6,self.am_carrier) + wx.EVT_SLIDER(self,ID_SLIDER_7,self.antenna_tune) + wx.EVT_SPINCTRL(self,ID_SPIN_1,self.spin_tune) + + wx.EVT_MENU(self, ID_EXIT, self.TimeToQuit) + + def __set_properties(self): + # begin wxGlade: MyFrame.__set_properties + self.SetTitle("HF Explorer 2") + self.slider_1.SetMinSize((450, 38)) + self.slider_2.SetMinSize((450, 38)) + self.panel_2.SetMinSize((640, 240)) + self.button_7.SetValue(1) + self.slider_3.SetMinSize((450, 19)) + self.slider_4.SetMinSize((275, 19)) + self.slider_5.SetMinSize((275, 19)) + if AM_SYNC_DISPLAY: + self.panel_9.SetMinSize((640, 240)) + self.slider_6.SetMinSize((300, 38)) + self.slider_7.SetMinSize((400, 38)) + # end wxGlade + + def __do_layout(self): + # begin wxGlade: MyFrame.__do_layout + sizer_1 = wx.BoxSizer(wx.VERTICAL) + grid_sizer_1 = wx.FlexGridSizer(11, 2, 0, 0) + sizer_7 = wx.BoxSizer(wx.HORIZONTAL) + sizer_5 = wx.BoxSizer(wx.HORIZONTAL) + sizer_4 = wx.BoxSizer(wx.HORIZONTAL) + sizer_3 = wx.BoxSizer(wx.HORIZONTAL) + sizer_6 = wx.BoxSizer(wx.VERTICAL) + sizer_2 = wx.BoxSizer(wx.HORIZONTAL) + grid_sizer_1.Add(self.panel_1, 1, wx.EXPAND, 0) + sizer_2.Add(self.button_1, 0, wx.ADJUST_MINSIZE, 0) + sizer_2.Add(self.button_2, 0, wx.ADJUST_MINSIZE, 0) + sizer_2.Add(self.button_3, 0, wx.ADJUST_MINSIZE, 0) + sizer_2.Add(self.button_4, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(sizer_2, 1, wx.EXPAND, 0) + grid_sizer_1.Add(self.button_5, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.slider_1, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.button_6, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.slider_2, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ADJUST_MINSIZE, 0) + sizer_6.Add(self.panel_5, 1, wx.EXPAND, 0) + sizer_6.Add(self.label_1, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ADJUST_MINSIZE, 0) + sizer_6.Add(self.text_ctrl_1, 0, wx.ADJUST_MINSIZE, 0) + sizer_6.Add(self.panel_6, 1, wx.EXPAND, 0) + sizer_6.Add(self.panel_7, 1, wx.EXPAND, 0) + grid_sizer_1.Add(sizer_6, 1, wx.EXPAND, 0) + grid_sizer_1.Add(self.panel_2, 1, wx.EXPAND, 0) + grid_sizer_1.Add(self.button_7, 0, wx.ADJUST_MINSIZE, 0) + sizer_3.Add(self.slider_3, 0, wx.ADJUST_MINSIZE, 0) + sizer_3.Add(self.spin_ctrl_1, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(sizer_3, 1, wx.EXPAND, 0) + grid_sizer_1.Add(self.button_8, 0, wx.ADJUST_MINSIZE, 0) + sizer_4.Add(self.slider_4, 0, wx.ADJUST_MINSIZE, 0) + sizer_4.Add(self.slider_5, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(sizer_4, 1, wx.EXPAND, 0) + grid_sizer_1.Add(self.button_9, 0, wx.ADJUST_MINSIZE, 0) + sizer_5.Add(self.button_11, 0, wx.ADJUST_MINSIZE, 0) + sizer_5.Add(self.button_10, 0, wx.ADJUST_MINSIZE, 0) + sizer_5.Add(self.panel_3, 1, wx.EXPAND, 0) + sizer_5.Add(self.label_2, 0, wx.ADJUST_MINSIZE, 0) + sizer_5.Add(self.panel_4, 1, wx.EXPAND, 0) + grid_sizer_1.Add(sizer_5, 1, wx.EXPAND, 0) + grid_sizer_1.Add(self.panel_8, 1, wx.EXPAND, 0) + grid_sizer_1.Add(self.panel_9, 1, wx.EXPAND, 0) + grid_sizer_1.Add(self.label_3, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALIGN_CENTER_VERTICAL|wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.slider_6, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.label_4, 0, wx.ALIGN_BOTTOM|wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.slider_7, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.panel_10, 1, wx.EXPAND, 0) + sizer_7.Add(self.button_12, 0, wx.ADJUST_MINSIZE, 0) + sizer_7.Add(self.button_13, 0, wx.ADJUST_MINSIZE, 0) + sizer_7.Add(self.button_14, 0, wx.ADJUST_MINSIZE, 0) + sizer_7.Add(self.panel_11, 1, wx.EXPAND, 0) + sizer_7.Add(self.panel_12, 1, wx.EXPAND, 0) + grid_sizer_1.Add(sizer_7, 1, wx.EXPAND, 0) + sizer_1.Add(grid_sizer_1, 1, wx.EXPAND, 0) + self.SetAutoLayout(True) + self.SetSizer(sizer_1) + sizer_1.Fit(self) + sizer_1.SetSizeHints(self) + self.Layout() + # end wxGlade + + # Menu exit + def TimeToQuit(self, event): + self.fg.stop() + self.Close(True) + + # Powermate being turned + def on_rotate(self, event): + if self.active_button == 5: + self.slider_1.SetValue(self.slider_1.GetValue()+event.delta) + if self.slider_2.GetValue() > (self.slider_1.GetValue() - 200) : + self.slider_2.SetValue(self.slider_1.GetValue() - 200) + self.filter() + if self.active_button == 6: + self.slider_2.SetValue(self.slider_2.GetValue()+event.delta) + if self.slider_1.GetValue() < (self.slider_2.GetValue() + 200) : + self.slider_1.SetValue(self.slider_2.GetValue() + 200) + self.filter() + if self.active_button == 7: + new = max(0, min(6000, self.slider_3.GetValue() + event.delta)) + self.slider_3.SetValue(new) + self.frequency = (self.f_slider_scale * new) + self.f_slider_offset + self.spin_ctrl_1.SetValue(self.frequency) + if self.AM_mode == False: + self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset)) + else: + self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset - 7.5e3)) + if self.button_12.GetValue(): + self.auto_antenna_tune() + if self.active_button == 8: + new = max(0, min(500, self.slider_4.GetValue() + event.delta)) + self.slider_4.SetValue(new) + self.scale.set_k(math.pow(10.,((self.slider_4.GetValue()-500.)/100.))) + if self.active_button == 9: + if self.PLAY_FROM_USRP == False: + if event.delta == -1: + self.src.seek(-1000000,gr.SEEK_CUR) + elif event.delta == 1: + self.src.seek(1000000,gr.SEEK_CUR) + + + # Powermate pressed to switch controlled function + def on_pmButton(self, event): + if event.value == 0: + if self.active_button == 5: + self.active_button = 6 + self.button_5.SetValue(False) + self.button_6.SetValue(True) + elif self.active_button == 6: + self.active_button = 7 + self.button_6.SetValue(False) + self.button_7.SetValue(True) + elif self.active_button == 7: + self.active_button = 8 + self.button_7.SetValue(False) + self.button_8.SetValue(True) + elif self.active_button == 8: + self.active_button = 9 + self.button_8.SetValue(False) + self.button_9.SetValue(True) + elif self.active_button == 9: + self.active_button = 5 + self.button_9.SetValue(False) + self.button_5.SetValue(True) + + # Clicking one PM control button turns the rest off + def on_button(self, event): + id = event.GetId() + if id == ID_BUTTON_5: + self.active_button = 5 + self.button_6.SetValue(False) + self.button_7.SetValue(False) + self.button_8.SetValue(False) + self.button_9.SetValue(False) + if id == ID_BUTTON_6: + self.active_button = 6 + self.button_5.SetValue(False) + self.button_7.SetValue(False) + self.button_8.SetValue(False) + self.button_9.SetValue(False) + if id == ID_BUTTON_7: + self.active_button = 7 + self.button_5.SetValue(False) + self.button_6.SetValue(False) + self.button_8.SetValue(False) + self.button_9.SetValue(False) + if id == ID_BUTTON_8: + self.active_button = 8 + self.button_5.SetValue(False) + self.button_6.SetValue(False) + self.button_7.SetValue(False) + self.button_9.SetValue(False) + if id == ID_BUTTON_9: + self.active_button = 9 + self.button_5.SetValue(False) + self.button_6.SetValue(False) + self.button_7.SetValue(False) + self.button_8.SetValue(False) + + # Make sure filter settings are legal + def set_filter(self, event): + slider = event.GetId() + slider1 = self.slider_1.GetValue() + slider2 = self.slider_2.GetValue() + if slider == ID_SLIDER_1: + if slider2 > (self.slider_1.GetValue() - 200) : + self.slider_2.SetValue(slider1 - 200) + elif slider == ID_SLIDER_2: + if slider1 < (self.slider_2.GetValue() + 200) : + self.slider_1.SetValue(slider2 + 200) + self.filter() + + # Calculate taps and apply + def filter(self): + audio_coeffs = gr.firdes.complex_band_pass ( + 1.0, # gain + self.af_sample_rate, # sample rate + self.slider_2.GetValue(), # low cutoff + self.slider_1.GetValue(), # high cutoff + 100, # transition + gr.firdes.WIN_HAMMING) # window + self.audio_filter.set_taps(audio_coeffs) + + def set_lsb(self, event): + self.AM_mode = False + self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset)) + self.sel_sb.set_k(1) + self.sel_am.set_k(0) + self.slider_1.SetValue(0) + self.slider_2.SetValue(-3000) + self.filter() + + def set_usb(self, event): + self.AM_mode = False + self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset)) + self.sel_sb.set_k(1) + self.sel_am.set_k(0) + self.slider_1.SetValue(3000) + self.slider_2.SetValue(0) + self.filter() + + def set_am(self, event): + self.AM_mode = True + self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset - 7.5e3)) + self.sel_sb.set_k(0) + self.sel_am.set_k(1) + self.slider_1.SetValue(12500) + self.slider_2.SetValue(2500) + self.filter() + + def set_cw(self, event): + self.AM_mode = False + self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset)) + self.AM_mode = False + self.sel_sb.set_k(1) + self.sel_am.set_k(0) + self.slider_1.SetValue(-400) + self.slider_2.SetValue(-800) + self.filter() + + def set_volume(self, event): + self.scale.set_k(math.pow(10.,((self.slider_4.GetValue()-500.)/100.))) + + def set_pga(self,event): + if self.PLAY_FROM_USRP: + self.subdev.set_gain(self.slider_5.GetValue()) + + def slide_tune(self, event): + self.frequency = (self.f_slider_scale * self.slider_3.GetValue()) + self.f_slider_offset + if self.AM_mode == False: + self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset)) + else: + self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset - 7.5e3)) + self.spin_ctrl_1.SetValue(self.frequency) + if self.button_12.GetValue(): + self.auto_antenna_tune() + + def spin_tune(self, event): + self.frequency = self.spin_ctrl_1.GetValue() + if self.AM_mode == False: + self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset)) + else: + self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset - 7.5e3)) + self.slider_3.SetValue(int((self.frequency-self.f_slider_offset)/self.f_slider_scale)) + if self.button_12.GetValue(): + self.auto_antenna_tune() + + # Seek forwards in file + def fwd(self, event): + if self.PLAY_FROM_USRP == False: + self.src.seek(10000000,gr.SEEK_CUR) + + # Seek backwards in file + def rew(self, event): + if self.PLAY_FROM_USRP == False: + self.src.seek(-10000000,gr.SEEK_CUR) + + # Mouse over fft display - show frequency in tooltip + def Mouse(self,event): + if self.AM_mode: + fRel = ( event.GetX() - 330. ) / 14.266666 - 7.5 + else: + fRel = ( event.GetX() - 330. ) / 14.266666 + self.fft.win.SetToolTip(wx.ToolTip(eng_notation.num_to_str(self.frequency + (fRel*1e3)))) + + # Mouse clicked on fft display - change frequency + def Click(self,event): + fRel = ( event.GetX() - 330. ) / 14.266666 + if self.AM_mode == False: + self.frequency = self.frequency + (fRel*1e3) + else: + self.frequency = self.frequency + (fRel*1e3) - 7.5e3 + self.spin_ctrl_1.SetValue(int(self.frequency)) + self.slider_3.SetValue(int((self.frequency-self.f_slider_offset)/self.f_slider_scale)) + if self.AM_mode == False: + self.xlate.set_center_freq ( self.usrp_center - ( self.frequency - self.tune_offset )) + else: + self.xlate.set_center_freq( self.usrp_center - (self.frequency - self.tune_offset - 7.5e3)) + + # Set power of AM sync carrier + def am_carrier(self,event): + scale = math.pow(10,(self.slider_6.GetValue())/50.) + self.pll_carrier_scale.set_k(complex(scale,0)) + + # Reset AT data and start calibrate over + def AT_reset(self, event): + self.xdata = [] + self.ydata = [] + + # Save AT setting for a particular frequency + def AT_calibrate(self, event): + self.xdata.append(float(self.frequency)) + self.ydata.append(self.slider_7.GetValue()) + if len(self.xdata) > 1: + self.m = [] + self.b = [] + for i in range(0,len(self.xdata)-1): + self.m.append( (self.ydata[i+1] - self.ydata[i]) / (self.xdata[i+1] - self.xdata[i]) ) + self.b.append( self.ydata[i] - self.m[i] * self.xdata[i] ) + + # Lookup calibrated points and calculate interpolated antenna tune voltage. + # This is to automatically tune a narrowband loop antenna when the freq + # is changed, to keep signals peaked. + def auto_antenna_tune(self): + for i in range(0,len(self.xdata)-1): + if (self.frequency > self.xdata[i]) & (self.frequency < self.xdata[i+1]): + self.slider_7.SetValue(self.m[i]*self.frequency + self.b[i]) + self.antenna_tune(0) + + # Slider to set loop antenna capacitance + def antenna_tune(self, evt): + if self.PLAY_FROM_USRP: + self.src.write_aux_dac(0,3,self.slider_7.GetValue()) + + # Timer events - check for web commands + def OnUpdate(self): + cmds = os.listdir("/var/www/cgi-bin/commands/") + if cmds!=[]: + if cmds[0]=='chfreq': + fd=open("/var/www/cgi-bin/commands/chfreq","r") + new=fd.readline() + fd.close() + if new!='': + os.unlink("/var/www/cgi-bin/commands/chfreq") + if ( int(new) >= self.f_lo ) & ( int(new) <= self.f_hi ): + self.frequency = int(new) + self.slider_3.SetValue(( self.frequency - self.f_slider_offset) / self.f_slider_scale ) + self.spin_ctrl_1.SetValue(self.frequency) + if self.button_12.GetValue(): + self.auto_antenna_tune() + if self.AM_mode: + self.xlate.set_center_freq ( self.usrp_center - ( self.frequency - self.tune_offset - 7.5e3 )) + else: + self.xlate.set_center_freq ( self.usrp_center - ( self.frequency - self.tune_offset )) + + if cmds[0]=='chvolume': + fd=open("/var/www/cgi-bin/commands/chvolume","r") + new=fd.readline() + fd.close() + if new!='': + os.unlink("/var/www/cgi-bin/commands/chvolume") + if ( int(new) >= 0 ) & ( int(new) <= 500 ): + self.volume = int(new) + self.slider_4.SetValue(self.volume) + self.scale.set_k(math.pow(10.,((self.slider_4.GetValue()-500.)/100.))) + + else: # no new web commands, update state + fh = open("/var/www/cgi-bin/state/freq","w") + fh.write(str(int(self.frequency))+'\n') + fh.close() + fh = open("/var/www/cgi-bin/state/volume","w") + fh.write(str(self.slider_4.GetValue())+'\n') + fh.close() + + +# end of class MyFrame + +# wx.Timer to check for web updates +class UpdateTimer(wx.Timer): + def __init__(self, target, dur=1000): + wx.Timer.__init__(self) + self.target = target + self.Start(dur) + + def Notify(self): + """Called every timer interval""" + if self.target: + self.target.OnUpdate() + + +class MyApp(wx.App): + def OnInit(self): + frame = MyFrame(None, -1, "HF Explorer 2") + frame.Show(True) + self.SetTopWindow(frame) + return True + +app = MyApp(0) +app.MainLoop() + diff --git a/gnuradio-examples/python/apps/hf_explorer/hfx_help b/gnuradio-examples/python/apps/hf_explorer/hfx_help new file mode 100644 index 00000000..9a52dd2b --- /dev/null +++ b/gnuradio-examples/python/apps/hf_explorer/hfx_help @@ -0,0 +1,180 @@ + + HF Explorer Help + + ----------------------------------------------------------------------- + + Command Line Switches: + + -c DDC center frequency, set band. + -c 7.2e6 or -c 7.2M for 40 meter ham band. + Default is 3.9e6 80 meter ham band. + Example: + + hfx.py -c 9500k + + starts up in the 31 meter band. + + -a Audio output file. Output file for 32kHz two channel + signed word audio. Two channels are used for + independent sideband. This file can be converted + to a wav file with sox. Example: + + sox -c 2 -r 3200 file.sw file.wav + + sox needs the .sw extension to indicate file type. + If not specified no audio file is created. + + -r Radio output file. File to write RF data to for later + demodulation. Records the entire band to disk, width + determined by sample rate/decimation. Be sure to + note the decimation and center freq for later use! + Example: + + hfx.py -c 900e3 -d 80 -r rf_data_AM-c900e3-d80 + + writes a pre-demod rf file centered on 900kHz with a + bandwidth of 800kHz (That's 80 AM stations!). The + center and decimation could be put in the filename for + proper use later. + If not specified no rf data file is created. + At default 250 decimation disk usage is about + 8Gb / hour. + + -i Radio input file. Use to play back a previously + recorded rf data file. Example: + + hfx.py -c 900e3 -d 80 -i rf_data_AM-c900e3-d80 + + plays back the previously recorded band, no + usrp hardware needed. Tune about the 800kHz wide band. + When playing a recorded file, time controls + fast-forward and rewind are available. + + -d Decimation. Sets sample rate and bandwidth. + This is the factor that the usrp sample rate, 64e6, + is divided by. Default is 250 for 256kHz bandwidth + which is enough to record a ham band without + eating up disk space too fast. The 64e6 sample + rate limits the upper practical frequency to 32MHz. + The Basic RX transformer limits the lower frequency + to about 200kHz. + + + Powermate Knob: + + A Powermate knob is recommended but not necessary. If a knob + is used, it is in one of 3 or 4 modes controlling frequency, + volume, filter and (if playing a recorded file) time. + Pushing the knob switches mode and the buttons on the HFX panel + change to show which mode is in effect. Then just turn the knob + to set frequency, volume, filter or go fast forward or rewind. + + + Bandswitch: + + Across the top are a set of predefined bands and buttons + to rapidly switch to the center of that band. To change a band, + type the frequency in Hz into the box under "Center Frequency", + then press "Set" on the left, then the button you want to + program. From then on (untill the program is exited) pushing + that button takes you to that band. To make a band button + permenant edit the hfx.py script with whatever frequency you + want assigned to what button. + + + Frequency: + + There are 6 ways to set the frequency. + 1) Move the slider with the mouse + 2) Use the Spin Control up/down arrows (very fine 1Hz control) + 3) Type the frequency in Hz into the Spin Control + 4) Turn the Powermate knob + 5) Web control. + 6) Clicking on the FFT display to set demod center. This is very + convenient for tuning +-15kHz when you see a signal on the + display. If in Lower Sideband, clicking just to the right of + a signal will tune to it immediately. Clicking several times + on the far right right or left of the display will rapidly + tune up or down the band. + + + Volume: + + Move the volume slider with the mouse, or push the Powermate knob + untill the volume button is active, or click on the volume button, + then turn the knob. Volume can also be set by web control if web + control is setup and enabled. + + + Filter: + + Similar to volume, switches in any of 30 audio filters from 600 + to 3600Hz in Sideband or up to 5kHz in AM. + + + Mode: + + Demodulation modes are chosen by clicking on the buttons for + Lower Sideband, Upper Sideband, or AM. + + + PGA: + + PGA slider sets the rf gain in the Analog-to-Digital converter + before digitizing. 0 to 20db gain easily shows up on the FFT + display. + + + Time: + + When playing back a recorded RF data file, you can enjoy the + freedom of rewinding or fast-forwarding. Replay a weak signal + or skip through annoying AM commercials. + + + Antennas and Preamps: + + The USRP Basic RX board is not sensitive enough for anything but + the strongest signals. In my experience about 40 db of small + signal gain is required to make the HFX as sensitive as other + receivers. Some working amplifiers are the Ramsey PR-2 with 20db + gain, fairly low noise and more bandwidth than we can use here. + Also the amp modules from Advanced Receiver Research are nice. + I use an ARR 7-7.4MHz GaAsFET 29db amp with .5db noise at the + apex of a 40 meter dipole with excellent results. Another + amp I like is a Minicircuits ZHL-32A 29db amp but they are + expensive and hard to find. Also it may help to use some filters + to keep strong local signals from the ADC, or limit rf input + to the band of interest, etc. + Resonant outdoor antennas, like a dipole, in a low-noise (away + from consumer electronics) environment are nice. Long random wires + with a tuner work. I like a small indoor tuned loop made from 10ft + of 1/4" copper tube, a 365pf tuning cap and a pickup loop connected + to rg-58. + + + Web Control: + + To control your radio remotely, ensure you have a web server + (Apache, etc) working and a compatible directory structure in + place. Directories /var/www/cgi-bin/commands and + /var/www/cgi-bin/state must already exist. You will need a + home page with forms and a set of scripts to put commands in + and put the current state on the home page. email me for further + help. Setting WEB_CONTROL to True in hfx.py turns on the timers + that check for commands and update the state. + + + IF Output: + + There is a provision for outputting un-demodulated complex + through the audio out in stereo for use with Digital Radio + Mondial (DRM) or using a seperate demodulation program like + SDRadio (by I2PHD). + Set IF_OUTPUT to True in weaver_isb_am1_usrp4.py. + + + --Good luck and happy LW/MW/SW Exploring. + Chuck + chuckek@musicriver.homeunix.com + diff --git a/gnuradio-examples/python/apps/hf_radio/README.TXT b/gnuradio-examples/python/apps/hf_radio/README.TXT new file mode 100644 index 00000000..df8a901e --- /dev/null +++ b/gnuradio-examples/python/apps/hf_radio/README.TXT @@ -0,0 +1,53 @@ +The files in this directory implement a fairly simple HF radio that works +with the basic rx daughter board on the USRP. + +Many thanks to the Gnu Radio folks for a great new way to waste large blocks +of time in infinitely tweaking a huge number of free parameters. + +Start the receiver by running the radio.py in this directory. Or from the +Python prompt type "from radio import *" and you'll get the prompt back +with the receiver running. You can then poke around to see what's going on. + +There are two spectrum displays. One is the output of the USRP and displays +about 300KHz of bandwidth centered at the current tuning freq. The other +displays the output spectrum of the demodulator. + +The demodulator does AM demod using the complex modulus block from gr. It +does SSB demod using the frequency translating fir filter as a complex +hilbert transformer. The taps for this filter were generated using a program +called Scilab and the Scilab program in the file hfir.sci. More details in +the associated files. + +Tune the receiver using the spin buttons under the big frequency display. + +The agc block is a roll your own. The standard agc in the newer CVS updates +seems to work but doesn't seem to have adjustable time constants or provide +access to internal signal nodes which are used for the RSSI. + +The AGC authority (a sort of gain parameter) and the reference level used +in the power to dB computagion can be adjusted using the spin buttons. + +The audio bandwidth can be similarly adjusted from about 50Hz to 10KHz. + +The GUI layout was produced using wxGlade. The file radio.xml is the GUI +specification. It will produce a file called ui.py which is subclassed +by classes defined in radio.py. The ui.py is purely generated by wxGlade +all app specific code for the GUI is in radio.py. + +Most of the actual signal processing code is built up in the other included +files using the hierarchical block facilities. This organization should +make it easier to tweak to your heart's content. + +Known bugs weakness and other + +wxPython and wxGlade seem to conspire to insure that the layout can never +be exactly what you have in mind. + +Some of the controls don't behave as one might like. wx spin controls +and spin boxes only support integers so it is rather a nuisance to make +units come out nice. In the process of development I came up with a reasonable +kluge so there is a mixture of approaches. + +Enjoy. + +M. Revnell 2006-Jan-06 diff --git a/gnuradio-examples/python/apps/hf_radio/hfir.sci b/gnuradio-examples/python/apps/hf_radio/hfir.sci new file mode 100644 index 00000000..a2d5e2a6 --- /dev/null +++ b/gnuradio-examples/python/apps/hf_radio/hfir.sci @@ -0,0 +1,59 @@ +// designs a complex tap fir filter akin to the hilbert transformer. +// +// The hilbert transformer is classified as a linear phase fir +// with allpass magnitude response and 90 degree phase response for +// positive frequencies and -90 degrees phase for negative frequencies. +// Or, if you prefer, normalized frequencies between .5 and 1 since +// negative frequencies don't really have much meaning outside the complex +// domain. +// +// Normally one would use the hilbert transformer in one leg of a complex +// processing block and a compensating delay in the other. +// +// This one differs in the following respects: +// It is low pass with a cutoff of .078125 +// The filter is a lowpass kaiser windowed filter with parameter 3 +// The phase response is 45 degrees for positive frequencies and -45 +// for negative frequencies. +// The coefficent set is used in one path and the same coefficients +// are used time reversed in the other. This results in the net effect +// of +/- 90 degrees as in the usual hilbert application. +// +// The coefficient set can be used in the gnuradio frequency translating +// fir filter for ssb demodulation. +// +// This isn't as computationally efficient as using the hilbert transformer +// and compensating delay but fascinating none the less. +// +// This program is for the scilab language a very powerful free math +// package similar to Matlab with infinitely better price/performace. +// +// compute the prototype lowpass fir +// length is 255 (odd) for the same symmetry reasons as the hilbert transformer + +len = 1023; +l2 = floor(len/2); +md = l2 + 1; +l3 = md + 1; + +h = wfir( 'lp', len, [10.0/256 0], 'kr', [3 0] ); + +H = fft(h); + +H(1:l2)=H(1:l2)*exp(%i*%pi/4); +H(md)=0+%i*0; +H(l3:len)=H(l3:len)*exp(-%i*%pi/4); + +j=real(ifft(H)); +k(1:len)=j(len:-1:1); +x=j+%i.*k; +X=fft(x); +plot(abs(X)) + +f = file('open','taps') +for i=(1:len) + fprintf( f, '%f%+fj', j(i), k(i) ) +end + +file('close',f) + diff --git a/gnuradio-examples/python/apps/hf_radio/input.py b/gnuradio-examples/python/apps/hf_radio/input.py new file mode 100644 index 00000000..3a62a68c --- /dev/null +++ b/gnuradio-examples/python/apps/hf_radio/input.py @@ -0,0 +1,41 @@ +# Basic USRP setup and control. +# It's only ever been tried with a basic rx daughter card. +# +# Imagine that the gnuradio boilerplate is here. +# +# M. Revnell 2005-Dec + +from gnuradio import gr, gru, optfir +from gnuradio import usrp +import usrp_dbid +import math + +# Put special knowlege of usrp here. + +class input: + def __init__( self, decim ): + self.freq = -2.5e6 + self.src = usrp.source_c( ) + self.subdev = usrp.pick_subdev( self.src, + (usrp_dbid.BASIC_RX, + usrp_dbid.TV_RX)) + + print self.subdev + + self.subdevice = usrp.selected_subdev( self.src, + self.subdev ) + + self.mux = usrp.determine_rx_mux_value( self.src, + self.subdev ) + self.decim = decim + + self.adc_rate = self.src.adc_rate() + self.usrp_rate = self.adc_rate / self.decim + self.src.set_decim_rate( self.decim ) + self.src.set_mux( self.mux ) + usrp.tune( self.src, 0, self.subdevice, self.freq ) + + def set_freq( self, x ): + r = usrp.tune( self.src, 0, self.subdevice, -x ) + if r: + self.freq = -x diff --git a/gnuradio-examples/python/apps/hf_radio/output.py b/gnuradio-examples/python/apps/hf_radio/output.py new file mode 100644 index 00000000..dc9caf52 --- /dev/null +++ b/gnuradio-examples/python/apps/hf_radio/output.py @@ -0,0 +1,17 @@ +# Audio output with a volume control. +# +# M. Revnell 2005-Dec + +from gnuradio import gr, gru +from gnuradio import audio + +class output( gr.hier_block ): + def __init__( self, fg, rate ): + self.out = audio.sink( rate ) + self.vol = gr.multiply_const_ff( 0.1 ) + fg.connect( self.vol, self.out ) + gr.hier_block.__init__(self, fg, self.vol, None ) + + def set( self, val ): + self.vol.set_k( val ) + diff --git a/gnuradio-examples/python/apps/hf_radio/radio.py b/gnuradio-examples/python/apps/hf_radio/radio.py new file mode 100755 index 00000000..9f444b91 --- /dev/null +++ b/gnuradio-examples/python/apps/hf_radio/radio.py @@ -0,0 +1,304 @@ +#!/usr/bin/env python + +# GUI interactions and high level connections handled here. +# +# Interacts with classes defined by wxGlade in ui.py. +# +# The usual gnuradio copyright boilerplate incorperated here by reference. +# +# M. Revnell 2006-Jan + +from threading import * +import wx +import wx.lib.evtmgr as em +import time + +from gnuradio import gr, gru, eng_notation, optfir +from gnuradio import audio +from gnuradio import usrp +from gnuradio import blks +from gnuradio.wxgui import fftsink +from gnuradio.wxgui import waterfallsink +from gnuradio.wxgui import scopesink + +from input import * +from output import * +from ssbdemod import * +from ssbagc import * +from ui import * +from math import log10 + +class graph( gr.hier_block ): + def __init__( self, fg ): + self.graph = fg + self.fe_decim = 250 + self.src = input( self.fe_decim ) + self.adc_rate = self.src.adc_rate + self.fe_rate = self.adc_rate / self.fe_decim + self.filter_decim = 1 + self.audio_decim = 16 + self.demod_rate = self.fe_rate / self.filter_decim + self.audio_rate = self.demod_rate / self.audio_decim + + self.demod = ssb_demod( fg, self.demod_rate, self.audio_rate ) + self.agc = agc( fg ) + #self.agc = gr.agc_ff() + self.out = output( fg, self.audio_rate ) + + fg.connect( self.src.src, + self.demod, + self.agc, + self.out ) + + gr.hier_block.__init__( self, fg, None, None ) + + def tune( self, freq ): + fe_target = -freq + self.src.set_freq( fe_target ) + fe_freq = self.src.src.rx_freq( 0 ) + demod_cf = fe_target - fe_freq + self.demod.tune( demod_cf ) + +class radio_frame( ui_frame ): + def __init__( self, block, *args, **kwds ): + ui_frame.__init__( self, *args, **kwds ) + self.block = block + self.freq_disp.SetRange(0, 30e6) + f = self.block.src.freq + self.freq_disp.SetValue( -f ) + self.volume.SetRange( 0, 20 ) + self.pga.SetRange( 0, 20 ) + self.rssi_range = 1 + self.rssi.SetRange( self.rssi_range ) + self.agc_max.SetValue( str( self.rssi_range ) ) + self.spin_e0.SetValue( 50 ) + self.spin_e1.SetValue( 50 ) + self.spin_e2.SetValue( 50 ) + self.spin_e3.SetValue( 50 ) + self.spin_e4.SetValue( 50 ) + self.spin_e5.SetValue( 50 ) + self.spin_e6.SetValue( 50 ) + bw = 3.3e3 + self.bandwidth.SetValue( str( bw ) ) + self.block.demod.set_bw( bw ) + self.bw_spin.SetValue( 5 ) + agc_gain = self.block.agc.gain.k() + self.agc_gain_s.SetValue( 5 ) + self.agc_gain.SetValue( str( agc_gain ) ) + agc_ref = self.block.agc.offs.k() + self.agc_ref.SetValue( str( agc_ref ) ) + self.agc_ref_s.SetValue( 5 ) + + self.fespectrum = fftsink.fft_sink_c( + self.block.graph, + self.fe_panel, + fft_size=512, + sample_rate = block.fe_rate, + baseband_freq = 0, + average = False, + size = ( 680, 140 ) ) + + self.ifspectrum = fftsink.fft_sink_c( + self.block.graph, + self.if_panel, + fft_size=512, + sample_rate = block.audio_rate, + baseband_freq = 0, + average = False, + size = ( 680, 140 ) ) + + em.eventManager.Register( self.fe_mouse, + wx.EVT_MOTION, + self.fespectrum.win ) + + em.eventManager.Register( self.fe_click, + wx.EVT_LEFT_DOWN, + self.fespectrum.win ) + + block.graph.connect( block.src.src, self.fespectrum ) + block.graph.connect( block.demod.xlate, self.ifspectrum ) + + def agc_ref_up( self, event ): + self.agc_ref_s.SetValue( 5 ) + r = float( self.agc_ref.GetValue() ) + r = r + 5 + self.agc_ref.SetValue( str( r ) ) + self.block.agc.offs.set_k( r ) + + def agc_ref_down( self, event ): + self.agc_ref_s.SetValue( 5 ) + r = float( self.agc_ref.GetValue() ) + r = r - 5 + self.agc_ref.SetValue( str( r ) ) + self.block.agc.offs.set_k( r ) + + def agc_gain_up( self, event ): + self.agc_gain_s.SetValue( 5 ) + g = float(self.agc_gain.GetValue()) + g = g + 10 + self.agc_gain.SetValue( str( g ) ) + self.block.agc.gain.set_k( g ) + + def agc_gain_down( self, event ): + self.agc_gain_s.SetValue( 5 ) + g = float(self.agc_gain.GetValue()) + g = g - 10 + self.agc_gain.SetValue( str( g ) ) + self.block.agc.gain.set_k( g ) + + def fe_mouse( self, event ): + f = int(self.freq_disp.GetValue()) + f = f+((event.GetX()-346.)*(400./610.))*1000 + self.fespectrum.win.SetToolTip( + wx.ToolTip( eng_notation.num_to_str(f))) + + def fe_click( self, event ): + f = int(self.freq_disp.GetValue()) + f = f+((event.GetX()-346.)*(400./610.))*1000 + self.tune( f ) + + def setrssi( self, level ): + if level < 0: + level = 0 + if level > self.rssi_range: + self.rssi_range = level + self.rssi.SetRange( level ) + self.agc_max.SetValue( str( level )) + self.rssi.SetValue( level ) + self.agc_level.SetValue( str( level )) + + def tune_evt( self, event ): + f = self.freq_disp.GetValue() + self.tune( f ) + + def tune( self, frequency ): + self.freq_disp.SetValue( frequency ) + self.block.tune( frequency ) + + def up_e0( self, event ): + self.spin_e0.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() + 1e0 ) + + def down_e0( self, event ): + self.spin_e0.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() - 1e0 ) + + def up_e1( self, event ): + self.spin_e1.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() + 1e1 ) + + def down_e1( self, event ): + self.spin_e1.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() - 1e1 ) + + def up_e2( self, event ): + self.spin_e2.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() + 1e2 ) + + def down_e2( self, event ): + self.spin_e2.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() - 1e2 ) + + def up_e3( self, event ): + self.spin_e3.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() + 1e3 ) + + def down_e3( self, event ): + self.spin_e3.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() - 1e3 ) + + def up_e4( self, event ): + self.spin_e4.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() + 1e4 ) + + def down_e4( self, event ): + self.spin_e4.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() - 1e4 ) + + def up_e5( self, event ): + self.spin_e5.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() + 1e5 ) + + def down_e5( self, event ): + self.spin_e5.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() - 1e5 ) + + def up_e6( self, event ): + self.spin_e6.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() + 1e6 ) + + def down_e6( self, event ): + self.spin_e6.SetValue( 50 ) + self.tune( self.freq_disp.GetValue() - 1e6 ) + + def event_pga( self, event ): + self.block.src.src.set_pga( 0, self.pga.GetValue()) + + def event_vol( self, event ): + self.block.out.set( self.volume.GetValue()/20.0 ) + + def set_usb( self, event ): + self.block.demod.upper_sb() + + def set_lsb( self, event ): + self.block.demod.lower_sb() + + def set_am( self, event ): + self.block.demod.set_am() + + def bw_up( self, event ): + self.bw_spin.SetValue( 5 ) + bw = float(self.bandwidth.GetValue()) + bw = bw + 20.0 + if bw > 10e3: + bw = 10e3 + self.bandwidth.SetValue( str( bw ) ) + self.block.demod.set_bw( bw ) + + def bw_down( self, event ): + self.bw_spin.SetValue( 5 ) + bw = float(self.bandwidth.GetValue()) + bw = bw - 20.0 + if bw < 50: + bw = 50 + self.bandwidth.SetValue( str( bw ) ) + self.block.demod.set_bw( bw ) + + +class radio( wx.App ): + def OnInit( self ): + self.graph = gr.flow_graph() + self.block = graph( self.graph ) + self.frame = radio_frame( self.block, None, -1, "Title" ) + self.frame.Show( True ) + self.SetTopWindow( self.frame ) + return True + +a=radio( 0 ) + +l=gr.probe_signal_f() +#l=gr.probe_avg_mag_sqrd_f(1,.001) +a.graph.connect(a.block.agc.offs,l ) +#a.graph.connect(a.block.demod,l) + +def main_function(): + global a + a.MainLoop() + + +def rssi_function(): + global a + global l + while 1: + level = l.level() + wx.CallAfter( a.frame.setrssi, level ) + time.sleep( .1 ) + +thread1 = Thread( target = main_function ) +thread2 = Thread( target = rssi_function ) + +thread1.start() +thread2.start() + +a.graph.start() + diff --git a/gnuradio-examples/python/apps/hf_radio/radio.xml b/gnuradio-examples/python/apps/hf_radio/radio.xml new file mode 100644 index 00000000..81daa19b --- /dev/null +++ b/gnuradio-examples/python/apps/hf_radio/radio.xml @@ -0,0 +1,441 @@ + + + + + + + frame_1 + + wxVERTICAL + + + wxEXPAND + 0 + + + wxHORIZONTAL + + wxEXPAND + 0 + + + wxVERTICAL + + wxEXPAND|wxADJUST_MINSIZE + 0 + + + + 32 + default + + normal + 0 + + + + tune_evt + + + + + wxEXPAND + 0 + + + 0 + 2 + 3 + 0 + + wxEXPAND + 0 + + + 0 + 1 + 7 + 0 + + wxADJUST_MINSIZE + 0 + + + + up_e6 + down_e6 + + + + + wxADJUST_MINSIZE + 0 + + + + up_e5 + down_e5 + + + + + wxADJUST_MINSIZE + 0 + + + + up_e4 + down_e4 + + + + + wxADJUST_MINSIZE + 0 + + + + up_e3 + down_e3 + + + + + wxADJUST_MINSIZE + 0 + + + + up_e2 + down_e2 + + + + + wxADJUST_MINSIZE + 0 + + + + up_e1 + down_e1 + + + + + wxADJUST_MINSIZE + 0 + + + + up_e0 + down_e0 + + + + + + + wxEXPAND + 0 + + + + + + + wxEXPAND + 0 + + + + + + + wxADJUST_MINSIZE + 0 + + + + + set_lsb + + + + + wxADJUST_MINSIZE + 0 + + + + + set_usb + + + + + wxADJUST_MINSIZE + 0 + + + + + set_am + + + + + + + + + wxEXPAND + 0 + + + wxVERTICAL + + wxEXPAND + 0 + + + 0 + 2 + 4 + 0 + + wxADJUST_MINSIZE + 0 + + + 1 + + + + + wxADJUST_MINSIZE + 0 + + + 1 + + + + + wxADJUST_MINSIZE + 0 + + + + + + wxADJUST_MINSIZE + 0 + + + 1 + + + + wxADJUST_MINSIZE + 0 + + + + event_vol + + + + + wxADJUST_MINSIZE + 0 + + + + event_pga + + + + + wxADJUST_MINSIZE + 0 + + + + + + wxADJUST_MINSIZE + 0 + + + 1 + + + + + + wxEXPAND + 0 + + + 0 + 2 + 4 + 0 + + wxADJUST_MINSIZE + 0 + + + 1 + + + + + wxADJUST_MINSIZE + 0 + + + 1 + + + + + wxADJUST_MINSIZE + 0 + + + 1 + + + + + wxADJUST_MINSIZE + 0 + + + 1 + + + + wxEXPAND + 0 + + + wxHORIZONTAL + + wxADJUST_MINSIZE + 0 + + + + + + wxADJUST_MINSIZE + 0 + + + + agc_gain_up + agc_gain_down + + + + + + + wxEXPAND + 0 + + + wxHORIZONTAL + + wxADJUST_MINSIZE + 0 + + + + + + wxADJUST_MINSIZE + 0 + + + + agc_ref_up + agc_ref_down + + + + + + + wxEXPAND + 0 + + + wxHORIZONTAL + + wxADJUST_MINSIZE + 0 + + + + + + wxADJUST_MINSIZE + 0 + + + + bw_up + bw_down + + + + + + + wxADJUST_MINSIZE + 0 + + + 1 + + + + + + wxEXPAND|wxADJUST_MINSIZE + 0 + + + #ff0000 + + 10 + 315, 10 + + + + + + + + wxEXPAND + 0 + + + + + + + wxEXPAND + 0 + + + + + + + + diff --git a/gnuradio-examples/python/apps/hf_radio/ssb_taps b/gnuradio-examples/python/apps/hf_radio/ssb_taps new file mode 100644 index 00000000..0ef3bbf2 --- /dev/null +++ b/gnuradio-examples/python/apps/hf_radio/ssb_taps @@ -0,0 +1,1023 @@ +-0.000035-0.000009j +-0.000066-0.000020j +-0.000080-0.000044j +-0.000084-0.000071j +-0.000077-0.000100j +-0.000063-0.000127j +-0.000041-0.000150j +-0.000013-0.000167j +0.000020-0.000177j +0.000054-0.000180j +0.000089-0.000174j +0.000121-0.000161j +0.000150-0.000140j +0.000173-0.000113j +0.000188-0.000081j +0.000196-0.000046j +0.000194-0.000011j +0.000184+0.000022j +0.000165+0.000052j +0.000139+0.000077j +0.000107+0.000093j +0.000071+0.000102j +0.000034+0.000101j +-0.000002+0.000090j +-0.000036+0.000070j +-0.000064+0.000042j +-0.000086+0.000006j +-0.000098-0.000034j +-0.000101-0.000077j +-0.000093-0.000120j +-0.000076-0.000161j +-0.000049-0.000197j +-0.000014-0.000227j +0.000026-0.000248j +0.000071-0.000259j +0.000117-0.000259j +0.000162-0.000249j +0.000203-0.000228j +0.000237-0.000199j +0.000263-0.000162j +0.000279-0.000120j +0.000284-0.000075j +0.000278-0.000031j +0.000260+0.000010j +0.000232+0.000045j +0.000196+0.000073j +0.000153+0.000090j +0.000106+0.000095j +0.000059+0.000089j +0.000014+0.000071j +-0.000027+0.000041j +-0.000059+0.000002j +-0.000082-0.000046j +-0.000093-0.000098j +-0.000091-0.000152j +-0.000077-0.000206j +-0.000050-0.000255j +-0.000012-0.000298j +0.000034-0.000330j +0.000088-0.000351j +0.000145-0.000359j +0.000202-0.000354j +0.000256-0.000335j +0.000304-0.000304j +0.000343-0.000262j +0.000370-0.000213j +0.000384-0.000158j +0.000384-0.000102j +0.000369-0.000048j +0.000341+0.000002j +0.000302+0.000042j +0.000252+0.000072j +0.000196+0.000088j +0.000137+0.000089j +0.000078+0.000075j +0.000024+0.000047j +-0.000023+0.000005j +-0.000059-0.000048j +-0.000082-0.000109j +-0.000090-0.000175j +-0.000081-0.000242j +-0.000058-0.000306j +-0.000019-0.000364j +0.000032-0.000411j +0.000093-0.000445j +0.000161-0.000465j +0.000232-0.000467j +0.000301-0.000453j +0.000365-0.000423j +0.000419-0.000379j +0.000461-0.000323j +0.000487-0.000259j +0.000497-0.000190j +0.000489-0.000121j +0.000464-0.000056j +0.000423+0.000001j +0.000369+0.000046j +0.000304+0.000076j +0.000233+0.000089j +0.000160+0.000083j +0.000089+0.000060j +0.000025+0.000018j +-0.000027-0.000038j +-0.000065-0.000107j +-0.000086-0.000185j +-0.000088-0.000266j +-0.000071-0.000347j +-0.000035-0.000422j +0.000019-0.000487j +0.000086-0.000538j +0.000164-0.000573j +0.000248-0.000588j +0.000334-0.000582j +0.000415-0.000557j +0.000488-0.000513j +0.000548-0.000452j +0.000592-0.000379j +0.000616-0.000297j +0.000619-0.000213j +0.000600-0.000130j +0.000561-0.000054j +0.000504+0.000010j +0.000432+0.000058j +0.000350+0.000086j +0.000261+0.000093j +0.000173+0.000078j +0.000090+0.000040j +0.000017-0.000017j +-0.000040-0.000092j +-0.000078-0.000180j +-0.000095-0.000275j +-0.000088-0.000374j +-0.000058-0.000469j +-0.000006-0.000555j +0.000065-0.000627j +0.000152-0.000681j +0.000250-0.000712j +0.000352-0.000720j +0.000454-0.000703j +0.000548-0.000663j +0.000630-0.000601j +0.000694-0.000521j +0.000737-0.000428j +0.000755-0.000327j +0.000748-0.000225j +0.000715-0.000128j +0.000659-0.000042j +0.000582+0.000028j +0.000490+0.000077j +0.000387+0.000101j +0.000280+0.000099j +0.000175+0.000070j +0.000080+0.000015j +-0.000001-0.000063j +-0.000061-0.000159j +-0.000097-0.000268j +-0.000106-0.000385j +-0.000087-0.000501j +-0.000040-0.000611j +0.000032-0.000708j +0.000125-0.000786j +0.000235-0.000839j +0.000354-0.000866j +0.000477-0.000863j +0.000595-0.000831j +0.000702-0.000772j +0.000792-0.000688j +0.000859-0.000585j +0.000898-0.000469j +0.000907-0.000347j +0.000886-0.000227j +0.000835-0.000115j +0.000757-0.000019j +0.000657+0.000055j +0.000540+0.000102j +0.000415+0.000119j +0.000287+0.000103j +0.000165+0.000056j +0.000058-0.000020j +-0.000029-0.000122j +-0.000090-0.000243j +-0.000121-0.000378j +-0.000118-0.000517j +-0.000082-0.000653j +-0.000014-0.000778j +0.000082-0.000885j +0.000201-0.000966j +0.000337-0.001017j +0.000481-0.001034j +0.000626-0.001016j +0.000762-0.000965j +0.000882-0.000882j +0.000978-0.000772j +0.001044-0.000643j +0.001076-0.000501j +0.001072-0.000355j +0.001032-0.000215j +0.000958-0.000089j +0.000854+0.000016j +0.000726+0.000091j +0.000582+0.000133j +0.000431+0.000138j +0.000281+0.000105j +0.000143+0.000035j +0.000024-0.000068j +-0.000068-0.000199j +-0.000126-0.000350j +-0.000147-0.000513j +-0.000128-0.000677j +-0.000070-0.000834j +0.000024-0.000974j +0.000150-0.001089j +0.000300-0.001171j +0.000465-0.001216j +0.000637-0.001219j +0.000805-0.001182j +0.000960-0.001105j +0.001091-0.000993j +0.001191-0.000853j +0.001253-0.000692j +0.001274-0.000521j +0.001252-0.000350j +0.001188-0.000189j +0.001085-0.000049j +0.000950+0.000062j +0.000790+0.000136j +0.000614+0.000168j +0.000435+0.000156j +0.000261+0.000099j +0.000105+0.000000j +-0.000024-0.000136j +-0.000117-0.000301j +-0.000169-0.000486j +-0.000175-0.000680j +-0.000134-0.000872j +-0.000048-0.001051j +0.000079-0.001206j +0.000240-0.001326j +0.000426-0.001406j +0.000626-0.001439j +0.000829-0.001424j +0.001022-0.001361j +0.001195-0.001252j +0.001336-0.001106j +0.001437-0.000929j +0.001491-0.000733j +0.001496-0.000529j +0.001449-0.000330j +0.001354-0.000148j +0.001217+0.000005j +0.001044+0.000120j +0.000846+0.000188j +0.000635+0.000206j +0.000424+0.000170j +0.000226+0.000083j +0.000053-0.000053j +-0.000084-0.000228j +-0.000176-0.000434j +-0.000216-0.000659j +-0.000201-0.000889j +-0.000131-0.001111j +-0.000009-0.001312j +0.000158-0.001480j +0.000362-0.001604j +0.000590-0.001677j +0.000829-0.001694j +0.001066-0.001653j +0.001286-0.001556j +0.001477-0.001408j +0.001626-0.001219j +0.001724-0.001000j +0.001765-0.000762j +0.001746-0.000522j +0.001668-0.000293j +0.001534-0.000090j +0.001353+0.000075j +0.001135+0.000190j +0.000893+0.000247j +0.000642+0.000243j +0.000396+0.000176j +0.000172+0.000049j +-0.000017-0.000131j +-0.000159-0.000355j +-0.000244-0.000609j +-0.000266-0.000880j +-0.000222-0.001151j +-0.000114-0.001406j +0.000053-0.001630j +0.000270-0.001810j +0.000524-0.001934j +0.000802-0.001994j +0.001087-0.001987j +0.001362-0.001911j +0.001611-0.001772j +0.001819-0.001576j +0.001973-0.001336j +0.002063-0.001065j +0.002084-0.000779j +0.002033-0.000497j +0.001914-0.000236j +0.001732-0.000011j +0.001498+0.000162j +0.001225+0.000272j +0.000931+0.000312j +0.000633+0.000277j +0.000349+0.000168j +0.000097-0.000009j +-0.000107-0.000246j +-0.000250-0.000528j +-0.000322-0.000841j +-0.000316-0.001166j +-0.000233-0.001484j +-0.000076-0.001775j +0.000148-0.002024j +0.000426-0.002213j +0.000743-0.002332j +0.001080-0.002373j +0.001418-0.002332j +0.001736-0.002211j +0.002017-0.002017j +0.002241-0.001760j +0.002397-0.001457j +0.002473-0.001124j +0.002464-0.000783j +0.002371-0.000453j +0.002198-0.000156j +0.001954+0.000091j +0.001654+0.000269j +0.001316+0.000369j +0.000959+0.000381j +0.000606+0.000303j +0.000279+0.000139j +-0.000003-0.000103j +-0.000220-0.000411j +-0.000359-0.000768j +-0.000408-0.001152j +-0.000365-0.001542j +-0.000229-0.001915j +-0.000006-0.002248j +0.000292-0.002522j +0.000648-0.002719j +0.001042-0.002826j +0.001452-0.002837j +0.001853-0.002750j +0.002223-0.002569j +0.002537-0.002304j +0.002778-0.001971j +0.002930-0.001588j +0.002984-0.001179j +0.002933-0.000770j +0.002782-0.000384j +0.002538-0.000046j +0.002215+0.000222j +0.001831+0.000402j +0.001410+0.000481j +0.000976+0.000452j +0.000557+0.000316j +0.000179+0.000077j +-0.000134-0.000252j +-0.000362-0.000654j +-0.000490-0.001105j +-0.000506-0.001580j +-0.000407-0.002052j +-0.000197-0.002492j +0.000113-0.002875j +0.000508-0.003176j +0.000966-0.003377j +0.001460-0.003464j +0.001963-0.003432j +0.002444-0.003281j +0.002876-0.003019j +0.003231-0.002659j +0.003488-0.002224j +0.003631-0.001739j +0.003649-0.001233j +0.003540-0.000737j +0.003309-0.000282j +0.002969+0.000103j +0.002539+0.000393j +0.002044+0.000568j +0.001515+0.000614j +0.000982+0.000525j +0.000480+0.000304j +0.000039-0.000039j +-0.000311-0.000487j +-0.000547-0.001016j +-0.000652-0.001595j +-0.000615-0.002193j +-0.000436-0.002773j +-0.000122-0.003301j +0.000311-0.003746j +0.000842-0.004081j +0.001440-0.004282j +0.002071-0.004338j +0.002700-0.004243j +0.003289-0.004000j +0.003803-0.003622j +0.004210-0.003132j +0.004485-0.002556j +0.004610-0.001930j +0.004574-0.001291j +0.004379-0.000679j +0.004034-0.000133j +0.003558+0.000313j +0.002977+0.000627j +0.002327+0.000787j +0.001647+0.000779j +0.000977+0.000598j +0.000360+0.000250j +-0.000163-0.000249j +-0.000559-0.000872j +-0.000799-0.001587j +-0.000864-0.002354j +-0.000744-0.003129j +-0.000442-0.003866j +0.000031-0.004522j +0.000651-0.005057j +0.001385-0.005437j +0.002193-0.005637j +0.003030-0.005643j +0.003848-0.005451j +0.004597-0.005069j +0.005234-0.004519j +0.005718-0.003830j +0.006019-0.003044j +0.006114-0.002206j +0.005997-0.001368j +0.005669-0.000583j +0.005147+0.000099j +0.004460+0.000631j +0.003647+0.000975j +0.002757+0.001105j +0.001842+0.001003j +0.000961+0.000668j +0.000168+0.000111j +-0.000482-0.000643j +-0.000944-0.001555j +-0.001183-0.002578j +-0.001176-0.003656j +-0.000912-0.004727j +-0.000397-0.005728j +0.000346-0.006601j +0.001284-0.007292j +0.002368-0.007755j +0.003540-0.007959j +0.004735-0.007886j +0.005885-0.007535j +0.006922-0.006922j +0.007782-0.006078j +0.008412-0.005050j +0.008769-0.003898j +0.008825-0.002691j +0.008572-0.001504j +0.008016-0.000412j +0.007185+0.000510j +0.006123+0.001196j +0.004891+0.001591j +0.003560+0.001657j +0.002212+0.001372j +0.000933+0.000734j +-0.000192-0.000236j +-0.001083-0.001500j +-0.001672-0.002998j +-0.001905-0.004655j +-0.001747-0.006384j +-0.001182-0.008090j +-0.000222-0.009676j +0.001101-0.011045j +0.002732-0.012114j +0.004593-0.012810j +0.006591-0.013081j +0.008621-0.012896j +0.010571-0.012253j +0.012328-0.011175j +0.013785-0.009712j +0.014847-0.007941j +0.015438-0.005962j +0.015507-0.003893j +0.015029-0.001863j +0.014011-0.000011j +0.012494+0.001529j +0.010549+0.002630j +0.008277+0.003179j +0.005809+0.003090j +0.003294+0.002304j +0.000896+0.000795j +-0.001212-0.001423j +-0.002859-0.004299j +-0.003886-0.007744j +-0.004151-0.011630j +-0.003539-0.015799j +-0.001969-0.020066j +0.000601-0.024225j +0.004168-0.028064j +0.008684-0.031367j +0.014056-0.033927j +0.020145-0.035558j +0.026775-0.036101j +0.033735-0.035433j +0.040789-0.033475j +0.047684-0.030197j +0.054164-0.025619j +0.059974-0.019815j +0.064878-0.012907j +0.068665-0.005067j +0.071159+0.003494j +0.072228+0.012531j +0.071791+0.021776j +0.069818+0.030947j +0.066339+0.039761j +0.061435+0.047944j +0.055243+0.055243j +0.047944+0.061435j +0.039761+0.066339j +0.030947+0.069818j +0.021776+0.071791j +0.012531+0.072228j +0.003494+0.071159j +-0.005067+0.068665j +-0.012907+0.064878j +-0.019815+0.059974j +-0.025619+0.054164j +-0.030197+0.047684j +-0.033475+0.040789j +-0.035433+0.033735j +-0.036101+0.026775j +-0.035558+0.020145j +-0.033927+0.014056j +-0.031367+0.008684j +-0.028064+0.004168j +-0.024225+0.000601j +-0.020066-0.001969j +-0.015799-0.003539j +-0.011630-0.004151j +-0.007744-0.003886j +-0.004299-0.002859j +-0.001423-0.001212j +0.000795+0.000896j +0.002304+0.003294j +0.003090+0.005809j +0.003179+0.008277j +0.002630+0.010549j +0.001529+0.012494j +-0.000011+0.014011j +-0.001863+0.015029j +-0.003893+0.015507j +-0.005962+0.015438j +-0.007941+0.014847j +-0.009712+0.013785j +-0.011175+0.012328j +-0.012253+0.010571j +-0.012896+0.008621j +-0.013081+0.006591j +-0.012810+0.004593j +-0.012114+0.002732j +-0.011045+0.001101j +-0.009676-0.000222j +-0.008090-0.001182j +-0.006384-0.001747j +-0.004655-0.001905j +-0.002998-0.001672j +-0.001500-0.001083j +-0.000236-0.000192j +0.000734+0.000933j +0.001372+0.002212j +0.001657+0.003560j +0.001591+0.004891j +0.001196+0.006123j +0.000510+0.007185j +-0.000412+0.008016j +-0.001504+0.008572j +-0.002691+0.008825j +-0.003898+0.008769j +-0.005050+0.008412j +-0.006078+0.007782j +-0.006922+0.006922j +-0.007535+0.005885j +-0.007886+0.004735j +-0.007959+0.003540j +-0.007755+0.002368j +-0.007292+0.001284j +-0.006601+0.000346j +-0.005728-0.000397j +-0.004727-0.000912j +-0.003656-0.001176j +-0.002578-0.001183j +-0.001555-0.000944j +-0.000643-0.000482j +0.000111+0.000168j +0.000668+0.000961j +0.001003+0.001842j +0.001105+0.002757j +0.000975+0.003647j +0.000631+0.004460j +0.000099+0.005147j +-0.000583+0.005669j +-0.001368+0.005997j +-0.002206+0.006114j +-0.003044+0.006019j +-0.003830+0.005718j +-0.004519+0.005234j +-0.005069+0.004597j +-0.005451+0.003848j +-0.005643+0.003030j +-0.005637+0.002193j +-0.005437+0.001385j +-0.005057+0.000651j +-0.004522+0.000031j +-0.003866-0.000442j +-0.003129-0.000744j +-0.002354-0.000864j +-0.001587-0.000799j +-0.000872-0.000559j +-0.000249-0.000163j +0.000250+0.000360j +0.000598+0.000977j +0.000779+0.001647j +0.000787+0.002327j +0.000627+0.002977j +0.000313+0.003558j +-0.000133+0.004034j +-0.000679+0.004379j +-0.001291+0.004574j +-0.001930+0.004610j +-0.002556+0.004485j +-0.003132+0.004210j +-0.003622+0.003803j +-0.004000+0.003289j +-0.004243+0.002700j +-0.004338+0.002071j +-0.004282+0.001440j +-0.004081+0.000842j +-0.003746+0.000311j +-0.003301-0.000122j +-0.002773-0.000436j +-0.002193-0.000615j +-0.001595-0.000652j +-0.001016-0.000547j +-0.000487-0.000311j +-0.000039+0.000039j +0.000304+0.000480j +0.000525+0.000982j +0.000614+0.001515j +0.000568+0.002044j +0.000393+0.002539j +0.000103+0.002969j +-0.000282+0.003309j +-0.000737+0.003540j +-0.001233+0.003649j +-0.001739+0.003631j +-0.002224+0.003488j +-0.002659+0.003231j +-0.003019+0.002876j +-0.003281+0.002444j +-0.003432+0.001963j +-0.003464+0.001460j +-0.003377+0.000966j +-0.003176+0.000508j +-0.002875+0.000113j +-0.002492-0.000197j +-0.002052-0.000407j +-0.001580-0.000506j +-0.001105-0.000490j +-0.000654-0.000362j +-0.000252-0.000134j +0.000077+0.000179j +0.000316+0.000557j +0.000452+0.000976j +0.000481+0.001410j +0.000402+0.001831j +0.000222+0.002215j +-0.000046+0.002538j +-0.000384+0.002782j +-0.000770+0.002933j +-0.001179+0.002984j +-0.001588+0.002930j +-0.001971+0.002778j +-0.002304+0.002537j +-0.002569+0.002223j +-0.002750+0.001853j +-0.002837+0.001452j +-0.002826+0.001042j +-0.002719+0.000648j +-0.002522+0.000292j +-0.002248-0.000006j +-0.001915-0.000229j +-0.001542-0.000365j +-0.001152-0.000408j +-0.000768-0.000359j +-0.000411-0.000220j +-0.000103-0.000003j +0.000139+0.000279j +0.000303+0.000606j +0.000381+0.000959j +0.000369+0.001316j +0.000269+0.001654j +0.000091+0.001954j +-0.000156+0.002198j +-0.000453+0.002371j +-0.000783+0.002464j +-0.001124+0.002473j +-0.001457+0.002397j +-0.001760+0.002241j +-0.002017+0.002017j +-0.002211+0.001736j +-0.002332+0.001418j +-0.002373+0.001080j +-0.002332+0.000743j +-0.002213+0.000426j +-0.002024+0.000148j +-0.001775-0.000076j +-0.001484-0.000233j +-0.001166-0.000316j +-0.000841-0.000322j +-0.000528-0.000250j +-0.000246-0.000107j +-0.000009+0.000097j +0.000168+0.000349j +0.000277+0.000633j +0.000312+0.000931j +0.000272+0.001225j +0.000162+0.001498j +-0.000011+0.001732j +-0.000236+0.001914j +-0.000497+0.002033j +-0.000779+0.002084j +-0.001065+0.002063j +-0.001336+0.001973j +-0.001576+0.001819j +-0.001772+0.001611j +-0.001911+0.001362j +-0.001987+0.001087j +-0.001994+0.000802j +-0.001934+0.000524j +-0.001810+0.000270j +-0.001630+0.000053j +-0.001406-0.000114j +-0.001151-0.000222j +-0.000880-0.000266j +-0.000609-0.000244j +-0.000355-0.000159j +-0.000131-0.000017j +0.000049+0.000172j +0.000176+0.000396j +0.000243+0.000642j +0.000247+0.000893j +0.000190+0.001135j +0.000075+0.001353j +-0.000090+0.001534j +-0.000293+0.001668j +-0.000522+0.001746j +-0.000762+0.001765j +-0.001000+0.001724j +-0.001219+0.001626j +-0.001408+0.001477j +-0.001556+0.001286j +-0.001653+0.001066j +-0.001694+0.000829j +-0.001677+0.000590j +-0.001604+0.000362j +-0.001480+0.000158j +-0.001312-0.000009j +-0.001111-0.000131j +-0.000889-0.000201j +-0.000659-0.000216j +-0.000434-0.000176j +-0.000228-0.000084j +-0.000053+0.000053j +0.000083+0.000226j +0.000170+0.000424j +0.000206+0.000635j +0.000188+0.000846j +0.000120+0.001044j +0.000005+0.001217j +-0.000148+0.001354j +-0.000330+0.001449j +-0.000529+0.001496j +-0.000733+0.001491j +-0.000929+0.001437j +-0.001106+0.001336j +-0.001252+0.001195j +-0.001361+0.001022j +-0.001424+0.000829j +-0.001439+0.000626j +-0.001406+0.000426j +-0.001326+0.000240j +-0.001206+0.000079j +-0.001051-0.000048j +-0.000872-0.000134j +-0.000680-0.000175j +-0.000486-0.000169j +-0.000301-0.000117j +-0.000136-0.000024j +0.000000+0.000105j +0.000099+0.000261j +0.000156+0.000435j +0.000168+0.000614j +0.000136+0.000790j +0.000062+0.000950j +-0.000049+0.001085j +-0.000189+0.001188j +-0.000350+0.001252j +-0.000521+0.001274j +-0.000692+0.001253j +-0.000853+0.001191j +-0.000993+0.001091j +-0.001105+0.000960j +-0.001182+0.000805j +-0.001219+0.000637j +-0.001216+0.000465j +-0.001171+0.000300j +-0.001089+0.000150j +-0.000974+0.000024j +-0.000834-0.000070j +-0.000677-0.000128j +-0.000513-0.000147j +-0.000350-0.000126j +-0.000199-0.000068j +-0.000068+0.000024j +0.000035+0.000143j +0.000105+0.000281j +0.000138+0.000431j +0.000133+0.000582j +0.000091+0.000726j +0.000016+0.000854j +-0.000089+0.000958j +-0.000215+0.001032j +-0.000355+0.001072j +-0.000501+0.001076j +-0.000643+0.001044j +-0.000772+0.000978j +-0.000882+0.000882j +-0.000965+0.000762j +-0.001016+0.000626j +-0.001034+0.000481j +-0.001017+0.000337j +-0.000966+0.000201j +-0.000885+0.000082j +-0.000778-0.000014j +-0.000653-0.000082j +-0.000517-0.000118j +-0.000378-0.000121j +-0.000243-0.000090j +-0.000122-0.000029j +-0.000020+0.000058j +0.000056+0.000165j +0.000103+0.000287j +0.000119+0.000415j +0.000102+0.000540j +0.000055+0.000657j +-0.000019+0.000757j +-0.000115+0.000835j +-0.000227+0.000886j +-0.000347+0.000907j +-0.000469+0.000898j +-0.000585+0.000859j +-0.000688+0.000792j +-0.000772+0.000702j +-0.000831+0.000595j +-0.000863+0.000477j +-0.000866+0.000354j +-0.000839+0.000235j +-0.000786+0.000125j +-0.000708+0.000032j +-0.000611-0.000040j +-0.000501-0.000087j +-0.000385-0.000106j +-0.000268-0.000097j +-0.000159-0.000061j +-0.000063-0.000001j +0.000015+0.000080j +0.000070+0.000175j +0.000099+0.000280j +0.000101+0.000387j +0.000077+0.000490j +0.000028+0.000582j +-0.000042+0.000659j +-0.000128+0.000715j +-0.000225+0.000748j +-0.000327+0.000755j +-0.000428+0.000737j +-0.000521+0.000694j +-0.000601+0.000630j +-0.000663+0.000548j +-0.000703+0.000454j +-0.000720+0.000352j +-0.000712+0.000250j +-0.000681+0.000152j +-0.000627+0.000065j +-0.000555-0.000006j +-0.000469-0.000058j +-0.000374-0.000088j +-0.000275-0.000095j +-0.000180-0.000078j +-0.000092-0.000040j +-0.000017+0.000017j +0.000040+0.000090j +0.000078+0.000173j +0.000093+0.000261j +0.000086+0.000350j +0.000058+0.000432j +0.000010+0.000504j +-0.000054+0.000561j +-0.000130+0.000600j +-0.000213+0.000619j +-0.000297+0.000616j +-0.000379+0.000592j +-0.000452+0.000548j +-0.000513+0.000488j +-0.000557+0.000415j +-0.000582+0.000334j +-0.000588+0.000248j +-0.000573+0.000164j +-0.000538+0.000086j +-0.000487+0.000019j +-0.000422-0.000035j +-0.000347-0.000071j +-0.000266-0.000088j +-0.000185-0.000086j +-0.000107-0.000065j +-0.000038-0.000027j +0.000018+0.000025j +0.000060+0.000089j +0.000083+0.000160j +0.000089+0.000233j +0.000076+0.000304j +0.000046+0.000369j +0.000001+0.000423j +-0.000056+0.000464j +-0.000121+0.000489j +-0.000190+0.000497j +-0.000259+0.000487j +-0.000323+0.000461j +-0.000379+0.000419j +-0.000423+0.000365j +-0.000453+0.000301j +-0.000467+0.000232j +-0.000465+0.000161j +-0.000445+0.000093j +-0.000411+0.000032j +-0.000364-0.000019j +-0.000306-0.000058j +-0.000242-0.000081j +-0.000175-0.000090j +-0.000109-0.000082j +-0.000048-0.000059j +0.000005-0.000023j +0.000047+0.000024j +0.000075+0.000078j +0.000089+0.000137j +0.000088+0.000196j +0.000072+0.000252j +0.000042+0.000302j +0.000002+0.000341j +-0.000048+0.000369j +-0.000102+0.000384j +-0.000158+0.000384j +-0.000213+0.000370j +-0.000262+0.000343j +-0.000304+0.000304j +-0.000335+0.000256j +-0.000354+0.000202j +-0.000359+0.000145j +-0.000351+0.000088j +-0.000330+0.000034j +-0.000298-0.000012j +-0.000255-0.000050j +-0.000206-0.000077j +-0.000152-0.000091j +-0.000098-0.000093j +-0.000046-0.000082j +0.000002-0.000059j +0.000041-0.000027j +0.000071+0.000014j +0.000089+0.000059j +0.000095+0.000106j +0.000090+0.000153j +0.000073+0.000196j +0.000045+0.000232j +0.000010+0.000260j +-0.000031+0.000278j +-0.000075+0.000284j +-0.000120+0.000279j +-0.000162+0.000263j +-0.000199+0.000237j +-0.000228+0.000203j +-0.000249+0.000162j +-0.000259+0.000117j +-0.000259+0.000071j +-0.000248+0.000026j +-0.000227-0.000014j +-0.000197-0.000049j +-0.000161-0.000076j +-0.000120-0.000093j +-0.000077-0.000101j +-0.000034-0.000098j +0.000006-0.000086j +0.000042-0.000064j +0.000070-0.000036j +0.000090-0.000002j +0.000101+0.000034j +0.000102+0.000071j +0.000093+0.000107j +0.000077+0.000139j +0.000052+0.000165j +0.000022+0.000184j +-0.000011+0.000194j +-0.000046+0.000196j +-0.000081+0.000188j +-0.000113+0.000173j +-0.000140+0.000150j +-0.000161+0.000121j +-0.000174+0.000089j +-0.000180+0.000054j +-0.000177+0.000020j +-0.000167-0.000013j +-0.000150-0.000041j +-0.000127-0.000063j +-0.000100-0.000077j +-0.000071-0.000084j +-0.000044-0.000080j +-0.000020-0.000066j +-0.000009-0.000035j diff --git a/gnuradio-examples/python/apps/hf_radio/ssbagc.py b/gnuradio-examples/python/apps/hf_radio/ssbagc.py new file mode 100644 index 00000000..fdf40bc6 --- /dev/null +++ b/gnuradio-examples/python/apps/hf_radio/ssbagc.py @@ -0,0 +1,48 @@ +# post detection agc processing +# +# Imagine that the usual gnuradio copyright stuff is right here. +# +# This agc strategy is copied more or less verbatim from +# weaver_isb_am1_usrp3.py by cswiger. +# +# Thanks. +# +# Then modified in a variety of ways. +# +# There doesn't appear to be a way to hook multiple blocks to the +# input port when building a hier block like this. Thus the +# split below. +# +# Basic operation. +# Power is estimated by squaring the input. +# Low pass filter using a 1 pole iir. +# The time constant can be tweaked by changing the taps. +# Currently there is no implementation to change this while operating +# a potentially useful addition. +# The log block turns this into dB +# gain adjusts the agc authority. +# +# M. Revnell 2006-Jan + +from gnuradio import gr, gru + +class agc( gr.hier_block ): + def __init__( self, fg ): + self.split = gr.multiply_const_ff( 1 ) + self.sqr = gr.multiply_ff( ) + self.int0 = gr.iir_filter_ffd( [.004, 0], [0, .999] ) + self.offs = gr.add_const_ff( -30 ) + self.gain = gr.multiply_const_ff( 70 ) + self.log = gr.nlog10_ff( 10, 1 ) + self.agc = gr.divide_ff( ) + + fg.connect( self.split, ( self.agc, 0 ) ) + fg.connect( self.split, ( self.sqr, 0 ) ) + fg.connect( self.split, ( self.sqr, 1 ) ) + fg.connect( self.sqr, self.int0 ) + fg.connect( self.int0, self.log ) + fg.connect( self.log, self.offs ) + fg.connect( self.offs, self.gain ) + fg.connect( self.gain, ( self.agc, 1 ) ) + + gr.hier_block.__init__( self, fg, self.split, self.agc ) diff --git a/gnuradio-examples/python/apps/hf_radio/ssbdemod.py b/gnuradio-examples/python/apps/hf_radio/ssbdemod.py new file mode 100644 index 00000000..c73567b6 --- /dev/null +++ b/gnuradio-examples/python/apps/hf_radio/ssbdemod.py @@ -0,0 +1,97 @@ +# This tries to push the hilbert transform for ssb demod back into the +# freq. xlating filter. +# +# The usual gnuradio copyright notice is hereby included by reference. +# +# The starting point for this was weaver_isb_am1_usrp3.py. +# +# The tap coefficients for freq_xlating_fir_filter_ccf were generated +# externally and are read from a file because I didn't want to learn how +# to make fir filters with arbitrary phase response using python numeric +# facilities. +# +# They were generated using Scilab which I am already familiar with. +# M. Revnell Jan 06 + +from gnuradio import gr, gru +from gnuradio import audio +from gnuradio import usrp + +class ssb_demod( gr.hier_block ): + def __init__( self, fg, if_rate, af_rate ): + + self.if_rate = if_rate + self.af_rate = af_rate + self.if_decim = if_rate / af_rate + self.sideband = 1 + + self.xlate_taps = ([complex(v) for v in file('ssb_taps').readlines()]) + + self.audio_taps = gr.firdes.low_pass( + 1.0, + self.af_rate, + 3e3, + 600, + gr.firdes.WIN_HAMMING ) + + self.xlate = gr.freq_xlating_fir_filter_ccc( + self.if_decim, + self.xlate_taps, + 0, + self.if_rate ) + + self.split = gr.complex_to_float() + + self.lpf = gr.fir_filter_fff( + 1, self.audio_taps ) + + self.sum = gr.add_ff( ) + self.am_sel = gr.multiply_const_ff( 0 ) + self.sb_sel = gr.multiply_const_ff( 1 ) + self.mixer = gr.add_ff() + self.am_det = gr.complex_to_mag() + + fg.connect( self.xlate, self.split ) + fg.connect( ( self.split,0 ), ( self.sum,0 ) ) + fg.connect( ( self.split,1 ), ( self.sum,1 ) ) + fg.connect( self.sum, self.sb_sel ) + fg.connect( self.xlate, self.am_det ) + fg.connect( self.sb_sel, ( self.mixer, 0 ) ) + fg.connect( self.am_det, self.am_sel ) + fg.connect( self.am_sel, ( self.mixer, 1 ) ) + fg.connect( self.mixer, self.lpf ) + + gr.hier_block.__init__( self, fg, self.xlate, self.lpf ) + + def upper_sb( self ): + self.xlate.set_taps([v.conjugate() for v in self.xlate_taps]) + self.sb_sel.set_k( 1.0 ) + self.am_sel.set_k( 0.0 ) + + def lower_sb( self ): + self.xlate.set_taps(self.xlate_taps) + self.sb_sel.set_k( 1.0 ) + self.am_sel.set_k( 0.0 ) + + def set_am( self ): + taps = gr.firdes.low_pass( 1.0, + self.if_rate, + 5e3, + 2e3, + gr.firdes.WIN_HAMMING ) + self.xlate.set_taps( taps ) + self.sb_sel.set_k( 0.0 ) + self.am_sel.set_k( 1.0 ) + + def set_bw( self, bw ): + self.audio_taps = gr.firdes.low_pass( + 1.0, + self.af_rate, + bw, + 600, + gr.firdes.WIN_HAMMING ) + self.lpf.set_taps( self.audio_taps ) + + def tune( self, freq ): + self.xlate.set_center_freq( freq ) + diff --git a/gnuradio-examples/python/apps/hf_radio/startup.py b/gnuradio-examples/python/apps/hf_radio/startup.py new file mode 100644 index 00000000..093369b5 --- /dev/null +++ b/gnuradio-examples/python/apps/hf_radio/startup.py @@ -0,0 +1 @@ +from radio import * diff --git a/gnuradio-examples/python/apps/hf_radio/ui.py b/gnuradio-examples/python/apps/hf_radio/ui.py new file mode 100755 index 00000000..71b73c12 --- /dev/null +++ b/gnuradio-examples/python/apps/hf_radio/ui.py @@ -0,0 +1,295 @@ +#!/usr/bin/env python +# -*- coding: UTF-8 -*- +# generated by wxGlade 0.4 on Mon Jan 2 19:02:03 2006 + +import wx + +class ui_frame(wx.Frame): + def __init__(self, *args, **kwds): + # begin wxGlade: ui_frame.__init__ + kwds["style"] = wx.DEFAULT_FRAME_STYLE + wx.Frame.__init__(self, *args, **kwds) + self.sizer_1_staticbox = wx.StaticBox(self, -1, "sizer_1") + self.freq_disp = wx.SpinCtrl(self, -1, "", min=0, max=100) + self.spin_e6 = wx.SpinButton(self, -1 ) + self.spin_e5 = wx.SpinButton(self, -1 ) + self.spin_e4 = wx.SpinButton(self, -1 ) + self.spin_e3 = wx.SpinButton(self, -1 ) + self.spin_e2 = wx.SpinButton(self, -1 ) + self.spin_e1 = wx.SpinButton(self, -1 ) + self.spin_e0 = wx.SpinButton(self, -1 ) + self.panel_1 = wx.Panel(self, -1) + self.panel_2 = wx.Panel(self, -1) + self.button_lsb = wx.Button(self, -1, "LSB") + self.button_usb = wx.Button(self, -1, "USB") + self.button_am = wx.Button(self, -1, "AM") + self.label_1 = wx.StaticText(self, -1, "VOLUME") + self.label_2 = wx.StaticText(self, -1, "PGA") + self.agc_level = wx.TextCtrl(self, -1, "") + self.label_6 = wx.StaticText(self, -1, "") + self.volume = wx.SpinCtrl(self, -1, "", min=0, max=100) + self.pga = wx.SpinCtrl(self, -1, "", min=0, max=100) + self.agc_max = wx.TextCtrl(self, -1, "") + self.label_7 = wx.StaticText(self, -1, "") + self.label_4 = wx.StaticText(self, -1, "AGC AUTHORITY") + self.label_5 = wx.StaticText(self, -1, "AGC REF LVL") + self.label_3 = wx.StaticText(self, -1, "BANDWIDTH") + self.label_8 = wx.StaticText(self, -1, "") + self.agc_gain = wx.TextCtrl(self, -1, "") + self.agc_gain_s = wx.SpinButton(self, -1 ) + self.agc_ref = wx.TextCtrl(self, -1, "") + self.agc_ref_s = wx.SpinButton(self, -1 ) + self.bandwidth = wx.TextCtrl(self, -1, "") + self.bw_spin = wx.SpinButton(self, -1 ) + self.label_9 = wx.StaticText(self, -1, "") + self.rssi = wx.Gauge(self, -1, 10, style=wx.GA_HORIZONTAL|wx.GA_SMOOTH) + self.fe_panel = wx.Panel(self, -1) + self.if_panel = wx.Panel(self, -1) + + self.__set_properties() + self.__do_layout() + + self.Bind(wx.EVT_SPINCTRL, self.tune_evt, self.freq_disp) + self.Bind(wx.EVT_SPIN_DOWN, self.down_e6, self.spin_e6) + self.Bind(wx.EVT_SPIN_UP, self.up_e6, self.spin_e6) + self.Bind(wx.EVT_SPIN_DOWN, self.down_e5, self.spin_e5) + self.Bind(wx.EVT_SPIN_UP, self.up_e5, self.spin_e5) + self.Bind(wx.EVT_SPIN_DOWN, self.down_e4, self.spin_e4) + self.Bind(wx.EVT_SPIN_UP, self.up_e4, self.spin_e4) + self.Bind(wx.EVT_SPIN_DOWN, self.down_e3, self.spin_e3) + self.Bind(wx.EVT_SPIN_UP, self.up_e3, self.spin_e3) + self.Bind(wx.EVT_SPIN_DOWN, self.down_e2, self.spin_e2) + self.Bind(wx.EVT_SPIN_UP, self.up_e2, self.spin_e2) + self.Bind(wx.EVT_SPIN_DOWN, self.down_e1, self.spin_e1) + self.Bind(wx.EVT_SPIN_UP, self.up_e1, self.spin_e1) + self.Bind(wx.EVT_SPIN_DOWN, self.down_e0, self.spin_e0) + self.Bind(wx.EVT_SPIN_UP, self.up_e0, self.spin_e0) + self.Bind(wx.EVT_BUTTON, self.set_lsb, self.button_lsb) + self.Bind(wx.EVT_BUTTON, self.set_usb, self.button_usb) + self.Bind(wx.EVT_BUTTON, self.set_am, self.button_am) + self.Bind(wx.EVT_SPINCTRL, self.event_vol, self.volume) + self.Bind(wx.EVT_SPINCTRL, self.event_pga, self.pga) + self.Bind(wx.EVT_SPIN_DOWN, self.agc_gain_down, self.agc_gain_s) + self.Bind(wx.EVT_SPIN_UP, self.agc_gain_up, self.agc_gain_s) + self.Bind(wx.EVT_SPIN_DOWN, self.agc_ref_down, self.agc_ref_s) + self.Bind(wx.EVT_SPIN_UP, self.agc_ref_up, self.agc_ref_s) + self.Bind(wx.EVT_SPIN_DOWN, self.bw_down, self.bw_spin) + self.Bind(wx.EVT_SPIN_UP, self.bw_up, self.bw_spin) + # end wxGlade + + def __set_properties(self): + # begin wxGlade: ui_frame.__set_properties + self.SetTitle("frame_1") + self.freq_disp.SetFont(wx.Font(32, wx.DEFAULT, wx.NORMAL, wx.NORMAL, 0, "")) + self.rssi.SetMinSize((315, 10)) + self.rssi.SetForegroundColour(wx.Colour(255, 0, 0)) + # end wxGlade + + def __do_layout(self): + # begin wxGlade: ui_frame.__do_layout + sizer_1 = wx.StaticBoxSizer(self.sizer_1_staticbox, wx.VERTICAL) + sizer_2 = wx.BoxSizer(wx.HORIZONTAL) + sizer_4 = wx.BoxSizer(wx.VERTICAL) + grid_sizer_4 = wx.GridSizer(2, 4, 0, 0) + sizer_5 = wx.BoxSizer(wx.HORIZONTAL) + sizer_7 = wx.BoxSizer(wx.HORIZONTAL) + sizer_6 = wx.BoxSizer(wx.HORIZONTAL) + grid_sizer_3 = wx.GridSizer(2, 4, 0, 0) + sizer_3 = wx.BoxSizer(wx.VERTICAL) + grid_sizer_1 = wx.GridSizer(2, 3, 0, 0) + grid_sizer_2 = wx.GridSizer(1, 7, 0, 0) + sizer_3.Add(self.freq_disp, 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.spin_e6, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.spin_e5, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.spin_e4, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.spin_e3, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.spin_e2, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.spin_e1, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_2.Add(self.spin_e0, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(grid_sizer_2, 1, wx.EXPAND, 0) + grid_sizer_1.Add(self.panel_1, 1, wx.EXPAND, 0) + grid_sizer_1.Add(self.panel_2, 1, wx.EXPAND, 0) + grid_sizer_1.Add(self.button_lsb, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.button_usb, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_1.Add(self.button_am, 0, wx.ADJUST_MINSIZE, 0) + sizer_3.Add(grid_sizer_1, 1, wx.EXPAND, 0) + sizer_2.Add(sizer_3, 1, wx.EXPAND, 0) + grid_sizer_3.Add(self.label_1, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_3.Add(self.label_2, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_3.Add(self.agc_level, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_3.Add(self.label_6, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_3.Add(self.volume, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_3.Add(self.pga, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_3.Add(self.agc_max, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_3.Add(self.label_7, 0, wx.ADJUST_MINSIZE, 0) + sizer_4.Add(grid_sizer_3, 1, wx.EXPAND, 0) + grid_sizer_4.Add(self.label_4, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_4.Add(self.label_5, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_4.Add(self.label_3, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_4.Add(self.label_8, 0, wx.ADJUST_MINSIZE, 0) + sizer_6.Add(self.agc_gain, 0, wx.ADJUST_MINSIZE, 0) + sizer_6.Add(self.agc_gain_s, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_4.Add(sizer_6, 1, wx.EXPAND, 0) + sizer_7.Add(self.agc_ref, 0, wx.ADJUST_MINSIZE, 0) + sizer_7.Add(self.agc_ref_s, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_4.Add(sizer_7, 1, wx.EXPAND, 0) + sizer_5.Add(self.bandwidth, 0, wx.ADJUST_MINSIZE, 0) + sizer_5.Add(self.bw_spin, 0, wx.ADJUST_MINSIZE, 0) + grid_sizer_4.Add(sizer_5, 1, wx.EXPAND, 0) + grid_sizer_4.Add(self.label_9, 0, wx.ADJUST_MINSIZE, 0) + sizer_4.Add(grid_sizer_4, 1, wx.EXPAND, 0) + sizer_4.Add(self.rssi, 1, wx.EXPAND|wx.ADJUST_MINSIZE, 0) + sizer_2.Add(sizer_4, 1, wx.EXPAND, 0) + sizer_1.Add(sizer_2, 1, wx.EXPAND, 0) + sizer_1.Add(self.fe_panel, 1, wx.EXPAND, 0) + sizer_1.Add(self.if_panel, 1, wx.EXPAND, 0) + self.SetAutoLayout(True) + self.SetSizer(sizer_1) + sizer_1.Fit(self) + sizer_1.SetSizeHints(self) + self.Layout() + # end wxGlade + + def down_e6(self, event): # wxGlade: ui_frame. + print "Event handler `down_e6' not implemented" + event.Skip() + + def up_e6(self, event): # wxGlade: ui_frame. + print "Event handler `up_e6' not implemented" + event.Skip() + + def down_e5(self, event): # wxGlade: ui_frame. + print "Event handler `down_e5' not implemented" + event.Skip() + + def up_e5(self, event): # wxGlade: ui_frame. + print "Event handler `up_e5' not implemented" + event.Skip() + + def down_e4(self, event): # wxGlade: ui_frame. + print "Event handler `down_e4' not implemented" + event.Skip() + + def up_e4(self, event): # wxGlade: ui_frame. + print "Event handler `up_e4' not implemented" + event.Skip() + + def down_e3(self, event): # wxGlade: ui_frame. + print "Event handler `down_e3' not implemented" + event.Skip() + + def up_e3(self, event): # wxGlade: ui_frame. + print "Event handler `up_e3' not implemented" + event.Skip() + + def down_e2(self, event): # wxGlade: ui_frame. + print "Event handler `down_e2' not implemented" + event.Skip() + + def up_e2(self, event): # wxGlade: ui_frame. + print "Event handler `up_e2' not implemented" + event.Skip() + + def down_e1(self, event): # wxGlade: ui_frame. + print "Event handler `down_e1' not implemented" + event.Skip() + + def up_e1(self, event): # wxGlade: ui_frame. + print "Event handler `up_e1' not implemented" + event.Skip() + + def down_e0(self, event): # wxGlade: ui_frame. + print "Event handler `down_e0' not implemented" + event.Skip() + + def up_e0(self, event): # wxGlade: ui_frame. + print "Event handler `up_e0' not implemented" + event.Skip() + + def event_vol(self, event): # wxGlade: ui_frame. + print "Event handler `event_vol' not implemented" + event.Skip() + + def event_pga(self, event): # wxGlade: ui_frame. + print "Event handler `event_pga' not implemented" + event.Skip() + + def set_lsb(self, event): # wxGlade: ui_frame. + print "Event handler `set_lsb' not implemented" + event.Skip() + + def set_usb(self, event): # wxGlade: ui_frame. + print "Event handler `set_usb' not implemented" + event.Skip() + + def set_am(self, event): # wxGlade: ui_frame. + print "Event handler `set_am' not implemented" + event.Skip() + + def set_bw(self, event): # wxGlade: ui_frame. + print "Event handler `set_bw' not implemented" + event.Skip() + + def tune_evt(self, event): # wxGlade: ui_frame. + print "Event handler `tune_evt' not implemented" + event.Skip() + + def bw_down(self, event): # wxGlade: ui_frame. + print "Event handler `bw_down' not implemented" + event.Skip() + + def bw_up(self, event): # wxGlade: ui_frame. + print "Event handler `bw_up' not implemented" + event.Skip() + + def agc_gain_down(self, event): # wxGlade: ui_frame. + print "Event handler `agc_gain_down' not implemented" + event.Skip() + + def agc_gain_up(self, event): # wxGlade: ui_frame. + print "Event handler `agc_gain_up' not implemented" + event.Skip() + + def agc_ref_down(self, event): # wxGlade: ui_frame. + print "Event handler `agc_ref_down' not implemented" + event.Skip() + + def agc_ref_up(self, event): # wxGlade: ui_frame. + print "Event handler `agc_ref_up' not implemented" + event.Skip() + +# end of class ui_frame + + +class RadioFrame(wx.Frame): + def __init__(self, *args, **kwds): + # content of this block not found: did you rename this class? + pass + + def __set_properties(self): + # content of this block not found: did you rename this class? + pass + + def __do_layout(self): + # content of this block not found: did you rename this class? + pass + +# end of class RadioFrame + + +class MyFrame(wx.Frame): + def __init__(self, *args, **kwds): + # content of this block not found: did you rename this class? + pass + + def __set_properties(self): + # content of this block not found: did you rename this class? + pass + + def __do_layout(self): + # content of this block not found: did you rename this class? + pass + +# end of class MyFrame + + diff --git a/gnuradio-examples/python/audio/Makefile.am b/gnuradio-examples/python/audio/Makefile.am new file mode 100644 index 00000000..27cea62a --- /dev/null +++ b/gnuradio-examples/python/audio/Makefile.am @@ -0,0 +1,32 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +EXTRA_DIST = \ + audio_copy.py \ + audio_play.py \ + audio_to_file.py \ + dial_tone.py \ + mono_tone.py \ + multi_tone.py \ + spectrum_inversion.py \ + test_resampler.py + + diff --git a/gnuradio-examples/python/audio/audio_copy.py b/gnuradio-examples/python/audio/audio_copy.py new file mode 100755 index 00000000..56fa836d --- /dev/null +++ b/gnuradio-examples/python/audio/audio_copy.py @@ -0,0 +1,64 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser = OptionParser(option_class=eng_option) + parser.add_option("-I", "--audio-input", type="string", default="", + help="pcm input device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-r", "--sample-rate", type="eng_float", default=48000, + help="set sample rate to RATE (48000)") + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + sample_rate = int(options.sample_rate) + src = audio.source (sample_rate, options.audio_input) + dst = audio.sink (sample_rate, options.audio_output) + + # Determine the maximum number of outputs on the source and + # maximum number of inputs on the sink, then connect together + # the most channels we can without overlap + nchan = min (src.output_signature().max_streams(), + dst.input_signature().max_streams()) + + for i in range (nchan): + self.connect ((src, i), (dst, i)) + + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass + diff --git a/gnuradio-examples/python/audio/audio_play.py b/gnuradio-examples/python/audio/audio_play.py new file mode 100755 index 00000000..e70b0f94 --- /dev/null +++ b/gnuradio-examples/python/audio/audio_play.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser = OptionParser(option_class=eng_option) + parser.add_option("-F", "--filename", type="string", default="audio.dat", + help="read input from FILE") + parser.add_option("-r", "--sample-rate", type="eng_float", default=48000, + help="set sample rate to RATE (48000)") + parser.add_option("-R", "--repeat", action="store_true", default=False) + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + sample_rate = int(options.sample_rate) + src = gr.file_source (gr.sizeof_float, options.filename, options.repeat) + dst = audio.sink (sample_rate, options.audio_output) + self.connect(src, dst) + + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/audio/audio_to_file.py b/gnuradio-examples/python/audio/audio_to_file.py new file mode 100755 index 00000000..74e1ea7a --- /dev/null +++ b/gnuradio-examples/python/audio/audio_to_file.py @@ -0,0 +1,63 @@ +#!/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 gnuradio import gr +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + usage="%prog: [options] output_filename" + parser = OptionParser(option_class=eng_option, usage=usage) + parser.add_option("-I", "--audio-input", type="string", default="", + help="pcm input device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-r", "--sample-rate", type="eng_float", default=48000, + help="set sample rate to RATE (48000)") + parser.add_option("-N", "--nsamples", type="eng_float", default=None, + help="number of samples to collect [default=+inf]") + + (options, args) = parser.parse_args () + if len(args) != 1: + parser.print_help() + raise SystemExit, 1 + filename = args[0] + + sample_rate = int(options.sample_rate) + src = audio.source (sample_rate, options.audio_input) + dst = gr.file_sink (gr.sizeof_float, filename) + + if options.nsamples is None: + self.connect((src, 0), dst) + else: + head = gr.head(gr.sizeof_float, int(options.nsamples)) + self.connect((src, 0), head, dst) + + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/audio/dial_squelch.py b/gnuradio-examples/python/audio/dial_squelch.py new file mode 100755 index 00000000..d947e586 --- /dev/null +++ b/gnuradio-examples/python/audio/dial_squelch.py @@ -0,0 +1,89 @@ +#!/usr/bin/env python + +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 gnuradio import gr, audio, eng_option +from gnuradio.eng_option import eng_option +from math import pi, cos +from optparse import OptionParser + +""" +This script generates a standard dial tone and then applies a sinusoidal +envelope to vary it's loudness. The audio is then passed through the +power squelch block before it gets sent to the sound card. By varying +the command line parameters, one can see the effect of differing +amounts of power averaging, threshold, and attack/decay ramping. +""" + +class app_flow_graph(gr.flow_graph): + def __init__(self, options, args): + gr.flow_graph.__init__(self) + + # Create dial tone by adding two sine waves + SRC1 = gr.sig_source_f(options.rate, gr.GR_SIN_WAVE, 350, 0.5, 0.0) + SRC2 = gr.sig_source_f(options.rate, gr.GR_SIN_WAVE, 440, 0.5, 0.0) + ADD = gr.add_ff() + + # Convert to vector stream (and back) to apply raised cosine envelope + # You could also do this with a vector_source_f block that repeats. + S2V = gr.stream_to_vector(gr.sizeof_float, options.rate) + ENV = [0.5-cos(2*pi*x/options.rate)/2 for x in range(options.rate)] + MLT = gr.multiply_const_vff(ENV) + V2S = gr.vector_to_stream(gr.sizeof_float, options.rate) + + # Run through power squelch with user supplied or default options + # Zero output when squelch is invoked + SQL = gr.pwr_squelch_ff(options.threshold, options.alpha, options.ramp, False) + DST = audio.sink(options.rate) + + # Solder it all together + self.connect(SRC1, (ADD, 0)) + self.connect(SRC2, (ADD, 1)) + self.connect(ADD, S2V, MLT, V2S, SQL, DST) + +def main(): + parser = OptionParser(option_class=eng_option) + parser.add_option("-r", "--rate", type="int", default=8000, help="set audio output sample rate to RATE", metavar="RATE") + parser.add_option("-t", "--threshold", type="eng_float", default=-10.0, help="set power squelch to DB", metavar="DB") + parser.add_option("-a", "--alpha", type="eng_float", default=None, help="set alpha to ALPHA", metavar="ALPHA") + parser.add_option("-m", "--ramp", type="int", default=None, help="set attack/decay ramp to SAMPLES", metavar="SAMPLES") + (options, args) = parser.parse_args() + + if options.alpha == None: + options.alpha = 50.0/options.rate + + if options.ramp == None: + options.ramp = options.rate/50 # ~ 20 ms + + print "Using audio rate of", options.rate + print "Using threshold of", options.threshold, "db" + print "Using alpha of", options.alpha + print "Using ramp of", options.ramp, "samples" + + fg = app_flow_graph(options, args) + + try: + fg.run() + except KeyboardInterrupt: + pass + +if __name__ == "__main__": + main() diff --git a/gnuradio-examples/python/audio/dial_tone.py b/gnuradio-examples/python/audio/dial_tone.py new file mode 100755 index 00000000..3ce84eb5 --- /dev/null +++ b/gnuradio-examples/python/audio/dial_tone.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser = OptionParser(option_class=eng_option) + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-r", "--sample-rate", type="eng_float", default=48000, + help="set sample rate to RATE (48000)") + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + sample_rate = int(options.sample_rate) + ampl = 0.1 + + src0 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 350, ampl) + src1 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 440, ampl) + dst = audio.sink (sample_rate, options.audio_output) + self.connect (src0, (dst, 0)) + self.connect (src1, (dst, 1)) + + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/audio/dialtone_v.py b/gnuradio-examples/python/audio/dialtone_v.py new file mode 100755 index 00000000..e704414a --- /dev/null +++ b/gnuradio-examples/python/audio/dialtone_v.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python + +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 gnuradio import gr, audio +from math import pi, sin + +""" +This test script demonstrates the use of element-wise vector processing +vs. stream processing. The example is artificial in that the stream +version in dial_tone.py is the normal way to do it; in addition, the +envelope processing here is just for demo purposes and isn't needed. +""" + +# For testing different buffer sizes +rate = 48000 + +fg = gr.flow_graph() + +# Two streams of floats +a = gr.sig_source_f(rate, gr.GR_SIN_WAVE, 350, 0.5, 0.0); +b = gr.sig_source_f(rate, gr.GR_SIN_WAVE, 440, 0.5, 0.0); + +# Turn them into vectors of length 'size' +av = gr.stream_to_vector(gr.sizeof_float, rate) +bv = gr.stream_to_vector(gr.sizeof_float, rate) + +# Make a vector adder for float vectors +adder = gr.add_vff(rate) + +# Make a 1 Hz sine envelope +envelope = [sin(2*pi*x/rate)*0.5 for x in range(rate)] +multiplier = gr.multiply_const_vff(envelope) + +# Make an offset adder +offset = gr.add_const_vff((0.5,)*rate) + +# Turn the vector back into a stream of floats +result = gr.vector_to_stream(gr.sizeof_float, rate) + +# Play it +sink = audio.sink(rate) + +fg.connect(a, av) +fg.connect(b, bv) +fg.connect(av, (adder, 0)) +fg.connect(bv, (adder, 1)) +fg.connect(adder, multiplier, offset, result, sink) + +try: + fg.run() +except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/audio/mono_tone.py b/gnuradio-examples/python/audio/mono_tone.py new file mode 100755 index 00000000..84c3b542 --- /dev/null +++ b/gnuradio-examples/python/audio/mono_tone.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +#import os +#print os.getpid() +#raw_input('Attach gdb and press Enter: ') + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser = OptionParser(option_class=eng_option) + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-r", "--sample-rate", type="eng_float", default=48000, + help="set sample rate to RATE (48000)") + parser.add_option("-D", "--dont-block", action="store_false", default=True, + dest="ok_to_block") + + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + sample_rate = int(options.sample_rate) + ampl = 0.1 + + src0 = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, 650, ampl) + + dst = audio.sink (sample_rate, + options.audio_output, + options.ok_to_block) + + self.connect (src0, (dst, 0)) + + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/audio/multi_tone.py b/gnuradio-examples/python/audio/multi_tone.py new file mode 100755 index 00000000..c6f83050 --- /dev/null +++ b/gnuradio-examples/python/audio/multi_tone.py @@ -0,0 +1,90 @@ +#!/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 gnuradio import gr +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +#import os +#print os.getpid() +#raw_input('Attach gdb and press Enter: ') + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser = OptionParser(option_class=eng_option) + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-r", "--sample-rate", type="eng_float", default=48000, + help="set sample rate to RATE (48000)") + parser.add_option ("-m", "--max-channels", type="int", default="16", + help="set maximum channels to use") + parser.add_option("-D", "--dont-block", action="store_false", default=True, + dest="ok_to_block") + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + sample_rate = int(options.sample_rate) + limit_channels = options.max_channels + + ampl = 0.1 + + # With a tip of the hat to Harry Partch, may he R.I.P. + # See "Genesis of a Music". He was into some very wild tunings... + base = 392 + ratios = { 1 : 1.0, + 3 : 3.0/2, + 5 : 5.0/4, + 7 : 7.0/4, + 9 : 9.0/8, + 11 : 11.0/8 } + + # progression = (1, 5, 3, 7) + # progression = (1, 9, 3, 7) + # progression = (3, 7, 9, 11) + # progression = (7, 11, 1, 5) + progression = (7, 11, 1, 5, 9) + + dst = audio.sink (sample_rate, + options.audio_output, + options.ok_to_block) + + max_chan = dst.input_signature().max_streams() + if (max_chan == -1) or (max_chan > limit_channels): + max_chan = limit_channels + + for i in range (max_chan): + quo, rem = divmod (i, len (progression)) + freq = base * ratios[progression[rem]] * (quo + 1) + src = gr.sig_source_f (sample_rate, gr.GR_SIN_WAVE, freq, ampl) + self.connect (src, (dst, i)) + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/audio/spectrum_inversion.py b/gnuradio-examples/python/audio/spectrum_inversion.py new file mode 100755 index 00000000..9bb87aa4 --- /dev/null +++ b/gnuradio-examples/python/audio/spectrum_inversion.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python +# +# Gang - Here's a simple script that demonstrates spectrum inversion +# using the multiply by [1,-1] method (mixing with Nyquist frequency). +# Requires nothing but a sound card, and sounds just like listening +# to a SSB signal on the wrong sideband. +# + +from gnuradio import gr +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser = OptionParser(option_class=eng_option) + parser.add_option("-I", "--audio-input", type="string", default="", + help="pcm input device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-r", "--sample-rate", type="eng_float", default=8000, + help="set sample rate to RATE (8000)") + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + sample_rate = int(options.sample_rate) + src = audio.source (sample_rate, options.audio_input) + dst = audio.sink (sample_rate, options.audio_output) + + vec1 = [1, -1] + vsource = gr.vector_source_f(vec1, True) + multiply = gr.multiply_ff() + + self.connect(src, (multiply, 0)) + self.connect(vsource, (multiply, 1)) + self.connect(multiply, dst) + + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/audio/test_resampler.py b/gnuradio-examples/python/audio/test_resampler.py new file mode 100755 index 00000000..6c9e5a76 --- /dev/null +++ b/gnuradio-examples/python/audio/test_resampler.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr, gru, blks +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser = OptionParser(option_class=eng_option) + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-i", "--input-rate", type="eng_float", default=8000, + help="set input sample rate to RATE (%default)") + parser.add_option("-o", "--output-rate", type="eng_float", default=48000, + help="set output sample rate to RATE (%default)") + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + input_rate = int(options.input_rate) + output_rate = int(options.output_rate) + + interp = gru.lcm(input_rate, output_rate) / input_rate + decim = gru.lcm(input_rate, output_rate) / output_rate + + print "interp =", interp + print "decim =", decim + + ampl = 0.1 + src0 = gr.sig_source_f (input_rate, gr.GR_SIN_WAVE, 650, ampl) + rr = blks.rational_resampler_fff(self, interp, decim) + dst = audio.sink (output_rate, options.audio_output) + self.connect (src0, rr, (dst, 0)) + + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/digital_voice/Makefile.am b/gnuradio-examples/python/digital_voice/Makefile.am new file mode 100644 index 00000000..ed88c22d --- /dev/null +++ b/gnuradio-examples/python/digital_voice/Makefile.am @@ -0,0 +1,23 @@ +# +# 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. +# + +EXTRA_DIST = \ + encdec.py diff --git a/gnuradio-examples/python/digital_voice/encdec.py b/gnuradio-examples/python/digital_voice/encdec.py new file mode 100755 index 00000000..11936a4b --- /dev/null +++ b/gnuradio-examples/python/digital_voice/encdec.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 gnuradio import gr, blks +from gnuradio import audio +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser = OptionParser(option_class=eng_option) + parser.add_option("-I", "--audio-input", type="string", default="", + help="pcm input device name. E.g., hw:0,0 or /dev/dsp") + parser.add_option("-O", "--audio-output", type="string", default="", + help="pcm output device name. E.g., hw:0,0 or /dev/dsp") + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + sample_rate = 8000 + src = audio.source(sample_rate, options.audio_input) + tx = blks.digital_voice_tx(self) + if_gain = gr.multiply_const_cc(10000) + # channel simulator here... + rx = blks.digital_voice_rx(self) + dst = audio.sink(sample_rate, options.audio_output) + + self.connect(src, tx, if_gain, rx, dst) + + +if __name__ == '__main__': + try: + my_graph().run() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/gmsk2/Makefile.am b/gnuradio-examples/python/gmsk2/Makefile.am new file mode 100644 index 00000000..cf2ffb39 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/Makefile.am @@ -0,0 +1,38 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. +# + +EXTRA_DIST = \ + benchmark_gmsk_rx.py \ + benchmark_gmsk_tx.py \ + benchmark_mpsk_rx.py \ + benchmark_mpsk_tx.py \ + fusb_options.py \ + gen_whitener.py \ + gmsk_test.py \ + pick_bitrate.py \ + receive_path.py \ + transmit_path.py \ + tunnel_ip_null_mac.py + + + + + diff --git a/gnuradio-examples/python/gmsk2/README b/gnuradio-examples/python/gmsk2/README new file mode 100644 index 00000000..b3c343e4 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/README @@ -0,0 +1,81 @@ +Quick overview of what's here: + +* gmsk_test.py: stand-alone program that exercises the GMSK packet tx +and rx code. The two halves are connected with a simulated noisy +channel. It's easy to add extra instrumentation to log various internal +states. We used a variant of this code to get this working in the +first place. + +* benchmark_gmsk_tx.py: generates packets of the size you +specify and sends them across the air using the USRP. Known to work +well using the USRP with the Flex 400 transceiver daughterboard. +You can specify the bitrate to use with the -r command line +parameter. The default is 500k. Some machines will do 1M or more. + +* benchmark_gmsk_rx.py: the receiver half of benchmark_gmsk_tx.py. +Command line arguments are pretty much the same as tx. Works well +with a USRP and Flex 400 transceiver daughterboard. Will also work +with TVRX daugherboard, but you'll need to fiddle with the gain. See +below. Prints a summary of each packet received and keeps a running +total of packets received, and how many of them were error free. +There are two levels of error reporting going on. If the access code +(PN code) and header of a packet were properly detected, then you'll +get an output line. If the CRC32 of the payload was correct you get +"ok = True", else "ok = False". The "pktno" is extracted from the +received packet. If there are skipped numbers, you're missing some +packets. Be sure you've got a suitable antenna connected to the TX/RX +port on each board. A "70 cm" / 420 MHz antenna for a ham +handi-talkie works great. These are available at ham radio supplies, +etc. The boards need to be at least 3m apart. You can also try +experimenting with the rx gain (-g command line option). + +Generally speaking, I start the rx first on one machine, and then fire +up the tx on the other machine. The tx also supports a discontinous +transmission mode where it sends bursts of 5 packets and then waits 1 +second. This is useful for ensuring that all the receiver control +loops lock up fast enough. + +* tunnel.py: This program provides a framework for building your own +MACs. It creates a "TAP" interface in the kernel, typically gr0, +and sends and receives ethernet frames through it. See +/usr/src/linux/Documentation/networking/tuntap.txt and/or Google for +"universal tun tap". The Linux 2.6 kernel includes the tun module, you +don't have to build it. You may have to "modprobe tun" if it's not +loaded by default. If /dev/net/tun doesn't exist, try "modprobe tun". + +To run this program you'll need to be root or running with the +appropriate capability to open the tun interface. You'll need to fire +up two copies on different machines. Once each is running you'll need +to ifconfig the gr0 interface to set the IP address. + +This will allow two machines to talk, but anything beyond the two +machines depends on your networking setup. Left as an exercise... + +On machine A: + + $ su + # ./tunnel.py --freq 423.0M --bitrate 500k + # # in another window on A, also as root... + # ifconfig gr0 10.10.10.1 + + +On machine B: + + $ su + # ./tunnel.py --freq 423.0M --bitrate 500k + # # in another window on B, also as root... + # ifconfig gr0 10.10.10.2 + +Now, on machine A you shold be able to ping machine B: + + $ ping 10.10.10.2 + +and you should see some output for each packet in the +tunnel.py window if you used the -v option. + +Likewise, on machine B: + + $ ping 10.10.10.1 + +This now uses a carrier sense MAC, so you should be able to ssh +between the machines, web browse, etc. diff --git a/gnuradio-examples/python/gmsk2/benchmark_gmsk_rx.py b/gnuradio-examples/python/gmsk2/benchmark_gmsk_rx.py new file mode 100755 index 00000000..d1f70c54 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/benchmark_gmsk_rx.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 gnuradio import gr, gru, blks +from gnuradio import usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +import random +import struct + +# from current dir +from receive_path import receive_path +import fusb_options + +#import os +#print os.getpid() +#raw_input('Attach and press enter') + + +class my_graph(gr.flow_graph): + + def __init__(self, demod_class, rx_subdev_spec, + bitrate, decim_rate, spb, + rx_callback, options, demod_kwargs): + gr.flow_graph.__init__(self) + self.rxpath = receive_path(self, demod_class, rx_subdev_spec, + bitrate, decim_rate, spb, + rx_callback, options, demod_kwargs) + +# ///////////////////////////////////////////////////////////////////////////// +# main +# ///////////////////////////////////////////////////////////////////////////// + +global n_rcvd, n_right + +def main(): + global n_rcvd, n_right + + n_rcvd = 0 + n_right = 0 + + def rx_callback(ok, payload): + global n_rcvd, n_right + (pktno,) = struct.unpack('!H', payload[0:2]) + n_rcvd += 1 + if ok: + n_right += 1 + + print "ok = %r pktno = %4d n_rcvd = %4d n_right = %4d" % ( + ok, pktno, n_rcvd, n_right) + + parser = OptionParser (option_class=eng_option) + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, + help="select USRP Rx side A or B") + parser.add_option("-f", "--freq", type="eng_float", default=423.1e6, + help="set Rx frequency to FREQ [default=%default]", + metavar="FREQ") + parser.add_option("-r", "--bitrate", type="eng_float", default=None, + help="specify bitrate. spb and interp will be derived.") + parser.add_option("-g", "--rx-gain", type="eng_float", default=27, + help="set rx gain") + parser.add_option("-S", "--spb", type="int", default=None, + help="set samples/baud [default=%default]") + parser.add_option("-d", "--decim", type="intx", default=None, + help="set fpga decim rate to DECIM [default=%default]") + fusb_options.add_options(parser) + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + if options.freq < 1e6: + options.freq *= 1e6 + + demod_kwargs = { } # placeholder + + # build the graph + fg = my_graph(blks.gmsk2_demod, + options.rx_subdev_spec, options.bitrate, + options.decim, options.spb, rx_callback, + options, demod_kwargs) + + print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.rxpath.bitrate()),) + print "spb: %3d" % (fg.rxpath.spb(),) + print "decim: %3d" % (fg.rxpath.decim(),) + + ok = fg.rxpath.set_freq(options.freq) + if not ok: + print "Failed to set Rx frequency to %s" % (eng_notation.num_to_str(options.freq),) + raise SystemExit + + fg.rxpath.set_gain(options.rx_gain) + print "Rx gain_range: ", fg.rxpath.subdev.gain_range(), " using", fg.rxpath.gain + + r = gr.enable_realtime_scheduling() + if r != gr.RT_OK: + print "Warning: Failed to enable realtime scheduling." + + fg.start() # start flow graph + fg.wait() # wait for it to finish + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/gmsk2/benchmark_gmsk_tx.py b/gnuradio-examples/python/gmsk2/benchmark_gmsk_tx.py new file mode 100755 index 00000000..2994003a --- /dev/null +++ b/gnuradio-examples/python/gmsk2/benchmark_gmsk_tx.py @@ -0,0 +1,146 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr, gru, blks +from gnuradio import usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +import random +import time +import struct +import sys + +# from current dir +from transmit_path import transmit_path +import fusb_options + +#import os +#print os.getpid() +#raw_input('Attach and press enter') + + +class my_graph(gr.flow_graph): + + def __init__(self, mod_class, tx_subdev_spec, + bitrate, interp_rate, spb, gain, + options, mod_kwargs): + gr.flow_graph.__init__(self) + self.txpath = transmit_path(self, mod_class, tx_subdev_spec, + bitrate, interp_rate, spb, gain, + options, mod_kwargs) + + +# ///////////////////////////////////////////////////////////////////////////// +# main +# ///////////////////////////////////////////////////////////////////////////// + +def main(): + + def send_pkt(payload='', eof=False): + return fg.txpath.send_pkt(payload, eof) + + def rx_callback(ok, payload): + print "ok = %r, payload = '%s'" % (ok, payload) + + parser = OptionParser (option_class=eng_option) + parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=None, + help="select USRP Tx side A or B") + parser.add_option("-f", "--freq", type="eng_float", default=423.1e6, + help="set Tx and Rx frequency to FREQ [default=%default]", + metavar="FREQ") + parser.add_option("-r", "--bitrate", type="eng_float", default=None, + help="specify bitrate. spb and interp will be derived.") + parser.add_option("-S", "--spb", type="int", default=None, + help="set samples/baud [default=%default]") + parser.add_option("-i", "--interp", type="intx", default=None, + help="set fpga interpolation rate to INTERP [default=%default]") + parser.add_option("-s", "--size", type="eng_float", default=1500, + help="set packet size [default=%default]") + parser.add_option("", "--bt", type="float", default=0.3, + help="set bandwidth-time product [default=%default]") + parser.add_option("-g", "--gain", type="eng_float", default=100.0, + help="transmitter gain [default=%default]") + parser.add_option("-M", "--megabytes", type="eng_float", default=1.0, + help="set megabytes to transmit [default=%default]") + parser.add_option("","--discontinuous", action="store_true", default=False, + help="enable discontinous transmission (bursts of 5 packets)") + fusb_options.add_options(parser) + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + if options.freq < 1e6: + options.freq *= 1e6 + + pkt_size = int(options.size) + + mod_kwargs = { + 'bt' : options.bt, + } + + # build the graph + fg = my_graph(blks.gmsk2_mod, options.tx_subdev_spec, + options.bitrate, options.interp, options.spb, options.gain, + options, mod_kwargs) + + print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.txpath.bitrate()),) + print "spb: %3d" % (fg.txpath.spb(),) + print "interp: %3d" % (fg.txpath.interp(),) + + ok = fg.txpath.set_freq(options.freq) + if not ok: + print "Failed to set Tx frequency to %s" % (eng_notation.num_to_str(options.freq),) + raise SystemExit + + r = gr.enable_realtime_scheduling() + if r != gr.RT_OK: + print "Warning: failed to enable realtime scheduling" + + fg.start() # start flow graph + + # generate and send packets + nbytes = int(1e6 * options.megabytes) + n = 0 + pktno = 0 + + while n < nbytes: + send_pkt(struct.pack('!H', pktno) + (pkt_size - 2) * chr(pktno & 0xff)) + n += pkt_size + sys.stderr.write('.') + if options.discontinuous and pktno % 5 == 4: + time.sleep(1) + pktno += 1 + + send_pkt(eof=True) + fg.wait() # wait for it to finish + fg.txpath.set_auto_tr(False) + + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/gmsk2/benchmark_mpsk_rx.py b/gnuradio-examples/python/gmsk2/benchmark_mpsk_rx.py new file mode 100755 index 00000000..ad6218b6 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/benchmark_mpsk_rx.py @@ -0,0 +1,149 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 gnuradio import gr, gru, blks +from gnuradio import usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +import random +import struct + +# from current dir +from bpsk import bpsk_demod +from dbpsk import dbpsk_demod +from dqpsk import dqpsk_demod +from receive_path import receive_path +import fusb_options + +if 1: + import os + print os.getpid() + raw_input('Attach and press enter') + + +class my_graph(gr.flow_graph): + + def __init__(self, demod_class, rx_subdev_spec, + bitrate, decim_rate, spb, + rx_callback, options, demod_kwargs): + gr.flow_graph.__init__(self) + self.rxpath = receive_path(self, demod_class, rx_subdev_spec, + bitrate, decim_rate, spb, + rx_callback, options, demod_kwargs) + +# ///////////////////////////////////////////////////////////////////////////// +# main +# ///////////////////////////////////////////////////////////////////////////// + +global n_rcvd, n_right + +def main(): + global n_rcvd, n_right + + n_rcvd = 0 + n_right = 0 + + def rx_callback(ok, payload): + global n_rcvd, n_right + (pktno,) = struct.unpack('!H', payload[0:2]) + n_rcvd += 1 + if ok: + n_right += 1 + + print "ok = %r pktno = %4d n_rcvd = %4d n_right = %4d" % ( + ok, pktno, n_rcvd, n_right) + + parser = OptionParser (option_class=eng_option) + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, + help="select USRP Rx side A or B") + parser.add_option("-f", "--freq", type="eng_float", default=423.1e6, + help="set Rx frequency to FREQ [default=%default]", + metavar="FREQ") + parser.add_option("-r", "--bitrate", type="eng_float", default=None, + help="specify bitrate. spb and interp will be derived.") + parser.add_option("-S", "--spb", type="int", default=None, + help="set samples/baud [default=%default]") + parser.add_option("-d", "--decim", type="intx", default=None, + help="set fpga decim rate to DECIM [default=%default]") + parser.add_option("-m", "--modulation", type="string", default='dbpsk', + help="modulation type (bpsk, dbpsk, dqpsk) [default=%default]") + parser.add_option("", "--excess-bw", type="float", default=0.3, + help="set RRC excess bandwith factor [default=%default]") + parser.add_option("-g", "--gain", type="eng_float", default=27, + help="set rx gain") + parser.add_option("","--log", action="store_true", default=False, + help="enable diagnostic logging") + fusb_options.add_options(parser) + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + if options.freq < 1e6: + options.freq *= 1e6 + + demod_kwargs = { + 'excess_bw' : options.excess_bw, + } + + #FIXME: Needs to be worked in to overall structure; this will be fixed + # once static class definitions for modulations are defined + if(options.modulation=='bpsk'): + modulation=bpsk_demod + elif(options.modulation=='dbpsk'): + modulation=dbpsk_demod + else: + modulation=dqpsk_demod + + # build the graph + fg = my_graph(modulation, + options.rx_subdev_spec, options.bitrate, + options.decim, options.spb, + rx_callback, options, demod_kwargs) + + print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.rxpath.bitrate()),) + print "spb: %3d" % (fg.rxpath.spb(),) + print "decim: %3d" % (fg.rxpath.decim(),) + + ok = fg.rxpath.set_freq(options.freq) + if not ok: + print "Failed to set Rx frequency to %s" % (eng_notation.num_to_str(options.freq),) + raise SystemExit + + fg.rxpath.set_gain(options.gain) + print "Rx gain_range: ", fg.rxpath.subdev.gain_range(), " using", fg.rxpath.gain + + r = gr.enable_realtime_scheduling() + if r != gr.RT_OK: + print "Warning: Failed to enable realtime scheduling." + + fg.start() # start flow graph + fg.wait() # wait for it to finish + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/gmsk2/benchmark_mpsk_tx.py b/gnuradio-examples/python/gmsk2/benchmark_mpsk_tx.py new file mode 100755 index 00000000..7b37da7f --- /dev/null +++ b/gnuradio-examples/python/gmsk2/benchmark_mpsk_tx.py @@ -0,0 +1,157 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr, gru, blks +from gnuradio import usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +import random, time, struct, sys + +# from current dir +from bpsk import bpsk_mod +from dbpsk import dbpsk_mod +from dqpsk import dqpsk_mod +from transmit_path import transmit_path +import fusb_options + +#import os +#print os.getpid() +#raw_input('Attach and press enter') + + +class my_graph(gr.flow_graph): + + def __init__(self, mod_class, tx_subdev_spec, + bitrate, interp_rate, spb, gain, + options, mod_kwargs): + gr.flow_graph.__init__(self) + self.txpath = transmit_path(self, mod_class, tx_subdev_spec, + bitrate, interp_rate, spb, gain, + options, mod_kwargs) + + +# ///////////////////////////////////////////////////////////////////////////// +# main +# ///////////////////////////////////////////////////////////////////////////// + +def main(): + + def send_pkt(payload='', eof=False): + return fg.txpath.send_pkt(payload, eof) + + def rx_callback(ok, payload): + print "ok = %r, payload = '%s'" % (ok, payload) + + parser = OptionParser (option_class=eng_option) + parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=None, + help="select USRP Tx side A or B") + parser.add_option("-f", "--freq", type="eng_float", default=423.1e6, + help="set Tx and Rx frequency to FREQ [default=%default]", + metavar="FREQ") + parser.add_option("-r", "--bitrate", type="eng_float", default=None, + help="specify bitrate. spb and interp will be derived.") + parser.add_option("-S", "--spb", type="int", default=None, + help="set samples/baud [default=%default]") + parser.add_option("-i", "--interp", type="intx", default=None, + help="set fpga interpolation rate to INTERP [default=%default]") + parser.add_option("-s", "--size", type="eng_float", default=1500, + help="set packet size [default=%default]") + parser.add_option("-m", "--modulation", type="string", default='dbpsk', + help="modulation type (bpsk, dbpsk, dqpsk) [default=%default]") + parser.add_option("", "--excess-bw", type="float", default=0.3, + help="set RRC excess bandwith factor [default=%default]") + parser.add_option("-g", "--gain", type="eng_float", default=100.0, + help="transmitter gain [default=%default]") + parser.add_option("-M", "--megabytes", type="eng_float", default=1.0, + help="set megabytes to transmit [default=%default]") + parser.add_option("","--discontinuous", action="store_true", default=False, + help="enable discontinous transmission (bursts of 5 packets)") + fusb_options.add_options(parser) + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + if options.freq < 1e6: + options.freq *= 1e6 + + pkt_size = int(options.size) + + mod_kwargs = { + 'excess_bw' : options.excess_bw, + } + + #FIXME: rework when static class defintions are ready for the modulation types + if(options.modulation=='bpsk'): + modulation=bpsk_mod + elif( options.modulation=='dbpsk'): + modulation=dbpsk_mod + else: + modulation=dqpsk_mod + + # build the graph + fg = my_graph(modulation, + options.tx_subdev_spec, options.bitrate, options.interp, + options.spb, options.gain, + options, mod_kwargs) + + print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.txpath.bitrate()),) + print "spb: %3d" % (fg.txpath.spb(),) + print "interp: %3d" % (fg.txpath.interp(),) + + ok = fg.txpath.set_freq(options.freq) + if not ok: + print "Failed to set Tx frequency to %s" % (eng_notation.num_to_str(options.freq),) + raise SystemExit + + r = gr.enable_realtime_scheduling() + if r != gr.RT_OK: + print "Warning: failed to enable realtime scheduling" + + fg.start() # start flow graph + + # generate and send packets + nbytes = int(1e6 * options.megabytes) + n = 0 + pktno = 0 + + while n < nbytes: + send_pkt(struct.pack('!H', pktno) + (pkt_size - 2) * chr(pktno & 0xff)) + n += pkt_size + sys.stderr.write('.') + if options.discontinuous and pktno % 5 == 4: + time.sleep(1) + pktno += 1 + + send_pkt(eof=True) + fg.wait() # wait for it to finish + fg.txpath.set_auto_tr(False) + + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/gmsk2/bpsk.py b/gnuradio-examples/python/gmsk2/bpsk.py new file mode 100644 index 00000000..14cea7b1 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/bpsk.py @@ -0,0 +1,256 @@ +# +# 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. +# + +# See gnuradio-examples/python/gmsk2 for examples + +""" +BPSK modulation and demodulation. +""" + +from gnuradio import gr, gru +from math import pi, sqrt +import cmath +import Numeric +from pprint import pprint + +_use_gray_code = True + +def make_constellation(m): + return [cmath.exp(i * 2 * pi / m * 1j) for i in range(m)] + +# Common definition of constellations for Tx and Rx +constellation = { + 2 : make_constellation(2), # BPSK + 4 : make_constellation(4), # QPSK + 8 : make_constellation(8) # 8PSK + } + +if 0: + print "const(2) =" + pprint(constellation[2]) + print "const(4) =" + pprint(constellation[4]) + print "const(8) =" + pprint(constellation[8]) + + +if _use_gray_code: + # ----------------------- + # Do Gray code + # ----------------------- + # binary to gray coding + binary_to_gray = { + 2 : (0, 1), + 4 : (0, 1, 3, 2), + 8 : (0, 1, 3, 2, 7, 6, 4, 5) + } + + # gray to binary + gray_to_binary = { + 2 : (0, 1), + 4 : (0, 1, 3, 2), + 8 : (0, 1, 3, 2, 6, 7, 5, 4) + } +else: + # ----------------------- + # Don't Gray code + # ----------------------- + # identity mapping + binary_to_gray = { + 2 : (0, 1), + 4 : (0, 1, 2, 3), + 8 : (0, 1, 2, 3, 4, 5, 6, 7) + } + + # identity mapping + gray_to_binary = { + 2 : (0, 1), + 4 : (0, 1, 2, 3), + 8 : (0, 1, 2, 3, 4, 5, 6, 7) + } + + +# ///////////////////////////////////////////////////////////////////////////// +# mPSK mod/demod with steams of bytes as data i/o +# ///////////////////////////////////////////////////////////////////////////// + + +class bpsk_mod(gr.hier_block): + + def __init__(self, fg, spb, excess_bw): + """ + Hierarchical block for RRC-filtered BPSK modulation. + + The input is a byte stream (unsigned char) and the + output is the complex modulated signal at baseband. + + @param fg: flow graph + @type fg: flow graph + @param spb: samples per baud >= 2 + @type spb: integer + @param excess_bw: Root-raised cosine filter excess bandwidth + @type excess_bw: float + """ + if not isinstance(spb, int) or spb < 2: + raise TypeError, "sbp must be an integer >= 2" + self.spb = spb + + ntaps = 11 * spb + + bits_per_symbol = self.bits_per_baud() + arity = pow(2,bits_per_symbol) + print "bits_per_symbol =", bits_per_symbol + + # turn bytes into k-bit vectors + self.bytes2chunks = \ + gr.packed_to_unpacked_bb(bits_per_symbol, gr.GR_MSB_FIRST) + + self.chunks2symbols = gr.chunks_to_symbols_bc(constellation[arity]) + + # pulse shaping filter + self.rrc_taps = gr.firdes.root_raised_cosine( + spb, # gain (spb since we're interpolating by spb) + spb, # sampling rate + 1.0, # symbol rate + excess_bw, # excess bandwidth (roll-off factor) + ntaps) + + self.rrc_filter = gr.interp_fir_filter_ccf(spb, self.rrc_taps) + + # Connect + fg.connect(self.bytes2chunks, self.chunks2symbols, self.rrc_filter) + + if 1: + fg.connect(self.rrc_filter, + gr.file_sink(gr.sizeof_gr_complex, "rrc.dat")) + + # Initialize base class + gr.hier_block.__init__(self, fg, self.bytes2chunks, self.rrc_filter) + + def samples_per_baud(self): + return self.spb + + def bits_per_baud(self=None): # staticmethod that's also callable on an instance + return 1 + bits_per_baud = staticmethod(bits_per_baud) # make it a static method. RTFM + + +class bpsk_demod__coherent_detection_of_psk(gr.hier_block): + def __init__(self, fg, spb, excess_bw, costas_alpha=0.005, gain_mu=0.05): + """ + Hierarchical block for RRC-filtered BPSK demodulation + + The input is the complex modulated signal at baseband. + The output is a stream of bits packed 1 bit per byte (LSB) + + @param fg: flow graph + @type fg: flow graph + @param spb: samples per baud >= 2 + @type spb: float + @param excess_bw: Root-raised cosine filter excess bandwidth + @type excess_bw: float + @param costas_alpha: loop filter gain + @type costas_alphas: float + @param gain_mu: + @type gain_mu: float + """ + if spb < 2: + raise TypeError, "sbp must be >= 2" + self.spb = spb + + bits_per_symbol = self.bits_per_baud() + arity = pow(2,bits_per_symbol) + print "bits_per_symbol =", bits_per_symbol + + # Automatic gain control + self.preamp = gr.multiply_const_cc(10e-5) + self.agc = gr.agc_cc(1e-3, 1, 1) + + # Costas loop (carrier tracking) + # FIXME: need to decide how to handle this more generally; do we pull it from higher layer? + costas_order = 2 + costas_alpha *= 15 # 2nd order loop needs more gain + beta = .25 * costas_alpha * costas_alpha + self.costas_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, costas_order) + + # RRC data filter + ntaps = 11 * spb + self.rrc_taps = gr.firdes.root_raised_cosine( + 1.0, # gain + spb, # sampling rate + 1.0, # symbol rate + excess_bw, # excess bandwidth (roll-off factor) + ntaps) + + self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps) + + # symbol clock recovery + omega = spb + gain_omega = .25 * gain_mu * gain_mu + omega_rel_limit = 0.5 + mu = 0.05 + gain_mu = 0.1 + self.clock_recovery=gr.clock_recovery_mm_cc(omega, gain_omega, + mu, gain_mu, omega_rel_limit) + + # find closest constellation point + #rot = .707 + .707j + rot = 1 + rotated_const = map(lambda pt: pt * rot, constellation[arity]) + print "rotated_const =", rotated_const + + self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity)) + self.gray_decoder = gr.map_bb(gray_to_binary[arity]) + + # unpack the k bit vector into a stream of bits + self.unpack = gr.unpack_k_bits_bb(bits_per_symbol) + + fg.connect(self.preamp, self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, + self.slicer, self.gray_decoder, self.unpack) + + # Debug sinks + if 1: + fg.connect(self.agc, + gr.file_sink(gr.sizeof_gr_complex, "agc.dat")) + fg.connect(self.costas_loop, + gr.file_sink(gr.sizeof_gr_complex, "costas_loop.dat")) + fg.connect(self.rrc_filter, + gr.file_sink(gr.sizeof_gr_complex, "rrc.dat")) + fg.connect(self.clock_recovery, + gr.file_sink(gr.sizeof_gr_complex, "clock_recovery.dat")) + fg.connect(self.slicer, + gr.file_sink(gr.sizeof_char, "slicer.dat")) + fg.connect(self.unpack, + gr.file_sink(gr.sizeof_char, "unpack.dat")) + + # Initialize base class + gr.hier_block.__init__(self, fg, self.preamp, self.unpack) + + def samples_per_baud(self): + return self.spb + + def bits_per_baud(self=None): # staticmethod that's also callable on an instance + return 1 + bits_per_baud = staticmethod(bits_per_baud) # make it a static method. RTFM + + +bpsk_demod = bpsk_demod__coherent_detection_of_psk + diff --git a/gnuradio-examples/python/gmsk2/dbpsk.py b/gnuradio-examples/python/gmsk2/dbpsk.py new file mode 100644 index 00000000..213e90c6 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/dbpsk.py @@ -0,0 +1,282 @@ +# +# 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. +# + +# See gnuradio-examples/python/gmsk2 for examples + +""" +differential BPSK modulation and demodulation. +""" + +from gnuradio import gr, gru +from math import pi, sqrt +import cmath +import Numeric +from pprint import pprint + +_use_gray_code = True + +def make_constellation(m): + return [cmath.exp(i * 2 * pi / m * 1j) for i in range(m)] + +# Common definition of constellations for Tx and Rx +constellation = { + 2 : make_constellation(2), # BPSK + 4 : make_constellation(4), # QPSK + 8 : make_constellation(8) # 8PSK + } + +if 0: + print "const(2) =" + pprint(constellation[2]) + print "const(4) =" + pprint(constellation[4]) + print "const(8) =" + pprint(constellation[8]) + + +if _use_gray_code: + # ----------------------- + # Do Gray code + # ----------------------- + # binary to gray coding + binary_to_gray = { + 2 : (0, 1), + 4 : (0, 1, 3, 2), + 8 : (0, 1, 3, 2, 7, 6, 4, 5) + } + + # gray to binary + gray_to_binary = { + 2 : (0, 1), + 4 : (0, 1, 3, 2), + 8 : (0, 1, 3, 2, 6, 7, 5, 4) + } +else: + # ----------------------- + # Don't Gray code + # ----------------------- + # identity mapping + binary_to_gray = { + 2 : (0, 1), + 4 : (0, 1, 2, 3), + 8 : (0, 1, 2, 3, 4, 5, 6, 7) + } + + # identity mapping + gray_to_binary = { + 2 : (0, 1), + 4 : (0, 1, 2, 3), + 8 : (0, 1, 2, 3, 4, 5, 6, 7) + } + + +# ///////////////////////////////////////////////////////////////////////////// +# BPSK mod/demod with steams of bytes as data i/o +# ///////////////////////////////////////////////////////////////////////////// + + +class dbpsk_mod(gr.hier_block): + + def __init__(self, fg, spb, excess_bw): + """ + Hierarchical block for RRC-filtered QPSK modulation. + + The input is a byte stream (unsigned char) and the + output is the complex modulated signal at baseband. + + @param fg: flow graph + @type fg: flow graph + @param spb: samples per baud >= 2 + @type spb: integer + @param excess_bw: Root-raised cosine filter excess bandwidth + @type excess_bw: float + """ + if not isinstance(spb, int) or spb < 2: + raise TypeError, "sbp must be an integer >= 2" + self.spb = spb + + ntaps = 11 * spb + + bits_per_symbol = self.bits_per_baud() + arity = pow(2,bits_per_symbol) + self.bits_per_symbol = bits_per_symbol + print "bits_per_symbol =", bits_per_symbol + + # turn bytes into k-bit vectors + self.bytes2chunks = \ + gr.packed_to_unpacked_bb(bits_per_symbol, gr.GR_MSB_FIRST) + + if True: + self.gray_coder = gr.map_bb(binary_to_gray[arity]) + else: + self.gray_coder = None + + self.diffenc = gr.diff_encoder_bb(arity) + + self.chunks2symbols = gr.chunks_to_symbols_bc(constellation[arity]) + + # pulse shaping filter + self.rrc_taps = gr.firdes.root_raised_cosine( + spb, # gain (spb since we're interpolating by spb) + spb, # sampling rate + 1.0, # symbol rate + excess_bw, # excess bandwidth (roll-off factor) + ntaps) + + self.rrc_filter = gr.interp_fir_filter_ccf(spb, self.rrc_taps) + + # Connect + if self.gray_coder: + fg.connect(self.bytes2chunks, self.gray_coder) + t = self.gray_coder + else: + t = self.bytes2chunks + + fg.connect(t, self.diffenc, self.chunks2symbols, self.rrc_filter) + + if 1: + fg.connect(self.gray_coder, + gr.file_sink(gr.sizeof_char, "graycoder.dat")) + fg.connect(self.diffenc, + gr.file_sink(gr.sizeof_char, "diffenc.dat")) + + # Initialize base class + gr.hier_block.__init__(self, fg, self.bytes2chunks, self.rrc_filter) + + def samples_per_baud(self): + return self.spb + + def bits_per_baud(self=None): # staticmethod that's also callable on an instance + return 1 + bits_per_baud = staticmethod(bits_per_baud) # make it a static method. RTFM + + + +class dbpsk_demod__coherent_detection_of_differentially_encoded_psk(gr.hier_block): + def __init__(self, fg, spb, excess_bw, costas_alpha=0.005, gain_mu=0.05): + """ + Hierarchical block for RRC-filtered BPSK demodulation + + The input is the complex modulated signal at baseband. + The output is a stream of bits packed 1 bit per byte (LSB) + + @param fg: flow graph + @type fg: flow graph + @param spb: samples per baud >= 2 + @type spb: float + @param excess_bw: Root-raised cosine filter excess bandwidth + @type excess_bw: float + @param costas_alpha: loop filter gain + @type costas_alphas: float + @param gain_mu: + @type gain_mu: float + """ + if spb < 2: + raise TypeError, "sbp must be >= 2" + self.spb = spb + + bits_per_symbol = self.bits_per_baud() + arity = pow(2,bits_per_symbol) + print "bits_per_symbol =", bits_per_symbol + + # Automatic gain control + self.preamp = gr.multiply_const_cc(10e-5) + self.agc = gr.agc_cc(1e-3, 1, 1, 1000) + + # Costas loop (carrier tracking) + # FIXME: need to decide how to handle this more generally; do we pull it from higher layer? + costas_order = 2 + costas_alpha *= 15 # 2nd order loop needs more gain + beta = .25 * costas_alpha * costas_alpha + self.costas_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, costas_order) + + # RRC data filter + ntaps = 11 * spb + self.rrc_taps = gr.firdes.root_raised_cosine( + 1.0, # gain + spb, # sampling rate + 1.0, # symbol rate + excess_bw, # excess bandwidth (roll-off factor) + ntaps) + + self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps) + + # symbol clock recovery + omega = spb + gain_omega = .25 * gain_mu * gain_mu + omega_rel_limit = 0.5 + mu = 0.05 + gain_mu = 0.1 + self.clock_recovery=gr.clock_recovery_mm_cc(omega, gain_omega, + mu, gain_mu, omega_rel_limit) + + # find closest constellation point + #rot = .707 + .707j + rot = 1 + rotated_const = map(lambda pt: pt * rot, constellation[arity]) + print "rotated_const =", rotated_const + + self.diffdec = gr.diff_phasor_cc() + #self.diffdec = gr.diff_decoder_bb(arity) + + self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity)) + self.gray_decoder = gr.map_bb(gray_to_binary[arity]) + + # unpack the k bit vector into a stream of bits + self.unpack = gr.unpack_k_bits_bb(bits_per_symbol) + + fg.connect(self.preamp, self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, + self.diffdec, self.slicer, self.gray_decoder, self.unpack) + #fg.connect(self.preamp, self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, + # self.slicer, self.diffdec, self.gray_decoder, self.unpack) + + # Debug sinks + if 1: + fg.connect(self.agc, + gr.file_sink(gr.sizeof_gr_complex, "agc.dat")) + fg.connect(self.costas_loop, + gr.file_sink(gr.sizeof_gr_complex, "costas_loop.dat")) + fg.connect(self.rrc_filter, + gr.file_sink(gr.sizeof_gr_complex, "rrc.dat")) + fg.connect(self.clock_recovery, + gr.file_sink(gr.sizeof_gr_complex, "clock_recovery.dat")) + fg.connect(self.slicer, + gr.file_sink(gr.sizeof_char, "slicer.dat")) + fg.connect(self.diffdec, + gr.file_sink(gr.sizeof_gr_complex, "diffdec.dat")) + #fg.connect(self.diffdec, + # gr.file_sink(gr.sizeof_char, "diffdec.dat")) + fg.connect(self.unpack, + gr.file_sink(gr.sizeof_char, "unpack.dat")) + + # Initialize base class + gr.hier_block.__init__(self, fg, self.preamp, self.unpack) + + def samples_per_baud(self): + return self.spb + + def bits_per_baud(self=None): # staticmethod that's also callable on an instance + return 1 + bits_per_baud = staticmethod(bits_per_baud) # make it a static method. RTFM + + +dbpsk_demod = dbpsk_demod__coherent_detection_of_differentially_encoded_psk + diff --git a/gnuradio-examples/python/gmsk2/dqpsk.py b/gnuradio-examples/python/gmsk2/dqpsk.py new file mode 100644 index 00000000..490dc6f7 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/dqpsk.py @@ -0,0 +1,280 @@ +# +# 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. +# + +# See gnuradio-examples/python/gmsk2 for examples + +""" +differential QPSK modulation and demodulation. +""" + +from gnuradio import gr, gru +from math import pi, sqrt +import cmath +import Numeric +from pprint import pprint + +_use_gray_code = True + +def make_constellation(m): + return [cmath.exp(i * 2 * pi / m * 1j) for i in range(m)] + +# Common definition of constellations for Tx and Rx +constellation = { + 2 : make_constellation(2), # BPSK + 4 : make_constellation(4), # QPSK + 8 : make_constellation(8) # 8PSK + } + +if 0: + print "const(2) =" + pprint(constellation[2]) + print "const(4) =" + pprint(constellation[4]) + print "const(8) =" + pprint(constellation[8]) + + +if _use_gray_code: + # ----------------------- + # Do Gray code + # ----------------------- + # binary to gray coding + binary_to_gray = { + 2 : (0, 1), + 4 : (0, 1, 3, 2), + 8 : (0, 1, 3, 2, 7, 6, 4, 5) + } + + # gray to binary + gray_to_binary = { + 2 : (0, 1), + 4 : (0, 1, 3, 2), + 8 : (0, 1, 3, 2, 6, 7, 5, 4) + } +else: + # ----------------------- + # Don't Gray code + # ----------------------- + # identity mapping + binary_to_gray = { + 2 : (0, 1), + 4 : (0, 1, 2, 3), + 8 : (0, 1, 2, 3, 4, 5, 6, 7) + } + + # identity mapping + gray_to_binary = { + 2 : (0, 1), + 4 : (0, 1, 2, 3), + 8 : (0, 1, 2, 3, 4, 5, 6, 7) + } + + +# ///////////////////////////////////////////////////////////////////////////// +# QPSK mod/demod with steams of bytes as data i/o +# ///////////////////////////////////////////////////////////////////////////// + + +class dqpsk_mod(gr.hier_block): + + def __init__(self, fg, spb, excess_bw): + """ + Hierarchical block for RRC-filtered QPSK modulation. + + The input is a byte stream (unsigned char) and the + output is the complex modulated signal at baseband. + + @param fg: flow graph + @type fg: flow graph + @param spb: samples per baud >= 2 + @type spb: integer + @param excess_bw: Root-raised cosine filter excess bandwidth + @type excess_bw: float + """ + if not isinstance(spb, int) or spb < 2: + raise TypeError, "sbp must be an integer >= 2" + self.spb = spb + + ntaps = 11 * spb + + bits_per_symbol = self.bits_per_baud() + arity = pow(2,bits_per_symbol) + print "bits_per_symbol =", bits_per_symbol + + # turn bytes into k-bit vectors + self.bytes2chunks = \ + gr.packed_to_unpacked_bb(bits_per_symbol, gr.GR_MSB_FIRST) + + if True: + self.gray_coder = gr.map_bb(binary_to_gray[arity]) + else: + self.gray_coder = None + + self.diffenc = gr.diff_encoder_bb(arity) + + self.chunks2symbols = gr.chunks_to_symbols_bc(constellation[arity]) + + # pulse shaping filter + self.rrc_taps = gr.firdes.root_raised_cosine( + spb, # gain (spb since we're interpolating by spb) + spb, # sampling rate + 1.0, # symbol rate + excess_bw, # excess bandwidth (roll-off factor) + ntaps) + + self.rrc_filter = gr.interp_fir_filter_ccf(spb, self.rrc_taps) + + # Connect + if self.gray_coder: + fg.connect(self.bytes2chunks, self.gray_coder) + t = self.gray_coder + else: + t = self.bytes2chunks + + fg.connect(t, self.diffenc, self.chunks2symbols, self.rrc_filter) + + if 1: + fg.connect(self.gray_coder, + gr.file_sink(gr.sizeof_char, "graycoder.dat")) + fg.connect(self.diffenc, + gr.file_sink(gr.sizeof_char, "diffenc.dat")) + + # Initialize base class + gr.hier_block.__init__(self, fg, self.bytes2chunks, self.rrc_filter) + + def samples_per_baud(self): + return self.spb + + def bits_per_baud(self=None): # staticmethod that's also callable on an instance + return 2 + bits_per_baud = staticmethod(bits_per_baud) # make it a static method. RTFM + + + +class dqpsk_demod__coherent_detection_of_differentially_encoded_psk(gr.hier_block): + def __init__(self, fg, spb, excess_bw, costas_alpha=0.005, gain_mu=0.05): + """ + Hierarchical block for RRC-filtered QPSK demodulation + + The input is the complex modulated signal at baseband. + The output is a stream of bits packed 1 bit per byte (LSB) + + @param fg: flow graph + @type fg: flow graph + @param spb: samples per baud >= 2 + @type spb: float + @param excess_bw: Root-raised cosine filter excess bandwidth + @type excess_bw: float + @param costas_alpha: loop filter gain + @type costas_alphas: float + @param gain_mu: + @type gain_mu: float + """ + if spb < 2: + raise TypeError, "sbp must be >= 2" + self.spb = spb + + bits_per_symbol = self.bits_per_baud() + arity = pow(2,bits_per_symbol) + print "bits_per_symbol =", bits_per_symbol + + # Automatic gain control + self.preamp = gr.multiply_const_cc(10e-5) + self.agc = gr.agc_cc(1e-3, 1, 1) + + # Costas loop (carrier tracking) + # FIXME: need to decide how to handle this more generally; do we pull it from higher layer? + costas_order = 4 + beta = .25 * costas_alpha * costas_alpha + self.costas_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, costas_order) + + # RRC data filter + ntaps = 11 * spb + self.rrc_taps = gr.firdes.root_raised_cosine( + 1.0, # gain + spb, # sampling rate + 1.0, # symbol rate + excess_bw, # excess bandwidth (roll-off factor) + ntaps) + + self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps) + + # symbol clock recovery + omega = spb + gain_omega = .25 * gain_mu * gain_mu + omega_rel_limit = 0.5 + mu = 0.05 + gain_mu = 0.1 + self.clock_recovery=gr.clock_recovery_mm_cc(omega, gain_omega, + mu, gain_mu, omega_rel_limit) + + # find closest constellation point + #rot = .707 + .707j + rot = 1 + rotated_const = map(lambda pt: pt * rot, constellation[arity]) + print "rotated_const =", rotated_const + + self.diffdec = gr.diff_phasor_cc() + #self.diffdec = gr.diff_decoder_bb(arity) + + self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity)) + self.gray_decoder = gr.map_bb(gray_to_binary[arity]) + + # unpack the k bit vector into a stream of bits + self.unpack = gr.unpack_k_bits_bb(bits_per_symbol) + + fg.connect(self.preamp, self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, + self.diffdec, self.slicer, self.gray_decoder, self.unpack) + #fg.connect(self.preamp, self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, + # self.slicer, self.diffdec, self.gray_decoder, self.unpack) + + # Debug sinks + if 1: + fg.connect(self.agc, + gr.file_sink(gr.sizeof_gr_complex, "agc.dat")) + fg.connect(self.costas_loop, + gr.file_sink(gr.sizeof_gr_complex, "costas_loop.dat")) + fg.connect(self.rrc_filter, + gr.file_sink(gr.sizeof_gr_complex, "rrc.dat")) + fg.connect(self.clock_recovery, + gr.file_sink(gr.sizeof_gr_complex, "clock_recovery.dat")) + fg.connect(self.slicer, + gr.file_sink(gr.sizeof_char, "slicer.dat")) + fg.connect(self.diffdec, + gr.file_sink(gr.sizeof_gr_complex, "diffdec.dat")) + #fg.connect(self.diffdec, + # gr.file_sink(gr.sizeof_char, "diffdec.dat")) + fg.connect(self.unpack, + gr.file_sink(gr.sizeof_char, "unpack.dat")) + + # Initialize base class + gr.hier_block.__init__(self, fg, self.preamp, self.unpack) + + def samples_per_baud(self): + return self.spb + + def bits_per_baud(self=None): # staticmethod that's also callable on an instance + return 2 + bits_per_baud = staticmethod(bits_per_baud) # make it a static method. RTFM + + +dqpsk_demod = dqpsk_demod__coherent_detection_of_differentially_encoded_psk + diff --git a/gnuradio-examples/python/gmsk2/fusb_options.py b/gnuradio-examples/python/gmsk2/fusb_options.py new file mode 100644 index 00000000..0d04e30c --- /dev/null +++ b/gnuradio-examples/python/gmsk2/fusb_options.py @@ -0,0 +1,31 @@ +# +# 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. +# + +def add_options(parser): + """ + Add Fast USB specifc options to command line parser. + + @param parser: instance of OptionParser + """ + parser.add_option("-B", "--fusb-block-size", type="int", default=0, + help="specify fast usb block size [default=%default]") + parser.add_option("-N", "--fusb-nblocks", type="int", default=0, + help="specify number of fast usb blocks [default=%default]") diff --git a/gnuradio-examples/python/gmsk2/gen_whitener.py b/gnuradio-examples/python/gmsk2/gen_whitener.py new file mode 100755 index 00000000..93aea2b8 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/gen_whitener.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python + +from gnuradio import gr, gru +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import sys + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser = OptionParser(option_class=eng_option) + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + src = gr.lfsr_32k_source_s() + head = gr.head(gr.sizeof_short, 2048) + self.dst = gr.vector_sink_s() + self.connect(src, head, self.dst) + +if __name__ == '__main__': + try: + fg = my_graph() + fg.run() + f = sys.stdout + i = 0 + for s in fg.dst.data(): + f.write("%3d, " % (s & 0xff,)) + f.write("%3d, " % ((s >> 8) & 0xff,)) + i = i+2 + if i % 16 == 0: + f.write('\n') + + except KeyboardInterrupt: + pass + + diff --git a/gnuradio-examples/python/gmsk2/gmsk_test.py b/gnuradio-examples/python/gmsk2/gmsk_test.py new file mode 100755 index 00000000..7ae69a0a --- /dev/null +++ b/gnuradio-examples/python/gmsk2/gmsk_test.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python + +from gnuradio import gr, blks +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import random +import struct + +#import os +#print os.getpid() +#raw_input('Attach and press enter') + + +class my_graph(gr.flow_graph): + + def __init__(self, rx_callback, spb, bt, SNR, freq_error): + gr.flow_graph.__init__(self) + + fg = self + + # Tuning Parameters + gain_mu = 0.002*spb + omega = spb*(1+freq_error) + + # transmitter + self.packet_transmitter = blks.gmsk2_mod_pkts(fg, spb=spb, bt=bt) + + # add some noise + add = gr.add_cc() + noise = gr.noise_source_c(gr.GR_GAUSSIAN, pow(10.0,-SNR/20.0)) + + # channel filter + rx_filt_taps = gr.firdes.low_pass(1,spb,0.8,0.1,gr.firdes.WIN_HANN) + rx_filt = gr.fir_filter_ccf(1,rx_filt_taps) + + # receiver + self.packet_receiver = blks.gmsk2_demod_pkts(fg, callback=rx_callback, + spb=spb, gain_mu=gain_mu, + freq_error=freq_error, omega=omega) + + fg.connect (self.packet_transmitter, (add,0)) + fg.connect (noise, (add,1)) + fg.connect(add, rx_filt, self.packet_receiver) + + +class stats(object): + def __init__(self): + self.npkts = 0 + self.nright = 0 + +def main(): + st = stats() + + def send_pkt(payload='', eof=False): + fg.packet_transmitter.send_pkt(payload, eof) + + def rx_callback(ok, payload): + st.npkts += 1 + if ok: + st.nright += 1 + if len(payload) <= 16: + print "ok = %5r payload = '%s' %d/%d" % (ok, payload, st.nright, st.npkts) + else: + (pktno,) = struct.unpack('!H', payload[0:2]) + print "ok = %5r pktno = %4d len(payload) = %4d %d/%d" % (ok, pktno, len(payload), + st.nright, st.npkts) + + + parser = OptionParser (option_class=eng_option) + parser.add_option("-M", "--megabytes", type="eng_float", default=1, + help="set megabytes to transmit [default=%default]") + parser.add_option("-s", "--size", type="eng_float", default=1500, + help="set packet size [default=%default]") + parser.add_option("","--spb", type=int, default=4, + help="set samples per baud to SPB [default=%default]") + parser.add_option("", "--bt", type="eng_float", default=0.3, + help="set bandwidth time product for Gaussian filter [default=%default]") + parser.add_option("", "--snr", type="eng_float", default=20, + help="set SNR in dB for simulation [default=%default]") + parser.add_option("", "--freq-error", type="eng_float", default=0, + help="set frequency error for simulation [default=%default]") + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + pkt_size = int(options.size) + + fg = my_graph(rx_callback, options.spb, options.bt, options.snr, options.freq_error) + fg.start() + + nbytes = int(1e6 * options.megabytes) + n = 0 + pktno = 0 + + send_pkt('Hello World') + + # generate and send packets + while n < nbytes: + send_pkt(struct.pack('!H', pktno) + (pkt_size - 2) * chr(pktno & 0xff)) + n += pkt_size + pktno += 1 + + send_pkt('Goodbye World') + send_pkt(eof=True) # tell modulator we're not sending any more pkts + + fg.wait() + + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/gmsk2/mpsk_test.py b/gnuradio-examples/python/gmsk2/mpsk_test.py new file mode 100755 index 00000000..1f257d9c --- /dev/null +++ b/gnuradio-examples/python/gmsk2/mpsk_test.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python + +from gnuradio import gr, blks +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import random +import struct +from mpsk_pkt import * +import cmath + +class my_graph(gr.flow_graph): + + def __init__(self, rx_callback, spb, excess_bw, SNR, freq_error, arity): + gr.flow_graph.__init__(self) + + fg = self + + # Tuning Parameters + gain_mu = 0.05/spb + + # transmitter + self.packet_transmitter = \ + mpsk_mod_pkts(fg, spb=spb, excess_bw=excess_bw, diff=True, arity=arity) + + # ---------------------------------------------------------------- + # Channel model + # ---------------------------------------------------------------- + + awgn = gr.noise_source_c(gr.GR_GAUSSIAN, pow(10.0,-SNR/20.0)) + add = gr.add_cc() # add some noise + fg.connect(awgn, (add,1)) + radians = 17*pi/180 + phase_rotate = gr.multiply_const_cc(cmath.exp(radians * 1j)) + + # ---------------------------------------------------------------- + + # channel filter + rx_filt_taps = gr.firdes.low_pass(1,spb,0.8,0.1,gr.firdes.WIN_HANN) + #rx_filt_taps = (1,) + rx_filt = gr.fir_filter_ccf(1,rx_filt_taps) + + # receiver + self.packet_receiver = \ + mpsk_demod_pkts(fg, callback=rx_callback, + excess_bw=excess_bw, arity=arity, diff=True, + costas_alpha=.005, gain_mu=gain_mu, spb=spb) + + fg.connect (self.packet_transmitter, (add,0)) + fg.connect(add, phase_rotate, rx_filt, self.packet_receiver) + + +class stats(object): + def __init__(self): + self.npkts = 0 + self.nright = 0 + +def main(): + st = stats() + + def send_pkt(payload='', eof=False): + fg.packet_transmitter.send_pkt(payload, eof) + + def rx_callback(ok, payload): + st.npkts += 1 + if ok: + st.nright += 1 + if len(payload) <= 16: + print "ok = %5r payload = '%s' %d/%d" % (ok, payload, st.nright, st.npkts) + else: + (pktno,) = struct.unpack('!H', payload[0:2]) + print "ok = %5r pktno = %4d len(payload) = %4d %d/%d" % (ok, pktno, len(payload), + st.nright, st.npkts) + + + parser = OptionParser (option_class=eng_option) + parser.add_option("-M", "--megabytes", type="eng_float", default=1, + help="set megabytes to transmit [default=%default]") + parser.add_option("-s", "--size", type="eng_float", default=1500, + help="set packet size [default=%default]") + parser.add_option("","--spb", type=int, default=4, + help="set samples per baud to SPB [default=%default]") + parser.add_option("", "--excess-bw", type="eng_float", default=0.4, + help="set excess bandwidth for RRC filter [default=%default]") + parser.add_option("", "--snr", type="eng_float", default=40, + help="set SNR in dB for simulation [default=%default]") + parser.add_option("", "--m-arity", type=int, default=4, + help="PSK arity [default=%default]") + parser.add_option("", "--freq-error", type="eng_float", default=0, + help="set frequency error for simulation [default=%default]") + + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + pkt_size = int(options.size) + + fg = my_graph(rx_callback, options.spb, options.excess_bw, options.snr, + options.freq_error, options.m_arity) + fg.start() + + nbytes = int(1e6 * options.megabytes) + n = 0 + pktno = 0 + + send_pkt('Hello World') + + # generate and send packets + while n < nbytes: + send_pkt(struct.pack('!H', pktno) + (pkt_size - 2) * chr(pktno & 0xff)) + n += pkt_size + pktno += 1 + + send_pkt('Goodbye World') + send_pkt(eof=True) # tell modulator we're not sending any more pkts + + fg.wait() + + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/gmsk2/pick_bitrate.py b/gnuradio-examples/python/gmsk2/pick_bitrate.py new file mode 100644 index 00000000..b35991ca --- /dev/null +++ b/gnuradio-examples/python/gmsk2/pick_bitrate.py @@ -0,0 +1,143 @@ +# +# 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. +# + +_default_bitrate = 500e3 + +_valid_spbs = (2,3,4,5,6,7) + +def _gen_tx_info(converter_rate): + results = [] + for spb in _valid_spbs: + for interp in range(16, 512 + 1, 4): + bitrate = converter_rate / interp / spb + results.append((bitrate, spb, interp)) + results.sort() + return results + +def _gen_rx_info(converter_rate): + results = [] + for spb in _valid_spbs: + for decim in range(8, 256 + 1, 2): + bitrate = converter_rate / decim / spb + results.append((bitrate, spb, decim)) + results.sort() + return results + +def _filter_info(info, samples_per_baud, xrate): + if samples_per_baud is not None: + info = [x for x in info if x[1] == samples_per_baud] + if xrate is not None: + info = [x for x in info if x[2] == xrate] + return info + +def _pick_best(target_bitrate, bits_per_symbol, info): + """ + @returns tuple (bitrate, samples_per_baud, interp_rate_or_decim_rate) + """ + if len(info) == 0: + raise RuntimeError, "info is zero length!" + + if target_bitrate is None: # return the fastest one + return info[-1] + + # convert bit rate to symbol rate + target_symbolrate = target_bitrate / bits_per_symbol + + # Find the closest matching symbol rate. + # In the event of a tie, the one with the lowest samples_per_baud wins. + # (We already sorted them, so the first one is the one we take) + + best = info[0] + best_delta = abs(target_symbolrate - best[0]) + for x in info[1:]: + delta = abs(target_symbolrate - x[0]) + if delta < best_delta: + best_delta = delta + best = x + + # convert symbol rate back to bit rate + return ((best[0] * bits_per_symbol),) + best[1:] + +def _pick_bitrate(bitrate, bits_per_symbol, samples_per_baud, + xrate, converter_rate, gen_info): + """ + @returns tuple (bitrate, samples_per_baud, interp_rate_or_decim_rate) + """ + if not isinstance(bits_per_symbol, int) or bits_per_symbol < 1: + raise ValueError, "bits_per_symbol must be an int >= 1" + + if samples_per_baud is not None and xrate is not None: # completely determined + return (float(converter_rate) / xrate / samples_per_baud, + samples_per_baud, xrate) + + if bitrate is None and samples_per_baud is None and xrate is None: + bitrate = _default_bitrate + + # now we have a target bitrate and possibly an xrate or + # samples_per_baud constraint, but not both of them. + + return _pick_best(bitrate, bits_per_symbol, + _filter_info(gen_info(converter_rate), samples_per_baud, xrate)) + +# --------------------------------------------------------------------------------------- + +def pick_tx_bitrate(bitrate, bits_per_symbol, samples_per_baud, + interp_rate, converter_rate=128e6): + """ + Given the 4 input parameters, return at configuration that matches + + @param bitrate: desired bitrate or None + @type bitrate: number or None + @param bits_per_symbol: E.g., BPSK -> 1, QPSK -> 2, 8-PSK -> 3 + @type bits_per_symbol: integer >= 1 + @param samples_per_baud: samples/baud (aka samples/symbol) + @type samples_per_baud: number or None + @param interp_rate: USRP interpolation factor + @type interp_rate: integer or None + @param converter_rate: converter sample rate in Hz + @type converter_rate: number + + @returns tuple (bitrate, samples_per_baud, interp_rate) + """ + return _pick_bitrate(bitrate, bits_per_symbol, samples_per_baud, + interp_rate, converter_rate, _gen_tx_info) + + +def pick_rx_bitrate(bitrate, bits_per_symbol, samples_per_baud, + decim_rate, converter_rate=64e6): + """ + Given the 4 input parameters, return at configuration that matches + + @param bitrate: desired bitrate or None + @type bitrate: number or None + @param bits_per_symbol: E.g., BPSK -> 1, QPSK -> 2, 8-PSK -> 3 + @type bits_per_symbol: integer >= 1 + @param samples_per_baud: samples/baud (aka samples/symbol) + @type samples_per_baud: number or None + @param decim_rate: USRP decimation factor + @type decim_rate: integer or None + @param converter_rate: converter sample rate in Hz + @type converter_rate: number + + @returns tuple (bitrate, samples_per_baud, decim_rate) + """ + return _pick_bitrate(bitrate, bits_per_symbol, samples_per_baud, + decim_rate, converter_rate, _gen_rx_info) diff --git a/gnuradio-examples/python/gmsk2/qpsk.py b/gnuradio-examples/python/gmsk2/qpsk.py new file mode 100644 index 00000000..6ca7f0e6 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/qpsk.py @@ -0,0 +1,418 @@ +# +# 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. +# + +# See gnuradio-examples/python/gmsk2 for examples + +""" +PSK and differential PSK modulation and demodulation. +""" + +from gnuradio import gr, gru +from math import pi, sqrt +import cmath +import Numeric +from pprint import pprint + +_use_gray_code = True + +def make_constellation(m): + return [cmath.exp(i * 2 * pi / m * 1j) for i in range(m)] + +# Common definition of constellations for Tx and Rx +constellation = { + 2 : make_constellation(2), # BPSK + 4 : make_constellation(4), # QPSK + 8 : make_constellation(8) # 8PSK + } + +if 0: + print "const(2) =" + pprint(constellation[2]) + print "const(4) =" + pprint(constellation[4]) + print "const(8) =" + pprint(constellation[8]) + + +if _use_gray_code: + # ----------------------- + # Do Gray code + # ----------------------- + # binary to gray coding + binary_to_gray = { + 2 : (0, 1), + 4 : (0, 1, 3, 2), + 8 : (0, 1, 3, 2, 7, 6, 4, 5) + } + + # gray to binary + gray_to_binary = { + 2 : (0, 1), + 4 : (0, 1, 3, 2), + 8 : (0, 1, 3, 2, 6, 7, 5, 4) + } +else: + # ----------------------- + # Don't Gray code + # ----------------------- + # identity mapping + binary_to_gray = { + 2 : (0, 1), + 4 : (0, 1, 2, 3), + 8 : (0, 1, 2, 3, 4, 5, 6, 7) + } + + # identity mapping + gray_to_binary = { + 2 : (0, 1), + 4 : (0, 1, 2, 3), + 8 : (0, 1, 2, 3, 4, 5, 6, 7) + } + + +# ///////////////////////////////////////////////////////////////////////////// +# mPSK mod/demod with steams of bytes as data i/o +# ///////////////////////////////////////////////////////////////////////////// + + +class mpsk_mod(gr.hier_block): + + def __init__(self, fg, spb, arity, excess_bw, diff=False): + """ + Hierarchical block for RRC-filtered PSK modulation. + + The input is a byte stream (unsigned char) and the + output is the complex modulated signal at baseband. + + @param fg: flow graph + @type fg: flow graph + @param spb: samples per baud >= 2 + @type spb: integer + @param excess_bw: Root-raised cosine filter excess bandwidth + @type excess_bw: float + @param arity: whick PSK: 2, 4, 8 + @type arity: int in {2, 4, 8} + @param diff: differential PSK if true + @type diff: bool + """ + if not isinstance(spb, int) or spb < 2: + raise TypeError, "sbp must be an integer >= 2" + self.spb = spb + + if not arity in (2, 4): + raise ValueError, "n must be 2, 4, or 8" + + ntaps = 11 * spb + + bits_per_symbol = int(gru.log2(arity)) + self.bits_per_symbol = bits_per_symbol + print "bits_per_symbol =", bits_per_symbol + + # turn bytes into k-bit vectors + self.bytes2chunks = \ + gr.packed_to_unpacked_bb(bits_per_symbol, gr.GR_MSB_FIRST) + + if True or arity > 2: + self.gray_coder = gr.map_bb(binary_to_gray[arity]) + else: + self.gray_coder = None + + if diff: + self.diffenc = gr.diff_encoder_bb(arity) + else: + self.diffenc = None + + self.chunks2symbols = gr.chunks_to_symbols_bc(constellation[arity]) + + # pulse shaping filter + self.rrc_taps = gr.firdes.root_raised_cosine( + spb, # gain (spb since we're interpolating by spb) + spb, # sampling rate + 1.0, # symbol rate + excess_bw, # excess bandwidth (roll-off factor) + ntaps) + + self.rrc_filter = gr.interp_fir_filter_ccf(spb, self.rrc_taps) + + # Connect + if self.gray_coder: + fg.connect(self.bytes2chunks, self.gray_coder) + t = self.gray_coder + else: + t = self.bytes2chunks + + if diff: + fg.connect(t, self.diffenc, self.chunks2symbols, self.rrc_filter) + else: + fg.connect(t, self.chunks2symbols, self.rrc_filter) + + if 1: + fg.connect(self.gray_coder, + gr.file_sink(gr.sizeof_char, "graycoder.dat")) + if diff: + fg.connect(self.diffenc, + gr.file_sink(gr.sizeof_char, "diffenc.dat")) + + # Initialize base class + gr.hier_block.__init__(self, fg, self.bytes2chunks, self.rrc_filter) + + def samples_per_baud(self): + return self.spb + + def bits_per_baud(self): + return self.bits_per_symbol + + +class mpsk_demod__coherent_detection_of_differentially_encoded_psk(gr.hier_block): + def __init__(self, fg, spb, arity, excess_bw, diff=False, costas_alpha=0.005, gain_mu=0.05): + """ + Hierarchical block for RRC-filtered PSK demodulation + + The input is the complex modulated signal at baseband. + The output is a stream of bits packed 1 bit per byte (LSB) + + @param fg: flow graph + @type fg: flow graph + @param spb: samples per baud >= 2 + @type spb: float + @param excess_bw: Root-raised cosine filter excess bandwidth + @type excess_bw: float + @param arity: whick PSK: 2, 4, 8 + @type arity: int in {2, 4, 8} + @param diff: differential PSK if true + @type diff: bool + @param costas_alpha: loop filter gain + @type costas_alphas: float + @param gain_mu: + @type gain_mu: float + """ + if spb < 2: + raise TypeError, "sbp must be >= 2" + self.spb = spb + + if not arity in (2, 4): + raise ValueError, "n must be 2 or 4" + + if not diff and arity==4: + raise NotImplementedError, "non-differential QPSK not supported yet" + + bits_per_symbol = int(gru.log2(arity)) + print "bits_per_symbol =", bits_per_symbol + + # Automatic gain control + self.agc = gr.agc_cc(1e-3, 1, 1) + + # Costas loop (carrier tracking) + # FIXME: need to decide how to handle this more generally; do we pull it from higher layer? + if arity == 2: + costas_order = 2 + costas_alpha *= 15 # 2nd order loop needs more gain + else: + costas_order = 4 + beta = .25 * costas_alpha * costas_alpha + self.costas_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, costas_order) + + # RRC data filter + ntaps = 11 * spb + self.rrc_taps = gr.firdes.root_raised_cosine( + 1.0, # gain + spb, # sampling rate + 1.0, # symbol rate + excess_bw, # excess bandwidth (roll-off factor) + ntaps) + + self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps) + + # symbol clock recovery + omega = spb + gain_omega = .25 * gain_mu * gain_mu + omega_rel_limit = 0.5 + mu = 0.05 + gain_mu = 0.1 + self.clock_recovery=gr.clock_recovery_mm_cc(omega, gain_omega, + mu, gain_mu, omega_rel_limit) + + # find closest constellation point + #rot = .707 + .707j + rot = 1 + rotated_const = map(lambda pt: pt * rot, constellation[arity]) + print "rotated_const =", rotated_const + + if(diff): + self.diffdec = gr.diff_phasor_cc() + #self.diffdec = gr.diff_decoder_bb(arity) + + self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity)) + self.gray_decoder = gr.map_bb(gray_to_binary[arity]) + + # unpack the k bit vector into a stream of bits + self.unpack = gr.unpack_k_bits_bb(bits_per_symbol) + + if(diff): + fg.connect(self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, + self.diffdec, self.slicer, self.gray_decoder, self.unpack) + else: + fg.connect(self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, + self.slicer, self.gray_decoder, self.unpack) + + #fg.connect(self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, + # self.slicer, self.diffdec, self.gray_decoder, self.unpack) + + # Debug sinks + if 1: + fg.connect(self.agc, + gr.file_sink(gr.sizeof_gr_complex, "agc.dat")) + fg.connect(self.costas_loop, + gr.file_sink(gr.sizeof_gr_complex, "costas_loop.dat")) + fg.connect(self.rrc_filter, + gr.file_sink(gr.sizeof_gr_complex, "rrc.dat")) + fg.connect(self.clock_recovery, + gr.file_sink(gr.sizeof_gr_complex, "clock_recovery.dat")) + fg.connect(self.slicer, + gr.file_sink(gr.sizeof_char, "slicer.dat")) + if(diff): + fg.connect(self.diffdec, + gr.file_sink(gr.sizeof_gr_complex, "diffdec.dat")) + #fg.connect(self.diffdec, + # gr.file_sink(gr.sizeof_char, "diffdec.dat")) + fg.connect(self.unpack, + gr.file_sink(gr.sizeof_char, "unpack.dat")) + + # Initialize base class + gr.hier_block.__init__(self, fg, self.agc, self.unpack) + + def samples_per_baud(self): + return self.spb + + def bits_per_baud(self): + return self.bits_per_symbol + + +######################################################################### + +class mpsk_demod__coherent_detection_of_nondifferentially_encoded_psk(gr.hier_block): + def __init__(self, fg, spb, arity, excess_bw, diff=False, costas_alpha=0.005, gain_mu=0.05): + """ + Hierarchical block for RRC-filtered PSK demodulation + + The input is the complex modulated signal at baseband. + The output is a stream of bits packed 1 bit per byte (LSB) + + @param fg: flow graph + @type fg: flow graph + @param spb: samples per baud >= 2 + @type spb: float + @param excess_bw: Root-raised cosine filter excess bandwidth + @type excess_bw: float + @param arity: whick PSK: 2, 4, 8 + @type arity: int in {2, 4, 8} + @param diff: differential PSK if true + @type diff: bool + @param costas_alpha: loop filter gain + @type costas_alphas: float + @param gain_mu: + @type gain_mu: float + """ + if spb < 2: + raise TypeError, "sbp must be >= 2" + self.spb = spb + + if not arity in (2, 4): + raise ValueError, "n must be 2 or 4" + + bits_per_symbol = int(gru.log2(arity)) + print "bits_per_symbol =", bits_per_symbol + + # Automatic gain control + self.agc = gr.agc_cc(1e-3, 1, 1) + + # Costas loop (carrier tracking) + # FIXME: need to decide how to handle this more generally; do we pull it from higher layer? + if arity == 2: + costas_order = 2 + costas_alpha *= 15 # 2nd order loop needs more gain + else: + costas_order = 4 + beta = .25 * costas_alpha * costas_alpha + self.costas_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, costas_order) + + # RRC data filter + ntaps = 11 * spb + self.rrc_taps = gr.firdes.root_raised_cosine( + 1.0, # gain + spb, # sampling rate + 1.0, # symbol rate + excess_bw, # excess bandwidth (roll-off factor) + ntaps) + + self.rrc_filter=gr.fir_filter_ccf(1, self.rrc_taps) + + # symbol clock recovery + omega = spb + gain_omega = .25 * gain_mu * gain_mu + omega_rel_limit = 0.5 + mu = 0.05 + gain_mu = 0.1 + self.clock_recovery=gr.clock_recovery_mm_cc(omega, gain_omega, + mu, gain_mu, omega_rel_limit) + + # find closest constellation point + #rot = .707 + .707j + rot = 1 + rotated_const = map(lambda pt: pt * rot, constellation[arity]) + print "rotated_const =", rotated_const + + self.slicer = gr.constellation_decoder_cb(rotated_const, range(arity)) + self.gray_decoder = gr.map_bb(gray_to_binary[arity]) + + # unpack the k bit vector into a stream of bits + self.unpack = gr.unpack_k_bits_bb(bits_per_symbol) + + fg.connect(self.agc, self.costas_loop, self.rrc_filter, self.clock_recovery, + self.slicer, self.gray_decoder, self.unpack) + + # Debug sinks + if 1: + fg.connect(self.agc, + gr.file_sink(gr.sizeof_gr_complex, "agc.dat")) + fg.connect(self.costas_loop, + gr.file_sink(gr.sizeof_gr_complex, "costas_loop.dat")) + fg.connect(self.rrc_filter, + gr.file_sink(gr.sizeof_gr_complex, "rrc.dat")) + fg.connect(self.clock_recovery, + gr.file_sink(gr.sizeof_gr_complex, "clock_recovery.dat")) + fg.connect(self.slicer, + gr.file_sink(gr.sizeof_char, "slicer.dat")) + fg.connect(self.unpack, + gr.file_sink(gr.sizeof_char, "unpack.dat")) + + # Initialize base class + gr.hier_block.__init__(self, fg, self.agc, self.unpack) + + def samples_per_baud(self): + return self.spb + + def bits_per_baud(self): + return self.bits_per_symbol + + +mpsk_demod = mpsk_demod__coherent_detection_of_differentially_encoded_psk +#mpsk_demod = mpsk_demod__coherent_detection_of_nondifferentially_encoded_psk diff --git a/gnuradio-examples/python/gmsk2/qpsk_tester.py b/gnuradio-examples/python/gmsk2/qpsk_tester.py new file mode 100644 index 00000000..ea7bae2e --- /dev/null +++ b/gnuradio-examples/python/gmsk2/qpsk_tester.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python + +import random +from gnuradio import gr + +default_access_code = '\xAC\xDD\xA4\xE2\xF2\x8C\x20\xFC' + +def string_to_1_0_list(s): + r = [] + for ch in s: + x = ord(ch) + for i in range(8): + t = (x >> i) & 0x1 + r.append(t) + + return r + +def to_1_0_string(L): + return ''.join(map(lambda x: chr(x + ord('0')), L)) + +code = string_to_1_0_list(default_access_code) +access_code = to_1_0_string(code) + +use_agc = 0 +use_rrc_tx = 1 +use_rrc_rx = 1 +use_sync_loop = 1 +use_clock_sync = 1 + +def main(): + fg = gr.flow_graph() + +# data = (1,2,3,4,5,6,7,8,9) + random.seed() + data = [random.randint(1,100) for i in range(20000)] + data[0] = 0 # you know, for the diff encoding stuff + bytes_src = gr.vector_source_b(data,False) + + k = 2 + spb = 50 + ntaps = 11*spb + excess_bw = 0.9 + threshold = 12 + constellation = (1+0j, 0+1j, -1+0j, 0-1j) + + bytes2chunks = gr.packed_to_unpacked_bb(k, gr.GR_MSB_FIRST) + diffenc = gr.diff_encoder_bb(4) + chunks2symbols = gr.chunks_to_symbols_bc(constellation) + + if use_rrc_tx: + rrc_taps_tx = gr.firdes.root_raised_cosine(spb, spb, 1.0, \ + excess_bw, ntaps) + rrc_tx = gr.interp_fir_filter_ccf(spb, rrc_taps_tx) + else: + rrc_tx = gr.interp_fir_filter_ccf(1, (1,)) + +################### CHANNEL MODEL ############################# + + phase_rotate = gr.multiply_const_cc(1-0.36j) + channel = gr.add_cc() + awgn = gr.noise_source_c(gr.GR_GAUSSIAN, 0.5) + fg.connect(awgn, (channel,1)) + +################### CHANNEL MODEL ############################# + + if use_agc: + agc = gr.agc_cc(1e-4, 1, 1) + else: + agc = gr.multiply_const_cc(1) + + # Downconverter + if use_sync_loop: + costas_alpha=0.005 + beta = costas_alpha*costas_alpha*0.25 + sync_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, 0) + else: + sync_loop = gr.multiply_const_cc(1) + + if use_rrc_rx: + rrc_taps_rx = gr.firdes.root_raised_cosine(1, spb, 1.0, \ + excess_bw, ntaps) + rrc_rx = gr.fir_filter_ccf(1, rrc_taps_rx) + else: + rrc_rx = gr.fir_filter_ccf(1, (1,)) + + # Sampler + if use_clock_sync: + mu = 0.05 + omega = spb + gain_mu = 0.05 + gain_omega = 0.25*gain_mu*gain_mu + omega_rel_limit = 0.5 + clock_sync = gr.clock_recovery_mm_cc(omega, gain_omega, mu, \ + gain_mu, omega_rel_limit) + #clock_sync.set_verbose(True); + else: + clock_sync = gr.fir_filter_ccf(1, (1,)) + + diff_phasor = gr.diff_phasor_cc() + slicer = gr.constellation_decoder_cb((constellation), (0,1,2,3)) + unpack = gr.unpack_k_bits_bb(k) + access = gr.correlate_access_code_bb(access_code,threshold) + + sink = gr.file_sink(gr.sizeof_char, 'output.dat') + + fg.connect(bytes_src, bytes2chunks, diffenc, chunks2symbols, rrc_tx) + fg.connect(rrc_tx, phase_rotate, channel, agc) + fg.connect(agc, sync_loop, rrc_rx, clock_sync, diff_phasor, slicer, sink) + + test = gr.file_sink(gr.sizeof_gr_complex, 'test.dat') + fg.connect(rrc_rx, test) + + fg.connect(chunks2symbols, gr.file_sink(gr.sizeof_gr_complex, 'rrc_tx.dat')) # into TX RRC + fg.connect(channel, gr.file_sink(gr.sizeof_gr_complex, 'channel.dat')) # Out of TX RRC + fg.connect(rrc_rx, gr.file_sink(gr.sizeof_gr_complex, 'rrc_rx.dat')) # Out of RX RRC -> clock_sync + fg.connect(clock_sync, gr.file_sink(gr.sizeof_gr_complex, 'clock_sync.dat')) # Out of M&M sync loop + fg.connect(bytes2chunks, gr.file_sink(gr.sizeof_char, 'source.dat')) + + fg.start() + fg.wait() + +if __name__ == "__main__": + main() + + + + diff --git a/gnuradio-examples/python/gmsk2/qpsk_usrp_tester.py b/gnuradio-examples/python/gmsk2/qpsk_usrp_tester.py new file mode 100644 index 00000000..bf7698a2 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/qpsk_usrp_tester.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python + +import random +from gnuradio import gr, gru, usrp + +default_access_code = '\xAC\xDD\xA4\xE2\xF2\x8C\x20\xFC' + +def string_to_1_0_list(s): + r = [] + for ch in s: + x = ord(ch) + for i in range(8): + t = (x >> i) & 0x1 + r.append(t) + + return r + +def to_1_0_string(L): + return ''.join(map(lambda x: chr(x + ord('0')), L)) + +code = string_to_1_0_list(default_access_code) + +access_code = to_1_0_string(code) + +def main(): + + fg = gr.flow_graph() + f_rf = 5e6 + fs = 400e3 + sr = 100e3 + alpha = 0.5 + M = 4 + k = int(gru.log2(M)) + + # Source + src = usrp.source_c () + adc_rate = src.adc_rate() + usrp_decim = int(adc_rate / fs) + src.set_decim_rate(usrp_decim) + + subdev_spec = usrp.pick_rx_subdevice(src) + subdev = usrp.selected_subdev(src, subdev_spec) + print "Using RX d'board %s" % (subdev.side_and_name(),) + src.set_mux(usrp.determine_rx_mux_value(src, subdev_spec)) + src.tune(0, subdev, f_rf) + + g = subdev.gain_range() + subdev.set_gain(g[1]) + subdev.set_auto_tr(True) + + print "USRP Decimation Rate = %d" % usrp_decim + print "RF Frequency = %d" % f_rf + + agc = gr.multiply_const_cc(0.0025) + + # Downconverter + costas_alpha=0.005 + beta = costas_alpha*costas_alpha*0.25 + sync_loop = gr.costas_loop_cc(costas_alpha, beta, 0.05, -0.05, 0) + + # Stage 2 +# fs2 = 200e3 +# D = int(fs / fs2) +# decimator = gr.keep_one_in_n(gr.sizeof_gr_complex, D) +# print "D = %d\nAfter decimator fs = %f" % (D, fs2) + + # Demodulator + taps = gr.firdes.root_raised_cosine(1, fs, sr, alpha, 45) + rrc = gr.fir_filter_ccf(1, taps) + + # Sampler + mu = 0.01 + omega = 4.3 + gain_mu = 0.05 + gain_omega = 0.25*gain_mu*gain_mu + omega_rel_limit = 0.5 + clock_sync = gr.clock_recovery_mm_cc(omega, gain_omega, mu, + gain_mu, omega_rel_limit) + clock_sync.set_verbose(False) + + diff_phasor = gr.diff_phasor_cc() + + threshold = 12 + constellation = (1+0j, 0+1j, -1+0j, 0-1j) + slicer = gr.constellation_decoder_cb((constellation), (0,1,2,3)) + unpack = gr.unpack_k_bits_bb(k) + access = gr.correlate_access_code_bb(access_code,threshold) + + test = gr.file_sink(gr.sizeof_gr_complex, 'test.dat') + sink = gr.file_sink(gr.sizeof_char, 'output.dat') + + fg.connect(src, agc, sync_loop, rrc, clock_sync) + fg.connect(clock_sync, diff_phasor, slicer, unpack, access, sink) + + fg.connect(slicer, gr.file_sink(gr.sizeof_char, 'chunks.dat')) + fg.connect(unpack, gr.file_sink(gr.sizeof_char, 'unpack.dat')) + fg.connect(clock_sync, gr.file_sink(gr.sizeof_gr_complex, 'phasor.dat')) + + fg.start() + fg.wait() + +if __name__ == "__main__": + main() diff --git a/gnuradio-examples/python/gmsk2/receive_path.py b/gnuradio-examples/python/gmsk2/receive_path.py new file mode 100644 index 00000000..505ff7c4 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/receive_path.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python +# +# 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. +# + +from gnuradio import gr, gru, blks +from gnuradio import usrp + +# from current dir +from pick_bitrate import pick_rx_bitrate + +# ///////////////////////////////////////////////////////////////////////////// +# receive path +# ///////////////////////////////////////////////////////////////////////////// + +class receive_path(gr.hier_block): + def __init__(self, fg, demod_class, rx_subdev_spec, + bitrate, decim, spb, + rx_callback, options, demod_kwargs): + + self.u = usrp.source_c (fusb_block_size=options.fusb_block_size, + fusb_nblocks=options.fusb_nblocks) + adc_rate = self.u.adc_rate() + + (self._bitrate, self._spb, self._decim) = \ + pick_rx_bitrate(bitrate, demod_class.bits_per_baud(), spb, decim, adc_rate) + + self.u.set_decim_rate(self._decim) + sw_decim = 1 + + if rx_subdev_spec is None: + rx_subdev_spec = usrp.pick_rx_subdevice(self.u) + self.subdev = usrp.selected_subdev(self.u, rx_subdev_spec) + print "Using RX d'board %s" % (self.subdev.side_and_name(),) + + self.u.set_mux(usrp.determine_rx_mux_value(self.u, rx_subdev_spec)) + + # Create filter to get actual channel we want + chan_coeffs = gr.firdes.low_pass (1.0, # gain + sw_decim * self._spb, # sampling rate + 1.0, # midpoint of trans. band + 0.1, # width of trans. band + gr.firdes.WIN_HANN) # filter type + + print "len(rx_chan_coeffs) =", len(chan_coeffs) + + # Decimating Channel filter + # complex in and out, float taps + self.chan_filt = gr.fft_filter_ccc(sw_decim, chan_coeffs) + #self.chan_filt = gr.fir_filter_ccf(sw_decim, chan_coeffs) + + # receiver + self.packet_receiver = \ + blks.demod_pkts(fg, + demod_class(fg, spb=self._spb, **demod_kwargs), + access_code=None, + callback=rx_callback, + threshold=-1) + + fg.connect(self.u, self.chan_filt, self.packet_receiver) + gr.hier_block.__init__(self, fg, None, None) + + g = self.subdev.gain_range() + #self.set_gain((g[0] + g[1])/2) # set gain to midpoint + self.set_gain(g[1]) # set gain to max + self.set_auto_tr(True) # enable Auto Transmit/Receive switching + + # Carrier Sensing Blocks + alpha = 0.001 + thresh = 30 # in dB, will have to adjust + self.probe = gr.probe_avg_mag_sqrd_c(thresh,alpha) + fg.connect(self.chan_filt, self.probe) + + def set_freq(self, target_freq): + """ + Set the center frequency we're interested in. + + @param target_freq: frequency in Hz + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital up converter. + """ + r = self.u.tune(0, self.subdev, target_freq) + if r: + return True + + return False + + def set_gain(self, gain): + if gain is None: + r = self.subdev.gain_range() + gain = (r[0] + r[1])/2 # set gain to midpoint + self.gain = gain + return self.subdev.set_gain(gain) + + def set_auto_tr(self, enable): + return self.subdev.set_auto_tr(enable) + + def bitrate(self): + return self._bitrate + + def spb(self): + return self._spb + + def decim(self): + return self._decim + + + def carrier_sensed(self): + """ + Return True if we think carrier is present. + """ + #return self.probe.level() > X + return self.probe.unmuted() + + def carrier_threshold(self): + """ + Return current setting in dB. + """ + return self.probe.threshold() + + def set_carrier_threshold(self, threshold_in_db): + """ + Set carrier threshold. + + @param threshold_in_db: set detection threshold + @type threshold_in_db: float (dB) + """ + self.probe.set_threshold(threshold_in_db) + diff --git a/gnuradio-examples/python/gmsk2/rx_voice.py b/gnuradio-examples/python/gmsk2/rx_voice.py new file mode 100755 index 00000000..3f5cc3b4 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/rx_voice.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 gnuradio import gr, gru, blks +from gnuradio import usrp +from gnuradio import audio +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +from gnuradio.vocoder import gsm_full_rate + +import random +import struct + +# from current dir +from receive_path import receive_path + +#import os +#print os.getpid() +#raw_input('Attach and press enter') + + +class audio_tx(gr.hier_block): + def __init__(self, fg): + self.packet_src = gr.message_source(33) + voice_decoder = gsm_full_rate.decode_ps() + s2f = gr.short_to_float () + sink_scale = gr.multiply_const_ff(1.0/32767.) + audio_sink = audio.sink(8000) + fg.connect(self.packet_src, voice_decoder, s2f, sink_scale, audio_sink) + gr.hier_block.__init__(self, fg, self.packet_src, audio_sink) + + def msgq(self): + return self.packet_src.msgq() + + +class my_graph(gr.flow_graph): + + def __init__(self, rx_subdev_spec, bitrate, decim_rate, spb, rx_callback, log): + gr.flow_graph.__init__(self) + self.rxpath = receive_path(self, rx_subdev_spec, bitrate, decim_rate, + spb, rx_callback, log) + + self.audio_tx = audio_tx(self) + + +# ///////////////////////////////////////////////////////////////////////////// +# main +# ///////////////////////////////////////////////////////////////////////////// + +global n_rcvd, n_right + +def main(): + global n_rcvd, n_right + + n_rcvd = 0 + n_right = 0 + + def rx_callback(ok, payload): + global n_rcvd, n_right + n_rcvd += 1 + if ok: + n_right += 1 + + fg.audio_tx.msgq().insert_tail(gr.message_from_string(payload)) + + print "ok = %r n_rcvd = %4d n_right = %4d" % ( + ok, n_rcvd, n_right) + + parser = OptionParser (option_class=eng_option) + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, + help="select USRP Rx side A or B") + parser.add_option("-f", "--freq", type="eng_float", default=423.1e6, + help="set Rx frequency to FREQ [default=%default]", metavar="FREQ") + parser.add_option("-r", "--bitrate", type="eng_float", default=100e3, + help="specify bitrate. spb and interp will be derived.") + parser.add_option("-S", "--spb", type="int", default=None, help="set samples/baud [default=%default]") + parser.add_option("-d", "--decim", type="intx", default=None, + help="set fpga decim rate to DECIM [default=%default]") + parser.add_option("-g", "--gain", type="eng_float", default=27, + help="set rx gain") + parser.add_option("","--log", action="store_true", default=False, + help="enable diagnostic logging") + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + if options.freq < 1e6: + options.freq *= 1e6 + + # build the graph + fg = my_graph(options.rx_subdev_spec, options.bitrate, + options.decim, options.spb, rx_callback, options.log) + + print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.rxpath.bitrate()),) + print "spb: %3d" % (fg.rxpath.spb(),) + print "decim: %3d" % (fg.rxpath.decim(),) + + fg.rxpath.set_freq(options.freq) + fg.rxpath.set_gain(options.gain) + print "Rx gain_range: ", fg.rxpath.subdev.gain_range(), " using", fg.rxpath.gain + + fg.start() # start flow graph + fg.wait() # wait for it to finish + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/gmsk2/transmit_path.py b/gnuradio-examples/python/gmsk2/transmit_path.py new file mode 100644 index 00000000..a1df1579 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/transmit_path.py @@ -0,0 +1,108 @@ +# +# 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. +# + +from gnuradio import gr, gru, blks +from gnuradio import usrp + +# from current dir +from pick_bitrate import pick_tx_bitrate + +# ///////////////////////////////////////////////////////////////////////////// +# transmit path +# ///////////////////////////////////////////////////////////////////////////// + +class transmit_path(gr.hier_block): + def __init__(self, fg, mod_class, tx_subdev_spec, + bitrate, interp, spb, gain, + options, mod_kwargs): + + self.normal_gain = gain + + self.u = usrp.sink_c (fusb_block_size=options.fusb_block_size, + fusb_nblocks=options.fusb_nblocks) + dac_rate = self.u.dac_rate(); + + print mod_class + print mod_class.bits_per_baud() + (self._bitrate, self._spb, self._interp) = \ + pick_tx_bitrate(bitrate, mod_class.bits_per_baud(), spb, interp, dac_rate) + + self.u.set_interp_rate(self._interp) + + # determine the daughterboard subdevice we're using + if tx_subdev_spec is None: + tx_subdev_spec = usrp.pick_tx_subdevice(self.u) + self.u.set_mux(usrp.determine_tx_mux_value(self.u, tx_subdev_spec)) + self.subdev = usrp.selected_subdev(self.u, tx_subdev_spec) + print "Using TX d'board %s" % (self.subdev.side_and_name(),) + + # transmitter + self.packet_transmitter = \ + blks.mod_pkts(fg, + mod_class(fg, spb=self._spb, **mod_kwargs), + access_code=None, + msgq_limit=4, + pad_for_usrp=True) + + self.amp = gr.multiply_const_cc (self.normal_gain) + + fg.connect(self.packet_transmitter, self.amp, self.u) + gr.hier_block.__init__(self, fg, None, None) + + self.set_gain(self.subdev.gain_range()[1]) # set max Tx gain + self.set_auto_tr(True) # enable Auto Transmit/Receive switching + + def set_freq(self, target_freq): + """ + Set the center frequency we're interested in. + + @param target_freq: frequency in Hz + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital up converter. + """ + r = self.u.tune(self.subdev._which, self.subdev, target_freq) + if r: + return True + + return False + + def set_gain(self, gain): + self.gain = gain + self.subdev.set_gain(gain) + + def set_auto_tr(self, enable): + return self.subdev.set_auto_tr(enable) + + def send_pkt(self, payload='', eof=False): + return self.packet_transmitter.send_pkt(payload, eof) + + def bitrate(self): + return self._bitrate + + def spb(self): + return self._spb + + def interp(self): + return self._interp diff --git a/gnuradio-examples/python/gmsk2/tunnel.py b/gnuradio-examples/python/gmsk2/tunnel.py new file mode 100755 index 00000000..bc10d3e3 --- /dev/null +++ b/gnuradio-examples/python/gmsk2/tunnel.py @@ -0,0 +1,300 @@ +#!/usr/bin/env python +# +# 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. +# + + +# ///////////////////////////////////////////////////////////////////////////// +# +# This code sets up up a virtual ethernet interface (typically gr0), +# and relays packets between the interface and the GNU Radio PHY+MAC +# +# What this means in plain language, is that if you've got a couple +# of USRPs on different machines, and if you run this code on those +# machines, you can talk between them using normal TCP/IP networking. +# +# ///////////////////////////////////////////////////////////////////////////// + + +from gnuradio import gr, gru, blks +from gnuradio import usrp +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +import random +import time +import struct +import sys +import os + +# from current dir +from transmit_path import transmit_path +from receive_path import receive_path +import fusb_options + +#print os.getpid() +#raw_input('Attach and press enter') + + +# ///////////////////////////////////////////////////////////////////////////// +# +# Use the Universal TUN/TAP device driver to move packets to/from kernel +# +# See /usr/src/linux/Documentation/networking/tuntap.txt +# +# ///////////////////////////////////////////////////////////////////////////// + +# Linux specific... +# TUNSETIFF ifr flags from + +IFF_TUN = 0x0001 # tunnel IP packets +IFF_TAP = 0x0002 # tunnel ethernet frames +IFF_NO_PI = 0x1000 # don't pass extra packet info +IFF_ONE_QUEUE = 0x2000 # beats me ;) + +def open_tun_interface(tun_device_filename): + from fcntl import ioctl + + mode = IFF_TAP | IFF_NO_PI + TUNSETIFF = 0x400454ca + + tun = os.open(tun_device_filename, os.O_RDWR) + ifs = ioctl(tun, TUNSETIFF, struct.pack("16sH", "gr%d", mode)) + ifname = ifs[:16].strip("\x00") + return (tun, ifname) + + +# ///////////////////////////////////////////////////////////////////////////// +# the flow graph +# ///////////////////////////////////////////////////////////////////////////// + +class my_graph(gr.flow_graph): + + def __init__(self, mod_class, demod_class, tx_subdev_spec, rx_subdev_spec, + bitrate, decim_rate, interp_rate, spb, + bt, rx_callback, options): + + gr.flow_graph.__init__(self) + self.txpath = transmit_path(self, mod_class, tx_subdev_spec, + bitrate, interp_rate, spb, + bt, options) + self.rxpath = receive_path(self, demod_class, rx_subdev_spec, + bitrate, decim_rate, spb, + rx_callback, options) + + def send_pkt(self, payload='', eof=False): + return self.txpath.send_pkt(payload, eof) + + def carrier_sensed(self): + """ + Return True if the receive path thinks there's carrier + """ + return self.rxpath.carrier_sensed() + + +# ///////////////////////////////////////////////////////////////////////////// +# Carrier Sense MAC +# ///////////////////////////////////////////////////////////////////////////// + +class cs_mac(object): + """ + Prototype carrier sense MAC + + Reads packets from the TUN/TAP interface, and sends them to the PHY. + Receives packets from the PHY via phy_rx_callback, and sends them + into the TUN/TAP interface. + + Of course, we're not restricted to getting packets via TUN/TAP, this + is just an example. + """ + def __init__(self, tun_fd, verbose=False): + self.tun_fd = tun_fd # file descriptor for TUN/TAP interface + self.verbose = verbose + self.fg = None # flow graph (access to PHY) + + def set_flow_graph(self, fg): + self.fg = fg + + def phy_rx_callback(self, ok, payload): + """ + Invoked by thread associated with PHY to pass received packet up. + + @param ok: bool indicating whether payload CRC was OK + @param payload: contents of the packet (string) + """ + if self.verbose: + print "Rx: ok = %r len(payload) = %4d" % (ok, len(payload)) + if ok: + os.write(self.tun_fd, payload) + + def main_loop(self): + """ + Main loop for MAC. + Only returns if we get an error reading from TUN. + + FIXME: may want to check for EINTR and EAGAIN and reissue read + """ + min_delay = 0.001 # seconds + + while 1: + payload = os.read(self.tun_fd, 10*1024) + if not payload: + self.fg.send_pkt(eof=True) + break + + if self.verbose: + print "Tx: len(payload) = %4d" % (len(payload),) + + delay = min_delay + while self.fg.carrier_sensed(): + sys.stderr.write('B') + time.sleep(delay) + if delay < 0.050: + delay = delay * 2 # exponential back-off + + self.fg.send_pkt(payload) + + +# ///////////////////////////////////////////////////////////////////////////// +# main +# ///////////////////////////////////////////////////////////////////////////// + +def main(): + + parser = OptionParser (option_class=eng_option) + parser.add_option("-f", "--freq", type="eng_float", default=423.1e6, + help="set Tx and Rx frequency to FREQ [default=%default]", metavar="FREQ") + parser.add_option("-r", "--bitrate", type="eng_float", default=None, + help="specify bitrate. spb and interp will be derived.") + parser.add_option("-g", "--rx-gain", type="eng_float", default=27, + help="set rx gain") + parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=None, + help="select USRP Tx side A or B") + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, + help="select USRP Rx side A or B") + parser.add_option("-S", "--spb", type="int", default=None, help="set samples/baud [default=%default]") + parser.add_option("-d", "--decim", type="intx", default=None, + help="set fpga decim rate to DECIM [default=%default]") + parser.add_option("-i", "--interp", type="intx", default=None, + help="set fpga interpolation rate to INTERP [default=%default]") + parser.add_option("-c", "--carrier-threshold", type="eng_float", default=30, + help="set carrier detect threshold (dB) [default=%default]") + parser.add_option("", "--bt", type="float", default=0.3, help="set bandwidth-time product [default=%default]") + parser.add_option("","--tun-device-filename", default="/dev/net/tun", + help="path to tun device file [default=%default]") + parser.add_option("-v","--verbose", action="store_true", default=False) + fusb_options.add_options(parser) + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + if options.freq < 1e6: + options.freq *= 1e6 + + # open the TUN/TAP interface + (tun_fd, tun_ifname) = open_tun_interface(options.tun_device_filename) + + # Attempt to enable realtime scheduling + r = gr.enable_realtime_scheduling() + if r == gr.RT_OK: + realtime = True + else: + realtime = False + print "Note: failed to enable realtime scheduling" + + + # If the user hasn't set the fusb_* parameters on the command line, + # pick some values that will reduce latency. + + if options.fusb_block_size == 0 and options.fusb_nblocks == 0: + if realtime: # be more aggressive + options.fusb_block_size = gr.prefs().get_long('fusb', 'rt_block_size', 1024) + options.fusb_nblocks = gr.prefs().get_long('fusb', 'rt_nblocks', 16) + else: + options.fusb_block_size = gr.prefs().get_long('fusb', 'block_size', 4096) + options.fusb_nblocks = gr.prefs().get_long('fusb', 'nblocks', 16) + + print "fusb_block_size =", options.fusb_block_size + print "fusb_nblocks =", options.fusb_nblocks + + # instantiate the MAC + mac = cs_mac(tun_fd, verbose=True) + + + # build the graph (PHY) + fg = my_graph(blks.gmsk2_mod, blks.gmsk2_demod, + options.tx_subdev_spec, options.rx_subdev_spec, + options.bitrate, options.decim, options.interp, + options.spb, options.bt, mac.phy_rx_callback, + options) + + mac.set_flow_graph(fg) # give the MAC a handle for the PHY + + if fg.txpath.bitrate() != fg.rxpath.bitrate(): + print "WARNING: Transmit bitrate = %sb/sec, Receive bitrate = %sb/sec" % ( + eng_notation.num_to_str(fg.txpath.bitrate()), + eng_notation.num_to_str(fg.rxpath.bitrate())) + + print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.txpath.bitrate()),) + print "spb: %3d" % (fg.txpath.spb(),) + print "interp: %3d" % (fg.txpath.interp(),) + + ok = fg.txpath.set_freq(options.freq) + if not ok: + print "Failed to set Tx frequency to %s" % (eng_notation.num_to_str(options.freq),) + raise SystemExit + + ok = fg.rxpath.set_freq(options.freq) + if not ok: + print "Failed to set Rx frequency to %s" % (eng_notation.num_to_str(options.freq),) + raise SystemExit + + fg.rxpath.set_gain(options.rx_gain) + print "Rx gain_range: ", fg.rxpath.subdev.gain_range(), " using", fg.rxpath.gain + + fg.rxpath.set_carrier_threshold(options.carrier_threshold) + print "Carrier sense threshold:", options.carrier_threshold, "dB" + + print + print "Allocated virtual ethernet interface: %s" % (tun_ifname,) + print "You must now use ifconfig to set its IP address. E.g.," + print + print " $ sudo ifconfig %s 10.10.10.1" % (tun_ifname,) + print + print "Be sure to use a different address in the same subnet for each machine." + print + + + fg.start() # Start executing the flow graph (runs in separate threads) + + mac.main_loop() # don't expect this to return... + + fg.stop() # but if it does, tell flow graph to stop. + fg.wait() # wait for it to finish + + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/gmsk2/tx_voice.py b/gnuradio-examples/python/gmsk2/tx_voice.py new file mode 100755 index 00000000..9e274e5e --- /dev/null +++ b/gnuradio-examples/python/gmsk2/tx_voice.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python +# +# Copyright 2005 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 gnuradio import gr, gru, blks +from gnuradio import usrp +from gnuradio import audio +from gnuradio import eng_notation +from gnuradio.eng_option import eng_option +from optparse import OptionParser + +from gnuradio.vocoder import gsm_full_rate + +import random +import time +import struct +import sys + +# from current dir +from transmit_path import transmit_path + +#import os +#print os.getpid() +#raw_input('Attach and press enter') + + +class my_graph(gr.flow_graph): + + def __init__(self, tx_subdev_spec, bitrate, interp_rate, spb, bt): + gr.flow_graph.__init__(self) + self.txpath = transmit_path(self, tx_subdev_spec, bitrate, interp_rate, spb, bt) + + audio_input = "" + sample_rate = 8000 + src = audio.source(sample_rate, audio_input) + src_scale = gr.multiply_const_ff(32767) + f2s = gr.float_to_short() + voice_coder = gsm_full_rate.encode_sp() + self.packets_from_encoder = gr.msg_queue() + packet_sink = gr.message_sink(33, self.packets_from_encoder, False) + self.connect(src, src_scale, f2s, voice_coder, packet_sink) + + + +# ///////////////////////////////////////////////////////////////////////////// +# main +# ///////////////////////////////////////////////////////////////////////////// + +def main(): + + def send_pkt(payload='', eof=False): + return fg.txpath.send_pkt(payload, eof) + + def rx_callback(ok, payload): + print "ok = %r, payload = '%s'" % (ok, payload) + + parser = OptionParser (option_class=eng_option) + parser.add_option("-T", "--tx-subdev-spec", type="subdev", default=None, + help="select USRP Tx side A or B") + parser.add_option("-f", "--freq", type="eng_float", default=423.1e6, + help="set Tx and Rx frequency to FREQ [default=%default]", metavar="FREQ") + parser.add_option("-r", "--bitrate", type="eng_float", default=100e3, + help="specify bitrate. spb and interp will be derived.") + parser.add_option("-S", "--spb", type="int", default=None, help="set samples/baud [default=%default]") + parser.add_option("-i", "--interp", type="intx", default=None, + help="set fpga interpolation rate to INTERP [default=%default]") + parser.add_option("-s", "--size", type="eng_float", default=1500, + help="set packet size [default=%default]") + parser.add_option("", "--bt", type="float", default=0.3, help="set bandwidth-time product [default=%default]") + parser.add_option("-M", "--megabytes", type="eng_float", default=1.0, + help="set megabytes to transmit [default=%default]") + parser.add_option("","--discontinuous", action="store_true", default=False, + help="enable discontinous transmission (bursts of 5 packets)") + (options, args) = parser.parse_args () + + if len(args) != 0: + parser.print_help() + sys.exit(1) + + if options.freq < 1e6: + options.freq *= 1e6 + + pkt_size = int(options.size) + + # build the graph + fg = my_graph(options.tx_subdev_spec, options.bitrate, options.interp, + options.spb, options.bt) + + print "bitrate: %sb/sec" % (eng_notation.num_to_str(fg.txpath.bitrate()),) + print "spb: %3d" % (fg.txpath.spb(),) + print "interp: %3d" % (fg.txpath.interp(),) + + fg.txpath.set_freq(options.freq) + + fg.start() # start flow graph + + # generate and send packets + nbytes = int(1e6 * options.megabytes) + n = 0 + pktno = 0 + + while n < nbytes: + packet = fg.packets_from_encoder.delete_head() + s = packet.to_string() + send_pkt(s) + n += len(s) + sys.stderr.write('.') + if options.discontinuous and pktno % 5 == 4: + time.sleep(1) + pktno += 1 + + send_pkt(eof=True) + fg.wait() # wait for it to finish + fg.txpath.set_auto_tr(False) + + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/mc4020/Makefile.am b/gnuradio-examples/python/mc4020/Makefile.am new file mode 100644 index 00000000..21bed3e4 --- /dev/null +++ b/gnuradio-examples/python/mc4020/Makefile.am @@ -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. +# + +EXTRA_DIST = \ + fm_demod.py \ + mc4020_fft.py + + + + diff --git a/gnuradio-examples/python/mc4020/fm_demod.py b/gnuradio-examples/python/mc4020/fm_demod.py new file mode 100755 index 00000000..e58407f7 --- /dev/null +++ b/gnuradio-examples/python/mc4020/fm_demod.py @@ -0,0 +1,150 @@ +#!/usr/bin/env python + +from gnuradio import gr +from gnuradio import audio +from gnuradio import mc4020 +import sys + +def high_speed_adc (fg, input_rate): + # return gr.file_source (gr.sizeof_short, "dummy.dat", False) + return mc4020.source (input_rate, mc4020.MCC_CH3_EN | mc4020.MCC_ALL_1V) + +# +# return a gr.flow_graph +# +def build_graph (freq1, freq2): + input_rate = 20e6 + cfir_decimation = 125 + audio_decimation = 5 + + quad_rate = input_rate / cfir_decimation + audio_rate = quad_rate / audio_decimation + + fg = gr.flow_graph () + + # use high speed ADC as input source + src = high_speed_adc (fg, input_rate) + + # compute FIR filter taps for channel selection + channel_coeffs = \ + gr.firdes.low_pass (1.0, # gain + input_rate, # sampling rate + 250e3, # low pass cutoff freq + 8*100e3, # width of trans. band + gr.firdes.WIN_HAMMING) + + # input: short; output: complex + chan_filter1 = \ + gr.freq_xlating_fir_filter_scf (cfir_decimation, + channel_coeffs, + freq1, # 1st station freq + input_rate) + + (head1, tail1) = build_pipeline (fg, quad_rate, audio_decimation) + + # sound card as final sink + audio_sink = audio.sink (int (audio_rate)) + + # now wire it all together + fg.connect (src, chan_filter1) + fg.connect (chan_filter1, head1) + fg.connect (tail1, (audio_sink, 0)) + + # two stations at once? + if freq2: + # Extract the second station and connect + # it to a second pipeline... + + # input: short; output: complex + chan_filter2 = \ + gr.freq_xlating_fir_filter_scf (cfir_decimation, + channel_coeffs, + freq2, # 2nd station freq + input_rate) + + (head2, tail2) = build_pipeline (fg, quad_rate, audio_decimation) + + fg.connect (src, chan_filter2) + fg.connect (chan_filter2, head2) + fg.connect (tail2, (audio_sink, 1)) + + return fg + +def build_pipeline (fg, quad_rate, audio_decimation): + '''Given a flow_graph, fg, construct a pipeline + for demodulating a broadcast FM signal. The + input is the downconverteed complex baseband + signal. The output is the demodulated audio. + + build_pipeline returns a two element tuple + containing the input and output endpoints. + ''' + fm_demod_gain = 2200.0/32768.0 + audio_rate = quad_rate / audio_decimation + volume = 1.0 + + # input: complex; output: float + fm_demod = gr.quadrature_demod_cf (volume*fm_demod_gain) + + # compute FIR filter taps for audio filter + width_of_transition_band = audio_rate / 32 + audio_coeffs = gr.firdes.low_pass (1.0, # gain + quad_rate, # sampling rate + audio_rate/2 - width_of_transition_band, + width_of_transition_band, + gr.firdes.WIN_HAMMING) + + # input: float; output: float + audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs) + + fg.connect (fm_demod, audio_filter) + return ((fm_demod, 0), (audio_filter, 0)) + + +def main (args): + nargs = len (args) + if nargs == 1: + freq1 = float (args[0]) * 1e6 + freq2 = None + elif nargs == 2: + freq1 = float (args[0]) * 1e6 + freq2 = float (args[1]) * 1e6 + else: + sys.stderr.write ('usage: fm_demod freq1 [freq2]\n') + sys.exit (1) + + # connect to RF front end + rf_front_end = gr.microtune_4937_eval_board () + if not rf_front_end.board_present_p (): + raise IOError, 'RF front end not found' + + # set front end gain + rf_front_end.set_AGC (300) + IF_freq = rf_front_end.get_output_freq () + IF_freq = 5.75e6 + + if not freq2: # one station + + rf_front_end.set_RF_freq (freq1) + fg = build_graph (IF_freq, None) + + else: # two stations + + if abs (freq1 - freq2) > 5.5e6: + raise IOError, 'freqs too far apart' + + target_freq = (freq1 + freq2) / 2 + actual_freq = rf_front_end.set_RF_freq (target_freq) + #actual_freq = target_freq + + fg = build_graph (IF_freq + freq1 - actual_freq, + IF_freq + freq2 - actual_freq) + + fg.start () # fork thread(s) and return + raw_input ('Press Enter to quit: ') + fg.stop () + +if __name__ == '__main__': + main (sys.argv[1:]) + + diff --git a/gnuradio-examples/python/mc4020/mc4020_fft.py b/gnuradio-examples/python/mc4020/mc4020_fft.py new file mode 100755 index 00000000..3348ad4f --- /dev/null +++ b/gnuradio-examples/python/mc4020/mc4020_fft.py @@ -0,0 +1,53 @@ +#!/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 gnuradio import gr +from gnuradio import mc4020 +from gnuradio.eng_option import eng_option +from gnuradio.wxgui import stdgui, fftsink +from optparse import OptionParser +import wx + +class app_flow_graph (stdgui.gui_flow_graph): + def __init__(self, frame, panel, vbox, argv): + stdgui.gui_flow_graph.__init__ (self, frame, panel, vbox, argv) + + + parser = OptionParser (option_class=eng_option) + (options, args) = parser.parse_args () + + input_rate = 20e6 + src = mc4020.source (input_rate, mc4020.MCC_CH3_EN | mc4020.MCC_ALL_1V) + cvt = gr.short_to_float () + block, fft_win = fftsink.make_fft_sink_f (self, panel, "Rx Data", 512, input_rate) + + self.connect (src, cvt) + self.connect (cvt, block) + vbox.Add (fft_win, 1, wx.EXPAND) + + +def main (): + app = stdgui.stdapp (app_flow_graph, "USRP FFT") + app.MainLoop () + +if __name__ == '__main__': + main () diff --git a/gnuradio-examples/python/multi-antenna/multi_fft.py b/gnuradio-examples/python/multi-antenna/multi_fft.py new file mode 100755 index 00000000..ca9c614a --- /dev/null +++ b/gnuradio-examples/python/multi-antenna/multi_fft.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python + +from gnuradio import gr, gru, eng_notation +from gnuradio import usrp +from gnuradio.eng_option import eng_option +from gnuradio import eng_notation +from gnuradio import optfir +from optparse import OptionParser +from gnuradio.wxgui import stdgui, fftsink, waterfallsink, scopesink, form, slider +import wx +import usrp_dbid +import time +import os.path +import sys + +# required FPGA that can do 4 rx channels. + + +class my_graph(stdgui.gui_flow_graph): + + def __init__(self, frame, panel, vbox, argv): + stdgui.gui_flow_graph.__init__(self) + + self.frame = frame + self.panel = panel + + parser = OptionParser (option_class=eng_option) + #parser.add_option("-S", "--subdev", type="subdev", default=(0, None), + # help="select USRP Rx side A or B (default=A)") + parser.add_option("-d", "--decim", type="int", default=128, + help="set fgpa decimation rate to DECIM [default=%default]") + parser.add_option("-f", "--freq", type="eng_float", default=146.585e6, + help="set frequency to FREQ [default=%default])", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=20, + help="set gain in dB [default=%default]") + parser.add_option("-F", "--filter", action="store_true", default=True, + help="Enable channel filter") + (options, args) = parser.parse_args() + + if len(args) != 0: + parser.print_help() + raise SystemExit + + nchan = 4 + + if options.filter: + sw_decim = 4 + else: + sw_decim = 1 + + self.u = usrp.source_c(0, options.decim, fpga_filename="std_4rx_0tx.rbf") + if self.u.nddc() < nchan: + sys.stderr.write('This code requires an FPGA build with %d DDCs. This FPGA has only %d.\n' % ( + nchan, self.u.nddc())) + raise SystemExit + + if not self.u.set_nchannels(nchan): + sys.stderr.write('set_nchannels(%d) failed\n' % (nchan,)) + raise SystemExit + + input_rate = self.u.adc_freq() / self.u.decim_rate() + print "USB data rate = %s" % (eng_notation.num_to_str(input_rate),) + print "Scope data rate = %s" % (eng_notation.num_to_str(input_rate/sw_decim),) + + self.subdev = self.u.db[0] + self.u.db[1] + + if (len (self.subdev) != 4 or + self.u.db[0][0].dbid() != usrp_dbid.BASIC_RX or + self.u.db[1][0].dbid() != usrp_dbid.BASIC_RX): + sys.stderr.write('This code requires a Basic Rx board on Sides A & B\n') + sys.exit(1) + + self.u.set_mux(gru.hexint(0xf3f2f1f0)) + + # deinterleave four channels from FPGA + di = gr.deinterleave(gr.sizeof_gr_complex) + + self.connect(self.u, di) + + + + # taps for channel filter + chan_filt_coeffs = optfir.low_pass (1, # gain + input_rate, # sampling rate + 80e3, # passband cutoff + 115e3, # stopband cutoff + 0.1, # passband ripple + 60) # stopband attenuation + #print len(chan_filt_coeffs) + + for i in range(nchan): + scope = fftsink.fft_sink_c(self, panel, sample_rate=input_rate/sw_decim, + title="Input %d" % (i,), + ref_level=80, y_per_div=20) + vbox.Add(scope.win, 10, wx.EXPAND) + + if options.filter: + chan_filt = gr.fir_filter_ccf(sw_decim, chan_filt_coeffs) + self.connect((di, i), chan_filt, scope) + else: + self.connect((di, i), scope) + + + self.set_gain(options.gain) + self.set_freq(options.freq) + + def set_gain(self, gain): + for i in range(len(self.subdev)): + self.subdev[i].set_gain(gain) + + def set_freq(self, target_freq): + ok = True + for i in range(len(self.subdev)): + r = usrp.tune(self.u, i, self.subdev[i], target_freq) + if not r: + ok = False + print "set_freq: failed to set subdev[%d] freq to %f" % ( + i, target_freq) + + return ok + + +def main (): + app = stdgui.stdapp(my_graph, "Multi Scope", nstatus=1) + app.MainLoop() + +if __name__ == '__main__': + main () diff --git a/gnuradio-examples/python/multi-antenna/multi_file.py b/gnuradio-examples/python/multi-antenna/multi_file.py new file mode 100755 index 00000000..e2a6e04f --- /dev/null +++ b/gnuradio-examples/python/multi-antenna/multi_file.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python + +from gnuradio import gr, gru, eng_notation +from gnuradio import usrp +from gnuradio.eng_option import eng_option +from gnuradio import eng_notation +from gnuradio import optfir +from optparse import OptionParser +from gnuradio.wxgui import stdgui, fftsink, waterfallsink, scopesink, form, slider +import wx +import usrp_dbid +import time +import os.path +import sys + +# required FPGA that can do 4 rx channels. + + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + parser = OptionParser (option_class=eng_option) + #parser.add_option("-S", "--subdev", type="subdev", default=(0, None), + # help="select USRP Rx side A or B (default=A)") + parser.add_option("-d", "--decim", type="int", default=128, + help="set fgpa decimation rate to DECIM [default=%default]") + parser.add_option("-f", "--freq", type="eng_float", default=146.585e6, + help="set frequency to FREQ [default=%default])", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=20, + help="set gain in dB [default=%default]") + parser.add_option("-F", "--filter", action="store_true", default=True, + help="Enable channel filter") + parser.add_option("-o", "--output", type="string", default=None, + help="set output basename") + (options, args) = parser.parse_args() + + if len(args) != 0: + parser.print_help() + raise SystemExit + + if options.output is None: + parser.print_help() + sys.stderr.write("You must provide an output filename base with -o OUTPUT\n") + raise SystemExit + else: + basename = options.output + + nchan = 4 + nsecs = 4.0 + + if options.filter: + sw_decim = 4 + else: + sw_decim = 1 + + self.u = usrp.source_c(0, options.decim, fpga_filename="std_4rx_0tx.rbf") + if self.u.nddc() < nchan: + sys.stderr.write('This code requires an FPGA build with %d DDCs. This FPGA has only %d.\n' % ( + nchan, self.u.nddc())) + raise SystemExit + + if not self.u.set_nchannels(nchan): + sys.stderr.write('set_nchannels(%d) failed\n' % (nchan,)) + raise SystemExit + + input_rate = self.u.adc_freq() / self.u.decim_rate() + print "USB data rate = %s" % (eng_notation.num_to_str(input_rate),) + sink_data_rate = input_rate/sw_decim + print "Scope data rate = %s" % (eng_notation.num_to_str(sink_data_rate),) + + self.subdev = self.u.db[0] + self.u.db[1] + + if (len(self.subdev) != 4 or + self.u.db[0][0].dbid() != usrp_dbid.BASIC_RX or + self.u.db[1][0].dbid() != usrp_dbid.BASIC_RX): + sys.stderr.write('This code requires a Basic Rx board on Sides A & B\n') + sys.exit(1) + + self.u.set_mux(gru.hexint(0xf3f2f1f0)) + + # collect 1 second worth of data + limit = int(nsecs * input_rate * nchan) + print "limit = ", limit + head = gr.head(gr.sizeof_gr_complex, limit) + + # deinterleave four channels from FPGA + di = gr.deinterleave(gr.sizeof_gr_complex) + + self.connect(self.u, head, di) + + # taps for channel filter + chan_filt_coeffs = optfir.low_pass (1, # gain + input_rate, # sampling rate + 80e3, # passband cutoff + 115e3, # stopband cutoff + 0.1, # passband ripple + 60) # stopband attenuation + #print len(chan_filt_coeffs) + + for i in range(nchan): + + sink = gr.file_sink(gr.sizeof_gr_complex, + basename + ("-%s-%d.dat" % (eng_notation.num_to_str(sink_data_rate), i))) + if options.filter: + chan_filt = gr.fir_filter_ccf(sw_decim, chan_filt_coeffs) + self.connect((di, i), chan_filt, sink) + else: + self.connect((di, i), sink) + + + self.set_gain(options.gain) + self.set_freq(options.freq) + + def set_gain(self, gain): + for i in range(len(self.subdev)): + self.subdev[i].set_gain(gain) + + def set_freq(self, target_freq): + ok = True + for i in range(len(self.subdev)): + r = usrp.tune(self.u, i, self.subdev[i], target_freq) + if not r: + ok = False + print "set_freq: failed to set subdev[%d] freq to %f" % ( + i, target_freq) + + return ok + + +def main (): + my_graph().run() + +if __name__ == '__main__': + main () diff --git a/gnuradio-examples/python/multi-antenna/multi_scope.py b/gnuradio-examples/python/multi-antenna/multi_scope.py new file mode 100755 index 00000000..43aa77b0 --- /dev/null +++ b/gnuradio-examples/python/multi-antenna/multi_scope.py @@ -0,0 +1,138 @@ +#!/usr/bin/env python + +from gnuradio import gr, gru, eng_notation +from gnuradio import usrp +from gnuradio.eng_option import eng_option +from gnuradio import eng_notation +from gnuradio import optfir +from optparse import OptionParser +from gnuradio.wxgui import stdgui, fftsink, waterfallsink, scopesink, form, slider +import wx +import usrp_dbid +import time +import os.path +import sys + +# required FPGA that can do 4 rx channels. + + +class my_graph(stdgui.gui_flow_graph): + + def __init__(self, frame, panel, vbox, argv): + stdgui.gui_flow_graph.__init__(self) + + self.frame = frame + self.panel = panel + + parser = OptionParser (option_class=eng_option) + #parser.add_option("-S", "--subdev", type="subdev", default=(0, None), + # help="select USRP Rx side A or B (default=A)") + parser.add_option("-d", "--decim", type="int", default=128, + help="set fgpa decimation rate to DECIM [default=%default]") + parser.add_option("-f", "--freq", type="eng_float", default=146.585e6, + help="set frequency to FREQ [default=%default])", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=20, + help="set gain in dB [default=%default]") + parser.add_option("-F", "--filter", action="store_true", default=True, + help="Enable channel filter") + (options, args) = parser.parse_args() + + if len(args) != 0: + parser.print_help() + raise SystemExit + + nchan = 4 + + if options.filter: + sw_decim = 4 + else: + sw_decim = 1 + + self.u = usrp.source_c(0, options.decim, fpga_filename="std_4rx_0tx.rbf") + if self.u.nddc() < nchan: + sys.stderr.write('This code requires an FPGA build with %d DDCs. This FPGA has only %d.\n' % ( + nchan, self.u.nddc())) + raise SystemExit + + if not self.u.set_nchannels(nchan): + sys.stderr.write('set_nchannels(%d) failed\n' % (nchan,)) + raise SystemExit + + input_rate = self.u.adc_freq() / self.u.decim_rate() + print "USB data rate = %s" % (eng_notation.num_to_str(input_rate),) + print "Scope data rate = %s" % (eng_notation.num_to_str(input_rate/sw_decim),) + + self.subdev = self.u.db[0] + self.u.db[1] + + if (len(self.subdev) != 4 or + self.u.db[0][0].dbid() != usrp_dbid.BASIC_RX or + self.u.db[1][0].dbid() != usrp_dbid.BASIC_RX): + sys.stderr.write('This code requires a Basic Rx board on Sides A & B\n') + sys.exit(1) + + self.u.set_mux(gru.hexint(0xf3f2f1f0)) + + # deinterleave four channels from FPGA + di = gr.deinterleave(gr.sizeof_gr_complex) + + self.connect(self.u, di) + + # our destination (8 float inputs) + self.scope = scopesink.scope_sink_f(self, panel, sample_rate=input_rate/sw_decim) + + # taps for channel filter + chan_filt_coeffs = optfir.low_pass (1, # gain + input_rate, # sampling rate + 80e3, # passband cutoff + 115e3, # stopband cutoff + 0.1, # passband ripple + 60) # stopband attenuation + #print len(chan_filt_coeffs) + + # bust the deinterleaved complex channels into floats + for i in range(nchan): + + if options.filter: + chan_filt = gr.fir_filter_ccf(sw_decim, chan_filt_coeffs) + c2f = gr.complex_to_float() + self.connect((di, i), chan_filt, c2f) + else: + c2f = gr.complex_to_float() + self.connect((di, i), c2f) + + self.connect((c2f, 0), (self.scope, 2*i + 0)) + self.connect((c2f, 1), (self.scope, 2*i + 1)) + + + self._build_gui(vbox) + + self.set_gain(options.gain) + self.set_freq(options.freq) + + def set_gain(self, gain): + for i in range(len(self.subdev)): + self.subdev[i].set_gain(gain) + + def set_freq(self, target_freq): + ok = True + for i in range(len(self.subdev)): + r = usrp.tune(self.u, i, self.subdev[i], target_freq) + if not r: + ok = False + print "set_freq: failed to set subdev[%d] freq to %f" % ( + i, target_freq) + + return ok + + + def _build_gui(self, vbox): + vbox.Add(self.scope.win, 10, wx.EXPAND) + + + +def main (): + app = stdgui.stdapp(my_graph, "Multi Scope", nstatus=1) + app.MainLoop() + +if __name__ == '__main__': + main () diff --git a/gnuradio-examples/python/multi_usrp/Makefile.am b/gnuradio-examples/python/multi_usrp/Makefile.am new file mode 100644 index 00000000..c2c6a294 --- /dev/null +++ b/gnuradio-examples/python/multi_usrp/Makefile.am @@ -0,0 +1,28 @@ +# +# 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. +# + +EXTRA_DIST = \ + README \ + multi_usrp_oscope.py \ + multi_usrp_rx_cfile.py + + + diff --git a/gnuradio-examples/python/multi_usrp/README b/gnuradio-examples/python/multi_usrp/README new file mode 100644 index 00000000..c93d7736 --- /dev/null +++ b/gnuradio-examples/python/multi_usrp/README @@ -0,0 +1,260 @@ +Quick start multi-usrp: + +Unpack, build and install usrp, gnuradio-core and gr-usrp +Versions need to be more recent then 2.7cvs/svn 11 may 2006 + +Make sure usrp/fpga/rbf/rev2/multi*.rbf is installed in /usr/local/share/usrp/rev2/ +Make sure usrp/fpga/rbf/rev4/multi*.rbf is installed in /usr/local/share/usrp/rev4/ +(If in doubt, copy manually) + +build and install gr-wxgui gr-audio-xxx and so on. + +unpack gnuradio-examples. + +There is a gnuradio-examples/python/multi_usrp directory which contains examples + + +Put at least a basic RX or dbsrx board in RXA of the master and RXA of the slave board. +Make sure that the usrps have a serial or unique identifier programmed in their eeprom. +(All new rev 4.1 boards have this) +You can do without a serial but then you never know which usrp is the master and which is the slave. + + +CONNECTING THE CABLES +Now connect the 64MHz clocks between the boards with a short sma coax cable. +(See the wiki on how to enable clock-out and clock-in +http://comsec.com/wiki?USRPClockingNotes ) + +You need one board with a clock out and one board with a clock in. + +You can choose any of the two boards as master or slave, this is not dependant on which board has the clock-out or in. +In my experiments I had fewer problems when the board that has the clock-in will be the master board. + +You can use a standard 16-pole flatcable to connect tvrx, basic-rx or dbsrx boards. +Of this 16pin flatcable only two pins are used (io15 and ground) +For all new daughterboards which use up a lot of io pins you have to use a cable with fewer connections. +The savest is using a 2pin headercable connected to io15,gnd (a cable like the ones used to connect frontpanel leds to the mainboard of a PC) + +If using basic rx board: + Connect a 16-pole flatcable from J25 on basicrx/dbs_rx in rxa of the master usrp to J25 on basicrx/dbsrx in RXA of the slave usrp + Don't twist the cable (Make sure the pin1 marker (red line on the flatcable) is on the same side of the connector (at io-8 on the master and at io8 on the slave.)) + For basic_rx this means the marker should be on the side of the dboard with the sma connectors. + For dbs_rx this means the marker should be on the side of the dboard with the two little chips. + In other words, don't twist the cable, you will burn your board if you do. + +You can also connect a flatcable with multiple connectors from master-J25 to slave1-J25 to slave2-J25 to ... +You will however have to think of something to create a common 64Mhz clock for more then two usrps. + +For all other daughterboards, connect a 2wire cable from masterRXA J25 io15,gnd to slaveRXA J25 io15,gnd + + +So now the hardware is setup, software is setup. Lets do some tests. + +Connect power to both usrps. +unpack the gnuradio_examples somewhere (cvs version later then 11 may 2006) +go to the gnuradio-examples/python/multi_usrp folder. + +Now run + ./multi_usrp_oscope.py -x 12345678 + +It should tell you that usrp 12345678 is not found and tell you which serials are available. + +Now run ./multi_usrp_oscope.py -x actualserialnum +You should now get an oscope with two channels, one is from the master and one is from the slave +It will which show the I-signal from channel 0 of the master usrp and I-signal from channel 0 of the slave usrp. +(For testing connect the same signal source to the inputs of both boards) +The signals should be aligned. +If you click the sync button, it will resync the master and slave (should never be needed) + +Now run +./multi_usrp_oscope.py --help +To see all available options. + + +Now you are ready to do phase-locked aligned signal processing. + +You can also capture to file with: +./multi_usrp_rx_cfile.py + +run ./multi_usrp_rx_cfile.py --help to see all available options. + + + +Here follows a description of the detail blocks used in usrp_multi.py + +Multi usrp + +With this code you can connect two or more usrps (with a locked clock) and get synchronised samples. +You must connect a (flat)cable between a dboard on the master in RXA and a dboard on the slave in RXA. +You then put one usrp in master mode, put the other in slave mode. + +The easiest thing to see how this works is just looking at the code in + multi_usrp_oscope.py + multi_usrp_rx_cfile.py + +Use the usrp_multi block which is installed by gr-usrp. +instantiate in the following way: + + self.multi=usrp_multi.multi_source_align( fg=self, master_serialno=options.master_serialno, decim=options.decim, nchan=options.nchan ) + +nchan should be 2 or 4. + +You determine which is the master by master_serialno (this is a text string a hexadecimal number). +If you enter a serial number which is not found it will print the serial numbers which are available. +If you give no serial number (master_serialno=None), the code will pick a Master for you. + +You can get a reference to the master and the slave usrp in the following way: + + self.um=self.multi.get_master_usrp() + self.us=self.multi.get_slave_usrp() + +You only need these references for setting freqs/gains or getting info about daughterboards. +Don't use the output directly but use the aligned output from multi.get_master_source_c() and multi.get_slave_source_c() + +You get references to the aligned output samples in the following way: +aligned_master_source_c=self.multi.get_master_source_c() +aligned_slave_source_c=self.multi.get_slave_source_c() + +These blocks have multiple outputs. +output 0 is the sample counter (high bits in I, low bits in Q) +You normally don't need the samplecounters so you can ignore output 0 + +output 1 is the first aligend output channel (if you enable 2 or 4 channels) +output 2 is the second output channel (only if you enable 4 channels) + +so the usefull 4 channels are: +self.aligned_master_chan1=(self.multi.get_master_source_c(),1) +self.aligned_master_chan2=(self.multi.get_master_source_c(),2) +self.aligned_slave_chan1=(self.multi.get_slave_source_c(),1) +self.aligned_slave_chan2=(self.multi.get_slave_source_c(),2) + +The two samplecounters are: +self.aligned_master_samplecounter=(self.multi.get_master_source_c(),0) +self.aligned_slave_samplecounter=(self.multi.get_slave_source_c(),0) + +You can set the gain or tune the frequency for all 4 receive daughetrboards at once: + self.multi.set_gain_all_rx(options.gain) + result,r1,r2,r3,r4 = self.multi.tune_all_rx(options.freq) + +This will only work reliably when you have all the same daughterboards. +Otherwise set all freqs and gains individually. + +You must call self.multi.sync() at least once AFTER the flowgraph has started running. +(This will synchronise the streams of the two usrps) + +This work was funded by Toby Oliver at Sensus Analytics / Path Intelligence. +Many Thanks for making this possible. + +It was written by Martin Dudok van Heel at Olifantasia. + + + +Here follows a brief of the new blocks and (changes)functionality written for multi-usrp support. + +You can also look at the generated documentation in +/usr/local/share/doc/gnuradio-core-X.X +/usr/local/share/doc/usrp-X.X +(Make sure to build and install the documentation, go to the doc directory of the sourcetree and issue make doc; make install) + + +gnuradio-examples: +new/changed files: +multi_usrp/multi_usrp_oscope.py +multi_usrp/multi_usrp_rx_cfile.py + + +gnuradio-core: +gr.align_on_samplenumbers_ss (int nchan,int align_interval) + +align several complex short (interleaved short) input channels with corresponding unsigned 32 bit sample_counters (provided as interleaved 16 bit values) + +Parameters: + nchan number of complex_short input channels (including the 32 bit counting channel) + align_interval interval at which the samples are aligned, ignored for now. + +Pay attention on how you connect this block It expects a minimum of 2 usrp_source_s with nchan number of channels and as mode usrp_prims.bmFR_MODE_RX_COUNTING_32BIT enabled. This means that the first complex_short channel is an interleaved 32 bit counter. The samples are aligned by dropping samples untill the samplenumbers match. + +files: +gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.cc +gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.h +gnuradio-core/src/lib/general/gr_align_on_samplenumbers_ss.i + + +gr-usrp + added _write_fpga_reg_masked + added usrp_multi.py + new usrp_multi block which can instantiate two linked usrps as master and slave and alignes their output. + It has a sync() function which should be called AFTER the flowgraph has started running. + bool sync(); + \brief Call this on a master usrp to sync master and slave by outputing a sync pulse on rx_a_io[15]. + The 32 bit samplecounter of master and slave will be reset to zero and all phase and buffer related things in the usrps are reset. + Call this only after the flowgraph has been started, otherwise there will be no effect since everything is kept in reset state as long as the flowgraph is not running. + \returns true if successfull. + +files: +configure.ac +src/Makefile.am +src/usrp1.i +src/usrp1_source_base.cc +src/usrp1_source_base.h +src/usrp_multi.py + +usrp-0.11cvsmulti: +usrp: + new constant bmFR_MODE_RX_COUNTING_32BIT (could also be added as extra mode like FPGA_MODE_COUNTING_32BIT) + Use this for the mode parameter when creating a usrp when you want to use the master/slave setup or if you want to use the 32 bit counter for other things, like testing with gr.check_counting_s(True) + + added register FR_RX_MASTER_SLAVE + added bitno and bitmaskes: + bmFR_MODE_RX_COUNTING_32BIT + + bitnoFR_RX_SYNC + bitnoFR_RX_SYNC_MASTER + bitnoFR_RX_SYNC_SLAVE + + bitnoFR_RX_SYNC_INPUT_IOPIN 15 + bmFR_RX_SYNC_INPUT_IOPIN (1<= 0: # dbid is < 0 if there's no d'board or a problem + return (0, 0) + if u.db[1][0].dbid() >= 0: + return (1, 0) + return (0, 0) + + +class app_flow_graph(stdgui.gui_flow_graph): + def __init__(self, frame, panel, vbox, argv): + stdgui.gui_flow_graph.__init__(self) + + self.frame = frame + self.panel = panel + + parser = OptionParser(option_class=eng_option) + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None, + help="select USRP Rx side A or B (default=first one with a daughterboard)") + parser.add_option("-d", "--decim", type="int", default=128, + help="set fgpa decimation rate to DECIM [default=%default]") + parser.add_option("-f", "--freq", type="eng_float", default=None, + help="set frequency to FREQ", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=None, + help="set gain in dB (default is midpoint)") + #align interval is default not yet enabled in gr.align_on_samplenumbers_ss + #parser.add_option("-a", "--align_interval", type="int", default=-1, + # help="Align master and slave every so much samples.") + + # width 8 does not work yet with multi_usrp because it interferes with the 32 bit samplecounter + #parser.add_option("-8", "--width-8", action="store_true", default=False, + # help="Enable 8-bit samples across USB") + parser.add_option("-m", "--mux", type="intx", default=None, + help="set fpga FR_RX_MUX register to MUX") + parser.add_option("-n", "--frame-decim", type="int", default=1, + help="set oscope frame decimation factor to n [default=1]") + parser.add_option("-N", "--nchan", type="int", default=2, + help="set nchannels to NCHAN") + parser.add_option("-q", "--show-q", action="store_true", default=False, + help="show the q value of the complex samples") + parser.add_option("-s", "--show-counters", action="store_true", default=False, + help="show the counters") + parser.add_option("-v", "--v-scale", type="eng_float", default=1000, + help="set oscope initial V/div to SCALE [default=%default]") + parser.add_option("-t", "--t-scale", type="eng_float", default=49e-6, + help="set oscope initial s/div to SCALE [default=50us]") + parser.add_option("-x", "--master-serialno", type="string", default=None, + help="Serial_no of the usrp which should be the MASTER (default= select any)") + (options, args) = parser.parse_args() + if len(args) != 0: + parser.print_help() + sys.exit(1) + + self.show_debug_info = True + + # build the graph + + #self.u = usrp.source_c(which=options.which_usrp,decim_rate=options.decim) + if (options.mux is None) | (4==options.nchan): + init_mux=None #use default mux which is 0x10321032 + else: + init_mux=options.mux + + init_gain=0.0 + init_freq=0.0 + init_align_interval=-1 + + self.multi=usrp_multi.multi_source_align( self, options.master_serialno, options.decim, + options.nchan, init_gain, init_freq, init_mux, init_align_interval) + self.um=self.multi.get_master_usrp() + self.us=self.multi.get_slave_usrp() + + if options.rx_subdev_spec is None: + options.rx_subdev_spec = pick_subdevice(self.um) + if (options.mux==None) and (options.nchan!=4): + mux=usrp.determine_rx_mux_value(self.um, options.rx_subdev_spec) + mux= (mux<<8 & 0xffffffff) | (mux & 0xff) + self.um.set_mux(mux) + self.us.set_mux(mux) + + # width 8 does not work yet with multi_usrp because it interferes with the 32 bit samplecounter + #if options.width_8: + # width = 8 + # shift = 8 + # format = self.um.make_format(width, shift) + # r = self.um.set_format(format) + # r = self.us.set_format(format) + + # determine the daughterboard subdevice of the first channel we're using + self.subdevm = usrp.selected_subdev(self.um, options.rx_subdev_spec) + self.subdevs = usrp.selected_subdev(self.us, options.rx_subdev_spec) + + input_rate = self.um.adc_freq() / self.um.decim_rate() + + self.scope = scopesink.scope_sink_f(self, panel, sample_rate=input_rate, + frame_decim=options.frame_decim, + v_scale=options.v_scale, + t_scale=options.t_scale) + self.sink_count=0 + self.add_to_scope((self.multi.get_master_source_c(),1),options.show_q) + self.add_to_scope((self.multi.get_slave_source_c(),1),options.show_q) + if 4==options.nchan: + self.add_to_scope((self.multi.get_master_source_c(),2),options.show_q) + self.add_to_scope((self.multi.get_slave_source_c(),2),options.show_q) + + if options.show_counters: + self.add_to_scope((self.multi.get_master_source_c(),0),options.show_q) + self.add_to_scope((self.multi.get_slave_source_c(),0),options.show_q) + + self._build_gui(vbox) + + # set initial values + + if options.gain is None: + # if no gain was specified, use the mid-point in dB + g = self.subdevm.gain_range() + options.gain = float(g[0]+g[1])/2 + + if options.freq is None: + # if no freq was specified, use the mid-point + r = self.subdevm.freq_range() + options.freq = float(r[0]+r[1])/2 + + self.set_gain(options.gain) + + if self.show_debug_info: + self.myform['decim'].set_value(self.um.decim_rate()) + self.myform['fs@usb'].set_value(self.um.adc_freq() / self.um.decim_rate()) + self.myform['dbname'].set_value(self.subdevm.name()) + self.myform['baseband'].set_value(0) + self.myform['ddc'].set_value(0) + + if not(self.set_freq(options.freq)): + self._set_status_msg("Failed to set initial frequency") + + self.multi.print_db_info() + self.unsynced=True + frame.Bind(wx.EVT_IDLE, self.onIdle) + + def add_to_scope(self,source_c,show_q): + c2f= gr.complex_to_float () + self.connect(source_c, c2f) + self.connect((c2f,0), (self.scope,self.sink_count)) + self.sink_count=self.sink_count+1 + if show_q: + self.connect((c2f,1), (self.scope,self.sink_count)) + self.sink_count=self.sink_count+1 + + + def _set_status_msg(self, msg): + self.frame.GetStatusBar().SetStatusText(msg, 0) + + def _build_gui(self, vbox): + + def _form_set_freq(kv): + return self.set_freq(kv['freq']) + + vbox.Add(self.scope.win, 10, wx.EXPAND) + + # add control area at the bottom + self.myform = myform = form.form() + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0, 0) + myform['freq'] = form.float_field( + parent=self.panel, sizer=hbox, label="Center freq", weight=1, + callback=myform.check_input_and_call(_form_set_freq, self._set_status_msg)) + + hbox.Add((5,0), 0, 0) + g = self.subdevm.gain_range() + myform['gain'] = form.slider_field(parent=self.panel, sizer=hbox, label="Gain", + weight=3, + min=int(g[0]), max=int(g[1]), + callback=self.set_gain) + + hbox.Add((5,0), 0, 0) + buttonSync = form.button_with_callback(parent=self.panel, label='sync',callback=self.sync_usrps) + hbox.Add(buttonSync,0,wx.EXPAND) + + hbox.Add((5,0), 0, 0) + vbox.Add(hbox, 0, wx.EXPAND) + + self._build_subpanel(vbox) + + def _build_subpanel(self, vbox_arg): + # build a secondary information panel (sometimes hidden) + + # FIXME figure out how to have this be a subpanel that is always + # created, but has its visibility controlled by foo.Show(True/False) + + if not(self.show_debug_info): + return + + panel = self.panel + vbox = vbox_arg + myform = self.myform + + #panel = wx.Panel(self.panel, -1) + #vbox = wx.BoxSizer(wx.VERTICAL) + + hbox = wx.BoxSizer(wx.HORIZONTAL) + hbox.Add((5,0), 0) + myform['decim'] = form.static_float_field( + parent=panel, sizer=hbox, label="Decim") + + hbox.Add((5,0), 1) + myform['fs@usb'] = form.static_float_field( + parent=panel, sizer=hbox, label="Fs@USB") + + hbox.Add((5,0), 1) + myform['dbname'] = form.static_text_field( + parent=panel, sizer=hbox) + + hbox.Add((5,0), 1) + myform['baseband'] = form.static_float_field( + parent=panel, sizer=hbox, label="Analog BB") + + hbox.Add((5,0), 1) + myform['ddc'] = form.static_float_field( + parent=panel, sizer=hbox, label="DDC") + + hbox.Add((5,0), 0) + vbox.Add(hbox, 0, wx.EXPAND) + + + def set_freq(self, target_freq, sync=True): + """ + Set the center frequency we're interested in for all channels, + on all rx daughterboards on MASTER and SLAVE. + + @param target_freq: frequency in Hz + @param sync: sync the usrps after setting the freqs (this will clear any phase differences in the DDCS) + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital down converter. + """ + result,r1,r2,r3,r4 = self.multi.tune_all_rx(target_freq) + if sync: + self.sync_usrps() #sync master and slave and clear any DDC phase differences + if r1: + self.myform['freq'].set_value(target_freq) # update displayed value + if self.show_debug_info: + self.myform['baseband'].set_value(r1.baseband_freq) + self.myform['ddc'].set_value(r1.dxc_freq) + return result + + def set_freq_chan0(self, target_freq, sync=True): + """ + Set the center frequency we're interested in for rx chan 0 only on MASTER and SLAVE. + + @param target_freq: frequency in Hz + @param sync: sync the usrps after setting the freqs (this will clear any phase differences in the DDCS) + @rypte: bool + + Tuning is a two step process. First we ask the front-end to + tune as close to the desired frequency as it can. Then we use + the result of that operation and our target_frequency to + determine the value for the digital down converter. + """ + rm = usrp.tune(self.um, 0, self.subdevm, target_freq) + rs = usrp.tune(self.us, 0, self.subdevs, target_freq) + r=rm + if sync: + self.sync_usrps() #sync master and slave and clear any DDC phase differences + if r: + self.myform['freq'].set_value(target_freq) # update displayed value + if self.show_debug_info: + self.myform['baseband'].set_value(r.baseband_freq) + self.myform['ddc'].set_value(r.dxc_freq) + return True + + return False + + def set_gain(self, gain): + self.myform['gain'].set_value(gain) # update displayed value + self.multi.set_gain_all_rx(gain) + + def set_gain_chan0(self, gain): + self.myform['gain'].set_value(gain) # update displayed value + self.subdevm.set_gain(gain) + self.subdevs.set_gain(gain) + + def onIdle(self,evt): + if self.unsynced: + time.sleep(0.5) + self.unsynced=True + self.multi.sync() + self.unsynced=False + #print 'synced' + + def sync_usrps(self): + self.multi.sync() + +def main (): + app = stdgui.stdapp(app_flow_graph, "MULTI_USRP O'scope", nstatus=1) + app.MainLoop() + +if __name__ == '__main__': + main () diff --git a/gnuradio-examples/python/multi_usrp/multi_usrp_rx_cfile.py b/gnuradio-examples/python/multi_usrp/multi_usrp_rx_cfile.py new file mode 100755 index 00000000..6084aba3 --- /dev/null +++ b/gnuradio-examples/python/multi_usrp/multi_usrp_rx_cfile.py @@ -0,0 +1,131 @@ +#!/usr/bin/env python + +""" +Read samples 2 from two linked synchronised USRP's and write to file formatted as binary +single-precision complex values. +Make sure you read README on how to link the two usrps + +""" + +from gnuradio import gr, eng_notation +from gnuradio import audio +from gnuradio import usrp +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import sys + +import time +from gnuradio import usrp_multi + +class my_graph(gr.flow_graph): + + def __init__(self): + gr.flow_graph.__init__(self) + + usage="%prog: [options] output_filename" + parser = OptionParser(option_class=eng_option, usage=usage) + parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=(0, 0), + help="select USRP Rx side A or B (default=A)") + parser.add_option("-d", "--decim", type="int", default=128, + help="set selfpa decimation rate to DECIM [default=%default]") + parser.add_option("-f", "--freq", type="eng_float", default=0.0, + help="set frequency to FREQ", metavar="FREQ") + parser.add_option("-g", "--gain", type="eng_float", default=None, + help="set gain in dB (default is midpoint)") + parser.add_option("-n", "--nchan", type="intx", default=2, + help="set nchannels to NCHAN") + parser.add_option("-N", "--nsamples", type="eng_float", default=None, + help="number of samples to collect [default=+inf]") + parser.add_option ("-o", "--output-file-m", default="usrp_rx_m.dat", + help="write master data to FILE", metavar="FILE") + parser.add_option ("--output-file-m2", default="usrp_rx_m2.dat", + help="write master data from second channel to FILE", metavar="FILE") + parser.add_option ("-p", "--output-file-s", default="usrp_rx_s.dat", + help="write slave data to FILE", metavar="FILE") + parser.add_option ("--output-file-s2", default="usrp_rx_s2.dat", + help="write slave data from second channel to FILE", metavar="FILE") + parser.add_option("-x", "--master-serialno", type="string", default=None, + help="Serial_no of the usrp which should be the MASTER (default= select any)") + (options, args) = parser.parse_args () + if len(args) != 0: + parser.print_help() + raise SystemExit, 1 + + if options.freq is None: + parser.print_help() + sys.stderr.write('You must specify the frequency with -f FREQ\n'); + raise SystemExit, 1 + + # build the graph + self.multi=usrp_multi.multi_source_align( fg=self, master_serialno=options.master_serialno, decim=options.decim, + nchan=options.nchan ) + self.um=self.multi.get_master_usrp() + self.us=self.multi.get_slave_usrp() + + dst_m=gr.file_sink (gr.sizeof_gr_complex, options.output_file_m) + dst_s=gr.file_sink (gr.sizeof_gr_complex, options.output_file_s) + if options.nsamples is None: + self.connect((self.multi.get_master_source_c(),1),dst_m) + self.connect((self.multi.get_slave_source_c(),1),dst_s) + else: + head_m = gr.head(gr.sizeof_gr_complex, int(options.nsamples)) + head_s = gr.head(gr.sizeof_gr_complex, int(options.nsamples)) + self.connect((self.multi.get_master_source_c(),1),head_m,dst_m) + self.connect((self.multi.get_slave_source_c(),1),head_s,dst_s) + + if(4==options.nchan): + dst_m2=gr.file_sink (gr.sizeof_gr_complex, options.output_file_m2) + dst_s2=gr.file_sink (gr.sizeof_gr_complex, options.output_file_s2) + if options.nsamples is None: + self.connect((self.multi.get_master_source_c(),2),dst_m2) + self.connect((self.multi.get_slave_source_c(),2),dst_s2) + else: + head_m2 = gr.head(gr.sizeof_gr_complex, int(options.nsamples)) + head_s2 = gr.head(gr.sizeof_gr_complex, int(options.nsamples)) + self.connect((self.multi.get_master_source_c(),2),head_m2,dst_m2) + self.connect((self.multi.get_slave_source_c(),2),head_s2,dst_s2) + + if options.rx_subdev_spec is None: + options.rx_subdev_spec = usrp.pick_rx_subdevice(self.um) + + if (options.nchan!=4): + mux=usrp.determine_rx_mux_value(self.um, options.rx_subdev_spec) + mux= (mux<<8 & 0xffffffff) | (mux & 0xff) + self.um.set_mux(mux) + self.us.set_mux(mux) + + # determine the daughterboard subdevice we're using + self.subdevm = usrp.selected_subdev(self.um, options.rx_subdev_spec) + self.subdevs = usrp.selected_subdev(self.us, options.rx_subdev_spec) + print "Using MASTER RX d'board %s" % (self.subdevm.side_and_name(),) + print "Using SLAVE RX d'board %s" % (self.subdevs.side_and_name(),) + input_rate = self.um.adc_freq() / self.um.decim_rate() + print "USB sample rate %s" % (eng_notation.num_to_str(input_rate)) + + if options.gain is None: + # if no gain was specified, use the mid-point in dB + g = self.subdevm.gain_range() + options.gain = float(g[0]+g[1])/2 + + self.multi.set_gain_all_rx(options.gain) + result,r1,r2,r3,r4 = self.multi.tune_all_rx(options.freq) + if not result: + sys.stderr.write('Failed to set frequency\n') + raise SystemExit, 1 + + def sync_usrps(self): + self.multi.sync() + + +if __name__ == '__main__': + fg=my_graph() + fg.start() + #time.sleep(0.5) + fg.sync_usrps() + raw_input ('Press Enter to quit: ') + fg.stop() + #try: + # fg.start() + # fg.sync_usrps() + #except KeyboardInterrupt: + # pass diff --git a/gnuradio-examples/python/networking/measurement_slave.py b/gnuradio-examples/python/networking/measurement_slave.py new file mode 100755 index 00000000..2bc7c39c --- /dev/null +++ b/gnuradio-examples/python/networking/measurement_slave.py @@ -0,0 +1,241 @@ +#!/usr/bin/env python +# +# Copyright 2006 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU 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 struct +import socket +import asyncore +import sys +import optparse +import random +from gnuradio.eng_option import eng_option +import gnuradio.gr.gr_threading as _threading + +LOOP_TIMEOUT = 0.001 +BROADCAST_ADDR = '255.255.255.255' + +BROADCAST_PORT = 27010 # UDP +CONTROL_PORT = 27011 # TCP + +PKT_HEADER_SIZE = 4 # 32-bit int + +logfile = None + +def unpack_header(s): + (len,) = struct.unpack('!i', s) + return (len,) + +def pack_header(len): + return struct.pack('!i', len) + + +class control_port_listener(asyncore.dispatcher): + def __init__(self, port=CONTROL_PORT, udp_socket=None, verbose=False): + """ + @param port: TCP port to listen on. + @type port: int + """ + asyncore.dispatcher.__init__(self) + + self._verbose = verbose + self._udp_socket = udp_socket + + host = '' # symbolic name for localhost + self.create_socket(socket.AF_INET, socket.SOCK_STREAM) + self.set_reuse_addr() + + try: + self.bind((host, port)) + except socket.error, err: + sys.stderr.write('Failed to bind to %s: %s\n' % + ((host, port), os.strerror (err.args[0]),)) + sys.exit(1) + + self.listen(3) + + def handle_accept(self): + socket, addr = self.accept() + sys.stderr.write("handle_accept: %r\n" % (addr,)) + if not(socket is None): + # instantiate a server + s = control_server(socket, addr, self._udp_socket, self._verbose) + + +class gr_dispatcher(asyncore.dispatcher): + def __init__(self, sock=None, map=None): + asyncore.dispatcher.__init__(self, sock=sock, map=map) + + def read_packet(self): + """ + Returns None or packet + """ + s = self.recvall(PKT_HEADER_SIZE) + if s == '': + return None + + (payload_len,) = unpack_header(s) + + payload_len = int(payload_len) + + if payload_len == 0: + payload = '' + else: + payload = self.recvall(payload_len) + if len(payload) != payload_len: + sys.stderr.write ('short recv, expected %d bytes, got %d\n' % ( + payload_len, len(payload))) + raise RuntimeError, "short recv" + + return payload + + def recvall(self, buffer_size): + result = '' + while len(result) < buffer_size: + data = self.recv(buffer_size - len(result)) + if not data: + return '' + result += data + return result + + +class pkt_receiver_thread(_threading.Thread): + def __init__(self, socket): + _threading.Thread.__init__(self) + self.setDaemon(1) + self.socket = socket + self.keep_running = True + self.start() + + def run(self): + while self.keep_running: + pkt, sender = self.socket.recvfrom(10000) + if pkt: + if len(pkt) > 2: + t = struct.unpack('!H', pkt[0:2]) + seqno = t[0] + else: + seqno = -1 + + logfile.write('RCVD seqno %4d len %4d from %s\n' % (seqno, len(pkt), sender)) + logfile.flush() + + +class control_server(gr_dispatcher): + def __init__(self, socket, addr, udp_socket, verbose=False): + gr_dispatcher.__init__(self, sock=socket) + + self._udp_socket = udp_socket + self.verbose = verbose + self.setblocking(1) + + def writable(self): + return False + + def handle_read(self): + pkt = self.read_packet() + if pkt: + annotate = 'ANNOTATE' + if pkt.startswith(annotate): + logfile.write(pkt[len(annotate)+1:]) + logfile.write('\n') + logfile.flush() + elif pkt.startswith('SEND'): + tokens = pkt.split() + if len(tokens) < 4: + invalid_packet(pkt) + else: + npkts = int(tokens[1]) + size = int(tokens[2]) + power = float(tokens[3]) + send_test_packets(self._udp_socket, npkts, size, power) + else: + invalid_packet(pkt) + + def handle_close(self): + self.close() + + +def invalid_packet(pkt): + sys.stderr.write('received unrecognized packet: %s\n' % (pkt,)) + + +def make_random_payload(size): + p = [0] * size + if 1: + for i in range(size): + p[i] = chr(random.randint(0, 255)) + else: + for i in range(size): + p[i] = chr(i % 256) + return ''.join(p) + + +def send_test_packets(udp_socket, npkts, size, power): + # we ignore power for now... + size = max(2, size) + payload = make_random_payload(size - 2) + for n in range(npkts): + pkt = struct.pack('!H', n) + payload + udp_socket.sendto(pkt, (BROADCAST_ADDR, BROADCAST_PORT)) + #udp_socket.sendall(pkt) + + +def open_udp_broadcast_socket(gr0_host_ip, port): + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +# s.bind((gr0_host_ip, port)) + s.bind(('', port)) + s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) +# s.connect((BROADCAST_ADDR, port)) + return s + + +def main(): + global logfile + + usage = 'usage: %prog [options] gr0-ip-addr' + parser = optparse.OptionParser (option_class=eng_option, usage=usage) + parser.add_option('-l', '--logfile', type='string', default=None, + help="specify log file name [default=]") + parser.add_option('-v', '--verbose', action="store_true", default=False, + help="enable verbose diagnostics") + + (options, args) = parser.parse_args () + if len(args) != 1: + parser.print_help() + sys.exit(1) + + gr0_ip_addr = args[0] + if options.logfile is None: + logfile = sys.stdout + else: + logfile = file(options.logfile, 'w') + + udp_socket = open_udp_broadcast_socket(gr0_ip_addr, BROADCAST_PORT) + R = pkt_receiver_thread(udp_socket) + L = control_port_listener(CONTROL_PORT, udp_socket=udp_socket, verbose=options.verbose) + asyncore.loop(LOOP_TIMEOUT) + + +if __name__ == '__main__': + try: + main() + except KeyboardInterrupt: + pass diff --git a/gnuradio-examples/python/usrp/Makefile.am b/gnuradio-examples/python/usrp/Makefile.am new file mode 100644 index 00000000..32442d5c --- /dev/null +++ b/gnuradio-examples/python/usrp/Makefile.am @@ -0,0 +1,52 @@ +# +# 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. +# + +EXTRA_DIST = \ + am_rcv.py \ + ayfabtu.py \ + benchmark_usb.py \ + fm_tx4.py \ + fsk_loopback.py \ + fsk_rx.py \ + fsk_tx.py \ + max_power.py \ + test_counting.py \ + test_dft_analysis.py \ + test_dft_synth.py \ + test_digital_loopback_counting.py \ + test_digital_loopback_lfsr.py \ + tvrx_am_rcv_gui.py \ + tvrx_tv_rcv.py \ + usrp_fft.py \ + usrp_fft_old.py \ + usrp_nbfm_ptt.py \ + usrp_nbfm_rcv.py \ + usrp_oscope.py \ + usrp_rx_cfile.py \ + usrp_rx_file.py \ + usrp_rx_nogui.py \ + usrp_siggen.py \ + usrp_wfm_rcv.py \ + usrp_wfm_rcv_nogui.py \ + usrp_wfm_rcv2_nogui.py \ + usrp_wfm_rcv_pll.py \ + usrp_wxapt_rcv.py \ + wfm_rcv_file.py diff --git a/gnuradio-examples/python/usrp/am_rcv.py b/gnuradio-examples/python/usrp/am_rcv.py new file mode 100755 index 00000000..2908dcbf --- /dev/null +++ b/gnuradio-examples/python/usrp/am_rcv.py @@ -0,0 +1,115 @@ +#!/usr/bin/env python + +from gnuradio import gr, eng_notation +from gnuradio import audio +from gnuradio import usrp +from gnuradio.eng_option import eng_option +from optparse import OptionParser +import sys +import math + +from gnuradio.wxgui import stdgui, fftsink +import wx + +class am_rx_graph (stdgui.gui_flow_graph): + def __init__(self,frame,panel,vbox,argv): + stdgui.gui_flow_graph.__init__ (self,frame,panel,vbox,argv) + + station = parseargs(argv[1:]) + offset_freq = 30e3 + IF_freq = offset_freq - station + + adc_rate = 64e6 + usrp_decim = 250 + if_rate = adc_rate / usrp_decim # 256 kHz + if_decim = 4 + demod_rate = if_rate / if_decim # 64 kHz + audio_decimation = 2 + audio_rate = demod_rate / audio_decimation # 16 kHz + + # usrp is data source + src = usrp.source_c (0, usrp_decim) + src.set_rx_freq (0, IF_freq) + actual_IF_freq =src.rx_freq(0) + actual_offset = actual_IF_freq + station + + #print actual_IF_freq + #print actual_offset + + src.set_pga(0,20) + # sound card as final sink + audio_sink = audio.sink (int (audio_rate)) + + channel_coeffs = \ + gr.firdes.low_pass (1.0, # gain + if_rate, # sampling rate + 9e3, # low pass cutoff freq + 10e3, # width of trans. band + gr.firdes.WIN_HANN) + + ddc = gr.freq_xlating_fir_filter_ccf (if_decim,channel_coeffs,-actual_offset,if_rate) + + magblock = gr.complex_to_mag() + volumecontrol = gr.multiply_const_ff(.003) + + # Deemphasis. Is this necessary on AM? + TAU = 75e-6 # 75us in US, 50us in EUR + fftaps = [ 1 - math.exp(-1/TAU/if_rate), 0] + fbtaps= [ 0 , math.exp(-1/TAU/if_rate) ] + + deemph = gr.iir_filter_ffd(fftaps,fbtaps) + + # compute FIR filter taps for audio filter + width_of_transition_band = audio_rate / 8 + audio_coeffs = gr.firdes.low_pass (1.0, # gain + if_rate, # sampling rate + 9e3, #audio_rate/2 - width_of_transition_band, + 4e3, # width_of_transition_band, + gr.firdes.WIN_HANN) + + # input: float; output: float + audio_filter = gr.fir_filter_fff (audio_decimation, audio_coeffs) + + + + + print len(channel_coeffs) + print len(audio_coeffs) + + # now wire it all together + self.connect (src, ddc) + self.connect (ddc, magblock) + self.connect (magblock, volumecontrol) + self.connect (volumecontrol,deemph) + self.connect (deemph,audio_filter) + self.connect (audio_filter, (audio_sink, 0)) + + if 1: + pre_demod = fftsink.fft_sink_c (self, panel, title="Pre-Demodulation", fft_size=128, sample_rate=if_rate) + self.connect (src, pre_demod) + vbox.Add (pre_demod.win, 1, wx.EXPAND) + + if 0: + post_demod = fftsink.fft_sink_c (self, panel, title="Post Demodulation", fft_size=256, sample_rate=demod_rate) + self.connect (ddc, post_demod) + vbox.Add (post_demod.win, 1, wx.EXPAND) + + if 0: + post_filt = fftsink.fft_sink_f (self, panel, title="Post Filter", fft_size=512, sample_rate=audio_rate) + self.connect (magblock,post_filt) + vbox.Add (post_filt.win, 1, wx.EXPAND) + +def parseargs (args): + nargs = len (args) + if nargs == 1: + freq1 = float (args[0]) * 1e3 + else: + sys.stderr.write ('usage: am_rcv freq1\n') + sys.exit (1) + + return freq1 + +if __name__ == '__main__': + app = stdgui.stdapp (am_rx_graph, "AM RX") + app.MainLoop () + diff --git a/gnuradio-examples/python/usrp/ayfabtu.dat b/gnuradio-examples/python/usrp/ayfabtu.dat new file mode 100644 index 0000000000000000000000000000000000000000..5c65cf48334a68c16a1f07193b3b02c0dbc27e54 GIT binary patch literal 544640 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 z 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

1  Introduction