2016-01-19 18:35:37 +01:00
|
|
|
/* -*- c++ -*- */
|
2016-01-21 20:33:08 +01:00
|
|
|
/*
|
|
|
|
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
|
|
|
|
*
|
2017-09-05 00:37:47 +02:00
|
|
|
* Copyright (C) 2016,2017
|
|
|
|
* Libre Space Foundation <http://librespacefoundation.org/>
|
2016-01-21 20:33:08 +01:00
|
|
|
*
|
|
|
|
* This program 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 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program 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 program. If not, see <http://www.gnu.org/licenses/>.
|
2016-01-19 18:35:37 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <gnuradio/io_signature.h>
|
|
|
|
#include <satnogs/morse_tree.h>
|
2016-01-21 20:33:08 +01:00
|
|
|
#include <satnogs/log.h>
|
|
|
|
#include <string.h>
|
2016-01-19 18:35:37 +01:00
|
|
|
|
2019-09-12 15:25:10 +02:00
|
|
|
namespace gr {
|
|
|
|
namespace satnogs {
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* Constructs a Morse code tree for Morse code decoding
|
|
|
|
*/
|
|
|
|
morse_tree::morse_tree() :
|
|
|
|
d_unrecognized_symbol('#'),
|
|
|
|
d_root(new tree_node(0)),
|
|
|
|
d_current(d_root),
|
|
|
|
d_buff_len(4096),
|
|
|
|
d_word_len(0),
|
|
|
|
d_word_buffer(new char[d_buff_len])
|
2016-01-19 18:35:37 +01:00
|
|
|
{
|
2019-09-12 15:25:10 +02:00
|
|
|
construct_tree();
|
|
|
|
}
|
2016-01-19 18:35:37 +01:00
|
|
|
|
2019-09-12 15:25:10 +02:00
|
|
|
/*!
|
|
|
|
* Constructs a Morse code tree for Morse code decoding
|
|
|
|
* @param unrecognized the character that will be placed
|
|
|
|
* in the place of unrecognized symbols
|
|
|
|
*/
|
|
|
|
morse_tree::morse_tree(char unrecognized) :
|
|
|
|
d_unrecognized_symbol(unrecognized),
|
|
|
|
d_root(new tree_node(0)),
|
|
|
|
d_current(d_root),
|
|
|
|
d_buff_len(4096),
|
|
|
|
d_word_len(0),
|
|
|
|
d_word_buffer(new char[d_buff_len])
|
|
|
|
{
|
|
|
|
construct_tree();
|
|
|
|
}
|
2016-01-21 20:33:08 +01:00
|
|
|
|
2019-09-12 15:25:10 +02:00
|
|
|
morse_tree::~morse_tree()
|
|
|
|
{
|
|
|
|
delete_tree(d_root);
|
|
|
|
}
|
2016-01-19 18:35:37 +01:00
|
|
|
|
2019-09-12 15:25:10 +02:00
|
|
|
/*!
|
|
|
|
* Resets the pointer to the initial root node
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
morse_tree::reset()
|
|
|
|
{
|
|
|
|
d_current = d_root;
|
|
|
|
d_word_len = 0;
|
|
|
|
memset(d_word_buffer.get(), 0, d_buff_len);
|
|
|
|
}
|
2016-01-19 18:35:37 +01:00
|
|
|
|
2019-09-12 15:25:10 +02:00
|
|
|
/*!
|
|
|
|
* Creates and initializes the Morse code decoder tree
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
morse_tree::construct_tree()
|
|
|
|
{
|
|
|
|
tree_node *e = new tree_node('E');
|
|
|
|
tree_node *t = new tree_node('T');
|
|
|
|
tree_node *i = new tree_node('I');
|
|
|
|
tree_node *a = new tree_node('A');
|
|
|
|
tree_node *n = new tree_node('N');
|
|
|
|
tree_node *m = new tree_node('M');
|
|
|
|
tree_node *s = new tree_node('S');
|
|
|
|
tree_node *u = new tree_node('U');
|
|
|
|
tree_node *r = new tree_node('R');
|
|
|
|
tree_node *w = new tree_node('W');
|
|
|
|
tree_node *d = new tree_node('D');
|
|
|
|
tree_node *k = new tree_node('K');
|
|
|
|
tree_node *g = new tree_node('G');
|
|
|
|
tree_node *o = new tree_node('O');
|
|
|
|
tree_node *h = new tree_node('H');
|
|
|
|
tree_node *v = new tree_node('V');
|
|
|
|
tree_node *f = new tree_node('F');
|
|
|
|
tree_node *u_u = new tree_node('U');
|
|
|
|
tree_node *l = new tree_node('L');
|
|
|
|
tree_node *u_a = new tree_node('A');
|
|
|
|
tree_node *p = new tree_node('P');
|
|
|
|
tree_node *j = new tree_node('J');
|
|
|
|
tree_node *b = new tree_node('B');
|
|
|
|
tree_node *x = new tree_node('X');
|
|
|
|
tree_node *c = new tree_node('C');
|
|
|
|
tree_node *y = new tree_node('Y');
|
|
|
|
tree_node *z = new tree_node('Z');
|
|
|
|
tree_node *q = new tree_node('Q');
|
|
|
|
tree_node *u_o = new tree_node('O');
|
|
|
|
tree_node *null0 = new tree_node(0);
|
|
|
|
tree_node *n5 = new tree_node('5');
|
|
|
|
tree_node *n4 = new tree_node('4');
|
|
|
|
tree_node *a_s = new tree_node('S');
|
|
|
|
tree_node *n3 = new tree_node('3');
|
|
|
|
tree_node *a_e = new tree_node('E');
|
|
|
|
tree_node *d_d = new tree_node('D');
|
|
|
|
tree_node *n2 = new tree_node('2');
|
|
|
|
tree_node *d_e = new tree_node('E');
|
|
|
|
tree_node *plus = new tree_node('+');
|
|
|
|
tree_node *d_a = new tree_node('A');
|
|
|
|
tree_node *d_j = new tree_node('J');
|
|
|
|
tree_node *n1 = new tree_node('1');
|
|
|
|
tree_node *n6 = new tree_node('6');
|
|
|
|
tree_node *eq = new tree_node('=');
|
|
|
|
tree_node *slash = new tree_node('/');
|
|
|
|
tree_node *null1 = new tree_node(0);
|
|
|
|
tree_node *n7 = new tree_node('7');
|
|
|
|
tree_node *null2 = new tree_node(0);
|
|
|
|
tree_node *n8 = new tree_node('8');
|
|
|
|
tree_node *n9 = new tree_node('9');
|
|
|
|
tree_node *n0 = new tree_node('0');
|
2016-01-19 18:35:37 +01:00
|
|
|
|
2019-09-12 15:25:10 +02:00
|
|
|
d_root->set_left_child(e);
|
|
|
|
d_root->set_right_child(t);
|
2016-01-19 18:35:37 +01:00
|
|
|
|
2019-09-12 15:25:10 +02:00
|
|
|
e->set_left_child(i);
|
|
|
|
e->set_right_child(a);
|
|
|
|
t->set_left_child(n);
|
|
|
|
t->set_right_child(m);
|
2016-01-19 18:35:37 +01:00
|
|
|
|
2019-09-12 15:25:10 +02:00
|
|
|
i->set_left_child(s);
|
|
|
|
i->set_right_child(u);
|
|
|
|
a->set_left_child(r);
|
|
|
|
a->set_right_child(w);
|
|
|
|
n->set_left_child(d);
|
|
|
|
n->set_right_child(k);
|
|
|
|
m->set_left_child(g);
|
|
|
|
m->set_right_child(o);
|
2016-01-19 18:35:37 +01:00
|
|
|
|
2019-09-12 15:25:10 +02:00
|
|
|
s->set_left_child(h);
|
|
|
|
s->set_right_child(v);
|
|
|
|
u->set_left_child(f);
|
|
|
|
u->set_right_child(u_u);
|
|
|
|
r->set_left_child(l);
|
|
|
|
r->set_right_child(u_a);
|
|
|
|
w->set_left_child(p);
|
|
|
|
w->set_right_child(j);
|
|
|
|
d->set_left_child(b);
|
|
|
|
d->set_right_child(x);
|
|
|
|
k->set_left_child(c);
|
|
|
|
k->set_right_child(y);
|
|
|
|
g->set_left_child(z);
|
|
|
|
g->set_right_child(q);
|
|
|
|
o->set_left_child(u_o);
|
|
|
|
o->set_right_child(null0);
|
2016-01-19 18:35:37 +01:00
|
|
|
|
2019-09-12 15:25:10 +02:00
|
|
|
h->set_left_child(n5);
|
|
|
|
h->set_right_child(n4);
|
|
|
|
v->set_left_child(a_s);
|
|
|
|
v->set_right_child(n3);
|
|
|
|
f->set_left_child(a_e);
|
|
|
|
u_u->set_left_child(d_d);
|
|
|
|
u_u->set_right_child(n2);
|
|
|
|
l->set_right_child(d_e);
|
|
|
|
u_a->set_left_child(plus);
|
|
|
|
p->set_right_child(d_a);
|
|
|
|
j->set_left_child(d_j);
|
|
|
|
j->set_right_child(n1);
|
|
|
|
b->set_left_child(n6);
|
|
|
|
b->set_right_child(eq);
|
|
|
|
x->set_left_child(slash);
|
|
|
|
c->set_right_child(null1);
|
|
|
|
z->set_left_child(n7);
|
|
|
|
z->set_right_child(null2);
|
|
|
|
u_o->set_left_child(n8);
|
|
|
|
null0->set_left_child(n9);
|
|
|
|
null0->set_right_child(n0);
|
|
|
|
}
|
2016-01-19 18:35:37 +01:00
|
|
|
|
2019-09-12 15:25:10 +02:00
|
|
|
bool
|
|
|
|
morse_tree::received_symbol(morse_symbol_t s)
|
|
|
|
{
|
|
|
|
char c = 0;
|
|
|
|
bool ret = false;
|
|
|
|
/* Check for overflow */
|
|
|
|
if (d_word_len == d_buff_len) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
switch (s) {
|
|
|
|
case MORSE_DOT:
|
|
|
|
if (d_current->get_left_child()) {
|
|
|
|
d_current = d_current->get_left_child();
|
|
|
|
ret = true;
|
2016-01-19 18:35:37 +01:00
|
|
|
}
|
2019-09-12 15:25:10 +02:00
|
|
|
break;
|
|
|
|
case MORSE_DASH:
|
|
|
|
if (d_current->get_right_child()) {
|
|
|
|
d_current = d_current->get_right_child();
|
|
|
|
ret = true;
|
2016-01-21 20:33:08 +01:00
|
|
|
}
|
2019-09-12 15:25:10 +02:00
|
|
|
break;
|
|
|
|
case MORSE_S_SPACE:
|
|
|
|
/*
|
|
|
|
* A short space received, but the decoder is still at the root.
|
|
|
|
* This is not in general an error so we return true
|
|
|
|
*/
|
|
|
|
if (d_current == d_root) {
|
|
|
|
return true;
|
2016-01-23 21:23:19 +01:00
|
|
|
}
|
2019-09-12 15:25:10 +02:00
|
|
|
c = d_current->get_char();
|
|
|
|
d_current = d_root;
|
|
|
|
/*
|
|
|
|
* Some nodes are null transitions and do not correspond to
|
|
|
|
* a specific character
|
|
|
|
*/
|
|
|
|
if (c != 0) {
|
|
|
|
d_word_buffer[d_word_len] = c;
|
|
|
|
d_word_len++;
|
|
|
|
ret = true;
|
2016-01-23 21:23:19 +01:00
|
|
|
}
|
2019-09-12 15:25:10 +02:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
LOG_ERROR("Unsupported Morse symbol");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
2016-01-23 21:23:19 +01:00
|
|
|
|
2019-09-12 15:25:10 +02:00
|
|
|
std::string
|
|
|
|
morse_tree::get_word()
|
|
|
|
{
|
|
|
|
return std::string(d_word_buffer.get(), d_word_len);
|
|
|
|
}
|
2016-01-21 20:33:08 +01:00
|
|
|
|
2019-09-12 15:25:10 +02:00
|
|
|
size_t
|
|
|
|
morse_tree::get_max_word_len() const
|
|
|
|
{
|
|
|
|
return d_buff_len;
|
|
|
|
}
|
2016-01-19 18:35:37 +01:00
|
|
|
|
2019-09-12 15:25:10 +02:00
|
|
|
size_t
|
|
|
|
morse_tree::get_word_len()
|
|
|
|
{
|
|
|
|
return d_word_len;
|
|
|
|
}
|
2016-01-19 18:35:37 +01:00
|
|
|
|
2019-09-12 15:25:10 +02:00
|
|
|
void
|
|
|
|
morse_tree::delete_tree(tree_node *node)
|
|
|
|
{
|
|
|
|
if (!node) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
delete_tree(node->get_left_child());
|
|
|
|
delete_tree(node->get_right_child());
|
|
|
|
delete node;
|
|
|
|
}
|
2016-01-19 18:35:37 +01:00
|
|
|
|
2019-09-12 15:25:10 +02:00
|
|
|
tree_node::tree_node(char c) :
|
|
|
|
d_char(c),
|
|
|
|
d_left(NULL),
|
|
|
|
d_right(NULL)
|
|
|
|
{
|
|
|
|
}
|
2016-01-19 18:35:37 +01:00
|
|
|
|
2019-09-12 15:25:10 +02:00
|
|
|
void
|
|
|
|
tree_node::set_left_child(tree_node *child)
|
|
|
|
{
|
|
|
|
d_left = child;
|
|
|
|
}
|
2016-01-21 20:33:08 +01:00
|
|
|
|
2019-09-12 15:25:10 +02:00
|
|
|
void
|
|
|
|
tree_node::set_right_child(tree_node *child)
|
|
|
|
{
|
|
|
|
d_right = child;
|
|
|
|
}
|
2016-01-21 20:33:08 +01:00
|
|
|
|
2019-09-12 15:25:10 +02:00
|
|
|
tree_node *
|
|
|
|
tree_node::get_left_child()
|
|
|
|
{
|
|
|
|
return d_left;
|
|
|
|
}
|
|
|
|
|
|
|
|
tree_node *
|
|
|
|
tree_node::get_right_child()
|
|
|
|
{
|
|
|
|
return d_right;
|
|
|
|
}
|
|
|
|
|
|
|
|
char
|
|
|
|
tree_node::get_char()
|
|
|
|
{
|
|
|
|
return d_char;
|
|
|
|
}
|
2016-01-21 20:33:08 +01:00
|
|
|
|
2019-09-12 15:25:10 +02:00
|
|
|
} /* namespace satnogs */
|
2016-01-19 18:35:37 +01:00
|
|
|
} /* namespace gr */
|