mirror of https://github.com/wb2osz/direwolf.git
Issue 271 - DCD dropping at wrong time.
This commit is contained in:
parent
74a5c34a94
commit
0661e23f21
45
src/atest.c
45
src/atest.c
|
@ -82,7 +82,7 @@
|
||||||
#include "ptt.h"
|
#include "ptt.h"
|
||||||
#include "dtime_now.h"
|
#include "dtime_now.h"
|
||||||
#include "fx25.h"
|
#include "fx25.h"
|
||||||
|
#include "hdlc_rec.h"
|
||||||
|
|
||||||
|
|
||||||
#if 0 /* Typical but not flexible enough. */
|
#if 0 /* Typical but not flexible enough. */
|
||||||
|
@ -188,6 +188,9 @@ static int J_opt = 0; /* 2400 bps PSK compatible MFJ-2400 and maybe others. */
|
||||||
static int h_opt = 0; // Hexadecimal display of received packet.
|
static int h_opt = 0; // Hexadecimal display of received packet.
|
||||||
static char P_opt[16] = ""; // Demodulator profiles.
|
static char P_opt[16] = ""; // Demodulator profiles.
|
||||||
static int d_x_opt = 1; // FX.25 debug.
|
static int d_x_opt = 1; // FX.25 debug.
|
||||||
|
static int d_o_opt = 0; // "-d o" option for DCD output control. */
|
||||||
|
static int dcd_count = 0;
|
||||||
|
static int dcd_missing_errors = 0;
|
||||||
|
|
||||||
|
|
||||||
int main (int argc, char *argv[])
|
int main (int argc, char *argv[])
|
||||||
|
@ -382,6 +385,7 @@ int main (int argc, char *argv[])
|
||||||
for (char *p=optarg; *p!='\0'; p++) {
|
for (char *p=optarg; *p!='\0'; p++) {
|
||||||
switch (*p) {
|
switch (*p) {
|
||||||
case 'x': d_x_opt++; break; // FX.25
|
case 'x': d_x_opt++; break; // FX.25
|
||||||
|
case 'o': d_o_opt++; break; // DCD output control
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -686,6 +690,10 @@ int main (int argc, char *argv[])
|
||||||
elapsed = dtime_now() - start_time;
|
elapsed = dtime_now() - start_time;
|
||||||
|
|
||||||
dw_printf ("%d packets decoded in %.3f seconds. %.1f x realtime\n", packets_decoded_total, elapsed, total_filetime/elapsed);
|
dw_printf ("%d packets decoded in %.3f seconds. %.1f x realtime\n", packets_decoded_total, elapsed, total_filetime/elapsed);
|
||||||
|
if (d_o_opt) {
|
||||||
|
dw_printf ("DCD count = %d\n", dcd_count);
|
||||||
|
dw_printf ("DCD missing erors = %d\n", dcd_missing_errors);
|
||||||
|
}
|
||||||
|
|
||||||
if (error_if_less_than != -1 && packets_decoded_total < error_if_less_than) {
|
if (error_if_less_than != -1 && packets_decoded_total < error_if_less_than) {
|
||||||
text_color_set(DW_COLOR_ERROR);
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
@ -744,6 +752,7 @@ void dlq_rec_frame (int chan, int subchan, int slice, packet_t pp, alevel_t alev
|
||||||
char alevel_text[AX25_ALEVEL_TO_TEXT_SIZE];
|
char alevel_text[AX25_ALEVEL_TO_TEXT_SIZE];
|
||||||
|
|
||||||
packets_decoded_one++;
|
packets_decoded_one++;
|
||||||
|
if ( ! hdlc_rec_data_detect_any(chan)) dcd_missing_errors++;
|
||||||
|
|
||||||
ax25_format_addrs (pp, stemp);
|
ax25_format_addrs (pp, stemp);
|
||||||
|
|
||||||
|
@ -777,7 +786,7 @@ void dlq_rec_frame (int chan, int subchan, int slice, packet_t pp, alevel_t alev
|
||||||
int min = (int)(sec / 60.);
|
int min = (int)(sec / 60.);
|
||||||
sec -= min * 60;
|
sec -= min * 60;
|
||||||
|
|
||||||
dw_printf ("%d:%07.4f ", min, sec);
|
dw_printf ("%d:%06.3f ", min, sec);
|
||||||
|
|
||||||
if (h != AX25_SOURCE) {
|
if (h != AX25_SOURCE) {
|
||||||
dw_printf ("Digipeater ");
|
dw_printf ("Digipeater ");
|
||||||
|
@ -876,6 +885,38 @@ void dlq_rec_frame (int chan, int subchan, int slice, packet_t pp, alevel_t alev
|
||||||
|
|
||||||
void ptt_set (int ot, int chan, int ptt_signal)
|
void ptt_set (int ot, int chan, int ptt_signal)
|
||||||
{
|
{
|
||||||
|
// Should only get here for DCD output control.
|
||||||
|
static double dcd_start_time[MAX_CHANS];
|
||||||
|
|
||||||
|
if (d_o_opt) {
|
||||||
|
double t = (double)sample_number / my_audio_config.adev[0].samples_per_sec;
|
||||||
|
double sec1, sec2;
|
||||||
|
int min1, min2;
|
||||||
|
|
||||||
|
text_color_set(DW_COLOR_INFO);
|
||||||
|
|
||||||
|
if (ptt_signal) {
|
||||||
|
//sec1 = t;
|
||||||
|
//min1 = (int)(sec1 / 60.);
|
||||||
|
//sec1 -= min1 * 60;
|
||||||
|
//dw_printf ("DCD[%d] = ON %d:%06.3f\n", chan, min1, sec1);
|
||||||
|
dcd_count++;
|
||||||
|
dcd_start_time[chan] = t;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//dw_printf ("DCD[%d] = off %d:%06.3f %3.0f\n", chan, min, sec, (t - dcd_start_time[chan]) * 1000.);
|
||||||
|
|
||||||
|
sec1 = dcd_start_time[chan];
|
||||||
|
min1 = (int)(sec1 / 60.);
|
||||||
|
sec1 -= min1 * 60;
|
||||||
|
|
||||||
|
sec2 = t;
|
||||||
|
min2 = (int)(sec2 / 60.);
|
||||||
|
sec2 -= min2 * 60;
|
||||||
|
|
||||||
|
dw_printf ("DCD[%d] %d:%06.3f - %d:%06.3f = %3.0f\n", chan, min1, sec1, min2, sec2, (t - dcd_start_time[chan]) * 1000.);
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,14 +44,24 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
// Fine tuning for different demodulator types.
|
||||||
|
|
||||||
|
#define DCD_THRESH_ON 32 // Hysteresis: Can miss 0 out of 32 for detecting lock.
|
||||||
|
// This is best for actual on-the-air signals.
|
||||||
|
// Still too many brief false matches.
|
||||||
|
#define DCD_THRESH_OFF 8 // Might want a little more fine tuning.
|
||||||
|
#define DCD_GOOD_WIDTH 1024 // No more than 1024!!!
|
||||||
|
#include "fsk_demod_state.h" // Values above override defaults.
|
||||||
|
|
||||||
#include "tune.h"
|
#include "tune.h"
|
||||||
#include "fsk_demod_state.h"
|
|
||||||
#include "hdlc_rec.h"
|
#include "hdlc_rec.h"
|
||||||
#include "demod_9600.h"
|
#include "demod_9600.h"
|
||||||
#include "textcolor.h"
|
#include "textcolor.h"
|
||||||
#include "dsp.h"
|
#include "dsp.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static float slice_point[MAX_SUBCHANS];
|
static float slice_point[MAX_SUBCHANS];
|
||||||
|
|
||||||
|
|
||||||
|
@ -407,7 +417,7 @@ void demod_9600_process_sample (int chan, int sam, struct demodulator_state_s *D
|
||||||
if (chan == 0) {
|
if (chan == 0) {
|
||||||
|
|
||||||
if (1) {
|
if (1) {
|
||||||
//if (hdlc_rec_gathering (chan, subchan, slice)) {
|
//if (D->slicer[slice].data_detect) {
|
||||||
char fname[30];
|
char fname[30];
|
||||||
int slice = 0;
|
int slice = 0;
|
||||||
|
|
||||||
|
@ -516,6 +526,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, D->modem_type == MODEM_SCRAMBLE, D->slicer[slice].lfsr);
|
hdlc_rec_bit (chan, subchan, slice, demod_out_f > 0, D->modem_type == MODEM_SCRAMBLE, D->slicer[slice].lfsr);
|
||||||
|
pll_dcd_each_symbol2 (D, chan, subchan, slice);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -526,11 +537,11 @@ inline static void nudge_pll (int chan, int subchan, int slice, float demod_out_
|
||||||
|
|
||||||
// Note: Test for this demodulator, not overall for channel.
|
// Note: Test for this demodulator, not overall for channel.
|
||||||
|
|
||||||
float target = 0;
|
pll_dcd_signal_transition2 (D, slice, D->slicer[slice].data_clock_pll);
|
||||||
|
|
||||||
target = D->pll_step_per_sample * demod_out_f / (demod_out_f - D->slicer[slice].prev_demod_out_f);
|
float target = D->pll_step_per_sample * demod_out_f / (demod_out_f - D->slicer[slice].prev_demod_out_f);
|
||||||
|
|
||||||
if (hdlc_rec_gathering (chan, subchan, slice)) {
|
if (D->slicer[slice].data_detect) {
|
||||||
D->slicer[slice].data_clock_pll = (int)(D->slicer[slice].data_clock_pll * D->pll_locked_inertia + target * (1.0f - D->pll_locked_inertia) );
|
D->slicer[slice].data_clock_pll = (int)(D->slicer[slice].data_clock_pll * D->pll_locked_inertia + target * (1.0f - D->pll_locked_inertia) );
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -542,7 +553,7 @@ inline static void nudge_pll (int chan, int subchan, int slice, float demod_out_
|
||||||
#if DEBUG5
|
#if DEBUG5
|
||||||
|
|
||||||
//if (chan == 0) {
|
//if (chan == 0) {
|
||||||
if (hdlc_rec_gathering (chan,subchan,slice)) {
|
if (D->slicer[slice].data_detect) {
|
||||||
|
|
||||||
char fname[30];
|
char fname[30];
|
||||||
|
|
||||||
|
|
|
@ -762,7 +762,7 @@ void demod_afsk_process_sample (int chan, int subchan, int sam, struct demodulat
|
||||||
#if DEBUG4
|
#if DEBUG4
|
||||||
|
|
||||||
if (chan == 0) {
|
if (chan == 0) {
|
||||||
if (hdlc_rec_gathering (chan, subchan)) {
|
if (D->slicer[slice].data_detect) {
|
||||||
char fname[30];
|
char fname[30];
|
||||||
|
|
||||||
|
|
||||||
|
@ -839,16 +839,18 @@ 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 - this is where we sample. */
|
||||||
hdlc_rec_bit (chan, subchan, slice, demod_data, 0, -1);
|
hdlc_rec_bit (chan, subchan, slice, demod_data, 0, -1);
|
||||||
|
pll_dcd_each_symbol2 (D, chan, subchan, slice);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Even if we used alternative method to extract the data bit,
|
// Transitions nudge the DPLL phase toward the incoming signal.
|
||||||
// we still use the low pass output for the PLL.
|
|
||||||
|
|
||||||
if (demod_data != D->slicer[slice].prev_demod_data) {
|
if (demod_data != D->slicer[slice].prev_demod_data) {
|
||||||
|
|
||||||
if (hdlc_rec_gathering (chan, subchan, slice)) {
|
pll_dcd_signal_transition2 (D, slice, D->slicer[slice].data_clock_pll);
|
||||||
|
|
||||||
|
if (D->slicer[slice].data_detect) {
|
||||||
D->slicer[slice].data_clock_pll = (int)(D->slicer[slice].data_clock_pll * D->pll_locked_inertia);
|
D->slicer[slice].data_clock_pll = (int)(D->slicer[slice].data_clock_pll * D->pll_locked_inertia);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -86,16 +86,25 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
// Fine tuning for different demodulator types.
|
||||||
|
|
||||||
|
#define DCD_THRESH_ON 30 // Hysteresis: Can miss 2 out of 32 for detecting lock.
|
||||||
|
#define DCD_THRESH_OFF 6 // Might want a little more fine tuning.
|
||||||
|
#define DCD_GOOD_WIDTH 512
|
||||||
|
#include "fsk_demod_state.h" // Values above override defaults.
|
||||||
|
|
||||||
#include "audio.h"
|
#include "audio.h"
|
||||||
#include "tune.h"
|
#include "tune.h"
|
||||||
#include "fsk_demod_state.h"
|
|
||||||
#include "fsk_gen_filter.h"
|
#include "fsk_gen_filter.h"
|
||||||
#include "hdlc_rec.h"
|
#include "hdlc_rec.h"
|
||||||
#include "textcolor.h"
|
#include "textcolor.h"
|
||||||
#include "demod_psk.h"
|
#include "demod_psk.h"
|
||||||
#include "dsp.h"
|
#include "dsp.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static const int phase_to_gray_v26[4] = {0, 1, 3, 2};
|
static const int phase_to_gray_v26[4] = {0, 1, 3, 2};
|
||||||
static const int phase_to_gray_v27[8] = {1, 0, 2, 3, 7, 6, 4, 5};
|
static const int phase_to_gray_v27[8] = {1, 0, 2, 3, 7, 6, 4, 5};
|
||||||
|
|
||||||
|
@ -800,6 +809,7 @@ static void nudge_pll (int chan, int subchan, int slice, int demod_bits, struct
|
||||||
hdlc_rec_bit (chan, subchan, slice, (gray >> 1) & 1, 0, bit_quality[1]);
|
hdlc_rec_bit (chan, subchan, slice, (gray >> 1) & 1, 0, bit_quality[1]);
|
||||||
hdlc_rec_bit (chan, subchan, slice, gray & 1, 0, bit_quality[0]);
|
hdlc_rec_bit (chan, subchan, slice, gray & 1, 0, bit_quality[0]);
|
||||||
}
|
}
|
||||||
|
pll_dcd_each_symbol2 (D, chan, subchan, slice);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -813,7 +823,9 @@ static void nudge_pll (int chan, int subchan, int slice, int demod_bits, struct
|
||||||
|
|
||||||
if (demod_bits != D->slicer[slice].prev_demod_data) {
|
if (demod_bits != D->slicer[slice].prev_demod_data) {
|
||||||
|
|
||||||
if (hdlc_rec_gathering (chan, subchan, slice)) {
|
pll_dcd_signal_transition2 (D, slice, D->slicer[slice].data_clock_pll);
|
||||||
|
|
||||||
|
if (D->slicer[slice].data_detect) {
|
||||||
D->slicer[slice].data_clock_pll = (int)floorf((float)(D->slicer[slice].data_clock_pll) * D->pll_locked_inertia);
|
D->slicer[slice].data_clock_pll = (int)floorf((float)(D->slicer[slice].data_clock_pll) * D->pll_locked_inertia);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
|
@ -226,6 +226,8 @@ struct demodulator_state_s
|
||||||
signed int data_clock_pll; // PLL for data clock recovery.
|
signed int data_clock_pll; // PLL for data clock recovery.
|
||||||
// It is incremented by pll_step_per_sample
|
// It is incremented by pll_step_per_sample
|
||||||
// for each audio sample.
|
// for each audio sample.
|
||||||
|
// Must be 32 bits!!!
|
||||||
|
// So far, this is the case for every compiler used.
|
||||||
|
|
||||||
signed int prev_d_c_pll; // Previous value of above, before
|
signed int prev_d_c_pll; // Previous value of above, before
|
||||||
// incrementing, to detect overflows.
|
// incrementing, to detect overflows.
|
||||||
|
@ -238,6 +240,18 @@ struct demodulator_state_s
|
||||||
|
|
||||||
int lfsr; // Descrambler shift register.
|
int lfsr; // Descrambler shift register.
|
||||||
|
|
||||||
|
// This is for detecting phase lock to incoming signal.
|
||||||
|
|
||||||
|
int good_flag; // Set if transition is near where expected,
|
||||||
|
// i.e. at a good time.
|
||||||
|
int bad_flag; // Set if transition is not where expected,
|
||||||
|
// i.e. at a bad time.
|
||||||
|
unsigned char good_hist; // History of good transitions for past octet.
|
||||||
|
unsigned char bad_hist; // History of bad transitions for past octet.
|
||||||
|
unsigned int score; // History of whether good triumphs over bad
|
||||||
|
// for past 32 symbols.
|
||||||
|
int data_detect; // True when locked on to signal.
|
||||||
|
|
||||||
} slicer [MAX_SLICERS]; // Actual number in use is num_slicers.
|
} slicer [MAX_SLICERS]; // Actual number in use is num_slicers.
|
||||||
// Should be in range 1 .. MAX_SLICERS,
|
// Should be in range 1 .. MAX_SLICERS,
|
||||||
/*
|
/*
|
||||||
|
@ -336,5 +350,100 @@ struct demodulator_state_s
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*-------------------------------------------------------------------
|
||||||
|
*
|
||||||
|
* Name: pll_dcd_signal_transition2
|
||||||
|
* dcd_each_symbol2
|
||||||
|
*
|
||||||
|
* Purpose: New DCD strategy for 1.6.
|
||||||
|
*
|
||||||
|
* Inputs: D Pointer to demodulator state.
|
||||||
|
*
|
||||||
|
* chan Radio channel: 0 to MAX_CHANS - 1
|
||||||
|
*
|
||||||
|
* subchan Which of multiple demodulators: 0 to MAX_SUBCHANS - 1
|
||||||
|
*
|
||||||
|
* slice Slicer number: 0 to MAX_SLICERS - 1.
|
||||||
|
*
|
||||||
|
* dpll_phase Signed 32 bit counter for DPLL phase.
|
||||||
|
* Wraparound is where data is sampled.
|
||||||
|
* Ideally transitions would occur close to 0.
|
||||||
|
*
|
||||||
|
* Output: D->slicer[slice].data_detect - true when PLL is locked to incoming signal.
|
||||||
|
*
|
||||||
|
* Description: From the beginning, DCD was based on finding several flag octets
|
||||||
|
* in a row and dropping when eight bits with no transitions.
|
||||||
|
* It was less than ideal but we limped along with it all these years.
|
||||||
|
* This fell apart when FX.25 came along and a couple of the
|
||||||
|
* correlation tags have eight "1" bits in a row.
|
||||||
|
*
|
||||||
|
* Our new strategy is to keep a running score of how well demodulator
|
||||||
|
* output transitions match to where expected.
|
||||||
|
*
|
||||||
|
*--------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "hdlc_rec.h" // for dcd_change
|
||||||
|
|
||||||
|
// These are good for 1200 bps AFSK.
|
||||||
|
// Might want to override for other modems.
|
||||||
|
|
||||||
|
#ifndef DCD_THRESH_ON
|
||||||
|
#define DCD_THRESH_ON 30 // Hysteresis: Can miss 2 out of 32 for detecting lock.
|
||||||
|
// 31 is best for TNC Test CD. 30 almost as good.
|
||||||
|
// 30 better for 1200 regression test.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DCD_THRESH_OFF
|
||||||
|
#define DCD_THRESH_OFF 6 // Might want a little more fine tuning.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DCD_GOOD_WIDTH
|
||||||
|
#define DCD_GOOD_WIDTH 512 // No more than 1024!!!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
__attribute__((always_inline))
|
||||||
|
inline static void pll_dcd_signal_transition2 (struct demodulator_state_s *D, int slice, int dpll_phase)
|
||||||
|
{
|
||||||
|
if (dpll_phase > - DCD_GOOD_WIDTH * 1024 * 1024 && dpll_phase < DCD_GOOD_WIDTH * 1024 * 1024) {
|
||||||
|
D->slicer[slice].good_flag = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
D->slicer[slice].bad_flag = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__attribute__((always_inline))
|
||||||
|
inline static void pll_dcd_each_symbol2 (struct demodulator_state_s *D, int chan, int subchan, int slice)
|
||||||
|
{
|
||||||
|
D->slicer[slice].good_hist <<= 1;
|
||||||
|
D->slicer[slice].good_hist |= D->slicer[slice].good_flag;
|
||||||
|
D->slicer[slice].good_flag = 0;
|
||||||
|
|
||||||
|
D->slicer[slice].bad_hist <<= 1;
|
||||||
|
D->slicer[slice].bad_hist |= D->slicer[slice].bad_flag;
|
||||||
|
D->slicer[slice].bad_flag = 0;
|
||||||
|
|
||||||
|
D->slicer[slice].score <<= 1;
|
||||||
|
// 2 is to detect 'flag' patterns with 2 transitions per octet.
|
||||||
|
D->slicer[slice].score |= (signed)__builtin_popcount(D->slicer[slice].good_hist)
|
||||||
|
- (signed)__builtin_popcount(D->slicer[slice].bad_hist) >= 2;
|
||||||
|
|
||||||
|
int s = __builtin_popcount(D->slicer[slice].score);
|
||||||
|
if (s >= DCD_THRESH_ON) {
|
||||||
|
if (D->slicer[slice].data_detect == 0) {
|
||||||
|
D->slicer[slice].data_detect = 1;
|
||||||
|
dcd_change (chan, subchan, slice, D->slicer[slice].data_detect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (s <= DCD_THRESH_OFF) {
|
||||||
|
if (D->slicer[slice].data_detect != 0) {
|
||||||
|
D->slicer[slice].data_detect = 0;
|
||||||
|
dcd_change (chan, subchan, slice, D->slicer[slice].data_detect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#define FSK_DEMOD_STATE_H 1
|
#define FSK_DEMOD_STATE_H 1
|
||||||
#endif
|
#endif
|
|
@ -117,6 +117,11 @@ static void send_packet (char *str)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pp = ax25_from_text (str, 1);
|
pp = ax25_from_text (str, 1);
|
||||||
|
if (pp == NULL) {
|
||||||
|
text_color_set(DW_COLOR_ERROR);
|
||||||
|
dw_printf ("\"%s\" is not valid TNC2 monitoring format.\n", str);
|
||||||
|
return;
|
||||||
|
}
|
||||||
flen = ax25_pack (pp, fbuf);
|
flen = ax25_pack (pp, fbuf);
|
||||||
for (c=0; c<modem.adev[0].num_channels; c++)
|
for (c=0; c<modem.adev[0].num_channels; c++)
|
||||||
{
|
{
|
||||||
|
@ -124,8 +129,7 @@ static void send_packet (char *str)
|
||||||
#if 1
|
#if 1
|
||||||
int samples_per_symbol, n, j;
|
int samples_per_symbol, n, j;
|
||||||
|
|
||||||
/* Insert random amount of quiet time, approx. 0 to 10 symbol times, to test */
|
// Insert random amount of quiet time.
|
||||||
/* how well the clock recovery PLL can regain lock after random phase shifts. */
|
|
||||||
|
|
||||||
if (modem.achan[c].modem_type == MODEM_QPSK) {
|
if (modem.achan[c].modem_type == MODEM_QPSK) {
|
||||||
samples_per_symbol = modem.adev[0].samples_per_sec / (modem.achan[c].baud / 2);
|
samples_per_symbol = modem.adev[0].samples_per_sec / (modem.achan[c].baud / 2);
|
||||||
|
@ -137,14 +141,19 @@ static void send_packet (char *str)
|
||||||
samples_per_symbol = modem.adev[0].samples_per_sec / modem.achan[c].baud;
|
samples_per_symbol = modem.adev[0].samples_per_sec / modem.achan[c].baud;
|
||||||
}
|
}
|
||||||
|
|
||||||
// for 1200 baud, 44100/sec, this should be 0 to 360.
|
// Provide enough time for the DCD to drop.
|
||||||
n = samples_per_symbol * 10 * (float)my_rand() / (float)MY_RAND_MAX;
|
// Then throw in a random amount of time so that receiving
|
||||||
|
// DPLL will need to adjust to a new phase.
|
||||||
|
|
||||||
|
n = samples_per_symbol * (32 + (float)my_rand() / (float)MY_RAND_MAX );
|
||||||
|
|
||||||
//dw_printf ("Random 0-360 = %d\n", n);
|
|
||||||
for (j=0; j<n; j++) {
|
for (j=0; j<n; j++) {
|
||||||
gen_tone_put_sample (c, 0, 0);
|
gen_tone_put_sample (c, 0, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
hdlc_send_flags (c, 8, 0);
|
||||||
|
hdlc_send_flags (c, 8, 0);
|
||||||
|
hdlc_send_flags (c, 8, 0);
|
||||||
hdlc_send_flags (c, 8, 0);
|
hdlc_send_flags (c, 8, 0);
|
||||||
hdlc_send_frame (c, fbuf, flen, 0, modem.fx25_xmit_enable);
|
hdlc_send_frame (c, fbuf, flen, 0, modem.fx25_xmit_enable);
|
||||||
hdlc_send_flags (c, 2, 1);
|
hdlc_send_flags (c, 2, 1);
|
||||||
|
|
139
src/hdlc_rec.c
139
src/hdlc_rec.c
|
@ -101,10 +101,6 @@ struct hdlc_state_s {
|
||||||
int frame_len; /* Number of octets in frame_buf. */
|
int frame_len; /* Number of octets in frame_buf. */
|
||||||
/* Should be in range of 0 .. MAX_FRAME_LEN. */
|
/* Should be in range of 0 .. MAX_FRAME_LEN. */
|
||||||
|
|
||||||
int data_detect; /* True when HDLC data is detected. */
|
|
||||||
/* This will not be triggered by voice or other */
|
|
||||||
/* noise or even tones. */
|
|
||||||
|
|
||||||
rrbb_t rrbb; /* Handle for bit array for raw received bits. */
|
rrbb_t rrbb; /* Handle for bit array for raw received bits. */
|
||||||
|
|
||||||
};
|
};
|
||||||
|
@ -130,6 +126,7 @@ static int was_init = 0;
|
||||||
|
|
||||||
static struct audio_s *g_audio_p;
|
static struct audio_s *g_audio_p;
|
||||||
|
|
||||||
|
|
||||||
void hdlc_rec_init (struct audio_s *pa)
|
void hdlc_rec_init (struct audio_s *pa)
|
||||||
{
|
{
|
||||||
int ch, sub, slice;
|
int ch, sub, slice;
|
||||||
|
@ -203,6 +200,7 @@ static int my_rand (void) {
|
||||||
* is_scrambled - Is the data scrambled?
|
* is_scrambled - Is the data scrambled?
|
||||||
*
|
*
|
||||||
* descram_state - Current descrambler state. (not used - remove)
|
* descram_state - Current descrambler state. (not used - remove)
|
||||||
|
* Not so fast - plans to add new parameter. PSK already provides it.
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* Description: This is called once for each received bit.
|
* Description: This is called once for each received bit.
|
||||||
|
@ -285,94 +283,6 @@ void hdlc_rec_bit (int chan, int subchan, int slice, int raw, int is_scrambled,
|
||||||
H->flag4_det |= 0x80000000;
|
H->flag4_det |= 0x80000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* "Data Carrier detect" function based on data patterns rather than
|
|
||||||
* audio signal strength.
|
|
||||||
*
|
|
||||||
* Idle time, at beginning of transmission should be filled
|
|
||||||
* with the special "flag" characters.
|
|
||||||
*
|
|
||||||
* Idle time of all zero bits (alternating tones at maximum rate)
|
|
||||||
* has also been observed rarely. It is easy to understand the reasoning.
|
|
||||||
* The tones alternate at the maximum rate, making it symmetrical and providing
|
|
||||||
* the most opportunity for the PLL to lock on to the edges.
|
|
||||||
* It also violates the published protocol spec.
|
|
||||||
*
|
|
||||||
* Recognize zero(s) followed by a single flag even though it violates the spec.
|
|
||||||
*
|
|
||||||
* It has been reported that the TinyTrak4 does this.
|
|
||||||
* https://groups.yahoo.com/neo/groups/direwolf_packet/conversations/messages/1207
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Originally, this looked for 4 flags in a row or 3 zeros and a flag.
|
|
||||||
* Is that too fussy?
|
|
||||||
* Here are the numbers of start of DCD for our favorite Track 2 test.
|
|
||||||
*
|
|
||||||
* 7e7e7e7e 504 7e000000 32
|
|
||||||
* 7e7e7e-- 513 7e0000-- 33
|
|
||||||
* 7e7e---- 555 7e00---- 42
|
|
||||||
* 7e------ 2088
|
|
||||||
*
|
|
||||||
* I don't think we want to look for a single flag because that would
|
|
||||||
* make DCD too sensitive to noise and it would interfere with waiting for a
|
|
||||||
* clear channel to transmit. Even a two byte match causes a lot of flickering
|
|
||||||
* when listening to live signals. Let's try 3 and see how that works out.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
//if (H->flag4_det == 0x7e7e7e7e) {
|
|
||||||
if ((H->flag4_det & 0xffffff00) == 0x7e7e7e00) { // three seems good
|
|
||||||
//if ((H->flag4_det & 0xffff0000) == 0x7e7e0000) { // two in a row
|
|
||||||
//if ((H->flag4_det & 0xff000000) == 0x7e000000) { // single flag
|
|
||||||
if ( ! H->data_detect) {
|
|
||||||
H->data_detect = 1;
|
|
||||||
dcd_change (chan, subchan, slice, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//else if (H->flag4_det == 0x7e000000) {
|
|
||||||
else if ((H->flag4_det & 0xffffff00) == 0x7e000000) {
|
|
||||||
//else if ((H->flag4_det & 0xffff0000) == 0x7e000000) {
|
|
||||||
|
|
||||||
if ( ! H->data_detect) {
|
|
||||||
H->data_detect = 1;
|
|
||||||
dcd_change (chan, subchan, slice, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Loss of signal should result in lack of transitions.
|
|
||||||
* (all '1' bits) for at least a little while.
|
|
||||||
*
|
|
||||||
* When this was written, I was only concerned about 1200 baud.
|
|
||||||
* For 9600, added later, there is a (de)scrambling function.
|
|
||||||
* So if there is no change in the signal, we would get pseudo random bits here.
|
|
||||||
* Maybe we need to put in another check earlier so DCD is not held on too long
|
|
||||||
* after loss of signal for 9600.
|
|
||||||
* No, that would not be a good idea. part of a valid frame, when scrambled,
|
|
||||||
* could have seven or more "1" bits in a row.
|
|
||||||
* Needs more study.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
if (H->pat_det == 0xff) {
|
|
||||||
|
|
||||||
if ( H->data_detect ) {
|
|
||||||
H->data_detect = 0;
|
|
||||||
dcd_change (chan, subchan, slice, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* End of data carrier detect.
|
|
||||||
*
|
|
||||||
* The rest is concerned with framing.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
rrbb_append_bit (H->rrbb, raw);
|
rrbb_append_bit (H->rrbb, raw);
|
||||||
|
|
||||||
if (H->pat_det == 0x7e) {
|
if (H->pat_det == 0x7e) {
|
||||||
|
@ -554,47 +464,10 @@ void hdlc_rec_bit (int chan, int subchan, int slice, int raw, int is_scrambled,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Data Carrier Detect (DCD) is now based on DPLL lock
|
||||||
|
// rather than data patterns found here.
|
||||||
/*-------------------------------------------------------------------
|
// It would make sense to move the next 2 functions to demod.c
|
||||||
*
|
// because this is done at the modem level, rather than HDLC decoder.
|
||||||
* Name: hdlc_rec_gathering
|
|
||||||
*
|
|
||||||
* Purpose: Report whether bits are currently being gathered into a frame.
|
|
||||||
* This is used to influence the PLL inertia.
|
|
||||||
* The idea is that the PLL should be a little more agreeable to
|
|
||||||
* synchronize with the incoming data stream when not in a frame
|
|
||||||
* and resist changing a little more when capturing a frame.
|
|
||||||
*
|
|
||||||
* Inputs: chan
|
|
||||||
* subchan
|
|
||||||
* slice
|
|
||||||
*
|
|
||||||
* Returns: True if we are currently gathering bits.
|
|
||||||
* In this case we want the PLL to have more inertia.
|
|
||||||
*
|
|
||||||
* Discussion: This simply returns the data carrier detect state.
|
|
||||||
* A couple other variations were tried but turned out to
|
|
||||||
* be slightly worse.
|
|
||||||
*
|
|
||||||
*--------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
int hdlc_rec_gathering (int chan, int subchan, int slice)
|
|
||||||
{
|
|
||||||
assert (chan >= 0 && chan < MAX_CHANS);
|
|
||||||
assert (subchan >= 0 && subchan < MAX_SUBCHANS);
|
|
||||||
assert (slice >= 0 && slice < MAX_SLICERS);
|
|
||||||
|
|
||||||
// Counts from Track 1 & Track 2
|
|
||||||
// data_detect 992 988
|
|
||||||
// olen>=0 992 985
|
|
||||||
// OR-ed 992 985
|
|
||||||
|
|
||||||
return ( hdlc_state[chan][subchan][slice].data_detect );
|
|
||||||
|
|
||||||
} /* end hdlc_rec_gathering */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------------------------
|
/*-------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
|
|
|
@ -3,5 +3,5 @@
|
||||||
@GEN_PACKETS_BIN@ -r 96000 -B19200 -a 170 -o test19.wav
|
@GEN_PACKETS_BIN@ -r 96000 -B19200 -a 170 -o test19.wav
|
||||||
@ATEST_BIN@ -B19200 -F0 -L4 test19.wav
|
@ATEST_BIN@ -B19200 -F0 -L4 test19.wav
|
||||||
@GEN_PACKETS_BIN@ -r 96000 -B19200 -n 100 -o test19.wav
|
@GEN_PACKETS_BIN@ -r 96000 -B19200 -n 100 -o test19.wav
|
||||||
@ATEST_BIN@ -B19200 -F0 -L60 -G64 test19.wav
|
@ATEST_BIN@ -B19200 -F0 -L60 -G66 test19.wav
|
||||||
@ATEST_BIN@ -B19200 -F1 -L64 -G68 test19.wav
|
@ATEST_BIN@ -B19200 -F1 -L64 -G69 test19.wav
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
@CUSTOM_SHELL_SHABANG@
|
@CUSTOM_SHELL_SHABANG@
|
||||||
|
|
||||||
@GEN_PACKETS_BIN@ -B2400 -j -n 100 -o test24-a.wav
|
@GEN_PACKETS_BIN@ -B2400 -j -n 100 -o test24-a.wav
|
||||||
@ATEST_BIN@ -B2400 -j -F0 -L76 -G80 test24-a.wav
|
@ATEST_BIN@ -B2400 -j -F0 -L76 -G83 test24-a.wav
|
||||||
@ATEST_BIN@ -B2400 -j -F1 -L84 -G88 test24-a.wav
|
@ATEST_BIN@ -B2400 -j -F1 -L84 -G89 test24-a.wav
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
@CUSTOM_SHELL_SHABANG@
|
@CUSTOM_SHELL_SHABANG@
|
||||||
|
|
||||||
@GEN_PACKETS_BIN@ -B2400 -J -n 100 -o test24-b.wav
|
@GEN_PACKETS_BIN@ -B2400 -J -n 100 -o test24-b.wav
|
||||||
@ATEST_BIN@ -B2400 -J -F0 -L84 -G88 test24-b.wav
|
@ATEST_BIN@ -B2400 -J -F0 -L81 -G88 test24-b.wav
|
||||||
@ATEST_BIN@ -B2400 -J -F1 -L86 -G90 test24-b.wav
|
@ATEST_BIN@ -B2400 -J -F1 -L86 -G90 test24-b.wav
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@CUSTOM_SHELL_SHABANG@
|
@CUSTOM_SHELL_SHABANG@
|
||||||
|
|
||||||
@GEN_PACKETS_BIN@ -B2400 -g -n 100 -o test24-g.wav
|
@GEN_PACKETS_BIN@ -B2400 -g -n 100 -o test24-g.wav
|
||||||
@ATEST_BIN@ -B2400 -g -F0 -L99 -G100 test24-g.wav
|
@ATEST_BIN@ -B2400 -g -F0 -L99 -G101 test24-g.wav
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
@CUSTOM_SHELL_SHABANG@
|
@CUSTOM_SHELL_SHABANG@
|
||||||
|
|
||||||
@GEN_PACKETS_BIN@ -B4800 -n 100 -o test48.wav
|
@GEN_PACKETS_BIN@ -B4800 -n 100 -o test48.wav
|
||||||
@ATEST_BIN@ -B4800 -F0 -L70 -G74 test48.wav
|
@ATEST_BIN@ -B4800 -F0 -L68 -G74 test48.wav
|
||||||
@ATEST_BIN@ -B4800 -F1 -L79 -G84 test48.wav
|
@ATEST_BIN@ -B4800 -F1 -L72 -G84 test48.wav
|
||||||
|
|
Loading…
Reference in New Issue