123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- /*
- * Morse decoder
- *
- * Copyright (c) 2012 Michael Buesch <m@bues.ch>
- * Licensed under the terms of the GNU General Public License version 2.
- */
- #include "morse.h"
- #include "util.h"
- #define dit MORSE_DIT
- #define dah MORSE_DAH
- #define CHAR_SYM(charac, sym) [(charac) - MORSE_CHARS_START] = sym
- #define NUM_SYM(num, sym) [(num) - MORSE_NUMS_START] = sym
- #define SPEC_SYM(spec, sym) [(spec) - MORSE_SPEC_START] = sym
- #define SIG_SYM(sig, sym) [(sig) - MORSE_SIG_START] = sym
- static const morse_sym_t PROGMEM character_symbols[] = {
- CHAR_SYM(MORSE_A, MORSE_SYM_2(dit, dah)),
- CHAR_SYM(MORSE_B, MORSE_SYM_4(dah, dit, dit, dit)),
- CHAR_SYM(MORSE_C, MORSE_SYM_4(dah, dit, dah, dit)),
- CHAR_SYM(MORSE_D, MORSE_SYM_3(dah, dit, dit)),
- CHAR_SYM(MORSE_E, MORSE_SYM_1(dit)),
- CHAR_SYM(MORSE_F, MORSE_SYM_4(dit, dit, dah, dit)),
- CHAR_SYM(MORSE_G, MORSE_SYM_3(dah, dah, dit)),
- CHAR_SYM(MORSE_H, MORSE_SYM_4(dit, dit, dit, dit)),
- CHAR_SYM(MORSE_I, MORSE_SYM_2(dit, dit)),
- CHAR_SYM(MORSE_J, MORSE_SYM_4(dit, dah, dah, dah)),
- CHAR_SYM(MORSE_K, MORSE_SYM_3(dah, dit, dah)),
- CHAR_SYM(MORSE_L, MORSE_SYM_4(dit, dah, dit, dit)),
- CHAR_SYM(MORSE_M, MORSE_SYM_2(dah, dah)),
- CHAR_SYM(MORSE_N, MORSE_SYM_2(dah, dit)),
- CHAR_SYM(MORSE_O, MORSE_SYM_3(dah, dah, dah)),
- CHAR_SYM(MORSE_P, MORSE_SYM_4(dit, dah, dah, dit)),
- CHAR_SYM(MORSE_Q, MORSE_SYM_4(dah, dah, dit, dah)),
- CHAR_SYM(MORSE_R, MORSE_SYM_3(dit, dah, dit)),
- CHAR_SYM(MORSE_S, MORSE_SYM_3(dit, dit, dit)),
- CHAR_SYM(MORSE_T, MORSE_SYM_1(dah)),
- CHAR_SYM(MORSE_U, MORSE_SYM_3(dit, dit, dah)),
- CHAR_SYM(MORSE_V, MORSE_SYM_4(dit, dit, dit, dah)),
- CHAR_SYM(MORSE_W, MORSE_SYM_3(dit, dah, dah)),
- CHAR_SYM(MORSE_X, MORSE_SYM_4(dah, dit, dit, dah)),
- CHAR_SYM(MORSE_Y, MORSE_SYM_4(dah, dit, dah, dah)),
- CHAR_SYM(MORSE_Z, MORSE_SYM_4(dah, dah, dit, dit)),
- };
- static const morse_sym_t PROGMEM number_symbols[] = {
- NUM_SYM(MORSE_0, MORSE_SYM_5(dah, dah, dah, dah, dah)),
- NUM_SYM(MORSE_1, MORSE_SYM_5(dit, dah, dah, dah, dah)),
- NUM_SYM(MORSE_2, MORSE_SYM_5(dit, dit, dah, dah, dah)),
- NUM_SYM(MORSE_3, MORSE_SYM_5(dit, dit, dit, dah, dah)),
- NUM_SYM(MORSE_4, MORSE_SYM_5(dit, dit, dit, dit, dah)),
- NUM_SYM(MORSE_5, MORSE_SYM_5(dit, dit, dit, dit, dit)),
- NUM_SYM(MORSE_6, MORSE_SYM_5(dah, dit, dit, dit, dit)),
- NUM_SYM(MORSE_7, MORSE_SYM_5(dah, dah, dit, dit, dit)),
- NUM_SYM(MORSE_8, MORSE_SYM_5(dah, dah, dah, dit, dit)),
- NUM_SYM(MORSE_9, MORSE_SYM_5(dah, dah, dah, dah, dit)),
- };
- static const morse_sym_t PROGMEM special_symbols[] = {
- SPEC_SYM(MORSE_GACC_A, MORSE_SYM_5(dit, dah, dah, dit, dah)),
- SPEC_SYM(MORSE_AE, MORSE_SYM_4(dit, dah, dit, dah)),
- SPEC_SYM(MORSE_GACC_E, MORSE_SYM_5(dit, dah, dit, dit, dah)),
- SPEC_SYM(MORSE_AACC_E, MORSE_SYM_5(dit, dit, dah, dit, dit)),
- SPEC_SYM(MORSE_OE, MORSE_SYM_4(dah, dah, dah, dit)),
- SPEC_SYM(MORSE_UE, MORSE_SYM_4(dit, dit, dah, dah)),
- SPEC_SYM(MORSE_SZ, MORSE_SYM_6(dit, dit, dit, dah, dah, dit)),
- SPEC_SYM(MORSE_CH, MORSE_SYM_4(dah, dah, dah, dah)),
- SPEC_SYM(MORSE_TILDE_N, MORSE_SYM_5(dah, dah, dit, dah, dah)),
- SPEC_SYM(MORSE_PERIOD, MORSE_SYM_6(dit, dah, dit, dah, dit, dah)),
- SPEC_SYM(MORSE_COMMA, MORSE_SYM_6(dah, dah, dit, dit, dah, dah)),
- SPEC_SYM(MORSE_COLON, MORSE_SYM_6(dah, dah, dah, dit, dit, dit)),
- SPEC_SYM(MORSE_SEMICOLON, MORSE_SYM_6(dah, dit, dah, dit, dah, dit)),
- SPEC_SYM(MORSE_QUESTION, MORSE_SYM_6(dit, dit, dah, dah, dit, dit)),
- SPEC_SYM(MORSE_DASH, MORSE_SYM_6(dah, dit, dit, dit, dit, dah)),
- SPEC_SYM(MORSE_UNDERSCORE, MORSE_SYM_6(dit, dit, dah, dah, dit, dah)),
- SPEC_SYM(MORSE_PAREN_OPEN, MORSE_SYM_5(dah, dit, dah, dah, dit)),
- SPEC_SYM(MORSE_PAREN_CLOSE, MORSE_SYM_6(dah, dit, dah, dah, dit, dah)),
- SPEC_SYM(MORSE_TICK, MORSE_SYM_6(dit, dah, dah, dah, dah, dit)),
- SPEC_SYM(MORSE_EQUAL, MORSE_SYM_5(dah, dit, dit, dit, dah)),
- SPEC_SYM(MORSE_PLUS, MORSE_SYM_5(dit, dah, dit, dah, dit)),
- SPEC_SYM(MORSE_SLASH, MORSE_SYM_5(dah, dit, dit, dah, dit)),
- SPEC_SYM(MORSE_AT, MORSE_SYM_6(dit, dah, dah, dit, dah, dit)),
- SPEC_SYM(MORSE_SPACE, 0),
- };
- static const morse_sym_t PROGMEM signal_symbols[] = {
- SIG_SYM(MORSE_SIG_KA, MORSE_SYM_5(dah, dit, dah, dit, dah)),
- SIG_SYM(MORSE_SIG_BT, MORSE_SYM_5(dah, dit, dit, dit, dah)),
- SIG_SYM(MORSE_SIG_AR, MORSE_SYM_5(dit, dah, dit, dah, dit)),
- SIG_SYM(MORSE_SIG_VE, MORSE_SYM_5(dit, dit, dit, dah, dit)),
- SIG_SYM(MORSE_SIG_SK, MORSE_SYM_6(dit, dit, dit, dah, dit, dah)),
- SIG_SYM(MORSE_SIG_SOS, MORSE_SYM_9(dit, dit, dit, dah, dah, dah, dit, dit, dit)),
- SIG_SYM(MORSE_SIG_ERROR, MORSE_SYM_8(dit, dit, dit, dit, dit, dit, dit, dit)),
- };
- static morse_sym_t fetch_sym(const morse_sym_t * PROGPTR table,
- uint8_t offset)
- {
- return pgm_read_word(&table[offset]);
- }
- morse_sym_t morse_encode_character(enum morse_character c)
- {
- if (c >= MORSE_CHARS_START && c <= MORSE_CHARS_END)
- return fetch_sym(character_symbols, c - MORSE_CHARS_START);
- if (c >= MORSE_NUMS_START && c <= MORSE_NUMS_END)
- return fetch_sym(number_symbols, c - MORSE_NUMS_START);
- if (c >= MORSE_SPEC_START && c <= MORSE_SPEC_END)
- return fetch_sym(special_symbols, c - MORSE_SPEC_START);
- if (c >= MORSE_SIG_START && c <= MORSE_SIG_END)
- return fetch_sym(signal_symbols, c - MORSE_SIG_START);
- return fetch_sym(signal_symbols, MORSE_SIG_ERROR - MORSE_SIG_START);
- }
- enum morse_character morse_decode_symbol(morse_sym_t sym)
- {
- unsigned int i;
- #define check_decode_tab(table, startchar) \
- for (i = 0; i < ARRAY_SIZE(table); i++) { \
- if (fetch_sym(table, i) == sym) \
- return (enum morse_character)(i + startchar); \
- }
- check_decode_tab(character_symbols, MORSE_CHARS_START)
- check_decode_tab(number_symbols, MORSE_NUMS_START)
- check_decode_tab(special_symbols, MORSE_SPEC_START)
- check_decode_tab(signal_symbols, MORSE_SIG_START)
- #undef check_decode_tab
- return MORSE_INVALID;
- }
- int8_t morse_to_ascii(char *buf, uint8_t buf_size,
- enum morse_character mchar)
- {
- int8_t ret = 0;
- #define put_char(c) { \
- if (!buf_size--) \
- return -1; \
- *buf++ = (c); \
- ret++; \
- }
- if ((mchar >= MORSE_CHARS_START && mchar <= MORSE_CHARS_END) ||
- (mchar >= MORSE_NUMS_START && mchar <= MORSE_NUMS_END)) {
- put_char((char)mchar);
- } else {
- switch (mchar) {
- case MORSE_GACC_A:
- put_char('A');
- break;
- case MORSE_GACC_E:
- case MORSE_AACC_E:
- put_char('E');
- break;
- case MORSE_AE:
- put_char('A');
- put_char('E');
- break;
- case MORSE_OE:
- put_char('O');
- put_char('E');
- break;
- case MORSE_UE:
- put_char('U');
- put_char('E');
- break;
- case MORSE_SZ:
- put_char('S');
- put_char('S');
- break;
- case MORSE_CH:
- put_char('C');
- put_char('H');
- break;
- case MORSE_TILDE_N:
- put_char('N');
- break;
- case MORSE_PERIOD:
- put_char('.');
- break;
- case MORSE_COMMA:
- put_char(',');
- break;
- case MORSE_COLON:
- put_char(':');
- break;
- case MORSE_SEMICOLON:
- put_char(';');
- break;
- case MORSE_QUESTION:
- put_char('?');
- break;
- case MORSE_DASH:
- put_char('-');
- break;
- case MORSE_UNDERSCORE:
- put_char('_');
- break;
- case MORSE_PAREN_OPEN:
- put_char('(');
- break;
- case MORSE_PAREN_CLOSE:
- put_char(')');
- break;
- case MORSE_TICK:
- put_char('\'');
- break;
- case MORSE_EQUAL:
- put_char('=');
- break;
- case MORSE_PLUS:
- put_char('+');
- break;
- case MORSE_SLASH:
- put_char('/');
- break;
- case MORSE_AT:
- put_char('@');
- break;
- case MORSE_SPACE:
- put_char(' ');
- break;
- case MORSE_SIG_KA:
- case MORSE_SIG_BT:
- case MORSE_SIG_AR:
- case MORSE_SIG_VE:
- case MORSE_SIG_SK:
- put_char(' ');
- break;
- case MORSE_SIG_SOS:
- put_char('S');
- put_char('0');
- put_char('S');
- break;
- case MORSE_SIG_ERROR:
- put_char('-');
- put_char('E');
- put_char('R');
- put_char('R');
- put_char('O');
- put_char('R');
- put_char('-');
- break;
- default:
- return -1;
- }
- }
- #undef put_char
- return ret;
- }
|