Abandon idea of P25 decoder being a sink. This means subclassing gr_block instead of gr_sync_block, some name changes and allowing for audio output from the block.
git-svn-id: http://op25.osmocom.org/svn/trunk@91 65a5c917-d112-43f1-993d-58c26a4786be
This commit is contained in:
parent
e816a8c913
commit
ead89bda24
|
@ -1 +1,3 @@
|
|||
This package implements an APCO P25 decoder as a GNU Radio signal sink.
|
||||
This package implements an APCO P25 decoder as a GNU Radio signal
|
||||
processing block. It is intended to be used with the Radio Rausch
|
||||
4-Level FSK demodulator.
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
include $(top_srcdir)/Makefile.common
|
||||
|
||||
# Install this stuff so that it ends up as the op25.decoder_f
|
||||
# Install this stuff so that it ends up as the op25.decoder_ff
|
||||
# module. This usually ends up at:
|
||||
# ${prefix}/lib/python${python_version}/site-packages/gnuradio
|
||||
|
||||
|
@ -68,7 +68,7 @@ _op25_la_SOURCES = \
|
|||
packet.cc \
|
||||
terminator.cc \
|
||||
op25.cc \
|
||||
op25_decoder_f.cc
|
||||
op25_decoder_ff.cc
|
||||
|
||||
# magic flags
|
||||
_op25_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version
|
||||
|
@ -84,7 +84,7 @@ op25.cc op25.py: $(LOCAL_IFILES) $(ALL_IFILES)
|
|||
|
||||
# These headers get installed in ${prefix}/include/gnuradio
|
||||
grinclude_HEADERS = \
|
||||
op25_decoder_f.h
|
||||
op25_decoder_ff.h
|
||||
|
||||
# These swig headers get installed in ${prefix}/include/gnuradio/swig
|
||||
swiginclude_HEADERS = \
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
%{
|
||||
#include "gnuradio_swig_bug_workaround.h"
|
||||
#include "op25_decoder_f.h"
|
||||
#include "op25_decoder_ff.h"
|
||||
#include <stdexcept>
|
||||
%}
|
||||
|
||||
|
@ -16,20 +16,20 @@
|
|||
* Second arg is the name of the class minus the prefix.
|
||||
*
|
||||
* This does some behind-the-scenes magic so we can access
|
||||
* op25_decoder_f from python as op25.decoder_f
|
||||
* op25_decoder_ff from python as op25.decoder_ff.
|
||||
*/
|
||||
GR_SWIG_BLOCK_MAGIC(op25,decoder_f);
|
||||
GR_SWIG_BLOCK_MAGIC(op25, decoder_ff);
|
||||
|
||||
/*
|
||||
* Publicly-accesible constuctor function for op25_decoder_f.
|
||||
* Publicly-accesible constuctor function for op25_decoder_ff.
|
||||
*/
|
||||
op25_decoder_f_sptr op25_make_decoder_f(gr_msg_queue_sptr msgq);
|
||||
op25_decoder_ff_sptr op25_make_decoder_ff(gr_msg_queue_sptr msgq);
|
||||
|
||||
/*
|
||||
* The actual op25_decoder block.
|
||||
*/
|
||||
class op25_decoder_f : public gr_sync_block
|
||||
class op25_decoder_ff : public gr_block
|
||||
{
|
||||
private:
|
||||
op25_decoder_f(gr_msg_queue_sptr msgq);
|
||||
op25_decoder_ff(gr_msg_queue_sptr msgq);
|
||||
};
|
||||
|
|
|
@ -24,31 +24,43 @@
|
|||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <op25_decoder_f.h>
|
||||
#include <algorithm>
|
||||
#include <op25_decoder_ff.h>
|
||||
#include <gr_io_signature.h>
|
||||
|
||||
/*
|
||||
* Create a new instance of op25_decoder_f and wrap it in a
|
||||
* Create a new instance of op25_decoder_ff and wrap it in a
|
||||
* shared_ptr. This is effectively the public constructor.
|
||||
*/
|
||||
op25_decoder_f_sptr
|
||||
op25_make_decoder_f(gr_msg_queue_sptr msgq)
|
||||
op25_decoder_ff_sptr
|
||||
op25_make_decoder_ff(gr_msg_queue_sptr msgq)
|
||||
{
|
||||
return op25_decoder_f_sptr(new op25_decoder_f(msgq));
|
||||
return op25_decoder_ff_sptr(new op25_decoder_ff(msgq));
|
||||
}
|
||||
|
||||
/*
|
||||
* Destruct an instance of this class.
|
||||
*/
|
||||
op25_decoder_f::~op25_decoder_f()
|
||||
op25_decoder_ff::~op25_decoder_ff()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Estimate nof_input_items_reqd for a given nof_output_items.
|
||||
*/
|
||||
void
|
||||
op25_decoder_ff::forecast(int nof_output_items, gr_vector_int &nof_input_items_reqd)
|
||||
{
|
||||
const int nof_symbols_per_LDU = 864;
|
||||
const size_t nof_inputs = nof_input_items_reqd.size();
|
||||
std::fill(&nof_input_items_reqd[0], &nof_input_items_reqd[nof_inputs], nof_symbols_per_LDU);
|
||||
}
|
||||
|
||||
/*
|
||||
* Take an incoming float value, convert to a dibit symbol and process.
|
||||
*/
|
||||
int
|
||||
op25_decoder_f::work(int nof_output_items, gr_vector_const_void_star& input_items, gr_vector_void_star& output_items)
|
||||
op25_decoder_ff::general_work(int nof_output_items, gr_vector_int& nof_input_items, gr_vector_const_void_star& input_items, gr_vector_void_star& output_items)
|
||||
{
|
||||
const float *in = reinterpret_cast<const float*>(input_items[0]);
|
||||
for(int i = 0; i < nof_output_items; ++i) {
|
||||
|
@ -64,14 +76,18 @@ op25_decoder_f::work(int nof_output_items, gr_vector_const_void_star& input_item
|
|||
}
|
||||
receive_symbol(d);
|
||||
}
|
||||
return nof_output_items;
|
||||
// ToDo: get IMBE decoder to provide audio
|
||||
float *out = reinterpret_cast<float*>(output_items[0]);
|
||||
std::fill(&out[0], &out[nof_output_items], 0);
|
||||
consume_each(nof_output_items);
|
||||
return 0; // ToDo: return IMBE-decoded audio
|
||||
}
|
||||
|
||||
/*
|
||||
* The private constructor.
|
||||
*/
|
||||
op25_decoder_f::op25_decoder_f(gr_msg_queue_sptr msgq) :
|
||||
gr_sync_block("decoder_f", gr_make_io_signature(1, 1, sizeof(float)), gr_make_io_signature(0, 0, 0)),
|
||||
op25_decoder_ff::op25_decoder_ff(gr_msg_queue_sptr msgq) :
|
||||
gr_block("decoder_ff", gr_make_io_signature(1, 1, sizeof(float)), gr_make_io_signature(1, 1, sizeof(float))),
|
||||
d_msgq(msgq),
|
||||
d_state(SYNCHRONIZING),
|
||||
d_substate(IDENTIFYING),
|
||||
|
@ -91,7 +107,7 @@ op25_decoder_f::op25_decoder_f(gr_msg_queue_sptr msgq) :
|
|||
* sync value.
|
||||
*/
|
||||
bool
|
||||
op25_decoder_f::correlates(dibit d)
|
||||
op25_decoder_ff::correlates(dibit d)
|
||||
{
|
||||
size_t errs = 0;
|
||||
const size_t ERR_THRESHOLD = 4;
|
||||
|
@ -116,7 +132,7 @@ op25_decoder_f::correlates(dibit d)
|
|||
* false. When found d_network_ID contains the network ID value.
|
||||
*/
|
||||
bool
|
||||
op25_decoder_f::identifies(dibit d)
|
||||
op25_decoder_ff::identifies(dibit d)
|
||||
{
|
||||
bool identified = false;
|
||||
d_network_ID <<= 2;
|
||||
|
@ -132,7 +148,7 @@ op25_decoder_f::identifies(dibit d)
|
|||
* Process a received symbol.
|
||||
*/
|
||||
void
|
||||
op25_decoder_f::receive_symbol(dibit d)
|
||||
op25_decoder_ff::receive_symbol(dibit d)
|
||||
{
|
||||
switch(d_state) {
|
||||
case SYNCHRONIZING:
|
||||
|
@ -153,7 +169,7 @@ op25_decoder_f::receive_symbol(dibit d)
|
|||
* Process a received symbol when synchronized.
|
||||
*/
|
||||
void
|
||||
op25_decoder_f::sync_receive_symbol(dibit d)
|
||||
op25_decoder_ff::sync_receive_symbol(dibit d)
|
||||
{
|
||||
switch(d_substate) {
|
||||
case IDENTIFYING:
|
||||
|
@ -169,6 +185,9 @@ op25_decoder_f::sync_receive_symbol(dibit d)
|
|||
break;
|
||||
case READING:
|
||||
if(d_data_unit->complete(d)) {
|
||||
|
||||
// ToDo: ask data_unit to produce audio here
|
||||
|
||||
gr_message_sptr msg(d_data_unit->decode());
|
||||
if(msg) {
|
||||
d_msgq->insert_tail(msg);
|
|
@ -20,31 +20,32 @@
|
|||
* 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef INCLUDED_OP25_DECODER_F_H
|
||||
#define INCLUDED_OP25_DECODER_F_H
|
||||
#ifndef INCLUDED_OP25_DECODER_FF_H
|
||||
#define INCLUDED_OP25_DECODER_FF_H
|
||||
|
||||
#include <data_unit.h>
|
||||
#include <gr_sync_block.h>
|
||||
#include <gr_block.h>
|
||||
#include <gr_msg_queue.h>
|
||||
|
||||
typedef boost::shared_ptr<class op25_decoder_f> op25_decoder_f_sptr;
|
||||
typedef boost::shared_ptr<class op25_decoder_ff> op25_decoder_ff_sptr;
|
||||
|
||||
op25_decoder_f_sptr op25_make_decoder_f(gr_msg_queue_sptr msgq);
|
||||
op25_decoder_ff_sptr op25_make_decoder_ff(gr_msg_queue_sptr msgq);
|
||||
|
||||
/*
|
||||
* op25_decoder_f is a GNU Radio block for decoding APCO P25
|
||||
* op25_decoder_ff is a GNU Radio block for decoding APCO P25
|
||||
* signals. This file expects its input to be a stream of symbols from
|
||||
* the demodulator and is a signal sink that produces no outputs.
|
||||
* Processed messages are sent to the message queue.
|
||||
*/
|
||||
class op25_decoder_f : public gr_sync_block
|
||||
class op25_decoder_ff : public gr_block
|
||||
{
|
||||
public:
|
||||
virtual ~op25_decoder_f();
|
||||
virtual int work(int nof_output_items, gr_vector_const_void_star& input_items, gr_vector_void_star& output_items);
|
||||
virtual ~op25_decoder_ff();
|
||||
virtual void forecast(int nof_output_items, gr_vector_int &nof_input_items_reqd);
|
||||
virtual int general_work(int nof_output_items, gr_vector_int& nof_input_items, gr_vector_const_void_star& input_items, gr_vector_void_star& output_items);
|
||||
private:
|
||||
friend op25_decoder_f_sptr op25_make_decoder_f(gr_msg_queue_sptr msgq); // expose class to public ctor
|
||||
op25_decoder_f(gr_msg_queue_sptr msgq);
|
||||
friend op25_decoder_ff_sptr op25_make_decoder_ff(gr_msg_queue_sptr msgq); // expose class to public ctor
|
||||
op25_decoder_ff(gr_msg_queue_sptr msgq);
|
||||
bool correlates(dibit d);
|
||||
bool identifies(dibit d);
|
||||
void receive_symbol(dibit d);
|
||||
|
@ -61,4 +62,4 @@ private:
|
|||
uint32_t d_unrecognized;
|
||||
};
|
||||
|
||||
#endif /* INCLUDED_OP25_DECODER_F_H */
|
||||
#endif /* INCLUDED_OP25_DECODER_FF_H */
|
|
@ -21,7 +21,6 @@
|
|||
#
|
||||
|
||||
from gnuradio import gr, gr_unittest
|
||||
#from gnuradio import op25
|
||||
import op25
|
||||
|
||||
# import os
|
||||
|
@ -37,20 +36,15 @@ class qa_op25(gr_unittest.TestCase):
|
|||
def tearDown(self):
|
||||
self.fg = None
|
||||
|
||||
# def test_op25_decoder_f_ctor(self):
|
||||
# msgq = gr.msg_queue()
|
||||
# self.fg.connect(src, p25)
|
||||
# p25 = op25.decoder_f(msgq)
|
||||
# # assert not null
|
||||
|
||||
def test_correlator(self):
|
||||
def test_constructor(self):
|
||||
framing_sequence = (3, 3, 3, 3, 3, -3, 3, 3, -3, -3, 3, 3, -3, -3, -3, -3, 3, -3, 3, -3, -3, -3, -3, -3)
|
||||
src = gr.vector_source_f(framing_sequence, False)
|
||||
msgq = gr.msg_queue()
|
||||
p25 = op25.decoder_f(msgq)
|
||||
p25 = op25.decoder_ff(msgq)
|
||||
self.fg.connect(src, p25)
|
||||
bit_bucket = gr.null_sink(gr.sizeof_float)
|
||||
self.fg.connect(p25, bit_bucket)
|
||||
self.fg.run()
|
||||
# check the msgq output (needs separate thread and terminate the flow graph)
|
||||
|
||||
if __name__ == '__main__':
|
||||
gr_unittest.main ()
|
||||
|
|
Reference in New Issue