This commit is contained in:
Steve Underwood 2012-07-21 07:18:27 +08:00
parent b5f7443524
commit e9b4a497cc
8 changed files with 240 additions and 156 deletions

View File

@ -64,6 +64,7 @@ SPAN_DECLARE_NONSTD(int) fax_modems_v29_v21_rx(void *user_data, const int16_t am
SPAN_DECLARE_NONSTD(int) fax_modems_v17_v21_rx_fillin(void *user_data, int len);
SPAN_DECLARE_NONSTD(int) fax_modems_v27ter_v21_rx_fillin(void *user_data, int len);
SPAN_DECLARE_NONSTD(int) fax_modems_v29_v21_rx_fillin(void *user_data, int len);
SPAN_DECLARE(void) fax_modems_start_rx_modem(fax_modems_state_t *s, int which);
SPAN_DECLARE(void) fax_modems_set_tep_mode(fax_modems_state_t *s, int use_tep);

View File

@ -86,8 +86,8 @@ typedef struct
uint16_t crc;
/*! \brief TRUE if non-ECM fill bits are to be stripped when sending image data. */
int fill_bit_removal;
/*! \brief The number of octets to send in each image packet (non-ECM or ECM) at the current
rate and the current specified packet interval. */
/*! \brief The number of octets to send in each image packet (non-ECM or ECM) at
the current rate and the current specified packet interval. */
int octets_per_data_packet;
/*! \brief Bits into the non-ECM buffer */

View File

@ -99,13 +99,6 @@ struct v22bis_state_s
/* Receive section */
struct
{
#if defined(SPANDSP_USE_FIXED_POINTx)
/*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
int16_t rrc_filter[V22BIS_RX_FILTER_STEPS];
#else
/*! \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. */
int rrc_filter_step;
@ -123,20 +116,11 @@ 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;
/*! \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;
/*! \brief A callback function which may be enabled to report every symbol's
constellation position. */
qam_report_handler_t qam_report;
@ -150,23 +134,49 @@ 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_POINTx)
/*! \brief The scaling factor accessed by the AGC algorithm. */
float agc_scaling;
/*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
int16_t rrc_filter[V22BIS_RX_FILTER_STEPS];
/*! \brief The current delta factor for updating the equalizer coefficients. */
float eq_delta;
#if defined(SPANDSP_USE_FIXED_POINTx)
/*! \brief The adaptive equalizer coefficients. */
complexi_t eq_coeff[2*V22BIS_EQUALIZER_LEN + 1];
/*! \brief The equalizer signal buffer. */
complexi_t eq_buf[V22BIS_EQUALIZER_MASK + 1];
/*! \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;
#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];
/*! \brief The current delta factor for updating the equalizer coefficients. */
float eq_delta;
/*! \brief The adaptive equalizer coefficients. */
complexf_t eq_coeff[2*V22BIS_EQUALIZER_LEN + 1];
/*! \brief The equalizer signal buffer. */
complexf_t eq_buf[V22BIS_EQUALIZER_MASK + 1];
/*! \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 Current offset into the equalizer buffer. */
int eq_step;
@ -192,11 +202,24 @@ struct v22bis_state_s
/* Transmit section */
struct
{
#if defined(SPANDSP_USE_FIXED_POINTx)
/*! \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. */
complexf_t rrc_filter[2*V22BIS_TX_FILTER_STEPS];
float rrc_filter_re[V22BIS_TX_FILTER_STEPS];
float rrc_filter_im[V22BIS_TX_FILTER_STEPS];
#endif
/*! \brief Current offset into the RRC pulse shaping filter buffer. */
int rrc_filter_step;
@ -218,7 +241,6 @@ 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_tone_gain;
/*! \brief The current fractional phase of the baud timing. */
int baud_phase;
/*! \brief The code number for the current position in the constellation. */

View File

@ -53,15 +53,18 @@ struct v27ter_tx_state_s
/*! \brief The gain factor needed to achieve the specified output power at 4800bps. */
int16_t gain_4800;
/*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
complexi16_t rrc_filter[2*V27TER_TX_FILTER_STEPS];
int16_t rrc_filter_re[V27TER_TX_FILTER_STEPS];
int16_t rrc_filter_im[V27TER_TX_FILTER_STEPS];
#else
/*! \brief The gain factor needed to achieve the specified output power at 2400bps. */
float gain_2400;
/*! \brief The gain factor needed to achieve the specified output power at 4800bps. */
float gain_4800;
/*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
complexf_t rrc_filter[2*V27TER_TX_FILTER_STEPS];
float rrc_filter_re[V27TER_TX_FILTER_STEPS];
float rrc_filter_im[V27TER_TX_FILTER_STEPS];
#endif
/*! \brief Current offset into the RRC pulse shaping filter buffer. */
int rrc_filter_step;

View File

@ -50,12 +50,13 @@ struct v29_tx_state_s
#if defined(SPANDSP_USE_FIXED_POINT)
/*! \brief Gain required to achieve the specified output power, not allowing
for the size of the current constellation. */
float base_gain;
int16_t base_gain;
/*! \brief Gain required to achieve the specified output power, allowing
for the size of the current constellation. */
int32_t gain;
int16_t gain;
/*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
complexi16_t rrc_filter[2*V29_TX_FILTER_STEPS];
int16_t rrc_filter_re[V29_TX_FILTER_STEPS];
int16_t rrc_filter_im[V29_TX_FILTER_STEPS];
#else
/*! \brief Gain required to achieve the specified output power, not allowing
for the size of the current constellation. */
@ -64,8 +65,10 @@ struct v29_tx_state_s
for the size of the current constellation. */
float gain;
/*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
complexf_t rrc_filter[2*V29_TX_FILTER_STEPS];
float rrc_filter_re[V29_TX_FILTER_STEPS];
float rrc_filter_im[V29_TX_FILTER_STEPS];
#endif
/*! \brief Current offset into the RRC pulse shaping filter buffer. */
int rrc_filter_step;

View File

@ -63,8 +63,10 @@
#include "spandsp/private/v22bis.h"
#if defined(SPANDSP_USE_FIXED_POINTx)
#define FP_SCALE FP_Q_6_10
#include "v22bis_tx_fixed_rrc.h"
#else
#define FP_SCALE(x) (x)
#include "v22bis_tx_floating_rrc.h"
#endif
@ -246,24 +248,28 @@ static const int phase_steps[4] =
1, 0, 2, 3
};
#if defined(SPANDSP_USE_FIXED_POINTx)
const complexi16_t v22bis_constellation[16] =
#else
const complexf_t v22bis_constellation[16] =
#endif
{
{ 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}
{FP_SCALE( 1.0f), FP_SCALE( 1.0f)},
{FP_SCALE( 3.0f), FP_SCALE( 1.0f)}, /* 1200bps 00 */
{FP_SCALE( 1.0f), FP_SCALE( 3.0f)},
{FP_SCALE( 3.0f), FP_SCALE( 3.0f)},
{FP_SCALE(-1.0f), FP_SCALE( 1.0f)},
{FP_SCALE(-1.0f), FP_SCALE( 3.0f)}, /* 1200bps 01 */
{FP_SCALE(-3.0f), FP_SCALE( 1.0f)},
{FP_SCALE(-3.0f), FP_SCALE( 3.0f)},
{FP_SCALE(-1.0f), FP_SCALE(-1.0f)},
{FP_SCALE(-3.0f), FP_SCALE(-1.0f)}, /* 1200bps 10 */
{FP_SCALE(-1.0f), FP_SCALE(-3.0f)},
{FP_SCALE(-3.0f), FP_SCALE(-3.0f)},
{FP_SCALE( 1.0f), FP_SCALE(-1.0f)},
{FP_SCALE( 1.0f), FP_SCALE(-3.0f)}, /* 1200bps 11 */
{FP_SCALE( 3.0f), FP_SCALE(-1.0f)},
{FP_SCALE( 3.0f), FP_SCALE(-3.0f)}
};
static int fake_get_bit(void *user_data)
@ -308,10 +314,18 @@ static __inline__ int get_scrambled_bit(v22bis_state_t *s)
}
/*- End of function --------------------------------------------------------*/
#if defined(SPANDSP_USE_FIXED_POINTx)
static complexi16_t training_get(v22bis_state_t *s)
#else
static complexf_t training_get(v22bis_state_t *s)
#endif
{
int bits;
#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;
/* V.22bis training sequence */
switch (s->tx.training)
@ -403,8 +417,17 @@ static complexf_t training_get(v22bis_state_t *s)
}
/*- End of function --------------------------------------------------------*/
#if defined(SPANDSP_USE_FIXED_POINTx)
static complexi16_t getbaud(v22bis_state_t *s)
#else
static complexf_t getbaud(v22bis_state_t *s)
#endif
{
#if defined(SPANDSP_USE_FIXED_POINTx)
static const complexi16_t zero = {0, 0};
#else
static const complexf_t zero = {0.0f, 0.0f};
#endif
int bits;
if (s->tx.training)
@ -419,7 +442,7 @@ static complexf_t getbaud(v22bis_state_t *s)
if (s->tx.shutdown)
{
if (++s->tx.shutdown > 10)
return complex_setf(0.0f, 0.0f);
return zero;
}
/* The first two bits define the quadrant */
bits = get_scrambled_bit(s);
@ -441,11 +464,18 @@ 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_POINTx)
complexi16_t v;
complexi32_t x;
complexi32_t z;
int16_t iamp;
#else
complexf_t v;
complexf_t x;
complexf_t z;
int i;
int sample;
float famp;
#endif
int sample;
if (s->tx.shutdown > 10)
return 0;
@ -454,28 +484,42 @@ 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;
s->tx.rrc_filter[s->tx.rrc_filter_step] =
s->tx.rrc_filter[s->tx.rrc_filter_step + V22BIS_TX_FILTER_STEPS] = getbaud(s);
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;
if (++s->tx.rrc_filter_step >= V22BIS_TX_FILTER_STEPS)
s->tx.rrc_filter_step = 0;
}
#if defined(SPANDSP_USE_FIXED_POINTx)
/* Root raised cosine pulse shaping at baseband */
x = complex_setf(0.0f, 0.0f);
for (i = 0; i < V22BIS_TX_FILTER_STEPS; i++)
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) >> 14;
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) >> 14;
/* 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))
{
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;
/* 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);
/* 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[s->tx.rrc_filter_step].re != 0.0f || s->tx.rrc_filter[s->tx.rrc_filter_step].im != 0.0f))
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))
{
/* Add the guard tone */
famp += dds_modf(&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] = (int16_t) lfastrintf(famp);
#endif
}
return sample;
}
@ -483,34 +527,49 @@ 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 l;
float sig_power;
float guard_tone_power;
float sig_gain;
float guard_tone_gain;
/* 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))
{
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_tone_gain = l*32768.0f;
sig_power = power - 1.0f;
guard_tone_power = sig_power - 3.0f;
}
else if(s->tx.guard_phase_rate == dds_phase_ratef(1800.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_tone_gain = l*32768.0f;
sig_power = power - 0.55f;
guard_tone_power = sig_power - 6.0f;
}
else
{
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_tone_gain = 0;
sig_power = power;
guard_tone_power = -9999.0f;
}
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_POINTx)
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)
{
cvec_zerof(s->tx.rrc_filter, sizeof(s->tx.rrc_filter)/sizeof(s->tx.rrc_filter[0]));
#if defined(SPANDSP_USE_FIXED_POINTx)
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
s->tx.rrc_filter_step = 0;
s->tx.scramble_reg = 0;
s->tx.scrambler_pattern_count = 0;

View File

@ -247,13 +247,16 @@ static complexf_t getbaud(v27ter_tx_state_t *s)
SPAN_DECLARE_NONSTD(int) v27ter_tx(v27ter_tx_state_t *s, int16_t amp[], int len)
{
#if defined(SPANDSP_USE_FIXED_POINT)
complexi_t x;
complexi_t z;
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;
if (s->training_step >= V27TER_TRAINING_SHUTDOWN_END)
@ -271,37 +274,30 @@ SPAN_DECLARE_NONSTD(int) v27ter_tx(v27ter_tx_state_t *s, int16_t amp[], int len)
if (++s->baud_phase >= 5)
{
s->baud_phase -= 5;
s->rrc_filter[s->rrc_filter_step] =
s->rrc_filter[s->rrc_filter_step + V27TER_TX_FILTER_STEPS] = getbaud(s);
v = getbaud(s);;
s->rrc_filter_re[s->rrc_filter_step] = v.re;
s->rrc_filter_im[s->rrc_filter_step] = v.im;
if (++s->rrc_filter_step >= V27TER_TX_FILTER_STEPS)
s->rrc_filter_step = 0;
}
/* Root raised cosine pulse shaping at baseband */
#if defined(SPANDSP_USE_FIXED_POINT)
x = complex_seti(0, 0);
for (i = 0; i < V27TER_TX_FILTER_STEPS; i++)
{
x.re += (int32_t) tx_pulseshaper_4800[TX_PULSESHAPER_4800_COEFF_SETS - 1 - s->baud_phase][i]*(int32_t) s->rrc_filter[i + s->rrc_filter_step].re;
x.im += (int32_t) tx_pulseshaper_4800[TX_PULSESHAPER_4800_COEFF_SETS - 1 - s->baud_phase][i]*(int32_t) s->rrc_filter[i + s->rrc_filter_step].im;
}
/* Root raised cosine pulse shaping at baseband */
x.re = vec_circular_dot_prodi16(s->rrc_filter_re, tx_pulseshaper_4800[TX_PULSESHAPER_4800_COEFF_SETS - 1 - s->baud_phase], V27TER_TX_FILTER_STEPS, s->rrc_filter_step) >> (10 + 4);
x.im = vec_circular_dot_prodi16(s->rrc_filter_im, tx_pulseshaper_4800[TX_PULSESHAPER_4800_COEFF_SETS - 1 - s->baud_phase], V27TER_TX_FILTER_STEPS, s->rrc_filter_step) >> (10 + 4);
/* Now create and modulate the carrier */
x.re >>= 14;
x.im >>= 14;
z = dds_complexi(&(s->carrier_phase), s->carrier_phase_rate);
z = dds_complexi32(&s->carrier_phase, s->carrier_phase_rate);
iamp = ((int32_t) x.re*z.re - x.im*z.im) >> 15;
/* Don't bother saturating. We should never clip. */
i = (x.re*z.re - x.im*z.im) >> 15;
amp[sample] = (int16_t) ((i*s->gain_4800) >> 15);
amp[sample] = (int16_t) (((int32_t) iamp*s->gain_4800) >> 11);
#else
x = complex_setf(0.0f, 0.0f);
for (i = 0; i < V27TER_TX_FILTER_STEPS; i++)
{
x.re += tx_pulseshaper_4800[TX_PULSESHAPER_4800_COEFF_SETS - 1 - s->baud_phase][i]*s->rrc_filter[i + s->rrc_filter_step].re;
x.im += tx_pulseshaper_4800[TX_PULSESHAPER_4800_COEFF_SETS - 1 - s->baud_phase][i]*s->rrc_filter[i + s->rrc_filter_step].im;
}
/* Root raised cosine pulse shaping at baseband */
x.re = vec_circular_dot_prodf(s->rrc_filter_re, tx_pulseshaper_4800[TX_PULSESHAPER_4800_COEFF_SETS - 1 - s->baud_phase], V27TER_TX_FILTER_STEPS, s->rrc_filter_step);
x.im = vec_circular_dot_prodf(s->rrc_filter_im, tx_pulseshaper_4800[TX_PULSESHAPER_4800_COEFF_SETS - 1 - s->baud_phase], V27TER_TX_FILTER_STEPS, s->rrc_filter_step);
/* Now create and modulate the carrier */
z = dds_complexf(&(s->carrier_phase), s->carrier_phase_rate);
z = dds_complexf(&s->carrier_phase, s->carrier_phase_rate);
famp = x.re*z.re - x.im*z.im;
/* Don't bother saturating. We should never clip. */
amp[sample] = (int16_t) lfastrintf((x.re*z.re - x.im*z.im)*s->gain_4800);
amp[sample] = (int16_t) lfastrintf(famp*s->gain_4800);
#endif
}
}
@ -312,37 +308,30 @@ SPAN_DECLARE_NONSTD(int) v27ter_tx(v27ter_tx_state_t *s, int16_t amp[], int len)
if ((s->baud_phase += 3) >= 20)
{
s->baud_phase -= 20;
s->rrc_filter[s->rrc_filter_step] =
s->rrc_filter[s->rrc_filter_step + V27TER_TX_FILTER_STEPS] = getbaud(s);
v = getbaud(s);
s->rrc_filter_re[s->rrc_filter_step] = v.re;
s->rrc_filter_im[s->rrc_filter_step] = v.im;
if (++s->rrc_filter_step >= V27TER_TX_FILTER_STEPS)
s->rrc_filter_step = 0;
}
/* Root raised cosine pulse shaping at baseband */
#if defined(SPANDSP_USE_FIXED_POINT)
x = complex_seti(0, 0);
for (i = 0; i < V27TER_TX_FILTER_STEPS; i++)
{
x.re += (int32_t) tx_pulseshaper_2400[TX_PULSESHAPER_2400_COEFF_SETS - 1 - s->baud_phase][i]*(int32_t) s->rrc_filter[i + s->rrc_filter_step].re;
x.im += (int32_t) tx_pulseshaper_2400[TX_PULSESHAPER_2400_COEFF_SETS - 1 - s->baud_phase][i]*(int32_t) s->rrc_filter[i + s->rrc_filter_step].im;
}
/* Root raised cosine pulse shaping at baseband */
x.re = vec_circular_dot_prodi16(s->rrc_filter_re, tx_pulseshaper_2400[TX_PULSESHAPER_2400_COEFF_SETS - 1 - s->baud_phase], V27TER_TX_FILTER_STEPS, s->rrc_filter_step) >> (10 + 4);
x.im = vec_circular_dot_prodi16(s->rrc_filter_im, tx_pulseshaper_2400[TX_PULSESHAPER_2400_COEFF_SETS - 1 - s->baud_phase], V27TER_TX_FILTER_STEPS, s->rrc_filter_step) >> (10 + 4);
/* Now create and modulate the carrier */
x.re >>= 14;
x.im >>= 14;
z = dds_complexi(&(s->carrier_phase), s->carrier_phase_rate);
z = dds_complexi32(&s->carrier_phase, s->carrier_phase_rate);
iamp = ((int32_t) x.re*z.re - x.im*z.im) >> 15;
/* Don't bother saturating. We should never clip. */
i = (x.re*z.re - x.im*z.im) >> 15;
amp[sample] = (int16_t) ((i*s->gain_2400) >> 15);
amp[sample] = (int16_t) (((int32_t) iamp*s->gain_2400) >> 11);
#else
x = complex_setf(0.0f, 0.0f);
for (i = 0; i < V27TER_TX_FILTER_STEPS; i++)
{
x.re += tx_pulseshaper_2400[TX_PULSESHAPER_2400_COEFF_SETS - 1 - s->baud_phase][i]*s->rrc_filter[i + s->rrc_filter_step].re;
x.im += tx_pulseshaper_2400[TX_PULSESHAPER_2400_COEFF_SETS - 1 - s->baud_phase][i]*s->rrc_filter[i + s->rrc_filter_step].im;
}
/* Root raised cosine pulse shaping at baseband */
x.re = vec_circular_dot_prodf(s->rrc_filter_re, tx_pulseshaper_2400[TX_PULSESHAPER_2400_COEFF_SETS - 1 - s->baud_phase], V27TER_TX_FILTER_STEPS, s->rrc_filter_step);
x.im = vec_circular_dot_prodf(s->rrc_filter_im, tx_pulseshaper_2400[TX_PULSESHAPER_2400_COEFF_SETS - 1 - s->baud_phase], V27TER_TX_FILTER_STEPS, s->rrc_filter_step);
/* Now create and modulate the carrier */
z = dds_complexf(&(s->carrier_phase), s->carrier_phase_rate);
z = dds_complexf(&s->carrier_phase, s->carrier_phase_rate);
famp = x.re*z.re - x.im*z.im;
/* Don't bother saturating. We should never clip. */
amp[sample] = (int16_t) lfastrintf((x.re*z.re - x.im*z.im)*s->gain_2400);
amp[sample] = (int16_t) lfastrintf(famp*s->gain_2400);
#endif
}
}
@ -352,15 +341,15 @@ SPAN_DECLARE_NONSTD(int) v27ter_tx(v27ter_tx_state_t *s, int16_t amp[], int len)
SPAN_DECLARE(void) v27ter_tx_power(v27ter_tx_state_t *s, float power)
{
float l;
float gain;
l = powf(10.0f, (power - DBM0_MAX_POWER)/20.0f)*32768.0f;
gain = powf(10.0f, (power - DBM0_MAX_POWER)/20.0f)*32768.0f;
#if defined(SPANDSP_USE_FIXED_POINT)
s->gain_2400 = 16.0f*1.024f*(32767.0f/28828.51f)*l/TX_PULSESHAPER_2400_GAIN;
s->gain_4800 = 16.0f*1.024f*(32767.0f/28828.46f)*l/TX_PULSESHAPER_4800_GAIN;
s->gain_2400 = (int16_t) (gain/TX_PULSESHAPER_2400_GAIN);
s->gain_4800 = (int16_t) (gain/TX_PULSESHAPER_4800_GAIN);
#else
s->gain_2400 = l/TX_PULSESHAPER_2400_GAIN;
s->gain_4800 = l/TX_PULSESHAPER_4800_GAIN;
s->gain_2400 = gain/TX_PULSESHAPER_2400_GAIN;
s->gain_4800 = gain/TX_PULSESHAPER_4800_GAIN;
#endif
}
/*- End of function --------------------------------------------------------*/
@ -393,9 +382,11 @@ SPAN_DECLARE(int) v27ter_tx_restart(v27ter_tx_state_t *s, int bit_rate, int tep)
return -1;
s->bit_rate = bit_rate;
#if defined(SPANDSP_USE_FIXED_POINT)
cvec_zeroi16(s->rrc_filter, sizeof(s->rrc_filter)/sizeof(s->rrc_filter[0]));
vec_zeroi16(s->rrc_filter_re, sizeof(s->rrc_filter_re)/sizeof(s->rrc_filter_re[0]));
vec_zeroi16(s->rrc_filter_im, sizeof(s->rrc_filter_im)/sizeof(s->rrc_filter_im[0]));
#else
cvec_zerof(s->rrc_filter, sizeof(s->rrc_filter)/sizeof(s->rrc_filter[0]));
vec_zerof(s->rrc_filter_re, sizeof(s->rrc_filter_re)/sizeof(s->rrc_filter_re[0]));
vec_zerof(s->rrc_filter_im, sizeof(s->rrc_filter_im)/sizeof(s->rrc_filter_im[0]));
#endif
s->rrc_filter_step = 0;
s->scramble_reg = 0x3C;

View File

@ -205,13 +205,16 @@ static __inline__ complexf_t getbaud(v29_tx_state_t *s)
SPAN_DECLARE_NONSTD(int) v29_tx(v29_tx_state_t *s, int16_t amp[], int len)
{
#if defined(SPANDSP_USE_FIXED_POINT)
complexi_t x;
complexi_t z;
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;
if (s->training_step >= V29_TRAINING_SHUTDOWN_END)
@ -224,37 +227,30 @@ SPAN_DECLARE_NONSTD(int) v29_tx(v29_tx_state_t *s, int16_t amp[], int len)
if ((s->baud_phase += 3) >= 10)
{
s->baud_phase -= 10;
s->rrc_filter[s->rrc_filter_step] =
s->rrc_filter[s->rrc_filter_step + V29_TX_FILTER_STEPS] = getbaud(s);
v = getbaud(s);
s->rrc_filter_re[s->rrc_filter_step] = v.re;
s->rrc_filter_im[s->rrc_filter_step] = v.im;
if (++s->rrc_filter_step >= V29_TX_FILTER_STEPS)
s->rrc_filter_step = 0;
}
/* Root raised cosine pulse shaping at baseband */
#if defined(SPANDSP_USE_FIXED_POINT)
x = complex_seti(0, 0);
for (i = 0; i < V29_TX_FILTER_STEPS; i++)
{
x.re += (int32_t) tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->baud_phase][i]*(int32_t) s->rrc_filter[i + s->rrc_filter_step].re;
x.im += (int32_t) tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->baud_phase][i]*(int32_t) s->rrc_filter[i + s->rrc_filter_step].im;
}
/* Root raised cosine pulse shaping at baseband */
x.re = vec_circular_dot_prodi16(s->rrc_filter_re, tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->baud_phase], V29_TX_FILTER_STEPS, s->rrc_filter_step) >> 4;
x.im = vec_circular_dot_prodi16(s->rrc_filter_im, tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->baud_phase], V29_TX_FILTER_STEPS, s->rrc_filter_step) >> 4;
/* Now create and modulate the carrier */
x.re >>= 4;
x.im >>= 4;
z = dds_complexi(&(s->carrier_phase), s->carrier_phase_rate);
z = dds_complexi32(&s->carrier_phase, s->carrier_phase_rate);
iamp = ((int32_t) x.re*z.re - x.im*z.im) >> 15;
/* Don't bother saturating. We should never clip. */
i = (x.re*z.re - x.im*z.im) >> 15;
amp[sample] = (int16_t) ((i*s->gain) >> 15);
amp[sample] = (int16_t) (((int32_t) iamp*s->gain) >> 11);
#else
x = complex_setf(0.0f, 0.0f);
for (i = 0; i < V29_TX_FILTER_STEPS; i++)
{
x.re += tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->baud_phase][i]*s->rrc_filter[i + s->rrc_filter_step].re;
x.im += tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->baud_phase][i]*s->rrc_filter[i + s->rrc_filter_step].im;
}
/* Root raised cosine pulse shaping at baseband */
x.re = vec_circular_dot_prodf(s->rrc_filter_re, tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->baud_phase], V29_TX_FILTER_STEPS, s->rrc_filter_step);
x.im = vec_circular_dot_prodf(s->rrc_filter_im, tx_pulseshaper[TX_PULSESHAPER_COEFF_SETS - 1 - s->baud_phase], V29_TX_FILTER_STEPS, s->rrc_filter_step);
/* Now create and modulate the carrier */
z = dds_complexf(&(s->carrier_phase), s->carrier_phase_rate);
z = dds_complexf(&s->carrier_phase, s->carrier_phase_rate);
famp = x.re*z.re - x.im*z.im;
/* Don't bother saturating. We should never clip. */
amp[sample] = (int16_t) lfastrintf((x.re*z.re - x.im*z.im)*s->gain);
amp[sample] = (int16_t) lfastrintf(famp*s->gain);
#endif
}
return sample;
@ -267,13 +263,13 @@ static void set_working_gain(v29_tx_state_t *s)
switch (s->bit_rate)
{
case 9600:
s->gain = 0.387f*s->base_gain*16.0f*32767.0f/30672.52f;
s->gain = ((int32_t) FP_Q_4_12(0.387f)*s->base_gain) >> 12;
break;
case 7200:
s->gain = 0.605f*s->base_gain*16.0f*32767.0f/30672.52f;
s->gain = ((int32_t) FP_Q_4_12(0.605f)*s->base_gain) >> 12;
break;
case 4800:
s->gain = 0.470f*s->base_gain*16.0f*32767.0f/30672.52f;
s->gain = ((int32_t) FP_Q_4_12(0.470f)*s->base_gain) >> 12;
break;
default:
break;
@ -299,10 +295,17 @@ static void set_working_gain(v29_tx_state_t *s)
SPAN_DECLARE(void) v29_tx_power(v29_tx_state_t *s, float power)
{
float gain;
/* The constellation does not maintain constant average power as we change bit rates.
We need to scale the gain we get here by a bit rate specific scaling factor each
time we restart the modem. */
s->base_gain = powf(10.0f, (power - DBM0_MAX_POWER)/20.0f)*32768.0f/TX_PULSESHAPER_GAIN;
gain = powf(10.0f, (power - DBM0_MAX_POWER)/20.0f)*32768.0f/TX_PULSESHAPER_GAIN;
#if defined(SPANDSP_USE_FIXED_POINT)
s->base_gain = (int16_t) gain;
#else
s->base_gain = gain;
#endif
set_working_gain(s);
}
/*- End of function --------------------------------------------------------*/
@ -349,9 +352,11 @@ SPAN_DECLARE(int) v29_tx_restart(v29_tx_state_t *s, int bit_rate, int tep)
return -1;
}
#if defined(SPANDSP_USE_FIXED_POINT)
cvec_zeroi16(s->rrc_filter, sizeof(s->rrc_filter)/sizeof(s->rrc_filter[0]));
vec_zeroi16(s->rrc_filter_re, sizeof(s->rrc_filter_re)/sizeof(s->rrc_filter_re[0]));
vec_zeroi16(s->rrc_filter_im, sizeof(s->rrc_filter_im)/sizeof(s->rrc_filter_im[0]));
#else
cvec_zerof(s->rrc_filter, sizeof(s->rrc_filter)/sizeof(s->rrc_filter[0]));
vec_zerof(s->rrc_filter_re, sizeof(s->rrc_filter_re)/sizeof(s->rrc_filter_re[0]));
vec_zerof(s->rrc_filter_im, sizeof(s->rrc_filter_im)/sizeof(s->rrc_filter_im[0]));
#endif
s->rrc_filter_step = 0;
s->scramble_reg = 0;