From e9b4a497cc2a301d2d09cfde20085101bd9fe85f Mon Sep 17 00:00:00 2001 From: Steve Underwood Date: Sat, 21 Jul 2012 07:18:27 +0800 Subject: [PATCH] Tweaks --- libs/spandsp/src/spandsp/fax_modems.h | 1 + .../spandsp/src/spandsp/private/t38_gateway.h | 4 +- libs/spandsp/src/spandsp/private/v22bis.h | 66 ++++++--- libs/spandsp/src/spandsp/private/v27ter_tx.h | 7 +- libs/spandsp/src/spandsp/private/v29tx.h | 11 +- libs/spandsp/src/v22bis_tx.c | 139 +++++++++++++----- libs/spandsp/src/v27ter_tx.c | 101 ++++++------- libs/spandsp/src/v29tx.c | 67 +++++---- 8 files changed, 240 insertions(+), 156 deletions(-) diff --git a/libs/spandsp/src/spandsp/fax_modems.h b/libs/spandsp/src/spandsp/fax_modems.h index 100e57eb5c..a3f77dcc00 100644 --- a/libs/spandsp/src/spandsp/fax_modems.h +++ b/libs/spandsp/src/spandsp/fax_modems.h @@ -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); diff --git a/libs/spandsp/src/spandsp/private/t38_gateway.h b/libs/spandsp/src/spandsp/private/t38_gateway.h index d7cd549264..af72e78213 100644 --- a/libs/spandsp/src/spandsp/private/t38_gateway.h +++ b/libs/spandsp/src/spandsp/private/t38_gateway.h @@ -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 */ diff --git a/libs/spandsp/src/spandsp/private/v22bis.h b/libs/spandsp/src/spandsp/private/v22bis.h index 48e4c42714..01c37e9aea 100644 --- a/libs/spandsp/src/spandsp/private/v22bis.h +++ b/libs/spandsp/src/spandsp/private/v22bis.h @@ -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; + + int constellation_state; + +#if defined(SPANDSP_USE_FIXED_POINTx) /*! \brief The scaling factor accessed by the AGC algorithm. */ float agc_scaling; - - int constellation_state; + /*! \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. */ diff --git a/libs/spandsp/src/spandsp/private/v27ter_tx.h b/libs/spandsp/src/spandsp/private/v27ter_tx.h index 18e27e1277..5d8d41f842 100644 --- a/libs/spandsp/src/spandsp/private/v27ter_tx.h +++ b/libs/spandsp/src/spandsp/private/v27ter_tx.h @@ -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; diff --git a/libs/spandsp/src/spandsp/private/v29tx.h b/libs/spandsp/src/spandsp/private/v29tx.h index 034631ef87..67c2b7098d 100644 --- a/libs/spandsp/src/spandsp/private/v29tx.h +++ b/libs/spandsp/src/spandsp/private/v29tx.h @@ -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; diff --git a/libs/spandsp/src/v22bis_tx.c b/libs/spandsp/src/v22bis_tx.c index 41c7ed2f38..2f8c724f6b 100644 --- a/libs/spandsp/src/v22bis_tx.c +++ b/libs/spandsp/src/v22bis_tx.c @@ -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; diff --git a/libs/spandsp/src/v27ter_tx.c b/libs/spandsp/src/v27ter_tx.c index f2673444ee..99d534e25c 100644 --- a/libs/spandsp/src/v27ter_tx.c +++ b/libs/spandsp/src/v27ter_tx.c @@ -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; diff --git a/libs/spandsp/src/v29tx.c b/libs/spandsp/src/v29tx.c index 10007a93fb..7604ae4ac1 100644 --- a/libs/spandsp/src/v29tx.c +++ b/libs/spandsp/src/v29tx.c @@ -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;