gr-satnogs/lib/morse_tree.cc

312 lines
7.0 KiB
C++

/* -*- c++ -*- */
/*
* gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module
*
* Copyright (C) 2016,2017
* Libre Space Foundation <http://librespacefoundation.org/>
*
* 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/>.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/io_signature.h>
#include <satnogs/morse_tree.h>
#include <satnogs/log.h>
#include <string.h>
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])
{
construct_tree();
}
/*!
* 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();
}
morse_tree::~morse_tree()
{
delete_tree(d_root);
}
/*!
* 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);
}
/*!
* 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');
d_root->set_left_child(e);
d_root->set_right_child(t);
e->set_left_child(i);
e->set_right_child(a);
t->set_left_child(n);
t->set_right_child(m);
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);
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);
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);
}
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;
}
break;
case MORSE_DASH:
if (d_current->get_right_child()) {
d_current = d_current->get_right_child();
ret = true;
}
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;
}
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;
}
break;
default:
LOG_ERROR("Unsupported Morse symbol");
return false;
}
return ret;
}
std::string
morse_tree::get_word()
{
return std::string(d_word_buffer.get(), d_word_len);
}
size_t
morse_tree::get_max_word_len() const
{
return d_buff_len;
}
size_t
morse_tree::get_word_len()
{
return d_word_len;
}
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;
}
tree_node::tree_node(char c) :
d_char(c),
d_left(NULL),
d_right(NULL)
{
}
void
tree_node::set_left_child(tree_node *child)
{
d_left = child;
}
void
tree_node::set_right_child(tree_node *child)
{
d_right = child;
}
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;
}
} /* namespace satnogs */
} /* namespace gr */