diff options
Diffstat (limited to 'gr-digital/lib')
21 files changed, 2552 insertions, 4 deletions
diff --git a/gr-digital/lib/CMakeLists.txt b/gr-digital/lib/CMakeLists.txt index 779972ff3..bd4f1a500 100644 --- a/gr-digital/lib/CMakeLists.txt +++ b/gr-digital/lib/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright 2011 Free Software Foundation, Inc. +# Copyright 2011,2012 Free Software Foundation, Inc. # # This file is part of GNU Radio # @@ -23,29 +23,102 @@ include_directories( ${GNURADIO_CORE_INCLUDE_DIRS} ${GR_DIGITAL_INCLUDE_DIRS} + ${CMAKE_CURRENT_BINARY_DIR}/../include ) include_directories(${Boost_INCLUDE_DIRS}) link_directories(${Boost_LIBRARY_DIRS}) + +######################################################################## +# generate helper scripts to expand templated files +######################################################################## +include(GrPython) + +file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py " +#!${PYTHON_EXECUTABLE} + +import sys, os, re +sys.path.append('${GR_CORE_PYTHONPATH}') +os.environ['srcdir'] = '${CMAKE_CURRENT_SOURCE_DIR}' +os.chdir('${CMAKE_CURRENT_BINARY_DIR}') + +if __name__ == '__main__': + import build_utils + root, inp = sys.argv[1:3] + for sig in sys.argv[3:]: + name = re.sub ('X+', sig, root) + d = build_utils.standard_dict(name, sig, 'digital') + build_utils.expand_template(d, inp) + +") + +macro(expand_cc root) + #make a list of all the generated files + unset(expanded_files_cc) + unset(expanded_files_h) + foreach(sig ${ARGN}) + string(REGEX REPLACE "X+" ${sig} name ${root}) + list(APPEND expanded_files_cc ${CMAKE_CURRENT_BINARY_DIR}/${name}.cc) + list(APPEND expanded_files_h ${CMAKE_CURRENT_BINARY_DIR}/../include/${name}.h) + endforeach(sig) + + #create a command to generate the files + add_custom_command( + OUTPUT ${expanded_files_cc} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.cc.t + COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py + ${root} ${root}.cc.t ${ARGN} + ) + + #make source files depends on headers to force generation + set_source_files_properties(${expanded_files_cc} + PROPERTIES OBJECT_DEPENDS "${expanded_files_h}" + ) + + #install rules for the generated cc files + list(APPEND generated_sources ${expanded_files_cc}) +endmacro(expand_cc) + +######################################################################## +# Invoke macro to generate various sources +######################################################################## +expand_cc(digital_chunks_to_symbols_XX bf bc sf sc if ic) + ######################################################################## # Setup library ######################################################################## list(APPEND gr_digital_sources + ${generated_sources} + digital_impl_glfsr.cc digital_impl_mpsk_snr_est.cc + digital_additive_scrambler_bb.cc digital_binary_slicer_fb.cc + digital_bytes_to_syms.cc digital_clock_recovery_mm_cc.cc digital_clock_recovery_mm_ff.cc + digital_cma_equalizer_cc.cc digital_constellation.cc digital_constellation_receiver_cb.cc digital_constellation_decoder_cb.cc digital_correlate_access_code_bb.cc + digital_correlate_access_code_tag_bb.cc digital_costas_loop_cc.cc - digital_cma_equalizer_cc.cc + digital_cpmmod_bc.cc digital_crc32.cc + digital_descrambler_bb.cc + digital_diff_decoder_bb.cc + digital_diff_encoder_bb.cc + digital_diff_phasor_cc.cc digital_fll_band_edge_cc.cc + digital_framer_sink_1.cc + digital_glfsr_source_b.cc + digital_glfsr_source_f.cc + digital_gmskmod_bc.cc digital_lms_dd_equalizer_cc.cc digital_kurtotic_equalizer_cc.cc + digital_map_bb.cc digital_mpsk_receiver_cc.cc digital_mpsk_snr_est_cc.cc digital_ofdm_cyclic_prefixer.cc @@ -54,9 +127,14 @@ list(APPEND gr_digital_sources digital_ofdm_insert_preamble.cc digital_ofdm_mapper_bcv.cc digital_ofdm_sampler.cc + digital_packet_sink.cc + digital_pfb_clock_sync_ccf.cc + digital_pfb_clock_sync_fff.cc + digital_pn_correlator_cc.cc + digital_probe_density_b.cc digital_probe_mpsk_snr_est_c.cc - digital_gmskmod_bc.cc - digital_cpmmod_bc.cc + digital_scrambler_bb.cc + digital_simple_framer.cc ) list(APPEND digital_libs @@ -67,3 +145,5 @@ list(APPEND digital_libs add_library(gnuradio-digital SHARED ${gr_digital_sources}) target_link_libraries(gnuradio-digital ${digital_libs}) GR_LIBRARY_FOO(gnuradio-digital RUNTIME_COMPONENT "digital_runtime" DEVEL_COMPONENT "digital_devel") + +add_dependencies(gnuradio-digital digital_generated_includes digital_generated_swigs) diff --git a/gr-digital/lib/digital_additive_scrambler_bb.cc b/gr-digital/lib/digital_additive_scrambler_bb.cc new file mode 100644 index 000000000..a8affaa78 --- /dev/null +++ b/gr-digital/lib/digital_additive_scrambler_bb.cc @@ -0,0 +1,69 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <digital_additive_scrambler_bb.h> +#include <gr_io_signature.h> + +digital_additive_scrambler_bb_sptr +digital_make_additive_scrambler_bb(int mask, int seed, int len, int count) +{ + return gnuradio::get_initial_sptr(new digital_additive_scrambler_bb + (mask, seed, len, count)); +} + +digital_additive_scrambler_bb::digital_additive_scrambler_bb(int mask, + int seed, + int len, + int count) + : gr_sync_block("additive_scrambler_bb", + gr_make_io_signature (1, 1, sizeof (unsigned char)), + gr_make_io_signature (1, 1, sizeof (unsigned char))), + d_lfsr(mask, seed, len), + d_count(count), + d_bits(0) +{ +} + +int +digital_additive_scrambler_bb::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const unsigned char *in = (const unsigned char *) input_items[0]; + unsigned char *out = (unsigned char *) output_items[0]; + + for (int i = 0; i < noutput_items; i++) { + out[i] = in[i]^d_lfsr.next_bit(); + if (d_count > 0) { + if (++d_bits == d_count) { + d_lfsr.reset(); + d_bits = 0; + } + } + } + + return noutput_items; +} diff --git a/gr-digital/lib/digital_bytes_to_syms.cc b/gr-digital/lib/digital_bytes_to_syms.cc new file mode 100644 index 000000000..f8bd82d5b --- /dev/null +++ b/gr-digital/lib/digital_bytes_to_syms.cc @@ -0,0 +1,74 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <digital_bytes_to_syms.h> +#include <gr_io_signature.h> +#include <assert.h> + +static const int BITS_PER_BYTE = 8; + +digital_bytes_to_syms_sptr +digital_make_bytes_to_syms () +{ + return gnuradio::get_initial_sptr(new digital_bytes_to_syms ()); +} + +digital_bytes_to_syms::digital_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 +digital_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/gr-digital/lib/digital_chunks_to_symbols_XX.cc.t b/gr-digital/lib/digital_chunks_to_symbols_XX.cc.t new file mode 100644 index 000000000..399a474a6 --- /dev/null +++ b/gr-digital/lib/digital_chunks_to_symbols_XX.cc.t @@ -0,0 +1,74 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <@NAME@.h> +#include <gr_io_signature.h> +#include <assert.h> +#include <iostream> +#include <string.h> + +@SPTR_NAME@ +digital_make_@BASE_NAME@ (const std::vector<@O_TYPE@> &symbol_table, const int D) +{ + return gnuradio::get_initial_sptr (new @NAME@ (symbol_table,D)); +} + +@NAME@::@NAME@ (const std::vector<@O_TYPE@> &symbol_table, const int D) + : gr_sync_interpolator ("@BASE_NAME@", + gr_make_io_signature (1, -1, sizeof (@I_TYPE@)), + gr_make_io_signature (1, -1, sizeof (@O_TYPE@)), + D), + d_D (D), + d_symbol_table (symbol_table) +{ +} + +int +@NAME@::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + assert (noutput_items % d_D == 0); + assert (input_items.size() == output_items.size()); + int nstreams = input_items.size(); + + for (int m=0;m<nstreams;m++) { + const @I_TYPE@ *in = (@I_TYPE@ *) input_items[m]; + @O_TYPE@ *out = (@O_TYPE@ *) output_items[m]; + + // per stream processing + for (int i = 0; i < noutput_items / d_D; i++){ + assert (((unsigned int)in[i]*d_D+d_D) <= d_symbol_table.size()); + memcpy(out, &d_symbol_table[(unsigned int)in[i]*d_D], d_D*sizeof(@O_TYPE@)); + out+=d_D; + } + // end of per stream processing + + } + return noutput_items; +} diff --git a/gr-digital/lib/digital_correlate_access_code_tag_bb.cc b/gr-digital/lib/digital_correlate_access_code_tag_bb.cc new file mode 100644 index 000000000..95f06534e --- /dev/null +++ b/gr-digital/lib/digital_correlate_access_code_tag_bb.cc @@ -0,0 +1,131 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006,2010-2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <digital_correlate_access_code_tag_bb.h> +#include <gr_io_signature.h> +#include <stdexcept> +#include <gr_count_bits.h> +#include <cstdio> +#include <iostream> + +#define VERBOSE 0 + + +digital_correlate_access_code_tag_bb_sptr +digital_make_correlate_access_code_tag_bb (const std::string &access_code, + int threshold, + const std::string &tag_name) +{ + return gnuradio::get_initial_sptr(new digital_correlate_access_code_tag_bb + (access_code, threshold, tag_name)); +} + + +digital_correlate_access_code_tag_bb::digital_correlate_access_code_tag_bb ( + const std::string &access_code, int threshold, const std::string &tag_name) + : gr_sync_block ("correlate_access_code_tag_bb", + gr_make_io_signature (1, 1, sizeof(char)), + gr_make_io_signature (1, 1, sizeof(char))), + d_data_reg(0), d_mask(0), + d_threshold(threshold), d_len(0) +{ + if (!set_access_code(access_code)) { + fprintf(stderr, "digital_correlate_access_code_tag_bb: access_code is > 64 bits\n"); + throw std::out_of_range ("access_code is > 64 bits"); + } + + std::stringstream str; + str << name() << unique_id(); + d_me = pmt::pmt_string_to_symbol(str.str()); + d_key = pmt::pmt_string_to_symbol(tag_name); +} + +digital_correlate_access_code_tag_bb::~digital_correlate_access_code_tag_bb () +{ +} + +bool +digital_correlate_access_code_tag_bb::set_access_code( + const std::string &access_code) +{ + d_len = access_code.length(); // # of bytes in string + if (d_len > 64) + return false; + + // set len top bits to 1. + d_mask = ((~0ULL) >> (64 - d_len)) << (64 - d_len); + + d_access_code = 0; + for (unsigned i=0; i < 64; i++){ + d_access_code <<= 1; + if (i < d_len) + d_access_code |= access_code[i] & 1; // look at LSB only + } + + return true; +} + +int +digital_correlate_access_code_tag_bb::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const unsigned char *in = (const unsigned char *) input_items[0]; + unsigned char *out = (unsigned char *) output_items[0]; + + uint64_t abs_out_sample_cnt = nitems_written(0); + + for (int i = 0; i < noutput_items; i++){ + + out[i] = in[i]; + + // compute hamming distance between desired access code and current data + unsigned long long wrong_bits = 0; + unsigned int nwrong = d_threshold+1; + int new_flag = 0; + + wrong_bits = (d_data_reg ^ d_access_code) & d_mask; + nwrong = gr_count_bits64(wrong_bits); + + // test for access code with up to threshold errors + new_flag = (nwrong <= d_threshold); + + // shift in new data and new flag + d_data_reg = (d_data_reg << 1) | (in[i] & 0x1); + if (new_flag) { + if(VERBOSE) std::cout << "writing tag at sample " << abs_out_sample_cnt + i << std::endl; + add_item_tag(0, //stream ID + abs_out_sample_cnt + i - 64 + d_len, //sample + d_key, //frame info + pmt::pmt_t(), //data (unused) + d_me //block src id + ); + } + } + + return noutput_items; +} + diff --git a/gr-digital/lib/digital_descrambler_bb.cc b/gr-digital/lib/digital_descrambler_bb.cc new file mode 100644 index 000000000..68cba7145 --- /dev/null +++ b/gr-digital/lib/digital_descrambler_bb.cc @@ -0,0 +1,56 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <digital_descrambler_bb.h> +#include <gr_io_signature.h> + +digital_descrambler_bb_sptr +digital_make_descrambler_bb(int mask, int seed, int len) +{ + return gnuradio::get_initial_sptr(new digital_descrambler_bb(mask, seed, len)); +} + +digital_descrambler_bb::digital_descrambler_bb(int mask, int seed, int len) + : gr_sync_block("descrambler_bb", + gr_make_io_signature (1, 1, sizeof (unsigned char)), + gr_make_io_signature (1, 1, sizeof (unsigned char))), + d_lfsr(mask, seed, len) +{ +} + +int +digital_descrambler_bb::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const unsigned char *in = (const unsigned char *) input_items[0]; + unsigned char *out = (unsigned char *) output_items[0]; + + for (int i = 0; i < noutput_items; i++) + out[i] = d_lfsr.next_bit_descramble(in[i]); + + return noutput_items; +} diff --git a/gr-digital/lib/digital_diff_decoder_bb.cc b/gr-digital/lib/digital_diff_decoder_bb.cc new file mode 100644 index 000000000..7b8e8726a --- /dev/null +++ b/gr-digital/lib/digital_diff_decoder_bb.cc @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <digital_diff_decoder_bb.h> +#include <gr_io_signature.h> + +digital_diff_decoder_bb_sptr +digital_make_diff_decoder_bb (unsigned int modulus) +{ + return gnuradio::get_initial_sptr(new digital_diff_decoder_bb(modulus)); +} + +digital_diff_decoder_bb::digital_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 +digital_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/gr-digital/lib/digital_diff_encoder_bb.cc b/gr-digital/lib/digital_diff_encoder_bb.cc new file mode 100644 index 000000000..bfbaba98f --- /dev/null +++ b/gr-digital/lib/digital_diff_encoder_bb.cc @@ -0,0 +1,62 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <digital_diff_encoder_bb.h> +#include <gr_io_signature.h> + +digital_diff_encoder_bb_sptr +digital_make_diff_encoder_bb (unsigned int modulus) +{ + return gnuradio::get_initial_sptr(new digital_diff_encoder_bb(modulus)); +} + +digital_diff_encoder_bb::digital_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 +digital_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/gr-digital/lib/digital_diff_phasor_cc.cc b/gr-digital/lib/digital_diff_phasor_cc.cc new file mode 100644 index 000000000..8313a4de8 --- /dev/null +++ b/gr-digital/lib/digital_diff_phasor_cc.cc @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <digital_diff_phasor_cc.h> +#include <gr_io_signature.h> + +digital_diff_phasor_cc_sptr +digital_make_diff_phasor_cc () +{ + return gnuradio::get_initial_sptr(new digital_diff_phasor_cc()); +} + +digital_diff_phasor_cc::digital_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); +} + + +digital_diff_phasor_cc::~digital_diff_phasor_cc(){} + +int +digital_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/gr-digital/lib/digital_framer_sink_1.cc b/gr-digital/lib/digital_framer_sink_1.cc new file mode 100644 index 000000000..ba1c5bd50 --- /dev/null +++ b/gr-digital/lib/digital_framer_sink_1.cc @@ -0,0 +1,192 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <digital_framer_sink_1.h> +#include <gr_io_signature.h> +#include <cstdio> +#include <stdexcept> +#include <string.h> + +#define VERBOSE 0 + +inline void +digital_framer_sink_1::enter_search() +{ + if (VERBOSE) + fprintf(stderr, "@ enter_search\n"); + + d_state = STATE_SYNC_SEARCH; +} + +inline void +digital_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 +digital_framer_sink_1::enter_have_header(int payload_len, + int whitener_offset) +{ + if (VERBOSE) + fprintf(stderr, "@ enter_have_header (payload_len = %d) (offset = %d)\n", + payload_len, whitener_offset); + + d_state = STATE_HAVE_HEADER; + d_packetlen = payload_len; + d_packet_whitener_offset = whitener_offset; + d_packetlen_cnt = 0; + d_packet_byte = 0; + d_packet_byte_index = 0; +} + +digital_framer_sink_1_sptr +digital_make_framer_sink_1(gr_msg_queue_sptr target_queue) +{ + return gnuradio::get_initial_sptr(new digital_framer_sink_1(target_queue)); +} + + +digital_framer_sink_1::digital_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(); +} + +digital_framer_sink_1::~digital_framer_sink_1 () +{ +} + +int +digital_framer_sink_1::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const unsigned char *in = (const unsigned char *) input_items[0]; + int count=0; + + if (VERBOSE) + fprintf(stderr,">>> Entering state machine\n"); + + while (count < noutput_items){ + switch(d_state) { + + case STATE_SYNC_SEARCH: // Look for flag indicating beginning of pkt + if (VERBOSE) + fprintf(stderr,"SYNC Search, noutput=%d\n", noutput_items); + + while (count < noutput_items) { + if (in[count] & 0x2){ // Found it, set up for header decode + enter_have_sync(); + break; + } + count++; + } + break; + + case STATE_HAVE_SYNC: + if (VERBOSE) + fprintf(stderr,"Header Search bitcnt=%d, header=0x%08x\n", + d_headerbitlen_cnt, d_header); + + while (count < noutput_items) { // Shift bits one at a time into header + d_header = (d_header << 1) | (in[count++] & 0x1); + if (++d_headerbitlen_cnt == HEADERBITLEN) { + + if (VERBOSE) + fprintf(stderr, "got header: 0x%08x\n", d_header); + + // we have a full header, check to see if it has been received properly + if (header_ok()){ + int payload_len; + int whitener_offset; + header_payload(&payload_len, &whitener_offset); + enter_have_header(payload_len, whitener_offset); + + if (d_packetlen == 0){ // check for zero-length payload + // build a zero-length message + // NOTE: passing header field as arg1 is not scalable + gr_message_sptr msg = + gr_make_message(0, d_packet_whitener_offset, 0, 0); + + d_target_queue->insert_tail(msg); // send it + msg.reset(); // free it up + + enter_search(); + } + } + else + enter_search(); // bad header + break; // we're in a new state + } + } + break; + + case STATE_HAVE_HEADER: + if (VERBOSE) + fprintf(stderr,"Packet Build\n"); + + while (count < noutput_items) { // shift bits into bytes of packet one at a time + d_packet_byte = (d_packet_byte << 1) | (in[count++] & 0x1); + if (d_packet_byte_index++ == 7) { // byte is full so move to next byte + d_packet[d_packetlen_cnt++] = d_packet_byte; + d_packet_byte_index = 0; + + if (d_packetlen_cnt == d_packetlen){ // packet is filled + + // build a message + // NOTE: passing header field as arg1 is not scalable + gr_message_sptr msg = + gr_make_message(0, d_packet_whitener_offset, 0, d_packetlen_cnt); + memcpy(msg->msg(), d_packet, d_packetlen_cnt); + + d_target_queue->insert_tail(msg); // send it + msg.reset(); // free it up + + enter_search(); + break; + } + } + } + break; + + default: + assert(0); + + } // switch + + } // while + + return noutput_items; +} diff --git a/gr-digital/lib/digital_glfsr_source_b.cc b/gr-digital/lib/digital_glfsr_source_b.cc new file mode 100644 index 000000000..e557e475a --- /dev/null +++ b/gr-digital/lib/digital_glfsr_source_b.cc @@ -0,0 +1,86 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <digital_glfsr_source_b.h> +#include <gri_glfsr.h> +#include <gr_io_signature.h> +#include <stdexcept> + +digital_glfsr_source_b_sptr +digital_make_glfsr_source_b(int degree, bool repeat, int mask, int seed) +{ + return gnuradio::get_initial_sptr(new digital_glfsr_source_b + (degree, repeat, mask, seed)); +} + +digital_glfsr_source_b::digital_glfsr_source_b(int degree, bool repeat, + int mask, int seed) + : gr_sync_block ("glfsr_source_b", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 1, sizeof(unsigned char))), + d_repeat(repeat), + d_index(0) +{ + if (degree < 1 || degree > 32) + throw std::runtime_error("digital_glfsr_source_b: degree must be between 1 and 32 inclusive"); + d_length = (unsigned int)((1ULL << degree)-1); + + if (mask == 0) + mask = gri_glfsr::glfsr_mask(degree); + d_glfsr = new gri_glfsr(mask, seed); +} + +digital_glfsr_source_b::~digital_glfsr_source_b() +{ + delete d_glfsr; +} + +int +digital_glfsr_source_b::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + char *out = (char *) output_items[0]; + if ((d_index > d_length) && d_repeat == false) + return -1; /* once through the sequence */ + + int i; + for (i = 0; i < noutput_items; i++) { + out[i] = d_glfsr->next_bit(); + d_index++; + if (d_index > d_length && d_repeat == false) + break; + } + + return i; +} + +int +digital_glfsr_source_b::mask() const +{ + return d_glfsr->mask(); +} diff --git a/gr-digital/lib/digital_glfsr_source_f.cc b/gr-digital/lib/digital_glfsr_source_f.cc new file mode 100644 index 000000000..5a7736ef8 --- /dev/null +++ b/gr-digital/lib/digital_glfsr_source_f.cc @@ -0,0 +1,86 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <digital_glfsr_source_f.h> +#include <gri_glfsr.h> +#include <gr_io_signature.h> +#include <stdexcept> + +digital_glfsr_source_f_sptr +digital_make_glfsr_source_f(int degree, bool repeat, int mask, int seed) +{ + return gnuradio::get_initial_sptr(new digital_glfsr_source_f + (degree, repeat, mask, seed)); +} + +digital_glfsr_source_f::digital_glfsr_source_f(int degree, bool repeat, + int mask, int seed) + : gr_sync_block ("glfsr_source_f", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 1, sizeof(float))), + d_repeat(repeat), + d_index(0) +{ + if (degree < 1 || degree > 32) + throw std::runtime_error("digital_glfsr_source_f: degree must be between 1 and 32 inclusive"); + d_length = (unsigned int)((1ULL << degree)-1); + + if (mask == 0) + mask = gri_glfsr::glfsr_mask(degree); + d_glfsr = new gri_glfsr(mask, seed); +} + +digital_glfsr_source_f::~digital_glfsr_source_f() +{ + delete d_glfsr; +} + +int +digital_glfsr_source_f::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float *out = (float *) output_items[0]; + if ((d_index > d_length) && d_repeat == false) + return -1; /* once through the sequence */ + + int i; + for (i = 0; i < noutput_items; i++) { + out[i] = (float)d_glfsr->next_bit()*2.0-1.0; + d_index++; + if (d_index > d_length && d_repeat == false) + break; + } + + return i; +} + +int +digital_glfsr_source_f::mask() const +{ + return d_glfsr->mask(); +} diff --git a/gr-digital/lib/digital_impl_glfsr.cc b/gr-digital/lib/digital_impl_glfsr.cc new file mode 100644 index 000000000..342980e53 --- /dev/null +++ b/gr-digital/lib/digital_impl_glfsr.cc @@ -0,0 +1,67 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <digital_impl_glfsr.h> +#include <stdexcept> + +static int s_polynomial_masks[] = { + 0x00000000, + 0x00000001, // x^1 + 1 + 0x00000003, // x^2 + x^1 + 1 + 0x00000005, // x^3 + x^1 + 1 + 0x00000009, // x^4 + x^1 + 1 + 0x00000012, // x^5 + x^2 + 1 + 0x00000021, // x^6 + x^1 + 1 + 0x00000041, // x^7 + x^1 + 1 + 0x0000008E, // x^8 + x^4 + x^3 + x^2 + 1 + 0x00000108, // x^9 + x^4 + 1 + 0x00000204, // x^10 + x^4 + 1 + 0x00000402, // x^11 + x^2 + 1 + 0x00000829, // x^12 + x^6 + x^4 + x^1 + 1 + 0x0000100D, // x^13 + x^4 + x^3 + x^1 + 1 + 0x00002015, // x^14 + x^5 + x^3 + x^1 + 1 + 0x00004001, // x^15 + x^1 + 1 + 0x00008016, // x^16 + x^5 + x^3 + x^2 + 1 + 0x00010004, // x^17 + x^3 + 1 + 0x00020013, // x^18 + x^5 + x^2 + x^1 + 1 + 0x00040013, // x^19 + x^5 + x^2 + x^1 + 1 + 0x00080004, // x^20 + x^3 + 1 + 0x00100002, // x^21 + x^2 + 1 + 0x00200001, // x^22 + x^1 + 1 + 0x00400010, // x^23 + x^5 + 1 + 0x0080000D, // x^24 + x^4 + x^3 + x^1 + 1 + 0x01000004, // x^25 + x^3 + 1 + 0x02000023, // x^26 + x^6 + x^2 + x^1 + 1 + 0x04000013, // x^27 + x^5 + x^2 + x^1 + 1 + 0x08000004, // x^28 + x^3 + 1 + 0x10000002, // x^29 + x^2 + 1 + 0x20000029, // x^30 + x^4 + x^1 + 1 + 0x40000004, // x^31 + x^3 + 1 + 0x80000057 // x^32 + x^7 + x^5 + x^3 + x^2 + x^1 + 1 +}; + +int digital_impl_glfsr::glfsr_mask(int degree) +{ + if (degree < 1 || degree > 32) + throw std::runtime_error("digital_impl_glfsr::glfsr_mask(): degree must be between 1 and 32 inclusive"); + return s_polynomial_masks[degree]; +} diff --git a/gr-digital/lib/digital_map_bb.cc b/gr-digital/lib/digital_map_bb.cc new file mode 100644 index 000000000..1d8444a40 --- /dev/null +++ b/gr-digital/lib/digital_map_bb.cc @@ -0,0 +1,61 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2007,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <digital_map_bb.h> +#include <gr_io_signature.h> + +digital_map_bb_sptr +digital_make_map_bb (const std::vector<int> &map) +{ + return gnuradio::get_initial_sptr(new digital_map_bb (map)); +} + +digital_map_bb::digital_map_bb (const std::vector<int> &map) + : gr_sync_block ("map_bb", + gr_make_io_signature (1, 1, sizeof (unsigned char)), + gr_make_io_signature (1, 1, sizeof (unsigned char))) +{ + for (int i = 0; i < 0x100; i++) + d_map[i] = i; + + unsigned int size = std::min((size_t) 0x100, map.size()); + for (unsigned int i = 0; i < size; i++) + d_map[i] = map[i]; +} + +int +digital_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/gr-digital/lib/digital_packet_sink.cc b/gr-digital/lib/digital_packet_sink.cc new file mode 100644 index 000000000..92521376f --- /dev/null +++ b/gr-digital/lib/digital_packet_sink.cc @@ -0,0 +1,207 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <digital_packet_sink.h> +#include <gr_io_signature.h> +#include <cstdio> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdexcept> +#include <gr_count_bits.h> +#include <string.h> + +#define VERBOSE 0 + +static const int DEFAULT_THRESHOLD = 12; // detect access code with up to DEFAULT_THRESHOLD bits wrong + +inline void +digital_packet_sink::enter_search() +{ + if (VERBOSE) + fprintf(stderr, "@ enter_search\n"); + + d_state = STATE_SYNC_SEARCH; + d_shift_reg = 0; +} + +inline void +digital_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 +digital_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; +} + +digital_packet_sink_sptr +digital_make_packet_sink (const std::vector<unsigned char>& sync_vector, + gr_msg_queue_sptr target_queue, int threshold) +{ + return gnuradio::get_initial_sptr(new digital_packet_sink (sync_vector, target_queue, threshold)); +} + + +digital_packet_sink::digital_packet_sink (const std::vector<unsigned char>& sync_vector, + gr_msg_queue_sptr target_queue, int threshold) + : gr_sync_block ("packet_sink", + gr_make_io_signature (1, 1, sizeof(float)), + gr_make_io_signature (0, 0, 0)), + d_target_queue(target_queue), d_threshold(threshold == -1 ? DEFAULT_THRESHOLD : threshold) +{ + d_sync_vector = 0; + for(int i=0;i<8;i++){ + d_sync_vector <<= 8; + d_sync_vector |= sync_vector[i]; + } + + enter_search(); +} + +digital_packet_sink::~digital_packet_sink () +{ +} + +int +digital_packet_sink::work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float *inbuf = (float *) input_items[0]; + int count=0; + + if (VERBOSE) + fprintf(stderr,">>> Entering state machine\n"),fflush(stderr); + + while (count<noutput_items) { + switch(d_state) { + + case STATE_SYNC_SEARCH: // Look for sync vector + if (VERBOSE) + fprintf(stderr,"SYNC Search, noutput=%d\n",noutput_items),fflush(stderr); + + while (count < noutput_items) { + if(slice(inbuf[count++])) + d_shift_reg = (d_shift_reg << 1) | 1; + else + d_shift_reg = d_shift_reg << 1; + + // Compute popcnt of putative sync vector + if(gr_count_bits64 (d_shift_reg ^ d_sync_vector) <= d_threshold) { + // Found it, set up for header decode + enter_have_sync(); + break; + } + } + break; + + case STATE_HAVE_SYNC: + if (VERBOSE) + fprintf(stderr,"Header Search bitcnt=%d, header=0x%08x\n", d_headerbitlen_cnt, d_header), + fflush(stderr); + + while (count < noutput_items) { // Shift bits one at a time into header + if(slice(inbuf[count++])) + d_header = (d_header << 1) | 1; + else + d_header = d_header << 1; + + if (++d_headerbitlen_cnt == HEADERBITLEN) { + + if (VERBOSE) + fprintf(stderr, "got header: 0x%08x\n", d_header); + + // we have a full header, check to see if it has been received properly + if (header_ok()){ + int payload_len = header_payload_len(); + if (payload_len <= MAX_PKT_LEN) // reasonable? + enter_have_header(payload_len); // yes. + else + enter_search(); // no. + } + else + enter_search(); // no. + break; // we're in a new state + } + } + break; + + case STATE_HAVE_HEADER: + if (VERBOSE) + fprintf(stderr,"Packet Build\n"),fflush(stderr); + + while (count < noutput_items) { // shift bits into bytes of packet one at a time + if(slice(inbuf[count++])) + d_packet_byte = (d_packet_byte << 1) | 1; + else + d_packet_byte = d_packet_byte << 1; + + if (d_packet_byte_index++ == 7) { // byte is full so move to next byte + d_packet[d_packetlen_cnt++] = d_packet_byte; + d_packet_byte_index = 0; + + if (d_packetlen_cnt == d_packetlen){ // packet is filled + + // build a message + gr_message_sptr msg = gr_make_message(0, 0, 0, d_packetlen_cnt); + memcpy(msg->msg(), d_packet, d_packetlen_cnt); + + d_target_queue->insert_tail(msg); // send it + msg.reset(); // free it up + + enter_search(); + break; + } + } + } + break; + + default: + assert(0); + + } // switch + + } // while + + return noutput_items; +} + diff --git a/gr-digital/lib/digital_pfb_clock_sync_ccf.cc b/gr-digital/lib/digital_pfb_clock_sync_ccf.cc new file mode 100644 index 000000000..1a2d5970b --- /dev/null +++ b/gr-digital/lib/digital_pfb_clock_sync_ccf.cc @@ -0,0 +1,440 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009-2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <cstdio> +#include <cmath> + +#include <digital_pfb_clock_sync_ccf.h> +#include <gr_fir_ccf.h> +#include <gr_fir_util.h> +#include <gr_io_signature.h> +#include <gr_math.h> + +digital_pfb_clock_sync_ccf_sptr +digital_make_pfb_clock_sync_ccf(double sps, float loop_bw, + const std::vector<float> &taps, + unsigned int filter_size, + float init_phase, + float max_rate_deviation, + int osps) +{ + return gnuradio::get_initial_sptr(new digital_pfb_clock_sync_ccf + (sps, loop_bw, taps, + filter_size, + init_phase, + max_rate_deviation, + osps)); +} + +static int ios[] = {sizeof(gr_complex), sizeof(float), sizeof(float), sizeof(float)}; +static std::vector<int> iosig(ios, ios+sizeof(ios)/sizeof(int)); +digital_pfb_clock_sync_ccf::digital_pfb_clock_sync_ccf (double sps, float loop_bw, + const std::vector<float> &taps, + unsigned int filter_size, + float init_phase, + float max_rate_deviation, + int osps) + : gr_block ("pfb_clock_sync_ccf", + gr_make_io_signature (1, 1, sizeof(gr_complex)), + gr_make_io_signaturev (1, 4, iosig)), + d_updated (false), d_nfilters(filter_size), + d_max_dev(max_rate_deviation), + d_osps(osps), d_error(0), d_out_idx(0) +{ + d_nfilters = filter_size; + d_sps = floor(sps); + + // Set the damping factor for a critically damped system + d_damping = sqrtf(2.0f)/2.0f; + + // Set the bandwidth, which will then call update_gains() + set_loop_bandwidth(loop_bw); + + // Store the last filter between calls to work + // The accumulator keeps track of overflow to increment the stride correctly. + // set it here to the fractional difference based on the initial phaes + d_k = init_phase; + d_rate = (sps-floor(sps))*(double)d_nfilters; + d_rate_i = (int)floor(d_rate); + d_rate_f = d_rate - (float)d_rate_i; + d_filtnum = (int)floor(d_k); + + d_filters = std::vector<gr_fir_ccf*>(d_nfilters); + d_diff_filters = std::vector<gr_fir_ccf*>(d_nfilters); + + // Create an FIR filter for each channel and zero out the taps + std::vector<float> vtaps(0, d_nfilters); + for(int i = 0; i < d_nfilters; i++) { + d_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps); + d_diff_filters[i] = gr_fir_util::create_gr_fir_ccf(vtaps); + } + + // Now, actually set the filters' taps + std::vector<float> dtaps; + create_diff_taps(taps, dtaps); + set_taps(taps, d_taps, d_filters); + set_taps(dtaps, d_dtaps, d_diff_filters); +} + +digital_pfb_clock_sync_ccf::~digital_pfb_clock_sync_ccf () +{ + for(int i = 0; i < d_nfilters; i++) { + delete d_filters[i]; + delete d_diff_filters[i]; + } +} + +bool +digital_pfb_clock_sync_ccf::check_topology(int ninputs, int noutputs) +{ + return noutputs == 1 || noutputs == 4; +} + + + +/******************************************************************* + SET FUNCTIONS +*******************************************************************/ + + +void +digital_pfb_clock_sync_ccf::set_loop_bandwidth(float bw) +{ + if(bw < 0) { + throw std::out_of_range ("digital_pfb_clock_sync_cc: invalid bandwidth. Must be >= 0."); + } + + d_loop_bw = bw; + update_gains(); +} + +void +digital_pfb_clock_sync_ccf::set_damping_factor(float df) +{ + if(df < 0 || df > 1.0) { + throw std::out_of_range ("digital_pfb_clock_sync_cc: invalid damping factor. Must be in [0,1]."); + } + + d_damping = df; + update_gains(); +} + +void +digital_pfb_clock_sync_ccf::set_alpha(float alpha) +{ + if(alpha < 0 || alpha > 1.0) { + throw std::out_of_range ("digital_pfb_clock_sync_cc: invalid alpha. Must be in [0,1]."); + } + d_alpha = alpha; +} + +void +digital_pfb_clock_sync_ccf::set_beta(float beta) +{ + if(beta < 0 || beta > 1.0) { + throw std::out_of_range ("digital_pfb_clock_sync_cc: invalid beta. Must be in [0,1]."); + } + d_beta = beta; +} + +/******************************************************************* + GET FUNCTIONS +*******************************************************************/ + + +float +digital_pfb_clock_sync_ccf::get_loop_bandwidth() const +{ + return d_loop_bw; +} + +float +digital_pfb_clock_sync_ccf::get_damping_factor() const +{ + return d_damping; +} + +float +digital_pfb_clock_sync_ccf::get_alpha() const +{ + return d_alpha; +} + +float +digital_pfb_clock_sync_ccf::get_beta() const +{ + return d_beta; +} + +float +digital_pfb_clock_sync_ccf::get_clock_rate() const +{ + return d_rate_f; +} + +/******************************************************************* +*******************************************************************/ + +void +digital_pfb_clock_sync_ccf::update_gains() +{ + float denom = (1.0 + 2.0*d_damping*d_loop_bw + d_loop_bw*d_loop_bw); + d_alpha = (4*d_damping*d_loop_bw) / denom; + d_beta = (4*d_loop_bw*d_loop_bw) / denom; +} + + +void +digital_pfb_clock_sync_ccf::set_taps (const std::vector<float> &newtaps, + std::vector< std::vector<float> > &ourtaps, + std::vector<gr_fir_ccf*> &ourfilter) +{ + int i,j; + + unsigned int ntaps = newtaps.size(); + d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_nfilters); + + // Create d_numchan vectors to store each channel's taps + ourtaps.resize(d_nfilters); + + // Make a vector of the taps plus fill it out with 0's to fill + // each polyphase filter with exactly d_taps_per_filter + std::vector<float> tmp_taps; + tmp_taps = newtaps; + while((float)(tmp_taps.size()) < d_nfilters*d_taps_per_filter) { + tmp_taps.push_back(0.0); + } + + // Partition the filter + for(i = 0; i < d_nfilters; i++) { + // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out + ourtaps[i] = std::vector<float>(d_taps_per_filter, 0); + for(j = 0; j < d_taps_per_filter; j++) { + ourtaps[i][j] = tmp_taps[i + j*d_nfilters]; + } + + // Build a filter for each channel and add it's taps to it + ourfilter[i]->set_taps(ourtaps[i]); + } + + // Set the history to ensure enough input items for each filter + set_history (d_taps_per_filter + d_sps); + + // Make sure there is enough output space for d_osps outputs/input. + set_output_multiple(d_osps); + + d_updated = true; +} + +void +digital_pfb_clock_sync_ccf::create_diff_taps(const std::vector<float> &newtaps, + std::vector<float> &difftaps) +{ + std::vector<float> diff_filter(3); + diff_filter[0] = -1; + diff_filter[1] = 0; + diff_filter[2] = 1; + + float pwr = 0; + difftaps.push_back(0); + for(unsigned int i = 0; i < newtaps.size()-2; i++) { + float tap = 0; + for(int j = 0; j < 3; j++) { + tap += diff_filter[j]*newtaps[i+j]; + pwr += fabsf(tap); + } + difftaps.push_back(tap); + } + difftaps.push_back(0); + + for(unsigned int i = 0; i < difftaps.size(); i++) { + difftaps[i] *= pwr; + } +} + +std::string +digital_pfb_clock_sync_ccf::get_taps_as_string() +{ + int i, j; + std::stringstream str; + str.precision(4); + str.setf(std::ios::scientific); + + str << "[ "; + for(i = 0; i < d_nfilters; i++) { + str << "[" << d_taps[i][0] << ", "; + for(j = 1; j < d_taps_per_filter-1; j++) { + str << d_taps[i][j] << ", "; + } + str << d_taps[i][j] << "],"; + } + str << " ]" << std::endl; + + return str.str(); +} + +std::string +digital_pfb_clock_sync_ccf::get_diff_taps_as_string() +{ + int i, j; + std::stringstream str; + str.precision(4); + str.setf(std::ios::scientific); + + str << "[ "; + for(i = 0; i < d_nfilters; i++) { + str << "[" << d_dtaps[i][0] << ", "; + for(j = 1; j < d_taps_per_filter-1; j++) { + str << d_dtaps[i][j] << ", "; + } + str << d_dtaps[i][j] << "],"; + } + str << " ]" << std::endl; + + return str.str(); +} + +std::vector< std::vector<float> > +digital_pfb_clock_sync_ccf::get_taps() +{ + return d_taps; +} + +std::vector< std::vector<float> > +digital_pfb_clock_sync_ccf::get_diff_taps() +{ + return d_dtaps; +} + +std::vector<float> +digital_pfb_clock_sync_ccf::get_channel_taps(int channel) +{ + std::vector<float> taps; + for(int i = 0; i < d_taps_per_filter; i++) { + taps.push_back(d_taps[channel][i]); + } + return taps; +} + +std::vector<float> +digital_pfb_clock_sync_ccf::get_diff_channel_taps(int channel) +{ + std::vector<float> taps; + for(int i = 0; i < d_taps_per_filter; i++) { + taps.push_back(d_dtaps[channel][i]); + } + return taps; +} + + +int +digital_pfb_clock_sync_ccf::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gr_complex *in = (gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + + float *err = NULL, *outrate = NULL, *outk = NULL; + if(output_items.size() == 4) { + err = (float *) output_items[1]; + outrate = (float*)output_items[2]; + outk = (float*)output_items[3]; + } + + if (d_updated) { + d_updated = false; + return 0; // history requirements may have changed. + } + + // We need this many to process one output + int nrequired = ninput_items[0] - d_taps_per_filter - d_osps; + + int i = 0, count = 0; + float error_r, error_i; + + // produce output as long as we can and there are enough input samples + while((i < noutput_items) && (count < nrequired)) { + while(d_out_idx < d_osps) { + d_filtnum = (int)floor(d_k); + + // Keep the current filter number in [0, d_nfilters] + // If we've run beyond the last filter, wrap around and go to next sample + // If we've go below 0, wrap around and go to previous sample + while(d_filtnum >= d_nfilters) { + d_k -= d_nfilters; + d_filtnum -= d_nfilters; + count += 1; + } + while(d_filtnum < 0) { + d_k += d_nfilters; + d_filtnum += d_nfilters; + count -= 1; + } + + out[i+d_out_idx] = d_filters[d_filtnum]->filter(&in[count+d_out_idx]); + d_k = d_k + d_rate_i + d_rate_f; // update phase + d_out_idx++; + + if(output_items.size() == 4) { + err[i] = d_error; + outrate[i] = d_rate_f; + outk[i] = d_k; + } + + // We've run out of output items we can create; return now. + if(i+d_out_idx >= noutput_items) { + consume_each(count); + return i; + } + } + + // reset here; if we didn't complete a full osps samples last time, + // the early return would take care of it. + d_out_idx = 0; + + // Update the phase and rate estimates for this symbol + gr_complex diff = d_diff_filters[d_filtnum]->filter(&in[count]); + error_r = out[i].real() * diff.real(); + error_i = out[i].imag() * diff.imag(); + d_error = (error_i + error_r) / 2.0; // average error from I&Q channel + + // Run the control loop to update the current phase (k) and + // tracking rate estimates based on the error value + d_rate_f = d_rate_f + d_beta*d_error; + d_k = d_k + d_alpha*d_error; + + // Keep our rate within a good range + d_rate_f = gr_branchless_clip(d_rate_f, d_max_dev); + + i+=d_osps; + count += (int)floor(d_sps); + } + + consume_each(count); + return i; +} diff --git a/gr-digital/lib/digital_pfb_clock_sync_fff.cc b/gr-digital/lib/digital_pfb_clock_sync_fff.cc new file mode 100644 index 000000000..0e7d2a52d --- /dev/null +++ b/gr-digital/lib/digital_pfb_clock_sync_fff.cc @@ -0,0 +1,434 @@ +/* -*- c++ -*- */ +/* + * Copyright 2009,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <cstdio> +#include <cmath> + +#include <digital_pfb_clock_sync_fff.h> +#include <gr_fir_fff.h> +#include <gr_fir_util.h> +#include <gr_io_signature.h> +#include <gr_math.h> + +digital_pfb_clock_sync_fff_sptr +digital_make_pfb_clock_sync_fff(double sps, float gain, + const std::vector<float> &taps, + unsigned int filter_size, + float init_phase, + float max_rate_deviation, + int osps) +{ + return gnuradio::get_initial_sptr(new digital_pfb_clock_sync_fff + (sps, gain, taps, + filter_size, + init_phase, + max_rate_deviation, + osps)); +} + +static int ios[] = {sizeof(float), sizeof(float), sizeof(float), sizeof(float)}; +static std::vector<int> iosig(ios, ios+sizeof(ios)/sizeof(int)); +digital_pfb_clock_sync_fff::digital_pfb_clock_sync_fff (double sps, float loop_bw, + const std::vector<float> &taps, + unsigned int filter_size, + float init_phase, + float max_rate_deviation, + int osps) + : gr_block ("pfb_clock_sync_fff", + gr_make_io_signature (1, 1, sizeof(float)), + gr_make_io_signaturev (1, 4, iosig)), + d_updated (false), d_nfilters(filter_size), + d_max_dev(max_rate_deviation), + d_osps(osps), d_error(0), d_out_idx(0) +{ + d_nfilters = filter_size; + d_sps = floor(sps); + + // Set the damping factor for a critically damped system + d_damping = sqrtf(2.0f)/2.0f; + + // Set the bandwidth, which will then call update_gains() + set_loop_bandwidth(loop_bw); + + // Store the last filter between calls to work + // The accumulator keeps track of overflow to increment the stride correctly. + // set it here to the fractional difference based on the initial phaes + d_k = init_phase; + d_rate = (sps-floor(sps))*(double)d_nfilters; + d_rate_i = (int)floor(d_rate); + d_rate_f = d_rate - (float)d_rate_i; + d_filtnum = (int)floor(d_k); + + d_filters = std::vector<gr_fir_fff*>(d_nfilters); + d_diff_filters = std::vector<gr_fir_fff*>(d_nfilters); + + // Create an FIR filter for each channel and zero out the taps + std::vector<float> vtaps(0, d_nfilters); + for(int i = 0; i < d_nfilters; i++) { + d_filters[i] = gr_fir_util::create_gr_fir_fff(vtaps); + d_diff_filters[i] = gr_fir_util::create_gr_fir_fff(vtaps); + } + + // Now, actually set the filters' taps + std::vector<float> dtaps; + create_diff_taps(taps, dtaps); + set_taps(taps, d_taps, d_filters); + set_taps(dtaps, d_dtaps, d_diff_filters); +} + +digital_pfb_clock_sync_fff::~digital_pfb_clock_sync_fff () +{ + for(int i = 0; i < d_nfilters; i++) { + delete d_filters[i]; + delete d_diff_filters[i]; + } +} + +bool +digital_pfb_clock_sync_fff::check_topology(int ninputs, int noutputs) +{ + return noutputs == 1 || noutputs == 4; +} + +/******************************************************************* + SET FUNCTIONS +*******************************************************************/ + + +void +digital_pfb_clock_sync_fff::set_loop_bandwidth(float bw) +{ + if(bw < 0) { + throw std::out_of_range ("digital_pfb_clock_sync_fff: invalid bandwidth. Must be >= 0."); + } + + d_loop_bw = bw; + update_gains(); +} + +void +digital_pfb_clock_sync_fff::set_damping_factor(float df) +{ + if(df < 0 || df > 1.0) { + throw std::out_of_range ("digital_pfb_clock_sync_fff: invalid damping factor. Must be in [0,1]."); + } + + d_damping = df; + update_gains(); +} + +void +digital_pfb_clock_sync_fff::set_alpha(float alpha) +{ + if(alpha < 0 || alpha > 1.0) { + throw std::out_of_range ("digital_pfb_clock_sync_fff: invalid alpha. Must be in [0,1]."); + } + d_alpha = alpha; +} + +void +digital_pfb_clock_sync_fff::set_beta(float beta) +{ + if(beta < 0 || beta > 1.0) { + throw std::out_of_range ("digital_pfb_clock_sync_fff: invalid beta. Must be in [0,1]."); + } + d_beta = beta; +} + +/******************************************************************* + GET FUNCTIONS +*******************************************************************/ + + +float +digital_pfb_clock_sync_fff::get_loop_bandwidth() const +{ + return d_loop_bw; +} + +float +digital_pfb_clock_sync_fff::get_damping_factor() const +{ + return d_damping; +} + +float +digital_pfb_clock_sync_fff::get_alpha() const +{ + return d_alpha; +} + +float +digital_pfb_clock_sync_fff::get_beta() const +{ + return d_beta; +} + +float +digital_pfb_clock_sync_fff::get_clock_rate() const +{ + return d_rate_f; +} + +/******************************************************************* +*******************************************************************/ + +void +digital_pfb_clock_sync_fff::update_gains() +{ + float denom = (1.0 + 2.0*d_damping*d_loop_bw + d_loop_bw*d_loop_bw); + d_alpha = (4*d_damping*d_loop_bw) / denom; + d_beta = (4*d_loop_bw*d_loop_bw) / denom; +} + + +void +digital_pfb_clock_sync_fff::set_taps (const std::vector<float> &newtaps, + std::vector< std::vector<float> > &ourtaps, + std::vector<gr_fir_fff*> &ourfilter) +{ + int i,j; + + unsigned int ntaps = newtaps.size(); + d_taps_per_filter = (unsigned int)ceil((double)ntaps/(double)d_nfilters); + + // Create d_numchan vectors to store each channel's taps + ourtaps.resize(d_nfilters); + + // Make a vector of the taps plus fill it out with 0's to fill + // each polyphase filter with exactly d_taps_per_filter + std::vector<float> tmp_taps; + tmp_taps = newtaps; + while((float)(tmp_taps.size()) < d_nfilters*d_taps_per_filter) { + tmp_taps.push_back(0.0); + } + + // Partition the filter + for(i = 0; i < d_nfilters; i++) { + // Each channel uses all d_taps_per_filter with 0's if not enough taps to fill out + ourtaps[i] = std::vector<float>(d_taps_per_filter, 0); + for(j = 0; j < d_taps_per_filter; j++) { + ourtaps[i][j] = tmp_taps[i + j*d_nfilters]; + } + + // Build a filter for each channel and add it's taps to it + ourfilter[i]->set_taps(ourtaps[i]); + } + + // Set the history to ensure enough input items for each filter + set_history (d_taps_per_filter + d_sps); + + // Make sure there is enough output space for d_osps outputs/input. + set_output_multiple(d_osps); + + d_updated = true; +} + +void +digital_pfb_clock_sync_fff::create_diff_taps(const std::vector<float> &newtaps, + std::vector<float> &difftaps) +{ + std::vector<float> diff_filter(3); + diff_filter[0] = -1; + diff_filter[1] = 0; + diff_filter[2] = 1; + + float pwr = 0; + difftaps.push_back(0); + for(unsigned int i = 0; i < newtaps.size()-2; i++) { + float tap = 0; + for(int j = 0; j < 3; j++) { + tap += diff_filter[j]*newtaps[i+j]; + pwr += fabsf(tap); + } + difftaps.push_back(tap); + } + difftaps.push_back(0); + + for(unsigned int i = 0; i < difftaps.size(); i++) { + difftaps[i] *= pwr; + } +} + +std::string +digital_pfb_clock_sync_fff::get_taps_as_string() +{ + int i, j; + std::stringstream str; + str.precision(4); + str.setf(std::ios::scientific); + + str << "[ "; + for(i = 0; i < d_nfilters; i++) { + str << "[" << d_taps[i][0] << ", "; + for(j = 1; j < d_taps_per_filter-1; j++) { + str << d_taps[i][j] << ", "; + } + str << d_taps[i][j] << "],"; + } + str << " ]" << std::endl; + + return str.str(); +} + +std::string +digital_pfb_clock_sync_fff::get_diff_taps_as_string() +{ + int i, j; + std::stringstream str; + str.precision(4); + str.setf(std::ios::scientific); + + str << "[ "; + for(i = 0; i < d_nfilters; i++) { + str << "[" << d_dtaps[i][0] << ", "; + for(j = 1; j < d_taps_per_filter-1; j++) { + str << d_dtaps[i][j] << ", "; + } + str << d_dtaps[i][j] << "],"; + } + str << " ]" << std::endl; + + return str.str(); +} + +std::vector< std::vector<float> > +digital_pfb_clock_sync_fff::get_taps() +{ + return d_taps; +} + +std::vector< std::vector<float> > +digital_pfb_clock_sync_fff::get_diff_taps() +{ + return d_dtaps; +} + +std::vector<float> +digital_pfb_clock_sync_fff::get_channel_taps(int channel) +{ + std::vector<float> taps; + for(int i = 0; i < d_taps_per_filter; i++) { + taps.push_back(d_taps[channel][i]); + } + return taps; +} + +std::vector<float> +digital_pfb_clock_sync_fff::get_diff_channel_taps(int channel) +{ + std::vector<float> taps; + for(int i = 0; i < d_taps_per_filter; i++) { + taps.push_back(d_dtaps[channel][i]); + } + return taps; +} + +int +digital_pfb_clock_sync_fff::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + float *in = (float *) input_items[0]; + float *out = (float *) output_items[0]; + + float *err = NULL, *outrate = NULL, *outk = NULL; + if(output_items.size() == 4) { + err = (float *) output_items[1]; + outrate = (float*)output_items[2]; + outk = (float*)output_items[3]; + } + + if (d_updated) { + d_updated = false; + return 0; // history requirements may have changed. + } + + // We need this many to process one output + int nrequired = ninput_items[0] - d_taps_per_filter - d_osps; + + int i = 0, count = 0; + + // produce output as long as we can and there are enough input samples + while((i < noutput_items) && (count < nrequired)) { + while(d_out_idx < d_osps) { + d_filtnum = (int)floor(d_k); + + // Keep the current filter number in [0, d_nfilters] + // If we've run beyond the last filter, wrap around and go to next sample + // If we've go below 0, wrap around and go to previous sample + while(d_filtnum >= d_nfilters) { + d_k -= d_nfilters; + d_filtnum -= d_nfilters; + count += 1; + } + while(d_filtnum < 0) { + d_k += d_nfilters; + d_filtnum += d_nfilters; + count -= 1; + } + + out[i+d_out_idx] = d_filters[d_filtnum]->filter(&in[count+d_out_idx]); + d_k = d_k + d_rate_i + d_rate_f; // update phase + d_out_idx++; + + if(output_items.size() == 4) { + err[i] = d_error; + outrate[i] = d_rate_f; + outk[i] = d_k; + } + + // We've run out of output items we can create; return now. + if(i+d_out_idx >= noutput_items) { + consume_each(count); + return i; + } + } + + // reset here; if we didn't complete a full osps samples last time, + // the early return would take care of it. + d_out_idx = 0; + + // Update the phase and rate estimates for this symbol + float diff = d_diff_filters[d_filtnum]->filter(&in[count]); + d_error = out[i] * diff; + + // Run the control loop to update the current phase (k) and + // tracking rate estimates based on the error value + d_rate_f = d_rate_f + d_beta*d_error; + d_k = d_k + d_alpha*d_error; + + // Keep our rate within a good range + d_rate_f = gr_branchless_clip(d_rate_f, d_max_dev); + + i+=d_osps; + count += (int)floor(d_sps); + } + + consume_each(count); + return i; +} diff --git a/gr-digital/lib/digital_pn_correlator_cc.cc b/gr-digital/lib/digital_pn_correlator_cc.cc new file mode 100644 index 000000000..43a3ddbd1 --- /dev/null +++ b/gr-digital/lib/digital_pn_correlator_cc.cc @@ -0,0 +1,80 @@ +/* -*- c++ -*- */ +/* + * Copyright 2007,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <digital_pn_correlator_cc.h> +#include <gr_io_signature.h> + +digital_pn_correlator_cc_sptr +digital_make_pn_correlator_cc(int degree, int mask, int seed) +{ + return gnuradio::get_initial_sptr(new digital_pn_correlator_cc + (degree, mask, seed)); +} + +digital_pn_correlator_cc::digital_pn_correlator_cc(int degree, + int mask, + int seed) + : gr_sync_decimator ("pn_correlator_cc", + gr_make_io_signature (1, 1, sizeof(gr_complex)), + gr_make_io_signature (1, 1, sizeof(gr_complex)), + (unsigned int)((1ULL << degree)-1)) // PN code length +{ + d_len = (unsigned int)((1ULL << degree)-1); + if (mask == 0) + mask = gri_glfsr::glfsr_mask(degree); + d_reference = new gri_glfsr(mask, seed); + for (int i = 0; i < d_len; i++) // initialize to last value in sequence + d_pn = 2.0*d_reference->next_bit()-1.0; +} + +digital_pn_correlator_cc::~digital_pn_correlator_cc() +{ + delete d_reference; +} + +int +digital_pn_correlator_cc::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const gr_complex *in = (const gr_complex *) input_items[0]; + gr_complex *out = (gr_complex *) output_items[0]; + gr_complex sum; + + for (int i = 0; i < noutput_items; i++) { + sum = 0.0; + + for (int j = 0; j < d_len; j++) { + if (j != 0) // retard PN generator one sample per period + d_pn = 2.0*d_reference->next_bit()-1.0; // no conditionals + sum += *in++ * d_pn; + } + + *out++ = sum*gr_complex(1.0/d_len, 0.0); + } + + return noutput_items; +} diff --git a/gr-digital/lib/digital_probe_density_b.cc b/gr-digital/lib/digital_probe_density_b.cc new file mode 100644 index 000000000..6b83d2ddb --- /dev/null +++ b/gr-digital/lib/digital_probe_density_b.cc @@ -0,0 +1,68 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2010,2012 Free Software Foundation, Inc. + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <digital_probe_density_b.h> +#include <gr_io_signature.h> +#include <stdexcept> +#include <iostream> + +digital_probe_density_b_sptr +digital_make_probe_density_b(double alpha) +{ + return gnuradio::get_initial_sptr(new digital_probe_density_b(alpha)); +} + +digital_probe_density_b::digital_probe_density_b(double alpha) + : gr_sync_block("density_b", + gr_make_io_signature(1, 1, sizeof(char)), + gr_make_io_signature(0, 0, 0)) +{ + set_alpha(alpha); + d_density = 1.0; +} + +digital_probe_density_b::~digital_probe_density_b() +{ +} + +int +digital_probe_density_b::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const char *in = (const char *)input_items[0]; + + for (int i = 0; i < noutput_items; i++) + d_density = d_alpha*(double)in[i] + d_beta*d_density; + + return noutput_items; +} + +void +digital_probe_density_b::set_alpha(double alpha) +{ + d_alpha = alpha; + d_beta = 1.0-d_alpha; +} + diff --git a/gr-digital/lib/digital_scrambler_bb.cc b/gr-digital/lib/digital_scrambler_bb.cc new file mode 100644 index 000000000..c81b09d8c --- /dev/null +++ b/gr-digital/lib/digital_scrambler_bb.cc @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2008,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <digital_scrambler_bb.h> +#include <gr_io_signature.h> + +digital_scrambler_bb_sptr +digital_make_scrambler_bb(int mask, int seed, int len) +{ + return gnuradio::get_initial_sptr(new digital_scrambler_bb + (mask, seed, len)); +} + +digital_scrambler_bb::digital_scrambler_bb(int mask, int seed, int len) + : gr_sync_block("scrambler_bb", + gr_make_io_signature (1, 1, sizeof (unsigned char)), + gr_make_io_signature (1, 1, sizeof (unsigned char))), + d_lfsr(mask, seed, len) +{ +} + +int +digital_scrambler_bb::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + const unsigned char *in = (const unsigned char *) input_items[0]; + unsigned char *out = (unsigned char *) output_items[0]; + + for (int i = 0; i < noutput_items; i++) + out[i] = d_lfsr.next_bit_scramble(in[i]); + + return noutput_items; +} diff --git a/gr-digital/lib/digital_simple_framer.cc b/gr-digital/lib/digital_simple_framer.cc new file mode 100644 index 000000000..5c194543c --- /dev/null +++ b/gr-digital/lib/digital_simple_framer.cc @@ -0,0 +1,102 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <digital_simple_framer.h> +#include <digital_simple_framer_sync.h> +#include <gr_io_signature.h> +#include <assert.h> +#include <stdexcept> +#include <string.h> + + +digital_simple_framer_sptr +digital_make_simple_framer (int payload_bytesize) +{ + return gnuradio::get_initial_sptr(new digital_simple_framer + (payload_bytesize)); +} + +digital_simple_framer::digital_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 +digital_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 +digital_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; +} |