user selectable callsign decoding + improved meta information display
parent
161688ce20
commit
b7036eab41
|
@ -1,7 +1,7 @@
|
|||
## Compiling for GNU Radio
|
||||
|
||||
The default targetted version is GNU Radio 3.10 (``main`` branch). Tested on Debian/GNU Linux sid with GNU Radio
|
||||
3.10.10.0 (Python 3.11.9) assuming the following dependencies are installed:
|
||||
3.10.10.0 (Python 3.11.9) and Ubuntu 24.04 LTS with GNU Radio 3.10.9.2, assuming the following dependencies are installed:
|
||||
|
||||
```
|
||||
sudo apt install git cmake build-essential doxygen gnuradio
|
||||
|
@ -22,7 +22,8 @@ will finish with a statement such as
|
|||
```
|
||||
-- Set runtime path of "/usr/local/lib/python3.11/dist-packages/gnuradio/m17/m17_python.cpython-311-x86_64-linux-gnu.so" to ""
|
||||
```
|
||||
meaning that variables must be set (tested with Debian/sid) to help GNU Radio Companion find the Python libraries:
|
||||
Depending on Linux distribution, variables might have to be set (tested with Debian/sid, but not needed with Ubuntu 24.04 LTS)
|
||||
to help GNU Radio Companion find the Python libraries:
|
||||
|
||||
```
|
||||
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib/x86_64-linux-gnu/
|
||||
|
|
|
@ -11,7 +11,7 @@ options:
|
|||
gen_linking: dynamic
|
||||
generate_options: qt_gui
|
||||
hier_block_src_path: '.:'
|
||||
id: m17_streamer
|
||||
id: m17_loopback
|
||||
max_nouts: '0'
|
||||
output_language: python
|
||||
placement: (0,0)
|
||||
|
@ -70,7 +70,7 @@ blocks:
|
|||
options: '[0, 1, 2]'
|
||||
orient: Qt.QVBoxLayout
|
||||
type: int
|
||||
value: '1'
|
||||
value: '0'
|
||||
widget: combo_box
|
||||
states:
|
||||
bus_sink: false
|
||||
|
@ -212,7 +212,7 @@ blocks:
|
|||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [952, 152.0]
|
||||
coordinate: [960, 152.0]
|
||||
rotation: 0
|
||||
state: enabled
|
||||
- name: blocks_null_sink_0
|
||||
|
@ -283,12 +283,13 @@ blocks:
|
|||
comment: 'since Meta can be a byte array, it cannot be fed with a QT GUI Entry
|
||||
|
||||
string but must be a "\x00" string in the Encoder block'
|
||||
debug: 'False'
|
||||
debug: 'True'
|
||||
dst_id: dst_str
|
||||
encr_subtype: enc_subtype
|
||||
encr_type: enc_type
|
||||
key: '''\x00\x00\x65\x41\xb0\x93\xff\x00'''
|
||||
maxoutbuf: '0'
|
||||
meta: '''\x00\x00\x65\x41\xb0\x93\xff\x00\x00\x00\x00\x00\x00\x00\x00'''
|
||||
meta: '''\x00\x00\x65\x41\xb0\x93\xff\x00'''
|
||||
minoutbuf: '0'
|
||||
mode: mode
|
||||
src_id: src_str
|
||||
|
@ -297,7 +298,7 @@ blocks:
|
|||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [320, 100.0]
|
||||
coordinate: [320, 92.0]
|
||||
rotation: 0
|
||||
state: true
|
||||
- name: m17_m17_decoder_0
|
||||
|
@ -305,9 +306,10 @@ blocks:
|
|||
parameters:
|
||||
affinity: ''
|
||||
alias: ''
|
||||
callsign: 'False'
|
||||
comment: ''
|
||||
debug_ctrl: 'False'
|
||||
debug_data: 'False'
|
||||
debug_ctrl: 'True'
|
||||
debug_data: 'True'
|
||||
maxoutbuf: '0'
|
||||
minoutbuf: '0'
|
||||
threshold: '2.0'
|
||||
|
@ -315,7 +317,7 @@ blocks:
|
|||
bus_sink: false
|
||||
bus_source: false
|
||||
bus_structure: null
|
||||
coordinate: [784, 152.0]
|
||||
coordinate: [784, 144.0]
|
||||
rotation: 0
|
||||
state: true
|
||||
- name: note_0_2
|
||||
|
|
|
@ -13,6 +13,11 @@ parameters:
|
|||
dtype: bool
|
||||
default: 'False'
|
||||
options: ['True', 'False']
|
||||
- id: callsign
|
||||
label: Display Callsign
|
||||
dtype: bool
|
||||
default: 'False'
|
||||
options: ['True', 'False']
|
||||
- id: threshold
|
||||
label: Threshold
|
||||
dtype: float
|
||||
|
@ -20,11 +25,12 @@ parameters:
|
|||
|
||||
templates:
|
||||
imports: from gnuradio import m17
|
||||
make: m17.m17_decoder(${debug_data},${debug_ctrl},${threshold})
|
||||
make: m17.m17_decoder(${debug_data},${debug_ctrl},${threshold},${callsign})
|
||||
callbacks:
|
||||
- set_debug_data(${debug_data})
|
||||
- set_debug_ctrl(${debug_ctrl})
|
||||
- set_threshold(${threshold})
|
||||
- set_callsign(${callsign})
|
||||
|
||||
# Make one 'inputs' list entry per input and one 'outputs' list entry per output.
|
||||
# Keys include:
|
||||
|
|
|
@ -32,9 +32,10 @@ public:
|
|||
* class. m17::m17_decoder::make is the public interface for
|
||||
* creating new instances.
|
||||
*/
|
||||
static sptr make(bool debug_data,bool debug_ctrl,float threshold);
|
||||
static sptr make(bool debug_data,bool debug_ctrl,float threshold,bool callsign);
|
||||
virtual void set_debug_data(bool debug)=0;
|
||||
virtual void set_debug_ctrl(bool debug)=0;
|
||||
virtual void set_callsign(bool callsign)=0;
|
||||
virtual void set_threshold(float threshold)=0;
|
||||
};
|
||||
|
||||
|
|
|
@ -33,10 +33,6 @@
|
|||
|
||||
#include "m17.h"
|
||||
|
||||
#define DECODE_CALLSIGNS
|
||||
//#define SHOW_VITERBI_ERRS
|
||||
//
|
||||
|
||||
#define CODE_MEAN -0.75 // mean(str_sync_symbols)
|
||||
#define CODE_STD 8.21583836f //std(str_sync_symbols)*sqrt(length(str_sync_symbols)-1)
|
||||
|
||||
|
@ -44,24 +40,25 @@ namespace gr {
|
|||
namespace m17 {
|
||||
|
||||
m17_decoder::sptr
|
||||
m17_decoder::make(bool debug_data,bool debug_ctrl,float threshold)
|
||||
m17_decoder::make(bool debug_data,bool debug_ctrl,float threshold,bool callsign)
|
||||
{
|
||||
return gnuradio::get_initial_sptr
|
||||
(new m17_decoder_impl(debug_data,debug_ctrl,threshold));
|
||||
(new m17_decoder_impl(debug_data,debug_ctrl,threshold,callsign));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The private constructor
|
||||
*/
|
||||
m17_decoder_impl::m17_decoder_impl(bool debug_data,bool debug_ctrl,float threshold)
|
||||
m17_decoder_impl::m17_decoder_impl(bool debug_data,bool debug_ctrl,float threshold,bool callsign)
|
||||
: gr::block("m17_decoder",
|
||||
gr::io_signature::make(1, 1, sizeof(float)),
|
||||
gr::io_signature::make(1, 1, sizeof(char))),
|
||||
_debug_data(debug_data), _debug_ctrl(debug_ctrl), _threshold(threshold)
|
||||
_debug_data(debug_data), _debug_ctrl(debug_ctrl), _threshold(threshold), _callsign(callsign)
|
||||
{set_debug_data(debug_data);
|
||||
set_debug_ctrl(debug_ctrl);
|
||||
set_threshold(threshold);
|
||||
set_callsign(callsign);
|
||||
_expected_next_fn=0;
|
||||
}
|
||||
|
||||
|
@ -87,6 +84,11 @@ namespace gr {
|
|||
if (_debug_ctrl==true) printf("Debug control: true\n"); else printf("Debug control: false\n");
|
||||
}
|
||||
|
||||
void m17_decoder_impl::set_callsign(bool callsign)
|
||||
{_callsign=callsign;
|
||||
if (_callsign==true) printf("Display callsign\n"); else printf("Do not display callsign\n");
|
||||
}
|
||||
|
||||
void
|
||||
m17_decoder_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
|
||||
{
|
||||
|
@ -171,30 +173,23 @@ namespace gr {
|
|||
}
|
||||
|
||||
//decode
|
||||
#ifdef SHOW_VITERBI_ERRS
|
||||
uint32_t e=
|
||||
#endif
|
||||
viterbi_decode_punctured(frame_data, enc_data, puncture_pattern_2, 272, 12);
|
||||
uint32_t e=viterbi_decode_punctured(frame_data, enc_data, puncture_pattern_2, 272, 12);
|
||||
|
||||
uint16_t fn = (frame_data[1] << 8) | frame_data[2];
|
||||
|
||||
if (_debug_data==true) {
|
||||
//dump data - first byte is empty
|
||||
printf("RX FN: %02X%02X PLD: ", frame_data[1], frame_data[2]);
|
||||
if (_debug_data==true) { //dump data - first byte is empty
|
||||
printf("RX FN: %04X PLD: ", fn);
|
||||
}
|
||||
|
||||
for(uint8_t i=3; i<19; i++)
|
||||
{
|
||||
if (_debug_data==true) {
|
||||
printf("%02X", frame_data[i]);
|
||||
}
|
||||
out[countout]=frame_data[i];countout++;
|
||||
out[countout]=frame_data[i];countout++;
|
||||
}
|
||||
if (_debug_data==true) {
|
||||
#ifdef SHOW_VITERBI_ERRS
|
||||
printf(" e=%1.1f\n", (float)e/0xFFFF);
|
||||
#else
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
//send codec2 stream to stdout
|
||||
//write(STDOUT_FILENO, &frame_data[3], 16);
|
||||
|
@ -219,128 +214,133 @@ namespace gr {
|
|||
//debug - dump LICH
|
||||
if(lich_chunks_rcvd==0x3F) //all 6 chunks received?
|
||||
{
|
||||
#ifdef DECODE_CALLSIGNS
|
||||
uint8_t d_dst[12], d_src[12]; //decoded strings
|
||||
|
||||
decode_callsign_bytes(d_dst, &lsf[0]);
|
||||
decode_callsign_bytes(d_src, &lsf[6]);
|
||||
|
||||
if (_debug_ctrl==true) {
|
||||
//DST
|
||||
printf("DST: %-9s ", d_dst);
|
||||
|
||||
//SRC
|
||||
printf("SRC: %-9s ", d_src);
|
||||
#else
|
||||
//DST
|
||||
printf("DST: ");
|
||||
for(uint8_t i=0; i<6; i++)
|
||||
if (_debug_ctrl==true)
|
||||
{if (_callsign==true)
|
||||
{decode_callsign_bytes(d_dst, &lsf[0]);
|
||||
decode_callsign_bytes(d_src, &lsf[6]);
|
||||
printf("DST: %-9s ", d_dst); //DST
|
||||
printf("SRC: %-9s ", d_src); //SRC
|
||||
}
|
||||
else
|
||||
{printf("DST: "); //DST
|
||||
for(uint8_t i=0; i<6; i++)
|
||||
printf("%02X", lsf[i]);
|
||||
printf(" ");
|
||||
|
||||
//SRC
|
||||
printf("SRC: ");
|
||||
for(uint8_t i=0; i<6; i++)
|
||||
printf(" ");
|
||||
printf("SRC: "); //SRC
|
||||
for(uint8_t i=0; i<6; i++)
|
||||
printf("%02X", lsf[6+i]);
|
||||
printf(" ");
|
||||
#endif
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
|
||||
//TYPE
|
||||
printf("TYPE: ");
|
||||
for(uint8_t i=0; i<2; i++)
|
||||
printf("%02X", lsf[12+i]);
|
||||
printf(" ");
|
||||
//TYPE
|
||||
uint16_t type=(uint16_t)lsf[12]*0x100+lsf[13]; //big-endian
|
||||
if (_debug_ctrl==true)
|
||||
{printf("TYPE: %04X (", type);
|
||||
if(type&&1)
|
||||
printf("STREAM: ");
|
||||
else
|
||||
printf("PACKET: "); //shouldn't happen
|
||||
if(((type>>1)&3)==1)
|
||||
printf("DATA, ");
|
||||
else if(((type>>1)&3)==2)
|
||||
printf("VOICE, ");
|
||||
else if(((type>>1)&3)==3)
|
||||
printf("VOICE+DATA, ");
|
||||
printf("ENCR: ");
|
||||
if(((type>>3)&3)==0)
|
||||
printf("PLAIN, ");
|
||||
else if(((type>>3)&3)==1)
|
||||
{
|
||||
printf("SCRAM ");
|
||||
if(((type>>5)&3)==1)
|
||||
printf("8-bit, ");
|
||||
else if(((type>>5)&3)==2)
|
||||
printf("16-bit, ");
|
||||
else if(((type>>5)&3)==3)
|
||||
printf("24-bit, ");
|
||||
}
|
||||
else if(((type>>3)&3)==2)
|
||||
printf("AES, ");
|
||||
else
|
||||
printf("UNK, ");
|
||||
printf("CAN: %d", (type>>7)&0xF);
|
||||
if((type>>11)&1)
|
||||
printf(", SIGNED");
|
||||
printf(") ");
|
||||
}
|
||||
|
||||
//META
|
||||
printf("META: ");
|
||||
for(uint8_t i=0; i<14; i++)
|
||||
printf("%02X", lsf[14+i]);
|
||||
//printf(" ");
|
||||
//META
|
||||
if (_debug_ctrl==true)
|
||||
{printf("META: ");
|
||||
for(uint8_t i=0; i<14; i++)
|
||||
printf("%02X", lsf[14+i]);
|
||||
|
||||
//CRC
|
||||
//printf("CRC: ");
|
||||
//for(uint8_t i=0; i<2; i++)
|
||||
//printf("%02X", lsf[28+i]);
|
||||
if(CRC_M17(lsf, 30))
|
||||
if(CRC_M17(lsf, 30)) //CRC
|
||||
printf(" LSF_CRC_ERR");
|
||||
else
|
||||
printf(" LSF_CRC_OK ");
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
_expected_next_fn = (fn + 1) % 0x8000;
|
||||
}
|
||||
else //lsf
|
||||
{
|
||||
if (_debug_ctrl==true) {
|
||||
printf("LSF\n");
|
||||
printf("{LSF}\n");
|
||||
}
|
||||
//decode
|
||||
#ifdef SHOW_VITERBI_ERRS
|
||||
uint32_t e=
|
||||
#endif
|
||||
viterbi_decode_punctured(lsf, d_soft_bit, puncture_pattern_1, 2*SYM_PER_PLD, 61);
|
||||
|
||||
uint32_t e=viterbi_decode_punctured(lsf, d_soft_bit, puncture_pattern_1, 2*SYM_PER_PLD, 61);
|
||||
|
||||
//shift the buffer 1 position left - get rid of the encoded flushing bits
|
||||
for(uint8_t i=0; i<30; i++)
|
||||
lsf[i]=lsf[i+1];
|
||||
|
||||
//dump data
|
||||
#ifdef DECODE_CALLSIGNS
|
||||
uint8_t d_dst[12], d_src[12]; //decoded strings
|
||||
|
||||
decode_callsign_bytes(d_dst, &lsf[0]);
|
||||
decode_callsign_bytes(d_src, &lsf[6]);
|
||||
|
||||
if (_debug_ctrl==true) {
|
||||
//DST
|
||||
printf("DST: %-9s ", d_dst);
|
||||
if (_debug_ctrl==true)
|
||||
{if (_callsign==true)
|
||||
{decode_callsign_bytes(d_dst, &lsf[0]);
|
||||
decode_callsign_bytes(d_src, &lsf[6]);
|
||||
printf("DST: %-9s ", d_dst); //DST
|
||||
printf("SRC: %-9s ", d_src); //SRC
|
||||
}
|
||||
else
|
||||
{printf("DST: "); //DST
|
||||
for(uint8_t i=0; i<6; i++)
|
||||
printf("%02X", lsf[i]);
|
||||
printf(" ");
|
||||
|
||||
//SRC
|
||||
printf("SRC: %-9s ", d_src);
|
||||
#else
|
||||
//DST
|
||||
printf("DST: ");
|
||||
for(uint8_t i=0; i<6; i++)
|
||||
printf("%02X", lsf[i]);
|
||||
printf(" ");
|
||||
//SRC
|
||||
printf("SRC: ");
|
||||
for(uint8_t i=0; i<6; i++)
|
||||
printf("%02X", lsf[6+i]);
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
//SRC
|
||||
printf("SRC: ");
|
||||
for(uint8_t i=0; i<6; i++)
|
||||
printf("%02X", lsf[6+i]);
|
||||
printf(" ");
|
||||
#endif
|
||||
|
||||
//TYPE
|
||||
printf("TYPE: ");
|
||||
for(uint8_t i=0; i<2; i++)
|
||||
//TYPE
|
||||
printf("TYPE: ");
|
||||
for(uint8_t i=0; i<2; i++)
|
||||
printf("%02X", lsf[12+i]);
|
||||
printf(" ");
|
||||
printf(" ");
|
||||
|
||||
//META
|
||||
printf("META: ");
|
||||
for(uint8_t i=0; i<14; i++)
|
||||
//META
|
||||
printf("META: ");
|
||||
for(uint8_t i=0; i<14; i++)
|
||||
printf("%02X", lsf[14+i]);
|
||||
printf(" ");
|
||||
printf(" ");
|
||||
|
||||
//CRC
|
||||
//printf("CRC: ");
|
||||
//for(uint8_t i=0; i<2; i++)
|
||||
//CRC
|
||||
//printf("CRC: ");
|
||||
//for(uint8_t i=0; i<2; i++)
|
||||
//printf("%02X", lsf[28+i]);
|
||||
if(CRC_M17(lsf, 30))
|
||||
if(CRC_M17(lsf, 30))
|
||||
printf("LSF_CRC_ERR");
|
||||
else
|
||||
else
|
||||
printf("LSF_CRC_OK ");
|
||||
//Viterbi decoder errors
|
||||
#ifdef SHOW_VITERBI_ERRS
|
||||
printf(" e=%1.1f\n", (float)e/0xFFFF);
|
||||
#else
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
//Viterbi decoder errors
|
||||
printf(" e=%1.1f\n", (float)e/0xFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
//job done
|
||||
|
|
|
@ -20,6 +20,7 @@ private:
|
|||
bool _debug_data=false;
|
||||
bool _debug_ctrl=false;
|
||||
float _threshold=0.9;
|
||||
bool _callsign=false;
|
||||
|
||||
float last[8] = {0}; //look-back buffer for finding syncwords
|
||||
float pld[SYM_PER_PLD]; //raw frame symbols
|
||||
|
@ -40,11 +41,14 @@ private:
|
|||
uint8_t fl=0; //Frame=0 of LSF=1
|
||||
uint8_t pushed; //counter for pushed symbols
|
||||
|
||||
uint8_t d_dst[12], d_src[12]; //decoded strings
|
||||
|
||||
public:
|
||||
m17_decoder_impl(bool debug_data,bool debug_ctrl,float threshold);
|
||||
m17_decoder_impl(bool debug_data,bool debug_ctrl,float threshold,bool callsign);
|
||||
~m17_decoder_impl();
|
||||
void set_debug_data(bool debug);
|
||||
void set_debug_ctrl(bool debug);
|
||||
void set_callsign(bool callsign);
|
||||
void set_threshold(float threshold);
|
||||
|
||||
// Where all the action really happens
|
||||
|
|
|
@ -26,4 +26,6 @@ static const char *__doc_gr_m17_m17_decoder_set_debug_data = R"doc()doc";
|
|||
|
||||
static const char *__doc_gr_m17_m17_decoder_set_debug_ctrl = R"doc()doc";
|
||||
|
||||
static const char *__doc_gr_m17_m17_decoder_set_callsign = R"doc()doc";
|
||||
|
||||
static const char *__doc_gr_m17_m17_decoder_set_threshold = R"doc()doc";
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
/* BINDTOOL_GEN_AUTOMATIC(0) */
|
||||
/* BINDTOOL_USE_PYGCCXML(0) */
|
||||
/* BINDTOOL_HEADER_FILE(m17_decoder.h) */
|
||||
/* BINDTOOL_HEADER_FILE_HASH(74e8e77389b1889023dbed48ecb9523e) */
|
||||
/* BINDTOOL_HEADER_FILE_HASH(265f7a49ed1b66cdd021af3149d8dc4b) */
|
||||
/***********************************************************************************/
|
||||
|
||||
#include <pybind11/complex.h>
|
||||
|
@ -37,7 +37,8 @@ void bind_m17_decoder(py::module &m) {
|
|||
std::shared_ptr<m17_decoder>>(m, "m17_decoder", D(m17_decoder))
|
||||
|
||||
.def(py::init(&m17_decoder::make), py::arg("debug_data"),
|
||||
py::arg("debug_ctrl"), py::arg("threshold"), D(m17_decoder, make))
|
||||
py::arg("debug_ctrl"), py::arg("threshold"), py::arg("callsign"),
|
||||
D(m17_decoder, make))
|
||||
|
||||
.def("set_debug_data", &m17_decoder::set_debug_data, py::arg("debug"),
|
||||
D(m17_decoder, set_debug_data))
|
||||
|
@ -45,6 +46,9 @@ void bind_m17_decoder(py::module &m) {
|
|||
.def("set_debug_ctrl", &m17_decoder::set_debug_ctrl, py::arg("debug"),
|
||||
D(m17_decoder, set_debug_ctrl))
|
||||
|
||||
.def("set_callsign", &m17_decoder::set_callsign, py::arg("callsign"),
|
||||
D(m17_decoder, set_callsign))
|
||||
|
||||
.def("set_threshold", &m17_decoder::set_threshold, py::arg("threshold"),
|
||||
D(m17_decoder, set_threshold))
|
||||
|
||||
|
|
Loading…
Reference in New Issue