diff options
Diffstat (limited to 'gr-analog/lib')
-rw-r--r-- | gr-analog/lib/CMakeLists.txt | 2 | ||||
-rw-r--r-- | gr-analog/lib/ctcss_squelch_ff_impl.cc | 130 | ||||
-rw-r--r-- | gr-analog/lib/ctcss_squelch_ff_impl.h | 82 | ||||
-rw-r--r-- | gr-analog/lib/squelch_base_ff_impl.cc | 140 | ||||
-rw-r--r-- | gr-analog/lib/squelch_base_ff_impl.h | 65 |
5 files changed, 419 insertions, 0 deletions
diff --git a/gr-analog/lib/CMakeLists.txt b/gr-analog/lib/CMakeLists.txt index f18c84274..b0f7a17de 100644 --- a/gr-analog/lib/CMakeLists.txt +++ b/gr-analog/lib/CMakeLists.txt @@ -104,6 +104,8 @@ endmacro(expand_cc) list(APPEND analog_sources ${generated_sources} cpm.cc + squelch_base_ff_impl.cc + ctcss_squelch_ff_impl.cc ) list(APPEND analog_libs diff --git a/gr-analog/lib/ctcss_squelch_ff_impl.cc b/gr-analog/lib/ctcss_squelch_ff_impl.cc new file mode 100644 index 000000000..db49b4f6e --- /dev/null +++ b/gr-analog/lib/ctcss_squelch_ff_impl.cc @@ -0,0 +1,130 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006,2010,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "ctcss_squelch_ff_impl.h" + +namespace gr { + namespace analog { + + static float ctcss_tones[] = { + 67.0, 71.9, 74.4, 77.0, 79.7, 82.5, 85.4, 88.5, 91.5, 94.8, + 97.4, 100.0, 103.5, 107.2, 110.9, 114.8, 118.8, 123.0, 127.3, 131.8, + 136.5, 141.3, 146.2, 151.4, 156.7, 162.2, 167.9, 173.8, 179.9, 186.2, + 192.8, 203.5, 210.7, 218.1, 225.7, 233.6, 241.8, 250.3 + }; + + static int max_tone_index = 37; + + ctcss_squelch_ff::sptr + ctcss_squelch_ff::make(int rate, float freq, float level, + int len, int ramp, bool gate) + { + return gnuradio::get_initial_sptr(new ctcss_squelch_ff_impl + (rate, freq, level, len, ramp, gate)); + } + + int + ctcss_squelch_ff_impl::find_tone(float freq) + { + for(int i = 0; i <= max_tone_index; i++) + if(ctcss_tones[i] == freq) // FIXME: make almost equal + return i; + return -1; + } + + ctcss_squelch_ff_impl::ctcss_squelch_ff_impl(int rate, float freq, float level, + int len, int ramp, bool gate) + : gr_block("ctcss_squelch_ff", + gr_make_io_signature(1, 1, sizeof(float)), + gr_make_io_signature(1, 1, sizeof(float))), + squelch_base_ff_impl("ctcss_squelch_ff", ramp, gate) + { + d_freq = freq; + d_level = level; + + // Default is 100 ms detection time + if(len == 0) + d_len = (int)(rate/10.0); + else + d_len = len; + + int i = find_tone(freq); + + // Non-standard tones or edge tones get 2% guard band, otherwise + // guards are set at adjacent ctcss tone frequencies + float f_l, f_r; + if(i == -1 || i == 0) + f_l = freq*0.98; + else + f_l = ctcss_tones[i-1]; + + if(i == -1 || i == max_tone_index) + f_r = freq*1.02; + else + f_r = ctcss_tones[i+1]; + + d_goertzel_l = fft::goertzel(rate, d_len, f_l); + d_goertzel_c = fft::goertzel(rate, d_len, freq); + d_goertzel_r = fft::goertzel(rate, d_len, f_r); + + d_mute = true; + } + + ctcss_squelch_ff_impl::~ctcss_squelch_ff_impl() + { + } + + std::vector<float> + ctcss_squelch_ff_impl::squelch_range() const + { + std::vector<float> r(3); + r[0] = 0.0; + r[1] = 1.0; + r[2] = (r[1]-r[0])/100; // step size + + return r; + } + + void + ctcss_squelch_ff_impl::update_state(const float &in) + { + d_goertzel_l.input(in); + d_goertzel_c.input(in); + d_goertzel_r.input(in); + + float d_out_l, d_out_c, d_out_r; + if(d_goertzel_c.ready()) { + d_out_l = abs(d_goertzel_l.output()); + d_out_c = abs(d_goertzel_c.output()); + d_out_r = abs(d_goertzel_r.output()); + + //printf("d_out_l=%f d_out_c=%f d_out_r=%f\n", d_out_l, d_out_c, d_out_r); + d_mute = (d_out_c < d_level || d_out_c < d_out_l || d_out_c < d_out_r); + } + } + + } /* namespace analog */ +} /* namespace gr */ diff --git a/gr-analog/lib/ctcss_squelch_ff_impl.h b/gr-analog/lib/ctcss_squelch_ff_impl.h new file mode 100644 index 000000000..0827fbafe --- /dev/null +++ b/gr-analog/lib/ctcss_squelch_ff_impl.h @@ -0,0 +1,82 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_ANALOG_CTCSS_SQUELCH_FF_IMPL_H +#define INCLUDED_ANALOG_CTCSS_SQUELCH_FF_IMPL_H + +#include <analog/ctcss_squelch_ff.h> +#include "squelch_base_ff_impl.h" +#include <fft/goertzel.h> + +namespace gr { + namespace analog { + + class ctcss_squelch_ff_impl : public ctcss_squelch_ff, squelch_base_ff_impl + { + private: + float d_freq; + float d_level; + int d_len; + bool d_mute; + + fft::goertzel d_goertzel_l; + fft::goertzel d_goertzel_c; + fft::goertzel d_goertzel_r; + + int find_tone(float freq); + + protected: + virtual void update_state(const float &in); + virtual bool mute() const { return d_mute; } + + public: + ctcss_squelch_ff_impl(int rate, float freq, float level, + int len, int ramp, bool gate); + ~ctcss_squelch_ff_impl(); + + std::vector<float> squelch_range() const; + float level() const { return d_level; } + void set_level(float level) { d_level = level; } + int len() const { return d_len; } + + int ramp() const { return squelch_base_ff_impl::ramp(); } + void set_ramp(int ramp) { squelch_base_ff_impl::set_ramp(ramp); } + bool gate() const { return squelch_base_ff_impl::gate(); } + void set_gate(bool gate) { squelch_base_ff_impl::set_gate(gate); } + bool unmuted() const { return squelch_base_ff_impl::unmuted(); } + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + return squelch_base_ff_impl::general_work(noutput_items, + ninput_items, + input_items, + output_items); + } + }; + + } /* namespace analog */ +} /* namespace gr */ + +#endif /* INCLUDED_ANALOG_CTCSS_SQUELCH_FF_IMPL_H */ diff --git a/gr-analog/lib/squelch_base_ff_impl.cc b/gr-analog/lib/squelch_base_ff_impl.cc new file mode 100644 index 000000000..f9f07d36d --- /dev/null +++ b/gr-analog/lib/squelch_base_ff_impl.cc @@ -0,0 +1,140 @@ +/* -*- c++ -*- */ +/* + * Copyright 2004,2006,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "squelch_base_ff_impl.h" +#include <gr_io_signature.h> + +namespace gr { + namespace analog { + + squelch_base_ff_impl::squelch_base_ff_impl(const char *name, int ramp, bool gate) + : gr_block(name, + gr_make_io_signature(1, 1, sizeof(float)), + gr_make_io_signature(1, 1, sizeof(float))) + { + set_ramp(ramp); + set_gate(gate); + d_state = ST_MUTED; + d_envelope = d_ramp ? 0.0 : 1.0; + d_ramped = 0; + } + + squelch_base_ff_impl::~squelch_base_ff_impl() + { + } + + int + squelch_base_ff_impl::ramp() const + { + return d_ramp; + } + + void + squelch_base_ff_impl::set_ramp(int ramp) + { + d_ramp = ramp; + } + + bool + squelch_base_ff_impl::gate() const + { + return d_gate; + } + + void + squelch_base_ff_impl::set_gate(bool gate) + { + d_gate = gate; + } + + bool + squelch_base_ff_impl::unmuted() const + { + return (d_state == ST_UNMUTED || d_state == ST_ATTACK); + } + + int + squelch_base_ff_impl::general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) + { + const float *in = (const float *) input_items[0]; + float *out = (float *) output_items[0]; + + int j = 0; + + for(int i = 0; i < noutput_items; i++) { + update_state(in[i]); + + // Adjust envelope based on current state + switch(d_state) { + case ST_MUTED: + if(!mute()) + // If not ramping, go straight to unmuted + d_state = d_ramp ? ST_ATTACK : ST_UNMUTED; + break; + + case ST_UNMUTED: + if(mute()) + // If not ramping, go straight to muted + d_state = d_ramp ? ST_DECAY : ST_MUTED; + break; + + case ST_ATTACK: + // FIXME: precalculate window for speed + d_envelope = 0.5-std::cos(M_PI*(++d_ramped)/d_ramp)/2.0; + + // use >= in case d_ramp is set to lower value elsewhere + if(d_ramped >= d_ramp) { + d_state = ST_UNMUTED; + d_envelope = 1.0; + } + break; + + case ST_DECAY: + // FIXME: precalculate window for speed + d_envelope = 0.5-std::cos(M_PI*(--d_ramped)/d_ramp)/2.0; + if(d_ramped == 0.0) + d_state = ST_MUTED; + break; + }; + + // If unmuted, copy input times envelope to output + // Otherwise, if not gating, copy zero to output + if(d_state != ST_MUTED) + out[j++] = in[i]*d_envelope; + else + if(!d_gate) + out[j++] = 0.0; + } + + consume_each(noutput_items); // Use all the inputs + return j; // But only report outputs copied + } + + } /* namespace analog */ +} /* namespace gr */ diff --git a/gr-analog/lib/squelch_base_ff_impl.h b/gr-analog/lib/squelch_base_ff_impl.h new file mode 100644 index 000000000..22659be74 --- /dev/null +++ b/gr-analog/lib/squelch_base_ff_impl.h @@ -0,0 +1,65 @@ +/* -*- c++ -*- */ +/* + * Copyright 2006,2012 Free Software Foundation, Inc. + * + * This file is part of GNU Radio + * + * GNU Radio is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * GNU Radio is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNU Radio; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +#ifndef INCLUDED_GR_SQUELCH_BASE_FF_IMPL_H +#define INCLUDED_GR_SQUELCH_BASE_FF_IMPL_H + +#include <analog/squelch_base_ff.h> + +namespace gr { + namespace analog { + + class squelch_base_ff_impl : public squelch_base_ff + { + private: + int d_ramp; + int d_ramped; + bool d_gate; + double d_envelope; + enum { ST_MUTED, ST_ATTACK, ST_UNMUTED, ST_DECAY } d_state; + + protected: + virtual void update_state(const float &sample) {}; + virtual bool mute() const { return false; }; + + public: + squelch_base_ff_impl(const char *name, int ramp, bool gate); + ~squelch_base_ff_impl(); + + int ramp() const; + void set_ramp(int ramp); + bool gate() const; + void set_gate(bool gate); + bool unmuted() const; + + virtual std::vector<float> squelch_range() const = 0; + + int general_work(int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + }; + + } /* namespace analog */ +} /* namespace gr */ + +#endif /* INCLUDED_ANALOG_SQUELCH_BASE_IMPL_FF_H */ |