2007-06-22 22:04:50 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// cw.h -- morse code modem
|
|
|
|
//
|
2010-03-01 12:56:30 +00:00
|
|
|
// Copyright (C) 2006-2009
|
2007-06-22 22:04:50 +00:00
|
|
|
// Dave Freese, W1HKJ
|
|
|
|
//
|
2007-06-22 22:10:49 +00:00
|
|
|
// This file is part of fldigi. Adapted in part from code contained in
|
|
|
|
// gmfsk source code distribution.
|
2007-06-22 22:04:50 +00:00
|
|
|
// gmfsk Copyright (C) 2001, 2002, 2003
|
|
|
|
// Tomi Manninen (oh2bns@sral.fi)
|
|
|
|
// Copyright (C) 2004
|
|
|
|
// Lawrence Glaister (ve7it@shaw.ca)
|
|
|
|
//
|
2010-03-01 12:56:30 +00:00
|
|
|
// Fldigi is free software: you can redistribute it and/or modify
|
2007-06-22 22:04:50 +00:00
|
|
|
// it under the terms of the GNU General Public License as published by
|
2010-03-01 12:56:30 +00:00
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
2007-06-22 22:04:50 +00:00
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
2010-03-01 12:56:30 +00:00
|
|
|
// Fldigi is distributed in the hope that it will be useful,
|
2007-06-22 22:04:50 +00:00
|
|
|
// 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
|
2010-03-01 12:56:30 +00:00
|
|
|
// along with fldigi. If not, see <http://www.gnu.org/licenses/>.
|
2007-06-22 22:04:50 +00:00
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
#ifndef _CW_H
|
|
|
|
#define _CW_H
|
|
|
|
|
2012-05-28 21:42:35 +00:00
|
|
|
#include <cstring>
|
|
|
|
#include <string>
|
|
|
|
|
2007-06-22 22:04:50 +00:00
|
|
|
#include "modem.h"
|
|
|
|
#include "filters.h"
|
2012-05-28 21:42:35 +00:00
|
|
|
#include "fftfilt.h"
|
2007-10-06 15:04:10 +00:00
|
|
|
#include "mbuffer.h"
|
2007-06-22 22:04:50 +00:00
|
|
|
|
2012-05-28 21:42:35 +00:00
|
|
|
|
2007-06-22 22:04:50 +00:00
|
|
|
#define CWSampleRate 8000
|
2012-05-28 21:42:35 +00:00
|
|
|
#define CWMaxSymLen 4096 // AG1LE: - was 4096
|
2014-12-19 15:57:51 +00:00
|
|
|
#define KNUM 640 // 1/2 dot length at 5 wpm
|
2007-06-22 22:04:50 +00:00
|
|
|
|
|
|
|
// decimation ratio for the receiver
|
2009-03-12 18:56:49 +00:00
|
|
|
//#define DEC_RATIO 8
|
|
|
|
//#define CW_FIRLEN 32
|
2012-05-28 21:42:35 +00:00
|
|
|
//#define CW_FIRLEN 122
|
2007-06-22 22:04:50 +00:00
|
|
|
//#define CW_FIRLEN 256
|
|
|
|
//#define CW_FIRLEN 512
|
|
|
|
// Limits on values of CW send and timing parameters
|
2007-06-22 22:10:49 +00:00
|
|
|
//#define CW_MIN_SPEED 5 // Lowest WPM allowed
|
|
|
|
//#define CW_MAX_SPEED 100 // Highest WPM allowed
|
2007-06-22 22:04:50 +00:00
|
|
|
|
|
|
|
// CW function return status codes.
|
2012-05-28 21:42:35 +00:00
|
|
|
#define CW_SUCCESS 0
|
|
|
|
#define CW_ERROR -1
|
2007-06-22 22:04:50 +00:00
|
|
|
|
|
|
|
#define ASC_NUL '\0' // End of string
|
|
|
|
#define ASC_SPACE ' ' // ASCII space char
|
|
|
|
|
|
|
|
// Tone and timing magic numbers.
|
|
|
|
#define DOT_MAGIC 1200000 // Dot length magic number. The Dot
|
|
|
|
// length is 1200000/WPM Usec
|
|
|
|
#define TONE_SILENT 0 // 0Hz = silent 'tone'
|
|
|
|
#define USECS_PER_SEC 1000000 // Microseconds in a second
|
|
|
|
|
|
|
|
#define INITIAL_SEND_SPEED 18 // Initial send speed in WPM
|
|
|
|
#define INITIAL_RECEIVE_SPEED 18 // Initial receive speed in WPM
|
|
|
|
|
|
|
|
// Initial adaptive speed threshold
|
|
|
|
#define INITIAL_THRESHOLD ((DOT_MAGIC / INITIAL_RECEIVE_SPEED) * 2)
|
|
|
|
|
|
|
|
// Initial noise filter threshold
|
|
|
|
#define INITIAL_NOISE_THRESHOLD ((DOT_MAGIC / CW_MAX_SPEED) / 2)
|
|
|
|
|
|
|
|
#define TRACKING_FILTER_SIZE 16
|
|
|
|
|
2012-05-28 21:42:35 +00:00
|
|
|
#define MAX_PIPE_SIZE (22 * CWSampleRate * 12 / 800)
|
|
|
|
|
2007-06-22 22:04:50 +00:00
|
|
|
enum CW_RX_STATE {
|
|
|
|
RS_IDLE = 0,
|
|
|
|
RS_IN_TONE,
|
|
|
|
RS_AFTER_TONE
|
|
|
|
};
|
|
|
|
|
|
|
|
enum CW_EVENT {
|
|
|
|
CW_RESET_EVENT,
|
|
|
|
CW_KEYDOWN_EVENT,
|
|
|
|
CW_KEYUP_EVENT,
|
|
|
|
CW_QUERY_EVENT
|
|
|
|
};
|
|
|
|
|
2007-11-02 01:02:35 +00:00
|
|
|
class cw : public modem {
|
2007-06-22 22:04:50 +00:00
|
|
|
|
2012-05-28 21:42:35 +00:00
|
|
|
#define CLRCOUNT 16
|
|
|
|
#define DEC_RATIO 16
|
|
|
|
#define CW_FIRLEN 512
|
|
|
|
// Maximum number of signs (dit or dah) in a Morse char.
|
|
|
|
#define WGT_SIZE 7
|
|
|
|
|
|
|
|
struct SOM_TABLE {
|
|
|
|
char chr; /* The character(s) represented */
|
|
|
|
const char *prt; /* The printable representation of the character */
|
|
|
|
float wgt[WGT_SIZE]; /* Dot-dash weight vector */
|
|
|
|
};
|
|
|
|
|
|
|
|
protected:
|
|
|
|
int symbollen; // length of a dot in sound samples (tx)
|
|
|
|
int fsymlen; // length of extra interelement space (farnsworth)
|
|
|
|
double phaseacc; // used by NCO for rx/tx tones
|
|
|
|
double FFTphase;
|
|
|
|
double FIRphase;
|
|
|
|
double FFTvalue;
|
|
|
|
double FIRvalue;
|
|
|
|
unsigned int smpl_ctr; // sample counter for timing cw rx
|
|
|
|
double agc_peak; // threshold for tone detection
|
|
|
|
|
|
|
|
int FilterFFTLen;
|
|
|
|
bool use_matched_filter;
|
|
|
|
bool use_fft_filter;
|
|
|
|
|
|
|
|
double upper_threshold;
|
|
|
|
double lower_threshold;
|
|
|
|
|
|
|
|
C_FIR_filter *hilbert; // Hilbert filter precedes sinc filter
|
|
|
|
fftfilt *cw_FFT_filter; // sinc / matched filter
|
|
|
|
C_FIR_filter *cw_FIR_filter; // linear phase finite impulse response filter
|
|
|
|
|
|
|
|
Cmovavg *bitfilter;
|
|
|
|
Cmovavg *trackingfilter;
|
2007-06-22 22:04:50 +00:00
|
|
|
|
2007-09-19 00:45:42 +00:00
|
|
|
int bitfilterlen;
|
|
|
|
|
2007-06-22 22:04:50 +00:00
|
|
|
CW_RX_STATE cw_receive_state; // Indicates receive state
|
2010-03-20 20:23:50 +00:00
|
|
|
CW_RX_STATE old_cw_receive_state;
|
2007-06-22 22:04:50 +00:00
|
|
|
CW_EVENT cw_event; // functions used by cw process routine
|
|
|
|
|
2012-05-28 21:42:35 +00:00
|
|
|
double pipe[MAX_PIPE_SIZE+1]; // storage for sync scope data
|
|
|
|
double clearpipe[MAX_PIPE_SIZE+1];
|
|
|
|
mbuffer<double, MAX_PIPE_SIZE + 1, 4> scopedata;
|
2007-06-22 22:04:50 +00:00
|
|
|
int pipeptr;
|
|
|
|
int pipesize;
|
2009-03-12 18:56:49 +00:00
|
|
|
bool scope_clear;
|
2007-06-22 22:04:50 +00:00
|
|
|
|
|
|
|
// user configurable data - local copy passed in from gui
|
|
|
|
int cw_speed;
|
|
|
|
int cw_bandwidth;
|
|
|
|
int cw_squelch;
|
|
|
|
int cw_send_speed; // Initially 18 WPM
|
2012-05-28 21:42:35 +00:00
|
|
|
int cw_receive_speed; // Initially 18 WPM
|
2007-06-22 22:10:49 +00:00
|
|
|
bool usedefaultWPM; // use default WPM
|
2007-06-22 22:04:50 +00:00
|
|
|
|
|
|
|
int cw_upper_limit;
|
|
|
|
int cw_lower_limit;
|
|
|
|
|
2012-05-28 21:42:35 +00:00
|
|
|
long int cw_noise_spike_threshold; // Initially ignore any tone < 10mS
|
2007-06-22 22:04:50 +00:00
|
|
|
int cw_in_sync; // Synchronization flag
|
|
|
|
|
|
|
|
// Sending parameters:
|
2012-05-28 21:42:35 +00:00
|
|
|
long int cw_send_dot_length; // Length of a send Dot, in Usec
|
|
|
|
long int cw_send_dash_length; // Length of a send Dash, in Usec
|
2007-06-22 22:04:50 +00:00
|
|
|
int lastsym; // last symbol sent
|
2012-05-28 21:42:35 +00:00
|
|
|
double risetime; // leading/trailing edge rise time (msec)
|
|
|
|
int knum; // number of samples on edges
|
|
|
|
int QSKshape; // leading/trailing edge shape factor
|
|
|
|
double qskbuf[OUTBUFSIZE]; // signal array for qsk drive
|
2009-03-07 13:42:11 +00:00
|
|
|
double qskphase; //
|
2007-06-22 22:19:01 +00:00
|
|
|
bool firstelement;
|
2015-01-04 19:53:22 +00:00
|
|
|
double maxval;
|
|
|
|
|
2007-06-22 22:10:49 +00:00
|
|
|
// double *keyshape; // array defining leading edge
|
|
|
|
|
2007-06-22 22:04:50 +00:00
|
|
|
// Receiving parameters:
|
|
|
|
long int cw_receive_dot_length; // Length of a receive Dot, in Usec
|
|
|
|
long int cw_receive_dash_length; // Length of a receive Dash, in Usec
|
|
|
|
|
|
|
|
// Receive buffering
|
|
|
|
#define RECEIVE_CAPACITY 256 // Way longer than any representation
|
|
|
|
char rx_rep_buf[RECEIVE_CAPACITY];
|
|
|
|
int cw_rr_current; // Receive buffer current location
|
2012-05-28 21:42:35 +00:00
|
|
|
unsigned int cw_rr_start_timestamp; // Tone start timestamp
|
|
|
|
unsigned int cw_rr_end_timestamp; // Tone end timestamp
|
2007-06-22 22:04:50 +00:00
|
|
|
|
2012-05-28 21:42:35 +00:00
|
|
|
long int cw_adaptive_receive_threshold; // 2-dot threshold for adaptive speed
|
|
|
|
int in_replay; //AG1LE: if we have replay even, set to 1 otherwise = 0 ;
|
2007-06-22 22:04:50 +00:00
|
|
|
|
|
|
|
// Receive adaptive speed tracking.
|
|
|
|
double dot_tracking;
|
|
|
|
double dash_tracking;
|
|
|
|
|
|
|
|
inline double nco(double freq);
|
2009-03-07 13:42:11 +00:00
|
|
|
inline double qsknco();
|
2007-06-22 22:04:50 +00:00
|
|
|
void update_syncscope();
|
2009-03-12 18:56:49 +00:00
|
|
|
void clear_syncscope();
|
2007-06-22 22:10:49 +00:00
|
|
|
void update_Status();
|
2007-06-22 22:04:50 +00:00
|
|
|
void sync_parameters();
|
2012-05-28 21:42:35 +00:00
|
|
|
void reset_rx_filter();
|
2007-06-22 22:27:16 +00:00
|
|
|
int handle_event(int cw_event, const char **c);
|
2007-06-22 22:04:50 +00:00
|
|
|
int usec_diff(unsigned int earlier, unsigned int later);
|
2009-04-21 23:09:06 +00:00
|
|
|
void send_symbol(int symbol, int len);
|
2007-06-22 22:04:50 +00:00
|
|
|
void send_ch(int c);
|
|
|
|
bool tables_init();
|
|
|
|
unsigned int tokenize_representation(char *representation);
|
|
|
|
void update_tracking(int dot, int dash);
|
2012-05-28 21:42:35 +00:00
|
|
|
|
|
|
|
static const SOM_TABLE som_table[];
|
|
|
|
float cw_buffer[512];
|
|
|
|
int cw_ptr;
|
|
|
|
int clrcount;
|
|
|
|
|
2014-12-19 15:57:51 +00:00
|
|
|
double lowerwpm;
|
|
|
|
double upperwpm;
|
|
|
|
|
2012-05-28 21:42:35 +00:00
|
|
|
bool use_paren;
|
|
|
|
std::string prosigns;
|
|
|
|
|
2014-12-19 15:57:51 +00:00
|
|
|
cmplx mixer(cmplx in);
|
|
|
|
|
|
|
|
// transmit wave shaping
|
|
|
|
int nusymbollen;
|
|
|
|
int nufsymlen;
|
|
|
|
int wpm;
|
|
|
|
int fwpm;
|
|
|
|
|
|
|
|
void makeshape();
|
|
|
|
void sync_transmit_parameters();
|
|
|
|
|
|
|
|
fftfilt *cw_xmt_filter;
|
|
|
|
double nbfreq;
|
|
|
|
double nbpf;
|
|
|
|
double lwr;
|
|
|
|
double upr;
|
|
|
|
double *xmt_signal;
|
|
|
|
double *qsk_signal;
|
|
|
|
int qsk_ptr;
|
|
|
|
void nb_filter(double *output, double *qsk, int len);
|
|
|
|
|
2007-06-22 22:04:50 +00:00
|
|
|
public:
|
|
|
|
cw();
|
|
|
|
~cw();
|
|
|
|
void init();
|
|
|
|
void rx_init();
|
2008-02-14 23:38:09 +00:00
|
|
|
void tx_init(SoundBase *sc);
|
2007-06-22 22:04:50 +00:00
|
|
|
void restart() {};
|
2012-05-28 21:42:35 +00:00
|
|
|
|
2007-09-19 00:45:42 +00:00
|
|
|
int rx_process(const double *buf, int len);
|
2012-05-28 21:42:35 +00:00
|
|
|
void rx_FFTprocess(const double *buf, int len);
|
|
|
|
void rx_FIRprocess(const double *buf, int len);
|
|
|
|
void decode_stream(double);
|
|
|
|
|
2007-06-22 22:04:50 +00:00
|
|
|
int tx_process();
|
2007-06-22 22:10:49 +00:00
|
|
|
void incWPM();
|
|
|
|
void decWPM();
|
|
|
|
void toggleWPM();
|
2007-06-22 22:04:50 +00:00
|
|
|
|
2012-05-28 21:42:35 +00:00
|
|
|
int normalize(float *v, int n, int twodots);
|
|
|
|
const char *find_winner (float *inbuf, int twodots);
|
|
|
|
|
2007-06-22 22:04:50 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|