diff options
Diffstat (limited to 'gr-trellis/lib')
35 files changed, 5170 insertions, 0 deletions
diff --git a/gr-trellis/lib/CMakeLists.txt b/gr-trellis/lib/CMakeLists.txt new file mode 100644 index 0000000000..5bd0227de6 --- /dev/null +++ b/gr-trellis/lib/CMakeLists.txt @@ -0,0 +1,139 @@ +# Copyright 2012 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. + +######################################################################## +# Setup the include and linker paths +######################################################################## +include_directories( + ${GNURADIO_CORE_INCLUDE_DIRS} + ${GR_TRELLIS_INCLUDE_DIRS} + ${GR_DIGITAL_INCLUDE_DIRS} + ${CMAKE_CURRENT_BINARY_DIR}/../include +) + +include_directories(${Boost_INCLUDE_DIRS}) +link_directories(${Boost_LIBRARY_DIRS}) + +if(ENABLE_GR_CTRLPORT) + ADD_DEFINITIONS(-DGR_CTRLPORT) +endif(ENABLE_GR_CTRLPORT) + +####################################################################### +# generate the python helper script which calls into the build utils +######################################################################## +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_impl_dict2(name, sig, 'trellis') + 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}/${name}.h) + endforeach(sig) + + #create a command to generate the source 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} + ) + + #create a command to generate the header file + add_custom_command( + OUTPUT ${expanded_files_h} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${root}.h.t + COMMAND ${PYTHON_EXECUTABLE} ${PYTHON_DASH_B} + ${CMAKE_CURRENT_BINARY_DIR}/generate_helper.py + ${root} ${root}.h.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}) + list(APPEND generated_headers ${expanded_files_h}) +endmacro(expand_cc) + +######################################################################## +# Invoke macro to generate various sources +######################################################################## +expand_cc(encoder_XX_impl bb bs bi ss si ii) +expand_cc(sccc_encoder_XX_impl bb bs bi ss si ii) +expand_cc(pccc_encoder_XX_impl bb bs bi ss si ii) +expand_cc(metrics_X_impl s i f c) +expand_cc(viterbi_X_impl b s i) +expand_cc(viterbi_combined_XX_impl sb ss si ib is ii fb fs fi cb cs ci) +expand_cc(sccc_decoder_X_impl b s i) +expand_cc(sccc_decoder_combined_XX_impl fb fs fi cb cs ci) +expand_cc(pccc_decoder_X_impl b s i) +expand_cc(pccc_decoder_combined_XX_impl fb fs fi cb cs ci) + +######################################################################## +# Setup library +######################################################################## +list(APPEND trellis_sources + ${generated_sources} + base.cc + calc_metric.cc + core_algorithms.cc + fsm.cc + interleaver.cc + quicksort_index.cc + constellation_metrics_cf_impl.cc + permutation_impl.cc + siso_f_impl.cc + siso_combined_f_impl.cc +) + +list(APPEND trellis_libs + gnuradio-core + gnuradio-digital + ${Boost_LIBRARIES} +) + +add_library(gnuradio-trellis SHARED ${trellis_sources}) +target_link_libraries(gnuradio-trellis ${trellis_libs}) +GR_LIBRARY_FOO(gnuradio-trellis RUNTIME_COMPONENT "trellis_runtime" DEVEL_COMPONENT "trellis_devel") +add_dependencies(gnuradio-trellis + trellis_generated_includes trellis_generated_swigs + gnuradio-core gnuradio-digital) diff --git a/gr-trellis/lib/base.cc b/gr-trellis/lib/base.cc new file mode 100644 index 0000000000..e9d0141e70 --- /dev/null +++ b/gr-trellis/lib/base.cc @@ -0,0 +1,86 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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 <cstdio> +#include <stdexcept> +#include <cmath> +#include <trellis/base.h> + +namespace gr { + namespace trellis { + + bool + dec2base(unsigned int num, int base, std::vector<int> &s) + { + int l = s.size(); + unsigned int n=num; + for(int i=0;i<l;i++) { + s[l-i-1] = n % base; //MSB first + n /= base; + } + if(n!=0) { + printf("Number %d requires more than %d digits.",num,l); + return false; + } + else + return true; + } + + unsigned int + base2dec(const std::vector<int> &s, int base) + { + int l = s.size(); + unsigned int num=0; + for(int i=0;i<l;i++) + num=num*base+s[i]; + return num; + } + + bool + dec2bases(unsigned int num, const std::vector<int> &bases, std::vector<int> &s) + { + int l = s.size(); + unsigned int n=num; + for(int i=0;i<l;i++) { + s[l-i-1] = n % bases[l-i-1]; + n /= bases[l-i-1]; + } + if(n!=0) { + printf("Number %d requires more than %d digits.",num,l); + return false; + } + else + return true; + } + + unsigned int + bases2dec(const std::vector<int> &s, const std::vector<int> &bases) + { + int l = s.size(); + unsigned int num=0; + for(int i=0;i<l;i++) + num = num * bases[i] + s[i]; + return num; + } + + } /* namespace trellis */ +} /* namespace gr */ diff --git a/gr-trellis/lib/calc_metric.cc b/gr-trellis/lib/calc_metric.cc new file mode 100644 index 0000000000..3c474e30fe --- /dev/null +++ b/gr-trellis/lib/calc_metric.cc @@ -0,0 +1,251 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <float.h> +#include <stdexcept> +#include <trellis/calc_metric.h> + +namespace gr { + namespace trellis { + + template <class T> + void calc_metric(int O, int D, const std::vector<T> &TABLE, const T *input, + float *metric, digital::trellis_metric_type_t type) + { + float minm = FLT_MAX; + int minmi = 0; + + switch(type) { + case digital::TRELLIS_EUCLIDEAN: + for(int o = 0; o < O; o++) { + metric[o] = 0.0; + for(int m = 0; m < D; m++) { + T s = input[m]-TABLE[o*D+m]; + //gr_complex sc(1.0*s,0); + //metric[o] += (sc*conj(sc)).real(); + metric[o] += s * s; + } + } + break; + case digital::TRELLIS_HARD_SYMBOL: + for(int o = 0; o < O; o++) { + metric[o] = 0.0; + for(int m = 0; m < D; m++) { + T s = input[m]-TABLE[o*D+m]; + //gr_complex sc(1.0*s,0); + //metric[o] + =(sc*conj(sc)).real(); + metric[o] += s * s; + } + if(metric[o] < minm) { + minm = metric[o]; + minmi = o; + } + } + for(int o = 0; o < O; o++) { + metric[o] = (o == minmi ? 0.0 : 1.0); + } + break; + case digital::TRELLIS_HARD_BIT: + throw std::runtime_error("calc_metric: Invalid metric type (not yet implemented)."); + break; + default: + throw std::runtime_error("calc_metric: Invalid metric type."); + } + } + + template + void calc_metric<short>(int O, int D, const std::vector<short> &TABLE, const short *input, + float *metric, digital::trellis_metric_type_t type); + + template + void calc_metric<int>(int O, int D, const std::vector<int> &TABLE, const int *input, + float *metric, digital::trellis_metric_type_t type); + + template + void calc_metric<float>(int O, int D, const std::vector<float> &TABLE, const float *input, + float *metric, digital::trellis_metric_type_t type); + + void calc_metric(int O, int D, const std::vector<short> &TABLE, const short *input, + float *metric, digital::trellis_metric_type_t type) + { + float minm = FLT_MAX; + int minmi = 0; + + switch(type) { + case digital::TRELLIS_EUCLIDEAN: + for(int o = 0; o < O; o++) { + metric[o] = 0.0; + for(int m = 0; m < D; m++) { + float s = input[m]-TABLE[o*D+m]; + metric[o] += s*s; + } + } + break; + case digital::TRELLIS_HARD_SYMBOL: + for(int o = 0; o < O; o++) { + metric[o] = 0.0; + for(int m = 0; m < D; m++) { + float s = input[m]-TABLE[o*D+m]; + metric[o] += s*s; + } + if(metric[o] < minm) { + minm = metric[o]; + minmi = o; + } + } + for(int o = 0; o < O; o++) { + metric[o] = (o == minmi ? 0.0 : 1.0); + } + break; + case digital::TRELLIS_HARD_BIT: + throw std::runtime_error("calc_metric: Invalid metric type (not yet implemented)."); + break; + default: + throw std::runtime_error("calc_metric: Invalid metric type."); + } + } + + /* + void calc_metric(int O, int D, const std::vector<int> &TABLE, const int *input, + float *metric, digital::trellis_metric_type_t type) + { + float minm = FLT_MAX; + int minmi = 0; + + switch(type){ + case digital::TRELLIS_EUCLIDEAN: + for(int o=0;o<O;o++) { + metric[o]=0.0; + for(int m=0;m<D;m++) { + float s=input[m]-TABLE[o*D+m]; + metric[o]+=s*s; + } + } + break; + case digital::TRELLIS_HARD_SYMBOL: + for(int o=0;o<O;o++) { + metric[o]=0.0; + for(int m=0;m<D;m++) { + float s=input[m]-TABLE[o*D+m]; + metric[o]+=s*s; + } + if(metric[o]<minm) { + minm=metric[o]; + minmi=o; + } + } + for(int o=0;o<O;o++) { + metric[o] = (o==minmi?0.0:1.0); + } + break; + case digital::TRELLIS_HARD_BIT: + throw std::runtime_error("calc_metric: Invalid metric type (not yet implemented)."); + break; + default: + throw std::runtime_error("calc_metric: Invalid metric type."); + } + } + + void calc_metric(int O, int D, const std::vector<float> &TABLE, const float *input, + float *metric, digital::trellis_metric_type_t type) + { + float minm = FLT_MAX; + int minmi = 0; + + switch(type) { + case digital::TRELLIS_EUCLIDEAN: + for(int o=0;o<O;o++) { + metric[o]=0.0; + for(int m=0;m<D;m++) { + float s=input[m]-TABLE[o*D+m]; + metric[o]+=s*s; + } + } + break; + case digital::TRELLIS_HARD_SYMBOL: + for(int o=0;o<O;o++) { + metric[o]=0.0; + for(int m=0;m<D;m++) { + float s=input[m]-TABLE[o*D+m]; + metric[o]+=s*s; + } + if(metric[o]<minm) { + minm=metric[o]; + minmi=o; + } + } + for(int o=0;o<O;o++) { + metric[o] = (o==minmi?0.0:1.0); + } + break; + case digital::TRELLIS_HARD_BIT: + throw std::runtime_error("calc_metric: Invalid metric type (not yet implemented)."); + break; + default: + throw std::runtime_error("calc_metric: Invalid metric type."); + } + } +*/ + + void calc_metric(int O, int D, const std::vector<gr_complex> &TABLE, const gr_complex *input, + float *metric, digital::trellis_metric_type_t type) + { + float minm = FLT_MAX; + int minmi = 0; + + switch(type) { + case digital::TRELLIS_EUCLIDEAN: + for(int o = 0; o < O; o++) { + metric[o] = 0.0; + for(int m = 0; m < D; m++) { + gr_complex s = input[m]-TABLE[o*D+m]; + metric[o] += s.real()*s.real()+s.imag()*s.imag(); + } + } + break; + case digital::TRELLIS_HARD_SYMBOL: + for(int o = 0; o < O; o++) { + metric[o] = 0.0; + for(int m = 0; m < D; m++) { + gr_complex s = input[m]-TABLE[o*D+m]; + metric[o] += s.real()*s.real()+s.imag()*s.imag(); + } + if(metric[o] < minm) { + minm = metric[o]; + minmi = o; + } + } + for(int o = 0; o < O; o++) { + metric[o] = (o == minmi ? 0.0 : 1.0); + } + break; + case digital::TRELLIS_HARD_BIT: + throw std::runtime_error("calc_metric: Invalid metric type (not yet implemented)."); + break; + default: + throw std::runtime_error("calc_metric: Invalid metric type."); + } + } + + } /* namespace trellis */ +} /* namespace gr */ + diff --git a/gr-trellis/lib/constellation_metrics_cf_impl.cc b/gr-trellis/lib/constellation_metrics_cf_impl.cc new file mode 100644 index 0000000000..18d3095802 --- /dev/null +++ b/gr-trellis/lib/constellation_metrics_cf_impl.cc @@ -0,0 +1,96 @@ +/* -*- 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 "constellation_metrics_cf_impl.h" +#include <gr_io_signature.h> +#include <assert.h> +#include <stdexcept> +#include <iostream> + +namespace gr { + namespace trellis { + + constellation_metrics_cf::sptr + constellation_metrics_cf::make(digital::constellation_sptr constellation, + digital::trellis_metric_type_t TYPE) + { + return gnuradio::get_initial_sptr + (new constellation_metrics_cf_impl(constellation, TYPE)); + } + + constellation_metrics_cf_impl::constellation_metrics_cf_impl(digital::constellation_sptr constellation, + digital::trellis_metric_type_t TYPE) + : gr_block("constellation_metrics_cf", + gr_make_io_signature(1, -1, sizeof(gr_complex)), + gr_make_io_signature(1, -1, sizeof(float))), + d_constellation(constellation), + d_TYPE(TYPE), + d_O(constellation->arity()), + d_D(constellation->dimensionality()) + { + set_relative_rate(1.0 * d_O / ((double) d_D)); + set_output_multiple((int)d_O); + } + + constellation_metrics_cf_impl::~constellation_metrics_cf_impl() + { + } + + void + constellation_metrics_cf_impl::forecast(int noutput_items, + gr_vector_int &ninput_items_required) + { + assert(noutput_items % d_O == 0); + + unsigned int input_required = d_D * noutput_items / d_O; + unsigned int ninputs = ninput_items_required.size(); + for(unsigned int i = 0; i < ninputs; i++) + ninput_items_required[i] = input_required; + } + + int + constellation_metrics_cf_impl::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + unsigned int nstreams = input_items.size(); + + for(unsigned int m=0;m<nstreams;m++) { + const gr_complex *in = (gr_complex*)input_items[m]; + float *out = (float*)output_items[m]; + + for(unsigned int i = 0; i < noutput_items / d_O ; i++) { + d_constellation->calc_metric(&(in[i*d_D]), &(out[i*d_O]), d_TYPE); + } + } + + consume_each(d_D * noutput_items / d_O); + return noutput_items; + } + + } /* namespace trellis */ +} /* namespace gr */ diff --git a/gr-trellis/lib/constellation_metrics_cf_impl.h b/gr-trellis/lib/constellation_metrics_cf_impl.h new file mode 100644 index 0000000000..52018c4baa --- /dev/null +++ b/gr-trellis/lib/constellation_metrics_cf_impl.h @@ -0,0 +1,57 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2010-2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_TRELLIS_CONSTELLATION_METRICS_CF_IMPL_H +#define INCLUDED_TRELLIS_CONSTELLATION_METRICS_CF_IMPL_H + +#include <trellis/api.h> +#include <trellis/constellation_metrics_cf.h> + +namespace gr { + namespace trellis { + + class constellation_metrics_cf_impl : public constellation_metrics_cf + { + private: + digital::constellation_sptr d_constellation; + digital::trellis_metric_type_t d_TYPE; + unsigned int d_O; + unsigned int d_D; + + public: + constellation_metrics_cf_impl(digital::constellation_sptr constellation, + digital::trellis_metric_type_t TYPE); + ~constellation_metrics_cf_impl(); + + 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); + }; + + } /* namespace trellis */ +} /* namespace gr */ + +#endif /* INCLUDED_TRELLIS_CONSTELLATION_METRICS_CF_IMPL_H */ diff --git a/gr-trellis/lib/core_algorithms.cc b/gr-trellis/lib/core_algorithms.cc new file mode 100644 index 0000000000..a704e5f9a6 --- /dev/null +++ b/gr-trellis/lib/core_algorithms.cc @@ -0,0 +1,1324 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <cstring> +#include <stdexcept> +#include <iostream> +#include <trellis/core_algorithms.h> +#include <trellis/calc_metric.h> + +namespace gr { + namespace trellis { + + static const float INF = 1.0e9; + + float + min(float a, float b) + { + return a <= b ? a : b; + } + + float + min_star(float a, float b) + { + return (a <= b ? a : b)-log(1+exp(a <= b ? a-b : b-a)); + } + + template <class T> void + viterbi_algorithm(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + const float *in, T *out)//, + //std::vector<int> &trace) + { + std::vector<int> trace(S*K); + std::vector<float> alpha(S*2); + int alphai; + float norm,mm,minm; + int minmi; + int st; + + if(S0<0) { // initial state not specified + for(int i=0;i<S;i++) alpha[0*S+i]=0; + } + else { + for(int i=0;i<S;i++) alpha[0*S+i]=INF; + alpha[0*S+S0]=0.0; + } + + alphai=0; + for(int k=0;k<K;k++) { + norm=INF; + for(int j=0;j<S;j++) { // for each next state do ACS + minm=INF; + minmi=0; + for(unsigned int i=0;i<PS[j].size();i++) { + //int i0 = j*I+i; + if((mm=alpha[alphai*S+PS[j][i]]+in[k*O+OS[PS[j][i]*I+PI[j][i]]])<minm) + minm=mm,minmi=i; + } + trace[k*S+j]=minmi; + alpha[((alphai+1)%2)*S+j]=minm; + if(minm<norm) norm=minm; + } + for(int j=0;j<S;j++) + alpha[((alphai+1)%2)*S+j]-=norm; // normalize total metrics so they do not explode + alphai=(alphai+1)%2; + } + + if(SK<0) { // final state not specified + minm=INF; + minmi=0; + for(int i=0;i<S;i++) + if((mm=alpha[alphai*S+i])<minm) minm=mm,minmi=i; + st=minmi; + } + else { + st=SK; + } + + for(int k=K-1;k>=0;k--) { // traceback + int i0=trace[k*S+st]; + out[k]= (T) PI[st][i0]; + st=PS[st][i0]; + } + } + + template void + viterbi_algorithm<unsigned char>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + const float *in, unsigned char *out); + + template void + viterbi_algorithm<short>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + const float *in, short *out); + + template void + viterbi_algorithm<int>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + const float *in, int *out); + + //============================================== + + template <class Ti, class To> void + viterbi_algorithm_combined(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<Ti> &TABLE, + digital::trellis_metric_type_t TYPE, + const Ti *in, To *out) + { + std::vector<int> trace(S*K); + std::vector<float> alpha(S*2); + float *metric = new float[O]; + int alphai; + float norm,mm,minm; + int minmi; + int st; + + if(S0<0) { // initial state not specified + for(int i=0;i<S;i++) alpha[0*S+i]=0; + } + else { + for(int i=0;i<S;i++) alpha[0*S+i]=INF; + alpha[0*S+S0]=0.0; + } + + alphai=0; + for(int k=0;k<K;k++) { + calc_metric(O, D, TABLE, &(in[k*D]), metric,TYPE); // calc metrics + norm=INF; + for(int j=0;j<S;j++) { // for each next state do ACS + minm=INF; + minmi=0; + for(unsigned int i=0;i<PS[j].size();i++) { + //int i0 = j*I+i; + if((mm=alpha[alphai*S+PS[j][i]]+metric[OS[PS[j][i]*I+PI[j][i]]])<minm) + minm=mm,minmi=i; + } + trace[k*S+j]=minmi; + alpha[((alphai+1)%2)*S+j]=minm; + if(minm<norm) norm=minm; + } + for(int j=0;j<S;j++) + alpha[((alphai+1)%2)*S+j]-=norm; // normalize total metrics so they do not explode + alphai=(alphai+1)%2; + } + + if(SK<0) { // final state not specified + minm=INF; + minmi=0; + for(int i=0;i<S;i++) + if((mm=alpha[alphai*S+i])<minm) minm=mm,minmi=i; + st=minmi; + } + else { + st=SK; + } + + for(int k=K-1;k>=0;k--) { // traceback + int i0=trace[k*S+st]; + out[k]= (To) PI[st][i0]; + st=PS[st][i0]; + } + + delete [] metric; + } + + // Ti = s i f c + // To = b s i + + //--------------- + + template void + viterbi_algorithm_combined<short,unsigned char>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<short> &TABLE, + digital::trellis_metric_type_t TYPE, + const short *in, unsigned char *out); + + template void + viterbi_algorithm_combined<int,unsigned char>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<int> &TABLE, + digital::trellis_metric_type_t TYPE, + const int *in, unsigned char *out); + + template void + viterbi_algorithm_combined<float,unsigned char>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<float> &TABLE, + digital::trellis_metric_type_t TYPE, + const float *in, unsigned char *out); + + template void + viterbi_algorithm_combined<gr_complex,unsigned char>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<gr_complex> &TABLE, + digital::trellis_metric_type_t TYPE, + const gr_complex *in, unsigned char *out); + + //--------------- + + template void + viterbi_algorithm_combined<short,short>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<short> &TABLE, + digital::trellis_metric_type_t TYPE, + const short *in, short *out); + + template void + viterbi_algorithm_combined<int,short>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<int> &TABLE, + digital::trellis_metric_type_t TYPE, + const int *in, short *out); + + template void + viterbi_algorithm_combined<float,short>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<float> &TABLE, + digital::trellis_metric_type_t TYPE, + const float *in, short *out); + + template void + viterbi_algorithm_combined<gr_complex,short>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<gr_complex> &TABLE, + digital::trellis_metric_type_t TYPE, + const gr_complex *in, short *out); + + //-------------- + + template void + viterbi_algorithm_combined<short,int>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<short> &TABLE, + digital::trellis_metric_type_t TYPE, + const short *in, int *out); + + template void + viterbi_algorithm_combined<int,int>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<int> &TABLE, + digital::trellis_metric_type_t TYPE, + const int *in, int *out); + + template void + viterbi_algorithm_combined<float,int>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<float> &TABLE, + digital::trellis_metric_type_t TYPE, + const float *in, int *out); + + template void + viterbi_algorithm_combined<gr_complex,int>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + int D, + const std::vector<gr_complex> &TABLE, + digital::trellis_metric_type_t TYPE, + const gr_complex *in, int *out); + + //=============================================== + + void + siso_algorithm(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + bool POSTI, bool POSTO, + float (*p2mymin)(float,float), + const float *priori, const float *prioro, float *post//, + //std::vector<float> &alpha, + //std::vector<float> &beta + ) + { + float norm,mm,minm; + std::vector<float> alpha(S*(K+1)); + std::vector<float> beta(S*(K+1)); + + if(S0<0) { // initial state not specified + for(int i=0;i<S;i++) alpha[0*S+i]=0; + } + else { + for(int i=0;i<S;i++) alpha[0*S+i]=INF; + alpha[0*S+S0]=0.0; + } + + for(int k=0;k<K;k++) { // forward recursion + norm=INF; + for(int j=0;j<S;j++) { + minm=INF; + for(unsigned int i=0;i<PS[j].size();i++) { + //int i0 = j*I+i; + mm=alpha[k*S+PS[j][i]]+priori[k*I+PI[j][i]]+prioro[k*O+OS[PS[j][i]*I+PI[j][i]]]; + minm=(*p2mymin)(minm,mm); + } + alpha[(k+1)*S+j]=minm; + if(minm<norm) norm=minm; + } + for(int j=0;j<S;j++) + alpha[(k+1)*S+j]-=norm; // normalize total metrics so they do not explode + } + + if(SK<0) { // final state not specified + for(int i=0;i<S;i++) beta[K*S+i]=0; + } + else { + for(int i=0;i<S;i++) beta[K*S+i]=INF; + beta[K*S+SK]=0.0; + } + + for(int k=K-1;k>=0;k--) { // backward recursion + norm=INF; + for(int j=0;j<S;j++) { + minm=INF; + for(int i=0;i<I;i++) { + int i0 = j*I+i; + mm=beta[(k+1)*S+NS[i0]]+priori[k*I+i]+prioro[k*O+OS[i0]]; + minm=(*p2mymin)(minm,mm); + } + beta[k*S+j]=minm; + if(minm<norm) norm=minm; + } + for(int j=0;j<S;j++) + beta[k*S+j]-=norm; // normalize total metrics so they do not explode + } + + if(POSTI && POSTO) + { + for(int k=0;k<K;k++) { // input combining + norm=INF; + for(int i=0;i<I;i++) { + minm=INF; + for(int j=0;j<S;j++) { + mm=alpha[k*S+j]+prioro[k*O+OS[j*I+i]]+beta[(k+1)*S+NS[j*I+i]]; + minm=(*p2mymin)(minm,mm); + } + post[k*(I+O)+i]=minm; + if(minm<norm) norm=minm; + } + for(int i=0;i<I;i++) + post[k*(I+O)+i]-=norm; // normalize metrics + } + + for(int k=0;k<K;k++) { // output combining + norm=INF; + for(int n=0;n<O;n++) { + minm=INF; + for(int j=0;j<S;j++) { + for(int i=0;i<I;i++) { + mm= (n==OS[j*I+i] ? alpha[k*S+j]+priori[k*I+i]+beta[(k+1)*S+NS[j*I+i]] : INF); + minm=(*p2mymin)(minm,mm); + } + } + post[k*(I+O)+I+n]=minm; + if(minm<norm) norm=minm; + } + for(int n=0;n<O;n++) + post[k*(I+O)+I+n]-=norm; // normalize metrics + } + } + else if(POSTI) + { + for(int k=0;k<K;k++) { // input combining + norm=INF; + for(int i=0;i<I;i++) { + minm=INF; + for(int j=0;j<S;j++) { + mm=alpha[k*S+j]+prioro[k*O+OS[j*I+i]]+beta[(k+1)*S+NS[j*I+i]]; + minm=(*p2mymin)(minm,mm); + } + post[k*I+i]=minm; + if(minm<norm) norm=minm; + } + for(int i=0;i<I;i++) + post[k*I+i]-=norm; // normalize metrics + } + } + else if(POSTO) + { + for(int k=0;k<K;k++) { // output combining + norm=INF; + for(int n=0;n<O;n++) { + minm=INF; + for(int j=0;j<S;j++) { + for(int i=0;i<I;i++) { + mm= (n==OS[j*I+i] ? alpha[k*S+j]+priori[k*I+i]+beta[(k+1)*S+NS[j*I+i]] : INF); + minm=(*p2mymin)(minm,mm); + } + } + post[k*O+n]=minm; + if(minm<norm) norm=minm; + } + for(int n=0;n<O;n++) + post[k*O+n]-=norm; // normalize metrics + } + } + else + throw std::runtime_error("Not both POSTI and POSTO can be false."); + } + + //=========================================================== + + template <class T> void + siso_algorithm_combined(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + bool POSTI, bool POSTO, + float (*p2mymin)(float,float), + int D, + const std::vector<T> &TABLE, + digital::trellis_metric_type_t TYPE, + const float *priori, const T *observations, float *post) + { + float norm,mm,minm; + std::vector<float> alpha(S*(K+1)); + std::vector<float> beta(S*(K+1)); + float *prioro = new float[O*K]; + + if(S0<0) { // initial state not specified + for(int i=0;i<S;i++) alpha[0*S+i]=0; + } + else { + for(int i=0;i<S;i++) alpha[0*S+i]=INF; + alpha[0*S+S0]=0.0; + } + + for(int k=0;k<K;k++) { // forward recursion + calc_metric(O, D, TABLE, &(observations[k*D]), &(prioro[k*O]),TYPE); // calc metrics + norm=INF; + for(int j=0;j<S;j++) { + minm=INF; + for(unsigned int i=0;i<PS[j].size();i++) { + //int i0 = j*I+i; + mm=alpha[k*S+PS[j][i]]+priori[k*I+PI[j][i]]+prioro[k*O+OS[PS[j][i]*I+PI[j][i]]]; + minm=(*p2mymin)(minm,mm); + } + alpha[(k+1)*S+j]=minm; + if(minm<norm) norm=minm; + } + for(int j=0;j<S;j++) + alpha[(k+1)*S+j]-=norm; // normalize total metrics so they do not explode + } + + if(SK<0) { // final state not specified + for(int i=0;i<S;i++) beta[K*S+i]=0; + } + else { + for(int i=0;i<S;i++) beta[K*S+i]=INF; + beta[K*S+SK]=0.0; + } + + for(int k=K-1;k>=0;k--) { // backward recursion + norm=INF; + for(int j=0;j<S;j++) { + minm=INF; + for(int i=0;i<I;i++) { + int i0 = j*I+i; + mm=beta[(k+1)*S+NS[i0]]+priori[k*I+i]+prioro[k*O+OS[i0]]; + minm=(*p2mymin)(minm,mm); + } + beta[k*S+j]=minm; + if(minm<norm) norm=minm; + } + for(int j=0;j<S;j++) + beta[k*S+j]-=norm; // normalize total metrics so they do not explode + } + + if(POSTI && POSTO) + { + for(int k=0;k<K;k++) { // input combining + norm=INF; + for(int i=0;i<I;i++) { + minm=INF; + for(int j=0;j<S;j++) { + mm=alpha[k*S+j]+prioro[k*O+OS[j*I+i]]+beta[(k+1)*S+NS[j*I+i]]; + minm=(*p2mymin)(minm,mm); + } + post[k*(I+O)+i]=minm; + if(minm<norm) norm=minm; + } + for(int i=0;i<I;i++) + post[k*(I+O)+i]-=norm; // normalize metrics + } + + for(int k=0;k<K;k++) { // output combining + norm=INF; + for(int n=0;n<O;n++) { + minm=INF; + for(int j=0;j<S;j++) { + for(int i=0;i<I;i++) { + mm= (n==OS[j*I+i] ? alpha[k*S+j]+priori[k*I+i]+beta[(k+1)*S+NS[j*I+i]] : INF); + minm=(*p2mymin)(minm,mm); + } + } + post[k*(I+O)+I+n]=minm; + if(minm<norm) norm=minm; + } + for(int n=0;n<O;n++) + post[k*(I+O)+I+n]-=norm; // normalize metrics + } + } + else if(POSTI) + { + for(int k=0;k<K;k++) { // input combining + norm=INF; + for(int i=0;i<I;i++) { + minm=INF; + for(int j=0;j<S;j++) { + mm=alpha[k*S+j]+prioro[k*O+OS[j*I+i]]+beta[(k+1)*S+NS[j*I+i]]; + minm=(*p2mymin)(minm,mm); + } + post[k*I+i]=minm; + if(minm<norm) norm=minm; + } + for(int i=0;i<I;i++) + post[k*I+i]-=norm; // normalize metrics + } + } + else if(POSTO) { + for(int k=0;k<K;k++) { // output combining + norm=INF; + for(int n=0;n<O;n++) { + minm=INF; + for(int j=0;j<S;j++) { + for(int i=0;i<I;i++) { + mm= (n==OS[j*I+i] ? alpha[k*S+j]+priori[k*I+i]+beta[(k+1)*S+NS[j*I+i]] : INF); + minm=(*p2mymin)(minm,mm); + } + } + post[k*O+n]=minm; + if(minm<norm) norm=minm; + } + for(int n=0;n<O;n++) + post[k*O+n]-=norm; // normalize metrics + } + } + else + throw std::runtime_error ("Not both POSTI and POSTO can be false."); + + delete [] prioro; + } + + //--------- + + template void + siso_algorithm_combined<short>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + bool POSTI, bool POSTO, + float (*p2mymin)(float,float), + int D, + const std::vector<short> &TABLE, + digital::trellis_metric_type_t TYPE, + const float *priori, const short *observations, float *post); + + template void + siso_algorithm_combined<int>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + bool POSTI, bool POSTO, + float (*p2mymin)(float,float), + int D, + const std::vector<int> &TABLE, + digital::trellis_metric_type_t TYPE, + const float *priori, const int *observations, float *post); + + template void + siso_algorithm_combined<float>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + bool POSTI, bool POSTO, + float (*p2mymin)(float,float), + int D, + const std::vector<float> &TABLE, + digital::trellis_metric_type_t TYPE, + const float *priori, const float *observations, float *post); + + template void + siso_algorithm_combined<gr_complex>(int I, int S, int O, + const std::vector<int> &NS, + const std::vector<int> &OS, + const std::vector< std::vector<int> > &PS, + const std::vector< std::vector<int> > &PI, + int K, + int S0,int SK, + bool POSTI, bool POSTO, + float (*p2mymin)(float,float), + int D, + const std::vector<gr_complex> &TABLE, + digital::trellis_metric_type_t TYPE, + const float *priori, const gr_complex *observations, float *post); + + //========================================================= + + template<class Ti, class To> void + sccc_decoder_combined(const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, int blocklength, int iterations, + float (*p2mymin)(float,float), + int D, const std::vector<Ti> &TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const Ti *observations, To *data) + { + //allocate space for priori, prioro and posti of inner FSM + std::vector<float> ipriori(blocklength*FSMi.I(),0.0); + std::vector<float> iprioro(blocklength*FSMi.O()); + std::vector<float> iposti(blocklength*FSMi.I()); + + //allocate space for priori, prioro and posto of outer FSM + std::vector<float> opriori(blocklength*FSMo.I(),0.0); + std::vector<float> oprioro(blocklength*FSMo.O()); + std::vector<float> oposti(blocklength*FSMo.I()); + std::vector<float> oposto(blocklength*FSMo.O()); + + // turn observations to neg-log-priors + for(int k=0;k<blocklength;k++) { + calc_metric(FSMi.O(), D, TABLE, &(observations[k*D]), &(iprioro[k*FSMi.O()]),METRIC_TYPE); + iprioro[k*FSMi.O()] *= scaling; + } + + for(int rep=0;rep<iterations;rep++) { + // run inner SISO + siso_algorithm(FSMi.I(),FSMi.S(),FSMi.O(), + FSMi.NS(), FSMi.OS(), FSMi.PS(), FSMi.PI(), + blocklength, + STi0,STiK, + true, false, + p2mymin, + &(ipriori[0]), &(iprioro[0]), &(iposti[0])); + + //interleave soft info inner -> outer + for(int k=0;k<blocklength;k++) { + int ki = INTERLEAVER.DEINTER()[k]; + //for(int i=0;i<FSMi.I();i++) { + //oprioro[k*FSMi.I()+i]=iposti[ki*FSMi.I()+i]; + //} + memcpy(&(oprioro[k*FSMi.I()]),&(iposti[ki*FSMi.I()]),FSMi.I()*sizeof(float)); + } + + // run outer SISO + + if(rep<iterations-1) { // do not produce posti + siso_algorithm(FSMo.I(),FSMo.S(),FSMo.O(), + FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(), + blocklength, + STo0,SToK, + false, true, + p2mymin, + &(opriori[0]), &(oprioro[0]), &(oposto[0])); + + //interleave soft info outer --> inner + for(int k=0;k<blocklength;k++) { + int ki = INTERLEAVER.DEINTER()[k]; + //for(int i=0;i<FSMi.I();i++) { + //ipriori[ki*FSMi.I()+i]=oposto[k*FSMi.I()+i]; + //} + memcpy(&(ipriori[ki*FSMi.I()]),&(oposto[k*FSMi.I()]),FSMi.I()*sizeof(float)); + } + } + else // produce posti but not posto + + siso_algorithm(FSMo.I(),FSMo.S(),FSMo.O(), + FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(), + blocklength, + STo0,SToK, + true, false, + p2mymin, + &(opriori[0]), &(oprioro[0]), &(oposti[0])); + + /* + viterbi_algorithm(FSMo.I(),FSMo.S(),FSMo.O(), + FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(), + blocklength, + STo0,SToK, + &(oprioro[0]), data + ); + */ + } + + // generate hard decisions + for(int k=0;k<blocklength;k++) { + float min=INF; + int mini=0; + for(int i=0;i<FSMo.I();i++) { + if(oposti[k*FSMo.I()+i]<min) { + min=oposti[k*FSMo.I()+i]; + mini=i; + } + } + data[k]=(To)mini; + } + } + + //------- + + template void + sccc_decoder_combined<float,unsigned char>(const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, int blocklength, + int iterations, + float (*p2mymin)(float,float), + int D, const std::vector<float> &TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const float *observations, unsigned char *data); + + template void + sccc_decoder_combined<float,short>(const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, int blocklength, + int iterations, + float (*p2mymin)(float,float), + int D, const std::vector<float> &TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const float *observations, short *data); + + template void + sccc_decoder_combined<float,int>(const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, int blocklength, + int iterations, + float (*p2mymin)(float,float), + int D, const std::vector<float> &TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const float *observations, int *data); + + template void + sccc_decoder_combined<gr_complex,unsigned char>(const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, int blocklength, + int iterations, + float (*p2mymin)(float,float), + int D, const std::vector<gr_complex> &TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const gr_complex *observations, unsigned char *data + ); + + template void + sccc_decoder_combined<gr_complex,short>(const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, int blocklength, + int iterations, + float (*p2mymin)(float,float), + int D, const std::vector<gr_complex> &TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const gr_complex *observations, short *data); + + template void + sccc_decoder_combined<gr_complex,int>(const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, int blocklength, + int iterations, + float (*p2mymin)(float,float), + int D, const std::vector<gr_complex> &TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const gr_complex *observations, int *data); + + //========================================================= + + template<class T> void + sccc_decoder(const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, int blocklength, int iterations, + float (*p2mymin)(float,float), + const float *iprioro, T *data) + { + //allocate space for priori, and posti of inner FSM + std::vector<float> ipriori(blocklength*FSMi.I(),0.0); + std::vector<float> iposti(blocklength*FSMi.I()); + + //allocate space for priori, prioro and posto of outer FSM + std::vector<float> opriori(blocklength*FSMo.I(),0.0); + std::vector<float> oprioro(blocklength*FSMo.O()); + std::vector<float> oposti(blocklength*FSMo.I()); + std::vector<float> oposto(blocklength*FSMo.O()); + + for(int rep=0;rep<iterations;rep++) { + // run inner SISO + siso_algorithm(FSMi.I(),FSMi.S(),FSMi.O(), + FSMi.NS(), FSMi.OS(), FSMi.PS(), FSMi.PI(), + blocklength, + STi0,STiK, + true, false, + p2mymin, + &(ipriori[0]), &(iprioro[0]), &(iposti[0])); + + //interleave soft info inner -> outer + for(int k=0;k<blocklength;k++) { + int ki = INTERLEAVER.DEINTER()[k]; + //for(int i=0;i<FSMi.I();i++) { + //oprioro[k*FSMi.I()+i]=iposti[ki*FSMi.I()+i]; + //} + memcpy(&(oprioro[k*FSMi.I()]),&(iposti[ki*FSMi.I()]),FSMi.I()*sizeof(float)); + } + + // run outer SISO + + if(rep<iterations-1) { // do not produce posti + siso_algorithm(FSMo.I(),FSMo.S(),FSMo.O(), + FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(), + blocklength, + STo0,SToK, + false, true, + p2mymin, + &(opriori[0]), &(oprioro[0]), &(oposto[0])); + + //interleave soft info outer --> inner + for(int k=0;k<blocklength;k++) { + int ki = INTERLEAVER.DEINTER()[k]; + //for(int i=0;i<FSMi.I();i++) { + //ipriori[ki*FSMi.I()+i]=oposto[k*FSMi.I()+i]; + //} + memcpy(&(ipriori[ki*FSMi.I()]),&(oposto[k*FSMi.I()]),FSMi.I()*sizeof(float)); + } + } + else {// produce posti but not posto + siso_algorithm(FSMo.I(),FSMo.S(),FSMo.O(), + FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(), + blocklength, + STo0,SToK, + true, false, + p2mymin, + &(opriori[0]), &(oprioro[0]), &(oposti[0])); + + /* + viterbi_algorithm(FSMo.I(),FSMo.S(),FSMo.O(), + FSMo.NS(), FSMo.OS(), FSMo.PS(), FSMo.PI(), + blocklength, + STo0,SToK, + &(oprioro[0]), data); + */ + } + } // end iterations + + // generate hard decisions + for(int k=0;k<blocklength;k++) { + float min=INF; + int mini=0; + for(int i=0;i<FSMo.I();i++) { + if(oposti[k*FSMo.I()+i]<min) { + min=oposti[k*FSMo.I()+i]; + mini=i; + } + } + data[k]=(T)mini; + } + } + + //------- + + template void + sccc_decoder<unsigned char>(const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, int blocklength, + int iterations, + float (*p2mymin)(float,float), + const float *iprioro, unsigned char *data); + + template void + sccc_decoder<short>(const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, int blocklength, + int iterations, + float (*p2mymin)(float,float), + const float *iprioro, short *data); + + template void + sccc_decoder<int>(const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, int blocklength, + int iterations, + float (*p2mymin)(float,float), + const float *iprioro, int *data); + + //==================================================== + + template<class T> void + pccc_decoder(const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, int blocklength, + int iterations, + float (*p2mymin)(float,float), + const float *cprioro, T *data) + { + //allocate space for priori, prioro and posti of FSM1 + std::vector<float> priori1(blocklength*FSM1.I(),0.0); + std::vector<float> prioro1(blocklength*FSM1.O()); + std::vector<float> posti1(blocklength*FSM1.I()); + + //allocate space for priori, prioro and posti of FSM2 + std::vector<float> priori2(blocklength*FSM2.I(),0.0); + std::vector<float> prioro2(blocklength*FSM2.O()); + std::vector<float> posti2(blocklength*FSM2.I()); + + //generate prioro1,2 (metrics are not updated per iteration: this is not the best you can do...) + for(int k=0;k<blocklength;k++) { + //std::cout << k << std::endl; + for(int i=0;i<FSM1.O();i++) { + float x=cprioro[k*FSM1.O()*FSM2.O()+i*FSM1.O()+0]; + for(int j=1;j<FSM2.O();j++) + x = (*p2mymin)(x,cprioro[k*FSM1.O()*FSM2.O()+i*FSM1.O()+j]); + prioro1[k*FSM1.O()+i]=x; + //std::cout << prioro1[k*FSM1.O()+i] << ", "; + } + //std::cout << std::endl; + for(int i=0;i<FSM2.O();i++) { + float x=cprioro[k*FSM1.O()*FSM2.O()+0*FSM1.O()+i]; + for(int j=1;j<FSM1.O();j++) + x = (*p2mymin)(x,cprioro[k*FSM1.O()*FSM2.O()+j*FSM1.O()+i]); + prioro2[k*FSM2.O()+i]=x; + } + } + + for(int rep=0;rep<iterations;rep++) { + // run SISO 1 + siso_algorithm(FSM1.I(),FSM1.S(),FSM1.O(), + FSM1.NS(), FSM1.OS(), FSM1.PS(), FSM1.PI(), + blocklength, + ST10,ST1K, + true, false, + p2mymin, + &(priori1[0]), &(prioro1[0]), &(posti1[0])); + + //for(int k=0;k<blocklength;k++){ + //for(int i=0;i<FSM1.I();i++) + //std::cout << posti1[k*FSM1.I()+i] << ", "; + //std::cout << std::endl; + //} + + //interleave soft info 1 -> 2 + for(int k=0;k<blocklength;k++) { + int ki = INTERLEAVER.INTER()[k]; + //for(int i=0;i<FSMi.I();i++) { + //oprioro[k*FSMi.I()+i]=iposti[ki*FSMi.I()+i]; + //} + memcpy(&(priori2[k*FSM2.I()]),&(posti1[ki*FSM1.I()]),FSM1.I()*sizeof(float)); + } + + // run SISO 2 + siso_algorithm(FSM2.I(),FSM2.S(),FSM2.O(), + FSM2.NS(), FSM2.OS(), FSM2.PS(), FSM2.PI(), + blocklength, + ST20,ST2K, + true, false, + p2mymin, + &(priori2[0]), &(prioro2[0]), &(posti2[0])); + + //interleave soft info 2 --> 1 + for(int k=0;k<blocklength;k++) { + int ki = INTERLEAVER.INTER()[k]; + //for(int i=0;i<FSMi.I();i++) { + //ipriori[ki*FSMi.I()+i]=oposto[k*FSMi.I()+i]; + //} + memcpy(&(priori1[ki*FSM1.I()]),&(posti2[k*FSM2.I()]),FSM1.I()*sizeof(float)); + } + } // end iterations + + // generate hard decisions + for(int k=0;k<blocklength;k++) { + for(int i=0;i<FSM1.I();i++) + posti1[k*FSM1.I()+i] = (*p2mymin)(priori1[k*FSM1.I()+i],posti1[k*FSM1.I()+i]); + float min=INF; + int mini=0; + for(int i=0;i<FSM1.I();i++) { + if(posti1[k*FSM1.I()+i]<min) { + min=posti1[k*FSM1.I()+i]; + mini=i; + } + } + data[k]=(T)mini; + //std::cout << data[k] << ", "<< std::endl; + } + //std::cout << std::endl; + } + + //---------------- + + template void + pccc_decoder<unsigned char>(const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, int blocklength, + int iterations, + float (*p2mymin)(float,float), + const float *cprioro, unsigned char *data); + + template void + pccc_decoder<short>(const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, int blocklength, + int iterations, + float (*p2mymin)(float,float), + const float *cprioro, short *data); + + template void + pccc_decoder<int>(const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, int blocklength, + int iterations, + float (*p2mymin)(float,float), + const float *cprioro, int *data); + + //---------------- + + template<class Ti, class To> void + pccc_decoder_combined(const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, int blocklength, + int iterations, + float (*p2mymin)(float,float), + int D, const std::vector<Ti> &TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const Ti *observations, To *data) + { + //allocate space for cprioro + std::vector<float> cprioro(blocklength*FSM1.O()*FSM2.O(),0.0); + + //allocate space for priori, prioro and posti of FSM1 + std::vector<float> priori1(blocklength*FSM1.I(),0.0); + std::vector<float> prioro1(blocklength*FSM1.O()); + std::vector<float> posti1(blocklength*FSM1.I()); + + //allocate space for priori, prioro and posti of FSM2 + std::vector<float> priori2(blocklength*FSM2.I(),0.0); + std::vector<float> prioro2(blocklength*FSM2.O()); + std::vector<float> posti2(blocklength*FSM2.I()); + + // turn observations to neg-log-priors for cprioiro + int O=FSM1.O()*FSM2.O(); + for(int k=0;k<blocklength;k++) { + calc_metric(O, D, TABLE, &(observations[k*D]), &(cprioro[k*O]),METRIC_TYPE); + cprioro[k*O] *= scaling; + } + + //generate prioro1,2 (metrics are not updated per iteration: this is not the best you can do...) + for(int k=0;k<blocklength;k++) { + //std::cout << k << std::endl; + for(int i=0;i<FSM1.O();i++) { + float x=cprioro[k*FSM1.O()*FSM2.O()+i*FSM1.O()+0]; + for(int j=1;j<FSM2.O();j++) + x = (*p2mymin)(x,cprioro[k*FSM1.O()*FSM2.O()+i*FSM1.O()+j]); + prioro1[k*FSM1.O()+i]=x; + //std::cout << prioro1[k*FSM1.O()+i] << ", "; + } + //std::cout << std::endl; + for(int i=0;i<FSM2.O();i++) { + float x=cprioro[k*FSM1.O()*FSM2.O()+0*FSM1.O()+i]; + for(int j=1;j<FSM1.O();j++) + x = (*p2mymin)(x,cprioro[k*FSM1.O()*FSM2.O()+j*FSM1.O()+i]); + prioro2[k*FSM2.O()+i]=x; + } + } + + for(int rep=0;rep<iterations;rep++) { + // run SISO 1 + siso_algorithm(FSM1.I(),FSM1.S(),FSM1.O(), + FSM1.NS(), FSM1.OS(), FSM1.PS(), FSM1.PI(), + blocklength, + ST10,ST1K, + true, false, + p2mymin, + &(priori1[0]), &(prioro1[0]), &(posti1[0])); + + //for(int k=0;k<blocklength;k++){ + //for(int i=0;i<FSM1.I();i++) + //std::cout << posti1[k*FSM1.I()+i] << ", "; + //std::cout << std::endl; + //} + + //interleave soft info 1 -> 2 + for(int k=0;k<blocklength;k++) { + int ki = INTERLEAVER.INTER()[k]; + //for(int i=0;i<FSMi.I();i++) { + //oprioro[k*FSMi.I()+i]=iposti[ki*FSMi.I()+i]; + //} + memcpy(&(priori2[k*FSM2.I()]),&(posti1[ki*FSM1.I()]),FSM1.I()*sizeof(float)); + } + + // run SISO 2 + siso_algorithm(FSM2.I(),FSM2.S(),FSM2.O(), + FSM2.NS(), FSM2.OS(), FSM2.PS(), FSM2.PI(), + blocklength, + ST20,ST2K, + true, false, + p2mymin, + &(priori2[0]), &(prioro2[0]), &(posti2[0])); + + //interleave soft info 2 --> 1 + for(int k=0;k<blocklength;k++) { + int ki = INTERLEAVER.INTER()[k]; + //for(int i=0;i<FSMi.I();i++) { + //ipriori[ki*FSMi.I()+i]=oposto[k*FSMi.I()+i]; + //} + memcpy(&(priori1[ki*FSM1.I()]),&(posti2[k*FSM2.I()]),FSM1.I()*sizeof(float)); + } + } // end iterations + + // generate hard decisions + for(int k=0;k<blocklength;k++) { + for(int i=0;i<FSM1.I();i++) + posti1[k*FSM1.I()+i] = (*p2mymin)(priori1[k*FSM1.I()+i],posti1[k*FSM1.I()+i]); + float min=INF; + int mini=0; + for(int i=0;i<FSM1.I();i++) { + if(posti1[k*FSM1.I()+i]<min) { + min=posti1[k*FSM1.I()+i]; + mini=i; + } + } + data[k]=(To)mini; + //std::cout << data[k] << ", "<< std::endl; + } + //std::cout << std::endl; + } + + template void + pccc_decoder_combined(const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, int blocklength, + int iterations, + float (*p2mymin)(float,float), + int D, const std::vector<float> &TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const float *observations, unsigned char *data); + + template void + pccc_decoder_combined(const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, int blocklength, + int iterations, + float (*p2mymin)(float,float), + int D, const std::vector<float> &TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const float *observations, short *data); + + template void + pccc_decoder_combined(const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, int blocklength, + int iterations, + float (*p2mymin)(float,float), + int D, const std::vector<float> &TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const float *observations, int *data); + + template void + pccc_decoder_combined(const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, int blocklength, + int iterations, + float (*p2mymin)(float,float), + int D, const std::vector<gr_complex> &TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const gr_complex *observations, unsigned char *data); + + template void + pccc_decoder_combined(const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, int blocklength, + int iterations, + float (*p2mymin)(float,float), + int D, const std::vector<gr_complex> &TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const gr_complex *observations, short *data); + + template void + pccc_decoder_combined(const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, int blocklength, + int iterations, + float (*p2mymin)(float,float), + int D, const std::vector<gr_complex> &TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling, + const gr_complex *observations, int *data); + + } /* namespace trellis */ +} /* namespace gr */ diff --git a/gr-trellis/lib/encoder_XX_impl.cc.t b/gr-trellis/lib/encoder_XX_impl.cc.t new file mode 100644 index 0000000000..fdda593d45 --- /dev/null +++ b/gr-trellis/lib/encoder_XX_impl.cc.t @@ -0,0 +1,82 @@ +/* -*- 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 <iostream> + +namespace gr { + namespace trellis { + + @BASE_NAME@::sptr + @BASE_NAME@::make(const fsm &FSM, int ST) + { + return gnuradio::get_initial_sptr + (new @IMPL_NAME@(FSM,ST)); + } + + @IMPL_NAME@::@IMPL_NAME@(const fsm &FSM, int ST) + : gr_sync_block("@BASE_NAME@", + gr_make_io_signature(1, -1, sizeof(@I_TYPE@)), + gr_make_io_signature(1, -1, sizeof(@O_TYPE@))), + d_FSM(FSM), + d_ST(ST) + { + } + + @IMPL_NAME@::~@IMPL_NAME@() + { + } + + int + @IMPL_NAME@::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + int ST_tmp = 0; + int nstreams = input_items.size(); + + for(int m=0;m<nstreams;m++) { + const @I_TYPE@ *in = (const @I_TYPE@*)input_items[m]; + @O_TYPE@ *out = (@O_TYPE@ *) output_items[m]; + ST_tmp = d_ST; + + // per stream processing + for(int i = 0; i < noutput_items; i++) { + out[i] = (@O_TYPE@)d_FSM.OS()[ST_tmp*d_FSM.I()+in[i]]; // direction of time? + ST_tmp = (int)d_FSM.NS()[ST_tmp*d_FSM.I()+in[i]]; + } + // end per stream processing + } + d_ST = ST_tmp; + + return noutput_items; + } + + } /* namespace trellis */ +} /* namespace gr */ diff --git a/gr-trellis/lib/encoder_XX_impl.h.t b/gr-trellis/lib/encoder_XX_impl.h.t new file mode 100644 index 0000000000..949f1182de --- /dev/null +++ b/gr-trellis/lib/encoder_XX_impl.h.t @@ -0,0 +1,54 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <trellis/@BASE_NAME@.h> + +namespace gr { + namespace trellis { + + class @IMPL_NAME@ : public @BASE_NAME@ + { + private: + fsm d_FSM; + int d_ST; + + public: + @IMPL_NAME@(const fsm &FSM, int ST); + ~@IMPL_NAME@(); + + fsm FSM() const { return d_FSM; } + int ST() const { return d_ST; } + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace trellis */ +} /* namespace gr */ + +#endif /* @GUARD_NAME@ */ diff --git a/gr-trellis/lib/fsm.cc b/gr-trellis/lib/fsm.cc new file mode 100644 index 0000000000..16efcd10f2 --- /dev/null +++ b/gr-trellis/lib/fsm.cc @@ -0,0 +1,521 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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 <cstdio> +#include <string> +#include <iostream> +#include <fstream> +#include <stdexcept> +#include <cmath> +#include <stdlib.h> +#include <trellis/base.h> +#include <trellis/fsm.h> + +namespace gr { + namespace trellis { + + fsm::fsm() + { + d_I=0; + d_S=0; + d_O=0; + d_NS.resize(0); + d_OS.resize(0); + d_PS.resize(0); + d_PI.resize(0); + d_TMi.resize(0); + d_TMl.resize(0); + } + + fsm::fsm(const fsm &FSM) + { + d_I=FSM.I(); + d_S=FSM.S(); + d_O=FSM.O(); + d_NS=FSM.NS(); + d_OS=FSM.OS(); + d_PS=FSM.PS(); // is this going to make a deep copy? + d_PI=FSM.PI(); + d_TMi=FSM.TMi(); + d_TMl=FSM.TMl(); + } + + fsm::fsm(int I, int S, int O, const std::vector<int> &NS, const std::vector<int> &OS) + { + d_I=I; + d_S=S; + d_O=O; + d_NS=NS; + d_OS=OS; + + generate_PS_PI(); + generate_TM(); + } + + //###################################################################### + //# Read an FSM specification from a file. + //# Format (hopefully will become more flexible in the future...): + //# I S O (in the first line) + //# blank line + //# Next state matrix (S lines, each with I integers separated by spaces) + //# blank line + //# output symbol matrix (S lines, each with I integers separated by spaces) + //# optional comments + //###################################################################### + fsm::fsm(const char *name) + { + FILE *fsmfile; + + if((fsmfile=fopen(name,"r"))==NULL) + throw std::runtime_error ("fsm::fsm(const char *name): file open error\n"); + //printf("file open error in fsm()\n"); + + if(fscanf(fsmfile,"%d %d %d\n",&d_I,&d_S,&d_O) == EOF) { + if(ferror(fsmfile) != 0) + throw std::runtime_error ("fsm::fsm(const char *name): file read error\n"); + } + + d_NS.resize(d_I*d_S); + d_OS.resize(d_I*d_S); + + for(int i=0;i<d_S;i++) { + for(int j=0;j<d_I;j++) { + if(fscanf(fsmfile,"%d",&(d_NS[i*d_I+j])) == EOF) { + if(ferror(fsmfile) != 0) + throw std::runtime_error ("fsm::fsm(const char *name): file read error\n"); + } + } + } + for(int i=0;i<d_S;i++) { + for(int j=0;j<d_I;j++) { + if(fscanf(fsmfile,"%d",&(d_OS[i*d_I+j])) == EOF) { + if(ferror(fsmfile) != 0) + throw std::runtime_error ("fsm::fsm(const char *name): file read error\n"); + } + } + } + + fclose(fsmfile); + + generate_PS_PI(); + generate_TM(); + } + + //###################################################################### + //# Automatically generate the FSM from the generator matrix + //# of a (n,k) binary convolutional code + //###################################################################### + fsm::fsm(int k, int n, const std::vector<int> &G) + { + // calculate maximum memory requirements for each input stream + std::vector<int> max_mem_x(k,-1); + int max_mem = -1; + for(int i=0;i<k;i++) { + for(int j=0;j<n;j++) { + int mem = -1; + if(G[i*n+j]!=0) + mem=(int)(log(double(G[i*n+j]))/log(2.0)); + if(mem>max_mem_x[i]) + max_mem_x[i]=mem; + if(mem>max_mem) + max_mem=mem; + } + } + + //printf("max_mem_x\n"); + //for(int j=0;j<max_mem_x.size();j++) printf("%d ",max_mem_x[j]); printf("\n"); + + // calculate total memory requirements to set S + int sum_max_mem = 0; + for(int i=0;i<k;i++) + sum_max_mem += max_mem_x[i]; + + //printf("sum_max_mem = %d\n",sum_max_mem); + + d_I=1<<k; + d_S=1<<sum_max_mem; + d_O=1<<n; + + // binary representation of the G matrix + std::vector<std::vector<int> > Gb(k*n); + for(int j=0;j<k*n;j++) { + Gb[j].resize(max_mem+1); + dec2base(G[j],2,Gb[j]); + //printf("Gb\n"); + //for(int m=0;m<Gb[j].size();m++) printf("%d ",Gb[j][m]); printf("\n"); + } + + // alphabet size of each shift register + std::vector<int> bases_x(k); + for(int j=0;j<k ;j++) + bases_x[j] = 1 << max_mem_x[j]; + //printf("bases_x\n"); + //for(int j=0;j<max_mem_x.size();j++) printf("%d ",max_mem_x[j]); printf("\n"); + + d_NS.resize(d_I*d_S); + d_OS.resize(d_I*d_S); + + std::vector<int> sx(k); + std::vector<int> nsx(k); + std::vector<int> tx(k); + std::vector<std::vector<int> > tb(k); + for(int j=0;j<k;j++) + tb[j].resize(max_mem+1); + std::vector<int> inb(k); + std::vector<int> outb(n); + + for(int s=0;s<d_S;s++) { + dec2bases(s,bases_x,sx); // split s into k values, each representing one of the k shift registers + //printf("state = %d \nstates = ",s); + //for(int j=0;j<sx.size();j++) printf("%d ",sx[j]); printf("\n"); + for(int i=0;i<d_I;i++) { + dec2base(i,2,inb); // input in binary + //printf("input = %d \ninputs = ",i); + //for(int j=0;j<inb.size();j++) printf("%d ",inb[j]); printf("\n"); + + // evaluate next state + for(int j=0;j<k;j++) + nsx[j] = (inb[j]*bases_x[j]+sx[j])/2; // next state (for each shift register) MSB first + d_NS[s*d_I+i]=bases2dec(nsx,bases_x); // collect all values into the new state + + // evaluate transitions + for(int j=0;j<k;j++) + tx[j] = inb[j]*bases_x[j]+sx[j]; // transition (for each shift register)MSB first + for(int j=0;j<k;j++) { + dec2base(tx[j],2,tb[j]); // transition in binary + //printf("transition = %d \ntransitions = ",tx[j]); + //for(int m=0;m<tb[j].size();m++) printf("%d ",tb[j][m]); printf("\n"); + } + + // evaluate outputs + for(int nn=0;nn<n;nn++) { + outb[nn] = 0; + for(int j=0;j<k;j++) { + for(int m=0;m<max_mem+1;m++) + outb[nn] = (outb[nn] + Gb[j*n+nn][m]*tb[j][m]) % 2; // careful: polynomial 1+D ir represented as 110, not as 011 + //printf("output %d equals %d\n",nn,outb[nn]); + } + } + d_OS[s*d_I+i] = base2dec(outb,2); + } + } + + generate_PS_PI(); + generate_TM(); + } + + //###################################################################### + //# Automatically generate an FSM specification describing the + //# ISI for a channel + //# of length ch_length and a modulation of size mod_size + //###################################################################### + fsm::fsm(int mod_size, int ch_length) + { + d_I=mod_size; + d_S=(int) (pow(1.0*d_I,1.0*ch_length-1)+0.5); + d_O=d_S*d_I; + + d_NS.resize(d_I*d_S); + d_OS.resize(d_I*d_S); + + for(int s=0;s<d_S;s++) { + for(int i=0;i<d_I;i++) { + int t=i*d_S+s; + d_NS[s*d_I+i] = t/d_I; + d_OS[s*d_I+i] = t; + } + } + + generate_PS_PI(); + generate_TM(); + } + + //###################################################################### + //# Automatically generate an FSM specification describing the + //# the trellis for a CPM with h=K/P (relatively prime), + //# alphabet size M, and frequency pulse duration L symbols + //# + //# This FSM is based on the paper by B. Rimoldi + //# "A decomposition approach to CPM", IEEE Trans. Info Theory, March 1988 + //# See also my own notes at http://www.eecs.umich.edu/~anastas/docs/cpm.pdf + //###################################################################### + fsm::fsm(int P, int M, int L) + { + d_I=M; + d_S=(int)(pow(1.0*M,1.0*L-1)+0.5)*P; + d_O=(int)(pow(1.0*M,1.0*L)+0.5)*P; + + d_NS.resize(d_I*d_S); + d_OS.resize(d_I*d_S); + int nv; + for(int s=0;s<d_S;s++) { + for(int i=0;i<d_I;i++) { + int s1=s/P; + int v=s%P; + int ns1= (i*(int)(pow(1.0*M,1.0*(L-1))+0.5)+s1)/M; + if (L==1) + nv=(i+v)%P; + else + nv=(s1%M+v)%P; + d_NS[s*d_I+i] = ns1*P+nv; + d_OS[s*d_I+i] = i*d_S+s; + } + } + + generate_PS_PI(); + generate_TM(); + } + + //###################################################################### + //# Automatically generate an FSM specification describing the + //# the joint trellis of fsm1 and fsm2 + //###################################################################### + fsm::fsm(const fsm &FSM1, const fsm &FSM2) + { + d_I=FSM1.I()*FSM2.I(); + d_S=FSM1.S()*FSM2.S(); + d_O=FSM1.O()*FSM2.O(); + + d_NS.resize(d_I*d_S); + d_OS.resize(d_I*d_S); + + for(int s=0;s<d_S;s++) { + for(int i=0;i<d_I;i++) { + int s1=s/FSM2.S(); + int s2=s%FSM2.S(); + int i1=i/FSM2.I(); + int i2=i%FSM2.I(); + d_NS[s*d_I+i] = FSM1.NS()[s1 * FSM1.I() + i1] * FSM2.S() + FSM2.NS()[s2 * FSM2.I() + i2]; + d_OS[s*d_I+i] = FSM1.OS()[s1 * FSM1.I() + i1] * FSM2.O() + FSM2.OS()[s2 * FSM2.I() + i2]; + } + } + + generate_PS_PI(); + generate_TM(); + } + + //###################################################################### + //# Generate a new FSM representing n stages through the original FSM + //# AKA radix-n FSM + //###################################################################### + fsm::fsm(const fsm &FSM, int n) + { + d_I=(int) (pow(1.0*FSM.I(),1.0*n)+0.5); + d_S=FSM.S(); + d_O=(int) (pow(1.0*FSM.O(),1.0*n)+0.5); + + d_NS.resize(d_I*d_S); + d_OS.resize(d_I*d_S); + + for(int s=0;s<d_S;s++ ) { + for(int i=0;i<d_I;i++ ) { + std::vector<int> ii(n); + dec2base(i,FSM.I(),ii); + std::vector<int> oo(n); + int ns=s; + for(int k=0;k<n;k++) { + oo[k]=FSM.OS()[ns*FSM.I()+ii[k]]; + ns=FSM.NS()[ns*FSM.I()+ii[k]]; + } + d_NS[s*d_I+i]=ns; + d_OS[s*d_I+i]=base2dec(oo,FSM.O()); + } + } + + generate_PS_PI(); + generate_TM(); + } + + //###################################################################### + //# generate the PS and PI tables for later use + //###################################################################### + void + fsm::generate_PS_PI() + { + d_PS.resize(d_S); + d_PI.resize(d_S); + + for(int i=0;i<d_S;i++) { + d_PS[i].resize(d_I*d_S); // max possible size + d_PI[i].resize(d_I*d_S); + int j=0; + for(int ii=0;ii<d_S;ii++) for(int jj=0;jj<d_I;jj++) { + if(d_NS[ii*d_I+jj]!=i) continue; + d_PS[i][j]=ii; + d_PI[i][j]=jj; + j++; + } + d_PS[i].resize(j); + d_PI[i].resize(j); + } + } + + //###################################################################### + //# generate the termination matrices TMl and TMi for later use + //###################################################################### + void + fsm::generate_TM() + { + d_TMi.resize(d_S*d_S); + d_TMl.resize(d_S*d_S); + + for(int i=0;i<d_S*d_S;i++) { + d_TMi[i] = -1; // no meaning + d_TMl[i] = d_S; //infinity: you need at most S-1 steps + if (i/d_S == i%d_S) + d_TMl[i] = 0; + } + + for(int s=0;s<d_S;s++) { + bool done = false; + int attempts = 0; + while (done == false && attempts < d_S-1) { + done = find_es(s); + attempts ++; + } + if (done == false && d_S > 1) { + //throw std::runtime_error ("fsm::generate_TM(): FSM appears to be disconnected\n"); + printf("fsm::generate_TM(): FSM appears to be disconnected\n"); + printf("state %d cannot be reached from all other states\n",s); + } + } + } + + // find a path from any state to the ending state "es" + bool + fsm::find_es(int es) + { + bool done = true; + for(int s=0;s<d_S;s++) { + if(d_TMl[s*d_S+es] < d_S) + continue; + int minl=d_S; + int mini=-1; + for(int i=0;i<d_I;i++) { + if( 1 + d_TMl[d_NS[s*d_I+i]*d_S+es] < minl) { + minl = 1 + d_TMl[d_NS[s*d_I+i]*d_S+es]; + mini = i; + } + } + if (mini != -1) { + d_TMl[s*d_S+es]=minl; + d_TMi[s*d_S+es]=mini; + } + else + done = false; + } + return done; + } + + //###################################################################### + //# generate trellis representation of FSM as an SVG file + //###################################################################### + void + fsm::write_trellis_svg(std::string filename, int number_stages) + { + std::ofstream trellis_fname (filename.c_str()); + if(!trellis_fname) { + std::cout << "file not found " << std::endl ; exit(-1); + } + const int TRELLIS_Y_OFFSET = 30; + const int TRELLIS_X_OFFSET = 20; + const int STAGE_LABEL_Y_OFFSET = 25; + const int STAGE_LABEL_X_OFFSET = 20; + const int STATE_LABEL_Y_OFFSET = 30; + const int STATE_LABEL_X_OFFSET = 5; + const int STAGE_STATE_OFFSETS = 10; + // std::cout << "################## BEGIN SVG TRELLIS PIC #####################" << std::endl; + trellis_fname << "<svg viewBox = \"0 0 200 200\" version = \"1.1\">" << std::endl; + + for(int stage_num = 0;stage_num < number_stages;stage_num ++) { + // draw states + for(int state_num = 0;state_num < d_S ; state_num ++ ) { + trellis_fname << "<circle cx = \"" << stage_num * STAGE_STATE_OFFSETS + TRELLIS_X_OFFSET << + "\" cy = \"" << state_num * STAGE_STATE_OFFSETS + TRELLIS_Y_OFFSET << "\" r = \"1\"/>" << std::endl; + //draw branches + if(stage_num != number_stages-1) { + for(int branch_num = 0;branch_num < d_I; branch_num++) { + trellis_fname << "<line x1 =\"" << STAGE_STATE_OFFSETS * stage_num+ TRELLIS_X_OFFSET << "\" "; + trellis_fname << "y1 =\"" << state_num * STAGE_STATE_OFFSETS + TRELLIS_Y_OFFSET<< "\" "; + trellis_fname << "x2 =\"" << STAGE_STATE_OFFSETS *stage_num + STAGE_STATE_OFFSETS+ TRELLIS_X_OFFSET << "\" "; + trellis_fname << "y2 =\"" << d_NS[d_I * state_num + branch_num] * STAGE_STATE_OFFSETS + TRELLIS_Y_OFFSET << "\" "; + trellis_fname << " stroke-dasharray = \"3," << branch_num << "\" "; + trellis_fname << " stroke = \"black\" stroke-width = \"0.3\"/>" << std::endl; + } + } + } + } + // label the stages + trellis_fname << "<g font-size = \"4\" font= \"times\" fill = \"black\">" << std::endl; + for(int stage_num = 0;stage_num < number_stages ;stage_num ++) { + trellis_fname << "<text x = \"" << stage_num * STAGE_STATE_OFFSETS + STAGE_LABEL_X_OFFSET << + "\" y = \"" << STAGE_LABEL_Y_OFFSET << "\" >" << std::endl; + trellis_fname << stage_num << std::endl; + trellis_fname << "</text>" << std::endl; + } + trellis_fname << "</g>" << std::endl; + + // label the states + trellis_fname << "<g font-size = \"4\" font= \"times\" fill = \"black\">" << std::endl; + for(int state_num = 0;state_num < d_S ; state_num ++) { + trellis_fname << "<text y = \"" << state_num * STAGE_STATE_OFFSETS + STATE_LABEL_Y_OFFSET << + "\" x = \"" << STATE_LABEL_X_OFFSET << "\" >" << std::endl; + trellis_fname << state_num << std::endl; + trellis_fname << "</text>" << std::endl; + } + trellis_fname << "</g>" << std::endl; + + trellis_fname << "</svg>" << std::endl; + // std::cout << "################## END SVG TRELLIS PIC ##################### " << std::endl; + trellis_fname.close(); + } + + //###################################################################### + //# Write trellis specification to a text file, + //# in the same format used when reading FSM files + //###################################################################### + void + fsm::write_fsm_txt(std::string filename) + { + std::ofstream trellis_fname (filename.c_str()); + if(!trellis_fname) { + std::cout << "file not found " << std::endl ; exit(-1); + } + trellis_fname << d_I << ' ' << d_S << ' ' << d_O << std::endl; + trellis_fname << std::endl; + for(int i=0;i<d_S;i++) { + for(int j=0;j<d_I;j++) + trellis_fname << d_NS[i*d_I+j] << ' '; + trellis_fname << std::endl; + } + trellis_fname << std::endl; + for(int i=0;i<d_S;i++) { + for(int j=0;j<d_I;j++) + trellis_fname << d_OS[i*d_I+j] << ' '; + trellis_fname << std::endl; + } + trellis_fname << std::endl; + trellis_fname.close(); + } + + } /* namespace trellis */ +} /* namespace gr */ diff --git a/gr-trellis/lib/interleaver.cc b/gr-trellis/lib/interleaver.cc new file mode 100644 index 0000000000..27248a6d43 --- /dev/null +++ b/gr-trellis/lib/interleaver.cc @@ -0,0 +1,147 @@ +/* -*- c++ -*- */ +/* + * Copyright 2002,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 <cstdlib> +#include <cstdio> +#include <iostream> +#include <string> +#include <fstream> +#include <stdexcept> +#include <cmath> +#include <trellis/quicksort_index.h> +#include <trellis/interleaver.h> + +namespace gr { + namespace trellis { + + interleaver::interleaver() + { + d_K=0; + d_INTER.resize(0); + d_DEINTER.resize(0); + } + + interleaver::interleaver(const interleaver &INTERLEAVER) + { + d_K=INTERLEAVER.K(); + d_INTER=INTERLEAVER.INTER(); + d_DEINTER=INTERLEAVER.DEINTER(); + } + + interleaver::interleaver(int K, const std::vector<int> &INTER) + { + d_K=K; + d_INTER=INTER; + d_DEINTER.resize(d_K); + + // generate DEINTER table + for(int i=0;i<d_K;i++) { + d_DEINTER[d_INTER[i]]=i; + } + } + + //###################################################################### + //# Read an INTERLEAVER specification from a file. + //# Format (hopefully will become more flexible in the future...): + //# K + //# blank line + //# list of space separated K integers from 0 to K-1 in appropriate order + //# optional comments + //###################################################################### + interleaver::interleaver(const char *name) + { + FILE *interleaverfile; + + if((interleaverfile=fopen(name,"r")) == NULL) + throw std::runtime_error ("file open error in interleaver()"); + //printf("file open error in interleaver()\n"); + + if(fscanf(interleaverfile,"%d\n",&d_K) == EOF) { + if(ferror(interleaverfile) != 0) + throw std::runtime_error ("interleaver::interleaver(const char *name): file read error\n"); + } + + d_INTER.resize(d_K); + d_DEINTER.resize(d_K); + + for(int i=0;i<d_K;i++) { + if(fscanf(interleaverfile,"%d",&(d_INTER[i])) == EOF) { + if(ferror(interleaverfile) != 0) + throw std::runtime_error("interleaver::interleaver(const char *name): file read error\n"); + } + } + + // generate DEINTER table + for(int i=0;i<d_K;i++) { + d_DEINTER[d_INTER[i]]=i; + } + } + + //###################################################################### + //# Generate a random interleaver + //###################################################################### + interleaver::interleaver(int K, int seed) + { + d_K=K; + d_INTER.resize(d_K); + d_DEINTER.resize(d_K); + + if(seed>=0) + srand((unsigned int)seed); + std::vector<int> tmp(d_K); + for(int i=0;i<d_K;i++) { + d_INTER[i]=i; + tmp[i] = rand(); + } + quicksort_index <int> (tmp,d_INTER,0,d_K-1); + + // generate DEINTER table + for(int i=0;i<d_K;i++) { + d_DEINTER[d_INTER[i]]=i; + } + } + + //###################################################################### + //# Write an INTERLEAVER specification to a file. + //# Format + //# K + //# blank line + //# list of space separated K integers from 0 to K-1 in appropriate order + //# optional comments + //###################################################################### + void + interleaver::write_interleaver_txt(std::string filename) + { + std::ofstream interleaver_fname (filename.c_str()); + if(!interleaver_fname) { + std::cout << "file not found " << std::endl ; exit(-1); + } + interleaver_fname << d_K << std::endl; + interleaver_fname << std::endl; + for(int i=0;i<d_K;i++) + interleaver_fname << d_INTER[i] << ' '; + interleaver_fname << std::endl; + interleaver_fname.close(); + } + + } /* namespace trellis */ +} /* namespace gr */ diff --git a/gr-trellis/lib/metrics_X_impl.cc.t b/gr-trellis/lib/metrics_X_impl.cc.t new file mode 100644 index 0000000000..c74051c53e --- /dev/null +++ b/gr-trellis/lib/metrics_X_impl.cc.t @@ -0,0 +1,98 @@ +/* -*- 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 <stdexcept> +#include <iostream> + +namespace gr { + namespace trellis { + + @BASE_NAME@::sptr + @BASE_NAME@::make(int O, int D, const std::vector<@I_TYPE@> &TABLE, + digital::trellis_metric_type_t TYPE) + { + return gnuradio::get_initial_sptr + (new @IMPL_NAME@(O,D,TABLE,TYPE)); + } + + @IMPL_NAME@::@IMPL_NAME@(int O, int D, const std::vector<@I_TYPE@> &TABLE, + digital::trellis_metric_type_t TYPE) + : gr_block("@BASE_NAME@", + gr_make_io_signature(1, -1, sizeof (@I_TYPE@)), + gr_make_io_signature(1, -1, sizeof (float))), + d_O(O), d_D(D), d_TYPE(TYPE), d_TABLE(TABLE) + { + set_relative_rate (1.0 * d_O / ((double) d_D)); + set_output_multiple ((int)d_O); + } + + @IMPL_NAME@::~@IMPL_NAME@() + { + } + + void + @IMPL_NAME@::set_TABLE(const std::vector<@I_TYPE@> &table) + { + d_TABLE = table; + } + + void + @IMPL_NAME@::forecast(int noutput_items, gr_vector_int &ninput_items_required) + { + int input_required = d_D * noutput_items / d_O; + unsigned ninputs = ninput_items_required.size(); + for(unsigned int i = 0; i < ninputs; i++) + ninput_items_required[i] = input_required; + } + + int + @IMPL_NAME@::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + int nstreams = input_items.size(); + + for(int m = 0; m < nstreams; m++) { + const @I_TYPE@ *in = (@I_TYPE@*)input_items[m]; + float *out = (float*)output_items[m]; + + for(int i = 0; i < noutput_items / d_O ; i++) { + calc_metric(d_O, d_D, d_TABLE,&(in[i*d_D]), &(out[i*d_O]), d_TYPE); + } + } + + consume_each(d_D * noutput_items / d_O); + return noutput_items; + } + + } /* namespace trellis */ +} /* namespace gr */ diff --git a/gr-trellis/lib/metrics_X_impl.h.t b/gr-trellis/lib/metrics_X_impl.h.t new file mode 100644 index 0000000000..0f52a8bc40 --- /dev/null +++ b/gr-trellis/lib/metrics_X_impl.h.t @@ -0,0 +1,64 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <trellis/@BASE_NAME@.h> + +namespace gr { + namespace trellis { + + class @IMPL_NAME@ : public @BASE_NAME@ + { + private: + int d_O; + int d_D; + digital::trellis_metric_type_t d_TYPE; + std::vector<@I_TYPE@> d_TABLE; + + public: + @IMPL_NAME@(int O, int D, const std::vector<@I_TYPE@> &TABLE, + digital::trellis_metric_type_t TYPE); + ~@IMPL_NAME@(); + + int O() const { return d_O; } + int D() const { return d_D; } + digital::trellis_metric_type_t TYPE() const { return d_TYPE; } + std::vector<@I_TYPE@> TABLE() const { return d_TABLE; } + void set_TABLE(const std::vector<@I_TYPE@> &table); + + 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); + }; + + } /* namespace trellis */ +} /* namespace gr */ + +#endif /* @GUARD_NAME@ */ diff --git a/gr-trellis/lib/pccc_decoder_X_impl.cc.t b/gr-trellis/lib/pccc_decoder_X_impl.cc.t new file mode 100644 index 0000000000..9bf85bc614 --- /dev/null +++ b/gr-trellis/lib/pccc_decoder_X_impl.cc.t @@ -0,0 +1,120 @@ +/* -*- 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 <iostream> +#include <trellis/core_algorithms.h> + +namespace gr { + namespace trellis { + + static const float INF = 1.0e9; + + @BASE_NAME@::sptr + @BASE_NAME@::make(const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + siso_type_t SISO_TYPE) + { + return gnuradio::get_initial_sptr + (new @IMPL_NAME@(FSM1, ST10, ST1K, + FSM2, ST20, ST2K, + INTERLEAVER, + blocklength, + repetitions, + SISO_TYPE)); + } + + @IMPL_NAME@::@IMPL_NAME@(const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + siso_type_t SISO_TYPE) + : gr_block("@BASE_NAME@", + gr_make_io_signature(1, 1, sizeof(float)), + gr_make_io_signature(1, 1, sizeof(@O_TYPE@))), + d_FSM1(FSM1), d_ST10(ST10), d_ST1K(ST1K), + d_FSM2(FSM2), d_ST20(ST20), d_ST2K(ST2K), + d_INTERLEAVER(INTERLEAVER), + d_blocklength(blocklength), + d_repetitions(repetitions), + d_SISO_TYPE(SISO_TYPE) + { + set_relative_rate (1.0 / ((double) d_FSM1.O() * d_FSM2.O())); + set_output_multiple (d_blocklength); + } + + @IMPL_NAME@::~@IMPL_NAME@() + { + } + + void + @IMPL_NAME@::forecast(int noutput_items, + gr_vector_int &ninput_items_required) + { + int input_required = d_FSM1.O() * d_FSM2.O() * noutput_items; + ninput_items_required[0] = input_required; + } + + //=========================================================== + + int + @IMPL_NAME@::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + int nblocks = noutput_items / d_blocklength; + + float (*p2min)(float, float) = NULL; + if(d_SISO_TYPE == TRELLIS_MIN_SUM) + p2min = &min; + else if(d_SISO_TYPE == TRELLIS_SUM_PRODUCT) + p2min = &min_star; + + const float *in = (const float *) input_items[0]; + @O_TYPE@ *out = (@O_TYPE@ *) output_items[0]; + for(int n=0;n<nblocks;n++) { + pccc_decoder(d_FSM1, d_ST10, d_ST1K, + d_FSM2, d_ST20, d_ST2K, + d_INTERLEAVER, d_blocklength, d_repetitions, + p2min, + &(in[n*d_blocklength*d_FSM1.O()*d_FSM2.O()]), + &(out[n*d_blocklength])); + } + + consume_each(d_FSM1.O() * d_FSM2.O() * noutput_items); + return noutput_items; + } + + } /* namespace trellis */ +} /* namespace gr */ diff --git a/gr-trellis/lib/pccc_decoder_X_impl.h.t b/gr-trellis/lib/pccc_decoder_X_impl.h.t new file mode 100644 index 0000000000..9b61e34fde --- /dev/null +++ b/gr-trellis/lib/pccc_decoder_X_impl.h.t @@ -0,0 +1,80 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <trellis/@BASE_NAME@.h> + +namespace gr { + namespace trellis { + + class @IMPL_NAME@ : public @BASE_NAME@ + { + private: + fsm d_FSM1; + int d_ST10; + int d_ST1K; + fsm d_FSM2; + int d_ST20; + int d_ST2K; + interleaver d_INTERLEAVER; + int d_blocklength; + int d_repetitions; + siso_type_t d_SISO_TYPE; + std::vector<float> d_buffer; + + public: + @IMPL_NAME@(const fsm &FSM1, int ST10, int ST1K, + const fsm &FSM2, int ST20, int ST2K, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + siso_type_t SISO_TYPE); + ~@IMPL_NAME@(); + + fsm FSM1() const { return d_FSM1; } + fsm FSM2() const { return d_FSM2; } + int ST10() const { return d_ST10; } + int ST1K() const { return d_ST1K; } + int ST20() const { return d_ST20; } + int ST2K() const { return d_ST2K; } + interleaver INTERLEAVER() const { return d_INTERLEAVER; } + int blocklength() const { return d_blocklength; } + int repetitions() const { return d_repetitions; } + siso_type_t SISO_TYPE() const { return d_SISO_TYPE; } + + 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); + }; + + } /* namespace trellis */ +} /* namespace gr */ + +#endif /* @GUARD_NAME@ */ diff --git a/gr-trellis/lib/pccc_decoder_combined_XX_impl.cc.t b/gr-trellis/lib/pccc_decoder_combined_XX_impl.cc.t new file mode 100644 index 0000000000..21a5c0b3ae --- /dev/null +++ b/gr-trellis/lib/pccc_decoder_combined_XX_impl.cc.t @@ -0,0 +1,139 @@ +/* -*- 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 <iostream> +#include <trellis/core_algorithms.h> + +namespace gr { + namespace trellis { + + static const float INF = 1.0e9; + + @BASE_NAME@::sptr + @BASE_NAME@::make(const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + siso_type_t SISO_TYPE, + int D, + const std::vector<@I_TYPE@> &TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling) + { + return gnuradio::get_initial_sptr + (new @NAME@(FSMo, STo0, SToK, FSMi, STi0, STiK, + INTERLEAVER, blocklength, repetitions, + SISO_TYPE, D, TABLE,METRIC_TYPE, scaling)); + } + + @IMPL_NAME@::@IMPL_NAME@(const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + siso_type_t SISO_TYPE, + int D, + const std::vector<@I_TYPE@> &TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling) + : gr_block("@BASE_NAME@", + gr_make_io_signature(1, 1, sizeof(@I_TYPE@)), + gr_make_io_signature(1, 1, sizeof(@O_TYPE@))), + d_FSMo(FSMo), d_STo0(STo0), d_SToK(SToK), + d_FSMi(FSMi), d_STi0(STi0), d_STiK(STiK), + d_INTERLEAVER(INTERLEAVER), + d_blocklength(blocklength), + d_repetitions(repetitions), + d_SISO_TYPE(SISO_TYPE), + d_D(D), + d_TABLE(TABLE), + d_METRIC_TYPE(METRIC_TYPE), + d_scaling(scaling) + { + assert(d_FSMo.I() == d_FSMi.I()); + set_relative_rate (1.0 / ((double) d_D)); + set_output_multiple (d_blocklength); + } + + @IMPL_NAME@::~@IMPL_NAME@() + { + } + + void + @IMPL_NAME@::set_scaling(float scaling) + { + d_scaling = scaling; + } + + void + @IMPL_NAME@::forecast(int noutput_items, + gr_vector_int &ninput_items_required) + { + int input_required = d_D * noutput_items; + ninput_items_required[0] = input_required; + } + + //=========================================================== + + int + @IMPL_NAME@::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + int nblocks = noutput_items / d_blocklength; + + float (*p2min)(float, float) = NULL; + if(d_SISO_TYPE == TRELLIS_MIN_SUM) + p2min = &min; + else if(d_SISO_TYPE == TRELLIS_SUM_PRODUCT) + p2min = &min_star; + + const @I_TYPE@ *in = (const @I_TYPE@ *) input_items[0]; + @O_TYPE@ *out = (@O_TYPE@ *) output_items[0]; + for (int n=0;n<nblocks;n++) { + pccc_decoder_combined(d_FSMo, d_STo0, d_SToK, + d_FSMi, d_STi0, d_STiK, + d_INTERLEAVER, d_blocklength, d_repetitions, + p2min, + d_D,d_TABLE, + d_METRIC_TYPE, + d_scaling, + &(in[n*d_blocklength*d_D]), + &(out[n*d_blocklength])); + } + + consume_each(d_D * noutput_items); + return noutput_items; + } + + } /* namespace trellis */ +} /* namespace gr */ diff --git a/gr-trellis/lib/pccc_decoder_combined_XX_impl.h.t b/gr-trellis/lib/pccc_decoder_combined_XX_impl.h.t new file mode 100644 index 0000000000..4c3655f40d --- /dev/null +++ b/gr-trellis/lib/pccc_decoder_combined_XX_impl.h.t @@ -0,0 +1,93 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <trellis/@BASE_NAME@.h> + +namespace gr { + namespace trellis { + + class @IMPL_NAME@ : public @BASE_NAME@ + { + private: + fsm d_FSMo; + int d_STo0; + int d_SToK; + fsm d_FSMi; + int d_STi0; + int d_STiK; + interleaver d_INTERLEAVER; + int d_blocklength; + int d_repetitions; + siso_type_t d_SISO_TYPE; + int d_D; + std::vector<@I_TYPE@> d_TABLE; + digital::trellis_metric_type_t d_METRIC_TYPE; + float d_scaling; + std::vector<float> d_buffer; + + public: + @IMPL_NAME@(const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + siso_type_t SISO_TYPE, + int D, + const std::vector<@I_TYPE@> &TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling); + ~@IMPL_NAME@(); + + fsm FSM1() const { return d_FSMo; } + fsm FSM2() const { return d_FSMi; } + int ST10() const { return d_STo0; } + int ST1K() const { return d_SToK; } + int ST20() const { return d_STi0; } + int ST2K() const { return d_STiK; } + interleaver INTERLEAVER() const { return d_INTERLEAVER; } + int blocklength() const { return d_blocklength; } + int repetitions() const { return d_repetitions; } + int D() const { return d_D; } + std::vector<@I_TYPE@> TABLE() const { return d_TABLE; } + digital::trellis_metric_type_t METRIC_TYPE() const { return d_METRIC_TYPE; } + siso_type_t SISO_TYPE() const { return d_SISO_TYPE; } + float scaling() const { return d_scaling; } + void set_scaling(float scaling); + + 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); + }; + + } /* namespace trellis */ +} /* namespace gr */ + +#endif /* @GUARD_NAME@ */ diff --git a/gr-trellis/lib/pccc_encoder_XX_impl.cc.t b/gr-trellis/lib/pccc_encoder_XX_impl.cc.t new file mode 100644 index 0000000000..4e804729a2 --- /dev/null +++ b/gr-trellis/lib/pccc_encoder_XX_impl.cc.t @@ -0,0 +1,91 @@ +/* -*- 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 <iostream> + +namespace gr { + namespace trellis { + + @BASE_NAME@::sptr + @BASE_NAME@::make(const fsm &FSM1, int ST1, + const fsm &FSM2, int ST2, + const interleaver &INTERLEAVER, + int blocklength) + { + return gnuradio::get_initial_sptr + (new @IMPL_NAME@(FSM1, ST1, FSM2, ST2, INTERLEAVER, blocklength)); + } + + @IMPL_NAME@::@IMPL_NAME@(const fsm &FSM1, int ST1, + const fsm &FSM2, int ST2, + const interleaver &INTERLEAVER, + int blocklength) + : gr_sync_block("@BASE_NAME@", + gr_make_io_signature(1, 1, sizeof(@I_TYPE@)), + gr_make_io_signature(1, 1, sizeof(@O_TYPE@))), + d_FSM1(FSM1), d_ST1(ST1), + d_FSM2(FSM2), d_ST2(ST2), + d_INTERLEAVER(INTERLEAVER), + d_blocklength(blocklength) + { + assert(d_FSM1.I() == d_FSM2.I()); + set_output_multiple(d_blocklength); + d_buffer.resize(d_blocklength); + } + + @IMPL_NAME@::~@IMPL_NAME@() + { + } + + int + @NAME@::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + for(int b = 0 ; b<noutput_items/d_blocklength; b++) { + const @I_TYPE@ *in = (const @I_TYPE@*)input_items[0]+b*d_blocklength; + @O_TYPE@ *out = (@O_TYPE@*)output_items[0]+b*d_blocklength; + + int ST1_tmp = d_ST1; + int ST2_tmp = d_ST2; + for(int i = 0; i < d_blocklength; i++) { + int k = d_INTERLEAVER.INTER()[i]; + int o1 = d_FSM1.OS()[ST1_tmp*d_FSM1.I()+in[i]]; + ST1_tmp = (int) d_FSM1.NS()[ST1_tmp*d_FSM1.I()+in[i]]; + int o2 = d_FSM2.OS()[ST2_tmp*d_FSM2.I()+in[k]]; + ST2_tmp = (int) d_FSM2.NS()[ST2_tmp*d_FSM2.I()+in[k]]; + out[i] = (@O_TYPE@) (o1*d_FSM1.O() + o2); + } + } + return noutput_items; + } + + } /* namespace trellis */ +} /* namespace gr */ diff --git a/gr-trellis/lib/pccc_encoder_XX_impl.h.t b/gr-trellis/lib/pccc_encoder_XX_impl.h.t new file mode 100644 index 0000000000..1eed3702be --- /dev/null +++ b/gr-trellis/lib/pccc_encoder_XX_impl.h.t @@ -0,0 +1,66 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <trellis/@BASE_NAME@.h> + +namespace gr { + namespace trellis { + + class @IMPL_NAME@ : public @BASE_NAME@ + { + private: + fsm d_FSM1; + int d_ST1; + fsm d_FSM2; + int d_ST2; + interleaver d_INTERLEAVER; + int d_blocklength; + std::vector<int> d_buffer; + + public: + @IMPL_NAME@(const fsm &FSM1, int ST1, + const fsm &FSM2, int ST2, + const interleaver &INTERLEAVER, + int blocklength); + ~@IMPL_NAME@(); + + fsm FSM1() const { return d_FSM1; } + int ST1() const { return d_ST1; } + fsm FSM2() const { return d_FSM2; } + int ST2() const { return d_ST2; } + interleaver INTERLEAVER() const { return d_INTERLEAVER; } + int blocklength() const { return d_blocklength; } + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace trellis */ +} /* namespace gr */ + +#endif /* @GUARD_NAME@ */ diff --git a/gr-trellis/lib/permutation_impl.cc b/gr-trellis/lib/permutation_impl.cc new file mode 100644 index 0000000000..da82e46832 --- /dev/null +++ b/gr-trellis/lib/permutation_impl.cc @@ -0,0 +1,90 @@ +/* -*- 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 "permutation_impl.h" +#include <gr_io_signature.h> +#include <iostream> +#include <string.h> + +namespace gr { + namespace trellis { + + permutation::sptr + permutation::make(int K, const std::vector<int> &TABLE, + int SYMS_PER_BLOCK, size_t BYTES_PER_SYMBOL) + { + return gnuradio::get_initial_sptr + (new permutation_impl(K,TABLE,SYMS_PER_BLOCK,BYTES_PER_SYMBOL)); + } + + permutation_impl::permutation_impl(int K, const std::vector<int> &TABLE, + int SYMS_PER_BLOCK, size_t BYTES_PER_SYMBOL) + : gr_sync_block("permutation", + gr_make_io_signature(1, -1, BYTES_PER_SYMBOL), + gr_make_io_signature(1, -1, BYTES_PER_SYMBOL)), + d_K(K), d_TABLE(TABLE), + d_SYMS_PER_BLOCK(SYMS_PER_BLOCK), + d_BYTES_PER_SYMBOL(BYTES_PER_SYMBOL) + { + set_output_multiple(d_K*SYMS_PER_BLOCK); + //std::cout << d_K << "\n"; + } + + permutation_impl::~permutation_impl() + { + } + + int + permutation_impl::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + int nstreams = input_items.size(); + + for(int m=0;m<nstreams;m++) { + const char *in = (const char *) input_items[m]; + char *out = (char *) output_items[m]; + + // per stream processing + for(int i = 0; i < noutput_items/d_SYMS_PER_BLOCK; i++) { + // Index i refers to blocks. + // Begining of packet (in blocks) + int i0 = d_K*(i/d_K); + // position of block within packet (in blocks) + int j0 = i%d_K; + // new position of block within packet (in blocks) + int k0 = d_TABLE[j0]; + memcpy(&(out[i*d_SYMS_PER_BLOCK*d_BYTES_PER_SYMBOL]), + &(in[(i0+k0)*d_SYMS_PER_BLOCK*d_BYTES_PER_SYMBOL]), + d_BYTES_PER_SYMBOL*d_SYMS_PER_BLOCK); + } + // end per stream processing + } + return noutput_items; + } + + } /* namespace trellis */ +} /* namespace gr */ diff --git a/gr-trellis/lib/permutation_impl.h b/gr-trellis/lib/permutation_impl.h new file mode 100644 index 0000000000..6e3ca2b2d7 --- /dev/null +++ b/gr-trellis/lib/permutation_impl.h @@ -0,0 +1,58 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_TRELLIS_PERMUTATION_IMPL_H +#define INCLUDED_TRELLIS_PERMUTATION_IMPL_H + +#include <trellis/api.h> +#include <trellis/permutation.h> + +namespace gr { + namespace trellis { + + class permutation_impl : public permutation + { + private: + int d_K; + std::vector<int> d_TABLE; + int d_SYMS_PER_BLOCK; + size_t d_BYTES_PER_SYMBOL; + + public: + permutation_impl(int K, const std::vector<int> &TABLE, + int SYMS_PER_BLOCK, size_t NBYTES); + ~permutation_impl(); + + int K() const { return d_K; } + const std::vector<int> & TABLE() const { return d_TABLE; } + int SYMS_PER_BLOCK() const { return d_SYMS_PER_BLOCK; } + size_t BYTES_PER_SYMBOL() const { return d_BYTES_PER_SYMBOL; } + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace trellis */ +} /* namespace gr */ + +#endif /* INCLUDED_TRELLIS_PERMUTATION_IMPL_H */ diff --git a/gr-trellis/lib/quicksort_index.cc b/gr-trellis/lib/quicksort_index.cc new file mode 100644 index 0000000000..02cd8a9134 --- /dev/null +++ b/gr-trellis/lib/quicksort_index.cc @@ -0,0 +1,70 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#include <trellis/quicksort_index.h> + +namespace gr { + namespace trellis { + + template <class T> void + SWAP(T & a, T & b) + { + T temp = a; + a = b; + b = temp; + } + + template <class T> void + quicksort_index (std::vector<T> & p, std::vector<int> & index, + int left, int right) + { + if(left < right) { + int i = left; + int j = right + 1; + T pivot = p[left]; + do { + do + i++; + while ((p[i] < pivot) && (i < right)); + do + j--; + while ((p[j] > pivot) && (j > left)); + if (i < j) { + SWAP <T> (p[i],p[j]); + SWAP <int> (index[i],index[j]); + } + } while (i < j); + SWAP <T> (p[left], p[j]); + SWAP <int> (index[left], index[j]); + quicksort_index <T> (p,index, left, j-1); + quicksort_index <T> (p,index, j+1, right); + } + } + + // instantiate an <int> version of the quicksort_index + //template <int> void SWAP (int & a, int & b); + template void + quicksort_index<int>(std::vector<int> & p, std::vector<int> & index, + int left, int right); + + } /* namespace trellis */ +} /* namespace gr */ diff --git a/gr-trellis/lib/sccc_decoder_X_impl.cc.t b/gr-trellis/lib/sccc_decoder_X_impl.cc.t new file mode 100644 index 0000000000..6eef46518d --- /dev/null +++ b/gr-trellis/lib/sccc_decoder_X_impl.cc.t @@ -0,0 +1,118 @@ +/* -*- 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 <iostream> +#include <trellis/core_algorithms.h> + +namespace gr { + namespace trellis { + + static const float INF = 1.0e9; + + @BASE_NAME@::sptr + @BASE_NAME@::make(const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + siso_type_t SISO_TYPE) + { + return gnuradio::get_initial_sptr + (new @IMPL_NAME@(FSMo, STo0, SToK, FSMi, STi0, STiK, + INTERLEAVER, blocklength, repetitions, + SISO_TYPE)); + } + + @IMPL_NAME@::@IMPL_NAME@(const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + siso_type_t SISO_TYPE) + : gr_block("@BASE_NAME@", + gr_make_io_signature(1, 1, sizeof(float)), + gr_make_io_signature(1, 1, sizeof(@O_TYPE@))), + d_FSMo(FSMo), d_STo0(STo0), d_SToK(SToK), + d_FSMi(FSMi), d_STi0(STi0), d_STiK(STiK), + d_INTERLEAVER(INTERLEAVER), + d_blocklength(blocklength), + d_repetitions(repetitions), + d_SISO_TYPE(SISO_TYPE) + { + set_relative_rate(1.0 / ((double) d_FSMi.O())); + set_output_multiple(d_blocklength); + } + + @IMPL_NAME@::~@IMPL_NAME@() + { + } + + void + @IMPL_NAME@::forecast(int noutput_items, + gr_vector_int &ninput_items_required) + { + int input_required = d_FSMi.O() * noutput_items ; + ninput_items_required[0] = input_required; + } + + //=========================================================== + + int + @IMPL_NAME@::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + int nblocks = noutput_items / d_blocklength; + float (*p2min)(float, float) = NULL; + + if(d_SISO_TYPE == TRELLIS_MIN_SUM) + p2min = &min; + else if(d_SISO_TYPE == TRELLIS_SUM_PRODUCT) + p2min = &min_star; + + const float *in = (const float*)input_items[0]; + @O_TYPE@ *out = (@O_TYPE@*)output_items[0]; + + for(int n = 0; n < nblocks; n++) { + sccc_decoder(d_FSMo, d_STo0, d_SToK, + d_FSMi, d_STi0, d_STiK, + d_INTERLEAVER, d_blocklength, d_repetitions, + p2min, + &(in[n*d_blocklength*d_FSMi.O()]), + &(out[n*d_blocklength])); + } + + consume_each(d_FSMi.O() * noutput_items ); + return noutput_items; + } + + } /* namespace trellis */ +} /* namespace gr */ diff --git a/gr-trellis/lib/sccc_decoder_X_impl.h.t b/gr-trellis/lib/sccc_decoder_X_impl.h.t new file mode 100644 index 0000000000..31f4edc4b8 --- /dev/null +++ b/gr-trellis/lib/sccc_decoder_X_impl.h.t @@ -0,0 +1,80 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <trellis/@BASE_NAME@.h> + +namespace gr { + namespace trellis { + + class @IMPL_NAME@ : public @BASE_NAME@ + { + private: + fsm d_FSMo; + int d_STo0; + int d_SToK; + fsm d_FSMi; + int d_STi0; + int d_STiK; + interleaver d_INTERLEAVER; + int d_blocklength; + int d_repetitions; + siso_type_t d_SISO_TYPE; + std::vector<float> d_buffer; + + public: + @IMPL_NAME@(const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + siso_type_t SISO_TYPE); + ~@IMPL_NAME@(); + + fsm FSMo() const { return d_FSMo; } + fsm FSMi() const { return d_FSMi; } + int STo0() const { return d_STo0; } + int SToK() const { return d_SToK; } + int STi0() const { return d_STi0; } + int STiK() const { return d_STiK; } + interleaver INTERLEAVER() const { return d_INTERLEAVER; } + int blocklength() const { return d_blocklength; } + int repetitions() const { return d_repetitions; } + siso_type_t SISO_TYPE() const { return d_SISO_TYPE; } + + 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); + }; + + } /* namespace trellis */ +} /* namespace gr */ + +#endif /* @GUARD_NAME@ */ diff --git a/gr-trellis/lib/sccc_decoder_combined_XX_impl.cc.t b/gr-trellis/lib/sccc_decoder_combined_XX_impl.cc.t new file mode 100644 index 0000000000..717f2c8e49 --- /dev/null +++ b/gr-trellis/lib/sccc_decoder_combined_XX_impl.cc.t @@ -0,0 +1,139 @@ +/* -*- 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 <iostream> +#include <trellis/core_algorithms.h> + +namespace gr { + namespace trellis { + + static const float INF = 1.0e9; + + @BASE_NAME@::sptr + @BASE_NAME@::make(const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + siso_type_t SISO_TYPE, + int D, + const std::vector<@I_TYPE@> &TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling) + { + return gnuradio::get_initial_sptr + (new @IMPL_NAME@(FSMo, STo0, SToK, FSMi, STi0, STiK, + INTERLEAVER, blocklength, repetitions, + SISO_TYPE, D, TABLE,METRIC_TYPE, scaling)); + } + + @IMPL_NAME@::@IMPL_NAME@(const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + siso_type_t SISO_TYPE, + int D, + const std::vector<@I_TYPE@> &TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling) + : gr_block("@BASE_NAME@", + gr_make_io_signature(1, 1, sizeof(@I_TYPE@)), + gr_make_io_signature(1, 1, sizeof(@O_TYPE@))), + d_FSMo(FSMo), d_STo0(STo0), d_SToK(SToK), + d_FSMi(FSMi), d_STi0(STi0), d_STiK(STiK), + d_INTERLEAVER(INTERLEAVER), + d_blocklength(blocklength), + d_repetitions(repetitions), + d_SISO_TYPE(SISO_TYPE), + d_D(D), + d_TABLE(TABLE), + d_METRIC_TYPE(METRIC_TYPE), + d_scaling(scaling) + { + set_relative_rate(1.0 / ((double) d_D)); + set_output_multiple(d_blocklength); + } + + @IMPL_NAME@::~@IMPL_NAME@() + { + } + + void + @IMPL_NAME@::set_scaling(float scaling) + { + d_scaling = scaling; + } + + void + @IMPL_NAME@::forecast(int noutput_items, + gr_vector_int &ninput_items_required) + { + int input_required = d_D * noutput_items ; + ninput_items_required[0] = input_required; + } + + //=========================================================== + + int + @IMPL_NAME@::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + int nblocks = noutput_items / d_blocklength; + float (*p2min)(float, float) = NULL; + + if(d_SISO_TYPE == TRELLIS_MIN_SUM) + p2min = &min; + else if(d_SISO_TYPE == TRELLIS_SUM_PRODUCT) + p2min = &min_star; + + const @I_TYPE@ *in = (const @I_TYPE@*)input_items[0]; + @O_TYPE@ *out = (@O_TYPE@*)output_items[0]; + + for(int n = 0; n < nblocks; n++) { + sccc_decoder_combined(d_FSMo, d_STo0, d_SToK, + d_FSMi, d_STi0, d_STiK, + d_INTERLEAVER, d_blocklength, d_repetitions, + p2min, + d_D,d_TABLE, + d_METRIC_TYPE, + d_scaling, + &(in[n*d_blocklength*d_D]), + &(out[n*d_blocklength])); + } + + consume_each(d_D * noutput_items); + return noutput_items; + } + + } /* namespace trellis */ +} /* namespace gr */ diff --git a/gr-trellis/lib/sccc_decoder_combined_XX_impl.h.t b/gr-trellis/lib/sccc_decoder_combined_XX_impl.h.t new file mode 100644 index 0000000000..f3dbd1b4bb --- /dev/null +++ b/gr-trellis/lib/sccc_decoder_combined_XX_impl.h.t @@ -0,0 +1,93 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <trellis/@BASE_NAME@.h> + +namespace gr { + namespace trellis { + + class @IMPL_NAME@ : public @BASE_NAME@ + { + private: + fsm d_FSMo; + int d_STo0; + int d_SToK; + fsm d_FSMi; + int d_STi0; + int d_STiK; + interleaver d_INTERLEAVER; + int d_blocklength; + int d_repetitions; + siso_type_t d_SISO_TYPE; + int d_D; + std::vector<@I_TYPE@> d_TABLE; + digital::trellis_metric_type_t d_METRIC_TYPE; + float d_scaling; + std::vector<float> d_buffer; + + public: + @IMPL_NAME@(const fsm &FSMo, int STo0, int SToK, + const fsm &FSMi, int STi0, int STiK, + const interleaver &INTERLEAVER, + int blocklength, + int repetitions, + siso_type_t SISO_TYPE, + int D, + const std::vector<@I_TYPE@> &TABLE, + digital::trellis_metric_type_t METRIC_TYPE, + float scaling); + ~@IMPL_NAME@(); + + fsm FSMo() const { return d_FSMo; } + fsm FSMi() const { return d_FSMi; } + int STo0() const { return d_STo0; } + int SToK() const { return d_SToK; } + int STi0() const { return d_STi0; } + int STiK() const { return d_STiK; } + interleaver INTERLEAVER() const { return d_INTERLEAVER; } + int blocklength() const { return d_blocklength; } + int repetitions() const { return d_repetitions; } + int D() const { return d_D; } + std::vector<@I_TYPE@> TABLE() const { return d_TABLE; } + digital::trellis_metric_type_t METRIC_TYPE() const { return d_METRIC_TYPE; } + siso_type_t SISO_TYPE() const { return d_SISO_TYPE; } + float scaling() const { return d_scaling; } + void set_scaling(float scaling); + + 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); + }; + + } /* namespace trellis */ +} /* namespace gr */ + +#endif /* @GUARD_NAME@ */ diff --git a/gr-trellis/lib/sccc_encoder_XX_impl.cc.t b/gr-trellis/lib/sccc_encoder_XX_impl.cc.t new file mode 100644 index 0000000000..390e65c4f3 --- /dev/null +++ b/gr-trellis/lib/sccc_encoder_XX_impl.cc.t @@ -0,0 +1,93 @@ +/* -*- 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 <iostream> + +namespace gr { + namespace trellis { + + @BASE_NAME@::sptr + @BASE_NAME@::make(const fsm &FSMo, int STo, + const fsm &FSMi, int STi, + const interleaver &INTERLEAVER, + int blocklength) + { + return gnuradio::get_initial_sptr + (new @IMPL_NAME@(FSMo, STo, FSMi, STi, INTERLEAVER, blocklength)); + } + + @IMPL_NAME@::@IMPL_NAME@(const fsm &FSMo, int STo, + const fsm &FSMi, int STi, + const interleaver &INTERLEAVER, + int blocklength) + : gr_sync_block("@BASE_NAME@", + gr_make_io_signature(1, 1, sizeof(@I_TYPE@)), + gr_make_io_signature(1, 1, sizeof(@O_TYPE@))), + d_FSMo(FSMo), d_STo(STo), + d_FSMi(FSMi), d_STi(STi), + d_INTERLEAVER(INTERLEAVER), + d_blocklength(blocklength) + { + set_output_multiple(d_blocklength); + d_buffer.resize(d_blocklength); + } + + @IMPL_NAME@::~@IMPL_NAME@() + { + } + + int + @IMPL_NAME@::work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + for(int b = 0; b < noutput_items/d_blocklength; b++) { + const @I_TYPE@ *in = (const @I_TYPE@*)input_items[0]+b*d_blocklength; + @O_TYPE@ *out = (@O_TYPE@*)output_items[0]+b*d_blocklength; + + int STo_tmp = d_STo; + for(int i = 0; i < d_blocklength; i++) { + d_buffer[i] = d_FSMo.OS()[STo_tmp*d_FSMo.I()+in[i]]; + STo_tmp = (int) d_FSMo.NS()[STo_tmp*d_FSMo.I()+in[i]]; + } + + int STi_tmp = d_STi; + for(int i = 0; i < d_blocklength; i++) { + int k = d_INTERLEAVER.INTER()[i]; + out[i] = (@O_TYPE@) d_FSMi.OS()[STi_tmp*d_FSMi.I()+d_buffer[k]]; + STi_tmp = (int) d_FSMi.NS()[STi_tmp*d_FSMi.I()+d_buffer[k]]; + } + } + return noutput_items; + } + + } /* namespace trellis */ +} /* namespace gr */ + diff --git a/gr-trellis/lib/sccc_encoder_XX_impl.h.t b/gr-trellis/lib/sccc_encoder_XX_impl.h.t new file mode 100644 index 0000000000..a3e582b5a0 --- /dev/null +++ b/gr-trellis/lib/sccc_encoder_XX_impl.h.t @@ -0,0 +1,66 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <trellis/@BASE_NAME@.h> + +namespace gr { + namespace trellis { + + class @IMPL_NAME@ : public @BASE_NAME@ + { + private: + fsm d_FSMo; + int d_STo; + fsm d_FSMi; + int d_STi; + interleaver d_INTERLEAVER; + int d_blocklength; + std::vector<int> d_buffer; + + public: + @IMPL_NAME@(const fsm &FSMo, int STo, + const fsm &FSMi, int STi, + const interleaver &INTERLEAVER, + int blocklength); + ~@IMPL_NAME@(); + + fsm FSMo() const { return d_FSMo; } + int STo() const { return d_STo; } + fsm FSMi() const { return d_FSMi; } + int STi() const { return d_STi; } + interleaver INTERLEAVER() const { return d_INTERLEAVER; } + int blocklength() const { return d_blocklength; } + + int work(int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace trellis */ +} /* namespace gr */ + +#endif /* @GUARD_NAME@ */ diff --git a/gr-trellis/lib/siso_combined_f_impl.cc b/gr-trellis/lib/siso_combined_f_impl.cc new file mode 100644 index 0000000000..7514d46747 --- /dev/null +++ b/gr-trellis/lib/siso_combined_f_impl.cc @@ -0,0 +1,180 @@ +/* -*- 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 "siso_combined_f_impl.h" +#include <gr_io_signature.h> +#include <stdexcept> +#include <assert.h> +#include <iostream> + +namespace gr { + namespace trellis { + + static const float INF = 1.0e9; + + siso_combined_f::sptr + siso_combined_f::make(const fsm &FSM, int K, + int S0, int SK, + bool POSTI, bool POSTO, + siso_type_t SISO_TYPE, + int D, const std::vector<float> &TABLE, + digital::trellis_metric_type_t TYPE) + { + return gnuradio::get_initial_sptr + (new siso_combined_f_impl(FSM, K, S0, SK, POSTI, POSTO, + SISO_TYPE, D, TABLE, TYPE)); + } + + siso_combined_f_impl::siso_combined_f_impl(const fsm &FSM, int K, + int S0, int SK, + bool POSTI, bool POSTO, + siso_type_t SISO_TYPE, + int D, const std::vector<float> &TABLE, + digital::trellis_metric_type_t TYPE) + : gr_block("siso_combined_f", + gr_make_io_signature(1, -1, sizeof(float)), + gr_make_io_signature(1, -1, sizeof(float))), + d_FSM(FSM), d_K(K), d_S0(S0), d_SK(SK), + d_POSTI(POSTI), d_POSTO(POSTO), + d_SISO_TYPE(SISO_TYPE), + d_D(D), d_TABLE(TABLE), d_TYPE(TYPE)//, + //d_alpha(FSM.S()*(K+1)), + //d_beta(FSM.S()*(K+1)) + { + int multiple; + if(d_POSTI && d_POSTO) + multiple = d_FSM.I()+d_FSM.O(); + else if(d_POSTI) + multiple = d_FSM.I(); + else if(d_POSTO) + multiple = d_FSM.O(); + else + throw std::runtime_error ("Not both POSTI and POSTO can be false."); + + //printf("constructor: Multiple = %d\n",multiple); + set_output_multiple(d_K*multiple); + + //what is the meaning of relative rate for a block with 2 inputs? + //set_relative_rate ( multiple / ((double) d_FSM.I()) ); + // it turns out that the above gives problems in the scheduler, so + // let's try (assumption O>I) + //set_relative_rate ( multiple / ((double) d_FSM.O()) ); + // I am tempted to automate like this + if(d_FSM.I() <= d_D) + set_relative_rate(multiple / ((double)d_D)); + else + set_relative_rate(multiple / ((double)d_FSM.I())); + } + + siso_combined_f_impl::~siso_combined_f_impl() + { + } + + void + siso_combined_f_impl::forecast(int noutput_items, + gr_vector_int &ninput_items_required) + { + int multiple; + if(d_POSTI && d_POSTO) + multiple = d_FSM.I()+d_FSM.O(); + else if(d_POSTI) + multiple = d_FSM.I(); + else if(d_POSTO) + multiple = d_FSM.O(); + else + throw std::runtime_error ("Not both POSTI and POSTO can be false."); + + //printf("forecast: Multiple = %d\n",multiple); + int input_required1 = d_FSM.I() * (noutput_items/multiple) ; + int input_required2 = d_D * (noutput_items/multiple) ; + //printf("forecast: Output requirements: %d\n",noutput_items); + //printf("forecast: Input requirements: %d %d\n",input_required1,input_required2); + unsigned ninputs = ninput_items_required.size(); + + for(unsigned int i = 0; i < ninputs/2; i++) { + ninput_items_required[2*i] = input_required1; + ninput_items_required[2*i+1] = input_required2; + } + } + + int + siso_combined_f_impl::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + int nstreams = output_items.size(); + //printf("general_work:Streams: %d\n",nstreams); + + int multiple; + if(d_POSTI && d_POSTO) + multiple = d_FSM.I()+d_FSM.O(); + else if(d_POSTI) + multiple = d_FSM.I(); + else if(d_POSTO) + multiple = d_FSM.O(); + else + throw std::runtime_error("siso_combined_f_impl:: Not both POSTI and POSTO can be false."); + + int nblocks = noutput_items / (d_K*multiple); + //printf("general_work:Blocks: %d\n",nblocks); + //for(int i=0;i<ninput_items.size();i++) + //printf("general_work:Input items available: %d\n",ninput_items[i]); + + float (*p2min)(float, float) = NULL; + if(d_SISO_TYPE == TRELLIS_MIN_SUM) + p2min = &min; + else if(d_SISO_TYPE == TRELLIS_SUM_PRODUCT) + p2min = &min_star; + + for(int m=0;m<nstreams;m++) { + const float *in1 = (const float*)input_items[2*m]; + const float *in2 = (const float*)input_items[2*m+1]; + float *out = (float *) output_items[m]; + for(int n=0;n<nblocks;n++) { + siso_algorithm_combined(d_FSM.I(),d_FSM.S(),d_FSM.O(), + d_FSM.NS(),d_FSM.OS(),d_FSM.PS(),d_FSM.PI(), + d_K,d_S0,d_SK, + d_POSTI,d_POSTO, + p2min, + d_D,d_TABLE,d_TYPE, + &(in1[n*d_K*d_FSM.I()]),&(in2[n*d_K*d_D]), + &(out[n*d_K*multiple])//, + //d_alpha,d_beta + ); + } + } + + for(unsigned int i = 0; i < input_items.size()/2; i++) { + consume(2*i,d_FSM.I() * noutput_items / multiple ); + consume(2*i+1,d_D * noutput_items / multiple ); + } + + return noutput_items; + } + + } /* namespace trellis */ +} /* namespace gr */ diff --git a/gr-trellis/lib/siso_combined_f_impl.h b/gr-trellis/lib/siso_combined_f_impl.h new file mode 100644 index 0000000000..27cef5e334 --- /dev/null +++ b/gr-trellis/lib/siso_combined_f_impl.h @@ -0,0 +1,79 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_TRELLIS_SISO_COMBINED_F_IMPL_H +#define INCLUDED_TRELLIS_SISO_COMBINED_F_IMPL_H + +#include <trellis/siso_combined_f.h> + +namespace gr { + namespace trellis { + + class siso_combined_f_impl : public siso_combined_f + { + private: + fsm d_FSM; + int d_K; + int d_S0; + int d_SK; + bool d_POSTI; + bool d_POSTO; + siso_type_t d_SISO_TYPE; + int d_D; + std::vector<float> d_TABLE; + digital::trellis_metric_type_t d_TYPE; + //std::vector<float> d_alpha; + //std::vector<float> d_beta; + + public: + siso_combined_f_impl(const fsm &FSM, int K, + int S0, int SK, + bool POSTI, bool POSTO, + siso_type_t d_SISO_TYPE, + int D, const std::vector<float> &TABLE, + digital::trellis_metric_type_t TYPE); + ~siso_combined_f_impl(); + + fsm FSM() const { return d_FSM; } + int K() const { return d_K; } + int S0() const { return d_S0; } + int SK() const { return d_SK; } + bool POSTI() const { return d_POSTI; } + bool POSTO() const { return d_POSTO; } + siso_type_t SISO_TYPE() const { return d_SISO_TYPE; } + int D() const { return d_D; } + std::vector<float> TABLE() const { return d_TABLE; } + digital::trellis_metric_type_t TYPE() const { return d_TYPE; } + + 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); + }; + + } /* namespace trellis */ +} /* namespace gr */ + +#endif /* INCLUDED_TRELLIS_SISO_COMBINED_F_IMPL_H */ diff --git a/gr-trellis/lib/siso_f_impl.cc b/gr-trellis/lib/siso_f_impl.cc new file mode 100644 index 0000000000..b0484f6f37 --- /dev/null +++ b/gr-trellis/lib/siso_f_impl.cc @@ -0,0 +1,171 @@ +/* -*- 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 "siso_f_impl.h" +#include <gr_io_signature.h> +#include <stdexcept> +#include <assert.h> +#include <iostream> + +namespace gr { + namespace trellis { + + static const float INF = 1.0e9; + + siso_f::sptr + siso_f::make(const fsm &FSM, int K, + int S0, int SK, + bool POSTI, bool POSTO, + siso_type_t SISO_TYPE) + { + return gnuradio::get_initial_sptr + (new siso_f_impl(FSM, K, S0, SK, POSTI, POSTO, SISO_TYPE)); + } + + siso_f_impl::siso_f_impl(const fsm &FSM, int K, + int S0, int SK, + bool POSTI, bool POSTO, + siso_type_t SISO_TYPE) + : gr_block("siso_f", + gr_make_io_signature(1, -1, sizeof(float)), + gr_make_io_signature(1, -1, sizeof(float))), + d_FSM(FSM), d_K(K), + d_S0(S0),d_SK(SK), + d_POSTI(POSTI), d_POSTO(POSTO), + d_SISO_TYPE(SISO_TYPE)//, + //d_alpha(FSM.S()*(K+1)), + //d_beta(FSM.S()*(K+1)) + { + int multiple; + if(d_POSTI && d_POSTO) + multiple = d_FSM.I()+d_FSM.O(); + else if(d_POSTI) + multiple = d_FSM.I(); + else if(d_POSTO) + multiple = d_FSM.O(); + else + throw std::runtime_error ("Not both POSTI and POSTO can be false."); + + //printf("constructor: Multiple = %d\n",multiple); + set_output_multiple (d_K*multiple); + + //what is the meaning of relative rate for a block with 2 inputs? + //set_relative_rate ( multiple / ((double) d_FSM.I()) ); + // it turns out that the above gives problems in the scheduler, so + // let's try (assumption O>I) + //set_relative_rate ( multiple / ((double) d_FSM.O()) ); + // I am tempted to automate like this + if(d_FSM.I() <= d_FSM.O()) + set_relative_rate(multiple / ((double) d_FSM.O())); + else + set_relative_rate(multiple / ((double) d_FSM.I())); + } + + siso_f_impl::~siso_f_impl() + { + } + + void + siso_f_impl::forecast(int noutput_items, gr_vector_int &ninput_items_required) + { + int multiple; + if(d_POSTI && d_POSTO) + multiple = d_FSM.I()+d_FSM.O(); + else if(d_POSTI) + multiple = d_FSM.I(); + else if(d_POSTO) + multiple = d_FSM.O(); + else + throw std::runtime_error ("Not both POSTI and POSTO can be false."); + + //printf("forecast: Multiple = %d\n",multiple); + int input_required1 = d_FSM.I() * (noutput_items/multiple) ; + int input_required2 = d_FSM.O() * (noutput_items/multiple) ; + //printf("forecast: Output requirements: %d\n",noutput_items); + //printf("forecast: Input requirements: %d %d\n",input_required1,input_required2); + unsigned ninputs = ninput_items_required.size(); + for(unsigned int i = 0; i < ninputs/2; i++) { + ninput_items_required[2*i] = input_required1; + ninput_items_required[2*i+1] = input_required2; + } + } + + int + siso_f_impl::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + int nstreams = output_items.size(); + //printf("general_work:Streams: %d\n",nstreams); + int multiple; + if(d_POSTI && d_POSTO) + multiple = d_FSM.I()+d_FSM.O(); + else if(d_POSTI) + multiple = d_FSM.I(); + else if(d_POSTO) + multiple = d_FSM.O(); + else + throw std::runtime_error("siso_f_impl: Not both POSTI and POSTO can be false.\n"); + + int nblocks = noutput_items / (d_K*multiple); + //printf("general_work:Blocks: %d\n",nblocks); + //for(int i=0;i<ninput_items.size();i++) + //printf("general_work:Input items available: %d\n",ninput_items[i]); + + float (*p2min)(float, float) = NULL; + if(d_SISO_TYPE == TRELLIS_MIN_SUM) + p2min = &min; + else if(d_SISO_TYPE == TRELLIS_SUM_PRODUCT) + p2min = &min_star; + + for(int m = 0; m < nstreams; m++) { + const float *in1 = (const float*)input_items[2*m]; + const float *in2 = (const float*)input_items[2*m+1]; + float *out = (float*)output_items[m]; + for(int n = 0;n < nblocks; n++) { + siso_algorithm(d_FSM.I(),d_FSM.S(),d_FSM.O(), + d_FSM.NS(),d_FSM.OS(),d_FSM.PS(),d_FSM.PI(), + d_K,d_S0,d_SK, + d_POSTI,d_POSTO, + p2min, + &(in1[n*d_K*d_FSM.I()]),&(in2[n*d_K*d_FSM.O()]), + &(out[n*d_K*multiple])//, + //d_alpha,d_beta + ); + } + } + + for(unsigned int i = 0; i < input_items.size()/2; i++) { + consume(2*i,d_FSM.I() * noutput_items / multiple ); + consume(2*i+1,d_FSM.O() * noutput_items / multiple ); + } + + return noutput_items; + } + + } /* namespace trellis */ +} /* namespace gr */ diff --git a/gr-trellis/lib/siso_f_impl.h b/gr-trellis/lib/siso_f_impl.h new file mode 100644 index 0000000000..40766b97fa --- /dev/null +++ b/gr-trellis/lib/siso_f_impl.h @@ -0,0 +1,75 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_TRELLIS_SISO_F_IMPL_H +#define INCLUDED_TRELLIS_SISO_F_IMPL_H + +#include <trellis/api.h> +#include <trellis/fsm.h> +#include <trellis/siso_type.h> +#include <trellis/core_algorithms.h> +#include <trellis/siso_f.h> + +namespace gr { + namespace trellis { + + class siso_f_impl : public siso_f + { + private: + fsm d_FSM; + int d_K; + int d_S0; + int d_SK; + bool d_POSTI; + bool d_POSTO; + siso_type_t d_SISO_TYPE; + //std::vector<float> d_alpha; + //std::vector<float> d_beta; + + public: + siso_f_impl(const fsm &FSM, int K, + int S0, int SK, + bool POSTI, bool POSTO, + siso_type_t d_SISO_TYPE); + ~siso_f_impl(); + + fsm FSM() const { return d_FSM; } + int K() const { return d_K; } + int S0() const { return d_S0; } + int SK() const { return d_SK; } + bool POSTI() const { return d_POSTI; } + bool POSTO() const { return d_POSTO; } + siso_type_t SISO_TYPE() const { return d_SISO_TYPE; } + + 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); + }; + + } /* namespace trellis */ +} /* namespace gr */ + +#endif /* INCLUDED_TRELLIS_SISO_F_IMPL_H */ diff --git a/gr-trellis/lib/viterbi_X_impl.cc.t b/gr-trellis/lib/viterbi_X_impl.cc.t new file mode 100644 index 0000000000..5097cc2053 --- /dev/null +++ b/gr-trellis/lib/viterbi_X_impl.cc.t @@ -0,0 +1,99 @@ +/* -*- 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 <iostream> + +namespace gr { + namespace trellis { + + static const float INF = 1.0e9; + + @BASE_NAME@::sptr + @BASE_NAME@::make(const fsm &FSM, int K, + int S0, int SK) + { + return gnuradio::get_initial_sptr + (new @IMPL_NAME@(FSM, K, S0, SK)); + } + + @IMPL_NAME@::@IMPL_NAME@(const fsm &FSM, int K, + int S0, int SK) + : gr_block("@BASE_NAME@", + gr_make_io_signature(1, -1, sizeof(float)), + gr_make_io_signature(1, -1, sizeof(@TYPE@))), + d_FSM(FSM), d_K(K), d_S0(S0), d_SK(SK)//, + //d_trace(FSM.S()*K) + { + set_relative_rate(1.0 / ((double)d_FSM.O())); + set_output_multiple(d_K); + } + + @IMPL_NAME@::~@IMPL_NAME@() + { + } + + void + @IMPL_NAME@::forecast(int noutput_items, + gr_vector_int &ninput_items_required) + { + int input_required = d_FSM.O() * noutput_items; + unsigned ninputs = ninput_items_required.size(); + for(unsigned int i = 0; i < ninputs; i++) { + ninput_items_required[i] = input_required; + } + } + + int + @IMPL_NAME@::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + int nstreams = input_items.size(); + int nblocks = noutput_items / d_K; + + for(int m = 0; m < nstreams; m++) { + const float *in = (const float*)input_items[m]; + @TYPE@ *out = (@TYPE@*)output_items[m]; + + for(int n = 0; n < nblocks; n++) { + viterbi_algorithm(d_FSM.I(), d_FSM.S(), d_FSM.O(), + d_FSM.NS(), d_FSM.OS(), d_FSM.PS(), + d_FSM.PI(), d_K,d_S0, d_SK, + &(in[n*d_K*d_FSM.O()]), &(out[n*d_K])); + } + } + + consume_each(d_FSM.O() * noutput_items); + return noutput_items; + } + + } /* namespace trellis */ +} /* namespace gr */ diff --git a/gr-trellis/lib/viterbi_X_impl.h.t b/gr-trellis/lib/viterbi_X_impl.h.t new file mode 100644 index 0000000000..accaacc158 --- /dev/null +++ b/gr-trellis/lib/viterbi_X_impl.h.t @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <trellis/@BASE_NAME@.h> + +namespace gr { + namespace trellis { + + class @IMPL_NAME@ : public @BASE_NAME@ + { + private: + fsm d_FSM; + int d_K; + int d_S0; + int d_SK; + //std::vector<int> d_trace; + + public: + @IMPL_NAME@(const fsm &FSM, int K, + int S0, int SK); + ~@IMPL_NAME@(); + + fsm FSM() const { return d_FSM; } + int K() const { return d_K; } + int S0() const { return d_S0; } + int SK() const { return d_SK; } + + //std::vector<int> trace () const { return d_trace; } + + 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); + }; + + } /* namespace trellis */ +} /* namespace gr */ + +#endif /* @GUARD_NAME@ */ diff --git a/gr-trellis/lib/viterbi_combined_XX_impl.cc.t b/gr-trellis/lib/viterbi_combined_XX_impl.cc.t new file mode 100644 index 0000000000..95175bef95 --- /dev/null +++ b/gr-trellis/lib/viterbi_combined_XX_impl.cc.t @@ -0,0 +1,112 @@ +/* -*- 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 <iostream> + +namespace gr { + namespace trellis { + + static const float INF = 1.0e9; + + @BASE_NAME@::sptr + @BASE_NAME@::make(const fsm &FSM, int K, + int S0, int SK, int D, + const std::vector<@I_TYPE@> &TABLE, + digital::trellis_metric_type_t TYPE) + { + return gnuradio::get_initial_sptr + (new @NAME@(FSM, K, S0, SK, D, TABLE,TYPE)); + } + + @IMPL_NAME@::@IMPL_NAME@(const fsm &FSM, int K, + int S0, int SK, int D, + const std::vector<@I_TYPE@> &TABLE, + digital::trellis_metric_type_t TYPE) + : gr_block("@BASE_NAME@", + gr_make_io_signature(1, -1, sizeof(@I_TYPE@)), + gr_make_io_signature(1, -1, sizeof(@O_TYPE@))), + d_FSM(FSM), d_K(K), d_S0(S0), d_SK(SK), d_D(D), + d_TABLE(TABLE), d_TYPE(TYPE)//, + //d_trace(FSM.S()*K) + { + set_relative_rate(1.0 / ((double)d_D)); + set_output_multiple(d_K); + } + + @IMPL_NAME@::~@IMPL_NAME@() + { + } + + void + @IMPL_NAME@::set_TABLE(const std::vector<@I_TYPE@> &table) + { + d_TABLE = table; + } + + void + @IMPL_NAME@::forecast(int noutput_items, + gr_vector_int &ninput_items_required) + { + int input_required = d_D * noutput_items; + unsigned ninputs = ninput_items_required.size(); + for(unsigned int i = 0; i < ninputs; i++) { + ninput_items_required[i] = input_required; + } + } + + int + @IMPL_NAME@::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + int nstreams = input_items.size(); + int nblocks = noutput_items / d_K; + + for(int m=0;m<nstreams;m++) { + const @I_TYPE@ *in = (const @I_TYPE@*)input_items[m]; + @O_TYPE@ *out = (@O_TYPE@*)output_items[m]; + + for(int n=0;n<nblocks;n++) { + viterbi_algorithm_combined(d_FSM.I(), d_FSM.S(), d_FSM.O(), + d_FSM.NS(), d_FSM.OS(), d_FSM.PS(), + d_FSM.PI(), d_K,d_S0, d_SK, d_D, + d_TABLE, d_TYPE, + &(in[n*d_K*d_D]), &(out[n*d_K])); + } + } + + consume_each(d_D * noutput_items); + return noutput_items; + } + + } /* namespace trellis */ +} /* namespace gr */ + diff --git a/gr-trellis/lib/viterbi_combined_XX_impl.h.t b/gr-trellis/lib/viterbi_combined_XX_impl.h.t new file mode 100644 index 0000000000..df62001110 --- /dev/null +++ b/gr-trellis/lib/viterbi_combined_XX_impl.h.t @@ -0,0 +1,74 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +// @WARNING@ + +#ifndef @GUARD_NAME@ +#define @GUARD_NAME@ + +#include <trellis/@BASE_NAME@.h> + +namespace gr { + namespace trellis { + + class @IMPL_NAME@ : public @BASE_NAME@ + { + private: + fsm d_FSM; + int d_K; + int d_S0; + int d_SK; + int d_D; + std::vector<@I_TYPE@> d_TABLE; + digital::trellis_metric_type_t d_TYPE; + //std::vector<int> d_trace; + + public: + @IMPL_NAME@(const fsm &FSM, int K, + int S0, int SK, int D, + const std::vector<@I_TYPE@> &TABLE, + digital::trellis_metric_type_t TYPE); + ~@IMPL_NAME@(); + + fsm FSM() const { return d_FSM; } + int K() const { return d_K; } + int S0() const { return d_S0; } + int SK() const { return d_SK; } + int D() const { return d_D; } + std::vector<@I_TYPE@> TABLE() const { return d_TABLE; } + digital::trellis_metric_type_t TYPE() const { return d_TYPE; } + //std::vector<int> trace() const { return d_trace; } + void set_TABLE(const std::vector<@I_TYPE@> &table); + + 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); + }; + + } /* namespace trellis */ +} /* namespace gr */ + +#endif /* @GUARD_NAME@ */ |