user selectable callsign decoding + improved meta information display

main
Jean-Michel Friedt 2024-06-19 19:15:09 +02:00
parent 161688ce20
commit b7036eab41
8 changed files with 145 additions and 125 deletions

View File

@ -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/

View File

@ -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

View File

@ -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:

View File

@ -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;
};

View File

@ -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

View File

@ -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

View File

@ -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";

View File

@ -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))