added a OQPSK demodulator

This commit is contained in:
Christoph Mayer 2019-11-05 21:24:51 +01:00
parent a26686f0fd
commit 2c96e006b0
8 changed files with 331 additions and 0 deletions

View File

@ -22,5 +22,6 @@ install(FILES
digitalhf_physical_layer_driver.xml
digitalhf_doppler_correction_cc.xml
digitalhf_cis_12_channelizer.xml
digitalhf_oqpsk_demodulator.xml
digitalhf_msg_proxy.xml DESTINATION share/gnuradio/grc/blocks
)

View File

@ -0,0 +1,40 @@
<?xml version="1.0"?>
<block>
<name>oqpsk_demodulator</name>
<key>digitalhf_oqpsk_demodulator</key>
<category>[digitalhf]</category>
<import>import digitalhf</import>
<make>digitalhf.oqpsk_demodulator($fs, $fd, $loop_bw, $df)</make>
<param>
<name>fs (Hz)</name>
<key>fs</key>
<type>float</type>
</param>
<param>
<name>fd (Hz)</name>
<key>fd</key>
<type>float</type>
</param>
<param>
<name>loop_bw</name>
<key>loop_bw</key>
<type>float</type>
</param>
<param>
<name>df (Hz)</name>
<key>df</key>
<type>float</type>
</param>
<sink>
<name>in</name>
<type>complex</type>
</sink>
<source>
<name>soft_dec_x</name>
<type>float</type>
</source>
<source>
<name>soft_dec_y</name>
<type>float</type>
</source>
</block>

View File

@ -29,6 +29,7 @@ install(FILES
viterbi29.h
viterbi39.h
viterbi48.h
oqpsk_demodulator.h
vector_pll_cc.h
DESTINATION include/digitalhf
)

View File

@ -0,0 +1,60 @@
/* -*- c++ -*- */
/*
* Copyright 2019 hcab14@gmail.com.
*
* This is free software; you can 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.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_DIGITALHF_OQPSK_DEMODULATOR_H
#define INCLUDED_DIGITALHF_OQPSK_DEMODULATOR_H
#include <digitalhf/api.h>
#include <gnuradio/block.h>
namespace gr {
namespace digitalhf {
/*!
* \brief <+description of block+>
* \ingroup digitalhf
*
*/
class DIGITALHF_API oqpsk_demodulator : virtual public gr::block
{
public:
typedef boost::shared_ptr<oqpsk_demodulator> sptr;
/*!
* \brief Return a shared_ptr to a new instance of digitalhf::oqpsk_demodulator.
*
* To avoid accidental use of raw pointers, digitalhf::oqpsk_demodulator's
* constructor is in a private implementation
* class. digitalhf::oqpsk_demodulator::make is the public interface for
* creating new instances.
*/
static sptr make(float fs=240e3,
float fd=48e3,
float loop_bw=3.1415/100.0f,
float df=20.0f);
};
} // namespace digitalhf
} // namespace gr
#endif /* INCLUDED_DIGITALHF_OQPSK_DEMODULATOR_H */

View File

@ -32,6 +32,7 @@ list(APPEND digitalhf_sources
viterbi29_impl.cc
viterbi39_impl.cc
viterbi48_impl.cc
oqpsk_demodulator_impl.cc
vector_pll_cc_impl.cc
vector_early_late_cc_impl.cc
lms.cc

View File

@ -0,0 +1,152 @@
/* -*- c++ -*- */
/*
* Copyright 2019 hcab14@gmail.com.
*
* This is free software; you can 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.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; 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 <cmath>
#include <gnuradio/io_signature.h>
#include <gnuradio/expj.h>
#include <gnuradio/logger.h>
#include <gnuradio/math.h>
#include <gnuradio/sincos.h>
#include "oqpsk_demodulator_impl.h"
namespace gr {
namespace digitalhf {
my_control_loop::~my_control_loop() {
}
void
my_control_loop::phase_wrap(float x)
{
// d_phase = fmodf(d_phase, x);
while (d_phase > x)
d_phase -= x;
while (d_phase < -x)
d_phase += x;
}
oqpsk_demodulator::sptr
oqpsk_demodulator::make(float fs,
float fd,
float loop_bw,
float df)
{
return gnuradio::get_initial_sptr
(new oqpsk_demodulator_impl(fs, fd, loop_bw, df));
}
/*
* The private constructor
*/
oqpsk_demodulator_impl::oqpsk_demodulator_impl(float fs,
float fd,
float loop_bw,
float df)
: gr::block("oqpsk_demodulator",
gr::io_signature::make(1, 1, sizeof(gr_complex)),
gr::io_signature::make(2, 2, sizeof(float)))
, _pll_plus (loop_bw,
(+0.5f*fd + df)/fs*2*M_PI,
(+0.5f*fd - df)/fs*2*M_PI)
, _pll_minus(loop_bw,
(-0.5f*fd + df)/fs*2*M_PI,
(-0.5f*fd - df)/fs*2*M_PI)
, _soft_dec_x(0.0f)
, _soft_dec_y(0.0f)
, _soft_dec_x_last(0.0f)
, _soft_dec_y_last(0.0f)
, _code_cos_last(0.0f)
, _code_sin_last(0.0f)
{
GR_LOG_DECLARE_LOGPTR(d_logger);
GR_LOG_ASSIGN_LOGPTR(d_logger, "oqpsk_demodulator");
}
oqpsk_demodulator_impl::~oqpsk_demodulator_impl()
{
}
int
oqpsk_demodulator_impl::general_work(int noutput_items,
gr_vector_int& ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
gr::thread::scoped_lock lock(d_setlock);
gr_complex const* in = static_cast<gr_complex const*>(input_items[0]);
float* out_x = static_cast<float*>(output_items[0]);
float* out_y = static_cast<float*>(output_items[1]);
int nout = 0;
int i = 0;
for (; i<ninput_items[0] && nout < noutput_items; ++i) {
gr_complex const sample = *in++;
float const carr_phase = 0.25f*(_pll_plus.get_phase() + _pll_minus.get_phase());
float const code_phase = 0.25f*(_pll_plus.get_phase() - _pll_minus.get_phase());
float code_sin(0.0f), code_cos(0.0f);
gr::sincosf(code_phase, &code_sin, &code_cos);
if (std::signbit(code_cos) != std::signbit(_code_cos_last)) {
_soft_dec_x_last = _soft_dec_x;
_soft_dec_x = 0.0f;
*out_x++ = _soft_dec_x_last;
*out_y++ = _soft_dec_y_last;
nout += 1;
}
if (std::signbit(code_sin) != std::signbit(_code_sin_last)) {
_soft_dec_y_last = _soft_dec_y;
_soft_dec_y = 0.0f;
*out_x++ = _soft_dec_x_last;
*out_y++ = _soft_dec_y_last;
nout += 1;
}
_code_cos_last = code_cos;
_code_sin_last = code_sin;
gr_complex const z = sample*gr_expj(-carr_phase);
_soft_dec_x += code_cos * std::real(z);
_soft_dec_y += code_sin * std::imag(z);
gr_complex const z2 = sample*sample;
float const error_plus = gr::fast_atan2f(z2 * gr_expj(-_pll_plus.get_phase()));
_pll_plus.advance_loop(error_plus);
_pll_plus.phase_wrap(8*M_PI);
_pll_plus.frequency_limit();
float const error_minus = gr::fast_atan2f(z2 * gr_expj(-_pll_minus.get_phase()));
_pll_minus.advance_loop(error_minus);
_pll_minus.phase_wrap(8*M_PI);
_pll_minus.frequency_limit();
}
consume_each(i);
return nout;
}
} /* namespace digitalhf */
} /* namespace gr */

View File

@ -0,0 +1,72 @@
/* -*- c++ -*- */
/*
* Copyright 2019 hcab14@gmail.com.
*
* This is free software; you can 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.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef INCLUDED_DIGITALHF_OQPSK_DEMODULATOR_IMPL_H
#define INCLUDED_DIGITALHF_OQPSK_DEMODULATOR_IMPL_H
#include <gnuradio/blocks/control_loop.h>
#include <digitalhf/oqpsk_demodulator.h>
namespace gr {
namespace digitalhf {
class my_control_loop : public blocks::control_loop {
public:
my_control_loop(float loop_bw, float max_freq, float min_freq)
: blocks::control_loop(loop_bw, max_freq, min_freq) {}
virtual ~my_control_loop();
virtual void phase_wrap(float x);
protected:
} ;
class oqpsk_demodulator_impl : public oqpsk_demodulator
{
private:
my_control_loop _pll_plus;
my_control_loop _pll_minus;
float _soft_dec_x;
float _soft_dec_y;
float _soft_dec_x_last;
float _soft_dec_y_last;
float _code_cos_last;
float _code_sin_last;
public:
oqpsk_demodulator_impl(float fs,
float fd,
float loop_bw,
float df);
virtual ~oqpsk_demodulator_impl();
int general_work(int noutput_items,
gr_vector_int& ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
protected:
};
} // namespace digitalhf
} // namespace gr
#endif /* INCLUDED_DIGITALHF_OQPSK_DEMODULATOR_IMPL_H */

View File

@ -10,6 +10,7 @@
%{
#include "digitalhf/adaptive_dfe.h"
#include "digitalhf/doppler_correction_cc.h"
#include "digitalhf/oqpsk_demodulator.h"
#include "digitalhf/viterbi27.h"
#include "digitalhf/viterbi29.h"
#include "digitalhf/viterbi39.h"
@ -27,6 +28,9 @@ GR_SWIG_BLOCK_MAGIC2(digitalhf, doppler_correction_cc);
%include "digitalhf/vector_pll_cc.h"
GR_SWIG_BLOCK_MAGIC2(digitalhf, vector_pll_cc);
%include "digitalhf/oqpsk_demodulator.h"
GR_SWIG_BLOCK_MAGIC2(digitalhf, oqpsk_demodulator);
%include "digitalhf/vector_early_late_cc.h"
GR_SWIG_BLOCK_MAGIC2(digitalhf, vector_early_late_cc);