mirror of https://github.com/wb2osz/direwolf.git
Clean out old obsolete demodulators.
This commit is contained in:
parent
747224ce57
commit
249f5bd471
|
@ -173,9 +173,6 @@ struct audio_s {
|
||||||
|
|
||||||
int upsample; /* Upsample by this factor for G3RUH. */
|
int upsample; /* Upsample by this factor for G3RUH. */
|
||||||
|
|
||||||
int interleave; /* If > 1, interleave samples among multiple decoders. */
|
|
||||||
/* Quick hack for experiment. */
|
|
||||||
|
|
||||||
int mark_freq; /* Two tones for AFSK modulation, in Hz. */
|
int mark_freq; /* Two tones for AFSK modulation, in Hz. */
|
||||||
int space_freq; /* Standard tones are 1200 and 2200 for 1200 baud. */
|
int space_freq; /* Standard tones are 1200 and 2200 for 1200 baud. */
|
||||||
|
|
||||||
|
|
45
src/demod.c
45
src/demod.c
|
@ -120,7 +120,6 @@ int demod_init (struct audio_s *pa)
|
||||||
* This can be increased by:
|
* This can be increased by:
|
||||||
* Multiple frequencies.
|
* Multiple frequencies.
|
||||||
* Multiple letters (not sure if I will continue this).
|
* Multiple letters (not sure if I will continue this).
|
||||||
* New interleaved decoders.
|
|
||||||
*
|
*
|
||||||
* num_slicers is set to max by the "+" option.
|
* num_slicers is set to max by the "+" option.
|
||||||
*/
|
*/
|
||||||
|
@ -313,48 +312,6 @@ int demod_init (struct audio_s *pa)
|
||||||
|
|
||||||
save_audio_config_p->achan[chan].num_subchan = num_letters;
|
save_audio_config_p->achan[chan].num_subchan = num_letters;
|
||||||
|
|
||||||
/*
|
|
||||||
* Quick hack with special case for another experiment.
|
|
||||||
* Do this in a more general way if it turns out to be useful.
|
|
||||||
*/
|
|
||||||
save_audio_config_p->achan[chan].interleave = 1;
|
|
||||||
if (strcasecmp(save_audio_config_p->achan[chan].profiles, "EE") == 0) {
|
|
||||||
save_audio_config_p->achan[chan].interleave = 2;
|
|
||||||
save_audio_config_p->achan[chan].decimate = 1;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(save_audio_config_p->achan[chan].profiles, "EEE") == 0) {
|
|
||||||
save_audio_config_p->achan[chan].interleave = 3;
|
|
||||||
save_audio_config_p->achan[chan].decimate = 1;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(save_audio_config_p->achan[chan].profiles, "EEEE") == 0) {
|
|
||||||
save_audio_config_p->achan[chan].interleave = 4;
|
|
||||||
save_audio_config_p->achan[chan].decimate = 1;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(save_audio_config_p->achan[chan].profiles, "EEEEE") == 0) {
|
|
||||||
save_audio_config_p->achan[chan].interleave = 5;
|
|
||||||
save_audio_config_p->achan[chan].decimate = 1;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(save_audio_config_p->achan[chan].profiles, "GG") == 0) {
|
|
||||||
save_audio_config_p->achan[chan].interleave = 2;
|
|
||||||
save_audio_config_p->achan[chan].decimate = 1;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(save_audio_config_p->achan[chan].profiles, "GGG") == 0) {
|
|
||||||
save_audio_config_p->achan[chan].interleave = 3;
|
|
||||||
save_audio_config_p->achan[chan].decimate = 1;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(save_audio_config_p->achan[chan].profiles, "GGG+") == 0) {
|
|
||||||
save_audio_config_p->achan[chan].interleave = 3;
|
|
||||||
save_audio_config_p->achan[chan].decimate = 1;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(save_audio_config_p->achan[chan].profiles, "GGGG") == 0) {
|
|
||||||
save_audio_config_p->achan[chan].interleave = 4;
|
|
||||||
save_audio_config_p->achan[chan].decimate = 1;
|
|
||||||
}
|
|
||||||
else if (strcasecmp(save_audio_config_p->achan[chan].profiles, "GGGGG") == 0) {
|
|
||||||
save_audio_config_p->achan[chan].interleave = 5;
|
|
||||||
save_audio_config_p->achan[chan].decimate = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (save_audio_config_p->achan[chan].num_subchan != num_letters) {
|
if (save_audio_config_p->achan[chan].num_subchan != num_letters) {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
dw_printf ("INTERNAL ERROR, %s:%d, chan=%d, num_subchan(%d) != strlen(\"%s\")\n",
|
dw_printf ("INTERNAL ERROR, %s:%d, chan=%d, num_subchan(%d) != strlen(\"%s\")\n",
|
||||||
|
@ -383,7 +340,7 @@ int demod_init (struct audio_s *pa)
|
||||||
dw_printf (" %d.%d: %c %d & %d\n", chan, d, profile, mark, space);
|
dw_printf (" %d.%d: %c %d & %d\n", chan, d, profile, mark, space);
|
||||||
}
|
}
|
||||||
|
|
||||||
demod_afsk_init (save_audio_config_p->adev[ACHAN2ADEV(chan)].samples_per_sec / (save_audio_config_p->achan[chan].decimate * save_audio_config_p->achan[chan].interleave),
|
demod_afsk_init (save_audio_config_p->adev[ACHAN2ADEV(chan)].samples_per_sec / save_audio_config_p->achan[chan].decimate,
|
||||||
save_audio_config_p->achan[chan].baud,
|
save_audio_config_p->achan[chan].baud,
|
||||||
mark,
|
mark,
|
||||||
space,
|
space,
|
||||||
|
|
|
@ -159,12 +159,6 @@ void demod_9600_init (int samples_per_sec, int baud, struct demodulator_state_s
|
||||||
D->pll_locked_inertia = 0.89;
|
D->pll_locked_inertia = 0.89;
|
||||||
D->pll_searching_inertia = 0.67;
|
D->pll_searching_inertia = 0.67;
|
||||||
|
|
||||||
D->play_it_again_sample = 0; // TODO: 1.6 experiment.
|
|
||||||
// assuming lp_filter_size > lp2_filter_size
|
|
||||||
|
|
||||||
D->lp2_filter_size = samples_per_sec / baud; // samples for 1 bit
|
|
||||||
|
|
||||||
|
|
||||||
// break;
|
// break;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
@ -216,12 +210,6 @@ void demod_9600_init (int samples_per_sec, int baud, struct demodulator_state_s
|
||||||
|
|
||||||
(void)gen_lowpass (fc, D->lp_filter, D->lp_filter_size, D->lp_window, 0);
|
(void)gen_lowpass (fc, D->lp_filter, D->lp_filter_size, D->lp_window, 0);
|
||||||
|
|
||||||
// Go back and resample where bit is expected.
|
|
||||||
|
|
||||||
fc = (float)baud * 1 / (float)samples_per_sec;
|
|
||||||
|
|
||||||
(void)gen_lowpass (fc, D->lp2_filter, D->lp2_filter_size, D->lp_window, 0);
|
|
||||||
|
|
||||||
/* Version 1.2: Experiment with different slicing levels. */
|
/* Version 1.2: Experiment with different slicing levels. */
|
||||||
|
|
||||||
for (j = 0; j < MAX_SUBCHANS; j++) {
|
for (j = 0; j < MAX_SUBCHANS; j++) {
|
||||||
|
@ -524,31 +512,7 @@ inline static void nudge_pll (int chan, int subchan, int slice, float demod_out_
|
||||||
|
|
||||||
/* Overflow. Was large positive, wrapped around, now large negative. */
|
/* Overflow. Was large positive, wrapped around, now large negative. */
|
||||||
|
|
||||||
|
hdlc_rec_bit (chan, subchan, slice, demod_out_f > 0, 1, D->slicer[slice].lfsr);
|
||||||
if (D->play_it_again_sample) { // New experiment in 1.6.
|
|
||||||
|
|
||||||
// FIXME: double check position and draw picture.
|
|
||||||
|
|
||||||
int offset = ( D->lp_filter_size - D->lp2_filter_size ) / 2;
|
|
||||||
|
|
||||||
float amp = convolve (D->raw_cb + offset, D->lp2_filter, D->lp2_filter_size);
|
|
||||||
|
|
||||||
int resampled;
|
|
||||||
|
|
||||||
if (D->num_slicers > 1) {
|
|
||||||
resampled = amp - slice_point[slice] > 0;;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
resampled = amp > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
hdlc_rec_bit (chan, subchan, slice, resampled, 1, D->slicer[slice].lfsr);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
|
|
||||||
// traditional
|
|
||||||
hdlc_rec_bit (chan, subchan, slice, demod_out_f > 0, 1, D->slicer[slice].lfsr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
248
src/demod_afsk.c
248
src/demod_afsk.c
|
@ -197,79 +197,6 @@ void demod_afsk_init (int samples_per_sec, int baud, int mark_freq,
|
||||||
|
|
||||||
switch (profile) {
|
switch (profile) {
|
||||||
|
|
||||||
case 'A':
|
|
||||||
|
|
||||||
/* Original. 52 taps, truncated bandpass, IIR lowpass */
|
|
||||||
/* 'F' is the fast version for low end processors. */
|
|
||||||
/* It is a special case that works only for a particular */
|
|
||||||
/* baud rate, tone pair, and sampling rate. */
|
|
||||||
|
|
||||||
D->use_prefilter = 0;
|
|
||||||
|
|
||||||
D->ms_filter_len_bits = 1.415; /* 52 @ 44100, 1200 */
|
|
||||||
D->ms_window = BP_WINDOW_TRUNCATED;
|
|
||||||
|
|
||||||
//D->bp_window = BP_WINDOW_TRUNCATED;
|
|
||||||
|
|
||||||
D->lpf_use_fir = 0;
|
|
||||||
D->lpf_iir = 0.195;
|
|
||||||
|
|
||||||
D->agc_fast_attack = 0.250;
|
|
||||||
D->agc_slow_decay = 0.00012;
|
|
||||||
D->hysteresis = 0.005;
|
|
||||||
|
|
||||||
D->pll_locked_inertia = 0.700;
|
|
||||||
D->pll_searching_inertia = 0.580;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'B':
|
|
||||||
|
|
||||||
/* Original bandpass. Use FIR lowpass instead. */
|
|
||||||
|
|
||||||
D->use_prefilter = 0;
|
|
||||||
|
|
||||||
D->ms_filter_len_bits = 1.415; /* 52 @ 44100, 1200 */
|
|
||||||
D->ms_window = BP_WINDOW_TRUNCATED;
|
|
||||||
|
|
||||||
//D->bp_window = BP_WINDOW_TRUNCATED;
|
|
||||||
|
|
||||||
D->lpf_use_fir = 1;
|
|
||||||
D->lpf_baud = 1.09;
|
|
||||||
D->lp_filter_len_bits = D->ms_filter_len_bits;
|
|
||||||
D->lp_window = BP_WINDOW_TRUNCATED;
|
|
||||||
|
|
||||||
D->agc_fast_attack = 0.370;
|
|
||||||
D->agc_slow_decay = 0.00014;
|
|
||||||
D->hysteresis = 0.003;
|
|
||||||
|
|
||||||
D->pll_locked_inertia = 0.620;
|
|
||||||
D->pll_searching_inertia = 0.350;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'C':
|
|
||||||
|
|
||||||
/* Cosine window, 76 taps for bandpass, FIR lowpass. */
|
|
||||||
|
|
||||||
D->use_prefilter = 0;
|
|
||||||
|
|
||||||
D->ms_filter_len_bits = 2.068; /* 76 @ 44100, 1200 */
|
|
||||||
D->ms_window = BP_WINDOW_COSINE;
|
|
||||||
|
|
||||||
//D->bp_window = BP_WINDOW_COSINE;
|
|
||||||
|
|
||||||
D->lpf_use_fir = 1;
|
|
||||||
D->lpf_baud = 1.09;
|
|
||||||
D->lp_filter_len_bits = D->ms_filter_len_bits;
|
|
||||||
D->lp_window = BP_WINDOW_TRUNCATED;
|
|
||||||
|
|
||||||
D->agc_fast_attack = 0.495;
|
|
||||||
D->agc_slow_decay = 0.00022;
|
|
||||||
D->hysteresis = 0.005;
|
|
||||||
|
|
||||||
D->pll_locked_inertia = 0.620;
|
|
||||||
D->pll_searching_inertia = 0.350;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'D':
|
case 'D':
|
||||||
|
|
||||||
/* Prefilter, Cosine window, FIR lowpass. Tweeked for 300 baud. */
|
/* Prefilter, Cosine window, FIR lowpass. Tweeked for 300 baud. */
|
||||||
|
@ -335,73 +262,6 @@ void demod_afsk_init (int samples_per_sec, int baud, int mark_freq,
|
||||||
D->pll_searching_inertia = 0.50;
|
D->pll_searching_inertia = 0.50;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'G':
|
|
||||||
|
|
||||||
/* 1200 baud - Started out same as E but add 3 way interleave. */
|
|
||||||
/* Version 1.3 - EXPERIMENTAL - Needs more fine tuning. */
|
|
||||||
|
|
||||||
//D->bp_window = BP_WINDOW_COSINE; /* The name says BP but it is used for all of them. */
|
|
||||||
|
|
||||||
D->use_prefilter = 1; /* first, a bandpass filter. */
|
|
||||||
D->prefilter_baud = 0.15;
|
|
||||||
D->pre_filter_len_bits = 128 * 1200. / (44100. / 3.);
|
|
||||||
D->pre_window = BP_WINDOW_TRUNCATED;
|
|
||||||
|
|
||||||
D->ms_filter_len_bits = 25 * 1200. / (44100. / 3.);
|
|
||||||
D->ms_window = BP_WINDOW_COSINE;
|
|
||||||
|
|
||||||
D->lpf_use_fir = 1;
|
|
||||||
D->lpf_baud = 1.16;
|
|
||||||
D->lp_filter_len_bits = 21 * 1200. / (44100. / 3.);
|
|
||||||
D->lp_window = BP_WINDOW_TRUNCATED;
|
|
||||||
|
|
||||||
D->agc_fast_attack = 0.130;
|
|
||||||
D->agc_slow_decay = 0.00013;
|
|
||||||
D->hysteresis = 0.01;
|
|
||||||
|
|
||||||
D->pll_locked_inertia = 0.73;
|
|
||||||
D->pll_searching_inertia = 0.64;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'H':
|
|
||||||
|
|
||||||
/* Experiment in Version 1.6 */
|
|
||||||
/* 1200 baud - Started out as a copy of E but */
|
|
||||||
/* will probably have little tweaks after the */
|
|
||||||
/* major experiment. */
|
|
||||||
/* Enhancements: */
|
|
||||||
/* + Look back and sample the bit position. */
|
|
||||||
/* + Avoid smearing by long filter and low pass. */
|
|
||||||
|
|
||||||
D->use_prefilter = 1; /* first, a bandpass filter. */
|
|
||||||
D->prefilter_baud = 0.21;
|
|
||||||
D->pre_filter_len_bits = 184 * 1200. / 44100.;
|
|
||||||
D->pre_filter_len_bits = 235 * 1200. / 44100.;
|
|
||||||
D->pre_window = BP_WINDOW_TRUNCATED;
|
|
||||||
|
|
||||||
D->ms_filter_len_bits = 65 * 1200. / 44100.; // Just over 2 bit times.
|
|
||||||
D->ms_window = BP_WINDOW_COSINE;
|
|
||||||
|
|
||||||
/* New for synchronous re-demod in 1.6. */
|
|
||||||
D->play_it_again_sample = 1;
|
|
||||||
D->m2_filter_len_bits = 44 * 1200. / 44100.; // a little more than 1 bit time.
|
|
||||||
D->s2_filter_len_bits = 48 * 1200. / 44100.; // a little more than 1 bit time.
|
|
||||||
D->ms2_window = BP_WINDOW_TRUNCATED;
|
|
||||||
D->lp_delay_fract = 0.53; // FIXME: This is backwards.
|
|
||||||
|
|
||||||
D->lpf_use_fir = 1;
|
|
||||||
D->lpf_baud = 1.10;
|
|
||||||
D->lp_filter_len_bits = 64 * 1200. / 44100.;
|
|
||||||
D->lp_window = BP_WINDOW_TRUNCATED;
|
|
||||||
|
|
||||||
D->agc_fast_attack = 0.820;
|
|
||||||
D->agc_slow_decay = 0.000214;
|
|
||||||
D->hysteresis = 0.001;
|
|
||||||
|
|
||||||
D->pll_locked_inertia = 0.765;
|
|
||||||
D->pll_searching_inertia = 0.44;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
@ -457,8 +317,6 @@ void demod_afsk_init (int samples_per_sec, int baud, int mark_freq,
|
||||||
|
|
||||||
D->pre_filter_size = (int) round( D->pre_filter_len_bits * (float)samples_per_sec / (float)baud );
|
D->pre_filter_size = (int) round( D->pre_filter_len_bits * (float)samples_per_sec / (float)baud );
|
||||||
D->ms_filter_size = (int) round( D->ms_filter_len_bits * (float)samples_per_sec / (float)baud );
|
D->ms_filter_size = (int) round( D->ms_filter_len_bits * (float)samples_per_sec / (float)baud );
|
||||||
D->m2_filter_size = (int) round( D->m2_filter_len_bits * (float)samples_per_sec / (float)baud );
|
|
||||||
D->s2_filter_size = (int) round( D->s2_filter_len_bits * (float)samples_per_sec / (float)baud );
|
|
||||||
D->lp_filter_size = (int) round( D->lp_filter_len_bits * (float)samples_per_sec / (float)baud );
|
D->lp_filter_size = (int) round( D->lp_filter_len_bits * (float)samples_per_sec / (float)baud );
|
||||||
|
|
||||||
/* Experiment with other sizes. */
|
/* Experiment with other sizes. */
|
||||||
|
@ -469,12 +327,6 @@ void demod_afsk_init (int samples_per_sec, int baud, int mark_freq,
|
||||||
#ifdef TUNE_MS_FILTER_SIZE
|
#ifdef TUNE_MS_FILTER_SIZE
|
||||||
D->ms_filter_size = TUNE_MS_FILTER_SIZE;
|
D->ms_filter_size = TUNE_MS_FILTER_SIZE;
|
||||||
#endif
|
#endif
|
||||||
#ifdef TUNE_M2_FILTER_SIZE
|
|
||||||
D->m2_filter_size = TUNE_M2_FILTER_SIZE;
|
|
||||||
#endif
|
|
||||||
#ifdef TUNE_S2_FILTER_SIZE
|
|
||||||
D->s2_filter_size = TUNE_S2_FILTER_SIZE;
|
|
||||||
#endif
|
|
||||||
#ifdef TUNE_LP_FILTER_SIZE
|
#ifdef TUNE_LP_FILTER_SIZE
|
||||||
D->lp_filter_size = TUNE_LP_FILTER_SIZE;
|
D->lp_filter_size = TUNE_LP_FILTER_SIZE;
|
||||||
#endif
|
#endif
|
||||||
|
@ -503,24 +355,7 @@ void demod_afsk_init (int samples_per_sec, int baud, int mark_freq,
|
||||||
exit (1);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (D->m2_filter_size * 2 > MAX_FILTER_SIZE)
|
|
||||||
{
|
|
||||||
text_color_set (DW_COLOR_ERROR);
|
|
||||||
dw_printf ("Calculated filter size of %d is too large.\n", D->m2_filter_size);
|
|
||||||
dw_printf ("Decrease the audio sample rate or increase the baud rate or\n");
|
|
||||||
dw_printf ("recompile the application with MAX_FILTER_SIZE larger than %d.\n",
|
|
||||||
MAX_FILTER_SIZE);
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
if (D->s2_filter_size * 2 > MAX_FILTER_SIZE)
|
|
||||||
{
|
|
||||||
text_color_set (DW_COLOR_ERROR);
|
|
||||||
dw_printf ("Calculated filter size of %d is too large.\n", D->s2_filter_size);
|
|
||||||
dw_printf ("Decrease the audio sample rate or increase the baud rate or\n");
|
|
||||||
dw_printf ("recompile the application with MAX_FILTER_SIZE larger than %d.\n",
|
|
||||||
MAX_FILTER_SIZE);
|
|
||||||
exit (1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (D->lp_filter_size > MAX_FILTER_SIZE)
|
if (D->lp_filter_size > MAX_FILTER_SIZE)
|
||||||
{
|
{
|
||||||
|
@ -585,13 +420,6 @@ void demod_afsk_init (int samples_per_sec, int baud, int mark_freq,
|
||||||
|
|
||||||
gen_ms (space_freq, samples_per_sec, D->s_sin_table, D->s_cos_table, D->ms_filter_size, D->ms_window);
|
gen_ms (space_freq, samples_per_sec, D->s_sin_table, D->s_cos_table, D->ms_filter_size, D->ms_window);
|
||||||
|
|
||||||
// Note that these are twice as long so we can try matching different phases.
|
|
||||||
|
|
||||||
if (D->play_it_again_sample) {
|
|
||||||
gen_ms (mark_freq, samples_per_sec, D->m2_sin_table, D->m2_cos_table, D->m2_filter_size * 2, D->ms2_window);
|
|
||||||
gen_ms (space_freq, samples_per_sec, D->s2_sin_table, D->s2_cos_table, D->s2_filter_size * 2, D->ms2_window);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now the lowpass filter.
|
* Now the lowpass filter.
|
||||||
* I thought we'd want a cutoff of about 0.5 the baud rate
|
* I thought we'd want a cutoff of about 0.5 the baud rate
|
||||||
|
@ -764,9 +592,6 @@ void demod_afsk_process_sample (int chan, int subchan, int sam, struct demodulat
|
||||||
// FIXME: calculate how much we really need.
|
// FIXME: calculate how much we really need.
|
||||||
|
|
||||||
int extra = 0;
|
int extra = 0;
|
||||||
if (D->play_it_again_sample) {
|
|
||||||
extra = D->lp_filter_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (D->use_prefilter) {
|
if (D->use_prefilter) {
|
||||||
float cleaner;
|
float cleaner;
|
||||||
|
@ -1015,76 +840,7 @@ inline static void nudge_pll (int chan, int subchan, int slice, int demod_data,
|
||||||
if (D->slicer[slice].data_clock_pll < 0 && D->slicer[slice].prev_d_c_pll > 0) {
|
if (D->slicer[slice].data_clock_pll < 0 && D->slicer[slice].prev_d_c_pll > 0) {
|
||||||
|
|
||||||
/* Overflow. */
|
/* Overflow. */
|
||||||
|
hdlc_rec_bit (chan, subchan, slice, demod_data, 0, -1);
|
||||||
// In version 1.6 we will try a new experiment.
|
|
||||||
// The tone filters are about 2 bit times wide so this smears the signal.
|
|
||||||
// I originally expected this to be about 1 bit time but 2 turned out
|
|
||||||
// to give the best results after extensive experimentation.
|
|
||||||
// We are looking at half of each adjacent bit, not just the one we want.
|
|
||||||
// The low pass filter also smears the signal.
|
|
||||||
//
|
|
||||||
// We will try to look back in time and re-demodulate only the time period of the bit.
|
|
||||||
//
|
|
||||||
|
|
||||||
if (D->play_it_again_sample) { // New in 1.6. Currently 'H' demod profile.
|
|
||||||
|
|
||||||
// FIXME: double check position and draw picture.
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
// This provided a slight benefit.
|
|
||||||
|
|
||||||
int offset = ( D->ms_filter_size - D->m2_filter_size ) / 2 + D->lp_filter_delay;
|
|
||||||
|
|
||||||
float m_sum1 = convolve (D->ms_in_cb + offset, D->m2_sin_table, D->m2_filter_size);
|
|
||||||
float m_sum2 = convolve (D->ms_in_cb + offset, D->m2_cos_table, D->m2_filter_size);
|
|
||||||
float m_amp = sqrtf(m_sum1 * m_sum1 + m_sum2 * m_sum2);
|
|
||||||
|
|
||||||
offset = ( D->ms_filter_size - D->s2_filter_size ) / 2 + D->lp_filter_delay;
|
|
||||||
|
|
||||||
float s_sum1 = convolve (D->ms_in_cb + offset, D->s2_sin_table, D->s2_filter_size);
|
|
||||||
float s_sum2 = convolve (D->ms_in_cb + offset, D->s2_cos_table, D->s2_filter_size);
|
|
||||||
float s_amp = sqrtf(s_sum1 * s_sum1 + s_sum2 * s_sum2);
|
|
||||||
#else
|
|
||||||
// Here we try something completely new.
|
|
||||||
// Rather than taking the vector magnitude of the I+Q components,
|
|
||||||
// correlate it with only a sine wave. We don't know the phase so
|
|
||||||
// we will try matching with a bunch of different phases and take the best match.
|
|
||||||
|
|
||||||
// Trying match with cosine as well could be beneficial for lower sample rates.
|
|
||||||
|
|
||||||
int j;
|
|
||||||
float m_amp = 0;
|
|
||||||
float s_amp = 0;
|
|
||||||
|
|
||||||
int offset = ( D->ms_filter_size - D->m2_filter_size ) / 2 + D->lp_filter_delay;
|
|
||||||
|
|
||||||
for (j = 0; j <= D->m2_filter_size; j++) {
|
|
||||||
float match = fabsf(convolve (D->ms_in_cb + offset, D->m2_sin_table + j, D->m2_filter_size));
|
|
||||||
if (match > m_amp) m_amp = match;
|
|
||||||
}
|
|
||||||
|
|
||||||
offset = ( D->ms_filter_size - D->s2_filter_size ) / 2 + D->lp_filter_delay;
|
|
||||||
|
|
||||||
for (j = 0; j <= D->s2_filter_size; j++) {
|
|
||||||
float match = fabsf(convolve (D->ms_in_cb + offset, D->s2_sin_table + j, D->s2_filter_size));
|
|
||||||
if (match > s_amp) s_amp = match;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int resampled;
|
|
||||||
if (D->num_slicers > 1) {
|
|
||||||
resampled = m_amp > s_amp * space_gain[slice];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
resampled = m_amp > s_amp;
|
|
||||||
}
|
|
||||||
|
|
||||||
hdlc_rec_bit (chan, subchan, slice, resampled, 0, -1);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Traditional way, after the low pass filter.
|
|
||||||
hdlc_rec_bit (chan, subchan, slice, demod_data, 0, -1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Even if we used alternative method to extract the data bit,
|
// Even if we used alternative method to extract the data bit,
|
||||||
|
|
|
@ -33,8 +33,6 @@ struct demodulator_state_s
|
||||||
char profile; // 'A', 'B', etc. Upper case.
|
char profile; // 'A', 'B', etc. Upper case.
|
||||||
// Only needed to see if we are using 'F' to take fast path.
|
// Only needed to see if we are using 'F' to take fast path.
|
||||||
|
|
||||||
int play_it_again_sample; // Enable new synchronous demod in version 1.6.
|
|
||||||
|
|
||||||
#define TICKS_PER_PLL_CYCLE ( 256.0 * 256.0 * 256.0 * 256.0 )
|
#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.
|
int pll_step_per_sample; // PLL is advanced by this much each audio sample.
|
||||||
|
@ -46,13 +44,6 @@ struct demodulator_state_s
|
||||||
/* but about 2 bit times turned out to be better. */
|
/* but about 2 bit times turned out to be better. */
|
||||||
/* Currently using same size for any prefilter. */
|
/* Currently using same size for any prefilter. */
|
||||||
|
|
||||||
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. */
|
|
||||||
|
|
||||||
|
|
||||||
#define MAX_FILTER_SIZE 320 /* 304 is needed for profile C, 300 baud & 44100. */
|
#define MAX_FILTER_SIZE 320 /* 304 is needed for profile C, 300 baud & 44100. */
|
||||||
|
|
||||||
|
@ -61,8 +52,6 @@ struct demodulator_state_s
|
||||||
* e.g. 1 means 1/1200 second for 1200 baud.
|
* e.g. 1 means 1/1200 second for 1200 baud.
|
||||||
*/
|
*/
|
||||||
float ms_filter_len_bits;
|
float ms_filter_len_bits;
|
||||||
float m2_filter_len_bits;
|
|
||||||
float s2_filter_len_bits;
|
|
||||||
float lp_delay_fract;
|
float lp_delay_fract;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -72,7 +61,6 @@ struct demodulator_state_s
|
||||||
bp_window_t pre_window;
|
bp_window_t pre_window;
|
||||||
bp_window_t ms_window;
|
bp_window_t ms_window;
|
||||||
bp_window_t lp_window;
|
bp_window_t lp_window;
|
||||||
bp_window_t ms2_window; /* New in 1.6. */
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -158,17 +146,6 @@ struct demodulator_state_s
|
||||||
float s_sin_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)));
|
float s_cos_table[MAX_FILTER_SIZE] __attribute__((aligned(16)));
|
||||||
|
|
||||||
/*
|
|
||||||
* 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)));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* These are for PSK only.
|
* These are for PSK only.
|
||||||
|
|
|
@ -306,7 +306,6 @@ void multi_modem_process_sample (int chan, int audio_sample)
|
||||||
{
|
{
|
||||||
int d;
|
int d;
|
||||||
int subchan;
|
int subchan;
|
||||||
static int i = 0; /* for interleaving among multiple demodulators. */
|
|
||||||
|
|
||||||
// Accumulate an average DC bias level.
|
// Accumulate an average DC bias level.
|
||||||
// Shouldn't happen with a soundcard but could with mistuned SDR.
|
// Shouldn't happen with a soundcard but could with mistuned SDR.
|
||||||
|
@ -334,21 +333,9 @@ void multi_modem_process_sample (int chan, int audio_sample)
|
||||||
/* Formerly one loop. */
|
/* Formerly one loop. */
|
||||||
/* 1.2: We can feed one demodulator but end up with multiple outputs. */
|
/* 1.2: We can feed one demodulator but end up with multiple outputs. */
|
||||||
|
|
||||||
|
/* Send same thing to all. */
|
||||||
if (save_audio_config_p->achan[chan].interleave > 1) {
|
for (d = 0; d < save_audio_config_p->achan[chan].num_subchan; d++) {
|
||||||
|
demod_process_sample(chan, d, audio_sample);
|
||||||
// TODO: temp debug, remove this.
|
|
||||||
|
|
||||||
assert (save_audio_config_p->achan[chan].interleave == save_audio_config_p->achan[chan].num_subchan);
|
|
||||||
demod_process_sample(chan, i, audio_sample);
|
|
||||||
i++;
|
|
||||||
if (i >= save_audio_config_p->achan[chan].interleave) i = 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
/* Send same thing to all. */
|
|
||||||
for (d = 0; d < save_audio_config_p->achan[chan].num_subchan; d++) {
|
|
||||||
demod_process_sample(chan, d, audio_sample);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (subchan = 0; subchan < save_audio_config_p->achan[chan].num_subchan; subchan++) {
|
for (subchan = 0; subchan < save_audio_config_p->achan[chan].num_subchan; subchan++) {
|
||||||
|
|
Loading…
Reference in New Issue