Skip to content
项目
群组
代码片段
帮助
正在加载...
登录
切换导航
F
freeswitch
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
分枝图
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
分枝图
统计图
创建新议题
作业
提交
议题看板
打开侧边栏
张华
freeswitch
Commits
e58b2e7d
提交
e58b2e7d
authored
7月 21, 2012
作者:
Steve Underwood
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Some modem cleanups, and movement towards efficient fixed point modem
implementations for platforms with slow floating point
上级
5922cb59
隐藏空白字符变更
内嵌
并排
正在显示
10 个修改的文件
包含
459 行增加
和
368 行删除
+459
-368
v22bis.h
libs/spandsp/src/spandsp/private/v22bis.h
+14
-14
v27ter_rx.h
libs/spandsp/src/spandsp/private/v27ter_rx.h
+7
-7
v29rx.h
libs/spandsp/src/spandsp/private/v29rx.h
+1
-1
v27ter_rx.h
libs/spandsp/src/spandsp/v27ter_rx.h
+1
-1
v29rx.h
libs/spandsp/src/spandsp/v29rx.h
+1
-1
v17tx.c
libs/spandsp/src/v17tx.c
+13
-6
v22bis_rx.c
libs/spandsp/src/v22bis_rx.c
+233
-114
v22bis_tx.c
libs/spandsp/src/v22bis_tx.c
+9
-9
v27ter_rx.c
libs/spandsp/src/v27ter_rx.c
+107
-125
v29rx.c
libs/spandsp/src/v29rx.c
+73
-90
没有找到文件。
libs/spandsp/src/spandsp/private/v22bis.h
浏览文件 @
e58b2e7d
...
@@ -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
...
@@ -139,24 +139,24 @@ struct v22bis_state_s
...
@@ -139,24 +139,24 @@ struct v22bis_state_s
#if defined(SPANDSP_USE_FIXED_POINTx)
#if defined(SPANDSP_USE_FIXED_POINTx)
/*! \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
];
/*! \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
];
/*! \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 The scaling factor accessed by the AGC algorithm. */
/*! \brief The scaling factor accessed by the AGC algorithm. */
float
agc_scaling
;
float
agc_scaling
;
...
@@ -166,9 +166,9 @@ struct v22bis_state_s
...
@@ -166,9 +166,9 @@ struct v22bis_state_s
/*! \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
];
/*! \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. */
...
@@ -202,7 +202,7 @@ struct v22bis_state_s
...
@@ -202,7 +202,7 @@ 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. */
int16_t
guard_tone_gain
;
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. */
...
...
libs/spandsp/src/spandsp/private/v27ter_rx.h
浏览文件 @
e58b2e7d
...
@@ -76,22 +76,22 @@ struct v27ter_rx_state_s
...
@@ -76,22 +76,22 @@ struct v27ter_rx_state_s
int16_t
agc_scaling_save
;
int16_t
agc_scaling_save
;
/*! \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. */
/*complexi16_t*/
complexf_t
eq_coeff
[
V27TER_EQUALIZER_LEN
];
complexi16_t
eq_coeff
[
V27TER_EQUALIZER_LEN
];
/*! \brief A saved set of adaptive equalizer coefficients for use after restarts. */
/*! \brief A saved set of adaptive equalizer coefficients for use after restarts. */
/*complexi16_t*/
complexf_t
eq_coeff_save
[
V27TER_EQUALIZER_LEN
];
complexi16_t
eq_coeff_save
[
V27TER_EQUALIZER_LEN
];
/*! \brief The equalizer signal buffer. */
/*! \brief The equalizer signal buffer. */
/*complexi16_t*/
complexf
_t
eq_buf
[
V27TER_EQUALIZER_LEN
];
complexi16
_t
eq_buf
[
V27TER_EQUALIZER_LEN
];
/*! \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
;
/*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
/*! \brief The root raised cosine (RRC) pulse shaping filter buffer. */
int16_t
rrc_filter
[
V27TER_RX_FILTER_STEPS
];
int16_t
rrc_filter
[
V27TER_RX_FILTER_STEPS
];
#else
#else
...
...
libs/spandsp/src/spandsp/private/v29rx.h
浏览文件 @
e58b2e7d
...
@@ -87,7 +87,7 @@ struct v29_rx_state_s
...
@@ -87,7 +87,7 @@ struct v29_rx_state_s
/*! \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. */
int32_t
carrier_track_p
;
int32_t
carrier_track_p
;
...
...
libs/spandsp/src/spandsp/v27ter_rx.h
浏览文件 @
e58b2e7d
...
@@ -126,7 +126,7 @@ SPAN_DECLARE_NONSTD(int) v27ter_rx_fillin(v27ter_rx_state_t *s, int len);
...
@@ -126,7 +126,7 @@ SPAN_DECLARE_NONSTD(int) v27ter_rx_fillin(v27ter_rx_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
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
SPAN_DECLARE
(
int
)
v27ter_rx_equalizer_state
(
v27ter_rx_state_t
*
s
,
complexi16_t
**
coeffs
);
SPAN_DECLARE
(
int
)
v27ter_rx_equalizer_state
(
v27ter_rx_state_t
*
s
,
complexi16_t
**
coeffs
);
#else
#else
SPAN_DECLARE
(
int
)
v27ter_rx_equalizer_state
(
v27ter_rx_state_t
*
s
,
complexf_t
**
coeffs
);
SPAN_DECLARE
(
int
)
v27ter_rx_equalizer_state
(
v27ter_rx_state_t
*
s
,
complexf_t
**
coeffs
);
...
...
libs/spandsp/src/spandsp/v29rx.h
浏览文件 @
e58b2e7d
...
@@ -118,7 +118,7 @@ scrambler register) cannot be trusted for the test. The receive modem,
...
@@ -118,7 +118,7 @@ scrambler register) cannot be trusted for the test. The receive modem,
therefore, only tests that bits starting at bit 24 are really ones.
therefore, only tests that bits starting at bit 24 are really ones.
*/
*/
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
typedef
void
(
*
qam_report_handler_t
)(
void
*
user_data
,
const
complexi16_t
*
constel
,
const
complexi16_t
*
target
,
int
symbol
);
typedef
void
(
*
qam_report_handler_t
)(
void
*
user_data
,
const
complexi16_t
*
constel
,
const
complexi16_t
*
target
,
int
symbol
);
#else
#else
typedef
void
(
*
qam_report_handler_t
)(
void
*
user_data
,
const
complexf_t
*
constel
,
const
complexf_t
*
target
,
int
symbol
);
typedef
void
(
*
qam_report_handler_t
)(
void
*
user_data
,
const
complexf_t
*
constel
,
const
complexf_t
*
target
,
int
symbol
);
...
...
libs/spandsp/src/v17tx.c
浏览文件 @
e58b2e7d
...
@@ -53,13 +53,19 @@
...
@@ -53,13 +53,19 @@
#include "spandsp/dds.h"
#include "spandsp/dds.h"
#include "spandsp/power_meter.h"
#include "spandsp/power_meter.h"
#if defined(SPANDSP_USE_FIXED_POINT)
#define SPANDSP_USE_FIXED_POINTx
#endif
#include "spandsp/v17tx.h"
#include "spandsp/v17tx.h"
#include "spandsp/private/logging.h"
#include "spandsp/private/logging.h"
#include "spandsp/private/v17tx.h"
#include "spandsp/private/v17tx.h"
#if defined(SPANDSP_USE_FIXED_POINT)
#if defined(SPANDSP_USE_FIXED_POINT)
#define SPANDSP_USE_FIXED_POINTx
#define FP_SCALE(x) ((int16_t) x)
#else
#define FP_SCALE(x) (x)
#endif
#endif
#include "v17_v32bis_tx_constellation_maps.h"
#include "v17_v32bis_tx_constellation_maps.h"
...
@@ -229,6 +235,11 @@ static __inline__ complexf_t getbaud(v17_tx_state_t *s)
...
@@ -229,6 +235,11 @@ static __inline__ complexf_t getbaud(v17_tx_state_t *s)
int
i
;
int
i
;
int
bit
;
int
bit
;
int
bits
;
int
bits
;
#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
if
(
s
->
in_training
)
if
(
s
->
in_training
)
{
{
...
@@ -251,11 +262,7 @@ static __inline__ complexf_t getbaud(v17_tx_state_t *s)
...
@@ -251,11 +262,7 @@ static __inline__ complexf_t getbaud(v17_tx_state_t *s)
{
{
/* The shutdown sequence is 32 bauds of all 1's, then 48 bauds
/* The shutdown sequence is 32 bauds of all 1's, then 48 bauds
of silence */
of silence */
#if defined(SPANDSP_USE_FIXED_POINT)
return
zero
;
return
complex_seti16
(
0
,
0
);
#else
return
complex_setf
(
0
.
0
f
,
0
.
0
f
);
#endif
}
}
if
(
s
->
training_step
==
V17_TRAINING_SHUTDOWN_END
)
if
(
s
->
training_step
==
V17_TRAINING_SHUTDOWN_END
)
{
{
...
...
libs/spandsp/src/v22bis_rx.c
浏览文件 @
e58b2e7d
...
@@ -73,9 +73,12 @@
...
@@ -73,9 +73,12 @@
#include "spandsp/private/v22bis.h"
#include "spandsp/private/v22bis.h"
#if defined(SPANDSP_USE_FIXED_POINTx)
#if defined(SPANDSP_USE_FIXED_POINTx)
#include "v22bis_rx_1200_floating_rrc.h"
#define FP_SHIFT_FACTOR 10
#include "v22bis_rx_2400_floating_rrc.h"
#define FP_SCALE FP_Q_6_10
#include "v22bis_rx_1200_fixed_rrc.h"
#include "v22bis_rx_2400_fixed_rrc.h"
#else
#else
#define FP_SCALE(x) (x)
#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"
#endif
#endif
...
@@ -170,10 +173,14 @@ void v22bis_report_status_change(v22bis_state_t *s, int status)
...
@@ -170,10 +173,14 @@ 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 --------------------------------------------------------*/
...
@@ -181,13 +188,17 @@ void v22bis_equalizer_coefficient_reset(v22bis_state_t *s)
...
@@ -181,13 +188,17 @@ 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_POINTx)
#if defined(SPANDSP_USE_FIXED_POINTx)
cvec_zeroi16
(
s
->
rx
.
eq_coeff
,
2
*
V22BIS_EQUALIZER_LEN
+
1
);
static
const
complexi16_t
x
=
{
FP_Q_6_10
(
3
.
0
f
),
FP_Q_6_10
(
0
.
0
f
)};
s
->
rx
.
eq_coeff
[
V22BIS_EQUALIZER_LEN
]
=
complex_seti16
(
3
*
FP_FACTOR
,
0
*
FP_FACTOR
);
s
->
rx
.
eq_delta
=
32768
.
0
f
*
EQUALIZER_DELTA
/
(
2
*
V22BIS_EQUALIZER_LEN
+
1
);
cvec_zeroi16
(
s
->
rx
.
eq_coeff
,
V22BIS_EQUALIZER_LEN
);
s
->
rx
.
eq_coeff
[
V22BIS_EQUALIZER_PRE_LEN
]
=
x
;
s
->
rx
.
eq_delta
=
32
.
0
f
*
EQUALIZER_DELTA
/
V22BIS_EQUALIZER_LEN
;
#else
#else
cvec_zerof
(
s
->
rx
.
eq_coeff
,
2
*
V22BIS_EQUALIZER_LEN
+
1
);
static
const
complexf_t
x
=
{
3
.
0
f
,
0
.
0
f
};
s
->
rx
.
eq_coeff
[
V22BIS_EQUALIZER_LEN
]
=
complex_setf
(
3
.
0
f
,
0
.
0
f
);
s
->
rx
.
eq_delta
=
EQUALIZER_DELTA
/
(
2
*
V22BIS_EQUALIZER_LEN
+
1
);
cvec_zerof
(
s
->
rx
.
eq_coeff
,
V22BIS_EQUALIZER_LEN
);
s
->
rx
.
eq_coeff
[
V22BIS_EQUALIZER_PRE_LEN
]
=
x
;
s
->
rx
.
eq_delta
=
EQUALIZER_DELTA
/
V22BIS_EQUALIZER_LEN
;
#endif
#endif
}
}
/*- End of function --------------------------------------------------------*/
/*- End of function --------------------------------------------------------*/
...
@@ -196,73 +207,99 @@ static void equalizer_reset(v22bis_state_t *s)
...
@@ -196,73 +207,99 @@ static void equalizer_reset(v22bis_state_t *s)
{
{
v22bis_equalizer_coefficient_reset
(
s
);
v22bis_equalizer_coefficient_reset
(
s
);
#if defined(SPANDSP_USE_FIXED_POINTx)
#if defined(SPANDSP_USE_FIXED_POINTx)
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_POINTx)
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
=
complex_subi16
(
target
,
z
);
ez
.
re
*=
s
->
rx
.
eq_delta
;
err
.
re
=
((
int32_t
)
err
.
re
*
s
->
rx
.
eq_delta
)
>>
5
;
ez
.
im
*=
s
->
rx
.
eq_delta
;
err
.
im
=
((
int32_t
)
err
.
im
*
s
->
rx
.
eq_delta
)
>>
5
;
//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_POINTx)
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
{
{
#if defined(SPANDSP_USE_FIXED_POINTx)
int32_t
error
;
#else
float
error
;
float
error
;
#endif
/* For small errors the imaginary part of the difference between the actual and the target
/* For small errors the imaginary part of the difference between the actual and the target
positions is proportional to the phase error, for any particular target. However, the
positions is proportional to the phase error, for any particular target. However, the
different amplitudes of the various target positions scale things. */
different amplitudes of the various target positions scale things. */
#if defined(SPANDSP_USE_FIXED_POINTx)
error
=
((
int32_t
)
z
->
im
*
target
->
re
-
(
int32_t
)
z
->
re
*
target
->
im
)
>>
FP_SHIFT_FACTOR
;
s
->
rx
.
carrier_phase_rate
+=
(
s
->
rx
.
carrier_track_i
*
error
);
s
->
rx
.
carrier_phase
+=
(
s
->
rx
.
carrier_track_p
*
error
);
//span_log(&s->logging,
// SPAN_LOG_FLOW,
// "CARR: Im = %15.5f f = %15.5f - %10d %10d\n",
// error/1024.0f,
// dds_frequency(s->rx.carrier_phase_rate),
// (s->rx.carrier_track_i*error),
// (s->rx.carrier_track_p*error));
#else
error
=
z
->
im
*
target
->
re
-
z
->
re
*
target
->
im
;
error
=
z
->
im
*
target
->
re
-
z
->
re
*
target
->
im
;
s
->
rx
.
carrier_phase_rate
+=
(
int32_t
)
(
s
->
rx
.
carrier_track_i
*
error
);
s
->
rx
.
carrier_phase_rate
+=
(
int32_t
)
(
s
->
rx
.
carrier_track_i
*
error
);
s
->
rx
.
carrier_phase
+=
(
int32_t
)
(
s
->
rx
.
carrier_track_p
*
error
);
s
->
rx
.
carrier_phase
+=
(
int32_t
)
(
s
->
rx
.
carrier_track_p
*
error
);
//span_log(&s->logging, SPAN_LOG_FLOW, "Im = %15.5f f = %15.5f\n", error, dds_frequencyf(s->rx.carrier_phase_rate));
//span_log(&s->logging,
// SPAN_LOG_FLOW,
// "CARR: Im = %15.5f f = %15.5f - %10d %10d\n",
// error,
// dds_frequencyf(s->rx.carrier_phase_rate),
// (int32_t) (s->rx.carrier_track_i*error),
// (int32_t) (s->rx.carrier_track_p*error));
#endif
}
}
/*- End of function --------------------------------------------------------*/
/*- End of function --------------------------------------------------------*/
...
@@ -339,40 +376,61 @@ static int decode_baudx(v22bis_state_t *s, int nearest)
...
@@ -339,40 +376,61 @@ 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_POINTx)
int32_t
p
;
int32_t
q
;
complexi16_t
a
;
complexi16_t
b
;
complexi16_t
c
;
static
const
complexi16_t
x
=
{
FP_Q_1_15
(
0
.
894427
f
),
FP_Q_1_15
(
0
.
44721
f
)};
#else
float
p
;
float
p
;
float
q
;
float
q
;
complexf_t
zz
;
complexf_t
a
;
complexf_t
a
;
complexf_t
b
;
complexf_t
b
;
complexf_t
c
;
complexf_t
c
;
static
const
complexf_t
x
=
{
0
.
894427
f
,
0
.
44721
f
};
#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. */
zz
=
complex_setf
(
0
.
894427
,
0
.
44721
f
);
#if defined(SPANDSP_USE_FIXED_POINT)
a
=
complex_mulf
(
&
s
->
rx
.
eq_buf
[(
s
->
rx
.
eq_step
-
3
)
&
V22BIS_EQUALIZER_MASK
],
&
zz
);
a
=
complex_mul_q1_15
(
&
s
->
rx
.
eq_buf
[
aa
[
2
]],
&
x
);
b
=
complex_mulf
(
&
s
->
rx
.
eq_buf
[(
s
->
rx
.
eq_step
-
2
)
&
V22BIS_EQUALIZER_MASK
],
&
zz
);
b
=
complex_mul_q1_15
(
&
s
->
rx
.
eq_buf
[
aa
[
1
]],
&
x
);
c
=
complex_mulf
(
&
s
->
rx
.
eq_buf
[(
s
->
rx
.
eq_step
-
1
)
&
V22BIS_EQUALIZER_MASK
],
&
zz
);
c
=
complex_mul_q1_15
(
&
s
->
rx
.
eq_buf
[
aa
[
0
]],
&
x
);
#else
a
=
complex_mulf
(
&
s
->
rx
.
eq_buf
[
aa
[
2
]],
&
x
);
b
=
complex_mulf
(
&
s
->
rx
.
eq_buf
[
aa
[
1
]],
&
x
);
c
=
complex_mulf
(
&
s
->
rx
.
eq_buf
[
aa
[
0
]],
&
x
);
#endif
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
;
}
}
s
->
rx
.
gardner_integrate
+=
(
p
+
q
>
0
.
0
f
)
?
s
->
rx
.
gardner_step
:
-
s
->
rx
.
gardner_step
;
s
->
rx
.
gardner_integrate
+=
(
p
+
q
>
0
)
?
s
->
rx
.
gardner_step
:
-
s
->
rx
.
gardner_step
;
if
(
abs
(
s
->
rx
.
gardner_integrate
)
>=
16
)
if
(
abs
(
s
->
rx
.
gardner_integrate
)
>=
16
)
{
{
...
@@ -389,11 +447,23 @@ static __inline__ void symbol_sync(v22bis_state_t *s)
...
@@ -389,11 +447,23 @@ static __inline__ void symbol_sync(v22bis_state_t *s)
}
}
/*- End of function --------------------------------------------------------*/
/*- End of function --------------------------------------------------------*/
static
void
process_half_baud
(
v22bis_state_t
*
s
,
const
complexf_t
*
sample
)
#if defined(SPANDSP_USE_FIXED_POINTx)
static
__inline__
void
process_half_baud
(
v22bis_state_t
*
s
,
const
complexi16_t
*
sample
)
#else
static
__inline__
void
process_half_baud
(
v22bis_state_t
*
s
,
const
complexf_t
*
sample
)
#endif
{
{
#if defined(SPANDSP_USE_FIXED_POINTx)
complexi16_t
z
;
complexi16_t
zz
;
const
complexi16_t
*
target
;
static
const
complexi16_t
x
=
{
FP_Q_1_15
(
0
.
894427
f
),
FP_Q_1_15
(
0
.
44721
f
)};
#else
complexf_t
z
;
complexf_t
z
;
complexf_t
zz
;
complexf_t
zz
;
const
complexf_t
*
target
;
const
complexf_t
*
target
;
static
const
complexf_t
x
=
{
0
.
894427
f
,
0
.
44721
f
};
#endif
int
re
;
int
re
;
int
im
;
int
im
;
int
nearest
;
int
nearest
;
...
@@ -406,7 +476,8 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
...
@@ -406,7 +476,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
))
...
@@ -419,12 +490,17 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
...
@@ -419,12 +490,17 @@ 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_POINTx)
re
=
(
z
.
re
+
FP_Q_6_10
(
3
.
0
f
))
>>
FP_SHIFT_FACTOR
;
im
=
(
z
.
im
+
FP_Q_6_10
(
3
.
0
f
))
>>
FP_SHIFT_FACTOR
;
#else
re
=
(
int
)
(
z
.
re
+
3
.
0
f
);
re
=
(
int
)
(
z
.
re
+
3
.
0
f
);
im
=
(
int
)
(
z
.
im
+
3
.
0
f
);
#endif
if
(
re
>
5
)
if
(
re
>
5
)
re
=
5
;
re
=
5
;
else
if
(
re
<
0
)
else
if
(
re
<
0
)
re
=
0
;
re
=
0
;
im
=
(
int
)
(
z
.
im
+
3
.
0
f
);
if
(
im
>
5
)
if
(
im
>
5
)
im
=
5
;
im
=
5
;
else
if
(
im
<
0
)
else
if
(
im
<
0
)
...
@@ -433,13 +509,16 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
...
@@ -433,13 +509,16 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
}
}
else
else
{
{
/* Rotate to 45 degrees, to make the slicing trivial */
/* Rotate to 45 degrees, to make the slicing trivial. */
zz
=
complex_setf
(
0
.
894427
,
0
.
44721
f
);
#if defined(SPANDSP_USE_FIXED_POINT)
zz
=
complex_mulf
(
&
z
,
&
zz
);
zz
=
complex_mul_q1_15
(
&
z
,
&
x
);
#else
zz
=
complex_mulf
(
&
z
,
&
x
);
#endif
nearest
=
0x01
;
nearest
=
0x01
;
if
(
zz
.
re
<
0
.
0
f
)
if
(
zz
.
re
<
0
)
nearest
|=
0x04
;
nearest
|=
0x04
;
if
(
zz
.
im
<
0
.
0
f
)
if
(
zz
.
im
<
0
)
{
{
nearest
^=
0x04
;
nearest
^=
0x04
;
nearest
|=
0x08
;
nearest
|=
0x08
;
...
@@ -493,10 +572,7 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
...
@@ -493,10 +572,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
;
...
@@ -612,7 +688,11 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
...
@@ -612,7 +688,11 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
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 */
s
->
rx
.
training
=
V22BIS_RX_TRAINING_STAGE_NORMAL_OPERATION
;
s
->
rx
.
training
=
V22BIS_RX_TRAINING_STAGE_NORMAL_OPERATION
;
#if defined(SPANDSP_USE_FIXED_POINTx)
s
->
rx
.
carrier_track_i
=
8
;
#else
s
->
rx
.
carrier_track_i
=
8000
.
0
f
;
s
->
rx
.
carrier_track_i
=
8000
.
0
f
;
#endif
}
}
else
else
{
{
...
@@ -636,7 +716,11 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
...
@@ -636,7 +716,11 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
s
->
rx
.
sixteen_way_decisions
=
TRUE
;
s
->
rx
.
sixteen_way_decisions
=
TRUE
;
s
->
rx
.
training
=
V22BIS_RX_TRAINING_STAGE_WAIT_FOR_SCRAMBLED_ONES_AT_2400
;
s
->
rx
.
training
=
V22BIS_RX_TRAINING_STAGE_WAIT_FOR_SCRAMBLED_ONES_AT_2400
;
s
->
rx
.
pattern_repeats
=
0
;
s
->
rx
.
pattern_repeats
=
0
;
#if defined(SPANDSP_USE_FIXED_POINTx)
s
->
rx
.
carrier_track_i
=
8
;
#else
s
->
rx
.
carrier_track_i
=
8000
.
0
f
;
s
->
rx
.
carrier_track_i
=
8000
.
0
f
;
#endif
}
}
}
}
else
else
...
@@ -698,12 +782,20 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
...
@@ -698,12 +782,20 @@ 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_POINTx)
complexi16_t
z
;
complexi16_t
zz
;
complexi16_t
sample
;
int32_t
ii
;
int32_t
qq
;
#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
++
)
{
{
...
@@ -720,7 +812,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
...
@@ -720,7 +812,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
...
@@ -728,12 +820,12 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
...
@@ -728,12 +820,12 @@ 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
}
}
power
=
power_meter_update
(
&
(
s
->
rx
.
rx_power
)
,
(
int16_t
)
ii
);
power
=
power_meter_update
(
&
s
->
rx
.
rx_power
,
(
int16_t
)
ii
);
if
(
s
->
rx
.
signal_present
)
if
(
s
->
rx
.
signal_present
)
{
{
/* Look for power below the carrier off point */
/* Look for power below the carrier off point */
...
@@ -752,58 +844,75 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
...
@@ -752,58 +844,75 @@ SPAN_DECLARE_NONSTD(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int l
s
->
rx
.
signal_present
=
TRUE
;
s
->
rx
.
signal_present
=
TRUE
;
v22bis_report_status_change
(
s
,
SIG_STATUS_CARRIER_UP
);
v22bis_report_status_change
(
s
,
SIG_STATUS_CARRIER_UP
);
}
}
if
(
s
->
rx
.
training
!=
V22BIS_RX_TRAINING_STAGE_PARKED
)
/* Only spend effort processing this data if the modem is not parked, after
a training failure. */
if
(
s
->
rx
.
training
==
V22BIS_RX_TRAINING_STAGE_PARKED
)
continue
;
/* Put things into the equalization buffer at T/2 rate. The Gardner algorithm
will fiddle the step to align this with the symbols. */
if
((
s
->
rx
.
eq_put_step
-=
PULSESHAPER_COEFF_SETS
)
<=
0
)
{
{
/* Only spend effort processing this data if the modem is not
parked, after a training failure. */
z
=
dds_complexf
(
&
s
->
rx
.
carrier_phase
,
s
->
rx
.
carrier_phase_rate
);
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_POINTx)
s
->
rx
.
agc_scaling
=
saturate16
(((
int32_t
)
(
1024
.
0
f
*
1024
.
0
f
*
0
.
18
f
*
3
.
60
f
))
/
fixed_sqrt32
(
power
));
#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
/* Pulse shape while still at the carrier frequency, using a quadrature
will fiddle the step to align this with the symbols. */
pair of filters. This results in a properly bandpass filtered complex
if
((
s
->
rx
.
eq_put_step
-=
PULSESHAPER_COEFF_SETS
)
<=
0
)
signal, which can be brought directly to bandband by complex mixing.
No further filtering, to remove mixer harmonics, is needed. */
step
=
-
s
->
rx
.
eq_put_step
;
if
(
step
>
PULSESHAPER_COEFF_SETS
-
1
)
step
=
PULSESHAPER_COEFF_SETS
-
1
;
s
->
rx
.
eq_put_step
+=
PULSESHAPER_COEFF_SETS
*
40
/
(
3
*
2
);
if
(
s
->
calling_party
)
{
{
/* Pulse shape while still at the carrier frequency, using a quadrature
#if defined(SPANDSP_USE_FIXED_POINTx)
pair of filters. This results in a properly bandpass filtered complex
ii
=
vec_circular_dot_prodi16
(
s
->
rx
.
rrc_filter
,
rx_pulseshaper_2400_re
[
step
],
V22BIS_RX_FILTER_STEPS
,
s
->
rx
.
rrc_filter_step
)
>>
15
;
signal, which can be brought directly to bandband by complex mixing.
qq
=
vec_circular_dot_prodi16
(
s
->
rx
.
rrc_filter
,
rx_pulseshaper_2400_im
[
step
],
V22BIS_RX_FILTER_STEPS
,
s
->
rx
.
rrc_filter_step
)
>>
15
;
No further filtering, to remove mixer harmonics, is needed. */
step
=
-
s
->
rx
.
eq_put_step
;
if
(
step
>
PULSESHAPER_COEFF_SETS
-
1
)
step
=
PULSESHAPER_COEFF_SETS
-
1
;
s
->
rx
.
eq_put_step
+=
PULSESHAPER_COEFF_SETS
*
40
/
(
3
*
2
);
if
(
s
->
calling_party
)
{
#if defined(SPANDSP_USE_FIXED_POINT)
ii
=
vec_circular_dot_prodi16
(
s
->
rx
.
rrc_filter
,
rx_pulseshaper_2400_re
[
step
],
V22BIS_RX_FILTER_STEPS
,
s
->
rx
.
rrc_filter_step
);
qq
=
vec_circular_dot_prodi16
(
s
->
rx
.
rrc_filter
,
rx_pulseshaper_2400_im
[
step
],
V22BIS_RX_FILTER_STEPS
,
s
->
rx
.
rrc_filter_step
);
#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
);
#endif
#endif
}
}
else
else
{
{
#if defined(SPANDSP_USE_FIXED_POINT)
#if defined(SPANDSP_USE_FIXED_POINT
x
)
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
}
sample
.
re
=
ii
*
s
->
rx
.
agc_scaling
;
sample
.
im
=
qq
*
s
->
rx
.
agc_scaling
;
/* Shift to baseband - since this is done in a full complex form, the
result is clean, and requires no further filtering apart from the
equalizer. */
zz
.
re
=
sample
.
re
*
z
.
re
-
sample
.
im
*
z
.
im
;
zz
.
im
=
-
sample
.
re
*
z
.
im
-
sample
.
im
*
z
.
re
;
process_half_baud
(
s
,
&
zz
);
}
}
/* Shift to baseband - since this is done in a full complex form, the
result is clean, and requires no further filtering apart from the
equalizer. */
#if defined(SPANDSP_USE_FIXED_POINTx)
sample
.
re
=
(
ii
*
s
->
rx
.
agc_scaling
)
>>
FP_SHIFT_FACTOR
;
sample
.
im
=
(
qq
*
s
->
rx
.
agc_scaling
)
>>
FP_SHIFT_FACTOR
;
z
=
dds_lookup_complexi16
(
s
->
rx
.
carrier_phase
);
zz
.
re
=
((
int32_t
)
sample
.
re
*
z
.
re
-
(
int32_t
)
sample
.
im
*
z
.
im
)
>>
15
;
zz
.
im
=
((
int32_t
)
-
sample
.
re
*
z
.
im
-
(
int32_t
)
sample
.
im
*
z
.
re
)
>>
15
;
#else
sample
.
re
=
ii
*
s
->
rx
.
agc_scaling
;
sample
.
im
=
qq
*
s
->
rx
.
agc_scaling
;
z
=
dds_lookup_complexf
(
s
->
rx
.
carrier_phase
);
zz
.
re
=
sample
.
re
*
z
.
re
-
sample
.
im
*
z
.
im
;
zz
.
im
=
-
sample
.
re
*
z
.
im
-
sample
.
im
*
z
.
re
;
#endif
process_half_baud
(
s
,
&
zz
);
}
}
#if defined(SPANDSP_USE_FIXED_POINT)
dds_advance
(
&
s
->
rx
.
carrier_phase
,
s
->
rx
.
carrier_phase_rate
);
#else
dds_advancef
(
&
s
->
rx
.
carrier_phase
,
s
->
rx
.
carrier_phase_rate
);
#endif
}
}
return
0
;
return
0
;
}
}
...
@@ -835,8 +944,10 @@ int v22bis_rx_restart(v22bis_state_t *s)
...
@@ -835,8 +944,10 @@ int v22bis_rx_restart(v22bis_state_t *s)
{
{
#if defined(SPANDSP_USE_FIXED_POINTx)
#if defined(SPANDSP_USE_FIXED_POINTx)
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
]));
s
->
rx
.
training_error
=
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
]));
s
->
rx
.
training_error
=
0
.
0
f
;
#endif
#endif
s
->
rx
.
rrc_filter_step
=
0
;
s
->
rx
.
rrc_filter_step
=
0
;
s
->
rx
.
scramble_reg
=
0
;
s
->
rx
.
scramble_reg
=
0
;
...
@@ -847,9 +958,13 @@ int v22bis_rx_restart(v22bis_state_t *s)
...
@@ -847,9 +958,13 @@ int v22bis_rx_restart(v22bis_state_t *s)
s
->
rx
.
carrier_phase_rate
=
dds_phase_ratef
((
s
->
calling_party
)
?
2400
.
0
f
:
1200
.
0
f
);
s
->
rx
.
carrier_phase_rate
=
dds_phase_ratef
((
s
->
calling_party
)
?
2400
.
0
f
:
1200
.
0
f
);
s
->
rx
.
carrier_phase
=
0
;
s
->
rx
.
carrier_phase
=
0
;
power_meter_init
(
&
(
s
->
rx
.
rx_power
)
,
5
);
power_meter_init
(
&
s
->
rx
.
rx_power
,
5
);
v22bis_rx_signal_cutoff
(
s
,
-
45
.
5
f
);
v22bis_rx_signal_cutoff
(
s
,
-
45
.
5
f
);
#if defined(SPANDSP_USE_FIXED_POINT)
s
->
rx
.
agc_scaling
=
(
float
)
(
1024
.
0
f
*
1024
.
0
f
)
*
0
.
0005
f
*
0
.
025
f
;
#else
s
->
rx
.
agc_scaling
=
0
.
0005
f
*
0
.
025
f
;
s
->
rx
.
agc_scaling
=
0
.
0005
f
*
0
.
025
f
;
#endif
s
->
rx
.
constellation_state
=
0
;
s
->
rx
.
constellation_state
=
0
;
s
->
rx
.
sixteen_way_decisions
=
FALSE
;
s
->
rx
.
sixteen_way_decisions
=
FALSE
;
...
@@ -861,11 +976,15 @@ int v22bis_rx_restart(v22bis_state_t *s)
...
@@ -861,11 +976,15 @@ int v22bis_rx_restart(v22bis_state_t *s)
s
->
rx
.
gardner_integrate
=
0
;
s
->
rx
.
gardner_integrate
=
0
;
s
->
rx
.
gardner_step
=
256
;
s
->
rx
.
gardner_step
=
256
;
s
->
rx
.
baud_phase
=
0
;
s
->
rx
.
baud_phase
=
0
;
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_POINTx)
s
->
rx
.
carrier_track_i
=
(
s
->
calling_party
)
?
8
:
40
;
s
->
rx
.
carrier_track_p
=
8000
;
#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
浏览文件 @
e58b2e7d
...
@@ -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)
#define FP_SCALE FP_Q_6_10
#define FP_SCALE FP_Q_6_10
#include "v22bis_tx_fixed_rrc.h"
#include "v22bis_tx_fixed_rrc.h"
#else
#else
...
@@ -248,7 +248,7 @@ static const int phase_steps[4] =
...
@@ -248,7 +248,7 @@ static const int phase_steps[4] =
1
,
0
,
2
,
3
1
,
0
,
2
,
3
};
};
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
const
complexi16_t
v22bis_constellation
[
16
]
=
const
complexi16_t
v22bis_constellation
[
16
]
=
#else
#else
const
complexf_t
v22bis_constellation
[
16
]
=
const
complexf_t
v22bis_constellation
[
16
]
=
...
@@ -314,7 +314,7 @@ static __inline__ int get_scrambled_bit(v22bis_state_t *s)
...
@@ -314,7 +314,7 @@ static __inline__ int get_scrambled_bit(v22bis_state_t *s)
}
}
/*- End of function --------------------------------------------------------*/
/*- End of function --------------------------------------------------------*/
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
static
complexi16_t
training_get
(
v22bis_state_t
*
s
)
static
complexi16_t
training_get
(
v22bis_state_t
*
s
)
#else
#else
static
complexf_t
training_get
(
v22bis_state_t
*
s
)
static
complexf_t
training_get
(
v22bis_state_t
*
s
)
...
@@ -417,13 +417,13 @@ static complexf_t training_get(v22bis_state_t *s)
...
@@ -417,13 +417,13 @@ static complexf_t training_get(v22bis_state_t *s)
}
}
/*- End of function --------------------------------------------------------*/
/*- End of function --------------------------------------------------------*/
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
static
complexi16_t
getbaud
(
v22bis_state_t
*
s
)
static
complexi16_t
getbaud
(
v22bis_state_t
*
s
)
#else
#else
static
complexf_t
getbaud
(
v22bis_state_t
*
s
)
static
complexf_t
getbaud
(
v22bis_state_t
*
s
)
#endif
#endif
{
{
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
static
const
complexi16_t
zero
=
{
0
,
0
};
static
const
complexi16_t
zero
=
{
0
,
0
};
#else
#else
static
const
complexf_t
zero
=
{
0
.
0
f
,
0
.
0
f
};
static
const
complexf_t
zero
=
{
0
.
0
f
,
0
.
0
f
};
...
@@ -464,7 +464,7 @@ static complexf_t getbaud(v22bis_state_t *s)
...
@@ -464,7 +464,7 @@ 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
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
complexi16_t
v
;
complexi16_t
v
;
complexi32_t
x
;
complexi32_t
x
;
complexi32_t
z
;
complexi32_t
z
;
...
@@ -490,7 +490,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_tx(v22bis_state_t *s, int16_t amp[], int len)
...
@@ -490,7 +490,7 @@ SPAN_DECLARE_NONSTD(int) v22bis_tx(v22bis_state_t *s, int16_t amp[], int len)
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
;
}
}
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
/* Root raised cosine pulse shaping at baseband */
/* Root raised cosine pulse shaping at baseband */
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
.
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
;
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
;
...
@@ -551,7 +551,7 @@ SPAN_DECLARE(void) v22bis_tx_power(v22bis_state_t *s, float power)
...
@@ -551,7 +551,7 @@ SPAN_DECLARE(void) v22bis_tx_power(v22bis_state_t *s, float power)
}
}
sig_gain
=
0
.
4490
f
*
powf
(
10
.
0
f
,
(
sig_power
-
DBM0_MAX_POWER
)
/
20
.
0
f
)
*
32768
.
0
f
/
TX_PULSESHAPER_GAIN
;
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
;
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
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
s
->
tx
.
gain
=
(
int16_t
)
sig_gain
;
s
->
tx
.
gain
=
(
int16_t
)
sig_gain
;
s
->
tx
.
guard_tone_gain
=
(
int16_t
)
guard_tone_gain
;
s
->
tx
.
guard_tone_gain
=
(
int16_t
)
guard_tone_gain
;
#else
#else
...
@@ -563,7 +563,7 @@ SPAN_DECLARE(void) v22bis_tx_power(v22bis_state_t *s, float power)
...
@@ -563,7 +563,7 @@ SPAN_DECLARE(void) v22bis_tx_power(v22bis_state_t *s, float power)
static
int
v22bis_tx_restart
(
v22bis_state_t
*
s
)
static
int
v22bis_tx_restart
(
v22bis_state_t
*
s
)
{
{
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#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_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
]));
vec_zeroi16
(
s
->
tx
.
rrc_filter_im
,
sizeof
(
s
->
tx
.
rrc_filter_im
)
/
sizeof
(
s
->
tx
.
rrc_filter_im
[
0
]));
#else
#else
...
...
libs/spandsp/src/v27ter_rx.c
浏览文件 @
e58b2e7d
...
@@ -65,11 +65,13 @@
...
@@ -65,11 +65,13 @@
#include "spandsp/private/v27ter_rx.h"
#include "spandsp/private/v27ter_rx.h"
#if defined(SPANDSP_USE_FIXED_POINT)
#if defined(SPANDSP_USE_FIXED_POINT)
#define FP_SCALE FP_Q_6_10
#define FP_SCALE FP_Q_6_10
#define FP_FACTOR 4096
#define FP_SHIFT_FACTOR 12
#include "v27ter_rx_4800_fixed_rrc.h"
#include "v27ter_rx_4800_fixed_rrc.h"
#include "v27ter_rx_2400_fixed_rrc.h"
#include "v27ter_rx_2400_fixed_rrc.h"
#else
#else
#define FP_SCALE(x) (x)
#define FP_SCALE(x)
(x)
#include "v27ter_rx_4800_floating_rrc.h"
#include "v27ter_rx_4800_floating_rrc.h"
#include "v27ter_rx_2400_floating_rrc.h"
#include "v27ter_rx_2400_floating_rrc.h"
#endif
#endif
...
@@ -87,11 +89,6 @@
...
@@ -87,11 +89,6 @@
/*! The adaption rate coefficient for the equalizer */
/*! The adaption rate coefficient for the equalizer */
#define EQUALIZER_DELTA 0.25f
#define EQUALIZER_DELTA 0.25f
#if defined(SPANDSP_USE_FIXED_POINT)
#define FP_FACTOR 4096
#define FP_SHIFT_FACTOR 12
#endif
/* Segments of the training sequence */
/* Segments of the training sequence */
/* V.27ter defines a long and a short sequence. FAX doesn't use the
/* V.27ter defines a long and a short sequence. FAX doesn't use the
short sequence, so it is not implemented here. */
short sequence, so it is not implemented here. */
...
@@ -113,7 +110,7 @@ enum
...
@@ -113,7 +110,7 @@ enum
TRAINING_STAGE_PARKED
TRAINING_STAGE_PARKED
};
};
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
static
const
complexi16_t
v27ter_constellation
[
8
]
=
static
const
complexi16_t
v27ter_constellation
[
8
]
=
#else
#else
static
const
complexf_t
v27ter_constellation
[
8
]
=
static
const
complexf_t
v27ter_constellation
[
8
]
=
...
@@ -167,7 +164,7 @@ static void report_status_change(v27ter_rx_state_t *s, int status)
...
@@ -167,7 +164,7 @@ static void report_status_change(v27ter_rx_state_t *s, int status)
}
}
/*- End of function --------------------------------------------------------*/
/*- End of function --------------------------------------------------------*/
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
SPAN_DECLARE
(
int
)
v27ter_rx_equalizer_state
(
v27ter_rx_state_t
*
s
,
complexi16_t
**
coeffs
)
SPAN_DECLARE
(
int
)
v27ter_rx_equalizer_state
(
v27ter_rx_state_t
*
s
,
complexi16_t
**
coeffs
)
#else
#else
SPAN_DECLARE
(
int
)
v27ter_rx_equalizer_state
(
v27ter_rx_state_t
*
s
,
complexf_t
**
coeffs
)
SPAN_DECLARE
(
int
)
v27ter_rx_equalizer_state
(
v27ter_rx_state_t
*
s
,
complexf_t
**
coeffs
)
...
@@ -180,7 +177,7 @@ SPAN_DECLARE(int) v27ter_rx_equalizer_state(v27ter_rx_state_t *s, complexf_t **c
...
@@ -180,7 +177,7 @@ SPAN_DECLARE(int) v27ter_rx_equalizer_state(v27ter_rx_state_t *s, complexf_t **c
static
void
equalizer_save
(
v27ter_rx_state_t
*
s
)
static
void
equalizer_save
(
v27ter_rx_state_t
*
s
)
{
{
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
cvec_copyi16
(
s
->
eq_coeff_save
,
s
->
eq_coeff
,
V27TER_EQUALIZER_LEN
);
cvec_copyi16
(
s
->
eq_coeff_save
,
s
->
eq_coeff
,
V27TER_EQUALIZER_LEN
);
#else
#else
cvec_copyf
(
s
->
eq_coeff_save
,
s
->
eq_coeff
,
V27TER_EQUALIZER_LEN
);
cvec_copyf
(
s
->
eq_coeff_save
,
s
->
eq_coeff
,
V27TER_EQUALIZER_LEN
);
...
@@ -190,7 +187,7 @@ static void equalizer_save(v27ter_rx_state_t *s)
...
@@ -190,7 +187,7 @@ static void equalizer_save(v27ter_rx_state_t *s)
static
void
equalizer_restore
(
v27ter_rx_state_t
*
s
)
static
void
equalizer_restore
(
v27ter_rx_state_t
*
s
)
{
{
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
cvec_copyi16
(
s
->
eq_coeff
,
s
->
eq_coeff_save
,
V27TER_EQUALIZER_LEN
);
cvec_copyi16
(
s
->
eq_coeff
,
s
->
eq_coeff_save
,
V27TER_EQUALIZER_LEN
);
cvec_zeroi16
(
s
->
eq_buf
,
V27TER_EQUALIZER_LEN
);
cvec_zeroi16
(
s
->
eq_buf
,
V27TER_EQUALIZER_LEN
);
s
->
eq_delta
=
32768
.
0
f
*
EQUALIZER_DELTA
/
V27TER_EQUALIZER_LEN
;
s
->
eq_delta
=
32768
.
0
f
*
EQUALIZER_DELTA
/
V27TER_EQUALIZER_LEN
;
...
@@ -208,7 +205,7 @@ static void equalizer_restore(v27ter_rx_state_t *s)
...
@@ -208,7 +205,7 @@ static void equalizer_restore(v27ter_rx_state_t *s)
static
void
equalizer_reset
(
v27ter_rx_state_t
*
s
)
static
void
equalizer_reset
(
v27ter_rx_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)
static
const
complexi16_t
x
=
{
FP_SCALE
(
1
.
414
f
),
FP_SCALE
(
0
.
0
f
)};
static
const
complexi16_t
x
=
{
FP_SCALE
(
1
.
414
f
),
FP_SCALE
(
0
.
0
f
)};
cvec_zeroi16
(
s
->
eq_coeff
,
V27TER_EQUALIZER_LEN
);
cvec_zeroi16
(
s
->
eq_coeff
,
V27TER_EQUALIZER_LEN
);
...
@@ -229,50 +226,36 @@ static void equalizer_reset(v27ter_rx_state_t *s)
...
@@ -229,50 +226,36 @@ static void equalizer_reset(v27ter_rx_state_t *s)
}
}
/*- End of function --------------------------------------------------------*/
/*- End of function --------------------------------------------------------*/
#if defined(SPANDSP_USE_FIXED_POINTx)
#if defined(SPANDSP_USE_FIXED_POINT)
static
__inline__
complexi16_t
complex_mul_q4_12
(
const
complexi16_t
*
x
,
const
complexi16_t
*
y
)
{
complexi16_t
z
;
z
.
re
=
((
int32_t
)
x
->
re
*
(
int32_t
)
y
->
re
-
(
int32_t
)
x
->
im
*
(
int32_t
)
y
->
im
)
>>
12
;
z
.
im
=
((
int32_t
)
x
->
re
*
(
int32_t
)
y
->
im
+
(
int32_t
)
x
->
im
*
(
int32_t
)
y
->
re
)
>>
12
;
return
z
;
}
/*- End of function --------------------------------------------------------*/
#endif
#if defined(SPANDSP_USE_FIXED_POINTx)
static
__inline__
complexi16_t
equalizer_get
(
v27ter_rx_state_t
*
s
)
static
__inline__
complexi16_t
equalizer_get
(
v27ter_rx_state_t
*
s
)
#else
static
__inline__
complexf_t
equalizer_get
(
v27ter_rx_state_t
*
s
)
#endif
{
{
#if defined(SPANDSP_USE_FIXED_POINTx)
complexi32_t
zz
;
complexi32_t
zz
;
complexi16_t
z
;
complexi16_t
z
;
/* Get the next equalized value. */
/* Get the next equalized value. */
zz
=
cvec_circular_dot_prodi16
(
s
->
eq_buf
,
s
->
eq_coeff
,
V27TER_EQUALIZER_LEN
,
s
->
eq_step
);
zz
=
cvec_circular_dot_prodi16
(
s
->
eq_buf
,
s
->
eq_coeff
,
V27TER_EQUALIZER_LEN
,
s
->
eq_step
);
z
.
re
=
zz
.
re
>>
FP_SHIFT_FACTOR
;
z
.
re
=
zz
.
re
>>
14
;
z
.
im
=
zz
.
im
>>
FP_SHIFT_FACTOR
;
z
.
im
=
zz
.
im
>>
14
;
return
z
;
return
z
;
}
#else
#else
static
__inline__
complexf_t
equalizer_get
(
v27ter_rx_state_t
*
s
)
{
/* Get the next equalized value. */
/* Get the next equalized value. */
return
cvec_circular_dot_prodf
(
s
->
eq_buf
,
s
->
eq_coeff
,
V27TER_EQUALIZER_LEN
,
s
->
eq_step
);
return
cvec_circular_dot_prodf
(
s
->
eq_buf
,
s
->
eq_coeff
,
V27TER_EQUALIZER_LEN
,
s
->
eq_step
);
#endif
}
}
#endif
/*- End of function --------------------------------------------------------*/
/*- End of function --------------------------------------------------------*/
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
static
void
tune_equalizer
(
v27ter_rx_state_t
*
s
,
const
complexi16_t
*
z
,
const
complexi16_t
*
target
)
static
void
tune_equalizer
(
v27ter_rx_state_t
*
s
,
const
complexi16_t
*
z
,
const
complexi16_t
*
target
)
{
{
complexi16_t
err
;
complexi16_t
err
;
/* Find the x and y mismatch from the exact constellation position. */
/* Find the x and y mismatch from the exact constellation position. */
err
.
re
=
target
->
re
*
FP_FACTOR
-
z
->
re
;
err
=
complex_subi16
(
target
,
z
);
err
.
im
=
target
->
im
*
FP_FACTOR
-
z
->
im
;
err
.
re
=
((
int32_t
)
err
.
re
*
s
->
eq_delta
)
>>
13
;
err
.
re
=
((
int32_t
)
err
.
re
*
(
int32_t
)
s
->
eq_delta
)
>>
15
;
err
.
im
=
((
int32_t
)
err
.
im
*
s
->
eq_delta
)
>>
13
;
err
.
im
=
((
int32_t
)
err
.
im
*
(
int32_t
)
s
->
eq_delta
)
>>
15
;
cvec_circular_lmsi16
(
s
->
eq_buf
,
s
->
eq_coeff
,
V27TER_EQUALIZER_LEN
,
s
->
eq_step
,
&
err
);
cvec_circular_lmsi16
(
s
->
eq_buf
,
s
->
eq_coeff
,
V27TER_EQUALIZER_LEN
,
s
->
eq_step
,
&
err
);
}
}
#else
#else
...
@@ -289,7 +272,7 @@ static void tune_equalizer(v27ter_rx_state_t *s, const complexf_t *z, const comp
...
@@ -289,7 +272,7 @@ static void tune_equalizer(v27ter_rx_state_t *s, const complexf_t *z, const comp
#endif
#endif
/*- End of function --------------------------------------------------------*/
/*- End of function --------------------------------------------------------*/
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
static
__inline__
int
find_quadrant
(
const
complexi16_t
*
z
)
static
__inline__
int
find_quadrant
(
const
complexi16_t
*
z
)
#else
#else
static
__inline__
int
find_quadrant
(
const
complexf_t
*
z
)
static
__inline__
int
find_quadrant
(
const
complexf_t
*
z
)
...
@@ -305,25 +288,36 @@ static __inline__ int find_quadrant(const complexf_t *z)
...
@@ -305,25 +288,36 @@ static __inline__ int find_quadrant(const complexf_t *z)
}
}
/*- End of function --------------------------------------------------------*/
/*- End of function --------------------------------------------------------*/
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
static
__inline__
int
find_octant
(
complexi16_t
*
z
)
static
__inline__
int
find_octant
(
complexi16_t
*
z
)
#else
#else
static
__inline__
int
find_octant
(
complexf_t
*
z
)
static
__inline__
int
find_octant
(
complexf_t
*
z
)
#endif
#endif
{
{
#if defined(SPANDSP_USE_FIXED_POINT)
int32_t
abs_re
;
int32_t
abs_im
;
#else
float
abs_re
;
float
abs_re
;
float
abs_im
;
float
abs_im
;
#endif
int
b1
;
int
b1
;
int
b2
;
int
b2
;
int
bits
;
int
bits
;
/* Are we near an axis or a diagonal? */
/* Are we near an axis or a diagonal? */
#if defined(SPANDSP_USE_FIXED_POINT)
abs_re
=
abs
(
z
->
re
);
abs_im
=
abs
(
z
->
im
);
if
(
abs_im
*
1000
>
abs_re
*
414
&&
abs_im
*
1000
<
abs_re
*
2414
)
#else
abs_re
=
fabsf
(
z
->
re
);
abs_re
=
fabsf
(
z
->
re
);
abs_im
=
fabsf
(
z
->
im
);
abs_im
=
fabsf
(
z
->
im
);
if
(
abs_im
>
abs_re
*
0
.
4142136
f
&&
abs_im
<
abs_re
*
2
.
4142136
f
)
if
(
abs_im
>
abs_re
*
0
.
4142136
f
&&
abs_im
<
abs_re
*
2
.
4142136
f
)
#endif
{
{
/* Split the space along the two axes. */
/* Split the space along the two axes. */
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
b1
=
(
z
->
re
<
0
);
b1
=
(
z
->
re
<
0
);
b2
=
(
z
->
im
<
0
);
b2
=
(
z
->
im
<
0
);
#else
#else
...
@@ -343,13 +337,13 @@ static __inline__ int find_octant(complexf_t *z)
...
@@ -343,13 +337,13 @@ static __inline__ int find_octant(complexf_t *z)
}
}
/*- End of function --------------------------------------------------------*/
/*- End of function --------------------------------------------------------*/
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
static
__inline__
void
track_carrier
(
v27ter_rx_state_t
*
s
,
const
complexi16_t
*
z
,
const
complexi16_t
*
target
)
static
__inline__
void
track_carrier
(
v27ter_rx_state_t
*
s
,
const
complexi16_t
*
z
,
const
complexi16_t
*
target
)
#else
#else
static
__inline__
void
track_carrier
(
v27ter_rx_state_t
*
s
,
const
complexf_t
*
z
,
const
complexf_t
*
target
)
static
__inline__
void
track_carrier
(
v27ter_rx_state_t
*
s
,
const
complexf_t
*
z
,
const
complexf_t
*
target
)
#endif
#endif
{
{
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
int32_t
error
;
int32_t
error
;
#else
#else
float
error
;
float
error
;
...
@@ -358,13 +352,12 @@ static __inline__ void track_carrier(v27ter_rx_state_t *s, const complexf_t *z,
...
@@ -358,13 +352,12 @@ static __inline__ void track_carrier(v27ter_rx_state_t *s, const complexf_t *z,
/* For small errors the imaginary part of the difference between the actual and the target
/* For small errors the imaginary part of the difference between the actual and the target
positions is proportional to the phase error, for any particular target. However, the
positions is proportional to the phase error, for any particular target. However, the
different amplitudes of the various target positions scale things. */
different amplitudes of the various target positions scale things. */
error
=
z
->
im
*
target
->
re
-
z
->
re
*
target
->
im
;
#if defined(SPANDSP_USE_FIXED_POINT)
error
=
((
int32_t
)
z
->
im
*
target
->
re
-
(
int32_t
)
z
->
re
*
target
->
im
)
>>
10
;
#if defined(SPANDSP_USE_FIXED_POINTx)
s
->
carrier_phase_rate
+=
((
s
->
carrier_track_i
*
error
)
>>
FP_SHIFT_FACTOR
);
error
/=
(
float
)
FP_FACTOR
;
s
->
carrier_phase
+=
((
s
->
carrier_track_p
*
error
)
>>
FP_SHIFT_FACTOR
);
s
->
carrier_phase_rate
+=
(
int32_t
)
(
s
->
carrier_track_i
*
error
);
s
->
carrier_phase
+=
(
int32_t
)
(
s
->
carrier_track_p
*
error
);
#else
#else
error
=
z
->
im
*
target
->
re
-
z
->
re
*
target
->
im
;
s
->
carrier_phase_rate
+=
(
int32_t
)
(
s
->
carrier_track_i
*
error
);
s
->
carrier_phase_rate
+=
(
int32_t
)
(
s
->
carrier_track_i
*
error
);
s
->
carrier_phase
+=
(
int32_t
)
(
s
->
carrier_track_p
*
error
);
s
->
carrier_phase
+=
(
int32_t
)
(
s
->
carrier_track_p
*
error
);
//span_log(&s->logging, SPAN_LOG_FLOW, "Im = %15.5f f = %15.5f\n", error, dds_frequencyf(s->carrier_phase_rate));
//span_log(&s->logging, SPAN_LOG_FLOW, "Im = %15.5f f = %15.5f\n", error, dds_frequencyf(s->carrier_phase_rate));
...
@@ -429,7 +422,7 @@ static __inline__ void put_bit(v27ter_rx_state_t *s, int bit)
...
@@ -429,7 +422,7 @@ static __inline__ void put_bit(v27ter_rx_state_t *s, int bit)
}
}
/*- End of function --------------------------------------------------------*/
/*- End of function --------------------------------------------------------*/
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
static
void
decode_baud
(
v27ter_rx_state_t
*
s
,
complexi16_t
*
z
)
static
void
decode_baud
(
v27ter_rx_state_t
*
s
,
complexi16_t
*
z
)
#else
#else
static
void
decode_baud
(
v27ter_rx_state_t
*
s
,
complexf_t
*
z
)
static
void
decode_baud
(
v27ter_rx_state_t
*
s
,
complexf_t
*
z
)
...
@@ -478,8 +471,13 @@ static void decode_baud(v27ter_rx_state_t *s, complexf_t *z)
...
@@ -478,8 +471,13 @@ static void decode_baud(v27ter_rx_state_t *s, complexf_t *z)
static
__inline__
void
symbol_sync
(
v27ter_rx_state_t
*
s
)
static
__inline__
void
symbol_sync
(
v27ter_rx_state_t
*
s
)
{
{
#if defined(SPANDSP_USE_FIXED_POINT)
int32_t
p
;
int32_t
q
;
#else
float
p
;
float
p
;
float
q
;
float
q
;
#endif
/* 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. */
...
@@ -492,7 +490,7 @@ static __inline__ void symbol_sync(v27ter_rx_state_t *s)
...
@@ -492,7 +490,7 @@ static __inline__ void symbol_sync(v27ter_rx_state_t *s)
-
s
->
eq_buf
[(
s
->
eq_step
-
1
)
&
(
V27TER_EQUALIZER_LEN
-
1
)].
im
;
-
s
->
eq_buf
[(
s
->
eq_step
-
1
)
&
(
V27TER_EQUALIZER_LEN
-
1
)].
im
;
q
*=
s
->
eq_buf
[(
s
->
eq_step
-
2
)
&
(
V27TER_EQUALIZER_LEN
-
1
)].
im
;
q
*=
s
->
eq_buf
[(
s
->
eq_step
-
2
)
&
(
V27TER_EQUALIZER_LEN
-
1
)].
im
;
s
->
gardner_integrate
+=
(
p
+
q
>
0
.
0
f
)
?
s
->
gardner_step
:
-
s
->
gardner_step
;
s
->
gardner_integrate
+=
(
p
+
q
>
0
)
?
s
->
gardner_step
:
-
s
->
gardner_step
;
if
(
abs
(
s
->
gardner_integrate
)
>=
256
)
if
(
abs
(
s
->
gardner_integrate
)
>=
256
)
{
{
...
@@ -516,22 +514,19 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexi16_
...
@@ -516,22 +514,19 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexi16_
static
__inline__
void
process_half_baud
(
v27ter_rx_state_t
*
s
,
const
complexf_t
*
sample
)
static
__inline__
void
process_half_baud
(
v27ter_rx_state_t
*
s
,
const
complexf_t
*
sample
)
#endif
#endif
{
{
static
const
int
abab_pos
[
2
]
=
static
const
int
abab_pos
[
2
]
=
{
0
,
4
};
{
#if defined(SPANDSP_USE_FIXED_POINT)
0
,
4
};
complexf_t
zz
;
#if defined(SPANDSP_USE_FIXED_POINTx)
complexf_t
z1
;
complexi16_t
z
;
complexi16_t
z
;
complexi16_t
z16
;
const
complexi16_t
*
target
;
const
complexi16_t
*
target
;
static
const
complexi16_t
zero
=
{
0
,
0
};
static
const
complexi16_t
zero
=
{
0
,
0
};
#else
#else
float
p
;
complexf_t
z
;
complexf_t
z
;
complexf_t
zz
;
const
complexf_t
*
target
;
const
complexf_t
*
target
;
static
const
complexf_t
zero
=
{
0
.
0
f
,
0
.
0
f
};
static
const
complexf_t
zero
=
{
0
.
0
f
,
0
.
0
f
};
#endif
#endif
float
p
;
int
i
;
int
i
;
int
j
;
int
j
;
int32_t
angle
;
int32_t
angle
;
...
@@ -540,12 +535,7 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
...
@@ -540,12 +535,7 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
/* 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. */
#if defined(SPANDSP_USE_FIXED_POINT)
s
->
eq_buf
[
s
->
eq_step
].
re
=
sample
->
re
/
(
float
)
FP_FACTOR
;
s
->
eq_buf
[
s
->
eq_step
].
im
=
sample
->
im
/
(
float
)
FP_FACTOR
;
#else
s
->
eq_buf
[
s
->
eq_step
]
=
*
sample
;
s
->
eq_buf
[
s
->
eq_step
]
=
*
sample
;
#endif
if
(
++
s
->
eq_step
>=
V27TER_EQUALIZER_LEN
)
if
(
++
s
->
eq_step
>=
V27TER_EQUALIZER_LEN
)
s
->
eq_step
=
0
;
s
->
eq_step
=
0
;
...
@@ -583,9 +573,8 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
...
@@ -583,9 +573,8 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
case
TRAINING_STAGE_LOG_PHASE
:
case
TRAINING_STAGE_LOG_PHASE
:
/* Record the current alternate phase angle */
/* Record the current alternate phase angle */
target
=
&
zero
;
target
=
&
zero
;
angle
=
arctan2
(
z
.
im
,
z
.
re
);
s
->
angles
[
1
]
=
s
->
angles
[
1
]
=
s
->
start_angles
[
1
]
=
a
ngle
;
s
->
start_angles
[
1
]
=
a
rctan2
(
z
.
im
,
z
.
re
)
;
s
->
training_count
=
1
;
s
->
training_count
=
1
;
s
->
training_stage
=
TRAINING_STAGE_WAIT_FOR_HOP
;
s
->
training_stage
=
TRAINING_STAGE_WAIT_FOR_HOP
;
break
;
break
;
...
@@ -609,8 +598,7 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
...
@@ -609,8 +598,7 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
if
(
i
)
if
(
i
)
{
{
j
=
i
&
0xF
;
j
=
i
&
0xF
;
ang
=
(
s
->
angles
[
j
]
-
s
->
start_angles
[
0
])
/
i
ang
=
(
s
->
angles
[
j
]
-
s
->
start_angles
[
0
])
/
i
+
(
s
->
angles
[
j
|
0x1
]
-
s
->
start_angles
[
1
])
/
i
;
+
(
s
->
angles
[
j
|
0x1
]
-
s
->
start_angles
[
1
])
/
i
;
if
(
s
->
bit_rate
==
4800
)
if
(
s
->
bit_rate
==
4800
)
s
->
carrier_phase_rate
+=
ang
/
10
;
s
->
carrier_phase_rate
+=
ang
/
10
;
else
else
...
@@ -622,27 +610,22 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
...
@@ -622,27 +610,22 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
||
||
s
->
carrier_phase_rate
>
dds_phase_ratef
(
CARRIER_NOMINAL_FREQ
+
20
.
0
f
))
s
->
carrier_phase_rate
>
dds_phase_ratef
(
CARRIER_NOMINAL_FREQ
+
20
.
0
f
))
{
{
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"Training failed (sequence failed)
\n
"
);
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"Training failed (sequence failed)
\n
"
);
/* Park this modem */
/* Park this modem */
s
->
training_stage
=
TRAINING_STAGE_PARKED
;
s
->
training_stage
=
TRAINING_STAGE_PARKED
;
report_status_change
(
s
,
SIG_STATUS_TRAINING_FAILED
);
report_status_change
(
s
,
SIG_STATUS_TRAINING_FAILED
);
break
;
break
;
}
}
/* Make a step shift in the phase, to pull it into line. We need to rotate the equalizer
/* Make a step shift in the phase, to pull it into line. We need to rotate the equalizer
buffer, as well as the carrier phase, for this to play out nicely. */
buffer, as well as the carrier phase, for this to play out nicely. */
angle
+=
0x80000000
;
angle
+=
0x80000000
;
p
=
angle
*
2
.
0
f
*
3
.
14159
f
/
(
65536
.
0
f
*
65536
.
0
f
);
#if defined(SPANDSP_USE_FIXED_POINT)
#if defined(SPANDSP_USE_FIXED_POINTx)
z16
=
complex_seti16
(
fixed_cos
(
angle
>>
16
),
-
fixed_sin
(
angle
>>
16
));
zz
=
complex_setf
(
cosf
(
p
),
-
sinf
(
p
));
for
(
i
=
0
;
i
<
V27TER_EQUALIZER_LEN
;
i
++
)
for
(
i
=
0
;
i
<
V27TER_EQUALIZER_LEN
;
i
++
)
{
s
->
eq_buf
[
i
]
=
complex_mul_q1_15
(
&
s
->
eq_buf
[
i
],
&
z16
);
z1
=
complex_setf
(
s
->
eq_buf
[
i
].
re
,
s
->
eq_buf
[
i
].
im
);
z1
=
complex_mulf
(
&
z1
,
&
zz
);
s
->
eq_buf
[
i
].
re
=
z1
.
re
;
s
->
eq_buf
[
i
].
im
=
z1
.
im
;
}
#else
#else
p
=
angle
*
2
.
0
f
*
3
.
14159
f
/
(
65536
.
0
f
*
65536
.
0
f
);
zz
=
complex_setf
(
cosf
(
p
),
-
sinf
(
p
));
zz
=
complex_setf
(
cosf
(
p
),
-
sinf
(
p
));
for
(
i
=
0
;
i
<
V27TER_EQUALIZER_LEN
;
i
++
)
for
(
i
=
0
;
i
<
V27TER_EQUALIZER_LEN
;
i
++
)
s
->
eq_buf
[
i
]
=
complex_mulf
(
&
s
->
eq_buf
[
i
],
&
zz
);
s
->
eq_buf
[
i
]
=
complex_mulf
(
&
s
->
eq_buf
[
i
],
&
zz
);
...
@@ -682,7 +665,7 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
...
@@ -682,7 +665,7 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
track_carrier
(
s
,
&
z
,
target
);
track_carrier
(
s
,
&
z
,
target
);
tune_equalizer
(
s
,
&
z
,
target
);
tune_equalizer
(
s
,
&
z
,
target
);
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
s
->
carrier_track_i
=
400
+
(
200000
-
400
)
*
(
float
)
(
V27TER_TRAINING_SEG_5_LEN
-
s
->
training_count
)
/
(
float
)
V27TER_TRAINING_SEG_5_LEN
;
s
->
carrier_track_i
=
400
+
(
200000
-
400
)
*
(
float
)
(
V27TER_TRAINING_SEG_5_LEN
-
s
->
training_count
)
/
(
float
)
V27TER_TRAINING_SEG_5_LEN
;
s
->
carrier_track_p
=
1000000
+
(
10000000
-
1000000
)
*
(
float
)
(
V27TER_TRAINING_SEG_5_LEN
-
s
->
training_count
)
/
(
float
)
V27TER_TRAINING_SEG_5_LEN
;
s
->
carrier_track_p
=
1000000
+
(
10000000
-
1000000
)
*
(
float
)
(
V27TER_TRAINING_SEG_5_LEN
-
s
->
training_count
)
/
(
float
)
V27TER_TRAINING_SEG_5_LEN
;
#else
#else
...
@@ -702,13 +685,9 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
...
@@ -702,13 +685,9 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
constellation_state
=
(
s
->
bit_rate
==
4800
)
?
s
->
constellation_state
:
(
s
->
constellation_state
<<
1
);
constellation_state
=
(
s
->
bit_rate
==
4800
)
?
s
->
constellation_state
:
(
s
->
constellation_state
<<
1
);
target
=
&
v27ter_constellation
[
constellation_state
];
target
=
&
v27ter_constellation
[
constellation_state
];
/* Measure the training error */
/* Measure the training error */
#if defined(SPANDSP_USE_FIXED_POINTx)
#if defined(SPANDSP_USE_FIXED_POINT)
z1
.
re
=
z
.
re
/
(
float
)
FP_FACTOR
;
z16
=
complex_subi16
(
&
z
,
target
);
z1
.
im
=
z
.
im
/
(
float
)
FP_FACTOR
;
s
->
training_error
+=
poweri16
(
&
z16
);
zz
.
re
=
target
->
re
;
zz
.
im
=
target
->
im
;
zz
=
complex_subf
(
&
z1
,
&
zz
);
s
->
training_error
+=
powerf
(
&
zz
);
#else
#else
zz
=
complex_subf
(
&
z
,
target
);
zz
=
complex_subf
(
&
z
,
target
);
s
->
training_error
+=
powerf
(
&
zz
);
s
->
training_error
+=
powerf
(
&
zz
);
...
@@ -717,12 +696,20 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
...
@@ -717,12 +696,20 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
{
{
/* At 4800bps the symbols are 1.08238 (Euclidian) apart.
/* At 4800bps the symbols are 1.08238 (Euclidian) apart.
At 2400bps the symbols are 2.0 (Euclidian) apart. */
At 2400bps the symbols are 2.0 (Euclidian) apart. */
#if defined(SPANDSP_USE_FIXED_POINT)
if
((
s
->
bit_rate
==
4800
&&
s
->
training_error
<
V27TER_TRAINING_SEG_6_LEN
*
FP_FACTOR
*
FP_FACTOR
/
4
)
||
(
s
->
bit_rate
==
2400
&&
s
->
training_error
<
V27TER_TRAINING_SEG_6_LEN
*
FP_FACTOR
*
FP_FACTOR
/
2
))
{
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"Training succeeded at %dbps (constellation mismatch %d)
\n
"
,
s
->
bit_rate
,
s
->
training_error
);
#else
if
((
s
->
bit_rate
==
4800
&&
s
->
training_error
<
V27TER_TRAINING_SEG_6_LEN
*
0
.
25
f
)
if
((
s
->
bit_rate
==
4800
&&
s
->
training_error
<
V27TER_TRAINING_SEG_6_LEN
*
0
.
25
f
)
||
||
(
s
->
bit_rate
==
2400
&&
s
->
training_error
<
V27TER_TRAINING_SEG_6_LEN
*
0
.
5
f
))
(
s
->
bit_rate
==
2400
&&
s
->
training_error
<
V27TER_TRAINING_SEG_6_LEN
*
0
.
5
f
))
{
{
/* We are up and running */
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"Training succeeded at %dbps (constellation mismatch %f)
\n
"
,
s
->
bit_rate
,
s
->
training_error
);
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"Training succeeded at %dbps (constellation mismatch %f)
\n
"
,
s
->
bit_rate
,
s
->
training_error
);
#endif
/* We are up and running */
report_status_change
(
s
,
SIG_STATUS_TRAINING_SUCCEEDED
);
report_status_change
(
s
,
SIG_STATUS_TRAINING_SUCCEEDED
);
/* Apply some lag to the carrier off condition, to ensure the last few bits get pushed through
/* Apply some lag to the carrier off condition, to ensure the last few bits get pushed through
the processing. */
the processing. */
...
@@ -735,7 +722,11 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
...
@@ -735,7 +722,11 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
else
else
{
{
/* Training has failed */
/* Training has failed */
#if defined(SPANDSP_USE_FIXED_POINT)
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"Training failed (constellation mismatch %d)
\n
"
,
s
->
training_error
);
#else
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"Training failed (constellation mismatch %f)
\n
"
,
s
->
training_error
);
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"Training failed (constellation mismatch %f)
\n
"
,
s
->
training_error
);
#endif
/* Park this modem */
/* Park this modem */
s
->
training_stage
=
TRAINING_STAGE_PARKED
;
s
->
training_stage
=
TRAINING_STAGE_PARKED
;
report_status_change
(
s
,
SIG_STATUS_TRAINING_FAILED
);
report_status_change
(
s
,
SIG_STATUS_TRAINING_FAILED
);
...
@@ -750,17 +741,7 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
...
@@ -750,17 +741,7 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
break
;
break
;
}
}
if
(
s
->
qam_report
)
if
(
s
->
qam_report
)
{
#if defined(SPANDSP_USE_FIXED_POINTx)
z1
.
re
=
z
.
re
/
(
float
)
FP_FACTOR
;
z1
.
im
=
z
.
im
/
(
float
)
FP_FACTOR
;
zz
.
re
=
target
->
re
;
zz
.
im
=
target
->
im
;
s
->
qam_report
(
s
->
qam_user_data
,
&
z1
,
&
zz
,
s
->
constellation_state
);
#else
s
->
qam_report
(
s
->
qam_user_data
,
&
z
,
target
,
s
->
constellation_state
);
s
->
qam_report
(
s
->
qam_user_data
,
&
z
,
target
,
s
->
constellation_state
);
#endif
}
}
}
/*- End of function --------------------------------------------------------*/
/*- End of function --------------------------------------------------------*/
...
@@ -777,7 +758,7 @@ static __inline__ int signal_detect(v27ter_rx_state_t *s, int16_t amp)
...
@@ -777,7 +758,7 @@ static __inline__ int signal_detect(v27ter_rx_state_t *s, int16_t amp)
/* There could be overflow here, but it isn't a problem in practice */
/* There could be overflow here, but it isn't a problem in practice */
diff
=
x
-
s
->
last_sample
;
diff
=
x
-
s
->
last_sample
;
s
->
last_sample
=
x
;
s
->
last_sample
=
x
;
power
=
power_meter_update
(
&
(
s
->
power
)
,
diff
);
power
=
power_meter_update
(
&
s
->
power
,
diff
);
#if defined(IAXMODEM_STUFF)
#if defined(IAXMODEM_STUFF)
/* Quick power drop fudge */
/* Quick power drop fudge */
diff
=
abs
(
diff
);
diff
=
abs
(
diff
);
...
@@ -785,7 +766,7 @@ static __inline__ int signal_detect(v27ter_rx_state_t *s, int16_t amp)
...
@@ -785,7 +766,7 @@ static __inline__ int signal_detect(v27ter_rx_state_t *s, int16_t amp)
{
{
if
(
++
s
->
low_samples
>
120
)
if
(
++
s
->
low_samples
>
120
)
{
{
power_meter_init
(
&
(
s
->
power
)
,
4
);
power_meter_init
(
&
s
->
power
,
4
);
s
->
high_sample
=
0
;
s
->
high_sample
=
0
;
s
->
low_samples
=
0
;
s
->
low_samples
=
0
;
}
}
...
@@ -797,7 +778,7 @@ static __inline__ int signal_detect(v27ter_rx_state_t *s, int16_t amp)
...
@@ -797,7 +778,7 @@ static __inline__ int signal_detect(v27ter_rx_state_t *s, int16_t amp)
s
->
high_sample
=
diff
;
s
->
high_sample
=
diff
;
}
}
#endif
#endif
//span_log(&s->logging, SPAN_LOG_FLOW, "Power = %f\n", power_meter_current_dbm0(&
(s->power)
));
//span_log(&s->logging, SPAN_LOG_FLOW, "Power = %f\n", power_meter_current_dbm0(&
s->power
));
if
(
s
->
signal_present
>
0
)
if
(
s
->
signal_present
>
0
)
{
{
/* Look for power below turn-off threshold to turn the carrier off */
/* Look for power below turn-off threshold to turn the carrier off */
...
@@ -867,7 +848,7 @@ SPAN_DECLARE_NONSTD(int) v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], in
...
@@ -867,7 +848,7 @@ SPAN_DECLARE_NONSTD(int) v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], in
parked, after training failure. */
parked, after training failure. */
if
(
s
->
training_stage
==
TRAINING_STAGE_PARKED
)
if
(
s
->
training_stage
==
TRAINING_STAGE_PARKED
)
continue
;
continue
;
/* 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. */
if
((
s
->
eq_put_step
-=
RX_PULSESHAPER_4800_COEFF_SETS
)
<=
0
)
if
((
s
->
eq_put_step
-=
RX_PULSESHAPER_4800_COEFF_SETS
)
<=
0
)
...
@@ -876,7 +857,7 @@ SPAN_DECLARE_NONSTD(int) v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], in
...
@@ -876,7 +857,7 @@ SPAN_DECLARE_NONSTD(int) v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], in
{
{
/* Only AGC during the initial training */
/* Only AGC during the initial training */
#if defined(SPANDSP_USE_FIXED_POINT)
#if defined(SPANDSP_USE_FIXED_POINT)
s
->
agc_scaling
=
(
float
)
FP_FACTOR
*
32768
.
0
f
*
(
1
.
0
f
/
RX_PULSESHAPER_4800_GAIN
)
*
1
.
414
f
/
sqrtf
(
power
);
s
->
agc_scaling
=
saturate16
(((
int32_t
)
(
1024
.
0
f
*
FP_FACTOR
*
1
.
414
f
))
/
fixed_sqrt32
(
power
)
);
#else
#else
s
->
agc_scaling
=
(
1
.
0
f
/
RX_PULSESHAPER_4800_GAIN
)
*
1
.
414
f
/
sqrtf
(
power
);
s
->
agc_scaling
=
(
1
.
0
f
/
RX_PULSESHAPER_4800_GAIN
)
*
1
.
414
f
/
sqrtf
(
power
);
#endif
#endif
...
@@ -890,13 +871,13 @@ SPAN_DECLARE_NONSTD(int) v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], in
...
@@ -890,13 +871,13 @@ SPAN_DECLARE_NONSTD(int) v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], in
step
=
RX_PULSESHAPER_4800_COEFF_SETS
-
1
;
step
=
RX_PULSESHAPER_4800_COEFF_SETS
-
1
;
s
->
eq_put_step
+=
RX_PULSESHAPER_4800_COEFF_SETS
*
5
/
2
;
s
->
eq_put_step
+=
RX_PULSESHAPER_4800_COEFF_SETS
*
5
/
2
;
#if defined(SPANDSP_USE_FIXED_POINT)
#if defined(SPANDSP_USE_FIXED_POINT)
v
=
vec_circular_dot_prodi16
(
s
->
rrc_filter
,
rx_pulseshaper_4800_re
[
step
],
V27TER_RX_FILTER_STEPS
,
s
->
rrc_filter_step
);
v
=
vec_circular_dot_prodi16
(
s
->
rrc_filter
,
rx_pulseshaper_4800_re
[
step
],
V27TER_RX_FILTER_STEPS
,
s
->
rrc_filter_step
)
>>
15
;
sample
.
re
=
(
v
*
(
int32_t
)
s
->
agc_scaling
)
>>
15
;
sample
.
re
=
(
v
*
s
->
agc_scaling
)
>>
10
;
v
=
vec_circular_dot_prodi16
(
s
->
rrc_filter
,
rx_pulseshaper_4800_im
[
step
],
V27TER_RX_FILTER_STEPS
,
s
->
rrc_filter_step
);
v
=
vec_circular_dot_prodi16
(
s
->
rrc_filter
,
rx_pulseshaper_4800_im
[
step
],
V27TER_RX_FILTER_STEPS
,
s
->
rrc_filter_step
)
>>
15
;
sample
.
im
=
(
v
*
(
int32_t
)
s
->
agc_scaling
)
>>
15
;
sample
.
im
=
(
v
*
s
->
agc_scaling
)
>>
10
;
z
=
dds_lookup_complexi16
(
s
->
carrier_phase
);
z
=
dds_lookup_complexi16
(
s
->
carrier_phase
);
zz
.
re
=
((
int32_t
)
sample
.
re
*
(
int32_t
)
z
.
re
-
(
int32_t
)
sample
.
im
*
(
int32_t
)
z
.
im
)
>>
15
;
zz
.
re
=
((
int32_t
)
sample
.
re
*
z
.
re
-
(
int32_t
)
sample
.
im
*
z
.
im
)
>>
15
;
zz
.
im
=
((
int32_t
)
-
sample
.
re
*
(
int32_t
)
z
.
im
-
(
int32_t
)
sample
.
im
*
(
int32_t
)
z
.
re
)
>>
15
;
zz
.
im
=
((
int32_t
)
-
sample
.
re
*
z
.
im
-
(
int32_t
)
sample
.
im
*
z
.
re
)
>>
15
;
#else
#else
v
=
vec_circular_dot_prodf
(
s
->
rrc_filter
,
rx_pulseshaper_4800_re
[
step
],
V27TER_RX_FILTER_STEPS
,
s
->
rrc_filter_step
);
v
=
vec_circular_dot_prodf
(
s
->
rrc_filter
,
rx_pulseshaper_4800_re
[
step
],
V27TER_RX_FILTER_STEPS
,
s
->
rrc_filter_step
);
sample
.
re
=
v
*
s
->
agc_scaling
;
sample
.
re
=
v
*
s
->
agc_scaling
;
...
@@ -929,7 +910,7 @@ SPAN_DECLARE_NONSTD(int) v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], in
...
@@ -929,7 +910,7 @@ SPAN_DECLARE_NONSTD(int) v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], in
parked, after training failure. */
parked, after training failure. */
if
(
s
->
training_stage
==
TRAINING_STAGE_PARKED
)
if
(
s
->
training_stage
==
TRAINING_STAGE_PARKED
)
continue
;
continue
;
/* 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. */
if
((
s
->
eq_put_step
-=
RX_PULSESHAPER_2400_COEFF_SETS
)
<=
0
)
if
((
s
->
eq_put_step
-=
RX_PULSESHAPER_2400_COEFF_SETS
)
<=
0
)
...
@@ -938,7 +919,7 @@ SPAN_DECLARE_NONSTD(int) v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], in
...
@@ -938,7 +919,7 @@ SPAN_DECLARE_NONSTD(int) v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], in
{
{
/* Only AGC during the initial training */
/* Only AGC during the initial training */
#if defined(SPANDSP_USE_FIXED_POINT)
#if defined(SPANDSP_USE_FIXED_POINT)
s
->
agc_scaling
=
(
float
)
FP_FACTOR
*
32768
.
0
f
*
(
1
.
0
f
/
RX_PULSESHAPER_2400_GAIN
)
*
1
.
414
f
/
sqrtf
(
power
);
s
->
agc_scaling
=
saturate16
(((
int32_t
)
(
1024
.
0
f
*
FP_FACTOR
*
1
.
414
f
))
/
fixed_sqrt32
(
power
)
);
#else
#else
s
->
agc_scaling
=
(
1
.
0
f
/
RX_PULSESHAPER_2400_GAIN
)
*
1
.
414
f
/
sqrtf
(
power
);
s
->
agc_scaling
=
(
1
.
0
f
/
RX_PULSESHAPER_2400_GAIN
)
*
1
.
414
f
/
sqrtf
(
power
);
#endif
#endif
...
@@ -952,13 +933,13 @@ SPAN_DECLARE_NONSTD(int) v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], in
...
@@ -952,13 +933,13 @@ SPAN_DECLARE_NONSTD(int) v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], in
step
=
RX_PULSESHAPER_2400_COEFF_SETS
-
1
;
step
=
RX_PULSESHAPER_2400_COEFF_SETS
-
1
;
s
->
eq_put_step
+=
RX_PULSESHAPER_2400_COEFF_SETS
*
20
/
(
3
*
2
);
s
->
eq_put_step
+=
RX_PULSESHAPER_2400_COEFF_SETS
*
20
/
(
3
*
2
);
#if defined(SPANDSP_USE_FIXED_POINT)
#if defined(SPANDSP_USE_FIXED_POINT)
v
=
vec_circular_dot_prodi16
(
s
->
rrc_filter
,
rx_pulseshaper_2400_re
[
step
],
V27TER_RX_FILTER_STEPS
,
s
->
rrc_filter_step
);
v
=
vec_circular_dot_prodi16
(
s
->
rrc_filter
,
rx_pulseshaper_2400_re
[
step
],
V27TER_RX_FILTER_STEPS
,
s
->
rrc_filter_step
)
>>
15
;
sample
.
re
=
(
v
*
(
int32_t
)
s
->
agc_scaling
)
>>
15
;
sample
.
re
=
(
v
*
s
->
agc_scaling
)
>>
10
;
v
=
vec_circular_dot_prodi16
(
s
->
rrc_filter
,
rx_pulseshaper_2400_im
[
step
],
V27TER_RX_FILTER_STEPS
,
s
->
rrc_filter_step
);
v
=
vec_circular_dot_prodi16
(
s
->
rrc_filter
,
rx_pulseshaper_2400_im
[
step
],
V27TER_RX_FILTER_STEPS
,
s
->
rrc_filter_step
)
>>
15
;
sample
.
im
=
(
v
*
(
int32_t
)
s
->
agc_scaling
)
>>
15
;
sample
.
im
=
(
v
*
s
->
agc_scaling
)
>>
10
;
z
=
dds_lookup_complexi16
(
s
->
carrier_phase
);
z
=
dds_lookup_complexi16
(
s
->
carrier_phase
);
zz
.
re
=
((
int32_t
)
sample
.
re
*
(
int32_t
)
z
.
re
-
(
int32_t
)
sample
.
im
*
(
int32_t
)
z
.
im
)
>>
15
;
zz
.
re
=
((
int32_t
)
sample
.
re
*
z
.
re
-
(
int32_t
)
sample
.
im
*
z
.
im
)
>>
15
;
zz
.
im
=
((
int32_t
)
-
sample
.
re
*
(
int32_t
)
z
.
im
-
(
int32_t
)
sample
.
im
*
(
int32_t
)
z
.
re
)
>>
15
;
zz
.
im
=
((
int32_t
)
-
sample
.
re
*
z
.
im
-
(
int32_t
)
sample
.
im
*
z
.
re
)
>>
15
;
#else
#else
v
=
vec_circular_dot_prodf
(
s
->
rrc_filter
,
rx_pulseshaper_2400_re
[
step
],
V27TER_RX_FILTER_STEPS
,
s
->
rrc_filter_step
);
v
=
vec_circular_dot_prodf
(
s
->
rrc_filter
,
rx_pulseshaper_2400_re
[
step
],
V27TER_RX_FILTER_STEPS
,
s
->
rrc_filter_step
);
sample
.
re
=
v
*
s
->
agc_scaling
;
sample
.
re
=
v
*
s
->
agc_scaling
;
...
@@ -1045,8 +1026,10 @@ SPAN_DECLARE(int) v27ter_rx_restart(v27ter_rx_state_t *s, int bit_rate, int old_
...
@@ -1045,8 +1026,10 @@ SPAN_DECLARE(int) v27ter_rx_restart(v27ter_rx_state_t *s, int bit_rate, int old_
#if defined(SPANDSP_USE_FIXED_POINT)
#if defined(SPANDSP_USE_FIXED_POINT)
vec_zeroi16
(
s
->
rrc_filter
,
sizeof
(
s
->
rrc_filter
)
/
sizeof
(
s
->
rrc_filter
[
0
]));
vec_zeroi16
(
s
->
rrc_filter
,
sizeof
(
s
->
rrc_filter
)
/
sizeof
(
s
->
rrc_filter
[
0
]));
s
->
training_error
=
0
;
#else
#else
vec_zerof
(
s
->
rrc_filter
,
sizeof
(
s
->
rrc_filter
)
/
sizeof
(
s
->
rrc_filter
[
0
]));
vec_zerof
(
s
->
rrc_filter
,
sizeof
(
s
->
rrc_filter
)
/
sizeof
(
s
->
rrc_filter
[
0
]));
s
->
training_error
=
0
.
0
f
;
#endif
#endif
s
->
rrc_filter_step
=
0
;
s
->
rrc_filter_step
=
0
;
...
@@ -1055,7 +1038,6 @@ SPAN_DECLARE(int) v27ter_rx_restart(v27ter_rx_state_t *s, int bit_rate, int old_
...
@@ -1055,7 +1038,6 @@ SPAN_DECLARE(int) v27ter_rx_restart(v27ter_rx_state_t *s, int bit_rate, int old_
s
->
training_stage
=
TRAINING_STAGE_SYMBOL_ACQUISITION
;
s
->
training_stage
=
TRAINING_STAGE_SYMBOL_ACQUISITION
;
s
->
training_bc
=
0
;
s
->
training_bc
=
0
;
s
->
training_count
=
0
;
s
->
training_count
=
0
;
s
->
training_error
=
0
.
0
f
;
s
->
signal_present
=
0
;
s
->
signal_present
=
0
;
#if defined(IAXMODEM_STUFF)
#if defined(IAXMODEM_STUFF)
s
->
high_sample
=
0
;
s
->
high_sample
=
0
;
...
@@ -1064,14 +1046,14 @@ SPAN_DECLARE(int) v27ter_rx_restart(v27ter_rx_state_t *s, int bit_rate, int old_
...
@@ -1064,14 +1046,14 @@ SPAN_DECLARE(int) v27ter_rx_restart(v27ter_rx_state_t *s, int bit_rate, int old_
#endif
#endif
s
->
carrier_phase
=
0
;
s
->
carrier_phase
=
0
;
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
s
->
carrier_track_i
=
200000
;
s
->
carrier_track_i
=
200000
;
s
->
carrier_track_p
=
10000000
;
s
->
carrier_track_p
=
10000000
;
#else
#else
s
->
carrier_track_i
=
200000
.
0
f
;
s
->
carrier_track_i
=
200000
.
0
f
;
s
->
carrier_track_p
=
10000000
.
0
f
;
s
->
carrier_track_p
=
10000000
.
0
f
;
#endif
#endif
power_meter_init
(
&
(
s
->
power
)
,
4
);
power_meter_init
(
&
s
->
power
,
4
);
s
->
constellation_state
=
0
;
s
->
constellation_state
=
0
;
...
@@ -1084,10 +1066,10 @@ SPAN_DECLARE(int) v27ter_rx_restart(v27ter_rx_state_t *s, int bit_rate, int old_
...
@@ -1084,10 +1066,10 @@ SPAN_DECLARE(int) v27ter_rx_restart(v27ter_rx_state_t *s, int bit_rate, int old_
else
else
{
{
s
->
carrier_phase_rate
=
dds_phase_ratef
(
CARRIER_NOMINAL_FREQ
);
s
->
carrier_phase_rate
=
dds_phase_ratef
(
CARRIER_NOMINAL_FREQ
);
#if defined(SPANDSP_USE_FIXED_POINT
x
)
#if defined(SPANDSP_USE_FIXED_POINT)
s
->
agc_scaling
=
(
float
)
FP_FACTOR
*
32768
.
0
f
*
0
.
005
f
/
RX_PULSESHAPER_4800_GAIN
;
s
->
agc_scaling
=
(
float
)
(
1024
.
0
f
*
FP_FACTOR
)
*
1
.
414
f
/
283
.
0
f
;
#else
#else
s
->
agc_scaling
=
0
.
005
f
/
RX_PULSESHAPER_4800_GAIN
;
s
->
agc_scaling
=
(
1
.
0
f
/
RX_PULSESHAPER_4800_GAIN
)
*
1
.
414
f
/
283
.
0
f
;
#endif
#endif
equalizer_reset
(
s
);
equalizer_reset
(
s
);
}
}
...
...
libs/spandsp/src/v29rx.c
浏览文件 @
e58b2e7d
...
@@ -63,10 +63,15 @@
...
@@ -63,10 +63,15 @@
#include "spandsp/private/logging.h"
#include "spandsp/private/logging.h"
#include "spandsp/private/v29rx.h"
#include "spandsp/private/v29rx.h"
#include "v29tx_constellation_maps.h"
#if defined(SPANDSP_USE_FIXED_POINT)
#if defined(SPANDSP_USE_FIXED_POINT)
#define FP_SCALE FP_Q_4_12
#define FP_FACTOR 4096
#define FP_SHIFT_FACTOR 12
#include "v29tx_constellation_maps.h"
#include "v29rx_fixed_rrc.h"
#include "v29rx_fixed_rrc.h"
#else
#else
#define FP_SCALE(x) (x)
#include "v29tx_constellation_maps.h"
#include "v29rx_floating_rrc.h"
#include "v29rx_floating_rrc.h"
#endif
#endif
...
@@ -77,11 +82,6 @@
...
@@ -77,11 +82,6 @@
/*! The adaption rate coefficient for the equalizer */
/*! The adaption rate coefficient for the equalizer */
#define EQUALIZER_DELTA 0.21f
#define EQUALIZER_DELTA 0.21f
#if defined(SPANDSP_USE_FIXED_POINT)
#define FP_FACTOR 4096
#define FP_SHIFT_FACTOR 12
#endif
/* Segments of the training sequence */
/* Segments of the training sequence */
/*! The length of training segment 2, in symbols */
/*! The length of training segment 2, in symbols */
#define V29_TRAINING_SEG_2_LEN 128
#define V29_TRAINING_SEG_2_LEN 128
...
@@ -136,13 +136,13 @@ static const uint8_t space_map_9600[20][20] =
...
@@ -136,13 +136,13 @@ static const uint8_t space_map_9600[20][20] =
#define ALPHA 0.99f
#define ALPHA 0.99f
#if defined(SPANDSP_USE_FIXED_POINT)
#if defined(SPANDSP_USE_FIXED_POINT)
#define SYNC_LOW_BAND_EDGE_COEFF_0
((int)(FP_FACTOR*(2.0f*ALPHA*COS_LOW_BAND_EDGE))
)
#define SYNC_LOW_BAND_EDGE_COEFF_0
FP_Q_6_10(2.0f*ALPHA*COS_LOW_BAND_EDGE
)
#define SYNC_LOW_BAND_EDGE_COEFF_1
((int)(FP_FACTOR*(-ALPHA*ALPHA))
)
#define SYNC_LOW_BAND_EDGE_COEFF_1
FP_Q_6_10(-ALPHA*ALPHA
)
#define SYNC_LOW_BAND_EDGE_COEFF_2
((int)(FP_FACTOR*(-ALPHA*SIN_LOW_BAND_EDGE))
)
#define SYNC_LOW_BAND_EDGE_COEFF_2
FP_Q_6_10(-ALPHA*SIN_LOW_BAND_EDGE
)
#define SYNC_HIGH_BAND_EDGE_COEFF_0
((int)(FP_FACTOR*(2.0f*ALPHA*COS_HIGH_BAND_EDGE))
)
#define SYNC_HIGH_BAND_EDGE_COEFF_0
FP_Q_6_10(2.0f*ALPHA*COS_HIGH_BAND_EDGE
)
#define SYNC_HIGH_BAND_EDGE_COEFF_1
((int)(FP_FACTOR*(-ALPHA*ALPHA))
)
#define SYNC_HIGH_BAND_EDGE_COEFF_1
FP_Q_6_10(-ALPHA*ALPHA
)
#define SYNC_HIGH_BAND_EDGE_COEFF_2
((int)(FP_FACTOR*(-ALPHA*SIN_HIGH_BAND_EDGE))
)
#define SYNC_HIGH_BAND_EDGE_COEFF_2
FP_Q_6_10(-ALPHA*SIN_HIGH_BAND_EDGE
)
#define SYNC_MIXED_EDGES_COEFF_3
((int)(FP_FACTOR*(-ALPHA*ALPHA*(SIN_HIGH_BAND_EDGE*COS_LOW_BAND_EDGE - SIN_LOW_BAND_EDGE*COS_HIGH_BAND_EDGE))
))
#define SYNC_MIXED_EDGES_COEFF_3
FP_Q_6_10(-ALPHA*ALPHA*(SIN_HIGH_BAND_EDGE*COS_LOW_BAND_EDGE - SIN_LOW_BAND_EDGE*COS_HIGH_BAND_EDGE
))
#else
#else
#define SYNC_LOW_BAND_EDGE_COEFF_0 (2.0f*ALPHA*COS_LOW_BAND_EDGE)
#define SYNC_LOW_BAND_EDGE_COEFF_0 (2.0f*ALPHA*COS_LOW_BAND_EDGE)
#define SYNC_LOW_BAND_EDGE_COEFF_1 (-ALPHA*ALPHA)
#define SYNC_LOW_BAND_EDGE_COEFF_1 (-ALPHA*ALPHA)
...
@@ -230,7 +230,7 @@ static void equalizer_reset(v29_rx_state_t *s)
...
@@ -230,7 +230,7 @@ static void equalizer_reset(v29_rx_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)
#if defined(SPANDSP_USE_FIXED_POINT)
static
const
complexi16_t
x
=
{
3
*
FP_FACTOR
,
0
*
FP_FACTOR
};
static
const
complexi16_t
x
=
{
FP_SCALE
(
3
.
0
f
),
FP_SCALE
(
0
.
0
f
)
};
cvec_zeroi16
(
s
->
eq_coeff
,
V29_EQUALIZER_LEN
);
cvec_zeroi16
(
s
->
eq_coeff
,
V29_EQUALIZER_LEN
);
s
->
eq_coeff
[
V29_EQUALIZER_PRE_LEN
]
=
x
;
s
->
eq_coeff
[
V29_EQUALIZER_PRE_LEN
]
=
x
;
...
@@ -250,25 +250,9 @@ static void equalizer_reset(v29_rx_state_t *s)
...
@@ -250,25 +250,9 @@ static void equalizer_reset(v29_rx_state_t *s)
}
}
/*- End of function --------------------------------------------------------*/
/*- End of function --------------------------------------------------------*/
#if defined(SPANDSP_USE_FIXED_POINT)
static
__inline__
complexi16_t
complex_mul_q4_12
(
const
complexi16_t
*
x
,
const
complexi16_t
*
y
)
{
complexi16_t
z
;
z
.
re
=
((
int32_t
)
x
->
re
*
(
int32_t
)
y
->
re
-
(
int32_t
)
x
->
im
*
(
int32_t
)
y
->
im
)
>>
FP_SHIFT_FACTOR
;
z
.
im
=
((
int32_t
)
x
->
re
*
(
int32_t
)
y
->
im
+
(
int32_t
)
x
->
im
*
(
int32_t
)
y
->
re
)
>>
FP_SHIFT_FACTOR
;
return
z
;
}
/*- End of function --------------------------------------------------------*/
#endif
#if defined(SPANDSP_USE_FIXED_POINT)
#if defined(SPANDSP_USE_FIXED_POINT)
static
__inline__
complexi16_t
equalizer_get
(
v29_rx_state_t
*
s
)
static
__inline__
complexi16_t
equalizer_get
(
v29_rx_state_t
*
s
)
#else
static
__inline__
complexf_t
equalizer_get
(
v29_rx_state_t
*
s
)
#endif
{
{
#if defined(SPANDSP_USE_FIXED_POINT)
complexi32_t
zz
;
complexi32_t
zz
;
complexi16_t
z
;
complexi16_t
z
;
...
@@ -277,11 +261,14 @@ static __inline__ complexf_t equalizer_get(v29_rx_state_t *s)
...
@@ -277,11 +261,14 @@ static __inline__ complexf_t equalizer_get(v29_rx_state_t *s)
z
.
re
=
zz
.
re
>>
FP_SHIFT_FACTOR
;
z
.
re
=
zz
.
re
>>
FP_SHIFT_FACTOR
;
z
.
im
=
zz
.
im
>>
FP_SHIFT_FACTOR
;
z
.
im
=
zz
.
im
>>
FP_SHIFT_FACTOR
;
return
z
;
return
z
;
}
#else
#else
static
__inline__
complexf_t
equalizer_get
(
v29_rx_state_t
*
s
)
{
/* Get the next equalized value. */
/* Get the next equalized value. */
return
cvec_circular_dot_prodf
(
s
->
eq_buf
,
s
->
eq_coeff
,
V29_EQUALIZER_LEN
,
s
->
eq_step
);
return
cvec_circular_dot_prodf
(
s
->
eq_buf
,
s
->
eq_coeff
,
V29_EQUALIZER_LEN
,
s
->
eq_step
);
#endif
}
}
#endif
/*- End of function --------------------------------------------------------*/
/*- End of function --------------------------------------------------------*/
#if defined(SPANDSP_USE_FIXED_POINT)
#if defined(SPANDSP_USE_FIXED_POINT)
...
@@ -290,10 +277,9 @@ static void tune_equalizer(v29_rx_state_t *s, const complexi16_t *z, const compl
...
@@ -290,10 +277,9 @@ static void tune_equalizer(v29_rx_state_t *s, const complexi16_t *z, const compl
complexi16_t
err
;
complexi16_t
err
;
/* Find the x and y mismatch from the exact constellation position. */
/* Find the x and y mismatch from the exact constellation position. */
err
.
re
=
target
->
re
*
FP_FACTOR
-
z
->
re
;
err
=
complex_subi16
(
target
,
z
);
err
.
im
=
target
->
im
*
FP_FACTOR
-
z
->
im
;
err
.
re
=
((
int32_t
)
err
.
re
*
s
->
eq_delta
)
>>
15
;
err
.
re
=
((
int32_t
)
err
.
re
*
(
int32_t
)
s
->
eq_delta
)
>>
15
;
err
.
im
=
((
int32_t
)
err
.
im
*
s
->
eq_delta
)
>>
15
;
err
.
im
=
((
int32_t
)
err
.
im
*
(
int32_t
)
s
->
eq_delta
)
>>
15
;
cvec_circular_lmsi16
(
s
->
eq_buf
,
s
->
eq_coeff
,
V29_EQUALIZER_LEN
,
s
->
eq_step
,
&
err
);
cvec_circular_lmsi16
(
s
->
eq_buf
,
s
->
eq_coeff
,
V29_EQUALIZER_LEN
,
s
->
eq_step
,
&
err
);
}
}
#else
#else
...
@@ -365,8 +351,11 @@ static __inline__ void track_carrier(v29_rx_state_t *s, const complexf_t *z, con
...
@@ -365,8 +351,11 @@ static __inline__ void track_carrier(v29_rx_state_t *s, const complexf_t *z, con
different amplitudes of the various target positions scale things. This isn't all bad,
different amplitudes of the various target positions scale things. This isn't all bad,
as the angular error for the larger amplitude constellation points is probably
as the angular error for the larger amplitude constellation points is probably
a more reliable indicator, and we are weighting it as such. */
a more reliable indicator, and we are weighting it as such. */
#if defined(SPANDSP_USE_FIXED_POINT)
error
=
(((
int32_t
)
z
->
im
*
target
->
re
)
>>
FP_SHIFT_FACTOR
)
-
(((
int32_t
)
z
->
re
*
target
->
im
)
>>
FP_SHIFT_FACTOR
);
#else
error
=
z
->
im
*
target
->
re
-
z
->
re
*
target
->
im
;
error
=
z
->
im
*
target
->
re
-
z
->
re
*
target
->
im
;
#endif
/* Use a proportional-integral approach to tracking the carrier. The PI
/* Use a proportional-integral approach to tracking the carrier. The PI
parameters are coarser at first, until we get precisely on target. Then,
parameters are coarser at first, until we get precisely on target. Then,
the filter will be damped more to keep us on target. */
the filter will be damped more to keep us on target. */
...
@@ -562,18 +551,19 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
...
@@ -562,18 +551,19 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
0
,
3
,
0
,
3
,
0
,
2
0
,
2
};
};
complexf_t
zz
;
#if defined(SPANDSP_USE_FIXED_POINT)
#if defined(SPANDSP_USE_FIXED_POINT)
complexf_t
z1
;
uint16_t
ip
;
complexi16_t
z
;
complexi16_t
z
;
complexi16_t
z16
;
const
complexi16_t
*
target
;
const
complexi16_t
*
target
;
static
const
complexi16_t
zero
=
{
0
,
0
};
static
const
complexi16_t
zero
=
{
0
,
0
};
#else
#else
float
p
;
complexf_t
z
;
complexf_t
z
;
complexf_t
zz
;
const
complexf_t
*
target
;
const
complexf_t
*
target
;
static
const
complexf_t
zero
=
{
0
.
0
f
,
0
.
0
f
};
static
const
complexf_t
zero
=
{
0
.
0
f
,
0
.
0
f
};
#endif
#endif
float
p
;
int
bit
;
int
bit
;
int
i
;
int
i
;
int
j
;
int
j
;
...
@@ -671,17 +661,15 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
...
@@ -671,17 +661,15 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
}
}
/* Make a step shift in the phase, to pull it into line. We need to rotate the equalizer
/* Make a step shift in the phase, to pull it into line. We need to rotate the equalizer
buffer, as well as the carrier phase, for this to play out nicely. */
buffer, as well as the carrier phase, for this to play out nicely. */
p
=
angle
*
2
.
0
f
*
3
.
14159
f
/
(
65536
.
0
f
*
65536
.
0
f
);
#if defined(SPANDSP_USE_FIXED_POINT)
#if defined(SPANDSP_USE_FIXED_POINT)
zz
=
complex_setf
(
cosf
(
p
),
-
sinf
(
p
));
ip
=
angle
>>
16
;
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"Spin by %d
\n
"
,
ip
);
z16
=
complex_seti16
(
fixed_cos
(
ip
),
-
fixed_sin
(
ip
));
for
(
i
=
0
;
i
<
V29_EQUALIZER_LEN
;
i
++
)
for
(
i
=
0
;
i
<
V29_EQUALIZER_LEN
;
i
++
)
{
s
->
eq_buf
[
i
]
=
complex_mul_q1_15
(
&
s
->
eq_buf
[
i
],
&
z16
);
z1
=
complex_setf
(
s
->
eq_buf
[
i
].
re
,
s
->
eq_buf
[
i
].
im
);
z1
=
complex_mulf
(
&
z1
,
&
zz
);
s
->
eq_buf
[
i
].
re
=
z1
.
re
;
s
->
eq_buf
[
i
].
im
=
z1
.
im
;
}
#else
#else
p
=
angle
*
2
.
0
f
*
3
.
14159
f
/
(
65536
.
0
f
*
65536
.
0
f
);
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"Spin by %.5f rads
\n
"
,
p
);
zz
=
complex_setf
(
cosf
(
p
),
-
sinf
(
p
));
zz
=
complex_setf
(
cosf
(
p
),
-
sinf
(
p
));
for
(
i
=
0
;
i
<
V29_EQUALIZER_LEN
;
i
++
)
for
(
i
=
0
;
i
<
V29_EQUALIZER_LEN
;
i
++
)
s
->
eq_buf
[
i
]
=
complex_mulf
(
&
s
->
eq_buf
[
i
],
&
zz
);
s
->
eq_buf
[
i
]
=
complex_mulf
(
&
s
->
eq_buf
[
i
],
&
zz
);
...
@@ -743,23 +731,26 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
...
@@ -743,23 +731,26 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
tune_equalizer
(
s
,
&
z
,
target
);
tune_equalizer
(
s
,
&
z
,
target
);
/* Measure the training error */
/* Measure the training error */
#if defined(SPANDSP_USE_FIXED_POINT)
#if defined(SPANDSP_USE_FIXED_POINT)
z1
.
re
=
z
.
re
/
(
float
)
FP_FACTOR
;
z16
=
complex_subi16
(
&
z
,
target
);
z1
.
im
=
z
.
im
/
(
float
)
FP_FACTOR
;
s
->
training_error
+=
poweri16
(
&
z16
);
zz
.
re
=
target
->
re
;
zz
.
im
=
target
->
im
;
zz
=
complex_subf
(
&
z1
,
&
zz
);
s
->
training_error
+=
powerf
(
&
zz
);
#else
#else
zz
=
complex_subf
(
&
z
,
target
);
zz
=
complex_subf
(
&
z
,
target
);
s
->
training_error
+=
powerf
(
&
zz
);
s
->
training_error
+=
powerf
(
&
zz
);
#endif
#endif
if
(
++
s
->
training_count
>=
V29_TRAINING_SEG_3_LEN
)
if
(
++
s
->
training_count
>=
V29_TRAINING_SEG_3_LEN
)
{
{
#if defined(SPANDSP_USE_FIXED_POINT)
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"Constellation mismatch %d
\n
"
,
s
->
training_error
);
if
(
s
->
training_error
<
48
*
2
*
FP_FACTOR
*
FP_FACTOR
)
{
s
->
training_error
=
0
;
#else
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"Constellation mismatch %f
\n
"
,
s
->
training_error
);
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"Constellation mismatch %f
\n
"
,
s
->
training_error
);
if
(
s
->
training_error
<
48
.
0
f
*
2
.
0
f
)
if
(
s
->
training_error
<
48
.
0
f
*
2
.
0
f
)
{
{
s
->
training_count
=
0
;
s
->
training_error
=
0
.
0
f
;
s
->
training_error
=
0
.
0
f
;
#endif
s
->
training_count
=
0
;
s
->
constellation_state
=
0
;
s
->
constellation_state
=
0
;
s
->
training_stage
=
TRAINING_STAGE_TEST_ONES
;
s
->
training_stage
=
TRAINING_STAGE_TEST_ONES
;
}
}
...
@@ -785,22 +776,26 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
...
@@ -785,22 +776,26 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
target
=
&
v29_9600_constellation
[
s
->
constellation_state
];
target
=
&
v29_9600_constellation
[
s
->
constellation_state
];
/* Measure the training error */
/* Measure the training error */
#if defined(SPANDSP_USE_FIXED_POINT)
#if defined(SPANDSP_USE_FIXED_POINT)
z1
.
re
=
z
.
re
/
(
float
)
FP_FACTOR
;
z16
=
complex_subi16
(
&
z
,
target
);
z1
.
im
=
z
.
im
/
(
float
)
FP_FACTOR
;
s
->
training_error
+=
poweri16
(
&
z16
);
zz
.
re
=
target
->
re
;
zz
.
im
=
target
->
im
;
zz
=
complex_subf
(
&
z1
,
&
zz
);
s
->
training_error
+=
powerf
(
&
zz
);
#else
#else
zz
=
complex_subf
(
&
z
,
target
);
zz
=
complex_subf
(
&
z
,
target
);
s
->
training_error
+=
powerf
(
&
zz
);
s
->
training_error
+=
powerf
(
&
zz
);
#endif
#endif
if
(
++
s
->
training_count
>=
V29_TRAINING_SEG_4_LEN
)
if
(
++
s
->
training_count
>=
V29_TRAINING_SEG_4_LEN
)
{
{
#if defined(SPANDSP_USE_FIXED_POINT)
if
(
s
->
training_error
<
48
*
FP_FACTOR
*
FP_FACTOR
)
#else
if
(
s
->
training_error
<
48
.
0
f
)
if
(
s
->
training_error
<
48
.
0
f
)
#endif
{
{
/* We are up and running */
/* We are up and running */
#if defined(SPANDSP_USE_FIXED_POINT)
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"Training succeeded at %dbps (constellation mismatch %d)
\n
"
,
s
->
bit_rate
,
s
->
training_error
);
#else
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"Training succeeded at %dbps (constellation mismatch %f)
\n
"
,
s
->
bit_rate
,
s
->
training_error
);
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"Training succeeded at %dbps (constellation mismatch %f)
\n
"
,
s
->
bit_rate
,
s
->
training_error
);
#endif
report_status_change
(
s
,
SIG_STATUS_TRAINING_SUCCEEDED
);
report_status_change
(
s
,
SIG_STATUS_TRAINING_SUCCEEDED
);
/* Apply some lag to the carrier off condition, to ensure the last few bits get pushed through
/* Apply some lag to the carrier off condition, to ensure the last few bits get pushed through
the processing. */
the processing. */
...
@@ -812,12 +807,12 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
...
@@ -812,12 +807,12 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
}
}
else
else
{
{
/* Training has failed */
/* Training has failed. Park this modem */
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"Training failed (constellation mismatch %f)
\n
"
,
s
->
training_error
);
/* Park this modem */
#if defined(SPANDSP_USE_FIXED_POINT)
#if defined(SPANDSP_USE_FIXED_POINT)
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"Training failed (constellation mismatch %d)
\n
"
,
s
->
training_error
);
s
->
agc_scaling_save
=
0
;
s
->
agc_scaling_save
=
0
;
#else
#else
span_log
(
&
s
->
logging
,
SPAN_LOG_FLOW
,
"Training failed (constellation mismatch %f)
\n
"
,
s
->
training_error
);
s
->
agc_scaling_save
=
0
.
0
f
;
s
->
agc_scaling_save
=
0
.
0
f
;
#endif
#endif
s
->
training_stage
=
TRAINING_STAGE_PARKED
;
s
->
training_stage
=
TRAINING_STAGE_PARKED
;
...
@@ -833,17 +828,7 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
...
@@ -833,17 +828,7 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
break
;
break
;
}
}
if
(
s
->
qam_report
)
if
(
s
->
qam_report
)
{
#if defined(SPANDSP_USE_FIXED_POINT)
z1
.
re
=
z
.
re
/
(
float
)
FP_FACTOR
;
z1
.
im
=
z
.
im
/
(
float
)
FP_FACTOR
;
zz
.
re
=
target
->
re
;
zz
.
im
=
target
->
im
;
s
->
qam_report
(
s
->
qam_user_data
,
&
z1
,
&
zz
,
s
->
constellation_state
);
#else
s
->
qam_report
(
s
->
qam_user_data
,
&
z
,
target
,
s
->
constellation_state
);
s
->
qam_report
(
s
->
qam_user_data
,
&
z
,
target
,
s
->
constellation_state
);
#endif
}
}
}
/*- End of function --------------------------------------------------------*/
/*- End of function --------------------------------------------------------*/
...
@@ -860,7 +845,7 @@ static __inline__ int signal_detect(v29_rx_state_t *s, int16_t amp)
...
@@ -860,7 +845,7 @@ static __inline__ int signal_detect(v29_rx_state_t *s, int16_t amp)
/* There could be overflow here, but it isn't a problem in practice */
/* There could be overflow here, but it isn't a problem in practice */
diff
=
x
-
s
->
last_sample
;
diff
=
x
-
s
->
last_sample
;
s
->
last_sample
=
x
;
s
->
last_sample
=
x
;
power
=
power_meter_update
(
&
(
s
->
power
)
,
diff
);
power
=
power_meter_update
(
&
s
->
power
,
diff
);
#if defined(IAXMODEM_STUFF)
#if defined(IAXMODEM_STUFF)
/* Quick power drop fudge */
/* Quick power drop fudge */
diff
=
abs
(
diff
);
diff
=
abs
(
diff
);
...
@@ -868,7 +853,7 @@ static __inline__ int signal_detect(v29_rx_state_t *s, int16_t amp)
...
@@ -868,7 +853,7 @@ static __inline__ int signal_detect(v29_rx_state_t *s, int16_t amp)
{
{
if
(
++
s
->
low_samples
>
120
)
if
(
++
s
->
low_samples
>
120
)
{
{
power_meter_init
(
&
(
s
->
power
)
,
4
);
power_meter_init
(
&
s
->
power
,
4
);
s
->
high_sample
=
0
;
s
->
high_sample
=
0
;
s
->
low_samples
=
0
;
s
->
low_samples
=
0
;
}
}
...
@@ -957,21 +942,20 @@ SPAN_DECLARE_NONSTD(int) v29_rx(v29_rx_state_t *s, const int16_t amp[], int len)
...
@@ -957,21 +942,20 @@ SPAN_DECLARE_NONSTD(int) v29_rx(v29_rx_state_t *s, const int16_t amp[], int len)
else
if
(
step
>
RX_PULSESHAPER_COEFF_SETS
-
1
)
else
if
(
step
>
RX_PULSESHAPER_COEFF_SETS
-
1
)
step
=
RX_PULSESHAPER_COEFF_SETS
-
1
;
step
=
RX_PULSESHAPER_COEFF_SETS
-
1
;
#if defined(SPANDSP_USE_FIXED_POINT)
#if defined(SPANDSP_USE_FIXED_POINT)
v
=
vec_circular_dot_prodi16
(
s
->
rrc_filter
,
rx_pulseshaper_re
[
step
],
V29_RX_FILTER_STEPS
,
s
->
rrc_filter_step
);
v
=
vec_circular_dot_prodi16
(
s
->
rrc_filter
,
rx_pulseshaper_re
[
step
],
V29_RX_FILTER_STEPS
,
s
->
rrc_filter_step
)
>>
15
;
sample
.
re
=
(
v
*
s
->
agc_scaling
)
>>
1
5
;
sample
.
re
=
(
v
*
s
->
agc_scaling
)
>>
1
0
;
#else
#else
v
=
vec_circular_dot_prodf
(
s
->
rrc_filter
,
rx_pulseshaper_re
[
step
],
V29_RX_FILTER_STEPS
,
s
->
rrc_filter_step
);
v
=
vec_circular_dot_prodf
(
s
->
rrc_filter
,
rx_pulseshaper_re
[
step
],
V29_RX_FILTER_STEPS
,
s
->
rrc_filter_step
);
sample
.
re
=
v
*
s
->
agc_scaling
;
sample
.
re
=
v
*
s
->
agc_scaling
;
#endif
#endif
/* Symbol timing synchronisation band edge filters */
/* Symbol timing synchronisation band edge filters */
#if defined(SPANDSP_USE_FIXED_POINT)
#if defined(SPANDSP_USE_FIXED_POINT)
/* Low Nyquist band edge filter */
/* Low Nyquist band edge filter */
v
=
((
s
->
symbol_sync_low
[
0
]
*
SYNC_LOW_BAND_EDGE_COEFF_0
)
>>
FP_SHIFT_FACTOR
)
+
((
s
->
symbol_sync_low
[
1
]
*
SYNC_LOW_BAND_EDGE_COEFF_1
)
>>
FP_SHIFT_FACTOR
)
+
sample
.
re
;
v
=
((
s
->
symbol_sync_low
[
0
]
*
SYNC_LOW_BAND_EDGE_COEFF_0
)
>>
10
)
+
((
s
->
symbol_sync_low
[
1
]
*
SYNC_LOW_BAND_EDGE_COEFF_1
)
>>
10
)
+
sample
.
re
;
s
->
symbol_sync_low
[
1
]
=
s
->
symbol_sync_low
[
0
];
s
->
symbol_sync_low
[
1
]
=
s
->
symbol_sync_low
[
0
];
s
->
symbol_sync_low
[
0
]
=
v
;
s
->
symbol_sync_low
[
0
]
=
v
;
/* High Nyquist band edge filter */
/* High Nyquist band edge filter */
v
=
((
s
->
symbol_sync_high
[
0
]
*
SYNC_HIGH_BAND_EDGE_COEFF_0
)
>>
FP_SHIFT_FACTOR
)
+
((
s
->
symbol_sync_high
[
1
]
*
SYNC_HIGH_BAND_EDGE_COEFF_1
)
>>
FP_SHIFT_FACTOR
)
+
sample
.
re
;
v
=
((
s
->
symbol_sync_high
[
0
]
*
SYNC_HIGH_BAND_EDGE_COEFF_0
)
>>
10
)
+
((
s
->
symbol_sync_high
[
1
]
*
SYNC_HIGH_BAND_EDGE_COEFF_1
)
>>
10
)
+
sample
.
re
;
s
->
symbol_sync_high
[
1
]
=
s
->
symbol_sync_high
[
0
];
s
->
symbol_sync_high
[
1
]
=
s
->
symbol_sync_high
[
0
];
s
->
symbol_sync_high
[
0
]
=
v
;
s
->
symbol_sync_high
[
0
]
=
v
;
#else
#else
...
@@ -991,10 +975,10 @@ SPAN_DECLARE_NONSTD(int) v29_rx(v29_rx_state_t *s, const int16_t amp[], int len)
...
@@ -991,10 +975,10 @@ SPAN_DECLARE_NONSTD(int) v29_rx(v29_rx_state_t *s, const int16_t amp[], int len)
/* Only AGC until we have locked down the setting. */
/* Only AGC until we have locked down the setting. */
#if defined(SPANDSP_USE_FIXED_POINT)
#if defined(SPANDSP_USE_FIXED_POINT)
if
(
s
->
agc_scaling_save
==
0
)
if
(
s
->
agc_scaling_save
==
0
)
s
->
agc_scaling
=
(
float
)
FP_FACTOR
*
32768
.
0
f
*
(
1
.
0
f
/
RX_PULSESHAPER_GAIN
)
*
5
.
0
f
*
0
.
25
f
/
sqrtf
(
power
);
s
->
agc_scaling
=
saturate16
(((
int32_t
)
(
1024
.
0
f
*
FP_FACTOR
*
1
.
25
f
))
/
fixed_sqrt32
(
power
)
);
#else
#else
if
(
s
->
agc_scaling_save
==
0
.
0
f
)
if
(
s
->
agc_scaling_save
==
0
.
0
f
)
s
->
agc_scaling
=
(
1
.
0
f
/
RX_PULSESHAPER_GAIN
)
*
5
.
0
f
*
0
.
25
f
/
sqrtf
(
power
);
s
->
agc_scaling
=
(
1
.
0
f
/
RX_PULSESHAPER_GAIN
)
*
1
.
25
f
/
sqrtf
(
power
);
#endif
#endif
/* Pulse shape while still at the carrier frequency, using a quadrature
/* Pulse shape while still at the carrier frequency, using a quadrature
pair of filters. This results in a properly bandpass filtered complex
pair of filters. This results in a properly bandpass filtered complex
...
@@ -1002,11 +986,11 @@ SPAN_DECLARE_NONSTD(int) v29_rx(v29_rx_state_t *s, const int16_t amp[], int len)
...
@@ -1002,11 +986,11 @@ SPAN_DECLARE_NONSTD(int) v29_rx(v29_rx_state_t *s, const int16_t amp[], int len)
No further filtering, to remove mixer harmonics, is needed. */
No further filtering, to remove mixer harmonics, is needed. */
s
->
eq_put_step
+=
RX_PULSESHAPER_COEFF_SETS
*
10
/
(
3
*
2
);
s
->
eq_put_step
+=
RX_PULSESHAPER_COEFF_SETS
*
10
/
(
3
*
2
);
#if defined(SPANDSP_USE_FIXED_POINT)
#if defined(SPANDSP_USE_FIXED_POINT)
v
=
vec_circular_dot_prodi16
(
s
->
rrc_filter
,
rx_pulseshaper_im
[
step
],
V29_RX_FILTER_STEPS
,
s
->
rrc_filter_step
);
v
=
vec_circular_dot_prodi16
(
s
->
rrc_filter
,
rx_pulseshaper_im
[
step
],
V29_RX_FILTER_STEPS
,
s
->
rrc_filter_step
)
>>
15
;
sample
.
im
=
(
v
*
s
->
agc_scaling
)
>>
1
5
;
sample
.
im
=
(
v
*
s
->
agc_scaling
)
>>
1
0
;
z
=
dds_lookup_complexi16
(
s
->
carrier_phase
);
z
=
dds_lookup_complexi16
(
s
->
carrier_phase
);
zz
.
re
=
((
int32_t
)
sample
.
re
*
(
int32_t
)
z
.
re
-
(
int32_t
)
sample
.
im
*
(
int32_t
)
z
.
im
)
>>
15
;
zz
.
re
=
((
int32_t
)
sample
.
re
*
z
.
re
-
(
int32_t
)
sample
.
im
*
z
.
im
)
>>
15
;
zz
.
im
=
((
int32_t
)
-
sample
.
re
*
(
int32_t
)
z
.
im
-
(
int32_t
)
sample
.
im
*
(
int32_t
)
z
.
re
)
>>
15
;
zz
.
im
=
((
int32_t
)
-
sample
.
re
*
z
.
im
-
(
int32_t
)
sample
.
im
*
z
.
re
)
>>
15
;
#else
#else
v
=
vec_circular_dot_prodf
(
s
->
rrc_filter
,
rx_pulseshaper_im
[
step
],
V29_RX_FILTER_STEPS
,
s
->
rrc_filter_step
);
v
=
vec_circular_dot_prodf
(
s
->
rrc_filter
,
rx_pulseshaper_im
[
step
],
V29_RX_FILTER_STEPS
,
s
->
rrc_filter_step
);
sample
.
im
=
v
*
s
->
agc_scaling
;
sample
.
im
=
v
*
s
->
agc_scaling
;
...
@@ -1115,7 +1099,7 @@ SPAN_DECLARE(int) v29_rx_restart(v29_rx_state_t *s, int bit_rate, int old_train)
...
@@ -1115,7 +1099,7 @@ SPAN_DECLARE(int) v29_rx_restart(v29_rx_state_t *s, int bit_rate, int old_train)
s
->
carrier_phase
=
0
;
s
->
carrier_phase
=
0
;
power_meter_init
(
&
(
s
->
power
)
,
4
);
power_meter_init
(
&
s
->
power
,
4
);
s
->
constellation_state
=
0
;
s
->
constellation_state
=
0
;
...
@@ -1131,10 +1115,10 @@ SPAN_DECLARE(int) v29_rx_restart(v29_rx_state_t *s, int bit_rate, int old_train)
...
@@ -1131,10 +1115,10 @@ SPAN_DECLARE(int) v29_rx_restart(v29_rx_state_t *s, int bit_rate, int old_train)
equalizer_reset
(
s
);
equalizer_reset
(
s
);
#if defined(SPANDSP_USE_FIXED_POINT)
#if defined(SPANDSP_USE_FIXED_POINT)
s
->
agc_scaling_save
=
0
;
s
->
agc_scaling_save
=
0
;
s
->
agc_scaling
=
(
float
)
FP_FACTOR
*
32768
.
0
f
*
0
.
0017
f
/
RX_PULSESHAPER_GAIN
;
s
->
agc_scaling
=
(
float
)
(
1024
.
0
f
*
FP_FACTOR
)
*
1
.
25
f
/
735
.
0
f
;
#else
#else
s
->
agc_scaling_save
=
0
.
0
f
;
s
->
agc_scaling_save
=
0
.
0
f
;
s
->
agc_scaling
=
0
.
0017
f
/
RX_PULSESHAPER_GAIN
;
s
->
agc_scaling
=
(
1
.
0
f
/
RX_PULSESHAPER_GAIN
)
*
1
.
25
f
/
735
.
0
f
;
#endif
#endif
}
}
#if defined(SPANDSP_USE_FIXED_POINT)
#if defined(SPANDSP_USE_FIXED_POINT)
...
@@ -1168,7 +1152,6 @@ SPAN_DECLARE(int) v29_rx_restart(v29_rx_state_t *s, int bit_rate, int old_train)
...
@@ -1168,7 +1152,6 @@ SPAN_DECLARE(int) v29_rx_restart(v29_rx_state_t *s, int bit_rate, int old_train)
s
->
baud_half
=
0
;
s
->
baud_half
=
0
;
s
->
total_baud_timing_correction
=
0
;
s
->
total_baud_timing_correction
=
0
;
return
0
;
return
0
;
}
}
/*- End of function --------------------------------------------------------*/
/*- End of function --------------------------------------------------------*/
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论