/* -*- c++ -*- */ /* * gr-satnogs: SatNOGS GNU Radio Out-Of-Tree Module * * Copyright (C) 2016,2017 * Libre Space Foundation * * 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 . */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include 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 */