mirror of
https://github.com/signalwire/freeswitch.git
synced 2025-03-13 12:40:17 +00:00
Tweaks for spandsp
This commit is contained in:
parent
7c7967fbae
commit
13fbaf7e0f
@ -32,8 +32,8 @@ typedef struct
|
||||
{
|
||||
/*! \brief Internet Aware FAX mode bit mask. */
|
||||
int iaf;
|
||||
/*! \brief Required time between T.38 transmissions, in milliseconds. */
|
||||
int ms_per_tx_chunk;
|
||||
/*! \brief Required time between T.38 transmissions, in microseconds. */
|
||||
int us_per_tx_chunk;
|
||||
/*! \brief Bit fields controlling the way data is packed into chunked for transmission. */
|
||||
int chunking_modes;
|
||||
|
||||
|
@ -26,10 +26,10 @@
|
||||
#if !defined(_SPANDSP_PRIVATE_V22BIS_H_)
|
||||
#define _SPANDSP_PRIVATE_V22BIS_H_
|
||||
|
||||
/*! The length of the equalizer buffer */
|
||||
#define V22BIS_EQUALIZER_LEN 17
|
||||
/*! Samples before the target position in the equalizer buffer */
|
||||
#define V22BIS_EQUALIZER_PRE_LEN 8
|
||||
/*! The number of steps to the left and to the right of the target position in the equalizer buffer. */
|
||||
#define V22BIS_EQUALIZER_LEN 7
|
||||
/*! One less than a power of 2 >= (2*V22BIS_EQUALIZER_LEN + 1) */
|
||||
#define V22BIS_EQUALIZER_MASK 15
|
||||
|
||||
/*! The number of taps in the transmit pulse shaping filter */
|
||||
#define V22BIS_TX_FILTER_STEPS 9
|
||||
@ -65,12 +65,6 @@ enum
|
||||
V22BIS_TX_TRAINING_STAGE_PARKED
|
||||
};
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
extern const complexi16_t v22bis_constellation[16];
|
||||
#else
|
||||
extern const complexf_t v22bis_constellation[16];
|
||||
#endif
|
||||
|
||||
/*!
|
||||
V.22bis modem descriptor. This defines the working state for a single instance
|
||||
of a V.22bis modem.
|
||||
@ -99,15 +93,10 @@ struct v22bis_state_s
|
||||
/* Receive section */
|
||||
struct
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
/*! \brief The scaling factor accessed by the AGC algorithm. */
|
||||
int16_t agc_scaling;
|
||||
/*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
|
||||
/*! \brief The route raised cosine (RRC) pulse shaping filter buffer. */
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
int16_t rrc_filter[V22BIS_RX_FILTER_STEPS];
|
||||
#else
|
||||
/*! \brief The scaling factor accessed by the AGC algorithm. */
|
||||
float agc_scaling;
|
||||
/*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
|
||||
float rrc_filter[V22BIS_RX_FILTER_STEPS];
|
||||
#endif
|
||||
/*! \brief Current offset into the RRC pulse shaping filter buffer. */
|
||||
@ -127,27 +116,19 @@ struct v22bis_state_s
|
||||
/*! \brief >0 if a signal above the minimum is present. It may or may not be a V.22bis signal. */
|
||||
int signal_present;
|
||||
|
||||
/*! \brief A measure of how much mismatch there is between the real constellation,
|
||||
and the decoded symbol positions. */
|
||||
float training_error;
|
||||
|
||||
/*! \brief The current phase of the carrier (i.e. the DDS parameter). */
|
||||
uint32_t carrier_phase;
|
||||
/*! \brief The update rate for the phase of the carrier (i.e. the DDS increment). */
|
||||
int32_t carrier_phase_rate;
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
/*! \brief A measure of how much mismatch there is between the real constellation,
|
||||
and the decoded symbol positions. */
|
||||
int32_t training_error;
|
||||
/*! \brief The proportional part of the carrier tracking filter. */
|
||||
int32_t carrier_track_p;
|
||||
/*! \brief The integral part of the carrier tracking filter. */
|
||||
int32_t carrier_track_i;
|
||||
#else
|
||||
/*! \brief A measure of how much mismatch there is between the real constellation,
|
||||
and the decoded symbol positions. */
|
||||
float training_error;
|
||||
|
||||
/*! \brief The proportional part of the carrier tracking filter. */
|
||||
float carrier_track_p;
|
||||
/*! \brief The integral part of the carrier tracking filter. */
|
||||
float carrier_track_i;
|
||||
#endif
|
||||
|
||||
/*! \brief A callback function which may be enabled to report every symbol's
|
||||
constellation position. */
|
||||
@ -162,23 +143,21 @@ struct v22bis_state_s
|
||||
int32_t carrier_on_power;
|
||||
/*! \brief The power meter level at which carrier off is declared. */
|
||||
int32_t carrier_off_power;
|
||||
|
||||
/*! \brief The scaling factor accessed by the AGC algorithm. */
|
||||
float agc_scaling;
|
||||
|
||||
int constellation_state;
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
/*! \brief The current delta factor for updating the equalizer coefficients. */
|
||||
int16_t eq_delta;
|
||||
/*! \brief The adaptive equalizer coefficients. */
|
||||
complexi16_t eq_coeff[V22BIS_EQUALIZER_LEN];
|
||||
/*! \brief The equalizer signal buffer. */
|
||||
complexi16_t eq_buf[V22BIS_EQUALIZER_LEN];
|
||||
#else
|
||||
/*! \brief The current delta factor for updating the equalizer coefficients. */
|
||||
float eq_delta;
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
/*! \brief The adaptive equalizer coefficients. */
|
||||
complexf_t eq_coeff[V22BIS_EQUALIZER_LEN];
|
||||
complexi_t eq_coeff[2*V22BIS_EQUALIZER_LEN + 1];
|
||||
/*! \brief The equalizer signal buffer. */
|
||||
complexf_t eq_buf[V22BIS_EQUALIZER_LEN];
|
||||
complexi_t eq_buf[V22BIS_EQUALIZER_MASK + 1];
|
||||
#else
|
||||
complexf_t eq_coeff[2*V22BIS_EQUALIZER_LEN + 1];
|
||||
complexf_t eq_buf[V22BIS_EQUALIZER_MASK + 1];
|
||||
#endif
|
||||
/*! \brief Current offset into the equalizer buffer. */
|
||||
int eq_step;
|
||||
@ -204,24 +183,11 @@ struct v22bis_state_s
|
||||
/* Transmit section */
|
||||
struct
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
/*! \brief The guard tone level. */
|
||||
int16_t guard_tone_gain;
|
||||
/*! \brief The gain factor needed to achieve the specified output power. */
|
||||
int16_t gain;
|
||||
/*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
|
||||
int16_t rrc_filter_re[V22BIS_TX_FILTER_STEPS];
|
||||
int16_t rrc_filter_im[V22BIS_TX_FILTER_STEPS];
|
||||
#else
|
||||
/*! \brief The guard tone level. */
|
||||
float guard_tone_gain;
|
||||
/*! \brief The gain factor needed to achieve the specified output power. */
|
||||
float gain;
|
||||
/*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
|
||||
float rrc_filter_re[V22BIS_TX_FILTER_STEPS];
|
||||
float rrc_filter_im[V22BIS_TX_FILTER_STEPS];
|
||||
#endif
|
||||
|
||||
/*! \brief The route raised cosine (RRC) pulse shaping filter buffer. */
|
||||
complexf_t rrc_filter[2*V22BIS_TX_FILTER_STEPS];
|
||||
/*! \brief Current offset into the RRC pulse shaping filter buffer. */
|
||||
int rrc_filter_step;
|
||||
|
||||
@ -243,6 +209,7 @@ struct v22bis_state_s
|
||||
uint32_t guard_phase;
|
||||
/*! \brief The update rate for the phase of the guard tone (i.e. the DDS increment). */
|
||||
int32_t guard_phase_rate;
|
||||
float guard_level;
|
||||
/*! \brief The current fractional phase of the baud timing. */
|
||||
int baud_phase;
|
||||
/*! \brief The code number for the current position in the constellation. */
|
||||
|
@ -61,6 +61,8 @@ enum
|
||||
*/
|
||||
typedef struct v22bis_state_s v22bis_state_t;
|
||||
|
||||
extern const complexf_t v22bis_constellation[16];
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C"
|
||||
{
|
||||
@ -86,11 +88,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx_fillin(v22bis_state_t *s, int len);
|
||||
\brief Get a snapshot of the current equalizer coefficients.
|
||||
\param coeffs The vector of complex coefficients.
|
||||
\return The number of coefficients in the vector. */
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
SPAN_DECLARE(int) v22bis_rx_equalizer_state(v22bis_state_t *s, complexi16_t **coeffs);
|
||||
#else
|
||||
SPAN_DECLARE(int) v22bis_rx_equalizer_state(v22bis_state_t *s, complexf_t **coeffs);
|
||||
#endif
|
||||
|
||||
/*! Get the current received carrier frequency.
|
||||
\param s The modem context.
|
||||
|
@ -109,7 +109,7 @@
|
||||
#include "spandsp/private/t38_terminal.h"
|
||||
|
||||
/* Settings suitable for paced transmission over a UDP transport */
|
||||
#define DEFAULT_MS_PER_TX_CHUNK 30
|
||||
#define DEFAULT_US_PER_TX_CHUNK 30000
|
||||
|
||||
#define INDICATOR_TX_COUNT 3
|
||||
#define DATA_TX_COUNT 1
|
||||
@ -613,7 +613,8 @@ static void send_hdlc(void *user_data, const uint8_t *msg, int len)
|
||||
}
|
||||
else
|
||||
{
|
||||
s->t38_fe.hdlc_tx.extra_bits = extra_bits_in_stuffed_frame(msg, len);
|
||||
if (s->t38_fe.us_per_tx_chunk)
|
||||
s->t38_fe.hdlc_tx.extra_bits = extra_bits_in_stuffed_frame(msg, len);
|
||||
bit_reverse(s->t38_fe.hdlc_tx.buf, msg, len);
|
||||
s->t38_fe.hdlc_tx.len = len;
|
||||
s->t38_fe.hdlc_tx.ptr = 0;
|
||||
@ -624,7 +625,7 @@ static void send_hdlc(void *user_data, const uint8_t *msg, int len)
|
||||
|
||||
static __inline__ int bits_to_us(t38_terminal_state_t *s, int bits)
|
||||
{
|
||||
if (s->t38_fe.ms_per_tx_chunk == 0 || s->t38_fe.tx_bit_rate == 0)
|
||||
if (s->t38_fe.us_per_tx_chunk == 0 || s->t38_fe.tx_bit_rate == 0)
|
||||
return 0;
|
||||
/*endif*/
|
||||
return bits*1000000/s->t38_fe.tx_bit_rate;
|
||||
@ -634,9 +635,9 @@ static __inline__ int bits_to_us(t38_terminal_state_t *s, int bits)
|
||||
static void set_octets_per_data_packet(t38_terminal_state_t *s, int bit_rate)
|
||||
{
|
||||
s->t38_fe.tx_bit_rate = bit_rate;
|
||||
if (s->t38_fe.ms_per_tx_chunk)
|
||||
if (s->t38_fe.us_per_tx_chunk)
|
||||
{
|
||||
s->t38_fe.octets_per_data_packet = s->t38_fe.ms_per_tx_chunk*bit_rate/(8*1000);
|
||||
s->t38_fe.octets_per_data_packet = (s->t38_fe.us_per_tx_chunk/1000)*bit_rate/(8*1000);
|
||||
/* Make sure we have a positive number (i.e. we didn't truncate to zero). */
|
||||
if (s->t38_fe.octets_per_data_packet < 1)
|
||||
s->t38_fe.octets_per_data_packet = 1;
|
||||
@ -660,14 +661,12 @@ static int set_no_signal(t38_terminal_state_t *s)
|
||||
return delay;
|
||||
/*endif*/
|
||||
s->t38_fe.timed_step = T38_TIMED_STEP_NO_SIGNAL;
|
||||
#if 0
|
||||
if ((s->t38_fe.chunking_modes & T38_CHUNKING_SEND_2S_REGULAR_INDICATORS))
|
||||
s->t38_fe.timeout_tx_samples = s->t38_fe.next_tx_samples + us_to_samples(2000000);
|
||||
else
|
||||
s->t38_fe.timeout_tx_samples = 0;
|
||||
/*endif*/
|
||||
#endif
|
||||
return s->t38_fe.ms_per_tx_chunk*1000;
|
||||
return s->t38_fe.us_per_tx_chunk;
|
||||
}
|
||||
/*endif*/
|
||||
if ((delay = t38_core_send_indicator(&s->t38_fe.t38, T38_IND_NO_SIGNAL)) < 0)
|
||||
@ -685,12 +684,10 @@ static int stream_no_signal(t38_terminal_state_t *s)
|
||||
if ((delay = t38_core_send_indicator(&s->t38_fe.t38, 0x100 | T38_IND_NO_SIGNAL)) < 0)
|
||||
return delay;
|
||||
/*endif*/
|
||||
#if 0
|
||||
if (s->t38_fe.timeout_tx_samples && s->t38_fe.next_tx_samples >= s->t38_fe.timeout_tx_samples)
|
||||
s->t38_fe.timed_step = T38_TIMED_STEP_NONE;
|
||||
/*endif*/
|
||||
#endif
|
||||
return s->t38_fe.ms_per_tx_chunk*1000;
|
||||
return s->t38_fe.us_per_tx_chunk;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
@ -717,20 +714,19 @@ static int stream_non_ecm(t38_terminal_state_t *s)
|
||||
}
|
||||
else
|
||||
{
|
||||
delay = 75000;
|
||||
if (fe->us_per_tx_chunk)
|
||||
delay = 75000;
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
fe->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_2;
|
||||
#if 0
|
||||
fe->timeout_tx_samples = fe->next_tx_samples
|
||||
+ us_to_samples(t38_core_send_training_delay(&fe->t38, fe->next_tx_indicator));
|
||||
#endif
|
||||
fe->next_tx_samples = fe->samples;
|
||||
break;
|
||||
case T38_TIMED_STEP_NON_ECM_MODEM_2:
|
||||
/* Switch on a fast modem, and give the training time to complete */
|
||||
#if 0
|
||||
if ((s->t38_fe.chunking_modes & T38_CHUNKING_SEND_REGULAR_INDICATORS))
|
||||
if ((fe->chunking_modes & T38_CHUNKING_SEND_REGULAR_INDICATORS))
|
||||
{
|
||||
if ((delay = t38_core_send_indicator(&fe->t38, 0x100 | fe->next_tx_indicator)) < 0)
|
||||
return delay;
|
||||
@ -738,10 +734,9 @@ static int stream_non_ecm(t38_terminal_state_t *s)
|
||||
if (fe->next_tx_samples >= fe->timeout_tx_samples)
|
||||
fe->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_3;
|
||||
/*endif*/
|
||||
return fe->ms_per_tx_chunk*1000;
|
||||
return fe->us_per_tx_chunk;
|
||||
}
|
||||
/*endif*/
|
||||
#endif
|
||||
if ((delay = t38_core_send_indicator(&fe->t38, fe->next_tx_indicator)) < 0)
|
||||
return delay;
|
||||
/*endif*/
|
||||
@ -760,7 +755,7 @@ static int stream_non_ecm(t38_terminal_state_t *s)
|
||||
if (len < fe->octets_per_data_packet)
|
||||
{
|
||||
/* That's the end of the image data. */
|
||||
if (s->t38_fe.ms_per_tx_chunk)
|
||||
if (fe->us_per_tx_chunk)
|
||||
{
|
||||
/* Pad the end of the data with some zeros. If we just stop abruptly
|
||||
at the end of the EOLs, some ATAs fail to clean up properly before
|
||||
@ -781,7 +776,7 @@ static int stream_non_ecm(t38_terminal_state_t *s)
|
||||
return res;
|
||||
/*endif*/
|
||||
fe->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_5;
|
||||
delay = 0;
|
||||
front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE);
|
||||
break;
|
||||
}
|
||||
/*endif*/
|
||||
@ -790,7 +785,9 @@ static int stream_non_ecm(t38_terminal_state_t *s)
|
||||
if ((res = t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_T4_NON_ECM_DATA, buf, len, T38_PACKET_CATEGORY_IMAGE_DATA)) < 0)
|
||||
return res;
|
||||
/*endif*/
|
||||
delay = bits_to_us(s, 8*len);
|
||||
if (fe->us_per_tx_chunk)
|
||||
delay = bits_to_us(s, 8*len);
|
||||
/*endif*/
|
||||
break;
|
||||
case T38_TIMED_STEP_NON_ECM_MODEM_4:
|
||||
/* Send padding */
|
||||
@ -806,9 +803,8 @@ static int stream_non_ecm(t38_terminal_state_t *s)
|
||||
fe->timed_step = T38_TIMED_STEP_NON_ECM_MODEM_5;
|
||||
/* Allow a bit more time than the data will take to play out, to ensure the far ATA does not
|
||||
cut things short. */
|
||||
delay = bits_to_us(s, 8*len);
|
||||
if (s->t38_fe.ms_per_tx_chunk)
|
||||
delay += 60000;
|
||||
if (fe->us_per_tx_chunk)
|
||||
delay = bits_to_us(s, 8*len) + 60000;
|
||||
/*endif*/
|
||||
front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE);
|
||||
break;
|
||||
@ -818,12 +814,21 @@ static int stream_non_ecm(t38_terminal_state_t *s)
|
||||
if ((res = t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_T4_NON_ECM_DATA, buf, len, T38_PACKET_CATEGORY_IMAGE_DATA)) < 0)
|
||||
return res;
|
||||
/*endif*/
|
||||
delay = bits_to_us(s, 8*len);
|
||||
if (fe->us_per_tx_chunk)
|
||||
delay = bits_to_us(s, 8*len);
|
||||
/*endif*/
|
||||
break;
|
||||
case T38_TIMED_STEP_NON_ECM_MODEM_5:
|
||||
/* This should not be needed, since the message above indicates the end of the signal, but it
|
||||
seems like it can improve compatibility with quirky implementations. */
|
||||
return set_no_signal(s);
|
||||
delay = set_no_signal(s);
|
||||
if (fe->queued_timed_step != T38_TIMED_STEP_NONE)
|
||||
{
|
||||
fe->timed_step = fe->queued_timed_step;
|
||||
fe->queued_timed_step = T38_TIMED_STEP_NONE;
|
||||
}
|
||||
/*endif*/
|
||||
return delay;
|
||||
}
|
||||
/*endswitch*/
|
||||
}
|
||||
@ -858,22 +863,19 @@ static int stream_hdlc(t38_terminal_state_t *s)
|
||||
}
|
||||
else
|
||||
{
|
||||
delay = 75000;
|
||||
delay = (fe->us_per_tx_chunk) ? 75000 : 0;
|
||||
}
|
||||
/*endif*/
|
||||
fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_2;
|
||||
#if 0
|
||||
fe->timeout_tx_samples = fe->next_tx_samples
|
||||
+ us_to_samples(t38_core_send_training_delay(&fe->t38, fe->next_tx_indicator))
|
||||
+ us_to_samples(t38_core_send_flags_delay(&fe->t38, fe->next_tx_indicator))
|
||||
+ us_to_samples(delay);
|
||||
#endif
|
||||
fe->next_tx_samples = fe->samples;
|
||||
break;
|
||||
case T38_TIMED_STEP_HDLC_MODEM_2:
|
||||
/* Send HDLC preambling */
|
||||
#if 0
|
||||
if ((s->t38_fe.chunking_modes & T38_CHUNKING_SEND_REGULAR_INDICATORS))
|
||||
if ((fe->chunking_modes & T38_CHUNKING_SEND_REGULAR_INDICATORS))
|
||||
{
|
||||
if ((delay = t38_core_send_indicator(&fe->t38, 0x100 | fe->next_tx_indicator)) < 0)
|
||||
return delay;
|
||||
@ -881,10 +883,9 @@ static int stream_hdlc(t38_terminal_state_t *s)
|
||||
if (fe->next_tx_samples >= fe->timeout_tx_samples)
|
||||
fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_3;
|
||||
/*endif*/
|
||||
return fe->ms_per_tx_chunk*1000;
|
||||
return fe->us_per_tx_chunk;
|
||||
}
|
||||
/*endif*/
|
||||
#endif
|
||||
if ((delay = t38_core_send_indicator(&fe->t38, fe->next_tx_indicator)) < 0)
|
||||
return delay;
|
||||
/*endif*/
|
||||
@ -897,7 +898,7 @@ static int stream_hdlc(t38_terminal_state_t *s)
|
||||
if (fe->octets_per_data_packet >= i)
|
||||
{
|
||||
/* The last part of an HDLC frame */
|
||||
if (fe->chunking_modes & T38_CHUNKING_MERGE_FCS_WITH_DATA)
|
||||
if ((fe->chunking_modes & T38_CHUNKING_MERGE_FCS_WITH_DATA))
|
||||
{
|
||||
/* Copy the data, as we might be about to refill the buffer it is in */
|
||||
memcpy(buf, &fe->hdlc_tx.buf[fe->hdlc_tx.ptr], i);
|
||||
@ -911,12 +912,24 @@ static int stream_hdlc(t38_terminal_state_t *s)
|
||||
fe->hdlc_tx.len = 0;
|
||||
front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE);
|
||||
/* The above step should have got the next HDLC step ready - either another frame, or an instruction to stop transmission. */
|
||||
if (fe->hdlc_tx.len < 0)
|
||||
if (fe->hdlc_tx.len >= 0)
|
||||
{
|
||||
data_fields[1].field_type = T38_FIELD_HDLC_FCS_OK;
|
||||
data_fields[1].field = NULL;
|
||||
data_fields[1].field_len = 0;
|
||||
category = (fe->current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA : T38_PACKET_CATEGORY_IMAGE_DATA;
|
||||
if ((res = t38_core_send_data_multi_field(&fe->t38, fe->current_tx_data_type, data_fields, 2, category)) < 0)
|
||||
return res;
|
||||
/*endif*/
|
||||
fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_3;
|
||||
delay = bits_to_us(s, i*8 + fe->hdlc_tx.extra_bits);
|
||||
}
|
||||
else
|
||||
{
|
||||
data_fields[1].field_type = T38_FIELD_HDLC_FCS_OK_SIG_END;
|
||||
data_fields[1].field = NULL;
|
||||
data_fields[1].field_len = 0;
|
||||
category = (s->t38_fe.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA_END : T38_PACKET_CATEGORY_IMAGE_DATA_END;
|
||||
category = (fe->current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA_END : T38_PACKET_CATEGORY_IMAGE_DATA_END;
|
||||
if ((res = t38_core_send_data_multi_field(&fe->t38, fe->current_tx_data_type, data_fields, 2, category)) < 0)
|
||||
return res;
|
||||
/*endif*/
|
||||
@ -924,28 +937,16 @@ static int stream_hdlc(t38_terminal_state_t *s)
|
||||
/* We add a bit of extra time here, as with some implementations
|
||||
the carrier falling too abruptly causes data loss. */
|
||||
delay = bits_to_us(s, i*8 + fe->hdlc_tx.extra_bits);
|
||||
if (s->t38_fe.ms_per_tx_chunk)
|
||||
if (fe->us_per_tx_chunk)
|
||||
delay += 100000;
|
||||
/*endif*/
|
||||
front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE);
|
||||
}
|
||||
else
|
||||
{
|
||||
data_fields[1].field_type = T38_FIELD_HDLC_FCS_OK;
|
||||
data_fields[1].field = NULL;
|
||||
data_fields[1].field_len = 0;
|
||||
category = (s->t38_fe.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA : T38_PACKET_CATEGORY_IMAGE_DATA;
|
||||
if ((res = t38_core_send_data_multi_field(&fe->t38, fe->current_tx_data_type, data_fields, 2, category)) < 0)
|
||||
return res;
|
||||
/*endif*/
|
||||
fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_3;
|
||||
delay = bits_to_us(s, i*8 + fe->hdlc_tx.extra_bits);
|
||||
}
|
||||
/*endif*/
|
||||
break;
|
||||
}
|
||||
/*endif*/
|
||||
category = (s->t38_fe.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA : T38_PACKET_CATEGORY_IMAGE_DATA;
|
||||
category = (fe->current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA : T38_PACKET_CATEGORY_IMAGE_DATA;
|
||||
if ((res = t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_HDLC_DATA, &fe->hdlc_tx.buf[fe->hdlc_tx.ptr], i, category)) < 0)
|
||||
return res;
|
||||
/*endif*/
|
||||
@ -954,7 +955,7 @@ static int stream_hdlc(t38_terminal_state_t *s)
|
||||
else
|
||||
{
|
||||
i = fe->octets_per_data_packet;
|
||||
category = (s->t38_fe.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA : T38_PACKET_CATEGORY_IMAGE_DATA;
|
||||
category = (fe->current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA : T38_PACKET_CATEGORY_IMAGE_DATA;
|
||||
if ((res = t38_core_send_data(&fe->t38, fe->current_tx_data_type, T38_FIELD_HDLC_DATA, &fe->hdlc_tx.buf[fe->hdlc_tx.ptr], i, category)) < 0)
|
||||
return res;
|
||||
/*endif*/
|
||||
@ -970,10 +971,28 @@ static int stream_hdlc(t38_terminal_state_t *s)
|
||||
fe->hdlc_tx.len = 0;
|
||||
front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE);
|
||||
/* The above step should have got the next HDLC step ready - either another frame, or an instruction to stop transmission. */
|
||||
if (fe->hdlc_tx.len < 0)
|
||||
if (fe->hdlc_tx.len >= 0)
|
||||
{
|
||||
if (fe->hdlc_tx.len == 0)
|
||||
{
|
||||
/* Now, how did we get here? We have finished a frame, but have no new frame to
|
||||
send, and no end of transmission condition. */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "No new frame or end transmission condition.\n");
|
||||
}
|
||||
/*endif*/
|
||||
/* Finish the current frame off, and prepare for the next one. */
|
||||
category = (fe->current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA : T38_PACKET_CATEGORY_IMAGE_DATA;
|
||||
if ((res = t38_core_send_data(&fe->t38, previous, T38_FIELD_HDLC_FCS_OK, NULL, 0, category)) < 0)
|
||||
return res;
|
||||
/*endif*/
|
||||
fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_3;
|
||||
/* We should now wait enough time for everything to clear through an analogue modem at the far end. */
|
||||
delay = bits_to_us(s, fe->hdlc_tx.extra_bits);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* End of transmission */
|
||||
category = (s->t38_fe.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA_END : T38_PACKET_CATEGORY_IMAGE_DATA_END;
|
||||
category = (fe->current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA_END : T38_PACKET_CATEGORY_IMAGE_DATA_END;
|
||||
if ((res = t38_core_send_data(&fe->t38, previous, T38_FIELD_HDLC_FCS_OK_SIG_END, NULL, 0, category)) < 0)
|
||||
return res;
|
||||
/*endif*/
|
||||
@ -981,33 +1000,24 @@ static int stream_hdlc(t38_terminal_state_t *s)
|
||||
/* We add a bit of extra time here, as with some implementations
|
||||
the carrier falling too abruptly causes data loss. */
|
||||
delay = bits_to_us(s, fe->hdlc_tx.extra_bits);
|
||||
if (s->t38_fe.ms_per_tx_chunk)
|
||||
if (fe->us_per_tx_chunk)
|
||||
delay += 100000;
|
||||
/*endif*/
|
||||
front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE);
|
||||
break;
|
||||
}
|
||||
/*endif*/
|
||||
if (fe->hdlc_tx.len == 0)
|
||||
{
|
||||
/* Now, how did we get here? We have finished a frame, but have no new frame to
|
||||
send, and no end of transmission condition. */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "No new frame or end transmission condition.\n");
|
||||
}
|
||||
/*endif*/
|
||||
/* Finish the current frame off, and prepare for the next one. */
|
||||
category = (s->t38_fe.current_tx_data_type == T38_DATA_V21) ? T38_PACKET_CATEGORY_CONTROL_DATA : T38_PACKET_CATEGORY_IMAGE_DATA;
|
||||
if ((res = t38_core_send_data(&fe->t38, previous, T38_FIELD_HDLC_FCS_OK, NULL, 0, category)) < 0)
|
||||
return res;
|
||||
/*endif*/
|
||||
fe->timed_step = T38_TIMED_STEP_HDLC_MODEM_3;
|
||||
/* We should now wait enough time for everything to clear through an analogue modem at the far end. */
|
||||
delay = bits_to_us(s, fe->hdlc_tx.extra_bits);
|
||||
break;
|
||||
case T38_TIMED_STEP_HDLC_MODEM_5:
|
||||
/* Note that some boxes do not like us sending a T38_FIELD_HDLC_SIG_END at this point.
|
||||
A T38_IND_NO_SIGNAL should always be OK. */
|
||||
return set_no_signal(s);
|
||||
delay = set_no_signal(s);
|
||||
if (fe->queued_timed_step != T38_TIMED_STEP_NONE)
|
||||
{
|
||||
fe->timed_step = fe->queued_timed_step;
|
||||
fe->queued_timed_step = T38_TIMED_STEP_NONE;
|
||||
}
|
||||
/*endif*/
|
||||
return delay;
|
||||
}
|
||||
/*endswitch*/
|
||||
}
|
||||
@ -1035,7 +1045,7 @@ static int stream_ced(t38_terminal_state_t *s)
|
||||
if ((delay = t38_core_send_indicator(&fe->t38, T38_IND_NO_SIGNAL)) < 0)
|
||||
return delay;
|
||||
/*endif*/
|
||||
delay = 200000;
|
||||
delay = (fe->us_per_tx_chunk) ? 200000 : 0;
|
||||
fe->next_tx_samples = fe->samples;
|
||||
break;
|
||||
case T38_TIMED_STEP_CED_2:
|
||||
@ -1048,7 +1058,7 @@ static int stream_ced(t38_terminal_state_t *s)
|
||||
break;
|
||||
case T38_TIMED_STEP_CED_3:
|
||||
/* End of CED */
|
||||
fe->timed_step = T38_TIMED_STEP_NONE;
|
||||
fe->timed_step = fe->queued_timed_step;
|
||||
front_end_status(s, T30_FRONT_END_SEND_STEP_COMPLETE);
|
||||
return 0;
|
||||
}
|
||||
@ -1078,17 +1088,15 @@ static int stream_cng(t38_terminal_state_t *s)
|
||||
if ((delay = t38_core_send_indicator(&fe->t38, T38_IND_NO_SIGNAL)) < 0)
|
||||
return delay;
|
||||
/*endif*/
|
||||
delay = 200000;
|
||||
delay = (fe->us_per_tx_chunk) ? 200000 : 0;
|
||||
fe->next_tx_samples = fe->samples;
|
||||
break;
|
||||
case T38_TIMED_STEP_CNG_2:
|
||||
/* Initial short delay over. Send the CNG indicator. CNG persists until something
|
||||
coming the other way interrupts it, or a long timeout controlled by the T.30 engine
|
||||
expires. */
|
||||
fe->timed_step = T38_TIMED_STEP_NONE;
|
||||
if ((delay = t38_core_send_indicator(&fe->t38, T38_IND_CNG)) < 0)
|
||||
return delay;
|
||||
/*endif*/
|
||||
delay = t38_core_send_indicator(&fe->t38, T38_IND_CNG);
|
||||
fe->timed_step = fe->queued_timed_step;
|
||||
fe->current_tx_data_type = T38_DATA_NONE;
|
||||
return delay;
|
||||
}
|
||||
@ -1123,7 +1131,7 @@ SPAN_DECLARE(int) t38_terminal_send_timeout(t38_terminal_state_t *s, int samples
|
||||
/*endif*/
|
||||
/* Wait until the right time comes along, unless we are working in "no delays" mode, while talking to an
|
||||
IAF terminal. */
|
||||
if (fe->ms_per_tx_chunk && fe->samples < fe->next_tx_samples)
|
||||
if (fe->us_per_tx_chunk && fe->samples < fe->next_tx_samples)
|
||||
return FALSE;
|
||||
/*endif*/
|
||||
/* Its time to send something */
|
||||
@ -1175,22 +1183,26 @@ static void set_rx_type(void *user_data, int type, int bit_rate, int short_train
|
||||
|
||||
static void start_tx(t38_terminal_front_end_state_t *fe, int use_hdlc)
|
||||
{
|
||||
int step;
|
||||
|
||||
/* The actual transmission process depends on whether we are sending at a paced manner,
|
||||
for interaction with a traditional FAX machine, or streaming as fast as we can, normally
|
||||
over a TCP connection to a machine directly connected to the internet. */
|
||||
if (fe->ms_per_tx_chunk)
|
||||
|
||||
step = (use_hdlc) ? T38_TIMED_STEP_HDLC_MODEM : T38_TIMED_STEP_NON_ECM_MODEM;
|
||||
if (fe->timed_step == T38_TIMED_STEP_NONE)
|
||||
{
|
||||
/* Start the paced packet transmission process. */
|
||||
fe->timed_step = (use_hdlc) ? T38_TIMED_STEP_HDLC_MODEM : T38_TIMED_STEP_NON_ECM_MODEM;
|
||||
if (fe->next_tx_samples < fe->samples)
|
||||
fe->next_tx_samples = fe->samples;
|
||||
/*endif*/
|
||||
fe->queued_timed_step = T38_TIMED_STEP_NONE;
|
||||
fe->timed_step = step;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Start the fast streaming transmission process. */
|
||||
fe->queued_timed_step = step;
|
||||
}
|
||||
/*endif*/
|
||||
if (fe->next_tx_samples < fe->samples)
|
||||
fe->next_tx_samples = fe->samples;
|
||||
/*endif*/
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
@ -1217,8 +1229,21 @@ static void set_tx_type(void *user_data, int type, int bit_rate, int short_train
|
||||
fe->current_tx_data_type = T38_DATA_NONE;
|
||||
break;
|
||||
case T30_MODEM_PAUSE:
|
||||
fe->next_tx_samples = fe->samples + ms_to_samples(short_train);
|
||||
fe->timed_step = T38_TIMED_STEP_PAUSE;
|
||||
if (s->t38_fe.us_per_tx_chunk)
|
||||
fe->next_tx_samples = fe->samples + ms_to_samples(short_train);
|
||||
else
|
||||
fe->next_tx_samples = fe->samples;
|
||||
/*endif*/
|
||||
if (fe->timed_step == T38_TIMED_STEP_NONE)
|
||||
{
|
||||
fe->queued_timed_step = T38_TIMED_STEP_NONE;
|
||||
fe->timed_step = T38_TIMED_STEP_PAUSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
fe->queued_timed_step = T38_TIMED_STEP_PAUSE;
|
||||
}
|
||||
/*endif*/
|
||||
fe->current_tx_data_type = T38_DATA_NONE;
|
||||
break;
|
||||
case T30_MODEM_CED:
|
||||
@ -1316,7 +1341,7 @@ SPAN_DECLARE(void) t38_terminal_set_config(t38_terminal_state_t *s, int config)
|
||||
t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_CONTROL_DATA_END, 1);
|
||||
t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_IMAGE_DATA, 1);
|
||||
t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_IMAGE_DATA_END, 1);
|
||||
s->t38_fe.ms_per_tx_chunk = 0;
|
||||
s->t38_fe.us_per_tx_chunk = 0;
|
||||
s->t38_fe.chunking_modes &= ~T38_CHUNKING_SEND_REGULAR_INDICATORS;
|
||||
s->t38_fe.chunking_modes |= T38_CHUNKING_MERGE_FCS_WITH_DATA;
|
||||
}
|
||||
@ -1334,7 +1359,7 @@ SPAN_DECLARE(void) t38_terminal_set_config(t38_terminal_state_t *s, int config)
|
||||
t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_CONTROL_DATA_END, DATA_END_TX_COUNT);
|
||||
t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_IMAGE_DATA, DATA_TX_COUNT);
|
||||
t38_set_redundancy_control(&s->t38_fe.t38, T38_PACKET_CATEGORY_IMAGE_DATA_END, DATA_END_TX_COUNT);
|
||||
s->t38_fe.ms_per_tx_chunk = DEFAULT_MS_PER_TX_CHUNK;
|
||||
s->t38_fe.us_per_tx_chunk = DEFAULT_US_PER_TX_CHUNK;
|
||||
if ((config & (T38_TERMINAL_OPTION_REGULAR_INDICATORS | T38_TERMINAL_OPTION_2S_REPEATING_INDICATORS)))
|
||||
s->t38_fe.chunking_modes |= T38_CHUNKING_SEND_REGULAR_INDICATORS;
|
||||
else
|
||||
@ -1401,6 +1426,7 @@ static int t38_terminal_t38_fe_restart(t38_terminal_state_t *t)
|
||||
s->next_tx_samples = 0;
|
||||
|
||||
s->hdlc_tx.ptr = 0;
|
||||
s->hdlc_tx.extra_bits = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1424,6 +1450,7 @@ static int t38_terminal_t38_fe_init(t38_terminal_state_t *t,
|
||||
|
||||
s->rx_signal_present = FALSE;
|
||||
s->timed_step = T38_TIMED_STEP_NONE;
|
||||
s->queued_timed_step = T38_TIMED_STEP_NONE;
|
||||
//s->iaf = T30_IAF_MODE_T37 | T30_IAF_MODE_T38;
|
||||
s->iaf = T30_IAF_MODE_T38;
|
||||
|
||||
@ -1432,6 +1459,7 @@ static int t38_terminal_t38_fe_init(t38_terminal_state_t *t,
|
||||
s->chunking_modes = T38_CHUNKING_ALLOW_TEP_TIME;
|
||||
|
||||
s->hdlc_tx.ptr = 0;
|
||||
s->hdlc_tx.extra_bits = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -69,9 +69,9 @@
|
||||
#include "spandsp/private/logging.h"
|
||||
#include "spandsp/private/v22bis.h"
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
#include "v22bis_rx_1200_fixed_rrc.h"
|
||||
#include "v22bis_rx_2400_fixed_rrc.h"
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
#include "v22bis_rx_1200_floating_rrc.h"
|
||||
#include "v22bis_rx_2400_floating_rrc.h"
|
||||
#else
|
||||
#include "v22bis_rx_1200_floating_rrc.h"
|
||||
#include "v22bis_rx_2400_floating_rrc.h"
|
||||
@ -79,11 +79,6 @@
|
||||
|
||||
#define ms_to_symbols(t) (((t)*600)/1000)
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
#define FP_FACTOR 4096
|
||||
#define FP_SHIFT_FACTOR 12
|
||||
#endif
|
||||
|
||||
/*! The adaption rate coefficient for the equalizer */
|
||||
#define EQUALIZER_DELTA 0.25f
|
||||
/*! The number of phase shifted coefficient set for the pulse shaping/bandpass filter */
|
||||
@ -172,28 +167,24 @@ void v22bis_report_status_change(v22bis_state_t *s, int status)
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
SPAN_DECLARE(int) v22bis_rx_equalizer_state(v22bis_state_t *s, complexi16_t **coeffs)
|
||||
#else
|
||||
SPAN_DECLARE(int) v22bis_rx_equalizer_state(v22bis_state_t *s, complexf_t **coeffs)
|
||||
#endif
|
||||
{
|
||||
*coeffs = s->rx.eq_coeff;
|
||||
return V22BIS_EQUALIZER_LEN;
|
||||
return 2*V22BIS_EQUALIZER_LEN + 1;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
void v22bis_equalizer_coefficient_reset(v22bis_state_t *s)
|
||||
{
|
||||
/* Start with an equalizer based on everything being perfect */
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
cvec_zeroi16(s->rx.eq_coeff, V22BIS_EQUALIZER_LEN);
|
||||
s->rx.eq_coeff[V22BIS_EQUALIZER_PRE_LEN] = complex_seti16(FP_Q_4_12(3.0), FP_Q_4_12(0.0));
|
||||
s->rx.eq_delta = 32768.0f*EQUALIZER_DELTA/V22BIS_EQUALIZER_LEN;
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
cvec_zeroi16(s->rx.eq_coeff, 2*V22BIS_EQUALIZER_LEN + 1);
|
||||
s->rx.eq_coeff[V22BIS_EQUALIZER_LEN] = complex_seti16(3*FP_FACTOR, 0*FP_FACTOR);
|
||||
s->rx.eq_delta = 32768.0f*EQUALIZER_DELTA/(2*V22BIS_EQUALIZER_LEN + 1);
|
||||
#else
|
||||
cvec_zerof(s->rx.eq_coeff, V22BIS_EQUALIZER_LEN);
|
||||
s->rx.eq_coeff[V22BIS_EQUALIZER_PRE_LEN] = complex_setf(3.0f, 0.0f);
|
||||
s->rx.eq_delta = EQUALIZER_DELTA/V22BIS_EQUALIZER_LEN;
|
||||
cvec_zerof(s->rx.eq_coeff, 2*V22BIS_EQUALIZER_LEN + 1);
|
||||
s->rx.eq_coeff[V22BIS_EQUALIZER_LEN] = complex_setf(3.0f, 0.0f);
|
||||
s->rx.eq_delta = EQUALIZER_DELTA/(2*V22BIS_EQUALIZER_LEN + 1);
|
||||
#endif
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
@ -201,68 +192,63 @@ void v22bis_equalizer_coefficient_reset(v22bis_state_t *s)
|
||||
static void equalizer_reset(v22bis_state_t *s)
|
||||
{
|
||||
v22bis_equalizer_coefficient_reset(s);
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
cvec_zeroi16(s->rx.eq_buf, V22BIS_EQUALIZER_LEN);
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
cvec_zeroi16(s->rx.eq_buf, V22BIS_EQUALIZER_MASK + 1);
|
||||
#else
|
||||
cvec_zerof(s->rx.eq_buf, V22BIS_EQUALIZER_LEN);
|
||||
cvec_zerof(s->rx.eq_buf, V22BIS_EQUALIZER_MASK + 1);
|
||||
#endif
|
||||
s->rx.eq_put_step = 20 - 1;
|
||||
s->rx.eq_step = 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
static __inline__ complexi16_t equalizer_get(v22bis_state_t *s)
|
||||
static complexf_t equalizer_get(v22bis_state_t *s)
|
||||
{
|
||||
complexi32_t zz;
|
||||
complexi16_t z;
|
||||
int i;
|
||||
int p;
|
||||
complexf_t z;
|
||||
complexf_t z1;
|
||||
|
||||
/* Get the next equalized value. */
|
||||
zz = cvec_circular_dot_prodi16(s->rx.eq_buf, s->rx.eq_coeff, V22BIS_EQUALIZER_LEN, s->rx.eq_step);
|
||||
z.re = zz.re >> FP_SHIFT_FACTOR;
|
||||
z.im = zz.im >> FP_SHIFT_FACTOR;
|
||||
z = complex_setf(0.0f, 0.0f);
|
||||
p = s->rx.eq_step - 1;
|
||||
for (i = 0; i < 2*V22BIS_EQUALIZER_LEN + 1; i++)
|
||||
{
|
||||
p = (p - 1) & V22BIS_EQUALIZER_MASK;
|
||||
z1 = complex_mulf(&s->rx.eq_coeff[i], &s->rx.eq_buf[p]);
|
||||
z = complex_addf(&z, &z1);
|
||||
}
|
||||
return z;
|
||||
}
|
||||
#else
|
||||
static __inline__ complexf_t equalizer_get(v22bis_state_t *s)
|
||||
{
|
||||
/* Get the next equalized value. */
|
||||
return cvec_circular_dot_prodf(s->rx.eq_buf, s->rx.eq_coeff, V22BIS_EQUALIZER_LEN, s->rx.eq_step);
|
||||
}
|
||||
#endif
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
static void tune_equalizer(v22bis_state_t *s, const complexi16_t *z, const complexi16_t *target)
|
||||
{
|
||||
complexi16_t err;
|
||||
|
||||
/* Find the x and y mismatch from the exact constellation position. */
|
||||
err.re = target->re*FP_FACTOR - z->re;
|
||||
err.im = target->im*FP_FACTOR - z->im;
|
||||
err.re = ((int32_t) err.re*s->rx.eq_delta) >> 15;
|
||||
err.im = ((int32_t) err.im*s->rx.eq_delta) >> 15;
|
||||
cvec_circular_lmsi16(s->rx.eq_buf, s->rx.eq_coeff, V22BIS_EQUALIZER_LEN, s->rx.eq_step, &err);
|
||||
}
|
||||
#else
|
||||
static void tune_equalizer(v22bis_state_t *s, const complexf_t *z, const complexf_t *target)
|
||||
{
|
||||
complexf_t err;
|
||||
int i;
|
||||
int p;
|
||||
complexf_t ez;
|
||||
complexf_t z1;
|
||||
|
||||
/* Find the x and y mismatch from the exact constellation position. */
|
||||
err = complex_subf(target, z);
|
||||
err.re *= s->rx.eq_delta;
|
||||
err.im *= s->rx.eq_delta;
|
||||
cvec_circular_lmsf(s->rx.eq_buf, s->rx.eq_coeff, V22BIS_EQUALIZER_LEN, s->rx.eq_step, &err);
|
||||
ez = complex_subf(target, z);
|
||||
ez.re *= s->rx.eq_delta;
|
||||
ez.im *= s->rx.eq_delta;
|
||||
|
||||
p = s->rx.eq_step - 1;
|
||||
for (i = 0; i < 2*V22BIS_EQUALIZER_LEN + 1; i++)
|
||||
{
|
||||
p = (p - 1) & V22BIS_EQUALIZER_MASK;
|
||||
z1 = complex_conjf(&s->rx.eq_buf[p]);
|
||||
z1 = complex_mulf(&ez, &z1);
|
||||
s->rx.eq_coeff[i] = complex_addf(&s->rx.eq_coeff[i], &z1);
|
||||
/* If we don't leak a little bit we seem to get some wandering adaption */
|
||||
s->rx.eq_coeff[i].re *= 0.9999f;
|
||||
s->rx.eq_coeff[i].im *= 0.9999f;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
static __inline__ void track_carrier(v22bis_state_t *s, const complexi16_t *z, const complexi16_t *target)
|
||||
#else
|
||||
static __inline__ void track_carrier(v22bis_state_t *s, const complexf_t *z, const complexf_t *target)
|
||||
#endif
|
||||
{
|
||||
float error;
|
||||
|
||||
@ -350,69 +336,40 @@ static int decode_baudx(v22bis_state_t *s, int nearest)
|
||||
|
||||
static __inline__ void symbol_sync(v22bis_state_t *s)
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
int32_t p;
|
||||
int32_t q;
|
||||
complexi16_t zz;
|
||||
complexi16_t a;
|
||||
complexi16_t b;
|
||||
complexi16_t c;
|
||||
#else
|
||||
float p;
|
||||
float q;
|
||||
complexf_t zz;
|
||||
complexf_t a;
|
||||
complexf_t b;
|
||||
complexf_t c;
|
||||
#endif
|
||||
int aa[3];
|
||||
int i;
|
||||
int j;
|
||||
|
||||
/* This routine adapts the position of the half baud samples entering the equalizer. */
|
||||
|
||||
/* Perform a Gardner test for baud alignment on the three most recent samples. */
|
||||
for (i = 0, j = s->rx.eq_step; i < 3; i++)
|
||||
{
|
||||
if (--j < 0)
|
||||
j = V22BIS_EQUALIZER_LEN - 1;
|
||||
aa[i] = j;
|
||||
}
|
||||
if (s->rx.sixteen_way_decisions)
|
||||
{
|
||||
p = s->rx.eq_buf[aa[2]].re - s->rx.eq_buf[aa[0]].re;
|
||||
p *= s->rx.eq_buf[aa[1]].re;
|
||||
p = s->rx.eq_buf[(s->rx.eq_step - 3) & V22BIS_EQUALIZER_MASK].re
|
||||
- s->rx.eq_buf[(s->rx.eq_step - 1) & V22BIS_EQUALIZER_MASK].re;
|
||||
p *= s->rx.eq_buf[(s->rx.eq_step - 2) & V22BIS_EQUALIZER_MASK].re;
|
||||
|
||||
q = s->rx.eq_buf[aa[2]].im - s->rx.eq_buf[aa[0]].im;
|
||||
q *= s->rx.eq_buf[aa[1]].im;
|
||||
q = s->rx.eq_buf[(s->rx.eq_step - 3) & V22BIS_EQUALIZER_MASK].im
|
||||
- s->rx.eq_buf[(s->rx.eq_step - 1) & V22BIS_EQUALIZER_MASK].im;
|
||||
q *= s->rx.eq_buf[(s->rx.eq_step - 2) & V22BIS_EQUALIZER_MASK].im;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Rotate the points to the 45 degree positions, to maximise the effectiveness of
|
||||
the Gardner algorithm. This is particularly significant at the start of operation
|
||||
to pull things in quickly. */
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
zz = complex_seti16(FP_Q_6_10(0.894427), FP_Q_6_10(0.44721f));
|
||||
a = complex_muli16(&s->rx.eq_buf[aa[2]], &zz);
|
||||
b = complex_muli16(&s->rx.eq_buf[aa[1]], &zz);
|
||||
c = complex_muli16(&s->rx.eq_buf[aa[0]], &zz);
|
||||
p = (a.re - c.re)*b.re;
|
||||
q = (a.im - c.im)*b.im;
|
||||
#else
|
||||
zz = complex_setf(0.894427, 0.44721f);
|
||||
a = complex_mulf(&s->rx.eq_buf[aa[2]], &zz);
|
||||
b = complex_mulf(&s->rx.eq_buf[aa[1]], &zz);
|
||||
c = complex_mulf(&s->rx.eq_buf[aa[0]], &zz);
|
||||
a = complex_mulf(&s->rx.eq_buf[(s->rx.eq_step - 3) & V22BIS_EQUALIZER_MASK], &zz);
|
||||
b = complex_mulf(&s->rx.eq_buf[(s->rx.eq_step - 2) & V22BIS_EQUALIZER_MASK], &zz);
|
||||
c = complex_mulf(&s->rx.eq_buf[(s->rx.eq_step - 1) & V22BIS_EQUALIZER_MASK], &zz);
|
||||
p = (a.re - c.re)*b.re;
|
||||
q = (a.im - c.im)*b.im;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
s->rx.gardner_integrate += (p + q > 0) ? s->rx.gardner_step : -s->rx.gardner_step;
|
||||
#else
|
||||
s->rx.gardner_integrate += (p + q > 0.0f) ? s->rx.gardner_step : -s->rx.gardner_step;
|
||||
#endif
|
||||
|
||||
if (abs(s->rx.gardner_integrate) >= 16)
|
||||
{
|
||||
@ -429,21 +386,11 @@ static __inline__ void symbol_sync(v22bis_state_t *s)
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
static void process_half_baud(v22bis_state_t *s, const complexi16_t *sample)
|
||||
#else
|
||||
static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
|
||||
#endif
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
complexi16_t z;
|
||||
complexi16_t zz;
|
||||
const complexi16_t *target;
|
||||
#else
|
||||
complexf_t z;
|
||||
complexf_t zz;
|
||||
const complexf_t *target;
|
||||
#endif
|
||||
int re;
|
||||
int im;
|
||||
int nearest;
|
||||
@ -456,8 +403,7 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
|
||||
/* Add a sample to the equalizer's circular buffer, but don't calculate anything
|
||||
at this time. */
|
||||
s->rx.eq_buf[s->rx.eq_step] = z;
|
||||
if (++s->rx.eq_step >= V22BIS_EQUALIZER_LEN)
|
||||
s->rx.eq_step = 0;
|
||||
s->rx.eq_step = (s->rx.eq_step + 1) & V22BIS_EQUALIZER_MASK;
|
||||
|
||||
/* On alternate insertions we have a whole baud and must process it. */
|
||||
if ((s->rx.baud_phase ^= 1))
|
||||
@ -470,18 +416,6 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
|
||||
/* Find the constellation point */
|
||||
if (s->rx.sixteen_way_decisions)
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
re = (int) (z.re + FP_Q_6_10(3.0f));
|
||||
if (re > 5)
|
||||
re = 5;
|
||||
else if (re < 0)
|
||||
re = 0;
|
||||
im = (int) (z.im + FP_Q_6_10(3.0f));
|
||||
if (im > 5)
|
||||
im = 5;
|
||||
else if (im < 0)
|
||||
im = 0;
|
||||
#else
|
||||
re = (int) (z.re + 3.0f);
|
||||
if (re > 5)
|
||||
re = 5;
|
||||
@ -492,19 +426,13 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
|
||||
im = 5;
|
||||
else if (im < 0)
|
||||
im = 0;
|
||||
#endif
|
||||
nearest = space_map_v22bis[re][im];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Rotate to 45 degrees, to make the slicing trivial */
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
zz = complex_seti16(FP_Q_4_12(0.894427), FP_Q_4_12(0.44721f));
|
||||
zz = complex_muli16(&z, &zz);
|
||||
#else
|
||||
zz = complex_setf(0.894427, 0.44721f);
|
||||
zz = complex_mulf(&z, &zz);
|
||||
#endif
|
||||
nearest = 0x01;
|
||||
if (zz.re < 0.0f)
|
||||
nearest |= 0x04;
|
||||
@ -562,7 +490,10 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
|
||||
error could be higher. */
|
||||
s->rx.gardner_step = 4;
|
||||
s->rx.pattern_repeats = 0;
|
||||
s->rx.training = (s->calling_party) ? V22BIS_RX_TRAINING_STAGE_UNSCRAMBLED_ONES : V22BIS_RX_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
|
||||
if (s->calling_party)
|
||||
s->rx.training = V22BIS_RX_TRAINING_STAGE_UNSCRAMBLED_ONES;
|
||||
else
|
||||
s->rx.training = V22BIS_RX_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
|
||||
/* Be pessimistic and see what the handshake brings */
|
||||
s->negotiated_bit_rate = 1200;
|
||||
break;
|
||||
@ -764,21 +695,12 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
|
||||
{
|
||||
int i;
|
||||
int step;
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
complexi16_t z;
|
||||
complexi16_t zz;
|
||||
complexi16_t sample;
|
||||
int32_t ii;
|
||||
int32_t qq;
|
||||
float vv;
|
||||
#else
|
||||
complexf_t z;
|
||||
complexf_t zz;
|
||||
int32_t power;
|
||||
complexf_t sample;
|
||||
float ii;
|
||||
float qq;
|
||||
#endif
|
||||
int32_t power;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
@ -795,7 +717,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
|
||||
if (s->calling_party)
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
ii = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_2400_re[6], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step) >> 15;
|
||||
ii = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_2400_re[6], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step);
|
||||
#else
|
||||
ii = vec_circular_dot_prodf(s->rx.rrc_filter, rx_pulseshaper_2400_re[6], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step);
|
||||
#endif
|
||||
@ -803,7 +725,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
|
||||
else
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
ii = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_1200_re[6], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step) >> 15;
|
||||
ii = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_1200_re[6], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step);
|
||||
#else
|
||||
ii = vec_circular_dot_prodf(s->rx.rrc_filter, rx_pulseshaper_1200_re[6], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step);
|
||||
#endif
|
||||
@ -831,25 +753,11 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
|
||||
{
|
||||
/* Only spend effort processing this data if the modem is not
|
||||
parked, after a training failure. */
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
z = dds_complexi16(&s->rx.carrier_phase, s->rx.carrier_phase_rate);
|
||||
#else
|
||||
z = dds_complexf(&s->rx.carrier_phase, s->rx.carrier_phase_rate);
|
||||
#endif
|
||||
if (s->rx.training == V22BIS_RX_TRAINING_STAGE_SYMBOL_ACQUISITION)
|
||||
{
|
||||
/* Only AGC during the initial symbol acquisition, and then lock the gain. */
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
vv = 0.18f*3.60f/sqrtf(power);
|
||||
if (vv > 32767.0f)
|
||||
s->rx.agc_scaling = 32767;
|
||||
else if (vv > -32768.0f)
|
||||
s->rx.agc_scaling = -32768;
|
||||
else
|
||||
s->rx.agc_scaling = vv;
|
||||
#else
|
||||
s->rx.agc_scaling = 0.18f*3.60f/sqrtf(power);
|
||||
#endif
|
||||
}
|
||||
/* Put things into the equalization buffer at T/2 rate. The Gardner algorithm
|
||||
will fiddle the step to align this with the symbols. */
|
||||
@ -866,8 +774,8 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
|
||||
if (s->calling_party)
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
ii = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_2400_re[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step) >> 15;
|
||||
qq = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_2400_im[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step) >> 15;
|
||||
ii = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_2400_re[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step);
|
||||
qq = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_2400_im[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step);
|
||||
#else
|
||||
ii = vec_circular_dot_prodf(s->rx.rrc_filter, rx_pulseshaper_2400_re[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step);
|
||||
qq = vec_circular_dot_prodf(s->rx.rrc_filter, rx_pulseshaper_2400_im[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step);
|
||||
@ -876,20 +784,15 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
|
||||
else
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
ii = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_1200_re[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step) >> 15;
|
||||
qq = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_1200_im[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step) >> 15;
|
||||
ii = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_1200_re[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step);
|
||||
qq = vec_circular_dot_prodi16(s->rx.rrc_filter, rx_pulseshaper_1200_im[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step);
|
||||
#else
|
||||
ii = vec_circular_dot_prodf(s->rx.rrc_filter, rx_pulseshaper_1200_re[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step);
|
||||
qq = vec_circular_dot_prodf(s->rx.rrc_filter, rx_pulseshaper_1200_im[step], V22BIS_RX_FILTER_STEPS, s->rx.rrc_filter_step);
|
||||
#endif
|
||||
}
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
sample.re = ((int32_t) ii*s->rx.agc_scaling) >> 10;
|
||||
sample.im = ((int32_t) qq*s->rx.agc_scaling) >> 10;
|
||||
#else
|
||||
sample.re = ii*s->rx.agc_scaling;
|
||||
sample.im = qq*s->rx.agc_scaling;
|
||||
#endif
|
||||
/* Shift to baseband - since this is done in a full complex form, the
|
||||
result is clean, and requires no further filtering apart from the
|
||||
equalizer. */
|
||||
@ -914,7 +817,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx_fillin(v22bis_state_t *s, int len)
|
||||
return 0;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
dds_advance(&s->rx.carrier_phase, s->rx.carrier_phase_rate);
|
||||
#else
|
||||
dds_advancef(&s->rx.carrier_phase, s->rx.carrier_phase_rate);
|
||||
@ -927,7 +830,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx_fillin(v22bis_state_t *s, int len)
|
||||
|
||||
int v22bis_rx_restart(v22bis_state_t *s)
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
vec_zeroi16(s->rx.rrc_filter, sizeof(s->rx.rrc_filter)/sizeof(s->rx.rrc_filter[0]));
|
||||
#else
|
||||
vec_zerof(s->rx.rrc_filter, sizeof(s->rx.rrc_filter)/sizeof(s->rx.rrc_filter[0]));
|
||||
@ -958,13 +861,8 @@ int v22bis_rx_restart(v22bis_state_t *s)
|
||||
s->rx.training_error = 0.0f;
|
||||
s->rx.total_baud_timing_correction = 0;
|
||||
/* We want the carrier to pull in faster on the answerer side, as it has very little time to adapt. */
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
s->rx.carrier_track_i = (s->calling_party) ? 8000 : 40000;
|
||||
s->rx.carrier_track_p = 8000000;
|
||||
#else
|
||||
s->rx.carrier_track_i = (s->calling_party) ? 8000.0f : 40000.0f;
|
||||
s->rx.carrier_track_p = 8000000.0f;
|
||||
#endif
|
||||
|
||||
s->negotiated_bit_rate = 1200;
|
||||
|
||||
|
@ -62,7 +62,7 @@
|
||||
#include "spandsp/private/logging.h"
|
||||
#include "spandsp/private/v22bis.h"
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
#include "v22bis_tx_fixed_rrc.h"
|
||||
#else
|
||||
#include "v22bis_tx_floating_rrc.h"
|
||||
@ -246,28 +246,24 @@ static const int phase_steps[4] =
|
||||
1, 0, 2, 3
|
||||
};
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
const complexi16_t v22bis_constellation[16] =
|
||||
#else
|
||||
const complexf_t v22bis_constellation[16] =
|
||||
#endif
|
||||
{
|
||||
{ 1, 1},
|
||||
{ 3, 1}, /* 1200bps 00 */
|
||||
{ 1, 3},
|
||||
{ 3, 3},
|
||||
{-1, 1},
|
||||
{-1, 3}, /* 1200bps 01 */
|
||||
{-3, 1},
|
||||
{-3, 3},
|
||||
{-1, -1},
|
||||
{-3, -1}, /* 1200bps 10 */
|
||||
{-1, -3},
|
||||
{-3, -3},
|
||||
{ 1, -1},
|
||||
{ 1, -3}, /* 1200bps 11 */
|
||||
{ 3, -1},
|
||||
{ 3, -3}
|
||||
{ 1.0f, 1.0f},
|
||||
{ 3.0f, 1.0f}, /* 1200bps 00 */
|
||||
{ 1.0f, 3.0f},
|
||||
{ 3.0f, 3.0f},
|
||||
{-1.0f, 1.0f},
|
||||
{-1.0f, 3.0f}, /* 1200bps 01 */
|
||||
{-3.0f, 1.0f},
|
||||
{-3.0f, 3.0f},
|
||||
{-1.0f, -1.0f},
|
||||
{-3.0f, -1.0f}, /* 1200bps 10 */
|
||||
{-1.0f, -3.0f},
|
||||
{-3.0f, -3.0f},
|
||||
{ 1.0f, -1.0f},
|
||||
{ 1.0f, -3.0f}, /* 1200bps 11 */
|
||||
{ 3.0f, -1.0f},
|
||||
{ 3.0f, -3.0f}
|
||||
};
|
||||
|
||||
static int fake_get_bit(void *user_data)
|
||||
@ -312,17 +308,9 @@ static __inline__ int get_scrambled_bit(v22bis_state_t *s)
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
static complexi16_t training_get(v22bis_state_t *s)
|
||||
#else
|
||||
static complexf_t training_get(v22bis_state_t *s)
|
||||
#endif
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
static const complexi16_t zero = {0, 0};
|
||||
#else
|
||||
static const complexf_t zero = {0.0f, 0.0f};
|
||||
#endif
|
||||
complexf_t z;
|
||||
int bits;
|
||||
|
||||
/* V.22bis training sequence */
|
||||
@ -341,17 +329,20 @@ static complexf_t training_get(v22bis_state_t *s)
|
||||
case V22BIS_TX_TRAINING_STAGE_INITIAL_SILENCE:
|
||||
/* Silence */
|
||||
s->tx.constellation_state = 0;
|
||||
return zero;
|
||||
z = complex_setf(0.0f, 0.0f);
|
||||
break;
|
||||
case V22BIS_TX_TRAINING_STAGE_U11:
|
||||
/* Send continuous unscrambled ones at 1200bps (i.e. 270 degree phase steps). */
|
||||
/* Only the answering modem sends unscrambled ones. It is the first thing exchanged between the modems. */
|
||||
s->tx.constellation_state = (s->tx.constellation_state + phase_steps[3]) & 3;
|
||||
return v22bis_constellation[(s->tx.constellation_state << 2) | 0x01];
|
||||
z = v22bis_constellation[(s->tx.constellation_state << 2) | 0x01];
|
||||
break;
|
||||
case V22BIS_TX_TRAINING_STAGE_U0011:
|
||||
/* Continuous unscrambled double dibit 00 11 at 1200bps. This is termed the S1 segment in
|
||||
the V.22bis spec. It is only sent to request or accept 2400bps mode, and lasts 100+-3ms. After this
|
||||
timed burst, we unconditionally change to sending scrambled ones at 1200bps. */
|
||||
s->tx.constellation_state = (s->tx.constellation_state + phase_steps[3*(s->tx.training_count & 1)]) & 3;
|
||||
z = v22bis_constellation[(s->tx.constellation_state << 2) | 0x01];
|
||||
if (++s->tx.training_count >= ms_to_symbols(100))
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting S11 after U0011\n");
|
||||
@ -366,7 +357,7 @@ static complexf_t training_get(v22bis_state_t *s)
|
||||
s->tx.training = V22BIS_TX_TRAINING_STAGE_TIMED_S11;
|
||||
}
|
||||
}
|
||||
return v22bis_constellation[(s->tx.constellation_state << 2) | 0x01];
|
||||
break;
|
||||
case V22BIS_TX_TRAINING_STAGE_TIMED_S11:
|
||||
/* A timed period of scrambled ones at 1200bps. */
|
||||
if (++s->tx.training_count >= ms_to_symbols(756))
|
||||
@ -392,7 +383,8 @@ static complexf_t training_get(v22bis_state_t *s)
|
||||
bits = scramble(s, 1);
|
||||
bits = (bits << 1) | scramble(s, 1);
|
||||
s->tx.constellation_state = (s->tx.constellation_state + phase_steps[bits]) & 3;
|
||||
return v22bis_constellation[(s->tx.constellation_state << 2) | 0x01];
|
||||
z = v22bis_constellation[(s->tx.constellation_state << 2) | 0x01];
|
||||
break;
|
||||
case V22BIS_TX_TRAINING_STAGE_S1111:
|
||||
/* Scrambled ones at 2400bps. We send a timed 200ms burst, and switch to normal operation at 2400bps */
|
||||
bits = scramble(s, 1);
|
||||
@ -400,6 +392,7 @@ static complexf_t training_get(v22bis_state_t *s)
|
||||
s->tx.constellation_state = (s->tx.constellation_state + phase_steps[bits]) & 3;
|
||||
bits = scramble(s, 1);
|
||||
bits = (bits << 1) | scramble(s, 1);
|
||||
z = v22bis_constellation[(s->tx.constellation_state << 2) | bits];
|
||||
if (++s->tx.training_count >= ms_to_symbols(200))
|
||||
{
|
||||
/* We have completed training. Now handle some real work. */
|
||||
@ -409,23 +402,18 @@ static complexf_t training_get(v22bis_state_t *s)
|
||||
v22bis_report_status_change(s, SIG_STATUS_TRAINING_SUCCEEDED);
|
||||
s->tx.current_get_bit = s->get_bit;
|
||||
}
|
||||
return v22bis_constellation[(s->tx.constellation_state << 2) | bits];
|
||||
break;
|
||||
case V22BIS_TX_TRAINING_STAGE_PARKED:
|
||||
default:
|
||||
z = complex_setf(0.0f, 0.0f);
|
||||
break;
|
||||
}
|
||||
return zero;
|
||||
return z;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
static complexi16_t getbaud(v22bis_state_t *s)
|
||||
#else
|
||||
static complexf_t getbaud(v22bis_state_t *s)
|
||||
#endif
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
static const complexi16_t zero = {0, 0};
|
||||
#else
|
||||
static const complexf_t zero = {0.0f, 0.0f};
|
||||
#endif
|
||||
int bits;
|
||||
|
||||
if (s->tx.training)
|
||||
@ -440,7 +428,7 @@ static complexf_t getbaud(v22bis_state_t *s)
|
||||
if (s->tx.shutdown)
|
||||
{
|
||||
if (++s->tx.shutdown > 10)
|
||||
return zero;
|
||||
return complex_setf(0.0f, 0.0f);
|
||||
}
|
||||
/* The first two bits define the quadrant */
|
||||
bits = get_scrambled_bit(s);
|
||||
@ -462,18 +450,11 @@ static complexf_t getbaud(v22bis_state_t *s)
|
||||
|
||||
SPAN_DECLARE_NONSTD(int) v22bis_tx(v22bis_state_t *s, int16_t amp[], int len)
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
complexi16_t v;
|
||||
complexi32_t x;
|
||||
complexi32_t z;
|
||||
int16_t iamp;
|
||||
#else
|
||||
complexf_t v;
|
||||
complexf_t x;
|
||||
complexf_t z;
|
||||
float famp;
|
||||
#endif
|
||||
int i;
|
||||
int sample;
|
||||
float famp;
|
||||
|
||||
if (s->tx.shutdown > 10)
|
||||
return 0;
|
||||
@ -482,41 +463,28 @@ SPAN_DECLARE_NONSTD(int) v22bis_tx(v22bis_state_t *s, int16_t amp[], int len)
|
||||
if ((s->tx.baud_phase += 3) >= 40)
|
||||
{
|
||||
s->tx.baud_phase -= 40;
|
||||
v = getbaud(s);
|
||||
s->tx.rrc_filter_re[s->tx.rrc_filter_step] = v.re;
|
||||
s->tx.rrc_filter_im[s->tx.rrc_filter_step] = v.im;
|
||||
s->tx.rrc_filter[s->tx.rrc_filter_step] =
|
||||
s->tx.rrc_filter[s->tx.rrc_filter_step + V22BIS_TX_FILTER_STEPS] = getbaud(s);
|
||||
if (++s->tx.rrc_filter_step >= V22BIS_TX_FILTER_STEPS)
|
||||
s->tx.rrc_filter_step = 0;
|
||||
}
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
x.re = vec_circular_dot_prodi16(s->tx.rrc_filter_re, tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->tx.baud_phase], V22BIS_TX_FILTER_STEPS, s->tx.rrc_filter_step) >> 4;
|
||||
x.im = vec_circular_dot_prodi16(s->tx.rrc_filter_im, tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->tx.baud_phase], V22BIS_TX_FILTER_STEPS, s->tx.rrc_filter_step) >> 4;
|
||||
/* Now create and modulate the carrier */
|
||||
z = dds_complexi32(&s->tx.carrier_phase, s->tx.carrier_phase_rate);
|
||||
iamp = (x.re*z.re - x.im*z.im) >> 15;
|
||||
iamp = (int16_t) (((int32_t) iamp*s->tx.gain) >> 11);
|
||||
if (s->tx.guard_phase_rate && (s->tx.rrc_filter_re[s->tx.rrc_filter_step] != 0 || s->tx.rrc_filter_im[s->tx.rrc_filter_step] != 0))
|
||||
{
|
||||
/* Add the guard tone */
|
||||
iamp += dds_mod(&s->tx.guard_phase, s->tx.guard_phase_rate, s->tx.guard_tone_gain, 0);
|
||||
}
|
||||
/* Don't bother saturating. We should never clip. */
|
||||
amp[sample] = iamp;
|
||||
#else
|
||||
/* Root raised cosine pulse shaping at baseband */
|
||||
x.re = vec_circular_dot_prodf(s->tx.rrc_filter_re, tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->tx.baud_phase], V22BIS_TX_FILTER_STEPS, s->tx.rrc_filter_step);
|
||||
x.im = vec_circular_dot_prodf(s->tx.rrc_filter_im, tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->tx.baud_phase], V22BIS_TX_FILTER_STEPS, s->tx.rrc_filter_step);
|
||||
x = complex_setf(0.0f, 0.0f);
|
||||
for (i = 0; i < V22BIS_TX_FILTER_STEPS; i++)
|
||||
{
|
||||
x.re += tx_pulseshaper[39 - s->tx.baud_phase][i]*s->tx.rrc_filter[i + s->tx.rrc_filter_step].re;
|
||||
x.im += tx_pulseshaper[39 - s->tx.baud_phase][i]*s->tx.rrc_filter[i + s->tx.rrc_filter_step].im;
|
||||
}
|
||||
/* Now create and modulate the carrier */
|
||||
z = dds_complexf(&(s->tx.carrier_phase), s->tx.carrier_phase_rate);
|
||||
famp = (x.re*z.re - x.im*z.im)*s->tx.gain;
|
||||
if (s->tx.guard_phase_rate && (s->tx.rrc_filter_re[s->tx.rrc_filter_step] != 0.0f || s->tx.rrc_filter_im[s->tx.rrc_filter_step] != 0.0f))
|
||||
if (s->tx.guard_phase_rate && (s->tx.rrc_filter[s->tx.rrc_filter_step].re != 0.0f || s->tx.rrc_filter[s->tx.rrc_filter_step].im != 0.0f))
|
||||
{
|
||||
/* Add the guard tone */
|
||||
famp += dds_modf(&s->tx.guard_phase, s->tx.guard_phase_rate, s->tx.guard_tone_gain, 0);
|
||||
famp += dds_modf(&(s->tx.guard_phase), s->tx.guard_phase_rate, s->tx.guard_level, 0);
|
||||
}
|
||||
/* Don't bother saturating. We should never clip. */
|
||||
amp[sample] = (int16_t) lfastrintf(famp);
|
||||
#endif
|
||||
}
|
||||
return sample;
|
||||
}
|
||||
@ -524,49 +492,34 @@ SPAN_DECLARE_NONSTD(int) v22bis_tx(v22bis_state_t *s, int16_t amp[], int len)
|
||||
|
||||
SPAN_DECLARE(void) v22bis_tx_power(v22bis_state_t *s, float power)
|
||||
{
|
||||
float sig_power;
|
||||
float guard_tone_power;
|
||||
float sig_gain;
|
||||
float guard_tone_gain;
|
||||
float l;
|
||||
|
||||
/* If is there is a guard tone we need to scale down the signal power a bit, so the aggregate of the signal
|
||||
and guard tone power is the specified power. */
|
||||
if (s->tx.guard_phase_rate == dds_phase_ratef(550.0f))
|
||||
{
|
||||
sig_power = power - 1.0f;
|
||||
guard_tone_power = sig_power - 3.0f;
|
||||
l = 1.6f*powf(10.0f, (power - 1.0f - DBM0_MAX_POWER)/20.0f);
|
||||
s->tx.gain = l*32768.0f/(TX_PULSESHAPER_GAIN*3.0f);
|
||||
l = powf(10.0f, (power - 1.0f - 3.0f - DBM0_MAX_POWER)/20.0f);
|
||||
s->tx.guard_level = l*32768.0f;
|
||||
}
|
||||
else if(s->tx.guard_phase_rate == dds_phase_ratef(1800.0f))
|
||||
{
|
||||
sig_power = power - 0.55f;
|
||||
guard_tone_power = sig_power - 6.0f;
|
||||
l = 1.6f*powf(10.0f, (power - 1.0f - 1.0f - DBM0_MAX_POWER)/20.0f);
|
||||
s->tx.gain = l*32768.0f/(TX_PULSESHAPER_GAIN*3.0f);
|
||||
l = powf(10.0f, (power - 1.0f - 6.0f - DBM0_MAX_POWER)/20.0f);
|
||||
s->tx.guard_level = l*32768.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
sig_power = power;
|
||||
guard_tone_power = -9999.0f;
|
||||
l = 1.6f*powf(10.0f, (power - DBM0_MAX_POWER)/20.0f);
|
||||
s->tx.gain = l*32768.0f/(TX_PULSESHAPER_GAIN*3.0f);
|
||||
s->tx.guard_level = 0;
|
||||
}
|
||||
sig_gain = 0.4490f*powf(10.0f, (sig_power - DBM0_MAX_POWER)/20.0f)*32768.0f/TX_PULSESHAPER_GAIN;
|
||||
guard_tone_gain = powf(10.0f, (guard_tone_power - DBM0_MAX_POWER)/20.0f)*32768.0f;
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
s->tx.gain = (int16_t) sig_gain;
|
||||
s->tx.guard_tone_gain = (int16_t) guard_tone_gain;
|
||||
#else
|
||||
s->tx.gain = sig_gain;
|
||||
s->tx.guard_tone_gain = guard_tone_gain;
|
||||
#endif
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int v22bis_tx_restart(v22bis_state_t *s)
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
vec_zeroi16(s->tx.rrc_filter_re, sizeof(s->tx.rrc_filter_re)/sizeof(s->tx.rrc_filter_re[0]));
|
||||
vec_zeroi16(s->tx.rrc_filter_im, sizeof(s->tx.rrc_filter_im)/sizeof(s->tx.rrc_filter_im[0]));
|
||||
#else
|
||||
vec_zerof(s->tx.rrc_filter_re, sizeof(s->tx.rrc_filter_re)/sizeof(s->tx.rrc_filter_re[0]));
|
||||
vec_zerof(s->tx.rrc_filter_im, sizeof(s->tx.rrc_filter_im)/sizeof(s->tx.rrc_filter_im[0]));
|
||||
#endif
|
||||
cvec_zerof(s->tx.rrc_filter, sizeof(s->tx.rrc_filter)/sizeof(s->tx.rrc_filter[0]));
|
||||
s->tx.rrc_filter_step = 0;
|
||||
s->tx.scramble_reg = 0;
|
||||
s->tx.scrambler_pattern_count = 0;
|
||||
|
@ -230,13 +230,17 @@ static void equalizer_reset(v29_rx_state_t *s)
|
||||
{
|
||||
/* Start with an equalizer based on everything being perfect */
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
static const complexi16_t x = {3*FP_FACTOR, 0*FP_FACTOR};
|
||||
|
||||
cvec_zeroi16(s->eq_coeff, V29_EQUALIZER_LEN);
|
||||
s->eq_coeff[V29_EQUALIZER_PRE_LEN] = complex_seti16(3*FP_FACTOR, 0*FP_FACTOR);
|
||||
s->eq_coeff[V29_EQUALIZER_PRE_LEN] = x;
|
||||
cvec_zeroi16(s->eq_buf, V29_EQUALIZER_LEN);
|
||||
s->eq_delta = 32768.0f*EQUALIZER_DELTA/V29_EQUALIZER_LEN;
|
||||
#else
|
||||
static const complexf_t x = {3.0f, 0.0f};
|
||||
|
||||
cvec_zerof(s->eq_coeff, V29_EQUALIZER_LEN);
|
||||
s->eq_coeff[V29_EQUALIZER_PRE_LEN] = complex_setf(3.0f, 0.0f);
|
||||
s->eq_coeff[V29_EQUALIZER_PRE_LEN] = x;
|
||||
cvec_zerof(s->eq_buf, V29_EQUALIZER_LEN);
|
||||
s->eq_delta = EQUALIZER_DELTA/V29_EQUALIZER_LEN;
|
||||
#endif
|
||||
@ -538,7 +542,7 @@ static __inline__ void symbol_sync(v29_rx_state_t *s)
|
||||
i = (v > 1000.0f) ? 5 : 1;
|
||||
if (s->baud_phase < 0.0f)
|
||||
i = -i;
|
||||
//printf("v = %10.5f %5d - %f %f %d %d\n", v, i, p, s->baud_phase, s->total_baud_timing_correction);
|
||||
//printf("v = %10.5f %5d - %f %f %d\n", v, i, p, s->baud_phase, s->total_baud_timing_correction);
|
||||
s->eq_put_step += i;
|
||||
s->total_baud_timing_correction += i;
|
||||
}
|
||||
@ -645,8 +649,7 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
|
||||
if (i)
|
||||
{
|
||||
j = i & 0xF;
|
||||
ang = (s->angles[j] - s->start_angles[0])/i
|
||||
+ (s->angles[j | 0x1] - s->start_angles[1])/i;
|
||||
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, "Coarse carrier frequency %7.2f\n", dds_frequencyf(s->carrier_phase_rate));
|
||||
@ -719,11 +722,12 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
|
||||
if (++s->training_count >= V29_TRAINING_SEG_3_LEN - 48)
|
||||
{
|
||||
s->training_stage = TRAINING_STAGE_TRAIN_ON_CDCD_AND_TEST;
|
||||
s->training_error = 0.0f;
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
s->training_error = 0;
|
||||
s->carrier_track_i = 200;
|
||||
s->carrier_track_p = 1000000;
|
||||
#else
|
||||
s->training_error = 0.0f;
|
||||
s->carrier_track_i = 200.0f;
|
||||
s->carrier_track_p = 1000000.0f;
|
||||
#endif
|
||||
@ -946,10 +950,12 @@ SPAN_DECLARE_NONSTD(int) v29_rx(v29_rx_state_t *s, const int16_t amp[], int len)
|
||||
parked, after training failure. */
|
||||
s->eq_put_step -= RX_PULSESHAPER_COEFF_SETS;
|
||||
step = -s->eq_put_step;
|
||||
if (step > RX_PULSESHAPER_COEFF_SETS - 1)
|
||||
step = RX_PULSESHAPER_COEFF_SETS - 1;
|
||||
if (step < 0)
|
||||
step += RX_PULSESHAPER_COEFF_SETS;
|
||||
if (step < 0)
|
||||
step = 0;
|
||||
else if (step > RX_PULSESHAPER_COEFF_SETS - 1)
|
||||
step = RX_PULSESHAPER_COEFF_SETS - 1;
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
v = vec_circular_dot_prodi16(s->rrc_filter, rx_pulseshaper_re[step], V29_RX_FILTER_STEPS, s->rrc_filter_step);
|
||||
sample.re = (v*s->agc_scaling) >> 15;
|
||||
|
@ -24,26 +24,18 @@
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#if !defined(FP_SCALE)
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
#define FP_SCALE(x) ((int16_t) x)
|
||||
#else
|
||||
#define FP_SCALE(x) (x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
static const complexi16_t v29_abab_constellation[6] =
|
||||
#else
|
||||
static const complexf_t v29_abab_constellation[6] =
|
||||
#endif
|
||||
{
|
||||
{FP_SCALE( 3.0f), FP_SCALE(-3.0f)}, /* 315deg high 9600 */
|
||||
{FP_SCALE(-3.0f), FP_SCALE( 0.0f)}, /* 180deg low */
|
||||
{FP_SCALE( 1.0f), FP_SCALE(-1.0f)}, /* 315deg low 7200 */
|
||||
{FP_SCALE(-3.0f), FP_SCALE( 0.0f)}, /* 180deg low */
|
||||
{FP_SCALE( 0.0f), FP_SCALE(-3.0f)}, /* 270deg low 4800 */
|
||||
{FP_SCALE(-3.0f), FP_SCALE( 0.0f)} /* 180deg low */
|
||||
{ 3, -3}, /* 315deg high 9600 */
|
||||
{-3, 0}, /* 180deg low */
|
||||
{ 1, -1}, /* 315deg low 7200 */
|
||||
{-3, 0}, /* 180deg low */
|
||||
{ 0, -3}, /* 270deg low 4800 */
|
||||
{-3, 0} /* 180deg low */
|
||||
};
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
@ -52,12 +44,12 @@ static const complexi16_t v29_cdcd_constellation[6] =
|
||||
static const complexf_t v29_cdcd_constellation[6] =
|
||||
#endif
|
||||
{
|
||||
{FP_SCALE( 3.0f), FP_SCALE( 0.0f)}, /* 0deg low 9600 */
|
||||
{FP_SCALE(-3.0f), FP_SCALE( 3.0f)}, /* 135deg high */
|
||||
{FP_SCALE( 3.0f), FP_SCALE( 0.0f)}, /* 0deg low 7200 */
|
||||
{FP_SCALE(-1.0f), FP_SCALE( 1.0f)}, /* 135deg low */
|
||||
{FP_SCALE( 3.0f), FP_SCALE( 0.0f)}, /* 0deg low 4800 */
|
||||
{FP_SCALE( 0.0f), FP_SCALE( 3.0f)} /* 90deg low */
|
||||
{ 3, 0}, /* 0deg low 9600 */
|
||||
{-3, 3}, /* 135deg high */
|
||||
{ 3, 0}, /* 0deg low 7200 */
|
||||
{-1, 1}, /* 135deg low */
|
||||
{ 3, 0}, /* 0deg low 4800 */
|
||||
{ 0, 3} /* 90deg low */
|
||||
};
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
@ -66,22 +58,22 @@ static const complexi16_t v29_9600_constellation[16] =
|
||||
static const complexf_t v29_9600_constellation[16] =
|
||||
#endif
|
||||
{
|
||||
{FP_SCALE( 3.0f), FP_SCALE( 0.0f)}, /* 0deg low */
|
||||
{FP_SCALE( 1.0f), FP_SCALE( 1.0f)}, /* 45deg low */
|
||||
{FP_SCALE( 0.0f), FP_SCALE( 3.0f)}, /* 90deg low */
|
||||
{FP_SCALE(-1.0f), FP_SCALE( 1.0f)}, /* 135deg low */
|
||||
{FP_SCALE(-3.0f), FP_SCALE( 0.0f)}, /* 180deg low */
|
||||
{FP_SCALE(-1.0f), FP_SCALE(-1.0f)}, /* 225deg low */
|
||||
{FP_SCALE( 0.0f), FP_SCALE(-3.0f)}, /* 270deg low */
|
||||
{FP_SCALE( 1.0f), FP_SCALE(-1.0f)}, /* 315deg low */
|
||||
{FP_SCALE( 5.0f), FP_SCALE( 0.0f)}, /* 0deg high */
|
||||
{FP_SCALE( 3.0f), FP_SCALE( 3.0f)}, /* 45deg high */
|
||||
{FP_SCALE( 0.0f), FP_SCALE( 5.0f)}, /* 90deg high */
|
||||
{FP_SCALE(-3.0f), FP_SCALE( 3.0f)}, /* 135deg high */
|
||||
{FP_SCALE(-5.0f), FP_SCALE( 0.0f)}, /* 180deg high */
|
||||
{FP_SCALE(-3.0f), FP_SCALE(-3.0f)}, /* 225deg high */
|
||||
{FP_SCALE( 0.0f), FP_SCALE(-5.0f)}, /* 270deg high */
|
||||
{FP_SCALE( 3.0f), FP_SCALE(-3.0f)} /* 315deg high */
|
||||
{ 3, 0}, /* 0deg low */
|
||||
{ 1, 1}, /* 45deg low */
|
||||
{ 0, 3}, /* 90deg low */
|
||||
{-1, 1}, /* 135deg low */
|
||||
{-3, 0}, /* 180deg low */
|
||||
{-1, -1}, /* 225deg low */
|
||||
{ 0, -3}, /* 270deg low */
|
||||
{ 1, -1}, /* 315deg low */
|
||||
{ 5, 0}, /* 0deg high */
|
||||
{ 3, 3}, /* 45deg high */
|
||||
{ 0, 5}, /* 90deg high */
|
||||
{-3, 3}, /* 135deg high */
|
||||
{-5, 0}, /* 180deg high */
|
||||
{-3, -3}, /* 225deg high */
|
||||
{ 0, -5}, /* 270deg high */
|
||||
{ 3, -3} /* 315deg high */
|
||||
};
|
||||
|
||||
/*- End of file ------------------------------------------------------------*/
|
||||
|
@ -1024,9 +1024,9 @@ SPAN_DECLARE(int) v8_restart(v8_state_t *s, int calling_party, v8_parms_t *parms
|
||||
{
|
||||
/* Send the ANSam or ANSam/ tone */
|
||||
s->state = V8_CM_WAIT;
|
||||
s->negotiation_timer = ms_to_samples(200 + 5000);
|
||||
v8_decode_init(s);
|
||||
modem_connect_tones_tx_init(&s->ansam_tx, s->parms.modem_connect_tone);
|
||||
s->negotiation_timer = ms_to_samples(200 + 5000);
|
||||
s->modem_connect_tone_tx_on = ms_to_samples(75) + 1;
|
||||
}
|
||||
|
||||
|
@ -300,7 +300,7 @@ t38_core_tests_SOURCES = t38_core_tests.c
|
||||
t38_core_tests_LDADD = $(LIBDIR) -lspandsp
|
||||
|
||||
t38_decode_SOURCES = t38_decode.c fax_utils.c pcap_parse.c udptl.c
|
||||
t38_decode_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp -lpcap
|
||||
t38_decode_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp
|
||||
|
||||
t38_non_ecm_buffer_tests_SOURCES = t38_non_ecm_buffer_tests.c
|
||||
t38_non_ecm_buffer_tests_LDADD = $(LIBDIR) -lspandsp
|
||||
|
@ -287,7 +287,7 @@ static void hdlc_rx_status(void *user_data, int status)
|
||||
faxtester_state_t *s;
|
||||
|
||||
s = (faxtester_state_t *) user_data;
|
||||
fprintf(stderr, "HDLC carrier status is %s (%d)\n", signal_status_to_str(status), status);
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC carrier status is %s (%d)\n", signal_status_to_str(status), status);
|
||||
switch (status)
|
||||
{
|
||||
case SIG_STATUS_TRAINING_FAILED:
|
||||
@ -409,9 +409,7 @@ int faxtester_rx(faxtester_state_t *s, int16_t *amp, int len)
|
||||
int faxtester_tx(faxtester_state_t *s, int16_t *amp, int max_len)
|
||||
{
|
||||
int len;
|
||||
int required_len;
|
||||
|
||||
required_len = max_len;
|
||||
len = 0;
|
||||
if (s->transmit)
|
||||
{
|
||||
|
@ -18,8 +18,8 @@
|
||||
run_fax_test()
|
||||
{
|
||||
rm -f fax_tests_1.tif
|
||||
echo -i ${FILE} ${OPTS}
|
||||
./fax_tests -i ${FILE} ${OPTS} >xyzzy 2>xyzzy2
|
||||
echo -i ${FILE} ${OPTS} -i ${FILE}
|
||||
./fax_tests ${OPTS} -i ${FILE} >xyzzy 2>xyzzy2
|
||||
RETVAL=$?
|
||||
if [ $RETVAL != 0 ]
|
||||
then
|
||||
@ -28,7 +28,7 @@ run_fax_test()
|
||||
fi
|
||||
# Now use tiffcmp to check the results. It will return non-zero if any page images differ. The -t
|
||||
# option means the normal differences in tags will be ignored.
|
||||
tiffcmp -t ${FILE} fax_tests_1.tif #>/dev/null
|
||||
tiffcmp -t ${FILE} fax_tests.tif #>/dev/null
|
||||
RETVAL=$?
|
||||
if [ $RETVAL != 0 ]
|
||||
then
|
||||
@ -39,165 +39,106 @@ run_fax_test()
|
||||
echo tested ${FILE}
|
||||
}
|
||||
|
||||
OPTS="-e"
|
||||
ITUTESTS_DIR=../test-data/itu/fax
|
||||
|
||||
FILE="../itutests/fax/R8_385_A4.tif"
|
||||
run_fax_test
|
||||
for OPTS in "-p AA" "-p AA -e" "-p TT" "-p TT -e" "-p GG" "-p GG -e" "-p TG" "-p TG -e" "-p GT" "-p GT -e"
|
||||
do
|
||||
FILE="${ITUTESTS_DIR}/R8_385_A4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R8_385_B4.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R8_385_B4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R8_385_A3.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R8_385_A3.tif"
|
||||
run_fax_test
|
||||
|
||||
|
||||
FILE="../itutests/fax/R8_77_A4.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R8_77_A4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R8_77_B4.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R8_77_B4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R8_77_A3.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R8_77_A3.tif"
|
||||
run_fax_test
|
||||
|
||||
|
||||
FILE="../itutests/fax/R8_154_A4.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R8_154_A4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R8_154_B4.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R8_154_B4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R8_154_A3.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R8_154_A3.tif"
|
||||
run_fax_test
|
||||
|
||||
|
||||
FILE="../itutests/fax/R300_300_A4.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R300_300_A4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R300_300_B4.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R300_300_B4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R300_300_A3.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R300_300_A3.tif"
|
||||
run_fax_test
|
||||
|
||||
|
||||
FILE="../itutests/fax/R300_600_A4.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R300_600_A4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R300_600_B4.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R300_600_B4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R300_600_A3.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R300_600_A3.tif"
|
||||
run_fax_test
|
||||
|
||||
|
||||
FILE="../itutests/fax/R16_154_A4.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R16_154_A4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R16_154_B4.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R16_154_B4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R16_154_A3.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R16_154_A3.tif"
|
||||
run_fax_test
|
||||
|
||||
|
||||
FILE="../itutests/fax/R16_800_A4.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R16_800_A4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R16_800_B4.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R16_800_B4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R16_800_A3.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R16_800_A3.tif"
|
||||
run_fax_test
|
||||
|
||||
|
||||
FILE="../itutests/fax/R600_600_A4.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R600_600_A4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R600_600_B4.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R600_600_B4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R600_600_A3.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R600_600_A3.tif"
|
||||
run_fax_test
|
||||
|
||||
|
||||
FILE="../itutests/fax/R600_1200_A4.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R600_1200_A4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R600_1200_B4.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R600_1200_B4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R600_1200_A3.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R600_1200_A3.tif"
|
||||
run_fax_test
|
||||
|
||||
|
||||
FILE="../itutests/fax/R1200_1200_A4.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R1200_1200_A4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R1200_1200_B4.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R1200_1200_B4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R1200_1200_A3.tif"
|
||||
run_fax_test
|
||||
|
||||
|
||||
OPTS=""
|
||||
|
||||
FILE="../itutests/fax/R8_385_A4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R8_385_B4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R8_385_A3.tif"
|
||||
run_fax_test
|
||||
|
||||
|
||||
FILE="../itutests/fax/R8_77_A4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R8_77_B4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R8_77_A3.tif"
|
||||
run_fax_test
|
||||
|
||||
|
||||
FILE="../itutests/fax/R8_154_A4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R8_154_B4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R8_154_A3.tif"
|
||||
run_fax_test
|
||||
|
||||
|
||||
FILE="../itutests/fax/R16_385_A4.tif"
|
||||
#run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R16_385_B4.tif"
|
||||
#run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R16_385_A3.tif"
|
||||
#run_fax_test
|
||||
|
||||
|
||||
FILE="../itutests/fax/R16_77_A4.tif"
|
||||
#run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R16_77_B4.tif"
|
||||
#run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R16_77_A3.tif"
|
||||
#run_fax_test
|
||||
|
||||
|
||||
FILE="../itutests/fax/R16_154_A4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R16_154_B4.tif"
|
||||
run_fax_test
|
||||
|
||||
FILE="../itutests/fax/R16_154_A3.tif"
|
||||
run_fax_test
|
||||
FILE="${ITUTESTS_DIR}/R1200_1200_A3.tif"
|
||||
run_fax_test
|
||||
done
|
||||
|
Loading…
x
Reference in New Issue
Block a user