/*
* morse.c
* $Id: morse.c 489 2018-05-05 12:49:09Z kprox $
*
* Copyright (C) 2002-2006:
* Ken Prox <kprox@users.sourceforge.net>
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <math.h>
#include <gsl/gsl_errno.h>
#include <gsl/gsl_fft_real.h>
#include <gsl/gsl_fft_halfcomplex.h>
#include "agc.h"
#include "dt_window.h"
#include "dglitch.h"
#include "morse.h"
#include "utility.h"
#include "fir_win.h"
/** Needed to unpack the in place radix2 FFT terms 0 to N/2 - 1 */
#define REAL(z,i) ((z)[i])
#define IMAG(z,i,length) ((i) == 0 ? 0 : (z)[length-i])
/** Words per minute seconds per dit (WPM s / dit).
* To calculate DIT length at 25 WPM:
*
* WPM_SECONDS_PER_DIT / 25WPM = 0.0468 s / dit.
*
*/
#define WPM_SECONDS_PER_DIT (double)1.170
/** The minumum number of packets that will make up a dit.
* This limit is used to control transient noise immunity.
*/
#define MIN_NUM_PACKS_PER_DIT 6
/** Maximum value of the FFT graph display. */
#define FFT_GRAPH_TOP (double)100000.0
/** @todo Change based on rolling average of packet amplitude array. */
#define CW_ON_AMPLITUDE (FFT_GRAPH_TOP * 0.51)
/** @todo Change based on rolling average of packet amplitude array. */
#define CW_OFF_AMPLITUDE (FFT_GRAPH_TOP * 0.5)
#define MORSE_AGC_TYPE AGC_LINEAR_PEAK_W_COMPUTED_GAIN_ON_CLIP
#define FFT_DATA_MAX_GAIN (double)10.0
#define FFT_DATA_MIN_GAIN (double)0.1
#define AGC_FULL_SCALE_DELAY_SECS (double)3.0
#define FFT_NOISE_FLOOR (double)50000.0
#define FFT_SCOPE_GAIN_UP_CRR_FACTOR (double)0.025
#define FFT_SCOPE_GAIN_DOWN_CRR_FACTOR (double)0.05
#define AUDIO_SEGMENTS_PER_STATUS_UPDATE 5
#if !(defined(FALSE) || defined(TRUE))
#define FALSE 0
#define TRUE 1
#endif
/* Character Status flags */
#define CLEAR_CHARACTER_STATUS 0x00u
#define END_OF_CHARACTER 0x01u
#define VALID_CW_ON_TONE_DETECTED 0x02u
#define VALID_CW_OFF_TONE_DETECTED 0x04u
/* Word status flags. */
#define CLEAR_WORD_STATUS 0x00u
#define END_OF_WORD 0x01u
#define SHORT_DAH_VS_DITS (double)2.4000
#define DAHS_PER_DIT (double)3.0000
#define LONG_DAH_VS_DITS (double)3.6000
#define SHORT_DIT_VS_DAHS (double)0.2667
#define LONG_DIT_VS_DAHS (double)0.4000
#define SHORT_ELEMENT (double)0.7500
#define LONG_ELEMENT (double)1.2500
#define CHARACTER_SPACE_DITS (double)2.5000
#define WORD_SPACE_DITS (double)6.0000
#define MORSE_ELEMENT_HISTORY 5
/*
* begin debugging options
*/
#define DEBUG_DIT_DAH_DETECTION(a) /* printf a */
#define DEBUG_MORSE_STATISTICS(a) /* printf a */
#define DEBUG_MORSE_TIMING(a) /* printf a */
#define DEBUG_TONE_DETECTION(a) /* printf a */
#define DEBUG_RAW_FFT_ARRAY(a) /* printf a */
#define DEBUG_DGLITCHED_FFT_ARRAY(a) /* printf a */
#define DEBUG_DATA_COLLECTION_THREAD(a) DEBUG_MORSE_THREAD(a)
#define DEBUG_AUDIO_PP_THREAD(a) DEBUG_MORSE_THREAD(a)
#define DEBUG_MORSE_THREAD(a) /* printf a */
#define DEBUG_MEMORY_MANAGEMENT(a) /* printf a */
#define DEBUG_GSL(a) /* printf a */
#define DEBUG_FILTER_FREQUENCY_CHANGE(a) /* printf a */
/*
* end debugging options
*/
/** \struct IMorse
* \brief Interface that GUI functions register to.
*/
typedef struct IMorse {
/*! User interface status bar. */
UI_update_status cb_morse_status;
/*! User interface time or FFT plot. */
UI_scope_plot cb_scope_plot;
/*! User interface for decoded characters. */
UI_display_character cb_display_character;
/** User Interface handler for debugging. */
UI_debug_plot debug_plot;
/** User interface for Morse Statistics. */
UI_Morse_statistics cb_Morse_statistics;
} IMorse;
static IMorse user_interface;
static te_morse_plot_type scope_or_fft = PLOT_FFT;
/** \struct ts_morse_2_char
* \brief Morse code stream to ASCII character element.
*/
typedef struct ts_morse_2_char
{
/*! The morse code stream. */
/*! Morse code streams are defines as follows:
The first three nibbles represent the morse character data stream, the fourth
nibble represents the number of elements in the character.
A binary 1, corresponds to a dah, and a binary 0 corresponds to a dit.
For example:
c -.-. is represented by b1010 0000 0000 0100, or 0xA004
*/
uint32_t morse;
/*! The character(s) represented by the morse data stream as defined in morse. */
char *character;
} ts_morse_2_char;
/** Morse code stream to acsii conversion table.
* An array of ts_morse_2_char structs.
* @sa ts_morse_2_char
*/
const ts_morse_2_char MORSE_CODE_DECODE_TABLE[] = {
{0x0001, "e"}, /* . */
{0x8001, "t"}, /* _ */
{0x0002, "i"}, /* . . */
{0xC002, "m"}, /* _ _ */
{0x8002, "n"}, /* _ . */
{0x4002, "a"}, /* . _ */
{0x0003, "s"}, /* . . . */
{0x8003, "d"}, /* _ . . */
{0xC003, "g"}, /* _ _ . */
{0x2003, "u"}, /* . . _ */
{0x4003, "r"}, /* . _ . */
{0xA003, "k"}, /* _ . _ */
{0x6003, "w"}, /* . _ _ */
{0xE003, "o"}, /* _ _ _ */
{0x8004, "b"}, /* _ . . . */
{0xA004, "c"}, /* _ . _ . */
{0x2004, "f"}, /* . . _ . */
{0x0004, "h"}, /* . . . . */
{0x7004, "j"}, /* . _ _ _ */
{0x4004, "l"}, /* . _ . . */
{0xB004, "y"}, /* _ . _ _ */
{0x6004, "p"}, /* . _ _ . */
{0xD004, "q"}, /* _ _ . _ */
{0x1004, "v"}, /* . . . _ */
{0x9004, "x"}, /* _ . . _ */
{0xC004, "z"}, /* _ _ . . */
{0xF805, "0"}, /* _ _ _ _ _ */
{0x7805, "1"}, /* . _ _ _ _ */
{0x3805, "2"}, /* . . _ _ _ */
{0x1805, "3"}, /* . . . _ _ */
{0x0805, "4"}, /* . . . . _ */
{0x0005, "5"}, /* . . . . . */
{0x8005, "6"}, /* _ . . . . */
{0xC005, "7"}, /* _ _ . . . */
{0xE005, "8"}, /* _ _ _ . . */
{0xF005, "9"}, /* _ _ _ _ . */
{0x8406, "-"}, /* _ . . . . _ */
{0x9005, "/"}, /* _ . . _ . */
{0x5406, "."}, /* . _ . _ . _ */
{0xCC06, ","}, /* _ _ . . _ _ */
{0x3006, "?"}, /* . . _ _ . . */
{0x8805, "="}, /* _ . . . _ */
{0x6806, "@"}, /* . _ _ . _ . */
{0xB005, "("}, /* _ . _ _ . */
{0xB406, ")"}, /* _ . _ _ . _ */
{0x3406, "_"}, /* . . _ _ _ . */
{0x4806,"\""}, /* _ . _ _ . _ */
{0x7806, "'"}, /* . _ _ _ _ . */
{0xE006, ":"}, /* _ _ _ . . . */
{0xA806, ";"}, /* _ . _ . _ . */
{0x1207, "$"}, /* . . . _ . . _ */
{0x5005, "+"}, /* . _ . _ . */
{0xE004, "!"}, /* _ _ _ . */
{0x4005, "&"} /* . _ . . . */
};
#define MORSE_CODE_DECODE_TABLE_SIZE (sizeof(MORSE_CODE_DECODE_TABLE) / sizeof(struct ts_morse_2_char))
/** CW level detection states.
* CW_ON, to
评论0