The FAX modem receive synchronisation algorithms have been changed to prevent
occasional false recognition of a fast modem when its really the V.21 modem. This was sometimes messing up T.38 gateway operation.
This commit is contained in:
parent
aa6bb702de
commit
cfce1fd240
|
@ -28,6 +28,9 @@
|
||||||
#if !defined(_SPANDSP_DDS_H_)
|
#if !defined(_SPANDSP_DDS_H_)
|
||||||
#define _SPANDSP_DDS_H_
|
#define _SPANDSP_DDS_H_
|
||||||
|
|
||||||
|
#define DDS_PHASE_RATE(frequency) (int32_t) ((frequency)*65536.0f*65536.0f/SAMPLE_RATE)
|
||||||
|
#define DDS_PHASE(angle) (int32_t) ((uint32_t) (((angle < 0.0f) ? (360.0f + angle) : angle)*65536.0f*65536.0f/360.0f))
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
extern "C"
|
extern "C"
|
||||||
{
|
{
|
||||||
|
|
|
@ -29,11 +29,10 @@
|
||||||
/* Target length for the equalizer is about 63 taps, to deal with the worst stuff
|
/* Target length for the equalizer is about 63 taps, to deal with the worst stuff
|
||||||
in V.56bis. */
|
in V.56bis. */
|
||||||
/*! The length of the equalizer buffer */
|
/*! The length of the equalizer buffer */
|
||||||
//#define V17_EQUALIZER_LEN 33
|
#define V17_EQUALIZER_LEN 33
|
||||||
#define V17_EQUALIZER_LEN 17
|
|
||||||
/*! Samples before the target position in the equalizer buffer */
|
/*! Samples before the target position in the equalizer buffer */
|
||||||
//#define V17_EQUALIZER_PRE_LEN 16
|
#define V17_EQUALIZER_PRE_LEN 16
|
||||||
#define V17_EQUALIZER_PRE_LEN 8
|
|
||||||
|
|
||||||
/*! The number of taps in the pulse shaping/bandpass filter */
|
/*! The number of taps in the pulse shaping/bandpass filter */
|
||||||
#define V17_RX_FILTER_STEPS 27
|
#define V17_RX_FILTER_STEPS 27
|
||||||
|
@ -72,7 +71,7 @@ struct v17_rx_state_s
|
||||||
routine. */
|
routine. */
|
||||||
void *qam_user_data;
|
void *qam_user_data;
|
||||||
|
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||||
/*! \brief The scaling factor assessed by the AGC algorithm. */
|
/*! \brief The scaling factor assessed by the AGC algorithm. */
|
||||||
int16_t agc_scaling;
|
int16_t agc_scaling;
|
||||||
/*! \brief The previous value of agc_scaling, needed to reuse old training. */
|
/*! \brief The previous value of agc_scaling, needed to reuse old training. */
|
||||||
|
@ -202,10 +201,10 @@ struct v17_rx_state_s
|
||||||
This is only for performance analysis purposes. */
|
This is only for performance analysis purposes. */
|
||||||
int total_baud_timing_correction;
|
int total_baud_timing_correction;
|
||||||
|
|
||||||
/*! \brief Starting phase angles for the coarse carrier aquisition step. */
|
/*! \brief The previous symbol phase angles for the coarse carrier aquisition step. */
|
||||||
int32_t start_angles[2];
|
int32_t last_angles[2];
|
||||||
/*! \brief History list of phase angles for the coarse carrier aquisition step. */
|
/*! \brief History list of phase angle differences for the coarse carrier aquisition step. */
|
||||||
int32_t angles[16];
|
int32_t diff_angles[16];
|
||||||
|
|
||||||
/*! \brief A pointer to the current space map. There is a space map for
|
/*! \brief A pointer to the current space map. There is a space map for
|
||||||
each trellis state. */
|
each trellis state. */
|
||||||
|
@ -219,7 +218,7 @@ struct v17_rx_state_s
|
||||||
int full_path_to_past_state_locations[V17_TRELLIS_STORAGE_DEPTH][8];
|
int full_path_to_past_state_locations[V17_TRELLIS_STORAGE_DEPTH][8];
|
||||||
/*! \brief The trellis. */
|
/*! \brief The trellis. */
|
||||||
int past_state_locations[V17_TRELLIS_STORAGE_DEPTH][8];
|
int past_state_locations[V17_TRELLIS_STORAGE_DEPTH][8];
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||||
/*! \brief Euclidean distances (actually the squares of the distances)
|
/*! \brief Euclidean distances (actually the squares of the distances)
|
||||||
from the last states of the trellis. */
|
from the last states of the trellis. */
|
||||||
uint32_t distances[8];
|
uint32_t distances[8];
|
||||||
|
|
|
@ -183,10 +183,11 @@ struct v27ter_rx_state_s
|
||||||
This is only for performance analysis purposes. */
|
This is only for performance analysis purposes. */
|
||||||
int total_baud_timing_correction;
|
int total_baud_timing_correction;
|
||||||
|
|
||||||
/*! \brief Starting phase angles for the coarse carrier aquisition step. */
|
/*! \brief The previous symbol phase angles for the coarse carrier aquisition step. */
|
||||||
int32_t start_angles[2];
|
int32_t last_angles[2];
|
||||||
/*! \brief History list of phase angles for the coarse carrier aquisition step. */
|
/*! \brief History list of phase angle differences for the coarse carrier aquisition step. */
|
||||||
int32_t angles[16];
|
int32_t diff_angles[16];
|
||||||
|
|
||||||
/*! \brief Error and flow logging control */
|
/*! \brief Error and flow logging control */
|
||||||
logging_state_t logging;
|
logging_state_t logging;
|
||||||
};
|
};
|
||||||
|
|
|
@ -184,10 +184,10 @@ struct v29_rx_state_s
|
||||||
This is only for performance analysis purposes. */
|
This is only for performance analysis purposes. */
|
||||||
int total_baud_timing_correction;
|
int total_baud_timing_correction;
|
||||||
|
|
||||||
/*! \brief Starting phase angles for the coarse carrier aquisition step. */
|
/*! \brief The previous symbol phase angles for the coarse carrier aquisition step. */
|
||||||
int32_t start_angles[2];
|
int32_t last_angles[2];
|
||||||
/*! \brief History list of phase angles for the coarse carrier aquisition step. */
|
/*! \brief History list of phase angle differences for the coarse carrier aquisition step. */
|
||||||
int32_t angles[16];
|
int32_t diff_angles[16];
|
||||||
|
|
||||||
/*! \brief The position of the current symbol in the constellation, used for
|
/*! \brief The position of the current symbol in the constellation, used for
|
||||||
differential decoding. */
|
differential decoding. */
|
||||||
|
|
|
@ -718,9 +718,9 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||||
if (++s->training_count >= 100)
|
if (++s->training_count >= 100)
|
||||||
{
|
{
|
||||||
/* Record the current phase angle */
|
/* Record the current phase angle */
|
||||||
s->angles[0] =
|
|
||||||
s->start_angles[0] = arctan2(z.im, z.re);
|
|
||||||
s->training_stage = TRAINING_STAGE_LOG_PHASE;
|
s->training_stage = TRAINING_STAGE_LOG_PHASE;
|
||||||
|
vec_zeroi32(s->diff_angles, 16);
|
||||||
|
s->last_angles[0] = arctan2(z.im, z.re);
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||||
if (s->agc_scaling_save == 0)
|
if (s->agc_scaling_save == 0)
|
||||||
s->agc_scaling_save = s->agc_scaling;
|
s->agc_scaling_save = s->agc_scaling;
|
||||||
|
@ -740,16 +740,16 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||||
/* We should already know the accurate carrier frequency. All we need to sort
|
/* We should already know the accurate carrier frequency. All we need to sort
|
||||||
out is the phase. */
|
out is the phase. */
|
||||||
/* Check if we just saw A or B */
|
/* Check if we just saw A or B */
|
||||||
if ((uint32_t) (angle - s->start_angles[0]) < 0x80000000U)
|
if ((uint32_t) (angle - s->last_angles[0]) < 0x80000000U)
|
||||||
{
|
{
|
||||||
angle = s->start_angles[0];
|
angle = s->last_angles[0];
|
||||||
s->angles[0] = 0xC0000000 + 219937506;
|
s->last_angles[0] = 0xC0000000 + 219937506;
|
||||||
s->angles[1] = 0x80000000 + 219937506;
|
s->last_angles[1] = 0x80000000 + 219937506;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
s->angles[0] = 0x80000000 + 219937506;
|
s->last_angles[0] = 0x80000000 + 219937506;
|
||||||
s->angles[1] = 0xC0000000 + 219937506;
|
s->last_angles[1] = 0xC0000000 + 219937506;
|
||||||
}
|
}
|
||||||
/* Make a step shift in the phase, to pull it into line. We need to rotate the equalizer
|
/* Make a step shift in the phase, to pull it into line. We need to rotate the equalizer
|
||||||
buffer, as well as the carrier phase, for this to play out nicely. */
|
buffer, as well as the carrier phase, for this to play out nicely. */
|
||||||
|
@ -775,8 +775,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
s->angles[1] =
|
s->last_angles[1] = angle;
|
||||||
s->start_angles[1] = angle;
|
|
||||||
s->training_stage = TRAINING_STAGE_WAIT_FOR_CDBA;
|
s->training_stage = TRAINING_STAGE_WAIT_FOR_CDBA;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -785,55 +784,32 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||||
angle = arctan2(z.im, z.re);
|
angle = arctan2(z.im, z.re);
|
||||||
/* Look for the initial ABAB sequence to display a phase reversal, which will
|
/* Look for the initial ABAB sequence to display a phase reversal, which will
|
||||||
signal the start of the scrambled CDBA segment */
|
signal the start of the scrambled CDBA segment */
|
||||||
ang = angle - s->angles[(s->training_count - 1) & 0xF];
|
i = s->training_count + 1;
|
||||||
s->angles[(s->training_count + 1) & 0xF] = angle;
|
ang = angle - s->last_angles[i & 1];
|
||||||
|
s->last_angles[i & 1] = angle;
|
||||||
/* Do a coarse frequency adjustment about half way through the reversals, as if we wait until
|
s->diff_angles[i & 0xF] = s->diff_angles[(i - 2) & 0xF] + (ang >> 4);
|
||||||
the end, we might have rotated too far to correct properly. */
|
if ((ang > DDS_PHASE(90.0f) || ang < DDS_PHASE(-90.0f)) && s->training_count >= 13)
|
||||||
if (s->training_count == 100)
|
|
||||||
{
|
|
||||||
i = s->training_count;
|
|
||||||
j = i & 0xF;
|
|
||||||
ang = (s->angles[j] - s->start_angles[0])/i
|
|
||||||
+ (s->angles[j | 0x1] - s->start_angles[1])/i;
|
|
||||||
s->carrier_phase_rate += 3*(ang/20);
|
|
||||||
//span_log(&s->logging, SPAN_LOG_FLOW, "Angles %x, %x, %x, %x, dist %d\n", s->angles[j], s->start_angles[0], s->angles[j | 0x1], s->start_angles[1], i);
|
|
||||||
|
|
||||||
s->start_angles[0] = s->angles[j];
|
|
||||||
s->start_angles[1] = s->angles[j | 0x1];
|
|
||||||
//span_log(&s->logging, SPAN_LOG_FLOW, "%d %d %d %d %d\n", s->angles[s->training_count & 0xF], s->start_angles[0], s->angles[(s->training_count | 0x1) & 0xF], s->start_angles[1], s->training_count);
|
|
||||||
span_log(&s->logging, SPAN_LOG_FLOW, "First coarse carrier frequency %7.2f (%d)\n", dds_frequencyf(s->carrier_phase_rate), s->training_count);
|
|
||||||
|
|
||||||
}
|
|
||||||
if ((ang > 0x40000000 || ang < -0x40000000) && s->training_count >= 13)
|
|
||||||
{
|
{
|
||||||
span_log(&s->logging, SPAN_LOG_FLOW, "We seem to have a reversal at symbol %d\n", s->training_count);
|
span_log(&s->logging, SPAN_LOG_FLOW, "We seem to have a reversal at symbol %d\n", s->training_count);
|
||||||
/* We seem to have a phase reversal */
|
/* We seem to have a phase reversal */
|
||||||
/* Slam the carrier frequency into line, based on the total phase drift over the last
|
/* Slam the carrier frequency into line, based on the total phase drift over the last
|
||||||
section. Use the shift from the odd bits and the shift from the even bits to get
|
section. Use the shift from the odd bits and the shift from the even bits to get
|
||||||
better jitter suppression. */
|
better jitter suppression. */
|
||||||
/* TODO: We are supposed to deal with frequancy errors up to +-8Hz. Over 200+
|
|
||||||
symbols that is more than half a cycle. We get confused an do crazy things.
|
|
||||||
We can only cope with errors up to 5Hz right now. We need to implement
|
|
||||||
greater tolerance to be compliant, although it doesn't really matter much
|
|
||||||
these days. */
|
|
||||||
/* Step back a few symbols so we don't get ISI distorting things. */
|
/* Step back a few symbols so we don't get ISI distorting things. */
|
||||||
i = (s->training_count - 8) & ~1;
|
i = (s->training_count - 8) & ~1;
|
||||||
/* Avoid the possibility of a divide by zero */
|
/* Avoid the possibility of a divide by zero */
|
||||||
if (i - 100 + 8)
|
if (i > 1)
|
||||||
{
|
{
|
||||||
j = i & 0xF;
|
j = i & 0xF;
|
||||||
ang = (s->angles[j] - s->start_angles[0])/(i - 100 + 8)
|
ang = (s->diff_angles[j] + s->diff_angles[j | 0x1])/(i - 1);
|
||||||
+ (s->angles[j | 0x1] - s->start_angles[1])/(i - 100 + 8);
|
s->carrier_phase_rate += 3*16*(ang/20);
|
||||||
s->carrier_phase_rate += 3*(ang/20);
|
span_log(&s->logging, SPAN_LOG_FLOW, "Angles %x, %x, dist %d\n", s->last_angles[0], s->last_angles[1], i);
|
||||||
span_log(&s->logging, SPAN_LOG_FLOW, "Angles %x, %x, %x, %x, dist %d\n", s->angles[j], s->start_angles[0], s->angles[j | 0x1], s->start_angles[1], i);
|
|
||||||
}
|
}
|
||||||
//span_log(&s->logging, SPAN_LOG_FLOW, "%d %d %d %d %d\n", s->angles[s->training_count & 0xF], s->start_angles[0], s->angles[(s->training_count | 0x1) & 0xF], s->start_angles[1], s->training_count);
|
span_log(&s->logging, SPAN_LOG_FLOW, "Coarse carrier frequency %7.2f (%d)\n", dds_frequencyf(s->carrier_phase_rate), s->training_count);
|
||||||
span_log(&s->logging, SPAN_LOG_FLOW, "Second coarse carrier frequency %7.2f (%d)\n", dds_frequencyf(s->carrier_phase_rate), s->training_count);
|
|
||||||
/* Check if the carrier frequency is plausible */
|
/* Check if the carrier frequency is plausible */
|
||||||
if (s->carrier_phase_rate < dds_phase_ratef(CARRIER_NOMINAL_FREQ - 20.0f)
|
if (s->carrier_phase_rate < DDS_PHASE_RATE(CARRIER_NOMINAL_FREQ - 20.0f)
|
||||||
||
|
||
|
||||||
s->carrier_phase_rate > dds_phase_ratef(CARRIER_NOMINAL_FREQ + 20.0f))
|
s->carrier_phase_rate > DDS_PHASE_RATE(CARRIER_NOMINAL_FREQ + 20.0f))
|
||||||
{
|
{
|
||||||
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n");
|
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n");
|
||||||
/* Park this modem */
|
/* Park this modem */
|
||||||
|
@ -1025,8 +1001,8 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||||
/* Look for the initial ABAB sequence to display a phase reversal, which will
|
/* Look for the initial ABAB sequence to display a phase reversal, which will
|
||||||
signal the start of the scrambled CDBA segment */
|
signal the start of the scrambled CDBA segment */
|
||||||
angle = arctan2(z.im, z.re);
|
angle = arctan2(z.im, z.re);
|
||||||
ang = angle - s->angles[s->training_count & 1];
|
ang = angle - s->last_angles[s->training_count & 1];
|
||||||
if (ang > 0x40000000 || ang < -0x40000000)
|
if (ang > DDS_PHASE(90.0f) || ang < DDS_PHASE(-90.0f))
|
||||||
{
|
{
|
||||||
/* We seem to have a phase reversal */
|
/* We seem to have a phase reversal */
|
||||||
/* We have just seen the first symbol of the scrambled sequence, so skip it. */
|
/* We have just seen the first symbol of the scrambled sequence, so skip it. */
|
||||||
|
@ -1507,8 +1483,8 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
|
||||||
#endif
|
#endif
|
||||||
if (short_train != 2)
|
if (short_train != 2)
|
||||||
s->short_train = short_train;
|
s->short_train = short_train;
|
||||||
memset(s->start_angles, 0, sizeof(s->start_angles));
|
memset(s->last_angles, 0, sizeof(s->last_angles));
|
||||||
memset(s->angles, 0, sizeof(s->angles));
|
memset(s->diff_angles, 0, sizeof(s->diff_angles));
|
||||||
|
|
||||||
/* Initialise the TCM decoder parameters. */
|
/* Initialise the TCM decoder parameters. */
|
||||||
/* The accumulated distance vectors are set so state zero starts
|
/* The accumulated distance vectors are set so state zero starts
|
||||||
|
@ -1544,7 +1520,7 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
s->carrier_phase_rate = dds_phase_ratef(CARRIER_NOMINAL_FREQ);
|
s->carrier_phase_rate = DDS_PHASE_RATE(CARRIER_NOMINAL_FREQ);
|
||||||
equalizer_reset(s);
|
equalizer_reset(s);
|
||||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||||
s->agc_scaling_save = 0;
|
s->agc_scaling_save = 0;
|
||||||
|
@ -1618,7 +1594,7 @@ SPAN_DECLARE(v17_rx_state_t *) v17_rx_init(v17_rx_state_t *s, int bit_rate, put_
|
||||||
s->short_train = FALSE;
|
s->short_train = FALSE;
|
||||||
s->scrambler_tap = 18 - 1;
|
s->scrambler_tap = 18 - 1;
|
||||||
v17_rx_signal_cutoff(s, -45.5f);
|
v17_rx_signal_cutoff(s, -45.5f);
|
||||||
s->carrier_phase_rate_save = dds_phase_ratef(CARRIER_NOMINAL_FREQ);
|
s->carrier_phase_rate_save = DDS_PHASE_RATE(CARRIER_NOMINAL_FREQ);
|
||||||
v17_rx_restart(s, bit_rate, s->short_train);
|
v17_rx_restart(s, bit_rate, s->short_train);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
|
@ -956,7 +956,7 @@ int v22bis_rx_restart(v22bis_state_t *s)
|
||||||
s->rx.training_count = 0;
|
s->rx.training_count = 0;
|
||||||
s->rx.signal_present = FALSE;
|
s->rx.signal_present = FALSE;
|
||||||
|
|
||||||
s->rx.carrier_phase_rate = dds_phase_ratef((s->calling_party) ? 2400.0f : 1200.0f);
|
s->rx.carrier_phase_rate = (s->calling_party) ? DDS_PHASE_RATE(2400.0f) : DDS_PHASE_RATE(1200.0f);
|
||||||
s->rx.carrier_phase = 0;
|
s->rx.carrier_phase = 0;
|
||||||
power_meter_init(&s->rx.rx_power, 5);
|
power_meter_init(&s->rx.rx_power, 5);
|
||||||
v22bis_rx_signal_cutoff(s, -45.5f);
|
v22bis_rx_signal_cutoff(s, -45.5f);
|
||||||
|
|
|
@ -566,15 +566,14 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
|
||||||
{
|
{
|
||||||
s->gardner_step = 32;
|
s->gardner_step = 32;
|
||||||
s->training_stage = TRAINING_STAGE_LOG_PHASE;
|
s->training_stage = TRAINING_STAGE_LOG_PHASE;
|
||||||
s->angles[0] =
|
vec_zeroi32(s->diff_angles, 16);
|
||||||
s->start_angles[0] = arctan2(z.im, z.re);
|
s->last_angles[0] = arctan2(z.im, z.re);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TRAINING_STAGE_LOG_PHASE:
|
case TRAINING_STAGE_LOG_PHASE:
|
||||||
/* Record the current alternate phase angle */
|
/* Record the current alternate phase angle */
|
||||||
target = &zero;
|
target = &zero;
|
||||||
s->angles[1] =
|
s->last_angles[1] = arctan2(z.im, z.re);
|
||||||
s->start_angles[1] = arctan2(z.im, z.re);
|
|
||||||
s->training_count = 1;
|
s->training_count = 1;
|
||||||
s->training_stage = TRAINING_STAGE_WAIT_FOR_HOP;
|
s->training_stage = TRAINING_STAGE_WAIT_FOR_HOP;
|
||||||
break;
|
break;
|
||||||
|
@ -583,9 +582,11 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
|
||||||
angle = arctan2(z.im, z.re);
|
angle = arctan2(z.im, z.re);
|
||||||
/* Look for the initial ABAB sequence to display a phase reversal, which will
|
/* Look for the initial ABAB sequence to display a phase reversal, which will
|
||||||
signal the start of the scrambled ABAB segment */
|
signal the start of the scrambled ABAB segment */
|
||||||
ang = angle - s->angles[(s->training_count - 1) & 0xF];
|
i = s->training_count + 1;
|
||||||
s->angles[(s->training_count + 1) & 0xF] = angle;
|
ang = angle - s->last_angles[i & 1];
|
||||||
if ((ang > 0x20000000 || ang < -0x20000000) && s->training_count >= 3)
|
s->last_angles[i & 1] = angle;
|
||||||
|
s->diff_angles[i & 0xF] = s->diff_angles[(i - 2) & 0xF] + (ang >> 4);
|
||||||
|
if ((ang > DDS_PHASE(45.0f) || ang < DDS_PHASE(-45.0f)) && s->training_count >= 13)
|
||||||
{
|
{
|
||||||
/* We seem to have a phase reversal */
|
/* We seem to have a phase reversal */
|
||||||
/* Slam the carrier frequency into line, based on the total phase drift over the last
|
/* Slam the carrier frequency into line, based on the total phase drift over the last
|
||||||
|
@ -595,20 +596,20 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
|
||||||
/* Step back a few symbols so we don't get ISI distorting things. */
|
/* Step back a few symbols so we don't get ISI distorting things. */
|
||||||
i = (s->training_count - 8) & ~1;
|
i = (s->training_count - 8) & ~1;
|
||||||
/* Avoid the possibility of a divide by zero */
|
/* Avoid the possibility of a divide by zero */
|
||||||
if (i)
|
if (i > 1)
|
||||||
{
|
{
|
||||||
j = i & 0xF;
|
j = i & 0xF;
|
||||||
ang = (s->angles[j] - s->start_angles[0])/i + (s->angles[j | 0x1] - s->start_angles[1])/i;
|
ang = (s->diff_angles[j] + s->diff_angles[j | 0x1])/(i - 1);
|
||||||
if (s->bit_rate == 4800)
|
if (s->bit_rate == 4800)
|
||||||
s->carrier_phase_rate += ang/10;
|
s->carrier_phase_rate += 16*(ang/10);
|
||||||
else
|
else
|
||||||
s->carrier_phase_rate += 3*(ang/40);
|
s->carrier_phase_rate += 3*16*(ang/40);
|
||||||
}
|
}
|
||||||
span_log(&s->logging, SPAN_LOG_FLOW, "Coarse carrier frequency %7.2f (%d)\n", dds_frequencyf(s->carrier_phase_rate), s->training_count);
|
span_log(&s->logging, SPAN_LOG_FLOW, "Coarse carrier frequency %7.2f (%d)\n", dds_frequencyf(s->carrier_phase_rate), s->training_count);
|
||||||
/* Check if the carrier frequency is plausible */
|
/* Check if the carrier frequency is plausible */
|
||||||
if (s->carrier_phase_rate < dds_phase_ratef(CARRIER_NOMINAL_FREQ - 20.0f)
|
if (s->carrier_phase_rate < DDS_PHASE_RATE(CARRIER_NOMINAL_FREQ - 20.0f)
|
||||||
||
|
||
|
||||||
s->carrier_phase_rate > dds_phase_ratef(CARRIER_NOMINAL_FREQ + 20.0f))
|
s->carrier_phase_rate > DDS_PHASE_RATE(CARRIER_NOMINAL_FREQ + 20.0f))
|
||||||
{
|
{
|
||||||
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n");
|
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n");
|
||||||
/* Park this modem */
|
/* Park this modem */
|
||||||
|
@ -1065,7 +1066,7 @@ SPAN_DECLARE(int) v27ter_rx_restart(v27ter_rx_state_t *s, int bit_rate, int old_
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
s->carrier_phase_rate = dds_phase_ratef(CARRIER_NOMINAL_FREQ);
|
s->carrier_phase_rate = DDS_PHASE_RATE(CARRIER_NOMINAL_FREQ);
|
||||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||||
s->agc_scaling = (float) (1024.0f*FP_FACTOR)*1.414f/283.0f;
|
s->agc_scaling = (float) (1024.0f*FP_FACTOR)*1.414f/283.0f;
|
||||||
#else
|
#else
|
||||||
|
|
|
@ -600,8 +600,8 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
|
||||||
{
|
{
|
||||||
/* Record the current phase angle */
|
/* Record the current phase angle */
|
||||||
s->training_stage = TRAINING_STAGE_LOG_PHASE;
|
s->training_stage = TRAINING_STAGE_LOG_PHASE;
|
||||||
s->angles[0] =
|
vec_zeroi32(s->diff_angles, 16);
|
||||||
s->start_angles[0] = arctan2(z.im, z.re);
|
s->last_angles[0] = arctan2(z.im, z.re);
|
||||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||||
if (s->agc_scaling_save == 0)
|
if (s->agc_scaling_save == 0)
|
||||||
s->agc_scaling_save = s->agc_scaling;
|
s->agc_scaling_save = s->agc_scaling;
|
||||||
|
@ -614,8 +614,7 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
|
||||||
case TRAINING_STAGE_LOG_PHASE:
|
case TRAINING_STAGE_LOG_PHASE:
|
||||||
/* Record the current alternate phase angle */
|
/* Record the current alternate phase angle */
|
||||||
target = &zero;
|
target = &zero;
|
||||||
s->angles[1] =
|
s->last_angles[1] = arctan2(z.im, z.re);
|
||||||
s->start_angles[1] = arctan2(z.im, z.re);
|
|
||||||
s->training_count = 1;
|
s->training_count = 1;
|
||||||
s->training_stage = TRAINING_STAGE_WAIT_FOR_CDCD;
|
s->training_stage = TRAINING_STAGE_WAIT_FOR_CDCD;
|
||||||
break;
|
break;
|
||||||
|
@ -624,9 +623,11 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
|
||||||
angle = arctan2(z.im, z.re);
|
angle = arctan2(z.im, z.re);
|
||||||
/* Look for the initial ABAB sequence to display a phase reversal, which will
|
/* Look for the initial ABAB sequence to display a phase reversal, which will
|
||||||
signal the start of the scrambled CDCD segment */
|
signal the start of the scrambled CDCD segment */
|
||||||
ang = angle - s->angles[(s->training_count - 1) & 0xF];
|
i = s->training_count + 1;
|
||||||
s->angles[(s->training_count + 1) & 0xF] = angle;
|
ang = angle - s->last_angles[i & 1];
|
||||||
if ((ang > 0x20000000 || ang < -0x20000000) && s->training_count >= 13)
|
s->last_angles[i & 1] = angle;
|
||||||
|
s->diff_angles[i & 0xF] = s->diff_angles[(i - 2) & 0xF] + (ang >> 4);
|
||||||
|
if ((ang > DDS_PHASE(45.0f) || ang < DDS_PHASE(-45.0f)) && s->training_count >= 13)
|
||||||
{
|
{
|
||||||
/* We seem to have a phase reversal */
|
/* We seem to have a phase reversal */
|
||||||
/* Slam the carrier frequency into line, based on the total phase drift over the last
|
/* Slam the carrier frequency into line, based on the total phase drift over the last
|
||||||
|
@ -636,17 +637,17 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
|
||||||
/* Step back a few symbols so we don't get ISI distorting things. */
|
/* Step back a few symbols so we don't get ISI distorting things. */
|
||||||
i = (s->training_count - 8) & ~1;
|
i = (s->training_count - 8) & ~1;
|
||||||
/* Avoid the possibility of a divide by zero */
|
/* Avoid the possibility of a divide by zero */
|
||||||
if (i)
|
if (i > 1)
|
||||||
{
|
{
|
||||||
j = i & 0xF;
|
j = i & 0xF;
|
||||||
ang = (s->angles[j] - s->start_angles[0])/i + (s->angles[j | 0x1] - s->start_angles[1])/i;
|
ang = (s->diff_angles[j] + s->diff_angles[j | 0x1])/(i - 1);
|
||||||
s->carrier_phase_rate += 3*(ang/20);
|
s->carrier_phase_rate += 3*16*(ang/20);
|
||||||
}
|
}
|
||||||
span_log(&s->logging, SPAN_LOG_FLOW, "Coarse carrier frequency %7.2f\n", dds_frequencyf(s->carrier_phase_rate));
|
span_log(&s->logging, SPAN_LOG_FLOW, "Coarse carrier frequency %7.2f\n", dds_frequencyf(s->carrier_phase_rate));
|
||||||
/* Check if the carrier frequency is plausible */
|
/* Check if the carrier frequency is plausible */
|
||||||
if (s->carrier_phase_rate < dds_phase_ratef(CARRIER_NOMINAL_FREQ - 20.0f)
|
if (s->carrier_phase_rate < DDS_PHASE_RATE(CARRIER_NOMINAL_FREQ - 20.0f)
|
||||||
||
|
||
|
||||||
s->carrier_phase_rate > dds_phase_ratef(CARRIER_NOMINAL_FREQ + 20.0f))
|
s->carrier_phase_rate > DDS_PHASE_RATE(CARRIER_NOMINAL_FREQ + 20.0f))
|
||||||
{
|
{
|
||||||
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n");
|
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n");
|
||||||
/* Park this modem */
|
/* Park this modem */
|
||||||
|
@ -1111,7 +1112,7 @@ SPAN_DECLARE(int) v29_rx_restart(v29_rx_state_t *s, int bit_rate, int old_train)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
s->carrier_phase_rate = dds_phase_ratef(CARRIER_NOMINAL_FREQ);
|
s->carrier_phase_rate = DDS_PHASE_RATE(CARRIER_NOMINAL_FREQ);
|
||||||
equalizer_reset(s);
|
equalizer_reset(s);
|
||||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||||
s->agc_scaling_save = 0;
|
s->agc_scaling_save = 0;
|
||||||
|
|
Loading…
Reference in New Issue