update to snapshot spandsp-20090421
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@13086 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
parent
900f820810
commit
4281523a8f
|
@ -16,7 +16,7 @@
|
|||
## License along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
##
|
||||
## $Id: Makefile.am,v 1.45 2008/11/28 12:41:25 steveu Exp $
|
||||
## $Id: Makefile.am,v 1.46 2009/03/19 14:13:12 steveu Exp $
|
||||
|
||||
AM_CFLAGS = $(COMP_VENDOR_CFLAGS)
|
||||
AM_LDFLAGS = $(COMP_VENDOR_LDFLAGS)
|
||||
|
@ -42,7 +42,7 @@ EXTRA_DIST = autogen.sh \
|
|||
debian/compat \
|
||||
debian/control \
|
||||
debian/copyright \
|
||||
debian/libspandsp5.install \
|
||||
debian/libspandsp6.install \
|
||||
debian/libspandsp-dev.install \
|
||||
debian/libspandsp-doc.install \
|
||||
debian/rules \
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
# License along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#
|
||||
# $Id: configure.ac,v 1.66 2009/02/10 17:20:31 steveu Exp $
|
||||
# $Id: configure.ac,v 1.67 2009/03/28 17:14:53 steveu Exp $
|
||||
|
||||
# @start 1
|
||||
|
||||
|
@ -271,7 +271,7 @@ AC_CHECK_LIB([xml2], [xmlParseFile], [AC_DEFINE([HAVE_LIBXML2], [1], [Define to
|
|||
if test -n "$enable_tests" ; then
|
||||
AC_LANG([C])
|
||||
AC_CHECK_LIB([audiofile], [afOpenFile], TESTLIBS="$TESTLIBS -laudiofile", AC_MSG_ERROR("Can't make tests without libaudiofile (does your system require a libaudiofile-devel package?)"))
|
||||
AC_CHECK_LIB([fftw3], [fftw_plan_dft_1d], TESTLIBS="$TESTLIBS -lfftw3", [AC_CHECK_LIB([fftw], [fftw_create_plan], TESTLIBS="$TESTLIBS -lfftw")])
|
||||
AC_CHECK_LIB([fftw3], [fftw_plan_dft_1d], TESTLIBS="$TESTLIBS -lfftw3", [AC_CHECK_LIB([fftw], [fftw_create_plan], TESTLIBS="$TESTLIBS -lfftw", AC_MSG_ERROR("Can't make tests without FFTW 2 or 3 (does your system require an fftw?-devel package?)"))])
|
||||
AC_CHECK_LIB([pthread], [pthread_attr_init], TESTLIBS="$TESTLIBS -lpthread")
|
||||
AC_CHECK_LIB([dl], [dlopen], TESTLIBS="$TESTLIBS -ldl")
|
||||
AC_CHECK_LIB([Xft], [XftFontOpen], TESTLIBS="$TESTLIBS -lXft",, $TESTLIBS)
|
||||
|
|
|
@ -1,3 +1,13 @@
|
|||
spandsp (0.0.6~pre7-1) unstable; urgency=low
|
||||
|
||||
[ Steve Underwood ]
|
||||
* New upstream release.
|
||||
* Fixed upstream file name for get-orig-source.
|
||||
* Updates to 64bit archs support
|
||||
* Removal of obsoleted files
|
||||
|
||||
-- Steve Underwood <steveu@coppice.org> Sat, 14 Mar 2009 09:23:36 +0100
|
||||
|
||||
spandsp (0.0.5~pre2-1) unstable; urgency=low
|
||||
|
||||
[ Massimo Cetra ]
|
||||
|
|
|
@ -8,7 +8,7 @@ Standards-Version: 3.7.2
|
|||
XS-Vcs-Svn: svn://svn.debian.org/pkg-voip/
|
||||
XS-Vcs-Browser: http://svn.debian.org/wsvn/pkg-voip/
|
||||
|
||||
Package: libspandsp5
|
||||
Package: libspandsp6
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}
|
||||
Conflicts: libspandsp0, libspandsp1, libspandsp2
|
||||
|
@ -22,7 +22,7 @@ Description: Telephony signal processing library
|
|||
Package: libspandsp-dev
|
||||
Section: libdevel
|
||||
Architecture: any
|
||||
Depends: libspandsp5 (= ${Source-Version}), libtiff4-dev, libjpeg62-dev
|
||||
Depends: libspandsp6 (= ${Source-Version}), libtiff4-dev, libjpeg62-dev
|
||||
Description: Telephony signal processing library
|
||||
This is a low-level signal processing library that modulate and demodulate
|
||||
signals commonly used in telephony, such as the "noise" generated by a
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
debian/tmp/usr/lib*/libspandsp.so.1.*
|
||||
debian/tmp/usr/lib*/libspandsp.so.1
|
|
@ -0,0 +1,2 @@
|
|||
debian/tmp/usr/lib*/libspandsp.so.2.*
|
||||
debian/tmp/usr/lib*/libspandsp.so.2
|
|
@ -53,16 +53,6 @@ CREATE_SUBDIRS = NO
|
|||
|
||||
OUTPUT_LANGUAGE = English
|
||||
|
||||
# This tag can be used to specify the encoding used in the generated output.
|
||||
# The encoding is not always determined by the language that is chosen,
|
||||
# but also whether or not the output is meant for Windows or non-Windows users.
|
||||
# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
|
||||
# forces the Windows encoding (this is the default for the Windows binary),
|
||||
# whereas setting the tag to NO uses a Unix-style encoding (the default for
|
||||
# all platforms other than Windows).
|
||||
|
||||
USE_WINDOWS_ENCODING = YES
|
||||
|
||||
# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
|
||||
# include brief member descriptions after the members that are listed in
|
||||
# the file and class documentation (similar to JavaDoc).
|
||||
|
@ -148,13 +138,6 @@ JAVADOC_AUTOBRIEF = NO
|
|||
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
|
||||
# If the DETAILS_AT_TOP tag is set to YES then Doxygen
|
||||
# will output the detailed description near the top, like JavaDoc.
|
||||
# If set to NO, the detailed description appears after the member
|
||||
# documentation.
|
||||
|
||||
DETAILS_AT_TOP = NO
|
||||
|
||||
# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
|
||||
# member inherits the documentation from any documented member that it
|
||||
# re-implements.
|
||||
|
@ -963,7 +946,7 @@ ENABLE_PREPROCESSING = YES
|
|||
# compilation will be performed. Macro expansion can be done in a controlled
|
||||
# way by setting EXPAND_ONLY_PREDEF to YES.
|
||||
|
||||
MACRO_EXPANSION = NO
|
||||
MACRO_EXPANSION = YES
|
||||
|
||||
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
|
||||
# then the macro expansion is limited to the macros specified with the
|
||||
|
@ -997,7 +980,7 @@ INCLUDE_FILE_PATTERNS =
|
|||
# undefined via #undef or recursively expanded use the := operator
|
||||
# instead of the = operator.
|
||||
|
||||
PREDEFINED =
|
||||
PREDEFINED = SPAN_DECLARE(x)=x
|
||||
|
||||
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
|
||||
# this tag can be used to specify a list of macro names that should be expanded.
|
||||
|
@ -1164,22 +1147,6 @@ DOT_PATH =
|
|||
|
||||
DOTFILE_DIRS =
|
||||
|
||||
# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
|
||||
# (in pixels) of the graphs generated by dot. If a graph becomes larger than
|
||||
# this value, doxygen will try to truncate the graph, so that it fits within
|
||||
# the specified constraint. Beware that most browsers cannot cope with very
|
||||
# large images.
|
||||
|
||||
MAX_DOT_GRAPH_WIDTH = 1024
|
||||
|
||||
# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
|
||||
# (in pixels) of the graphs generated by dot. If a graph becomes larger than
|
||||
# this value, doxygen will try to truncate the graph, so that it fits within
|
||||
# the specified constraint. Beware that most browsers cannot cope with very
|
||||
# large images.
|
||||
|
||||
MAX_DOT_GRAPH_HEIGHT = 1024
|
||||
|
||||
# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
|
||||
# graphs generated by dot. A depth value of 3 means that only nodes reachable
|
||||
# from the root by following a path via at most 3 edges will be shown. Nodes
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
## License along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
##
|
||||
## $Id: Makefile.am,v 1.128 2009/03/01 12:49:28 steveu Exp $
|
||||
## $Id: Makefile.am,v 1.130 2009/04/16 13:09:40 steveu Exp $
|
||||
|
||||
AM_CFLAGS = $(COMP_VENDOR_CFLAGS)
|
||||
AM_LDFLAGS = $(COMP_VENDOR_LDFLAGS)
|
||||
|
@ -126,6 +126,7 @@ libspandsp_la_SOURCES = adsi.c \
|
|||
tone_generate.c \
|
||||
v17rx.c \
|
||||
v17tx.c \
|
||||
v18.c \
|
||||
v22bis_rx.c \
|
||||
v22bis_tx.c \
|
||||
v27ter_rx.c \
|
||||
|
@ -205,6 +206,7 @@ nobase_include_HEADERS = spandsp/adsi.h \
|
|||
spandsp/tone_generate.h \
|
||||
spandsp/v17rx.h \
|
||||
spandsp/v17tx.h \
|
||||
spandsp/v18.h \
|
||||
spandsp/v22bis.h \
|
||||
spandsp/v27ter_rx.h \
|
||||
spandsp/v27ter_tx.h \
|
||||
|
@ -241,6 +243,7 @@ nobase_include_HEADERS = spandsp/adsi.h \
|
|||
spandsp/private/queue.h \
|
||||
spandsp/private/schedule.h \
|
||||
spandsp/private/sig_tone.h \
|
||||
spandsp/private/silence_gen.h \
|
||||
spandsp/private/super_tone_rx.h \
|
||||
spandsp/private/super_tone_tx.h \
|
||||
spandsp/private/t30.h \
|
||||
|
@ -255,6 +258,7 @@ nobase_include_HEADERS = spandsp/adsi.h \
|
|||
spandsp/private/tone_generate.h \
|
||||
spandsp/private/v17rx.h \
|
||||
spandsp/private/v17tx.h \
|
||||
spandsp/private/v18.h \
|
||||
spandsp/private/v22bis.h \
|
||||
spandsp/private/v27ter_rx.h \
|
||||
spandsp/private/v27ter_tx.h \
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: adsi.c,v 1.70 2009/02/10 13:06:46 steveu Exp $
|
||||
* $Id: adsi.c,v 1.76 2009/04/12 09:12:10 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -69,14 +69,19 @@
|
|||
#include "spandsp/private/dtmf.h"
|
||||
#include "spandsp/private/adsi.h"
|
||||
|
||||
/*! The baudot code to shift from alpha to digits and symbols */
|
||||
#define BAUDOT_FIGURE_SHIFT 0x1B
|
||||
/*! The baudot code to shift from digits and symbols to alpha */
|
||||
#define BAUDOT_LETTER_SHIFT 0x1F
|
||||
|
||||
#define SOH 0x01
|
||||
#define STX 0x02
|
||||
#define ETX 0x03
|
||||
#define DLE 0x10
|
||||
#define SUB 0x1A
|
||||
enum
|
||||
{
|
||||
SOH = 0x01,
|
||||
STX = 0x02,
|
||||
ETX = 0x03,
|
||||
DLE = 0x10,
|
||||
SUB = 0x1A
|
||||
};
|
||||
|
||||
static uint16_t adsi_encode_baudot(adsi_tx_state_t *s, uint8_t ch);
|
||||
static uint8_t adsi_decode_baudot(adsi_rx_state_t *s, uint8_t ch);
|
||||
|
@ -183,18 +188,16 @@ static void adsi_rx_put_bit(void *user_data, int bit)
|
|||
if (bit < 0)
|
||||
{
|
||||
/* Special conditions */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "ADSI signal status is %s (%d)\n", signal_status_to_str(bit), bit);
|
||||
switch (bit)
|
||||
{
|
||||
case SIG_STATUS_CARRIER_UP:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Carrier up.\n");
|
||||
s->consecutive_ones = 0;
|
||||
s->bit_pos = 0;
|
||||
s->in_progress = 0;
|
||||
s->msg_len = 0;
|
||||
s->baudot_shift = 0;
|
||||
break;
|
||||
case SIG_STATUS_CARRIER_DOWN:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Carrier down.\n");
|
||||
break;
|
||||
default:
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "Unexpected special put bit value - %d!\n", bit);
|
||||
|
@ -303,10 +306,11 @@ static void adsi_tdd_put_async_byte(void *user_data, int byte)
|
|||
uint8_t octet;
|
||||
|
||||
s = (adsi_rx_state_t *) user_data;
|
||||
//printf("Rx bit %x\n", bit);
|
||||
if (byte < 0)
|
||||
{
|
||||
/* Special conditions */
|
||||
printf("Status is %s (%d)\n", signal_status_to_str(byte), byte);
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "ADSI signal status is %s (%d)\n", signal_status_to_str(byte), byte);
|
||||
switch (byte)
|
||||
{
|
||||
case SIG_STATUS_CARRIER_UP:
|
||||
|
@ -314,7 +318,6 @@ static void adsi_tdd_put_async_byte(void *user_data, int byte)
|
|||
s->bit_pos = 0;
|
||||
s->in_progress = 0;
|
||||
s->msg_len = 0;
|
||||
s->baudot_shift = 0;
|
||||
break;
|
||||
case SIG_STATUS_CARRIER_DOWN:
|
||||
if (s->msg_len > 0)
|
||||
|
@ -330,7 +333,7 @@ static void adsi_tdd_put_async_byte(void *user_data, int byte)
|
|||
}
|
||||
return;
|
||||
}
|
||||
if ((octet = adsi_decode_baudot(s, (uint8_t) byte)))
|
||||
if ((octet = adsi_decode_baudot(s, (uint8_t) (byte & 0x1F))))
|
||||
s->msg[s->msg_len++] = octet;
|
||||
if (s->msg_len >= 256)
|
||||
{
|
||||
|
@ -393,7 +396,7 @@ static void start_tx(adsi_tx_state_t *s)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) adsi_rx(adsi_rx_state_t *s, const int16_t *amp, int len)
|
||||
SPAN_DECLARE(int) adsi_rx(adsi_rx_state_t *s, const int16_t amp[], int len)
|
||||
{
|
||||
switch (s->standard)
|
||||
{
|
||||
|
@ -439,8 +442,9 @@ SPAN_DECLARE(adsi_rx_state_t *) adsi_rx_init(adsi_rx_state_t *s,
|
|||
dtmf_rx_init(&(s->dtmfrx), adsi_rx_dtmf, s);
|
||||
break;
|
||||
case ADSI_STANDARD_TDD:
|
||||
fsk_rx_init(&(s->fskrx), &preset_fsk_specs[FSK_WEITBRECHT], FALSE, async_rx_put_bit, &(s->asyncrx));
|
||||
async_rx_init(&(s->asyncrx), 5, ASYNC_PARITY_NONE, 2, TRUE, adsi_tdd_put_async_byte, s);
|
||||
/* TDD uses 5 bit data, no parity and 1.5 stop bits. We scan for the first stop bit, and
|
||||
ride over the fraction. */
|
||||
fsk_rx_init(&(s->fskrx), &preset_fsk_specs[FSK_WEITBRECHT], 7, adsi_tdd_put_async_byte, s);
|
||||
break;
|
||||
}
|
||||
s->standard = standard;
|
||||
|
@ -462,7 +466,7 @@ SPAN_DECLARE(int) adsi_rx_free(adsi_rx_state_t *s)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) adsi_tx(adsi_tx_state_t *s, int16_t *amp, int max_len)
|
||||
SPAN_DECLARE(int) adsi_tx(adsi_tx_state_t *s, int16_t amp[], int max_len)
|
||||
{
|
||||
int len;
|
||||
int lenx;
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: at_interpreter.c,v 1.36 2009/02/10 13:06:46 steveu Exp $
|
||||
* $Id: at_interpreter.c,v 1.37 2009/03/23 14:17:42 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -52,6 +52,8 @@
|
|||
#include "spandsp/async.h"
|
||||
#include "spandsp/hdlc.h"
|
||||
#include "spandsp/fsk.h"
|
||||
#include "spandsp/super_tone_rx.h"
|
||||
#include "spandsp/fax_modems.h"
|
||||
|
||||
#include "spandsp/at_interpreter.h"
|
||||
|
||||
|
@ -111,18 +113,6 @@ static const char *revision = VERSION;
|
|||
#define DLE 0x10
|
||||
#define SUB 0x1A
|
||||
|
||||
/* BEWARE: right now this must match up with a list in the T.31 code. */
|
||||
enum
|
||||
{
|
||||
T31_NONE = -1,
|
||||
T31_FLUSH = 0,
|
||||
T31_SILENCE_TX,
|
||||
T31_SILENCE_RX,
|
||||
T31_CED_TONE,
|
||||
T31_CNG_TONE,
|
||||
T31_NOCNG_TONE,
|
||||
};
|
||||
|
||||
static const char *at_response_codes[] =
|
||||
{
|
||||
"OK",
|
||||
|
@ -239,7 +229,7 @@ SPAN_DECLARE(void) at_call_event(at_state_t *s, int event)
|
|||
{
|
||||
/* FAX modem connection */
|
||||
at_set_at_rx_mode(s, AT_MODE_DELIVERY);
|
||||
at_modem_control(s, AT_MODEM_CONTROL_RESTART, (void *) T31_CED_TONE);
|
||||
at_modem_control(s, AT_MODEM_CONTROL_RESTART, (void *) FAX_MODEM_CED_TONE);
|
||||
}
|
||||
break;
|
||||
case AT_CALL_EVENT_CONNECTED:
|
||||
|
@ -256,9 +246,9 @@ SPAN_DECLARE(void) at_call_event(at_state_t *s, int event)
|
|||
/* FAX modem connection */
|
||||
at_set_at_rx_mode(s, AT_MODE_DELIVERY);
|
||||
if (s->silent_dial)
|
||||
at_modem_control(s, AT_MODEM_CONTROL_RESTART, (void *) T31_NOCNG_TONE);
|
||||
at_modem_control(s, AT_MODEM_CONTROL_RESTART, (void *) FAX_MODEM_NOCNG_TONE);
|
||||
else
|
||||
at_modem_control(s, AT_MODEM_CONTROL_RESTART, (void *) T31_CNG_TONE);
|
||||
at_modem_control(s, AT_MODEM_CONTROL_RESTART, (void *) FAX_MODEM_CNG_TONE);
|
||||
s->dte_is_waiting = TRUE;
|
||||
}
|
||||
break;
|
||||
|
@ -931,7 +921,7 @@ static const char *at_cmd_H(at_state_t *s, const char *t)
|
|||
if (s->at_rx_mode != AT_MODE_ONHOOK_COMMAND && s->at_rx_mode != AT_MODE_OFFHOOK_COMMAND)
|
||||
{
|
||||
/* Push out the last of the audio (probably by sending a short silence). */
|
||||
at_modem_control(s, AT_MODEM_CONTROL_RESTART, (void *) T31_FLUSH);
|
||||
at_modem_control(s, AT_MODEM_CONTROL_RESTART, (void *) FAX_MODEM_FLUSH);
|
||||
s->do_hangup = TRUE;
|
||||
at_set_at_rx_mode(s, AT_MODE_CONNECTED);
|
||||
return (const char *) -1;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: bell_r2_mf.c,v 1.38 2009/02/10 13:06:46 steveu Exp $
|
||||
* $Id: bell_r2_mf.c,v 1.39 2009/04/11 18:11:19 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -67,6 +67,9 @@
|
|||
|
||||
#define ms_to_samples(t) (((t)*SAMPLE_RATE)/1000)
|
||||
|
||||
/*!
|
||||
MF tone descriptor.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int f1; /* First freq */
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: bert.c,v 1.32 2009/02/10 13:06:46 steveu Exp $
|
||||
* $Id: bert.c,v 1.33 2009/04/14 16:04:53 steveu Exp $
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
|
@ -44,6 +44,8 @@
|
|||
#include "spandsp/private/logging.h"
|
||||
#include "spandsp/private/bert.h"
|
||||
|
||||
#define MEASUREMENT_STEP 100
|
||||
|
||||
static const char *qbf = "VoyeZ Le BricK GeanT QuE J'ExaminE PreS Du WharF 123 456 7890 + - * : = $ % ( )"
|
||||
"ThE QuicK BrowN FoX JumpS OveR ThE LazY DoG 123 456 7890 + - * : = $ % ( )";
|
||||
|
||||
|
@ -80,53 +82,53 @@ SPAN_DECLARE(int) bert_get_bit(bert_state_t *s)
|
|||
{
|
||||
int bit;
|
||||
|
||||
if (s->limit && s->tx_bits >= s->limit)
|
||||
if (s->limit && s->tx.bits >= s->limit)
|
||||
return SIG_STATUS_END_OF_DATA;
|
||||
bit = 0;
|
||||
switch (s->pattern_class)
|
||||
{
|
||||
case 0:
|
||||
bit = s->tx_reg & 1;
|
||||
s->tx_reg = (s->tx_reg >> 1) | ((s->tx_reg & 1) << s->shift2);
|
||||
bit = s->tx.reg & 1;
|
||||
s->tx.reg = (s->tx.reg >> 1) | ((s->tx.reg & 1) << s->shift2);
|
||||
break;
|
||||
case 1:
|
||||
bit = s->tx_reg & 1;
|
||||
s->tx_reg = (s->tx_reg >> 1) | (((s->tx_reg ^ (s->tx_reg >> s->shift)) & 1) << s->shift2);
|
||||
bit = s->tx.reg & 1;
|
||||
s->tx.reg = (s->tx.reg >> 1) | (((s->tx.reg ^ (s->tx.reg >> s->shift)) & 1) << s->shift2);
|
||||
if (s->max_zeros)
|
||||
{
|
||||
/* This generator suppresses runs >s->max_zeros */
|
||||
if (bit)
|
||||
{
|
||||
if (++s->tx_zeros > s->max_zeros)
|
||||
if (++s->tx.zeros > s->max_zeros)
|
||||
{
|
||||
s->tx_zeros = 0;
|
||||
s->tx.zeros = 0;
|
||||
bit ^= 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s->tx_zeros = 0;
|
||||
s->tx.zeros = 0;
|
||||
}
|
||||
}
|
||||
bit ^= s->invert;
|
||||
break;
|
||||
case 2:
|
||||
if (s->tx_step_bit == 0)
|
||||
if (s->tx.step_bit == 0)
|
||||
{
|
||||
s->tx_step_bit = 7;
|
||||
s->tx_reg = qbf[s->tx_step++];
|
||||
if (s->tx_reg == 0)
|
||||
s->tx.step_bit = 7;
|
||||
s->tx.reg = qbf[s->tx.step++];
|
||||
if (s->tx.reg == 0)
|
||||
{
|
||||
s->tx_reg = 'V';
|
||||
s->tx_step = 1;
|
||||
s->tx.reg = 'V';
|
||||
s->tx.step = 1;
|
||||
}
|
||||
}
|
||||
bit = s->tx_reg & 1;
|
||||
s->tx_reg >>= 1;
|
||||
s->tx_step_bit--;
|
||||
bit = s->tx.reg & 1;
|
||||
s->tx.reg >>= 1;
|
||||
s->tx.step_bit--;
|
||||
break;
|
||||
}
|
||||
s->tx_bits++;
|
||||
s->tx.bits++;
|
||||
return bit;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -192,58 +194,58 @@ SPAN_DECLARE(void) bert_put_bit(bert_state_t *s, int bit)
|
|||
return;
|
||||
}
|
||||
bit = (bit & 1) ^ s->invert;
|
||||
s->rx_bits++;
|
||||
s->rx.bits++;
|
||||
switch (s->pattern_class)
|
||||
{
|
||||
case 0:
|
||||
if (s->resync)
|
||||
if (s->rx.resync)
|
||||
{
|
||||
s->rx_reg = (s->rx_reg >> 1) | (bit << s->shift2);
|
||||
s->ref_reg = (s->ref_reg >> 1) | ((s->ref_reg & 1) << s->shift2);
|
||||
if (s->rx_reg == s->ref_reg)
|
||||
s->rx.reg = (s->rx.reg >> 1) | (bit << s->shift2);
|
||||
s->rx.ref_reg = (s->rx.ref_reg >> 1) | ((s->rx.ref_reg & 1) << s->shift2);
|
||||
if (s->rx.reg == s->rx.ref_reg)
|
||||
{
|
||||
if (++s->resync > s->resync_time)
|
||||
if (++s->rx.resync > s->resync_time)
|
||||
{
|
||||
s->resync = 0;
|
||||
s->rx.resync = 0;
|
||||
if (s->reporter)
|
||||
s->reporter(s->user_data, BERT_REPORT_SYNCED, &s->results);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s->resync = 2;
|
||||
s->ref_reg = s->master_reg;
|
||||
s->rx.resync = 2;
|
||||
s->rx.ref_reg = s->rx.master_reg;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s->results.total_bits++;
|
||||
if ((bit ^ s->ref_reg) & 1)
|
||||
if ((bit ^ s->rx.ref_reg) & 1)
|
||||
s->results.bad_bits++;
|
||||
s->ref_reg = (s->ref_reg >> 1) | ((s->ref_reg & 1) << s->shift2);
|
||||
s->rx.ref_reg = (s->rx.ref_reg >> 1) | ((s->rx.ref_reg & 1) << s->shift2);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (s->resync)
|
||||
if (s->rx.resync)
|
||||
{
|
||||
/* If we get a reasonable period for which we correctly predict the
|
||||
next bit, we must be in sync. */
|
||||
/* Don't worry about max. zeros tests when resyncing.
|
||||
It might just extend the resync time a little. Trying
|
||||
to include the test might affect robustness. */
|
||||
if (bit == (int) ((s->rx_reg >> s->shift) & 1))
|
||||
if (bit == (int) ((s->rx.reg >> s->shift) & 1))
|
||||
{
|
||||
if (++s->resync > s->resync_time)
|
||||
if (++s->rx.resync > s->resync_time)
|
||||
{
|
||||
s->resync = 0;
|
||||
s->rx.resync = 0;
|
||||
if (s->reporter)
|
||||
s->reporter(s->user_data, BERT_REPORT_SYNCED, &s->results);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s->resync = 2;
|
||||
s->rx_reg ^= s->mask;
|
||||
s->rx.resync = 2;
|
||||
s->rx.reg ^= s->mask;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -252,73 +254,73 @@ SPAN_DECLARE(void) bert_put_bit(bert_state_t *s, int bit)
|
|||
if (s->max_zeros)
|
||||
{
|
||||
/* This generator suppresses runs >s->max_zeros */
|
||||
if ((s->rx_reg & s->mask))
|
||||
if ((s->rx.reg & s->mask))
|
||||
{
|
||||
if (++s->rx_zeros > s->max_zeros)
|
||||
if (++s->rx.zeros > s->max_zeros)
|
||||
{
|
||||
s->rx_zeros = 0;
|
||||
s->rx.zeros = 0;
|
||||
bit ^= 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s->rx_zeros = 0;
|
||||
s->rx.zeros = 0;
|
||||
}
|
||||
}
|
||||
if (bit != (int) ((s->rx_reg >> s->shift) & 1))
|
||||
if (bit != (int) ((s->rx.reg >> s->shift) & 1))
|
||||
{
|
||||
s->results.bad_bits++;
|
||||
s->resync_bad_bits++;
|
||||
s->rx.resync_bad_bits++;
|
||||
s->decade_bad[2][s->decade_ptr[2]]++;
|
||||
}
|
||||
if (--s->step <= 0)
|
||||
if (--s->rx.measurement_step <= 0)
|
||||
{
|
||||
/* Every hundred bits we need to do the error rate measurement */
|
||||
s->step = 100;
|
||||
s->rx.measurement_step = MEASUREMENT_STEP;
|
||||
assess_error_rate(s);
|
||||
}
|
||||
if (--s->resync_cnt <= 0)
|
||||
if (--s->rx.resync_cnt <= 0)
|
||||
{
|
||||
/* Check if there were enough bad bits during this period to
|
||||
justify a resync. */
|
||||
if (s->resync_bad_bits >= (s->resync_len*s->resync_percent)/100)
|
||||
if (s->rx.resync_bad_bits >= (s->rx.resync_len*s->rx.resync_percent)/100)
|
||||
{
|
||||
s->resync = 1;
|
||||
s->rx.resync = 1;
|
||||
s->results.resyncs++;
|
||||
if (s->reporter)
|
||||
s->reporter(s->user_data, BERT_REPORT_UNSYNCED, &s->results);
|
||||
}
|
||||
s->resync_cnt = s->resync_len;
|
||||
s->resync_bad_bits = 0;
|
||||
s->rx.resync_cnt = s->rx.resync_len;
|
||||
s->rx.resync_bad_bits = 0;
|
||||
}
|
||||
}
|
||||
s->rx_reg = (s->rx_reg >> 1) | (((s->rx_reg ^ (s->rx_reg >> s->shift)) & 1) << s->shift2);
|
||||
s->rx.reg = (s->rx.reg >> 1) | (((s->rx.reg ^ (s->rx.reg >> s->shift)) & 1) << s->shift2);
|
||||
break;
|
||||
case 2:
|
||||
s->rx_reg = (s->rx_reg >> 1) | (bit << 6);
|
||||
s->rx.reg = (s->rx.reg >> 1) | (bit << 6);
|
||||
/* TODO: There is no mechanism for synching yet. This only works if things start in sync. */
|
||||
if (++s->rx_step_bit == 7)
|
||||
if (++s->rx.step_bit == 7)
|
||||
{
|
||||
s->rx_step_bit = 0;
|
||||
if ((int) s->rx_reg != qbf[s->rx_step])
|
||||
s->rx.step_bit = 0;
|
||||
if ((int) s->rx.reg != qbf[s->rx.step])
|
||||
{
|
||||
/* We need to work out the number of actual bad bits here. We need to look at the
|
||||
error rate, and see it a resync is needed. etc. */
|
||||
s->results.bad_bits++;
|
||||
}
|
||||
if (qbf[++s->rx_step] == '\0')
|
||||
s->rx_step = 0;
|
||||
if (qbf[++s->rx.step] == '\0')
|
||||
s->rx.step = 0;
|
||||
}
|
||||
s->results.total_bits++;
|
||||
break;
|
||||
}
|
||||
if (s->report_frequency > 0)
|
||||
{
|
||||
if (--s->report_countdown <= 0)
|
||||
if (--s->rx.report_countdown <= 0)
|
||||
{
|
||||
if (s->reporter)
|
||||
s->reporter(s->user_data, BERT_REPORT_REGULAR, &s->results);
|
||||
s->report_countdown = s->report_frequency;
|
||||
s->rx.report_countdown = s->report_frequency;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -339,7 +341,7 @@ SPAN_DECLARE(void) bert_set_report(bert_state_t *s, int freq, bert_report_func_t
|
|||
s->reporter = reporter;
|
||||
s->user_data = user_data;
|
||||
|
||||
s->report_countdown = s->report_frequency;
|
||||
s->rx.report_countdown = s->report_frequency;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -366,47 +368,47 @@ SPAN_DECLARE(bert_state_t *) bert_init(bert_state_t *s, int limit, int pattern,
|
|||
switch (s->pattern)
|
||||
{
|
||||
case BERT_PATTERN_ZEROS:
|
||||
s->tx_reg = 0;
|
||||
s->tx.reg = 0;
|
||||
s->shift2 = 31;
|
||||
s->pattern_class = 0;
|
||||
break;
|
||||
case BERT_PATTERN_ONES:
|
||||
s->tx_reg = ~((uint32_t) 0);
|
||||
s->tx.reg = ~((uint32_t) 0);
|
||||
s->shift2 = 31;
|
||||
s->pattern_class = 0;
|
||||
break;
|
||||
case BERT_PATTERN_7_TO_1:
|
||||
s->tx_reg = 0xFEFEFEFE;
|
||||
s->tx.reg = 0xFEFEFEFE;
|
||||
s->shift2 = 31;
|
||||
s->pattern_class = 0;
|
||||
break;
|
||||
case BERT_PATTERN_3_TO_1:
|
||||
s->tx_reg = 0xEEEEEEEE;
|
||||
s->tx.reg = 0xEEEEEEEE;
|
||||
s->shift2 = 31;
|
||||
s->pattern_class = 0;
|
||||
break;
|
||||
case BERT_PATTERN_1_TO_1:
|
||||
s->tx_reg = 0xAAAAAAAA;
|
||||
s->tx.reg = 0xAAAAAAAA;
|
||||
s->shift2 = 31;
|
||||
s->pattern_class = 0;
|
||||
break;
|
||||
case BERT_PATTERN_1_TO_3:
|
||||
s->tx_reg = 0x11111111;
|
||||
s->tx.reg = 0x11111111;
|
||||
s->shift2 = 31;
|
||||
s->pattern_class = 0;
|
||||
break;
|
||||
case BERT_PATTERN_1_TO_7:
|
||||
s->tx_reg = 0x01010101;
|
||||
s->tx.reg = 0x01010101;
|
||||
s->shift2 = 31;
|
||||
s->pattern_class = 0;
|
||||
break;
|
||||
case BERT_PATTERN_QBF:
|
||||
s->tx_reg = 0;
|
||||
s->tx.reg = 0;
|
||||
s->pattern_class = 2;
|
||||
break;
|
||||
case BERT_PATTERN_ITU_O151_23:
|
||||
s->pattern_class = 1;
|
||||
s->tx_reg = 0x7FFFFF;
|
||||
s->tx.reg = 0x7FFFFF;
|
||||
s->mask = 0x20;
|
||||
s->shift = 5;
|
||||
s->shift2 = 22;
|
||||
|
@ -416,7 +418,7 @@ SPAN_DECLARE(bert_state_t *) bert_init(bert_state_t *s, int limit, int pattern,
|
|||
break;
|
||||
case BERT_PATTERN_ITU_O151_20:
|
||||
s->pattern_class = 1;
|
||||
s->tx_reg = 0xFFFFF;
|
||||
s->tx.reg = 0xFFFFF;
|
||||
s->mask = 0x8;
|
||||
s->shift = 3;
|
||||
s->shift2 = 19;
|
||||
|
@ -426,7 +428,7 @@ SPAN_DECLARE(bert_state_t *) bert_init(bert_state_t *s, int limit, int pattern,
|
|||
break;
|
||||
case BERT_PATTERN_ITU_O151_15:
|
||||
s->pattern_class = 1;
|
||||
s->tx_reg = 0x7FFF;
|
||||
s->tx.reg = 0x7FFF;
|
||||
s->mask = 0x2;
|
||||
s->shift = 1;
|
||||
s->shift2 = 14;
|
||||
|
@ -436,7 +438,7 @@ SPAN_DECLARE(bert_state_t *) bert_init(bert_state_t *s, int limit, int pattern,
|
|||
break;
|
||||
case BERT_PATTERN_ITU_O152_11:
|
||||
s->pattern_class = 1;
|
||||
s->tx_reg = 0x7FF;
|
||||
s->tx.reg = 0x7FF;
|
||||
s->mask = 0x4;
|
||||
s->shift = 2;
|
||||
s->shift2 = 10;
|
||||
|
@ -446,7 +448,7 @@ SPAN_DECLARE(bert_state_t *) bert_init(bert_state_t *s, int limit, int pattern,
|
|||
break;
|
||||
case BERT_PATTERN_ITU_O153_9:
|
||||
s->pattern_class = 1;
|
||||
s->tx_reg = 0x1FF;
|
||||
s->tx.reg = 0x1FF;
|
||||
s->mask = 0x10;
|
||||
s->shift = 4;
|
||||
s->shift2 = 8;
|
||||
|
@ -455,28 +457,29 @@ SPAN_DECLARE(bert_state_t *) bert_init(bert_state_t *s, int limit, int pattern,
|
|||
s->max_zeros = 0;
|
||||
break;
|
||||
}
|
||||
s->tx_bits = 0;
|
||||
s->tx_step = 0;
|
||||
s->tx_step_bit = 0;
|
||||
s->tx_zeros = 0;
|
||||
s->tx.bits = 0;
|
||||
s->tx.step = 0;
|
||||
s->tx.step_bit = 0;
|
||||
s->tx.zeros = 0;
|
||||
|
||||
s->rx_reg = s->tx_reg;
|
||||
s->ref_reg = s->rx_reg;
|
||||
s->master_reg = s->ref_reg;
|
||||
s->rx_bits = 0;
|
||||
s->rx_step = 0;
|
||||
s->rx_step_bit = 0;
|
||||
s->rx.reg = s->tx.reg;
|
||||
s->rx.ref_reg = s->rx.reg;
|
||||
s->rx.master_reg = s->rx.ref_reg;
|
||||
s->rx.bits = 0;
|
||||
s->rx.step = 0;
|
||||
s->rx.step_bit = 0;
|
||||
|
||||
s->rx.resync = 1;
|
||||
s->rx.resync_cnt = resync_len;
|
||||
s->rx.resync_bad_bits = 0;
|
||||
s->rx.resync_len = resync_len;
|
||||
s->rx.resync_percent = resync_percent;
|
||||
|
||||
s->resync = 1;
|
||||
s->resync_cnt = resync_len;
|
||||
s->resync_bad_bits = 0;
|
||||
s->resync_len = resync_len;
|
||||
s->resync_percent = resync_percent;
|
||||
s->results.total_bits = 0;
|
||||
s->results.bad_bits = 0;
|
||||
s->results.resyncs = 0;
|
||||
|
||||
s->report_countdown = 0;
|
||||
s->rx.report_countdown = 0;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
|
@ -485,7 +488,7 @@ SPAN_DECLARE(bert_state_t *) bert_init(bert_state_t *s, int limit, int pattern,
|
|||
s->decade_ptr[i] = 0;
|
||||
}
|
||||
s->error_rate = 8;
|
||||
s->step = 100;
|
||||
s->rx.measurement_step = MEASUREMENT_STEP;
|
||||
|
||||
span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
|
||||
span_log_set_protocol(&s->logging, "BERT");
|
||||
|
|
|
@ -22,10 +22,10 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: dtmf.c,v 1.51 2009/02/10 13:06:46 steveu Exp $
|
||||
* $Id: dtmf.c,v 1.53 2009/04/12 09:12:10 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file dtmf.h */
|
||||
/*! \file */
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "config.h"
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: fax.c,v 1.88 2009/02/16 09:57:22 steveu Exp $
|
||||
* $Id: fax.c,v 1.91 2009/04/12 03:29:58 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -83,6 +83,7 @@
|
|||
#include "spandsp/fax.h"
|
||||
|
||||
#include "spandsp/private/logging.h"
|
||||
#include "spandsp/private/silence_gen.h"
|
||||
#include "spandsp/private/fsk.h"
|
||||
#include "spandsp/private/v17tx.h"
|
||||
#include "spandsp/private/v17rx.h"
|
||||
|
@ -127,6 +128,27 @@ static void hdlc_underflow_handler(void *user_data)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void set_rx_handler(fax_state_t *s, span_rx_handler_t *handler, void *user_data)
|
||||
{
|
||||
s->modems.rx_handler = handler;
|
||||
s->modems.rx_user_data = user_data;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void set_tx_handler(fax_state_t *s, span_tx_handler_t *handler, void *user_data)
|
||||
{
|
||||
s->modems.tx_handler = handler;
|
||||
s->modems.tx_user_data = user_data;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void set_next_tx_handler(fax_state_t *s, span_tx_handler_t *handler, void *user_data)
|
||||
{
|
||||
s->modems.next_tx_handler = handler;
|
||||
s->modems.next_tx_user_data = user_data;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int v17_v21_rx(void *user_data, const int16_t amp[], int len)
|
||||
{
|
||||
fax_state_t *t;
|
||||
|
@ -140,8 +162,7 @@ static int v17_v21_rx(void *user_data, const int16_t amp[], int len)
|
|||
/* The fast modem has trained, so we no longer need to run the slow
|
||||
one in parallel. */
|
||||
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->v17_rx));
|
||||
s->rx_handler = (span_rx_handler_t *) &v17_rx;
|
||||
s->rx_user_data = &s->v17_rx;
|
||||
set_rx_handler(t, (span_rx_handler_t *) &v17_rx, &s->v17_rx);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -151,8 +172,7 @@ static int v17_v21_rx(void *user_data, const int16_t amp[], int len)
|
|||
/* We have received something, and the fast modem has not trained. We must
|
||||
be receiving valid V.21 */
|
||||
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
|
||||
s->rx_handler = (span_rx_handler_t *) &fsk_rx;
|
||||
s->rx_user_data = &s->v21_rx;
|
||||
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -172,8 +192,7 @@ static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
|
|||
/* The fast modem has trained, so we no longer need to run the slow
|
||||
one in parallel. */
|
||||
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->v27ter_rx));
|
||||
s->rx_handler = (span_rx_handler_t *) &v27ter_rx;
|
||||
s->rx_user_data = &s->v27ter_rx;
|
||||
set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, &s->v27ter_rx);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -183,8 +202,7 @@ static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
|
|||
/* We have received something, and the fast modem has not trained. We must
|
||||
be receiving valid V.21 */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
|
||||
s->rx_handler = (span_rx_handler_t *) &fsk_rx;
|
||||
s->rx_user_data = &s->v21_rx;
|
||||
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -204,8 +222,7 @@ static int v29_v21_rx(void *user_data, const int16_t amp[], int len)
|
|||
/* The fast modem has trained, so we no longer need to run the slow
|
||||
one in parallel. */
|
||||
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->v29_rx));
|
||||
s->rx_handler = (span_rx_handler_t *) &v29_rx;
|
||||
s->rx_user_data = &s->v29_rx;
|
||||
set_rx_handler(t, (span_rx_handler_t *) &v29_rx, &s->v29_rx);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -215,8 +232,7 @@ static int v29_v21_rx(void *user_data, const int16_t amp[], int len)
|
|||
/* We have received something, and the fast modem has not trained. We must
|
||||
be receiving valid V.21 */
|
||||
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
|
||||
s->rx_handler = (span_rx_handler_t *) &fsk_rx;
|
||||
s->rx_user_data = &s->v21_rx;
|
||||
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
@ -239,6 +255,51 @@ SPAN_DECLARE(int) fax_rx(fax_state_t *s, int16_t *amp, int len)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) fax_rx_fillin(fax_state_t *s, int len)
|
||||
{
|
||||
/* To mitigate the effect of lost packets on a packet network we should
|
||||
try to sustain the status quo. If there is no receive modem running, keep
|
||||
things that way. If there is a receive modem running, try to sustain its
|
||||
operation, without causing a phase hop, or letting its adaptive functions
|
||||
diverge. */
|
||||
#if defined(LOG_FAX_AUDIO)
|
||||
if (s->modems.audio_rx_log >= 0)
|
||||
{
|
||||
int i;
|
||||
#if defined(_MSC_VER)
|
||||
int16_t *amp = (int16_t *) _alloca(sizeof(int16_t)*len);
|
||||
#else
|
||||
int16_t amp[len];
|
||||
#endif
|
||||
|
||||
vec_zeroi16(amp, len);
|
||||
write(s->modems.audio_rx_log, amp, len*sizeof(int16_t));
|
||||
}
|
||||
#endif
|
||||
t30_timer_update(&s->t30, len);
|
||||
/* Call the fillin function of the current modem (if there is one). */
|
||||
switch (s->modems.current_rx_type)
|
||||
{
|
||||
case T30_MODEM_V21:
|
||||
len = fsk_rx_fillin(&s->modems.v21_rx, len);
|
||||
break;
|
||||
case T30_MODEM_V27TER:
|
||||
/* TODO: what about FSK in the early stages */
|
||||
len = v27ter_rx_fillin(&s->modems.v27ter_rx, len);
|
||||
break;
|
||||
case T30_MODEM_V29:
|
||||
/* TODO: what about FSK in the early stages */
|
||||
len = v29_rx_fillin(&s->modems.v29_rx, len);
|
||||
break;
|
||||
case T30_MODEM_V17:
|
||||
/* TODO: what about FSK in the early stages */
|
||||
len = v17_rx_fillin(&s->modems.v17_rx, len);
|
||||
break;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int set_next_tx_type(fax_state_t *s)
|
||||
{
|
||||
fax_modems_state_t *t;
|
||||
|
@ -246,16 +307,14 @@ static int set_next_tx_type(fax_state_t *s)
|
|||
t = &s->modems;
|
||||
if (t->next_tx_handler)
|
||||
{
|
||||
t->tx_handler = t->next_tx_handler;
|
||||
t->tx_user_data = t->next_tx_user_data;
|
||||
set_tx_handler(s, t->next_tx_handler, t->next_tx_user_data);
|
||||
t->next_tx_handler = NULL;
|
||||
return 0;
|
||||
}
|
||||
/* If there is nothing else to change to, so use zero length silence */
|
||||
silence_gen_alter(&t->silence_gen, 0);
|
||||
t->tx_handler = (span_tx_handler_t *) &silence_gen;
|
||||
t->tx_user_data = &t->silence_gen;
|
||||
t->next_tx_handler = NULL;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
|
||||
t->transmit = FALSE;
|
||||
return -1;
|
||||
}
|
||||
|
@ -340,32 +399,27 @@ static void fax_set_rx_type(void *user_data, int type, int bit_rate, int short_t
|
|||
case T30_MODEM_V21:
|
||||
fsk_rx_init(&t->v21_rx, &preset_fsk_specs[FSK_V21CH2], TRUE, (put_bit_func_t) hdlc_rx_put_bit, put_bit_user_data);
|
||||
fsk_rx_signal_cutoff(&t->v21_rx, -45.5f);
|
||||
t->rx_handler = (span_rx_handler_t *) &fsk_rx;
|
||||
t->rx_user_data = &t->v21_rx;
|
||||
set_rx_handler(s, (span_rx_handler_t *) &fsk_rx, &t->v21_rx);
|
||||
break;
|
||||
case T30_MODEM_V27TER:
|
||||
v27ter_rx_restart(&t->v27ter_rx, bit_rate, FALSE);
|
||||
v27ter_rx_set_put_bit(&t->v27ter_rx, put_bit_func, put_bit_user_data);
|
||||
t->rx_handler = (span_rx_handler_t *) &v27ter_v21_rx;
|
||||
t->rx_user_data = s;
|
||||
set_rx_handler(s, &v27ter_v21_rx, s);
|
||||
break;
|
||||
case T30_MODEM_V29:
|
||||
v29_rx_restart(&t->v29_rx, bit_rate, FALSE);
|
||||
v29_rx_set_put_bit(&t->v29_rx, put_bit_func, put_bit_user_data);
|
||||
t->rx_handler = (span_rx_handler_t *) &v29_v21_rx;
|
||||
t->rx_user_data = s;
|
||||
set_rx_handler(s, &v29_v21_rx, s);
|
||||
break;
|
||||
case T30_MODEM_V17:
|
||||
v17_rx_restart(&t->v17_rx, bit_rate, short_train);
|
||||
v17_rx_set_put_bit(&t->v17_rx, put_bit_func, put_bit_user_data);
|
||||
t->rx_handler = (span_rx_handler_t *) &v17_v21_rx;
|
||||
t->rx_user_data = s;
|
||||
set_rx_handler(s, &v17_v21_rx, s);
|
||||
break;
|
||||
case T30_MODEM_DONE:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "FAX exchange complete\n");
|
||||
default:
|
||||
t->rx_handler = (span_rx_handler_t *) &span_dummy_rx;
|
||||
t->rx_user_data = s;
|
||||
set_rx_handler(s, (span_rx_handler_t *) &span_dummy_rx, s);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -398,9 +452,8 @@ static void fax_set_tx_type(void *user_data, int type, int bit_rate, int short_t
|
|||
{
|
||||
case T30_MODEM_PAUSE:
|
||||
silence_gen_alter(&t->silence_gen, ms_to_samples(short_train));
|
||||
t->tx_handler = (span_tx_handler_t *) &silence_gen;
|
||||
t->tx_user_data = &t->silence_gen;
|
||||
t->next_tx_handler = NULL;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
|
||||
t->transmit = TRUE;
|
||||
break;
|
||||
case T30_MODEM_CED:
|
||||
|
@ -410,9 +463,8 @@ static void fax_set_tx_type(void *user_data, int type, int bit_rate, int short_t
|
|||
else
|
||||
tone = MODEM_CONNECT_TONES_FAX_CNG;
|
||||
modem_connect_tones_tx_init(&t->connect_tx, tone);
|
||||
t->tx_handler = (span_tx_handler_t *) &modem_connect_tones_tx;
|
||||
t->tx_user_data = &t->connect_tx;
|
||||
t->next_tx_handler = NULL;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &modem_connect_tones_tx, &t->connect_tx);
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
|
||||
t->transmit = TRUE;
|
||||
break;
|
||||
case T30_MODEM_V21:
|
||||
|
@ -424,10 +476,8 @@ static void fax_set_tx_type(void *user_data, int type, int bit_rate, int short_t
|
|||
a 75ms gap before any V.21 transmission is harmless, adds little to the overall length of
|
||||
a call, and ensures the receiving end is ready. */
|
||||
silence_gen_alter(&t->silence_gen, ms_to_samples(75));
|
||||
t->tx_handler = (span_tx_handler_t *) &silence_gen;
|
||||
t->tx_user_data = &t->silence_gen;
|
||||
t->next_tx_handler = (span_tx_handler_t *) &fsk_tx;
|
||||
t->next_tx_user_data = &t->v21_tx;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) &fsk_tx, &t->v21_tx);
|
||||
t->transmit = TRUE;
|
||||
break;
|
||||
case T30_MODEM_V27TER:
|
||||
|
@ -436,10 +486,8 @@ static void fax_set_tx_type(void *user_data, int type, int bit_rate, int short_t
|
|||
hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5));
|
||||
v27ter_tx_restart(&t->v27ter_tx, bit_rate, t->use_tep);
|
||||
v27ter_tx_set_get_bit(&t->v27ter_tx, get_bit_func, get_bit_user_data);
|
||||
t->tx_handler = (span_tx_handler_t *) &silence_gen;
|
||||
t->tx_user_data = &t->silence_gen;
|
||||
t->next_tx_handler = (span_tx_handler_t *) &v27ter_tx;
|
||||
t->next_tx_user_data = &t->v27ter_tx;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) &v27ter_tx, &t->v27ter_tx);
|
||||
t->transmit = TRUE;
|
||||
break;
|
||||
case T30_MODEM_V29:
|
||||
|
@ -448,10 +496,8 @@ static void fax_set_tx_type(void *user_data, int type, int bit_rate, int short_t
|
|||
hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5));
|
||||
v29_tx_restart(&t->v29_tx, bit_rate, t->use_tep);
|
||||
v29_tx_set_get_bit(&t->v29_tx, get_bit_func, get_bit_user_data);
|
||||
t->tx_handler = (span_tx_handler_t *) &silence_gen;
|
||||
t->tx_user_data = &t->silence_gen;
|
||||
t->next_tx_handler = (span_tx_handler_t *) &v29_tx;
|
||||
t->next_tx_user_data = &t->v29_tx;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) &v29_tx, &t->v29_tx);
|
||||
t->transmit = TRUE;
|
||||
break;
|
||||
case T30_MODEM_V17:
|
||||
|
@ -460,10 +506,8 @@ static void fax_set_tx_type(void *user_data, int type, int bit_rate, int short_t
|
|||
hdlc_tx_flags(&t->hdlc_tx, bit_rate/(8*5));
|
||||
v17_tx_restart(&t->v17_tx, bit_rate, t->use_tep, short_train);
|
||||
v17_tx_set_get_bit(&t->v17_tx, get_bit_func, get_bit_user_data);
|
||||
t->tx_handler = (span_tx_handler_t *) &silence_gen;
|
||||
t->tx_user_data = &t->silence_gen;
|
||||
t->next_tx_handler = (span_tx_handler_t *) &v17_tx;
|
||||
t->next_tx_user_data = &t->v17_tx;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) &v17_tx, &t->v17_tx);
|
||||
t->transmit = TRUE;
|
||||
break;
|
||||
case T30_MODEM_DONE:
|
||||
|
@ -471,9 +515,8 @@ static void fax_set_tx_type(void *user_data, int type, int bit_rate, int short_t
|
|||
/* Fall through */
|
||||
default:
|
||||
silence_gen_alter(&t->silence_gen, 0);
|
||||
t->tx_handler = (span_tx_handler_t *) &silence_gen;
|
||||
t->tx_user_data = &t->silence_gen;
|
||||
t->next_tx_handler = NULL;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
|
||||
t->transmit = FALSE;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: fax_modems.c,v 1.3 2009/02/21 04:27:46 steveu Exp $
|
||||
* $Id: fax_modems.c,v 1.5 2009/04/12 03:29:58 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -74,6 +74,7 @@
|
|||
#include "spandsp/fax_modems.h"
|
||||
|
||||
#include "spandsp/private/logging.h"
|
||||
#include "spandsp/private/silence_gen.h"
|
||||
#include "spandsp/private/fsk.h"
|
||||
#include "spandsp/private/v17tx.h"
|
||||
#include "spandsp/private/v17rx.h"
|
||||
|
@ -106,6 +107,17 @@ SPAN_DECLARE(int) fax_modems_v17_v21_rx(void *user_data, const int16_t amp[], in
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) fax_modems_v17_v21_rx_fillin(void *user_data, int len)
|
||||
{
|
||||
fax_modems_state_t *s;
|
||||
|
||||
s = (fax_modems_state_t *) user_data;
|
||||
v17_rx_fillin(&s->v17_rx, len);
|
||||
fsk_rx_fillin(&s->v21_rx, len);
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) fax_modems_v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
|
||||
{
|
||||
fax_modems_state_t *s;
|
||||
|
@ -125,6 +137,17 @@ SPAN_DECLARE(int) fax_modems_v27ter_v21_rx(void *user_data, const int16_t amp[],
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) fax_modems_v27ter_v21_rx_fillin(void *user_data, int len)
|
||||
{
|
||||
fax_modems_state_t *s;
|
||||
|
||||
s = (fax_modems_state_t *) user_data;
|
||||
v27ter_rx_fillin(&s->v27ter_rx, len);
|
||||
fsk_rx_fillin(&s->v21_rx, len);
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) fax_modems_v29_v21_rx(void *user_data, const int16_t amp[], int len)
|
||||
{
|
||||
fax_modems_state_t *s;
|
||||
|
@ -144,6 +167,17 @@ SPAN_DECLARE(int) fax_modems_v29_v21_rx(void *user_data, const int16_t amp[], in
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) fax_modems_v29_v21_rx_fillin(void *user_data, int len)
|
||||
{
|
||||
fax_modems_state_t *s;
|
||||
|
||||
s = (fax_modems_state_t *) user_data;
|
||||
v29_rx_fillin(&s->v29_rx, len);
|
||||
fsk_rx_fillin(&s->v21_rx, len);
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void v21_rx_status_handler(void *user_data, int status)
|
||||
{
|
||||
fax_modems_state_t *s;
|
||||
|
@ -200,7 +234,7 @@ static void v29_rx_status_handler(void *user_data, int status)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(void) start_fax_modems_rx_modem(fax_modems_state_t *s, int which)
|
||||
SPAN_DECLARE(void) fax_modems_start_rx_modem(fax_modems_state_t *s, int which)
|
||||
{
|
||||
switch (which)
|
||||
{
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: fsk.c,v 1.52 2009/02/10 13:06:46 steveu Exp $
|
||||
* $Id: fsk.c,v 1.58 2009/04/01 13:22:40 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -111,12 +111,20 @@ const fsk_spec_t preset_fsk_specs[] =
|
|||
1200*100
|
||||
},
|
||||
{
|
||||
"Weitbrecht", /* Used for TDD (Telecoms Device for the Deaf) */
|
||||
"Weitbrecht 45.45", /* Used for TDD (Telecoms Device for the Deaf) */
|
||||
1800,
|
||||
1400,
|
||||
-14,
|
||||
-30,
|
||||
4545
|
||||
},
|
||||
{
|
||||
"Weitbrecht 50", /* Used for TDD (Telecoms Device for the Deaf) */
|
||||
1800,
|
||||
1400,
|
||||
-14,
|
||||
-30,
|
||||
5000
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -140,7 +148,6 @@ SPAN_DECLARE(fsk_tx_state_t *) fsk_tx_init(fsk_tx_state_t *s,
|
|||
s->scaling = dds_scaling_dbm0((float) spec->tx_level);
|
||||
/* Initialise fractional sample baud generation. */
|
||||
s->phase_acc = 0;
|
||||
s->baud_inc = s->baud_rate;
|
||||
s->baud_frac = 0;
|
||||
s->current_phase_rate = s->phase_rates[1];
|
||||
|
||||
|
@ -175,7 +182,7 @@ SPAN_DECLARE(int) fsk_tx(fsk_tx_state_t *s, int16_t amp[], int len)
|
|||
with them, if they care about accurate transition timing. */
|
||||
for (sample = 0; sample < len; sample++)
|
||||
{
|
||||
if ((s->baud_frac += s->baud_inc) >= SAMPLE_RATE*100)
|
||||
if ((s->baud_frac += s->baud_rate) >= SAMPLE_RATE*100)
|
||||
{
|
||||
s->baud_frac -= SAMPLE_RATE*100;
|
||||
if ((bit = s->get_bit(s->get_bit_user_data)) == SIG_STATUS_END_OF_DATA)
|
||||
|
@ -245,7 +252,7 @@ SPAN_DECLARE(void) fsk_rx_set_modem_status_handler(fsk_rx_state_t *s, modem_tx_s
|
|||
|
||||
SPAN_DECLARE(fsk_rx_state_t *) fsk_rx_init(fsk_rx_state_t *s,
|
||||
const fsk_spec_t *spec,
|
||||
int sync_mode,
|
||||
int framing_mode,
|
||||
put_bit_func_t put_bit,
|
||||
void *user_data)
|
||||
{
|
||||
|
@ -259,7 +266,7 @@ SPAN_DECLARE(fsk_rx_state_t *) fsk_rx_init(fsk_rx_state_t *s,
|
|||
|
||||
memset(s, 0, sizeof(*s));
|
||||
s->baud_rate = spec->baud_rate;
|
||||
s->sync_mode = sync_mode;
|
||||
s->framing_mode = framing_mode;
|
||||
fsk_rx_signal_cutoff(s, (float) spec->min_level);
|
||||
s->put_bit = put_bit;
|
||||
s->put_bit_user_data = user_data;
|
||||
|
@ -292,8 +299,10 @@ SPAN_DECLARE(fsk_rx_state_t *) fsk_rx_init(fsk_rx_state_t *s,
|
|||
}
|
||||
|
||||
/* Initialise the baud/bit rate tracking. */
|
||||
s->baud_inc = s->baud_rate;
|
||||
s->baud_pll = 0;
|
||||
s->baud_phase = 0;
|
||||
s->frame_state = 0;
|
||||
s->frame_bits = 0;
|
||||
s->last_bit = 0;
|
||||
|
||||
/* Initialise a power detector, so sense when a signal is present. */
|
||||
power_meter_init(&(s->power), 4);
|
||||
|
@ -340,40 +349,6 @@ SPAN_DECLARE(int) fsk_rx(fsk_rx_state_t *s, const int16_t *amp, int len)
|
|||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
/* If there isn't much signal, don't demodulate - it will only produce
|
||||
useless junk results. */
|
||||
/* There should be no DC in the signal, but sometimes there is.
|
||||
We need to measure the power with the DC blocked, but not using
|
||||
a slow to respond DC blocker. Use the most elementary HPF. */
|
||||
x = amp[i] >> 1;
|
||||
power = power_meter_update(&(s->power), x - s->last_sample);
|
||||
s->last_sample = x;
|
||||
if (s->signal_present)
|
||||
{
|
||||
/* Look for power below turn-off threshold to turn the carrier off */
|
||||
if (power < s->carrier_off_power)
|
||||
{
|
||||
if (--s->signal_present <= 0)
|
||||
{
|
||||
/* Count down a short delay, to ensure we push the last
|
||||
few bits through the filters before stopping. */
|
||||
report_status_change(s, SIG_STATUS_CARRIER_DOWN);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Look for power exceeding turn-on threshold to turn the carrier on */
|
||||
if (power < s->carrier_on_power)
|
||||
continue;
|
||||
s->signal_present = 1;
|
||||
report_status_change(s, SIG_STATUS_CARRIER_UP);
|
||||
}
|
||||
/* Non-coherent FSK demodulation by correlation with the target tones
|
||||
over a one baud interval. The slow V.xx specs. are too open ended
|
||||
to allow anything fancier to be used. The dot products are calculated
|
||||
using a sliding window approach, so the compute load is not that great. */
|
||||
/* The *totally* asynchronous character to character behaviour of these
|
||||
modems, when carrying async. data, seems to force a sample by sample
|
||||
approach. */
|
||||
|
@ -394,38 +369,180 @@ SPAN_DECLARE(int) fsk_rx(fsk_rx_state_t *s, const int16_t *amp, int len)
|
|||
dot = s->dot[j].im >> 15;
|
||||
sum[j] += dot*dot;
|
||||
}
|
||||
baudstate = (sum[0] < sum[1]);
|
||||
|
||||
if (s->lastbit != baudstate)
|
||||
/* If there isn't much signal, don't demodulate - it will only produce
|
||||
useless junk results. */
|
||||
/* There should be no DC in the signal, but sometimes there is.
|
||||
We need to measure the power with the DC blocked, but not using
|
||||
a slow to respond DC blocker. Use the most elementary HPF. */
|
||||
x = amp[i] >> 1;
|
||||
power = power_meter_update(&(s->power), x - s->last_sample);
|
||||
s->last_sample = x;
|
||||
if (s->signal_present)
|
||||
{
|
||||
s->lastbit = baudstate;
|
||||
if (s->sync_mode)
|
||||
/* Look for power below turn-off threshold to turn the carrier off */
|
||||
if (power < s->carrier_off_power)
|
||||
{
|
||||
if (--s->signal_present <= 0)
|
||||
{
|
||||
/* Count down a short delay, to ensure we push the last
|
||||
few bits through the filters before stopping. */
|
||||
report_status_change(s, SIG_STATUS_CARRIER_DOWN);
|
||||
s->baud_phase = 0;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Look for power exceeding turn-on threshold to turn the carrier on */
|
||||
if (power < s->carrier_on_power)
|
||||
{
|
||||
s->baud_phase = 0;
|
||||
continue;
|
||||
}
|
||||
if (s->baud_phase < (s->correlation_span >> 1) - 30)
|
||||
{
|
||||
s->baud_phase++;
|
||||
continue;
|
||||
}
|
||||
s->signal_present = 1;
|
||||
/* Initialise the baud/bit rate tracking. */
|
||||
s->baud_phase = 0;
|
||||
s->frame_state = 0;
|
||||
s->frame_bits = 0;
|
||||
s->last_bit = 0;
|
||||
report_status_change(s, SIG_STATUS_CARRIER_UP);
|
||||
}
|
||||
/* Non-coherent FSK demodulation by correlation with the target tones
|
||||
over a one baud interval. The slow V.xx specs. are too open ended
|
||||
to allow anything fancier to be used. The dot products are calculated
|
||||
using a sliding window approach, so the compute load is not that great. */
|
||||
|
||||
baudstate = (sum[0] < sum[1]);
|
||||
switch (s->framing_mode)
|
||||
{
|
||||
case 1:
|
||||
/* Synchronous serial operation - e.g. for HDLC */
|
||||
if (s->last_bit != baudstate)
|
||||
{
|
||||
/* On a transition we check our timing */
|
||||
s->last_bit = baudstate;
|
||||
/* For synchronous use (e.g. HDLC channels in FAX modems), nudge
|
||||
the baud phase gently, trying to keep it centred on the bauds. */
|
||||
if (s->baud_pll < (SAMPLE_RATE*50))
|
||||
s->baud_pll += (s->baud_inc >> 3);
|
||||
if (s->baud_phase < (SAMPLE_RATE*50))
|
||||
s->baud_phase += (s->baud_rate >> 3);
|
||||
else
|
||||
s->baud_pll -= (s->baud_inc >> 3);
|
||||
s->baud_phase -= (s->baud_rate >> 3);
|
||||
}
|
||||
else
|
||||
if ((s->baud_phase += s->baud_rate) >= (SAMPLE_RATE*100))
|
||||
{
|
||||
/* We should be in the middle of a baud now, so report the current
|
||||
state as the next bit */
|
||||
s->baud_phase -= (SAMPLE_RATE*100);
|
||||
s->put_bit(s->put_bit_user_data, baudstate);
|
||||
}
|
||||
break;
|
||||
case 0:
|
||||
/* Fully asynchronous mode */
|
||||
if (s->last_bit != baudstate)
|
||||
{
|
||||
/* On a transition we check our timing */
|
||||
s->last_bit = baudstate;
|
||||
/* For async. operation, believe transitions completely, and
|
||||
sample appropriately. This allows instant start on the first
|
||||
transition. */
|
||||
/* We must now be about half way to a sampling point. We do not do
|
||||
any fractional sample estimation of the transitions, so this is
|
||||
the most accurate baud alignment we can do. */
|
||||
s->baud_pll = SAMPLE_RATE*50;
|
||||
s->baud_phase = SAMPLE_RATE*50;
|
||||
}
|
||||
|
||||
}
|
||||
if ((s->baud_pll += s->baud_inc) >= (SAMPLE_RATE*100))
|
||||
{
|
||||
/* We should be in the middle of a baud now, so report the current
|
||||
state as the next bit */
|
||||
s->baud_pll -= (SAMPLE_RATE*100);
|
||||
s->put_bit(s->put_bit_user_data, baudstate);
|
||||
if ((s->baud_phase += s->baud_rate) >= (SAMPLE_RATE*100))
|
||||
{
|
||||
/* We should be in the middle of a baud now, so report the current
|
||||
state as the next bit */
|
||||
s->baud_phase -= (SAMPLE_RATE*100);
|
||||
s->put_bit(s->put_bit_user_data, baudstate);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* Gather the specified number of bits, with robust checking to ensure reasonable voice immunity.
|
||||
The first bit should be a start bit (0), and the last bit should be a stop bit (1) */
|
||||
if (s->frame_state == 0)
|
||||
{
|
||||
/* Looking for the start of a zero bit, which hopefully the start of a start bit */
|
||||
if (baudstate == 0)
|
||||
{
|
||||
s->baud_phase = SAMPLE_RATE*(100 - 40)/2;
|
||||
s->frame_state = -1;
|
||||
s->frame_bits = 0;
|
||||
s->last_bit = -1;
|
||||
}
|
||||
}
|
||||
else if (s->frame_state == -1)
|
||||
{
|
||||
/* Look for a continuous zero from the start of the start bit until
|
||||
beyond the middle */
|
||||
if (baudstate != 0)
|
||||
{
|
||||
/* If we aren't looking at a stable start bit, restart */
|
||||
s->frame_state = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
s->baud_phase += s->baud_rate;
|
||||
if (s->baud_phase >= SAMPLE_RATE*100)
|
||||
{
|
||||
s->frame_state = 1;
|
||||
s->last_bit = baudstate;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s->baud_phase += s->baud_rate;
|
||||
if (s->baud_phase >= SAMPLE_RATE*(100 - 40))
|
||||
{
|
||||
if (s->last_bit < 0)
|
||||
s->last_bit = baudstate;
|
||||
/* Look for the bit being consistent over the central 20% of the bit time. */
|
||||
if (s->last_bit != baudstate)
|
||||
{
|
||||
s->frame_state = 0;
|
||||
}
|
||||
else if (s->baud_phase >= SAMPLE_RATE*100)
|
||||
{
|
||||
/* We should be in the middle of a baud now, so report the current
|
||||
state as the next bit */
|
||||
if (s->last_bit == baudstate)
|
||||
{
|
||||
s->frame_bits |= (baudstate << s->framing_mode);
|
||||
s->frame_bits >>= 1;
|
||||
s->baud_phase -= (SAMPLE_RATE*100);
|
||||
if (++s->frame_state > s->framing_mode)
|
||||
{
|
||||
/* Check we have a stop bit */
|
||||
if (baudstate == 1)
|
||||
{
|
||||
/* Check we have a start bit */
|
||||
if ((s->frame_bits & 1) == 0)
|
||||
{
|
||||
/* Drop the start bit, and pass the rest back */
|
||||
s->frame_bits >>= 1;
|
||||
s->put_bit(s->put_bit_user_data, s->frame_bits);
|
||||
}
|
||||
}
|
||||
s->frame_state = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
s->frame_state = 0;
|
||||
}
|
||||
s->last_bit = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (++buf_ptr >= s->correlation_span)
|
||||
buf_ptr = 0;
|
||||
|
@ -434,4 +551,14 @@ SPAN_DECLARE(int) fsk_rx(fsk_rx_state_t *s, const int16_t *amp, int len)
|
|||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) fsk_rx_fillin(fsk_rx_state_t *s, int len)
|
||||
{
|
||||
/* The valid choice here is probably to do nothing. We don't change state
|
||||
(i.e carrier on<->carrier off), and we'll just output less bits than we
|
||||
should. */
|
||||
/* TODO: Advance the symbol phase the appropriate amount */
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
/*- End of file ------------------------------------------------------------*/
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
* This code is based on the widely used GSM 06.10 code available from
|
||||
* http://kbs.cs.tu-berlin.de/~jutta/toast.html
|
||||
*
|
||||
* $Id: gsm0610_local.h,v 1.14 2009/03/07 16:47:30 steveu Exp $
|
||||
* $Id: gsm0610_local.h,v 1.15 2009/03/13 15:57:29 steveu Exp $
|
||||
*/
|
||||
|
||||
#if !defined(_GSM0610_LOCAL_H_)
|
||||
|
@ -39,7 +39,7 @@
|
|||
|
||||
static __inline__ int16_t gsm_add(int16_t a, int16_t b)
|
||||
{
|
||||
#if defined(__GNUC__) && defined(SPANDSP_USE_MMX)
|
||||
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
__asm__ __volatile__(
|
||||
" addw %2,%0;\n"
|
||||
" jno 0f;\n"
|
||||
|
@ -62,7 +62,7 @@ static __inline__ int16_t gsm_add(int16_t a, int16_t b)
|
|||
|
||||
static __inline__ int32_t gsm_l_add(int32_t a, int32_t b)
|
||||
{
|
||||
#if defined(__GNUC__) && defined(SPANDSP_USE_MMX)
|
||||
#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))
|
||||
__asm__ __volatile__(
|
||||
" addl %2,%0;\n"
|
||||
" jno 0f;\n"
|
||||
|
@ -214,16 +214,6 @@ extern void gsm0610_short_term_synthesis_filter(gsm0610_state_t *s,
|
|||
|
||||
extern int16_t gsm0610_norm(int32_t a);
|
||||
|
||||
#if defined(__GNUC__) && defined(__i386__)
|
||||
|
||||
int32_t gsm0610_vec_iprod(const int16_t *p, const int16_t *q, int n);
|
||||
|
||||
int32_t gsm0610_vec_maxmin(const int16_t *p, int n, int16_t *out);
|
||||
|
||||
int32_t gsm0610_max_cross_corr(const int16_t *wt, const int16_t *dp, int16_t *Nc_out);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*- End of include ---------------------------------------------------------*/
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
* This code is based on the widely used GSM 06.10 code available from
|
||||
* http://kbs.cs.tu-berlin.de/~jutta/toast.html
|
||||
*
|
||||
* $Id: gsm0610_long_term.c,v 1.21 2009/02/03 16:28:39 steveu Exp $
|
||||
* $Id: gsm0610_long_term.c,v 1.24 2009/04/20 16:36:36 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -67,156 +67,174 @@ static const int16_t gsm_QLB[4] =
|
|||
|
||||
/* 4.2.11 .. 4.2.12 LONG TERM PREDICTOR (LTP) SECTION */
|
||||
|
||||
#if defined(__GNUC__) && defined(SPANDSP_USE_MMX)
|
||||
int32_t gsm0610_max_cross_corr(const int16_t *wt, const int16_t *dp, int16_t *Nc_out)
|
||||
static int32_t gsm0610_max_cross_corr(const int16_t *wt, const int16_t *dp, int16_t *index_out)
|
||||
{
|
||||
int32_t lmax;
|
||||
int32_t out;
|
||||
int32_t max;
|
||||
int32_t index;
|
||||
int32_t res;
|
||||
int i;
|
||||
|
||||
#if defined(__x86_64__)
|
||||
__asm__ __volatile__(
|
||||
" emms;\n"
|
||||
" pushq %%rbx;\n"
|
||||
" movl $0,%%edx;\n" /* Will be maximum inner-product */
|
||||
" movl $40,%%ebx;\n"
|
||||
" movl %%ebx,%%ecx;\n" /* Will be index of max inner-product */
|
||||
" subq $80,%%rsi;\n"
|
||||
" .p2align 2;\n"
|
||||
"1:\n"
|
||||
" movq (%%rdi),%%mm0;\n"
|
||||
" movq (%%rsi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm0;\n"
|
||||
" movq 8(%%rdi),%%mm1;\n"
|
||||
" movq 8(%%rsi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 16(%%rdi),%%mm1;\n"
|
||||
" movq 16(%%rsi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 24(%%rdi),%%mm1;\n"
|
||||
" movq 24(%%rsi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 32(%%rdi),%%mm1;\n"
|
||||
" movq 32(%%rsi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 40(%%rdi),%%mm1;\n"
|
||||
" movq 40(%%rsi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 48(%%rdi),%%mm1;\n"
|
||||
" movq 48(%%rsi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 56(%%rdi),%%mm1;\n"
|
||||
" movq 56(%%rsi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 64(%%rdi),%%mm1;\n"
|
||||
" movq 64(%%rsi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 72(%%rdi),%%mm1;\n"
|
||||
" movq 72(%%rsi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq %%mm0,%%mm1;\n"
|
||||
" punpckhdq %%mm0,%%mm1;\n" /* mm1 has high int32 of mm0 dup'd */
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movd %%mm0,%%eax;\n" /* eax has result */
|
||||
" cmpl %%edx,%%eax;\n"
|
||||
" jle 2f;\n"
|
||||
" movl %%eax,%%edx;\n"
|
||||
" movl %%ebx,%%ecx;\n"
|
||||
" .p2align 2;\n"
|
||||
"2:\n"
|
||||
" subq $2,%%rsi;\n"
|
||||
" incl %%ebx;\n"
|
||||
" cmpq $120,%%rbx;\n"
|
||||
" jle 1b;\n"
|
||||
" popq %%rbx;\n"
|
||||
" emms;\n"
|
||||
: "=d" (lmax), "=c" (out)
|
||||
: "D" (wt), "S" (dp)
|
||||
: "eax"
|
||||
);
|
||||
max = 0;
|
||||
index = 40; /* index for the maximum cross-correlation */
|
||||
|
||||
for (i = 40; i <= 120; i++)
|
||||
{
|
||||
#if defined(__GNUC__) && defined(SPANDSP_USE_MMX) && defined(__x86_64__)
|
||||
__asm__ __volatile__(
|
||||
" emms;\n"
|
||||
" .p2align 2;\n"
|
||||
" movq (%%rdi),%%mm0;\n"
|
||||
" movq (%%rsi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm0;\n"
|
||||
" movq 8(%%rdi),%%mm1;\n"
|
||||
" movq 8(%%rsi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 16(%%rdi),%%mm1;\n"
|
||||
" movq 16(%%rsi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 24(%%rdi),%%mm1;\n"
|
||||
" movq 24(%%rsi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 32(%%rdi),%%mm1;\n"
|
||||
" movq 32(%%rsi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 40(%%rdi),%%mm1;\n"
|
||||
" movq 40(%%rsi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 48(%%rdi),%%mm1;\n"
|
||||
" movq 48(%%rsi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 56(%%rdi),%%mm1;\n"
|
||||
" movq 56(%%rsi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 64(%%rdi),%%mm1;\n"
|
||||
" movq 64(%%rsi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 72(%%rdi),%%mm1;\n"
|
||||
" movq 72(%%rsi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq %%mm0,%%mm1;\n"
|
||||
" punpckhdq %%mm0,%%mm1;\n" /* mm1 has high int32 of mm0 dup'd */
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movd %%mm0,%[res];\n"
|
||||
" emms;\n"
|
||||
: [res] "=r" (res)
|
||||
: "D" (wt), "S" (&dp[-i])
|
||||
);
|
||||
#elif defined(__GNUC__) && defined(SPANDSP_USE_MMX) && defined(__i386__)
|
||||
__asm__ __volatile__(
|
||||
" emms;\n"
|
||||
" .p2align 2;\n"
|
||||
" movq (%%edi),%%mm0;\n"
|
||||
" movq (%%esi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm0;\n"
|
||||
" movq 8(%%edi),%%mm1;\n"
|
||||
" movq 8(%%esi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 16(%%edi),%%mm1;\n"
|
||||
" movq 16(%%esi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 24(%%edi),%%mm1;\n"
|
||||
" movq 24(%%esi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 32(%%edi),%%mm1;\n"
|
||||
" movq 32(%%esi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 40(%%edi),%%mm1;\n"
|
||||
" movq 40(%%esi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 48(%%edi),%%mm1;\n"
|
||||
" movq 48(%%esi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 56(%%edi),%%mm1;\n"
|
||||
" movq 56(%%esi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 64(%%edi),%%mm1;\n"
|
||||
" movq 64(%%esi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 72(%%edi),%%mm1;\n"
|
||||
" movq 72(%%esi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq %%mm0,%%mm1;\n"
|
||||
" punpckhdq %%mm0,%%mm1;\n" /* mm1 has high int32 of mm0 dup'd */
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movd %%mm0,%[res];\n"
|
||||
" emms;\n"
|
||||
: [res] "=r" (res)
|
||||
: "D" (wt), "S" (&dp[-i])
|
||||
);
|
||||
#else
|
||||
__asm__ __volatile__(
|
||||
" emms;\n"
|
||||
" pushl %%ebx;\n"
|
||||
" movl $0,%%edx;\n" /* Will be maximum inner-product */
|
||||
" movl $40,%%ebx;\n"
|
||||
" movl %%ebx,%%ecx;\n" /* Will be index of max inner-product */
|
||||
" subl $80,%%esi;\n"
|
||||
" .p2align 2;\n"
|
||||
"1:\n"
|
||||
" movq (%%edi),%%mm0;\n"
|
||||
" movq (%%esi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm0;\n"
|
||||
" movq 8(%%edi),%%mm1;\n"
|
||||
" movq 8(%%esi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 16(%%edi),%%mm1;\n"
|
||||
" movq 16(%%esi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 24(%%edi),%%mm1;\n"
|
||||
" movq 24(%%esi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 32(%%edi),%%mm1;\n"
|
||||
" movq 32(%%esi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 40(%%edi),%%mm1;\n"
|
||||
" movq 40(%%esi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 48(%%edi),%%mm1;\n"
|
||||
" movq 48(%%esi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 56(%%edi),%%mm1;\n"
|
||||
" movq 56(%%esi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 64(%%edi),%%mm1;\n"
|
||||
" movq 64(%%esi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq 72(%%edi),%%mm1;\n"
|
||||
" movq 72(%%esi),%%mm2;\n"
|
||||
" pmaddwd %%mm2,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movq %%mm0,%%mm1;\n"
|
||||
" punpckhdq %%mm0,%%mm1;\n" /* mm1 has high int32 of mm0 dup'd */
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
" movd %%mm0,%%eax;\n" /* eax has result */
|
||||
" cmpl %%edx,%%eax;\n"
|
||||
" jle 2f;\n"
|
||||
" movl %%eax,%%edx;\n"
|
||||
" movl %%ebx,%%ecx;\n"
|
||||
" .p2align 2;\n"
|
||||
"2:\n"
|
||||
" subl $2,%%esi;\n"
|
||||
" incl %%ebx;\n"
|
||||
" cmpl $120,%%ebx;\n"
|
||||
" jle 1b;\n"
|
||||
" popl %%ebx;\n"
|
||||
" emms;\n"
|
||||
: "=d" (lmax), "=c" (out)
|
||||
: "D" (wt), "S" (dp)
|
||||
: "eax"
|
||||
);
|
||||
res = (wt[0]*dp[0 - i])
|
||||
+ (wt[1]*dp[1 - i])
|
||||
+ (wt[2]*dp[2 - i])
|
||||
+ (wt[3]*dp[3 - i])
|
||||
+ (wt[4]*dp[4 - i])
|
||||
+ (wt[5]*dp[5 - i])
|
||||
+ (wt[6]*dp[6 - i])
|
||||
+ (wt[7]*dp[7 - i])
|
||||
+ (wt[8]*dp[8 - i])
|
||||
+ (wt[9]*dp[9 - i])
|
||||
+ (wt[10]*dp[10 - i])
|
||||
+ (wt[11]*dp[11 - i])
|
||||
+ (wt[12]*dp[12 - i])
|
||||
+ (wt[13]*dp[13 - i])
|
||||
+ (wt[14]*dp[14 - i])
|
||||
+ (wt[15]*dp[15 - i])
|
||||
+ (wt[16]*dp[16 - i])
|
||||
+ (wt[17]*dp[17 - i])
|
||||
+ (wt[18]*dp[18 - i])
|
||||
+ (wt[19]*dp[19 - i])
|
||||
+ (wt[20]*dp[20 - i])
|
||||
+ (wt[21]*dp[21 - i])
|
||||
+ (wt[22]*dp[22 - i])
|
||||
+ (wt[23]*dp[23 - i])
|
||||
+ (wt[24]*dp[24 - i])
|
||||
+ (wt[25]*dp[25 - i])
|
||||
+ (wt[26]*dp[26 - i])
|
||||
+ (wt[27]*dp[27 - i])
|
||||
+ (wt[28]*dp[28 - i])
|
||||
+ (wt[29]*dp[29 - i])
|
||||
+ (wt[30]*dp[30 - i])
|
||||
+ (wt[31]*dp[31 - i])
|
||||
+ (wt[32]*dp[32 - i])
|
||||
+ (wt[33]*dp[33 - i])
|
||||
+ (wt[34]*dp[34 - i])
|
||||
+ (wt[35]*dp[35 - i])
|
||||
+ (wt[36]*dp[36 - i])
|
||||
+ (wt[37]*dp[37 - i])
|
||||
+ (wt[38]*dp[38 - i])
|
||||
+ (wt[39]*dp[39 - i]);
|
||||
#endif
|
||||
*Nc_out = out;
|
||||
return lmax;
|
||||
if (res > max)
|
||||
{
|
||||
max = res;
|
||||
index = i;
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*endfor*/
|
||||
*index_out = index;
|
||||
return max;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
#endif
|
||||
|
||||
/* This procedure computes the LTP gain (bc) and the LTP lag (Nc)
|
||||
for the long term analysis filter. This is done by calculating a
|
||||
|
@ -237,7 +255,6 @@ static int16_t evaluate_ltp_parameters(int16_t d[40],
|
|||
int16_t *Nc_out)
|
||||
{
|
||||
int k;
|
||||
int16_t Nc;
|
||||
int16_t bc;
|
||||
int16_t wt[40];
|
||||
int32_t L_max;
|
||||
|
@ -248,9 +265,6 @@ static int16_t evaluate_ltp_parameters(int16_t d[40],
|
|||
int16_t scale;
|
||||
int16_t temp;
|
||||
int32_t L_temp;
|
||||
#if !(defined(__GNUC__) && defined(SPANDSP_USE_MMX))
|
||||
int16_t lambda;
|
||||
#endif
|
||||
|
||||
/* Search of the optimum scaling of d[0..39]. */
|
||||
dmax = 0;
|
||||
|
@ -288,81 +302,20 @@ static int16_t evaluate_ltp_parameters(int16_t d[40],
|
|||
/*endfor*/
|
||||
|
||||
/* Search for the maximum cross-correlation and coding of the LTP lag */
|
||||
#if defined(__GNUC__) && defined(SPANDSP_USE_MMX)
|
||||
L_max = gsm0610_max_cross_corr(wt, dp, &Nc);
|
||||
#else
|
||||
L_max = 0;
|
||||
Nc = 40; /* index for the maximum cross-correlation */
|
||||
|
||||
for (lambda = 40; lambda <= 120; lambda++)
|
||||
{
|
||||
int32_t L_result;
|
||||
|
||||
L_result = (wt[0]*dp[0 - lambda])
|
||||
+ (wt[1]*dp[1 - lambda])
|
||||
+ (wt[2]*dp[2 - lambda])
|
||||
+ (wt[3]*dp[3 - lambda])
|
||||
+ (wt[4]*dp[4 - lambda])
|
||||
+ (wt[5]*dp[5 - lambda])
|
||||
+ (wt[6]*dp[6 - lambda])
|
||||
+ (wt[7]*dp[7 - lambda])
|
||||
+ (wt[8]*dp[8 - lambda])
|
||||
+ (wt[9]*dp[9 - lambda])
|
||||
+ (wt[10]*dp[10 - lambda])
|
||||
+ (wt[11]*dp[11 - lambda])
|
||||
+ (wt[12]*dp[12 - lambda])
|
||||
+ (wt[13]*dp[13 - lambda])
|
||||
+ (wt[14]*dp[14 - lambda])
|
||||
+ (wt[15]*dp[15 - lambda])
|
||||
+ (wt[16]*dp[16 - lambda])
|
||||
+ (wt[17]*dp[17 - lambda])
|
||||
+ (wt[18]*dp[18 - lambda])
|
||||
+ (wt[19]*dp[19 - lambda])
|
||||
+ (wt[20]*dp[20 - lambda])
|
||||
+ (wt[21]*dp[21 - lambda])
|
||||
+ (wt[22]*dp[22 - lambda])
|
||||
+ (wt[23]*dp[23 - lambda])
|
||||
+ (wt[24]*dp[24 - lambda])
|
||||
+ (wt[25]*dp[25 - lambda])
|
||||
+ (wt[26]*dp[26 - lambda])
|
||||
+ (wt[27]*dp[27 - lambda])
|
||||
+ (wt[28]*dp[28 - lambda])
|
||||
+ (wt[29]*dp[29 - lambda])
|
||||
+ (wt[30]*dp[30 - lambda])
|
||||
+ (wt[31]*dp[31 - lambda])
|
||||
+ (wt[32]*dp[32 - lambda])
|
||||
+ (wt[33]*dp[33 - lambda])
|
||||
+ (wt[34]*dp[34 - lambda])
|
||||
+ (wt[35]*dp[35 - lambda])
|
||||
+ (wt[36]*dp[36 - lambda])
|
||||
+ (wt[37]*dp[37 - lambda])
|
||||
+ (wt[38]*dp[38 - lambda])
|
||||
+ (wt[39]*dp[39 - lambda]);
|
||||
|
||||
if (L_result > L_max)
|
||||
{
|
||||
Nc = lambda;
|
||||
L_max = L_result;
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*endfor*/
|
||||
#endif
|
||||
*Nc_out = Nc;
|
||||
|
||||
L_max = gsm0610_max_cross_corr(wt, dp, Nc_out);
|
||||
L_max <<= 1;
|
||||
|
||||
/* Rescaling of L_max */
|
||||
assert(scale <= 100 && scale >= -100);
|
||||
L_max = L_max >> (6 - scale);
|
||||
|
||||
assert(Nc <= 120 && Nc >= 40);
|
||||
assert(*Nc_out <= 120 && *Nc_out >= 40);
|
||||
|
||||
/* Compute the power of the reconstructed short term residual signal dp[..] */
|
||||
L_power = 0;
|
||||
for (k = 0; k < 40; k++)
|
||||
{
|
||||
L_temp = dp[k - Nc] >> 3;
|
||||
L_temp = dp[k - *Nc_out] >> 3;
|
||||
L_power += L_temp*L_temp;
|
||||
}
|
||||
/*endfor*/
|
||||
|
@ -453,7 +406,7 @@ void gsm0610_long_term_synthesis_filtering(gsm0610_state_t *s,
|
|||
int16_t drpp;
|
||||
int16_t Nr;
|
||||
|
||||
/* This procedure uses the bcr and Ncr parameter to realize the
|
||||
/* This procedure uses the bcr and Ncr parameters to realize the
|
||||
long term synthesis filter. The decoding of bcr needs
|
||||
table 4.3b. */
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: ima_adpcm.c,v 1.35 2009/02/10 13:06:46 steveu Exp $
|
||||
* $Id: ima_adpcm.c,v 1.36 2009/04/11 18:11:19 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -115,6 +115,7 @@
|
|||
to indicate a partially filled last octet.
|
||||
*/
|
||||
|
||||
/*! The number of ADPCM step sizes */
|
||||
#define STEP_MAX 88
|
||||
|
||||
/* Intel ADPCM step variation table */
|
||||
|
@ -277,7 +278,9 @@ static uint8_t encode(ima_adpcm_state_t *s, int16_t linear)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(ima_adpcm_state_t *) ima_adpcm_init(ima_adpcm_state_t *s, int variant, int chunk_size)
|
||||
SPAN_DECLARE(ima_adpcm_state_t *) ima_adpcm_init(ima_adpcm_state_t *s,
|
||||
int variant,
|
||||
int chunk_size)
|
||||
{
|
||||
if (s == NULL)
|
||||
{
|
||||
|
|
|
@ -158,6 +158,7 @@
|
|||
<File RelativePath="tone_generate.c"></File>
|
||||
<File RelativePath="v17rx.c"></File>
|
||||
<File RelativePath="v17tx.c"></File>
|
||||
<File RelativePath="v18.c"></File>
|
||||
<File RelativePath="v22bis_rx.c"></File>
|
||||
<File RelativePath="v22bis_tx.c"></File>
|
||||
<File RelativePath="v27ter_rx.c"></File>
|
||||
|
@ -236,6 +237,7 @@
|
|||
<File RelativePath="spandsp/tone_generate.h"></File>
|
||||
<File RelativePath="spandsp/v17rx.h"></File>
|
||||
<File RelativePath="spandsp/v17tx.h"></File>
|
||||
<File RelativePath="spandsp/v18.h"></File>
|
||||
<File RelativePath="spandsp/v22bis.h"></File>
|
||||
<File RelativePath="spandsp/v27ter_rx.h"></File>
|
||||
<File RelativePath="spandsp/v27ter_tx.h"></File>
|
||||
|
@ -272,6 +274,7 @@
|
|||
<File RelativePath="spandsp/private/queue.h"></File>
|
||||
<File RelativePath="spandsp/private/schedule.h"></File>
|
||||
<File RelativePath="spandsp/private/sig_tone.h"></File>
|
||||
<File RelativePath="spandsp/private/silence_gen.h"></File>
|
||||
<File RelativePath="spandsp/private/super_tone_rx.h"></File>
|
||||
<File RelativePath="spandsp/private/super_tone_tx.h"></File>
|
||||
<File RelativePath="spandsp/private/t30.h"></File>
|
||||
|
@ -286,6 +289,7 @@
|
|||
<File RelativePath="spandsp/private/tone_generate.h"></File>
|
||||
<File RelativePath="spandsp/private/v17rx.h"></File>
|
||||
<File RelativePath="spandsp/private/v17tx.h"></File>
|
||||
<File RelativePath="spandsp/private/v18.h"></File>
|
||||
<File RelativePath="spandsp/private/v22bis.h"></File>
|
||||
<File RelativePath="spandsp/private/v27ter_rx.h"></File>
|
||||
<File RelativePath="spandsp/private/v27ter_tx.h"></File>
|
||||
|
|
|
@ -228,6 +228,7 @@
|
|||
<File RelativePath="tone_generate.c"></File>
|
||||
<File RelativePath="v17rx.c"></File>
|
||||
<File RelativePath="v17tx.c"></File>
|
||||
<File RelativePath="v18.c"></File>
|
||||
<File RelativePath="v22bis_rx.c"></File>
|
||||
<File RelativePath="v22bis_tx.c"></File>
|
||||
<File RelativePath="v27ter_rx.c"></File>
|
||||
|
@ -306,6 +307,7 @@
|
|||
<File RelativePath="spandsp/tone_generate.h"></File>
|
||||
<File RelativePath="spandsp/v17rx.h"></File>
|
||||
<File RelativePath="spandsp/v17tx.h"></File>
|
||||
<File RelativePath="spandsp/v18.h"></File>
|
||||
<File RelativePath="spandsp/v22bis.h"></File>
|
||||
<File RelativePath="spandsp/v27ter_rx.h"></File>
|
||||
<File RelativePath="spandsp/v27ter_tx.h"></File>
|
||||
|
@ -342,6 +344,7 @@
|
|||
<File RelativePath="spandsp/private/queue.h"></File>
|
||||
<File RelativePath="spandsp/private/schedule.h"></File>
|
||||
<File RelativePath="spandsp/private/sig_tone.h"></File>
|
||||
<File RelativePath="spandsp/private/silence_gen.h"></File>
|
||||
<File RelativePath="spandsp/private/super_tone_rx.h"></File>
|
||||
<File RelativePath="spandsp/private/super_tone_tx.h"></File>
|
||||
<File RelativePath="spandsp/private/t30.h"></File>
|
||||
|
@ -356,6 +359,7 @@
|
|||
<File RelativePath="spandsp/private/tone_generate.h"></File>
|
||||
<File RelativePath="spandsp/private/v17rx.h"></File>
|
||||
<File RelativePath="spandsp/private/v17tx.h"></File>
|
||||
<File RelativePath="spandsp/private/v18.h"></File>
|
||||
<File RelativePath="spandsp/private/v22bis.h"></File>
|
||||
<File RelativePath="spandsp/private/v27ter_rx.h"></File>
|
||||
<File RelativePath="spandsp/private/v27ter_tx.h"></File>
|
||||
|
|
|
@ -357,6 +357,10 @@ SOURCE=.\v17tx.c
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\v18.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\v22bis_rx.c
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -667,6 +671,10 @@ SOURCE=.\spandsp/v17tx.h
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\spandsp/v18.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\spandsp/v22bis.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -811,6 +819,10 @@ SOURCE=.\spandsp/private/sig_tone.h
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\spandsp/private/silence_gen.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\spandsp/private/super_tone_rx.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
@ -867,6 +879,10 @@ SOURCE=.\spandsp/private/v17tx.h
|
|||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\spandsp/private/v18.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\spandsp/private/v22bis.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: spandsp.h.in,v 1.17 2009/02/12 12:38:39 steveu Exp $
|
||||
* $Id: spandsp.h.in,v 1.18 2009/04/02 13:43:49 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -95,6 +95,7 @@
|
|||
#include <spandsp/v27ter_rx.h>
|
||||
#include <spandsp/v27ter_tx.h>
|
||||
#include <spandsp/v8.h>
|
||||
#include <spandsp/v18.h>
|
||||
#include <spandsp/v42.h>
|
||||
#include <spandsp/v42bis.h>
|
||||
#include <spandsp/t4.h>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: queue.c,v 1.29 2009/02/10 13:06:46 steveu Exp $
|
||||
* $Id: queue.c,v 1.31 2009/04/11 18:11:19 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -176,7 +176,7 @@ SPAN_DECLARE(int) queue_read(queue_state_t *s, uint8_t *buf, int len)
|
|||
memcpy(buf, s->data + optr, real_len);
|
||||
/*endif*/
|
||||
new_optr = optr + real_len;
|
||||
if (new_optr > s->len)
|
||||
if (new_optr >= s->len)
|
||||
new_optr = 0;
|
||||
/*endif*/
|
||||
}
|
||||
|
@ -250,7 +250,7 @@ SPAN_DECLARE(int) queue_write(queue_state_t *s, const uint8_t *buf, int len)
|
|||
/* A one step process */
|
||||
memcpy(s->data + iptr, buf, real_len);
|
||||
new_iptr = iptr + real_len;
|
||||
if (new_iptr > s->len)
|
||||
if (new_iptr >= s->len)
|
||||
new_iptr = 0;
|
||||
/*endif*/
|
||||
}
|
||||
|
@ -365,7 +365,7 @@ SPAN_DECLARE(int) queue_write_msg(queue_state_t *s, const uint8_t *buf, int len)
|
|||
memcpy(s->data + iptr, &lenx, sizeof(uint16_t));
|
||||
memcpy(s->data + iptr + sizeof(uint16_t), buf, len);
|
||||
new_iptr = iptr + real_len;
|
||||
if (new_iptr > s->len)
|
||||
if (new_iptr >= s->len)
|
||||
new_iptr = 0;
|
||||
/*endif*/
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: sig_tone.c,v 1.31 2009/02/10 13:06:46 steveu Exp $
|
||||
* $Id: sig_tone.c,v 1.32 2009/04/12 14:18:02 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -56,6 +56,7 @@
|
|||
|
||||
#include "spandsp/private/sig_tone.h"
|
||||
|
||||
/*! PI */
|
||||
#define PI 3.14159265358979323
|
||||
|
||||
/* The coefficients for the data notch filter. This filter is also the
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: silence_gen.c,v 1.20 2009/02/10 13:06:46 steveu Exp $
|
||||
* $Id: silence_gen.c,v 1.21 2009/04/12 03:29:58 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -51,6 +51,8 @@
|
|||
#include "spandsp/async.h"
|
||||
#include "spandsp/silence_gen.h"
|
||||
|
||||
#include "spandsp/private/silence_gen.h"
|
||||
|
||||
SPAN_DECLARE(int) silence_gen(silence_gen_state_t *s, int16_t *amp, int max_len)
|
||||
{
|
||||
if (s->remaining_samples != INT_MAX)
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: spandsp.h.in,v 1.17 2009/02/12 12:38:39 steveu Exp $
|
||||
* $Id: spandsp.h.in,v 1.18 2009/04/02 13:43:49 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -92,6 +92,7 @@
|
|||
#include <spandsp/v27ter_rx.h>
|
||||
#include <spandsp/v27ter_tx.h>
|
||||
#include <spandsp/v8.h>
|
||||
#include <spandsp/v18.h>
|
||||
#include <spandsp/v42.h>
|
||||
#include <spandsp/v42bis.h>
|
||||
#include <spandsp/t4.h>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: adsi.h,v 1.37 2009/03/04 12:15:15 steveu Exp $
|
||||
* $Id: adsi.h,v 1.39 2009/04/11 18:11:19 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -354,9 +354,11 @@ enum
|
|||
JCLIP_ABSENCE = 0x04
|
||||
};
|
||||
|
||||
/*! Definitions for CLIP-DTMF and its variants */
|
||||
/* Definitions for CLIP-DTMF and its variants */
|
||||
|
||||
/*! Caller number is '#' terminated DTMF. */
|
||||
#define CLIP_DTMF_HASH_TERMINATED '#'
|
||||
/*! Caller number is 'C' terminated DTMF. */
|
||||
#define CLIP_DTMF_C_TERMINATED 'C'
|
||||
|
||||
/*! Caller number */
|
||||
|
@ -398,10 +400,21 @@ extern "C"
|
|||
\param user_data An opaque pointer for the callback routine.
|
||||
\return A pointer to the initialised context, or NULL if there was a problem.
|
||||
*/
|
||||
SPAN_DECLARE(adsi_rx_state_t *) adsi_rx_init(adsi_rx_state_t *s, int standard, put_msg_func_t put_msg, void *user_data);
|
||||
SPAN_DECLARE(adsi_rx_state_t *) adsi_rx_init(adsi_rx_state_t *s,
|
||||
int standard,
|
||||
put_msg_func_t put_msg,
|
||||
void *user_data);
|
||||
|
||||
/*! \brief Release an ADSI receive context.
|
||||
\param s The ADSI receive context.
|
||||
\return 0 for OK.
|
||||
*/
|
||||
SPAN_DECLARE(int) adsi_rx_release(adsi_rx_state_t *s);
|
||||
|
||||
/*! \brief Free the resources of an ADSI receive context.
|
||||
\param s The ADSI receive context.
|
||||
\return 0 for OK.
|
||||
*/
|
||||
SPAN_DECLARE(int) adsi_rx_free(adsi_rx_state_t *s);
|
||||
|
||||
/*! \brief Receive a chunk of ADSI audio.
|
||||
|
@ -410,7 +423,7 @@ SPAN_DECLARE(int) adsi_rx_free(adsi_rx_state_t *s);
|
|||
\param len The number of samples in the buffer.
|
||||
\return The number of samples unprocessed.
|
||||
*/
|
||||
SPAN_DECLARE(int) adsi_rx(adsi_rx_state_t *s, const int16_t *amp, int len);
|
||||
SPAN_DECLARE(int) adsi_rx(adsi_rx_state_t *s, const int16_t amp[], int len);
|
||||
|
||||
/*! \brief Initialise an ADSI transmit context.
|
||||
\param s The ADSI transmit context.
|
||||
|
@ -419,8 +432,16 @@ SPAN_DECLARE(int) adsi_rx(adsi_rx_state_t *s, const int16_t *amp, int len);
|
|||
*/
|
||||
SPAN_DECLARE(adsi_tx_state_t *) adsi_tx_init(adsi_tx_state_t *s, int standard);
|
||||
|
||||
/*! \brief Release an ADSI transmit context.
|
||||
\param s The ADSI transmit context.
|
||||
\return 0 for OK.
|
||||
*/
|
||||
SPAN_DECLARE(int) adsi_tx_release(adsi_tx_state_t *s);
|
||||
|
||||
/*! \brief Free the resources of an ADSI transmit context.
|
||||
\param s The ADSI transmit context.
|
||||
\return 0 for OK.
|
||||
*/
|
||||
SPAN_DECLARE(int) adsi_tx_free(adsi_tx_state_t *s);
|
||||
|
||||
/*! \brief Adjust the preamble associated with an ADSI transmit context.
|
||||
|
@ -442,7 +463,7 @@ SPAN_DECLARE(void) adsi_tx_set_preamble(adsi_tx_state_t *s,
|
|||
\param max_len The number of samples to be generated.
|
||||
\return The number of samples actually generated.
|
||||
*/
|
||||
SPAN_DECLARE(int) adsi_tx(adsi_tx_state_t *s, int16_t *amp, int max_len);
|
||||
SPAN_DECLARE(int) adsi_tx(adsi_tx_state_t *s, int16_t amp[], int max_len);
|
||||
|
||||
/*! \brief Request generation of an ADSI alert tone.
|
||||
\param s The ADSI transmit context.
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: expose.h,v 1.11 2008/11/30 13:44:35 steveu Exp $
|
||||
* $Id: expose.h,v 1.12 2009/04/12 03:29:58 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -55,6 +55,7 @@
|
|||
#include <spandsp/private/time_scale.h>
|
||||
#include <spandsp/private/super_tone_tx.h>
|
||||
#include <spandsp/private/super_tone_rx.h>
|
||||
#include <spandsp/private/silence_gen.h>
|
||||
#include <spandsp/private/async.h>
|
||||
#include <spandsp/private/fsk.h>
|
||||
#include <spandsp/private/v29rx.h>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: fast_convert.h,v 1.6 2009/02/26 16:08:51 steveu Exp $
|
||||
* $Id: fast_convert.h,v 1.7 2009/04/18 03:18:41 steveu Exp $
|
||||
*/
|
||||
|
||||
#if !defined(_SPANDSP_FAST_CONVERT_H_)
|
||||
|
@ -229,6 +229,17 @@ extern "C"
|
|||
|
||||
return res[1];
|
||||
}
|
||||
#else
|
||||
/* Fallback routines, for unrecognised platforms */
|
||||
static __inline__ long int lfastrint(double x)
|
||||
{
|
||||
return (long int) x;
|
||||
}
|
||||
|
||||
static __inline__ long int lfastrintf(float x)
|
||||
{
|
||||
return (long int) x;
|
||||
}
|
||||
#endif
|
||||
|
||||
#elif defined(_M_IX86)
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: fax.h,v 1.38 2009/02/03 16:28:41 steveu Exp $
|
||||
* $Id: fax.h,v 1.39 2009/03/13 12:59:26 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -54,6 +54,16 @@ extern "C"
|
|||
*/
|
||||
SPAN_DECLARE(int) fax_rx(fax_state_t *s, int16_t *amp, int len);
|
||||
|
||||
/*! Apply fake T.30 receive processing when a block of audio samples is missing (e.g due
|
||||
to packet loss).
|
||||
\brief Apply fake T.30 receive processing.
|
||||
\param s The FAX context.
|
||||
\param len The number of samples to fake.
|
||||
\return The number of samples unprocessed. This should only be non-zero if
|
||||
the software has reached the end of the FAX call.
|
||||
*/
|
||||
SPAN_DECLARE(int) fax_rx_fillin(fax_state_t *s, int len);
|
||||
|
||||
/*! Apply T.30 transmit processing to generate a block of audio samples.
|
||||
\brief Apply T.30 transmit processing to generate a block of audio samples.
|
||||
\param s The FAX context.
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: fsk.h,v 1.36 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: fsk.h,v 1.39 2009/04/01 13:22:40 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -111,7 +111,8 @@ enum
|
|||
FSK_BELL103CH1,
|
||||
FSK_BELL103CH2,
|
||||
FSK_BELL202,
|
||||
FSK_WEITBRECHT /* Used for TDD (Telecom Device for the Deaf) */
|
||||
FSK_WEITBRECHT, /* 45.45 baud version, used for TDD (Telecom Device for the Deaf) */
|
||||
FSK_WEITBRECHT50 /* 50 baud version, used for TDD (Telecom Device for the Deaf) */
|
||||
};
|
||||
|
||||
SPAN_DECLARE_DATA extern const fsk_spec_t preset_fsk_specs[];
|
||||
|
@ -191,13 +192,14 @@ SPAN_DECLARE(void) fsk_rx_signal_cutoff(fsk_rx_state_t *s, float cutoff);
|
|||
\brief Initialise an FSK modem receive context.
|
||||
\param s The modem context.
|
||||
\param spec The specification of the modem tones and rate.
|
||||
\param sync_mode TRUE for synchronous modem. FALSE for asynchronous mode.
|
||||
\param framing_mode 0 for fully asynchronous mode. 1 for synchronous mode. >1 for
|
||||
this many bits per asynchronous character frame.
|
||||
\param put_bit The callback routine used to put the received data.
|
||||
\param user_data An opaque pointer.
|
||||
\return A pointer to the modem context, or NULL if there was a problem. */
|
||||
SPAN_DECLARE(fsk_rx_state_t *) fsk_rx_init(fsk_rx_state_t *s,
|
||||
const fsk_spec_t *spec,
|
||||
int sync_mode,
|
||||
int framing_mode,
|
||||
put_bit_func_t put_bit,
|
||||
void *user_data);
|
||||
|
||||
|
@ -214,6 +216,15 @@ SPAN_DECLARE(int) fsk_rx_free(fsk_rx_state_t *s);
|
|||
*/
|
||||
SPAN_DECLARE(int) fsk_rx(fsk_rx_state_t *s, const int16_t *amp, int len);
|
||||
|
||||
/*! Fake processing of a missing block of received FSK modem audio samples
|
||||
(e.g due to packet loss).
|
||||
\brief Fake processing of a missing block of received FSK modem audio samples.
|
||||
\param s The modem context.
|
||||
\param len The number of samples to fake.
|
||||
\return The number of samples unprocessed.
|
||||
*/
|
||||
SPAN_DECLARE(int) fsk_rx_fillin(fsk_rx_state_t *s, int len);
|
||||
|
||||
SPAN_DECLARE(void) fsk_rx_set_put_bit(fsk_rx_state_t *s, put_bit_func_t put_bit, void *user_data);
|
||||
|
||||
/*! Change the modem status report function associated with an FSK modem receive context.
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: g711.h,v 1.18 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: g711.h,v 1.19 2009/04/12 09:12:10 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -53,7 +53,9 @@ specification by other means.
|
|||
#define _SPANDSP_G711_H_
|
||||
|
||||
/* The usual values to use on idle channels, to emulate silence */
|
||||
/*! Idle value for A-law channels */
|
||||
#define G711_ALAW_IDLE_OCTET 0x5D
|
||||
/*! Idle value for u-law channels */
|
||||
#define G711_ULAW_IDLE_OCTET 0xFF
|
||||
|
||||
enum
|
||||
|
@ -62,6 +64,9 @@ enum
|
|||
G711_ULAW
|
||||
};
|
||||
|
||||
/*!
|
||||
G.711 state
|
||||
*/
|
||||
typedef struct g711_state_s g711_state_t;
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
@ -106,8 +111,10 @@ extern "C"
|
|||
* John Wiley & Sons, pps 98-111 and 472-476.
|
||||
*/
|
||||
|
||||
//#define ULAW_ZEROTRAP /* turn on the trap as per the MIL-STD */
|
||||
#define ULAW_BIAS 0x84 /* Bias for linear code. */
|
||||
/* Enable the trap as per the MIL-STD */
|
||||
//#define ULAW_ZEROTRAP
|
||||
/*! Bias for u-law encoding from linear. */
|
||||
#define ULAW_BIAS 0x84
|
||||
|
||||
/*! \brief Encode a linear sample to u-law
|
||||
\param linear The sample to encode.
|
||||
|
@ -187,6 +194,7 @@ static __inline__ int16_t ulaw_to_linear(uint8_t ulaw)
|
|||
* John Wiley & Sons, pps 98-111 and 472-476.
|
||||
*/
|
||||
|
||||
/*! The A-law alternate mark inversion mask */
|
||||
#define ALAW_AMI_MASK 0x55
|
||||
|
||||
/*! \brief Encode a linear sample to A-law
|
||||
|
@ -259,16 +267,37 @@ SPAN_DECLARE(uint8_t) alaw_to_ulaw(uint8_t alaw);
|
|||
*/
|
||||
SPAN_DECLARE(uint8_t) ulaw_to_alaw(uint8_t ulaw);
|
||||
|
||||
/*! \brief Decode from u-law or A-law to linear.
|
||||
\param s The G.711 context.
|
||||
\param amp The linear audio buffer.
|
||||
\param g711_data The G.711 data.
|
||||
\param g711_bytes The number of G.711 samples to decode.
|
||||
\return The number of samples of linear audio produced.
|
||||
*/
|
||||
SPAN_DECLARE(int) g711_decode(g711_state_t *s,
|
||||
int16_t amp[],
|
||||
const uint8_t g711_data[],
|
||||
int g711_bytes);
|
||||
|
||||
/*! \brief Encode from linear to u-law or A-law.
|
||||
\param s The G.711 context.
|
||||
\param g711_data The G.711 data.
|
||||
\param amp The linear audio buffer.
|
||||
\param len The number of samples to encode.
|
||||
\return The number of G.711 samples produced.
|
||||
*/
|
||||
SPAN_DECLARE(int) g711_encode(g711_state_t *s,
|
||||
uint8_t g711_data[],
|
||||
const int16_t amp[],
|
||||
int len);
|
||||
|
||||
/*! \brief Transcode between u-law and A-law.
|
||||
\param s The G.711 context.
|
||||
\param g711_out The resulting G.711 data.
|
||||
\param g711_in The original G.711 data.
|
||||
\param g711_bytes The number of G.711 samples to transcode.
|
||||
\return The number of G.711 samples produced.
|
||||
*/
|
||||
SPAN_DECLARE(int) g711_transcode(g711_state_t *s,
|
||||
uint8_t g711_out[],
|
||||
const uint8_t g711_in[],
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
* Computer Science, Speech Group
|
||||
* Chengxiang Lu and Alex Hauptmann
|
||||
*
|
||||
* $Id: g722.h,v 1.25 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: g722.h,v 1.26 2009/04/12 09:12:10 steveu Exp $
|
||||
*/
|
||||
|
||||
|
||||
|
@ -56,8 +56,14 @@ enum
|
|||
G722_PACKED = 0x0002
|
||||
};
|
||||
|
||||
/*!
|
||||
G.722 encode state
|
||||
*/
|
||||
typedef struct g722_encode_state_s g722_encode_state_t;
|
||||
|
||||
/*!
|
||||
G.722 decode state
|
||||
*/
|
||||
typedef struct g722_decode_state_s g722_decode_state_t;
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
@ -73,8 +79,14 @@ extern "C"
|
|||
\return A pointer to the G.722 encode context, or NULL for error. */
|
||||
SPAN_DECLARE(g722_encode_state_t *) g722_encode_init(g722_encode_state_t *s, int rate, int options);
|
||||
|
||||
/*! Release a G.722 encode context.
|
||||
\param s The G.722 encode context.
|
||||
\return 0 for OK. */
|
||||
SPAN_DECLARE(int) g722_encode_release(g722_encode_state_t *s);
|
||||
|
||||
/*! Free a G.722 encode context.
|
||||
\param s The G.722 encode context.
|
||||
\return 0 for OK. */
|
||||
SPAN_DECLARE(int) g722_encode_free(g722_encode_state_t *s);
|
||||
|
||||
/*! Encode a buffer of linear PCM data to G.722
|
||||
|
@ -93,8 +105,14 @@ SPAN_DECLARE(int) g722_encode(g722_encode_state_t *s, uint8_t g722_data[], const
|
|||
\return A pointer to the G.722 decode context, or NULL for error. */
|
||||
SPAN_DECLARE(g722_decode_state_t *) g722_decode_init(g722_decode_state_t *s, int rate, int options);
|
||||
|
||||
/*! Release a G.722 decode context.
|
||||
\param s The G.722 decode context.
|
||||
\return 0 for OK. */
|
||||
SPAN_DECLARE(int) g722_decode_release(g722_decode_state_t *s);
|
||||
|
||||
/*! Free a G.722 decode context.
|
||||
\param s The G.722 decode context.
|
||||
\return 0 for OK. */
|
||||
SPAN_DECLARE(int) g722_decode_free(g722_decode_state_t *s);
|
||||
|
||||
/*! Decode a buffer of G.722 data to linear PCM.
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: g726.h,v 1.25 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: g726.h,v 1.26 2009/04/12 09:12:10 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -59,6 +59,9 @@ enum
|
|||
G726_PACKING_RIGHT = 2
|
||||
};
|
||||
|
||||
/*!
|
||||
G.726 state
|
||||
*/
|
||||
typedef struct g726_state_s g726_state_t;
|
||||
|
||||
typedef int16_t (*g726_decoder_func_t)(g726_state_t *s, uint8_t code);
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
* Based on a bit from here, a bit from there, eye of toad,
|
||||
* ear of bat, etc - plus, of course, my own 2 cents.
|
||||
*
|
||||
* $Id: ima_adpcm.h,v 1.24 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: ima_adpcm.h,v 1.25 2009/04/11 18:11:19 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -67,8 +67,8 @@ extern "C"
|
|||
#endif
|
||||
|
||||
/*! Initialise an IMA ADPCM encode or decode context.
|
||||
\param s The IMA ADPCM context
|
||||
\param variant ???
|
||||
\param s The IMA ADPCM context.
|
||||
\param variant IMA_ADPCM_IMA4, IMA_ADPCM_DVI4, or IMA_ADPCM_VDVI.
|
||||
\param chunk_size The size of a chunk, in samples. A chunk size of
|
||||
zero sample samples means treat each encode or decode operation
|
||||
as a chunk.
|
||||
|
@ -101,8 +101,8 @@ SPAN_DECLARE(int) ima_adpcm_encode(ima_adpcm_state_t *s,
|
|||
/*! Decode a buffer of IMA ADPCM data to linear PCM.
|
||||
\param s The IMA ADPCM context.
|
||||
\param amp The audio sample buffer.
|
||||
\param ima_data
|
||||
\param ima_bytes
|
||||
\param ima_data The IMA ADPCM data
|
||||
\param ima_bytes The number of bytes of IMA ADPCM data
|
||||
\return The number of samples returned. */
|
||||
SPAN_DECLARE(int) ima_adpcm_decode(ima_adpcm_state_t *s,
|
||||
int16_t amp[],
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: lpc10.h,v 1.21 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: lpc10.h,v 1.22 2009/04/11 18:11:19 steveu Exp $
|
||||
*/
|
||||
|
||||
#if !defined(_SPANDSP_LPC10_H_)
|
||||
|
@ -48,8 +48,11 @@ or other restrictions.
|
|||
*/
|
||||
typedef struct
|
||||
{
|
||||
/*! Pitch */
|
||||
int32_t ipitch;
|
||||
/*! Energy */
|
||||
int32_t irms;
|
||||
/*! Reflection coefficients */
|
||||
int32_t irc[10];
|
||||
} lpc10_frame_t;
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: adsi.h,v 1.1 2008/10/13 13:14:01 steveu Exp $
|
||||
* $Id: adsi.h,v 1.4 2009/04/12 04:20:01 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -36,27 +36,45 @@
|
|||
*/
|
||||
struct adsi_tx_state_s
|
||||
{
|
||||
/*! */
|
||||
int standard;
|
||||
|
||||
/*! */
|
||||
tone_gen_descriptor_t alert_tone_desc;
|
||||
/*! */
|
||||
tone_gen_state_t alert_tone_gen;
|
||||
/*! */
|
||||
fsk_tx_state_t fsktx;
|
||||
/*! */
|
||||
dtmf_tx_state_t dtmftx;
|
||||
/*! */
|
||||
async_tx_state_t asynctx;
|
||||
|
||||
|
||||
/*! */
|
||||
int tx_signal_on;
|
||||
|
||||
|
||||
/*! */
|
||||
int byte_no;
|
||||
/*! */
|
||||
int bit_pos;
|
||||
/*! */
|
||||
int bit_no;
|
||||
/*! */
|
||||
uint8_t msg[256];
|
||||
/*! */
|
||||
int msg_len;
|
||||
/*! */
|
||||
int preamble_len;
|
||||
/*! */
|
||||
int preamble_ones_len;
|
||||
/*! */
|
||||
int postamble_ones_len;
|
||||
/*! */
|
||||
int stop_bits;
|
||||
/*! */
|
||||
int baudot_shift;
|
||||
|
||||
/*! */
|
||||
logging_state_t logging;
|
||||
};
|
||||
|
||||
|
@ -66,24 +84,35 @@ struct adsi_tx_state_s
|
|||
*/
|
||||
struct adsi_rx_state_s
|
||||
{
|
||||
/*! */
|
||||
int standard;
|
||||
/*! */
|
||||
put_msg_func_t put_msg;
|
||||
/*! */
|
||||
void *user_data;
|
||||
|
||||
/*! */
|
||||
fsk_rx_state_t fskrx;
|
||||
/*! */
|
||||
dtmf_rx_state_t dtmfrx;
|
||||
async_rx_state_t asyncrx;
|
||||
|
||||
|
||||
/*! */
|
||||
int consecutive_ones;
|
||||
/*! */
|
||||
int bit_pos;
|
||||
/*! */
|
||||
int in_progress;
|
||||
/*! */
|
||||
uint8_t msg[256];
|
||||
/*! */
|
||||
int msg_len;
|
||||
/*! */
|
||||
int baudot_shift;
|
||||
|
||||
/*! A count of the framing errors. */
|
||||
int framing_errors;
|
||||
|
||||
/*! */
|
||||
logging_state_t logging;
|
||||
};
|
||||
|
||||
|
|
|
@ -22,12 +22,39 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: bert.h,v 1.1 2008/11/30 12:38:27 steveu Exp $
|
||||
* $Id: bert.h,v 1.2 2009/04/14 16:04:54 steveu Exp $
|
||||
*/
|
||||
|
||||
#if !defined(_SPANDSP_PRIVATE_BERT_H_)
|
||||
#define _SPANDSP_PRIVATE_BERT_H_
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t reg;
|
||||
int step;
|
||||
int step_bit;
|
||||
int bits;
|
||||
int zeros;
|
||||
} bert_tx_state_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t reg;
|
||||
uint32_t ref_reg;
|
||||
uint32_t master_reg;
|
||||
int step;
|
||||
int step_bit;
|
||||
int resync;
|
||||
int bits;
|
||||
int zeros;
|
||||
int resync_len;
|
||||
int resync_percent;
|
||||
int resync_bad_bits;
|
||||
int resync_cnt;
|
||||
int report_countdown;
|
||||
int measurement_step;
|
||||
} bert_rx_state_t;
|
||||
|
||||
/*!
|
||||
Bit error rate tester (BERT) descriptor. This defines the working state for a
|
||||
single instance of the BERT.
|
||||
|
@ -41,25 +68,6 @@ struct bert_state_s
|
|||
int report_frequency;
|
||||
int limit;
|
||||
|
||||
uint32_t tx_reg;
|
||||
int tx_step;
|
||||
int tx_step_bit;
|
||||
int tx_bits;
|
||||
int tx_zeros;
|
||||
|
||||
uint32_t rx_reg;
|
||||
uint32_t ref_reg;
|
||||
uint32_t master_reg;
|
||||
int rx_step;
|
||||
int rx_step_bit;
|
||||
int resync;
|
||||
int rx_bits;
|
||||
int rx_zeros;
|
||||
int resync_len;
|
||||
int resync_percent;
|
||||
int resync_bad_bits;
|
||||
int resync_cnt;
|
||||
|
||||
uint32_t mask;
|
||||
int shift;
|
||||
int shift2;
|
||||
|
@ -69,11 +77,10 @@ struct bert_state_s
|
|||
|
||||
int decade_ptr[9];
|
||||
int decade_bad[9][10];
|
||||
int step;
|
||||
int error_rate;
|
||||
|
||||
int bit_error_status;
|
||||
int report_countdown;
|
||||
bert_tx_state_t tx;
|
||||
bert_rx_state_t rx;
|
||||
|
||||
bert_results_t results;
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: fax_modems.h,v 1.2 2009/02/14 15:21:14 steveu Exp $
|
||||
* $Id: fax_modems.h,v 1.3 2009/03/23 14:17:42 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -97,6 +97,10 @@ struct fax_modems_state_s
|
|||
span_rx_handler_t *rx_handler;
|
||||
void *rx_user_data;
|
||||
|
||||
/*! The current receive missing signal fill-in handler */
|
||||
span_rx_fillin_handler_t *rx_fillin_handler;
|
||||
void *rx_fillin_user_data;
|
||||
|
||||
/*! The current transmit signal handler */
|
||||
span_tx_handler_t *tx_handler;
|
||||
void *tx_user_data;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: fsk.h,v 1.2 2009/01/29 18:30:14 steveu Exp $
|
||||
* $Id: fsk.h,v 1.5 2009/04/01 13:22:40 steveu Exp $
|
||||
*/
|
||||
|
||||
#if !defined(_SPANDSP_PRIVATE_FSK_H_)
|
||||
|
@ -50,7 +50,6 @@ struct fsk_tx_state_s
|
|||
int32_t current_phase_rate;
|
||||
uint32_t phase_acc;
|
||||
int baud_frac;
|
||||
int baud_inc;
|
||||
int shutdown;
|
||||
};
|
||||
|
||||
|
@ -61,7 +60,8 @@ struct fsk_tx_state_s
|
|||
struct fsk_rx_state_s
|
||||
{
|
||||
int baud_rate;
|
||||
int sync_mode;
|
||||
/*! \brief Synchronous/asynchronous framing control */
|
||||
int framing_mode;
|
||||
/*! \brief The callback function used to put each bit received. */
|
||||
put_bit_func_t put_bit;
|
||||
/*! \brief A user specified opaque pointer passed to the put_bit routine. */
|
||||
|
@ -89,9 +89,10 @@ struct fsk_rx_state_s
|
|||
complexi32_t dot[2];
|
||||
int buf_ptr;
|
||||
|
||||
int baud_inc;
|
||||
int baud_pll;
|
||||
int lastbit;
|
||||
int frame_state;
|
||||
int frame_bits;
|
||||
int baud_phase;
|
||||
int last_bit;
|
||||
int scaling_shift;
|
||||
};
|
||||
|
||||
|
|
|
@ -22,12 +22,15 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: g711.h,v 1.1 2008/11/30 10:17:31 steveu Exp $
|
||||
* $Id: g711.h,v 1.2 2009/04/12 09:12:11 steveu Exp $
|
||||
*/
|
||||
|
||||
#if !defined(_SPANDSP_PRIVATE_G711_H_)
|
||||
#define _SPANDSP_PRIVATE_G711_H_
|
||||
|
||||
/*!
|
||||
G.711 state
|
||||
*/
|
||||
struct g711_state_s
|
||||
{
|
||||
/*! One of the G.711_xxx options */
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
* Computer Science, Speech Group
|
||||
* Chengxiang Lu and Alex Hauptmann
|
||||
*
|
||||
* $Id: g722.h,v 1.1 2008/10/13 13:14:01 steveu Exp $
|
||||
* $Id: g722.h,v 1.2 2009/04/12 09:12:11 steveu Exp $
|
||||
*/
|
||||
|
||||
|
||||
|
@ -51,6 +51,9 @@ typedef struct
|
|||
int16_t d[7];
|
||||
} g722_band_t;
|
||||
|
||||
/*!
|
||||
G.722 encode state
|
||||
*/
|
||||
struct g722_encode_state_s
|
||||
{
|
||||
/*! TRUE if the operating in the special ITU test mode, with the band split filters
|
||||
|
@ -76,6 +79,9 @@ struct g722_encode_state_s
|
|||
int out_bits;
|
||||
};
|
||||
|
||||
/*!
|
||||
G.722 decode state
|
||||
*/
|
||||
struct g722_decode_state_s
|
||||
{
|
||||
/*! TRUE if the operating in the special ITU test mode, with the band split filters
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: g726.h,v 1.3 2009/01/29 18:30:14 steveu Exp $
|
||||
* $Id: g726.h,v 1.4 2009/04/12 09:12:11 steveu Exp $
|
||||
*/
|
||||
|
||||
#if !defined(_SPANDSP_PRIVATE_G726_H_)
|
||||
|
@ -33,7 +33,7 @@
|
|||
* used by the G.726 encoder and decoder to preserve their internal
|
||||
* state between successive calls. The meanings of the majority
|
||||
* of the state structure fields are explained in detail in the
|
||||
* CCITT Recommendation G.726. The field names are essentially indentical
|
||||
* ITU Recommendation G.726. The field names are essentially indentical
|
||||
* to variable names in the bit level description of the coding algorithm
|
||||
* included in this recommendation.
|
||||
*/
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: lpc10.h,v 1.1 2008/11/30 05:43:37 steveu Exp $
|
||||
* $Id: lpc10.h,v 1.3 2009/04/12 09:12:11 steveu Exp $
|
||||
*/
|
||||
|
||||
#if !defined(_SPANDSP_PRIVATE_LPC10_H_)
|
||||
|
@ -34,62 +34,107 @@
|
|||
*/
|
||||
struct lpc10_encode_state_s
|
||||
{
|
||||
/*! \brief ??? */
|
||||
int error_correction;
|
||||
|
||||
/* State used only by function high_pass_100hz */
|
||||
/*! \brief ??? */
|
||||
float z11;
|
||||
/*! \brief ??? */
|
||||
float z21;
|
||||
/*! \brief ??? */
|
||||
float z12;
|
||||
/*! \brief ??? */
|
||||
float z22;
|
||||
|
||||
/* State used by function lpc10_analyse */
|
||||
/*! \brief ??? */
|
||||
float inbuf[LPC10_SAMPLES_PER_FRAME*3];
|
||||
/*! \brief ??? */
|
||||
float pebuf[LPC10_SAMPLES_PER_FRAME*3];
|
||||
/*! \brief ??? */
|
||||
float lpbuf[696];
|
||||
/*! \brief ??? */
|
||||
float ivbuf[312];
|
||||
/*! \brief ??? */
|
||||
float bias;
|
||||
int32_t osbuf[10]; /* No initial value necessary */
|
||||
int32_t osptr; /* Initial value 1 */
|
||||
/*! \brief No initial value necessary */
|
||||
int32_t osbuf[10];
|
||||
/*! \brief Initial value 1 */
|
||||
int32_t osptr;
|
||||
/*! \brief ??? */
|
||||
int32_t obound[3];
|
||||
int32_t vwin[3][2]; /* Initial value vwin[2][0] = 307; vwin[2][1] = 462; */
|
||||
int32_t awin[3][2]; /* Initial value awin[2][0] = 307; awin[2][1] = 462; */
|
||||
/*! \brief Initial value vwin[2][0] = 307; vwin[2][1] = 462; */
|
||||
int32_t vwin[3][2];
|
||||
/*! \brief Initial value awin[2][0] = 307; awin[2][1] = 462; */
|
||||
int32_t awin[3][2];
|
||||
/*! \brief ??? */
|
||||
int32_t voibuf[4][2];
|
||||
/*! \brief ??? */
|
||||
float rmsbuf[3];
|
||||
/*! \brief ??? */
|
||||
float rcbuf[3][10];
|
||||
/*! \brief ??? */
|
||||
float zpre;
|
||||
|
||||
/* State used by function onset */
|
||||
/*! \brief ??? */
|
||||
float n;
|
||||
float d__; /* Initial value 1.0f */
|
||||
float fpc; /* No initial value necessary */
|
||||
/*! \brief Initial value 1.0f */
|
||||
float d__;
|
||||
/*! \brief No initial value necessary */
|
||||
float fpc;
|
||||
/*! \brief ??? */
|
||||
float l2buf[16];
|
||||
/*! \brief ??? */
|
||||
float l2sum1;
|
||||
int32_t l2ptr1; /* Initial value 1 */
|
||||
int32_t l2ptr2; /* Initial value 9 */
|
||||
int32_t lasti; /* No initial value necessary */
|
||||
int hyst; /* Initial value FALSE */
|
||||
/*! \brief Initial value 1 */
|
||||
int32_t l2ptr1;
|
||||
/*! \brief Initial value 9 */
|
||||
int32_t l2ptr2;
|
||||
/*! \brief No initial value necessary */
|
||||
int32_t lasti;
|
||||
/*! \brief Initial value FALSE */
|
||||
int hyst;
|
||||
|
||||
/* State used by function lpc10_voicing */
|
||||
float dither; /* Initial value 20.0f */
|
||||
/*! \brief Initial value 20.0f */
|
||||
float dither;
|
||||
/*! \brief ??? */
|
||||
float snr;
|
||||
/*! \brief ??? */
|
||||
float maxmin;
|
||||
float voice[3][2]; /* Initial value is probably unnecessary */
|
||||
/*! \brief Initial value is probably unnecessary */
|
||||
float voice[3][2];
|
||||
/*! \brief ??? */
|
||||
int32_t lbve;
|
||||
/*! \brief ??? */
|
||||
int32_t lbue;
|
||||
/*! \brief ??? */
|
||||
int32_t fbve;
|
||||
/*! \brief ??? */
|
||||
int32_t fbue;
|
||||
/*! \brief ??? */
|
||||
int32_t ofbue;
|
||||
/*! \brief ??? */
|
||||
int32_t sfbue;
|
||||
/*! \brief ??? */
|
||||
int32_t olbue;
|
||||
/*! \brief ??? */
|
||||
int32_t slbue;
|
||||
|
||||
/* State used by function dynamic_pitch_tracking */
|
||||
/*! \brief ??? */
|
||||
float s[60];
|
||||
/*! \brief ??? */
|
||||
int32_t p[2][60];
|
||||
/*! \brief ??? */
|
||||
int32_t ipoint;
|
||||
/*! \brief ??? */
|
||||
float alphax;
|
||||
|
||||
/* State used by function lpc10_pack */
|
||||
/*! \brief ??? */
|
||||
int32_t isync;
|
||||
};
|
||||
|
||||
|
@ -99,46 +144,75 @@ struct lpc10_encode_state_s
|
|||
*/
|
||||
struct lpc10_decode_state_s
|
||||
{
|
||||
/*! \brief ??? */
|
||||
int error_correction;
|
||||
|
||||
/* State used by function decode */
|
||||
int32_t iptold; /* Initial value 60 */
|
||||
int first; /* Initial value TRUE */
|
||||
/*! \brief Initial value 60 */
|
||||
int32_t iptold;
|
||||
/*! \brief Initial value TRUE */
|
||||
int first;
|
||||
/*! \brief ??? */
|
||||
int32_t ivp2h;
|
||||
/*! \brief ??? */
|
||||
int32_t iovoic;
|
||||
int32_t iavgp; /* Initial value 60 */
|
||||
/*! \brief Initial value 60. */
|
||||
int32_t iavgp;
|
||||
/*! \brief ??? */
|
||||
int32_t erate;
|
||||
/*! \brief ??? */
|
||||
int32_t drc[10][3];
|
||||
/*! \brief ??? */
|
||||
int32_t dpit[3];
|
||||
/*! \brief ??? */
|
||||
int32_t drms[3];
|
||||
|
||||
/* State used by function synths */
|
||||
/*! \brief ??? */
|
||||
float buf[LPC10_SAMPLES_PER_FRAME*2];
|
||||
int32_t buflen; /* Initial value LPC10_SAMPLES_PER_FRAME */
|
||||
/*! \brief Initial value LPC10_SAMPLES_PER_FRAME */
|
||||
int32_t buflen;
|
||||
|
||||
/* State used by function pitsyn */
|
||||
int32_t ivoico; /* No initial value necessary as long as first_pitsyn is initially TRUE_ */
|
||||
int32_t ipito; /* No initial value necessary as long as first_pitsyn is initially TRUE_ */
|
||||
float rmso; /* Initial value 1.0f */
|
||||
float rco[10]; /* No initial value necessary as long as first_pitsyn is initially TRUE_ */
|
||||
int32_t jsamp; /* Nno initial value necessary as long as first_pitsyn is initially TRUE_ */
|
||||
int first_pitsyn; /* Initial value TRUE */
|
||||
/*! \brief No initial value necessary as long as first_pitsyn is initially TRUE */
|
||||
int32_t ivoico;
|
||||
/*! \brief No initial value necessary as long as first_pitsyn is initially TRUE */
|
||||
int32_t ipito;
|
||||
/*! \brief Initial value 1.0f */
|
||||
float rmso;
|
||||
/*! \brief No initial value necessary as long as first_pitsyn is initially TRUE */
|
||||
float rco[10];
|
||||
/*! \brief No initial value necessary as long as first_pitsyn is initially TRUE */
|
||||
int32_t jsamp;
|
||||
/*! \brief Initial value TRUE */
|
||||
int first_pitsyn;
|
||||
|
||||
/* State used by function bsynz */
|
||||
/*! \brief ??? */
|
||||
int32_t ipo;
|
||||
/*! \brief ??? */
|
||||
float exc[166];
|
||||
/*! \brief ??? */
|
||||
float exc2[166];
|
||||
/*! \brief ??? */
|
||||
float lpi[3];
|
||||
/*! \brief ??? */
|
||||
float hpi[3];
|
||||
/*! \brief ??? */
|
||||
float rmso_bsynz;
|
||||
|
||||
/* State used by function random */
|
||||
/*! \brief ??? */
|
||||
int32_t j;
|
||||
/*! \brief ??? */
|
||||
int32_t k;
|
||||
/*! \brief ??? */
|
||||
int16_t y[5];
|
||||
|
||||
/* State used by function deemp */
|
||||
/*! \brief ??? */
|
||||
float dei[2];
|
||||
/*! \brief ??? */
|
||||
float deo[3];
|
||||
};
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: sig_tone.h,v 1.2 2009/01/30 07:19:25 steveu Exp $
|
||||
* $Id: sig_tone.h,v 1.3 2009/04/12 14:18:02 steveu Exp $
|
||||
*/
|
||||
|
||||
#if !defined(_SPANDSP_PRIVATE_SIG_TONE_H_)
|
||||
|
@ -53,6 +53,7 @@ struct sig_tone_descriptor_s
|
|||
/*! \brief Parameters to control the behaviour of the notch filter, used
|
||||
to remove the tone from the voice path in some protocols. */
|
||||
int notch_lag_time;
|
||||
/*! \brief TRUE if the notch may be used in the media flow. */
|
||||
int notch_allowed;
|
||||
|
||||
/*! \brief The tone on persistence check, in audio samples. */
|
||||
|
@ -60,6 +61,7 @@ struct sig_tone_descriptor_s
|
|||
/*! \brief The tone off persistence check, in audio samples. */
|
||||
int tone_off_check_time;
|
||||
|
||||
/*! \brief ??? */
|
||||
int tones;
|
||||
/*! \brief The coefficients for the cascaded bi-quads notch filter. */
|
||||
struct
|
||||
|
@ -79,17 +81,22 @@ struct sig_tone_descriptor_s
|
|||
} tone[2];
|
||||
|
||||
|
||||
/*! \brief Flat mode bandpass bi-quad parameters */
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
/*! \brief Flat mode bandpass bi-quad parameters */
|
||||
int32_t broad_a[3];
|
||||
/*! \brief Flat mode bandpass bi-quad parameters */
|
||||
int32_t broad_b[3];
|
||||
/*! \brief Post filter scaling */
|
||||
int broad_postscale;
|
||||
#else
|
||||
/*! \brief Flat mode bandpass bi-quad parameters */
|
||||
float broad_a[3];
|
||||
/*! \brief Flat mode bandpass bi-quad parameters */
|
||||
float broad_b[3];
|
||||
#endif
|
||||
/*! \brief The coefficients for the post notch leaky integrator. */
|
||||
int32_t notch_slugi;
|
||||
/*! \brief ??? */
|
||||
int32_t notch_slugp;
|
||||
|
||||
/*! \brief The coefficients for the post modulus leaky integrator in the
|
||||
|
@ -97,20 +104,27 @@ struct sig_tone_descriptor_s
|
|||
detection ratio. This is called the guard ratio in some
|
||||
protocols. */
|
||||
int32_t unfiltered_slugi;
|
||||
/*! \brief ??? */
|
||||
int32_t unfiltered_slugp;
|
||||
|
||||
/*! \brief The coefficients for the post modulus leaky integrator in the
|
||||
bandpass filter data path. */
|
||||
int32_t broad_slugi;
|
||||
/*! \brief ??? */
|
||||
int32_t broad_slugp;
|
||||
|
||||
/*! \brief Masks which effectively threshold the notched, weighted and
|
||||
bandpassed data. */
|
||||
int32_t notch_threshold;
|
||||
/*! \brief ??? */
|
||||
int32_t unfiltered_threshold;
|
||||
/*! \brief ??? */
|
||||
int32_t broad_threshold;
|
||||
};
|
||||
|
||||
/*!
|
||||
Signaling tone transmit state
|
||||
*/
|
||||
struct sig_tone_tx_state_s
|
||||
{
|
||||
/*! \brief The callback function used to handle signaling changes. */
|
||||
|
@ -118,6 +132,7 @@ struct sig_tone_tx_state_s
|
|||
/*! \brief A user specified opaque pointer passed to the callback function. */
|
||||
void *user_data;
|
||||
|
||||
/*! \brief Tone descriptor */
|
||||
sig_tone_descriptor_t *desc;
|
||||
|
||||
/*! The scaling values for the high and low level tones */
|
||||
|
@ -130,11 +145,17 @@ struct sig_tone_tx_state_s
|
|||
/*! The phase accumulators for the one or two tones */
|
||||
uint32_t phase_acc[2];
|
||||
|
||||
/*! \brief Current transmit tone */
|
||||
int current_tx_tone;
|
||||
/*! \brief Current transmit timeout */
|
||||
int current_tx_timeout;
|
||||
/*! \brief Time in current signaling state, in samples. */
|
||||
int signaling_state_duration;
|
||||
};
|
||||
|
||||
/*!
|
||||
Signaling tone receive state
|
||||
*/
|
||||
struct sig_tone_rx_state_s
|
||||
{
|
||||
/*! \brief The callback function used to handle signaling changes. */
|
||||
|
@ -142,19 +163,25 @@ struct sig_tone_rx_state_s
|
|||
/*! \brief A user specified opaque pointer passed to the callback function. */
|
||||
void *user_data;
|
||||
|
||||
/*! \brief Tone descriptor */
|
||||
sig_tone_descriptor_t *desc;
|
||||
|
||||
/*! \brief The current receive tone */
|
||||
int current_rx_tone;
|
||||
/*! \brief The timeout for switching from the high level to low level tone detector. */
|
||||
int high_low_timer;
|
||||
|
||||
struct
|
||||
{
|
||||
/*! \brief The z's for the notch filter */
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
/*! \brief The z's for the notch filter */
|
||||
int32_t notch_z1[3];
|
||||
/*! \brief The z's for the notch filter */
|
||||
int32_t notch_z2[3];
|
||||
#else
|
||||
/*! \brief The z's for the notch filter */
|
||||
float notch_z1[3];
|
||||
/*! \brief The z's for the notch filter */
|
||||
float notch_z2[3];
|
||||
#endif
|
||||
|
||||
|
@ -162,22 +189,30 @@ struct sig_tone_rx_state_s
|
|||
int32_t notch_zl;
|
||||
} tone[2];
|
||||
|
||||
/*! \brief The z's for the weighting/bandpass filter. */
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
/*! \brief The z's for the weighting/bandpass filter. */
|
||||
int32_t broad_z[3];
|
||||
#else
|
||||
/*! \brief The z's for the weighting/bandpass filter. */
|
||||
float broad_z[3];
|
||||
#endif
|
||||
/*! \brief The z for the broadband integrator. */
|
||||
int32_t broad_zl;
|
||||
|
||||
/*! \brief ??? */
|
||||
int flat_mode;
|
||||
/*! \brief ??? */
|
||||
int tone_present;
|
||||
/*! \brief ??? */
|
||||
int notch_enabled;
|
||||
/*! \brief ??? */
|
||||
int flat_mode_timeout;
|
||||
/*! \brief ??? */
|
||||
int notch_insertion_timeout;
|
||||
/*! \brief ??? */
|
||||
int tone_persistence_timeout;
|
||||
|
||||
/*! \brief ??? */
|
||||
int signaling_state_duration;
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* SpanDSP - a series of DSP components for telephony
|
||||
*
|
||||
* private/silence_gen.c - A silence generator, for inserting timed silences.
|
||||
*
|
||||
* Written by Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* Copyright (C) 2006 Steve Underwood
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License version 2.1,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: silence_gen.h,v 1.1 2009/04/12 03:29:58 steveu Exp $
|
||||
*/
|
||||
|
||||
#if !defined(_SPANDSP_PRIVATE_SILENCE_GEN_H_)
|
||||
#define _SPANDSP_PRIVATE_SILENCE_GEN_H_
|
||||
|
||||
struct silence_gen_state_s
|
||||
{
|
||||
/*! \brief The callback function used to report status changes. */
|
||||
modem_tx_status_func_t status_handler;
|
||||
/*! \brief A user specified opaque pointer passed to the status function. */
|
||||
void *status_user_data;
|
||||
|
||||
int remaining_samples;
|
||||
int total_samples;
|
||||
};
|
||||
|
||||
#endif
|
||||
/*- End of file ------------------------------------------------------------*/
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: t30.h,v 1.3 2009/01/29 18:30:14 steveu Exp $
|
||||
* $Id: t30.h,v 1.4 2009/04/12 14:18:02 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -41,6 +41,7 @@ struct t30_state_s
|
|||
/*! \brief T.4 context for reading or writing image data. */
|
||||
t4_state_t t4;
|
||||
|
||||
/*! \brief The type of FAX operation currently in progress */
|
||||
int operation_in_progress;
|
||||
|
||||
/*! \brief TRUE if behaving as the calling party */
|
||||
|
@ -235,8 +236,10 @@ struct t30_state_s
|
|||
/*! \brief TRUE if we are at the end of an ECM page to se sent - i.e. there are no more
|
||||
partial pages still to come. */
|
||||
int ecm_at_page_end;
|
||||
|
||||
/*! \brief The transmission step queued to follow the one in progress. */
|
||||
int next_tx_step;
|
||||
/* The FCF for the next receive step */
|
||||
/*! \brief The FCF for the next receive step. */
|
||||
uint8_t next_rx_step;
|
||||
/*! \brief Image file name for image reception. */
|
||||
char rx_file[256];
|
||||
|
@ -248,6 +251,7 @@ struct t30_state_s
|
|||
int tx_start_page;
|
||||
/*! \brief The last page to be sent from the image file. -1 means no restriction. */
|
||||
int tx_stop_page;
|
||||
/*! \brief The current completion status. */
|
||||
int current_status;
|
||||
/*! \brief Internet Aware FAX mode bit mask. */
|
||||
int iaf;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: t38_core.h,v 1.2 2009/01/19 17:14:10 steveu Exp $
|
||||
* $Id: t38_core.h,v 1.3 2009/04/12 14:18:02 steveu Exp $
|
||||
*/
|
||||
|
||||
#if !defined(_SPANDSP_PRIVATE_T38_CORE_H_)
|
||||
|
@ -33,18 +33,18 @@
|
|||
*/
|
||||
struct t38_core_state_s
|
||||
{
|
||||
/*! Handler routine to transmit IFP packets generated by the T.38 protocol engine */
|
||||
/*! \brief Handler routine to transmit IFP packets generated by the T.38 protocol engine */
|
||||
t38_tx_packet_handler_t *tx_packet_handler;
|
||||
/*! An opaque pointer passed to tx_packet_handler */
|
||||
/*! \brief An opaque pointer passed to tx_packet_handler */
|
||||
void *tx_packet_user_data;
|
||||
|
||||
/*! Handler routine to process received indicator packets */
|
||||
/*! \brief Handler routine to process received indicator packets */
|
||||
t38_rx_indicator_handler_t *rx_indicator_handler;
|
||||
/*! Handler routine to process received data packets */
|
||||
/*! \brief Handler routine to process received data packets */
|
||||
t38_rx_data_handler_t *rx_data_handler;
|
||||
/*! Handler routine to process the missing packet condition */
|
||||
/*! \brief Handler routine to process the missing packet condition */
|
||||
t38_rx_missing_handler_t *rx_missing_handler;
|
||||
/*! An opaque pointer passed to any of the above receive handling routines */
|
||||
/*! \brief An opaque pointer passed to any of the above receive handling routines */
|
||||
void *rx_user_data;
|
||||
|
||||
/*! NOTE - Bandwidth reduction shall only be done on suitable Phase C data, i.e., MH, MR
|
||||
|
@ -52,49 +52,49 @@ struct t38_core_state_s
|
|||
transport such as that provided by TCP. When transcoding is selected, it shall be
|
||||
applied to every suitable page in a call. */
|
||||
|
||||
/*! Method 1: Local generation of TCF (required for use with TCP).
|
||||
Method 2: Transfer of TCF is required for use with UDP (UDPTL or RTP).
|
||||
Method 2 is not recommended for use with TCP. */
|
||||
/*! \brief Method 1: Local generation of TCF (required for use with TCP).
|
||||
Method 2: Transfer of TCF is required for use with UDP (UDPTL or RTP).
|
||||
Method 2 is not recommended for use with TCP. */
|
||||
int data_rate_management_method;
|
||||
|
||||
/*! The emitting gateway may indicate a preference for either UDP/UDPTL, or
|
||||
UDP/RTP, or TCP for transport of T.38 IFP Packets. The receiving device
|
||||
selects the transport protocol. */
|
||||
/*! \brief The emitting gateway may indicate a preference for either UDP/UDPTL, or
|
||||
UDP/RTP, or TCP for transport of T.38 IFP Packets. The receiving device
|
||||
selects the transport protocol. */
|
||||
int data_transport_protocol;
|
||||
|
||||
/*! Indicates the capability to remove and insert fill bits in Phase C, non-ECM
|
||||
/*! \brief Indicates the capability to remove and insert fill bits in Phase C, non-ECM
|
||||
data to reduce bandwidth in the packet network. */
|
||||
int fill_bit_removal;
|
||||
|
||||
/*! Indicates the ability to convert to/from MMR from/to the line format to
|
||||
/*! \brief Indicates the ability to convert to/from MMR from/to the line format to
|
||||
improve the compression of the data, and reduce the bandwidth, in the
|
||||
packet network. */
|
||||
int mmr_transcoding;
|
||||
|
||||
/*! Indicates the ability to convert to/from JBIG to reduce bandwidth. */
|
||||
/*! \brief Indicates the ability to convert to/from JBIG to reduce bandwidth. */
|
||||
int jbig_transcoding;
|
||||
|
||||
/*! For UDP (UDPTL or RTP) modes, this option indicates the maximum
|
||||
number of octets that can be stored on the remote device before an overflow
|
||||
condition occurs. It is the responsibility of the transmitting application to
|
||||
limit the transfer rate to prevent an overflow. The negotiated data rate
|
||||
should be used to determine the rate at which data is being removed from
|
||||
the buffer. */
|
||||
/*! \brief For UDP (UDPTL or RTP) modes, this option indicates the maximum
|
||||
number of octets that can be stored on the remote device before an
|
||||
overflow condition occurs. It is the responsibility of the transmitting
|
||||
application to limit the transfer rate to prevent an overflow. The
|
||||
negotiated data rate should be used to determine the rate at which
|
||||
data is being removed from the buffer. */
|
||||
int max_buffer_size;
|
||||
|
||||
/*! This option indicates the maximum size of a UDPTL packet or the
|
||||
maximum size of the payload within an RTP packet that can be accepted by
|
||||
the remote device. */
|
||||
/*! \brief This option indicates the maximum size of a UDPTL packet or the
|
||||
maximum size of the payload within an RTP packet that can be accepted
|
||||
by the remote device. */
|
||||
int max_datagram_size;
|
||||
|
||||
/*! This is the version number of ITU-T Rec. T.38. New versions shall be
|
||||
compatible with previous versions. */
|
||||
/*! \brief This is the version number of ITU-T Rec. T.38. New versions shall be
|
||||
compatible with previous versions. */
|
||||
int t38_version;
|
||||
|
||||
/*! Allow time for TEP playout */
|
||||
/*! \brief Allow time for TEP playout */
|
||||
int allow_for_tep;
|
||||
|
||||
/*! The fastest data rate supported by the T.38 channel. */
|
||||
/*! \brief The fastest data rate supported by the T.38 channel. */
|
||||
int fastest_image_data_rate;
|
||||
|
||||
/*! \brief The number of times an indicator packet will be sent. Numbers greater than one
|
||||
|
@ -111,30 +111,31 @@ struct t38_core_state_s
|
|||
greater than one will increase reliability for UDP transmission. Zero is not valid. */
|
||||
int data_end_tx_count;
|
||||
|
||||
/*! TRUE if IFP packet sequence numbers are relevant. For some transports, like TPKT
|
||||
over TCP they are not relevent. */
|
||||
/*! \brief TRUE if IFP packet sequence numbers are relevant. For some transports, like TPKT
|
||||
over TCP they are not relevent. */
|
||||
int check_sequence_numbers;
|
||||
|
||||
/*! The sequence number for the next packet to be transmitted */
|
||||
/*! \brief The sequence number for the next packet to be transmitted */
|
||||
int tx_seq_no;
|
||||
/*! The sequence number expected in the next received packet */
|
||||
/*! \brief The sequence number expected in the next received packet */
|
||||
int rx_expected_seq_no;
|
||||
|
||||
/*! The current receive indicator - i.e. the last indicator received */
|
||||
/*! \brief The current receive indicator - i.e. the last indicator received */
|
||||
int current_rx_indicator;
|
||||
/*! The current receive data type - i.e. the last data type received */
|
||||
/*! \brief The current receive data type - i.e. the last data type received */
|
||||
int current_rx_data_type;
|
||||
/*! The current receive field type - i.e. the last field_type received */
|
||||
/*! \brief The current receive field type - i.e. the last field_type received */
|
||||
int current_rx_field_type;
|
||||
/*! The current transmit indicator - i.e. the last indicator transmitted */
|
||||
/*! \brief The current transmit indicator - i.e. the last indicator transmitted */
|
||||
int current_tx_indicator;
|
||||
/*! The bit rate for V.34 operation */
|
||||
/*! \brief The bit rate for V.34 operation */
|
||||
int v34_rate;
|
||||
|
||||
/*! A count of missing receive packets. This count might not be accurate if the
|
||||
received packet numbers jump wildly. */
|
||||
int missing_packets;
|
||||
|
||||
/*! \brief Error and flow logging control */
|
||||
logging_state_t logging;
|
||||
};
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: t38_gateway.h,v 1.1 2008/10/13 13:14:01 steveu Exp $
|
||||
* $Id: t38_gateway.h,v 1.3 2009/04/12 14:18:02 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -59,12 +59,16 @@ typedef struct
|
|||
*/
|
||||
typedef struct
|
||||
{
|
||||
/*! \brief The FAX modem set for the audio side fo the gateway. */
|
||||
fax_modems_state_t modems;
|
||||
/*! \brief The current receive signal handler. Actual receiving hop between this
|
||||
and a dummy receive routine. */
|
||||
span_rx_handler_t *base_rx_handler;
|
||||
} t38_gateway_audio_state_t;
|
||||
|
||||
/*!
|
||||
T.38 gateway T.38 side state.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/*! \brief non-ECM and HDLC modem receive data buffer. */
|
||||
|
@ -87,10 +91,15 @@ typedef struct
|
|||
rate and the current specified packet interval. */
|
||||
int octets_per_data_packet;
|
||||
|
||||
/*! \brief Bits into the non-ECM buffer */
|
||||
int in_bits;
|
||||
/*! \brief Octets fed out from the non-ECM buffer */
|
||||
int out_octets;
|
||||
} t38_gateway_to_t38_state_t;
|
||||
|
||||
/*!
|
||||
T.38 gateway HDLC buffer.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/*! \brief HDLC message buffers. */
|
||||
|
@ -103,6 +112,9 @@ typedef struct
|
|||
int contents;
|
||||
} t38_gateway_hdlc_buf_t;
|
||||
|
||||
/*!
|
||||
T.38 gateway HDLC state.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/*! \brief HDLC message buffers. */
|
||||
|
@ -183,8 +195,11 @@ typedef struct
|
|||
*/
|
||||
struct t38_gateway_state_s
|
||||
{
|
||||
/*! T.38 side state */
|
||||
t38_gateway_t38_state_t t38x;
|
||||
/*! Audio side state */
|
||||
t38_gateway_audio_state_t audio;
|
||||
/*! T.38 core state */
|
||||
t38_gateway_core_state_t core;
|
||||
|
||||
/*! \brief Error and flow logging control */
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* SpanDSP - a series of DSP components for telephony
|
||||
*
|
||||
* private/v18.h - V.18 text telephony for the deaf.
|
||||
*
|
||||
* Written by Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* Copyright (C) 2004-2009 Steve Underwood
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License version 2.1,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: v18.h,v 1.4 2009/04/11 15:16:14 steveu Exp $
|
||||
*/
|
||||
|
||||
#if !defined(_SPANDSP_PRIVATE_V18_H_)
|
||||
#define _SPANDSP_PRIVATE_V18_H_
|
||||
|
||||
struct v18_state_s
|
||||
{
|
||||
/*! \brief TRUE if we are the calling modem */
|
||||
int caller;
|
||||
int mode;
|
||||
put_msg_func_t put_msg;
|
||||
void *user_data;
|
||||
|
||||
union
|
||||
{
|
||||
queue_state_t queue;
|
||||
uint8_t buf[QUEUE_STATE_T_SIZE(128)];
|
||||
} queue;
|
||||
tone_gen_descriptor_t alert_tone_desc;
|
||||
tone_gen_state_t alert_tone_gen;
|
||||
fsk_tx_state_t fsktx;
|
||||
dtmf_tx_state_t dtmftx;
|
||||
async_tx_state_t asynctx;
|
||||
int baudot_tx_shift;
|
||||
int tx_signal_on;
|
||||
int byte_no;
|
||||
|
||||
fsk_rx_state_t fskrx;
|
||||
dtmf_rx_state_t dtmfrx;
|
||||
int baudot_rx_shift;
|
||||
int consecutive_ones;
|
||||
uint8_t rx_msg[256 + 1];
|
||||
int rx_msg_len;
|
||||
int bit_pos;
|
||||
int in_progress;
|
||||
|
||||
/*! \brief Error and flow logging control */
|
||||
logging_state_t logging;
|
||||
};
|
||||
|
||||
#endif
|
||||
/*- End of file ------------------------------------------------------------*/
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: v22bis.h,v 1.1 2008/11/30 03:39:58 steveu Exp $
|
||||
* $Id: v22bis.h,v 1.4 2009/04/17 14:37:53 steveu Exp $
|
||||
*/
|
||||
|
||||
#if !defined(_SPANDSP_PRIVATE_V22BIS_H_)
|
||||
|
@ -44,6 +44,10 @@ struct v22bis_state_s
|
|||
get_bit_func_t get_bit;
|
||||
/*! \brief A user specified opaque pointer passed to the callback routines. */
|
||||
void *user_data;
|
||||
/*! \brief The callback function used to report modem status changes. */
|
||||
modem_rx_status_func_t status_handler;
|
||||
/*! \brief A user specified opaque pointer passed to the status function. */
|
||||
void *status_user_data;
|
||||
|
||||
/* RECEIVE SECTION */
|
||||
struct
|
||||
|
@ -79,6 +83,8 @@ struct v22bis_state_s
|
|||
float carrier_track_p;
|
||||
/*! \brief The integral part of the carrier tracking filter. */
|
||||
float carrier_track_i;
|
||||
|
||||
int scrambled_ones_to_date;
|
||||
|
||||
/*! \brief A callback function which may be enabled to report every symbol's
|
||||
constellation position. */
|
||||
|
@ -125,6 +131,10 @@ struct v22bis_state_s
|
|||
int baud_phase;
|
||||
|
||||
int sixteen_way_decisions;
|
||||
|
||||
int detected_unscrambled_ones;
|
||||
int detected_unscrambled_zeros;
|
||||
int detected_2400bps_markers;
|
||||
} rx;
|
||||
|
||||
/* TRANSMIT SECTION */
|
||||
|
@ -167,14 +177,6 @@ struct v22bis_state_s
|
|||
get_bit_func_t current_get_bit;
|
||||
} tx;
|
||||
|
||||
int detected_unscrambled_ones;
|
||||
int detected_unscrambled_zeros;
|
||||
|
||||
int detected_unscrambled_ones_or_zeros;
|
||||
int detected_unscrambled_0011_ending;
|
||||
int detected_scrambled_ones_or_zeros_at_1200bps;
|
||||
int detected_scrambled_ones_at_2400bps;
|
||||
|
||||
/*! \brief Error and flow logging control */
|
||||
logging_state_t logging;
|
||||
};
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: sig_tone.h,v 1.18 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: sig_tone.h,v 1.19 2009/04/12 14:18:02 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -115,8 +115,16 @@ SPAN_DECLARE(int) sig_tone_rx(sig_tone_rx_state_t *s, int16_t amp[], int len);
|
|||
\return A pointer to the signalling tone context, or NULL if there was a problem. */
|
||||
SPAN_DECLARE(sig_tone_rx_state_t *) sig_tone_rx_init(sig_tone_rx_state_t *s, int tone_type, sig_tone_func_t sig_update, void *user_data);
|
||||
|
||||
/*! Release a signaling tone receiver context.
|
||||
\brief Release a signaling tone receiver context.
|
||||
\param s The signaling tone context.
|
||||
\return 0 for OK */
|
||||
SPAN_DECLARE(int) sig_tone_rx_release(sig_tone_rx_state_t *s);
|
||||
|
||||
/*! Free a signaling tone receiver context.
|
||||
\brief Free a signaling tone receiver context.
|
||||
\param s The signaling tone context.
|
||||
\return 0 for OK */
|
||||
SPAN_DECLARE(int) sig_tone_rx_free(sig_tone_rx_state_t *s);
|
||||
|
||||
/*! Generate a block of signaling tone audio samples.
|
||||
|
@ -142,8 +150,16 @@ SPAN_DECLARE(void) sig_tone_tx_set_mode(sig_tone_tx_state_t *s, int mode);
|
|||
\return A pointer to the signalling tone context, or NULL if there was a problem. */
|
||||
SPAN_DECLARE(sig_tone_tx_state_t *) sig_tone_tx_init(sig_tone_tx_state_t *s, int tone_type, sig_tone_func_t sig_update, void *user_data);
|
||||
|
||||
/*! Release a signaling tone transmitter context.
|
||||
\brief Release a signaling tone transmitter context.
|
||||
\param s The signaling tone context.
|
||||
\return 0 for OK */
|
||||
SPAN_DECLARE(int) sig_tone_tx_release(sig_tone_tx_state_t *s);
|
||||
|
||||
/*! Free a signaling tone transmitter context.
|
||||
\brief Free a signaling tone transmitter context.
|
||||
\param s The signaling tone context.
|
||||
\return 0 for OK */
|
||||
SPAN_DECLARE(int) sig_tone_tx_free(sig_tone_tx_state_t *s);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
|
|
@ -22,22 +22,13 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: silence_gen.h,v 1.16 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: silence_gen.h,v 1.17 2009/04/12 03:29:58 steveu Exp $
|
||||
*/
|
||||
|
||||
#if !defined(_SPANDSP_SILENCE_GEN_H_)
|
||||
#define _SPANDSP_SILENCE_GEN_H_
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/*! \brief The callback function used to report status changes. */
|
||||
modem_tx_status_func_t status_handler;
|
||||
/*! \brief A user specified opaque pointer passed to the status function. */
|
||||
void *status_user_data;
|
||||
|
||||
int remaining_samples;
|
||||
int total_samples;
|
||||
} silence_gen_state_t;
|
||||
typedef struct silence_gen_state_s silence_gen_state_t;
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C"
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: t30.h,v 1.124 2009/02/20 12:34:20 steveu Exp $
|
||||
* $Id: t30.h,v 1.125 2009/04/12 09:12:10 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -140,8 +140,11 @@ There are many other commonly encountered variations between machines, including
|
|||
- DCN usage
|
||||
*/
|
||||
|
||||
/*! The maximum length of a DIS, DTC or DCS frame */
|
||||
#define T30_MAX_DIS_DTC_DCS_LEN 22
|
||||
/*! The maximum length of the body of an ident string */
|
||||
#define T30_MAX_IDENT_LEN 20
|
||||
/*! The maximum length of the user string to insert in page headers */
|
||||
#define T30_MAX_PAGE_HEADER_INFO 50
|
||||
|
||||
typedef struct t30_state_s t30_state_t;
|
||||
|
@ -190,7 +193,7 @@ typedef void (t30_phase_e_handler_t)(t30_state_t *s, void *user_data, int comple
|
|||
typedef void (t30_real_time_frame_handler_t)(t30_state_t *s,
|
||||
void *user_data,
|
||||
int direction,
|
||||
const uint8_t *msg,
|
||||
const uint8_t msg[],
|
||||
int len);
|
||||
|
||||
/*!
|
||||
|
@ -220,7 +223,7 @@ typedef void (t30_set_handler_t)(void *user_data, int type, int bit_rate, int sh
|
|||
\param msg The HDLC message.
|
||||
\param len The length of the message.
|
||||
*/
|
||||
typedef void (t30_send_hdlc_handler_t)(void *user_data, const uint8_t *msg, int len);
|
||||
typedef void (t30_send_hdlc_handler_t)(void *user_data, const uint8_t msg[], int len);
|
||||
|
||||
/*!
|
||||
T.30 protocol completion codes, at phase E.
|
||||
|
@ -650,7 +653,7 @@ SPAN_DECLARE(void) t30_non_ecm_put_chunk(void *user_data, const uint8_t buf[], i
|
|||
\param msg The HDLC message.
|
||||
\param len The length of the message, in octets.
|
||||
\param ok TRUE if the frame was received without error. */
|
||||
SPAN_DECLARE_NONSTD(void) t30_hdlc_accept(void *user_data, const uint8_t *msg, int len, int ok);
|
||||
SPAN_DECLARE_NONSTD(void) t30_hdlc_accept(void *user_data, const uint8_t msg[], int len, int ok);
|
||||
|
||||
/*! Report the passage of time to the T.30 engine.
|
||||
\brief Report the passage of time to the T.30 engine.
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: t30_api.h,v 1.9 2009/02/03 16:28:41 steveu Exp $
|
||||
* $Id: t30_api.h,v 1.10 2009/04/12 09:12:10 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -60,7 +60,7 @@ SPAN_DECLARE(size_t) t30_get_rx_nsf(t30_state_t *s, const uint8_t *nsf[]);
|
|||
/*! Set the transmitted NSC frame to be associated with a T.30 context.
|
||||
\brief Set the transmitted NSC frame to be associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param nsf A pointer to the frame.
|
||||
\param nsc A pointer to the frame.
|
||||
\param len The length of the frame.
|
||||
\return 0 for OK, else -1. */
|
||||
SPAN_DECLARE(int) t30_set_tx_nsc(t30_state_t *s, const uint8_t *nsc, int len);
|
||||
|
@ -82,7 +82,7 @@ SPAN_DECLARE(size_t) t30_get_rx_nsc(t30_state_t *s, const uint8_t *nsc[]);
|
|||
/*! Set the transmitted NSS frame to be associated with a T.30 context.
|
||||
\brief Set the transmitted NSS frame to be associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param nsf A pointer to the frame.
|
||||
\param nss A pointer to the frame.
|
||||
\param len The length of the frame.
|
||||
\return 0 for OK, else -1. */
|
||||
SPAN_DECLARE(int) t30_set_tx_nss(t30_state_t *s, const uint8_t *nss, int len);
|
||||
|
@ -111,15 +111,13 @@ SPAN_DECLARE(int) t30_set_tx_ident(t30_state_t *s, const char *id);
|
|||
/*! Get the transmitted identifier associated with a T.30 context.
|
||||
\brief Set the transmitted identifier associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param id A pointer to the identifier.
|
||||
\return 0 for OK, else -1. */
|
||||
\return A pointer to the identifier. */
|
||||
SPAN_DECLARE(const char *) t30_get_tx_ident(t30_state_t *s);
|
||||
|
||||
/*! Get the transmitted identifier associated with a T.30 context.
|
||||
\brief Set the transmitted identifier associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param id A pointer to the identifier.
|
||||
\return 0 for OK, else -1. */
|
||||
\return A pointer to the identifier. */
|
||||
SPAN_DECLARE(const char *) t30_get_rx_ident(t30_state_t *s);
|
||||
|
||||
/*! Set the transmitted sub-address associated with a T.30 context.
|
||||
|
@ -132,15 +130,13 @@ SPAN_DECLARE(int) t30_set_tx_sub_address(t30_state_t *s, const char *sub_address
|
|||
/*! Get the received sub-address associated with a T.30 context.
|
||||
\brief Get the received sub-address associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param sub_address A pointer to the sub-address.
|
||||
\return 0 for OK, else -1. */
|
||||
\return A pointer to the sub-address. */
|
||||
SPAN_DECLARE(const char *) t30_get_tx_sub_address(t30_state_t *s);
|
||||
|
||||
/*! Get the received sub-address associated with a T.30 context.
|
||||
\brief Get the received sub-address associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param sub_address A pointer to the sub-address.
|
||||
\return 0 for OK, else -1. */
|
||||
\return A pointer to the sub-address. */
|
||||
SPAN_DECLARE(const char *) t30_get_rx_sub_address(t30_state_t *s);
|
||||
|
||||
/*! Set the transmitted selective polling address (i.e. the one we will send to the far
|
||||
|
@ -155,16 +151,14 @@ SPAN_DECLARE(int) t30_set_tx_selective_polling_address(t30_state_t *s, const cha
|
|||
end) associated with a T.30 context.
|
||||
\brief Get the received selective polling address associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param selective_polling_address A pointer to the selective polling address.
|
||||
\return 0 for OK, else -1. */
|
||||
\return A pointer to the selective polling address. */
|
||||
SPAN_DECLARE(const char *) t30_get_tx_selective_polling_address(t30_state_t *s);
|
||||
|
||||
/*! Get the received selective polling address (i.e. the one we will send to the far
|
||||
end) associated with a T.30 context.
|
||||
\brief Get the received selective polling address associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param selective_polling_address A pointer to the selective polling address.
|
||||
\return 0 for OK, else -1. */
|
||||
\return A pointer to the selective polling address. */
|
||||
SPAN_DECLARE(const char *) t30_get_rx_selective_polling_address(t30_state_t *s);
|
||||
|
||||
/*! Set the transmitted polled sub-address (i.e. the one we will send to the far
|
||||
|
@ -179,16 +173,14 @@ SPAN_DECLARE(int) t30_set_tx_polled_sub_address(t30_state_t *s, const char *poll
|
|||
end) associated with a T.30 context.
|
||||
\brief Get the received polled sub-address associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param polled_sub_address A pointer to the polled sub-address.
|
||||
\return 0 for OK, else -1. */
|
||||
\return A pointer to the polled sub-address. */
|
||||
SPAN_DECLARE(const char *) t30_get_tx_polled_sub_address(t30_state_t *s);
|
||||
|
||||
/*! Get the received polled sub-address (i.e. the one we will send to the far
|
||||
end) associated with a T.30 context.
|
||||
\brief Get the received polled sub-address associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param polled_sub_address A pointer to the polled sub-address.
|
||||
\return 0 for OK, else -1. */
|
||||
\return A pointer to the polled sub-address. */
|
||||
SPAN_DECLARE(const char *) t30_get_rx_polled_sub_address(t30_state_t *s);
|
||||
|
||||
/*! Set the transmitted sender ident (i.e. the one we will send to the far
|
||||
|
@ -203,16 +195,14 @@ SPAN_DECLARE(int) t30_set_tx_sender_ident(t30_state_t *s, const char *sender_ide
|
|||
end) associated with a T.30 context.
|
||||
\brief Get the received sender ident associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param sender_ident A pointer to the sender ident.
|
||||
\return 0 for OK, else -1. */
|
||||
\return A pointer to the sender ident. */
|
||||
SPAN_DECLARE(const char *) t30_get_tx_sender_ident(t30_state_t *s);
|
||||
|
||||
/*! Get the received sender ident (i.e. the one we will send to the far
|
||||
end) associated with a T.30 context.
|
||||
\brief Get the received sender ident associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param sender_ident A pointer to the sender ident.
|
||||
\return 0 for OK, else -1. */
|
||||
\return A pointer to the sender ident. */
|
||||
SPAN_DECLARE(const char *) t30_get_rx_sender_ident(t30_state_t *s);
|
||||
|
||||
/*! Set the transmitted password (i.e. the one we will send to the far
|
||||
|
@ -227,16 +217,14 @@ SPAN_DECLARE(int) t30_set_tx_password(t30_state_t *s, const char *password);
|
|||
end) associated with a T.30 context.
|
||||
\brief Get the received password associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param password A pointer to the password.
|
||||
\return 0 for OK, else -1. */
|
||||
\return A pointer to the password. */
|
||||
SPAN_DECLARE(const char *) t30_get_tx_password(t30_state_t *s);
|
||||
|
||||
/*! Get the received password (i.e. the one we will send to the far
|
||||
end) associated with a T.30 context.
|
||||
\brief Get the received password associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param password A pointer to the password.
|
||||
\return 0 for OK, else -1. */
|
||||
\return A pointer to the password. */
|
||||
SPAN_DECLARE(const char *) t30_get_rx_password(t30_state_t *s);
|
||||
|
||||
/*! Set the transmitted ??? (i.e. the one we will send to the far
|
||||
|
@ -244,7 +232,7 @@ SPAN_DECLARE(const char *) t30_get_rx_password(t30_state_t *s);
|
|||
\brief Set the transmitted ??? associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param type The type of address.
|
||||
\param type A pointer to the address.
|
||||
\param address A pointer to the address.
|
||||
\param len The length of the address.
|
||||
\return 0 for OK, else -1. */
|
||||
SPAN_DECLARE(int) t30_set_tx_tsa(t30_state_t *s, int type, const char *address, int len);
|
||||
|
@ -254,9 +242,8 @@ SPAN_DECLARE(int) t30_set_tx_tsa(t30_state_t *s, int type, const char *address,
|
|||
\brief Get the received ??? associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param type The type of address.
|
||||
\param type A pointer to the address.
|
||||
\param len The length of the address.
|
||||
\return 0 for OK, else -1. */
|
||||
\param address A pointer to the address.
|
||||
\return The length of the address. */
|
||||
SPAN_DECLARE(size_t) t30_get_tx_tsa(t30_state_t *s, int *type, const char *address[]);
|
||||
|
||||
/*! Get the received ??? (i.e. the one we will send to the far
|
||||
|
@ -264,9 +251,8 @@ SPAN_DECLARE(size_t) t30_get_tx_tsa(t30_state_t *s, int *type, const char *addre
|
|||
\brief Get the received ??? associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param type The type of address.
|
||||
\param type A pointer to the address.
|
||||
\param len The length of the address.
|
||||
\return 0 for OK, else -1. */
|
||||
\param address A pointer to the address.
|
||||
\return The length of the address. */
|
||||
SPAN_DECLARE(size_t) t30_get_rx_tsa(t30_state_t *s, int *type, const char *address[]);
|
||||
|
||||
/*! Set the transmitted ??? (i.e. the one we will send to the far
|
||||
|
@ -274,7 +260,7 @@ SPAN_DECLARE(size_t) t30_get_rx_tsa(t30_state_t *s, int *type, const char *addre
|
|||
\brief Set the transmitted ??? associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param type The type of address.
|
||||
\param type A pointer to the address.
|
||||
\param address A pointer to the address.
|
||||
\param len The length of the address.
|
||||
\return 0 for OK, else -1. */
|
||||
SPAN_DECLARE(int) t30_set_tx_ira(t30_state_t *s, int type, const char *address, int len);
|
||||
|
@ -284,9 +270,8 @@ SPAN_DECLARE(int) t30_set_tx_ira(t30_state_t *s, int type, const char *address,
|
|||
\brief Get the received ??? associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param type The type of address.
|
||||
\param type A pointer to the address.
|
||||
\param len The length of the address.
|
||||
\return 0 for OK, else -1. */
|
||||
\param address A pointer to the address.
|
||||
\return The length of the address. */
|
||||
SPAN_DECLARE(size_t) t30_get_tx_ira(t30_state_t *s, int *type, const char *address[]);
|
||||
|
||||
/*! Get the received ??? (i.e. the one we will send to the far
|
||||
|
@ -294,9 +279,8 @@ SPAN_DECLARE(size_t) t30_get_tx_ira(t30_state_t *s, int *type, const char *addre
|
|||
\brief Get the received ??? associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param type The type of address.
|
||||
\param type A pointer to the address.
|
||||
\param len The length of the address.
|
||||
\return 0 for OK, else -1. */
|
||||
\param address A pointer to the address.
|
||||
\return The length of the address. */
|
||||
SPAN_DECLARE(size_t) t30_get_rx_ira(t30_state_t *s, int *type, const char *address[]);
|
||||
|
||||
/*! Set the transmitted ??? (i.e. the one we will send to the far
|
||||
|
@ -304,7 +288,7 @@ SPAN_DECLARE(size_t) t30_get_rx_ira(t30_state_t *s, int *type, const char *addre
|
|||
\brief Set the transmitted ??? associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param type The type of address.
|
||||
\param type A pointer to the address.
|
||||
\param address A pointer to the address.
|
||||
\param len The length of the address.
|
||||
\return 0 for OK, else -1. */
|
||||
SPAN_DECLARE(int) t30_set_tx_cia(t30_state_t *s, int type, const char *address, int len);
|
||||
|
@ -314,9 +298,8 @@ SPAN_DECLARE(int) t30_set_tx_cia(t30_state_t *s, int type, const char *address,
|
|||
\brief Get the received ??? associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param type The type of address.
|
||||
\param type A pointer to the address.
|
||||
\param len The length of the address.
|
||||
\return 0 for OK, else -1. */
|
||||
\param address A pointer to the address.
|
||||
\return The length of the address. */
|
||||
SPAN_DECLARE(size_t) t30_get_tx_cia(t30_state_t *s, int *type, const char *address[]);
|
||||
|
||||
/*! Get the received ??? (i.e. the one we will send to the far
|
||||
|
@ -324,8 +307,7 @@ SPAN_DECLARE(size_t) t30_get_tx_cia(t30_state_t *s, int *type, const char *addre
|
|||
\brief Get the received ??? associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param type The type of address.
|
||||
\param type A pointer to the address.
|
||||
\param len The length of the address.
|
||||
\param address A pointer to the address.
|
||||
\return 0 for OK, else -1. */
|
||||
SPAN_DECLARE(size_t) t30_get_rx_cia(t30_state_t *s, int *type, const char *address[]);
|
||||
|
||||
|
@ -334,7 +316,7 @@ SPAN_DECLARE(size_t) t30_get_rx_cia(t30_state_t *s, int *type, const char *addre
|
|||
\brief Set the transmitted ??? associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param type The type of address.
|
||||
\param type A pointer to the address.
|
||||
\param address A pointer to the address.
|
||||
\param len The length of the address.
|
||||
\return 0 for OK, else -1. */
|
||||
SPAN_DECLARE(int) t30_set_tx_isp(t30_state_t *s, int type, const char *address, int len);
|
||||
|
@ -344,7 +326,7 @@ SPAN_DECLARE(int) t30_set_tx_isp(t30_state_t *s, int type, const char *address,
|
|||
\brief Get the received ??? associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param type The type of address.
|
||||
\param type A pointer to the address.
|
||||
\param address A pointer to the address.
|
||||
\return 0 for OK, else -1. */
|
||||
SPAN_DECLARE(size_t) t30_get_tx_isp(t30_state_t *s, int *type, const char *address[]);
|
||||
|
||||
|
@ -353,7 +335,7 @@ SPAN_DECLARE(size_t) t30_get_tx_isp(t30_state_t *s, int *type, const char *addre
|
|||
\brief Get the received ??? associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param type The type of address.
|
||||
\param type A pointer to the address.
|
||||
\param address A pointer to the address.
|
||||
\return 0 for OK, else -1. */
|
||||
SPAN_DECLARE(size_t) t30_get_rx_isp(t30_state_t *s, int *type, const char *address[]);
|
||||
|
||||
|
@ -362,7 +344,7 @@ SPAN_DECLARE(size_t) t30_get_rx_isp(t30_state_t *s, int *type, const char *addre
|
|||
\brief Set the transmitted ??? associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param type The type of address.
|
||||
\param type A pointer to the address.
|
||||
\param address A pointer to the address.
|
||||
\param len The length of the address.
|
||||
\return 0 for OK, else -1. */
|
||||
SPAN_DECLARE(int) t30_set_tx_csa(t30_state_t *s, int type, const char *address, int len);
|
||||
|
@ -372,9 +354,8 @@ SPAN_DECLARE(int) t30_set_tx_csa(t30_state_t *s, int type, const char *address,
|
|||
\brief Get the received ??? associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param type The type of address.
|
||||
\param type A pointer to the address.
|
||||
\param len The length of the address.
|
||||
\return 0 for OK, else -1. */
|
||||
\param address A pointer to the address.
|
||||
\return The length of the address. */
|
||||
SPAN_DECLARE(size_t) t30_get_tx_csa(t30_state_t *s, int *type, const char *address[]);
|
||||
|
||||
/*! Get the received ??? (i.e. the one we will send to the far
|
||||
|
@ -382,8 +363,7 @@ SPAN_DECLARE(size_t) t30_get_tx_csa(t30_state_t *s, int *type, const char *addre
|
|||
\brief Get the received ??? associated with a T.30 context.
|
||||
\param s The T.30 context.
|
||||
\param type The type of address.
|
||||
\param type A pointer to the address.
|
||||
\param len The length of the address.
|
||||
\param address A pointer to the address.
|
||||
\return 0 for OK, else -1. */
|
||||
SPAN_DECLARE(size_t) t30_get_rx_csa(t30_state_t *s, int *type, const char *address[]);
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: t31.h,v 1.58 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: t31.h,v 1.59 2009/03/13 12:59:26 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -69,6 +69,14 @@ SPAN_DECLARE(int) t31_at_rx(t31_state_t *s, const char *t, int len);
|
|||
\return The number of samples unprocessed. */
|
||||
SPAN_DECLARE(int) t31_rx(t31_state_t *s, int16_t amp[], int len);
|
||||
|
||||
/*! Fake processing of a missing block of received T.31 modem audio samples
|
||||
(e.g due to packet loss).
|
||||
\brief Fake processing of a missing block of received T.31 modem audio samples.
|
||||
\param s The T.31 modem context.
|
||||
\param len The number of samples to fake.
|
||||
\return The number of samples unprocessed. */
|
||||
SPAN_DECLARE(int) t31_rx_fillin(t31_state_t *s, int len);
|
||||
|
||||
/*! Generate a block of T.31 modem audio samples.
|
||||
\brief Generate a block of T.31 modem audio samples.
|
||||
\param s The T.31 modem context.
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: t38_core.h,v 1.37 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: t38_core.h,v 1.38 2009/04/12 14:18:02 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -173,8 +173,11 @@ enum t38_data_rate_management_types_e
|
|||
/*! T.38 data field */
|
||||
typedef struct
|
||||
{
|
||||
/*! Field type */
|
||||
int field_type;
|
||||
/*! Field contents */
|
||||
const uint8_t *field;
|
||||
/*! Field length */
|
||||
int field_len;
|
||||
} t38_data_field_t;
|
||||
|
||||
|
@ -328,6 +331,16 @@ SPAN_DECLARE(void) t38_set_tep_handling(t38_core_state_t *s, int allow_for_tep);
|
|||
*/
|
||||
SPAN_DECLARE(logging_state_t *) t38_core_get_logging_state(t38_core_state_t *s);
|
||||
|
||||
/*! Initialise a T.38 core context.
|
||||
\brief Initialise a T.38 core context.
|
||||
\param s The T.38 context.
|
||||
\param rx_indicator_handler Receive indicator handling routine.
|
||||
\param rx_data_handler Receive data packet handling routine.
|
||||
\param rx_rx_missing_handler Missing receive packet handling routine.
|
||||
\param rx_packet_user_data An opaque pointer passed to the rx packet handling routines.
|
||||
\param tx_packet_handler Packet transmit handling routine.
|
||||
\param tx_packet_user_data An opaque pointer passed to the tx_packet_handler.
|
||||
\return A pointer to the T.38 context, or NULL if there was a problem. */
|
||||
SPAN_DECLARE(t38_core_state_t *) t38_core_init(t38_core_state_t *s,
|
||||
t38_rx_indicator_handler_t *rx_indicator_handler,
|
||||
t38_rx_data_handler_t *rx_data_handler,
|
||||
|
@ -336,8 +349,16 @@ SPAN_DECLARE(t38_core_state_t *) t38_core_init(t38_core_state_t *s,
|
|||
t38_tx_packet_handler_t *tx_packet_handler,
|
||||
void *tx_packet_user_data);
|
||||
|
||||
/*! Release a signaling tone transmitter context.
|
||||
\brief Release a signaling tone transmitter context.
|
||||
\param s The T.38 context.
|
||||
\return 0 for OK */
|
||||
SPAN_DECLARE(int) t38_core_release(t38_core_state_t *s);
|
||||
|
||||
/*! Free a signaling tone transmitter context.
|
||||
\brief Free a signaling tone transmitter context.
|
||||
\param s The T.38 context.
|
||||
\return 0 for OK */
|
||||
SPAN_DECLARE(int) t38_core_free(t38_core_state_t *s);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: t38_gateway.h,v 1.62 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: t38_gateway.h,v 1.63 2009/04/12 09:12:10 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -40,9 +40,11 @@ to maximum the tolerance of jitter and packet loss on the IP network.
|
|||
\section t38_gateway_page_sec_2 How does it work?
|
||||
*/
|
||||
|
||||
/*! The receive buffer length */
|
||||
#define T38_RX_BUF_LEN 2048
|
||||
/*! The number of HDLC transmit buffers */
|
||||
#define T38_TX_HDLC_BUFS 256
|
||||
/* Make sure the HDLC frame buffers are big enough for ECM frames. */
|
||||
/*! The maximum length of an HDLC frame buffer. This must be big enough for ECM frames. */
|
||||
#define T38_MAX_HDLC_LEN 260
|
||||
|
||||
typedef struct t38_gateway_state_s t38_gateway_state_t;
|
||||
|
@ -62,6 +64,9 @@ typedef void (t38_gateway_real_time_frame_handler_t)(t38_gateway_state_t *s,
|
|||
const uint8_t *msg,
|
||||
int len);
|
||||
|
||||
/*!
|
||||
T.38 gateway results.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/*! \brief The current bit rate for image transfer. */
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: t4.h,v 1.58 2009/02/20 12:34:20 steveu Exp $
|
||||
* $Id: t4.h,v 1.59 2009/04/12 09:12:10 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -258,6 +258,11 @@ SPAN_DECLARE(int) t4_rx_release(t4_state_t *s);
|
|||
\return 0 for success, otherwise -1. */
|
||||
SPAN_DECLARE(int) t4_rx_free(t4_state_t *s);
|
||||
|
||||
/*! \brief Set the row write handler for a T.4 receive context.
|
||||
\param s The T.4 receive context.
|
||||
\param handler A pointer to the handler routine.
|
||||
\param user_data An opaque pointer passed to the handler routine.
|
||||
\return 0 for success, otherwise -1. */
|
||||
SPAN_DECLARE(int) t4_rx_set_row_write_handler(t4_state_t *s, t4_row_write_handler_t handler, void *user_data);
|
||||
|
||||
/*! \brief Set the encoding for the received data.
|
||||
|
@ -416,6 +421,11 @@ SPAN_DECLARE(void) t4_tx_set_local_ident(t4_state_t *s, const char *ident);
|
|||
\param info A string, of up to 50 bytes, which will form the info field. */
|
||||
SPAN_DECLARE(void) t4_tx_set_header_info(t4_state_t *s, const char *info);
|
||||
|
||||
/*! \brief Set the row read handler for a T.4 transmit context.
|
||||
\param s The T.4 transmit context.
|
||||
\param handler A pointer to the handler routine.
|
||||
\param user_data An opaque pointer passed to the handler routine.
|
||||
\return 0 for success, otherwise -1. */
|
||||
SPAN_DECLARE(int) t4_tx_set_row_read_handler(t4_state_t *s, t4_row_read_handler_t handler, void *user_data);
|
||||
|
||||
/*! \brief Get the row-to-row (y) resolution of the current page.
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: telephony.h,v 1.17 2009/02/25 15:30:21 steveu Exp $
|
||||
* $Id: telephony.h,v 1.18 2009/03/23 14:17:42 steveu Exp $
|
||||
*/
|
||||
|
||||
#if !defined(_SPANDSP_TELEPHONY_H_)
|
||||
|
@ -63,6 +63,9 @@ typedef int (span_rx_handler_t)(void *s, const int16_t amp[], int len);
|
|||
/*! \brief A handler for receive, where the buffer can be altered. */
|
||||
typedef int (span_mod_handler_t)(void *s, int16_t amp[], int len);
|
||||
|
||||
/*! \brief A handler for missing receive data fill-in. */
|
||||
typedef int (span_rx_fillin_handler_t)(void *s, int len);
|
||||
|
||||
/*! \brief A handler for transmit, where the buffer will be filled. */
|
||||
typedef int (span_tx_handler_t)(void *s, int16_t amp[], int max_len);
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: v17rx.h,v 1.61 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: v17rx.h,v 1.63 2009/04/12 04:20:01 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -213,16 +213,21 @@ TCM absolutely transformed the phone line modem business.
|
|||
|
||||
/* Target length for the equalizer is about 63 taps, to deal with the worst stuff
|
||||
in V.56bis. */
|
||||
#define V17_EQUALIZER_PRE_LEN 8 /* This much before the real event */
|
||||
#define V17_EQUALIZER_POST_LEN 8 /* This much after the real event (must be even) */
|
||||
/*! Samples before the target position in the equalizer buffer */
|
||||
#define V17_EQUALIZER_PRE_LEN 8
|
||||
/*! Samples after the target position in the equalizer buffer */
|
||||
#define V17_EQUALIZER_POST_LEN 8
|
||||
|
||||
/*! The number of taps in the pulse shaping/bandpass filter */
|
||||
#define V17_RX_FILTER_STEPS 27
|
||||
|
||||
/* We can store more trellis depth that we look back over, so that we can push out a group
|
||||
of symbols in one go, giving greater processing efficiency, at the expense of a bit more
|
||||
latency through the modem. */
|
||||
/* Right now we don't take advantage of this optimisation. */
|
||||
/*! The depth of the trellis buffer */
|
||||
#define V17_TRELLIS_STORAGE_DEPTH 16
|
||||
/*! How far we look back into history for trellis decisions */
|
||||
#define V17_TRELLIS_LOOKBACK_DEPTH 16
|
||||
|
||||
/*!
|
||||
|
@ -265,6 +270,10 @@ SPAN_DECLARE(int) v17_rx_release(v17_rx_state_t *s);
|
|||
\return 0 for OK */
|
||||
SPAN_DECLARE(int) v17_rx_free(v17_rx_state_t *s);
|
||||
|
||||
/*! Get the logging context associated with a V.17 modem receive context.
|
||||
\brief Get the logging context associated with a V.17 modem receive context.
|
||||
\param s The modem context.
|
||||
\return A pointer to the logging context */
|
||||
SPAN_DECLARE(logging_state_t *) v17_rx_get_logging_state(v17_rx_state_t *s);
|
||||
|
||||
/*! Change the put_bit function associated with a V.17 modem receive context.
|
||||
|
@ -290,6 +299,15 @@ SPAN_DECLARE(void) v17_rx_set_modem_status_handler(v17_rx_state_t *s, modem_rx_s
|
|||
*/
|
||||
SPAN_DECLARE(int) v17_rx(v17_rx_state_t *s, const int16_t amp[], int len);
|
||||
|
||||
/*! Fake processing of a missing block of received V.17 modem audio samples.
|
||||
(e.g due to packet loss).
|
||||
\brief Fake processing of a missing block of received V.17 modem audio samples.
|
||||
\param s The modem context.
|
||||
\param len The number of samples to fake.
|
||||
\return The number of samples unprocessed.
|
||||
*/
|
||||
SPAN_DECLARE(int) v17_rx_fillin(v17_rx_state_t *s, int len);
|
||||
|
||||
/*! Get a snapshot of the current equalizer coefficients.
|
||||
\brief Get a snapshot of the current equalizer coefficients.
|
||||
\param s The modem context.
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: v17tx.h,v 1.40 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: v17tx.h,v 1.41 2009/04/12 09:12:11 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -81,6 +81,7 @@ suits the receiver better, so the same signal generator is also used for the
|
|||
transmitter.
|
||||
*/
|
||||
|
||||
/*! The number of taps in the pulse shaping/bandpass filter */
|
||||
#define V17_TX_FILTER_STEPS 9
|
||||
|
||||
/*!
|
||||
|
@ -132,6 +133,10 @@ SPAN_DECLARE(int) v17_tx_release(v17_tx_state_t *s);
|
|||
\return 0 for OK */
|
||||
SPAN_DECLARE(int) v17_tx_free(v17_tx_state_t *s);
|
||||
|
||||
/*! Get the logging context associated with a V.17 modem transmit context.
|
||||
\brief Get the logging context associated with a V.17 modem transmit context.
|
||||
\param s The modem context.
|
||||
\return A pointer to the logging context */
|
||||
SPAN_DECLARE(logging_state_t *) v17_tx_get_logging_state(v17_tx_state_t *s);
|
||||
|
||||
/*! Change the get_bit function associated with a V.17 modem transmit context.
|
||||
|
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* SpanDSP - a series of DSP components for telephony
|
||||
*
|
||||
* v18.h - V.18 text telephony for the deaf.
|
||||
*
|
||||
* Written by Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* Copyright (C) 2004-2009 Steve Underwood
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License version 2.1,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: v18.h,v 1.3 2009/04/12 09:12:11 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
||||
/*! \page v18_page The V.18 text telephony protocols
|
||||
\section v18_page_sec_1 What does it do?
|
||||
|
||||
\section v18_page_sec_2 How does it work?
|
||||
*/
|
||||
|
||||
#if !defined(_SPANDSP_V18_H_)
|
||||
#define _SPANDSP_V18_H_
|
||||
|
||||
typedef struct v18_state_s v18_state_t;
|
||||
|
||||
enum
|
||||
{
|
||||
V18_MODE_NONE = 0,
|
||||
/* V.18 Annex A - Weitbrecht TDD at 45.45bps, half-duplex, 5 bit baudot. */
|
||||
V18_MODE_5BIT_45 = 1,
|
||||
/* V.18 Annex A - Weitbrecht TDD at 50bps, half-duplex, 5 bit baudot. */
|
||||
V18_MODE_5BIT_50 = 2,
|
||||
/* V.18 Annex B - DTMF encoding of ASCII. */
|
||||
V18_MODE_DTMF = 3,
|
||||
/* V.18 Annex C - EDT 110bps, V.21, half-duplex, ASCII. */
|
||||
V18_MODE_EDT = 4,
|
||||
/* V.18 Annex D - 300bps, Bell 103, duplex, ASCII. */
|
||||
V18_MODE_BELL103 = 5,
|
||||
/* V.18 Annex E - 1200bps Videotex terminals, ASCII. */
|
||||
V18_MODE_V23VIDEOTEX = 6,
|
||||
/* V.18 Annex F - V.21 text telephone, V.21, duplex, ASCII. */
|
||||
V18_MODE_V21TEXTPHONE = 7,
|
||||
/* V.18 Annex G - V.18 text telephone mode. */
|
||||
V18_MODE_V18TEXTPHONE = 8
|
||||
};
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
SPAN_DECLARE(logging_state_t *) v18_get_logging_state(v18_state_t *s);
|
||||
|
||||
/*! Initialise a V.18 context.
|
||||
\brief Initialise a V.18 context.
|
||||
\param s The V.18 context.
|
||||
\param caller TRUE if caller mode, else answerer mode.
|
||||
\param mode Mode of operation.
|
||||
\param put_msg A callback routine called to deliver the received text
|
||||
to the application.
|
||||
\param user_data An opaque pointer for the callback routine.
|
||||
\return A pointer to the V.18 context, or NULL if there was a problem. */
|
||||
SPAN_DECLARE(v18_state_t *) v18_init(v18_state_t *s,
|
||||
int caller,
|
||||
int mode,
|
||||
put_msg_func_t put_msg,
|
||||
void *user_data);
|
||||
|
||||
/*! Release a V.18 context.
|
||||
\brief Release a V.18 context.
|
||||
\param s The V.18 context.
|
||||
\return 0 for OK. */
|
||||
SPAN_DECLARE(int) v18_release(v18_state_t *s);
|
||||
|
||||
/*! Free a V.18 context.
|
||||
\brief Release a V.18 context.
|
||||
\param s The V.18 context.
|
||||
\return 0 for OK. */
|
||||
SPAN_DECLARE(int) v18_free(v18_state_t *s);
|
||||
|
||||
/*! Generate a block of V.18 audio samples.
|
||||
\brief Generate a block of V.18 audio samples.
|
||||
\param s The V.18 context.
|
||||
\param amp The audio sample buffer.
|
||||
\param max_len The number of samples to be generated.
|
||||
\return The number of samples actually generated.
|
||||
*/
|
||||
SPAN_DECLARE(int) v18_tx(v18_state_t *s, int16_t amp[], int max_len);
|
||||
|
||||
/*! Process a block of received V.18 audio samples.
|
||||
\brief Process a block of received V.18 audio samples.
|
||||
\param s The V.18 context.
|
||||
\param amp The audio sample buffer.
|
||||
\param len The number of samples in the buffer.
|
||||
*/
|
||||
SPAN_DECLARE(int) v18_rx(v18_state_t *s, const int16_t amp[], int len);
|
||||
|
||||
/*! \brief Put a string to a V.18 context's input buffer.
|
||||
\param s The V.18 context.
|
||||
\param msg The string to be added.
|
||||
\param len The length of the string. If negative, the string is
|
||||
assumed to be a NULL terminated string.
|
||||
\return The number of characters actually added. This may be less than the
|
||||
length of the digit string, if the buffer fills up. */
|
||||
SPAN_DECLARE(int) v18_put(v18_state_t *s, const char msg[], int len);
|
||||
|
||||
/*! Convert a text string to a V.18 DTMF string.
|
||||
\brief Convert a text string to a V.18 DTMF string.
|
||||
\param s The V.18 context.
|
||||
\param dtmf The resulting DTMF string.
|
||||
\param msg The text string to be converted.
|
||||
\return The length of the DTMF string.
|
||||
*/
|
||||
SPAN_DECLARE(int) v18_encode_dtmf(v18_state_t *s, char dtmf[], const char msg[]);
|
||||
|
||||
/*! Convert a V.18 DTMF string to a text string.
|
||||
\brief Convert a V.18 DTMF string to a text string.
|
||||
\param s The V.18 context.
|
||||
\param msg The resulting test string.
|
||||
\param dtmf The DTMF string to be converted.
|
||||
\return The length of the text string.
|
||||
*/
|
||||
SPAN_DECLARE(int) v18_decode_dtmf(v18_state_t *s, char msg[], const char dtmf[]);
|
||||
|
||||
SPAN_DECLARE(uint16_t) v18_encode_baudot(v18_state_t *s, uint8_t ch);
|
||||
|
||||
SPAN_DECLARE(uint8_t) v18_decode_baudot(v18_state_t *s, uint8_t ch);
|
||||
|
||||
/*! \brief Return a short name for an V.18 mode
|
||||
\param mode The code for the V.18 mode.
|
||||
\return A pointer to the name.
|
||||
*/
|
||||
SPAN_DECLARE(const char *) v18_mode_to_str(int mode);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/*- End of file ------------------------------------------------------------*/
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: v22bis.h,v 1.35 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: v22bis.h,v 1.39 2009/04/17 14:37:53 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -50,11 +50,22 @@ or 1200bps if one or both ends to not acknowledge that 2400bps is OK.
|
|||
#if !defined(_SPANDSP_V22BIS_H_)
|
||||
#define _SPANDSP_V22BIS_H_
|
||||
|
||||
#define V22BIS_EQUALIZER_LEN 7 /* this much to the left and this much to the right */
|
||||
#define V22BIS_EQUALIZER_MASK 15 /* one less than a power of 2 >= (2*V22BIS_EQUALIZER_LEN + 1) */
|
||||
enum
|
||||
{
|
||||
V22BIS_GUARD_TONE_NONE,
|
||||
V22BIS_GUARD_TONE_550HZ,
|
||||
V22BIS_GUARD_TONE_1800HZ
|
||||
};
|
||||
|
||||
/*! The number of steps to the left and to the right of the target position in the equalizer buffer. */
|
||||
#define V22BIS_EQUALIZER_LEN 7
|
||||
/*! One less than a power of 2 >= (2*V22BIS_EQUALIZER_LEN + 1) */
|
||||
#define V22BIS_EQUALIZER_MASK 15
|
||||
|
||||
/*! The number of taps in the transmit pulse shaping filter */
|
||||
#define V22BIS_TX_FILTER_STEPS 9
|
||||
|
||||
/*! The number of taps in the receive pulse shaping/bandpass filter */
|
||||
#define V22BIS_RX_FILTER_STEPS 37
|
||||
|
||||
/*!
|
||||
|
@ -85,6 +96,14 @@ SPAN_DECLARE(int) v22bis_rx_restart(v22bis_state_t *s, int bit_rate);
|
|||
\return The number of samples unprocessed. */
|
||||
SPAN_DECLARE(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int len);
|
||||
|
||||
/*! Fake processing of a missing block of received V.22bis modem audio samples.
|
||||
(e.g due to packet loss).
|
||||
\brief Fake processing of a missing block of received V.22bis modem audio samples.
|
||||
\param s The modem context.
|
||||
\param len The number of samples to fake.
|
||||
\return The number of samples unprocessed. */
|
||||
SPAN_DECLARE(int) v22bis_rx_fillin(v22bis_state_t *s, int len);
|
||||
|
||||
/*! Get a snapshot of the current equalizer coefficients.
|
||||
\brief Get a snapshot of the current equalizer coefficients.
|
||||
\param coeffs The vector of complex coefficients.
|
||||
|
@ -106,6 +125,11 @@ SPAN_DECLARE(float) v22bis_symbol_timing_correction(v22bis_state_t *s);
|
|||
\return The signal power, in dBm0. */
|
||||
SPAN_DECLARE(float) v22bis_rx_signal_power(v22bis_state_t *s);
|
||||
|
||||
/*! Set the power level at which the carrier detection will cut in
|
||||
\param s The modem context.
|
||||
\param cutoff The signal cutoff power, in dBm0. */
|
||||
SPAN_DECLARE(void) v22bis_rx_signal_cutoff(v22bis_state_t *s, float cutoff);
|
||||
|
||||
/*! Set a handler routine to process QAM status reports
|
||||
\param s The modem context.
|
||||
\param handler The handler routine.
|
||||
|
@ -164,6 +188,10 @@ SPAN_DECLARE(int) v22bis_release(v22bis_state_t *s);
|
|||
\return 0 for OK */
|
||||
SPAN_DECLARE(int) v22bis_free(v22bis_state_t *s);
|
||||
|
||||
/*! Get the logging context associated with a V.22bis modem context.
|
||||
\brief Get the logging context associated with a V.22bis modem context.
|
||||
\param s The modem context.
|
||||
\return A pointer to the logging context */
|
||||
SPAN_DECLARE(logging_state_t *) v22bis_get_logging_state(v22bis_state_t *s);
|
||||
|
||||
/*! Change the get_bit function associated with a V.22bis modem context.
|
||||
|
@ -180,6 +208,13 @@ SPAN_DECLARE(void) v22bis_set_get_bit(v22bis_state_t *s, get_bit_func_t get_bit,
|
|||
\param user_data An opaque pointer. */
|
||||
SPAN_DECLARE(void) v22bis_set_put_bit(v22bis_state_t *s, put_bit_func_t put_bit, void *user_data);
|
||||
|
||||
/*! Change the modem status report function associated with a V.22bis modem receive context.
|
||||
\brief Change the modem status report function associated with a V.22bis modem receive context.
|
||||
\param s The modem context.
|
||||
\param handler The callback routine used to report modem status changes.
|
||||
\param user_data An opaque pointer. */
|
||||
SPAN_DECLARE(void) v22bis_set_modem_status_handler(v22bis_state_t *s, modem_rx_status_func_t handler, void *user_data);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: v27ter_rx.h,v 1.57 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: v27ter_rx.h,v 1.59 2009/04/12 09:12:11 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -48,10 +48,14 @@ straightforward.
|
|||
|
||||
/* Target length for the equalizer is about 43 taps for 4800bps and 32 taps for 2400bps
|
||||
to deal with the worst stuff in V.56bis. */
|
||||
/*! Samples before the target position in the equalizer buffer */
|
||||
#define V27TER_EQUALIZER_PRE_LEN 16 /* This much before the real event */
|
||||
/*! Samples after the target position in the equalizer buffer */
|
||||
#define V27TER_EQUALIZER_POST_LEN 14 /* This much after the real event (must be even) */
|
||||
|
||||
/*! The number of taps in the 4800bps pulse shaping/bandpass filter */
|
||||
#define V27TER_RX_4800_FILTER_STEPS 27
|
||||
/*! The number of taps in the 2400bps pulse shaping/bandpass filter */
|
||||
#define V27TER_RX_2400_FILTER_STEPS 27
|
||||
|
||||
#if V27TER_RX_4800_FILTER_STEPS > V27TER_RX_2400_FILTER_STEPS
|
||||
|
@ -100,6 +104,10 @@ SPAN_DECLARE(int) v27ter_rx_release(v27ter_rx_state_t *s);
|
|||
\return 0 for OK */
|
||||
SPAN_DECLARE(int) v27ter_rx_free(v27ter_rx_state_t *s);
|
||||
|
||||
/*! Get the logging context associated with a V.27ter modem receive context.
|
||||
\brief Get the logging context associated with a V.27ter modem receive context.
|
||||
\param s The modem context.
|
||||
\return A pointer to the logging context */
|
||||
SPAN_DECLARE(logging_state_t *) v27ter_rx_get_logging_state(v27ter_rx_state_t *s);
|
||||
|
||||
/*! Change the put_bit function associated with a V.27ter modem receive context.
|
||||
|
@ -125,6 +133,15 @@ SPAN_DECLARE(void) v27ter_rx_set_modem_status_handler(v27ter_rx_state_t *s, mode
|
|||
*/
|
||||
SPAN_DECLARE(int) v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], int len);
|
||||
|
||||
/*! Fake processing of a missing block of received V.27ter modem audio samples.
|
||||
(e.g due to packet loss).
|
||||
\brief Fake processing of a missing block of received V.27ter modem audio samples.
|
||||
\param s The modem context.
|
||||
\param len The number of samples to fake.
|
||||
\return The number of samples unprocessed.
|
||||
*/
|
||||
SPAN_DECLARE(int) v27ter_rx_fillin(v27ter_rx_state_t *s, int len);
|
||||
|
||||
/*! Get a snapshot of the current equalizer coefficients.
|
||||
\brief Get a snapshot of the current equalizer coefficients.
|
||||
\param coeffs The vector of complex coefficients.
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: v27ter_tx.h,v 1.40 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: v27ter_tx.h,v 1.41 2009/04/12 09:12:11 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -64,6 +64,7 @@ suits the receiver better, so then same signal generator is also used for the
|
|||
transmitter.
|
||||
*/
|
||||
|
||||
/*! The number of taps in the pulse shaping/bandpass filter */
|
||||
#define V27TER_TX_FILTER_STEPS 9
|
||||
|
||||
/*!
|
||||
|
@ -113,6 +114,10 @@ SPAN_DECLARE(int) v27ter_tx_release(v27ter_tx_state_t *s);
|
|||
\return 0 for OK */
|
||||
SPAN_DECLARE(int) v27ter_tx_free(v27ter_tx_state_t *s);
|
||||
|
||||
/*! Get the logging context associated with a V.27ter modem transmit context.
|
||||
\brief Get the logging context associated with a V.27ter modem transmit context.
|
||||
\param s The modem context.
|
||||
\return A pointer to the logging context */
|
||||
SPAN_DECLARE(logging_state_t *) v27ter_tx_get_logging_state(v27ter_tx_state_t *s);
|
||||
|
||||
/*! Change the get_bit function associated with a V.27ter modem transmit context.
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: v29rx.h,v 1.68 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: v29rx.h,v 1.70 2009/04/12 09:12:11 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -122,9 +122,12 @@ therefore, only tests that bits starting at bit 24 are really ones.
|
|||
|
||||
/* Target length for the equalizer is about 63 taps, to deal with the worst stuff
|
||||
in V.56bis. */
|
||||
#define V29_EQUALIZER_PRE_LEN 16 /* This much before the real event */
|
||||
#define V29_EQUALIZER_POST_LEN 14 /* This much after the real event (must be even) */
|
||||
/*! Samples before the target position in the equalizer buffer */
|
||||
#define V29_EQUALIZER_PRE_LEN 16
|
||||
/*! Samples after the target position in the equalizer buffer */
|
||||
#define V29_EQUALIZER_POST_LEN 14
|
||||
|
||||
/*! The number of taps in the pulse shaping/bandpass filter */
|
||||
#define V29_RX_FILTER_STEPS 27
|
||||
|
||||
typedef void (*qam_report_handler_t)(void *user_data, const complexf_t *constel, const complexf_t *target, int symbol);
|
||||
|
@ -169,6 +172,10 @@ SPAN_DECLARE(int) v29_rx_release(v29_rx_state_t *s);
|
|||
\return 0 for OK */
|
||||
SPAN_DECLARE(int) v29_rx_free(v29_rx_state_t *s);
|
||||
|
||||
/*! Get the logging context associated with a V.29 modem receive context.
|
||||
\brief Get the logging context associated with a V.29 modem receive context.
|
||||
\param s The modem context.
|
||||
\return A pointer to the logging context */
|
||||
SPAN_DECLARE(logging_state_t *) v29_rx_get_logging_state(v29_rx_state_t *s);
|
||||
|
||||
/*! Change the put_bit function associated with a V.29 modem receive context.
|
||||
|
@ -193,6 +200,14 @@ SPAN_DECLARE(void) v29_rx_set_modem_status_handler(v29_rx_state_t *s, modem_rx_s
|
|||
\return The number of samples unprocessed. */
|
||||
SPAN_DECLARE(int) v29_rx(v29_rx_state_t *s, const int16_t amp[], int len);
|
||||
|
||||
/*! Fake processing of a missing block of received V.29 modem audio samples.
|
||||
(e.g due to packet loss).
|
||||
\brief Fake processing of a missing block of received V.29 modem audio samples.
|
||||
\param s The modem context.
|
||||
\param len The number of samples to fake.
|
||||
\return The number of samples unprocessed. */
|
||||
SPAN_DECLARE(int) v29_rx_fillin(v29_rx_state_t *s, int len);
|
||||
|
||||
/*! Get a snapshot of the current equalizer coefficients.
|
||||
\brief Get a snapshot of the current equalizer coefficients.
|
||||
\param s The modem context.
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: v29tx.h,v 1.38 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: v29tx.h,v 1.39 2009/04/12 09:12:11 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -94,6 +94,7 @@ gives
|
|||
|
||||
*/
|
||||
|
||||
/*! The number of taps in the pulse shaping/bandpass filter */
|
||||
#define V29_TX_FILTER_STEPS 9
|
||||
|
||||
/*!
|
||||
|
@ -144,6 +145,10 @@ SPAN_DECLARE(int) v29_tx_release(v29_tx_state_t *s);
|
|||
\return 0 for OK */
|
||||
SPAN_DECLARE(int) v29_tx_free(v29_tx_state_t *s);
|
||||
|
||||
/*! Get the logging context associated with a V.29 modem transmit context.
|
||||
\brief Get the logging context associated with a V.29 modem transmit context.
|
||||
\param s The modem context.
|
||||
\return A pointer to the logging context */
|
||||
SPAN_DECLARE(logging_state_t *) v29_tx_get_logging_state(v29_tx_state_t *s);
|
||||
|
||||
/*! Change the get_bit function associated with a V.29 modem transmit context.
|
||||
|
@ -167,7 +172,7 @@ SPAN_DECLARE(void) v29_tx_set_modem_status_handler(v29_tx_state_t *s, modem_tx_s
|
|||
\param len The number of samples to be generated.
|
||||
\return The number of samples actually generated.
|
||||
*/
|
||||
SPAN_DECLARE(int) v29_tx(v29_tx_state_t *s, int16_t *amp, int len);
|
||||
SPAN_DECLARE(int) v29_tx(v29_tx_state_t *s, int16_t amp[], int len);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: v42bis.h,v 1.26 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: v42bis.h,v 1.27 2009/04/11 18:11:19 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \page v42bis_page V.42bis modem data compression
|
||||
|
@ -107,11 +107,11 @@ SPAN_DECLARE(void) v42bis_compression_control(v42bis_state_t *s, int mode);
|
|||
\param negotiated_p0 The negotiated P0 parameter, from the V.42bis spec.
|
||||
\param negotiated_p1 The negotiated P1 parameter, from the V.42bis spec.
|
||||
\param negotiated_p2 The negotiated P2 parameter, from the V.42bis spec.
|
||||
\param frame_handler .
|
||||
\param frame_user_data .
|
||||
\param frame_handler Frame callback handler.
|
||||
\param frame_user_data An opaque pointer passed to the frame callback handler.
|
||||
\param max_frame_len The maximum length that should be passed to the frame handler.
|
||||
\param data_handler .
|
||||
\param data_user_data .
|
||||
\param data_handler data callback handler.
|
||||
\param data_user_data An opaque pointer passed to the data callback handler.
|
||||
\param max_data_len The maximum length that should be passed to the data handler.
|
||||
\return The V.42bis context. */
|
||||
SPAN_DECLARE(v42bis_state_t *) v42bis_init(v42bis_state_t *s,
|
||||
|
|
|
@ -30,9 +30,9 @@
|
|||
|
||||
/* The date and time of the version are in UTC form. */
|
||||
|
||||
#define SPANDSP_RELEASE_DATE 20090307
|
||||
#define SPANDSP_RELEASE_TIME 165620
|
||||
#define SPANDSP_RELEASE_DATETIME_STRING "20090307 165620"
|
||||
#define SPANDSP_RELEASE_DATE 20090420
|
||||
#define SPANDSP_RELEASE_TIME 163808
|
||||
#define SPANDSP_RELEASE_DATETIME_STRING "20090420 163808"
|
||||
|
||||
#endif
|
||||
/*- End of file ------------------------------------------------------------*/
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: t30.c,v 1.288 2009/02/26 12:11:51 steveu Exp $
|
||||
* $Id: t30.c,v 1.290 2009/04/16 12:11:54 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -73,8 +73,10 @@
|
|||
|
||||
#include "t30_local.h"
|
||||
|
||||
/*! The maximum number of consecutive retries allowed. */
|
||||
#define MAX_MESSAGE_TRIES 3
|
||||
|
||||
/*! Conversion between milliseconds and audio samples. */
|
||||
#define ms_to_samples(t) (((t)*SAMPLE_RATE)/1000)
|
||||
|
||||
/* T.30 defines the following call phases:
|
||||
|
@ -207,7 +209,7 @@ enum
|
|||
|
||||
/* All timers specified in milliseconds */
|
||||
|
||||
/* Time-out T0 defines the amount of time an automatic calling terminal waits for the called terminal
|
||||
/*! Time-out T0 defines the amount of time an automatic calling terminal waits for the called terminal
|
||||
to answer the call.
|
||||
T0 begins after the dialling of the number is completed and is reset:
|
||||
a) when T0 times out; or
|
||||
|
@ -219,41 +221,45 @@ time may be encountered, an alternative value of up to 120s may be used.
|
|||
NOTE - National regulations may require the use of other values for T0. */
|
||||
#define DEFAULT_TIMER_T0 60000
|
||||
|
||||
/* Time-out T1 defines the amount of time two terminals will continue to attempt to identify each
|
||||
/*! Time-out T1 defines the amount of time two terminals will continue to attempt to identify each
|
||||
other. T1 is 35+-5s, begins upon entering phase B, and is reset upon detecting a valid signal or
|
||||
when T1 times out.
|
||||
For operating methods 3 and 4 (see 3.1), the calling terminal starts time-out T1 upon reception of
|
||||
the V.21 modulation scheme.
|
||||
For operating method 4 bis a (see 3.1), the calling terminal starts time-out T1 upon starting
|
||||
transmission using the V.21 modulation scheme. */
|
||||
transmission using the V.21 modulation scheme.
|
||||
Annex A says T1 is also the timeout to be used for the receipt of the first HDLC frame after the
|
||||
start of high speed flags in ECM mode. This seems a strange reuse of the T1 name, so we distinguish
|
||||
it here by calling it T1A. */
|
||||
#define DEFAULT_TIMER_T1 35000
|
||||
#define DEFAULT_TIMER_T1A 35000
|
||||
|
||||
/* Time-out T2 makes use of the tight control between commands and responses to detect the loss of
|
||||
/*! Time-out T2 makes use of the tight control between commands and responses to detect the loss of
|
||||
command/response synchronization. T2 is 6+-1s, and begins when initiating a command search
|
||||
(e.g., the first entrance into the "command received" subroutine, reference flow diagram in section 5.2).
|
||||
T2 is reset when an HDLC flag is received or when T2 times out. */
|
||||
#define DEFAULT_TIMER_T2 7000
|
||||
|
||||
/* Once HDLC flags begin, T2 is reset, and a 3s timer begins. This timer is unnamed in T.30. Here we
|
||||
/*! Once HDLC flags begin, T2 is reset, and a 3s timer begins. This timer is unnamed in T.30. Here we
|
||||
term it T2A. No tolerance is specified for this timer. T2A specifies the maximum time to wait for the
|
||||
end of a frame, after the initial flag has been seen. */
|
||||
#define DEFAULT_TIMER_T2A 3000
|
||||
|
||||
/* If the HDLC carrier falls during reception, we need to apply a minimum time before continuing. if we
|
||||
/*! If the HDLC carrier falls during reception, we need to apply a minimum time before continuing. if we
|
||||
don't, there are circumstances where we could continue and reply before the incoming signals have
|
||||
really finished. E.g. if a bad DCS is received in a DCS-TCF sequence, we need wait for the TCF
|
||||
carrier to pass, before continuing. This timer is specified as 200ms, but no tolerance is specified.
|
||||
It is unnamed in T.30. Here we termin it T2B */
|
||||
It is unnamed in T.30. Here we term it T2B */
|
||||
#define DEFAULT_TIMER_T2B 200
|
||||
|
||||
/* Time-out T3 defines the amount of time a terminal will attempt to alert the local operator in
|
||||
/*! Time-out T3 defines the amount of time a terminal will attempt to alert the local operator in
|
||||
response to a procedural interrupt. Failing to achieve operator intervention, the terminal will
|
||||
discontinue this attempt and shall issue other commands or responses. T3 is 10+-5s, begins on the
|
||||
first detection of a procedural interrupt command/response signal (i.e., PIN/PIP or PRI-Q) and is
|
||||
reset when T3 times out or when the operator initiates a line request. */
|
||||
#define DEFAULT_TIMER_T3 15000
|
||||
|
||||
/* Time-out T4 defines the amount of time a terminal will wait for flags to begin, when waiting for a
|
||||
/*! Time-out T4 defines the amount of time a terminal will wait for flags to begin, when waiting for a
|
||||
response from a remote terminal. T2 is 3s +-15%, and begins when initiating a response search
|
||||
(e.g., the first entrance into the "response received" subroutine, reference flow diagram in section 5.2).
|
||||
T4 is reset when an HDLC flag is received or when T4 times out.
|
||||
|
@ -262,19 +268,20 @@ If the value of 4.5s is used, then after detection of a valid response to the fi
|
|||
be reduced to 3.0s +-15%. T4 = 3.0s +-15% for automatic units. */
|
||||
#define DEFAULT_TIMER_T4 3450
|
||||
|
||||
/* Once HDLC flags begin, T4 is reset, and a 3s timer begins. This timer is unnamed in T.30. Here we
|
||||
/*! Once HDLC flags begin, T4 is reset, and a 3s timer begins. This timer is unnamed in T.30. Here we
|
||||
term it T4A. No tolerance is specified for this timer. T4A specifies the maximum time to wait for the
|
||||
end of a frame, after the initial flag has been seen. */
|
||||
end of a frame, after the initial flag has been seen. Note that a different timer is used for the fast
|
||||
HDLC in ECM mode, to provide time for physical paper handling. */
|
||||
#define DEFAULT_TIMER_T4A 3000
|
||||
|
||||
/* If the HDLC carrier falls during reception, we need to apply a minimum time before continuing. if we
|
||||
/*! If the HDLC carrier falls during reception, we need to apply a minimum time before continuing. if we
|
||||
don't, there are circumstances where we could continue and reply before the incoming signals have
|
||||
really finished. E.g. if a bad DCS is received in a DCS-TCF sequence, we need wait for the TCF
|
||||
carrier to pass, before continuing. This timer is specified as 200ms, but no tolerance is specified.
|
||||
It is unnamed in T.30. Here we termin it T4B */
|
||||
It is unnamed in T.30. Here we term it T4B */
|
||||
#define DEFAULT_TIMER_T4B 200
|
||||
|
||||
/* Time-out T5 is defined for the optional T.4 error correction mode. Time-out T5 defines the amount
|
||||
/*! Time-out T5 is defined for the optional T.4 error correction mode. Time-out T5 defines the amount
|
||||
of time waiting for clearance of the busy condition of the receiving terminal. T5 is 60+-5s and
|
||||
begins on the first detection of the RNR response. T5 is reset when T5 times out or the MCF or PIP
|
||||
response is received or when the ERR or PIN response is received in the flow control process after
|
||||
|
@ -282,27 +289,27 @@ transmitting the EOR command. If the timer T5 has expired, the DCN command is tr
|
|||
call release. */
|
||||
#define DEFAULT_TIMER_T5 65000
|
||||
|
||||
/* (Annex C - ISDN) Time-out T6 defines the amount of time two terminals will continue to attempt to
|
||||
/*! (Annex C - ISDN) Time-out T6 defines the amount of time two terminals will continue to attempt to
|
||||
identify each other. T6 is 5+-0.5s. The timeout begins upon entering Phase B, and is reset upon
|
||||
detecting a valid signal, or when T6 times out. */
|
||||
#define DEFAULT_TIMER_T6 5000
|
||||
|
||||
/* (Annex C - ISDN) Time-out T7 is used to detect loss of command/response synchronization. T7 is 6+-1s.
|
||||
/*! (Annex C - ISDN) Time-out T7 is used to detect loss of command/response synchronization. T7 is 6+-1s.
|
||||
The timeout begins when initiating a command search (e.g., the first entrance into the "command received"
|
||||
subroutine - see flow diagram in C.5) and is reset upon detecting a valid signal or when T7 times out. */
|
||||
#define DEFAULT_TIMER_T7 7000
|
||||
|
||||
/* (Annex C - ISDN) Time-out T8 defines the amount of time waiting for clearance of the busy condition
|
||||
/*! (Annex C - ISDN) Time-out T8 defines the amount of time waiting for clearance of the busy condition
|
||||
of the receiving terminal. T8 is 10+-1s. The timeout begins on the first detection of the combination
|
||||
of no outstanding corrections and the RNR response. T8 is reset when T8 times out or MCF response is
|
||||
received. If the timer T8 expires, a DCN command is transmitted for call release. */
|
||||
#define DEFAULT_TIMER_T8 10000
|
||||
|
||||
/* Final time we allow for things to flush through the system, before we disconnect, in milliseconds.
|
||||
/*! Final time we allow for things to flush through the system, before we disconnect, in milliseconds.
|
||||
200ms should be fine for a PSTN call. For a T.38 call something longer is desirable. */
|
||||
#define FINAL_FLUSH_TIME 1000
|
||||
|
||||
/* The number of PPRs received before CTC or EOR is sent in ECM mode. T.30 defines this as 4,
|
||||
/*! The number of PPRs received before CTC or EOR is sent in ECM mode. T.30 defines this as 4,
|
||||
but it could be varied, and the Japanese spec, for example, does make this value a
|
||||
variable. */
|
||||
#define PPR_LIMIT_BEFORE_CTC_OR_EOR 4
|
||||
|
@ -320,8 +327,11 @@ enum
|
|||
};
|
||||
|
||||
/* Start points in the fallback table for different capabilities */
|
||||
/*! The starting point in the modem fallback sequence if V.17 is allowed */
|
||||
#define T30_V17_FALLBACK_START 0
|
||||
/*! The starting point in the modem fallback sequence if V.17 is not allowed */
|
||||
#define T30_V29_FALLBACK_START 3
|
||||
/*! The starting point in the modem fallback sequence if V.29 is not allowed */
|
||||
#define T30_V27TER_FALLBACK_START 6
|
||||
|
||||
static const struct
|
||||
|
@ -361,10 +371,15 @@ static void timer_t2b_start(t30_state_t *s);
|
|||
static void timer_t4_start(t30_state_t *s);
|
||||
static void timer_t4a_start(t30_state_t *s);
|
||||
static void timer_t4b_start(t30_state_t *s);
|
||||
static void timer_t2_t4_stop(t30_state_t *s);
|
||||
|
||||
/*! Test a specified bit within a DIS, DTC or DCS frame */
|
||||
#define test_ctrl_bit(s,bit) ((s)[3 + ((bit - 1)/8)] & (1 << ((bit - 1)%8)))
|
||||
/*! Set a specified bit within a DIS, DTC or DCS frame */
|
||||
#define set_ctrl_bit(s,bit) (s)[3 + ((bit - 1)/8)] |= (1 << ((bit - 1)%8))
|
||||
/*! Set a specified block of bits within a DIS, DTC or DCS frame */
|
||||
#define set_ctrl_bits(s,val,bit) (s)[3 + ((bit - 1)/8)] |= ((val) << ((bit - 1)%8))
|
||||
/*! Clear a specified bit within a DIS, DTC or DCS frame */
|
||||
#define clr_ctrl_bit(s,bit) (s)[3 + ((bit - 1)/8)] &= ~(1 << ((bit - 1)%8))
|
||||
|
||||
static int terminate_operation_in_progress(t30_state_t *s)
|
||||
|
@ -4648,8 +4663,19 @@ static void timer_t2_start(t30_state_t *s)
|
|||
|
||||
static void timer_t2a_start(t30_state_t *s)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Start T2A\n");
|
||||
s->timer_t2_t4 = ms_to_samples(DEFAULT_TIMER_T2A);
|
||||
/* T.30 Annex A says timeout T1 should be used in ECM phase C to time out the
|
||||
first frame after the flags start. This seems a strange reuse of the name T1
|
||||
for a different purpose, but there it is. We distinguish it by calling it T1A. */
|
||||
if (s->phase == T30_PHASE_C_ECM_RX)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Start T1A\n");
|
||||
s->timer_t2_t4 = ms_to_samples(DEFAULT_TIMER_T1A);
|
||||
}
|
||||
else
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Start T2A\n");
|
||||
s->timer_t2_t4 = ms_to_samples(DEFAULT_TIMER_T2A);
|
||||
}
|
||||
s->timer_t2_t4_is = TIMER_IS_T2A;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -4686,6 +4712,13 @@ static void timer_t4b_start(t30_state_t *s)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void timer_t2_t4_stop(t30_state_t *s)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Stop T2/T4\n");
|
||||
s->timer_t2_t4 = 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void timer_t0_expired(t30_state_t *s)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "T0 expired in state %d\n", s->state);
|
||||
|
@ -4934,7 +4967,7 @@ static void t30_non_ecm_rx_status(void *user_data, int status)
|
|||
s->tcf_most_zeros = 0;
|
||||
s->rx_signal_present = TRUE;
|
||||
s->rx_trained = TRUE;
|
||||
s->timer_t2_t4 = 0;
|
||||
timer_t2_t4_stop(s);
|
||||
break;
|
||||
case SIG_STATUS_CARRIER_UP:
|
||||
break;
|
||||
|
@ -5261,11 +5294,11 @@ static void t30_hdlc_rx_status(void *user_data, int status)
|
|||
{
|
||||
case TIMER_IS_T2B:
|
||||
s->timer_t2_t4_is = TIMER_IS_T2C;
|
||||
s->timer_t2_t4 = 0;
|
||||
timer_t2_t4_stop(s);
|
||||
break;
|
||||
case TIMER_IS_T4B:
|
||||
s->timer_t2_t4_is = TIMER_IS_T4C;
|
||||
s->timer_t2_t4 = 0;
|
||||
timer_t2_t4_stop(s);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -5276,7 +5309,7 @@ static void t30_hdlc_rx_status(void *user_data, int status)
|
|||
its time to change. */
|
||||
if (s->next_phase != T30_PHASE_IDLE)
|
||||
{
|
||||
s->timer_t2_t4 = 0;
|
||||
timer_t2_t4_stop(s);
|
||||
set_phase(s, s->next_phase);
|
||||
if (s->next_phase == T30_PHASE_C_NON_ECM_RX)
|
||||
timer_t2_start(s);
|
||||
|
@ -5384,7 +5417,7 @@ SPAN_DECLARE_NONSTD(void) t30_hdlc_accept(void *user_data, const uint8_t *msg, i
|
|||
}
|
||||
s->rx_frame_received = TRUE;
|
||||
/* Cancel the command or response timer */
|
||||
s->timer_t2_t4 = 0;
|
||||
timer_t2_t4_stop(s);
|
||||
process_rx_control_msg(s, msg, len);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -5684,7 +5717,7 @@ SPAN_DECLARE(void) t30_front_end_status(void *user_data, int status)
|
|||
/* Cancel any receive timeout, and declare that a receive signal is present,
|
||||
since the front end is explicitly telling us we have seen something. */
|
||||
s->rx_signal_present = TRUE;
|
||||
s->timer_t2_t4 = 0;
|
||||
timer_t2_t4_stop(s);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: t30_logging.c,v 1.11 2009/02/03 16:28:40 steveu Exp $
|
||||
* $Id: t30_logging.c,v 1.12 2009/04/12 09:12:10 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -72,6 +72,7 @@
|
|||
|
||||
#include "t30_local.h"
|
||||
|
||||
/*! Value string pair structure */
|
||||
typedef struct
|
||||
{
|
||||
int val;
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: t31.c,v 1.144 2009/02/16 09:57:22 steveu Exp $
|
||||
* $Id: t31.c,v 1.150 2009/04/12 09:12:10 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -86,6 +86,7 @@
|
|||
|
||||
#include "spandsp/private/logging.h"
|
||||
#include "spandsp/private/t38_core.h"
|
||||
#include "spandsp/private/silence_gen.h"
|
||||
#include "spandsp/private/fsk.h"
|
||||
#include "spandsp/private/v17tx.h"
|
||||
#include "spandsp/private/v17rx.h"
|
||||
|
@ -100,10 +101,15 @@
|
|||
#include "spandsp/private/t31.h"
|
||||
|
||||
/* Settings suitable for paced transmission over a UDP transport */
|
||||
/*! The default number of milliseconds per transmitted IFP when sending bulk T.38 data */
|
||||
#define MS_PER_TX_CHUNK 30
|
||||
/*! The number of transmissions of indicator IFP packets */
|
||||
#define INDICATOR_TX_COUNT 3
|
||||
/*! The number of transmissions of data IFP packets */
|
||||
#define DATA_TX_COUNT 1
|
||||
/*! The number of transmissions of terminating data IFP packets */
|
||||
#define DATA_END_TX_COUNT 3
|
||||
/*! The default DTE timeout, in seconds */
|
||||
#define DEFAULT_DTE_TIMEOUT 5
|
||||
|
||||
/* Settings suitable for unpaced transmission over a TCP transport */
|
||||
|
@ -135,26 +141,6 @@ enum
|
|||
DISBIT8 = 0x80
|
||||
};
|
||||
|
||||
/* BEWARE: right now this must match up with a list in the AT interpreter code. */
|
||||
enum
|
||||
{
|
||||
T31_NONE = -1,
|
||||
T31_FLUSH = 0,
|
||||
T31_SILENCE_TX,
|
||||
T31_SILENCE_RX,
|
||||
T31_CED_TONE,
|
||||
T31_CNG_TONE,
|
||||
T31_NOCNG_TONE,
|
||||
T31_V21_TX,
|
||||
T31_V17_TX,
|
||||
T31_V27TER_TX,
|
||||
T31_V29_TX,
|
||||
T31_V21_RX,
|
||||
T31_V17_RX,
|
||||
T31_V27TER_RX,
|
||||
T31_V29_RX
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
T38_CHUNKING_MERGE_FCS_WITH_DATA = 0x0001,
|
||||
|
@ -190,6 +176,9 @@ enum
|
|||
|
||||
static int restart_modem(t31_state_t *s, int new_modem);
|
||||
static void hdlc_accept_frame(void *user_data, const uint8_t *msg, int len, int ok);
|
||||
static void set_rx_handler(t31_state_t *s, span_rx_handler_t *handler, void *user_data);
|
||||
static void set_tx_handler(t31_state_t *s, span_tx_handler_t *handler, void *user_data);
|
||||
static void set_next_tx_handler(t31_state_t *s, span_tx_handler_t *handler, void *user_data);
|
||||
static int v17_v21_rx(void *user_data, const int16_t amp[], int len);
|
||||
static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len);
|
||||
static int v29_v21_rx(void *user_data, const int16_t amp[], int len);
|
||||
|
@ -239,8 +228,8 @@ static void front_end_status(t31_state_t *s, int status)
|
|||
case T30_FRONT_END_SEND_STEP_COMPLETE:
|
||||
switch (s->modem)
|
||||
{
|
||||
case T31_SILENCE_TX:
|
||||
s->modem = T31_NONE;
|
||||
case FAX_MODEM_SILENCE_TX:
|
||||
s->modem = FAX_MODEM_NONE;
|
||||
at_put_response_code(&s->at_state, AT_RESPONSE_CODE_OK);
|
||||
if (s->at_state.do_hangup)
|
||||
{
|
||||
|
@ -253,20 +242,20 @@ static void front_end_status(t31_state_t *s, int status)
|
|||
t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND);
|
||||
}
|
||||
break;
|
||||
case T31_CED_TONE:
|
||||
case FAX_MODEM_CED_TONE:
|
||||
/* Go directly to V.21/HDLC transmit. */
|
||||
s->modem = T31_NONE;
|
||||
restart_modem(s, T31_V21_TX);
|
||||
s->modem = FAX_MODEM_NONE;
|
||||
restart_modem(s, FAX_MODEM_V21_TX);
|
||||
t31_set_at_rx_mode(s, AT_MODE_HDLC);
|
||||
break;
|
||||
case T31_V21_TX:
|
||||
case T31_V17_TX:
|
||||
case T31_V27TER_TX:
|
||||
case T31_V29_TX:
|
||||
s->modem = T31_NONE;
|
||||
case FAX_MODEM_V21_TX:
|
||||
case FAX_MODEM_V17_TX:
|
||||
case FAX_MODEM_V27TER_TX:
|
||||
case FAX_MODEM_V29_TX:
|
||||
s->modem = FAX_MODEM_NONE;
|
||||
at_put_response_code(&s->at_state, AT_RESPONSE_CODE_OK);
|
||||
t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND);
|
||||
restart_modem(s, T31_SILENCE_TX);
|
||||
restart_modem(s, FAX_MODEM_SILENCE_TX);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
@ -669,7 +658,7 @@ static void send_hdlc(void *user_data, const uint8_t *msg, int len)
|
|||
|
||||
static __inline__ int bits_to_us(t31_state_t *s, int bits)
|
||||
{
|
||||
if (s->t38_fe.ms_per_tx_chunk == 0)
|
||||
if (s->t38_fe.ms_per_tx_chunk == 0 || s->t38_fe.tx_bit_rate == 0)
|
||||
return 0;
|
||||
return bits*1000000/s->t38_fe.tx_bit_rate;
|
||||
}
|
||||
|
@ -1075,7 +1064,7 @@ static int t31_modem_control_handler(at_state_t *s, void *user_data, int op, con
|
|||
t->at_state.rx_data_bytes);
|
||||
t->at_state.rx_data_bytes = 0;
|
||||
}
|
||||
restart_modem(t, T31_SILENCE_TX);
|
||||
restart_modem(t, FAX_MODEM_SILENCE_TX);
|
||||
break;
|
||||
case AT_MODEM_CONTROL_RESTART:
|
||||
restart_modem(t, (int) (intptr_t) num);
|
||||
|
@ -1339,7 +1328,7 @@ static void hdlc_rx_status(void *user_data, int status)
|
|||
s->at_state.rx_trained = TRUE;
|
||||
break;
|
||||
case SIG_STATUS_CARRIER_UP:
|
||||
if (s->modem == T31_CNG_TONE || s->modem == T31_NOCNG_TONE || s->modem == T31_V21_RX)
|
||||
if (s->modem == FAX_MODEM_CNG_TONE || s->modem == FAX_MODEM_NOCNG_TONE || s->modem == FAX_MODEM_V21_RX)
|
||||
{
|
||||
s->at_state.rx_signal_present = TRUE;
|
||||
s->rx_frame_received = FALSE;
|
||||
|
@ -1372,14 +1361,14 @@ static void hdlc_rx_status(void *user_data, int status)
|
|||
s->at_state.rx_trained = FALSE;
|
||||
break;
|
||||
case SIG_STATUS_FRAMING_OK:
|
||||
if (s->modem == T31_CNG_TONE || s->modem == T31_NOCNG_TONE)
|
||||
if (s->modem == FAX_MODEM_CNG_TONE || s->modem == FAX_MODEM_NOCNG_TONE)
|
||||
{
|
||||
/* Once we get any valid HDLC the CNG tone stops, and we drop
|
||||
to the V.21 receive modem on its own. */
|
||||
s->modem = T31_V21_RX;
|
||||
s->modem = FAX_MODEM_V21_RX;
|
||||
s->at_state.transmit = FALSE;
|
||||
}
|
||||
if (s->modem == T31_V17_RX || s->modem == T31_V27TER_RX || s->modem == T31_V29_RX)
|
||||
if (s->modem == FAX_MODEM_V17_RX || s->modem == FAX_MODEM_V27TER_RX || s->modem == FAX_MODEM_V29_RX)
|
||||
{
|
||||
/* V.21 has been detected while expecting a different carrier.
|
||||
If +FAR=0 then result +FCERROR and return to command-mode.
|
||||
|
@ -1389,7 +1378,7 @@ static void hdlc_rx_status(void *user_data, int status)
|
|||
{
|
||||
s->at_state.rx_signal_present = TRUE;
|
||||
s->rx_frame_received = TRUE;
|
||||
s->modem = T31_V21_RX;
|
||||
s->modem = FAX_MODEM_V21_RX;
|
||||
s->at_state.transmit = FALSE;
|
||||
s->at_state.dte_is_waiting = TRUE;
|
||||
at_put_response_code(&s->at_state, AT_RESPONSE_CODE_FRH3);
|
||||
|
@ -1397,7 +1386,7 @@ static void hdlc_rx_status(void *user_data, int status)
|
|||
}
|
||||
else
|
||||
{
|
||||
s->modem = T31_SILENCE_TX;
|
||||
s->modem = FAX_MODEM_SILENCE_TX;
|
||||
t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND);
|
||||
s->rx_frame_received = FALSE;
|
||||
at_put_response_code(&s->at_state, AT_RESPONSE_CODE_FCERROR);
|
||||
|
@ -1530,12 +1519,11 @@ static int restart_modem(t31_state_t *s, int new_modem)
|
|||
s->at_state.rx_signal_present = FALSE;
|
||||
s->at_state.rx_trained = FALSE;
|
||||
s->rx_frame_received = FALSE;
|
||||
t->rx_handler = (span_rx_handler_t *) &span_dummy_rx;
|
||||
t->rx_user_data = NULL;
|
||||
set_rx_handler(s, (span_rx_handler_t *) &span_dummy_rx, NULL);
|
||||
use_hdlc = FALSE;
|
||||
switch (s->modem)
|
||||
{
|
||||
case T31_CNG_TONE:
|
||||
case FAX_MODEM_CNG_TONE:
|
||||
if (s->t38_mode)
|
||||
{
|
||||
s->t38_fe.next_tx_samples = s->t38_fe.samples;
|
||||
|
@ -1550,31 +1538,27 @@ static int restart_modem(t31_state_t *s, int new_modem)
|
|||
/* Do V.21/HDLC receive in parallel. The other end may send its
|
||||
first message at any time. The CNG tone will continue until
|
||||
we get a valid preamble. */
|
||||
t->rx_handler = (span_rx_handler_t *) &cng_rx;
|
||||
t->rx_user_data = s;
|
||||
set_rx_handler(s, (span_rx_handler_t *) &cng_rx, s);
|
||||
t31_v21_rx(s);
|
||||
t->tx_handler = (span_tx_handler_t *) &modem_connect_tones_tx;
|
||||
t->tx_user_data = &t->connect_tx;
|
||||
s->audio.next_tx_handler = NULL;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &modem_connect_tones_tx, &t->connect_tx);
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
|
||||
}
|
||||
s->at_state.transmit = TRUE;
|
||||
break;
|
||||
case T31_NOCNG_TONE:
|
||||
case FAX_MODEM_NOCNG_TONE:
|
||||
if (s->t38_mode)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
t->rx_handler = (span_rx_handler_t *) &cng_rx;
|
||||
t->rx_user_data = s;
|
||||
set_rx_handler(s, (span_rx_handler_t *) &cng_rx, s);
|
||||
t31_v21_rx(s);
|
||||
silence_gen_set(&t->silence_gen, 0);
|
||||
t->tx_handler = (span_tx_handler_t *) &silence_gen;
|
||||
t->tx_user_data = &t->silence_gen;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
|
||||
}
|
||||
s->at_state.transmit = FALSE;
|
||||
break;
|
||||
case T31_CED_TONE:
|
||||
case FAX_MODEM_CED_TONE:
|
||||
if (s->t38_mode)
|
||||
{
|
||||
s->t38_fe.next_tx_samples = s->t38_fe.samples;
|
||||
|
@ -1584,13 +1568,12 @@ static int restart_modem(t31_state_t *s, int new_modem)
|
|||
else
|
||||
{
|
||||
modem_connect_tones_tx_init(&t->connect_tx, MODEM_CONNECT_TONES_FAX_CED);
|
||||
t->tx_handler = (span_tx_handler_t *) &modem_connect_tones_tx;
|
||||
t->tx_user_data = &t->connect_tx;
|
||||
s->audio.next_tx_handler = NULL;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &modem_connect_tones_tx, &t->connect_tx);
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
|
||||
}
|
||||
s->at_state.transmit = TRUE;
|
||||
break;
|
||||
case T31_V21_TX:
|
||||
case FAX_MODEM_V21_TX:
|
||||
if (s->t38_mode)
|
||||
{
|
||||
s->t38_fe.next_tx_indicator = T38_IND_V21_PREAMBLE;
|
||||
|
@ -1605,27 +1588,25 @@ static int restart_modem(t31_state_t *s, int new_modem)
|
|||
/* The spec says 1s +-15% of preamble. So, the minimum is 32 octets. */
|
||||
hdlc_tx_flags(&t->hdlc_tx, 32);
|
||||
fsk_tx_init(&t->v21_tx, &preset_fsk_specs[FSK_V21CH2], (get_bit_func_t) hdlc_tx_get_bit, &t->hdlc_tx);
|
||||
t->tx_handler = (span_tx_handler_t *) &fsk_tx;
|
||||
t->tx_user_data = &t->v21_tx;
|
||||
s->audio.next_tx_handler = NULL;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &fsk_tx, &t->v21_tx);
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
|
||||
}
|
||||
s->hdlc_tx.final = FALSE;
|
||||
s->hdlc_tx.len = 0;
|
||||
s->dled = FALSE;
|
||||
s->at_state.transmit = TRUE;
|
||||
break;
|
||||
case T31_V21_RX:
|
||||
case FAX_MODEM_V21_RX:
|
||||
if (s->t38_mode)
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
t->rx_handler = (span_rx_handler_t *) &fsk_rx;
|
||||
t->rx_user_data = &t->v21_rx;
|
||||
set_rx_handler(s, (span_rx_handler_t *) &fsk_rx, &t->v21_rx);
|
||||
t31_v21_rx(s);
|
||||
}
|
||||
break;
|
||||
case T31_V17_TX:
|
||||
case FAX_MODEM_V17_TX:
|
||||
if (s->t38_mode)
|
||||
{
|
||||
switch (s->bit_rate)
|
||||
|
@ -1653,26 +1634,24 @@ static int restart_modem(t31_state_t *s, int new_modem)
|
|||
else
|
||||
{
|
||||
v17_tx_restart(&t->v17_tx, s->bit_rate, FALSE, s->short_train);
|
||||
t->tx_handler = (span_tx_handler_t *) &v17_tx;
|
||||
t->tx_user_data = &t->v17_tx;
|
||||
s->audio.next_tx_handler = NULL;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &v17_tx, &t->v17_tx);
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
|
||||
}
|
||||
s->tx.out_bytes = 0;
|
||||
s->tx.data_started = FALSE;
|
||||
s->at_state.transmit = TRUE;
|
||||
break;
|
||||
case T31_V17_RX:
|
||||
case FAX_MODEM_V17_RX:
|
||||
if (!s->t38_mode)
|
||||
{
|
||||
t->rx_handler = (span_rx_handler_t *) &v17_v21_rx;
|
||||
t->rx_user_data = s;
|
||||
set_rx_handler(s, (span_rx_handler_t *) &v17_v21_rx, s);
|
||||
v17_rx_restart(&t->v17_rx, s->bit_rate, s->short_train);
|
||||
/* Allow for +FCERROR/+FRH:3 */
|
||||
t31_v21_rx(s);
|
||||
}
|
||||
s->at_state.transmit = FALSE;
|
||||
break;
|
||||
case T31_V27TER_TX:
|
||||
case FAX_MODEM_V27TER_TX:
|
||||
if (s->t38_mode)
|
||||
{
|
||||
switch (s->bit_rate)
|
||||
|
@ -1692,26 +1671,24 @@ static int restart_modem(t31_state_t *s, int new_modem)
|
|||
else
|
||||
{
|
||||
v27ter_tx_restart(&t->v27ter_tx, s->bit_rate, FALSE);
|
||||
t->tx_handler = (span_tx_handler_t *) &v27ter_tx;
|
||||
t->tx_user_data = &t->v27ter_tx;
|
||||
s->audio.next_tx_handler = NULL;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &v27ter_tx, &t->v27ter_tx);
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
|
||||
}
|
||||
s->tx.out_bytes = 0;
|
||||
s->tx.data_started = FALSE;
|
||||
s->at_state.transmit = TRUE;
|
||||
break;
|
||||
case T31_V27TER_RX:
|
||||
case FAX_MODEM_V27TER_RX:
|
||||
if (!s->t38_mode)
|
||||
{
|
||||
t->rx_handler = (span_rx_handler_t *) &v27ter_v21_rx;
|
||||
t->rx_user_data = s;
|
||||
set_rx_handler(s, (span_rx_handler_t *) &v27ter_v21_rx, s);
|
||||
v27ter_rx_restart(&t->v27ter_rx, s->bit_rate, FALSE);
|
||||
/* Allow for +FCERROR/+FRH:3 */
|
||||
t31_v21_rx(s);
|
||||
}
|
||||
s->at_state.transmit = FALSE;
|
||||
break;
|
||||
case T31_V29_TX:
|
||||
case FAX_MODEM_V29_TX:
|
||||
if (s->t38_mode)
|
||||
{
|
||||
switch (s->bit_rate)
|
||||
|
@ -1731,26 +1708,24 @@ static int restart_modem(t31_state_t *s, int new_modem)
|
|||
else
|
||||
{
|
||||
v29_tx_restart(&t->v29_tx, s->bit_rate, FALSE);
|
||||
t->tx_handler = (span_tx_handler_t *) &v29_tx;
|
||||
t->tx_user_data = &t->v29_tx;
|
||||
s->audio.next_tx_handler = NULL;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &v29_tx, &t->v29_tx);
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
|
||||
}
|
||||
s->tx.out_bytes = 0;
|
||||
s->tx.data_started = FALSE;
|
||||
s->at_state.transmit = TRUE;
|
||||
break;
|
||||
case T31_V29_RX:
|
||||
case FAX_MODEM_V29_RX:
|
||||
if (!s->t38_mode)
|
||||
{
|
||||
t->rx_handler = (span_rx_handler_t *) &v29_v21_rx;
|
||||
t->rx_user_data = s;
|
||||
set_rx_handler(s, (span_rx_handler_t *) &v29_v21_rx, s);
|
||||
v29_rx_restart(&t->v29_rx, s->bit_rate, FALSE);
|
||||
/* Allow for +FCERROR/+FRH:3 */
|
||||
t31_v21_rx(s);
|
||||
}
|
||||
s->at_state.transmit = FALSE;
|
||||
break;
|
||||
case T31_SILENCE_TX:
|
||||
case FAX_MODEM_SILENCE_TX:
|
||||
if (s->t38_mode)
|
||||
{
|
||||
t38_core_send_indicator(&s->t38_fe.t38, T38_IND_NO_SIGNAL, INDICATOR_TX_COUNT);
|
||||
|
@ -1761,26 +1736,22 @@ static int restart_modem(t31_state_t *s, int new_modem)
|
|||
else
|
||||
{
|
||||
silence_gen_set(&t->silence_gen, 0);
|
||||
t->tx_handler = (span_tx_handler_t *) &silence_gen;
|
||||
t->tx_user_data = &t->silence_gen;
|
||||
s->audio.next_tx_handler = NULL;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
|
||||
}
|
||||
s->at_state.transmit = FALSE;
|
||||
break;
|
||||
case T31_SILENCE_RX:
|
||||
case FAX_MODEM_SILENCE_RX:
|
||||
if (!s->t38_mode)
|
||||
{
|
||||
t->rx_handler = (span_rx_handler_t *) &silence_rx;
|
||||
t->rx_user_data = s;
|
||||
|
||||
set_rx_handler(s, (span_rx_handler_t *) &silence_rx, s);
|
||||
silence_gen_set(&t->silence_gen, 0);
|
||||
t->tx_handler = (span_tx_handler_t *) &silence_gen;
|
||||
t->tx_user_data = &t->silence_gen;
|
||||
s->audio.next_tx_handler = NULL;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
|
||||
}
|
||||
s->at_state.transmit = FALSE;
|
||||
break;
|
||||
case T31_FLUSH:
|
||||
case FAX_MODEM_FLUSH:
|
||||
/* Send 200ms of silence to "push" the last audio out */
|
||||
if (s->t38_mode)
|
||||
{
|
||||
|
@ -1788,11 +1759,10 @@ static int restart_modem(t31_state_t *s, int new_modem)
|
|||
}
|
||||
else
|
||||
{
|
||||
s->modem = T31_SILENCE_TX;
|
||||
s->modem = FAX_MODEM_SILENCE_TX;
|
||||
silence_gen_alter(&t->silence_gen, ms_to_samples(200));
|
||||
t->tx_handler = (span_tx_handler_t *) &silence_gen;
|
||||
t->tx_user_data = &t->silence_gen;
|
||||
s->audio.next_tx_handler = NULL;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
|
||||
s->at_state.transmit = TRUE;
|
||||
}
|
||||
break;
|
||||
|
@ -1910,7 +1880,7 @@ static int process_class1_cmd(at_state_t *t, void *user_data, int direction, int
|
|||
if (new_transmit)
|
||||
{
|
||||
/* Send a specified period of silence, to space transmissions. */
|
||||
restart_modem(s, T31_SILENCE_TX);
|
||||
restart_modem(s, FAX_MODEM_SILENCE_TX);
|
||||
if (s->t38_mode)
|
||||
s->t38_fe.next_tx_samples = s->t38_fe.samples + ms_to_samples(val*10);
|
||||
else
|
||||
|
@ -1930,7 +1900,7 @@ static int process_class1_cmd(at_state_t *t, void *user_data, int direction, int
|
|||
}
|
||||
else
|
||||
{
|
||||
restart_modem(s, T31_SILENCE_RX);
|
||||
restart_modem(s, FAX_MODEM_SILENCE_RX);
|
||||
}
|
||||
}
|
||||
immediate_response = FALSE;
|
||||
|
@ -1940,7 +1910,7 @@ static int process_class1_cmd(at_state_t *t, void *user_data, int direction, int
|
|||
switch (val)
|
||||
{
|
||||
case 3:
|
||||
new_modem = (new_transmit) ? T31_V21_TX : T31_V21_RX;
|
||||
new_modem = (new_transmit) ? FAX_MODEM_V21_TX : FAX_MODEM_V21_RX;
|
||||
s->short_train = FALSE;
|
||||
s->bit_rate = 300;
|
||||
break;
|
||||
|
@ -2003,84 +1973,84 @@ static int process_class1_cmd(at_state_t *t, void *user_data, int direction, int
|
|||
case 24:
|
||||
s->t38_fe.next_tx_indicator = T38_IND_V27TER_2400_TRAINING;
|
||||
s->t38_fe.current_tx_data_type = T38_DATA_V27TER_2400;
|
||||
new_modem = (new_transmit) ? T31_V27TER_TX : T31_V27TER_RX;
|
||||
new_modem = (new_transmit) ? FAX_MODEM_V27TER_TX : FAX_MODEM_V27TER_RX;
|
||||
s->short_train = FALSE;
|
||||
s->bit_rate = 2400;
|
||||
break;
|
||||
case 48:
|
||||
s->t38_fe.next_tx_indicator = T38_IND_V27TER_4800_TRAINING;
|
||||
s->t38_fe.current_tx_data_type = T38_DATA_V27TER_4800;
|
||||
new_modem = (new_transmit) ? T31_V27TER_TX : T31_V27TER_RX;
|
||||
new_modem = (new_transmit) ? FAX_MODEM_V27TER_TX : FAX_MODEM_V27TER_RX;
|
||||
s->short_train = FALSE;
|
||||
s->bit_rate = 4800;
|
||||
break;
|
||||
case 72:
|
||||
s->t38_fe.next_tx_indicator = T38_IND_V29_7200_TRAINING;
|
||||
s->t38_fe.current_tx_data_type = T38_DATA_V29_7200;
|
||||
new_modem = (new_transmit) ? T31_V29_TX : T31_V29_RX;
|
||||
new_modem = (new_transmit) ? FAX_MODEM_V29_TX : FAX_MODEM_V29_RX;
|
||||
s->short_train = FALSE;
|
||||
s->bit_rate = 7200;
|
||||
break;
|
||||
case 96:
|
||||
s->t38_fe.next_tx_indicator = T38_IND_V29_9600_TRAINING;
|
||||
s->t38_fe.current_tx_data_type = T38_DATA_V29_9600;
|
||||
new_modem = (new_transmit) ? T31_V29_TX : T31_V29_RX;
|
||||
new_modem = (new_transmit) ? FAX_MODEM_V29_TX : FAX_MODEM_V29_RX;
|
||||
s->short_train = FALSE;
|
||||
s->bit_rate = 9600;
|
||||
break;
|
||||
case 73:
|
||||
s->t38_fe.next_tx_indicator = T38_IND_V17_7200_LONG_TRAINING;
|
||||
s->t38_fe.current_tx_data_type = T38_DATA_V17_7200;
|
||||
new_modem = (new_transmit) ? T31_V17_TX : T31_V17_RX;
|
||||
new_modem = (new_transmit) ? FAX_MODEM_V17_TX : FAX_MODEM_V17_RX;
|
||||
s->short_train = FALSE;
|
||||
s->bit_rate = 7200;
|
||||
break;
|
||||
case 74:
|
||||
s->t38_fe.next_tx_indicator = T38_IND_V17_7200_SHORT_TRAINING;
|
||||
s->t38_fe.current_tx_data_type = T38_DATA_V17_7200;
|
||||
new_modem = (new_transmit) ? T31_V17_TX : T31_V17_RX;
|
||||
new_modem = (new_transmit) ? FAX_MODEM_V17_TX : FAX_MODEM_V17_RX;
|
||||
s->short_train = TRUE;
|
||||
s->bit_rate = 7200;
|
||||
break;
|
||||
case 97:
|
||||
s->t38_fe.next_tx_indicator = T38_IND_V17_9600_LONG_TRAINING;
|
||||
s->t38_fe.current_tx_data_type = T38_DATA_V17_9600;
|
||||
new_modem = (new_transmit) ? T31_V17_TX : T31_V17_RX;
|
||||
new_modem = (new_transmit) ? FAX_MODEM_V17_TX : FAX_MODEM_V17_RX;
|
||||
s->short_train = FALSE;
|
||||
s->bit_rate = 9600;
|
||||
break;
|
||||
case 98:
|
||||
s->t38_fe.next_tx_indicator = T38_IND_V17_9600_SHORT_TRAINING;
|
||||
s->t38_fe.current_tx_data_type = T38_DATA_V17_9600;
|
||||
new_modem = (new_transmit) ? T31_V17_TX : T31_V17_RX;
|
||||
new_modem = (new_transmit) ? FAX_MODEM_V17_TX : FAX_MODEM_V17_RX;
|
||||
s->short_train = TRUE;
|
||||
s->bit_rate = 9600;
|
||||
break;
|
||||
case 121:
|
||||
s->t38_fe.next_tx_indicator = T38_IND_V17_12000_LONG_TRAINING;
|
||||
s->t38_fe.current_tx_data_type = T38_DATA_V17_12000;
|
||||
new_modem = (new_transmit) ? T31_V17_TX : T31_V17_RX;
|
||||
new_modem = (new_transmit) ? FAX_MODEM_V17_TX : FAX_MODEM_V17_RX;
|
||||
s->short_train = FALSE;
|
||||
s->bit_rate = 12000;
|
||||
break;
|
||||
case 122:
|
||||
s->t38_fe.next_tx_indicator = T38_IND_V17_12000_SHORT_TRAINING;
|
||||
s->t38_fe.current_tx_data_type = T38_DATA_V17_12000;
|
||||
new_modem = (new_transmit) ? T31_V17_TX : T31_V17_RX;
|
||||
new_modem = (new_transmit) ? FAX_MODEM_V17_TX : FAX_MODEM_V17_RX;
|
||||
s->short_train = TRUE;
|
||||
s->bit_rate = 12000;
|
||||
break;
|
||||
case 145:
|
||||
s->t38_fe.next_tx_indicator = T38_IND_V17_14400_LONG_TRAINING;
|
||||
s->t38_fe.current_tx_data_type = T38_DATA_V17_14400;
|
||||
new_modem = (new_transmit) ? T31_V17_TX : T31_V17_RX;
|
||||
new_modem = (new_transmit) ? FAX_MODEM_V17_TX : FAX_MODEM_V17_RX;
|
||||
s->short_train = FALSE;
|
||||
s->bit_rate = 14400;
|
||||
break;
|
||||
case 146:
|
||||
s->t38_fe.next_tx_indicator = T38_IND_V17_14400_SHORT_TRAINING;
|
||||
s->t38_fe.current_tx_data_type = T38_DATA_V17_14400;
|
||||
new_modem = (new_transmit) ? T31_V17_TX : T31_V17_RX;
|
||||
new_modem = (new_transmit) ? FAX_MODEM_V17_TX : FAX_MODEM_V17_RX;
|
||||
s->short_train = TRUE;
|
||||
s->bit_rate = 14400;
|
||||
break;
|
||||
|
@ -2134,8 +2104,8 @@ SPAN_DECLARE(int) t31_at_rx(t31_state_t *s, const char *t, int len)
|
|||
}
|
||||
s->at_state.rx_data_bytes = 0;
|
||||
s->at_state.transmit = FALSE;
|
||||
s->modem = T31_SILENCE_TX;
|
||||
s->audio.modems.rx_handler = span_dummy_rx;
|
||||
s->modem = FAX_MODEM_SILENCE_TX;
|
||||
set_rx_handler(s, (span_rx_handler_t *) &span_dummy_rx, NULL);
|
||||
t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND);
|
||||
at_put_response_code(&s->at_state, AT_RESPONSE_CODE_OK);
|
||||
}
|
||||
|
@ -2158,6 +2128,27 @@ SPAN_DECLARE(int) t31_at_rx(t31_state_t *s, const char *t, int len)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void set_rx_handler(t31_state_t *s, span_rx_handler_t *handler, void *user_data)
|
||||
{
|
||||
s->audio.modems.rx_handler = handler;
|
||||
s->audio.modems.rx_user_data = user_data;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void set_tx_handler(t31_state_t *s, span_tx_handler_t *handler, void *user_data)
|
||||
{
|
||||
s->audio.modems.tx_handler = handler;
|
||||
s->audio.modems.tx_user_data = user_data;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void set_next_tx_handler(t31_state_t *s, span_tx_handler_t *handler, void *user_data)
|
||||
{
|
||||
s->audio.modems.next_tx_handler = handler;
|
||||
s->audio.modems.next_tx_user_data = user_data;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int silence_rx(void *user_data, const int16_t amp[], int len)
|
||||
{
|
||||
t31_state_t *s;
|
||||
|
@ -2184,7 +2175,7 @@ static int cng_rx(void *user_data, const int16_t amp[], int len)
|
|||
{
|
||||
/* After calling, S7 has elapsed... no carrier found. */
|
||||
at_put_response_code(&s->at_state, AT_RESPONSE_CODE_NO_CARRIER);
|
||||
restart_modem(s, T31_SILENCE_TX);
|
||||
restart_modem(s, FAX_MODEM_SILENCE_TX);
|
||||
at_modem_control(&s->at_state, AT_MODEM_CONTROL_HANGUP, NULL);
|
||||
t31_set_at_rx_mode(s, AT_MODE_ONHOOK_COMMAND);
|
||||
}
|
||||
|
@ -2209,8 +2200,7 @@ static int v17_v21_rx(void *user_data, const int16_t amp[], int len)
|
|||
/* The fast modem has trained, so we no longer need to run the slow
|
||||
one in parallel. */
|
||||
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->v17_rx));
|
||||
s->rx_handler = (span_rx_handler_t *) &v17_rx;
|
||||
s->rx_user_data = &s->v17_rx;
|
||||
set_rx_handler(t, (span_rx_handler_t *) &v17_rx, &s->v17_rx);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2220,8 +2210,7 @@ static int v17_v21_rx(void *user_data, const int16_t amp[], int len)
|
|||
/* We have received something, and the fast modem has not trained. We must
|
||||
be receiving valid V.21 */
|
||||
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
|
||||
s->rx_handler = (span_rx_handler_t *) &fsk_rx;
|
||||
s->rx_user_data = &s->v21_rx;
|
||||
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx);
|
||||
}
|
||||
}
|
||||
return len;
|
||||
|
@ -2241,8 +2230,7 @@ static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
|
|||
/* The fast modem has trained, so we no longer need to run the slow
|
||||
one in parallel. */
|
||||
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->v27ter_rx));
|
||||
s->rx_handler = (span_rx_handler_t *) &v27ter_rx;
|
||||
s->rx_user_data = &s->v27ter_rx;
|
||||
set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, &s->v27ter_rx);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2252,8 +2240,7 @@ static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
|
|||
/* We have received something, and the fast modem has not trained. We must
|
||||
be receiving valid V.21 */
|
||||
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
|
||||
s->rx_handler = (span_rx_handler_t *) &fsk_rx;
|
||||
s->rx_user_data = &s->v21_rx;
|
||||
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx);
|
||||
}
|
||||
}
|
||||
return len;
|
||||
|
@ -2273,8 +2260,7 @@ static int v29_v21_rx(void *user_data, const int16_t amp[], int len)
|
|||
/* The fast modem has trained, so we no longer need to run the slow
|
||||
one in parallel. */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->v29_rx));
|
||||
s->rx_handler = (span_rx_handler_t *) &v29_rx;
|
||||
s->rx_user_data = &s->v29_rx;
|
||||
set_rx_handler(t, (span_rx_handler_t *) &v29_rx, &s->v29_rx);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2284,8 +2270,7 @@ static int v29_v21_rx(void *user_data, const int16_t amp[], int len)
|
|||
/* We have received something, and the fast modem has not trained. We must
|
||||
be receiving valid V.21 */
|
||||
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
|
||||
s->rx_handler = (span_rx_handler_t *) &fsk_rx;
|
||||
s->rx_user_data = &s->v21_rx;
|
||||
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx);
|
||||
}
|
||||
}
|
||||
return len;
|
||||
|
@ -2298,7 +2283,7 @@ SPAN_DECLARE(int) t31_rx(t31_state_t *s, int16_t amp[], int len)
|
|||
int32_t power;
|
||||
|
||||
/* Monitor for received silence. Maximum needed detection is AT+FRS=255 (255*10ms). */
|
||||
/* We could probably only run this loop if (s->modem == T31_SILENCE_RX), however,
|
||||
/* We could probably only run this loop if (s->modem == FAX_MODEM_SILENCE_RX), however,
|
||||
the spec says "when silence has been present on the line for the amount of
|
||||
time specified". That means some of the silence may have occurred before
|
||||
the AT+FRS=n command. This condition, however, is not likely to ever be the
|
||||
|
@ -2329,12 +2314,54 @@ SPAN_DECLARE(int) t31_rx(t31_state_t *s, int16_t amp[], int len)
|
|||
{
|
||||
t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND);
|
||||
at_put_response_code(&s->at_state, AT_RESPONSE_CODE_ERROR);
|
||||
restart_modem(s, T31_SILENCE_TX);
|
||||
restart_modem(s, FAX_MODEM_SILENCE_TX);
|
||||
}
|
||||
|
||||
if (!s->at_state.transmit || s->modem == T31_CNG_TONE)
|
||||
if (!s->at_state.transmit || s->modem == FAX_MODEM_CNG_TONE)
|
||||
s->audio.modems.rx_handler(s->audio.modems.rx_user_data, amp, len);
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) t31_rx_fillin(t31_state_t *s, int len)
|
||||
{
|
||||
/* To mitigate the effect of lost packets on a packet network we should
|
||||
try to sustain the status quo. If there is no receive modem running, keep
|
||||
things that way. If there is a receive modem running, try to sustain its
|
||||
operation, without causing a phase hop, or letting its adaptive functions
|
||||
diverge. */
|
||||
/* Time is determined by counting the samples in audio packets coming in. */
|
||||
s->call_samples += len;
|
||||
|
||||
/* In HDLC transmit mode, if 5 seconds elapse without data from the DTE
|
||||
we must treat this as an error. We return the result ERROR, and change
|
||||
to command-mode. */
|
||||
if (s->dte_data_timeout && s->call_samples > s->dte_data_timeout)
|
||||
{
|
||||
t31_set_at_rx_mode(s, AT_MODE_OFFHOOK_COMMAND);
|
||||
at_put_response_code(&s->at_state, AT_RESPONSE_CODE_ERROR);
|
||||
restart_modem(s, FAX_MODEM_SILENCE_TX);
|
||||
}
|
||||
/* Call the fillin function of the current modem (if there is one). */
|
||||
switch (s->modem)
|
||||
{
|
||||
case FAX_MODEM_V21_RX:
|
||||
len = fsk_rx_fillin(&s->audio.modems.v21_rx, len);
|
||||
break;
|
||||
case FAX_MODEM_V27TER_RX:
|
||||
/* TODO: what about FSK in the early stages */
|
||||
len = v27ter_rx_fillin(&s->audio.modems.v27ter_rx, len);
|
||||
break;
|
||||
case FAX_MODEM_V29_RX:
|
||||
/* TODO: what about FSK in the early stages */
|
||||
len = v29_rx_fillin(&s->audio.modems.v29_rx, len);
|
||||
break;
|
||||
case FAX_MODEM_V17_RX:
|
||||
/* TODO: what about FSK in the early stages */
|
||||
len = v17_rx_fillin(&s->audio.modems.v17_rx, len);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -2342,16 +2369,14 @@ static int set_next_tx_type(t31_state_t *s)
|
|||
{
|
||||
if (s->audio.next_tx_handler)
|
||||
{
|
||||
s->audio.modems.tx_handler = s->audio.next_tx_handler;
|
||||
s->audio.modems.tx_user_data = s->audio.next_tx_user_data;
|
||||
s->audio.next_tx_handler = NULL;
|
||||
set_tx_handler(s, s->audio.next_tx_handler, s->audio.next_tx_user_data);
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
|
||||
return 0;
|
||||
}
|
||||
/* There is nothing else to change to, so use zero length silence */
|
||||
silence_gen_alter(&(s->audio.modems.silence_gen), 0);
|
||||
s->audio.modems.tx_handler = (span_tx_handler_t *) &silence_gen;
|
||||
s->audio.modems.tx_user_data = &(s->audio.modems.silence_gen);
|
||||
s->audio.next_tx_handler = NULL;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &s->audio.modems.silence_gen);
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
|
||||
return -1;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -2523,7 +2548,7 @@ SPAN_DECLARE(t31_state_t *) t31_init(t31_state_t *s,
|
|||
s->audio.silence_heard = 0;
|
||||
s->silence_awaited = 0;
|
||||
s->call_samples = 0;
|
||||
s->modem = T31_NONE;
|
||||
s->modem = FAX_MODEM_NONE;
|
||||
s->at_state.transmit = TRUE;
|
||||
|
||||
if ((s->rx_queue = queue_init(NULL, 4096, QUEUE_WRITE_ATOMIC | QUEUE_READ_ATOMIC)) == NULL)
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: t35.c,v 1.29 2009/02/03 16:28:40 steveu Exp $
|
||||
* $Id: t35.c,v 1.30 2009/04/12 09:12:10 steveu Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -68,19 +68,29 @@
|
|||
#include "spandsp/bit_operations.h"
|
||||
#include "spandsp/t35.h"
|
||||
|
||||
/*! NSF pattern for FAX machine identification */
|
||||
typedef struct
|
||||
{
|
||||
/*! The number of bytes of the NSF byte string to match */
|
||||
int model_id_size;
|
||||
/*! The NSF byte string to expect */
|
||||
const char *model_id;
|
||||
/*! The model name of the FAX terminal */
|
||||
const char *model_name;
|
||||
} model_data_t;
|
||||
|
||||
/*! NSF pattern for identifying the manufacturer of a FAX machine */
|
||||
typedef struct
|
||||
{
|
||||
/*! The vendor ID byte string */
|
||||
const char *vendor_id;
|
||||
/*! The length of the vendor ID byte string */
|
||||
int vendor_id_len;
|
||||
/*! The vendor's name */
|
||||
const char *vendor_name;
|
||||
/*! TRUE if the station ID for this vendor is reversed */
|
||||
int inverse_station_id_order;
|
||||
/*! A pointer to a list of known models from this vendor */
|
||||
const model_data_t *known_models;
|
||||
} nsf_data_t;
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: t38_gateway.c,v 1.157 2009/02/16 09:57:22 steveu Exp $
|
||||
* $Id: t38_gateway.c,v 1.162 2009/04/12 14:18:02 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -84,6 +84,7 @@
|
|||
#include "spandsp/t38_gateway.h"
|
||||
|
||||
#include "spandsp/private/logging.h"
|
||||
#include "spandsp/private/silence_gen.h"
|
||||
#include "spandsp/private/fsk.h"
|
||||
#include "spandsp/private/v17tx.h"
|
||||
#include "spandsp/private/v17rx.h"
|
||||
|
@ -102,12 +103,18 @@
|
|||
|
||||
/* This is the target time per transmission chunk. The actual
|
||||
packet timing will sync to the data octets. */
|
||||
#define MS_PER_TX_CHUNK 30
|
||||
#define HDLC_START_BUFFER_LEVEL 8
|
||||
/*! The default number of milliseconds per transmitted IFP when sending bulk T.38 data */
|
||||
#define MS_PER_TX_CHUNK 30
|
||||
/*! The number of bytes which must be in the audio to T.38 HDLC buffer before we start
|
||||
outputting them as IFP messages. */
|
||||
#define HDLC_START_BUFFER_LEVEL 8
|
||||
|
||||
#define INDICATOR_TX_COUNT 3
|
||||
#define DATA_TX_COUNT 1
|
||||
#define DATA_END_TX_COUNT 3
|
||||
/*! The number of transmissions of indicator IFP packets */
|
||||
#define INDICATOR_TX_COUNT 3
|
||||
/*! The number of transmissions of data IFP packets */
|
||||
#define DATA_TX_COUNT 1
|
||||
/*! The number of transmissions of terminating data IFP packets */
|
||||
#define DATA_END_TX_COUNT 3
|
||||
|
||||
enum
|
||||
{
|
||||
|
@ -152,8 +159,11 @@ enum
|
|||
TCF_MODE_PREDICTABLE_MODEM_START_BEGIN
|
||||
};
|
||||
|
||||
/*! The maximum number of bytes to be zapped, in order to corrupt NSF,
|
||||
NSS and NSC messages, so the receiver does not recognise them. */
|
||||
#define MAX_NSX_SUPPRESSION 10
|
||||
|
||||
/*! The number of consecutive flags to declare HDLC framing is OK. */
|
||||
#define HDLC_FRAMING_OK_THRESHOLD 5
|
||||
|
||||
static uint8_t nsx_overwrite[2][MAX_NSX_SUPPRESSION] =
|
||||
|
@ -181,6 +191,20 @@ static void set_rx_handler(t38_gateway_state_t *s, span_rx_handler_t *handler, v
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void set_tx_handler(t38_gateway_state_t *s, span_tx_handler_t *handler, void *user_data)
|
||||
{
|
||||
s->audio.modems.tx_handler = handler;
|
||||
s->audio.modems.tx_user_data = user_data;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void set_next_tx_handler(t38_gateway_state_t *s, span_tx_handler_t *handler, void *user_data)
|
||||
{
|
||||
s->audio.modems.next_tx_handler = handler;
|
||||
s->audio.modems.next_tx_user_data = user_data;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void set_rx_active(t38_gateway_state_t *s, int active)
|
||||
{
|
||||
s->audio.modems.rx_handler = (active) ? s->audio.base_rx_handler : span_dummy_rx;
|
||||
|
@ -195,17 +219,17 @@ static int v17_v21_rx(void *user_data, const int16_t amp[], int len)
|
|||
t = (t38_gateway_state_t *) user_data;
|
||||
s = &t->audio.modems;
|
||||
v17_rx(&s->v17_rx, amp, len);
|
||||
fsk_rx(&s->v21_rx, amp, len);
|
||||
if (s->rx_signal_present)
|
||||
if (s->rx_trained)
|
||||
{
|
||||
if (s->rx_trained)
|
||||
{
|
||||
/* The fast modem has trained, so we no longer need to run the slow
|
||||
one in parallel. */
|
||||
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->v17_rx));
|
||||
set_rx_handler(t, (span_rx_handler_t *) &v17_rx, &s->v17_rx);
|
||||
}
|
||||
else
|
||||
/* The fast modem has trained, so we no longer need to run the slow
|
||||
one in parallel. */
|
||||
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.17 (%.2fdBm0)\n", v17_rx_signal_power(&s->v17_rx));
|
||||
set_rx_handler(t, (span_rx_handler_t *) &v17_rx, &s->v17_rx);
|
||||
}
|
||||
else
|
||||
{
|
||||
fsk_rx(&s->v21_rx, amp, len);
|
||||
if (s->rx_signal_present)
|
||||
{
|
||||
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.17 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
|
||||
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx);
|
||||
|
@ -225,17 +249,17 @@ static int v27ter_v21_rx(void *user_data, const int16_t amp[], int len)
|
|||
t = (t38_gateway_state_t *) user_data;
|
||||
s = &t->audio.modems;
|
||||
v27ter_rx(&s->v27ter_rx, amp, len);
|
||||
fsk_rx(&s->v21_rx, amp, len);
|
||||
if (s->rx_signal_present)
|
||||
if (s->rx_trained)
|
||||
{
|
||||
if (s->rx_trained)
|
||||
{
|
||||
/* The fast modem has trained, so we no longer need to run the slow
|
||||
one in parallel. */
|
||||
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->v27ter_rx));
|
||||
set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, &s->v27ter_rx);
|
||||
}
|
||||
else
|
||||
/* The fast modem has trained, so we no longer need to run the slow
|
||||
one in parallel. */
|
||||
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.27ter (%.2fdBm0)\n", v27ter_rx_signal_power(&s->v27ter_rx));
|
||||
set_rx_handler(t, (span_rx_handler_t *) &v27ter_rx, &s->v27ter_rx);
|
||||
}
|
||||
else
|
||||
{
|
||||
fsk_rx(&s->v21_rx, amp, len);
|
||||
if (s->rx_signal_present)
|
||||
{
|
||||
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.27ter + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
|
||||
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx);
|
||||
|
@ -255,17 +279,17 @@ static int v29_v21_rx(void *user_data, const int16_t amp[], int len)
|
|||
t = (t38_gateway_state_t *) user_data;
|
||||
s = &t->audio.modems;
|
||||
v29_rx(&s->v29_rx, amp, len);
|
||||
fsk_rx(&s->v21_rx, amp, len);
|
||||
if (s->rx_signal_present)
|
||||
if (s->rx_trained)
|
||||
{
|
||||
if (s->rx_trained)
|
||||
{
|
||||
/* The fast modem has trained, so we no longer need to run the slow
|
||||
one in parallel. */
|
||||
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->v29_rx));
|
||||
set_rx_handler(t, (span_rx_handler_t *) &v29_rx, &s->v29_rx);
|
||||
}
|
||||
else
|
||||
/* The fast modem has trained, so we no longer need to run the slow
|
||||
one in parallel. */
|
||||
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.29 (%.2fdBm0)\n", v29_rx_signal_power(&s->v29_rx));
|
||||
set_rx_handler(t, (span_rx_handler_t *) &v29_rx, &s->v29_rx);
|
||||
}
|
||||
else
|
||||
{
|
||||
fsk_rx(&s->v21_rx, amp, len);
|
||||
if (s->rx_signal_present)
|
||||
{
|
||||
span_log(&t->logging, SPAN_LOG_FLOW, "Switching from V.29 + V.21 to V.21 (%.2fdBm0)\n", fsk_rx_signal_power(&s->v21_rx));
|
||||
set_rx_handler(t, (span_rx_handler_t *) &fsk_rx, &s->v21_rx);
|
||||
|
@ -348,9 +372,8 @@ static int set_next_tx_type(t38_gateway_state_t *s)
|
|||
if (t->next_tx_handler)
|
||||
{
|
||||
/* There is a handler queued, so that is the next one. */
|
||||
t->tx_handler = t->next_tx_handler;
|
||||
t->tx_user_data = t->next_tx_user_data;
|
||||
t->next_tx_handler = NULL;
|
||||
set_tx_handler(s, t->next_tx_handler, t->next_tx_user_data);
|
||||
set_next_tx_handler(s, NULL, NULL);
|
||||
if (t->tx_handler == (span_tx_handler_t *) &(silence_gen)
|
||||
||
|
||||
t->tx_handler == (span_tx_handler_t *) &(tone_gen))
|
||||
|
@ -399,27 +422,23 @@ static int set_next_tx_type(t38_gateway_state_t *s)
|
|||
t->tx_bit_rate = 0;
|
||||
/* Impose 75ms minimum on transmitted silence */
|
||||
//silence_gen_set(&t->silence_gen, ms_to_samples(75));
|
||||
t->tx_handler = (span_tx_handler_t *) &(silence_gen);
|
||||
t->tx_user_data = &t->silence_gen;
|
||||
t->next_tx_handler = NULL;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
|
||||
set_rx_active(s, TRUE);
|
||||
break;
|
||||
case T38_IND_CNG:
|
||||
t->tx_bit_rate = 0;
|
||||
modem_connect_tones_tx_init(&t->connect_tx, MODEM_CONNECT_TONES_FAX_CNG);
|
||||
t->tx_handler = (span_tx_handler_t *) &modem_connect_tones_tx;
|
||||
t->tx_user_data = &t->connect_tx;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &modem_connect_tones_tx, &t->connect_tx);
|
||||
silence_gen_set(&t->silence_gen, 0);
|
||||
t->next_tx_handler = (span_tx_handler_t *) &(silence_gen);
|
||||
t->next_tx_user_data = &t->silence_gen;
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
|
||||
set_rx_active(s, TRUE);
|
||||
break;
|
||||
case T38_IND_CED:
|
||||
t->tx_bit_rate = 0;
|
||||
modem_connect_tones_tx_init(&t->connect_tx, MODEM_CONNECT_TONES_FAX_CED);
|
||||
t->tx_handler = (span_tx_handler_t *) &modem_connect_tones_tx;
|
||||
t->tx_user_data = &t->connect_tx;
|
||||
t->next_tx_handler = NULL;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &modem_connect_tones_tx, &t->connect_tx);
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) NULL, NULL);
|
||||
set_rx_active(s, TRUE);
|
||||
break;
|
||||
case T38_IND_V21_PREAMBLE:
|
||||
|
@ -429,10 +448,8 @@ static int set_next_tx_type(t38_gateway_state_t *s)
|
|||
silence_gen_alter(&t->silence_gen, ms_to_samples(75));
|
||||
u->buf[u->in].len = 0;
|
||||
fsk_tx_init(&t->v21_tx, &preset_fsk_specs[FSK_V21CH2], (get_bit_func_t) hdlc_tx_get_bit, &t->hdlc_tx);
|
||||
t->tx_handler = (span_tx_handler_t *) &(silence_gen);
|
||||
t->tx_user_data = &t->silence_gen;
|
||||
t->next_tx_handler = (span_tx_handler_t *) &(fsk_tx);
|
||||
t->next_tx_user_data = &t->v21_tx;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) &fsk_tx, &t->v21_tx);
|
||||
set_rx_active(s, TRUE);
|
||||
break;
|
||||
case T38_IND_V27TER_2400_TRAINING:
|
||||
|
@ -450,10 +467,8 @@ static int set_next_tx_type(t38_gateway_state_t *s)
|
|||
silence_gen_alter(&t->silence_gen, ms_to_samples(75));
|
||||
v27ter_tx_restart(&t->v27ter_tx, t->tx_bit_rate, t->use_tep);
|
||||
v27ter_tx_set_get_bit(&t->v27ter_tx, get_bit_func, get_bit_user_data);
|
||||
t->tx_handler = (span_tx_handler_t *) &(silence_gen);
|
||||
t->tx_user_data = &t->silence_gen;
|
||||
t->next_tx_handler = (span_tx_handler_t *) &(v27ter_tx);
|
||||
t->next_tx_user_data = &t->v27ter_tx;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) &v27ter_tx, &t->v27ter_tx);
|
||||
set_rx_active(s, TRUE);
|
||||
break;
|
||||
case T38_IND_V29_7200_TRAINING:
|
||||
|
@ -471,10 +486,8 @@ static int set_next_tx_type(t38_gateway_state_t *s)
|
|||
silence_gen_alter(&t->silence_gen, ms_to_samples(75));
|
||||
v29_tx_restart(&t->v29_tx, t->tx_bit_rate, t->use_tep);
|
||||
v29_tx_set_get_bit(&t->v29_tx, get_bit_func, get_bit_user_data);
|
||||
t->tx_handler = (span_tx_handler_t *) &(silence_gen);
|
||||
t->tx_user_data = &t->silence_gen;
|
||||
t->next_tx_handler = (span_tx_handler_t *) &(v29_tx);
|
||||
t->next_tx_user_data = &t->v29_tx;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) &v29_tx, &t->v29_tx);
|
||||
set_rx_active(s, TRUE);
|
||||
break;
|
||||
case T38_IND_V17_7200_SHORT_TRAINING:
|
||||
|
@ -521,10 +534,8 @@ static int set_next_tx_type(t38_gateway_state_t *s)
|
|||
silence_gen_alter(&t->silence_gen, ms_to_samples(75));
|
||||
v17_tx_restart(&t->v17_tx, t->tx_bit_rate, t->use_tep, short_train);
|
||||
v17_tx_set_get_bit(&t->v17_tx, get_bit_func, get_bit_user_data);
|
||||
t->tx_handler = (span_tx_handler_t *) &(silence_gen);
|
||||
t->tx_user_data = &t->silence_gen;
|
||||
t->next_tx_handler = (span_tx_handler_t *) &(v17_tx);
|
||||
t->next_tx_user_data = &t->v17_tx;
|
||||
set_tx_handler(s, (span_tx_handler_t *) &silence_gen, &t->silence_gen);
|
||||
set_next_tx_handler(s, (span_tx_handler_t *) &v17_tx, &t->v17_tx);
|
||||
set_rx_active(s, TRUE);
|
||||
break;
|
||||
case T38_IND_V8_ANSAM:
|
||||
|
@ -1575,8 +1586,8 @@ static void non_ecm_push_residue(t38_gateway_state_t *t)
|
|||
s->data[s->data_ptr++] = (uint8_t) (s->bit_stream << (8 - s->bit_no));
|
||||
}
|
||||
t38_core_send_data(&t->t38x.t38, t->t38x.current_tx_data_type, T38_FIELD_T4_NON_ECM_SIG_END, s->data, s->data_ptr, t->t38x.t38.data_end_tx_count);
|
||||
s->out_octets += s->data_ptr;
|
||||
s->in_bits += s->bits_absorbed;
|
||||
s->out_octets += s->data_ptr;
|
||||
s->data_ptr = 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -1589,8 +1600,8 @@ static void non_ecm_push(t38_gateway_state_t *t)
|
|||
if (s->data_ptr)
|
||||
{
|
||||
t38_core_send_data(&t->t38x.t38, t->t38x.current_tx_data_type, T38_FIELD_T4_NON_ECM_DATA, s->data, s->data_ptr, t->t38x.t38.data_tx_count);
|
||||
s->out_octets += s->data_ptr;
|
||||
s->in_bits += s->bits_absorbed;
|
||||
s->out_octets += s->data_ptr;
|
||||
s->bits_absorbed = 0;
|
||||
s->data_ptr = 0;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: t38_terminal.c,v 1.123 2009/02/10 13:06:46 steveu Exp $
|
||||
* $Id: t38_terminal.c,v 1.124 2009/03/13 14:49:56 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -527,7 +527,7 @@ static void send_hdlc(void *user_data, const uint8_t *msg, int len)
|
|||
|
||||
static __inline__ int bits_to_us(t38_terminal_state_t *s, int bits)
|
||||
{
|
||||
if (s->t38_fe.ms_per_tx_chunk == 0)
|
||||
if (s->t38_fe.ms_per_tx_chunk == 0 || s->t38_fe.tx_bit_rate == 0)
|
||||
return 0;
|
||||
return bits*1000000/s->t38_fe.tx_bit_rate;
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: t4.c,v 1.128 2009/03/01 11:47:03 steveu Exp $
|
||||
* $Id: t4.c,v 1.130 2009/04/12 09:12:10 steveu Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -91,13 +91,19 @@
|
|||
#include "spandsp/private/logging.h"
|
||||
#include "spandsp/private/t4.h"
|
||||
|
||||
/*! The number of centimetres in one inch */
|
||||
#define CM_PER_INCH 2.54f
|
||||
|
||||
/*! The number of EOLs to be sent at the end of a T.4 page */
|
||||
#define EOLS_TO_END_T4_TX_PAGE 6
|
||||
/*! The number of EOLs to be sent at the end of a T.6 page */
|
||||
#define EOLS_TO_END_T6_TX_PAGE 2
|
||||
|
||||
/*! The number of EOLs to expect at the end of a T.4 page */
|
||||
#define EOLS_TO_END_ANY_RX_PAGE 6
|
||||
/*! The number of EOLs to check at the end of a T.4 page */
|
||||
#define EOLS_TO_END_T4_RX_PAGE 5
|
||||
/*! The number of EOLs to check at the end of a T.6 page */
|
||||
#define EOLS_TO_END_T6_RX_PAGE 2
|
||||
|
||||
/* Finite state machine state codes */
|
||||
|
@ -134,19 +140,26 @@ static void STATE_TRACE(const char *format, ...)
|
|||
#define STATE_TRACE(...) /**/
|
||||
#endif
|
||||
|
||||
/* Finite state machine state table entry */
|
||||
/*! T.4 finite state machine state table entry */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t state; /* See above */
|
||||
uint8_t width; /* Width of code in bits */
|
||||
int16_t param; /* Run length in bits */
|
||||
/*! State */
|
||||
uint8_t state;
|
||||
/*! Width of code in bits */
|
||||
uint8_t width;
|
||||
/*! Run length in bits */
|
||||
int16_t param;
|
||||
} t4_table_entry_t;
|
||||
|
||||
/*! T.4 run length table entry */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t length; /* Length of T.4 code, in bits */
|
||||
uint16_t code; /* T.4 code */
|
||||
int16_t run_length; /* Run length, in bits */
|
||||
/*! Length of T.4 code, in bits */
|
||||
uint16_t length;
|
||||
/*! T.4 code */
|
||||
uint16_t code;
|
||||
/*! Run length, in bits */
|
||||
int16_t run_length;
|
||||
} t4_run_table_entry_t;
|
||||
|
||||
#include "t4_states.h"
|
||||
|
@ -302,24 +315,25 @@ static int get_tiff_directory_info(t4_state_t *s)
|
|||
{ -1.00f, -1, -1}
|
||||
};
|
||||
uint16_t res_unit;
|
||||
uint32_t parm;
|
||||
uint16_t parm16;
|
||||
uint32_t parm32;
|
||||
float x_resolution;
|
||||
float y_resolution;
|
||||
int i;
|
||||
t4_tiff_state_t *t;
|
||||
|
||||
t = &s->tiff;
|
||||
parm = 0;
|
||||
TIFFGetField(t->tiff_file, TIFFTAG_BITSPERSAMPLE, &parm);
|
||||
if (parm != 1)
|
||||
parm16 = 0;
|
||||
TIFFGetField(t->tiff_file, TIFFTAG_BITSPERSAMPLE, &parm16);
|
||||
if (parm16 != 1)
|
||||
return -1;
|
||||
parm = 0;
|
||||
TIFFGetField(t->tiff_file, TIFFTAG_IMAGEWIDTH, &parm);
|
||||
s->image_width = parm;
|
||||
parm32 = 0;
|
||||
TIFFGetField(t->tiff_file, TIFFTAG_IMAGEWIDTH, &parm32);
|
||||
s->image_width = parm32;
|
||||
s->bytes_per_row = (s->image_width + 7)/8;
|
||||
parm = 0;
|
||||
TIFFGetField(t->tiff_file, TIFFTAG_IMAGELENGTH, &parm);
|
||||
s->image_length = parm;
|
||||
parm32 = 0;
|
||||
TIFFGetField(t->tiff_file, TIFFTAG_IMAGELENGTH, &parm32);
|
||||
s->image_length = parm32;
|
||||
x_resolution = 0.0f;
|
||||
TIFFGetField(t->tiff_file, TIFFTAG_XRESOLUTION, &x_resolution);
|
||||
y_resolution = 0.0f;
|
||||
|
@ -400,20 +414,21 @@ static int test_tiff_directory_info(t4_state_t *s)
|
|||
{ -1.00f, -1, -1}
|
||||
};
|
||||
uint16_t res_unit;
|
||||
uint32_t parm;
|
||||
uint16_t parm16;
|
||||
uint32_t parm32;
|
||||
float x_resolution;
|
||||
float y_resolution;
|
||||
int i;
|
||||
t4_tiff_state_t *t;
|
||||
|
||||
t = &s->tiff;
|
||||
parm = 0;
|
||||
TIFFGetField(t->tiff_file, TIFFTAG_BITSPERSAMPLE, &parm);
|
||||
if (parm != 1)
|
||||
parm16 = 0;
|
||||
TIFFGetField(t->tiff_file, TIFFTAG_BITSPERSAMPLE, &parm16);
|
||||
if (parm16 != 1)
|
||||
return -1;
|
||||
parm = 0;
|
||||
TIFFGetField(t->tiff_file, TIFFTAG_IMAGEWIDTH, &parm);
|
||||
if (s->image_width != (int) parm)
|
||||
parm32 = 0;
|
||||
TIFFGetField(t->tiff_file, TIFFTAG_IMAGEWIDTH, &parm32);
|
||||
if (s->image_width != (int) parm32)
|
||||
return 1;
|
||||
x_resolution = 0.0f;
|
||||
TIFFGetField(t->tiff_file, TIFFTAG_XRESOLUTION, &x_resolution);
|
||||
|
|
|
@ -22,10 +22,10 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: tone_detect.c,v 1.51 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: tone_detect.c,v 1.53 2009/04/12 09:12:10 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file tone_detect.h */
|
||||
/*! \file */
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "config.h"
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: tone_generate.c,v 1.50 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: tone_generate.c,v 1.52 2009/04/12 09:12:10 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#define IAXMODEM_STUFF
|
||||
/*
|
||||
* SpanDSP - a series of DSP components for telephony
|
||||
*
|
||||
|
@ -22,7 +23,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: v17rx.c,v 1.133 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: v17rx.c,v 1.145 2009/04/20 16:36:36 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -71,21 +72,33 @@
|
|||
#include "v17rx_floating_rrc.h"
|
||||
#endif
|
||||
|
||||
/*! The nominal frequency of the carrier, in Hertz */
|
||||
#define CARRIER_NOMINAL_FREQ 1800.0f
|
||||
/*! The nominal baud or symbol rate */
|
||||
#define BAUD_RATE 2400
|
||||
/*! The adaption rate coefficient for the equalizer during initial training */
|
||||
#define EQUALIZER_DELTA 0.21f
|
||||
/*! The adaption rate coefficient for the equalizer during continuous fine tuning */
|
||||
#define EQUALIZER_SLOW_ADAPT_RATIO 0.1f
|
||||
|
||||
/* Segments of the training sequence */
|
||||
/*! The length of training segment 1, in symbols */
|
||||
#define V17_TRAINING_SEG_1_LEN 256
|
||||
/*! The length of training segment 2 in long training mode, in symbols */
|
||||
#define V17_TRAINING_SEG_2_LEN 2976
|
||||
/*! The length of training segment 2 in short training mode, in symbols */
|
||||
#define V17_TRAINING_SHORT_SEG_2_LEN 38
|
||||
/*! The length of training segment 3, in symbols */
|
||||
#define V17_TRAINING_SEG_3_LEN 64
|
||||
/*! The length of training segment 4A, in symbols */
|
||||
#define V17_TRAINING_SEG_4A_LEN 15
|
||||
/*! The length of training segment 4, in symbols */
|
||||
#define V17_TRAINING_SEG_4_LEN 48
|
||||
|
||||
/*! The 16 bit pattern used in the bridge section of the training sequence */
|
||||
#define V17_BRIDGE_WORD 0x8880
|
||||
|
||||
/*! The length of the equalizer buffer */
|
||||
#define V17_EQUALIZER_LEN (V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN)
|
||||
|
||||
enum
|
||||
|
@ -106,13 +119,25 @@ enum
|
|||
};
|
||||
|
||||
/* Coefficients for the band edge symbol timing synchroniser (alpha = 0.99) */
|
||||
#define SYNC_LOW_BAND_EDGE_COEFF_0 1.764193f /* 2*alpha*cos(low_edge) */
|
||||
#define SYNC_LOW_BAND_EDGE_COEFF_1 -0.980100f /* -alpha^2 */
|
||||
#define SYNC_HIGH_BAND_EDGE_COEFF_0 -1.400072f /* 2*alpha*cos(high_edge) */
|
||||
#define SYNC_HIGH_BAND_EDGE_COEFF_1 -0.980100f /* -alpha^2 */
|
||||
#define SYNC_CROSS_CORR_COEFF_A -0.932131f /* -alpha^2*sin(freq_diff) */
|
||||
#define SYNC_CROSS_CORR_COEFF_B 0.700036f /* alpha*sin(high_edge) */
|
||||
#define SYNC_CROSS_CORR_COEFF_C -0.449451f /* -alpha*sin(low_edge) */
|
||||
/* low_edge = 2.0f*M_PI*(CARRIER_NOMINAL_FREQ - BAUD_RATE/2.0f)/SAMPLE_RATE; */
|
||||
/* high_edge = 2.0f*M_PI*(CARRIER_NOMINAL_FREQ + BAUD_RATE/2.0f)/SAMPLE_RATE; */
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
#define SYNC_LOW_BAND_EDGE_COEFF_0 ((int)(FP_FACTOR* 1.764193f)) /* 2*alpha*cos(low_edge) */
|
||||
#define SYNC_LOW_BAND_EDGE_COEFF_1 ((int)(FP_FACTOR*-0.980100f)) /* -alpha^2 */
|
||||
#define SYNC_HIGH_BAND_EDGE_COEFF_0 ((int)(FP_FACTOR*-1.400072f)) /* 2*alpha*cos(high_edge) */
|
||||
#define SYNC_HIGH_BAND_EDGE_COEFF_1 ((int)(FP_FACTOR*-0.980100f)) /* -alpha^2 */
|
||||
#define SYNC_CROSS_CORR_COEFF_A ((int)(FP_FACTOR*-0.932131f)) /* -alpha^2*sin(freq_diff) */
|
||||
#define SYNC_CROSS_CORR_COEFF_B ((int)(FP_FACTOR* 0.700036f)) /* alpha*sin(high_edge) */
|
||||
#define SYNC_CROSS_CORR_COEFF_C ((int)(FP_FACTOR*-0.449451f)) /* -alpha*sin(low_edge) */
|
||||
#else
|
||||
#define SYNC_LOW_BAND_EDGE_COEFF_0 1.764193f /* 2*alpha*cos(low_edge) */
|
||||
#define SYNC_LOW_BAND_EDGE_COEFF_1 -0.980100f /* -alpha^2 */
|
||||
#define SYNC_HIGH_BAND_EDGE_COEFF_0 -1.400072f /* 2*alpha*cos(high_edge) */
|
||||
#define SYNC_HIGH_BAND_EDGE_COEFF_1 -0.980100f /* -alpha^2 */
|
||||
#define SYNC_CROSS_CORR_COEFF_A -0.932131f /* -alpha^2*sin(freq_diff) */
|
||||
#define SYNC_CROSS_CORR_COEFF_B 0.700036f /* alpha*sin(high_edge) */
|
||||
#define SYNC_CROSS_CORR_COEFF_C -0.449451f /* -alpha*sin(low_edge) */
|
||||
#endif
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
static const int constellation_spacing[4] =
|
||||
|
@ -146,7 +171,7 @@ SPAN_DECLARE(float) v17_rx_symbol_timing_correction(v17_rx_state_t *s)
|
|||
|
||||
SPAN_DECLARE(float) v17_rx_signal_power(v17_rx_state_t *s)
|
||||
{
|
||||
return power_meter_current_dbm0(&s->power);
|
||||
return power_meter_current_dbm0(&s->power) + 3.98f;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -504,11 +529,40 @@ static int decode_baud(v17_rx_state_t *s, complexf_t *z)
|
|||
static __inline__ void symbol_sync(v17_rx_state_t *s)
|
||||
{
|
||||
int i;
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
int32_t v;
|
||||
int32_t p;
|
||||
#else
|
||||
float v;
|
||||
float p;
|
||||
#endif
|
||||
|
||||
/* This routine adapts the position of the half baud samples entering the equalizer. */
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
/* TODO: The scalings used here need more thorough evaluation, to see if overflows are possible. */
|
||||
/* Cross correlate */
|
||||
v = (((s->symbol_sync_low[1] >> 5)*(s->symbol_sync_high[1] >> 4)) >> 15)*SYNC_CROSS_CORR_COEFF_A
|
||||
+ (((s->symbol_sync_low[0] >> 5)*(s->symbol_sync_high[1] >> 4)) >> 15)*SYNC_CROSS_CORR_COEFF_B
|
||||
+ (((s->symbol_sync_low[1] >> 5)*(s->symbol_sync_high[0] >> 4)) >> 15)*SYNC_CROSS_CORR_COEFF_C;
|
||||
/* Filter away any DC component */
|
||||
p = v - s->symbol_sync_dc_filter[1];
|
||||
s->symbol_sync_dc_filter[1] = s->symbol_sync_dc_filter[0];
|
||||
s->symbol_sync_dc_filter[0] = v;
|
||||
/* A little integration will now filter away much of the noise */
|
||||
s->baud_phase -= p;
|
||||
if (abs(s->baud_phase) > 100*FP_FACTOR)
|
||||
{
|
||||
if (s->baud_phase > 0)
|
||||
i = (s->baud_phase > 1000*FP_FACTOR) ? 5 : 1;
|
||||
else
|
||||
i = (s->baud_phase < -1000*FP_FACTOR) ? -5 : -1;
|
||||
|
||||
//printf("v = %10.5f %5d - %f %f %d %d\n", v, i, p, s->baud_phase, s->total_baud_timing_correction);
|
||||
s->eq_put_step += i;
|
||||
s->total_baud_timing_correction += i;
|
||||
}
|
||||
#else
|
||||
/* Cross correlate */
|
||||
v = s->symbol_sync_low[1]*s->symbol_sync_high[1]*SYNC_CROSS_CORR_COEFF_A
|
||||
+ s->symbol_sync_low[0]*s->symbol_sync_high[1]*SYNC_CROSS_CORR_COEFF_B
|
||||
|
@ -532,6 +586,7 @@ static __inline__ void symbol_sync(v17_rx_state_t *s)
|
|||
s->eq_put_step += i;
|
||||
s->total_baud_timing_correction += i;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -589,11 +644,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
case TRAINING_STAGE_SYMBOL_ACQUISITION:
|
||||
/* Allow time for the symbol synchronisation to settle the symbol timing. */
|
||||
target = &zero;
|
||||
#if defined(IAXMODEM_STUFF)
|
||||
if (++s->training_count >= 100)
|
||||
#else
|
||||
if (++s->training_count >= 50)
|
||||
#endif
|
||||
{
|
||||
/* Record the current phase angle */
|
||||
s->angles[0] =
|
||||
|
@ -723,8 +774,9 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
s->carrier_phase += (angle - 219937506);
|
||||
|
||||
/* We have just seen the first symbol of the scrambled sequence, so skip it. */
|
||||
descramble(s, 1);
|
||||
descramble(s, 1);
|
||||
bit = descramble(s, 1);
|
||||
bit = (bit << 1) | descramble(s, 1);
|
||||
target = &cdba[bit];
|
||||
s->training_count = 1;
|
||||
s->training_stage = TRAINING_STAGE_COARSE_TRAIN_ON_CDBA;
|
||||
report_status_change(s, SIG_STATUS_TRAINING_IN_PROGRESS);
|
||||
|
@ -826,7 +878,6 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
}
|
||||
break;
|
||||
case TRAINING_STAGE_SHORT_WAIT_FOR_CDBA:
|
||||
target = &cdba[(s->training_count & 1) + 2];
|
||||
/* Look for the initial ABAB sequence to display a phase reversal, which will
|
||||
signal the start of the scrambled CDBA segment */
|
||||
angle = arctan2(z.im, z.re);
|
||||
|
@ -835,13 +886,15 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
{
|
||||
/* We seem to have a phase reversal */
|
||||
/* We have just seen the first symbol of the scrambled sequence, so skip it. */
|
||||
descramble(s, 1);
|
||||
descramble(s, 1);
|
||||
bit = descramble(s, 1);
|
||||
bit = (bit << 1) | descramble(s, 1);
|
||||
target = &cdba[bit];
|
||||
s->training_count = 1;
|
||||
s->training_error = 0.0f;
|
||||
s->training_stage = TRAINING_STAGE_SHORT_TRAIN_ON_CDBA_AND_TEST;
|
||||
break;
|
||||
}
|
||||
target = &cdba[(s->training_count & 1) + 2];
|
||||
track_carrier(s, &z, target);
|
||||
if (++s->training_count > V17_TRAINING_SEG_1_LEN)
|
||||
{
|
||||
|
@ -984,7 +1037,7 @@ SPAN_DECLARE(int) v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
|
|||
We need to measure the power with the DC blocked, but not using
|
||||
a slow to respond DC blocker. Use the most elementary HPF. */
|
||||
x = amp[i] >> 1;
|
||||
/* There could be oveflow 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;
|
||||
power = power_meter_update(&(s->power), diff);
|
||||
#if defined(IAXMODEM_STUFF)
|
||||
|
@ -1111,6 +1164,34 @@ SPAN_DECLARE(int) v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) v17_rx_fillin(v17_rx_state_t *s, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* We want to sustain the current state (i.e carrier on<->carrier off), and
|
||||
try to sustain the carrier phase. We should probably push the filters, as well */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Fill-in %d samples\n", len);
|
||||
if (!s->signal_present)
|
||||
return 0;
|
||||
if (s->training_stage == TRAINING_STAGE_PARKED)
|
||||
return 0;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
dds_advance(&s->carrier_phase, s->carrier_phase_rate);
|
||||
#else
|
||||
dds_advancef(&s->carrier_phase, s->carrier_phase_rate);
|
||||
#endif
|
||||
/* Advance the symbol phase the appropriate amount */
|
||||
s->eq_put_step -= RX_PULSESHAPER_COEFF_SETS;
|
||||
if (s->eq_put_step <= 0)
|
||||
s->eq_put_step += RX_PULSESHAPER_COEFF_SETS*10/(3*2);
|
||||
/* TODO: Should we rotate any buffers */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(void) v17_rx_set_put_bit(v17_rx_state_t *s, put_bit_func_t put_bit, void *user_data)
|
||||
{
|
||||
s->put_bit = put_bit;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: v17tx.c,v 1.71 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: v17tx.c,v 1.72 2009/04/12 04:20:01 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -69,21 +69,31 @@
|
|||
#include "v17tx_floating_rrc.h"
|
||||
#endif
|
||||
|
||||
/*! The nominal frequency of the carrier, in Hertz */
|
||||
#define CARRIER_NOMINAL_FREQ 1800.0f
|
||||
|
||||
/* Segments of the training sequence */
|
||||
/*! The start of the optional TEP, that may preceed the actual training, in symbols */
|
||||
#define V17_TRAINING_SEG_TEP_A 0
|
||||
/*! The mid point of the optional TEP, that may preceed the actual training, in symbols */
|
||||
#define V17_TRAINING_SEG_TEP_B (V17_TRAINING_SEG_TEP_A + 480)
|
||||
/*! The start of training segment 1, in symbols */
|
||||
#define V17_TRAINING_SEG_1 (V17_TRAINING_SEG_TEP_B + 48)
|
||||
/*! The start of training segment 2, in symbols */
|
||||
#define V17_TRAINING_SEG_2 (V17_TRAINING_SEG_1 + 256)
|
||||
/*! The start of training segment 3, in symbols */
|
||||
#define V17_TRAINING_SEG_3 (V17_TRAINING_SEG_2 + 2976)
|
||||
/*! The start of training segment 4, in symbols */
|
||||
#define V17_TRAINING_SEG_4 (V17_TRAINING_SEG_3 + 64)
|
||||
/*! The start of training segment 4 in short training mode, in symbols */
|
||||
#define V17_TRAINING_SHORT_SEG_4 (V17_TRAINING_SEG_2 + 38)
|
||||
/*! The end of the training, in symbols */
|
||||
#define V17_TRAINING_END (V17_TRAINING_SEG_4 + 48)
|
||||
#define V17_TRAINING_SHUTDOWN_A (V17_TRAINING_END + 32)
|
||||
/*! The end of the shutdown sequence, in symbols */
|
||||
#define V17_TRAINING_SHUTDOWN_END (V17_TRAINING_SHUTDOWN_A + 48)
|
||||
|
||||
#define V17_TRAINING_SHORT_SEG_4 (V17_TRAINING_SEG_2 + 38)
|
||||
|
||||
/*! The 16 bit pattern used in the bridge section of the training sequence */
|
||||
#define V17_BRIDGE_WORD 0x8880
|
||||
|
||||
static __inline__ int scramble(v17_tx_state_t *s, int in_bit)
|
||||
|
|
|
@ -0,0 +1,819 @@
|
|||
/*
|
||||
* SpanDSP - a series of DSP components for telephony
|
||||
*
|
||||
* v18.c - V.18 text telephony for the deaf.
|
||||
*
|
||||
* Written by Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* Copyright (C) 2004-2009 Steve Underwood
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License version 2.1,
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: v18.c,v 1.6 2009/04/20 16:36:36 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
#if defined(HAVE_TGMATH_H)
|
||||
#include <tgmath.h>
|
||||
#endif
|
||||
#if defined(HAVE_MATH_H)
|
||||
#include <math.h>
|
||||
#endif
|
||||
#include "floating_fudge.h"
|
||||
|
||||
#include "spandsp/telephony.h"
|
||||
#include "spandsp/logging.h"
|
||||
#include "spandsp/queue.h"
|
||||
#include "spandsp/async.h"
|
||||
#include "spandsp/complex.h"
|
||||
#include "spandsp/dds.h"
|
||||
#include "spandsp/tone_detect.h"
|
||||
#include "spandsp/tone_generate.h"
|
||||
#include "spandsp/super_tone_rx.h"
|
||||
#include "spandsp/power_meter.h"
|
||||
#include "spandsp/fsk.h"
|
||||
#include "spandsp/dtmf.h"
|
||||
#include "spandsp/modem_connect_tones.h"
|
||||
#include "spandsp/v8.h"
|
||||
#include "spandsp/v18.h"
|
||||
|
||||
#include "spandsp/private/logging.h"
|
||||
#include "spandsp/private/queue.h"
|
||||
#include "spandsp/private/tone_generate.h"
|
||||
#include "spandsp/private/async.h"
|
||||
#include "spandsp/private/fsk.h"
|
||||
#include "spandsp/private/dtmf.h"
|
||||
#include "spandsp/private/modem_connect_tones.h"
|
||||
#include "spandsp/private/v18.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/*! The baudot code to shift from alpha to digits and symbols */
|
||||
#define BAUDOT_FIGURE_SHIFT 0x1B
|
||||
/*! The baudot code to shift from digits and symbols to alpha */
|
||||
#define BAUDOT_LETTER_SHIFT 0x1F
|
||||
|
||||
struct dtmf_to_ascii_s
|
||||
{
|
||||
const char *dtmf;
|
||||
char ascii;
|
||||
};
|
||||
|
||||
static const struct dtmf_to_ascii_s dtmf_to_ascii[] =
|
||||
{
|
||||
{"###1", 'C'},
|
||||
{"###2", 'F'},
|
||||
{"###3", 'I'},
|
||||
{"###4", 'L'},
|
||||
{"###5", 'O'},
|
||||
{"###6", 'R'},
|
||||
{"###7", 'U'},
|
||||
{"###8", 'X'},
|
||||
{"###9", ';'},
|
||||
{"###0", '!'},
|
||||
{"##*1", 'A'},
|
||||
{"##*2", 'D'},
|
||||
{"##*3", 'G'},
|
||||
{"##*4", 'J'},
|
||||
{"##*5", 'M'},
|
||||
{"##*6", 'P'},
|
||||
{"##*7", 'S'},
|
||||
{"##*8", 'V'},
|
||||
{"##*9", 'Y'},
|
||||
{"##1", 'B'},
|
||||
{"##2", 'E'},
|
||||
{"##3", 'H'},
|
||||
{"##4", 'K'},
|
||||
{"##5", 'N'},
|
||||
{"##6", 'Q'},
|
||||
{"##7", 'T'},
|
||||
{"##8", 'W'},
|
||||
{"##9", 'Z'},
|
||||
{"##0", ' '},
|
||||
{"#*1", 'æ'}, // (Note 1) 111 1011
|
||||
{"#*2", 'ø'}, // (Note 1) 111 1100
|
||||
{"#*3", 'å'}, // (Note 1) 111 1101
|
||||
{"#*4", 'Æ'}, // (Note 1) 101 1011
|
||||
{"#*5", 'Ø'}, // (Note 1) 101 1100
|
||||
{"#*6", 'Å'}, // (Note 1) 101 1101
|
||||
{"#0", '?'},
|
||||
{"#1", 'c'},
|
||||
{"#2", 'f'},
|
||||
{"#3", 'i'},
|
||||
{"#4", 'l'},
|
||||
{"#5", 'o'},
|
||||
{"#6", 'r'},
|
||||
{"#7", 'u'},
|
||||
{"#8", 'x'},
|
||||
{"#9", '.'},
|
||||
{"*#0", '0'},
|
||||
{"*#1", '1'},
|
||||
{"*#2", '2'},
|
||||
{"*#3", '3'},
|
||||
{"*#4", '4'},
|
||||
{"*#5", '5'},
|
||||
{"*#6", '6'},
|
||||
{"*#7", '7'},
|
||||
{"*#8", '8'},
|
||||
{"*#9", '9'},
|
||||
{"**1", '+'},
|
||||
{"**2", '-'},
|
||||
{"**3", '='},
|
||||
{"**4", ':'},
|
||||
{"**5", '%'},
|
||||
{"**6", '('},
|
||||
{"**7", ')'},
|
||||
{"**8", ','},
|
||||
{"**9", '\n'},
|
||||
{"*0", '\b'},
|
||||
{"*1", 'a'},
|
||||
{"*2", 'd'},
|
||||
{"*3", 'g'},
|
||||
{"*4", 'j'},
|
||||
{"*5", 'm'},
|
||||
{"*6", 'p'},
|
||||
{"*7", 's'},
|
||||
{"*8", 'v'},
|
||||
{"*9", 'y'},
|
||||
{"0", ' '},
|
||||
{"1", 'b'},
|
||||
{"2", 'e'},
|
||||
{"3", 'h'},
|
||||
{"4", 'k'},
|
||||
{"5", 'n'},
|
||||
{"6", 'q'},
|
||||
{"7", 't'},
|
||||
{"8", 'w'},
|
||||
{"9", 'z'},
|
||||
{"", '\0'}
|
||||
};
|
||||
|
||||
static const char *ascii_to_dtmf[128] =
|
||||
{
|
||||
"", /* NULL */
|
||||
"", /* SOH */
|
||||
"", /* STX */
|
||||
"", /* ETX */
|
||||
"", /* EOT */
|
||||
"", /* ENQ */
|
||||
"", /* ACK */
|
||||
"", /* BEL */
|
||||
"*0", /* BACK SPACE */
|
||||
"0", /* HT >> SPACE */
|
||||
"**9", /* LF */
|
||||
"**9", /* VT >> LF */
|
||||
"**9", /* FF >> LF */
|
||||
"", /* CR */
|
||||
"", /* SO */
|
||||
"", /* SI */
|
||||
"", /* DLE */
|
||||
"", /* DC1 */
|
||||
"", /* DC2 */
|
||||
"", /* DC3 */
|
||||
"", /* DC4 */
|
||||
"", /* NAK */
|
||||
"", /* SYN */
|
||||
"", /* ETB */
|
||||
"", /* CAN */
|
||||
"", /* EM */
|
||||
"#0", /* SUB >> ? */
|
||||
"", /* ESC */
|
||||
"**9", /* IS4 >> LF */
|
||||
"**9", /* IS3 >> LF */
|
||||
"**9", /* IS2 >> LF */
|
||||
"0", /* IS1 >> SPACE */
|
||||
"0", /* SPACE */
|
||||
"###0", /* ! */
|
||||
"", /* " */
|
||||
"", /* # */
|
||||
"", /* $ */
|
||||
"**5", /* % */
|
||||
"**1", /* & >> + */
|
||||
"", /* ’ */
|
||||
"**6", /* ( */
|
||||
"**7", /* ) */
|
||||
"#9", /* _ >> . */
|
||||
"**1", /* + */
|
||||
"**8", /* , */
|
||||
"**2", /* - */
|
||||
"#9", /* . */
|
||||
"", /* / */
|
||||
"*#0", /* 0 */
|
||||
"*#1", /* 1 */
|
||||
"*#2", /* 2 */
|
||||
"*#3", /* 3 */
|
||||
"*#4", /* 4 */
|
||||
"*#5", /* 5 */
|
||||
"*#6", /* 6 */
|
||||
"*#7", /* 7 */
|
||||
"*#8", /* 8 */
|
||||
"*#9", /* 9 */
|
||||
"**4", /* : */
|
||||
"###9", /* ; */
|
||||
"**6", /* < >> ( */
|
||||
"**3", /* = */
|
||||
"**7", /* > >> ) */
|
||||
"#0", /* ? */
|
||||
"###8", /* @ >> X */
|
||||
"##*1", /* A */
|
||||
"##1", /* B */
|
||||
"###1", /* C */
|
||||
"##*2", /* D */
|
||||
"##2", /* E */
|
||||
"###2", /* F */
|
||||
"##*3", /* G */
|
||||
"##3", /* H */
|
||||
"###3", /* I */
|
||||
"##*4", /* J */
|
||||
"##4", /* K */
|
||||
"###4", /* L */
|
||||
"##*5", /* M */
|
||||
"##5", /* N */
|
||||
"###5", /* O */
|
||||
"##*6", /* P */
|
||||
"##6", /* Q */
|
||||
"###6", /* R */
|
||||
"##*7", /* S */
|
||||
"##7", /* T */
|
||||
"###7", /* U */
|
||||
"##*8", /* V */
|
||||
"##8", /* W */
|
||||
"###8", /* X */
|
||||
"##*9", /* Y */
|
||||
"##9", /* Z */
|
||||
"#*4", /* Æ (National code) */
|
||||
"#*5", /* Ø (National code) */
|
||||
"#*6", /* Å (National code) */
|
||||
"", /* ^ */
|
||||
"0", /* _ >> SPACE */
|
||||
"", /* ’ */
|
||||
"*1", /* a */
|
||||
"1", /* b */
|
||||
"#1", /* c */
|
||||
"*2", /* d */
|
||||
"2", /* e */
|
||||
"#2", /* f */
|
||||
"*3", /* g */
|
||||
"3", /* h */
|
||||
"#3", /* i */
|
||||
"*4", /* j */
|
||||
"4", /* k */
|
||||
"#4", /* l */
|
||||
"*5", /* m */
|
||||
"5", /* n */
|
||||
"#5", /* o */
|
||||
"*6", /* p */
|
||||
"6", /* q */
|
||||
"#6", /* r */
|
||||
"*7", /* s */
|
||||
"7", /* t */
|
||||
"#7", /* u */
|
||||
"*8", /* v */
|
||||
"8", /* w */
|
||||
"#8", /* x */
|
||||
"*9", /* y */
|
||||
"9", /* z */
|
||||
"#*1", /* æ (National code) */
|
||||
"#*2", /* ø (National code) */
|
||||
"#*3", /* å (National code) */
|
||||
"0", /* ~ >> SPACE */
|
||||
"*0" /* DEL >> BACK SPACE */
|
||||
};
|
||||
|
||||
static int cmp(const void *s, const void *t)
|
||||
{
|
||||
const char *ss;
|
||||
struct dtmf_to_ascii_s *tt;
|
||||
|
||||
ss = (const char *) s;
|
||||
tt = (struct dtmf_to_ascii_s *) t;
|
||||
return strncmp(ss, tt->dtmf, strlen(tt->dtmf));
|
||||
}
|
||||
|
||||
SPAN_DECLARE(int) v18_encode_dtmf(v18_state_t *s, char dtmf[], const char msg[])
|
||||
{
|
||||
const char *t;
|
||||
char *u;
|
||||
const char *v;
|
||||
|
||||
t = msg;
|
||||
u = dtmf;
|
||||
while (*t)
|
||||
{
|
||||
v = ascii_to_dtmf[*t & 0x7F];
|
||||
while (*v)
|
||||
*u++ = *v++;
|
||||
t++;
|
||||
}
|
||||
*u = '\0';
|
||||
|
||||
return u - dtmf;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) v18_decode_dtmf(v18_state_t *s, char msg[], const char dtmf[])
|
||||
{
|
||||
int entries;
|
||||
const char *t;
|
||||
char *u;
|
||||
struct dtmf_to_ascii_s *ss;
|
||||
|
||||
entries = sizeof(dtmf_to_ascii)/sizeof(dtmf_to_ascii[0]) - 1;
|
||||
t = dtmf;
|
||||
u = msg;
|
||||
while (*t)
|
||||
{
|
||||
ss = bsearch(t, dtmf_to_ascii, entries, sizeof(dtmf_to_ascii[0]), cmp);
|
||||
if (ss)
|
||||
{
|
||||
t += strlen(ss->dtmf);
|
||||
*u++ = ss->ascii;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Can't match the code. Let's assume this is a code we just don't know, and skip over it */
|
||||
while (*t == '#' || *t == '*')
|
||||
t++;
|
||||
if (*t)
|
||||
t++;
|
||||
}
|
||||
}
|
||||
*u = '\0';
|
||||
return u - msg;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(uint16_t) v18_encode_baudot(v18_state_t *s, uint8_t ch)
|
||||
{
|
||||
static const uint8_t conv[128] =
|
||||
{
|
||||
0x00, /* NUL */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0x42, /* LF */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0x48, /* CR */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0xFF, /* */
|
||||
0x44, /* */
|
||||
0xFF, /* ! */
|
||||
0xFF, /* " */
|
||||
0x94, /* # */
|
||||
0x89, /* $ */
|
||||
0xFF, /* % */
|
||||
0xFF, /* & */
|
||||
0x85, /* ' */
|
||||
0x8F, /* ( */
|
||||
0x92, /* ) */
|
||||
0x8B, /* * */
|
||||
0x91, /* + */
|
||||
0x8C, /* , */
|
||||
0x83, /* - */
|
||||
0x9C, /* . */
|
||||
0x9D, /* / */
|
||||
0x96, /* 0 */
|
||||
0x97, /* 1 */
|
||||
0x93, /* 2 */
|
||||
0x81, /* 3 */
|
||||
0x8A, /* 4 */
|
||||
0x90, /* 5 */
|
||||
0x95, /* 6 */
|
||||
0x87, /* 7 */
|
||||
0x86, /* 8 */
|
||||
0x98, /* 9 */
|
||||
0x8E, /* : */
|
||||
0xFF, /* ; */
|
||||
0xFF, /* < */
|
||||
0x9E, /* = */
|
||||
0xFF, /* > */
|
||||
0x99, /* ? */
|
||||
0xFF, /* @ */
|
||||
0x03, /* A */
|
||||
0x19, /* B */
|
||||
0x0E, /* C */
|
||||
0x09, /* D */
|
||||
0x01, /* E */
|
||||
0x0D, /* F */
|
||||
0x1A, /* G */
|
||||
0x14, /* H */
|
||||
0x06, /* I */
|
||||
0x0B, /* J */
|
||||
0x0F, /* K */
|
||||
0x12, /* L */
|
||||
0x1C, /* M */
|
||||
0x0C, /* N */
|
||||
0x18, /* O */
|
||||
0x16, /* P */
|
||||
0x17, /* Q */
|
||||
0x0A, /* R */
|
||||
0x05, /* S */
|
||||
0x10, /* T */
|
||||
0x07, /* U */
|
||||
0x1E, /* V */
|
||||
0x13, /* W */
|
||||
0x1D, /* X */
|
||||
0x15, /* Y */
|
||||
0x11, /* Z */
|
||||
0xFF, /* [ */
|
||||
0xFF, /* \ */
|
||||
0xFF, /* ] */
|
||||
0x9B, /* ^ */
|
||||
0xFF, /* _ */
|
||||
0xFF, /* ` */
|
||||
0x03, /* a */
|
||||
0x19, /* b */
|
||||
0x0E, /* c */
|
||||
0x09, /* d */
|
||||
0x01, /* e */
|
||||
0x0D, /* f */
|
||||
0x1A, /* g */
|
||||
0x14, /* h */
|
||||
0x06, /* i */
|
||||
0x0B, /* j */
|
||||
0x0F, /* k */
|
||||
0x12, /* l */
|
||||
0x1C, /* m */
|
||||
0x0C, /* n */
|
||||
0x18, /* o */
|
||||
0x16, /* p */
|
||||
0x17, /* q */
|
||||
0x0A, /* r */
|
||||
0x05, /* s */
|
||||
0x10, /* t */
|
||||
0x07, /* u */
|
||||
0x1E, /* v */
|
||||
0x13, /* w */
|
||||
0x1D, /* x */
|
||||
0x15, /* y */
|
||||
0x11, /* z */
|
||||
0xFF, /* { */
|
||||
0xFF, /* | */
|
||||
0xFF, /* } */
|
||||
0xFF, /* ~ */
|
||||
0xFF, /* DEL */
|
||||
};
|
||||
uint16_t shift;
|
||||
|
||||
ch = conv[ch];
|
||||
if (ch == 0xFF)
|
||||
return 0;
|
||||
if ((ch & 0x40))
|
||||
return ch & 0x1F;
|
||||
if ((ch & 0x80))
|
||||
{
|
||||
if (s->baudot_tx_shift == 1)
|
||||
return ch & 0x1F;
|
||||
s->baudot_tx_shift = 1;
|
||||
shift = BAUDOT_FIGURE_SHIFT;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s->baudot_tx_shift == 0)
|
||||
return ch & 0x1F;
|
||||
s->baudot_tx_shift = 0;
|
||||
shift = BAUDOT_LETTER_SHIFT;
|
||||
}
|
||||
return (shift << 5) | (ch & 0x1F);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(uint8_t) v18_decode_baudot(v18_state_t *s, uint8_t ch)
|
||||
{
|
||||
static const uint8_t conv[2][32] =
|
||||
{
|
||||
{"\000E\nA SIU\rDRJNFCKTZLWHYPQOBG^MXV^"},
|
||||
{"\0003\n- '87\r$4*,*:(5+)2#6019?*^./=^"}
|
||||
};
|
||||
|
||||
switch (ch)
|
||||
{
|
||||
case BAUDOT_FIGURE_SHIFT:
|
||||
s->baudot_rx_shift = 1;
|
||||
break;
|
||||
case BAUDOT_LETTER_SHIFT:
|
||||
s->baudot_rx_shift = 0;
|
||||
break;
|
||||
default:
|
||||
return conv[s->baudot_rx_shift][ch];
|
||||
}
|
||||
/* return 0 if we did not produce a character */
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void v18_rx_dtmf(void *user_data, const char digits[], int len)
|
||||
{
|
||||
v18_state_t *s;
|
||||
|
||||
s = (v18_state_t *) user_data;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int v18_tdd_get_async_byte(void *user_data)
|
||||
{
|
||||
v18_state_t *s;
|
||||
int ch;
|
||||
|
||||
s = (v18_state_t *) user_data;
|
||||
if ((ch = queue_read_byte(&s->queue.queue)) >= 0)
|
||||
{
|
||||
int space;
|
||||
int cont;
|
||||
space = queue_free_space(&s->queue.queue);
|
||||
cont = queue_contents(&s->queue.queue);
|
||||
return ch;
|
||||
}
|
||||
if (s->tx_signal_on)
|
||||
{
|
||||
/* The FSK should now be switched off. */
|
||||
s->tx_signal_on = FALSE;
|
||||
}
|
||||
return 0x1F;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void v18_tdd_put_async_byte(void *user_data, int byte)
|
||||
{
|
||||
v18_state_t *s;
|
||||
uint8_t octet;
|
||||
|
||||
s = (v18_state_t *) user_data;
|
||||
//printf("Rx byte %x\n", byte);
|
||||
if (byte < 0)
|
||||
{
|
||||
/* Special conditions */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "V.18 signal status is %s (%d)\n", signal_status_to_str(byte), byte);
|
||||
switch (byte)
|
||||
{
|
||||
case SIG_STATUS_CARRIER_UP:
|
||||
s->consecutive_ones = 0;
|
||||
s->bit_pos = 0;
|
||||
s->in_progress = 0;
|
||||
s->rx_msg_len = 0;
|
||||
break;
|
||||
case SIG_STATUS_CARRIER_DOWN:
|
||||
if (s->rx_msg_len > 0)
|
||||
{
|
||||
/* Whatever we have to date constitutes the message */
|
||||
s->rx_msg[s->rx_msg_len] = '\0';
|
||||
s->put_msg(s->user_data, s->rx_msg, s->rx_msg_len);
|
||||
s->rx_msg_len = 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "Unexpected special put byte value - %d!\n", byte);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ((octet = v18_decode_baudot(s, (uint8_t) (byte & 0x1F))))
|
||||
s->rx_msg[s->rx_msg_len++] = octet;
|
||||
if (s->rx_msg_len >= 256)
|
||||
{
|
||||
s->rx_msg[s->rx_msg_len] = '\0';
|
||||
s->put_msg(s->user_data, s->rx_msg, s->rx_msg_len);
|
||||
s->rx_msg_len = 0;
|
||||
}
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) v18_tx(v18_state_t *s, int16_t *amp, int max_len)
|
||||
{
|
||||
int len;
|
||||
int lenx;
|
||||
|
||||
len = tone_gen(&(s->alert_tone_gen), amp, max_len);
|
||||
if (s->tx_signal_on)
|
||||
{
|
||||
switch (s->mode)
|
||||
{
|
||||
case V18_MODE_DTMF:
|
||||
if (len < max_len)
|
||||
len += dtmf_tx(&(s->dtmftx), amp, max_len - len);
|
||||
break;
|
||||
default:
|
||||
if (len < max_len)
|
||||
{
|
||||
if ((lenx = fsk_tx(&(s->fsktx), amp + len, max_len - len)) <= 0)
|
||||
s->tx_signal_on = FALSE;
|
||||
len += lenx;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) v18_rx(v18_state_t *s, const int16_t amp[], int len)
|
||||
{
|
||||
switch (s->mode)
|
||||
{
|
||||
case V18_MODE_DTMF:
|
||||
/* Apply a message timeout. */
|
||||
s->in_progress -= len;
|
||||
if (s->in_progress <= 0)
|
||||
s->rx_msg_len = 0;
|
||||
dtmf_rx(&(s->dtmfrx), amp, len);
|
||||
break;
|
||||
default:
|
||||
fsk_rx(&(s->fskrx), amp, len);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) v18_put(v18_state_t *s, const char msg[], int len)
|
||||
{
|
||||
char buf[256 + 1];
|
||||
int x;
|
||||
int n;
|
||||
int i;
|
||||
|
||||
/* This returns the number of characters that would not fit in the buffer.
|
||||
The buffer will only be loaded if the whole string of digits will fit,
|
||||
in which case zero is returned. */
|
||||
if (len < 0)
|
||||
{
|
||||
if ((len = strlen(msg)) == 0)
|
||||
return 0;
|
||||
}
|
||||
switch (s->mode)
|
||||
{
|
||||
case V18_MODE_5BIT_45:
|
||||
case V18_MODE_5BIT_50:
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
n = 0;
|
||||
if ((x = v18_encode_baudot(s, msg[i])))
|
||||
{
|
||||
if ((x & 0x3E0))
|
||||
buf[n++] = (uint8_t) ((x >> 5) & 0x1F);
|
||||
buf[n++] = (uint8_t) (x & 0x1F);
|
||||
/* TODO: Deal with out of space condition */
|
||||
if (queue_write(&s->queue.queue, (const uint8_t *) buf, n) < 0)
|
||||
return 0;
|
||||
s->tx_signal_on = TRUE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case V18_MODE_DTMF:
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(logging_state_t *) v18_get_logging_state(v18_state_t *s)
|
||||
{
|
||||
return &s->logging;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(v18_state_t *) v18_init(v18_state_t *s,
|
||||
int caller,
|
||||
int mode,
|
||||
put_msg_func_t put_msg,
|
||||
void *user_data)
|
||||
{
|
||||
if (s == NULL)
|
||||
{
|
||||
if ((s = (v18_state_t *) malloc(sizeof(*s))) == NULL)
|
||||
return NULL;
|
||||
}
|
||||
memset(s, 0, sizeof(*s));
|
||||
s->caller = caller;
|
||||
s->mode = mode;
|
||||
s->put_msg = put_msg;
|
||||
s->user_data = user_data;
|
||||
|
||||
switch (s->mode)
|
||||
{
|
||||
case V18_MODE_5BIT_45:
|
||||
fsk_tx_init(&(s->fsktx), &preset_fsk_specs[FSK_WEITBRECHT], async_tx_get_bit, &(s->asynctx));
|
||||
async_tx_init(&(s->asynctx), 5, ASYNC_PARITY_NONE, 2, FALSE, v18_tdd_get_async_byte, s);
|
||||
/* Schedule an explicit shift at the start of baudot transmission */
|
||||
s->baudot_tx_shift = 2;
|
||||
/* TDD uses 5 bit data, no parity and 1.5 stop bits. We scan for the first stop bit, and
|
||||
ride over the fraction. */
|
||||
fsk_rx_init(&(s->fskrx), &preset_fsk_specs[FSK_WEITBRECHT], 7, v18_tdd_put_async_byte, s);
|
||||
s->baudot_rx_shift = 0;
|
||||
break;
|
||||
case V18_MODE_5BIT_50:
|
||||
fsk_tx_init(&(s->fsktx), &preset_fsk_specs[FSK_WEITBRECHT50], async_tx_get_bit, &(s->asynctx));
|
||||
async_tx_init(&(s->asynctx), 5, ASYNC_PARITY_NONE, 2, FALSE, v18_tdd_get_async_byte, s);
|
||||
/* Schedule an explicit shift at the start of baudot transmission */
|
||||
s->baudot_tx_shift = 2;
|
||||
/* TDD uses 5 bit data, no parity and 1.5 stop bits. We scan for the first stop bit, and
|
||||
ride over the fraction. */
|
||||
fsk_rx_init(&(s->fskrx), &preset_fsk_specs[FSK_WEITBRECHT50], 7, v18_tdd_put_async_byte, s);
|
||||
s->baudot_rx_shift = 0;
|
||||
break;
|
||||
case V18_MODE_DTMF:
|
||||
dtmf_tx_init(&(s->dtmftx));
|
||||
dtmf_rx_init(&(s->dtmfrx), v18_rx_dtmf, s);
|
||||
break;
|
||||
case V18_MODE_EDT:
|
||||
break;
|
||||
case V18_MODE_BELL103:
|
||||
break;
|
||||
case V18_MODE_V23VIDEOTEX:
|
||||
break;
|
||||
case V18_MODE_V21TEXTPHONE:
|
||||
break;
|
||||
case V18_MODE_V18TEXTPHONE:
|
||||
break;
|
||||
}
|
||||
queue_init(&s->queue.queue, 128, QUEUE_READ_ATOMIC | QUEUE_WRITE_ATOMIC);
|
||||
return s;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) v18_release(v18_state_t *s)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) v18_free(v18_state_t *s)
|
||||
{
|
||||
free(s);
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(const char *) v18_mode_to_str(int mode)
|
||||
{
|
||||
switch (mode)
|
||||
{
|
||||
case V18_MODE_NONE:
|
||||
return "None";
|
||||
case V18_MODE_5BIT_45:
|
||||
return "Weitbrecht TDD (45.45bps)";
|
||||
case V18_MODE_5BIT_50:
|
||||
return "Weitbrecht TDD (50bps)";
|
||||
case V18_MODE_DTMF:
|
||||
return "DTMF";
|
||||
case V18_MODE_EDT:
|
||||
return "EDT";
|
||||
case V18_MODE_BELL103:
|
||||
return "Bell 103";
|
||||
case V18_MODE_V23VIDEOTEX:
|
||||
return "Videotex";
|
||||
case V18_MODE_V21TEXTPHONE:
|
||||
return "V.21";
|
||||
case V18_MODE_V18TEXTPHONE:
|
||||
return "V.18 text telephone";
|
||||
}
|
||||
return "???";
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
/*- End of file ------------------------------------------------------------*/
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: v22bis_rx.c,v 1.47 2009/02/03 16:28:40 steveu Exp $
|
||||
* $Id: v22bis_rx.c,v 1.56 2009/04/20 12:26:38 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -61,7 +61,7 @@
|
|||
#include "spandsp/private/logging.h"
|
||||
#include "spandsp/private/v22bis.h"
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
#include "v22bis_rx_1200_floating_rrc.h"
|
||||
#include "v22bis_rx_2400_floating_rrc.h"
|
||||
#else
|
||||
|
@ -71,7 +71,9 @@
|
|||
|
||||
#define ms_to_symbols(t) (((t)*600)/1000)
|
||||
|
||||
/*! The adaption rate coefficient for the equalizer */
|
||||
#define EQUALIZER_DELTA 0.25f
|
||||
/*! The number of phase shifted coefficient set for the pulse shaping/bandpass filter */
|
||||
#define PULSESHAPER_COEFF_SETS 12
|
||||
|
||||
/*
|
||||
|
@ -102,16 +104,29 @@ The basic method used by the V.22bis receiver is:
|
|||
|
||||
enum
|
||||
{
|
||||
V22BIS_TRAINING_STAGE_NORMAL_OPERATION,
|
||||
V22BIS_TRAINING_STAGE_SYMBOL_ACQUISITION,
|
||||
V22BIS_TRAINING_STAGE_LOG_PHASE,
|
||||
V22BIS_TRAINING_STAGE_UNSCRAMBLED_ONES,
|
||||
V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011,
|
||||
V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200,
|
||||
V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_2400,
|
||||
V22BIS_TRAINING_STAGE_WAIT_FOR_START_1,
|
||||
V22BIS_TRAINING_STAGE_WAIT_FOR_START_2,
|
||||
V22BIS_TRAINING_STAGE_PARKED
|
||||
V22BIS_RX_TRAINING_STAGE_NORMAL_OPERATION,
|
||||
V22BIS_RX_TRAINING_STAGE_SYMBOL_ACQUISITION,
|
||||
V22BIS_RX_TRAINING_STAGE_LOG_PHASE,
|
||||
V22BIS_RX_TRAINING_STAGE_UNSCRAMBLED_ONES,
|
||||
V22BIS_RX_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200,
|
||||
V22BIS_RX_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200_SUSTAINING,
|
||||
V22BIS_RX_TRAINING_STAGE_WAIT_FOR_START_1,
|
||||
V22BIS_RX_TRAINING_STAGE_WAIT_FOR_START_2,
|
||||
V22BIS_RX_TRAINING_STAGE_PARKED
|
||||
};
|
||||
|
||||
/* Segments of the training sequence */
|
||||
enum
|
||||
{
|
||||
V22BIS_TX_TRAINING_STAGE_NORMAL_OPERATION = 0,
|
||||
V22BIS_TX_TRAINING_STAGE_INITIAL_TIMED_SILENCE,
|
||||
V22BIS_TX_TRAINING_STAGE_INITIAL_SILENCE,
|
||||
V22BIS_TX_TRAINING_STAGE_U11,
|
||||
V22BIS_TX_TRAINING_STAGE_U0011,
|
||||
V22BIS_TX_TRAINING_STAGE_S11,
|
||||
V22BIS_TX_TRAINING_STAGE_TIMED_S11,
|
||||
V22BIS_TX_TRAINING_STAGE_S1111,
|
||||
V22BIS_TX_TRAINING_STAGE_PARKED
|
||||
};
|
||||
|
||||
static const uint8_t space_map_v22bis[6][6] =
|
||||
|
@ -124,6 +139,19 @@ static const uint8_t space_map_v22bis[6][6] =
|
|||
{15, 14, 14, 1, 1, 3}
|
||||
};
|
||||
|
||||
static const uint8_t phase_steps[4] =
|
||||
{
|
||||
1, 0, 2, 3
|
||||
};
|
||||
|
||||
static const uint8_t ones[] =
|
||||
{
|
||||
0, 1, 1, 2,
|
||||
1, 2, 2, 3,
|
||||
1, 2, 2, 3,
|
||||
2, 3, 3, 4
|
||||
};
|
||||
|
||||
SPAN_DECLARE(float) v22bis_rx_carrier_frequency(v22bis_state_t *s)
|
||||
{
|
||||
return dds_frequencyf(s->rx.carrier_phase_rate);
|
||||
|
@ -138,7 +166,23 @@ SPAN_DECLARE(float) v22bis_symbol_timing_correction(v22bis_state_t *s)
|
|||
|
||||
SPAN_DECLARE(float) v22bis_rx_signal_power(v22bis_state_t *s)
|
||||
{
|
||||
return power_meter_current_dbm0(&s->rx.rx_power);
|
||||
return power_meter_current_dbm0(&s->rx.rx_power) + 6.34f;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(void) v22bis_rx_signal_cutoff(v22bis_state_t *s, float cutoff)
|
||||
{
|
||||
s->rx.carrier_on_power = (int32_t) (power_meter_level_dbm0(cutoff + 2.5f)*0.232f);
|
||||
s->rx.carrier_off_power = (int32_t) (power_meter_level_dbm0(cutoff - 2.5f)*0.232f);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void report_status_change(v22bis_state_t *s, int status)
|
||||
{
|
||||
if (s->status_handler)
|
||||
s->status_handler(s->status_user_data, status);
|
||||
else if (s->put_bit)
|
||||
s->put_bit(s->user_data, status);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -240,15 +284,14 @@ static __inline__ void track_carrier(v22bis_state_t *s, const complexf_t *z, con
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ void put_bit(v22bis_state_t *s, int bit)
|
||||
static __inline__ int descramble(v22bis_state_t *s, int bit)
|
||||
{
|
||||
int out_bit;
|
||||
|
||||
bit &= 1;
|
||||
|
||||
/* Descramble the bit */
|
||||
s->rx.scramble_reg = (s->rx.scramble_reg << 1) | bit;
|
||||
out_bit = (bit ^ (s->rx.scramble_reg >> 15) ^ (s->rx.scramble_reg >> 18)) & 1;
|
||||
out_bit = (bit ^ (s->rx.scramble_reg >> 14) ^ (s->rx.scramble_reg >> 17)) & 1;
|
||||
if (s->rx.scrambler_pattern_count >= 64)
|
||||
{
|
||||
out_bit ^= 1;
|
||||
|
@ -258,23 +301,29 @@ static __inline__ void put_bit(v22bis_state_t *s, int bit)
|
|||
s->rx.scrambler_pattern_count++;
|
||||
else
|
||||
s->rx.scrambler_pattern_count = 0;
|
||||
s->rx.scramble_reg = (s->rx.scramble_reg << 1) | bit;
|
||||
return out_bit;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ void put_bit(v22bis_state_t *s, int bit)
|
||||
{
|
||||
int out_bit;
|
||||
|
||||
/* Descramble the bit */
|
||||
out_bit = descramble(s, bit);
|
||||
s->put_bit(s->user_data, out_bit);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void decode_baud(v22bis_state_t *s, int nearest)
|
||||
{
|
||||
static const uint8_t phase_steps[4] =
|
||||
{
|
||||
1, 0, 2, 3
|
||||
};
|
||||
int raw_bits;
|
||||
|
||||
raw_bits = phase_steps[((nearest - s->rx.constellation_state) >> 2) & 3];
|
||||
raw_bits = phase_steps[((nearest >> 2) - (s->rx.constellation_state >> 2)) & 3];
|
||||
/* The first two bits are the quadrant */
|
||||
put_bit(s, raw_bits);
|
||||
put_bit(s, raw_bits >> 1);
|
||||
put_bit(s, raw_bits);
|
||||
if (s->bit_rate == 2400)
|
||||
{
|
||||
/* The other two bits are the position within the quadrant */
|
||||
|
@ -285,23 +334,36 @@ static void decode_baud(v22bis_state_t *s, int nearest)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int decode_baudx(v22bis_state_t *s, int nearest)
|
||||
{
|
||||
int raw_bits;
|
||||
int out_bits;
|
||||
|
||||
raw_bits = phase_steps[((nearest >> 2) - (s->rx.constellation_state >> 2)) & 3];
|
||||
/* The first two bits are the quadrant */
|
||||
out_bits = descramble(s, raw_bits >> 1);
|
||||
out_bits = (out_bits << 1) | descramble(s, raw_bits);
|
||||
if (s->bit_rate == 2400)
|
||||
{
|
||||
/* The other two bits are the position within the quadrant */
|
||||
out_bits = (out_bits << 1) | descramble(s, nearest >> 1);
|
||||
out_bits = (out_bits << 1) | descramble(s, nearest);
|
||||
}
|
||||
s->rx.constellation_state = nearest;
|
||||
return out_bits;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ int find_quadrant(const complexf_t *z)
|
||||
{
|
||||
int b1;
|
||||
int b2;
|
||||
|
||||
#if 0
|
||||
/* Split along the axes, as follows:
|
||||
1 0
|
||||
2 3
|
||||
*/
|
||||
b1 = (z->re <= 0.0f);
|
||||
b2 = (z->im <= 0.0f);
|
||||
return (b2 << 1) | (b1 ^ b2);
|
||||
#endif
|
||||
/* Split the space along the two diagonals, as follows:
|
||||
\ 1 /
|
||||
2 0
|
||||
\ /
|
||||
2 X 0
|
||||
/ \
|
||||
/ 3 \
|
||||
*/
|
||||
b1 = (z->im > z->re);
|
||||
|
@ -324,6 +386,8 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
|
|||
int re;
|
||||
int im;
|
||||
int nearest;
|
||||
int bitstream;
|
||||
int raw_bits;
|
||||
|
||||
z.re = sample->re;
|
||||
z.im = sample->im;
|
||||
|
@ -379,16 +443,15 @@ static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
|
|||
when the true symbol boundary is close to a sample boundary. */
|
||||
s->rx.eq_put_step += (s->rx.gardner_integrate/16);
|
||||
s->rx.total_baud_timing_correction += (s->rx.gardner_integrate/16);
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Gardner kick %d [total %d]\n", s->rx.gardner_integrate, s->rx.total_baud_timing_correction);
|
||||
//span_log(&s->logging, SPAN_LOG_FLOW, "Gardner kick %d [total %d]\n", s->rx.gardner_integrate, s->rx.total_baud_timing_correction);
|
||||
if (s->rx.qam_report)
|
||||
s->rx.qam_report(s->rx.qam_user_data, NULL, NULL, s->rx.gardner_integrate);
|
||||
s->rx.gardner_integrate = 0;
|
||||
}
|
||||
|
||||
z = equalizer_get(s);
|
||||
printf("VVV %15.5f %15.5f\n", z.re, z.im);
|
||||
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "VVV %p %d\n", s->user_data, s->rx.training);
|
||||
//span_log(&s->logging, SPAN_LOG_FLOW, "VVV %p %d\n", s->user_data, s->rx.training);
|
||||
if (s->rx.sixteen_way_decisions)
|
||||
{
|
||||
re = (int) (z.re + 3.0f);
|
||||
|
@ -408,153 +471,203 @@ span_log(&s->logging, SPAN_LOG_FLOW, "VVV %p %d\n", s->user_data, s->rx.training
|
|||
zz = complex_setf(3.0f/sqrtf(10.0f), -1.0f/sqrtf(10.0f));
|
||||
zz = complex_mulf(&z, &zz);
|
||||
nearest = (find_quadrant(&zz) << 2) | 0x01;
|
||||
printf("Trackit %15.5f %15.5f %15.5f %15.5f %d\n", z.re, z.im, zz.re, zz.im, nearest);
|
||||
printf("Trackit rx %p %15.5f %15.5f %15.5f %15.5f %d\n", s, z.re, z.im, zz.re, zz.im, nearest);
|
||||
}
|
||||
|
||||
switch (s->rx.training)
|
||||
{
|
||||
case V22BIS_TRAINING_STAGE_NORMAL_OPERATION:
|
||||
case V22BIS_RX_TRAINING_STAGE_NORMAL_OPERATION:
|
||||
/* Normal operation. */
|
||||
track_carrier(s, &z, &v22bis_constellation[nearest]);
|
||||
tune_equalizer(s, &z, &v22bis_constellation[nearest]);
|
||||
decode_baud(s, nearest);
|
||||
target = &v22bis_constellation[s->rx.constellation_state];
|
||||
break;
|
||||
case V22BIS_TRAINING_STAGE_SYMBOL_ACQUISITION:
|
||||
case V22BIS_RX_TRAINING_STAGE_SYMBOL_ACQUISITION:
|
||||
/* Allow time for the Gardner algorithm to settle the symbol timing. */
|
||||
target = &z;
|
||||
if (++s->rx.training_count >= 40)
|
||||
{
|
||||
/* QAM and Gardner only play nicely with heavy damping, so we need to change to
|
||||
a slow rate of symbol timing adaption. However, it must not be so slow that it
|
||||
cannot track the worst case timing error specified in V.22bis. This should be 0.01%,
|
||||
but since we might be off in the opposite direction from the source, the total
|
||||
error could be higher. */
|
||||
s->rx.gardner_step = 4;
|
||||
s->rx.detected_unscrambled_zeros = 0;
|
||||
s->rx.detected_unscrambled_ones = 0;
|
||||
s->rx.detected_2400bps_markers = 0;
|
||||
if (s->caller)
|
||||
{
|
||||
s->rx.training = V22BIS_TRAINING_STAGE_UNSCRAMBLED_ONES;
|
||||
}
|
||||
s->rx.training = V22BIS_RX_TRAINING_STAGE_UNSCRAMBLED_ONES;
|
||||
else
|
||||
{
|
||||
if (s->bit_rate == 2400)
|
||||
s->rx.training = V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011;
|
||||
else
|
||||
s->rx.training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
|
||||
}
|
||||
s->rx.training = V22BIS_RX_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
|
||||
break;
|
||||
}
|
||||
|
||||
/* QAM and Gardner only play nicely with heavy damping, so we need to change to
|
||||
a slow rate of symbol timing adaption. However, it must not be so slow that it
|
||||
cannot track the worst case timing error specified in V.22bis. This should be 0.01%,
|
||||
but since we might be off in the opposite direction from the source, the total
|
||||
error could be higher. */
|
||||
/* Once we have pulled in the symbol timing in a coarse way, use finer
|
||||
steps to fine tune the timing. */
|
||||
if (s->rx.training_count == 30)
|
||||
s->rx.gardner_step = 32;
|
||||
break;
|
||||
case V22BIS_TRAINING_STAGE_UNSCRAMBLED_ONES:
|
||||
/* The answering modem should initially receive unscrambled ones at 1200bps */
|
||||
case V22BIS_RX_TRAINING_STAGE_UNSCRAMBLED_ONES:
|
||||
/* Calling modem only */
|
||||
/* The calling modem should initially receive unscrambled ones at 1200bps */
|
||||
track_carrier(s, &z, &v22bis_constellation[nearest]);
|
||||
target = &z;
|
||||
if (nearest == ((s->rx.constellation_state - 4) & 0x0F))
|
||||
s->detected_unscrambled_ones++;
|
||||
if (nearest == ((s->rx.constellation_state + 4) & 0x0F))
|
||||
s->detected_unscrambled_zeros++;
|
||||
raw_bits = phase_steps[((nearest >> 2) - (s->rx.constellation_state >> 2)) & 3];
|
||||
s->rx.constellation_state = nearest;
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "TWIDDLING THUMBS - %d\n", s->rx.training_count);
|
||||
switch (raw_bits)
|
||||
{
|
||||
case 0:
|
||||
s->rx.detected_unscrambled_zeros++;
|
||||
break;
|
||||
case 3:
|
||||
s->rx.detected_unscrambled_ones++;
|
||||
break;
|
||||
default:
|
||||
s->rx.detected_2400bps_markers++;
|
||||
break;
|
||||
}
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "TWIDDLING THUMBS - %d %d\n", s->rx.training_count, s->rx.detected_2400bps_markers);
|
||||
if (++s->rx.training_count == ms_to_symbols(155 + 456))
|
||||
{
|
||||
if (s->detected_unscrambled_ones >= 250 || s->detected_unscrambled_zeros >= 250)
|
||||
s->detected_unscrambled_ones_or_zeros = TRUE;
|
||||
}
|
||||
if (s->rx.training_count == ms_to_symbols(155 + 457))
|
||||
{
|
||||
/* We should only bother looking for the 2400bps marker if we are allowed to use
|
||||
2400bps */
|
||||
if (s->rx.detected_unscrambled_ones >= ms_to_symbols(456)
|
||||
||
|
||||
s->rx.detected_unscrambled_zeros >= ms_to_symbols(456))
|
||||
{
|
||||
if (s->bit_rate == 2400)
|
||||
{
|
||||
/* Try to establish at 2400bps */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting U0011 (S1) (Caller)\n");
|
||||
s->tx.training = V22BIS_TX_TRAINING_STAGE_U0011;
|
||||
s->tx.training_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Only try to establish at 1200bps */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting S11 (Caller)\n");
|
||||
s->tx.training = V22BIS_TX_TRAINING_STAGE_TIMED_S11;
|
||||
s->tx.training_count = 0;
|
||||
}
|
||||
}
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "unscrambled ones = %d, unscrambled zeros = %d, 2400 markers = %d\n", s->rx.detected_unscrambled_ones, s->rx.detected_unscrambled_zeros, s->rx.detected_2400bps_markers);
|
||||
s->rx.training_count = 0;
|
||||
s->rx.training = V22BIS_RX_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
|
||||
s->rx.detected_unscrambled_zeros = 0;
|
||||
s->rx.detected_unscrambled_ones = 0;
|
||||
s->rx.detected_2400bps_markers = 0;
|
||||
s->rx.scrambled_ones_to_date = 0;
|
||||
}
|
||||
break;
|
||||
case V22BIS_RX_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200:
|
||||
track_carrier(s, &z, &v22bis_constellation[nearest]);
|
||||
tune_equalizer(s, &z, &v22bis_constellation[nearest]);
|
||||
target = &z;
|
||||
raw_bits = phase_steps[((nearest >> 2) - (s->rx.constellation_state >> 2)) & 3];
|
||||
switch (raw_bits)
|
||||
{
|
||||
case 0:
|
||||
s->rx.detected_unscrambled_zeros++;
|
||||
break;
|
||||
case 3:
|
||||
s->rx.detected_unscrambled_ones++;
|
||||
break;
|
||||
default:
|
||||
s->rx.detected_2400bps_markers++;
|
||||
break;
|
||||
}
|
||||
bitstream = decode_baudx(s, nearest);
|
||||
s->rx.scrambled_ones_to_date += ones[bitstream];
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "S11 0x%02x 0x%02x 0x%X %d %d %d %d %d %d\n", raw_bits, nearest, bitstream, s->rx.scrambled_ones_to_date, s->rx.detected_unscrambled_ones, s->rx.detected_unscrambled_zeros, s->rx.detected_2400bps_markers, s->rx.training_count, s->rx.detected_2400bps_markers);
|
||||
if (s->rx.detected_2400bps_markers && ++s->rx.training_count > ms_to_symbols(270))
|
||||
{
|
||||
if (!s->caller)
|
||||
{
|
||||
if (s->bit_rate == 2400 && s->rx.detected_2400bps_markers > 20)
|
||||
{
|
||||
/* Try to establish at 2400bps */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting U0011 (S1) (Answerer)\n");
|
||||
s->tx.training = V22BIS_TX_TRAINING_STAGE_U0011;
|
||||
s->tx.training_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We are going to work at 1200bps. */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ [1200] starting S11 (Answerer)\n");
|
||||
s->bit_rate = 1200;
|
||||
s->tx.training = V22BIS_TX_TRAINING_STAGE_TIMED_S11;
|
||||
s->tx.training_count = 0;
|
||||
}
|
||||
}
|
||||
s->rx.training = V22BIS_RX_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200_SUSTAINING;
|
||||
}
|
||||
break;
|
||||
case V22BIS_RX_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200_SUSTAINING:
|
||||
track_carrier(s, &z, &v22bis_constellation[nearest]);
|
||||
tune_equalizer(s, &z, &v22bis_constellation[nearest]);
|
||||
target = &z;
|
||||
raw_bits = phase_steps[((nearest >> 2) - (s->rx.constellation_state >> 2)) & 3];
|
||||
switch (raw_bits)
|
||||
{
|
||||
case 0:
|
||||
s->rx.detected_unscrambled_zeros++;
|
||||
break;
|
||||
case 3:
|
||||
s->rx.detected_unscrambled_ones++;
|
||||
break;
|
||||
default:
|
||||
s->rx.detected_2400bps_markers++;
|
||||
break;
|
||||
}
|
||||
bitstream = decode_baudx(s, nearest);
|
||||
s->rx.scrambled_ones_to_date += ones[bitstream];
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "S11 0x%02x 0x%02x 0x%X %d %d %d %d %d sustain\n", raw_bits, nearest, bitstream, s->rx.scrambled_ones_to_date, s->rx.detected_unscrambled_ones, s->rx.detected_unscrambled_zeros, s->rx.detected_2400bps_markers, s->rx.training_count);
|
||||
if (s->rx.detected_2400bps_markers == 20)
|
||||
{
|
||||
/* It looks like we have the S1 (Unscrambled 00 11) section, so 2400bps
|
||||
operation is possible. */
|
||||
s->rx.detected_2400bps_markers++;
|
||||
if (s->bit_rate == 2400)
|
||||
s->rx.training = V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011;
|
||||
else
|
||||
s->rx.training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
|
||||
}
|
||||
break;
|
||||
case V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011:
|
||||
s->rx.sixteen_way_decisions = TRUE;
|
||||
/* If we can actually find this it means we can use 2400bps. If we find unscrambled ones, it means we
|
||||
we must use 1200bps. */
|
||||
track_carrier(s, &z, &v22bis_constellation[nearest]);
|
||||
tune_equalizer(s, &z, &v22bis_constellation[nearest]);
|
||||
target = &z;
|
||||
//s->rx.carrier_track_i = 1000.0f;
|
||||
//s->rx.carrier_track_p = 1000000.0f;
|
||||
#if 0
|
||||
if (++s->rx.training_count > ms_to_symbols(800))
|
||||
{
|
||||
s->detected_unscrambled_0011_ending = TRUE;
|
||||
s->rx.training = V22BIS_TRAINING_STAGE_UNSCRAMBLED_ONES;
|
||||
}
|
||||
#else
|
||||
if (++s->rx.training_count == 1)
|
||||
{
|
||||
s->detected_unscrambled_zeros = nearest;
|
||||
s->detected_unscrambled_ones = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "0x%X 0x%X 0x%X\n", s->detected_unscrambled_zeros, nearest, (s->detected_unscrambled_zeros + nearest) & 0x0F);
|
||||
if ((s->rx.training_count & 1) == 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "AAA\n");
|
||||
if (((s->detected_unscrambled_zeros + nearest) & 0x0F) == 0x06)
|
||||
s->detected_unscrambled_ones = 1;
|
||||
else if (((s->detected_unscrambled_zeros + nearest) & 0x0F) == 0x02)
|
||||
s->detected_unscrambled_ones = -1;
|
||||
else
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "AAA 1\n");
|
||||
if (s->detected_unscrambled_ones > 5 || s->detected_unscrambled_ones < -5)
|
||||
s->detected_unscrambled_0011_ending = TRUE;
|
||||
else
|
||||
s->bit_rate = 1200;
|
||||
s->rx.training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "BBB\n");
|
||||
if (((s->detected_unscrambled_zeros + nearest) & 0x0F) == 0x06)
|
||||
s->detected_unscrambled_ones = 1;
|
||||
else if (((s->detected_unscrambled_zeros + nearest) & 0x0F) == 0x02)
|
||||
s->detected_unscrambled_ones = -1;
|
||||
else
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "BBB 1\n");
|
||||
if (s->detected_unscrambled_ones > 5 || s->detected_unscrambled_ones < -5)
|
||||
s->detected_unscrambled_0011_ending = TRUE;
|
||||
else
|
||||
s->bit_rate = 1200;
|
||||
s->rx.training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
|
||||
}
|
||||
/* We are allowed to use 2400bps, and the far end is requesting 2400bps. Result: we are going to
|
||||
work at 2400bps */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ [2400] starting U0011 (S1)\n");
|
||||
s->tx.training = V22BIS_TX_TRAINING_STAGE_U0011;
|
||||
s->tx.training_count = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
case V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200:
|
||||
track_carrier(s, &z, &v22bis_constellation[nearest]);
|
||||
tune_equalizer(s, &z, &v22bis_constellation[nearest]);
|
||||
target = &z;
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "S11 0x%02x\n", nearest);
|
||||
if (++s->rx.training_count > ms_to_symbols(900))
|
||||
if (++s->rx.training_count > ms_to_symbols(270 + 765))
|
||||
{
|
||||
s->detected_scrambled_ones_or_zeros_at_1200bps = TRUE;
|
||||
s->rx.training = V22BIS_TRAINING_STAGE_NORMAL_OPERATION;
|
||||
if (s->caller)
|
||||
{
|
||||
if (s->bit_rate == 2400)
|
||||
{
|
||||
/* We've continued for a further 756+-10ms. This should have given the other
|
||||
side enough time to train its equaliser. */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting S1111 (B)\n");
|
||||
s->tx.training = V22BIS_TX_TRAINING_STAGE_S1111;
|
||||
s->tx.training_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ Tx normal operation (1200)\n");
|
||||
s->tx.training = V22BIS_TX_TRAINING_STAGE_NORMAL_OPERATION;
|
||||
s->tx.training_count = 0;
|
||||
s->tx.current_get_bit = s->get_bit;
|
||||
}
|
||||
}
|
||||
if (s->bit_rate == 2400)
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ Rx normal operation (2400)\n");
|
||||
else
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ Rx normal operation (1200)\n");
|
||||
s->rx.training = V22BIS_RX_TRAINING_STAGE_NORMAL_OPERATION;
|
||||
}
|
||||
if (s->bit_rate == 2400 && s->rx.training_count == ms_to_symbols(450))
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting 16 way decisions\n");
|
||||
s->rx.sixteen_way_decisions = TRUE;
|
||||
}
|
||||
break;
|
||||
case V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_2400:
|
||||
track_carrier(s, &z, &v22bis_constellation[nearest]);
|
||||
tune_equalizer(s, &z, &v22bis_constellation[nearest]);
|
||||
s->rx.sixteen_way_decisions = TRUE;
|
||||
target = &z;
|
||||
break;
|
||||
case V22BIS_TRAINING_STAGE_PARKED:
|
||||
case V22BIS_RX_TRAINING_STAGE_PARKED:
|
||||
default:
|
||||
/* We failed to train! */
|
||||
/* Park here until the carrier drops. */
|
||||
|
@ -590,7 +703,6 @@ SPAN_DECLARE(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int len)
|
|||
|
||||
/* Calculate the I filter, with an arbitrary phase step, just so we can calculate
|
||||
the signal power. */
|
||||
/* TODO: get rid of this */
|
||||
if (s->caller)
|
||||
{
|
||||
ii = rx_pulseshaper_2400_re[6][0]*s->rx.rrc_filter[s->rx.rrc_filter_step];
|
||||
|
@ -603,34 +715,34 @@ SPAN_DECLARE(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int len)
|
|||
for (j = 1; j < V22BIS_RX_FILTER_STEPS; j++)
|
||||
ii += rx_pulseshaper_1200_re[6][j]*s->rx.rrc_filter[j + s->rx.rrc_filter_step];
|
||||
}
|
||||
power = power_meter_update(&(s->rx.rx_power), (int16_t) (ii/10.0f));
|
||||
power = power_meter_update(&(s->rx.rx_power), (int16_t) ii);
|
||||
if (s->rx.signal_present)
|
||||
{
|
||||
/* Look for power below -48dBm0 to turn the carrier off */
|
||||
/* Look for power below the carrier off point */
|
||||
if (power < s->rx.carrier_off_power)
|
||||
{
|
||||
v22bis_rx_restart(s, s->bit_rate);
|
||||
s->put_bit(s->user_data, SIG_STATUS_CARRIER_DOWN);
|
||||
report_status_change(s, SIG_STATUS_CARRIER_DOWN);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Look for power exceeding -43dBm0 to turn the carrier on */
|
||||
/* Look for power exceeding the carrier on point */
|
||||
if (power < s->rx.carrier_on_power)
|
||||
continue;
|
||||
s->rx.signal_present = TRUE;
|
||||
s->put_bit(s->user_data, SIG_STATUS_CARRIER_UP);
|
||||
report_status_change(s, SIG_STATUS_CARRIER_UP);
|
||||
}
|
||||
if (s->rx.training != V22BIS_TRAINING_STAGE_PARKED)
|
||||
if (s->rx.training != V22BIS_RX_TRAINING_STAGE_PARKED)
|
||||
{
|
||||
/* Only spend effort processing this data if the modem is not
|
||||
parked, after training failure. */
|
||||
z = dds_complexf(&(s->rx.carrier_phase), s->rx.carrier_phase_rate);
|
||||
if (s->rx.training == V22BIS_TRAINING_STAGE_SYMBOL_ACQUISITION)
|
||||
z = dds_complexf(&s->rx.carrier_phase, s->rx.carrier_phase_rate);
|
||||
if (s->rx.training == V22BIS_RX_TRAINING_STAGE_SYMBOL_ACQUISITION)
|
||||
{
|
||||
/* Only AGC during the initial symbol acquisition, and then lock the gain. */
|
||||
s->rx.agc_scaling = 0.018f*3.60f/sqrtf(power);
|
||||
s->rx.agc_scaling = 0.18f*3.60f/sqrtf(power);
|
||||
}
|
||||
/* Put things into the equalization buffer at T/2 rate. The Gardner algorithm
|
||||
will fiddle the step to align this with the symbols. */
|
||||
|
@ -679,6 +791,28 @@ SPAN_DECLARE(int) v22bis_rx(v22bis_state_t *s, const int16_t amp[], int len)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) v22bis_rx_fillin(v22bis_state_t *s, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* We want to sustain the current state (i.e carrier on<->carrier off), and
|
||||
try to sustain the carrier phase. We should probably push the filters, as well */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Fill-in %d samples\n", len);
|
||||
if (!s->rx.signal_present)
|
||||
return 0;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
dds_advance(&s->rx.carrier_phase, s->rx.carrier_phase_rate);
|
||||
#else
|
||||
dds_advancef(&s->rx.carrier_phase, s->rx.carrier_phase_rate);
|
||||
#endif
|
||||
}
|
||||
/* TODO: Advance the symbol phase the appropriate amount */
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) v22bis_rx_restart(v22bis_state_t *s, int bit_rate)
|
||||
{
|
||||
/* If bit_rate is 2400, the real bit rate is negotiated. If bit_rate
|
||||
|
@ -688,15 +822,14 @@ SPAN_DECLARE(int) v22bis_rx_restart(v22bis_state_t *s, int bit_rate)
|
|||
s->rx.rrc_filter_step = 0;
|
||||
s->rx.scramble_reg = 0;
|
||||
s->rx.scrambler_pattern_count = 0;
|
||||
s->rx.training = V22BIS_TRAINING_STAGE_SYMBOL_ACQUISITION;
|
||||
s->rx.training = V22BIS_RX_TRAINING_STAGE_SYMBOL_ACQUISITION;
|
||||
s->rx.training_count = 0;
|
||||
s->rx.signal_present = FALSE;
|
||||
|
||||
s->rx.carrier_phase_rate = dds_phase_ratef((s->caller) ? 2400.0f : 1200.0f);
|
||||
s->rx.carrier_phase = 0;
|
||||
power_meter_init(&(s->rx.rx_power), 5);
|
||||
s->rx.carrier_on_power = power_meter_level_dbm0(-43);
|
||||
s->rx.carrier_off_power = power_meter_level_dbm0(-48);
|
||||
v22bis_rx_signal_cutoff(s, -45.5f);
|
||||
s->rx.agc_scaling = 0.0005f*0.025f;
|
||||
|
||||
s->rx.constellation_state = 0;
|
||||
|
@ -704,8 +837,9 @@ SPAN_DECLARE(int) v22bis_rx_restart(v22bis_state_t *s, int bit_rate)
|
|||
|
||||
equalizer_reset(s);
|
||||
|
||||
s->detected_unscrambled_ones = 0;
|
||||
s->detected_unscrambled_zeros = 0;
|
||||
s->rx.detected_unscrambled_ones = 0;
|
||||
s->rx.detected_unscrambled_zeros = 0;
|
||||
s->rx.detected_2400bps_markers = 0;
|
||||
s->rx.gardner_integrate = 0;
|
||||
s->rx.gardner_step = 256;
|
||||
s->rx.baud_phase = 0;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: v22bis_tx.c,v 1.51 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: v22bis_tx.c,v 1.56 2009/04/17 14:37:52 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -61,7 +61,7 @@
|
|||
#include "spandsp/private/logging.h"
|
||||
#include "spandsp/private/v22bis.h"
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
#include "v22bis_tx_fixed_rrc.h"
|
||||
#else
|
||||
#include "v22bis_tx_floating_rrc.h"
|
||||
|
@ -243,13 +243,15 @@ Both ends should accept unscrambled binary 1 or binary 0 as the preamble.
|
|||
/* Segments of the training sequence */
|
||||
enum
|
||||
{
|
||||
V22BIS_TRAINING_STAGE_NORMAL_OPERATION = 0,
|
||||
V22BIS_TRAINING_STAGE_INITIAL_SILENCE,
|
||||
V22BIS_TRAINING_STAGE_UNSCRAMBLED_ONES,
|
||||
V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011,
|
||||
V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200,
|
||||
V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_2400,
|
||||
V22BIS_TRAINING_STAGE_PARKED
|
||||
V22BIS_TX_TRAINING_STAGE_NORMAL_OPERATION = 0,
|
||||
V22BIS_TX_TRAINING_STAGE_INITIAL_TIMED_SILENCE,
|
||||
V22BIS_TX_TRAINING_STAGE_INITIAL_SILENCE,
|
||||
V22BIS_TX_TRAINING_STAGE_U11,
|
||||
V22BIS_TX_TRAINING_STAGE_U0011,
|
||||
V22BIS_TX_TRAINING_STAGE_S11,
|
||||
V22BIS_TX_TRAINING_STAGE_TIMED_S11,
|
||||
V22BIS_TX_TRAINING_STAGE_S1111,
|
||||
V22BIS_TX_TRAINING_STAGE_PARKED
|
||||
};
|
||||
|
||||
static const int phase_steps[4] =
|
||||
|
@ -260,19 +262,19 @@ static const int phase_steps[4] =
|
|||
const complexf_t v22bis_constellation[16] =
|
||||
{
|
||||
{ 1.0f, 1.0f},
|
||||
{ 3.0f, 1.0f},
|
||||
{ 3.0f, 1.0f}, /* 1200bps 00 */
|
||||
{ 1.0f, 3.0f},
|
||||
{ 3.0f, 3.0f},
|
||||
{-1.0f, 1.0f},
|
||||
{-1.0f, 3.0f},
|
||||
{-1.0f, 3.0f}, /* 1200bps 01 */
|
||||
{-3.0f, 1.0f},
|
||||
{-3.0f, 3.0f},
|
||||
{-1.0f, -1.0f},
|
||||
{-3.0f, -1.0f},
|
||||
{-3.0f, -1.0f}, /* 1200bps 10 */
|
||||
{-1.0f, -3.0f},
|
||||
{-3.0f, -3.0f},
|
||||
{ 1.0f, -1.0f},
|
||||
{ 1.0f, -3.0f},
|
||||
{ 1.0f, -3.0f}, /* 1200bps 11 */
|
||||
{ 3.0f, -1.0f},
|
||||
{ 3.0f, -3.0f}
|
||||
};
|
||||
|
@ -287,12 +289,12 @@ static __inline__ int scramble(v22bis_state_t *s, int bit)
|
|||
{
|
||||
int out_bit;
|
||||
|
||||
out_bit = (bit ^ (s->tx.scramble_reg >> 14) ^ (s->tx.scramble_reg >> 17)) & 1;
|
||||
if (s->tx.scrambler_pattern_count >= 64)
|
||||
{
|
||||
out_bit ^= 1;
|
||||
bit ^= 1;
|
||||
s->tx.scrambler_pattern_count = 0;
|
||||
}
|
||||
out_bit = (bit ^ (s->tx.scramble_reg >> 14) ^ (s->tx.scramble_reg >> 17)) & 1;
|
||||
if (out_bit == 1)
|
||||
s->tx.scrambler_pattern_count++;
|
||||
else
|
||||
|
@ -326,159 +328,90 @@ static complexf_t training_get(v22bis_state_t *s)
|
|||
/* V.22bis training sequence */
|
||||
switch (s->tx.training)
|
||||
{
|
||||
case V22BIS_TRAINING_STAGE_INITIAL_SILENCE:
|
||||
/* Segment 1: silence */
|
||||
case V22BIS_TX_TRAINING_STAGE_INITIAL_TIMED_SILENCE:
|
||||
/* The answerer waits 75ms, then sends unscrambled ones */
|
||||
if (++s->tx.training_count >= ms_to_symbols(75))
|
||||
{
|
||||
/* Initial 75ms of silence is over */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting U11 1200\n");
|
||||
s->tx.training = V22BIS_TX_TRAINING_STAGE_U11;
|
||||
s->tx.training_count = 0;
|
||||
}
|
||||
/* Fall through */
|
||||
case V22BIS_TX_TRAINING_STAGE_INITIAL_SILENCE:
|
||||
/* Silence */
|
||||
s->tx.constellation_state = 0;
|
||||
z = complex_setf(0.0f, 0.0f);
|
||||
if (s->caller)
|
||||
{
|
||||
/* The caller just waits for a signal from the far end, which should be unscrambled ones */
|
||||
if (s->detected_unscrambled_ones_or_zeros)
|
||||
{
|
||||
if (s->bit_rate == 2400)
|
||||
{
|
||||
/* Try to establish at 2400bps */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting unscrambled 0011 at 1200 (S1)\n");
|
||||
s->tx.training = V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Only try at 1200bps */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting scrambled ones at 1200 (A)\n");
|
||||
s->tx.training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
|
||||
}
|
||||
s->tx.training_count = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* The answerer waits 75ms, then sends unscrambled ones */
|
||||
if (++s->tx.training_count >= ms_to_symbols(75))
|
||||
{
|
||||
/* Inital 75ms of silence is over */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting unscrambled ones at 1200\n");
|
||||
s->tx.training = V22BIS_TRAINING_STAGE_UNSCRAMBLED_ONES;
|
||||
s->tx.training_count = 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case V22BIS_TRAINING_STAGE_UNSCRAMBLED_ONES:
|
||||
/* Segment 2: Continuous unscrambled ones at 1200bps (i.e. reversals). */
|
||||
case V22BIS_TX_TRAINING_STAGE_U11:
|
||||
/* Send continuous unscrambled ones at 1200bps (i.e. 270 degree phase steps). */
|
||||
/* Only the answering modem sends unscrambled ones. It is the first thing exchanged between the modems. */
|
||||
s->tx.constellation_state = (s->tx.constellation_state + phase_steps[3]) & 3;
|
||||
z = v22bis_constellation[(s->tx.constellation_state << 2) | 0x01];
|
||||
if (s->bit_rate == 2400 && s->detected_unscrambled_0011_ending)
|
||||
{
|
||||
/* We are allowed to use 2400bps, and the far end is requesting 2400bps. Result: we are going to
|
||||
work at 2400bps */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ [2400] starting unscrambled 0011 at 1200 (S1)\n");
|
||||
s->tx.training = V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011;
|
||||
s->tx.training_count = 0;
|
||||
break;
|
||||
}
|
||||
if (s->detected_scrambled_ones_or_zeros_at_1200bps)
|
||||
{
|
||||
/* We are going to work at 1200bps. */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ [1200] starting scrambled ones at 1200 (B)\n");
|
||||
s->bit_rate = 1200;
|
||||
s->tx.training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
|
||||
s->tx.training_count = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011:
|
||||
/* Segment 3: Continuous unscrambled double dibit 00 11 at 1200bps. This is termed the S1 segment in
|
||||
case V22BIS_TX_TRAINING_STAGE_U0011:
|
||||
/* Continuous unscrambled double dibit 00 11 at 1200bps. This is termed the S1 segment in
|
||||
the V.22bis spec. It is only sent to request or accept 2400bps mode, and lasts 100+-3ms. After this
|
||||
timed burst, we unconditionally change to sending scrambled ones at 1200bps. */
|
||||
s->tx.constellation_state = (s->tx.constellation_state + phase_steps[(s->tx.training_count & 1) ? 3 : 0]) & 3;
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "U0011 Tx 0x%02x\n", s->tx.constellation_state);
|
||||
z = v22bis_constellation[(s->tx.constellation_state << 2) | 0x01];
|
||||
if (++s->tx.training_count >= ms_to_symbols(100))
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting scrambled ones at 1200 (C)\n");
|
||||
s->tx.training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting S11 after U0011\n");
|
||||
if (s->caller)
|
||||
s->tx.training = V22BIS_TX_TRAINING_STAGE_S11;
|
||||
else
|
||||
s->tx.training = V22BIS_TX_TRAINING_STAGE_TIMED_S11;
|
||||
s->tx.training_count = 0;
|
||||
}
|
||||
break;
|
||||
case V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200:
|
||||
/* Segment 4: Scrambled ones at 1200bps. */
|
||||
bits = scramble(s, 1);
|
||||
bits = (bits << 1) | scramble(s, 1);
|
||||
s->tx.constellation_state = (s->tx.constellation_state + phase_steps[bits]) & 3;
|
||||
z = v22bis_constellation[(s->tx.constellation_state << 2) | 0x01];
|
||||
if (s->caller)
|
||||
case V22BIS_TX_TRAINING_STAGE_TIMED_S11:
|
||||
/* A timed period of scrambled ones at 1200bps. */
|
||||
if (!s->caller)
|
||||
{
|
||||
if (s->detected_unscrambled_0011_ending)
|
||||
{
|
||||
/* Continue for a further 600+-10ms */
|
||||
if (++s->tx.training_count >= ms_to_symbols(600))
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting scrambled ones at 2400 (A)\n");
|
||||
s->tx.training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_2400;
|
||||
s->tx.training_count = 0;
|
||||
}
|
||||
}
|
||||
else if (s->detected_scrambled_ones_or_zeros_at_1200bps)
|
||||
if (++s->tx.training_count >= ms_to_symbols(756))
|
||||
{
|
||||
if (s->bit_rate == 2400)
|
||||
{
|
||||
/* Continue for a further 756+-10ms */
|
||||
if (++s->tx.training_count >= ms_to_symbols(756))
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting scrambled ones at 2400 (B)\n");
|
||||
s->tx.training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_2400;
|
||||
s->tx.training_count = 0;
|
||||
}
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting S1111 (C)\n");
|
||||
s->tx.training = V22BIS_TX_TRAINING_STAGE_S1111;
|
||||
s->tx.training_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ finished\n");
|
||||
s->tx.training = V22BIS_TRAINING_STAGE_NORMAL_OPERATION;
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ Tx normal operation (1200)\n");
|
||||
s->tx.training = V22BIS_TX_TRAINING_STAGE_NORMAL_OPERATION;
|
||||
s->tx.training_count = 0;
|
||||
s->tx.current_get_bit = s->get_bit;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s->bit_rate == 2400)
|
||||
{
|
||||
if (++s->tx.training_count >= ms_to_symbols(500))
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting scrambled ones at 2400 (C)\n");
|
||||
s->tx.training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_2400;
|
||||
s->tx.training_count = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (++s->tx.training_count >= ms_to_symbols(756))
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ finished\n");
|
||||
s->tx.training = 0;
|
||||
s->tx.training_count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Fall through */
|
||||
case V22BIS_TX_TRAINING_STAGE_S11:
|
||||
/* Scrambled ones at 1200bps. */
|
||||
bits = scramble(s, 1);
|
||||
bits = (bits << 1) | scramble(s, 1);
|
||||
s->tx.constellation_state = (s->tx.constellation_state + phase_steps[bits]) & 3;
|
||||
z = v22bis_constellation[(s->tx.constellation_state << 2) | 0x01];
|
||||
break;
|
||||
case V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_2400:
|
||||
/* Segment 4: Scrambled ones at 2400bps. */
|
||||
case V22BIS_TX_TRAINING_STAGE_S1111:
|
||||
/* Scrambled ones at 2400bps. We send a timed 200ms burst, and switch to normal operation at 2400bps */
|
||||
bits = scramble(s, 1);
|
||||
bits = (bits << 1) | scramble(s, 1);
|
||||
s->tx.constellation_state = (s->tx.constellation_state + phase_steps[bits]) & 3;
|
||||
bits = scramble(s, 1);
|
||||
bits = (bits << 1) | scramble(s, 1);
|
||||
z = v22bis_constellation[(s->tx.constellation_state << 2) | 0x01];
|
||||
z = v22bis_constellation[(s->tx.constellation_state << 2) | bits];
|
||||
if (++s->tx.training_count >= ms_to_symbols(200))
|
||||
{
|
||||
/* We have completed training. Now handle some real work. */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ finished\n");
|
||||
s->tx.training = 0;
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "+++ Tx normal operation (2400)\n");
|
||||
s->tx.training = V22BIS_TX_TRAINING_STAGE_NORMAL_OPERATION;
|
||||
s->tx.training_count = 0;
|
||||
s->tx.current_get_bit = s->get_bit;
|
||||
}
|
||||
break;
|
||||
case V22BIS_TRAINING_STAGE_PARKED:
|
||||
case V22BIS_TX_TRAINING_STAGE_PARKED:
|
||||
default:
|
||||
z = complex_setf(0.0f, 0.0f);
|
||||
break;
|
||||
|
@ -569,8 +502,26 @@ SPAN_DECLARE(void) v22bis_tx_power(v22bis_state_t *s, float power)
|
|||
{
|
||||
float l;
|
||||
|
||||
l = 1.6f*powf(10.0f, (power - DBM0_MAX_POWER)/20.0f);
|
||||
s->tx.gain = l*32768.0f/(TX_PULSESHAPER_GAIN*3.0f);
|
||||
if (s->tx.guard_phase_rate == dds_phase_ratef(550.0f))
|
||||
{
|
||||
l = 1.6f*powf(10.0f, (power - 1.0f - DBM0_MAX_POWER)/20.0f);
|
||||
s->tx.gain = l*32768.0f/(TX_PULSESHAPER_GAIN*3.0f);
|
||||
l = powf(10.0f, (power - 1.0f - 3.0f - DBM0_MAX_POWER)/20.0f);
|
||||
s->tx.guard_level = l*32768.0f;
|
||||
}
|
||||
else if(s->tx.guard_phase_rate == dds_phase_ratef(1800.0f))
|
||||
{
|
||||
l = 1.6f*powf(10.0f, (power - 1.0f - 1.0f - DBM0_MAX_POWER)/20.0f);
|
||||
s->tx.gain = l*32768.0f/(TX_PULSESHAPER_GAIN*3.0f);
|
||||
l = powf(10.0f, (power - 1.0f - 6.0f - DBM0_MAX_POWER)/20.0f);
|
||||
s->tx.guard_level = l*32768.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
l = 1.6f*powf(10.0f, (power - DBM0_MAX_POWER)/20.0f);
|
||||
s->tx.gain = l*32768.0f/(TX_PULSESHAPER_GAIN*3.0f);
|
||||
s->tx.guard_level = 0;
|
||||
}
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -581,7 +532,10 @@ static int v22bis_tx_restart(v22bis_state_t *s, int bit_rate)
|
|||
s->tx.rrc_filter_step = 0;
|
||||
s->tx.scramble_reg = 0;
|
||||
s->tx.scrambler_pattern_count = 0;
|
||||
s->tx.training = V22BIS_TRAINING_STAGE_INITIAL_SILENCE;
|
||||
if (s->caller)
|
||||
s->tx.training = V22BIS_TX_TRAINING_STAGE_INITIAL_SILENCE;
|
||||
else
|
||||
s->tx.training = V22BIS_TX_TRAINING_STAGE_INITIAL_TIMED_SILENCE;
|
||||
s->tx.training_count = 0;
|
||||
s->tx.carrier_phase = 0;
|
||||
s->tx.guard_phase = 0;
|
||||
|
@ -607,6 +561,13 @@ SPAN_DECLARE(void) v22bis_set_put_bit(v22bis_state_t *s, put_bit_func_t put_bit,
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(void) v22bis_set_modem_status_handler(v22bis_state_t *s, modem_tx_status_func_t handler, void *user_data)
|
||||
{
|
||||
s->status_handler = handler;
|
||||
s->status_user_data = user_data;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(logging_state_t *) v22bis_get_logging_state(v22bis_state_t *s)
|
||||
{
|
||||
return &s->logging;
|
||||
|
@ -653,21 +614,20 @@ SPAN_DECLARE(v22bis_state_t *) v22bis_init(v22bis_state_t *s,
|
|||
else
|
||||
{
|
||||
s->tx.carrier_phase_rate = dds_phase_ratef(2400.0f);
|
||||
if (guard)
|
||||
switch (guard)
|
||||
{
|
||||
if (guard == 1)
|
||||
{
|
||||
s->tx.guard_phase_rate = dds_phase_ratef(550.0f);
|
||||
s->tx.guard_level = 1500.0f;
|
||||
}
|
||||
else
|
||||
{
|
||||
s->tx.guard_phase_rate = dds_phase_ratef(1800.0f);
|
||||
s->tx.guard_level = 1000.0f;
|
||||
}
|
||||
case V22BIS_GUARD_TONE_550HZ:
|
||||
s->tx.guard_phase_rate = dds_phase_ratef(550.0f);
|
||||
break;
|
||||
case V22BIS_GUARD_TONE_1800HZ:
|
||||
s->tx.guard_phase_rate = dds_phase_ratef(1800.0f);
|
||||
break;
|
||||
default:
|
||||
s->tx.guard_phase_rate = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
v22bis_tx_power(s, -10.0f);
|
||||
v22bis_tx_power(s, -14.0f);
|
||||
v22bis_restart(s, s->bit_rate);
|
||||
return s;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#define IAXMODEM_STUFF
|
||||
/*
|
||||
* SpanDSP - a series of DSP components for telephony
|
||||
*
|
||||
|
@ -22,7 +23,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: v27ter_rx.c,v 1.117 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: v27ter_rx.c,v 1.125 2009/04/20 16:36:36 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -74,7 +75,13 @@
|
|||
signal to a static constellation, even though dealing with differences is all
|
||||
that is necessary. */
|
||||
|
||||
/*! The nominal frequency of the carrier, in Hertz */
|
||||
#define CARRIER_NOMINAL_FREQ 1800.0f
|
||||
/*! The nominal baud or symbol rate in 2400bps mode */
|
||||
#define BAUD_RATE_2400 1200
|
||||
/*! The nominal baud or symbol rate in 4800bps mode */
|
||||
#define BAUD_RATE_4800 1600
|
||||
/*! The adaption rate coefficient for the equalizer */
|
||||
#define EQUALIZER_DELTA 0.25f
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
|
@ -85,10 +92,14 @@
|
|||
/* Segments of the training sequence */
|
||||
/* V.27ter defines a long and a short sequence. FAX doesn't use the
|
||||
short sequence, so it is not implemented here. */
|
||||
/*! The length of training segment 3, in symbols */
|
||||
#define V27TER_TRAINING_SEG_3_LEN 50
|
||||
/*! The length of training segment 5, in symbols */
|
||||
#define V27TER_TRAINING_SEG_5_LEN 1074
|
||||
/*! The length of training segment 6, in symbols */
|
||||
#define V27TER_TRAINING_SEG_6_LEN 8
|
||||
|
||||
/*! The length of the equalizer buffer */
|
||||
#define V27TER_EQUALIZER_LEN (V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN)
|
||||
|
||||
enum
|
||||
|
@ -145,7 +156,7 @@ SPAN_DECLARE(float) v27ter_rx_symbol_timing_correction(v27ter_rx_state_t *s)
|
|||
|
||||
SPAN_DECLARE(float) v27ter_rx_signal_power(v27ter_rx_state_t *s)
|
||||
{
|
||||
return power_meter_current_dbm0(&s->power);
|
||||
return power_meter_current_dbm0(&s->power) + 3.98f;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -630,6 +641,7 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
|
|||
s->training_bc ^= descramble(s, 1);
|
||||
descramble(s, 1);
|
||||
descramble(s, 1);
|
||||
s->constellation_state = abab_pos[s->training_bc];
|
||||
s->training_count = 1;
|
||||
s->training_stage = TRAINING_STAGE_TRAIN_ON_ABAB;
|
||||
report_status_change(s, SIG_STATUS_TRAINING_IN_PROGRESS);
|
||||
|
@ -772,7 +784,7 @@ SPAN_DECLARE(int) v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], int len)
|
|||
We need to measure the power with the DC blocked, but not using
|
||||
a slow to respond DC blocker. Use the most elementary HPF. */
|
||||
x = amp[i] >> 1;
|
||||
/* There could be oveflow 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;
|
||||
power = power_meter_update(&(s->power), diff);
|
||||
#if defined(IAXMODEM_STUFF)
|
||||
|
@ -894,7 +906,7 @@ SPAN_DECLARE(int) v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], int len)
|
|||
We need to measure the power with the DC blocked, but not using
|
||||
a slow to respond DC blocker. Use the most elementary HPF. */
|
||||
x = amp[i] >> 1;
|
||||
/* There could be oveflow 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;
|
||||
power = power_meter_update(&(s->power), diff);
|
||||
#if defined(IAXMODEM_STUFF)
|
||||
|
@ -1009,6 +1021,41 @@ SPAN_DECLARE(int) v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], int len)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) v27ter_rx_fillin(v27ter_rx_state_t *s, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* We want to sustain the current state (i.e carrier on<->carrier off), and
|
||||
try to sustain the carrier phase. We should probably push the filters, as well */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Fill-in %d samples\n", len);
|
||||
if (!s->signal_present)
|
||||
return 0;
|
||||
if (s->training_stage == TRAINING_STAGE_PARKED)
|
||||
return 0;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
dds_advance(&s->carrier_phase, s->carrier_phase_rate);
|
||||
#else
|
||||
dds_advancef(&s->carrier_phase, s->carrier_phase_rate);
|
||||
#endif
|
||||
/* Advance the symbol phase the appropriate amount */
|
||||
if (s->bit_rate == 4800)
|
||||
{
|
||||
if ((s->eq_put_step -= RX_PULSESHAPER_4800_COEFF_SETS) <= 0)
|
||||
s->eq_put_step += RX_PULSESHAPER_4800_COEFF_SETS*5/2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((s->eq_put_step -= RX_PULSESHAPER_2400_COEFF_SETS) <= 0)
|
||||
s->eq_put_step += RX_PULSESHAPER_2400_COEFF_SETS*20/(3*2);
|
||||
}
|
||||
/* TODO: Should we rotate any buffers */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(void) v27ter_rx_set_put_bit(v27ter_rx_state_t *s, put_bit_func_t put_bit, void *user_data)
|
||||
{
|
||||
s->put_bit = put_bit;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: v27ter_tx.c,v 1.73 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: v27ter_tx.c,v 1.74 2009/04/12 04:20:01 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -66,17 +66,25 @@
|
|||
#include "v27ter_tx_2400_floating_rrc.h"
|
||||
#endif
|
||||
|
||||
/*! The nominal frequency of the carrier, in Hertz */
|
||||
#define CARRIER_NOMINAL_FREQ 1800.0f
|
||||
|
||||
/* Segments of the training sequence */
|
||||
/* V.27ter defines a long and a short sequence. FAX doesn't use the
|
||||
short sequence, so it is not implemented here. */
|
||||
/*! The start of training segment 1, in symbols */
|
||||
#define V27TER_TRAINING_SEG_1 0
|
||||
/*! The start of training segment 2, in symbols */
|
||||
#define V27TER_TRAINING_SEG_2 (V27TER_TRAINING_SEG_1 + 320)
|
||||
/*! The start of training segment 3, in symbols */
|
||||
#define V27TER_TRAINING_SEG_3 (V27TER_TRAINING_SEG_2 + 32)
|
||||
/*! The start of training segment 4, in symbols */
|
||||
#define V27TER_TRAINING_SEG_4 (V27TER_TRAINING_SEG_3 + 50)
|
||||
/*! The start of training segment 5, in symbols */
|
||||
#define V27TER_TRAINING_SEG_5 (V27TER_TRAINING_SEG_4 + 1074)
|
||||
/*! The end of the training, in symbols */
|
||||
#define V27TER_TRAINING_END (V27TER_TRAINING_SEG_5 + 8)
|
||||
/*! The end of the shutdown sequence, in symbols */
|
||||
#define V27TER_TRAINING_SHUTDOWN_END (V27TER_TRAINING_END + 32)
|
||||
|
||||
static int fake_get_bit(void *user_data)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#define IAXMODEM_STUFF
|
||||
/*
|
||||
* SpanDSP - a series of DSP components for telephony
|
||||
*
|
||||
|
@ -22,7 +23,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: v29rx.c,v 1.154 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: v29rx.c,v 1.163 2009/04/20 16:36:36 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -68,8 +69,11 @@
|
|||
#include "v29rx_floating_rrc.h"
|
||||
#endif
|
||||
|
||||
/*! The nominal frequency of the carrier, in Hertz */
|
||||
#define CARRIER_NOMINAL_FREQ 1700.0f
|
||||
/*! The nominal baud or symbol rate */
|
||||
#define BAUD_RATE 2400
|
||||
/*! The adaption rate coefficient for the equalizer */
|
||||
#define EQUALIZER_DELTA 0.21f
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
|
@ -78,10 +82,14 @@
|
|||
#endif
|
||||
|
||||
/* Segments of the training sequence */
|
||||
/*! The length of training segment 2, in symbols */
|
||||
#define V29_TRAINING_SEG_2_LEN 128
|
||||
/*! The length of training segment 3, in symbols */
|
||||
#define V29_TRAINING_SEG_3_LEN 384
|
||||
/*! The length of training segment 4, in symbols */
|
||||
#define V29_TRAINING_SEG_4_LEN 48
|
||||
|
||||
/*! The length of the equalizer buffer */
|
||||
#define V29_EQUALIZER_LEN (V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN)
|
||||
|
||||
enum
|
||||
|
@ -121,6 +129,8 @@ static const uint8_t space_map_9600[20][20] =
|
|||
};
|
||||
|
||||
/* Coefficients for the band edge symbol timing synchroniser (alpha = 0.99) */
|
||||
/* low_edge = 2.0f*M_PI*(CARRIER_NOMINAL_FREQ - BAUD_RATE/2.0f)/SAMPLE_RATE; */
|
||||
/* high_edge = 2.0f*M_PI*(CARRIER_NOMINAL_FREQ + BAUD_RATE/2.0f)/SAMPLE_RATE; */
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
#define SYNC_LOW_BAND_EDGE_COEFF_0 ((int)(FP_FACTOR* 1.829281f)) /* 2*alpha*cos(low_edge) */
|
||||
#define SYNC_LOW_BAND_EDGE_COEFF_1 ((int)(FP_FACTOR*-0.980100f)) /* -alpha^2 */
|
||||
|
@ -153,7 +163,7 @@ SPAN_DECLARE(float) v29_rx_symbol_timing_correction(v29_rx_state_t *s)
|
|||
|
||||
SPAN_DECLARE(float) v29_rx_signal_power(v29_rx_state_t *s)
|
||||
{
|
||||
return power_meter_current_dbm0(&s->power);
|
||||
return power_meter_current_dbm0(&s->power) + 3.98f;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -492,7 +502,7 @@ static __inline__ void symbol_sync(v29_rx_state_t *s)
|
|||
s->symbol_sync_dc_filter[0] = v;
|
||||
/* A little integration will now filter away much of the noise */
|
||||
s->baud_phase -= p;
|
||||
if (abs(s->baud_phase) > 100*FP_FACTOR)
|
||||
if (abs(s->baud_phase) > 30*FP_FACTOR)
|
||||
{
|
||||
if (s->baud_phase > 0)
|
||||
i = (s->baud_phase > 1000*FP_FACTOR) ? 5 : 1;
|
||||
|
@ -674,6 +684,8 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
|
|||
s->carrier_phase += angle;
|
||||
/* We have just seen the first bit of the scrambled sequence, so skip it. */
|
||||
bit = scrambled_training_bit(s);
|
||||
s->constellation_state = cdcd_pos[s->training_cd + bit];
|
||||
target = &v29_9600_constellation[s->constellation_state];
|
||||
s->training_count = 1;
|
||||
s->training_stage = TRAINING_STAGE_TRAIN_ON_CDCD;
|
||||
report_status_change(s, SIG_STATUS_TRAINING_IN_PROGRESS);
|
||||
|
@ -858,7 +870,7 @@ SPAN_DECLARE(int) v29_rx(v29_rx_state_t *s, const int16_t amp[], int len)
|
|||
We need to measure the power with the DC blocked, but not using
|
||||
a slow to respond DC blocker. Use the most elementary HPF. */
|
||||
x = amp[i] >> 1;
|
||||
/* There could be oveflow 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;
|
||||
power = power_meter_update(&(s->power), diff);
|
||||
#if defined(IAXMODEM_STUFF)
|
||||
|
@ -999,6 +1011,34 @@ SPAN_DECLARE(int) v29_rx(v29_rx_state_t *s, const int16_t amp[], int len)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) v29_rx_fillin(v29_rx_state_t *s, int len)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* We want to sustain the current state (i.e carrier on<->carrier off), and
|
||||
try to sustain the carrier phase. We should probably push the filters, as well */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Fill-in %d samples\n", len);
|
||||
if (!s->signal_present)
|
||||
return 0;
|
||||
if (s->training_stage == TRAINING_STAGE_PARKED)
|
||||
return 0;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
dds_advance(&s->carrier_phase, s->carrier_phase_rate);
|
||||
#else
|
||||
dds_advancef(&s->carrier_phase, s->carrier_phase_rate);
|
||||
#endif
|
||||
/* Advance the symbol phase the appropriate amount */
|
||||
s->eq_put_step -= RX_PULSESHAPER_COEFF_SETS;
|
||||
if (s->eq_put_step <= 0)
|
||||
s->eq_put_step += RX_PULSESHAPER_COEFF_SETS*10/(3*2);
|
||||
/* TODO: Should we rotate any buffers */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(void) v29_rx_set_put_bit(v29_rx_state_t *s, put_bit_func_t put_bit, void *user_data)
|
||||
{
|
||||
s->put_bit = put_bit;
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: v29tx.c,v 1.86 2009/02/10 13:06:47 steveu Exp $
|
||||
* $Id: v29tx.c,v 1.87 2009/04/12 04:20:01 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -65,15 +65,23 @@
|
|||
#include "v29tx_floating_rrc.h"
|
||||
#endif
|
||||
|
||||
/*! The nominal frequency of the carrier, in Hertz */
|
||||
#define CARRIER_NOMINAL_FREQ 1700.0f
|
||||
|
||||
/* Segments of the training sequence */
|
||||
/*! The start of the optional TEP, that may preceed the actual training, in symbols */
|
||||
#define V29_TRAINING_SEG_TEP 0
|
||||
/*! The start of training segment 1, in symbols */
|
||||
#define V29_TRAINING_SEG_1 (V29_TRAINING_SEG_TEP + 480)
|
||||
/*! The start of training segment 2, in symbols */
|
||||
#define V29_TRAINING_SEG_2 (V29_TRAINING_SEG_1 + 48)
|
||||
/*! The start of training segment 3, in symbols */
|
||||
#define V29_TRAINING_SEG_3 (V29_TRAINING_SEG_2 + 128)
|
||||
/*! The start of training segment 4, in symbols */
|
||||
#define V29_TRAINING_SEG_4 (V29_TRAINING_SEG_3 + 384)
|
||||
/*! The end of the training, in symbols */
|
||||
#define V29_TRAINING_END (V29_TRAINING_SEG_4 + 48)
|
||||
/*! The end of the shutdown sequence, in symbols */
|
||||
#define V29_TRAINING_SHUTDOWN_END (V29_TRAINING_END + 32)
|
||||
|
||||
static int fake_get_bit(void *user_data)
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: generate_etsi_300_242_pages.c,v 1.4 2009/03/01 12:39:02 steveu Exp $
|
||||
* $Id: generate_etsi_300_242_pages.c,v 1.5 2009/03/23 14:34:13 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -186,12 +186,6 @@ static void clear_row(uint8_t buf[], int width)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void set_row(uint8_t buf[], int width)
|
||||
{
|
||||
memset(buf, 0xFF, width/8 + 1);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void set_pixel(uint8_t buf[], int row, int pixel)
|
||||
{
|
||||
row--;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
## along with this program; if not, write to the Free Software
|
||||
## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
##
|
||||
## $Id: Makefile.am,v 1.110 2009/02/20 12:34:20 steveu Exp $
|
||||
## $Id: Makefile.am,v 1.112 2009/04/01 13:22:40 steveu Exp $
|
||||
|
||||
AM_CFLAGS = $(COMP_VENDOR_CFLAGS)
|
||||
AM_LDFLAGS = $(COMP_VENDOR_LDFLAGS)
|
||||
|
@ -93,6 +93,7 @@ noinst_PROGRAMS = adsi_tests \
|
|||
tone_generate_tests \
|
||||
tsb85_tests \
|
||||
v17_tests \
|
||||
v18_tests \
|
||||
v22bis_tests \
|
||||
v27ter_tests \
|
||||
v29_tests \
|
||||
|
@ -107,6 +108,7 @@ noinst_PROGRAMS = adsi_tests \
|
|||
|
||||
noinst_HEADERS = echo_monitor.h \
|
||||
fax_tester.h \
|
||||
fax_utils.h \
|
||||
line_model_monitor.h \
|
||||
media_monitor.h \
|
||||
modem_monitor.h
|
||||
|
@ -291,6 +293,9 @@ tsb85_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspan
|
|||
v17_tests_SOURCES = v17_tests.c line_model_monitor.cpp modem_monitor.cpp
|
||||
v17_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp
|
||||
|
||||
v18_tests_SOURCES = v18_tests.c
|
||||
v18_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp
|
||||
|
||||
v22bis_tests_SOURCES = v22bis_tests.c line_model_monitor.cpp modem_monitor.cpp
|
||||
v22bis_tests_LDADD = -L$(top_builddir)/spandsp-sim -lspandsp-sim $(LIBDIR) -lspandsp
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: adsi_tests.c,v 1.48 2008/11/30 10:17:31 steveu Exp $
|
||||
* $Id: adsi_tests.c,v 1.55 2009/04/11 15:16:14 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \page adsi_tests_page ADSI tests
|
||||
|
@ -58,19 +58,38 @@ tests, these tests do not include line modelling.
|
|||
#include "spandsp.h"
|
||||
#include "spandsp-sim.h"
|
||||
|
||||
#define OUT_FILE_NAME "adsi.wav"
|
||||
#define OUTPUT_FILE_NAME "adsi.wav"
|
||||
|
||||
#define BLOCK_LEN 160
|
||||
#define BLOCK_LEN 160
|
||||
|
||||
#define MITEL_DIR "../test-data/mitel/"
|
||||
#define BELLCORE_DIR "../test-data/bellcore/"
|
||||
|
||||
const char *bellcore_files[] =
|
||||
{
|
||||
MITEL_DIR "mitel-cm7291-talkoff.wav",
|
||||
BELLCORE_DIR "tr-tsy-00763-1.wav",
|
||||
BELLCORE_DIR "tr-tsy-00763-2.wav",
|
||||
BELLCORE_DIR "tr-tsy-00763-3.wav",
|
||||
BELLCORE_DIR "tr-tsy-00763-4.wav",
|
||||
BELLCORE_DIR "tr-tsy-00763-5.wav",
|
||||
BELLCORE_DIR "tr-tsy-00763-6.wav",
|
||||
""
|
||||
};
|
||||
|
||||
char *decode_test_file = NULL;
|
||||
|
||||
int errors = 0;
|
||||
int basic_testing = FALSE;
|
||||
|
||||
adsi_rx_state_t *rx_adsi;
|
||||
adsi_tx_state_t *tx_adsi;
|
||||
|
||||
int current_standard = 0;
|
||||
int good_message_received;
|
||||
int log_audio = FALSE;
|
||||
AFfilehandle outhandle = NULL;
|
||||
int short_preamble = FALSE;
|
||||
|
||||
static int adsi_create_message(adsi_tx_state_t *s, uint8_t *msg)
|
||||
{
|
||||
|
@ -453,13 +472,16 @@ static void put_adsi_msg(void *user_data, const uint8_t *msg, int len)
|
|||
}
|
||||
break;
|
||||
case ADSI_STANDARD_TDD:
|
||||
if (len != 59
|
||||
||
|
||||
memcmp(msg, "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG 0123456789#$*()", 59))
|
||||
if (basic_testing)
|
||||
{
|
||||
printf("\n");
|
||||
printf("String error\n");
|
||||
exit(2);
|
||||
if (len != 59
|
||||
||
|
||||
memcmp(msg, "THE QUICK BROWN FOX JUMPS OVER THE LAZY DOG 0123456789#$*()", 59))
|
||||
{
|
||||
printf("\n");
|
||||
printf("String error\n");
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -568,32 +590,175 @@ static void put_adsi_msg(void *user_data, const uint8_t *msg, int len)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
static void tdd_character_set_tests(void)
|
||||
{
|
||||
#if 0
|
||||
char *s;
|
||||
int ch;
|
||||
int xx;
|
||||
int yy;
|
||||
|
||||
/* This part tests internal static routines in the ADSI module. It can
|
||||
only be run with a modified version of the ADSI module, which makes
|
||||
the routines visible. */
|
||||
/* Check the character encode/decode cycle */
|
||||
tx_adsi = adsi_tx_init(NULL, ADSI_STANDARD_TDD);
|
||||
rx_adsi = adsi_rx_init(NULL, ADSI_STANDARD_TDD, put_adsi_msg, NULL);
|
||||
s = "The quick Brown Fox Jumps Over The Lazy dog 0123456789!@#$%^&*()";
|
||||
while ((ch = *s++))
|
||||
{
|
||||
xx = adsi_encode_baudot(tx_adsi, ch);
|
||||
if ((xx & 0x3E0))
|
||||
{
|
||||
yy = adsi_decode_baudot(rx_adsi, (xx >> 5) & 0x1F);
|
||||
if (yy)
|
||||
printf("%c", yy);
|
||||
}
|
||||
yy = adsi_decode_baudot(rx_adsi, xx & 0x1F);
|
||||
if (yy)
|
||||
printf("%c", yy);
|
||||
}
|
||||
adsi_tx_free(tx_adsi);
|
||||
adsi_rx_free(rx_adsi);
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void basic_tests(int standard)
|
||||
{
|
||||
int16_t amp[BLOCK_LEN];
|
||||
uint8_t adsi_msg[256 + 42];
|
||||
int adsi_msg_len;
|
||||
AFfilehandle inhandle;
|
||||
AFfilehandle outhandle;
|
||||
int outframes;
|
||||
int len;
|
||||
int i;
|
||||
int adsi_msg_len;
|
||||
int push;
|
||||
int log_audio;
|
||||
int short_preamble;
|
||||
int i;
|
||||
|
||||
basic_testing = TRUE;
|
||||
printf("Testing %s\n", adsi_standard_to_str(standard));
|
||||
tx_adsi = adsi_tx_init(NULL, standard);
|
||||
if (short_preamble)
|
||||
adsi_tx_set_preamble(tx_adsi, 50, 20, 5, -1);
|
||||
rx_adsi = adsi_rx_init(NULL, standard, put_adsi_msg, NULL);
|
||||
|
||||
/* Fake an OK condition for the first message test */
|
||||
good_message_received = TRUE;
|
||||
push = 0;
|
||||
for (i = 0; i < 100000; i++)
|
||||
{
|
||||
if (push == 0)
|
||||
{
|
||||
if ((len = adsi_tx(tx_adsi, amp, BLOCK_LEN)) == 0)
|
||||
push = 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = 0;
|
||||
/* Push a little silence through, to flush things out */
|
||||
if (--push == 0)
|
||||
{
|
||||
if (!good_message_received)
|
||||
{
|
||||
printf("No message received %s (%d)\n", adsi_standard_to_str(standard), i);
|
||||
exit(2);
|
||||
}
|
||||
good_message_received = FALSE;
|
||||
adsi_msg_len = adsi_create_message(tx_adsi, adsi_msg);
|
||||
adsi_msg_len = adsi_tx_put_message(tx_adsi, adsi_msg, adsi_msg_len);
|
||||
}
|
||||
}
|
||||
if (len < BLOCK_LEN)
|
||||
{
|
||||
memset(&[len], 0, sizeof(int16_t)*(BLOCK_LEN - len));
|
||||
len = BLOCK_LEN;
|
||||
}
|
||||
if (log_audio)
|
||||
{
|
||||
outframes = afWriteFrames(outhandle,
|
||||
AF_DEFAULT_TRACK,
|
||||
amp,
|
||||
len);
|
||||
if (outframes != len)
|
||||
{
|
||||
fprintf(stderr, " Error writing wave file\n");
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
adsi_rx(rx_adsi, amp, len);
|
||||
}
|
||||
adsi_rx_free(rx_adsi);
|
||||
adsi_tx_free(tx_adsi);
|
||||
basic_testing = FALSE;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void mitel_cm7291_side_2_and_bellcore_tests(int standard)
|
||||
{
|
||||
int j;
|
||||
int16_t amp[BLOCK_LEN];
|
||||
AFfilehandle inhandle;
|
||||
int frames;
|
||||
|
||||
/* The remainder of the Mitel tape is the talk-off test */
|
||||
/* Here we use the Bellcore test tapes (much tougher), in six
|
||||
wave files - 1 from each side of the original 3 cassette tapes */
|
||||
printf("Talk-off tests for %s\n", adsi_standard_to_str(standard));
|
||||
rx_adsi = adsi_rx_init(NULL, standard, put_adsi_msg, NULL);
|
||||
for (j = 0; bellcore_files[j][0]; j++)
|
||||
{
|
||||
printf("Testing with %s\n", bellcore_files[j]);
|
||||
if ((inhandle = afOpenFile_telephony_read(bellcore_files[j], 1)) == AF_NULL_FILEHANDLE)
|
||||
{
|
||||
printf(" Cannot open speech file '%s'\n", bellcore_files[j]);
|
||||
exit(2);
|
||||
}
|
||||
while ((frames = afReadFrames(inhandle, AF_DEFAULT_TRACK, amp, BLOCK_LEN)))
|
||||
{
|
||||
adsi_rx(rx_adsi, amp, frames);
|
||||
}
|
||||
if (afCloseFile(inhandle) != 0)
|
||||
{
|
||||
printf(" Cannot close speech file '%s'\n", bellcore_files[j]);
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
adsi_rx_free(rx_adsi);
|
||||
if (j > 470)
|
||||
{
|
||||
printf(" Failed\n");
|
||||
exit(2);
|
||||
}
|
||||
printf(" Passed\n");
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int16_t amp[BLOCK_LEN];
|
||||
AFfilehandle inhandle;
|
||||
int len;
|
||||
int test_standard;
|
||||
int first_standard;
|
||||
int last_standard;
|
||||
int opt;
|
||||
int enable_basic_tests;
|
||||
int enable_talkoff_tests;
|
||||
|
||||
log_audio = FALSE;
|
||||
decode_test_file = NULL;
|
||||
test_standard = -1;
|
||||
short_preamble = FALSE;
|
||||
while ((opt = getopt(argc, argv, "d:lps:")) != -1)
|
||||
enable_basic_tests = TRUE;
|
||||
enable_talkoff_tests = FALSE;
|
||||
while ((opt = getopt(argc, argv, "bd:lps:t")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
case 'b':
|
||||
enable_basic_tests = TRUE;
|
||||
enable_talkoff_tests = FALSE;
|
||||
break;
|
||||
case 'd':
|
||||
decode_test_file = optarg;
|
||||
break;
|
||||
|
@ -619,6 +784,10 @@ int main(int argc, char *argv[])
|
|||
else
|
||||
test_standard = atoi(optarg);
|
||||
break;
|
||||
case 't':
|
||||
enable_basic_tests = FALSE;
|
||||
enable_talkoff_tests = TRUE;
|
||||
break;
|
||||
default:
|
||||
//usage();
|
||||
exit(2);
|
||||
|
@ -627,32 +796,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
outhandle = AF_NULL_FILEHANDLE;
|
||||
|
||||
#if 0
|
||||
/* This part tests internal static routines in the ADSI module. It can
|
||||
only be run with a modified version of the ADSI module, which makes
|
||||
the routines visible. */
|
||||
/* Check the character encode/decode cycle */
|
||||
current_standard = ADSI_STANDARD_TDD;
|
||||
tx_adsi = adsi_tx_init(NULL, ADSI_STANDARD_TDD);
|
||||
rx_adsi = adsi_rx_init(NULL, ADSI_STANDARD_TDD, put_adsi_msg, NULL);
|
||||
s = "The quick Brown Fox Jumps Over The Lazy dog 0123456789!@#$%^&*()";
|
||||
while ((ch = *s++))
|
||||
{
|
||||
xx = adsi_encode_baudot(tx_adsi, ch);
|
||||
if ((xx & 0x3E0))
|
||||
{
|
||||
yy = adsi_decode_baudot(rx_adsi, (xx >> 5) & 0x1F);
|
||||
if (yy)
|
||||
printf("%c", yy);
|
||||
}
|
||||
yy = adsi_decode_baudot(rx_adsi, xx & 0x1F);
|
||||
if (yy)
|
||||
printf("%c", yy);
|
||||
}
|
||||
adsi_tx_free(tx_adsi);
|
||||
adsi_rx_free(rx_adsi);
|
||||
printf("\n");
|
||||
#endif
|
||||
tdd_character_set_tests();
|
||||
|
||||
if (decode_test_file)
|
||||
{
|
||||
|
@ -693,9 +837,9 @@ int main(int argc, char *argv[])
|
|||
{
|
||||
if (log_audio)
|
||||
{
|
||||
if ((outhandle = afOpenFile_telephony_write(OUT_FILE_NAME, 1)) == AF_NULL_FILEHANDLE)
|
||||
if ((outhandle = afOpenFile_telephony_write(OUTPUT_FILE_NAME, 1)) == AF_NULL_FILEHANDLE)
|
||||
{
|
||||
fprintf(stderr, " Cannot create wave file '%s'\n", OUT_FILE_NAME);
|
||||
fprintf(stderr, " Cannot create wave file '%s'\n", OUTPUT_FILE_NAME);
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
|
@ -713,71 +857,22 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
for (current_standard = first_standard; current_standard <= last_standard; current_standard++)
|
||||
{
|
||||
printf("Testing %s\n", adsi_standard_to_str(current_standard));
|
||||
tx_adsi = adsi_tx_init(NULL, current_standard);
|
||||
if (short_preamble)
|
||||
adsi_tx_set_preamble(tx_adsi, 50, 20, 5, -1);
|
||||
rx_adsi = adsi_rx_init(NULL, current_standard, put_adsi_msg, NULL);
|
||||
|
||||
/* Fake an OK condition for the first message test */
|
||||
good_message_received = TRUE;
|
||||
push = 0;
|
||||
for (i = 0; i < 100000; i++)
|
||||
{
|
||||
if (push == 0)
|
||||
{
|
||||
if ((len = adsi_tx(tx_adsi, amp, BLOCK_LEN)) == 0)
|
||||
push = 10;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = 0;
|
||||
/* Push a little silence through, to flush things out */
|
||||
if (--push == 0)
|
||||
{
|
||||
if (!good_message_received)
|
||||
{
|
||||
printf("No message received %s (%d)\n", adsi_standard_to_str(current_standard), i);
|
||||
exit(2);
|
||||
}
|
||||
good_message_received = FALSE;
|
||||
adsi_msg_len = adsi_create_message(tx_adsi, adsi_msg);
|
||||
adsi_msg_len = adsi_tx_put_message(tx_adsi, adsi_msg, adsi_msg_len);
|
||||
}
|
||||
}
|
||||
if (len < BLOCK_LEN)
|
||||
{
|
||||
memset(&[len], 0, sizeof(int16_t)*(BLOCK_LEN - len));
|
||||
len = BLOCK_LEN;
|
||||
}
|
||||
if (log_audio)
|
||||
{
|
||||
outframes = afWriteFrames(outhandle,
|
||||
AF_DEFAULT_TRACK,
|
||||
amp,
|
||||
len);
|
||||
if (outframes != len)
|
||||
{
|
||||
fprintf(stderr, " Error writing wave file\n");
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
adsi_rx(rx_adsi, amp, len);
|
||||
}
|
||||
adsi_rx_free(rx_adsi);
|
||||
adsi_tx_free(tx_adsi);
|
||||
if (enable_basic_tests)
|
||||
basic_tests(current_standard);
|
||||
if (enable_talkoff_tests)
|
||||
mitel_cm7291_side_2_and_bellcore_tests(current_standard);
|
||||
}
|
||||
if (log_audio)
|
||||
{
|
||||
if (afCloseFile(outhandle) != 0)
|
||||
{
|
||||
fprintf(stderr, " Cannot close wave file '%s'\n", OUT_FILE_NAME);
|
||||
fprintf(stderr, " Cannot close wave file '%s'\n", OUTPUT_FILE_NAME);
|
||||
exit(2);
|
||||
}
|
||||
}
|
||||
printf("Tests passed.\n");
|
||||
}
|
||||
|
||||
printf("Tests passed.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: bell_mf_rx_tests.c,v 1.14 2008/11/30 10:17:31 steveu Exp $
|
||||
* $Id: bell_mf_rx_tests.c,v 1.15 2009/04/11 18:11:19 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -79,6 +79,9 @@ a fair test of performance in a real PSTN channel.
|
|||
#define MF_PAUSE (68*8)
|
||||
#define MF_CYCLE (MF_DURATION + MF_PAUSE)
|
||||
|
||||
/*!
|
||||
MF tone descriptor for tests.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
float f1; /* First freq */
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: bert_tests.c,v 1.26 2008/11/30 12:38:27 steveu Exp $
|
||||
* $Id: bert_tests.c,v 1.27 2009/04/14 16:04:54 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -212,7 +212,7 @@ int main(int argc, char *argv[])
|
|||
zeros++;
|
||||
}
|
||||
bert_put_bit(&rx_bert, bit);
|
||||
test[tx_bert.tx_reg]++;
|
||||
test[tx_bert.tx.reg]++;
|
||||
}
|
||||
failed = FALSE;
|
||||
if (test[0] != 0)
|
||||
|
@ -256,7 +256,7 @@ int main(int argc, char *argv[])
|
|||
zeros++;
|
||||
}
|
||||
bert_put_bit(&rx_bert, bit);
|
||||
test[tx_bert.tx_reg]++;
|
||||
test[tx_bert.tx.reg]++;
|
||||
}
|
||||
failed = FALSE;
|
||||
if (test[0] != 0)
|
||||
|
@ -300,7 +300,7 @@ int main(int argc, char *argv[])
|
|||
zeros++;
|
||||
}
|
||||
bert_put_bit(&rx_bert, bit);
|
||||
test[tx_bert.tx_reg]++;
|
||||
test[tx_bert.tx.reg]++;
|
||||
}
|
||||
failed = FALSE;
|
||||
if (test[0] != 0)
|
||||
|
@ -344,7 +344,7 @@ int main(int argc, char *argv[])
|
|||
zeros++;
|
||||
}
|
||||
bert_put_bit(&rx_bert, bit);
|
||||
test[tx_bert.tx_reg]++;
|
||||
test[tx_bert.tx.reg]++;
|
||||
}
|
||||
failed = FALSE;
|
||||
if (test[0] != 0)
|
||||
|
@ -385,7 +385,7 @@ int main(int argc, char *argv[])
|
|||
zeros++;
|
||||
}
|
||||
bert_put_bit(&rx_bert, bit);
|
||||
test[tx_bert.tx_reg]++;
|
||||
test[tx_bert.tx.reg]++;
|
||||
}
|
||||
failed = FALSE;
|
||||
if (test[0] != 0)
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* SpanDSP - a series of DSP components for telephony
|
||||
*
|
||||
* fax_utils.h
|
||||
*
|
||||
* Written by Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* Copyright (C) 2009 Steve Underwood
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: fax_utils.h,v 1.1 2009/02/20 12:34:20 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
||||
#if !defined(_SPANDSP_FAX_UTILS_H_)
|
||||
#define _SPANDSP_FAX_UTILS_H_
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
void log_tx_parameters(t30_state_t *s, const char *tag);
|
||||
|
||||
void log_rx_parameters(t30_state_t *s, const char *tag);
|
||||
|
||||
void log_transfer_statistics(t30_state_t *s, const char *tag);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/*- End of file ------------------------------------------------------------*/
|
|
@ -22,7 +22,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: fsk_tests.c,v 1.55 2009/02/12 14:21:16 steveu Exp $
|
||||
* $Id: fsk_tests.c,v 1.56 2009/04/14 16:04:54 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \page fsk_tests_page FSK modem tests
|
||||
|
@ -392,7 +392,7 @@ int main(int argc, char *argv[])
|
|||
bert_set_report(&caller_bert, 100000, reporter, (void *) (intptr_t) 1);
|
||||
bert_init(&answerer_bert, bits_per_test, BERT_PATTERN_ITU_O152_11, test_bps, 20);
|
||||
bert_set_report(&answerer_bert, 100000, reporter, (void *) (intptr_t) 2);
|
||||
if ((model = both_ways_line_model_init(line_model_no, (float) noise_level, line_model_no, noise_level, channel_codec, rbs_pattern)) == NULL)
|
||||
if ((model = both_ways_line_model_init(line_model_no, (float) noise_level, line_model_no, (float) noise_level, channel_codec, rbs_pattern)) == NULL)
|
||||
{
|
||||
fprintf(stderr, " Failed to create line model\n");
|
||||
exit(2);
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: queue_tests.c,v 1.12 2008/11/30 13:08:42 steveu Exp $
|
||||
* $Id: queue_tests.c,v 1.13 2009/04/11 17:43:04 steveu Exp $
|
||||
*/
|
||||
|
||||
/* THIS IS A WORK IN PROGRESS. IT IS NOT FINISHED. */
|
||||
|
@ -65,7 +65,7 @@ int total_out;
|
|||
static void tests_failed(void)
|
||||
{
|
||||
printf("Tests failed\n");
|
||||
tests_failed();
|
||||
exit(2);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -309,7 +309,7 @@ static void check_contents(int total_in, int total_out)
|
|||
static int monitored_queue_write(const uint8_t buf[], int len)
|
||||
{
|
||||
int lenx;
|
||||
|
||||
|
||||
lenx = queue_write(queue, buf, len);
|
||||
if (lenx >= 0)
|
||||
total_in += lenx;
|
||||
|
@ -321,7 +321,7 @@ static int monitored_queue_write(const uint8_t buf[], int len)
|
|||
static int monitored_queue_write_byte(const uint8_t buf)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
||||
if ((res = queue_write_byte(queue, buf)) >= 0)
|
||||
total_in++;
|
||||
check_contents(total_in, total_out);
|
||||
|
@ -332,7 +332,7 @@ static int monitored_queue_write_byte(const uint8_t buf)
|
|||
static int monitored_queue_read(uint8_t buf[], int len)
|
||||
{
|
||||
int lenx;
|
||||
|
||||
|
||||
lenx = queue_read(queue, buf, len);
|
||||
if (lenx >= 0)
|
||||
total_out += lenx;
|
||||
|
@ -344,7 +344,7 @@ static int monitored_queue_read(uint8_t buf[], int len)
|
|||
static int monitored_queue_read_byte(void)
|
||||
{
|
||||
int res;
|
||||
|
||||
|
||||
if ((res = queue_read_byte(queue)) >= 0)
|
||||
total_out++;
|
||||
check_contents(total_in, total_out);
|
||||
|
@ -357,7 +357,7 @@ static void functional_stream_tests(void)
|
|||
uint8_t buf[MSG_LEN];
|
||||
int i;
|
||||
int res;
|
||||
|
||||
|
||||
total_in = 0;
|
||||
total_out = 0;
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: r2_mf_rx_tests.c,v 1.12 2008/11/30 10:17:31 steveu Exp $
|
||||
* $Id: r2_mf_rx_tests.c,v 1.13 2009/04/11 18:11:19 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
|
@ -87,6 +87,9 @@ a fair test of performance in a real PSTN channel.
|
|||
#define MF_PAUSE (68*8)
|
||||
#define MF_CYCLE (MF_DURATION + MF_PAUSE)
|
||||
|
||||
/*!
|
||||
MF tone generator descriptor for tests.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
float f1; /* First freq */
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
# License along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#
|
||||
# $Id: regression_tests.sh,v 1.55 2009/02/20 14:04:40 steveu Exp $
|
||||
# $Id: regression_tests.sh,v 1.56 2009/04/02 13:43:49 steveu Exp $
|
||||
#
|
||||
|
||||
ITUTESTS_TIF=../test-data/itu/fax/itutests.tif
|
||||
|
@ -800,6 +800,15 @@ then
|
|||
fi
|
||||
echo v8_tests completed OK
|
||||
|
||||
./v18_tests >$STDOUT_DEST 2>$STDERR_DEST
|
||||
RETVAL=$?
|
||||
if [ $RETVAL != 0 ]
|
||||
then
|
||||
echo v18_tests failed!
|
||||
exit $RETVAL
|
||||
fi
|
||||
echo v18_tests completed OK
|
||||
|
||||
./vector_float_tests >$STDOUT_DEST 2>$STDERR_DEST
|
||||
RETVAL=$?
|
||||
if [ $RETVAL != 0 ]
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: v17_tests.c,v 1.100 2009/02/12 14:21:16 steveu Exp $
|
||||
* $Id: v17_tests.c,v 1.101 2009/03/15 09:09:21 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \page v17_tests_page V.17 modem tests
|
||||
|
@ -189,7 +189,7 @@ static void qam_report(void *user_data, const complexf_t *constel, const complex
|
|||
fpower = (constel->re - target->re)*(constel->re - target->re)
|
||||
+ (constel->im - target->im)*(constel->im - target->im);
|
||||
smooth_power = 0.95f*smooth_power + 0.05f*fpower;
|
||||
printf("%8d [%8.4f, %8.4f] [%8.4f, %8.4f] %2x %8.4f %8.4f %9.4f %7.3f %7.2f\n",
|
||||
printf("%8d [%8.4f, %8.4f] [%8.4f, %8.4f] %2x %8.4f %8.4f %9.4f %7.3f %7.4f\n",
|
||||
symbol_no,
|
||||
constel->re,
|
||||
constel->im,
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue