mirror of
https://github.com/signalwire/freeswitch.git
synced 2026-10-15 07:44:13 +00:00
update spandsp to use newest snapshot http://www.soft-switch.org/downloads/snapshots/spandsp/spandsp-20080910.tar.gz
git-svn-id: http://svn.freeswitch.org/svn/freeswitch/trunk@9493 d0543943-73ff-0310-b7d9-9358b9ac24b2
This commit is contained in:
1 parent
bc5cf34915
commit
ea964d8fe6
79 files changed
+2804
-1642
No files matched your search
@@ -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.100 2008/08/14 14:06:05 steveu Exp $
|
||||
## $Id: Makefile.am,v 1.101 2008/09/08 12:45:02 steveu Exp $
|
||||
|
||||
AM_CFLAGS = $(COMP_VENDOR_CFLAGS)
|
||||
AM_LDFLAGS = $(COMP_VENDOR_LDFLAGS)
|
||||
@@ -120,6 +120,7 @@ nobase_include_HEADERS = spandsp/adsi.h \
|
||||
spandsp/complex.h \
|
||||
spandsp/complex_filters.h \
|
||||
spandsp/complex_vector_float.h \
|
||||
spandsp/complex_vector_int.h \
|
||||
spandsp/dc_restore.h \
|
||||
spandsp/dds.h \
|
||||
spandsp/dtmf.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.59 2008/07/02 14:48:25 steveu Exp $
|
||||
* $Id: adsi.c,v 1.60 2008/09/07 12:45:16 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -134,7 +134,7 @@ static int adsi_tx_get_bit(void *user_data)
|
||||
}
|
||||
else
|
||||
{
|
||||
bit = PUTBIT_END_OF_DATA;
|
||||
bit = SIG_STATUS_END_OF_DATA;
|
||||
if (s->tx_signal_on)
|
||||
{
|
||||
/* The FSK should now be switched off. */
|
||||
@@ -176,7 +176,7 @@ static void adsi_rx_put_bit(void *user_data, int bit)
|
||||
/* Special conditions */
|
||||
switch (bit)
|
||||
{
|
||||
case PUTBIT_CARRIER_UP:
|
||||
case SIG_STATUS_CARRIER_UP:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Carrier up.\n");
|
||||
s->consecutive_ones = 0;
|
||||
s->bit_pos = 0;
|
||||
@@ -184,7 +184,7 @@ static void adsi_rx_put_bit(void *user_data, int bit)
|
||||
s->msg_len = 0;
|
||||
s->baudot_shift = 0;
|
||||
break;
|
||||
case PUTBIT_CARRIER_DOWN:
|
||||
case SIG_STATUS_CARRIER_DOWN:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Carrier down.\n");
|
||||
break;
|
||||
default:
|
||||
@@ -297,18 +297,17 @@ static void adsi_tdd_put_async_byte(void *user_data, int byte)
|
||||
if (byte < 0)
|
||||
{
|
||||
/* Special conditions */
|
||||
printf("Status is %s (%d)\n", signal_status_to_str(byte), byte);
|
||||
switch (byte)
|
||||
{
|
||||
case PUTBIT_CARRIER_UP:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Carrier up.\n");
|
||||
case SIG_STATUS_CARRIER_UP:
|
||||
s->consecutive_ones = 0;
|
||||
s->bit_pos = 0;
|
||||
s->in_progress = 0;
|
||||
s->msg_len = 0;
|
||||
s->baudot_shift = 0;
|
||||
break;
|
||||
case PUTBIT_CARRIER_DOWN:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Carrier down.\n");
|
||||
case SIG_STATUS_CARRIER_DOWN:
|
||||
if (s->msg_len > 0)
|
||||
{
|
||||
/* Whatever we have to date constitutes the message */
|
||||
|
||||
@@ -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: async.c,v 1.11 2008/05/13 13:17:21 steveu Exp $
|
||||
* $Id: async.c,v 1.13 2008/09/07 12:45:16 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -39,6 +39,37 @@
|
||||
#include "spandsp/telephony.h"
|
||||
#include "spandsp/async.h"
|
||||
|
||||
const char *signal_status_to_str(int status)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case SIG_STATUS_CARRIER_DOWN:
|
||||
return "Carrier down";
|
||||
case SIG_STATUS_CARRIER_UP:
|
||||
return "Carrier up";
|
||||
case SIG_STATUS_TRAINING_IN_PROGRESS:
|
||||
return "Training in progress";
|
||||
case SIG_STATUS_TRAINING_SUCCEEDED:
|
||||
return "Training succeeded";
|
||||
case SIG_STATUS_TRAINING_FAILED:
|
||||
return "Training failed";
|
||||
case SIG_STATUS_FRAMING_OK:
|
||||
return "Framing OK";
|
||||
case SIG_STATUS_END_OF_DATA:
|
||||
return "End of data";
|
||||
case SIG_STATUS_ABORT:
|
||||
return "Abort";
|
||||
case SIG_STATUS_BREAK:
|
||||
return "Break";
|
||||
case SIG_STATUS_SHUTDOWN_COMPLETE:
|
||||
return "Shutdown complete";
|
||||
case SIG_STATUS_OCTET_REPORT:
|
||||
return "Octet report";
|
||||
}
|
||||
return "???";
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
async_rx_state_t *async_rx_init(async_rx_state_t *s,
|
||||
int data_bits,
|
||||
int parity,
|
||||
@@ -80,12 +111,12 @@ void async_rx_put_bit(void *user_data, int bit)
|
||||
/* Special conditions */
|
||||
switch (bit)
|
||||
{
|
||||
case PUTBIT_CARRIER_UP:
|
||||
case PUTBIT_CARRIER_DOWN:
|
||||
case PUTBIT_TRAINING_IN_PROGRESS:
|
||||
case PUTBIT_TRAINING_SUCCEEDED:
|
||||
case PUTBIT_TRAINING_FAILED:
|
||||
case PUTBIT_END_OF_DATA:
|
||||
case SIG_STATUS_CARRIER_UP:
|
||||
case SIG_STATUS_CARRIER_DOWN:
|
||||
case SIG_STATUS_TRAINING_IN_PROGRESS:
|
||||
case SIG_STATUS_TRAINING_SUCCEEDED:
|
||||
case SIG_STATUS_TRAINING_FAILED:
|
||||
case SIG_STATUS_END_OF_DATA:
|
||||
s->put_byte(s->user_data, bit);
|
||||
s->bitpos = 0;
|
||||
s->byte_in_progress = 0;
|
||||
@@ -194,7 +225,7 @@ int async_tx_get_bit(void *user_data)
|
||||
if ((s->byte_in_progress = s->get_byte(s->user_data)) < 0)
|
||||
{
|
||||
/* No more data */
|
||||
bit = PUTBIT_END_OF_DATA;
|
||||
bit = SIG_STATUS_END_OF_DATA;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
+3
-23
@@ -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.27 2008/05/13 13:17:22 steveu Exp $
|
||||
* $Id: bert.c,v 1.28 2008/09/07 12:45:16 steveu Exp $
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H)
|
||||
@@ -78,7 +78,7 @@ int bert_get_bit(bert_state_t *s)
|
||||
int bit;
|
||||
|
||||
if (s->limit && s->tx_bits >= s->limit)
|
||||
return PUTBIT_END_OF_DATA;
|
||||
return SIG_STATUS_END_OF_DATA;
|
||||
bit = 0;
|
||||
switch (s->pattern_class)
|
||||
{
|
||||
@@ -185,27 +185,7 @@ void bert_put_bit(bert_state_t *s, int bit)
|
||||
if (bit < 0)
|
||||
{
|
||||
/* Special conditions */
|
||||
switch (bit)
|
||||
{
|
||||
case PUTBIT_TRAINING_IN_PROGRESS:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Training in progress\n");
|
||||
break;
|
||||
case PUTBIT_TRAINING_FAILED:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed\n");
|
||||
break;
|
||||
case PUTBIT_TRAINING_SUCCEEDED:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Training succeeded\n");
|
||||
break;
|
||||
case PUTBIT_CARRIER_UP:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Carrier up\n");
|
||||
break;
|
||||
case PUTBIT_CARRIER_DOWN:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Carrier down\n");
|
||||
break;
|
||||
default:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Eh!\n");
|
||||
break;
|
||||
}
|
||||
printf("Status is %s (%d)\n", signal_status_to_str(bit), bit);
|
||||
return;
|
||||
}
|
||||
bit = (bit & 1) ^ s->invert;
|
||||
|
||||
@@ -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: dds_int.c,v 1.9 2008/07/02 14:48:25 steveu Exp $
|
||||
* $Id: dds_int.c,v 1.10 2008/09/01 16:07:33 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -288,4 +288,58 @@ complexi_t dds_complexi_mod(uint32_t *phase_acc, int32_t phase_rate, int scale,
|
||||
return amp;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
complexi16_t dds_lookup_complexi16(uint32_t phase)
|
||||
{
|
||||
return complex_seti16(dds_lookup(phase + (1 << 30)), dds_lookup(phase));
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
complexi16_t dds_complexi16(uint32_t *phase_acc, int32_t phase_rate)
|
||||
{
|
||||
complexi16_t amp;
|
||||
|
||||
amp = complex_seti16(dds_lookup(*phase_acc + (1 << 30)), dds_lookup(*phase_acc));
|
||||
*phase_acc += phase_rate;
|
||||
return amp;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
complexi16_t dds_complexi16_mod(uint32_t *phase_acc, int32_t phase_rate, int scale, int32_t phase)
|
||||
{
|
||||
complexi16_t amp;
|
||||
|
||||
amp = complex_seti16((dds_lookup(*phase_acc + phase + (1 << 30))*scale) >> 15,
|
||||
(dds_lookup(*phase_acc + phase)*scale) >> 15);
|
||||
*phase_acc += phase_rate;
|
||||
return amp;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
complexi32_t dds_lookup_complexi32(uint32_t phase)
|
||||
{
|
||||
return complex_seti32(dds_lookup(phase + (1 << 30)), dds_lookup(phase));
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
complexi32_t dds_complexi32(uint32_t *phase_acc, int32_t phase_rate)
|
||||
{
|
||||
complexi32_t amp;
|
||||
|
||||
amp = complex_seti32(dds_lookup(*phase_acc + (1 << 30)), dds_lookup(*phase_acc));
|
||||
*phase_acc += phase_rate;
|
||||
return amp;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
complexi32_t dds_complexi32_mod(uint32_t *phase_acc, int32_t phase_rate, int scale, int32_t phase)
|
||||
{
|
||||
complexi32_t amp;
|
||||
|
||||
amp = complex_seti32((dds_lookup(*phase_acc + phase + (1 << 30))*scale) >> 15,
|
||||
(dds_lookup(*phase_acc + phase)*scale) >> 15);
|
||||
*phase_acc += phase_rate;
|
||||
return amp;
|
||||
}
|
||||
/*- 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: fsk.c,v 1.44 2008/07/16 17:01:49 steveu Exp $
|
||||
* $Id: fsk.c,v 1.46 2008/09/07 12:45:16 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -163,12 +163,12 @@ int fsk_tx(fsk_tx_state_t *s, int16_t *amp, int len)
|
||||
if ((s->baud_frac += s->baud_inc) >= SAMPLE_RATE*100)
|
||||
{
|
||||
s->baud_frac -= SAMPLE_RATE*100;
|
||||
if ((bit = s->get_bit(s->get_bit_user_data)) == PUTBIT_END_OF_DATA)
|
||||
if ((bit = s->get_bit(s->get_bit_user_data)) == SIG_STATUS_END_OF_DATA)
|
||||
{
|
||||
if (s->status_handler)
|
||||
s->status_handler(s->status_user_data, MODEM_TX_STATUS_DATA_EXHAUSTED);
|
||||
s->status_handler(s->status_user_data, SIG_STATUS_END_OF_DATA);
|
||||
if (s->status_handler)
|
||||
s->status_handler(s->status_user_data, MODEM_TX_STATUS_SHUTDOWN_COMPLETE);
|
||||
s->status_handler(s->status_user_data, SIG_STATUS_SHUTDOWN_COMPLETE);
|
||||
s->shutdown = TRUE;
|
||||
break;
|
||||
}
|
||||
@@ -329,7 +329,7 @@ int fsk_rx(fsk_rx_state_t *s, const int16_t *amp, int len)
|
||||
{
|
||||
/* Count down a short delay, to ensure we push the last
|
||||
few bits through the filters before stopping. */
|
||||
report_status_change(s, PUTBIT_CARRIER_DOWN);
|
||||
report_status_change(s, SIG_STATUS_CARRIER_DOWN);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -340,7 +340,7 @@ int fsk_rx(fsk_rx_state_t *s, const int16_t *amp, int len)
|
||||
if (power < s->carrier_on_power)
|
||||
continue;
|
||||
s->signal_present = 1;
|
||||
report_status_change(s, PUTBIT_CARRIER_UP);
|
||||
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
|
||||
|
||||
@@ -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_lpc.c,v 1.20 2008/07/02 14:48:25 steveu Exp $
|
||||
* $Id: gsm0610_lpc.c,v 1.21 2008/09/04 14:40:05 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <math.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
|
||||
#include "spandsp/telephony.h"
|
||||
#include "spandsp/bitstream.h"
|
||||
|
||||
+13
-13
@@ -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: hdlc.c,v 1.60 2008/05/13 13:17:22 steveu Exp $
|
||||
* $Id: hdlc.c,v 1.61 2008/09/07 12:45:16 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -47,8 +47,8 @@ static void rx_special_condition(hdlc_rx_state_t *s, int condition)
|
||||
/* Special conditions */
|
||||
switch (condition)
|
||||
{
|
||||
case PUTBIT_CARRIER_UP:
|
||||
case PUTBIT_TRAINING_SUCCEEDED:
|
||||
case SIG_STATUS_CARRIER_UP:
|
||||
case SIG_STATUS_TRAINING_SUCCEEDED:
|
||||
/* Reset the HDLC receiver. */
|
||||
s->raw_bit_stream = 0;
|
||||
s->len = 0;
|
||||
@@ -56,10 +56,10 @@ static void rx_special_condition(hdlc_rx_state_t *s, int condition)
|
||||
s->flags_seen = 0;
|
||||
s->framing_ok_announced = FALSE;
|
||||
/* Fall through */
|
||||
case PUTBIT_TRAINING_IN_PROGRESS:
|
||||
case PUTBIT_TRAINING_FAILED:
|
||||
case PUTBIT_CARRIER_DOWN:
|
||||
case PUTBIT_END_OF_DATA:
|
||||
case SIG_STATUS_TRAINING_IN_PROGRESS:
|
||||
case SIG_STATUS_TRAINING_FAILED:
|
||||
case SIG_STATUS_CARRIER_DOWN:
|
||||
case SIG_STATUS_END_OF_DATA:
|
||||
s->frame_handler(s->user_data, NULL, condition, TRUE);
|
||||
break;
|
||||
default:
|
||||
@@ -81,7 +81,7 @@ static __inline__ void octet_set_and_count(hdlc_rx_state_t *s)
|
||||
if (--s->octet_count <= 0)
|
||||
{
|
||||
s->octet_count = s->octet_count_report_interval;
|
||||
s->frame_handler(s->user_data, NULL, PUTBIT_OCTET_REPORT, TRUE);
|
||||
s->frame_handler(s->user_data, NULL, SIG_STATUS_OCTET_REPORT, TRUE);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -104,7 +104,7 @@ static __inline__ void octet_count(hdlc_rx_state_t *s)
|
||||
if (--s->octet_count <= 0)
|
||||
{
|
||||
s->octet_count = s->octet_count_report_interval;
|
||||
s->frame_handler(s->user_data, NULL, PUTBIT_OCTET_REPORT, TRUE);
|
||||
s->frame_handler(s->user_data, NULL, SIG_STATUS_OCTET_REPORT, TRUE);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,7 +116,7 @@ static void rx_flag_or_abort(hdlc_rx_state_t *s)
|
||||
{
|
||||
/* Hit HDLC abort */
|
||||
s->rx_aborts++;
|
||||
s->frame_handler(s->user_data, NULL, PUTBIT_ABORT, TRUE);
|
||||
s->frame_handler(s->user_data, NULL, SIG_STATUS_ABORT, TRUE);
|
||||
/* If we have not yet seen enough flags, restart the count. If we
|
||||
are beyond that point, just back off one step, so we need to see
|
||||
another flag before proceeding to collect frame octets. */
|
||||
@@ -184,7 +184,7 @@ static void rx_flag_or_abort(hdlc_rx_state_t *s)
|
||||
s->flags_seen = 0;
|
||||
if (++s->flags_seen >= s->framing_ok_threshold && !s->framing_ok_announced)
|
||||
{
|
||||
s->frame_handler(s->user_data, NULL, PUTBIT_FRAMING_OK, TRUE);
|
||||
s->frame_handler(s->user_data, NULL, SIG_STATUS_FRAMING_OK, TRUE);
|
||||
s->framing_ok_announced = TRUE;
|
||||
}
|
||||
}
|
||||
@@ -493,7 +493,7 @@ int hdlc_tx_get_byte(hdlc_tx_state_t *s)
|
||||
if (s->tx_end)
|
||||
{
|
||||
s->tx_end = FALSE;
|
||||
return PUTBIT_END_OF_DATA;
|
||||
return SIG_STATUS_END_OF_DATA;
|
||||
}
|
||||
return s->idle_octet;
|
||||
}
|
||||
@@ -522,7 +522,7 @@ int hdlc_tx_get(hdlc_tx_state_t *s, uint8_t buf[], size_t max_len)
|
||||
|
||||
for (i = 0; i < max_len; i++)
|
||||
{
|
||||
if ((x = hdlc_tx_get_byte(s)) == PUTBIT_END_OF_DATA)
|
||||
if ((x = hdlc_tx_get_byte(s)) == SIG_STATUS_END_OF_DATA)
|
||||
return i;
|
||||
buf[i] = x;
|
||||
}
|
||||
|
||||
@@ -459,6 +459,10 @@ SOURCE=.\spandsp/complex_vector_float.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\spandsp/complex_vector_int.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
SOURCE=.\spandsp/dc_restore.h
|
||||
# End Source File
|
||||
# Begin Source File
|
||||
|
||||
@@ -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: modem_connect_tones.c,v 1.27 2008/08/13 14:55:51 steveu Exp $
|
||||
* $Id: modem_connect_tones.c,v 1.28 2008/09/07 12:45:16 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -284,12 +284,12 @@ static void v21_put_bit(void *user_data, int bit)
|
||||
/* Special conditions. */
|
||||
switch (bit)
|
||||
{
|
||||
case PUTBIT_CARRIER_DOWN:
|
||||
case SIG_STATUS_CARRIER_DOWN:
|
||||
/* Only declare tone off, if we were the one to declare tone on. */
|
||||
if (s->tone_present == MODEM_CONNECT_TONES_FAX_PREAMBLE)
|
||||
report_tone_state(s, MODEM_CONNECT_TONES_NONE, -99);
|
||||
/* Fall through */
|
||||
case PUTBIT_CARRIER_UP:
|
||||
case SIG_STATUS_CARRIER_UP:
|
||||
s->raw_bit_stream = 0;
|
||||
s->num_bits = 0;
|
||||
s->flags_seen = 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: queue.c,v 1.22 2008/05/15 14:26:30 steveu Exp $
|
||||
* $Id: queue.c,v 1.23 2008/09/09 16:25:51 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <inttypes.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#define FULLY_DEFINE_QUEUE_STATE_T
|
||||
#include "spandsp/queue.h"
|
||||
|
||||
int queue_empty(queue_state_t *s)
|
||||
|
||||
@@ -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.14 2008/07/26 04:53:00 steveu Exp $
|
||||
* $Id: silence_gen.c,v 1.16 2008/09/07 12:45:16 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -59,7 +59,7 @@ int silence_gen(silence_gen_state_t *s, int16_t *amp, int max_len)
|
||||
{
|
||||
max_len = s->remaining_samples;
|
||||
if (max_len && s->status_handler)
|
||||
s->status_handler(s->status_user_data, MODEM_TX_STATUS_SHUTDOWN_COMPLETE);
|
||||
s->status_handler(s->status_user_data, SIG_STATUS_SHUTDOWN_COMPLETE);
|
||||
}
|
||||
s->remaining_samples -= 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: spandsp.h.in,v 1.9 2008/08/14 14:06:05 steveu Exp $
|
||||
* $Id: spandsp.h.in,v 1.10 2008/09/01 16:07:34 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -53,6 +53,7 @@
|
||||
#include <spandsp/vector_float.h>
|
||||
#include <spandsp/complex_vector_float.h>
|
||||
#include <spandsp/vector_int.h>
|
||||
#include <spandsp/complex_vector_int.h>
|
||||
#include <spandsp/arctan2.h>
|
||||
#include <spandsp/biquad.h>
|
||||
#include <spandsp/fir.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: async.h,v 1.16 2008/07/17 14:27:11 steveu Exp $
|
||||
* $Id: async.h,v 1.18 2008/09/07 12:45:17 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -49,42 +49,36 @@ and decoding must occur before data is fed to this module.
|
||||
#if !defined(_SPANDSP_ASYNC_H_)
|
||||
#define _SPANDSP_ASYNC_H_
|
||||
|
||||
/*! Special "bit" values for the put and get bit functions */
|
||||
/*! Special "bit" values for the bitstream put and get functions, and the signal status functions. */
|
||||
enum
|
||||
{
|
||||
/*! \brief The carrier signal has dropped. */
|
||||
PUTBIT_CARRIER_DOWN = -1,
|
||||
SIG_STATUS_CARRIER_DOWN = -1,
|
||||
/*! \brief The carrier signal is up. This merely indicates that carrier
|
||||
energy has been seen. It is not an indication that the carrier is either
|
||||
valid, or of the expected type. */
|
||||
PUTBIT_CARRIER_UP = -2,
|
||||
SIG_STATUS_CARRIER_UP = -2,
|
||||
/*! \brief The modem is training. This is an early indication that the
|
||||
signal seems to be of the right type. This may be needed in time critical
|
||||
applications, like T.38, to forward an early indication of what is happening
|
||||
on the wire. */
|
||||
PUTBIT_TRAINING_IN_PROGRESS = -3,
|
||||
SIG_STATUS_TRAINING_IN_PROGRESS = -3,
|
||||
/*! \brief The modem has trained, and is ready for data exchange. */
|
||||
PUTBIT_TRAINING_SUCCEEDED = -4,
|
||||
SIG_STATUS_TRAINING_SUCCEEDED = -4,
|
||||
/*! \brief The modem has failed to train. */
|
||||
PUTBIT_TRAINING_FAILED = -5,
|
||||
SIG_STATUS_TRAINING_FAILED = -5,
|
||||
/*! \brief Packet framing (e.g. HDLC framing) is OK. */
|
||||
PUTBIT_FRAMING_OK = -6,
|
||||
SIG_STATUS_FRAMING_OK = -6,
|
||||
/*! \brief The data stream has ended. */
|
||||
PUTBIT_END_OF_DATA = -7,
|
||||
SIG_STATUS_END_OF_DATA = -7,
|
||||
/*! \brief An abort signal (e.g. an HDLC abort) has been received. */
|
||||
PUTBIT_ABORT = -8,
|
||||
SIG_STATUS_ABORT = -8,
|
||||
/*! \brief A break signal (e.g. an async break) has been received. */
|
||||
PUTBIT_BREAK = -9,
|
||||
SIG_STATUS_BREAK = -9,
|
||||
/*! \brief A modem has completed its task, and shut down. */
|
||||
SIG_STATUS_SHUTDOWN_COMPLETE = -10,
|
||||
/*! \brief Regular octet report for things like HDLC to the MTP standards. */
|
||||
PUTBIT_OCTET_REPORT = -10
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
/*! \brief The data source for a transmitter is exhausted. */
|
||||
MODEM_TX_STATUS_DATA_EXHAUSTED = -1,
|
||||
/*! \brief The transmitter has completed its task, and shut down. */
|
||||
MODEM_TX_STATUS_SHUTDOWN_COMPLETE = -2
|
||||
SIG_STATUS_OCTET_REPORT = -11
|
||||
};
|
||||
|
||||
/*! Message put function for data pumps */
|
||||
@@ -185,6 +179,12 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*! Convert a signal status to a short text description.
|
||||
\brief Convert a signal status to a short text description.
|
||||
\param status The modem signal status.
|
||||
\return A pointer to the description. */
|
||||
const char *signal_status_to_str(int status);
|
||||
|
||||
/*! Initialise an asynchronous data transmit context.
|
||||
\brief Initialise an asynchronous data transmit context.
|
||||
\param s The transmitter context.
|
||||
@@ -231,11 +231,11 @@ async_rx_state_t *async_rx_init(async_rx_state_t *s,
|
||||
\brief Accept a bit from a received serial bit stream
|
||||
\param user_data An opaque point which must point to a receiver context.
|
||||
\param bit The new bit. Some special values are supported for this field.
|
||||
- PUTBIT_CARRIER_UP
|
||||
- PUTBIT_CARRIER_DOWN
|
||||
- PUTBIT_TRAINING_SUCCEEDED
|
||||
- PUTBIT_TRAINING_FAILED
|
||||
- PUTBIT_END_OF_DATA */
|
||||
- SIG_STATUS_CARRIER_UP
|
||||
- SIG_STATUS_CARRIER_DOWN
|
||||
- SIG_STATUS_TRAINING_SUCCEEDED
|
||||
- SIG_STATUS_TRAINING_FAILED
|
||||
- SIG_STATUS_END_OF_DATA */
|
||||
void async_rx_put_bit(void *user_data, int bit);
|
||||
|
||||
#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: complex.h,v 1.16 2008/04/17 14:27:00 steveu Exp $
|
||||
* $Id: complex.h,v 1.18 2008/09/03 13:41:42 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -329,6 +329,56 @@ static __inline__ complexl_t complex_mull(const complexl_t *x, const complexl_t
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
#endif
|
||||
|
||||
static __inline__ complexi_t complex_muli(const complexi_t *x, const complexi_t *y)
|
||||
{
|
||||
complexi_t z;
|
||||
|
||||
z.re = x->re*y->re - x->im*y->im;
|
||||
z.im = x->re*y->im + x->im*y->re;
|
||||
return z;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ complexi16_t complex_muli16(const complexi16_t *x, const complexi16_t *y)
|
||||
{
|
||||
complexi16_t z;
|
||||
|
||||
z.re = (int32_t) x->re*(int32_t) y->re - (int32_t) x->im*(int32_t) y->im;
|
||||
z.im = (int32_t) x->re*(int32_t) y->im + (int32_t) x->im*(int32_t) y->re;
|
||||
return z;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ complexi16_t complex_mul_q1_15(const complexi16_t *x, const complexi16_t *y)
|
||||
{
|
||||
complexi16_t z;
|
||||
|
||||
z.re = ((int32_t) x->re*(int32_t) y->re - (int32_t) x->im*(int32_t) y->im) >> 15;
|
||||
z.im = ((int32_t) x->re*(int32_t) y->im + (int32_t) x->im*(int32_t) y->re) >> 15;
|
||||
return z;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ complexi32_t complex_muli32i16(const complexi32_t *x, const complexi16_t *y)
|
||||
{
|
||||
complexi32_t z;
|
||||
|
||||
z.re = x->re*(int32_t) y->re - x->im*(int32_t) y->im;
|
||||
z.im = x->re*(int32_t) y->im + x->im*(int32_t) y->re;
|
||||
return z;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ complexi32_t complex_muli32(const complexi32_t *x, const complexi32_t *y)
|
||||
{
|
||||
complexi32_t z;
|
||||
|
||||
z.re = x->re*y->re - x->im*y->im;
|
||||
z.im = x->re*y->im + x->im*y->re;
|
||||
return z;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ complexf_t complex_divf(const complexf_t *x, const complexf_t *y)
|
||||
{
|
||||
complexf_t z;
|
||||
@@ -399,7 +449,7 @@ static __inline__ complexl_t complex_conjl(const complexl_t *x)
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
#endif
|
||||
|
||||
static __inline__ complexi_t complexi_conj(const complexi_t *x)
|
||||
static __inline__ complexi_t complex_conji(const complexi_t *x)
|
||||
{
|
||||
complexi_t z;
|
||||
|
||||
@@ -409,6 +459,26 @@ static __inline__ complexi_t complexi_conj(const complexi_t *x)
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ complexi16_t complex_conji16(const complexi16_t *x)
|
||||
{
|
||||
complexi16_t z;
|
||||
|
||||
z.re = x->re;
|
||||
z.im = -x->im;
|
||||
return z;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ complexi32_t complex_conji32(const complexi32_t *x)
|
||||
{
|
||||
complexi32_t z;
|
||||
|
||||
z.re = x->re;
|
||||
z.im = -x->im;
|
||||
return z;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ float powerf(const complexf_t *x)
|
||||
{
|
||||
return x->re*x->re + x->im*x->im;
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* SpanDSP - a series of DSP components for telephony
|
||||
*
|
||||
* complex_vector_int.h
|
||||
*
|
||||
* Written by Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* Copyright (C) 2003 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: complex_vector_int.h,v 1.1 2008/09/01 16:07:34 steveu Exp $
|
||||
*/
|
||||
|
||||
#if !defined(_SPANDSP_COMPLEX_VECTOR_INT_H_)
|
||||
#define _SPANDSP_COMPLEX_VECTOR_INT_H_
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
static __inline__ void cvec_copyi(complexi_t z[], const complexi_t x[], int n)
|
||||
{
|
||||
memcpy(z, x, n*sizeof(z[0]));
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ void cvec_copyi16(complexi16_t z[], const complexi16_t x[], int n)
|
||||
{
|
||||
memcpy(z, x, n*sizeof(z[0]));
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ void cvec_copyi32(complexi32_t z[], const complexi32_t x[], int n)
|
||||
{
|
||||
memcpy(z, x, n*sizeof(z[0]));
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ void cvec_zeroi(complexi_t z[], int n)
|
||||
{
|
||||
memset(z, 0, n*sizeof(z[0]));
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ void cvec_zeroi16(complexi16_t z[], int n)
|
||||
{
|
||||
memset(z, 0, n*sizeof(z[0]));
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ void cvec_zeroi32(complexi32_t z[], int n)
|
||||
{
|
||||
memset(z, 0, n*sizeof(z[0]));
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ void cvec_seti(complexi_t z[], complexi_t *x, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
z[i] = *x;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ void cvec_seti16(complexi16_t z[], complexi16_t *x, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
z[i] = *x;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ void cvec_seti32(complexi32_t z[], complexi32_t *x, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
z[i] = *x;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
#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: dds.h,v 1.18 2008/04/17 14:27:00 steveu Exp $
|
||||
* $Id: dds.h,v 1.20 2008/09/04 14:40:05 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -100,6 +100,12 @@ int16_t dds_lookup(uint32_t phase);
|
||||
*/
|
||||
int16_t dds_mod(uint32_t *phase_acc, int32_t phase_rate, int scale, int32_t phase);
|
||||
|
||||
/*! \brief Lookup the complex integer value of a specified phase.
|
||||
\param phase The phase accumulator value to be looked up.
|
||||
\return The complex signal amplitude, between (-32767, -32767) and (32767, 32767).
|
||||
*/
|
||||
complexi_t dds_lookup_complexi(uint32_t phase);
|
||||
|
||||
/*! \brief Generate a complex integer tone sample.
|
||||
\param phase_acc A pointer to a phase accumulator value.
|
||||
\param phase_rate The phase increment to be applied.
|
||||
@@ -107,12 +113,6 @@ int16_t dds_mod(uint32_t *phase_acc, int32_t phase_rate, int scale, int32_t phas
|
||||
*/
|
||||
complexi_t dds_complexi(uint32_t *phase_acc, int32_t phase_rate);
|
||||
|
||||
/*! \brief Lookup the complex integer value of a specified phase.
|
||||
\param phase The phase accumulator value to be looked up.
|
||||
\return The complex signal amplitude, between (-32767, -32767) and (32767, 32767).
|
||||
*/
|
||||
complexi_t dds_lookup_complexi(uint32_t phase);
|
||||
|
||||
/*! \brief Generate a complex integer tone sample, with modulation.
|
||||
\param phase_acc A pointer to a phase accumulator value.
|
||||
\param phase_rate The phase increment to be applied.
|
||||
@@ -122,6 +122,61 @@ complexi_t dds_lookup_complexi(uint32_t phase);
|
||||
*/
|
||||
complexi_t dds_complexi_mod(uint32_t *phase_acc, int32_t phase_rate, int scale, int32_t phase);
|
||||
|
||||
/*! \brief Generate a complex 16 bit integer tone sample.
|
||||
\param phase_acc A pointer to a phase accumulator value.
|
||||
\param phase_rate The phase increment to be applied.
|
||||
\return The complex signal amplitude, between (-32767, -32767) and (32767, 32767).
|
||||
*/
|
||||
complexi16_t dds_lookup_complexi16(uint32_t phase);
|
||||
|
||||
/*! \brief Generate a complex 16 bit integer tone sample.
|
||||
\param phase_acc A pointer to a phase accumulator value.
|
||||
\param phase_rate The phase increment to be applied.
|
||||
\return The complex signal amplitude, between (-32767, -32767) and (32767, 32767).
|
||||
*/
|
||||
complexi16_t dds_complexi16(uint32_t *phase_acc, int32_t phase_rate);
|
||||
|
||||
/*! \brief Generate a complex 16bit integer tone sample, with modulation.
|
||||
\param phase_acc A pointer to a phase accumulator value.
|
||||
\param phase_rate The phase increment to be applied.
|
||||
\param scale The scaling factor.
|
||||
\param phase The phase offset.
|
||||
\return The complex signal amplitude, between (-32767, -32767) and (32767, 32767).
|
||||
*/
|
||||
complexi16_t dds_complexi16_mod(uint32_t *phase_acc, int32_t phase_rate, int scale, int32_t phase);
|
||||
|
||||
/*! \brief Generate a complex 32 bit integer tone sample, with modulation.
|
||||
\param phase_acc A pointer to a phase accumulator value.
|
||||
\param phase_rate The phase increment to be applied.
|
||||
\param scale The scaling factor.
|
||||
\param phase The phase offset.
|
||||
\return The complex signal amplitude, between (-32767, -32767) and (32767, 32767).
|
||||
*/
|
||||
complexi32_t dds_complexi32_mod(uint32_t *phase_acc, int32_t phase_rate, int scale, int32_t phase);
|
||||
|
||||
/*! \brief Generate a complex 32 bit integer tone sample.
|
||||
\param phase_acc A pointer to a phase accumulator value.
|
||||
\param phase_rate The phase increment to be applied.
|
||||
\return The complex signal amplitude, between (-32767, -32767) and (32767, 32767).
|
||||
*/
|
||||
complexi32_t dds_lookup_complexi32(uint32_t phase);
|
||||
|
||||
/*! \brief Generate a complex 32 bit integer tone sample.
|
||||
\param phase_acc A pointer to a phase accumulator value.
|
||||
\param phase_rate The phase increment to be applied.
|
||||
\return The complex signal amplitude, between (-32767, -32767) and (32767, 32767).
|
||||
*/
|
||||
complexi32_t dds_complexi32(uint32_t *phase_acc, int32_t phase_rate);
|
||||
|
||||
/*! \brief Generate a complex 32 bit integer tone sample, with modulation.
|
||||
\param phase_acc A pointer to a phase accumulator value.
|
||||
\param phase_rate The phase increment to be applied.
|
||||
\param scale The scaling factor.
|
||||
\param phase The phase offset.
|
||||
\return The complex signal amplitude, between (-32767, -32767) and (32767, 32767).
|
||||
*/
|
||||
complexi32_t dds_complexi32_mod(uint32_t *phase_acc, int32_t phase_rate, int scale, int32_t phase);
|
||||
|
||||
/*! \brief Find the phase rate equivalent to a frequency, in Hz.
|
||||
\param frequency The frequency, in Hz.
|
||||
\return The equivalent phase 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: echo.h,v 1.15 2008/08/29 10:02:47 steveu Exp $
|
||||
* $Id: echo.h,v 1.16 2008/09/04 14:40:05 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -126,7 +126,7 @@ enum
|
||||
ECHO_CAN_USE_SUPPRESSOR = 0x10,
|
||||
ECHO_CAN_USE_TX_HPF = 0x20,
|
||||
ECHO_CAN_USE_RX_HPF = 0x40,
|
||||
ECHO_CAN_DISABLE = 0x80,
|
||||
ECHO_CAN_DISABLE = 0x80
|
||||
};
|
||||
|
||||
/*!
|
||||
|
||||
@@ -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.30 2008/07/16 14:23:48 steveu Exp $
|
||||
* $Id: fsk.h,v 1.31 2008/09/04 14:40:05 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -111,7 +111,7 @@ enum
|
||||
FSK_BELL103CH1,
|
||||
FSK_BELL103CH2,
|
||||
FSK_BELL202,
|
||||
FSK_WEITBRECHT, /* Used for TDD (Telecom Device for the Deaf) */
|
||||
FSK_WEITBRECHT /* Used for TDD (Telecom Device for the Deaf) */
|
||||
};
|
||||
|
||||
extern const fsk_spec_t preset_fsk_specs[];
|
||||
|
||||
@@ -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.h,v 1.16 2008/05/30 13:51:28 steveu Exp $
|
||||
* $Id: queue.h,v 1.17 2008/09/09 16:25:51 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -63,8 +63,10 @@ typedef struct
|
||||
volatile int iptr;
|
||||
/*! \brief The buffer output pointer. */
|
||||
volatile int optr;
|
||||
#if defined(FULLY_DEFINE_QUEUE_STATE_T)
|
||||
/*! \brief The data buffer, sized at the time the structure is created. */
|
||||
uint8_t data[];
|
||||
#endif
|
||||
} queue_state_t;
|
||||
|
||||
#define QUEUE_STATE_T_SIZE(len) (sizeof(queue_state_t) + len + 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: t30.h,v 1.114 2008/08/13 00:11:30 steveu Exp $
|
||||
* $Id: t30.h,v 1.115 2008/09/04 14:40:05 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -338,7 +338,7 @@ enum
|
||||
T30_SUPPORT_V29 = 0x02,
|
||||
T30_SUPPORT_V17 = 0x04,
|
||||
T30_SUPPORT_V34 = 0x08,
|
||||
T30_SUPPORT_IAF = 0x10,
|
||||
T30_SUPPORT_IAF = 0x10
|
||||
};
|
||||
|
||||
enum
|
||||
|
||||
@@ -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.28 2008/06/19 13:27:45 steveu Exp $
|
||||
* $Id: t38_core.h,v 1.29 2008/09/04 14:40:05 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -142,7 +142,7 @@ enum t38_field_classes_e
|
||||
{
|
||||
T38_FIELD_CLASS_NONE = 0,
|
||||
T38_FIELD_CLASS_HDLC,
|
||||
T38_FIELD_CLASS_NON_ECM,
|
||||
T38_FIELD_CLASS_NON_ECM
|
||||
};
|
||||
|
||||
/*! T.38 message types */
|
||||
|
||||
@@ -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.56 2008/08/14 14:06:05 steveu Exp $
|
||||
* $Id: t38_gateway.h,v 1.57 2008/09/02 13:56:10 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -125,6 +125,21 @@ typedef struct
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/*! \brief HDLC message buffers. */
|
||||
uint8_t buf[T38_MAX_HDLC_LEN];
|
||||
/*! \brief HDLC message lengths. */
|
||||
int len;
|
||||
/*! \brief HDLC message status flags. */
|
||||
int flags;
|
||||
/*! \brief HDLC buffer contents. */
|
||||
int contents;
|
||||
} t38_gateway_hdlc_buf_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/*! \brief HDLC message buffers. */
|
||||
t38_gateway_hdlc_buf_t buf[T38_TX_HDLC_BUFS];
|
||||
#if 0
|
||||
/*! \brief HDLC message buffers. */
|
||||
uint8_t buf[T38_TX_HDLC_BUFS][T38_MAX_HDLC_LEN];
|
||||
/*! \brief HDLC message lengths. */
|
||||
@@ -133,6 +148,7 @@ typedef struct
|
||||
int flags[T38_TX_HDLC_BUFS];
|
||||
/*! \brief HDLC buffer contents. */
|
||||
int contents[T38_TX_HDLC_BUFS];
|
||||
#endif
|
||||
/*! \brief HDLC buffer number for input. */
|
||||
int in;
|
||||
/*! \brief HDLC buffer number for output. */
|
||||
|
||||
@@ -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_non_ecm_buffer.h,v 1.1 2008/08/14 14:06:05 steveu Exp $
|
||||
* $Id: t38_non_ecm_buffer.h,v 1.2 2008/09/02 13:56:10 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -83,10 +83,13 @@ typedef struct
|
||||
|
||||
/*! \brief The number of octets input to the buffer. */
|
||||
int in_octets;
|
||||
/*! \brief The number of octets output from the buffer. */
|
||||
int out_octets;
|
||||
/*! \brief The number of rows input to the buffer. */
|
||||
int in_rows;
|
||||
/*! \brief The number of non-ECM fill octets generated for minimum row bits
|
||||
purposes. */
|
||||
int min_row_bits_fill_octets;
|
||||
/*! \brief The number of octets output from the buffer. */
|
||||
int out_octets;
|
||||
/*! \brief The number of rows output from the buffer. */
|
||||
int out_rows;
|
||||
/*! \brief The number of non-ECM fill octets generated for flow control
|
||||
@@ -106,6 +109,12 @@ extern "C"
|
||||
\return A pointer to the buffer context, or NULL if there was a problem. */
|
||||
t38_non_ecm_buffer_state_t *t38_non_ecm_buffer_init(t38_non_ecm_buffer_state_t *s, int mode, int min_row_bits);
|
||||
|
||||
/*! \brief Set the mode of a T.38 rate adapting non-ECM buffer context.
|
||||
\param s The buffer context.
|
||||
\param mode TRUE for image data mode, or FALSE for TCF mode.
|
||||
\param bits The minimum number of bits per FAX image row. */
|
||||
void t38_non_ecm_buffer_set_mode(t38_non_ecm_buffer_state_t *s, int mode, int min_row_bits);
|
||||
|
||||
/*! \brief Inject data to T.38 rate adapting non-ECM buffer context.
|
||||
\param s The buffer context.
|
||||
\param buf The data buffer to be injected.
|
||||
@@ -117,11 +126,17 @@ void t38_non_ecm_buffer_inject(t38_non_ecm_buffer_state_t *s, const uint8_t *buf
|
||||
\param s The buffer context. */
|
||||
void t38_non_ecm_buffer_push(t38_non_ecm_buffer_state_t *s);
|
||||
|
||||
/*! \brief Report the status of a T.38 rate adapting non-ECM buffer context to the specified
|
||||
/*! \brief Report the input status of a T.38 rate adapting non-ECM buffer context to the specified
|
||||
logging context.
|
||||
\param s The buffer context.
|
||||
\param logging The logging context. */
|
||||
void t38_non_ecm_buffer_report_status(t38_non_ecm_buffer_state_t *s, logging_state_t *logging);
|
||||
void t38_non_ecm_buffer_report_input_status(t38_non_ecm_buffer_state_t *s, logging_state_t *logging);
|
||||
|
||||
/*! \brief Report the output status of a T.38 rate adapting non-ECM buffer context to the specified
|
||||
logging context.
|
||||
\param s The buffer context.
|
||||
\param logging The logging context. */
|
||||
void t38_non_ecm_buffer_report_output_status(t38_non_ecm_buffer_state_t *s, logging_state_t *logging);
|
||||
|
||||
/*! \brief Get the next bit of data from a T.38 rate adapting non-ECM buffer context.
|
||||
\param user_data The buffer context, cast to a void pointer.
|
||||
|
||||
@@ -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.52 2008/07/16 14:23:48 steveu Exp $
|
||||
* $Id: v17rx.h,v 1.53 2008/09/08 12:54:32 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -306,28 +306,26 @@ typedef struct
|
||||
/*! \brief The previous value of agc_scaling, needed to reuse old training. */
|
||||
float agc_scaling_save;
|
||||
|
||||
/*! \brief The current delta factor for updating the equalizer coefficients. */
|
||||
float eq_delta;
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
/*! \brief The adaptive equalizer coefficients. */
|
||||
complexi_t eq_coeff[V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN];
|
||||
/*! \brief A saved set of adaptive equalizer coefficients for use after restarts. */
|
||||
complexi_t eq_coeff_save[V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN];
|
||||
/*! \brief The equalizer signal buffer. */
|
||||
complexi_t eq_buf[V17_EQUALIZER_MASK + 1];
|
||||
#else
|
||||
complexf_t eq_coeff[V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN];
|
||||
complexf_t eq_coeff_save[V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN];
|
||||
complexf_t eq_buf[V17_EQUALIZER_MASK + 1];
|
||||
#endif
|
||||
/*! \brief Current read offset into the equalizer buffer. */
|
||||
int eq_step;
|
||||
/*! \brief Current write offset into the equalizer buffer. */
|
||||
int eq_put_step;
|
||||
/*! \brief Symbol counter to the next equalizer update. */
|
||||
int eq_skip;
|
||||
|
||||
/*! \brief The current half of the baud. */
|
||||
int baud_half;
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
/*! \brief The current delta factor for updating the equalizer coefficients. */
|
||||
float eq_delta;
|
||||
/*! \brief The adaptive equalizer coefficients. */
|
||||
complexi16_t eq_coeff[V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN];
|
||||
/*! \brief A saved set of adaptive equalizer coefficients for use after restarts. */
|
||||
complexi16_t eq_coeff_save[V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN];
|
||||
/*! \brief The equalizer signal buffer. */
|
||||
complexi16_t eq_buf[V17_EQUALIZER_MASK + 1];
|
||||
|
||||
/*! Low band edge filter for symbol sync. */
|
||||
int32_t symbol_sync_low[2];
|
||||
/*! High band edge filter for symbol sync. */
|
||||
@@ -337,6 +335,15 @@ typedef struct
|
||||
/*! Baud phase for symbol sync. */
|
||||
int32_t baud_phase;
|
||||
#else
|
||||
/*! \brief The current delta factor for updating the equalizer coefficients. */
|
||||
float eq_delta;
|
||||
/*! \brief The adaptive equalizer coefficients. */
|
||||
complexf_t eq_coeff[V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN];
|
||||
/*! \brief A saved set of adaptive equalizer coefficients for use after restarts. */
|
||||
complexf_t eq_coeff_save[V17_EQUALIZER_PRE_LEN + 1 + V17_EQUALIZER_POST_LEN];
|
||||
/*! \brief The equalizer signal buffer. */
|
||||
complexf_t eq_buf[V17_EQUALIZER_MASK + 1];
|
||||
|
||||
/*! Low band edge filter for symbol sync. */
|
||||
float symbol_sync_low[2];
|
||||
/*! High band edge filter for symbol sync. */
|
||||
@@ -346,6 +353,7 @@ typedef struct
|
||||
/*! Baud phase for symbol sync. */
|
||||
float baud_phase;
|
||||
#endif
|
||||
|
||||
/*! \brief The total symbol timing correction since the carrier came up.
|
||||
This is only for performance analysis purposes. */
|
||||
int total_baud_timing_correction;
|
||||
|
||||
@@ -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.47 2008/07/16 14:23:48 steveu Exp $
|
||||
* $Id: v27ter_rx.h,v 1.48 2008/09/08 12:54:32 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -144,22 +144,10 @@ typedef struct
|
||||
/*! \brief The previous value of agc_scaling, needed to reuse old training. */
|
||||
float agc_scaling_save;
|
||||
|
||||
/*! \brief The position of the current symbol in the constellation, used for
|
||||
differential decoding. */
|
||||
int constellation_state;
|
||||
|
||||
/*! \brief The current delta factor for updating the equalizer coefficients. */
|
||||
float eq_delta;
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
/*! \brief The adaptive equalizer coefficients. */
|
||||
complexi_t eq_coeff[V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN];
|
||||
/*! \brief A saved set of adaptive equalizer coefficients for use after restarts. */
|
||||
complexi_t eq_coeff_save[V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN];
|
||||
/*! \brief The equalizer signal buffer. */
|
||||
complexi_t eq_buf[V27TER_EQUALIZER_MASK + 1];
|
||||
#else
|
||||
complexf_t eq_coeff[V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN];
|
||||
complexf_t eq_coeff_save[V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN];
|
||||
complexf_t eq_buf[V27TER_EQUALIZER_MASK + 1];
|
||||
#endif
|
||||
/*! \brief Current offset into the equalizer buffer. */
|
||||
int eq_step;
|
||||
/*! \brief Current write offset into the equalizer buffer. */
|
||||
@@ -167,6 +155,29 @@ typedef struct
|
||||
/*! \brief Symbol counter to the next equalizer update. */
|
||||
int eq_skip;
|
||||
|
||||
/*! \brief The current half of the baud. */
|
||||
int baud_half;
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
/*! \brief The current delta factor for updating the equalizer coefficients. */
|
||||
float eq_delta;
|
||||
/*! \brief The adaptive equalizer coefficients. */
|
||||
complexi16_t eq_coeff[V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN];
|
||||
/*! \brief A saved set of adaptive equalizer coefficients for use after restarts. */
|
||||
complexi16_t eq_coeff_save[V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN];
|
||||
/*! \brief The equalizer signal buffer. */
|
||||
complexi16_t eq_buf[V27TER_EQUALIZER_MASK + 1];
|
||||
#else
|
||||
/*! \brief The current delta factor for updating the equalizer coefficients. */
|
||||
float eq_delta;
|
||||
/*! \brief The adaptive equalizer coefficients. */
|
||||
complexf_t eq_coeff[V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN];
|
||||
/*! \brief A saved set of adaptive equalizer coefficients for use after restarts. */
|
||||
complexf_t eq_coeff_save[V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN];
|
||||
/*! \brief The equalizer signal buffer. */
|
||||
complexf_t eq_buf[V27TER_EQUALIZER_MASK + 1];
|
||||
#endif
|
||||
|
||||
/*! \brief Integration variable for damping the Gardner algorithm tests. */
|
||||
int gardner_integrate;
|
||||
/*! \brief Current step size of Gardner algorithm integration. */
|
||||
@@ -174,8 +185,6 @@ typedef struct
|
||||
/*! \brief The total symbol timing correction since the carrier came up.
|
||||
This is only for performance analysis purposes. */
|
||||
int total_baud_timing_correction;
|
||||
/*! \brief The current fractional phase of the baud timing. */
|
||||
int baud_phase;
|
||||
|
||||
/*! \brief Starting phase angles for the coarse carrier aquisition step. */
|
||||
int32_t start_angles[2];
|
||||
|
||||
@@ -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.55 2008/07/16 14:23:48 steveu Exp $
|
||||
* $Id: v29rx.h,v 1.59 2008/09/08 12:45:02 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -212,22 +212,10 @@ typedef struct
|
||||
/*! \brief The previous value of agc_scaling, needed to reuse old training. */
|
||||
float agc_scaling_save;
|
||||
|
||||
/*! \brief The position of the current symbol in the constellation, used for
|
||||
differential decoding. */
|
||||
int constellation_state;
|
||||
|
||||
/*! \brief The current delta factor for updating the equalizer coefficients. */
|
||||
float eq_delta;
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
/*! \brief The adaptive equalizer coefficients. */
|
||||
complexi_t eq_coeff[V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN];
|
||||
/*! \brief A saved set of adaptive equalizer coefficients for use after restarts. */
|
||||
complexi_t eq_coeff_save[V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN];
|
||||
/*! \brief The equalizer signal buffer. */
|
||||
complexi_t eq_buf[V29_EQUALIZER_MASK + 1];
|
||||
#else
|
||||
complexf_t eq_coeff[V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN];
|
||||
complexf_t eq_coeff_save[V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN];
|
||||
complexf_t eq_buf[V29_EQUALIZER_MASK + 1];
|
||||
#endif
|
||||
/*! \brief Current offset into the equalizer buffer. */
|
||||
int eq_step;
|
||||
/*! \brief Current write offset into the equalizer buffer. */
|
||||
@@ -237,7 +225,17 @@ typedef struct
|
||||
|
||||
/*! \brief The current half of the baud. */
|
||||
int baud_half;
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
/*! \brief The current delta factor for updating the equalizer coefficients. */
|
||||
int16_t eq_delta;
|
||||
/*! \brief The adaptive equalizer coefficients. */
|
||||
complexi16_t eq_coeff[V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN];
|
||||
/*! \brief A saved set of adaptive equalizer coefficients for use after restarts. */
|
||||
complexi16_t eq_coeff_save[V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN];
|
||||
/*! \brief The equalizer signal buffer. */
|
||||
complexi16_t eq_buf[V29_EQUALIZER_MASK + 1];
|
||||
|
||||
/*! Low band edge filter for symbol sync. */
|
||||
int32_t symbol_sync_low[2];
|
||||
/*! High band edge filter for symbol sync. */
|
||||
@@ -247,6 +245,15 @@ typedef struct
|
||||
/*! Baud phase for symbol sync. */
|
||||
int32_t baud_phase;
|
||||
#else
|
||||
/*! \brief The current delta factor for updating the equalizer coefficients. */
|
||||
float eq_delta;
|
||||
/*! \brief The adaptive equalizer coefficients. */
|
||||
complexf_t eq_coeff[V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN];
|
||||
/*! \brief A saved set of adaptive equalizer coefficients for use after restarts. */
|
||||
complexf_t eq_coeff_save[V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN];
|
||||
/*! \brief The equalizer signal buffer. */
|
||||
complexf_t eq_buf[V29_EQUALIZER_MASK + 1];
|
||||
|
||||
/*! Low band edge filter for symbol sync. */
|
||||
float symbol_sync_low[2];
|
||||
/*! High band edge filter for symbol sync. */
|
||||
@@ -324,7 +331,11 @@ int v29_rx(v29_rx_state_t *s, const int16_t amp[], int len);
|
||||
\param s The modem context.
|
||||
\param coeffs The vector of complex coefficients.
|
||||
\return The number of coefficients in the vector. */
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
int v29_rx_equalizer_state(v29_rx_state_t *s, complexi16_t **coeffs);
|
||||
#else
|
||||
int v29_rx_equalizer_state(v29_rx_state_t *s, complexf_t **coeffs);
|
||||
#endif
|
||||
|
||||
/*! Get the current received carrier frequency.
|
||||
\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: v8.h,v 1.22 2008/05/14 15:41:25 steveu Exp $
|
||||
* $Id: v8.h,v 1.23 2008/09/04 14:40:05 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -76,7 +76,7 @@ enum v8_modulation_e
|
||||
V8_MOD_V90 = (1 << 12), /* V.90 duplex */
|
||||
V8_MOD_V92 = (1 << 13), /* V.92 duplex */
|
||||
|
||||
V8_MOD_FAILED = (1 << 15), /* Indicates failure to negotiate */
|
||||
V8_MOD_FAILED = (1 << 15) /* Indicates failure to negotiate */
|
||||
};
|
||||
|
||||
enum v8_protocol_e
|
||||
|
||||
@@ -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: vector_float.h,v 1.10 2008/04/17 14:27:01 steveu Exp $
|
||||
* $Id: vector_float.h,v 1.11 2008/09/01 16:07:34 steveu Exp $
|
||||
*/
|
||||
|
||||
#if !defined(_SPANDSP_VECTOR_FLOAT_H_)
|
||||
@@ -105,11 +105,26 @@ void vec_mul(double z[], const double x[], const double y[], int n);
|
||||
void vec_mull(long double z[], const long double x[], const long double y[], int n);
|
||||
#endif
|
||||
|
||||
/*! \brief Find the dot product of two float vectors.
|
||||
\param x The first vector.
|
||||
\param y The first vector.
|
||||
\param n The number of elements in the vectors.
|
||||
\return The dot product of the two vectors. */
|
||||
float vec_dot_prodf(const float x[], const float y[], int n);
|
||||
|
||||
/*! \brief Find the dot product of two double vectors.
|
||||
\param x The first vector.
|
||||
\param y The first vector.
|
||||
\param n The number of elements in the vectors.
|
||||
\return The dot product of the two vectors. */
|
||||
double vec_dot_prod(const double x[], const double y[], int n);
|
||||
|
||||
#if defined(HAVE_LONG_DOUBLE)
|
||||
/*! \brief Find the dot product of two long double vectors.
|
||||
\param x The first vector.
|
||||
\param y The first vector.
|
||||
\param n The number of elements in the vectors.
|
||||
\return The dot product of the two vectors. */
|
||||
long double vec_dot_prodl(const long double x[], const long double y[], int n);
|
||||
#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: vector_int.h,v 1.10 2008/04/17 14:27:01 steveu Exp $
|
||||
* $Id: vector_int.h,v 1.11 2008/09/01 16:07:34 steveu Exp $
|
||||
*/
|
||||
|
||||
#if !defined(_SPANDSP_VECTOR_INT_H_)
|
||||
@@ -33,11 +33,79 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
static __inline__ void vec_copyi(int z[], const int x[], int n)
|
||||
{
|
||||
memcpy(z, x, n*sizeof(z[0]));
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ void vec_copyi16(int16_t z[], const int16_t x[], int n)
|
||||
{
|
||||
memcpy(z, x, n*sizeof(z[0]));
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ void vec_copyi32(int32_t z[], const int32_t x[], int n)
|
||||
{
|
||||
memcpy(z, x, n*sizeof(z[0]));
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ void vec_zeroi(int z[], int n)
|
||||
{
|
||||
memset(z, 0, n*sizeof(z[0]));
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ void vec_zeroi16(int16_t z[], int n)
|
||||
{
|
||||
memset(z, 0, n*sizeof(z[0]));
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ void vec_zeroi32(int32_t z[], int n)
|
||||
{
|
||||
memset(z, 0, n*sizeof(z[0]));
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ void vec_seti(int z[], int x, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
z[i] = x;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ void vec_seti16(int16_t z[], int16_t x, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
z[i] = x;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ void vec_seti32(int32_t z[], int32_t x, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
z[i] = x;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
/*! \brief Find the dot product of two int16_t vectors.
|
||||
\param x The first vector.
|
||||
\param y The first vector.
|
||||
\param n The number of elements in the vectors.
|
||||
\return The dot product of the two vectors. */
|
||||
int32_t vec_dot_prodi16(const int16_t x[], const int16_t y[], int n);
|
||||
|
||||
/*! \brief Find the minimum and maximum values in a vector.
|
||||
/*! \brief Find the minimum and maximum values in an int16_t vector.
|
||||
\param x The vector to be searched.
|
||||
\param n The number of elements in the vetor.
|
||||
\param n The number of elements in the vector.
|
||||
\param out A two element vector. The first will receive the
|
||||
maximum. The second will receive the minimum. This parameter
|
||||
may be set to NULL.
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
|
||||
/* The date and time of the version are in UTC form. */
|
||||
|
||||
#define SPANDSP_RELEASE_DATE 20080829
|
||||
#define SPANDSP_RELEASE_TIME 104025
|
||||
#define SPANDSP_RELEASE_DATE 20080909
|
||||
#define SPANDSP_RELEASE_TIME 162813
|
||||
|
||||
#endif
|
||||
/*- End of file ------------------------------------------------------------*/
|
||||
+19
-21
@@ -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.262 2008/08/17 16:25:52 steveu Exp $
|
||||
* $Id: t30.c,v 1.264 2008/09/09 15:30:43 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -1831,7 +1831,6 @@ static int start_receiving_document(t30_state_t *s)
|
||||
}
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Start receiving document\n");
|
||||
queue_phase(s, T30_PHASE_B_TX);
|
||||
s->dis_received = FALSE;
|
||||
s->ecm_block = 0;
|
||||
send_dis_or_dtc_sequence(s, TRUE);
|
||||
return 0;
|
||||
@@ -2006,7 +2005,6 @@ static int process_rx_dis_dtc(t30_state_t *s, const uint8_t *msg, int len)
|
||||
send_dcn(s);
|
||||
return -1;
|
||||
}
|
||||
s->dis_received = TRUE;
|
||||
if (set_dis_or_dtc(s))
|
||||
{
|
||||
s->current_status = T30_ERR_INCOMPATIBLE;
|
||||
@@ -4823,13 +4821,13 @@ static void t30_non_ecm_rx_status(void *user_data, int status)
|
||||
s = (t30_state_t *) user_data;
|
||||
switch (status)
|
||||
{
|
||||
case PUTBIT_TRAINING_IN_PROGRESS:
|
||||
case SIG_STATUS_TRAINING_IN_PROGRESS:
|
||||
break;
|
||||
case PUTBIT_TRAINING_FAILED:
|
||||
case SIG_STATUS_TRAINING_FAILED:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Non-ECM carrier training failed in state %d\n", s->state);
|
||||
s->rx_trained = FALSE;
|
||||
break;
|
||||
case PUTBIT_TRAINING_SUCCEEDED:
|
||||
case SIG_STATUS_TRAINING_SUCCEEDED:
|
||||
/* The modem is now trained */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Non-ECM carrier trained in state %d\n", s->state);
|
||||
/* In case we are in trainability test mode... */
|
||||
@@ -4840,10 +4838,10 @@ static void t30_non_ecm_rx_status(void *user_data, int status)
|
||||
s->rx_trained = TRUE;
|
||||
s->timer_t2_t4 = 0;
|
||||
break;
|
||||
case PUTBIT_CARRIER_UP:
|
||||
case SIG_STATUS_CARRIER_UP:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Non-ECM carrier up in state %d\n", s->state);
|
||||
break;
|
||||
case PUTBIT_CARRIER_DOWN:
|
||||
case SIG_STATUS_CARRIER_DOWN:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Non-ECM carrier down in state %d\n", s->state);
|
||||
was_trained = s->rx_trained;
|
||||
s->rx_signal_present = FALSE;
|
||||
@@ -5052,7 +5050,7 @@ int t30_non_ecm_get_bit(void *user_data)
|
||||
if (s->tcf_test_bits-- < 0)
|
||||
{
|
||||
/* Finished sending training test. */
|
||||
bit = PUTBIT_END_OF_DATA;
|
||||
bit = SIG_STATUS_END_OF_DATA;
|
||||
}
|
||||
break;
|
||||
case T30_STATE_I:
|
||||
@@ -5066,7 +5064,7 @@ int t30_non_ecm_get_bit(void *user_data)
|
||||
break;
|
||||
default:
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "t30_non_ecm_get_bit in bad state %d\n", s->state);
|
||||
bit = PUTBIT_END_OF_DATA;
|
||||
bit = SIG_STATUS_END_OF_DATA;
|
||||
break;
|
||||
}
|
||||
return bit;
|
||||
@@ -5150,19 +5148,19 @@ static void t30_hdlc_rx_status(void *user_data, int status)
|
||||
s = (t30_state_t *) user_data;
|
||||
switch (status)
|
||||
{
|
||||
case PUTBIT_TRAINING_IN_PROGRESS:
|
||||
case SIG_STATUS_TRAINING_IN_PROGRESS:
|
||||
break;
|
||||
case PUTBIT_TRAINING_FAILED:
|
||||
case SIG_STATUS_TRAINING_FAILED:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC carrier training failed in state %d\n", s->state);
|
||||
s->rx_trained = FALSE;
|
||||
break;
|
||||
case PUTBIT_TRAINING_SUCCEEDED:
|
||||
case SIG_STATUS_TRAINING_SUCCEEDED:
|
||||
/* The modem is now trained */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC carrier trained in state %d\n", s->state);
|
||||
s->rx_signal_present = TRUE;
|
||||
s->rx_trained = TRUE;
|
||||
break;
|
||||
case PUTBIT_CARRIER_UP:
|
||||
case SIG_STATUS_CARRIER_UP:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC carrier up in state %d\n", s->state);
|
||||
s->rx_signal_present = TRUE;
|
||||
switch (s->timer_t2_t4_is)
|
||||
@@ -5177,7 +5175,7 @@ static void t30_hdlc_rx_status(void *user_data, int status)
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case PUTBIT_CARRIER_DOWN:
|
||||
case SIG_STATUS_CARRIER_DOWN:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC carrier down in state %d\n", s->state);
|
||||
s->rx_signal_present = FALSE;
|
||||
s->rx_trained = FALSE;
|
||||
@@ -5206,7 +5204,7 @@ static void t30_hdlc_rx_status(void *user_data, int status)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PUTBIT_FRAMING_OK:
|
||||
case SIG_STATUS_FRAMING_OK:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC framing OK in state %d\n", s->state);
|
||||
if (!s->far_end_detected && s->timer_t0_t1 > 0)
|
||||
{
|
||||
@@ -5232,7 +5230,7 @@ static void t30_hdlc_rx_status(void *user_data, int status)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PUTBIT_ABORT:
|
||||
case SIG_STATUS_ABORT:
|
||||
/* Just ignore these */
|
||||
break;
|
||||
default:
|
||||
@@ -5559,10 +5557,10 @@ void t30_front_end_status(void *user_data, int status)
|
||||
switch (s->phase)
|
||||
{
|
||||
case T30_PHASE_C_NON_ECM_RX:
|
||||
t30_non_ecm_rx_status(s, PUTBIT_CARRIER_DOWN);
|
||||
t30_non_ecm_rx_status(s, SIG_STATUS_CARRIER_DOWN);
|
||||
break;
|
||||
default:
|
||||
t30_hdlc_rx_status(s, PUTBIT_CARRIER_DOWN);
|
||||
t30_hdlc_rx_status(s, SIG_STATUS_CARRIER_DOWN);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -5584,8 +5582,8 @@ void t30_front_end_status(void *user_data, int status)
|
||||
case T30_PHASE_D_RX:
|
||||
/* We are running a V.21 receive modem, where an explicit training indication
|
||||
will not occur. */
|
||||
t30_hdlc_rx_status(s, PUTBIT_CARRIER_UP);
|
||||
t30_hdlc_rx_status(s, PUTBIT_FRAMING_OK);
|
||||
t30_hdlc_rx_status(s, SIG_STATUS_CARRIER_UP);
|
||||
t30_hdlc_rx_status(s, SIG_STATUS_FRAMING_OK);
|
||||
break;
|
||||
default:
|
||||
/* Cancel any receive timeout, and declare that a receive signal is present,
|
||||
|
||||
+17
-17
@@ -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.119 2008/08/09 05:09:56 steveu Exp $
|
||||
* $Id: t31.c,v 1.120 2008/09/07 12:45:17 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -341,7 +341,7 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
||||
packets, when they have sent no data for the body of the frame. */
|
||||
if (s->tx.out_bytes > 0)
|
||||
hdlc_accept((void *) s, fe->hdlc_rx.buf, fe->hdlc_rx.len, TRUE);
|
||||
hdlc_accept((void *) s, NULL, PUTBIT_CARRIER_DOWN, TRUE);
|
||||
hdlc_accept((void *) s, NULL, SIG_STATUS_CARRIER_DOWN, TRUE);
|
||||
}
|
||||
s->tx.out_bytes = 0;
|
||||
fe->missing_data = FALSE;
|
||||
@@ -352,7 +352,7 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_BAD_SIG_END!\n");
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC bad, sig end (%s)\n", t30_frametype(s->tx.data[2]), (fe->missing_data) ? "missing octets" : "clean");
|
||||
if (fe->current_rx_type == T31_V21_RX)
|
||||
hdlc_accept((void *) s, NULL, PUTBIT_CARRIER_DOWN, TRUE);
|
||||
hdlc_accept((void *) s, NULL, SIG_STATUS_CARRIER_DOWN, TRUE);
|
||||
fe->hdlc_rx.len = 0;
|
||||
fe->missing_data = FALSE;
|
||||
break;
|
||||
@@ -363,7 +363,7 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
||||
i.e. they send T38_FIELD_HDLC_FCS_OK, and then T38_FIELD_HDLC_SIG_END when the carrier actually drops.
|
||||
The other is because the HDLC signal drops unexpectedly - i.e. not just after a final frame. */
|
||||
if (fe->current_rx_type == T31_V21_RX)
|
||||
hdlc_accept((void *) s, NULL, PUTBIT_CARRIER_DOWN, TRUE);
|
||||
hdlc_accept((void *) s, NULL, SIG_STATUS_CARRIER_DOWN, TRUE);
|
||||
fe->hdlc_rx.len = 0;
|
||||
fe->missing_data = FALSE;
|
||||
break;
|
||||
@@ -709,20 +709,20 @@ static void non_ecm_rx_status(void *user_data, int status)
|
||||
s = (t31_state_t *) user_data;
|
||||
switch (status)
|
||||
{
|
||||
case PUTBIT_TRAINING_IN_PROGRESS:
|
||||
case SIG_STATUS_TRAINING_IN_PROGRESS:
|
||||
break;
|
||||
case PUTBIT_TRAINING_FAILED:
|
||||
case SIG_STATUS_TRAINING_FAILED:
|
||||
s->at_state.rx_trained = FALSE;
|
||||
break;
|
||||
case PUTBIT_TRAINING_SUCCEEDED:
|
||||
case SIG_STATUS_TRAINING_SUCCEEDED:
|
||||
/* The modem is now trained */
|
||||
at_put_response_code(&s->at_state, AT_RESPONSE_CODE_CONNECT);
|
||||
s->at_state.rx_signal_present = TRUE;
|
||||
s->at_state.rx_trained = TRUE;
|
||||
break;
|
||||
case PUTBIT_CARRIER_UP:
|
||||
case SIG_STATUS_CARRIER_UP:
|
||||
break;
|
||||
case PUTBIT_CARRIER_DOWN:
|
||||
case SIG_STATUS_CARRIER_DOWN:
|
||||
if (s->at_state.rx_signal_present)
|
||||
{
|
||||
s->at_state.rx_data[s->at_state.rx_data_bytes++] = DLE;
|
||||
@@ -806,7 +806,7 @@ static int non_ecm_get_bit(void *user_data)
|
||||
s->tx.final = FALSE;
|
||||
/* This will put the modem into its shutdown sequence. When
|
||||
it has finally shut down, an OK response will be sent. */
|
||||
return PUTBIT_END_OF_DATA;
|
||||
return SIG_STATUS_END_OF_DATA;
|
||||
}
|
||||
/* Fill with 0xFF bytes at the start of transmission, or 0x00 if we are in
|
||||
the middle of transmission. This follows T.31 and T.30 practice. */
|
||||
@@ -856,24 +856,24 @@ static void hdlc_rx_status(void *user_data, int status)
|
||||
s = (t31_state_t *) user_data;
|
||||
switch (status)
|
||||
{
|
||||
case PUTBIT_TRAINING_IN_PROGRESS:
|
||||
case SIG_STATUS_TRAINING_IN_PROGRESS:
|
||||
break;
|
||||
case PUTBIT_TRAINING_FAILED:
|
||||
case SIG_STATUS_TRAINING_FAILED:
|
||||
s->at_state.rx_trained = FALSE;
|
||||
break;
|
||||
case PUTBIT_TRAINING_SUCCEEDED:
|
||||
case SIG_STATUS_TRAINING_SUCCEEDED:
|
||||
/* The modem is now trained */
|
||||
s->at_state.rx_signal_present = TRUE;
|
||||
s->at_state.rx_trained = TRUE;
|
||||
break;
|
||||
case PUTBIT_CARRIER_UP:
|
||||
case SIG_STATUS_CARRIER_UP:
|
||||
if (s->modem == T31_CNG_TONE || s->modem == T31_NOCNG_TONE || s->modem == T31_V21_RX)
|
||||
{
|
||||
s->at_state.rx_signal_present = TRUE;
|
||||
s->rx_frame_received = FALSE;
|
||||
}
|
||||
break;
|
||||
case PUTBIT_CARRIER_DOWN:
|
||||
case SIG_STATUS_CARRIER_DOWN:
|
||||
if (s->rx_frame_received)
|
||||
{
|
||||
if (s->at_state.dte_is_waiting)
|
||||
@@ -899,7 +899,7 @@ static void hdlc_rx_status(void *user_data, int status)
|
||||
s->at_state.rx_signal_present = FALSE;
|
||||
s->at_state.rx_trained = FALSE;
|
||||
break;
|
||||
case PUTBIT_FRAMING_OK:
|
||||
case SIG_STATUS_FRAMING_OK:
|
||||
if (s->modem == T31_CNG_TONE || s->modem == T31_NOCNG_TONE)
|
||||
{
|
||||
/* Once we get any valid HDLC the CNG tone stops, and we drop
|
||||
@@ -949,7 +949,7 @@ static void hdlc_rx_status(void *user_data, int status)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PUTBIT_ABORT:
|
||||
case SIG_STATUS_ABORT:
|
||||
/* Just ignore these */
|
||||
break;
|
||||
default:
|
||||
|
||||
+215
-139
@@ -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.139 2008/08/17 16:25:52 steveu Exp $
|
||||
* $Id: t38_gateway.c,v 1.142 2008/09/07 12:45:17 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -308,31 +308,31 @@ static void hdlc_underflow_handler(void *user_data)
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC underflow at %d\n", t->out);
|
||||
/* If the current HDLC buffer is not at the HDLC_FLAG_PROCEED_WITH_OUTPUT stage, this
|
||||
underflow must be an end of preamble condition. */
|
||||
if ((t->flags[t->out] & HDLC_FLAG_PROCEED_WITH_OUTPUT))
|
||||
if ((t->buf[t->out].flags & HDLC_FLAG_PROCEED_WITH_OUTPUT))
|
||||
{
|
||||
old_data_type = t->contents[t->out];
|
||||
t->len[t->out] = 0;
|
||||
t->flags[t->out] = 0;
|
||||
t->contents[t->out] = 0;
|
||||
old_data_type = t->buf[t->out].contents;
|
||||
t->buf[t->out].len = 0;
|
||||
t->buf[t->out].flags = 0;
|
||||
t->buf[t->out].contents = 0;
|
||||
if (++t->out >= T38_TX_HDLC_BUFS)
|
||||
t->out = 0;
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC next is 0x%X\n", t->contents[t->out]);
|
||||
if ((t->contents[t->out] & FLAG_INDICATOR))
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC next is 0x%X\n", t->buf[t->out].contents);
|
||||
if ((t->buf[t->out].contents & FLAG_INDICATOR))
|
||||
{
|
||||
/* The next thing in the queue is an indicator, so we need to stop this modem. */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC shutdown\n");
|
||||
hdlc_tx_frame(&s->audio.modems.hdlc_tx, NULL, 0);
|
||||
}
|
||||
else if ((t->contents[t->out] & FLAG_DATA))
|
||||
else if ((t->buf[t->out].contents & FLAG_DATA))
|
||||
{
|
||||
/* Check if we should start sending the next frame */
|
||||
if ((t->flags[t->out] & HDLC_FLAG_PROCEED_WITH_OUTPUT))
|
||||
if ((t->buf[t->out].flags & HDLC_FLAG_PROCEED_WITH_OUTPUT))
|
||||
{
|
||||
/* This frame is ready to go, and uses the same modem we are running now. So, send
|
||||
whatever we have. This might or might not be an entire frame. */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC start next frame\n");
|
||||
hdlc_tx_frame(&s->audio.modems.hdlc_tx, t->buf[t->out], t->len[t->out]);
|
||||
if ((t->flags[t->out] & HDLC_FLAG_CORRUPT_CRC))
|
||||
hdlc_tx_frame(&s->audio.modems.hdlc_tx, t->buf[t->out].buf, t->buf[t->out].len);
|
||||
if ((t->buf[t->out].flags & HDLC_FLAG_CORRUPT_CRC))
|
||||
hdlc_tx_corrupt_frame(&s->audio.modems.hdlc_tx);
|
||||
/*endif*/
|
||||
}
|
||||
@@ -355,9 +355,10 @@ static int set_next_tx_type(t38_gateway_state_t *s)
|
||||
|
||||
t = &s->audio.modems;
|
||||
u = &s->core.hdlc_to_modem;
|
||||
t38_non_ecm_buffer_report_output_status(&s->core.non_ecm_to_modem, &s->logging);
|
||||
if (t->next_tx_handler)
|
||||
{
|
||||
/* There is a handler queued, so that is the next one */
|
||||
/* 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;
|
||||
@@ -378,13 +379,13 @@ static int set_next_tx_type(t38_gateway_state_t *s)
|
||||
if (u->in == u->out)
|
||||
return FALSE;
|
||||
/*endif*/
|
||||
if ((u->contents[u->out] & FLAG_INDICATOR) == 0)
|
||||
if ((u->buf[u->out].contents & FLAG_INDICATOR) == 0)
|
||||
return FALSE;
|
||||
/*endif*/
|
||||
indicator = (u->contents[u->out] & 0xFF);
|
||||
u->len[u->out] = 0;
|
||||
u->flags[u->out] = 0;
|
||||
u->contents[u->out] = 0;
|
||||
indicator = (u->buf[u->out].contents & 0xFF);
|
||||
u->buf[u->out].len = 0;
|
||||
u->buf[u->out].flags = 0;
|
||||
u->buf[u->out].contents = 0;
|
||||
if (++u->out >= T38_TX_HDLC_BUFS)
|
||||
u->out = 0;
|
||||
/*endif*/
|
||||
@@ -437,7 +438,7 @@ static int set_next_tx_type(t38_gateway_state_t *s)
|
||||
hdlc_tx_init(&t->hdlc_tx, FALSE, 2, TRUE, hdlc_underflow_handler, s);
|
||||
hdlc_tx_flags(&t->hdlc_tx, 32);
|
||||
silence_gen_alter(&t->silence_gen, ms_to_samples(75));
|
||||
u->len[u->in] = 0;
|
||||
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;
|
||||
@@ -456,6 +457,7 @@ static int set_next_tx_type(t38_gateway_state_t *s)
|
||||
t->tx_bit_rate = 2400;
|
||||
break;
|
||||
}
|
||||
/*endswitch*/
|
||||
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);
|
||||
@@ -476,6 +478,7 @@ static int set_next_tx_type(t38_gateway_state_t *s)
|
||||
t->tx_bit_rate = 9600;
|
||||
break;
|
||||
}
|
||||
/*endswitch*/
|
||||
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);
|
||||
@@ -525,6 +528,7 @@ static int set_next_tx_type(t38_gateway_state_t *s)
|
||||
t->tx_bit_rate = 14400;
|
||||
break;
|
||||
}
|
||||
/*endswitch*/
|
||||
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);
|
||||
@@ -563,36 +567,41 @@ static int set_next_tx_type(t38_gateway_state_t *s)
|
||||
if (t->tx_bit_rate > 300)
|
||||
hdlc_tx_flags(&t->hdlc_tx, t->tx_bit_rate/(8*5));
|
||||
/*endif*/
|
||||
t38_non_ecm_buffer_report_status(&s->core.non_ecm_to_modem, &s->logging);
|
||||
t38_non_ecm_buffer_init(&s->core.non_ecm_to_modem, s->core.image_data_mode, s->core.min_row_bits);
|
||||
s->t38x.in_progress_rx_indicator = indicator;
|
||||
return TRUE;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void pump_out_final_hdlc(t38_gateway_state_t *s, int good_fcs)
|
||||
static void finalise_hdlc_frame(t38_gateway_state_t *s, int good_fcs)
|
||||
{
|
||||
if (!good_fcs)
|
||||
s->core.hdlc_to_modem.flags[s->core.hdlc_to_modem.in] |= HDLC_FLAG_CORRUPT_CRC;
|
||||
t38_gateway_hdlc_buf_t *hdlc_buf;
|
||||
|
||||
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
|
||||
if (!good_fcs || (hdlc_buf->flags & HDLC_FLAG_MISSING_DATA))
|
||||
hdlc_buf->flags |= HDLC_FLAG_CORRUPT_CRC;
|
||||
/*endif*/
|
||||
if (s->core.hdlc_to_modem.in == s->core.hdlc_to_modem.out)
|
||||
{
|
||||
/* This is the frame in progress at the output. */
|
||||
if ((s->core.hdlc_to_modem.flags[s->core.hdlc_to_modem.out] & HDLC_FLAG_PROCEED_WITH_OUTPUT) == 0)
|
||||
if ((hdlc_buf->flags & HDLC_FLAG_PROCEED_WITH_OUTPUT) == 0)
|
||||
{
|
||||
/* Output of this frame has not yet begun. Throw it all out now. */
|
||||
hdlc_tx_frame(&s->audio.modems.hdlc_tx, s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.out], s->core.hdlc_to_modem.len[s->core.hdlc_to_modem.out]);
|
||||
hdlc_tx_frame(&s->audio.modems.hdlc_tx, hdlc_buf->buf, hdlc_buf->len);
|
||||
}
|
||||
/*endif*/
|
||||
if ((s->core.hdlc_to_modem.flags[s->core.hdlc_to_modem.out] & HDLC_FLAG_CORRUPT_CRC))
|
||||
if ((hdlc_buf->flags & HDLC_FLAG_CORRUPT_CRC))
|
||||
hdlc_tx_corrupt_frame(&s->audio.modems.hdlc_tx);
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
s->core.hdlc_to_modem.flags[s->core.hdlc_to_modem.in] |= (HDLC_FLAG_PROCEED_WITH_OUTPUT | HDLC_FLAG_FINISHED);
|
||||
hdlc_buf->flags |= (HDLC_FLAG_PROCEED_WITH_OUTPUT | HDLC_FLAG_FINISHED);
|
||||
if (++s->core.hdlc_to_modem.in >= T38_TX_HDLC_BUFS)
|
||||
s->core.hdlc_to_modem.in = 0;
|
||||
/*endif*/
|
||||
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
|
||||
hdlc_buf->len = 0;
|
||||
hdlc_buf->flags = 0;
|
||||
hdlc_buf->contents = 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
@@ -853,53 +862,53 @@ static void monitor_control_messages(t38_gateway_state_t *s, int from_modem, uin
|
||||
static void queue_missing_indicator(t38_gateway_state_t *s, int data_type)
|
||||
{
|
||||
t38_core_state_t *t;
|
||||
int expected;
|
||||
int expected_alt;
|
||||
|
||||
t = &s->t38x.t38;
|
||||
expected = -1;
|
||||
expected_alt = -1;
|
||||
/* Missing packets might have lost us the indicator that should have put us in
|
||||
the required mode of operation. It might be a bit late to fill in such a gap
|
||||
now, but we should try. We may also want to force indicators into the queue,
|
||||
such as when the data says 'end of signal'. */
|
||||
/* We have an expectation of whether long or short training should occur, but be
|
||||
tolerant of either kind of indicator being present. */
|
||||
switch (data_type)
|
||||
{
|
||||
case T38_DATA_NONE:
|
||||
if (t->current_rx_indicator != T38_IND_NO_SIGNAL)
|
||||
process_rx_indicator(t, (void *) s, T38_IND_NO_SIGNAL);
|
||||
expected = T38_IND_NO_SIGNAL;
|
||||
break;
|
||||
case T38_DATA_V21:
|
||||
if (t->current_rx_indicator != T38_IND_V21_PREAMBLE)
|
||||
process_rx_indicator(t, (void *) s, T38_IND_V21_PREAMBLE);
|
||||
expected = T38_IND_V21_PREAMBLE;
|
||||
break;
|
||||
case T38_DATA_V27TER_2400:
|
||||
if (t->current_rx_indicator != T38_IND_V27TER_2400_TRAINING)
|
||||
process_rx_indicator(t, (void *) s, T38_IND_V27TER_2400_TRAINING);
|
||||
expected = T38_IND_V27TER_2400_TRAINING;
|
||||
break;
|
||||
case T38_DATA_V27TER_4800:
|
||||
if (t->current_rx_indicator != T38_IND_V27TER_4800_TRAINING)
|
||||
process_rx_indicator(t, (void *) s, T38_IND_V27TER_4800_TRAINING);
|
||||
expected = T38_IND_V27TER_4800_TRAINING;
|
||||
break;
|
||||
case T38_DATA_V29_7200:
|
||||
if (t->current_rx_indicator != T38_IND_V29_7200_TRAINING)
|
||||
process_rx_indicator(t, (void *) s, T38_IND_V29_7200_TRAINING);
|
||||
expected = T38_IND_V29_7200_TRAINING;
|
||||
break;
|
||||
case T38_DATA_V29_9600:
|
||||
if (t->current_rx_indicator != T38_IND_V29_9600_TRAINING)
|
||||
process_rx_indicator(t, (void *) s, T38_IND_V29_9600_TRAINING);
|
||||
expected = T38_IND_V29_9600_TRAINING;
|
||||
break;
|
||||
case T38_DATA_V17_7200:
|
||||
if (t->current_rx_indicator != T38_IND_V17_7200_SHORT_TRAINING && t->current_rx_indicator != T38_IND_V17_7200_LONG_TRAINING)
|
||||
process_rx_indicator(t, (void *) s, T38_IND_V17_7200_LONG_TRAINING);
|
||||
expected = (s->core.short_train) ? T38_IND_V17_7200_SHORT_TRAINING : T38_IND_V17_7200_LONG_TRAINING;
|
||||
expected_alt = (s->core.short_train) ? T38_IND_V17_7200_LONG_TRAINING : T38_IND_V17_7200_SHORT_TRAINING;
|
||||
break;
|
||||
case T38_DATA_V17_9600:
|
||||
if (t->current_rx_indicator != T38_IND_V17_9600_SHORT_TRAINING && t->current_rx_indicator != T38_IND_V17_9600_LONG_TRAINING)
|
||||
process_rx_indicator(t, (void *) s, T38_IND_V17_9600_LONG_TRAINING);
|
||||
expected = (s->core.short_train) ? T38_IND_V17_9600_SHORT_TRAINING : T38_IND_V17_9600_LONG_TRAINING;
|
||||
expected_alt = (s->core.short_train) ? T38_IND_V17_9600_LONG_TRAINING : T38_IND_V17_9600_SHORT_TRAINING;
|
||||
break;
|
||||
case T38_DATA_V17_12000:
|
||||
if (t->current_rx_indicator != T38_IND_V17_12000_SHORT_TRAINING && t->current_rx_indicator != T38_IND_V17_12000_LONG_TRAINING)
|
||||
process_rx_indicator(t, (void *) s, T38_IND_V17_12000_LONG_TRAINING);
|
||||
expected = (s->core.short_train) ? T38_IND_V17_12000_SHORT_TRAINING : T38_IND_V17_12000_LONG_TRAINING;
|
||||
expected_alt = (s->core.short_train) ? T38_IND_V17_12000_LONG_TRAINING : T38_IND_V17_12000_SHORT_TRAINING;
|
||||
break;
|
||||
case T38_DATA_V17_14400:
|
||||
if (t->current_rx_indicator != T38_IND_V17_14400_SHORT_TRAINING && t->current_rx_indicator != T38_IND_V17_14400_LONG_TRAINING)
|
||||
process_rx_indicator(t, (void *) s, T38_IND_V17_14400_LONG_TRAINING);
|
||||
expected = (s->core.short_train) ? T38_IND_V17_14400_SHORT_TRAINING : T38_IND_V17_14400_LONG_TRAINING;
|
||||
expected_alt = (s->core.short_train) ? T38_IND_V17_14400_LONG_TRAINING : T38_IND_V17_14400_SHORT_TRAINING;
|
||||
break;
|
||||
case T38_DATA_V8:
|
||||
break;
|
||||
@@ -914,6 +923,20 @@ static void queue_missing_indicator(t38_gateway_state_t *s, int data_type)
|
||||
case T38_DATA_V33_14400:
|
||||
break;
|
||||
}
|
||||
/*endswitch*/
|
||||
if (expected < 0)
|
||||
return;
|
||||
if (t->current_rx_indicator == expected)
|
||||
return;
|
||||
if (expected_alt >= 0 && t->current_rx_indicator == expected_alt)
|
||||
return;
|
||||
span_log(&s->logging,
|
||||
SPAN_LOG_FLOW,
|
||||
"Queuing missing indicator - %s\n",
|
||||
t38_indicator_to_str(expected));
|
||||
process_rx_indicator(t, (void *) s, expected);
|
||||
/* Force the indicator setting here, as the core won't set in when its missing. */
|
||||
t->current_rx_indicator = expected;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
@@ -922,7 +945,7 @@ static int process_rx_missing(t38_core_state_t *t, void *user_data, int rx_seq_n
|
||||
t38_gateway_state_t *s;
|
||||
|
||||
s = (t38_gateway_state_t *) user_data;
|
||||
s->core.hdlc_to_modem.flags[s->core.hdlc_to_modem.in] |= HDLC_FLAG_MISSING_DATA;
|
||||
s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in].flags |= HDLC_FLAG_MISSING_DATA;
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
@@ -933,23 +956,26 @@ static int process_rx_indicator(t38_core_state_t *t, void *user_data, int indica
|
||||
|
||||
s = (t38_gateway_state_t *) user_data;
|
||||
|
||||
t38_non_ecm_buffer_report_input_status(&s->core.non_ecm_to_modem, &s->logging);
|
||||
if (t->current_rx_indicator == indicator)
|
||||
{
|
||||
/* This is probably due to the far end repeating itself. Ignore it. Its harmless */
|
||||
return 0;
|
||||
}
|
||||
/*endif*/
|
||||
if (s->core.hdlc_to_modem.contents[s->core.hdlc_to_modem.in])
|
||||
if (s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in].contents)
|
||||
{
|
||||
if (++s->core.hdlc_to_modem.in >= T38_TX_HDLC_BUFS)
|
||||
s->core.hdlc_to_modem.in = 0;
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
s->core.hdlc_to_modem.contents[s->core.hdlc_to_modem.in] = (indicator | FLAG_INDICATOR);
|
||||
s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in].contents = (indicator | FLAG_INDICATOR);
|
||||
if (++s->core.hdlc_to_modem.in >= T38_TX_HDLC_BUFS)
|
||||
s->core.hdlc_to_modem.in = 0;
|
||||
/*endif*/
|
||||
t38_non_ecm_buffer_set_mode(&s->core.non_ecm_to_modem, s->core.image_data_mode, s->core.min_row_bits);
|
||||
|
||||
span_log(&s->logging,
|
||||
SPAN_LOG_FLOW,
|
||||
"Queued change - (%d) %s -> %s\n",
|
||||
@@ -967,9 +993,9 @@ static int process_rx_indicator(t38_core_state_t *t, void *user_data, int indica
|
||||
static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type, int field_type, const uint8_t *buf, int len)
|
||||
{
|
||||
int i;
|
||||
int previous;
|
||||
t38_gateway_state_t *s;
|
||||
t38_gateway_t38_state_t *xx;
|
||||
t38_gateway_hdlc_buf_t *hdlc_buf;
|
||||
|
||||
s = (t38_gateway_state_t *) user_data;
|
||||
xx = &s->t38x;
|
||||
@@ -977,46 +1003,52 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
||||
{
|
||||
case T38_FIELD_HDLC_DATA:
|
||||
xx->current_rx_field_class = T38_FIELD_CLASS_HDLC;
|
||||
if (s->core.hdlc_to_modem.contents[s->core.hdlc_to_modem.in] != (data_type | FLAG_DATA))
|
||||
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
|
||||
if (hdlc_buf->contents != (data_type | FLAG_DATA))
|
||||
{
|
||||
queue_missing_indicator(s, data_type);
|
||||
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
|
||||
}
|
||||
/*endif*/
|
||||
previous = s->core.hdlc_to_modem.len[s->core.hdlc_to_modem.in];
|
||||
/* Check if this data would overflow the buffer. */
|
||||
if (s->core.hdlc_to_modem.len[s->core.hdlc_to_modem.in] + len > T38_MAX_HDLC_LEN)
|
||||
if (hdlc_buf->len + len > T38_MAX_HDLC_LEN)
|
||||
break;
|
||||
/*endif*/
|
||||
s->core.hdlc_to_modem.contents[s->core.hdlc_to_modem.in] = (data_type | FLAG_DATA);
|
||||
bit_reverse(&s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in][s->core.hdlc_to_modem.len[s->core.hdlc_to_modem.in]], buf, len);
|
||||
hdlc_buf->contents = (data_type | FLAG_DATA);
|
||||
bit_reverse(&hdlc_buf->buf[hdlc_buf->len], buf, len);
|
||||
/* We need to send out the control messages as they are arriving. They are
|
||||
too slow to capture a whole frame, and then pass it on.
|
||||
too slow to capture a whole frame before starting to pass it on.
|
||||
For the faster frames, take in the whole frame before sending it out. Also, there
|
||||
is no need to monitor, or modify, the contents of the faster frames. */
|
||||
if (data_type == T38_DATA_V21)
|
||||
{
|
||||
for (i = 1; i <= len; i++)
|
||||
edit_control_messages(s, 0, s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in], s->core.hdlc_to_modem.len[s->core.hdlc_to_modem.in] + i);
|
||||
edit_control_messages(s, 0, hdlc_buf->buf, hdlc_buf->len + i);
|
||||
/*endfor*/
|
||||
/* Don't start pumping data into the actual output stream until there is
|
||||
enough backlog to create some elasticity for jitter tolerance. */
|
||||
if (s->core.hdlc_to_modem.len[s->core.hdlc_to_modem.in] + len >= HDLC_START_BUFFER_LEVEL)
|
||||
if (hdlc_buf->len + len >= HDLC_START_BUFFER_LEVEL)
|
||||
{
|
||||
if (s->core.hdlc_to_modem.in == s->core.hdlc_to_modem.out)
|
||||
{
|
||||
if ((s->core.hdlc_to_modem.flags[s->core.hdlc_to_modem.in] & HDLC_FLAG_PROCEED_WITH_OUTPUT) == 0)
|
||||
previous = 0;
|
||||
/* Output is not running, so kick it into life. */
|
||||
if ((hdlc_buf->flags & HDLC_FLAG_PROCEED_WITH_OUTPUT) == 0)
|
||||
hdlc_tx_frame(&s->audio.modems.hdlc_tx, hdlc_buf->buf, hdlc_buf->len + len);
|
||||
else
|
||||
hdlc_tx_frame(&s->audio.modems.hdlc_tx, hdlc_buf->buf + hdlc_buf->len, len);
|
||||
/*endif*/
|
||||
hdlc_tx_frame(&s->audio.modems.hdlc_tx, s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.out] + previous, s->core.hdlc_to_modem.len[s->core.hdlc_to_modem.out] - previous + len);
|
||||
}
|
||||
/*endif*/
|
||||
s->core.hdlc_to_modem.flags[s->core.hdlc_to_modem.in] |= HDLC_FLAG_PROCEED_WITH_OUTPUT;
|
||||
hdlc_buf->flags |= HDLC_FLAG_PROCEED_WITH_OUTPUT;
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
s->core.hdlc_to_modem.len[s->core.hdlc_to_modem.in] += len;
|
||||
s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in].len += len;
|
||||
break;
|
||||
case T38_FIELD_HDLC_FCS_OK:
|
||||
xx->current_rx_field_class = T38_FIELD_CLASS_HDLC;
|
||||
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
|
||||
if (len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_OK!\n");
|
||||
@@ -1027,22 +1059,22 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
||||
/* Some T.38 implementations send multiple T38_FIELD_HDLC_FCS_OK messages, in IFP packets with
|
||||
incrementing sequence numbers, which are actually repeats. They get through to this point because
|
||||
of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */
|
||||
if (t->current_rx_data_type != data_type
|
||||
||
|
||||
t->current_rx_field_type != field_type)
|
||||
if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC frame type %s - CRC good\n", t30_frametype(s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in][2]));
|
||||
if (s->core.hdlc_to_modem.contents[s->core.hdlc_to_modem.in] != (data_type | FLAG_DATA))
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC frame type %s - CRC good\n", t30_frametype(hdlc_buf->buf[2]));
|
||||
if (hdlc_buf->contents != (data_type | FLAG_DATA))
|
||||
{
|
||||
queue_missing_indicator(s, data_type);
|
||||
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
|
||||
}
|
||||
/*endif*/
|
||||
s->core.hdlc_to_modem.contents[s->core.hdlc_to_modem.in] = (data_type | FLAG_DATA);
|
||||
if (data_type == T38_DATA_V21)
|
||||
{
|
||||
if ((s->core.hdlc_to_modem.flags[s->core.hdlc_to_modem.in] & HDLC_FLAG_MISSING_DATA) == 0)
|
||||
if ((hdlc_buf->flags & HDLC_FLAG_MISSING_DATA) == 0)
|
||||
{
|
||||
monitor_control_messages(s, FALSE, s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in], s->core.hdlc_to_modem.len[s->core.hdlc_to_modem.in]);
|
||||
monitor_control_messages(s, FALSE, hdlc_buf->buf, hdlc_buf->len);
|
||||
if (s->core.real_time_frame_handler)
|
||||
s->core.real_time_frame_handler(s, s->core.real_time_frame_user_data, FALSE, s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in], s->core.hdlc_to_modem.len[s->core.hdlc_to_modem.in]);
|
||||
s->core.real_time_frame_handler(s, s->core.real_time_frame_user_data, FALSE, hdlc_buf->buf, hdlc_buf->len);
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
@@ -1050,21 +1082,21 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
||||
else
|
||||
{
|
||||
/* Make sure we go back to short training if CTC/CTR has kicked us into
|
||||
long training. Theer has to be more than one value HDLC frame in a
|
||||
chunk of image data, so just setting short training mode heer should
|
||||
long training. There has to be more than one value HDLC frame in a
|
||||
chunk of image data, so just setting short training mode here should
|
||||
be enough. */
|
||||
s->core.short_train = TRUE;
|
||||
}
|
||||
/*endif*/
|
||||
pump_out_final_hdlc(s, (s->core.hdlc_to_modem.flags[s->core.hdlc_to_modem.in] & HDLC_FLAG_MISSING_DATA) == 0);
|
||||
hdlc_buf->contents = (data_type | FLAG_DATA);
|
||||
finalise_hdlc_frame(s, TRUE);
|
||||
}
|
||||
/*endif*/
|
||||
s->core.hdlc_to_modem.len[s->core.hdlc_to_modem.in] = 0;
|
||||
s->core.hdlc_to_modem.flags[s->core.hdlc_to_modem.in] = 0;
|
||||
xx->corrupt_current_frame[0] = FALSE;
|
||||
break;
|
||||
case T38_FIELD_HDLC_FCS_BAD:
|
||||
xx->current_rx_field_class = T38_FIELD_CLASS_HDLC;
|
||||
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
|
||||
if (len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_BAD!\n");
|
||||
@@ -1077,24 +1109,32 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
||||
of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */
|
||||
if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC frame type %s - CRC bad\n", t30_frametype(s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in][2]));
|
||||
if (s->core.hdlc_to_modem.contents[s->core.hdlc_to_modem.in] != (data_type | FLAG_DATA))
|
||||
queue_missing_indicator(s, data_type);
|
||||
/*endif*/
|
||||
if (s->core.hdlc_to_modem.len[s->core.hdlc_to_modem.in] > 0)
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC frame type %s - CRC bad\n", t30_frametype(hdlc_buf->buf[2]));
|
||||
/* Only bother with frames that have a bad CRC, if they also have some content. */
|
||||
if (hdlc_buf->len > 0)
|
||||
{
|
||||
s->core.hdlc_to_modem.contents[s->core.hdlc_to_modem.in] = (data_type | FLAG_DATA);
|
||||
pump_out_final_hdlc(s, FALSE);
|
||||
if (hdlc_buf->contents != (data_type | FLAG_DATA))
|
||||
{
|
||||
queue_missing_indicator(s, data_type);
|
||||
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
|
||||
}
|
||||
/*endif*/
|
||||
hdlc_buf->contents = (data_type | FLAG_DATA);
|
||||
finalise_hdlc_frame(s, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Just restart using the current frame buffer */
|
||||
hdlc_buf->contents = 0;
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
s->core.hdlc_to_modem.len[s->core.hdlc_to_modem.in] = 0;
|
||||
s->core.hdlc_to_modem.flags[s->core.hdlc_to_modem.in] = 0;
|
||||
xx->corrupt_current_frame[0] = FALSE;
|
||||
break;
|
||||
case T38_FIELD_HDLC_FCS_OK_SIG_END:
|
||||
xx->current_rx_field_class = T38_FIELD_CLASS_HDLC;
|
||||
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
|
||||
if (len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_OK_SIG_END!\n");
|
||||
@@ -1107,23 +1147,35 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
||||
of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */
|
||||
if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC frame type %s - CRC OK, sig end\n", t30_frametype(s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in][2]));
|
||||
if (s->core.hdlc_to_modem.contents[s->core.hdlc_to_modem.in] != (data_type | FLAG_DATA))
|
||||
queue_missing_indicator(s, data_type);
|
||||
/*endif*/
|
||||
s->core.hdlc_to_modem.contents[s->core.hdlc_to_modem.in] = (data_type | FLAG_DATA);
|
||||
if (data_type == T38_DATA_V21 && (s->core.hdlc_to_modem.flags[s->core.hdlc_to_modem.in] & HDLC_FLAG_MISSING_DATA) == 0)
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC frame type %s - CRC OK, sig end\n", t30_frametype(hdlc_buf->buf[2]));
|
||||
if (hdlc_buf->contents != (data_type | FLAG_DATA))
|
||||
{
|
||||
monitor_control_messages(s, FALSE, s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in], s->core.hdlc_to_modem.len[s->core.hdlc_to_modem.in]);
|
||||
if (s->core.real_time_frame_handler)
|
||||
s->core.real_time_frame_handler(s, s->core.real_time_frame_user_data, FALSE, s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in], s->core.hdlc_to_modem.len[s->core.hdlc_to_modem.in]);
|
||||
/*endif*/
|
||||
queue_missing_indicator(s, data_type);
|
||||
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
|
||||
}
|
||||
/*endif*/
|
||||
pump_out_final_hdlc(s, (s->core.hdlc_to_modem.flags[s->core.hdlc_to_modem.in] & HDLC_FLAG_MISSING_DATA) == 0);
|
||||
s->core.hdlc_to_modem.len[s->core.hdlc_to_modem.in] = 0;
|
||||
s->core.hdlc_to_modem.flags[s->core.hdlc_to_modem.in] = 0;
|
||||
s->core.hdlc_to_modem.contents[s->core.hdlc_to_modem.in] = 0;
|
||||
if (data_type == T38_DATA_V21)
|
||||
{
|
||||
if ((hdlc_buf->flags & HDLC_FLAG_MISSING_DATA) == 0)
|
||||
{
|
||||
monitor_control_messages(s, FALSE, hdlc_buf->buf, hdlc_buf->len);
|
||||
if (s->core.real_time_frame_handler)
|
||||
s->core.real_time_frame_handler(s, s->core.real_time_frame_user_data, FALSE, hdlc_buf->buf, hdlc_buf->len);
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Make sure we go back to short training if CTC/CTR has kicked us into
|
||||
long training. There has to be more than one value HDLC frame in a
|
||||
chunk of image data, so just setting short training mode here should
|
||||
be enough. */
|
||||
s->core.short_train = TRUE;
|
||||
}
|
||||
/*endif*/
|
||||
hdlc_buf->contents = (data_type | FLAG_DATA);
|
||||
finalise_hdlc_frame(s, TRUE);
|
||||
queue_missing_indicator(s, T38_DATA_NONE);
|
||||
xx->current_rx_field_class = T38_FIELD_CLASS_NONE;
|
||||
}
|
||||
@@ -1132,6 +1184,7 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
||||
break;
|
||||
case T38_FIELD_HDLC_FCS_BAD_SIG_END:
|
||||
xx->current_rx_field_class = T38_FIELD_CLASS_HDLC;
|
||||
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
|
||||
if (len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_FCS_BAD_SIG_END!\n");
|
||||
@@ -1144,19 +1197,25 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
||||
of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */
|
||||
if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC frame type %s - CRC bad, sig end\n", t30_frametype(s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in][2]));
|
||||
if (s->core.hdlc_to_modem.contents[s->core.hdlc_to_modem.in] != (data_type | FLAG_DATA))
|
||||
queue_missing_indicator(s, data_type);
|
||||
/*endif*/
|
||||
if (s->core.hdlc_to_modem.len[s->core.hdlc_to_modem.in] > 0)
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC frame type %s - CRC bad, sig end\n", t30_frametype(hdlc_buf->buf[2]));
|
||||
if (hdlc_buf->contents != (data_type | FLAG_DATA))
|
||||
{
|
||||
s->core.hdlc_to_modem.contents[s->core.hdlc_to_modem.in] = (data_type | FLAG_DATA);
|
||||
pump_out_final_hdlc(s, FALSE);
|
||||
queue_missing_indicator(s, data_type);
|
||||
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
|
||||
}
|
||||
/*endif*/
|
||||
/* Only bother with frames that have a bad CRC, if they also have some content. */
|
||||
if (hdlc_buf->len > 0)
|
||||
{
|
||||
hdlc_buf->contents = (data_type | FLAG_DATA);
|
||||
finalise_hdlc_frame(s, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Just restart using the current frame buffer */
|
||||
hdlc_buf->contents = 0;
|
||||
}
|
||||
/*endif*/
|
||||
s->core.hdlc_to_modem.len[s->core.hdlc_to_modem.in] = 0;
|
||||
s->core.hdlc_to_modem.flags[s->core.hdlc_to_modem.in] = 0;
|
||||
s->core.hdlc_to_modem.contents[s->core.hdlc_to_modem.in] = 0;
|
||||
queue_missing_indicator(s, T38_DATA_NONE);
|
||||
xx->current_rx_field_class = T38_FIELD_CLASS_NONE;
|
||||
}
|
||||
@@ -1164,6 +1223,7 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
||||
xx->corrupt_current_frame[0] = FALSE;
|
||||
break;
|
||||
case T38_FIELD_HDLC_SIG_END:
|
||||
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
|
||||
if (len > 0)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "There is data in a T38_FIELD_HDLC_SIG_END!\n");
|
||||
@@ -1176,8 +1236,11 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
||||
of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */
|
||||
if (t->current_rx_data_type != data_type || t->current_rx_field_type != field_type)
|
||||
{
|
||||
if (s->core.hdlc_to_modem.contents[s->core.hdlc_to_modem.in] != (data_type | FLAG_DATA))
|
||||
if (hdlc_buf->contents != (data_type | FLAG_DATA))
|
||||
{
|
||||
queue_missing_indicator(s, data_type);
|
||||
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
|
||||
}
|
||||
/* WORKAROUND: At least some Mediatrix boxes have a bug, where they can send this message at the
|
||||
end of non-ECM data. We need to tolerate this. */
|
||||
if (xx->current_rx_field_class == T38_FIELD_CLASS_NON_ECM)
|
||||
@@ -1190,10 +1253,12 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
||||
{
|
||||
/* This message is expected under 2 circumstances. One is as an alternative to T38_FIELD_HDLC_FCS_OK_SIG_END -
|
||||
i.e. they send T38_FIELD_HDLC_FCS_OK, and then T38_FIELD_HDLC_SIG_END when the carrier actually drops.
|
||||
The other is because the HDLC signal drops unexpectedly - i.e. not just after a final frame. */
|
||||
s->core.hdlc_to_modem.len[s->core.hdlc_to_modem.in] = 0;
|
||||
s->core.hdlc_to_modem.flags[s->core.hdlc_to_modem.in] = 0;
|
||||
s->core.hdlc_to_modem.contents[s->core.hdlc_to_modem.in] = 0;
|
||||
The other is because the HDLC signal drops unexpectedly - i.e. not just after a final frame. In
|
||||
this case we just clear out any partial frame data that might be in the buffer. */
|
||||
/* TODO: what if any junk in the buffer has reached the HDLC_FLAG_PROCEED_WITH_OUTPUT stage? */
|
||||
hdlc_buf->len = 0;
|
||||
hdlc_buf->flags = 0;
|
||||
hdlc_buf->contents = 0;
|
||||
}
|
||||
/*endif*/
|
||||
queue_missing_indicator(s, T38_DATA_NONE);
|
||||
@@ -1204,12 +1269,17 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
||||
break;
|
||||
case T38_FIELD_T4_NON_ECM_DATA:
|
||||
xx->current_rx_field_class = T38_FIELD_CLASS_NON_ECM;
|
||||
if (s->core.hdlc_to_modem.contents[s->core.hdlc_to_modem.in] != (data_type | FLAG_DATA))
|
||||
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
|
||||
if (hdlc_buf->contents != (data_type | FLAG_DATA))
|
||||
{
|
||||
queue_missing_indicator(s, data_type);
|
||||
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
|
||||
}
|
||||
t38_non_ecm_buffer_inject(&s->core.non_ecm_to_modem, buf, len);
|
||||
xx->corrupt_current_frame[0] = FALSE;
|
||||
break;
|
||||
case T38_FIELD_T4_NON_ECM_SIG_END:
|
||||
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
|
||||
/* Some T.38 implementations send multiple T38_FIELD_T4_NON_ECM_SIG_END messages, in IFP packets with
|
||||
incrementing sequence numbers, which are actually repeats. They get through to this point because
|
||||
of the incrementing sequence numbers. We need to filter them here in a context sensitive manner. */
|
||||
@@ -1222,14 +1292,20 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
||||
{
|
||||
if (len > 0)
|
||||
{
|
||||
if (s->core.hdlc_to_modem.contents[s->core.hdlc_to_modem.in] != (data_type | FLAG_DATA))
|
||||
if (hdlc_buf->contents != (data_type | FLAG_DATA))
|
||||
{
|
||||
queue_missing_indicator(s, data_type);
|
||||
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
|
||||
}
|
||||
/*endif*/
|
||||
t38_non_ecm_buffer_inject(&s->core.non_ecm_to_modem, buf, len);
|
||||
}
|
||||
/*endif*/
|
||||
if (s->core.hdlc_to_modem.contents[s->core.hdlc_to_modem.in] != (data_type | FLAG_DATA))
|
||||
if (hdlc_buf->contents != (data_type | FLAG_DATA))
|
||||
{
|
||||
queue_missing_indicator(s, data_type);
|
||||
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
|
||||
}
|
||||
/*endif*/
|
||||
/* Don't flow control the data any more. Just pump out the remainder as fast as we can. */
|
||||
t38_non_ecm_buffer_push(&s->core.non_ecm_to_modem);
|
||||
@@ -1237,12 +1313,16 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
||||
else
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "T38_FIELD_NON_ECM_SIG_END received at the end of HDLC data!\n");
|
||||
if (s->core.hdlc_to_modem.contents[s->core.hdlc_to_modem.in] != (data_type | FLAG_DATA))
|
||||
if (s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in].contents != (data_type | FLAG_DATA))
|
||||
{
|
||||
queue_missing_indicator(s, data_type);
|
||||
hdlc_buf = &s->core.hdlc_to_modem.buf[s->core.hdlc_to_modem.in];
|
||||
}
|
||||
/*endif*/
|
||||
s->core.hdlc_to_modem.len[s->core.hdlc_to_modem.in] = 0;
|
||||
s->core.hdlc_to_modem.flags[s->core.hdlc_to_modem.in] = 0;
|
||||
s->core.hdlc_to_modem.contents[s->core.hdlc_to_modem.in] = 0;
|
||||
/* TODO: what if any junk in the buffer has reached the HDLC_FLAG_PROCEED_WITH_OUTPUT stage? */
|
||||
hdlc_buf->len = 0;
|
||||
hdlc_buf->flags = 0;
|
||||
hdlc_buf->contents = 0;
|
||||
}
|
||||
/*endif*/
|
||||
queue_missing_indicator(s, T38_DATA_NONE);
|
||||
@@ -1408,27 +1488,27 @@ static void non_ecm_rx_status(void *user_data, int status)
|
||||
s = (t38_gateway_state_t *) user_data;
|
||||
switch (status)
|
||||
{
|
||||
case PUTBIT_TRAINING_IN_PROGRESS:
|
||||
case SIG_STATUS_TRAINING_IN_PROGRESS:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Non-ECM carrier training in progress\n");
|
||||
if (s->core.tcf_mode_predictable_modem_start)
|
||||
s->core.tcf_mode_predictable_modem_start = 0;
|
||||
else
|
||||
announce_training(s);
|
||||
break;
|
||||
case PUTBIT_TRAINING_FAILED:
|
||||
case SIG_STATUS_TRAINING_FAILED:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Non-ECM carrier training failed\n");
|
||||
break;
|
||||
case PUTBIT_TRAINING_SUCCEEDED:
|
||||
case SIG_STATUS_TRAINING_SUCCEEDED:
|
||||
/* The modem is now trained */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Non-ECM carrier trained\n");
|
||||
s->audio.modems.rx_signal_present = TRUE;
|
||||
s->audio.modems.rx_trained = TRUE;
|
||||
to_t38_buffer_init(&s->core.to_t38);
|
||||
break;
|
||||
case PUTBIT_CARRIER_UP:
|
||||
case SIG_STATUS_CARRIER_UP:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Non-ECM carrier up\n");
|
||||
break;
|
||||
case PUTBIT_CARRIER_DOWN:
|
||||
case SIG_STATUS_CARRIER_DOWN:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Non-ECM carrier down\n");
|
||||
s->core.tcf_mode_predictable_modem_start = 0;
|
||||
switch (s->t38x.current_tx_data_type)
|
||||
@@ -1573,26 +1653,23 @@ static void hdlc_rx_status(hdlc_rx_state_t *t, int status)
|
||||
t38_gateway_state_t *s;
|
||||
|
||||
s = (t38_gateway_state_t *) t->user_data;
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC carrier status is %s (%d)\n", signal_status_to_str(status), status);
|
||||
switch (status)
|
||||
{
|
||||
case PUTBIT_TRAINING_IN_PROGRESS:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC carrier training in progress\n");
|
||||
case SIG_STATUS_TRAINING_IN_PROGRESS:
|
||||
announce_training(s);
|
||||
break;
|
||||
case PUTBIT_TRAINING_FAILED:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC carrier training failed\n");
|
||||
case SIG_STATUS_TRAINING_FAILED:
|
||||
break;
|
||||
case PUTBIT_TRAINING_SUCCEEDED:
|
||||
case SIG_STATUS_TRAINING_SUCCEEDED:
|
||||
/* The modem is now trained. */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC carrier trained\n");
|
||||
s->audio.modems.rx_signal_present = TRUE;
|
||||
s->audio.modems.rx_trained = TRUE;
|
||||
/* Behave like HDLC preamble has been announced. */
|
||||
t->framing_ok_announced = TRUE;
|
||||
to_t38_buffer_init(&s->core.to_t38);
|
||||
break;
|
||||
case PUTBIT_CARRIER_UP:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC carrier up\n");
|
||||
case SIG_STATUS_CARRIER_UP:
|
||||
/* Reset the HDLC receiver. */
|
||||
t->raw_bit_stream = 0;
|
||||
t->len = 0;
|
||||
@@ -1601,8 +1678,7 @@ static void hdlc_rx_status(hdlc_rx_state_t *t, int status)
|
||||
t->framing_ok_announced = FALSE;
|
||||
to_t38_buffer_init(&s->core.to_t38);
|
||||
break;
|
||||
case PUTBIT_CARRIER_DOWN:
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "HDLC carrier down\n");
|
||||
case SIG_STATUS_CARRIER_DOWN:
|
||||
if (t->framing_ok_announced)
|
||||
{
|
||||
t38_core_send_data(&s->t38x.t38, s->t38x.current_tx_data_type, T38_FIELD_HDLC_SIG_END, NULL, 0, s->t38x.t38.data_end_tx_count);
|
||||
|
||||
@@ -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_non_ecm_buffer.c,v 1.1 2008/08/14 14:06:05 steveu Exp $
|
||||
* $Id: t38_non_ecm_buffer.c,v 1.3 2008/09/07 12:45:17 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -59,6 +59,21 @@
|
||||
|
||||
#include "spandsp/t38_non_ecm_buffer.h"
|
||||
|
||||
static void restart_buffer(t38_non_ecm_buffer_state_t *s)
|
||||
{
|
||||
/* This should be called when draining the buffer is complete, which should
|
||||
occur before any fresh data can possibly arrive to begin refilling it. */
|
||||
s->octet = 0xFF;
|
||||
s->flow_control_fill_octet = 0xFF;
|
||||
s->at_initial_all_ones = TRUE;
|
||||
s->bit_stream = 0xFFFF;
|
||||
s->out_ptr = 0;
|
||||
s->in_ptr = 0;
|
||||
s->latest_eol_ptr = 0;
|
||||
s->data_finished = FALSE;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
int t38_non_ecm_buffer_get_bit(void *user_data)
|
||||
{
|
||||
t38_non_ecm_buffer_state_t *s;
|
||||
@@ -80,12 +95,8 @@ int t38_non_ecm_buffer_get_bit(void *user_data)
|
||||
{
|
||||
/* The queue is empty, and we have received the end of data signal. This must
|
||||
really be the end to transmission. */
|
||||
s->data_finished = FALSE;
|
||||
/* Reset the data pointers for next time. */
|
||||
s->out_ptr = 0;
|
||||
s->in_ptr = 0;
|
||||
s->latest_eol_ptr = 0;
|
||||
return PUTBIT_END_OF_DATA;
|
||||
restart_buffer(s);
|
||||
return SIG_STATUS_END_OF_DATA;
|
||||
}
|
||||
/* The queue is blocked, but this does not appear to be the end of the data. Idle with
|
||||
fill octets, which should be safe at this point. */
|
||||
@@ -160,10 +171,11 @@ void t38_non_ecm_buffer_inject(t38_non_ecm_buffer_state_t *s, const uint8_t *buf
|
||||
rough approach. */
|
||||
while (s->row_bits < s->min_row_bits)
|
||||
{
|
||||
s->min_row_bits_fill_octets++;
|
||||
s->data[s->in_ptr] = 0;
|
||||
s->row_bits += 8;
|
||||
/* TODO: We can't buffer overflow, since we wrap around. However, the tail could overwrite
|
||||
itself if things fall badly behind. */
|
||||
/* TODO: We can't buffer overflow, since we wrap around. However, the tail could
|
||||
overwrite itself if things fall badly behind. */
|
||||
s->in_ptr = (s->in_ptr + 1) & (T38_NON_ECM_TX_BUF_LEN - 1);
|
||||
}
|
||||
/* Start a new row */
|
||||
@@ -205,28 +217,47 @@ void t38_non_ecm_buffer_inject(t38_non_ecm_buffer_state_t *s, const uint8_t *buf
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
void t38_non_ecm_buffer_report_status(t38_non_ecm_buffer_state_t *s, logging_state_t *logging)
|
||||
void t38_non_ecm_buffer_report_input_status(t38_non_ecm_buffer_state_t *s, logging_state_t *logging)
|
||||
{
|
||||
if (s->in_octets || s->out_octets)
|
||||
if (s->in_octets || s->min_row_bits_fill_octets)
|
||||
{
|
||||
span_log(logging,
|
||||
SPAN_LOG_FLOW,
|
||||
"%d incoming non-ECM octets, %d rows. %d outgoing non-ECM octets, %d rows\n",
|
||||
"%d+%d incoming non-ECM octets, %d rows.\n",
|
||||
s->in_octets,
|
||||
s->in_rows,
|
||||
s->out_octets,
|
||||
s->out_rows);
|
||||
s->min_row_bits_fill_octets,
|
||||
s->in_rows);
|
||||
s->in_octets = 0;
|
||||
s->in_rows = 0;
|
||||
s->min_row_bits_fill_octets = 0;
|
||||
}
|
||||
if (s->flow_control_fill_octets)
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
void t38_non_ecm_buffer_report_output_status(t38_non_ecm_buffer_state_t *s, logging_state_t *logging)
|
||||
{
|
||||
if (s->out_octets || s->flow_control_fill_octets)
|
||||
{
|
||||
span_log(logging,
|
||||
SPAN_LOG_FLOW,
|
||||
"Non-ECM flow control generated %d octets\n",
|
||||
s->flow_control_fill_octets);
|
||||
"%d+%d outgoing non-ECM octets, %d rows.\n",
|
||||
s->out_octets - s->flow_control_fill_octets,
|
||||
s->flow_control_fill_octets,
|
||||
s->out_rows);
|
||||
s->out_octets = 0;
|
||||
s->out_rows = 0;
|
||||
s->flow_control_fill_octets = 0;
|
||||
}
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
void t38_non_ecm_buffer_set_mode(t38_non_ecm_buffer_state_t *s, int mode, int min_row_bits)
|
||||
{
|
||||
s->image_data_mode = mode;
|
||||
s->min_row_bits = min_row_bits;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
t38_non_ecm_buffer_state_t *t38_non_ecm_buffer_init(t38_non_ecm_buffer_state_t *s, int mode, int min_row_bits)
|
||||
{
|
||||
memset(s, 0, sizeof(*s));
|
||||
|
||||
@@ -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.100 2008/08/13 14:55:51 steveu Exp $
|
||||
* $Id: t38_terminal.c,v 1.101 2008/09/07 12:45:17 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -192,7 +192,7 @@ static int process_rx_indicator(t38_core_state_t *t, void *user_data, int indica
|
||||
&&
|
||||
(fe->current_rx_type == T30_MODEM_V21 || fe->current_rx_type == T30_MODEM_CNG))
|
||||
{
|
||||
t30_hdlc_accept(&s->t30, NULL, PUTBIT_CARRIER_DOWN, TRUE);
|
||||
t30_hdlc_accept(&s->t30, NULL, SIG_STATUS_CARRIER_DOWN, TRUE);
|
||||
}
|
||||
fe->timeout_rx_samples = 0;
|
||||
t30_front_end_status(&s->t30, T30_FRONT_END_SIGNAL_ABSENT);
|
||||
@@ -357,7 +357,7 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC OK, sig end (%s)\n", (fe->hdlc_rx.len >= 3) ? t30_frametype(fe->hdlc_rx.buf[2]) : "???", (fe->rx_data_missing) ? "missing octets" : "clean");
|
||||
t30_hdlc_accept(&s->t30, fe->hdlc_rx.buf, fe->hdlc_rx.len, !fe->rx_data_missing);
|
||||
t30_hdlc_accept(&s->t30, NULL, PUTBIT_CARRIER_DOWN, TRUE);
|
||||
t30_hdlc_accept(&s->t30, NULL, SIG_STATUS_CARRIER_DOWN, TRUE);
|
||||
}
|
||||
fe->hdlc_rx.len = 0;
|
||||
fe->rx_data_missing = FALSE;
|
||||
@@ -377,7 +377,7 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Type %s - CRC bad, sig end (%s)\n", (fe->hdlc_rx.len >= 3) ? t30_frametype(fe->hdlc_rx.buf[2]) : "???", (fe->rx_data_missing) ? "missing octets" : "clean");
|
||||
t30_hdlc_accept(&s->t30, fe->hdlc_rx.buf, fe->hdlc_rx.len, FALSE);
|
||||
t30_hdlc_accept(&s->t30, NULL, PUTBIT_CARRIER_DOWN, TRUE);
|
||||
t30_hdlc_accept(&s->t30, NULL, SIG_STATUS_CARRIER_DOWN, TRUE);
|
||||
}
|
||||
fe->hdlc_rx.len = 0;
|
||||
fe->rx_data_missing = FALSE;
|
||||
@@ -410,7 +410,7 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
||||
case T38_FIELD_T4_NON_ECM_DATA:
|
||||
if (!fe->rx_signal_present)
|
||||
{
|
||||
t30_non_ecm_put_bit(&s->t30, PUTBIT_TRAINING_SUCCEEDED);
|
||||
t30_non_ecm_put_bit(&s->t30, SIG_STATUS_TRAINING_SUCCEEDED);
|
||||
fe->rx_signal_present = TRUE;
|
||||
}
|
||||
bit_reverse(buf2, buf, len);
|
||||
@@ -427,7 +427,7 @@ static int process_rx_data(t38_core_state_t *t, void *user_data, int data_type,
|
||||
{
|
||||
if (!fe->rx_signal_present)
|
||||
{
|
||||
t30_non_ecm_put_bit(&s->t30, PUTBIT_TRAINING_SUCCEEDED);
|
||||
t30_non_ecm_put_bit(&s->t30, SIG_STATUS_TRAINING_SUCCEEDED);
|
||||
fe->rx_signal_present = TRUE;
|
||||
}
|
||||
bit_reverse(buf2, buf, len);
|
||||
|
||||
@@ -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.112 2008/07/22 13:48:15 steveu Exp $
|
||||
* $Id: t4.c,v 1.113 2008/09/07 12:45:17 steveu Exp $
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -1963,7 +1963,7 @@ int t4_tx_get_bit(t4_state_t *s)
|
||||
int bit;
|
||||
|
||||
if (s->bit_ptr >= s->image_size)
|
||||
return PUTBIT_END_OF_DATA;
|
||||
return SIG_STATUS_END_OF_DATA;
|
||||
bit = (s->image_buffer[s->bit_ptr] >> (7 - s->bit_pos)) & 1;
|
||||
if (--s->bit_pos < 0)
|
||||
{
|
||||
@@ -1999,7 +1999,7 @@ int t4_tx_check_bit(t4_state_t *s)
|
||||
int bit;
|
||||
|
||||
if (s->bit_ptr >= s->image_size)
|
||||
return PUTBIT_END_OF_DATA;
|
||||
return SIG_STATUS_END_OF_DATA;
|
||||
bit = (s->image_buffer[s->bit_ptr] >> s->bit_pos) & 1;
|
||||
return bit;
|
||||
}
|
||||
|
||||
+67
-53
@@ -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.c,v 1.112 2008/07/17 19:12:27 steveu Exp $
|
||||
* $Id: v17rx.c,v 1.116 2008/09/07 12:45:17 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -471,44 +471,14 @@ static int decode_baud(v17_rx_state_t *s, complexf_t *z)
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||
static __inline__ void symbol_sync(v17_rx_state_t *s)
|
||||
{
|
||||
static const complexf_t cdba[4] =
|
||||
{
|
||||
{ 6.0f, 2.0f},
|
||||
{-2.0f, 6.0f},
|
||||
{ 2.0f, -6.0f},
|
||||
{-6.0f, -2.0f}
|
||||
};
|
||||
complexf_t z;
|
||||
complexf_t zz;
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
const complexi_t *target;
|
||||
#else
|
||||
const complexf_t *target;
|
||||
#endif
|
||||
int i;
|
||||
float v;
|
||||
float p;
|
||||
int bit;
|
||||
int i;
|
||||
int j;
|
||||
int32_t angle;
|
||||
int32_t ang;
|
||||
int constellation_state;
|
||||
|
||||
/* This routine processes every half a baud, as we put things into the equalizer at the T/2 rate.
|
||||
This routine adapts the position of the half baud samples, which the caller takes. */
|
||||
/* This routine adapts the position of the half baud samples entering the equalizer. */
|
||||
|
||||
/* Add a sample to the equalizer's circular buffer, but don't calculate anything
|
||||
at this time. */
|
||||
s->eq_buf[s->eq_step] = *sample;
|
||||
s->eq_step = (s->eq_step + 1) & V17_EQUALIZER_MASK;
|
||||
|
||||
/* On alternate insertions we have a whole baud and must process it. */
|
||||
if ((s->baud_half ^= 1))
|
||||
return;
|
||||
|
||||
/* Symbol timing synchronisation */
|
||||
/* 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 +502,48 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||
s->eq_put_step += i;
|
||||
s->total_baud_timing_correction += i;
|
||||
}
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||
{
|
||||
static const complexf_t cdba[4] =
|
||||
{
|
||||
{ 6.0f, 2.0f},
|
||||
{-2.0f, 6.0f},
|
||||
{ 2.0f, -6.0f},
|
||||
{-6.0f, -2.0f}
|
||||
};
|
||||
complexf_t z;
|
||||
complexf_t zz;
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
const complexi_t *target;
|
||||
static const complexi16_t zero = {0, 0};
|
||||
#else
|
||||
const complexf_t *target;
|
||||
static const complexf_t zero = {0, 0};
|
||||
#endif
|
||||
float p;
|
||||
int bit;
|
||||
int i;
|
||||
int j;
|
||||
int32_t angle;
|
||||
int32_t ang;
|
||||
int constellation_state;
|
||||
|
||||
/* This routine processes every half a baud, as we put things into the equalizer at the T/2 rate. */
|
||||
|
||||
/* Add a sample to the equalizer's circular buffer, but don't calculate anything
|
||||
at this time. */
|
||||
s->eq_buf[s->eq_step] = *sample;
|
||||
s->eq_step = (s->eq_step + 1) & V17_EQUALIZER_MASK;
|
||||
|
||||
/* On alternate insertions we have a whole baud and must process it. */
|
||||
if ((s->baud_half ^= 1))
|
||||
return;
|
||||
|
||||
/* Symbol timing synchronisation */
|
||||
symbol_sync(s);
|
||||
|
||||
z = equalizer_get(s);
|
||||
|
||||
@@ -545,7 +557,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||
break;
|
||||
case TRAINING_STAGE_SYMBOL_ACQUISITION:
|
||||
/* Allow time for the symbol synchronisation to settle the symbol timing. */
|
||||
target = &z;
|
||||
target = &zero;
|
||||
#if defined(IAXMODEM_STUFF)
|
||||
if (++s->training_count >= 100)
|
||||
#else
|
||||
@@ -562,7 +574,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||
break;
|
||||
case TRAINING_STAGE_LOG_PHASE:
|
||||
/* Record the current alternate phase angle */
|
||||
target = &z;
|
||||
target = &zero;
|
||||
angle = arctan2(z.im, z.re);
|
||||
s->training_count = 1;
|
||||
if (s->short_train)
|
||||
@@ -603,7 +615,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||
}
|
||||
break;
|
||||
case TRAINING_STAGE_WAIT_FOR_CDBA:
|
||||
target = &z;
|
||||
target = &zero;
|
||||
angle = arctan2(z.im, z.re);
|
||||
/* Look for the initial ABAB sequence to display a phase reversal, which will
|
||||
signal the start of the scrambled CDBA segment */
|
||||
@@ -665,7 +677,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||
/* Park this modem */
|
||||
s->agc_scaling_save = 0.0f;
|
||||
s->training_stage = TRAINING_STAGE_PARKED;
|
||||
report_status_change(s, PUTBIT_TRAINING_FAILED);
|
||||
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -684,7 +696,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||
descramble(s, 1);
|
||||
s->training_count = 1;
|
||||
s->training_stage = TRAINING_STAGE_COARSE_TRAIN_ON_CDBA;
|
||||
report_status_change(s, PUTBIT_TRAINING_IN_PROGRESS);
|
||||
report_status_change(s, SIG_STATUS_TRAINING_IN_PROGRESS);
|
||||
break;
|
||||
}
|
||||
if (++s->training_count > V17_TRAINING_SEG_1_LEN)
|
||||
@@ -695,7 +707,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||
/* Park this modem */
|
||||
s->agc_scaling_save = 0.0f;
|
||||
s->training_stage = TRAINING_STAGE_PARKED;
|
||||
report_status_change(s, PUTBIT_TRAINING_FAILED);
|
||||
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
||||
}
|
||||
break;
|
||||
case TRAINING_STAGE_COARSE_TRAIN_ON_CDBA:
|
||||
@@ -767,7 +779,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||
/* Park this modem */
|
||||
s->agc_scaling_save = 0.0f;
|
||||
s->training_stage = TRAINING_STAGE_PARKED;
|
||||
report_status_change(s, PUTBIT_TRAINING_FAILED);
|
||||
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -806,8 +818,8 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||
of a real training sequence. Note that this might be TEP. */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n");
|
||||
/* Park this modem */
|
||||
report_status_change(s, PUTBIT_TRAINING_FAILED);
|
||||
s->training_stage = TRAINING_STAGE_PARKED;
|
||||
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
||||
}
|
||||
break;
|
||||
case TRAINING_STAGE_SHORT_TRAIN_ON_CDBA_AND_TEST:
|
||||
@@ -836,14 +848,14 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||
{
|
||||
s->training_count = 0;
|
||||
s->training_stage = TRAINING_STAGE_TCM_WINDUP;
|
||||
report_status_change(s, PUTBIT_TRAINING_IN_PROGRESS);
|
||||
report_status_change(s, SIG_STATUS_TRAINING_IN_PROGRESS);
|
||||
}
|
||||
else
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Short training failed (convergence failed)\n");
|
||||
/* Park this modem */
|
||||
report_status_change(s, PUTBIT_TRAINING_FAILED);
|
||||
s->training_stage = TRAINING_STAGE_PARKED;
|
||||
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -883,7 +895,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||
{
|
||||
/* We are up and running */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Training succeeded (constellation mismatch %f)\n", s->training_error);
|
||||
report_status_change(s, PUTBIT_TRAINING_SUCCEEDED);
|
||||
report_status_change(s, SIG_STATUS_TRAINING_SUCCEEDED);
|
||||
/* Apply some lag to the carrier off condition, to ensure the last few bits get pushed through
|
||||
the processing. */
|
||||
s->signal_present = 60;
|
||||
@@ -899,8 +911,8 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||
/* Park this modem */
|
||||
if (!s->short_train)
|
||||
s->agc_scaling_save = 0.0f;
|
||||
report_status_change(s, PUTBIT_TRAINING_FAILED);
|
||||
s->training_stage = TRAINING_STAGE_PARKED;
|
||||
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -908,7 +920,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
||||
default:
|
||||
/* We failed to train! */
|
||||
/* Park here until the carrier drops. */
|
||||
target = &z;
|
||||
target = &zero;
|
||||
break;
|
||||
}
|
||||
if (s->qam_report)
|
||||
@@ -979,7 +991,7 @@ int v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
|
||||
/* Count down a short delay, to ensure we push the last
|
||||
few bits through the filters before stopping. */
|
||||
v17_rx_restart(s, s->bit_rate, s->short_train);
|
||||
report_status_change(s, PUTBIT_CARRIER_DOWN);
|
||||
report_status_change(s, SIG_STATUS_CARRIER_DOWN);
|
||||
continue;
|
||||
}
|
||||
#if defined(IAXMODEM_STUFF)
|
||||
@@ -998,7 +1010,7 @@ int v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
|
||||
#if defined(IAXMODEM_STUFF)
|
||||
s->carrier_drop_pending = FALSE;
|
||||
#endif
|
||||
report_status_change(s, PUTBIT_CARRIER_UP);
|
||||
report_status_change(s, SIG_STATUS_CARRIER_UP);
|
||||
}
|
||||
if (s->training_stage == TRAINING_STAGE_PARKED)
|
||||
continue;
|
||||
@@ -1051,20 +1063,22 @@ int v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
|
||||
for (j = 1; j < V17_RX_FILTER_STEPS; j++)
|
||||
zi.im += (int32_t) rx_pulseshaper[step][j].im*(int32_t) s->rrc_filter[j + s->rrc_filter_step];
|
||||
sample.im = zi.im*s->agc_scaling;
|
||||
s->eq_put_step += RX_PULSESHAPER_COEFF_SETS*10/(3*2);
|
||||
z = dds_lookup_complexf(s->carrier_phase);
|
||||
zz.re = sample.re*z.re - sample.im*z.im;
|
||||
zz.im = -sample.re*z.im - sample.im*z.re;
|
||||
process_half_baud(s, &zz);
|
||||
#else
|
||||
zz.im = rx_pulseshaper[step][0].im*s->rrc_filter[s->rrc_filter_step];
|
||||
for (j = 1; j < V17_RX_FILTER_STEPS; j++)
|
||||
zz.im += rx_pulseshaper[step][j].im*s->rrc_filter[j + s->rrc_filter_step];
|
||||
sample.im = zz.im*s->agc_scaling;
|
||||
#endif
|
||||
s->eq_put_step += RX_PULSESHAPER_COEFF_SETS*10/(3*2);
|
||||
/* Shift to baseband - since this is done in a full complex form, the
|
||||
result is clean, and requires no further filtering, apart from the
|
||||
equalizer. */
|
||||
z = dds_lookup_complexf(s->carrier_phase);
|
||||
zz.re = sample.re*z.re - sample.im*z.im;
|
||||
zz.im = -sample.re*z.im - sample.im*z.re;
|
||||
process_half_baud(s, &zz);
|
||||
#endif
|
||||
}
|
||||
dds_advancef(&(s->carrier_phase), s->carrier_phase_rate);
|
||||
}
|
||||
|
||||
@@ -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.62 2008/07/16 14:23:47 steveu Exp $
|
||||
* $Id: v17tx.c,v 1.64 2008/09/07 12:45:17 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -222,19 +222,19 @@ static __inline__ complexf_t getbaud(v17_tx_state_t *s)
|
||||
if (s->training_step == V17_TRAINING_SHUTDOWN_END)
|
||||
{
|
||||
if (s->status_handler)
|
||||
s->status_handler(s->status_user_data, MODEM_TX_STATUS_SHUTDOWN_COMPLETE);
|
||||
s->status_handler(s->status_user_data, SIG_STATUS_SHUTDOWN_COMPLETE);
|
||||
}
|
||||
}
|
||||
}
|
||||
bits = 0;
|
||||
for (i = 0; i < s->bits_per_symbol; i++)
|
||||
{
|
||||
if ((bit = s->current_get_bit(s->get_bit_user_data)) == PUTBIT_END_OF_DATA)
|
||||
if ((bit = s->current_get_bit(s->get_bit_user_data)) == SIG_STATUS_END_OF_DATA)
|
||||
{
|
||||
/* End of real data. Switch to the fake get_bit routine, until we
|
||||
have shut down completely. */
|
||||
if (s->status_handler)
|
||||
s->status_handler(s->status_user_data, MODEM_TX_STATUS_DATA_EXHAUSTED);
|
||||
s->status_handler(s->status_user_data, SIG_STATUS_END_OF_DATA);
|
||||
s->current_get_bit = fake_get_bit;
|
||||
s->in_training = TRUE;
|
||||
bit = 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: v22bis_rx.c,v 1.40 2008/07/25 13:56:54 steveu Exp $
|
||||
* $Id: v22bis_rx.c,v 1.41 2008/09/07 12:45:17 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -607,7 +607,7 @@ int v22bis_rx(v22bis_state_t *s, const int16_t amp[], int len)
|
||||
if (power < s->rx.carrier_off_power)
|
||||
{
|
||||
v22bis_rx_restart(s, s->bit_rate);
|
||||
s->put_bit(s->user_data, PUTBIT_CARRIER_DOWN);
|
||||
s->put_bit(s->user_data, SIG_STATUS_CARRIER_DOWN);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -617,7 +617,7 @@ int v22bis_rx(v22bis_state_t *s, const int16_t amp[], int len)
|
||||
if (power < s->rx.carrier_on_power)
|
||||
continue;
|
||||
s->rx.signal_present = TRUE;
|
||||
s->put_bit(s->user_data, PUTBIT_CARRIER_UP);
|
||||
s->put_bit(s->user_data, SIG_STATUS_CARRIER_UP);
|
||||
}
|
||||
if (s->rx.training != V22BIS_TRAINING_STAGE_PARKED)
|
||||
{
|
||||
|
||||
@@ -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.43 2008/07/02 14:48:26 steveu Exp $
|
||||
* $Id: v22bis_tx.c,v 1.44 2008/09/07 12:45:17 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -302,7 +302,7 @@ static __inline__ int get_scrambled_bit(v22bis_state_t *s)
|
||||
{
|
||||
int bit;
|
||||
|
||||
if ((bit = s->tx.current_get_bit(s->user_data)) == PUTBIT_END_OF_DATA)
|
||||
if ((bit = s->tx.current_get_bit(s->user_data)) == SIG_STATUS_END_OF_DATA)
|
||||
{
|
||||
/* Fill out this symbol with ones, and prepare to send
|
||||
the rest of the shutdown sequence. */
|
||||
|
||||
+217
-47
@@ -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.c,v 1.97 2008/08/04 14:03:17 steveu Exp $
|
||||
* $Id: v27ter_rx.c,v 1.101 2008/09/08 13:13:29 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -48,6 +48,8 @@
|
||||
#include "spandsp/complex.h"
|
||||
#include "spandsp/vector_float.h"
|
||||
#include "spandsp/complex_vector_float.h"
|
||||
#include "spandsp/vector_int.h"
|
||||
#include "spandsp/complex_vector_int.h"
|
||||
#include "spandsp/async.h"
|
||||
#include "spandsp/power_meter.h"
|
||||
#include "spandsp/arctan2.h"
|
||||
@@ -72,6 +74,11 @@
|
||||
#define CARRIER_NOMINAL_FREQ 1800.0f
|
||||
#define EQUALIZER_DELTA 0.25f
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
#define FP_FACTOR 4096
|
||||
#define FP_SHIFT_FACTOR 12
|
||||
#endif
|
||||
|
||||
/* Segments of the training sequence */
|
||||
/* V.27ter defines a long and a short sequence. FAX doesn't use the
|
||||
short sequence, so it is not implemented here. */
|
||||
@@ -90,17 +97,31 @@ enum
|
||||
TRAINING_STAGE_PARKED
|
||||
};
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
static const complexi16_t v27ter_constellation[8] =
|
||||
{
|
||||
{((int)(FP_FACTOR* 1.414f), ((int)(FP_FACTOR* 0.0f)}, /* 0deg */
|
||||
{((int)(FP_FACTOR* 1.0f), ((int)(FP_FACTOR* 1.0f)}, /* 45deg */
|
||||
{((int)(FP_FACTOR* 0.0f), ((int)(FP_FACTOR* 1.414f)}, /* 90deg */
|
||||
{((int)(FP_FACTOR*-1.0f), ((int)(FP_FACTOR* 1.0f)}, /* 135deg */
|
||||
{((int)(FP_FACTOR*-1.414f), ((int)(FP_FACTOR* 0.0f)}, /* 180deg */
|
||||
{((int)(FP_FACTOR*-1.0f), ((int)(FP_FACTOR*-1.0f)}, /* 225deg */
|
||||
{((int)(FP_FACTOR* 0.0f), ((int)(FP_FACTOR*-1.414f)}, /* 270deg */
|
||||
{((int)(FP_FACTOR* 1.0f), ((int)(FP_FACTOR*-1.0f)} /* 315deg */
|
||||
};
|
||||
#else
|
||||
static const complexf_t v27ter_constellation[8] =
|
||||
{
|
||||
{ 1.414f, 0.0f}, /* 0deg */
|
||||
{ 1.0f, 1.0f}, /* 45deg */
|
||||
{ 0.0f, 1.414f}, /* 90deg */
|
||||
{-1.0f, 1.0f}, /* 135deg */
|
||||
{-1.414f, 0.0f}, /* 180deg */
|
||||
{-1.0f, -1.0f}, /* 225deg */
|
||||
{ 0.0f, -1.414f}, /* 270deg */
|
||||
{ 1.0f, -1.0f} /* 315deg */
|
||||
{ 1.414f, 0.0f}, /* 0deg */
|
||||
{ 1.0f, 1.0f}, /* 45deg */
|
||||
{ 0.0f, 1.414f}, /* 90deg */
|
||||
{-1.0f, 1.0f}, /* 135deg */
|
||||
{-1.414f, 0.0f}, /* 180deg */
|
||||
{-1.0f, -1.0f}, /* 225deg */
|
||||
{ 0.0f, -1.414f}, /* 270deg */
|
||||
{ 1.0f, -1.0f} /* 315deg */
|
||||
};
|
||||
#endif
|
||||
|
||||
float v27ter_rx_carrier_frequency(v27ter_rx_state_t *s)
|
||||
{
|
||||
@@ -149,14 +170,23 @@ static void report_status_change(v27ter_rx_state_t *s, int status)
|
||||
|
||||
static void equalizer_save(v27ter_rx_state_t *s)
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
cvec_copyi16(s->eq_coeff_save, s->eq_coeff, V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN);
|
||||
#else
|
||||
cvec_copyf(s->eq_coeff_save, s->eq_coeff, V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN);
|
||||
#endif
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void equalizer_restore(v27ter_rx_state_t *s)
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
cvec_copyi16(s->eq_coeff, s->eq_coeff_save, V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN);
|
||||
cvec_zeroi16(s->eq_buf, V27TER_EQUALIZER_MASK);
|
||||
#else
|
||||
cvec_copyf(s->eq_coeff, s->eq_coeff_save, V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN);
|
||||
cvec_zerof(s->eq_buf, V27TER_EQUALIZER_MASK);
|
||||
#endif
|
||||
|
||||
s->eq_put_step = (s->bit_rate == 4800) ? RX_PULSESHAPER_4800_COEFF_SETS*5/2 : RX_PULSESHAPER_2400_COEFF_SETS*20/(3*2);
|
||||
s->eq_step = 0;
|
||||
@@ -166,10 +196,16 @@ static void equalizer_restore(v27ter_rx_state_t *s)
|
||||
|
||||
static void equalizer_reset(v27ter_rx_state_t *s)
|
||||
{
|
||||
/* Start with an equalizer based on everything being perfect */
|
||||
/* Start with an equalizer based on everything being perfect. */
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
cvec_zeroi16(s->eq_coeff, V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN);
|
||||
s->eq_coeff[V27TER_EQUALIZER_PRE_LEN] = complex_seti16(1.414f*FP_FACTOR, 0);
|
||||
cvec_zeroi16(s->eq_buf, V27TER_EQUALIZER_MASK);
|
||||
#else
|
||||
cvec_zerof(s->eq_coeff, V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN);
|
||||
s->eq_coeff[V27TER_EQUALIZER_PRE_LEN] = complex_setf(1.414f, 0.0f);
|
||||
cvec_zerof(s->eq_buf, V27TER_EQUALIZER_MASK);
|
||||
#endif
|
||||
|
||||
s->eq_put_step = (s->bit_rate == 4800) ? RX_PULSESHAPER_4800_COEFF_SETS*5/2 : RX_PULSESHAPER_2400_COEFF_SETS*20/(3*2);
|
||||
s->eq_step = 0;
|
||||
@@ -177,60 +213,122 @@ static void equalizer_reset(v27ter_rx_state_t *s)
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
static __inline__ complexi16_t complex_mul_q4_12(const complexi16_t *x, const complexi16_t *y)
|
||||
{
|
||||
complexi16_t z;
|
||||
|
||||
z.re = ((int32_t) x->re*(int32_t) y->re - (int32_t) x->im*(int32_t) y->im) >> 12;
|
||||
z.im = ((int32_t) x->re*(int32_t) y->im + (int32_t) x->im*(int32_t) y->re) >> 12;
|
||||
return z;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
#endif
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
static __inline__ complexi16_t equalizer_get(v27ter_rx_state_t *s)
|
||||
#else
|
||||
static __inline__ complexf_t equalizer_get(v27ter_rx_state_t *s)
|
||||
#endif
|
||||
{
|
||||
int i;
|
||||
int p;
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
complexi16_t z;
|
||||
complexi16_t z1;
|
||||
#else
|
||||
complexf_t z;
|
||||
complexf_t z1;
|
||||
#endif
|
||||
|
||||
/* Get the next equalized value. */
|
||||
z = complex_setf(0.0f, 0.0f);
|
||||
p = s->eq_step - 1;
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
z = complex_seti16(0, 0);
|
||||
for (i = 0; i < V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN; i++)
|
||||
{
|
||||
p = (p - 1) & V27TER_EQUALIZER_MASK;
|
||||
z1 = complex_mul_q4_12(&s->eq_coeff[i], &s->eq_buf[p]);
|
||||
z = complex_addi16(&z, &z1);
|
||||
}
|
||||
#else
|
||||
z = complex_setf(0.0f, 0.0f);
|
||||
for (i = 0; i < V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN; i++)
|
||||
{
|
||||
p = (p - 1) & V27TER_EQUALIZER_MASK;
|
||||
z1 = complex_mulf(&s->eq_coeff[i], &s->eq_buf[p]);
|
||||
z = complex_addf(&z, &z1);
|
||||
}
|
||||
#endif
|
||||
return z;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
static void tune_equalizer(v27ter_rx_state_t *s, const complexi16_t *z, const complexi16_t *target)
|
||||
#else
|
||||
static void tune_equalizer(v27ter_rx_state_t *s, const complexf_t *z, const complexf_t *target)
|
||||
#endif
|
||||
{
|
||||
int i;
|
||||
int p;
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
complexi16_t ez;
|
||||
complexi16_t z1;
|
||||
#else
|
||||
complexf_t ez;
|
||||
complexf_t z1;
|
||||
#endif
|
||||
|
||||
/* Find the x and y mismatch from the exact constellation position. */
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
ez.re = target->re*FP_FACTOR - z->re;
|
||||
ez.im = target->im*FP_FACTOR - z->im;
|
||||
ez.re = ((int32_t) ez.re*(int32_t) s->eq_delta) >> 15;
|
||||
ez.im = ((int32_t) ez.im*(int32_t) s->eq_delta) >> 15;
|
||||
#else
|
||||
ez = complex_subf(target, z);
|
||||
ez.re *= s->eq_delta;
|
||||
ez.im *= s->eq_delta;
|
||||
#endif
|
||||
|
||||
p = s->eq_step - 1;
|
||||
for (i = 0; i < V27TER_EQUALIZER_PRE_LEN + 1 + V27TER_EQUALIZER_POST_LEN; i++)
|
||||
{
|
||||
p = (p - 1) & V27TER_EQUALIZER_MASK;
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
z1 = complex_conji16(&s->eq_buf[p]);
|
||||
z1 = complex_mul_q4_12(&ez, &z1);
|
||||
s->eq_coeff[i] = complex_addi16(&s->eq_coeff[i], &z1);
|
||||
#else
|
||||
z1 = complex_conjf(&s->eq_buf[p]);
|
||||
z1 = complex_mulf(&ez, &z1);
|
||||
s->eq_coeff[i] = complex_addf(&s->eq_coeff[i], &z1);
|
||||
/* Leak a little to tame uncontrolled wandering */
|
||||
s->eq_coeff[i].re *= 0.9999f;
|
||||
s->eq_coeff[i].im *= 0.9999f;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
static __inline__ void track_carrier(v27ter_rx_state_t *s, const complexi16_t *z, const complexi16_t *target)
|
||||
#else
|
||||
static __inline__ void track_carrier(v27ter_rx_state_t *s, const complexf_t *z, const complexf_t *target)
|
||||
#endif
|
||||
{
|
||||
float error;
|
||||
|
||||
/* For small errors the imaginary part of the difference between the actual and the target
|
||||
positions is proportional to the phase error, for any particular target. However, the
|
||||
different amplitudes of the various target positions scale things. */
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
error = z->im*target->re - z->re*target->im;
|
||||
error /= (float) FP_FACTOR;
|
||||
#else
|
||||
error = z->im*target->re - z->re*target->im;
|
||||
#endif
|
||||
|
||||
s->carrier_phase_rate += (int32_t) (s->carrier_track_i*error);
|
||||
s->carrier_phase += (int32_t) (s->carrier_track_p*error);
|
||||
@@ -295,7 +393,11 @@ static __inline__ void put_bit(v27ter_rx_state_t *s, int bit)
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
static __inline__ int find_quadrant(const complexi16_t *z)
|
||||
#else
|
||||
static __inline__ int find_quadrant(const complexf_t *z)
|
||||
#endif
|
||||
{
|
||||
int b1;
|
||||
int b2;
|
||||
@@ -307,7 +409,11 @@ static __inline__ int find_quadrant(const complexf_t *z)
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
static __inline__ int find_octant(complexi16_t *z)
|
||||
#else
|
||||
static __inline__ int find_octant(complexf_t *z)
|
||||
#endif
|
||||
{
|
||||
float abs_re;
|
||||
float abs_im;
|
||||
@@ -336,7 +442,11 @@ static __inline__ int find_octant(complexf_t *z)
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
static void decode_baud(v27ter_rx_state_t *s, complexi16_t *z)
|
||||
#else
|
||||
static void decode_baud(v27ter_rx_state_t *s, complexf_t *z)
|
||||
#endif
|
||||
{
|
||||
static const uint8_t phase_steps_4800[8] =
|
||||
{
|
||||
@@ -381,33 +491,12 @@ static void decode_baud(v27ter_rx_state_t *s, complexf_t *z)
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t *sample)
|
||||
static __inline__ void symbol_sync(v27ter_rx_state_t *s)
|
||||
{
|
||||
static const int abab_pos[2] =
|
||||
{
|
||||
0, 4
|
||||
};
|
||||
complexf_t z;
|
||||
complexf_t zz;
|
||||
float p;
|
||||
float q;
|
||||
int i;
|
||||
int j;
|
||||
int32_t angle;
|
||||
int32_t ang;
|
||||
|
||||
/* Add a sample to the equalizer's circular buffer, but don't calculate anything
|
||||
at this time. */
|
||||
s->eq_buf[s->eq_step] = *sample;
|
||||
s->eq_step = (s->eq_step + 1) & V27TER_EQUALIZER_MASK;
|
||||
|
||||
/* On alternate insertions we have a whole baud, and must process it. */
|
||||
if ((s->baud_phase ^= 1))
|
||||
{
|
||||
//span_log(&s->logging, SPAN_LOG_FLOW, "Samp, %f, %f, %f, -1, 0x%X\n", z.re, z.im, sqrtf(z.re*z.re + z.im*z.im), s->eq_put_step);
|
||||
return;
|
||||
}
|
||||
//span_log(&s->logging, SPAN_LOG_FLOW, "Samp, %f, %f, %f, 1, 0x%X\n", z.re, z.im, sqrtf(z.re*z.re + z.im*z.im), s->eq_put_step);
|
||||
/* This routine adapts the position of the half baud samples entering the equalizer. */
|
||||
|
||||
/* Perform a Gardner test for baud alignment */
|
||||
p = s->eq_buf[(s->eq_step - 3) & V27TER_EQUALIZER_MASK].re
|
||||
@@ -433,6 +522,37 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
|
||||
s->gardner_integrate = 0;
|
||||
}
|
||||
//span_log(&s->logging, SPAN_LOG_FLOW, "Gardner=%10.5f 0x%X\n", p, s->eq_put_step);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexi16_t *sample)
|
||||
#else
|
||||
static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t *sample)
|
||||
#endif
|
||||
{
|
||||
static const int abab_pos[2] =
|
||||
{
|
||||
0, 4
|
||||
};
|
||||
complexf_t z;
|
||||
complexf_t zz;
|
||||
float p;
|
||||
int i;
|
||||
int j;
|
||||
int32_t angle;
|
||||
int32_t ang;
|
||||
|
||||
/* Add a sample to the equalizer's circular buffer, but don't calculate anything
|
||||
at this time. */
|
||||
s->eq_buf[s->eq_step] = *sample;
|
||||
s->eq_step = (s->eq_step + 1) & V27TER_EQUALIZER_MASK;
|
||||
|
||||
/* On alternate insertions we have a whole baud, and must process it. */
|
||||
if ((s->baud_half ^= 1))
|
||||
return;
|
||||
|
||||
symbol_sync(s);
|
||||
|
||||
z = equalizer_get(s);
|
||||
|
||||
@@ -498,7 +618,7 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n");
|
||||
/* Park this modem */
|
||||
s->training_stage = TRAINING_STAGE_PARKED;
|
||||
report_status_change(s, PUTBIT_TRAINING_FAILED);
|
||||
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -506,9 +626,20 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
|
||||
buffer, as well as the carrier phase, for this to play out nicely. */
|
||||
angle += 0x80000000;
|
||||
p = angle*2.0f*3.14159f/(65536.0f*65536.0f);
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
zz = complex_setf(cosf(p), -sinf(p));
|
||||
for (i = 0; i <= V27TER_EQUALIZER_MASK; i++)
|
||||
{
|
||||
z1 = complex_setf(s->eq_buf[i].re, s->eq_buf[i].im);
|
||||
z1 = complex_mulf(&z1, &zz);
|
||||
s->eq_buf[i].re = z1.re;
|
||||
s->eq_buf[i].im = z1.im;
|
||||
}
|
||||
#else
|
||||
zz = complex_setf(cosf(p), -sinf(p));
|
||||
for (i = 0; i <= V27TER_EQUALIZER_MASK; i++)
|
||||
s->eq_buf[i] = complex_mulf(&s->eq_buf[i], &zz);
|
||||
#endif
|
||||
s->carrier_phase += angle;
|
||||
|
||||
s->gardner_step = 2;
|
||||
@@ -519,7 +650,7 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
|
||||
descramble(s, 1);
|
||||
s->training_count = 1;
|
||||
s->training_stage = TRAINING_STAGE_TRAIN_ON_ABAB;
|
||||
report_status_change(s, PUTBIT_TRAINING_IN_PROGRESS);
|
||||
report_status_change(s, SIG_STATUS_TRAINING_IN_PROGRESS);
|
||||
}
|
||||
else if (++s->training_count > V27TER_TRAINING_SEG_3_LEN)
|
||||
{
|
||||
@@ -528,7 +659,7 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n");
|
||||
/* Park this modem */
|
||||
s->training_stage = TRAINING_STAGE_PARKED;
|
||||
report_status_change(s, PUTBIT_TRAINING_FAILED);
|
||||
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
||||
}
|
||||
break;
|
||||
case TRAINING_STAGE_TRAIN_ON_ABAB:
|
||||
@@ -552,11 +683,22 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
|
||||
case TRAINING_STAGE_TEST_ONES:
|
||||
decode_baud(s, &z);
|
||||
/* Measure the training error */
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
z1.re = z.re/(float) FP_FACTOR;
|
||||
z1.im = z.im/(float) FP_FACTOR;
|
||||
if (s->bit_rate == 4800)
|
||||
zz = complex_subf(&z, &v27ter_constellation[s->constellation_state]);
|
||||
else
|
||||
zz = complex_subf(&z, &v27ter_constellation[s->constellation_state << 1]);
|
||||
zz = complex_subf(&z1, &zz);
|
||||
s->training_error += powerf(&zz);
|
||||
#else
|
||||
if (s->bit_rate == 4800)
|
||||
zz = complex_subf(&z, &v27ter_constellation[s->constellation_state]);
|
||||
else
|
||||
zz = complex_subf(&z, &v27ter_constellation[s->constellation_state << 1]);
|
||||
s->training_error += powerf(&zz);
|
||||
#endif
|
||||
if (++s->training_count >= V27TER_TRAINING_SEG_6_LEN)
|
||||
{
|
||||
if ((s->bit_rate == 4800 && s->training_error < 0.5f)
|
||||
@@ -565,7 +707,7 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
|
||||
{
|
||||
/* We are up and running */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Training succeeded (constellation mismatch %f)\n", s->training_error);
|
||||
report_status_change(s, PUTBIT_TRAINING_SUCCEEDED);
|
||||
report_status_change(s, SIG_STATUS_TRAINING_SUCCEEDED);
|
||||
/* Apply some lag to the carrier off condition, to ensure the last few bits get pushed through
|
||||
the processing. */
|
||||
s->signal_present = (s->bit_rate == 4800) ? 90 : 120;
|
||||
@@ -580,7 +722,7 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (constellation mismatch %f)\n", s->training_error);
|
||||
/* Park this modem */
|
||||
s->training_stage = TRAINING_STAGE_PARKED;
|
||||
report_status_change(s, PUTBIT_TRAINING_FAILED);
|
||||
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -591,10 +733,21 @@ static __inline__ void process_half_baud(v27ter_rx_state_t *s, const complexf_t
|
||||
}
|
||||
if (s->qam_report)
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
z1.re = z.re/(float) FP_FACTOR;
|
||||
z1.im = z.im/(float) FP_FACTOR;
|
||||
zz.re = v27ter_constellation[s->constellation_state].re;
|
||||
zz.im = v27ter_constellation[s->constellation_state].im;
|
||||
s->qam_report(s->qam_user_data,
|
||||
&z1,
|
||||
&zz,
|
||||
s->constellation_state);
|
||||
#else
|
||||
s->qam_report(s->qam_user_data,
|
||||
&z,
|
||||
&v27ter_constellation[s->constellation_state],
|
||||
s->constellation_state);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
@@ -607,10 +760,15 @@ int v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], int len)
|
||||
int16_t x;
|
||||
int32_t diff;
|
||||
complexf_t z;
|
||||
complexf_t zz;
|
||||
complexf_t sample;
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
complexi_t zi;
|
||||
#endif
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
complexi16_t sample;
|
||||
complexi16_t zz;
|
||||
#else
|
||||
complexf_t sample;
|
||||
complexf_t zz;
|
||||
#endif
|
||||
int32_t power;
|
||||
|
||||
@@ -664,7 +822,7 @@ int v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], int len)
|
||||
/* Count down a short delay, to ensure we push the last
|
||||
few bits through the filters before stopping. */
|
||||
v27ter_rx_restart(s, s->bit_rate, FALSE);
|
||||
report_status_change(s, PUTBIT_CARRIER_DOWN);
|
||||
report_status_change(s, SIG_STATUS_CARRIER_DOWN);
|
||||
continue;
|
||||
}
|
||||
#if defined(IAXMODEM_STUFF)
|
||||
@@ -683,7 +841,7 @@ int v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], int len)
|
||||
#if defined(IAXMODEM_STUFF)
|
||||
s->carrier_drop_pending = FALSE;
|
||||
#endif
|
||||
report_status_change(s, PUTBIT_CARRIER_UP);
|
||||
report_status_change(s, SIG_STATUS_CARRIER_UP);
|
||||
}
|
||||
/* Only spend effort processing this data if the modem is not
|
||||
parked, after training failure. */
|
||||
@@ -697,7 +855,11 @@ int v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], int len)
|
||||
if (s->training_stage == TRAINING_STAGE_SYMBOL_ACQUISITION)
|
||||
{
|
||||
/* Only AGC during the initial training */
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
s->agc_scaling = (float) FP_FACTOR*(1.0f/RX_PULSESHAPER_4800_GAIN)*1.414f/sqrtf(power);
|
||||
#else
|
||||
s->agc_scaling = (1.0f/RX_PULSESHAPER_4800_GAIN)*1.414f/sqrtf(power);
|
||||
#endif
|
||||
}
|
||||
/* Pulse shape while still at the carrier frequency, using a quadrature
|
||||
pair of filters. This results in a properly bandpass filtered complex
|
||||
@@ -789,7 +951,7 @@ int v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], int len)
|
||||
/* Count down a short delay, to ensure we push the last
|
||||
few bits through the filters before stopping. */
|
||||
v27ter_rx_restart(s, s->bit_rate, FALSE);
|
||||
report_status_change(s, PUTBIT_CARRIER_DOWN);
|
||||
report_status_change(s, SIG_STATUS_CARRIER_DOWN);
|
||||
continue;
|
||||
}
|
||||
#if defined(IAXMODEM_STUFF)
|
||||
@@ -808,7 +970,7 @@ int v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], int len)
|
||||
#if defined(IAXMODEM_STUFF)
|
||||
s->carrier_drop_pending = FALSE;
|
||||
#endif
|
||||
report_status_change(s, PUTBIT_CARRIER_UP);
|
||||
report_status_change(s, SIG_STATUS_CARRIER_UP);
|
||||
}
|
||||
/* Only spend effort processing this data if the modem is not
|
||||
parked, after training failure. */
|
||||
@@ -822,7 +984,11 @@ int v27ter_rx(v27ter_rx_state_t *s, const int16_t amp[], int len)
|
||||
if (s->training_stage == TRAINING_STAGE_SYMBOL_ACQUISITION)
|
||||
{
|
||||
/* Only AGC during the initial training */
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
s->agc_scaling = (float) FP_FACTOR*(1.0f/RX_PULSESHAPER_2400_GAIN)*1.414f/sqrtf(power);
|
||||
#else
|
||||
s->agc_scaling = (1.0f/RX_PULSESHAPER_2400_GAIN)*1.414f/sqrtf(power);
|
||||
#endif
|
||||
}
|
||||
/* Pulse shape while still at the carrier frequency, using a quadrature
|
||||
pair of filters. This results in a properly bandpass filtered complex
|
||||
@@ -890,7 +1056,7 @@ int v27ter_rx_restart(v27ter_rx_state_t *s, int bit_rate, int old_train)
|
||||
s->bit_rate = bit_rate;
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
memset(s->rrc_filter, 0, sizeof(s->rrc_filter));
|
||||
vec_zeroi16(s->rrc_filter, sizeof(s->rrc_filter)/sizeof(s->rrc_filter[0]));
|
||||
#else
|
||||
vec_zerof(s->rrc_filter, sizeof(s->rrc_filter)/sizeof(s->rrc_filter[0]));
|
||||
#endif
|
||||
@@ -925,7 +1091,11 @@ int v27ter_rx_restart(v27ter_rx_state_t *s, int bit_rate, int old_train)
|
||||
else
|
||||
{
|
||||
s->carrier_phase_rate = dds_phase_ratef(CARRIER_NOMINAL_FREQ);
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
s->agc_scaling = (float) FP_FACTOR*0.005f/RX_PULSESHAPER_4800_GAIN;
|
||||
#else
|
||||
s->agc_scaling = 0.005f/RX_PULSESHAPER_4800_GAIN;
|
||||
#endif
|
||||
equalizer_reset(s);
|
||||
}
|
||||
s->eq_skip = 0;
|
||||
@@ -934,7 +1104,7 @@ int v27ter_rx_restart(v27ter_rx_state_t *s, int bit_rate, int old_train)
|
||||
s->gardner_integrate = 0;
|
||||
s->total_baud_timing_correction = 0;
|
||||
s->gardner_step = 512;
|
||||
s->baud_phase = 0;
|
||||
s->baud_half = 0;
|
||||
|
||||
return 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: v27ter_tx.c,v 1.64 2008/07/16 14:23:47 steveu Exp $
|
||||
* $Id: v27ter_tx.c,v 1.66 2008/09/07 12:45:17 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -108,12 +108,12 @@ static __inline__ int get_scrambled_bit(v27ter_tx_state_t *s)
|
||||
{
|
||||
int bit;
|
||||
|
||||
if ((bit = s->current_get_bit(s->get_bit_user_data)) == PUTBIT_END_OF_DATA)
|
||||
if ((bit = s->current_get_bit(s->get_bit_user_data)) == SIG_STATUS_END_OF_DATA)
|
||||
{
|
||||
/* End of real data. Switch to the fake get_bit routine, until we
|
||||
have shut down completely. */
|
||||
if (s->status_handler)
|
||||
s->status_handler(s->status_user_data, MODEM_TX_STATUS_DATA_EXHAUSTED);
|
||||
s->status_handler(s->status_user_data, SIG_STATUS_END_OF_DATA);
|
||||
s->current_get_bit = fake_get_bit;
|
||||
s->in_training = TRUE;
|
||||
bit = 1;
|
||||
@@ -212,7 +212,7 @@ static complexf_t getbaud(v27ter_tx_state_t *s)
|
||||
if (s->training_step == V27TER_TRAINING_SHUTDOWN_END)
|
||||
{
|
||||
if (s->status_handler)
|
||||
s->status_handler(s->status_user_data, MODEM_TX_STATUS_SHUTDOWN_COMPLETE);
|
||||
s->status_handler(s->status_user_data, SIG_STATUS_SHUTDOWN_COMPLETE);
|
||||
}
|
||||
}
|
||||
/* 4800bps uses 8 phases. 2400bps uses 4 phases. */
|
||||
|
||||
+344
-129
@@ -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.c,v 1.124 2008/07/17 19:12:27 steveu Exp $
|
||||
* $Id: v29rx.c,v 1.135 2008/09/09 16:13:12 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -48,6 +48,8 @@
|
||||
#include "spandsp/complex.h"
|
||||
#include "spandsp/vector_float.h"
|
||||
#include "spandsp/complex_vector_float.h"
|
||||
#include "spandsp/vector_int.h"
|
||||
#include "spandsp/complex_vector_int.h"
|
||||
#include "spandsp/async.h"
|
||||
#include "spandsp/power_meter.h"
|
||||
#include "spandsp/arctan2.h"
|
||||
@@ -67,6 +69,11 @@
|
||||
#define BAUD_RATE 2400
|
||||
#define EQUALIZER_DELTA 0.21f
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
#define FP_FACTOR 4096
|
||||
#define FP_SHIFT_FACTOR 12
|
||||
#endif
|
||||
|
||||
/* Segments of the training sequence */
|
||||
#define V29_TRAINING_SEG_2_LEN 128
|
||||
#define V29_TRAINING_SEG_3_LEN 384
|
||||
@@ -109,13 +116,23 @@ static const uint8_t space_map_9600[20][20] =
|
||||
};
|
||||
|
||||
/* Coefficients for the band edge symbol timing synchroniser (alpha = 0.99) */
|
||||
#define SYNC_LOW_BAND_EDGE_COEFF_0 1.829281f /* 2*alpha*cos(low_edge) */
|
||||
#define SYNC_LOW_BAND_EDGE_COEFF_1 -0.980100f /* -alpha^2 */
|
||||
#define SYNC_HIGH_BAND_EDGE_COEFF_0 -1.285907f /* 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.752802f /* alpha*sin(high_edge) */
|
||||
#define SYNC_CROSS_CORR_COEFF_C -0.378857f /* -alpha*sin(low_edge) */
|
||||
#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 */
|
||||
#define SYNC_HIGH_BAND_EDGE_COEFF_0 ((int)(FP_FACTOR*-1.285907f)) /* 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.752802f)) /* alpha*sin(high_edge) */
|
||||
#define SYNC_CROSS_CORR_COEFF_C ((int)(FP_FACTOR*-0.378857f)) /* -alpha*sin(low_edge) */
|
||||
#else
|
||||
#define SYNC_LOW_BAND_EDGE_COEFF_0 1.829281f /* 2*alpha*cos(low_edge) */
|
||||
#define SYNC_LOW_BAND_EDGE_COEFF_1 -0.980100f /* -alpha^2 */
|
||||
#define SYNC_HIGH_BAND_EDGE_COEFF_0 -1.285907f /* 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.752802f /* alpha*sin(high_edge) */
|
||||
#define SYNC_CROSS_CORR_COEFF_C -0.378857f /* -alpha*sin(low_edge) */
|
||||
#endif
|
||||
|
||||
float v29_rx_carrier_frequency(v29_rx_state_t *s)
|
||||
{
|
||||
@@ -143,19 +160,17 @@ float v29_rx_signal_power(v29_rx_state_t *s)
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
int v29_rx_equalizer_state(v29_rx_state_t *s, complexi16_t **coeffs)
|
||||
#else
|
||||
int v29_rx_equalizer_state(v29_rx_state_t *s, complexf_t **coeffs)
|
||||
#endif
|
||||
{
|
||||
*coeffs = s->eq_coeff;
|
||||
return V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void equalizer_save(v29_rx_state_t *s)
|
||||
{
|
||||
cvec_copyf(s->eq_coeff_save, s->eq_coeff, V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void report_status_change(v29_rx_state_t *s, int status)
|
||||
{
|
||||
if (s->status_handler)
|
||||
@@ -165,51 +180,105 @@ static void report_status_change(v29_rx_state_t *s, int status)
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void equalizer_save(v29_rx_state_t *s)
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
cvec_copyi16(s->eq_coeff_save, s->eq_coeff, V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
|
||||
#else
|
||||
cvec_copyf(s->eq_coeff_save, s->eq_coeff, V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
|
||||
#endif
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void equalizer_restore(v29_rx_state_t *s)
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
cvec_copyi16(s->eq_coeff, s->eq_coeff_save, V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
|
||||
cvec_zeroi16(s->eq_buf, V29_EQUALIZER_MASK);
|
||||
s->eq_delta = 32768.0f*EQUALIZER_DELTA/(V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
|
||||
#else
|
||||
cvec_copyf(s->eq_coeff, s->eq_coeff_save, V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
|
||||
cvec_zerof(s->eq_buf, V29_EQUALIZER_MASK);
|
||||
s->eq_delta = EQUALIZER_DELTA/(V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
|
||||
#endif
|
||||
|
||||
s->eq_put_step = RX_PULSESHAPER_COEFF_SETS*10/(3*2) - 1;
|
||||
s->eq_step = 0;
|
||||
s->eq_delta = EQUALIZER_DELTA/(V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void equalizer_reset(v29_rx_state_t *s)
|
||||
{
|
||||
/* Start with an equalizer based on everything being perfect */
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
cvec_zeroi16(s->eq_coeff, V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
|
||||
s->eq_coeff[V29_EQUALIZER_PRE_LEN] = complex_seti16(3*FP_FACTOR, 0*FP_FACTOR);
|
||||
cvec_zeroi16(s->eq_buf, V29_EQUALIZER_MASK);
|
||||
s->eq_delta = 32768.0f*EQUALIZER_DELTA/(V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
|
||||
#else
|
||||
cvec_zerof(s->eq_coeff, V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
|
||||
s->eq_coeff[V29_EQUALIZER_PRE_LEN] = complex_setf(3.0f, 0.0f);
|
||||
cvec_zerof(s->eq_buf, V29_EQUALIZER_MASK);
|
||||
s->eq_delta = EQUALIZER_DELTA/(V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
|
||||
#endif
|
||||
|
||||
s->eq_put_step = RX_PULSESHAPER_COEFF_SETS*10/(3*2) - 1;
|
||||
s->eq_step = 0;
|
||||
s->eq_delta = EQUALIZER_DELTA/(V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
static __inline__ complexi16_t complex_mul_q4_12(const complexi16_t *x, const complexi16_t *y)
|
||||
{
|
||||
complexi16_t z;
|
||||
|
||||
z.re = ((int32_t) x->re*(int32_t) y->re - (int32_t) x->im*(int32_t) y->im) >> 12;
|
||||
z.im = ((int32_t) x->re*(int32_t) y->im + (int32_t) x->im*(int32_t) y->re) >> 12;
|
||||
return z;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
#endif
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
static __inline__ complexi16_t equalizer_get(v29_rx_state_t *s)
|
||||
#else
|
||||
static __inline__ complexf_t equalizer_get(v29_rx_state_t *s)
|
||||
#endif
|
||||
{
|
||||
int i;
|
||||
int p;
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
complexi16_t z;
|
||||
complexi16_t z1;
|
||||
#else
|
||||
complexf_t z;
|
||||
complexf_t z1;
|
||||
#endif
|
||||
|
||||
/* Get the next equalized value. */
|
||||
z = complex_setf(0.0f, 0.0f);
|
||||
p = s->eq_step - 1;
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
z = complex_seti16(0, 0);
|
||||
for (i = 0; i < V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN; i++)
|
||||
{
|
||||
p = (p - 1) & V29_EQUALIZER_MASK;
|
||||
z1 = complex_mul_q4_12(&s->eq_coeff[i], &s->eq_buf[p]);
|
||||
z = complex_addi16(&z, &z1);
|
||||
}
|
||||
#else
|
||||
z = complex_setf(0.0f, 0.0f);
|
||||
for (i = 0; i < V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN; i++)
|
||||
{
|
||||
p = (p - 1) & V29_EQUALIZER_MASK;
|
||||
z1 = complex_mulf(&s->eq_coeff[i], &s->eq_buf[p]);
|
||||
z = complex_addf(&z, &z1);
|
||||
}
|
||||
#endif
|
||||
return z;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINTy)
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
static void tune_equalizer(v29_rx_state_t *s, const complexi16_t *z, const complexi16_t *target)
|
||||
#else
|
||||
static void tune_equalizer(v29_rx_state_t *s, const complexf_t *z, const complexf_t *target)
|
||||
@@ -217,24 +286,42 @@ static void tune_equalizer(v29_rx_state_t *s, const complexf_t *z, const complex
|
||||
{
|
||||
int i;
|
||||
int p;
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
complexi16_t ez;
|
||||
complexi16_t z1;
|
||||
#else
|
||||
complexf_t ez;
|
||||
complexf_t z1;
|
||||
#endif
|
||||
|
||||
/* Find the x and y mismatch from the exact constellation position. */
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
ez.re = target->re*FP_FACTOR - z->re;
|
||||
ez.im = target->im*FP_FACTOR - z->im;
|
||||
ez.re = ((int32_t) ez.re*(int32_t) s->eq_delta) >> 15;
|
||||
ez.im = ((int32_t) ez.im*(int32_t) s->eq_delta) >> 15;
|
||||
#else
|
||||
ez = complex_subf(target, z);
|
||||
ez.re *= s->eq_delta;
|
||||
ez.im *= s->eq_delta;
|
||||
#endif
|
||||
|
||||
p = s->eq_step - 1;
|
||||
for (i = 0; i < V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN; i++)
|
||||
{
|
||||
p = (p - 1) & V29_EQUALIZER_MASK;
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
z1 = complex_conji16(&s->eq_buf[p]);
|
||||
z1 = complex_mul_q4_12(&ez, &z1);
|
||||
s->eq_coeff[i] = complex_addi16(&s->eq_coeff[i], &z1);
|
||||
#else
|
||||
z1 = complex_conjf(&s->eq_buf[p]);
|
||||
z1 = complex_mulf(&ez, &z1);
|
||||
s->eq_coeff[i] = complex_addf(&s->eq_coeff[i], &z1);
|
||||
/* Leak a little to tame uncontrolled wandering */
|
||||
s->eq_coeff[i].re *= 0.9999f;
|
||||
s->eq_coeff[i].im *= 0.9999f;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
@@ -253,7 +340,7 @@ static int scrambled_training_bit(v29_rx_state_t *s)
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINTy)
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
static __inline__ int find_quadrant(const complexi16_t *z)
|
||||
#else
|
||||
static __inline__ int find_quadrant(const complexf_t *z)
|
||||
@@ -269,7 +356,7 @@ static __inline__ int find_quadrant(const complexf_t *z)
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINTy)
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
static __inline__ void track_carrier(v29_rx_state_t *s, const complexi16_t *z, const complexi16_t *target)
|
||||
#else
|
||||
static __inline__ void track_carrier(v29_rx_state_t *s, const complexf_t *z, const complexf_t *target)
|
||||
@@ -290,7 +377,12 @@ static __inline__ void track_carrier(v29_rx_state_t *s, const complexf_t *z, con
|
||||
different amplitudes of the various target positions scale things. This isn't all bad,
|
||||
as the angular error for the larger amplitude constellation points is probably
|
||||
a more reliable indicator, and we are weighting it as such. */
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
error = z->im*target->re - z->re*target->im;
|
||||
error /= (float) FP_FACTOR;
|
||||
#else
|
||||
error = z->im*target->re - z->re*target->im;
|
||||
#endif
|
||||
|
||||
/* Use a proportional-integral approach to tracking the carrier. The PI
|
||||
parameters are coarser at first, until we get precisely on target. Then,
|
||||
@@ -326,7 +418,11 @@ static __inline__ void put_bit(v29_rx_state_t *s, int bit)
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
static void decode_baud(v29_rx_state_t *s, complexi16_t *z)
|
||||
#else
|
||||
static void decode_baud(v29_rx_state_t *s, complexf_t *z)
|
||||
#endif
|
||||
{
|
||||
static const uint8_t phase_steps_9600[8] =
|
||||
{
|
||||
@@ -342,57 +438,51 @@ static void decode_baud(v29_rx_state_t *s, complexf_t *z)
|
||||
int re;
|
||||
int im;
|
||||
|
||||
switch (s->bit_rate)
|
||||
if (s->bit_rate == 4800)
|
||||
{
|
||||
case 9600:
|
||||
default:
|
||||
/* 4800 is a special case. */
|
||||
nearest = find_quadrant(z) << 1;
|
||||
raw_bits = phase_steps_4800[((nearest - s->constellation_state) >> 1) & 3];
|
||||
put_bit(s, raw_bits);
|
||||
put_bit(s, raw_bits >> 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 9600 and 7200 are quite similar. */
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
re = (z->re + 5*FP_FACTOR) >> (FP_SHIFT_FACTOR - 1);
|
||||
im = (z->im + 5*FP_FACTOR) >> (FP_SHIFT_FACTOR - 1);
|
||||
#else
|
||||
re = (int) ((z->re + 5.0f)*2.0f);
|
||||
im = (int) ((z->im + 5.0f)*2.0f);
|
||||
#endif
|
||||
if (re > 19)
|
||||
re = 19;
|
||||
else if (re < 0)
|
||||
re = 0;
|
||||
im = (int) ((z->im + 5.0f)*2.0f);
|
||||
if (im > 19)
|
||||
im = 19;
|
||||
else if (im < 0)
|
||||
im = 0;
|
||||
nearest = space_map_9600[re][im];
|
||||
/* Deal with the amplitude bit */
|
||||
put_bit(s, nearest >> 3);
|
||||
if (s->bit_rate == 9600)
|
||||
{
|
||||
/* Send out the top (amplitude) bit. */
|
||||
put_bit(s, nearest >> 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We can reuse the space map for 9600, but drop the top bit. */
|
||||
nearest &= 7;
|
||||
}
|
||||
raw_bits = phase_steps_9600[(nearest - s->constellation_state) & 7];
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
put_bit(s, raw_bits);
|
||||
raw_bits >>= 1;
|
||||
}
|
||||
break;
|
||||
case 7200:
|
||||
/* We can reuse the space map for 9600, but drop the top bit */
|
||||
re = (int) ((z->re + 5.0f)*2.0f);
|
||||
if (re > 19)
|
||||
re = 19;
|
||||
else if (re < 0)
|
||||
re = 0;
|
||||
im = (int) ((z->im + 5.0f)*2.0f);
|
||||
if (im > 19)
|
||||
im = 19;
|
||||
else if (im < 0)
|
||||
im = 0;
|
||||
nearest = space_map_9600[re][im] & 7;
|
||||
raw_bits = phase_steps_9600[(nearest - s->constellation_state) & 7];
|
||||
for (i = 0; i < 3; i++)
|
||||
{
|
||||
put_bit(s, raw_bits);
|
||||
raw_bits >>= 1;
|
||||
}
|
||||
break;
|
||||
case 4800:
|
||||
nearest = find_quadrant(z) << 1;
|
||||
raw_bits = phase_steps_4800[((nearest - s->constellation_state) >> 1) & 3];
|
||||
put_bit(s, raw_bits);
|
||||
put_bit(s, raw_bits >> 1);
|
||||
break;
|
||||
}
|
||||
|
||||
track_carrier(s, z, &v29_9600_constellation[nearest]);
|
||||
if (--s->eq_skip <= 0)
|
||||
{
|
||||
@@ -406,7 +496,73 @@ static void decode_baud(v29_rx_state_t *s, complexf_t *z)
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ void symbol_sync(v29_rx_state_t *s)
|
||||
{
|
||||
int i;
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
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_POINT)
|
||||
/* 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) > 50*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
|
||||
+ s->symbol_sync_low[1]*s->symbol_sync_high[0]*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 (fabsf(s->baud_phase) > 50.0f)
|
||||
{
|
||||
if (s->baud_phase > 0.0f)
|
||||
i = (s->baud_phase > 1000.0f) ? 5 : 1;
|
||||
else
|
||||
i = (s->baud_phase < -1000.0f) ? -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;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
static void process_half_baud(v29_rx_state_t *s, complexi16_t *sample)
|
||||
#else
|
||||
static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
|
||||
#endif
|
||||
{
|
||||
static const int cdcd_pos[6] =
|
||||
{
|
||||
@@ -414,14 +570,17 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
|
||||
0, 3,
|
||||
0, 2
|
||||
};
|
||||
complexf_t z;
|
||||
complexf_t zz;
|
||||
#if defined(SPANDSP_USE_FIXED_POINTy)
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
complexf_t z1;
|
||||
complexi16_t z;
|
||||
const complexi16_t *target;
|
||||
static const complexi16_t zero = {0, 0};
|
||||
#else
|
||||
complexf_t z;
|
||||
const complexf_t *target;
|
||||
static const complexf_t zero = {0.0f, 0.0f};
|
||||
#endif
|
||||
float v;
|
||||
float p;
|
||||
int bit;
|
||||
int i;
|
||||
@@ -429,8 +588,7 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
|
||||
int32_t angle;
|
||||
int32_t ang;
|
||||
|
||||
/* This routine processes every half a baud, as we put things into the equalizer at the T/2 rate.
|
||||
This routine adapts the position of the half baud samples, which the caller takes. */
|
||||
/* This routine processes every half a baud, as we put things into the equalizer at the T/2 rate. */
|
||||
|
||||
/* Add a sample to the equalizer's circular buffer, but don't calculate anything
|
||||
at this time. */
|
||||
@@ -442,29 +600,7 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
|
||||
return;
|
||||
|
||||
/* Symbol timing synchronisation */
|
||||
/* 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
|
||||
+ s->symbol_sync_low[1]*s->symbol_sync_high[0]*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 (fabsf(s->baud_phase) > 30.0f)
|
||||
{
|
||||
if (s->baud_phase > 0.0f)
|
||||
i = (s->baud_phase > 1000.0f) ? 5 : 1;
|
||||
else
|
||||
i = (s->baud_phase < -1000.0f) ? -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;
|
||||
}
|
||||
symbol_sync(s);
|
||||
|
||||
z = equalizer_get(s);
|
||||
|
||||
@@ -477,25 +613,27 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
|
||||
break;
|
||||
case TRAINING_STAGE_SYMBOL_ACQUISITION:
|
||||
/* Allow time for symbol synchronisation to settle the symbol timing. */
|
||||
target = &z;
|
||||
target = &zero;
|
||||
if (++s->training_count >= 60)
|
||||
{
|
||||
/* Record the current phase angle */
|
||||
s->training_stage = TRAINING_STAGE_LOG_PHASE;
|
||||
s->angles[0] =
|
||||
s->start_angles[0] = arctan2(z.im, z.re);
|
||||
if (s->agc_scaling_save == 0.0f)
|
||||
s->agc_scaling_save = s->agc_scaling;
|
||||
}
|
||||
break;
|
||||
case TRAINING_STAGE_LOG_PHASE:
|
||||
/* Record the current alternate phase angle */
|
||||
target = &z;
|
||||
target = &zero;
|
||||
s->angles[1] =
|
||||
s->start_angles[1] = arctan2(z.im, z.re);
|
||||
s->training_count = 1;
|
||||
s->training_stage = TRAINING_STAGE_WAIT_FOR_CDCD;
|
||||
break;
|
||||
case TRAINING_STAGE_WAIT_FOR_CDCD:
|
||||
target = &z;
|
||||
target = &zero;
|
||||
angle = arctan2(z.im, z.re);
|
||||
/* Look for the initial ABAB sequence to display a phase reversal, which will
|
||||
signal the start of the scrambled CDCD segment */
|
||||
@@ -524,24 +662,36 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
|
||||
||
|
||||
s->carrier_phase_rate > dds_phase_ratef(CARRIER_NOMINAL_FREQ + 20.0f))
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n");
|
||||
/* Park this modem */
|
||||
s->training_stage = TRAINING_STAGE_PARKED;
|
||||
report_status_change(s, PUTBIT_TRAINING_FAILED);
|
||||
break;
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n");
|
||||
/* Park this modem */
|
||||
s->agc_scaling_save = 0.0f;
|
||||
s->training_stage = TRAINING_STAGE_PARKED;
|
||||
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
||||
break;
|
||||
}
|
||||
/* Make a step shift in the phase, to pull it into line. We need to rotate the equalizer
|
||||
buffer, as well as the carrier phase, for this to play out nicely. */
|
||||
p = angle*2.0f*3.14159f/(65536.0f*65536.0f);
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
zz = complex_setf(cosf(p), -sinf(p));
|
||||
for (i = 0; i <= V29_EQUALIZER_MASK; i++)
|
||||
{
|
||||
z1 = complex_setf(s->eq_buf[i].re, s->eq_buf[i].im);
|
||||
z1 = complex_mulf(&z1, &zz);
|
||||
s->eq_buf[i].re = z1.re;
|
||||
s->eq_buf[i].im = z1.im;
|
||||
}
|
||||
#else
|
||||
zz = complex_setf(cosf(p), -sinf(p));
|
||||
for (i = 0; i <= V29_EQUALIZER_MASK; i++)
|
||||
s->eq_buf[i] = complex_mulf(&s->eq_buf[i], &zz);
|
||||
#endif
|
||||
s->carrier_phase += angle;
|
||||
/* We have just seen the first bit of the scrambled sequence, so skip it. */
|
||||
bit = scrambled_training_bit(s);
|
||||
s->training_count = 1;
|
||||
s->training_stage = TRAINING_STAGE_TRAIN_ON_CDCD;
|
||||
report_status_change(s, PUTBIT_TRAINING_IN_PROGRESS);
|
||||
report_status_change(s, SIG_STATUS_TRAINING_IN_PROGRESS);
|
||||
break;
|
||||
}
|
||||
if (++s->training_count > V29_TRAINING_SEG_2_LEN)
|
||||
@@ -550,8 +700,9 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
|
||||
of a real training sequence. */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n");
|
||||
/* Park this modem */
|
||||
s->agc_scaling_save = 0.0f;
|
||||
s->training_stage = TRAINING_STAGE_PARKED;
|
||||
report_status_change(s, PUTBIT_TRAINING_FAILED);
|
||||
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
||||
}
|
||||
break;
|
||||
case TRAINING_STAGE_TRAIN_ON_CDCD:
|
||||
@@ -579,8 +730,17 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
|
||||
track_carrier(s, &z, target);
|
||||
tune_equalizer(s, &z, target);
|
||||
/* Measure the training error */
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
z1.re = z.re/(float) FP_FACTOR;
|
||||
z1.im = z.im/(float) FP_FACTOR;
|
||||
zz.re = target->re;
|
||||
zz.im = target->im;
|
||||
zz = complex_subf(&z1, &zz);
|
||||
s->training_error += powerf(&zz);
|
||||
#else
|
||||
zz = complex_subf(&z, target);
|
||||
s->training_error += powerf(&zz);
|
||||
#endif
|
||||
if (++s->training_count >= V29_TRAINING_SEG_3_LEN)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Constellation mismatch %f\n", s->training_error);
|
||||
@@ -595,8 +755,9 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (convergence failed)\n");
|
||||
/* Park this modem */
|
||||
s->agc_scaling_save = 0.0f;
|
||||
s->training_stage = TRAINING_STAGE_PARKED;
|
||||
report_status_change(s, PUTBIT_TRAINING_FAILED);
|
||||
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -607,15 +768,24 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
|
||||
decode_baud(s, &z);
|
||||
target = &v29_9600_constellation[s->constellation_state];
|
||||
/* Measure the training error */
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
z1.re = z.re/(float) FP_FACTOR;
|
||||
z1.im = z.im/(float) FP_FACTOR;
|
||||
zz.re = target->re;
|
||||
zz.im = target->im;
|
||||
zz = complex_subf(&z1, &zz);
|
||||
s->training_error += powerf(&zz);
|
||||
#else
|
||||
zz = complex_subf(&z, target);
|
||||
s->training_error += powerf(&zz);
|
||||
#endif
|
||||
if (++s->training_count >= V29_TRAINING_SEG_4_LEN)
|
||||
{
|
||||
if (s->training_error < 50.0f)
|
||||
{
|
||||
/* We are up and running */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Training succeeded (constellation mismatch %f)\n", s->training_error);
|
||||
report_status_change(s, PUTBIT_TRAINING_SUCCEEDED);
|
||||
report_status_change(s, SIG_STATUS_TRAINING_SUCCEEDED);
|
||||
/* Apply some lag to the carrier off condition, to ensure the last few bits get pushed through
|
||||
the processing. */
|
||||
s->signal_present = 60;
|
||||
@@ -629,8 +799,9 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
|
||||
/* Training has failed */
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (constellation mismatch %f)\n", s->training_error);
|
||||
/* Park this modem */
|
||||
report_status_change(s, PUTBIT_TRAINING_FAILED);
|
||||
s->agc_scaling_save = 0.0f;
|
||||
s->training_stage = TRAINING_STAGE_PARKED;
|
||||
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -638,11 +809,21 @@ static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
|
||||
default:
|
||||
/* We failed to train! */
|
||||
/* Park here until the carrier drops. */
|
||||
target = &z;
|
||||
target = &zero;
|
||||
break;
|
||||
}
|
||||
if (s->qam_report)
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
z1.re = z.re/(float) FP_FACTOR;
|
||||
z1.im = z.im/(float) FP_FACTOR;
|
||||
zz.re = target->re;
|
||||
zz.im = target->im;
|
||||
s->qam_report(s->qam_user_data, &z1, &zz, s->constellation_state);
|
||||
#else
|
||||
s->qam_report(s->qam_user_data, &z, target, s->constellation_state);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
@@ -653,14 +834,19 @@ int v29_rx(v29_rx_state_t *s, const int16_t amp[], int len)
|
||||
int step;
|
||||
int16_t x;
|
||||
int32_t diff;
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
complexi16_t z;
|
||||
complexi16_t zz;
|
||||
complexi16_t sample;
|
||||
int32_t v;
|
||||
float y;
|
||||
#else
|
||||
complexf_t z;
|
||||
complexf_t zz;
|
||||
complexf_t sample;
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
complexi_t zi;
|
||||
float v;
|
||||
#endif
|
||||
int32_t power;
|
||||
float v;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
@@ -709,7 +895,7 @@ int v29_rx(v29_rx_state_t *s, const int16_t amp[], int len)
|
||||
/* Count down a short delay, to ensure we push the last
|
||||
few bits through the filters before stopping. */
|
||||
v29_rx_restart(s, s->bit_rate, FALSE);
|
||||
report_status_change(s, PUTBIT_CARRIER_DOWN);
|
||||
report_status_change(s, SIG_STATUS_CARRIER_DOWN);
|
||||
continue;
|
||||
}
|
||||
#if defined(IAXMODEM_STUFF)
|
||||
@@ -728,7 +914,7 @@ int v29_rx(v29_rx_state_t *s, const int16_t amp[], int len)
|
||||
#if defined(IAXMODEM_STUFF)
|
||||
s->carrier_drop_pending = FALSE;
|
||||
#endif
|
||||
report_status_change(s, PUTBIT_CARRIER_UP);
|
||||
report_status_change(s, SIG_STATUS_CARRIER_UP);
|
||||
}
|
||||
if (s->training_stage == TRAINING_STAGE_PARKED)
|
||||
continue;
|
||||
@@ -741,18 +927,29 @@ int v29_rx(v29_rx_state_t *s, const int16_t amp[], int len)
|
||||
if (step < 0)
|
||||
step += RX_PULSESHAPER_COEFF_SETS;
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
zi.re = (int32_t) rx_pulseshaper[step][0].re*(int32_t) s->rrc_filter[s->rrc_filter_step];
|
||||
v = (int32_t) rx_pulseshaper[step][0].re*(int32_t) s->rrc_filter[s->rrc_filter_step];
|
||||
for (j = 1; j < V29_RX_FILTER_STEPS; j++)
|
||||
zi.re += (int32_t) rx_pulseshaper[step][j].re*(int32_t) s->rrc_filter[j + s->rrc_filter_step];
|
||||
sample.re = zi.re*s->agc_scaling;
|
||||
v += (int32_t) rx_pulseshaper[step][j].re*(int32_t) s->rrc_filter[j + s->rrc_filter_step];
|
||||
y = v*s->agc_scaling;
|
||||
sample.re = y;
|
||||
#else
|
||||
zz.re = rx_pulseshaper[step][0].re*s->rrc_filter[s->rrc_filter_step];
|
||||
v = rx_pulseshaper[step][0].re*s->rrc_filter[s->rrc_filter_step];
|
||||
for (j = 1; j < V29_RX_FILTER_STEPS; j++)
|
||||
zz.re += rx_pulseshaper[step][j].re*s->rrc_filter[j + s->rrc_filter_step];
|
||||
sample.re = zz.re*s->agc_scaling;
|
||||
v += rx_pulseshaper[step][j].re*s->rrc_filter[j + s->rrc_filter_step];
|
||||
sample.re = v*s->agc_scaling;
|
||||
#endif
|
||||
|
||||
/* Symbol timing synchronisation band edge filters */
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
/* Low Nyquist band edge filter */
|
||||
v = ((s->symbol_sync_low[0]*SYNC_LOW_BAND_EDGE_COEFF_0) >> 12) + ((s->symbol_sync_low[1]*SYNC_LOW_BAND_EDGE_COEFF_1) >> 12) + sample.re;
|
||||
s->symbol_sync_low[1] = s->symbol_sync_low[0];
|
||||
s->symbol_sync_low[0] = v;
|
||||
/* High Nyquist band edge filter */
|
||||
v = ((s->symbol_sync_high[0]*SYNC_HIGH_BAND_EDGE_COEFF_0) >> 12) + ((s->symbol_sync_high[1]*SYNC_HIGH_BAND_EDGE_COEFF_1) >> 12) + sample.re;
|
||||
s->symbol_sync_high[1] = s->symbol_sync_high[0];
|
||||
s->symbol_sync_high[0] = v;
|
||||
#else
|
||||
/* Low Nyquist band edge filter */
|
||||
v = s->symbol_sync_low[0]*SYNC_LOW_BAND_EDGE_COEFF_0 + s->symbol_sync_low[1]*SYNC_LOW_BAND_EDGE_COEFF_1 + sample.re;
|
||||
s->symbol_sync_low[1] = s->symbol_sync_low[0];
|
||||
@@ -761,16 +958,19 @@ int v29_rx(v29_rx_state_t *s, const int16_t amp[], int len)
|
||||
v = s->symbol_sync_high[0]*SYNC_HIGH_BAND_EDGE_COEFF_0 + s->symbol_sync_high[1]*SYNC_HIGH_BAND_EDGE_COEFF_1 + sample.re;
|
||||
s->symbol_sync_high[1] = s->symbol_sync_high[0];
|
||||
s->symbol_sync_high[0] = v;
|
||||
|
||||
#endif
|
||||
/* Put things into the equalization buffer at T/2 rate. The symbol synchronisation
|
||||
will fiddle the step to align this with the symbols. */
|
||||
if (s->eq_put_step <= 0)
|
||||
{
|
||||
if (s->training_stage == TRAINING_STAGE_SYMBOL_ACQUISITION)
|
||||
{
|
||||
/* Only AGC during the initial training */
|
||||
/* Only AGC until we have locked down the setting. */
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
if (s->agc_scaling_save == 0.0f)
|
||||
s->agc_scaling = (float) FP_FACTOR*(1.0f/RX_PULSESHAPER_GAIN)*5.0f*0.25f/sqrtf(power);
|
||||
#else
|
||||
if (s->agc_scaling_save == 0.0f)
|
||||
s->agc_scaling = (1.0f/RX_PULSESHAPER_GAIN)*5.0f*0.25f/sqrtf(power);
|
||||
}
|
||||
#endif
|
||||
/* Pulse shape while still at the carrier frequency, using a quadrature
|
||||
pair of filters. This results in a properly bandpass filtered complex
|
||||
signal, which can be brought directly to baseband by complex mixing.
|
||||
@@ -778,24 +978,24 @@ int v29_rx(v29_rx_state_t *s, const int16_t amp[], int len)
|
||||
step = -s->eq_put_step;
|
||||
if (step > RX_PULSESHAPER_COEFF_SETS - 1)
|
||||
step = RX_PULSESHAPER_COEFF_SETS - 1;
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
zi.im = (int32_t) rx_pulseshaper[step][0].im*(int32_t) s->rrc_filter[s->rrc_filter_step];
|
||||
for (j = 1; j < V29_RX_FILTER_STEPS; j++)
|
||||
zi.im += (int32_t) rx_pulseshaper[step][j].im*(int32_t) s->rrc_filter[j + s->rrc_filter_step];
|
||||
sample.im = zi.im*s->agc_scaling;
|
||||
#else
|
||||
zz.im = rx_pulseshaper[step][0].im*s->rrc_filter[s->rrc_filter_step];
|
||||
for (j = 1; j < V29_RX_FILTER_STEPS; j++)
|
||||
zz.im += rx_pulseshaper[step][j].im*s->rrc_filter[j + s->rrc_filter_step];
|
||||
sample.im = zz.im*s->agc_scaling;
|
||||
#endif
|
||||
s->eq_put_step += RX_PULSESHAPER_COEFF_SETS*10/(3*2);
|
||||
/* Shift to baseband - since this is done in a full complex form, the
|
||||
result is clean, and requires no further filtering, apart from the
|
||||
equalizer. */
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
v = (int32_t) rx_pulseshaper[step][0].im*(int32_t) s->rrc_filter[s->rrc_filter_step];
|
||||
for (j = 1; j < V29_RX_FILTER_STEPS; j++)
|
||||
v += (int32_t) rx_pulseshaper[step][j].im*(int32_t) s->rrc_filter[j + s->rrc_filter_step];
|
||||
sample.im = v*s->agc_scaling;
|
||||
z = dds_lookup_complexi16(s->carrier_phase);
|
||||
zz.re = ((int32_t) sample.re*(int32_t) z.re - (int32_t) sample.im*(int32_t) z.im) >> 15;
|
||||
zz.im = ((int32_t) -sample.re*(int32_t) z.im - (int32_t) sample.im*(int32_t) z.re) >> 15;
|
||||
#else
|
||||
v = rx_pulseshaper[step][0].im*s->rrc_filter[s->rrc_filter_step];
|
||||
for (j = 1; j < V29_RX_FILTER_STEPS; j++)
|
||||
v += rx_pulseshaper[step][j].im*s->rrc_filter[j + s->rrc_filter_step];
|
||||
sample.im = v*s->agc_scaling;
|
||||
z = dds_lookup_complexf(s->carrier_phase);
|
||||
zz.re = sample.re*z.re - sample.im*z.im;
|
||||
zz.im = -sample.re*z.im - sample.im*z.re;
|
||||
#endif
|
||||
process_half_baud(s, &zz);
|
||||
}
|
||||
dds_advancef(&(s->carrier_phase), s->carrier_phase_rate);
|
||||
@@ -837,7 +1037,7 @@ int v29_rx_restart(v29_rx_state_t *s, int bit_rate, int old_train)
|
||||
s->bit_rate = bit_rate;
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
memset(s->rrc_filter, 0, sizeof(s->rrc_filter));
|
||||
vec_zeroi16(s->rrc_filter, sizeof(s->rrc_filter)/sizeof(s->rrc_filter[0]));
|
||||
#else
|
||||
vec_zerof(s->rrc_filter, sizeof(s->rrc_filter)/sizeof(s->rrc_filter[0]));
|
||||
#endif
|
||||
@@ -856,8 +1056,6 @@ int v29_rx_restart(v29_rx_state_t *s, int bit_rate, int old_train)
|
||||
s->old_train = old_train;
|
||||
|
||||
s->carrier_phase = 0;
|
||||
s->carrier_track_i = 8000.0f;
|
||||
s->carrier_track_p = 8000000.0f;
|
||||
|
||||
power_meter_init(&(s->power), 4);
|
||||
|
||||
@@ -872,13 +1070,29 @@ int v29_rx_restart(v29_rx_state_t *s, int bit_rate, int old_train)
|
||||
else
|
||||
{
|
||||
s->carrier_phase_rate = dds_phase_ratef(CARRIER_NOMINAL_FREQ);
|
||||
s->agc_scaling_save = 0.0f;
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
s->agc_scaling = (float) FP_FACTOR*0.0017f/RX_PULSESHAPER_GAIN;
|
||||
#else
|
||||
s->agc_scaling = 0.0017f/RX_PULSESHAPER_GAIN;
|
||||
#endif
|
||||
equalizer_reset(s);
|
||||
}
|
||||
s->eq_skip = 0;
|
||||
s->carrier_track_i = 8000.0f;
|
||||
s->carrier_track_p = 8000000.0f;
|
||||
s->last_sample = 0;
|
||||
s->eq_skip = 0;
|
||||
|
||||
/* Initialise the working data for symbol timing synchronisation */
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
s->symbol_sync_low[0] = 0;
|
||||
s->symbol_sync_low[1] = 0;
|
||||
s->symbol_sync_high[0] = 0;
|
||||
s->symbol_sync_high[1] = 0;
|
||||
s->symbol_sync_dc_filter[0] = 0;
|
||||
s->symbol_sync_dc_filter[1] = 0;
|
||||
s->baud_phase = 0;
|
||||
#else
|
||||
s->symbol_sync_low[0] = 0.0f;
|
||||
s->symbol_sync_low[1] = 0.0f;
|
||||
s->symbol_sync_high[0] = 0.0f;
|
||||
@@ -886,6 +1100,7 @@ int v29_rx_restart(v29_rx_state_t *s, int bit_rate, int old_train)
|
||||
s->symbol_sync_dc_filter[0] = 0.0f;
|
||||
s->symbol_sync_dc_filter[1] = 0.0f;
|
||||
s->baud_phase = 0.0f;
|
||||
#endif
|
||||
s->baud_half = 0;
|
||||
|
||||
s->total_baud_timing_correction = 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: v29tx.c,v 1.76 2008/07/16 14:23:47 steveu Exp $
|
||||
* $Id: v29tx.c,v 1.79 2008/09/07 12:45:17 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -54,10 +54,6 @@
|
||||
|
||||
#include "spandsp/v29tx.h"
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
#define SPANDSP_USE_FIXED_POINTx
|
||||
#endif
|
||||
|
||||
#include "v29tx_constellation_maps.h"
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
#include "v29tx_fixed_rrc.h"
|
||||
@@ -87,12 +83,12 @@ static __inline__ int get_scrambled_bit(v29_tx_state_t *s)
|
||||
int bit;
|
||||
int out_bit;
|
||||
|
||||
if ((bit = s->current_get_bit(s->get_bit_user_data)) == PUTBIT_END_OF_DATA)
|
||||
if ((bit = s->current_get_bit(s->get_bit_user_data)) == SIG_STATUS_END_OF_DATA)
|
||||
{
|
||||
/* End of real data. Switch to the fake get_bit routine, until we
|
||||
have shut down completely. */
|
||||
if (s->status_handler)
|
||||
s->status_handler(s->status_user_data, MODEM_TX_STATUS_DATA_EXHAUSTED);
|
||||
s->status_handler(s->status_user_data, SIG_STATUS_END_OF_DATA);
|
||||
s->current_get_bit = fake_get_bit;
|
||||
s->in_training = TRUE;
|
||||
bit = 1;
|
||||
@@ -166,7 +162,7 @@ static __inline__ complexf_t getbaud(v29_tx_state_t *s)
|
||||
if (s->training_step == V29_TRAINING_SHUTDOWN_END)
|
||||
{
|
||||
if (s->status_handler)
|
||||
s->status_handler(s->status_user_data, MODEM_TX_STATUS_SHUTDOWN_COMPLETE);
|
||||
s->status_handler(s->status_user_data, SIG_STATUS_SHUTDOWN_COMPLETE);
|
||||
}
|
||||
}
|
||||
/* 9600bps uses the full constellation.
|
||||
|
||||
@@ -23,10 +23,10 @@
|
||||
* License along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*
|
||||
* $Id: v29tx_constellation_maps.h,v 1.1 2008/07/10 13:34:01 steveu Exp $
|
||||
* $Id: v29tx_constellation_maps.h,v 1.2 2008/09/04 14:40:05 steveu Exp $
|
||||
*/
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
static const complexi16_t v29_abab_constellation[6] =
|
||||
#else
|
||||
static const complexf_t v29_abab_constellation[6] =
|
||||
@@ -40,7 +40,7 @@ static const complexf_t v29_abab_constellation[6] =
|
||||
{-3, 0} /* 180deg low */
|
||||
};
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
static const complexi16_t v29_cdcd_constellation[6] =
|
||||
#else
|
||||
static const complexf_t v29_cdcd_constellation[6] =
|
||||
@@ -54,7 +54,7 @@ static const complexf_t v29_cdcd_constellation[6] =
|
||||
{ 0, 3} /* 90deg low */
|
||||
};
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
static const complexi16_t v29_9600_constellation[16] =
|
||||
#else
|
||||
static const complexf_t v29_9600_constellation[16] =
|
||||
|
||||
+3
-39
@@ -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: v42.c,v 1.42 2008/05/13 13:17:25 steveu Exp $
|
||||
* $Id: v42.c,v 1.43 2008/09/07 12:45:17 steveu Exp $
|
||||
*/
|
||||
|
||||
/* THIS IS A WORK IN PROGRESS. IT IS NOT FINISHED. */
|
||||
@@ -721,31 +721,7 @@ fprintf(stderr, "LAPM receive %d %d\n", ok, len);
|
||||
if (len < 0)
|
||||
{
|
||||
/* Special conditions */
|
||||
switch (len)
|
||||
{
|
||||
case PUTBIT_TRAINING_FAILED:
|
||||
span_log(&s->logging, SPAN_LOG_DEBUG, "Training failed\n");
|
||||
break;
|
||||
case PUTBIT_TRAINING_SUCCEEDED:
|
||||
span_log(&s->logging, SPAN_LOG_DEBUG, "Training succeeded\n");
|
||||
break;
|
||||
case PUTBIT_CARRIER_UP:
|
||||
span_log(&s->logging, SPAN_LOG_DEBUG, "Carrier up\n");
|
||||
break;
|
||||
case PUTBIT_CARRIER_DOWN:
|
||||
span_log(&s->logging, SPAN_LOG_DEBUG, "Carrier down\n");
|
||||
break;
|
||||
case PUTBIT_FRAMING_OK:
|
||||
span_log(&s->logging, SPAN_LOG_DEBUG, "Framing OK\n");
|
||||
break;
|
||||
case PUTBIT_ABORT:
|
||||
span_log(&s->logging, SPAN_LOG_DEBUG, "Abort\n");
|
||||
break;
|
||||
default:
|
||||
span_log(&s->logging, SPAN_LOG_DEBUG, "Eh!\n");
|
||||
break;
|
||||
}
|
||||
/*endswitch*/
|
||||
span_log(&s->logging, SPAN_LOG_DEBUG, "V.42 rx status is %s (%d)\n", signal_status_to_str(len), len);
|
||||
return;
|
||||
}
|
||||
/*endif*/
|
||||
@@ -1133,19 +1109,7 @@ static void negotiation_rx_bit(v42_state_t *s, int new_bit)
|
||||
if (new_bit < 0)
|
||||
{
|
||||
/* Special conditions */
|
||||
switch (new_bit)
|
||||
{
|
||||
case PUTBIT_CARRIER_UP:
|
||||
break;
|
||||
case PUTBIT_CARRIER_DOWN:
|
||||
case PUTBIT_TRAINING_SUCCEEDED:
|
||||
case PUTBIT_TRAINING_FAILED:
|
||||
break;
|
||||
default:
|
||||
span_log(&s->logging, SPAN_LOG_WARNING, "Unexpected special 'bit' code %d\n", new_bit);
|
||||
break;
|
||||
}
|
||||
/*endswitch*/
|
||||
span_log(&s->logging, SPAN_LOG_DEBUG, "V.42 rx status is %s (%d)\n", signal_status_to_str(new_bit), new_bit);
|
||||
return;
|
||||
}
|
||||
/*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: v8.c,v 1.30 2008/07/02 14:48:26 steveu Exp $
|
||||
* $Id: v8.c,v 1.31 2008/09/07 12:45:17 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -396,10 +396,10 @@ static void put_bit(void *user_data, int bit)
|
||||
/* Special conditions */
|
||||
switch (bit)
|
||||
{
|
||||
case PUTBIT_CARRIER_UP:
|
||||
case PUTBIT_CARRIER_DOWN:
|
||||
case PUTBIT_TRAINING_SUCCEEDED:
|
||||
case PUTBIT_TRAINING_FAILED:
|
||||
case SIG_STATUS_CARRIER_UP:
|
||||
case SIG_STATUS_CARRIER_DOWN:
|
||||
case SIG_STATUS_TRAINING_SUCCEEDED:
|
||||
case SIG_STATUS_TRAINING_FAILED:
|
||||
break;
|
||||
default:
|
||||
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: vector_int.c,v 1.11 2008/07/02 14:48:26 steveu Exp $
|
||||
* $Id: vector_int.c,v 1.12 2008/09/01 16:07:34 steveu Exp $
|
||||
*/
|
||||
|
||||
/*! \file */
|
||||
@@ -87,7 +87,7 @@ int32_t vec_dot_prodi16(const int16_t x[], const int16_t y[], int n)
|
||||
|
||||
" .p2align 2;\n"
|
||||
"1:\n"
|
||||
" addl $24,%%edx;\n" /* now edx = top - 8 */
|
||||
" addl $24,%%edx;\n" /* Now edx = top - 8 */
|
||||
" cmpl %%edx,%%esi;\n"
|
||||
" ja 3f;\n"
|
||||
|
||||
@@ -106,7 +106,7 @@ int32_t vec_dot_prodi16(const int16_t x[], const int16_t y[], int n)
|
||||
|
||||
" .p2align 2;\n"
|
||||
"3:\n"
|
||||
" addl $4,%%edx;\n" /* now edx = top - 4 */
|
||||
" addl $4,%%edx;\n" /* Now edx = top - 4 */
|
||||
" cmpl %%edx,%%esi;\n"
|
||||
" ja 5f;\n"
|
||||
|
||||
@@ -121,7 +121,7 @@ int32_t vec_dot_prodi16(const int16_t x[], const int16_t y[], int n)
|
||||
|
||||
" .p2align 2;\n"
|
||||
"5:\n"
|
||||
" addl $2,%%edx;\n" /* now edx = top - 2 */
|
||||
" addl $2,%%edx;\n" /* Now edx = top - 2 */
|
||||
" cmpl %%edx,%%esi;\n"
|
||||
" ja 6f;\n"
|
||||
|
||||
@@ -141,7 +141,7 @@ int32_t vec_dot_prodi16(const int16_t x[], const int16_t y[], int n)
|
||||
" movq %%mm0,%%mm1;\n"
|
||||
" punpckhdq %%mm0,%%mm1;\n"
|
||||
" paddd %%mm1,%%mm0;\n"
|
||||
/* et voila, eax has the final result */
|
||||
/* Et voila, eax has the final result */
|
||||
" movd %%mm0,%%eax;\n"
|
||||
|
||||
" emms;\n"
|
||||
|
||||
Reference in new issue
Block a user