Skip to content
项目
群组
代码片段
帮助
正在加载...
登录
切换导航
F
freeswitch
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
张华
freeswitch
Commits
80d5c5aa
提交
80d5c5aa
authored
12月 14, 2011
作者:
Steve Underwood
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Some tweaks to the V.22bis modem, so it builds OK in a fixed point build
上级
cc08b939
显示空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
311 行增加
和
157 行删除
+311
-157
v22bis.h
libs/spandsp/src/spandsp/private/v22bis.h
+24
-23
v22bis.h
libs/spandsp/src/spandsp/v22bis.h
+4
-0
v22bis_rx.c
libs/spandsp/src/v22bis_rx.c
+178
-76
v22bis_tx.c
libs/spandsp/src/v22bis_tx.c
+105
-58
没有找到文件。
libs/spandsp/src/spandsp/private/v22bis.h
浏览文件 @
80d5c5aa
...
@@ -26,10 +26,10 @@
...
@@ -26,10 +26,10 @@
#if !defined(_SPANDSP_PRIVATE_V22BIS_H_)
#if !defined(_SPANDSP_PRIVATE_V22BIS_H_)
#define _SPANDSP_PRIVATE_V22BIS_H_
#define _SPANDSP_PRIVATE_V22BIS_H_
/*! The
number of steps to the left and to the right of the target position in the equalizer buffer.
*/
/*! The
length of the equalizer buffer
*/
#define V22BIS_EQUALIZER_LEN 7
#define V22BIS_EQUALIZER_LEN
1
7
/*!
One less than a power of 2 >= (2*V22BIS_EQUALIZER_LEN + 1)
*/
/*!
Samples before the target position in the equalizer buffer
*/
#define V22BIS_EQUALIZER_
MASK 15
#define V22BIS_EQUALIZER_
PRE_LEN 8
/*! The number of taps in the transmit pulse shaping filter */
/*! The number of taps in the transmit pulse shaping filter */
#define V22BIS_TX_FILTER_STEPS 9
#define V22BIS_TX_FILTER_STEPS 9
...
@@ -99,9 +99,9 @@ struct v22bis_state_s
...
@@ -99,9 +99,9 @@ struct v22bis_state_s
/* Receive section */
/* Receive section */
struct
struct
{
{
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
/*! \brief The scaling factor accessed by the AGC algorithm. */
/*! \brief The scaling factor accessed by the AGC algorithm. */
floa
t
agc_scaling
;
int16_
t
agc_scaling
;
/*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
/*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
int16_t
rrc_filter
[
V22BIS_RX_FILTER_STEPS
];
int16_t
rrc_filter
[
V22BIS_RX_FILTER_STEPS
];
#else
#else
...
@@ -131,15 +131,14 @@ struct v22bis_state_s
...
@@ -131,15 +131,14 @@ struct v22bis_state_s
uint32_t
carrier_phase
;
uint32_t
carrier_phase
;
/*! \brief The update rate for the phase of the carrier (i.e. the DDS increment). */
/*! \brief The update rate for the phase of the carrier (i.e. the DDS increment). */
int32_t
carrier_phase_rate
;
int32_t
carrier_phase_rate
;
#if defined(SPANDSP_USE_FIXED_POINT)
#if defined(SPANDSP_USE_FIXED_POINTx)
/*! \brief A measure of how much mismatch there is between the real constellation,
/*! \brief A measure of how much mismatch there is between the real constellation,
and the decoded symbol positions. */
and the decoded symbol positions. */
floa
t
training_error
;
int32_
t
training_error
;
/*! \brief The proportional part of the carrier tracking filter. */
/*! \brief The proportional part of the carrier tracking filter. */
floa
t
carrier_track_p
;
int32_
t
carrier_track_p
;
/*! \brief The integral part of the carrier tracking filter. */
/*! \brief The integral part of the carrier tracking filter. */
floa
t
carrier_track_i
;
int32_
t
carrier_track_i
;
#else
#else
/*! \brief A measure of how much mismatch there is between the real constellation,
/*! \brief A measure of how much mismatch there is between the real constellation,
and the decoded symbol positions. */
and the decoded symbol positions. */
...
@@ -166,20 +165,20 @@ struct v22bis_state_s
...
@@ -166,20 +165,20 @@ struct v22bis_state_s
int
constellation_state
;
int
constellation_state
;
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
/*! \brief The current delta factor for updating the equalizer coefficients. */
/*! \brief The current delta factor for updating the equalizer coefficients. */
floa
t
eq_delta
;
int16_
t
eq_delta
;
/*! \brief The adaptive equalizer coefficients. */
/*! \brief The adaptive equalizer coefficients. */
complexi
_t
eq_coeff
[
2
*
V22BIS_EQUALIZER_LEN
+
1
];
complexi
16_t
eq_coeff
[
V22BIS_EQUALIZER_LEN
];
/*! \brief The equalizer signal buffer. */
/*! \brief The equalizer signal buffer. */
complexi
_t
eq_buf
[
V22BIS_EQUALIZER_MASK
+
1
];
complexi
16_t
eq_buf
[
V22BIS_EQUALIZER_LEN
];
#else
#else
/*! \brief The current delta factor for updating the equalizer coefficients. */
/*! \brief The current delta factor for updating the equalizer coefficients. */
float
eq_delta
;
float
eq_delta
;
/*! \brief The adaptive equalizer coefficients. */
/*! \brief The adaptive equalizer coefficients. */
complexf_t
eq_coeff
[
2
*
V22BIS_EQUALIZER_LEN
+
1
];
complexf_t
eq_coeff
[
V22BIS_EQUALIZER_LEN
];
/*! \brief The equalizer signal buffer. */
/*! \brief The equalizer signal buffer. */
complexf_t
eq_buf
[
V22BIS_EQUALIZER_
MASK
+
1
];
complexf_t
eq_buf
[
V22BIS_EQUALIZER_
LEN
];
#endif
#endif
/*! \brief Current offset into the equalizer buffer. */
/*! \brief Current offset into the equalizer buffer. */
int
eq_step
;
int
eq_step
;
...
@@ -205,20 +204,22 @@ struct v22bis_state_s
...
@@ -205,20 +204,22 @@ struct v22bis_state_s
/* Transmit section */
/* Transmit section */
struct
struct
{
{
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
/*! \brief The guard tone level. */
/*! \brief The guard tone level. */
float
guard_level
;
int16_t
guard_tone_gain
;
/*! \brief The gain factor needed to achieve the specified output power. */
/*! \brief The gain factor needed to achieve the specified output power. */
floa
t
gain
;
int16_
t
gain
;
/*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
/*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
complexf_t
rrc_filter
[
2
*
V22BIS_TX_FILTER_STEPS
];
int16_t
rrc_filter_re
[
V22BIS_TX_FILTER_STEPS
];
int16_t
rrc_filter_im
[
V22BIS_TX_FILTER_STEPS
];
#else
#else
/*! \brief The guard tone level. */
/*! \brief The guard tone level. */
float
guard_
level
;
float
guard_
tone_gain
;
/*! \brief The gain factor needed to achieve the specified output power. */
/*! \brief The gain factor needed to achieve the specified output power. */
float
gain
;
float
gain
;
/*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
/*! \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
#endif
/*! \brief Current offset into the RRC pulse shaping filter buffer. */
/*! \brief Current offset into the RRC pulse shaping filter buffer. */
...
...
libs/spandsp/src/spandsp/v22bis.h
浏览文件 @
80d5c5aa
...
@@ -86,7 +86,11 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx_fillin(v22bis_state_t *s, int len);
...
@@ -86,7 +86,11 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx_fillin(v22bis_state_t *s, int len);
\brief Get a snapshot of the current equalizer coefficients.
\brief Get a snapshot of the current equalizer coefficients.
\param coeffs The vector of complex coefficients.
\param coeffs The vector of complex coefficients.
\return The number of coefficients in the vector. */
\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
);
SPAN_DECLARE
(
int
)
v22bis_rx_equalizer_state
(
v22bis_state_t
*
s
,
complexf_t
**
coeffs
);
#endif
/*! Get the current received carrier frequency.
/*! Get the current received carrier frequency.
\param s The modem context.
\param s The modem context.
...
...
libs/spandsp/src/v22bis_rx.c
浏览文件 @
80d5c5aa
...
@@ -69,9 +69,9 @@
...
@@ -69,9 +69,9 @@
#include "spandsp/private/logging.h"
#include "spandsp/private/logging.h"
#include "spandsp/private/v22bis.h"
#include "spandsp/private/v22bis.h"
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
#include "v22bis_rx_1200_f
loating
_rrc.h"
#include "v22bis_rx_1200_f
ixed
_rrc.h"
#include "v22bis_rx_2400_f
loating
_rrc.h"
#include "v22bis_rx_2400_f
ixed
_rrc.h"
#else
#else
#include "v22bis_rx_1200_floating_rrc.h"
#include "v22bis_rx_1200_floating_rrc.h"
#include "v22bis_rx_2400_floating_rrc.h"
#include "v22bis_rx_2400_floating_rrc.h"
...
@@ -79,6 +79,11 @@
...
@@ -79,6 +79,11 @@
#define ms_to_symbols(t) (((t)*600)/1000)
#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 */
/*! The adaption rate coefficient for the equalizer */
#define EQUALIZER_DELTA 0.25f
#define EQUALIZER_DELTA 0.25f
/*! The number of phase shifted coefficient set for the pulse shaping/bandpass filter */
/*! The number of phase shifted coefficient set for the pulse shaping/bandpass filter */
...
@@ -167,24 +172,28 @@ void v22bis_report_status_change(v22bis_state_t *s, int status)
...
@@ -167,24 +172,28 @@ void v22bis_report_status_change(v22bis_state_t *s, int status)
}
}
/*- End of function --------------------------------------------------------*/
/*- 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
)
SPAN_DECLARE
(
int
)
v22bis_rx_equalizer_state
(
v22bis_state_t
*
s
,
complexf_t
**
coeffs
)
#endif
{
{
*
coeffs
=
s
->
rx
.
eq_coeff
;
*
coeffs
=
s
->
rx
.
eq_coeff
;
return
2
*
V22BIS_EQUALIZER_LEN
+
1
;
return
V22BIS_EQUALIZER_LEN
;
}
}
/*- End of function --------------------------------------------------------*/
/*- End of function --------------------------------------------------------*/
void
v22bis_equalizer_coefficient_reset
(
v22bis_state_t
*
s
)
void
v22bis_equalizer_coefficient_reset
(
v22bis_state_t
*
s
)
{
{
/* Start with an equalizer based on everything being perfect */
/* Start with an equalizer based on everything being perfect */
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
cvec_zeroi16
(
s
->
rx
.
eq_coeff
,
2
*
V22BIS_EQUALIZER_LEN
+
1
);
cvec_zeroi16
(
s
->
rx
.
eq_coeff
,
V22BIS_EQUALIZER_LEN
);
s
->
rx
.
eq_coeff
[
V22BIS_EQUALIZER_
LEN
]
=
complex_seti16
(
3
*
FP_FACTOR
,
0
*
FP_FACTOR
);
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
.
0
f
*
EQUALIZER_DELTA
/
(
2
*
V22BIS_EQUALIZER_LEN
+
1
)
;
s
->
rx
.
eq_delta
=
32768
.
0
f
*
EQUALIZER_DELTA
/
V22BIS_EQUALIZER_LEN
;
#else
#else
cvec_zerof
(
s
->
rx
.
eq_coeff
,
2
*
V22BIS_EQUALIZER_LEN
+
1
);
cvec_zerof
(
s
->
rx
.
eq_coeff
,
V22BIS_EQUALIZER_LEN
);
s
->
rx
.
eq_coeff
[
V22BIS_EQUALIZER_LEN
]
=
complex_setf
(
3
.
0
f
,
0
.
0
f
);
s
->
rx
.
eq_coeff
[
V22BIS_EQUALIZER_
PRE_
LEN
]
=
complex_setf
(
3
.
0
f
,
0
.
0
f
);
s
->
rx
.
eq_delta
=
EQUALIZER_DELTA
/
(
2
*
V22BIS_EQUALIZER_LEN
+
1
)
;
s
->
rx
.
eq_delta
=
EQUALIZER_DELTA
/
V22BIS_EQUALIZER_LEN
;
#endif
#endif
}
}
/*- End of function --------------------------------------------------------*/
/*- End of function --------------------------------------------------------*/
...
@@ -192,63 +201,68 @@ void v22bis_equalizer_coefficient_reset(v22bis_state_t *s)
...
@@ -192,63 +201,68 @@ void v22bis_equalizer_coefficient_reset(v22bis_state_t *s)
static
void
equalizer_reset
(
v22bis_state_t
*
s
)
static
void
equalizer_reset
(
v22bis_state_t
*
s
)
{
{
v22bis_equalizer_coefficient_reset
(
s
);
v22bis_equalizer_coefficient_reset
(
s
);
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
cvec_zeroi16
(
s
->
rx
.
eq_buf
,
V22BIS_EQUALIZER_
MASK
+
1
);
cvec_zeroi16
(
s
->
rx
.
eq_buf
,
V22BIS_EQUALIZER_
LEN
);
#else
#else
cvec_zerof
(
s
->
rx
.
eq_buf
,
V22BIS_EQUALIZER_
MASK
+
1
);
cvec_zerof
(
s
->
rx
.
eq_buf
,
V22BIS_EQUALIZER_
LEN
);
#endif
#endif
s
->
rx
.
eq_put_step
=
20
-
1
;
s
->
rx
.
eq_put_step
=
20
-
1
;
s
->
rx
.
eq_step
=
0
;
s
->
rx
.
eq_step
=
0
;
}
}
/*- End of function --------------------------------------------------------*/
/*- End of function --------------------------------------------------------*/
static
complexf_t
equalizer_get
(
v22bis_state_t
*
s
)
#if defined(SPANDSP_USE_FIXED_POINT)
static
__inline__
complexi16_t
equalizer_get
(
v22bis_state_t
*
s
)
{
{
int
i
;
complexi32_t
zz
;
int
p
;
complexi16_t
z
;
complexf_t
z
;
complexf_t
z1
;
/* Get the next equalized value. */
/* Get the next equalized value. */
z
=
complex_setf
(
0
.
0
f
,
0
.
0
f
);
zz
=
cvec_circular_dot_prodi16
(
s
->
rx
.
eq_buf
,
s
->
rx
.
eq_coeff
,
V22BIS_EQUALIZER_LEN
,
s
->
rx
.
eq_step
);
p
=
s
->
rx
.
eq_step
-
1
;
z
.
re
=
zz
.
re
>>
FP_SHIFT_FACTOR
;
for
(
i
=
0
;
i
<
2
*
V22BIS_EQUALIZER_LEN
+
1
;
i
++
)
z
.
im
=
zz
.
im
>>
FP_SHIFT_FACTOR
;
{
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
;
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 --------------------------------------------------------*/
/*- End of function --------------------------------------------------------*/
static
void
tune_equalizer
(
v22bis_state_t
*
s
,
const
complexf_t
*
z
,
const
complexf_t
*
target
)
#if defined(SPANDSP_USE_FIXED_POINT)
static
void
tune_equalizer
(
v22bis_state_t
*
s
,
const
complexi16_t
*
z
,
const
complexi16_t
*
target
)
{
{
int
i
;
complexi16_t
err
;
int
p
;
complexf_t
ez
;
complexf_t
z1
;
/* Find the x and y mismatch from the exact constellation position. */
/* Find the x and y mismatch from the exact constellation position. */
ez
=
complex_subf
(
target
,
z
);
err
.
re
=
target
->
re
*
FP_FACTOR
-
z
->
re
;
ez
.
re
*=
s
->
rx
.
eq_delta
;
err
.
im
=
target
->
im
*
FP_FACTOR
-
z
->
im
;
ez
.
im
*=
s
->
rx
.
eq_delta
;
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
;
p
=
s
->
rx
.
eq_step
-
1
;
/* Find the x and y mismatch from the exact constellation position. */
for
(
i
=
0
;
i
<
2
*
V22BIS_EQUALIZER_LEN
+
1
;
i
++
)
err
=
complex_subf
(
target
,
z
);
{
err
.
re
*=
s
->
rx
.
eq_delta
;
p
=
(
p
-
1
)
&
V22BIS_EQUALIZER_MASK
;
err
.
im
*=
s
->
rx
.
eq_delta
;
z1
=
complex_conjf
(
&
s
->
rx
.
eq_buf
[
p
]);
cvec_circular_lmsf
(
s
->
rx
.
eq_buf
,
s
->
rx
.
eq_coeff
,
V22BIS_EQUALIZER_LEN
,
s
->
rx
.
eq_step
,
&
err
);
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
.
9999
f
;
s
->
rx
.
eq_coeff
[
i
].
im
*=
0
.
9999
f
;
}
}
}
#endif
/*- End of function --------------------------------------------------------*/
/*- 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
)
static
__inline__
void
track_carrier
(
v22bis_state_t
*
s
,
const
complexf_t
*
z
,
const
complexf_t
*
target
)
#endif
{
{
float
error
;
float
error
;
...
@@ -336,40 +350,69 @@ static int decode_baudx(v22bis_state_t *s, int nearest)
...
@@ -336,40 +350,69 @@ static int decode_baudx(v22bis_state_t *s, int nearest)
static
__inline__
void
symbol_sync
(
v22bis_state_t
*
s
)
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
p
;
float
q
;
float
q
;
complexf_t
zz
;
complexf_t
zz
;
complexf_t
a
;
complexf_t
a
;
complexf_t
b
;
complexf_t
b
;
complexf_t
c
;
complexf_t
c
;
#endif
int
aa
[
3
];
int
i
;
int
j
;
/* This routine adapts the position of the half baud samples entering the equalizer. */
/* 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. */
/* 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
)
if
(
s
->
rx
.
sixteen_way_decisions
)
{
{
p
=
s
->
rx
.
eq_buf
[(
s
->
rx
.
eq_step
-
3
)
&
V22BIS_EQUALIZER_MASK
].
re
p
=
s
->
rx
.
eq_buf
[
aa
[
2
]].
re
-
s
->
rx
.
eq_buf
[
aa
[
0
]].
re
;
-
s
->
rx
.
eq_buf
[(
s
->
rx
.
eq_step
-
1
)
&
V22BIS_EQUALIZER_MASK
].
re
;
p
*=
s
->
rx
.
eq_buf
[
aa
[
1
]].
re
;
p
*=
s
->
rx
.
eq_buf
[(
s
->
rx
.
eq_step
-
2
)
&
V22BIS_EQUALIZER_MASK
].
re
;
q
=
s
->
rx
.
eq_buf
[(
s
->
rx
.
eq_step
-
3
)
&
V22BIS_EQUALIZER_MASK
].
im
q
=
s
->
rx
.
eq_buf
[
aa
[
2
]].
im
-
s
->
rx
.
eq_buf
[
aa
[
0
]].
im
;
-
s
->
rx
.
eq_buf
[(
s
->
rx
.
eq_step
-
1
)
&
V22BIS_EQUALIZER_MASK
].
im
;
q
*=
s
->
rx
.
eq_buf
[
aa
[
1
]].
im
;
q
*=
s
->
rx
.
eq_buf
[(
s
->
rx
.
eq_step
-
2
)
&
V22BIS_EQUALIZER_MASK
].
im
;
}
}
else
else
{
{
/* Rotate the points to the 45 degree positions, to maximise the effectiveness of
/* 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
the Gardner algorithm. This is particularly significant at the start of operation
to pull things in quickly. */
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
.
44721
f
));
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
.
44721
f
);
zz
=
complex_setf
(
0
.
894427
,
0
.
44721
f
);
a
=
complex_mulf
(
&
s
->
rx
.
eq_buf
[
(
s
->
rx
.
eq_step
-
3
)
&
V22BIS_EQUALIZER_MASK
],
&
zz
);
a
=
complex_mulf
(
&
s
->
rx
.
eq_buf
[
aa
[
2
]
],
&
zz
);
b
=
complex_mulf
(
&
s
->
rx
.
eq_buf
[
(
s
->
rx
.
eq_step
-
2
)
&
V22BIS_EQUALIZER_MASK
],
&
zz
);
b
=
complex_mulf
(
&
s
->
rx
.
eq_buf
[
aa
[
1
]
],
&
zz
);
c
=
complex_mulf
(
&
s
->
rx
.
eq_buf
[
(
s
->
rx
.
eq_step
-
1
)
&
V22BIS_EQUALIZER_MASK
],
&
zz
);
c
=
complex_mulf
(
&
s
->
rx
.
eq_buf
[
aa
[
0
]
],
&
zz
);
p
=
(
a
.
re
-
c
.
re
)
*
b
.
re
;
p
=
(
a
.
re
-
c
.
re
)
*
b
.
re
;
q
=
(
a
.
im
-
c
.
im
)
*
b
.
im
;
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
.
0
f
)
?
s
->
rx
.
gardner_step
:
-
s
->
rx
.
gardner_step
;
s
->
rx
.
gardner_integrate
+=
(
p
+
q
>
0
.
0
f
)
?
s
->
rx
.
gardner_step
:
-
s
->
rx
.
gardner_step
;
#endif
if
(
abs
(
s
->
rx
.
gardner_integrate
)
>=
16
)
if
(
abs
(
s
->
rx
.
gardner_integrate
)
>=
16
)
{
{
...
@@ -386,11 +429,21 @@ static __inline__ void symbol_sync(v22bis_state_t *s)
...
@@ -386,11 +429,21 @@ static __inline__ void symbol_sync(v22bis_state_t *s)
}
}
/*- End of function --------------------------------------------------------*/
/*- 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
)
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
z
;
complexf_t
zz
;
complexf_t
zz
;
const
complexf_t
*
target
;
const
complexf_t
*
target
;
#endif
int
re
;
int
re
;
int
im
;
int
im
;
int
nearest
;
int
nearest
;
...
@@ -403,7 +456,8 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
...
@@ -403,7 +456,8 @@ 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
/* Add a sample to the equalizer's circular buffer, but don't calculate anything
at this time. */
at this time. */
s
->
rx
.
eq_buf
[
s
->
rx
.
eq_step
]
=
z
;
s
->
rx
.
eq_buf
[
s
->
rx
.
eq_step
]
=
z
;
s
->
rx
.
eq_step
=
(
s
->
rx
.
eq_step
+
1
)
&
V22BIS_EQUALIZER_MASK
;
if
(
++
s
->
rx
.
eq_step
>=
V22BIS_EQUALIZER_LEN
)
s
->
rx
.
eq_step
=
0
;
/* On alternate insertions we have a whole baud and must process it. */
/* On alternate insertions we have a whole baud and must process it. */
if
((
s
->
rx
.
baud_phase
^=
1
))
if
((
s
->
rx
.
baud_phase
^=
1
))
...
@@ -416,6 +470,18 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
...
@@ -416,6 +470,18 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
/* Find the constellation point */
/* Find the constellation point */
if
(
s
->
rx
.
sixteen_way_decisions
)
if
(
s
->
rx
.
sixteen_way_decisions
)
{
{
#if defined(SPANDSP_USE_FIXED_POINT)
re
=
(
int
)
(
z
.
re
+
FP_Q_6_10
(
3
.
0
f
));
if
(
re
>
5
)
re
=
5
;
else
if
(
re
<
0
)
re
=
0
;
im
=
(
int
)
(
z
.
im
+
FP_Q_6_10
(
3
.
0
f
));
if
(
im
>
5
)
im
=
5
;
else
if
(
im
<
0
)
im
=
0
;
#else
re
=
(
int
)
(
z
.
re
+
3
.
0
f
);
re
=
(
int
)
(
z
.
re
+
3
.
0
f
);
if
(
re
>
5
)
if
(
re
>
5
)
re
=
5
;
re
=
5
;
...
@@ -426,13 +492,19 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
...
@@ -426,13 +492,19 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
im
=
5
;
im
=
5
;
else
if
(
im
<
0
)
else
if
(
im
<
0
)
im
=
0
;
im
=
0
;
#endif
nearest
=
space_map_v22bis
[
re
][
im
];
nearest
=
space_map_v22bis
[
re
][
im
];
}
}
else
else
{
{
/* Rotate to 45 degrees, to make the slicing trivial */
/* 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
.
44721
f
));
zz
=
complex_muli16
(
&
z
,
&
zz
);
#else
zz
=
complex_setf
(
0
.
894427
,
0
.
44721
f
);
zz
=
complex_setf
(
0
.
894427
,
0
.
44721
f
);
zz
=
complex_mulf
(
&
z
,
&
zz
);
zz
=
complex_mulf
(
&
z
,
&
zz
);
#endif
nearest
=
0x01
;
nearest
=
0x01
;
if
(
zz
.
re
<
0
.
0
f
)
if
(
zz
.
re
<
0
.
0
f
)
nearest
|=
0x04
;
nearest
|=
0x04
;
...
@@ -490,10 +562,7 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
...
@@ -490,10 +562,7 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
error could be higher. */
error could be higher. */
s
->
rx
.
gardner_step
=
4
;
s
->
rx
.
gardner_step
=
4
;
s
->
rx
.
pattern_repeats
=
0
;
s
->
rx
.
pattern_repeats
=
0
;
if
(
s
->
calling_party
)
s
->
rx
.
training
=
(
s
->
calling_party
)
?
V22BIS_RX_TRAINING_STAGE_UNSCRAMBLED_ONES
:
V22BIS_RX_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200
;
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 */
/* Be pessimistic and see what the handshake brings */
s
->
negotiated_bit_rate
=
1200
;
s
->
negotiated_bit_rate
=
1200
;
break
;
break
;
...
@@ -527,14 +596,14 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
...
@@ -527,14 +596,14 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
/* It looks like the answering machine is sending us a clean unscrambled 11 or 00 */
/* It looks like the answering machine is sending us a clean unscrambled 11 or 00 */
if
(
s
->
bit_rate
==
2400
)
if
(
s
->
bit_rate
==
2400
)
{
{
/* Try to establish at 2400bps */
/* Try to establish at 2400bps
.
*/
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"+++ starting U0011 (S1) (Caller)
\n
"
);
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"+++ starting U0011 (S1) (Caller)
\n
"
);
s
->
tx
.
training
=
V22BIS_TX_TRAINING_STAGE_U0011
;
s
->
tx
.
training
=
V22BIS_TX_TRAINING_STAGE_U0011
;
s
->
tx
.
training_count
=
0
;
s
->
tx
.
training_count
=
0
;
}
}
else
else
{
{
/* Only try to establish at 1200bps */
/* Only try to establish at 1200bps
.
*/
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"+++ starting S11 (1200) (Caller)
\n
"
);
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"+++ starting S11 (1200) (Caller)
\n
"
);
s
->
tx
.
training
=
V22BIS_TX_TRAINING_STAGE_S11
;
s
->
tx
.
training
=
V22BIS_TX_TRAINING_STAGE_S11
;
s
->
tx
.
training_count
=
0
;
s
->
tx
.
training_count
=
0
;
...
@@ -547,14 +616,14 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
...
@@ -547,14 +616,14 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
break
;
break
;
case
V22BIS_RX_TRAINING_STAGE_UNSCRAMBLED_ONES_SUSTAINING
:
case
V22BIS_RX_TRAINING_STAGE_UNSCRAMBLED_ONES_SUSTAINING
:
/* Calling modem only */
/* Calling modem only */
/* Wait for the end of the unscrambled ones at 1200bps */
/* Wait for the end of the unscrambled ones at 1200bps
.
*/
target
=
&
v22bis_constellation
[
nearest
];
target
=
&
v22bis_constellation
[
nearest
];
track_carrier
(
s
,
&
z
,
target
);
track_carrier
(
s
,
&
z
,
target
);
raw_bits
=
phase_steps
[((
nearest
>>
2
)
-
(
s
->
rx
.
constellation_state
>>
2
))
&
3
];
raw_bits
=
phase_steps
[((
nearest
>>
2
)
-
(
s
->
rx
.
constellation_state
>>
2
))
&
3
];
s
->
rx
.
constellation_state
=
nearest
;
s
->
rx
.
constellation_state
=
nearest
;
if
(
raw_bits
!=
s
->
rx
.
last_raw_bits
)
if
(
raw_bits
!=
s
->
rx
.
last_raw_bits
)
{
{
/* This looks like the end of the sustained initial unscrambled 11 or 00 */
/* This looks like the end of the sustained initial unscrambled 11 or 00
.
*/
s
->
tx
.
training_count
=
0
;
s
->
tx
.
training_count
=
0
;
s
->
tx
.
training
=
V22BIS_TX_TRAINING_STAGE_TIMED_S11
;
s
->
tx
.
training
=
V22BIS_TX_TRAINING_STAGE_TIMED_S11
;
s
->
rx
.
training_count
=
0
;
s
->
rx
.
training_count
=
0
;
...
@@ -600,11 +669,11 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
...
@@ -600,11 +669,11 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
}
}
if
(
s
->
rx
.
training_count
>=
ms_to_symbols
(
270
))
if
(
s
->
rx
.
training_count
>=
ms_to_symbols
(
270
))
{
{
/* If we haven't seen the S1 signal by now, we are committed to be in 1200bps mode */
/* If we haven't seen the S1 signal by now, we are committed to be in 1200bps mode
.
*/
if
(
s
->
calling_party
)
if
(
s
->
calling_party
)
{
{
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"+++ Rx normal operation (1200)
\n
"
);
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"+++ Rx normal operation (1200)
\n
"
);
/* The transmit side needs to sustain the scrambled ones for a timed period */
/* The transmit side needs to sustain the scrambled ones for a timed period
.
*/
s
->
tx
.
training_count
=
0
;
s
->
tx
.
training_count
=
0
;
s
->
tx
.
training
=
V22BIS_TX_TRAINING_STAGE_TIMED_S11
;
s
->
tx
.
training
=
V22BIS_TX_TRAINING_STAGE_TIMED_S11
;
/* Normal reception starts immediately */
/* Normal reception starts immediately */
...
@@ -614,7 +683,7 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
...
@@ -614,7 +683,7 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
else
else
{
{
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"+++ starting S11 (1200) (Answerer)
\n
"
);
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"+++ starting S11 (1200) (Answerer)
\n
"
);
/* The transmit side needs to sustain the scrambled ones for a timed period */
/* The transmit side needs to sustain the scrambled ones for a timed period
.
*/
s
->
tx
.
training_count
=
0
;
s
->
tx
.
training_count
=
0
;
s
->
tx
.
training
=
V22BIS_TX_TRAINING_STAGE_TIMED_S11
;
s
->
tx
.
training
=
V22BIS_TX_TRAINING_STAGE_TIMED_S11
;
/* The receive side needs to wait a timed period, receiving scrambled ones,
/* The receive side needs to wait a timed period, receiving scrambled ones,
...
@@ -695,12 +764,21 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
...
@@ -695,12 +764,21 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
{
{
int
i
;
int
i
;
int
step
;
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
z
;
complexf_t
zz
;
complexf_t
zz
;
int32_t
power
;
complexf_t
sample
;
complexf_t
sample
;
float
ii
;
float
ii
;
float
qq
;
float
qq
;
#endif
int32_t
power
;
for
(
i
=
0
;
i
<
len
;
i
++
)
for
(
i
=
0
;
i
<
len
;
i
++
)
{
{
...
@@ -717,7 +795,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
...
@@ -717,7 +795,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
if
(
s
->
calling_party
)
if
(
s
->
calling_party
)
{
{
#if defined(SPANDSP_USE_FIXED_POINT)
#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
);
ii
=
vec_circular_dot_prodi16
(
s
->
rx
.
rrc_filter
,
rx_pulseshaper_2400_re
[
6
],
V22BIS_RX_FILTER_STEPS
,
s
->
rx
.
rrc_filter_step
)
>>
15
;
#else
#else
ii
=
vec_circular_dot_prodf
(
s
->
rx
.
rrc_filter
,
rx_pulseshaper_2400_re
[
6
],
V22BIS_RX_FILTER_STEPS
,
s
->
rx
.
rrc_filter_step
);
ii
=
vec_circular_dot_prodf
(
s
->
rx
.
rrc_filter
,
rx_pulseshaper_2400_re
[
6
],
V22BIS_RX_FILTER_STEPS
,
s
->
rx
.
rrc_filter_step
);
#endif
#endif
...
@@ -725,7 +803,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
...
@@ -725,7 +803,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
else
else
{
{
#if defined(SPANDSP_USE_FIXED_POINT)
#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
);
ii
=
vec_circular_dot_prodi16
(
s
->
rx
.
rrc_filter
,
rx_pulseshaper_1200_re
[
6
],
V22BIS_RX_FILTER_STEPS
,
s
->
rx
.
rrc_filter_step
)
>>
15
;
#else
#else
ii
=
vec_circular_dot_prodf
(
s
->
rx
.
rrc_filter
,
rx_pulseshaper_1200_re
[
6
],
V22BIS_RX_FILTER_STEPS
,
s
->
rx
.
rrc_filter_step
);
ii
=
vec_circular_dot_prodf
(
s
->
rx
.
rrc_filter
,
rx_pulseshaper_1200_re
[
6
],
V22BIS_RX_FILTER_STEPS
,
s
->
rx
.
rrc_filter_step
);
#endif
#endif
...
@@ -753,11 +831,25 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
...
@@ -753,11 +831,25 @@ 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
/* Only spend effort processing this data if the modem is not
parked, after a training failure. */
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
);
z
=
dds_complexf
(
&
s
->
rx
.
carrier_phase
,
s
->
rx
.
carrier_phase_rate
);
#endif
if
(
s
->
rx
.
training
==
V22BIS_RX_TRAINING_STAGE_SYMBOL_ACQUISITION
)
if
(
s
->
rx
.
training
==
V22BIS_RX_TRAINING_STAGE_SYMBOL_ACQUISITION
)
{
{
/* Only AGC during the initial symbol acquisition, and then lock the gain. */
/* Only AGC during the initial symbol acquisition, and then lock the gain. */
#if defined(SPANDSP_USE_FIXED_POINT)
vv
=
0
.
18
f
*
3
.
60
f
/
sqrtf
(
power
);
if
(
vv
>
32767
.
0
f
)
s
->
rx
.
agc_scaling
=
32767
;
else
if
(
vv
>
-
32768
.
0
f
)
s
->
rx
.
agc_scaling
=
-
32768
;
else
s
->
rx
.
agc_scaling
=
vv
;
#else
s
->
rx
.
agc_scaling
=
0
.
18
f
*
3
.
60
f
/
sqrtf
(
power
);
s
->
rx
.
agc_scaling
=
0
.
18
f
*
3
.
60
f
/
sqrtf
(
power
);
#endif
}
}
/* Put things into the equalization buffer at T/2 rate. The Gardner algorithm
/* Put things into the equalization buffer at T/2 rate. The Gardner algorithm
will fiddle the step to align this with the symbols. */
will fiddle the step to align this with the symbols. */
...
@@ -774,8 +866,8 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
...
@@ -774,8 +866,8 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
if
(
s
->
calling_party
)
if
(
s
->
calling_party
)
{
{
#if defined(SPANDSP_USE_FIXED_POINT)
#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
);
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
);
qq
=
vec_circular_dot_prodi16
(
s
->
rx
.
rrc_filter
,
rx_pulseshaper_2400_im
[
step
],
V22BIS_RX_FILTER_STEPS
,
s
->
rx
.
rrc_filter_step
)
>>
15
;
#else
#else
ii
=
vec_circular_dot_prodf
(
s
->
rx
.
rrc_filter
,
rx_pulseshaper_2400_re
[
step
],
V22BIS_RX_FILTER_STEPS
,
s
->
rx
.
rrc_filter_step
);
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
);
qq
=
vec_circular_dot_prodf
(
s
->
rx
.
rrc_filter
,
rx_pulseshaper_2400_im
[
step
],
V22BIS_RX_FILTER_STEPS
,
s
->
rx
.
rrc_filter_step
);
...
@@ -784,15 +876,20 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
...
@@ -784,15 +876,20 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
else
else
{
{
#if defined(SPANDSP_USE_FIXED_POINT)
#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
);
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
);
qq
=
vec_circular_dot_prodi16
(
s
->
rx
.
rrc_filter
,
rx_pulseshaper_1200_im
[
step
],
V22BIS_RX_FILTER_STEPS
,
s
->
rx
.
rrc_filter_step
)
>>
15
;
#else
#else
ii
=
vec_circular_dot_prodf
(
s
->
rx
.
rrc_filter
,
rx_pulseshaper_1200_re
[
step
],
V22BIS_RX_FILTER_STEPS
,
s
->
rx
.
rrc_filter_step
);
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
);
qq
=
vec_circular_dot_prodf
(
s
->
rx
.
rrc_filter
,
rx_pulseshaper_1200_im
[
step
],
V22BIS_RX_FILTER_STEPS
,
s
->
rx
.
rrc_filter_step
);
#endif
#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
.
re
=
ii
*
s
->
rx
.
agc_scaling
;
sample
.
im
=
qq
*
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
/* Shift to baseband - since this is done in a full complex form, the
result is clean, and requires no further filtering apart from the
result is clean, and requires no further filtering apart from the
equalizer. */
equalizer. */
...
@@ -817,7 +914,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx_fillin(v22bis_state_t *s, int len)
...
@@ -817,7 +914,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx_fillin(v22bis_state_t *s, int len)
return
0
;
return
0
;
for
(
i
=
0
;
i
<
len
;
i
++
)
for
(
i
=
0
;
i
<
len
;
i
++
)
{
{
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
dds_advance
(
&
s
->
rx
.
carrier_phase
,
s
->
rx
.
carrier_phase_rate
);
dds_advance
(
&
s
->
rx
.
carrier_phase
,
s
->
rx
.
carrier_phase_rate
);
#else
#else
dds_advancef
(
&
s
->
rx
.
carrier_phase
,
s
->
rx
.
carrier_phase_rate
);
dds_advancef
(
&
s
->
rx
.
carrier_phase
,
s
->
rx
.
carrier_phase_rate
);
...
@@ -830,7 +927,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx_fillin(v22bis_state_t *s, int len)
...
@@ -830,7 +927,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx_fillin(v22bis_state_t *s, int len)
int
v22bis_rx_restart
(
v22bis_state_t
*
s
)
int
v22bis_rx_restart
(
v22bis_state_t
*
s
)
{
{
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
vec_zeroi16
(
s
->
rx
.
rrc_filter
,
sizeof
(
s
->
rx
.
rrc_filter
)
/
sizeof
(
s
->
rx
.
rrc_filter
[
0
]));
vec_zeroi16
(
s
->
rx
.
rrc_filter
,
sizeof
(
s
->
rx
.
rrc_filter
)
/
sizeof
(
s
->
rx
.
rrc_filter
[
0
]));
#else
#else
vec_zerof
(
s
->
rx
.
rrc_filter
,
sizeof
(
s
->
rx
.
rrc_filter
)
/
sizeof
(
s
->
rx
.
rrc_filter
[
0
]));
vec_zerof
(
s
->
rx
.
rrc_filter
,
sizeof
(
s
->
rx
.
rrc_filter
)
/
sizeof
(
s
->
rx
.
rrc_filter
[
0
]));
...
@@ -861,8 +958,13 @@ int v22bis_rx_restart(v22bis_state_t *s)
...
@@ -861,8 +958,13 @@ int v22bis_rx_restart(v22bis_state_t *s)
s
->
rx
.
training_error
=
0
.
0
f
;
s
->
rx
.
training_error
=
0
.
0
f
;
s
->
rx
.
total_baud_timing_correction
=
0
;
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. */
/* 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
.
0
f
:
40000
.
0
f
;
s
->
rx
.
carrier_track_i
=
(
s
->
calling_party
)
?
8000
.
0
f
:
40000
.
0
f
;
s
->
rx
.
carrier_track_p
=
8000000
.
0
f
;
s
->
rx
.
carrier_track_p
=
8000000
.
0
f
;
#endif
s
->
negotiated_bit_rate
=
1200
;
s
->
negotiated_bit_rate
=
1200
;
...
...
libs/spandsp/src/v22bis_tx.c
浏览文件 @
80d5c5aa
...
@@ -62,7 +62,7 @@
...
@@ -62,7 +62,7 @@
#include "spandsp/private/logging.h"
#include "spandsp/private/logging.h"
#include "spandsp/private/v22bis.h"
#include "spandsp/private/v22bis.h"
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
#include "v22bis_tx_fixed_rrc.h"
#include "v22bis_tx_fixed_rrc.h"
#else
#else
#include "v22bis_tx_floating_rrc.h"
#include "v22bis_tx_floating_rrc.h"
...
@@ -246,24 +246,28 @@ static const int phase_steps[4] =
...
@@ -246,24 +246,28 @@ static const int phase_steps[4] =
1
,
0
,
2
,
3
1
,
0
,
2
,
3
};
};
#if defined(SPANDSP_USE_FIXED_POINT)
const
complexi16_t
v22bis_constellation
[
16
]
=
#else
const
complexf_t
v22bis_constellation
[
16
]
=
const
complexf_t
v22bis_constellation
[
16
]
=
#endif
{
{
{
1
.
0
f
,
1
.
0
f
},
{
1
,
1
},
{
3
.
0
f
,
1
.
0
f
},
/* 1200bps 00 */
{
3
,
1
},
/* 1200bps 00 */
{
1
.
0
f
,
3
.
0
f
},
{
1
,
3
},
{
3
.
0
f
,
3
.
0
f
},
{
3
,
3
},
{
-
1
.
0
f
,
1
.
0
f
},
{
-
1
,
1
},
{
-
1
.
0
f
,
3
.
0
f
},
/* 1200bps 01 */
{
-
1
,
3
},
/* 1200bps 01 */
{
-
3
.
0
f
,
1
.
0
f
},
{
-
3
,
1
},
{
-
3
.
0
f
,
3
.
0
f
},
{
-
3
,
3
},
{
-
1
.
0
f
,
-
1
.
0
f
},
{
-
1
,
-
1
},
{
-
3
.
0
f
,
-
1
.
0
f
},
/* 1200bps 10 */
{
-
3
,
-
1
},
/* 1200bps 10 */
{
-
1
.
0
f
,
-
3
.
0
f
},
{
-
1
,
-
3
},
{
-
3
.
0
f
,
-
3
.
0
f
},
{
-
3
,
-
3
},
{
1
.
0
f
,
-
1
.
0
f
},
{
1
,
-
1
},
{
1
.
0
f
,
-
3
.
0
f
},
/* 1200bps 11 */
{
1
,
-
3
},
/* 1200bps 11 */
{
3
.
0
f
,
-
1
.
0
f
},
{
3
,
-
1
},
{
3
.
0
f
,
-
3
.
0
f
}
{
3
,
-
3
}
};
};
static
int
fake_get_bit
(
void
*
user_data
)
static
int
fake_get_bit
(
void
*
user_data
)
...
@@ -308,9 +312,17 @@ static __inline__ int get_scrambled_bit(v22bis_state_t *s)
...
@@ -308,9 +312,17 @@ static __inline__ int get_scrambled_bit(v22bis_state_t *s)
}
}
/*- End of function --------------------------------------------------------*/
/*- 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
)
static
complexf_t
training_get
(
v22bis_state_t
*
s
)
#endif
{
{
complexf_t
z
;
#if defined(SPANDSP_USE_FIXED_POINT)
static
const
complexi16_t
zero
=
{
0
,
0
};
#else
static
const
complexf_t
zero
=
{
0
.
0
f
,
0
.
0
f
};
#endif
int
bits
;
int
bits
;
/* V.22bis training sequence */
/* V.22bis training sequence */
...
@@ -329,20 +341,17 @@ static complexf_t training_get(v22bis_state_t *s)
...
@@ -329,20 +341,17 @@ static complexf_t training_get(v22bis_state_t *s)
case
V22BIS_TX_TRAINING_STAGE_INITIAL_SILENCE
:
case
V22BIS_TX_TRAINING_STAGE_INITIAL_SILENCE
:
/* Silence */
/* Silence */
s
->
tx
.
constellation_state
=
0
;
s
->
tx
.
constellation_state
=
0
;
z
=
complex_setf
(
0
.
0
f
,
0
.
0
f
);
return
zero
;
break
;
case
V22BIS_TX_TRAINING_STAGE_U11
:
case
V22BIS_TX_TRAINING_STAGE_U11
:
/* Send continuous unscrambled ones at 1200bps (i.e. 270 degree phase steps). */
/* 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. */
/* 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
;
s
->
tx
.
constellation_state
=
(
s
->
tx
.
constellation_state
+
phase_steps
[
3
])
&
3
;
z
=
v22bis_constellation
[(
s
->
tx
.
constellation_state
<<
2
)
|
0x01
];
return
v22bis_constellation
[(
s
->
tx
.
constellation_state
<<
2
)
|
0x01
];
break
;
case
V22BIS_TX_TRAINING_STAGE_U0011
:
case
V22BIS_TX_TRAINING_STAGE_U0011
:
/* Continuous unscrambled double dibit 00 11 at 1200bps. This is termed the S1 segment in
/* 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
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. */
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
;
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
))
if
(
++
s
->
tx
.
training_count
>=
ms_to_symbols
(
100
))
{
{
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"+++ starting S11 after U0011
\n
"
);
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"+++ starting S11 after U0011
\n
"
);
...
@@ -357,7 +366,7 @@ static complexf_t training_get(v22bis_state_t *s)
...
@@ -357,7 +366,7 @@ static complexf_t training_get(v22bis_state_t *s)
s
->
tx
.
training
=
V22BIS_TX_TRAINING_STAGE_TIMED_S11
;
s
->
tx
.
training
=
V22BIS_TX_TRAINING_STAGE_TIMED_S11
;
}
}
}
}
break
;
return
v22bis_constellation
[(
s
->
tx
.
constellation_state
<<
2
)
|
0x01
]
;
case
V22BIS_TX_TRAINING_STAGE_TIMED_S11
:
case
V22BIS_TX_TRAINING_STAGE_TIMED_S11
:
/* A timed period of scrambled ones at 1200bps. */
/* A timed period of scrambled ones at 1200bps. */
if
(
++
s
->
tx
.
training_count
>=
ms_to_symbols
(
756
))
if
(
++
s
->
tx
.
training_count
>=
ms_to_symbols
(
756
))
...
@@ -383,8 +392,7 @@ static complexf_t training_get(v22bis_state_t *s)
...
@@ -383,8 +392,7 @@ static complexf_t training_get(v22bis_state_t *s)
bits
=
scramble
(
s
,
1
);
bits
=
scramble
(
s
,
1
);
bits
=
(
bits
<<
1
)
|
scramble
(
s
,
1
);
bits
=
(
bits
<<
1
)
|
scramble
(
s
,
1
);
s
->
tx
.
constellation_state
=
(
s
->
tx
.
constellation_state
+
phase_steps
[
bits
])
&
3
;
s
->
tx
.
constellation_state
=
(
s
->
tx
.
constellation_state
+
phase_steps
[
bits
])
&
3
;
z
=
v22bis_constellation
[(
s
->
tx
.
constellation_state
<<
2
)
|
0x01
];
return
v22bis_constellation
[(
s
->
tx
.
constellation_state
<<
2
)
|
0x01
];
break
;
case
V22BIS_TX_TRAINING_STAGE_S1111
:
case
V22BIS_TX_TRAINING_STAGE_S1111
:
/* Scrambled ones at 2400bps. We send a timed 200ms burst, and switch to normal operation at 2400bps */
/* Scrambled ones at 2400bps. We send a timed 200ms burst, and switch to normal operation at 2400bps */
bits
=
scramble
(
s
,
1
);
bits
=
scramble
(
s
,
1
);
...
@@ -392,7 +400,6 @@ static complexf_t training_get(v22bis_state_t *s)
...
@@ -392,7 +400,6 @@ static complexf_t training_get(v22bis_state_t *s)
s
->
tx
.
constellation_state
=
(
s
->
tx
.
constellation_state
+
phase_steps
[
bits
])
&
3
;
s
->
tx
.
constellation_state
=
(
s
->
tx
.
constellation_state
+
phase_steps
[
bits
])
&
3
;
bits
=
scramble
(
s
,
1
);
bits
=
scramble
(
s
,
1
);
bits
=
(
bits
<<
1
)
|
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
))
if
(
++
s
->
tx
.
training_count
>=
ms_to_symbols
(
200
))
{
{
/* We have completed training. Now handle some real work. */
/* We have completed training. Now handle some real work. */
...
@@ -402,18 +409,23 @@ static complexf_t training_get(v22bis_state_t *s)
...
@@ -402,18 +409,23 @@ static complexf_t training_get(v22bis_state_t *s)
v22bis_report_status_change
(
s
,
SIG_STATUS_TRAINING_SUCCEEDED
);
v22bis_report_status_change
(
s
,
SIG_STATUS_TRAINING_SUCCEEDED
);
s
->
tx
.
current_get_bit
=
s
->
get_bit
;
s
->
tx
.
current_get_bit
=
s
->
get_bit
;
}
}
break
;
return
v22bis_constellation
[(
s
->
tx
.
constellation_state
<<
2
)
|
bits
];
case
V22BIS_TX_TRAINING_STAGE_PARKED
:
default:
z
=
complex_setf
(
0
.
0
f
,
0
.
0
f
);
break
;
}
}
return
z
;
return
z
ero
;
}
}
/*- End of function --------------------------------------------------------*/
/*- 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
)
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
.
0
f
,
0
.
0
f
};
#endif
int
bits
;
int
bits
;
if
(
s
->
tx
.
training
)
if
(
s
->
tx
.
training
)
...
@@ -428,7 +440,7 @@ static complexf_t getbaud(v22bis_state_t *s)
...
@@ -428,7 +440,7 @@ static complexf_t getbaud(v22bis_state_t *s)
if
(
s
->
tx
.
shutdown
)
if
(
s
->
tx
.
shutdown
)
{
{
if
(
++
s
->
tx
.
shutdown
>
10
)
if
(
++
s
->
tx
.
shutdown
>
10
)
return
complex_setf
(
0
.
0
f
,
0
.
0
f
)
;
return
zero
;
}
}
/* The first two bits define the quadrant */
/* The first two bits define the quadrant */
bits
=
get_scrambled_bit
(
s
);
bits
=
get_scrambled_bit
(
s
);
...
@@ -450,11 +462,18 @@ static complexf_t getbaud(v22bis_state_t *s)
...
@@ -450,11 +462,18 @@ static complexf_t getbaud(v22bis_state_t *s)
SPAN_DECLARE_NONSTD
(
int
)
v22bis_tx
(
v22bis_state_t
*
s
,
int16_t
amp
[],
int
len
)
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
x
;
complexf_t
z
;
complexf_t
z
;
int
i
;
int
sample
;
float
famp
;
float
famp
;
#endif
int
sample
;
if
(
s
->
tx
.
shutdown
>
10
)
if
(
s
->
tx
.
shutdown
>
10
)
return
0
;
return
0
;
...
@@ -463,28 +482,41 @@ SPAN_DECLARE_NONSTD(int) v22bis_tx(v22bis_state_t *s, int16_t amp[], int len)
...
@@ -463,28 +482,41 @@ SPAN_DECLARE_NONSTD(int) v22bis_tx(v22bis_state_t *s, int16_t amp[], int len)
if
((
s
->
tx
.
baud_phase
+=
3
)
>=
40
)
if
((
s
->
tx
.
baud_phase
+=
3
)
>=
40
)
{
{
s
->
tx
.
baud_phase
-=
40
;
s
->
tx
.
baud_phase
-=
40
;
s
->
tx
.
rrc_filter
[
s
->
tx
.
rrc_filter_step
]
=
v
=
getbaud
(
s
);
s
->
tx
.
rrc_filter
[
s
->
tx
.
rrc_filter_step
+
V22BIS_TX_FILTER_STEPS
]
=
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
)
if
(
++
s
->
tx
.
rrc_filter_step
>=
V22BIS_TX_FILTER_STEPS
)
s
->
tx
.
rrc_filter_step
=
0
;
s
->
tx
.
rrc_filter_step
=
0
;
}
}
/* Root raised cosine pulse shaping at baseband */
#if defined(SPANDSP_USE_FIXED_POINT)
x
=
complex_setf
(
0
.
0
f
,
0
.
0
f
);
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
;
for
(
i
=
0
;
i
<
V22BIS_TX_FILTER_STEPS
;
i
++
)
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
))
{
{
x
.
re
+=
tx_pulseshaper
[
39
-
s
->
tx
.
baud_phase
][
i
]
*
s
->
tx
.
rrc_filter
[
i
+
s
->
tx
.
rrc_filter_step
].
re
;
/* Add the guard tone */
x
.
im
+=
tx_pulseshaper
[
39
-
s
->
tx
.
baud_phase
][
i
]
*
s
->
tx
.
rrc_filter
[
i
+
s
->
tx
.
rrc_filter_step
].
im
;
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 */
/* Now create and modulate the carrier */
z
=
dds_complexf
(
&
(
s
->
tx
.
carrier_phase
),
s
->
tx
.
carrier_phase_rate
);
z
=
dds_complexf
(
&
(
s
->
tx
.
carrier_phase
),
s
->
tx
.
carrier_phase_rate
);
famp
=
(
x
.
re
*
z
.
re
-
x
.
im
*
z
.
im
)
*
s
->
tx
.
gain
;
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
.
0
f
||
s
->
tx
.
rrc_filter
[
s
->
tx
.
rrc_filter_step
].
im
!=
0
.
0
f
))
if
(
s
->
tx
.
guard_phase_rate
&&
(
s
->
tx
.
rrc_filter
_re
[
s
->
tx
.
rrc_filter_step
]
!=
0
.
0
f
||
s
->
tx
.
rrc_filter_im
[
s
->
tx
.
rrc_filter_step
]
!=
0
.
0
f
))
{
{
/* Add the guard tone */
/* Add the guard tone */
famp
+=
dds_modf
(
&
(
s
->
tx
.
guard_phase
),
s
->
tx
.
guard_phase_rate
,
s
->
tx
.
guard_level
,
0
);
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. */
/* Don't bother saturating. We should never clip. */
amp
[
sample
]
=
(
int16_t
)
lfastrintf
(
famp
);
amp
[
sample
]
=
(
int16_t
)
lfastrintf
(
famp
);
#endif
}
}
return
sample
;
return
sample
;
}
}
...
@@ -492,34 +524,49 @@ SPAN_DECLARE_NONSTD(int) v22bis_tx(v22bis_state_t *s, int16_t amp[], int len)
...
@@ -492,34 +524,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
)
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
.
0
f
))
if
(
s
->
tx
.
guard_phase_rate
==
dds_phase_ratef
(
550
.
0
f
))
{
{
l
=
1
.
6
f
*
powf
(
10
.
0
f
,
(
power
-
1
.
0
f
-
DBM0_MAX_POWER
)
/
20
.
0
f
);
sig_power
=
power
-
1
.
0
f
;
s
->
tx
.
gain
=
l
*
32768
.
0
f
/
(
TX_PULSESHAPER_GAIN
*
3
.
0
f
);
guard_tone_power
=
sig_power
-
3
.
0
f
;
l
=
powf
(
10
.
0
f
,
(
power
-
1
.
0
f
-
3
.
0
f
-
DBM0_MAX_POWER
)
/
20
.
0
f
);
s
->
tx
.
guard_level
=
l
*
32768
.
0
f
;
}
}
else
if
(
s
->
tx
.
guard_phase_rate
==
dds_phase_ratef
(
1800
.
0
f
))
else
if
(
s
->
tx
.
guard_phase_rate
==
dds_phase_ratef
(
1800
.
0
f
))
{
{
l
=
1
.
6
f
*
powf
(
10
.
0
f
,
(
power
-
1
.
0
f
-
1
.
0
f
-
DBM0_MAX_POWER
)
/
20
.
0
f
);
sig_power
=
power
-
0
.
55
f
;
s
->
tx
.
gain
=
l
*
32768
.
0
f
/
(
TX_PULSESHAPER_GAIN
*
3
.
0
f
);
guard_tone_power
=
sig_power
-
6
.
0
f
;
l
=
powf
(
10
.
0
f
,
(
power
-
1
.
0
f
-
6
.
0
f
-
DBM0_MAX_POWER
)
/
20
.
0
f
);
s
->
tx
.
guard_level
=
l
*
32768
.
0
f
;
}
}
else
else
{
{
l
=
1
.
6
f
*
powf
(
10
.
0
f
,
(
power
-
DBM0_MAX_POWER
)
/
20
.
0
f
);
sig_power
=
power
;
s
->
tx
.
gain
=
l
*
32768
.
0
f
/
(
TX_PULSESHAPER_GAIN
*
3
.
0
f
);
guard_tone_power
=
-
9999
.
0
f
;
s
->
tx
.
guard_level
=
0
;
}
}
sig_gain
=
0
.
4490
f
*
powf
(
10
.
0
f
,
(
sig_power
-
DBM0_MAX_POWER
)
/
20
.
0
f
)
*
32768
.
0
f
/
TX_PULSESHAPER_GAIN
;
guard_tone_gain
=
powf
(
10
.
0
f
,
(
guard_tone_power
-
DBM0_MAX_POWER
)
/
20
.
0
f
)
*
32768
.
0
f
;
#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 --------------------------------------------------------*/
/*- End of function --------------------------------------------------------*/
static
int
v22bis_tx_restart
(
v22bis_state_t
*
s
)
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_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
s
->
tx
.
rrc_filter_step
=
0
;
s
->
tx
.
rrc_filter_step
=
0
;
s
->
tx
.
scramble_reg
=
0
;
s
->
tx
.
scramble_reg
=
0
;
s
->
tx
.
scrambler_pattern_count
=
0
;
s
->
tx
.
scrambler_pattern_count
=
0
;
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论