2015-07-27 00:35:07 +00:00
|
|
|
/* fsk_demod_state.h */
|
|
|
|
|
|
|
|
#ifndef FSK_DEMOD_STATE_H
|
|
|
|
|
2015-07-27 01:05:48 +00:00
|
|
|
#include "rpack.h"
|
|
|
|
|
2016-05-01 22:46:47 +00:00
|
|
|
#include "audio.h" // for enum modem_t
|
2015-07-27 01:05:48 +00:00
|
|
|
|
2015-07-27 00:35:07 +00:00
|
|
|
/*
|
|
|
|
* Demodulator state.
|
2016-05-01 22:46:47 +00:00
|
|
|
* The name of the file is from we only had FSK. Now we have other techniques.
|
2015-07-27 00:35:07 +00:00
|
|
|
* Different copy is required for each channel & subchannel being processed concurrently.
|
|
|
|
*/
|
|
|
|
|
2015-07-27 01:17:23 +00:00
|
|
|
// TODO1.2: change prefix from BP_ to DSP_
|
2015-07-27 00:35:07 +00:00
|
|
|
|
|
|
|
typedef enum bp_window_e { BP_WINDOW_TRUNCATED,
|
|
|
|
BP_WINDOW_COSINE,
|
|
|
|
BP_WINDOW_HAMMING,
|
|
|
|
BP_WINDOW_BLACKMAN,
|
|
|
|
BP_WINDOW_FLATTOP } bp_window_t;
|
|
|
|
|
2015-07-27 01:17:23 +00:00
|
|
|
|
2015-07-27 00:35:07 +00:00
|
|
|
struct demodulator_state_s
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* These are set once during initialization.
|
|
|
|
*/
|
2016-05-01 22:46:47 +00:00
|
|
|
enum modem_t modem_type; // MODEM_AFSK, MODEM_8PSK, etc.
|
2015-07-27 00:35:07 +00:00
|
|
|
|
2019-05-20 00:57:56 +00:00
|
|
|
enum v26_e v26_alt; // Which alternative when V.26.
|
|
|
|
|
2015-07-27 01:17:23 +00:00
|
|
|
char profile; // 'A', 'B', etc. Upper case.
|
|
|
|
// Only needed to see if we are using 'F' to take fast path.
|
|
|
|
|
2019-01-21 16:07:20 +00:00
|
|
|
int play_it_again_sample; // Enable new synchronous demod in version 1.6.
|
|
|
|
|
2015-07-27 00:35:07 +00:00
|
|
|
#define TICKS_PER_PLL_CYCLE ( 256.0 * 256.0 * 256.0 * 256.0 )
|
|
|
|
|
|
|
|
int pll_step_per_sample; // PLL is advanced by this much each audio sample.
|
|
|
|
// Data is sampled when it overflows.
|
|
|
|
|
|
|
|
|
|
|
|
int ms_filter_size; /* Size of mark & space filters, in audio samples. */
|
|
|
|
/* Started off as a guess of one bit length */
|
2019-01-21 16:07:20 +00:00
|
|
|
/* but about 2 bit times turned out to be better. */
|
2015-07-27 00:35:07 +00:00
|
|
|
/* Currently using same size for any prefilter. */
|
|
|
|
|
2019-01-21 16:07:20 +00:00
|
|
|
int m2_filter_size;
|
|
|
|
int s2_filter_size; /* Size of mark & space filters, in audio samples */
|
|
|
|
/* for the synchronous demodulator. I'm expecting */
|
|
|
|
/* smaller, perhaps just over 1 bit time here. */
|
|
|
|
|
|
|
|
int lp2_filter_size; /* FSK resampling - Size of Low Pass filter, in audio samples. */
|
|
|
|
|
|
|
|
|
2015-07-27 00:35:07 +00:00
|
|
|
#define MAX_FILTER_SIZE 320 /* 304 is needed for profile C, 300 baud & 44100. */
|
|
|
|
|
|
|
|
/*
|
2015-07-27 01:17:23 +00:00
|
|
|
* Filter length for Mark & Space in bit times.
|
|
|
|
* e.g. 1 means 1/1200 second for 1200 baud.
|
2015-07-27 00:35:07 +00:00
|
|
|
*/
|
2015-07-27 01:17:23 +00:00
|
|
|
float ms_filter_len_bits;
|
2019-01-21 16:07:20 +00:00
|
|
|
float m2_filter_len_bits;
|
|
|
|
float s2_filter_len_bits;
|
|
|
|
float lp_delay_fract;
|
2015-07-27 00:35:07 +00:00
|
|
|
|
|
|
|
/*
|
2015-07-27 01:17:23 +00:00
|
|
|
* Window type for the various filters.
|
2015-07-27 00:35:07 +00:00
|
|
|
*/
|
2015-07-27 01:17:23 +00:00
|
|
|
|
|
|
|
bp_window_t pre_window;
|
|
|
|
bp_window_t ms_window;
|
|
|
|
bp_window_t lp_window;
|
2019-01-21 16:07:20 +00:00
|
|
|
bp_window_t ms2_window; /* New in 1.6. */
|
2015-07-27 01:17:23 +00:00
|
|
|
|
2015-07-27 00:35:07 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Alternate Low pass filters.
|
|
|
|
* First is arbitrary number for quick IIR.
|
|
|
|
* Second is frequency as ratio to baud rate for FIR.
|
|
|
|
*/
|
|
|
|
int lpf_use_fir; /* 0 for IIR, 1 for FIR. */
|
2015-07-27 01:17:23 +00:00
|
|
|
|
|
|
|
float lpf_iir; /* Only if using IIR. */
|
|
|
|
|
|
|
|
float lpf_baud; /* Cutoff frequency as fraction of baud. */
|
|
|
|
/* Intuitively we'd expect this to be somewhere */
|
|
|
|
/* in the range of 0.5 to 1. */
|
|
|
|
/* In practice, it turned out a little larger */
|
|
|
|
/* for profiles B, C, D. */
|
|
|
|
|
|
|
|
float lp_filter_len_bits; /* Length in number of bit times. */
|
|
|
|
|
|
|
|
int lp_filter_size; /* Size of Low Pass filter, in audio samples. */
|
|
|
|
/* Previously it was always the same as the M/S */
|
|
|
|
/* filters but in version 1.2 it's now independent. */
|
2015-07-27 00:35:07 +00:00
|
|
|
|
2019-01-21 16:07:20 +00:00
|
|
|
int lp_filter_delay; /* Number of samples that the low pass filter */
|
|
|
|
/* delays the signal. */
|
|
|
|
|
|
|
|
/* New in 1.6. */
|
|
|
|
|
|
|
|
|
2015-07-27 00:35:07 +00:00
|
|
|
/*
|
|
|
|
* Automatic gain control. Fast attack and slow decay factors.
|
|
|
|
*/
|
|
|
|
float agc_fast_attack;
|
|
|
|
float agc_slow_decay;
|
2015-07-27 01:17:23 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Use a longer term view for reporting signal levels.
|
|
|
|
*/
|
|
|
|
float quick_attack;
|
|
|
|
float sluggish_decay;
|
|
|
|
|
2015-07-27 00:35:07 +00:00
|
|
|
/*
|
|
|
|
* Hysteresis before final demodulator 0 / 1 decision.
|
|
|
|
*/
|
|
|
|
float hysteresis;
|
2015-07-27 01:17:23 +00:00
|
|
|
int num_slicers; /* >1 for multiple slicers. */
|
2015-07-27 00:35:07 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Phase Locked Loop (PLL) inertia.
|
|
|
|
* Larger number means less influence by signal transitions.
|
|
|
|
*/
|
|
|
|
float pll_locked_inertia;
|
|
|
|
float pll_searching_inertia;
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Optional band pass pre-filter before mark/space detector.
|
|
|
|
*/
|
|
|
|
int use_prefilter; /* True to enable it. */
|
|
|
|
|
|
|
|
float prefilter_baud; /* Cutoff frequencies, as fraction of */
|
|
|
|
/* baud rate, beyond tones used. */
|
|
|
|
/* Example, if we used 1600/1800 tones at */
|
|
|
|
/* 300 baud, and this was 0.5, the cutoff */
|
|
|
|
/* frequencies would be: */
|
|
|
|
/* lower = min(1600,1800) - 0.5 * 300 = 1450 */
|
|
|
|
/* upper = max(1600,1800) + 0.5 * 300 = 1950 */
|
|
|
|
|
2015-07-27 01:17:23 +00:00
|
|
|
float pre_filter_len_bits; /* Length in number of bit times. */
|
|
|
|
|
|
|
|
int pre_filter_size; /* Size of pre filter, in audio samples. */
|
|
|
|
|
2015-07-27 00:35:07 +00:00
|
|
|
float pre_filter[MAX_FILTER_SIZE] __attribute__((aligned(16)));
|
|
|
|
|
2019-05-20 00:57:56 +00:00
|
|
|
|
2015-07-27 00:35:07 +00:00
|
|
|
/*
|
|
|
|
* Kernel for the mark and space detection filters.
|
|
|
|
*/
|
|
|
|
|
|
|
|
float m_sin_table[MAX_FILTER_SIZE] __attribute__((aligned(16)));
|
|
|
|
float m_cos_table[MAX_FILTER_SIZE] __attribute__((aligned(16)));
|
|
|
|
|
|
|
|
float s_sin_table[MAX_FILTER_SIZE] __attribute__((aligned(16)));
|
|
|
|
float s_cos_table[MAX_FILTER_SIZE] __attribute__((aligned(16)));
|
|
|
|
|
2019-01-21 16:07:20 +00:00
|
|
|
/*
|
|
|
|
* Same for the synchronous re-demodulator.
|
|
|
|
*/
|
|
|
|
|
|
|
|
float m2_sin_table[MAX_FILTER_SIZE] __attribute__((aligned(16)));
|
|
|
|
float m2_cos_table[MAX_FILTER_SIZE] __attribute__((aligned(16)));
|
|
|
|
|
|
|
|
float s2_sin_table[MAX_FILTER_SIZE] __attribute__((aligned(16)));
|
|
|
|
float s2_cos_table[MAX_FILTER_SIZE] __attribute__((aligned(16)));
|
|
|
|
|
|
|
|
float lp2_filter[MAX_FILTER_SIZE] __attribute__((aligned(16)));
|
|
|
|
|
2016-05-01 22:46:47 +00:00
|
|
|
/*
|
|
|
|
* These are for PSK only.
|
|
|
|
* They are number of delay line taps into previous symbol.
|
|
|
|
* They are one symbol period and + or - 45 degrees of the carrier frequency.
|
|
|
|
*/
|
|
|
|
int boffs; /* symbol length based on sample rate and baud. */
|
|
|
|
int coffs; /* to get cos component of previous symbol. */
|
|
|
|
int soffs; /* to get sin component of previous symbol. */
|
|
|
|
|
|
|
|
unsigned int lo_step; /* How much to advance the local oscillator */
|
|
|
|
/* phase for each audio sample. */
|
|
|
|
|
|
|
|
int psk_use_lo; /* Use local oscillator rather than self correlation. */
|
|
|
|
|
|
|
|
|
2015-07-27 00:35:07 +00:00
|
|
|
/*
|
|
|
|
* The rest are continuously updated.
|
|
|
|
*/
|
|
|
|
|
2016-05-01 22:46:47 +00:00
|
|
|
unsigned int lo_phase; /* Local oscillator for PSK. */
|
|
|
|
|
|
|
|
|
2015-07-27 00:35:07 +00:00
|
|
|
/*
|
|
|
|
* Most recent raw audio samples, before/after prefiltering.
|
|
|
|
*/
|
|
|
|
float raw_cb[MAX_FILTER_SIZE] __attribute__((aligned(16)));
|
|
|
|
|
2015-07-27 01:17:23 +00:00
|
|
|
/*
|
|
|
|
* Use half of the AGC code to get a measure of input audio amplitude.
|
|
|
|
* These use "quick" attack and "sluggish" decay while the
|
|
|
|
* AGC uses "fast" attack and "slow" decay.
|
|
|
|
*/
|
|
|
|
|
|
|
|
float alevel_rec_peak;
|
|
|
|
float alevel_rec_valley;
|
|
|
|
float alevel_mark_peak;
|
|
|
|
float alevel_space_peak;
|
|
|
|
|
2015-07-27 00:35:07 +00:00
|
|
|
/*
|
|
|
|
* Input to the mark/space detector.
|
|
|
|
* Could be prefiltered or raw audio.
|
|
|
|
*/
|
|
|
|
float ms_in_cb[MAX_FILTER_SIZE] __attribute__((aligned(16)));
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Outputs from the mark and space amplitude detection,
|
|
|
|
* used as inputs to the FIR lowpass filters.
|
|
|
|
* Kernel for the lowpass filters.
|
|
|
|
*/
|
|
|
|
|
|
|
|
float m_amp_cb[MAX_FILTER_SIZE] __attribute__((aligned(16)));
|
|
|
|
float s_amp_cb[MAX_FILTER_SIZE] __attribute__((aligned(16)));
|
|
|
|
|
|
|
|
float lp_filter[MAX_FILTER_SIZE] __attribute__((aligned(16)));
|
|
|
|
|
|
|
|
|
|
|
|
float m_peak, s_peak;
|
|
|
|
float m_valley, s_valley;
|
|
|
|
float m_amp_prev, s_amp_prev;
|
|
|
|
|
2019-05-20 00:57:56 +00:00
|
|
|
|
2015-07-27 01:17:23 +00:00
|
|
|
/*
|
|
|
|
* For the PLL and data bit timing.
|
|
|
|
* starting in version 1.2 we can have multiple slicers for one demodulator.
|
|
|
|
* Each slicer has its own PLL and HDLC decoder.
|
|
|
|
*/
|
2015-07-27 00:35:07 +00:00
|
|
|
|
2015-11-29 15:44:30 +00:00
|
|
|
/*
|
|
|
|
* Version 1.3: Clean up subchan vs. slicer.
|
|
|
|
*
|
|
|
|
* Originally some number of CHANNELS (originally 2, later 6)
|
|
|
|
* which can have multiple parallel demodulators called SUB-CHANNELS.
|
|
|
|
* This was originally for staggered frequencies for HF SSB.
|
|
|
|
* It can also be used for multiple demodulators with the same
|
|
|
|
* frequency but other differing parameters.
|
|
|
|
* Each subchannel has its own demodulator and HDLC decoder.
|
|
|
|
*
|
|
|
|
* In version 1.2 we added multiple SLICERS.
|
|
|
|
* The data structure, here, has multiple slicers per
|
|
|
|
* demodulator (subchannel). Due to fuzzy thinking or
|
|
|
|
* expediency, the multiple slicers got mapped into subchannels.
|
|
|
|
* This means we can't use both multiple decoders and
|
|
|
|
* multiple slicers at the same time.
|
|
|
|
*
|
|
|
|
* Clean this up in 1.3 and keep the concepts separate.
|
|
|
|
* This means adding a third variable many places
|
|
|
|
* we are passing around the origin.
|
|
|
|
*
|
|
|
|
*/
|
2015-07-27 01:17:23 +00:00
|
|
|
struct {
|
2015-07-27 00:35:07 +00:00
|
|
|
|
2015-07-27 01:17:23 +00:00
|
|
|
signed int data_clock_pll; // PLL for data clock recovery.
|
|
|
|
// It is incremented by pll_step_per_sample
|
|
|
|
// for each audio sample.
|
2015-07-27 00:35:07 +00:00
|
|
|
|
2015-07-27 01:17:23 +00:00
|
|
|
signed int prev_d_c_pll; // Previous value of above, before
|
|
|
|
// incrementing, to detect overflows.
|
2015-07-27 00:35:07 +00:00
|
|
|
|
2015-07-27 01:17:23 +00:00
|
|
|
int prev_demod_data; // Previous data bit detected.
|
|
|
|
// Used to look for transitions.
|
2016-07-03 22:09:34 +00:00
|
|
|
float prev_demod_out_f;
|
2015-07-27 00:35:07 +00:00
|
|
|
|
2015-07-27 01:17:23 +00:00
|
|
|
/* This is used only for "9600" baud data. */
|
|
|
|
|
|
|
|
int lfsr; // Descrambler shift register.
|
|
|
|
|
2015-11-29 15:44:30 +00:00
|
|
|
} slicer [MAX_SLICERS]; // Actual number in use is num_slicers.
|
|
|
|
// Should be in range 1 .. MAX_SLICERS,
|
2015-07-27 00:35:07 +00:00
|
|
|
|
2015-07-27 01:05:48 +00:00
|
|
|
/*
|
|
|
|
* Special for Rino decoder only.
|
|
|
|
* One for each possible signal polarity.
|
2015-11-29 15:44:30 +00:00
|
|
|
* The project showed promise but fell by the wayside.
|
2015-07-27 01:05:48 +00:00
|
|
|
*/
|
|
|
|
|
2015-07-27 01:17:23 +00:00
|
|
|
#if 0
|
2015-07-27 01:05:48 +00:00
|
|
|
|
|
|
|
struct gr_state_s {
|
|
|
|
|
|
|
|
signed int data_clock_pll; // PLL for data clock recovery.
|
|
|
|
// It is incremented by pll_step_per_sample
|
|
|
|
// for each audio sample.
|
|
|
|
|
|
|
|
signed int prev_d_c_pll; // Previous value of above, before
|
|
|
|
// incrementing, to detect overflows.
|
|
|
|
|
|
|
|
float gr_minus_peak; // For automatic gain control.
|
|
|
|
float gr_plus_peak;
|
|
|
|
|
|
|
|
int gr_sync; // Is sync pulse present?
|
|
|
|
int gr_prev_sync; // Previous state to detect leading edge.
|
|
|
|
|
|
|
|
int gr_first_sample; // Index of starting sample index for debugging.
|
|
|
|
|
|
|
|
int gr_dcd; // Data carrier detect. i.e. are we
|
|
|
|
// currently decoding a message.
|
|
|
|
|
|
|
|
float gr_early_sum; // For averaging bit values in two regions.
|
|
|
|
int gr_early_count;
|
|
|
|
float gr_late_sum;
|
|
|
|
int gr_late_count;
|
|
|
|
float gr_sync_sum;
|
|
|
|
int gr_sync_count;
|
|
|
|
|
|
|
|
int gr_bit_count; // Bit index into message.
|
|
|
|
|
|
|
|
struct rpack_s rpack; // Collection of bits.
|
|
|
|
|
|
|
|
} gr_state[2];
|
|
|
|
#endif
|
|
|
|
|
2015-07-27 00:35:07 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#define FSK_DEMOD_STATE_H 1
|
|
|
|
#endif
|