spandsp DSP tweaks to avoid problems with the LPC10 code compiled with the latest GCC 6.2 series compilers. Various other additional tweaks to spandsp.
This commit is contained in:
parent
62fe767e65
commit
9732d32503
|
@ -37,7 +37,7 @@ m4_include(m4/ax_c99_features.m4)
|
|||
m4_include(m4/ax_check_export_capability.m4)
|
||||
m4_include(m4/ax_check_arm_neon.m4)
|
||||
m4_include(m4/ax_func_aligned_alloc.m4)
|
||||
m4_include(m4/memmove.m4)
|
||||
m4_include(m4/ac_func_memmove.m4)
|
||||
|
||||
AC_CONFIG_SRCDIR([src/tone_generate.c])
|
||||
AC_CONFIG_AUX_DIR([config])
|
||||
|
|
|
@ -5594,6 +5594,15 @@ SPAN_DECLARE(void) at_set_modem_control_handler(at_state_t *s,
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(void) at_set_at_tx_handler(at_state_t *s,
|
||||
at_tx_handler_t at_tx_handler,
|
||||
void *at_tx_user_data)
|
||||
{
|
||||
s->at_tx_handler = at_tx_handler;
|
||||
s->at_tx_user_data = at_tx_user_data;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(logging_state_t *) at_get_logging_state(at_state_t *s)
|
||||
{
|
||||
return &s->logging;
|
||||
|
|
|
@ -52,6 +52,11 @@
|
|||
#if defined(HAVE_MATH_H)
|
||||
#include <math.h>
|
||||
#endif
|
||||
#if defined(HAVE_STDBOOL_H)
|
||||
#include <stdbool.h>
|
||||
#else
|
||||
#include "spandsp/stdbool.h"
|
||||
#endif
|
||||
#include "floating_fudge.h"
|
||||
|
||||
#include "spandsp/telephony.h"
|
||||
|
@ -62,67 +67,76 @@
|
|||
|
||||
#include "spandsp/private/awgn.h"
|
||||
|
||||
/* Gaussian noise generator constants */
|
||||
/* Random number generator constants */
|
||||
#define M1 259200
|
||||
#define IA1 7141
|
||||
#define IC1 54773
|
||||
#define RM1 (1.0/M1)
|
||||
#define RM1 (1.0/(double) M1)
|
||||
#define M2 134456
|
||||
#define IA2 8121
|
||||
#define IC2 28411
|
||||
#define RM2 (1.0/M2)
|
||||
#define RM2 (1.0/(double) M2)
|
||||
#define M3 243000
|
||||
#define IA3 4561
|
||||
#define IC3 51349
|
||||
|
||||
static double ran1(awgn_state_t *s)
|
||||
static void ran_init(awgn_state_t *s, int idum)
|
||||
{
|
||||
int j;
|
||||
|
||||
if (idum < 0)
|
||||
idum = -idum;
|
||||
s->ix1 = (IC1 + (int32_t) idum)%M1;
|
||||
s->ix1 = (IA1*s->ix1 + IC1)%M1;
|
||||
s->ix2 = s->ix1%M2;
|
||||
s->ix1 = (IA1*s->ix1 + IC1)%M1;
|
||||
s->ix3 = s->ix1%M3;
|
||||
for (j = 0; j < 97; j++)
|
||||
{
|
||||
s->ix1 = (IA1*s->ix1 + IC1)%M1;
|
||||
s->ix2 = (IA2*s->ix2 + IC2)%M2;
|
||||
s->r[j] = (s->ix1 + s->ix2*RM2)*RM1;
|
||||
}
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static double ran(awgn_state_t *s)
|
||||
{
|
||||
double temp;
|
||||
int j;
|
||||
|
||||
/* This produces evenly spread random numbers between 0.0 and 1.0 */
|
||||
s->ix1 = (IA1*s->ix1 + IC1)%M1;
|
||||
s->ix2 = (IA2*s->ix2 + IC2)%M2;
|
||||
s->ix3 = (IA3*s->ix3 + IC3)%M3;
|
||||
j = 1 + ((97*s->ix3)/M3);
|
||||
if (j > 97 || j < 1)
|
||||
j = (97*s->ix3)/M3;
|
||||
if (j > 96 || j < 0)
|
||||
{
|
||||
/* Error */
|
||||
return -1;
|
||||
temp = -1.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = s->r[j];
|
||||
s->r[j] = (s->ix1 + s->ix2*RM2)*RM1;
|
||||
}
|
||||
temp = s->r[j];
|
||||
s->r[j] = (s->ix1 + s->ix2*RM2)*RM1;
|
||||
return temp;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(awgn_state_t *) awgn_init_dbov(awgn_state_t *s, int idum, float level)
|
||||
{
|
||||
int j;
|
||||
|
||||
if (s == NULL)
|
||||
{
|
||||
if ((s = (awgn_state_t *) span_alloc(sizeof(*s))) == NULL)
|
||||
return NULL;
|
||||
}
|
||||
if (idum < 0)
|
||||
idum = -idum;
|
||||
|
||||
ran_init(s, idum);
|
||||
|
||||
s->rms = pow(10.0, level/20.0)*32768.0;
|
||||
|
||||
s->ix1 = (IC1 + idum)%M1;
|
||||
s->ix1 = (IA1*s->ix1 + IC1)%M1;
|
||||
s->ix2 = s->ix1%M2;
|
||||
s->ix1 = (IA1*s->ix1 + IC1)%M1;
|
||||
s->ix3 = s->ix1%M3;
|
||||
s->r[0] = 0.0;
|
||||
for (j = 1; j <= 97; j++)
|
||||
{
|
||||
s->ix1 = (IA1*s->ix1 + IC1)%M1;
|
||||
s->ix2 = (IA2*s->ix2 + IC2)%M2;
|
||||
s->r[j] = (s->ix1 + s->ix2*RM2)*RM1;
|
||||
}
|
||||
s->gset = 0.0;
|
||||
s->iset = 0;
|
||||
s->amp2 = 0.0;
|
||||
s->odd = true;
|
||||
return s;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -148,31 +162,30 @@ SPAN_DECLARE(int) awgn_free(awgn_state_t *s)
|
|||
|
||||
SPAN_DECLARE(int16_t) awgn(awgn_state_t *s)
|
||||
{
|
||||
double fac;
|
||||
double r;
|
||||
double v1;
|
||||
double v2;
|
||||
double amp;
|
||||
|
||||
if (s->iset == 0)
|
||||
/* The polar method of generating a Gaussian distribution */
|
||||
if ((s->odd = !s->odd))
|
||||
{
|
||||
do
|
||||
{
|
||||
v1 = 2.0*ran1(s) - 1.0;
|
||||
v2 = 2.0*ran1(s) - 1.0;
|
||||
r = v1*v1 + v2*v2;
|
||||
}
|
||||
while (r >= 1.0);
|
||||
fac = sqrt(-2.0*log(r)/r);
|
||||
s->gset = v1*fac;
|
||||
s->iset = 1;
|
||||
amp = v2*fac*s->rms;
|
||||
amp = s->amp2;
|
||||
}
|
||||
else
|
||||
{
|
||||
s->iset = 0;
|
||||
amp = s->gset*s->rms;
|
||||
do
|
||||
{
|
||||
v1 = 2.0*ran(s) - 1.0;
|
||||
v2 = 2.0*ran(s) - 1.0;
|
||||
r = v1*v1 + v2*v2;
|
||||
}
|
||||
while (r >= 1.0);
|
||||
r = sqrt(-2.0*log(r)/r);
|
||||
s->amp2 = v1*r;
|
||||
amp = v2*r;
|
||||
}
|
||||
amp *= s->rms;
|
||||
return fsaturate(amp);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
#include "spandsp/tone_detect.h"
|
||||
#include "spandsp/tone_generate.h"
|
||||
#include "spandsp/async.h"
|
||||
#include "spandsp/at_interpreter.h"
|
||||
#include "spandsp/silence_gen.h"
|
||||
#include "spandsp/fsk.h"
|
||||
#include "spandsp/v29rx.h"
|
||||
|
@ -86,6 +87,7 @@
|
|||
#include "spandsp/data_modems.h"
|
||||
|
||||
#include "spandsp/private/logging.h"
|
||||
#include "spandsp/private/at_interpreter.h"
|
||||
#include "spandsp/private/silence_gen.h"
|
||||
#include "spandsp/private/power_meter.h"
|
||||
#include "spandsp/private/fsk.h"
|
||||
|
@ -139,6 +141,7 @@ SPAN_DECLARE(const char *) data_modems_modulation_to_str(int modulation_scheme)
|
|||
case DATA_MODEM_V34:
|
||||
return "V.34 duplex";
|
||||
}
|
||||
/*endswitch*/
|
||||
return "???";
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -149,6 +152,13 @@ SPAN_DECLARE(logging_state_t *) data_modems_get_logging_state(data_modems_state_
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(void) data_modems_call_event(data_modems_state_t *s, int event)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Call event %s (%d) received\n", at_call_state_to_str(event), event);
|
||||
at_call_event(&s->at_state, event);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int async_get_byte(void *user_data)
|
||||
{
|
||||
data_modems_state_t *s;
|
||||
|
@ -169,6 +179,7 @@ static void async_put_byte(void *user_data, int byte)
|
|||
msg[0] = byte;
|
||||
if (byte < 0)
|
||||
s->put_msg(s->user_data, msg, byte);
|
||||
/*endif*/
|
||||
s->put_msg(s->user_data, msg, 1);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -193,7 +204,9 @@ static void log_supported_modulations(data_modems_state_t *s, int modulation_sch
|
|||
span_log(&s->logging, SPAN_LOG_FLOW | SPAN_LOG_SUPPRESS_LABELLING, "%s%s", comma, v8_modulation_to_str(modulation_schemes & (1 << i)));
|
||||
comma = ", ";
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*endfor*/
|
||||
span_log(&s->logging, SPAN_LOG_FLOW | SPAN_LOG_SUPPRESS_LABELLING, " supported\n");
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -385,6 +398,7 @@ SPAN_DECLARE(void) data_modems_set_modem_type(data_modems_state_t *s, int which,
|
|||
v8_parms.modem_connect_tone = MODEM_CONNECT_TONES_NONE;
|
||||
else
|
||||
v8_parms.modem_connect_tone = MODEM_CONNECT_TONES_ANSAM_PR;
|
||||
/*endif*/
|
||||
v8_parms.send_ci = false;
|
||||
v8_parms.v92 = -1;
|
||||
v8_parms.call_function = V8_CALL_V_SERIES;
|
||||
|
@ -396,6 +410,9 @@ SPAN_DECLARE(void) data_modems_set_modem_type(data_modems_state_t *s, int which,
|
|||
| V8_MOD_V23
|
||||
| V8_MOD_V27TER
|
||||
| V8_MOD_V29
|
||||
#if defined(SPANDSP_SUPPORT_V34)
|
||||
| V8_MOD_V34HDX
|
||||
#endif
|
||||
| 0;
|
||||
v8_parms.protocol = V8_PROTOCOL_LAPM_V42;
|
||||
#elif 1
|
||||
|
@ -417,10 +434,10 @@ SPAN_DECLARE(void) data_modems_set_modem_type(data_modems_state_t *s, int which,
|
|||
v8_parms.nsf = -1;
|
||||
v8_parms.t66 = -1;
|
||||
v8_init(&s->modems.v8, s->calling_party, &v8_parms, v8_handler, (void *) s);
|
||||
logging = v8_get_logging_state(&s->modems.v8);
|
||||
level = span_log_get_level(&s->logging);
|
||||
span_log_set_level(logging, level);
|
||||
span_log_set_tag(logging, "V.8");
|
||||
logging = v8_get_logging_state(&s->modems.v8);
|
||||
level = span_log_get_level(&s->logging);
|
||||
span_log_set_level(logging, level);
|
||||
span_log_set_tag(logging, "V.8");
|
||||
break;
|
||||
case DATA_MODEM_BELL103:
|
||||
s->rx_handler = (span_rx_handler_t) &fsk_rx;
|
||||
|
@ -438,6 +455,7 @@ SPAN_DECLARE(void) data_modems_set_modem_type(data_modems_state_t *s, int which,
|
|||
fsk_rx_spec = &preset_fsk_specs[FSK_BELL103CH1];
|
||||
fsk_tx_spec = &preset_fsk_specs[FSK_BELL103CH2];
|
||||
}
|
||||
/*endif*/
|
||||
fsk_rx_init(&s->modems.fsk.rx, fsk_rx_spec, FSK_FRAME_MODE_SYNC, s->put_bit, s->put_user_data);
|
||||
fsk_tx_init(&s->modems.fsk.tx, fsk_tx_spec, s->get_bit, s->get_user_data);
|
||||
break;
|
||||
|
@ -457,6 +475,7 @@ SPAN_DECLARE(void) data_modems_set_modem_type(data_modems_state_t *s, int which,
|
|||
fsk_rx_spec = &preset_fsk_specs[FSK_V21CH1];
|
||||
fsk_tx_spec = &preset_fsk_specs[FSK_V21CH2];
|
||||
}
|
||||
/*endif*/
|
||||
fsk_rx_init(&s->modems.fsk.rx, fsk_rx_spec, FSK_FRAME_MODE_SYNC, s->put_bit, s->put_user_data);
|
||||
fsk_tx_init(&s->modems.fsk.tx, fsk_tx_spec, s->get_bit, s->get_user_data);
|
||||
break;
|
||||
|
@ -487,6 +506,7 @@ SPAN_DECLARE(void) data_modems_set_modem_type(data_modems_state_t *s, int which,
|
|||
fsk_rx_spec = &preset_fsk_specs[FSK_V23CH1];
|
||||
fsk_tx_spec = &preset_fsk_specs[FSK_V23CH2];
|
||||
}
|
||||
/*endif*/
|
||||
fsk_rx_init(&s->modems.fsk.rx, fsk_rx_spec, FSK_FRAME_MODE_SYNC, s->put_bit, s->put_user_data);
|
||||
fsk_tx_init(&s->modems.fsk.tx, fsk_tx_spec, s->get_bit, s->get_user_data);
|
||||
break;
|
||||
|
@ -497,10 +517,10 @@ SPAN_DECLARE(void) data_modems_set_modem_type(data_modems_state_t *s, int which,
|
|||
s->tx_handler = (span_tx_handler_t) &v22bis_tx;
|
||||
s->tx_user_data = &s->modems.v22bis;
|
||||
v22bis_init(&s->modems.v22bis, bit_rate, 0, s->calling_party, s->get_bit, s->get_user_data, s->put_bit, s->put_user_data);
|
||||
logging = v22bis_get_logging_state(&s->modems.v22bis);
|
||||
level = span_log_get_level(&s->logging);
|
||||
span_log_set_level(logging, level);
|
||||
span_log_set_tag(logging, "V.22bis");
|
||||
logging = v22bis_get_logging_state(&s->modems.v22bis);
|
||||
level = span_log_get_level(&s->logging);
|
||||
span_log_set_level(logging, level);
|
||||
span_log_set_tag(logging, "V.22bis");
|
||||
break;
|
||||
#if defined(SPANDSP_SUPPORT_V32BIS)
|
||||
case DATA_MODEM_V32BIS:
|
||||
|
@ -510,10 +530,10 @@ SPAN_DECLARE(void) data_modems_set_modem_type(data_modems_state_t *s, int which,
|
|||
s->tx_handler = (span_tx_handler_t) &v32bis_tx;
|
||||
s->tx_user_data = &s->modems.v32bis;
|
||||
v32bis_init(&s->modems.v32bis, bit_rate, s->calling_party, s->get_bit, s->get_user_data, s->put_bit, s->put_user_data);
|
||||
logging = v32bis_get_logging_state(&s->modems.v32bis);
|
||||
level = span_log_get_level(&s->logging);
|
||||
span_log_set_level(logging, level);
|
||||
span_log_set_tag(logging, "V.32bis");
|
||||
logging = v32bis_get_logging_state(&s->modems.v32bis);
|
||||
level = span_log_get_level(&s->logging);
|
||||
span_log_set_level(logging, level);
|
||||
span_log_set_tag(logging, "V.32bis");
|
||||
break;
|
||||
#endif
|
||||
#if defined(SPANDSP_SUPPORT_V34)
|
||||
|
@ -524,13 +544,14 @@ SPAN_DECLARE(void) data_modems_set_modem_type(data_modems_state_t *s, int which,
|
|||
s->tx_handler = (span_tx_handler_t) &v34_tx;
|
||||
s->tx_user_data = &s->modems.v34;
|
||||
v34_init(&s->modems.v34, baud_rate, bit_rate, s->calling_party, true, s->get_bit, s->get_user_data, s->put_bit, s->put_user_data);
|
||||
logging = v34_get_logging_state(&s->modems.v34);
|
||||
level = span_log_get_level(&s->logging);
|
||||
span_log_set_level(logging, level);
|
||||
span_log_set_tag(logging, "V.34");
|
||||
logging = v34_get_logging_state(&s->modems.v34);
|
||||
level = span_log_get_level(&s->logging);
|
||||
span_log_set_level(logging, level);
|
||||
span_log_set_tag(logging, "V.34");
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
/*endswitch*/
|
||||
s->current_modem = which;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -541,9 +562,11 @@ SPAN_DECLARE(int) data_modems_rx(data_modems_state_t *s, const int16_t amp[], in
|
|||
|
||||
if (s->rx_handler == NULL)
|
||||
return len;
|
||||
/*endif*/
|
||||
res = s->rx_handler(s->rx_user_data, amp, len);
|
||||
if (s->current_modem != s->queued_modem)
|
||||
data_modems_set_modem_type(s, s->queued_modem, s->queued_baud_rate, s->queued_bit_rate);
|
||||
/*endif*/
|
||||
return res;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -552,6 +575,7 @@ SPAN_DECLARE(int) data_modems_rx_fillin(data_modems_state_t *s, int len)
|
|||
{
|
||||
if (s->rx_fillin_handler == NULL)
|
||||
return len;
|
||||
/*endif*/
|
||||
return s->rx_fillin_handler(s->rx_user_data, len);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -564,12 +588,52 @@ SPAN_DECLARE(int) data_modems_tx(data_modems_state_t *s, int16_t amp[], int max_
|
|||
{
|
||||
if (s->tx_handler == NULL)
|
||||
break;
|
||||
/*endif*/
|
||||
len += s->tx_handler(s->tx_user_data, &[len], max_len - len);
|
||||
}
|
||||
/*endfor*/
|
||||
return len;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int data_modems_control_handler(void *user_data, int op, const char *num)
|
||||
{
|
||||
data_modems_state_t *s;
|
||||
|
||||
s = (data_modems_state_t *) user_data;
|
||||
switch (op)
|
||||
{
|
||||
case AT_MODEM_CONTROL_CALL:
|
||||
s->call_samples = 0;
|
||||
break;
|
||||
case AT_MODEM_CONTROL_ANSWER:
|
||||
s->call_samples = 0;
|
||||
break;
|
||||
case AT_MODEM_CONTROL_ONHOOK:
|
||||
if (s->at_state.rx_signal_present)
|
||||
{
|
||||
s->at_state.rx_data_bytes = 0;
|
||||
}
|
||||
/*endif*/
|
||||
break;
|
||||
case AT_MODEM_CONTROL_RESTART:
|
||||
return 0;
|
||||
case AT_MODEM_CONTROL_DTE_TIMEOUT:
|
||||
return 0;
|
||||
}
|
||||
/*endswitch*/
|
||||
return s->modem_control_handler(s, s->modem_control_user_data, op, num);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(void) data_modems_set_at_tx_handler(data_modems_state_t *s,
|
||||
at_tx_handler_t at_tx_handler,
|
||||
void *at_tx_user_data)
|
||||
{
|
||||
at_set_at_tx_handler(&s->at_state, at_tx_handler, at_tx_user_data);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
SPAN_DECLARE(int) data_modems_restart(data_modems_state_t *s)
|
||||
{
|
||||
return 0;
|
||||
|
@ -578,21 +642,34 @@ SPAN_DECLARE(int) data_modems_restart(data_modems_state_t *s)
|
|||
|
||||
SPAN_DECLARE(data_modems_state_t *) data_modems_init(data_modems_state_t *s,
|
||||
bool calling_party,
|
||||
at_tx_handler_t at_tx_handler,
|
||||
void *at_tx_user_data,
|
||||
data_modems_control_handler_t modem_control_handler,
|
||||
void *modem_control_user_data,
|
||||
put_msg_func_t put_msg,
|
||||
get_msg_func_t get_msg,
|
||||
void *user_data)
|
||||
{
|
||||
if (at_tx_handler == NULL || modem_control_handler == NULL)
|
||||
return NULL;
|
||||
/*endif*/
|
||||
|
||||
if (s == NULL)
|
||||
{
|
||||
if ((s = (data_modems_state_t *) span_alloc(sizeof(*s))) == NULL)
|
||||
return NULL;
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
memset(s, 0, sizeof(*s));
|
||||
span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
|
||||
span_log_set_protocol(&s->logging, "Modem");
|
||||
|
||||
dc_restore_init(&s->dc_restore);
|
||||
|
||||
s->modem_control_handler = modem_control_handler;
|
||||
s->modem_control_user_data = modem_control_user_data;
|
||||
|
||||
s->put_msg = put_msg;
|
||||
s->get_msg = get_msg;
|
||||
s->user_data = user_data;
|
||||
|
@ -602,6 +679,8 @@ SPAN_DECLARE(data_modems_state_t *) data_modems_init(data_modems_state_t *s,
|
|||
|
||||
data_modems_set_async_mode(s, 8, 1, 1);
|
||||
|
||||
at_init(&s->at_state, at_tx_handler, at_tx_user_data, data_modems_control_handler, s);
|
||||
|
||||
s->get_bit = async_tx_get_bit;
|
||||
s->get_user_data = &s->async_tx;
|
||||
s->put_bit = async_rx_put_bit;
|
||||
|
@ -627,6 +706,7 @@ SPAN_DECLARE(int) data_modems_free(data_modems_state_t *s)
|
|||
{
|
||||
if (s)
|
||||
span_free(s);
|
||||
/*endif*/
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
|
|
@ -89,6 +89,7 @@ static __inline__ void octet_set_and_count(hdlc_rx_state_t *s)
|
|||
{
|
||||
if (s->octet_count_report_interval == 0)
|
||||
return;
|
||||
/*endif*/
|
||||
|
||||
/* If we are not in octet counting mode, we start it.
|
||||
If we are in octet counting mode, we update it. */
|
||||
|
@ -625,6 +626,7 @@ SPAN_DECLARE(int) hdlc_tx_get_byte(hdlc_tx_state_t *s)
|
|||
/* An input byte will generate between 8 and 10 output bits */
|
||||
return (s->octets_in_progress >> s->num_bits) & 0xFF;
|
||||
}
|
||||
/*endif*/
|
||||
/* Untimed idling on flags */
|
||||
if (s->tx_end)
|
||||
{
|
||||
|
@ -644,8 +646,10 @@ SPAN_DECLARE(int) hdlc_tx_get_bit(hdlc_tx_state_t *s)
|
|||
{
|
||||
if ((s->byte = hdlc_tx_get_byte(s)) < 0)
|
||||
return s->byte;
|
||||
/*endif*/
|
||||
s->bits = 8;
|
||||
}
|
||||
/*endif*/
|
||||
s->bits--;
|
||||
txbit = (s->byte >> s->bits) & 0x01;
|
||||
return txbit;
|
||||
|
@ -661,8 +665,10 @@ SPAN_DECLARE(int) hdlc_tx_get(hdlc_tx_state_t *s, uint8_t buf[], size_t max_len)
|
|||
{
|
||||
if ((x = hdlc_tx_get_byte(s)) == SIG_STATUS_END_OF_DATA)
|
||||
return i;
|
||||
/*endif*/
|
||||
buf[i] = (uint8_t) x;
|
||||
}
|
||||
/*endfor*/
|
||||
return (int) i;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
|
|
@ -532,7 +532,7 @@ static int floyd_steinberg_dither_row(image_translate_state_t *s, uint8_t buf[])
|
|||
s->output_row = -1;
|
||||
}
|
||||
}
|
||||
/* Apply Floyd-Steinberg dithering to the 8 bit pixels, using a bustrophodontic
|
||||
/* Apply Floyd-Steinberg dithering to the 8 bit pixels, using a bustrophedontic
|
||||
scan, to reduce the grayscale image to pure black and white */
|
||||
/* The first and last pixels in each row need special treatment, so we do not
|
||||
step outside the row. */
|
||||
|
|
|
@ -564,7 +564,7 @@ void lpc10_analyse(lpc10_encode_state_t *s, float speech[], int32_t voice[], int
|
|||
static const float precoef = 0.9375f;
|
||||
|
||||
float amdf[60];
|
||||
float abuf[156];
|
||||
float abuf[LPC10_MIN_PITCH];
|
||||
float ivrc[2];
|
||||
float temp;
|
||||
float phi[100] /* was [10][10] */;
|
||||
|
@ -634,7 +634,7 @@ void lpc10_analyse(lpc10_encode_state_t *s, float speech[], int32_t voice[], int
|
|||
s->zpre = preemp(&s->inbuf[i - 181], &s->pebuf[i - 181], LPC10_SAMPLES_PER_FRAME, precoef, s->zpre);
|
||||
onset(s, s->pebuf, s->osbuf, &s->osptr, 10, 181, 720, LPC10_SAMPLES_PER_FRAME);
|
||||
|
||||
lpc10_placev(s->osbuf, &s->osptr, 10, &s->obound[2], s->vwin, 3, LPC10_SAMPLES_PER_FRAME, 90, 156, 307, 462);
|
||||
lpc10_placev(s->osbuf, &s->osptr, 10, &s->obound[2], s->vwin, 3, LPC10_SAMPLES_PER_FRAME, 90, LPC10_MIN_PITCH, 307, 462);
|
||||
/* The Pitch Extraction algorithm estimates the pitch for a frame
|
||||
of speech by locating the minimum of the average magnitude difference
|
||||
function (AMDF). The AMDF operates on low-pass, inverse filtered
|
||||
|
@ -655,7 +655,7 @@ void lpc10_analyse(lpc10_encode_state_t *s, float speech[], int32_t voice[], int
|
|||
/* eval_highres_amdf reads indices PWINL = 229 through
|
||||
(PWINL-1)+MAXWIN+(TAU(LTAU)-TAU(1))/2 = 452 of IVBUF, and writes
|
||||
indices 1 through LTAU = 60 of AMDF. */
|
||||
eval_highres_amdf(s->ivbuf, 156, tau, 60, amdf, &minptr, &maxptr, &mintau);
|
||||
eval_highres_amdf(s->ivbuf, LPC10_MIN_PITCH, tau, 60, amdf, &minptr, &maxptr, &mintau);
|
||||
/* Voicing decisions are made for each half frame of input speech.
|
||||
An initial voicing classification is made for each half of the
|
||||
analysis frame, and the voicing decisions for the present frame
|
||||
|
@ -688,7 +688,7 @@ void lpc10_analyse(lpc10_encode_state_t *s, float speech[], int32_t voice[], int
|
|||
dynamic_pitch_tracking(s, amdf, 60, &minptr, s->voibuf[3][1], pitch, &midx);
|
||||
ipitch = tau[midx - 1];
|
||||
/* Place spectrum analysis and energy windows */
|
||||
lpc10_placea(&ipitch, s->voibuf, &s->obound[2], 3, s->vwin, s->awin, ewin, LPC10_SAMPLES_PER_FRAME, 156);
|
||||
lpc10_placea(&ipitch, s->voibuf, &s->obound[2], 3, s->vwin, s->awin, ewin, LPC10_SAMPLES_PER_FRAME, LPC10_MIN_PITCH);
|
||||
/* Remove short term DC bias over the analysis window. */
|
||||
lanal = s->awin[2][1] + 1 - s->awin[2][0];
|
||||
remove_dc_bias(&s->pebuf[s->awin[2][0] - 181], lanal, abuf);
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
#include "spandsp/lpc10.h"
|
||||
#include "spandsp/private/lpc10.h"
|
||||
|
||||
#define LPC10_ORDER 10
|
||||
#include "lpc10_encdecs.h"
|
||||
|
||||
#if !defined(min)
|
||||
#define min(a,b) ((a) <= (b) ? (a) : (b))
|
||||
|
@ -81,32 +81,6 @@ static int32_t lpc10_random(lpc10_decode_state_t *s)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static __inline__ int32_t pow_ii(int32_t x, int32_t n)
|
||||
{
|
||||
int32_t pow;
|
||||
uint32_t u;
|
||||
|
||||
if (n <= 0)
|
||||
{
|
||||
if (n == 0 || x == 1)
|
||||
return 1;
|
||||
if (x != -1)
|
||||
return (x != 0) ? 1/x : 0;
|
||||
n = -n;
|
||||
}
|
||||
u = n;
|
||||
for (pow = 1; ; )
|
||||
{
|
||||
if ((u & 1))
|
||||
pow *= x;
|
||||
if ((u >>= 1) == 0)
|
||||
break;
|
||||
x *= x;
|
||||
}
|
||||
return pow;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
/* Synthesize one pitch epoch */
|
||||
static void bsynz(lpc10_decode_state_t *s,
|
||||
float coef[],
|
||||
|
@ -127,7 +101,7 @@ static void bsynz(lpc10_decode_state_t *s,
|
|||
int32_t j;
|
||||
int32_t k;
|
||||
int32_t px;
|
||||
float noise[166];
|
||||
float noise[LPC10_MIN_PITCH];
|
||||
float pulse;
|
||||
float r1;
|
||||
float gain;
|
||||
|
@ -177,14 +151,13 @@ static void bsynz(lpc10_decode_state_t *s,
|
|||
}
|
||||
for (i = 0; i < ip; i++)
|
||||
{
|
||||
noise[LPC10_ORDER + i] = lpc10_random(s)/64.0f;
|
||||
hpi0 = noise[LPC10_ORDER + i];
|
||||
noise[LPC10_ORDER + i] = noise[LPC10_ORDER + i]*-0.125f + s->hpi[0]*0.25f + s->hpi[1]*-0.125f;
|
||||
hpi0 = lpc10_random(s)/64.0f;
|
||||
noise[i] = hpi0*-0.125f + s->hpi[0]*0.25f + s->hpi[1]*-0.125f;
|
||||
s->hpi[1] = s->hpi[0];
|
||||
s->hpi[0] = hpi0;
|
||||
}
|
||||
for (i = 0; i < ip; i++)
|
||||
s->exc[LPC10_ORDER + i] += noise[LPC10_ORDER + i];
|
||||
s->exc[LPC10_ORDER + i] += noise[i];
|
||||
}
|
||||
/* Synthesis filters: */
|
||||
/* Modify the excitation with all-zero filter 1 + G*SUM */
|
||||
|
@ -224,20 +197,17 @@ static void bsynz(lpc10_decode_state_t *s,
|
|||
|
||||
/* Synthesize a single pitch epoch */
|
||||
static int pitsyn(lpc10_decode_state_t *s,
|
||||
int voice[],
|
||||
int voice[2],
|
||||
int32_t *pitch,
|
||||
float *rms,
|
||||
float *rc,
|
||||
int32_t ivuv[],
|
||||
int32_t ipiti[],
|
||||
float *rmsi,
|
||||
float *rci,
|
||||
float rms,
|
||||
float rc[LPC10_ORDER],
|
||||
int32_t ivuv[16],
|
||||
int32_t ipiti[16],
|
||||
float rmsi[16],
|
||||
float rci[16*LPC10_ORDER],
|
||||
int32_t *nout,
|
||||
float *ratio)
|
||||
{
|
||||
int32_t rci_dim1;
|
||||
int32_t rci_offset;
|
||||
int32_t i1;
|
||||
int32_t i;
|
||||
int32_t j;
|
||||
int32_t vflag;
|
||||
|
@ -257,16 +227,12 @@ static int pitsyn(lpc10_decode_state_t *s,
|
|||
float xxy;
|
||||
float msix;
|
||||
|
||||
rci_dim1 = LPC10_ORDER;
|
||||
rci_offset = rci_dim1 + 1;
|
||||
rci -= rci_offset;
|
||||
|
||||
if (*rms < 1.0f)
|
||||
*rms = 1.0f;
|
||||
if (rms < 1.0f)
|
||||
rms = 1.0f;
|
||||
if (s->rmso < 1.0f)
|
||||
s->rmso = 1.0f;
|
||||
uvpit = 0.0f;
|
||||
*ratio = *rms/(s->rmso + 8.0f);
|
||||
*ratio = rms/(s->rmso + 8.0f);
|
||||
if (s->first_pitsyn)
|
||||
{
|
||||
ivoice = voice[1];
|
||||
|
@ -275,14 +241,13 @@ static int pitsyn(lpc10_decode_state_t *s,
|
|||
*nout = LPC10_SAMPLES_PER_FRAME / *pitch;
|
||||
s->jsamp = LPC10_SAMPLES_PER_FRAME - *nout * *pitch;
|
||||
|
||||
i1 = *nout;
|
||||
for (i = 0; i < i1; i++)
|
||||
for (i = 0; i < *nout; i++)
|
||||
{
|
||||
for (j = 0; j < LPC10_ORDER; j++)
|
||||
rci[j + (i + 1)*rci_dim1 + 1] = rc[j];
|
||||
rci[j + i*LPC10_ORDER] = rc[j];
|
||||
ivuv[i] = ivoice;
|
||||
ipiti[i] = *pitch;
|
||||
rmsi[i] = *rms;
|
||||
rmsi[i] = rms;
|
||||
}
|
||||
s->first_pitsyn = false;
|
||||
}
|
||||
|
@ -301,7 +266,7 @@ static int pitsyn(lpc10_decode_state_t *s,
|
|||
*pitch = LPC10_SAMPLES_PER_FRAME/4;
|
||||
s->ipito = *pitch;
|
||||
if (*ratio > 8.0f)
|
||||
s->rmso = *rms;
|
||||
s->rmso = rms;
|
||||
}
|
||||
/* SSVC - - 1 , 1 , 1 */
|
||||
slope = (*pitch - s->ipito)/(float) lsamp;
|
||||
|
@ -329,8 +294,8 @@ static int pitsyn(lpc10_decode_state_t *s,
|
|||
rmsi[1] = s->rmso;
|
||||
for (i = 0; i < LPC10_ORDER; i++)
|
||||
{
|
||||
rci[i + rci_dim1 + 1] = s->rco[i];
|
||||
rci[i + (rci_dim1 << 1) + 1] = s->rco[i];
|
||||
rci[i] = s->rco[i];
|
||||
rci[i + LPC10_ORDER] = s->rco[i];
|
||||
s->rco[i] = rc[i];
|
||||
}
|
||||
*nout = 2;
|
||||
|
@ -434,10 +399,9 @@ static int pitsyn(lpc10_decode_state_t *s,
|
|||
ip = (int32_t) uvpit;
|
||||
if (ip <= i - jused)
|
||||
{
|
||||
++(*nout);
|
||||
ipiti[*nout - 1] = ip;
|
||||
ipiti[*nout] = ip;
|
||||
*pitch = ip;
|
||||
ivuv[*nout - 1] = ivoice;
|
||||
ivuv[*nout] = ivoice;
|
||||
jused += ip;
|
||||
prop = (jused - ip/2)/(float) lsamp;
|
||||
for (j = 0; j < LPC10_ORDER; j++)
|
||||
|
@ -446,12 +410,13 @@ static int pitsyn(lpc10_decode_state_t *s,
|
|||
alrn = logf((rc[j] + 1)/(1 - rc[j]));
|
||||
xxy = alro + prop*(alrn - alro);
|
||||
xxy = expf(xxy);
|
||||
rci[j + *nout*rci_dim1 + 1] = (xxy - 1.0f)/(xxy + 1.0f);
|
||||
rci[j + *nout*LPC10_ORDER] = (xxy - 1.0f)/(xxy + 1.0f);
|
||||
}
|
||||
msix = logf(*rms) - logf(s->rmso);
|
||||
msix = logf(rms) - logf(s->rmso);
|
||||
msix = prop*msix;
|
||||
msix = logf(s->rmso) + msix;
|
||||
rmsi[*nout - 1] = expf(msix);
|
||||
rmsi[*nout] = expf(msix);
|
||||
(*nout)++;
|
||||
}
|
||||
}
|
||||
if (vflag != 1)
|
||||
|
@ -465,7 +430,7 @@ static int pitsyn(lpc10_decode_state_t *s,
|
|||
uvpit = (float) ((lsamp - istart)/2);
|
||||
if (uvpit > 90.0f)
|
||||
uvpit /= 2;
|
||||
s->rmso = *rms;
|
||||
s->rmso = rms;
|
||||
for (i = 0; i < LPC10_ORDER; i++)
|
||||
{
|
||||
rc[i] = yarc[i];
|
||||
|
@ -478,7 +443,7 @@ static int pitsyn(lpc10_decode_state_t *s,
|
|||
{
|
||||
s->ivoico = voice[1];
|
||||
s->ipito = *pitch;
|
||||
s->rmso = *rms;
|
||||
s->rmso = rms;
|
||||
for (i = 0; i < LPC10_ORDER; i++)
|
||||
s->rco[i] = rc[i];
|
||||
}
|
||||
|
@ -532,13 +497,12 @@ static float reflection_coeffs_to_predictor_coeffs(float rc[], float pc[], float
|
|||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int synths(lpc10_decode_state_t *s,
|
||||
int voice[],
|
||||
int voice[2],
|
||||
int32_t *pitch,
|
||||
float *rms,
|
||||
float *rc,
|
||||
float rms,
|
||||
float rc[LPC10_ORDER],
|
||||
float speech[])
|
||||
{
|
||||
int32_t i1;
|
||||
int32_t ivuv[16];
|
||||
int32_t ipiti[16];
|
||||
int32_t nout;
|
||||
|
@ -547,11 +511,10 @@ static int synths(lpc10_decode_state_t *s,
|
|||
float rmsi[16];
|
||||
float ratio;
|
||||
float g2pass;
|
||||
float pc[10];
|
||||
float rci[160];
|
||||
float pc[LPC10_ORDER];
|
||||
float rci[16*LPC10_ORDER];
|
||||
|
||||
i1 = min(*pitch, 156);
|
||||
*pitch = max(i1, 20);
|
||||
*pitch = max(min(*pitch, LPC10_MIN_PITCH), LPC10_MAX_PITCH);
|
||||
for (i = 0; i < LPC10_ORDER; i++)
|
||||
rc[i] = max(min(rc[i], 0.99f), -0.99f);
|
||||
pitsyn(s, voice, pitch, rms, rc, ivuv, ipiti, rmsi, rci, &nout, &ratio);
|
||||
|
@ -560,14 +523,13 @@ static int synths(lpc10_decode_state_t *s,
|
|||
for (j = 0; j < nout; j++)
|
||||
{
|
||||
/* Add synthesized speech for pitch period J to the end of s->buf. */
|
||||
g2pass = reflection_coeffs_to_predictor_coeffs(&rci[j*10], pc, 0.7f);
|
||||
g2pass = reflection_coeffs_to_predictor_coeffs(&rci[j*LPC10_ORDER], pc, 0.7f);
|
||||
bsynz(s, pc, ipiti[j], &ivuv[j], &s->buf[s->buflen], rmsi[j], ratio, g2pass);
|
||||
deemp(s, &s->buf[s->buflen], ipiti[j]);
|
||||
s->buflen += ipiti[j];
|
||||
}
|
||||
/* Copy first MAXFRM samples from BUF to output array speech (scaling them),
|
||||
and then remove them from the beginning of s->buf. */
|
||||
|
||||
for (i = 0; i < LPC10_SAMPLES_PER_FRAME; i++)
|
||||
speech[i] = s->buf[i]/4096.0f;
|
||||
s->buflen -= LPC10_SAMPLES_PER_FRAME;
|
||||
|
@ -709,7 +671,7 @@ static int32_t median(int32_t d1, int32_t d2, int32_t d3)
|
|||
|
||||
static void decode(lpc10_decode_state_t *s,
|
||||
lpc10_frame_t *t,
|
||||
int voice[],
|
||||
int voice[2],
|
||||
int32_t *pitch,
|
||||
float *rms,
|
||||
float rc[])
|
||||
|
@ -1110,7 +1072,7 @@ SPAN_DECLARE(int) lpc10_decode(lpc10_decode_state_t *s, int16_t amp[], const uin
|
|||
{
|
||||
lpc10_unpack(&frame, &code[i*7]);
|
||||
decode(s, &frame, voice, &pitch, &rms, rc);
|
||||
synths(s, voice, &pitch, &rms, rc, speech);
|
||||
synths(s, voice, &pitch, rms, rc, speech);
|
||||
base = i*LPC10_SAMPLES_PER_FRAME;
|
||||
for (j = 0; j < LPC10_SAMPLES_PER_FRAME; j++)
|
||||
amp[base + j] = (int16_t) lfastrintf(32768.0f*speech[j]);
|
||||
|
|
|
@ -23,7 +23,9 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#define LPC10_ORDER 10
|
||||
#define LPC10_ORDER 10
|
||||
#define LPC10_MAX_PITCH 20
|
||||
#define LPC10_MIN_PITCH 156
|
||||
|
||||
#if !defined(min)
|
||||
#define min(a,b) ((a) <= (b) ? (a) : (b))
|
||||
|
|
|
@ -353,10 +353,6 @@ void lpc10_voicing(lpc10_encode_state_t *s,
|
|||
/* Voicing decision for current half-frame: 1 = Voiced; 0 = Unvoiced */
|
||||
s->voibuf[3][half] = (s->voice[2][half] > 0.0f) ? 1 : 0;
|
||||
/* Skip voicing decision smoothing in first half-frame: */
|
||||
/* Give a value to VSTATE, so that trace statements below will print */
|
||||
/* a consistent value from one call to the next when HALF .EQ. 1. */
|
||||
/* The value of VSTATE is not used for any other purpose when this is */
|
||||
/* true. */
|
||||
if (half != 0)
|
||||
{
|
||||
/* Voicing decision smoothing rules (override of linear combination): */
|
||||
|
|
|
@ -646,7 +646,7 @@ int main(int argc, char *argv[])
|
|||
exit(2);
|
||||
/*endif*/
|
||||
|
||||
printf("/* THIS FILE WAS AUTOMATICALLY GENERATED - ANY MODIFICATIONS MADE TO THIS");
|
||||
printf("/* THIS FILE WAS AUTOMATICALLY GENERATED - ANY MODIFICATIONS MADE TO THIS\n");
|
||||
printf(" FILE MAY BE OVERWRITTEN DURING FUTURE BUILDS OF THE SOFTWARE */\n");
|
||||
printf("\n");
|
||||
|
||||
|
@ -661,7 +661,7 @@ int main(int argc, char *argv[])
|
|||
trie_recursive_build_packed_trie(s->root);
|
||||
|
||||
dump_trie();
|
||||
|
||||
|
||||
trie_free(s);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -46,7 +46,7 @@ int main(int argc, char *argv[])
|
|||
uint8_t srgb;
|
||||
int i;
|
||||
|
||||
printf("/* THIS FILE WAS AUTOMATICALLY GENERATED - ANY MODIFICATIONS MADE TO THIS");
|
||||
printf("/* THIS FILE WAS AUTOMATICALLY GENERATED - ANY MODIFICATIONS MADE TO THIS\n");
|
||||
printf(" FILE MAY BE OVERWRITTEN DURING FUTURE BUILDS OF THE SOFTWARE */\n");
|
||||
printf("\n");
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ int main(int argc, char *argv[])
|
|||
double val;
|
||||
int ival;
|
||||
|
||||
printf("/* THIS FILE WAS AUTOMATICALLY GENERATED - ANY MODIFICATIONS MADE TO THIS");
|
||||
printf("/* THIS FILE WAS AUTOMATICALLY GENERATED - ANY MODIFICATIONS MADE TO THIS\n");
|
||||
printf(" FILE MAY BE OVERWRITTEN DURING FUTURE BUILDS OF THE SOFTWARE */\n");
|
||||
printf("\n");
|
||||
|
||||
|
|
|
@ -32,11 +32,7 @@
|
|||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
#include <math.h>
|
||||
#if defined(HAVE_STDBOOL_H)
|
||||
#include <stdbool.h>
|
||||
#else
|
||||
#include "spandsp/stdbool.h"
|
||||
#endif
|
||||
#if defined(__sunos) || defined(__solaris) || defined(__sun)
|
||||
#include <getopt.h>
|
||||
#endif
|
||||
|
@ -103,7 +99,7 @@ static void make_tx_filter(int coeff_sets,
|
|||
|
||||
/* Churn out the data as a C source code header file, which can be directly included by the
|
||||
modem code. */
|
||||
printf("/* THIS FILE WAS AUTOMATICALLY GENERATED - ANY MODIFICATIONS MADE TO THIS");
|
||||
printf("/* THIS FILE WAS AUTOMATICALLY GENERATED - ANY MODIFICATIONS MADE TO THIS\n");
|
||||
printf(" FILE MAY BE OVERWRITTEN DURING FUTURE BUILDS OF THE SOFTWARE */\n");
|
||||
printf("\n");
|
||||
printf("#if defined(SPANDSP_USE_FIXED_POINT)\n");
|
||||
|
|
|
@ -39,7 +39,7 @@ int main(int argc, char *argv[])
|
|||
int new_gray;
|
||||
int restore;
|
||||
|
||||
printf("/* THIS FILE WAS AUTOMATICALLY GENERATED - ANY MODIFICATIONS MADE TO THIS");
|
||||
printf("/* THIS FILE WAS AUTOMATICALLY GENERATED - ANY MODIFICATIONS MADE TO THIS\n");
|
||||
printf(" FILE MAY BE OVERWRITTEN DURING FUTURE BUILDS OF THE SOFTWARE */\n");
|
||||
printf("\n");
|
||||
|
||||
|
|
|
@ -177,6 +177,10 @@ SPAN_DECLARE(void) at_set_modem_control_handler(at_state_t *s,
|
|||
at_modem_control_handler_t modem_control_handler,
|
||||
void *modem_control_user_data);
|
||||
|
||||
SPAN_DECLARE(void) at_set_at_tx_handler(at_state_t *s,
|
||||
at_tx_handler_t at_tx_handler,
|
||||
void *at_tx_user_data);
|
||||
|
||||
/*! Initialise an AT interpreter context.
|
||||
\brief Initialise an AT interpreter context.
|
||||
\param s The AT context.
|
||||
|
|
|
@ -50,6 +50,8 @@ enum
|
|||
*/
|
||||
typedef struct data_modems_state_s data_modems_state_t;
|
||||
|
||||
typedef int (*data_modems_control_handler_t)(data_modems_state_t *s, void *user_data, int op, const char *num);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C"
|
||||
{
|
||||
|
@ -62,6 +64,8 @@ SPAN_DECLARE(void) data_modems_set_tep_mode(data_modems_state_t *s, int use_tep)
|
|||
|
||||
SPAN_DECLARE(logging_state_t *) data_modems_get_logging_state(data_modems_state_t *s);
|
||||
|
||||
SPAN_DECLARE(void) data_modems_call_event(data_modems_state_t *s, int event);
|
||||
|
||||
SPAN_DECLARE(int) data_modems_restart(data_modems_state_t *s);
|
||||
|
||||
SPAN_DECLARE(void) data_modems_set_async_mode(data_modems_state_t *s,
|
||||
|
@ -77,8 +81,16 @@ SPAN_DECLARE(int) data_modems_rx_fillin(data_modems_state_t *s, int len);
|
|||
|
||||
SPAN_DECLARE(int) data_modems_tx(data_modems_state_t *s, int16_t amp[], int max_len);
|
||||
|
||||
SPAN_DECLARE(void) data_modems_set_at_tx_handler(data_modems_state_t *s,
|
||||
at_tx_handler_t at_tx_handler,
|
||||
void *at_tx_user_data);
|
||||
|
||||
SPAN_DECLARE(data_modems_state_t *) data_modems_init(data_modems_state_t *s,
|
||||
bool calling_party,
|
||||
at_tx_handler_t at_tx_handler,
|
||||
void *at_tx_user_data,
|
||||
data_modems_control_handler_t modem_control_handler,
|
||||
void *modem_control_user_data,
|
||||
put_msg_func_t put_msg,
|
||||
get_msg_func_t get_msg,
|
||||
void *user_data);
|
||||
|
|
|
@ -115,7 +115,7 @@ extern "C"
|
|||
/* Enable the trap as per the MIL-STD */
|
||||
//#define G711_ULAW_ZEROTRAP
|
||||
/*! Bias for u-law encoding from linear. */
|
||||
#define G711_ULAW_BIAS 0x84
|
||||
#define G711_ULAW_BIAS 0x84
|
||||
|
||||
/*! \brief Encode a linear sample to u-law
|
||||
\param linear The sample to encode.
|
||||
|
|
|
@ -31,13 +31,16 @@
|
|||
*/
|
||||
struct awgn_state_s
|
||||
{
|
||||
/* Scaling factor */
|
||||
double rms;
|
||||
long int ix1;
|
||||
long int ix2;
|
||||
long int ix3;
|
||||
double r[98];
|
||||
double gset;
|
||||
int iset;
|
||||
/* Working data for the Gaussian generator */
|
||||
bool odd;
|
||||
double amp2;
|
||||
/* Working data for the random number generator */
|
||||
int32_t ix1;
|
||||
int32_t ix2;
|
||||
int32_t ix3;
|
||||
double r[97];
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -43,6 +43,9 @@ struct data_modems_state_s
|
|||
silent audio. */
|
||||
bool transmit_on_idle;
|
||||
|
||||
at_state_t at_state;
|
||||
data_modems_control_handler_t modem_control_handler;
|
||||
void *modem_control_user_data;
|
||||
get_bit_func_t get_bit;
|
||||
void *get_user_data;
|
||||
put_bit_func_t put_bit;
|
||||
|
@ -60,6 +63,9 @@ struct data_modems_state_s
|
|||
async_tx_state_t async_tx;
|
||||
async_rx_state_t async_rx;
|
||||
|
||||
/*! \brief Samples elapsed in the current call */
|
||||
int64_t call_samples;
|
||||
|
||||
union
|
||||
{
|
||||
v8_state_t v8;
|
||||
|
|
|
@ -31,10 +31,13 @@ struct v18_state_s
|
|||
/*! \brief True if we are the calling modem */
|
||||
bool calling_party;
|
||||
int mode;
|
||||
int initial_mode;
|
||||
int current_mode;
|
||||
int nation;
|
||||
put_msg_func_t put_msg;
|
||||
void *user_data;
|
||||
int repeat_shifts;
|
||||
bool repeat_shifts;
|
||||
bool autobauding;
|
||||
|
||||
union
|
||||
{
|
||||
|
@ -48,10 +51,38 @@ struct v18_state_s
|
|||
async_tx_state_t async_tx;
|
||||
int baudot_tx_shift;
|
||||
int tx_signal_on;
|
||||
bool tx_draining;
|
||||
uint8_t next_byte;
|
||||
|
||||
fsk_rx_state_t fsk_rx;
|
||||
dtmf_rx_state_t dtmf_rx;
|
||||
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
/*! Minimum acceptable tone level for detection. */
|
||||
int32_t threshold;
|
||||
/*! The accumlating total energy on the same period over which the Goertzels work. */
|
||||
int32_t energy;
|
||||
#else
|
||||
/*! Minimum acceptable tone level for detection. */
|
||||
float threshold;
|
||||
/*! The accumlating total energy on the same period over which the Goertzels work. */
|
||||
float energy;
|
||||
#endif
|
||||
goertzel_state_t tone_390;
|
||||
goertzel_state_t tone_980;
|
||||
goertzel_state_t tone_1180;
|
||||
goertzel_state_t tone_1270;
|
||||
goertzel_state_t tone_1300;
|
||||
goertzel_state_t tone_1400;
|
||||
goertzel_state_t tone_1650;
|
||||
goertzel_state_t tone_1800;
|
||||
/*! The current sample number within a processing block. */
|
||||
int current_sample;
|
||||
/*! Tone state duration */
|
||||
int duration;
|
||||
int target_duration;
|
||||
int in_tone;
|
||||
|
||||
int baudot_rx_shift;
|
||||
int consecutive_ones;
|
||||
uint8_t rx_msg[256 + 1];
|
||||
|
@ -59,6 +90,7 @@ struct v18_state_s
|
|||
int bit_pos;
|
||||
int in_progress;
|
||||
int rx_suppression;
|
||||
int tx_suppression;
|
||||
|
||||
/*! \brief Error and flow logging control */
|
||||
logging_state_t logging;
|
||||
|
|
|
@ -39,15 +39,14 @@
|
|||
|
||||
#if !defined(__cplusplus)
|
||||
|
||||
#define _Bool int
|
||||
#define bool int
|
||||
typedef int _Bool;
|
||||
typedef int bool;
|
||||
#define false 0
|
||||
#define true (!false)
|
||||
|
||||
#else
|
||||
|
||||
#define _Bool bool
|
||||
#define bool bool
|
||||
typedef bool _Bool;
|
||||
#define false false
|
||||
#define true true
|
||||
|
||||
|
|
|
@ -67,60 +67,64 @@ typedef int (*span_rx_fillin_handler_t)(void *s, int len);
|
|||
/*! \brief A handler for transmit, where the buffer will be filled. */
|
||||
typedef int (*span_tx_handler_t)(void *s, int16_t amp[], int max_len);
|
||||
|
||||
#define seconds_to_samples(t) ((t)*SAMPLE_RATE)
|
||||
#define milliseconds_to_samples(t) ((t)*(SAMPLE_RATE/1000))
|
||||
#define microseconds_to_samples(t) ((t)/(1000000/SAMPLE_RATE))
|
||||
|
||||
#define ms_to_samples(t) ((t)*(SAMPLE_RATE/1000))
|
||||
#define us_to_samples(t) ((t)/(1000000/SAMPLE_RATE))
|
||||
|
||||
/* Fixed point constant macros for 16 bit values */
|
||||
#define FP_Q16_0(x) ((int16_t) (1.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q15_1(x) ((int16_t) (2.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q14_2(x) ((int16_t) (4.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q13_3(x) ((int16_t) (8.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q12_4(x) ((int16_t) (16.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q11_5(x) ((int16_t) (32.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q10_6(x) ((int16_t) (64.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q9_7(x) ((int16_t) (128.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q8_8(x) ((int16_t) (256.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q7_9(x) ((int16_t) (512.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q6_10(x) ((int16_t) (1024.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q5_11(x) ((int16_t) (2048.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q4_12(x) ((int16_t) (4096.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q3_13(x) ((int16_t) (8192.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q2_14(x) ((int16_t) (16384.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q1_15(x) ((int16_t) (32768.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q16_0(x) ((int16_t) (1.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q15_1(x) ((int16_t) (2.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q14_2(x) ((int16_t) (4.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q13_3(x) ((int16_t) (8.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q12_4(x) ((int16_t) (16.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q11_5(x) ((int16_t) (32.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q10_6(x) ((int16_t) (64.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q9_7(x) ((int16_t) (128.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q8_8(x) ((int16_t) (256.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q7_9(x) ((int16_t) (512.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q6_10(x) ((int16_t) (1024.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q5_11(x) ((int16_t) (2048.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q4_12(x) ((int16_t) (4096.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q3_13(x) ((int16_t) (8192.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q2_14(x) ((int16_t) (16384.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q1_15(x) ((int16_t) (32768.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
|
||||
/* Fixed point constant macros for 32 bit values */
|
||||
#define FP_Q32_0(x) ((int32_t) (1.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q31_1(x) ((int32_t) (2.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q30_2(x) ((int32_t) (4.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q29_3(x) ((int32_t) (8.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q28_4(x) ((int32_t) (16.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q27_5(x) ((int32_t) (32.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q26_6(x) ((int32_t) (64.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q25_7(x) ((int32_t) (128.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q24_8(x) ((int32_t) (256.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q23_9(x) ((int32_t) (512.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q22_10(x) ((int32_t) (1024.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q21_11(x) ((int32_t) (2048.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q20_12(x) ((int32_t) (4096.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q19_13(x) ((int32_t) (8192.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q18_14(x) ((int32_t) (16384.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q17_15(x) ((int32_t) (32768.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q16_16(x) ((int32_t) (65536.0*1.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q15_17(x) ((int32_t) (65536.0*2.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q14_18(x) ((int32_t) (65536.0*4.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q13_19(x) ((int32_t) (65536.0*8.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q12_20(x) ((int32_t) (65536.0*16.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q11_21(x) ((int32_t) (65536.0*32.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q10_22(x) ((int32_t) (65536.0*64.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q9_23(x) ((int32_t) (65536.0*128.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q8_24(x) ((int32_t) (65536.0*256.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q7_25(x) ((int32_t) (65536.0*512.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q6_26(x) ((int32_t) (65536.0*1024.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q5_27(x) ((int32_t) (65536.0*2048.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q4_28(x) ((int32_t) (65536.0*4096.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q3_29(x) ((int32_t) (65536.0*8192.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q2_30(x) ((int32_t) (65536.0*16384.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q1_31(x) ((int32_t) (65536.0*32768.0*x + ((x >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q32_0(x) ((int32_t) (1.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q31_1(x) ((int32_t) (2.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q30_2(x) ((int32_t) (4.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q29_3(x) ((int32_t) (8.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q28_4(x) ((int32_t) (16.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q27_5(x) ((int32_t) (32.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q26_6(x) ((int32_t) (64.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q25_7(x) ((int32_t) (128.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q24_8(x) ((int32_t) (256.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q23_9(x) ((int32_t) (512.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q22_10(x) ((int32_t) (1024.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q21_11(x) ((int32_t) (2048.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q20_12(x) ((int32_t) (4096.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q19_13(x) ((int32_t) (8192.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q18_14(x) ((int32_t) (16384.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q17_15(x) ((int32_t) (32768.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q16_16(x) ((int32_t) (65536.0*1.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q15_17(x) ((int32_t) (65536.0*2.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q14_18(x) ((int32_t) (65536.0*4.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q13_19(x) ((int32_t) (65536.0*8.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q12_20(x) ((int32_t) (65536.0*16.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q11_21(x) ((int32_t) (65536.0*32.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q10_22(x) ((int32_t) (65536.0*64.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q9_23(x) ((int32_t) (65536.0*128.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q8_24(x) ((int32_t) (65536.0*256.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q7_25(x) ((int32_t) (65536.0*512.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q6_26(x) ((int32_t) (65536.0*1024.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q5_27(x) ((int32_t) (65536.0*2048.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q4_28(x) ((int32_t) (65536.0*4096.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q3_29(x) ((int32_t) (65536.0*8192.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q2_30(x) ((int32_t) (65536.0*16384.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
#define FP_Q1_31(x) ((int32_t) (65536.0*32768.0*(x) + (((x) >= 0.0) ? 0.5 : -0.5)))
|
||||
|
||||
#if defined(__cplusplus)
|
||||
/* C++ doesn't seem to have sane rounding functions/macros yet */
|
||||
|
|
|
@ -66,6 +66,8 @@ enum
|
|||
{
|
||||
V18_AUTOMODING_GLOBAL = 0,
|
||||
|
||||
V18_AUTOMODING_NONE,
|
||||
|
||||
/* 5-bit, V.21, V.23, EDT, DTMF, Bell 103 */
|
||||
V18_AUTOMODING_AUSTRALIA,
|
||||
V18_AUTOMODING_IRELAND,
|
||||
|
@ -173,6 +175,11 @@ SPAN_DECLARE(int) v18_rx_fillin(v18_state_t *s, int len);
|
|||
invalid, this function will return -1. */
|
||||
SPAN_DECLARE(int) v18_put(v18_state_t *s, const char msg[], int len);
|
||||
|
||||
/*! \brief Get the current mode of a V.18 connection.
|
||||
\param s The V.18 context.
|
||||
\return The mode. */
|
||||
SPAN_DECLARE(int) v18_get_current_mode(v18_state_t *s);
|
||||
|
||||
/*! \brief Return a short name for an V.18 mode
|
||||
\param mode The code for the V.18 mode.
|
||||
\return A pointer to the name.
|
||||
|
|
|
@ -959,6 +959,7 @@ SPAN_DECLARE(void) t30_decode_dis_dtc_dcs(t30_state_t *s, const uint8_t *pkt, in
|
|||
octet_bit_field(log, pkt, 96, "Extension indicator", NULL, NULL);
|
||||
if (!(pkt[14] & DISBIT8))
|
||||
return;
|
||||
/*endif*/
|
||||
if (len <= 15)
|
||||
{
|
||||
span_log(log, SPAN_LOG_FLOW, " Frame is short\n");
|
||||
|
|
|
@ -202,6 +202,7 @@ static void report_status_change(v17_rx_state_t *s, int status)
|
|||
s->status_handler(s->status_user_data, status);
|
||||
else if (s->put_bit)
|
||||
s->put_bit(s->put_bit_user_data, status);
|
||||
/*endif*/
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -360,6 +361,7 @@ static int descramble(v17_rx_state_t *s, int in_bit)
|
|||
s->scramble_reg |= out_bit;
|
||||
else
|
||||
s->scramble_reg |= (in_bit & 1);
|
||||
/*endif*/
|
||||
return out_bit;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -382,6 +384,7 @@ static __inline__ void put_bit(v17_rx_state_t *s, int bit)
|
|||
testing for ones, but just rely on a constellation mismatch measurement. */
|
||||
//span_log(&s->logging, SPAN_LOG_FLOW, "A 1 is really %d\n", out_bit);
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -437,6 +440,8 @@ static int decode_baud(v17_rx_state_t *s, complexf_t *z)
|
|||
int re;
|
||||
int im;
|
||||
int raw;
|
||||
int min_index;
|
||||
int set;
|
||||
int constellation_state;
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
#define DIST_FACTOR 1024 /* Something less than sqrt(0xFFFFFFFF/10)/10 */
|
||||
|
@ -462,20 +467,23 @@ static int decode_baud(v17_rx_state_t *s, complexf_t *z)
|
|||
re = 35;
|
||||
else if (re < 0)
|
||||
re = 0;
|
||||
/*endif*/
|
||||
if (im > 35)
|
||||
im = 35;
|
||||
else if (im < 0)
|
||||
im = 0;
|
||||
/*endif*/
|
||||
if (s->bits_per_symbol == 2)
|
||||
{
|
||||
/* 4800bps V.32bis mode, without trellis coding */
|
||||
nearest = constel_map_4800[re][im];
|
||||
raw = v32bis_4800_differential_decoder[s->diff][nearest];
|
||||
s->diff = nearest;
|
||||
constellation_state = constel_map_4800[re][im];
|
||||
raw = v32bis_4800_differential_decoder[s->diff][constellation_state];
|
||||
s->diff = constellation_state;
|
||||
put_bit(s, raw);
|
||||
put_bit(s, raw >> 1);
|
||||
return nearest;
|
||||
return constellation_state;
|
||||
}
|
||||
/*endif*/
|
||||
|
||||
/* Find a set of 8 candidate constellation positions, that are the closest
|
||||
to the target, with different patterns in the last 3 bits. */
|
||||
|
@ -485,7 +493,7 @@ static int decode_baud(v17_rx_state_t *s, complexf_t *z)
|
|||
#else
|
||||
min = 9999999.0f;
|
||||
#endif
|
||||
j = 0;
|
||||
min_index = 0;
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
nearest = constel_maps[s->space_map][re][im][i];
|
||||
|
@ -499,13 +507,16 @@ static int decode_baud(v17_rx_state_t *s, complexf_t *z)
|
|||
if (min > distances[i])
|
||||
{
|
||||
min = distances[i];
|
||||
j = i;
|
||||
min_index = i;
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/* Use the nearest of these soft-decisions as the basis for DFE */
|
||||
constellation_state = constel_maps[s->space_map][re][im][j];
|
||||
/* Control the equalizer, carrier tracking, etc. based on the non-trellis
|
||||
corrected information. The trellis correct stuff comes out a bit late. */
|
||||
/*endfor*/
|
||||
/* Use the nearest of these soft-decisions as the basis for DFE and carrier
|
||||
tracking. This is a compromise. It means we will use the correct error
|
||||
less often, but using the output of the traceback would put more lag
|
||||
into the feedback path. */
|
||||
constellation_state = constel_maps[s->space_map][re][im][min_index];
|
||||
track_carrier(s, z, &s->constellation[constellation_state]);
|
||||
//tune_equalizer(s, z, &s->constellation[constellation_state]);
|
||||
|
||||
|
@ -517,70 +528,62 @@ static int decode_baud(v17_rx_state_t *s, complexf_t *z)
|
|||
/* Update the minimum accumulated distance to each of the 8 states */
|
||||
if (++s->trellis_ptr >= V17_TRELLIS_STORAGE_DEPTH)
|
||||
s->trellis_ptr = 0;
|
||||
for (i = 0; i < 4; i++)
|
||||
/*endif*/
|
||||
for (i = 0; i < 8; i++)
|
||||
{
|
||||
min = distances[tcm_paths[i][0]] + s->distances[0];
|
||||
k = 0;
|
||||
set = i >> 2;
|
||||
min = distances[tcm_paths[i][0]] + s->distances[set];
|
||||
min_index = 0;
|
||||
for (j = 1; j < 4; j++)
|
||||
{
|
||||
if (min > distances[tcm_paths[i][j]] + s->distances[j << 1])
|
||||
k = (j << 1) + set;
|
||||
if (min > distances[tcm_paths[i][j]] + s->distances[k])
|
||||
{
|
||||
min = distances[tcm_paths[i][j]] + s->distances[j << 1];
|
||||
k = j;
|
||||
min = distances[tcm_paths[i][j]] + s->distances[k];
|
||||
min_index = j;
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*endfor*/
|
||||
k = (min_index << 1) + set;
|
||||
/* Use an elementary IIR filter to track the distance to date. */
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
new_distances[i] = s->distances[k << 1]*9/10 + distances[tcm_paths[i][k]]*1/10;
|
||||
new_distances[i] = s->distances[k]*9/10 + distances[tcm_paths[i][min_index]]*1/10;
|
||||
#else
|
||||
new_distances[i] = s->distances[k << 1]*0.9f + distances[tcm_paths[i][k]]*0.1f;
|
||||
new_distances[i] = s->distances[k]*0.9f + distances[tcm_paths[i][min_index]]*0.1f;
|
||||
#endif
|
||||
s->full_path_to_past_state_locations[s->trellis_ptr][i] = constel_maps[s->space_map][re][im][tcm_paths[i][k]];
|
||||
s->past_state_locations[s->trellis_ptr][i] = k << 1;
|
||||
}
|
||||
for (i = 4; i < 8; i++)
|
||||
{
|
||||
min = distances[tcm_paths[i][0]] + s->distances[1];
|
||||
k = 0;
|
||||
for (j = 1; j < 4; j++)
|
||||
{
|
||||
if (min > distances[tcm_paths[i][j]] + s->distances[(j << 1) + 1])
|
||||
{
|
||||
min = distances[tcm_paths[i][j]] + s->distances[(j << 1) + 1];
|
||||
k = j;
|
||||
}
|
||||
}
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
new_distances[i] = s->distances[(k << 1) + 1]*9/10 + distances[tcm_paths[i][k]]*1/10;
|
||||
#else
|
||||
new_distances[i] = s->distances[(k << 1) + 1]*0.9f + distances[tcm_paths[i][k]]*0.1f;
|
||||
#endif
|
||||
s->full_path_to_past_state_locations[s->trellis_ptr][i] = constel_maps[s->space_map][re][im][tcm_paths[i][k]];
|
||||
s->past_state_locations[s->trellis_ptr][i] = (k << 1) + 1;
|
||||
s->full_path_to_past_state_locations[s->trellis_ptr][i] = constel_maps[s->space_map][re][im][tcm_paths[i][min_index]];
|
||||
s->past_state_locations[s->trellis_ptr][i] = k;
|
||||
}
|
||||
/*endfor*/
|
||||
memcpy(s->distances, new_distances, sizeof(s->distances));
|
||||
|
||||
/* Find the minimum distance to date. This is the start of the path back to the result. */
|
||||
min = s->distances[0];
|
||||
k = 0;
|
||||
min_index = 0;
|
||||
for (i = 1; i < 8; i++)
|
||||
{
|
||||
if (min > s->distances[i])
|
||||
{
|
||||
min = s->distances[i];
|
||||
k = i;
|
||||
min_index = i;
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*endfor*/
|
||||
/* Trace back through every time step, starting with the current one, and find the
|
||||
state from which the path came one step before. At the end of this search, the
|
||||
last state found also points to the constellation point at that state. This is the
|
||||
output of the trellis. */
|
||||
k = min_index;
|
||||
for (i = 0, j = s->trellis_ptr; i < V17_TRELLIS_LOOKBACK_DEPTH - 1; i++)
|
||||
{
|
||||
k = s->past_state_locations[j][k];
|
||||
if (--j < 0)
|
||||
j = V17_TRELLIS_STORAGE_DEPTH - 1;
|
||||
/*endif*/
|
||||
}
|
||||
/*endfor*/
|
||||
nearest = s->full_path_to_past_state_locations[j][k] >> 1;
|
||||
|
||||
/* Differentially decode */
|
||||
|
@ -591,6 +594,7 @@ static int decode_baud(v17_rx_state_t *s, complexf_t *z)
|
|||
put_bit(s, raw);
|
||||
raw >>= 1;
|
||||
}
|
||||
/*endfor*/
|
||||
return constellation_state;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -645,10 +649,12 @@ static __inline__ void symbol_sync(v17_rx_state_t *s)
|
|||
i = (v > FP_SYNC_SCALE_32(1000.0f)) ? 15 : 1;
|
||||
if (s->baud_phase < FP_SYNC_SCALE_32(0.0f))
|
||||
i = -i;
|
||||
/*endif*/
|
||||
//printf("v = %10.5f %5d - %f %f %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 --------------------------------------------------------*/
|
||||
|
||||
|
@ -696,10 +702,12 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
s->eq_buf[s->eq_step] = *sample;
|
||||
if (++s->eq_step >= V17_EQUALIZER_LEN)
|
||||
s->eq_step = 0;
|
||||
/*endif*/
|
||||
|
||||
/* On alternate insertions we have a whole baud and must process it. */
|
||||
if ((s->baud_half ^= 1))
|
||||
return;
|
||||
/*endif*/
|
||||
|
||||
/* Symbol timing synchronisation */
|
||||
symbol_sync(s);
|
||||
|
@ -725,7 +733,9 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
s->last_angles[0] = arctan2(z.im, z.re);
|
||||
if (s->agc_scaling_save == FP_SCALE(0.0f))
|
||||
s->agc_scaling_save = s->agc_scaling;
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
break;
|
||||
case TRAINING_STAGE_LOG_PHASE:
|
||||
/* Record the current alternate phase angle */
|
||||
|
@ -749,6 +759,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
s->last_angles[0] = DDS_PHASE(180.0f + 18.433f);
|
||||
s->last_angles[1] = DDS_PHASE(270.0f + 18.433f);
|
||||
}
|
||||
/*endif*/
|
||||
/* 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. */
|
||||
/* angle is now the difference between where A is, and where it should be */
|
||||
|
@ -759,6 +770,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
z16 = complex_seti16(fixed_cos(ip), -fixed_sin(ip));
|
||||
for (i = 0; i < V17_EQUALIZER_LEN; i++)
|
||||
s->eq_buf[i] = complex_mul_q1_15(&s->eq_buf[i], &z16);
|
||||
/*endfor*/
|
||||
s->carrier_track_p = 500000;
|
||||
#else
|
||||
p = dds_phase_to_radians(phase_step);
|
||||
|
@ -766,6 +778,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
zz = complex_setf(cosf(p), -sinf(p));
|
||||
for (i = 0; i < V17_EQUALIZER_LEN; i++)
|
||||
s->eq_buf[i] = complex_mulf(&s->eq_buf[i], &zz);
|
||||
/*endfor*/
|
||||
s->carrier_track_p = 500000.0f;
|
||||
#endif
|
||||
s->carrier_phase += phase_step;
|
||||
|
@ -776,6 +789,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
s->last_angles[1] = angle;
|
||||
s->training_stage = TRAINING_STAGE_WAIT_FOR_CDBA;
|
||||
}
|
||||
/*endif*/
|
||||
break;
|
||||
case TRAINING_STAGE_WAIT_FOR_CDBA:
|
||||
target = &zero;
|
||||
|
@ -803,6 +817,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
s->carrier_phase_rate += 3*16*(ang/20);
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Angles %x, %x, dist %d\n", s->last_angles[0], s->last_angles[1], i);
|
||||
}
|
||||
/*endif*/
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Coarse carrier frequency %7.2f (%d)\n", dds_frequencyf(s->carrier_phase_rate), s->training_count);
|
||||
/* Check if the carrier frequency is plausible */
|
||||
if (s->carrier_phase_rate < DDS_PHASE_RATE(CARRIER_NOMINAL_FREQ - 20.0f)
|
||||
|
@ -816,6 +831,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
||||
break;
|
||||
}
|
||||
/*endif*/
|
||||
|
||||
/* 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. */
|
||||
|
@ -827,12 +843,14 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
z16 = complex_seti16(fixed_cos(ip), -fixed_sin(ip));
|
||||
for (i = 0; i < V17_EQUALIZER_LEN; i++)
|
||||
s->eq_buf[i] = complex_mul_q1_15(&s->eq_buf[i], &z16);
|
||||
/*endfor*/
|
||||
#else
|
||||
p = dds_phase_to_radians(phase_step);
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Spin (long) by %.5f rads\n", p);
|
||||
zz = complex_setf(cosf(p), -sinf(p));
|
||||
for (i = 0; i < V17_EQUALIZER_LEN; i++)
|
||||
s->eq_buf[i] = complex_mulf(&s->eq_buf[i], &zz);
|
||||
/*endfor*/
|
||||
#endif
|
||||
s->carrier_phase += phase_step;
|
||||
|
||||
|
@ -845,6 +863,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
report_status_change(s, SIG_STATUS_TRAINING_IN_PROGRESS);
|
||||
break;
|
||||
}
|
||||
/*endif*/
|
||||
if (++s->training_count > V17_TRAINING_SEG_1_LEN)
|
||||
{
|
||||
/* This is bogus. There are not this many bits in this section
|
||||
|
@ -855,6 +874,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
s->training_stage = TRAINING_STAGE_PARKED;
|
||||
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
||||
}
|
||||
/*endif*/
|
||||
break;
|
||||
case TRAINING_STAGE_COARSE_TRAIN_ON_CDBA:
|
||||
/* Train on the scrambled CDBA section. */
|
||||
|
@ -886,6 +906,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
#endif
|
||||
s->training_stage = TRAINING_STAGE_FINE_TRAIN_ON_CDBA;
|
||||
}
|
||||
/*endif*/
|
||||
break;
|
||||
case TRAINING_STAGE_FINE_TRAIN_ON_CDBA:
|
||||
/* Train on the scrambled CDBA section. */
|
||||
|
@ -907,6 +928,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
#endif
|
||||
s->training_stage = TRAINING_STAGE_TRAIN_ON_CDBA_AND_TEST;
|
||||
}
|
||||
/*endif*/
|
||||
break;
|
||||
case TRAINING_STAGE_TRAIN_ON_CDBA_AND_TEST:
|
||||
/* Continue training on the scrambled CDBA section, but measure the quality of training too. */
|
||||
|
@ -950,7 +972,9 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
s->training_stage = TRAINING_STAGE_PARKED;
|
||||
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
break;
|
||||
case TRAINING_STAGE_BRIDGE:
|
||||
descramble(s, V17_BRIDGE_WORD >> ((s->training_count & 0x7) << 1));
|
||||
|
@ -972,7 +996,9 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
/* Wait for the trellis to wind up */
|
||||
s->training_stage = TRAINING_STAGE_TCM_WINDUP;
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
break;
|
||||
case TRAINING_STAGE_SHORT_WAIT_FOR_CDBA:
|
||||
/* Look for the initial ABAB sequence to display a phase reversal, which will
|
||||
|
@ -989,19 +1015,23 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
s->training_error = FP_SCALE(0.0f);
|
||||
s->training_count = 1;
|
||||
s->training_stage = TRAINING_STAGE_SHORT_TRAIN_ON_CDBA_AND_TEST;
|
||||
break;
|
||||
}
|
||||
target = &cdba[(s->training_count & 1) + 2];
|
||||
track_carrier(s, &z, target);
|
||||
if (++s->training_count > V17_TRAINING_SEG_1_LEN)
|
||||
else
|
||||
{
|
||||
/* This is bogus. There are not this many bits in this section
|
||||
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 */
|
||||
s->training_stage = TRAINING_STAGE_PARKED;
|
||||
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
||||
target = &cdba[(s->training_count & 1) + 2];
|
||||
track_carrier(s, &z, target);
|
||||
if (++s->training_count > V17_TRAINING_SEG_1_LEN)
|
||||
{
|
||||
/* This is bogus. There are not this many bits in this section
|
||||
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 */
|
||||
s->training_stage = TRAINING_STAGE_PARKED;
|
||||
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
break;
|
||||
case TRAINING_STAGE_SHORT_TRAIN_ON_CDBA_AND_TEST:
|
||||
/* Short retrain on the scrambled CDBA section, but measure the quality of training too. */
|
||||
|
@ -1022,6 +1052,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
s->training_error += powerf(&zz);
|
||||
#endif
|
||||
}
|
||||
/*endif*/
|
||||
if (++s->training_count >= V17_TRAINING_SHORT_SEG_2_LEN)
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
|
@ -1052,6 +1083,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
/* Wait for the trellis to wind up */
|
||||
s->training_stage = TRAINING_STAGE_TCM_WINDUP;
|
||||
}
|
||||
/*endif*/
|
||||
report_status_change(s, SIG_STATUS_TRAINING_IN_PROGRESS);
|
||||
}
|
||||
else
|
||||
|
@ -1061,7 +1093,9 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
s->training_stage = TRAINING_STAGE_PARKED;
|
||||
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
break;
|
||||
case TRAINING_STAGE_TCM_WINDUP:
|
||||
/* We need to wait 15 bauds while the trellis fills up. */
|
||||
|
@ -1084,6 +1118,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
s->diff = (s->short_train) ? 0 : 1;
|
||||
s->training_stage = TRAINING_STAGE_TEST_ONES;
|
||||
}
|
||||
/*endif*/
|
||||
break;
|
||||
case TRAINING_STAGE_TEST_ONES:
|
||||
/* We are in the test phase, where we check that we can receive reliably.
|
||||
|
@ -1128,10 +1163,13 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
#endif
|
||||
if (!s->short_train)
|
||||
s->agc_scaling_save = FP_SCALE(0.0f);
|
||||
/*endif*/
|
||||
s->training_stage = TRAINING_STAGE_PARKED;
|
||||
report_status_change(s, SIG_STATUS_TRAINING_FAILED);
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
break;
|
||||
case TRAINING_STAGE_PARKED:
|
||||
default:
|
||||
|
@ -1140,6 +1178,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
target = &zero;
|
||||
break;
|
||||
}
|
||||
/*endswitch*/
|
||||
if (s->qam_report)
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
|
@ -1155,6 +1194,7 @@ static void process_half_baud(v17_rx_state_t *s, const complexf_t *sample)
|
|||
s->qam_report(s->qam_user_data, &z, target, constellation_state);
|
||||
#endif
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -1183,13 +1223,16 @@ static __inline__ int signal_detect(v17_rx_state_t *s, int16_t amp)
|
|||
s->high_sample = 0;
|
||||
s->low_samples = 0;
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
else
|
||||
{
|
||||
s->low_samples = 0;
|
||||
if (diff > s->high_sample)
|
||||
s->high_sample = diff;
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
#endif
|
||||
if (s->signal_present > 0)
|
||||
{
|
||||
|
@ -1208,23 +1251,27 @@ static __inline__ int signal_detect(v17_rx_state_t *s, int16_t amp)
|
|||
report_status_change(s, SIG_STATUS_CARRIER_DOWN);
|
||||
return 0;
|
||||
}
|
||||
/*endif*/
|
||||
#if defined(IAXMODEM_STUFF)
|
||||
/* Carrier has dropped, but the put_bit is pending the signal_present delay. */
|
||||
s->carrier_drop_pending = true;
|
||||
#endif
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Look for power exceeding turn-on threshold to turn the carrier on */
|
||||
if (power < s->carrier_on_power)
|
||||
return 0;
|
||||
/*endif*/
|
||||
s->signal_present = 1;
|
||||
#if defined(IAXMODEM_STUFF)
|
||||
s->carrier_drop_pending = false;
|
||||
#endif
|
||||
report_status_change(s, SIG_STATUS_CARRIER_UP);
|
||||
}
|
||||
/*endif*/
|
||||
return power;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -1252,21 +1299,26 @@ SPAN_DECLARE(int) v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
|
|||
s->rrc_filter[s->rrc_filter_step] = amp[i];
|
||||
if (++s->rrc_filter_step >= V17_RX_FILTER_STEPS)
|
||||
s->rrc_filter_step = 0;
|
||||
/*endif*/
|
||||
|
||||
if ((power = signal_detect(s, amp[i])) == 0)
|
||||
continue;
|
||||
/*endif*/
|
||||
if (s->training_stage == TRAINING_STAGE_PARKED)
|
||||
continue;
|
||||
/*endif*/
|
||||
/* Only spend effort processing this data if the modem is not
|
||||
parked, after training failure. */
|
||||
s->eq_put_step -= RX_PULSESHAPER_COEFF_SETS;
|
||||
step = -s->eq_put_step;
|
||||
if (step < 0)
|
||||
step += RX_PULSESHAPER_COEFF_SETS;
|
||||
/*endif*/
|
||||
if (step < 0)
|
||||
step = 0;
|
||||
else if (step > RX_PULSESHAPER_COEFF_SETS - 1)
|
||||
step = RX_PULSESHAPER_COEFF_SETS - 1;
|
||||
/*endif*/
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
v = vec_circular_dot_prodi16(s->rrc_filter, rx_pulseshaper_re[step], V17_RX_FILTER_STEPS, s->rrc_filter_step) >> 15;
|
||||
sample.re = (v*s->agc_scaling) >> 10;
|
||||
|
@ -1305,12 +1357,14 @@ SPAN_DECLARE(int) v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
|
|||
{
|
||||
if ((root_power = fixed_sqrt32(power)) == 0)
|
||||
root_power = 1;
|
||||
/*endif*/
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
s->agc_scaling = saturate16(((int32_t) (FP_SCALE(2.17f)*1024.0f))/root_power);
|
||||
#else
|
||||
s->agc_scaling = (FP_SCALE(2.17f)/RX_PULSESHAPER_GAIN)/root_power;
|
||||
#endif
|
||||
}
|
||||
/*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.
|
||||
|
@ -1331,12 +1385,14 @@ SPAN_DECLARE(int) v17_rx(v17_rx_state_t *s, const int16_t amp[], int len)
|
|||
s->eq_put_step += RX_PULSESHAPER_COEFF_SETS*10/(3*2);
|
||||
process_half_baud(s, &zz);
|
||||
}
|
||||
/*endif*/
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
dds_advance(&s->carrier_phase, s->carrier_phase_rate);
|
||||
#else
|
||||
dds_advancef(&s->carrier_phase, s->carrier_phase_rate);
|
||||
#endif
|
||||
}
|
||||
/*endfor*/
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -1350,8 +1406,10 @@ SPAN_DECLARE(int) v17_rx_fillin(v17_rx_state_t *s, int len)
|
|||
span_log(&s->logging, SPAN_LOG_FLOW, "Fill-in %d samples\n", len);
|
||||
if (s->signal_present <= 0)
|
||||
return 0;
|
||||
/*endif*/
|
||||
if (s->training_stage == TRAINING_STAGE_PARKED)
|
||||
return 0;
|
||||
/*endif*/
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
#if defined(SPANDSP_USE_FIXED_POINT)
|
||||
|
@ -1363,8 +1421,10 @@ SPAN_DECLARE(int) v17_rx_fillin(v17_rx_state_t *s, int len)
|
|||
s->eq_put_step -= RX_PULSESHAPER_COEFF_SETS;
|
||||
if (s->eq_put_step <= 0)
|
||||
s->eq_put_step += RX_PULSESHAPER_COEFF_SETS*10/(3*2);
|
||||
/*endif*/
|
||||
/* TODO: Should we rotate any buffers */
|
||||
}
|
||||
/*endfor*/
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -1426,6 +1486,7 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
|
|||
default:
|
||||
return -1;
|
||||
}
|
||||
/*endswitch*/
|
||||
s->bit_rate = bit_rate;
|
||||
#if defined(SPANDSP_USE_FIXED_POINTx)
|
||||
vec_zeroi16(s->rrc_filter, sizeof(s->rrc_filter)/sizeof(s->rrc_filter[0]));
|
||||
|
@ -1447,6 +1508,7 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
|
|||
#endif
|
||||
if (short_train != 2)
|
||||
s->short_train = short_train;
|
||||
/*endif*/
|
||||
vec_zeroi32(s->last_angles, 2);
|
||||
vec_zeroi32(s->diff_angles, 16);
|
||||
|
||||
|
@ -1456,6 +1518,7 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
|
|||
initial paths to merge at the zero states. */
|
||||
for (i = 0; i < 8; i++)
|
||||
s->distances[i] = FP_CONSTELLATION_SCALE(99.0f)*FP_CONSTELLATION_SCALE(1.0f);
|
||||
/*endfor*/
|
||||
memset(s->full_path_to_past_state_locations, 0, sizeof(s->full_path_to_past_state_locations));
|
||||
memset(s->past_state_locations, 0, sizeof(s->past_state_locations));
|
||||
s->distances[0] = 0;
|
||||
|
@ -1493,6 +1556,7 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
|
|||
s->carrier_track_p = 40000.0f;
|
||||
#endif
|
||||
}
|
||||
/*endif*/
|
||||
s->last_sample = 0;
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Gains %f %f\n", (float) s->agc_scaling_save, (float) s->agc_scaling);
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "Phase rates %f %f\n", dds_frequencyf(s->carrier_phase_rate), dds_frequencyf(s->carrier_phase_rate_save));
|
||||
|
@ -1504,6 +1568,7 @@ SPAN_DECLARE(int) v17_rx_restart(v17_rx_state_t *s, int bit_rate, int short_trai
|
|||
s->symbol_sync_high[i] = FP_SCALE(0.0f);
|
||||
s->symbol_sync_dc_filter[i] = FP_SCALE(0.0f);
|
||||
}
|
||||
/*endfor*/
|
||||
s->baud_phase = FP_SCALE(0.0f);
|
||||
s->baud_half = 0;
|
||||
|
||||
|
@ -1527,11 +1592,14 @@ SPAN_DECLARE(v17_rx_state_t *) v17_rx_init(v17_rx_state_t *s, int bit_rate, put_
|
|||
default:
|
||||
return NULL;
|
||||
}
|
||||
/*endswitch*/
|
||||
if (s == NULL)
|
||||
{
|
||||
if ((s = (v17_rx_state_t *) span_alloc(sizeof(*s))) == NULL)
|
||||
return NULL;
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
memset(s, 0, sizeof(*s));
|
||||
span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
|
||||
span_log_set_protocol(&s->logging, "V.17 RX");
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* Written by Steve Underwood <steveu@coppice.org>
|
||||
*
|
||||
* Copyright (C) 2004-2009 Steve Underwood
|
||||
* Copyright (C) 2004-2015 Steve Underwood
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
|
|
|
@ -71,8 +71,10 @@
|
|||
|
||||
enum
|
||||
{
|
||||
V8_WAIT_1S = 0, /* Start point when sending CI */
|
||||
V8_AWAIT_ANSAM, /* Start point when sending initial silence */
|
||||
/* Start point when sending CI */
|
||||
V8_WAIT_1S = 0,
|
||||
/* Start point when sending initial silence */
|
||||
V8_AWAIT_ANSAM,
|
||||
V8_CI_ON,
|
||||
V8_CI_OFF,
|
||||
V8_HEARD_ANSAM,
|
||||
|
@ -113,6 +115,8 @@ enum
|
|||
V8_V92_SYNC_OCTET = 0x55
|
||||
};
|
||||
|
||||
#define Te_TIMEOUT 500
|
||||
|
||||
SPAN_DECLARE(const char *) v8_call_function_to_str(int call_function)
|
||||
{
|
||||
switch (call_function)
|
||||
|
@ -134,6 +138,7 @@ SPAN_DECLARE(const char *) v8_call_function_to_str(int call_function)
|
|||
case V8_CALL_FUNCTION_EXTENSION:
|
||||
return "Call function is in extension octet";
|
||||
}
|
||||
/*endswitch*/
|
||||
return "Unknown call function";
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -171,6 +176,7 @@ SPAN_DECLARE(const char *) v8_modulation_to_str(int modulation_scheme)
|
|||
case V8_MOD_V92:
|
||||
return "V.92 duplex";
|
||||
}
|
||||
/*endswitch*/
|
||||
return "???";
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -186,6 +192,7 @@ SPAN_DECLARE(const char *) v8_protocol_to_str(int protocol)
|
|||
case V8_PROTOCOL_EXTENSION:
|
||||
return "Extension";
|
||||
}
|
||||
/*endswitch*/
|
||||
return "Undefined";
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -209,6 +216,7 @@ SPAN_DECLARE(const char *) v8_pstn_access_to_str(int pstn_access)
|
|||
case (V8_PSTN_ACCESS_DCE_ON_DIGITAL | V8_PSTN_ACCESS_ANSWER_DCE_CELLULAR | V8_PSTN_ACCESS_CALL_DCE_CELLULAR):
|
||||
return "DCE on digital, and answering and calling modems on cellular";
|
||||
}
|
||||
/*endswitch*/
|
||||
return "PSTN access unknown";
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -220,6 +228,7 @@ SPAN_DECLARE(const char *) v8_nsf_to_str(int nsf)
|
|||
case 0:
|
||||
return "???";
|
||||
}
|
||||
/*endswitch*/
|
||||
return "???";
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -245,6 +254,7 @@ SPAN_DECLARE(const char *) v8_pcm_modem_availability_to_str(int pcm_modem_availa
|
|||
case (V8_PSTN_PCM_MODEM_V91 | V8_PSTN_PCM_MODEM_V90_V92_DIGITAL | V8_PSTN_PCM_MODEM_V90_V92_ANALOGUE):
|
||||
return "V.91 and V.90/V.92 digital/analogue available";
|
||||
}
|
||||
/*endswitch*/
|
||||
return "PCM availability unknown";
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -271,6 +281,7 @@ SPAN_DECLARE(const char *) v8_t66_to_str(int t66)
|
|||
case 7:
|
||||
return "Reserved TIA + others";
|
||||
}
|
||||
/*endswitch*/
|
||||
return "???";
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -289,7 +300,9 @@ SPAN_DECLARE(void) v8_log_supported_modulations(v8_state_t *s, int modulation_sc
|
|||
span_log(&s->logging, SPAN_LOG_FLOW | SPAN_LOG_SUPPRESS_LABELLING, "%s%s", comma, v8_modulation_to_str(modulation_schemes & (1 << i)));
|
||||
comma = ", ";
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*endfor*/
|
||||
span_log(&s->logging, SPAN_LOG_FLOW | SPAN_LOG_SUPPRESS_LABELLING, " supported\n");
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -298,6 +311,7 @@ static int report_event(v8_state_t *s)
|
|||
{
|
||||
if (s->result_handler)
|
||||
s->result_handler(s->result_handler_user_data, &s->result);
|
||||
/*endif*/
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -321,10 +335,13 @@ static const uint8_t *process_modulation_mode(v8_state_t *s, const uint8_t *p)
|
|||
s->modulation_bytes = 1;
|
||||
if (*p & 0x80)
|
||||
modulations |= V8_MOD_V34HDX;
|
||||
/*endif*/
|
||||
if (*p & 0x40)
|
||||
modulations |= V8_MOD_V34;
|
||||
/*endif*/
|
||||
if (*p & 0x20)
|
||||
modulations |= V8_MOD_V90;
|
||||
/*endif*/
|
||||
++p;
|
||||
|
||||
/* Check for an extension octet */
|
||||
|
@ -333,14 +350,19 @@ static const uint8_t *process_modulation_mode(v8_state_t *s, const uint8_t *p)
|
|||
s->modulation_bytes++;
|
||||
if (*p & 0x80)
|
||||
modulations |= V8_MOD_V27TER;
|
||||
/*endif*/
|
||||
if (*p & 0x40)
|
||||
modulations |= V8_MOD_V29;
|
||||
/*endif*/
|
||||
if (*p & 0x04)
|
||||
modulations |= V8_MOD_V17;
|
||||
/*endif*/
|
||||
if (*p & 0x02)
|
||||
modulations |= V8_MOD_V22;
|
||||
/*endif*/
|
||||
if (*p & 0x01)
|
||||
modulations |= V8_MOD_V32;
|
||||
/*endif*/
|
||||
++p;
|
||||
|
||||
/* Check for an extension octet */
|
||||
|
@ -349,17 +371,24 @@ static const uint8_t *process_modulation_mode(v8_state_t *s, const uint8_t *p)
|
|||
s->modulation_bytes++;
|
||||
if (*p & 0x80)
|
||||
modulations |= V8_MOD_V21;
|
||||
/*endif*/
|
||||
if (*p & 0x40)
|
||||
modulations |= V8_MOD_V23HDX;
|
||||
/*endif*/
|
||||
if (*p & 0x04)
|
||||
modulations |= V8_MOD_V23;
|
||||
/*endif*/
|
||||
if (*p & 0x02)
|
||||
modulations |= V8_MOD_V26BIS;
|
||||
/*endif*/
|
||||
if (*p & 0x01)
|
||||
modulations |= V8_MOD_V26TER;
|
||||
++p;
|
||||
/*endif*/
|
||||
++p;
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
s->result.modulations = modulations;
|
||||
v8_log_supported_modulations(s, modulations);
|
||||
return p;
|
||||
|
@ -411,6 +440,7 @@ static void ci_decode(v8_state_t *s)
|
|||
{
|
||||
if ((s->rx_data[0] & 0x1F) == V8_CALL_FUNCTION_TAG)
|
||||
process_call_function(s, &s->rx_data[0]);
|
||||
/*endif*/
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -420,6 +450,7 @@ static void cm_jm_decode(v8_state_t *s)
|
|||
|
||||
if (s->got_cm_jm)
|
||||
return;
|
||||
/*endif*/
|
||||
|
||||
/* We must receive two consecutive identical CM or JM sequences to accept it. */
|
||||
if (s->cm_jm_len <= 0
|
||||
|
@ -433,6 +464,7 @@ static void cm_jm_decode(v8_state_t *s)
|
|||
memcpy(s->cm_jm_data, s->rx_data, s->rx_data_ptr);
|
||||
return;
|
||||
}
|
||||
/*endif*/
|
||||
/* We have a matching pair of CMs or JMs, so we are happy this is correct. */
|
||||
s->got_cm_jm = true;
|
||||
|
||||
|
@ -473,10 +505,13 @@ static void cm_jm_decode(v8_state_t *s)
|
|||
p++;
|
||||
break;
|
||||
}
|
||||
/*endswitch*/
|
||||
/* Skip any future extensions we do not understand */
|
||||
while ((*p & 0x38) == 0x10)
|
||||
p++;
|
||||
/*endwhile*/
|
||||
}
|
||||
/*endwhile*/
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -501,8 +536,10 @@ static void put_bit(void *user_data, int bit)
|
|||
default:
|
||||
break;
|
||||
}
|
||||
/*endswitch*/
|
||||
return;
|
||||
}
|
||||
/*endif*/
|
||||
//span_log(&s->logging, SPAN_LOG_FLOW, "Bit %d\n", bit);
|
||||
/* Wait until we sync. */
|
||||
s->bit_stream = (s->bit_stream >> 1) | (bit << 19);
|
||||
|
@ -529,6 +566,7 @@ static void put_bit(void *user_data, int bit)
|
|||
new_preamble_type = V8_SYNC_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
/*endswitch*/
|
||||
if (new_preamble_type != V8_SYNC_UNKNOWN)
|
||||
{
|
||||
/* We have seen a fresh sync code */
|
||||
|
@ -552,9 +590,12 @@ static void put_bit(void *user_data, int bit)
|
|||
tag = ">??: ";
|
||||
break;
|
||||
}
|
||||
/*endswitch*/
|
||||
span_log_buf(&s->logging, SPAN_LOG_FLOW, tag, s->rx_data, s->rx_data_ptr);
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
/* If we were handling a valid sync code then we should process what has been
|
||||
received to date. */
|
||||
switch (s->preamble_type)
|
||||
|
@ -566,10 +607,12 @@ static void put_bit(void *user_data, int bit)
|
|||
cm_jm_decode(s);
|
||||
break;
|
||||
}
|
||||
/*endswitch*/
|
||||
s->preamble_type = new_preamble_type;
|
||||
s->bit_cnt = 0;
|
||||
s->rx_data_ptr = 0;
|
||||
}
|
||||
/*endif*/
|
||||
|
||||
if (s->preamble_type != V8_SYNC_UNKNOWN)
|
||||
{
|
||||
|
@ -585,17 +628,22 @@ static void put_bit(void *user_data, int bit)
|
|||
{
|
||||
if (++s->zero_byte_count == 3)
|
||||
s->got_cj = true;
|
||||
/*endif*/
|
||||
}
|
||||
else
|
||||
{
|
||||
s->zero_byte_count = 0;
|
||||
}
|
||||
/*endif*/
|
||||
|
||||
if (s->rx_data_ptr < (int) (sizeof(s->rx_data) - 1))
|
||||
s->rx_data[s->rx_data_ptr++] = data;
|
||||
/*endif*/
|
||||
s->bit_cnt = 0;
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -625,6 +673,7 @@ static int get_bit(void *user_data)
|
|||
s = user_data;
|
||||
if (queue_read(s->tx_queue, &bit, 1) <= 0)
|
||||
return SIG_STATUS_END_OF_DATA;
|
||||
/*endif*/
|
||||
return bit;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -657,9 +706,11 @@ static void v8_put_bytes(v8_state_t *s, uint8_t buf[], int len)
|
|||
bits[j] = byte & 1;
|
||||
byte >>= 1;
|
||||
}
|
||||
/*endfor*/
|
||||
bits[9] = 1;
|
||||
queue_write(s->tx_queue, bits, 10);
|
||||
}
|
||||
/*endfor*/
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -684,50 +735,68 @@ static void send_cm_jm(v8_state_t *s)
|
|||
val = 0x05;
|
||||
if (offered_modulations & V8_MOD_V90)
|
||||
val |= 0x20;
|
||||
/*endif*/
|
||||
if (offered_modulations & V8_MOD_V34)
|
||||
val |= 0x40;
|
||||
/*endif*/
|
||||
if (offered_modulations & V8_MOD_V34HDX)
|
||||
val |= 0x80;
|
||||
/*endif*/
|
||||
buf[ptr++] = val;
|
||||
if (++bytes < s->modulation_bytes)
|
||||
{
|
||||
val = 0x10;
|
||||
if (offered_modulations & V8_MOD_V32)
|
||||
val |= 0x01;
|
||||
/*endif*/
|
||||
if (offered_modulations & V8_MOD_V22)
|
||||
val |= 0x02;
|
||||
/*endif*/
|
||||
if (offered_modulations & V8_MOD_V17)
|
||||
val |= 0x04;
|
||||
/*endif*/
|
||||
if (offered_modulations & V8_MOD_V29)
|
||||
val |= 0x40;
|
||||
/*endif*/
|
||||
if (offered_modulations & V8_MOD_V27TER)
|
||||
val |= 0x80;
|
||||
/*endif*/
|
||||
buf[ptr++] = val;
|
||||
}
|
||||
/*endif*/
|
||||
if (++bytes < s->modulation_bytes)
|
||||
{
|
||||
val = 0x10;
|
||||
if (offered_modulations & V8_MOD_V26TER)
|
||||
val |= 0x01;
|
||||
/*endif*/
|
||||
if (offered_modulations & V8_MOD_V26BIS)
|
||||
val |= 0x02;
|
||||
/*endif*/
|
||||
if (offered_modulations & V8_MOD_V23)
|
||||
val |= 0x04;
|
||||
/*endif*/
|
||||
if (offered_modulations & V8_MOD_V23HDX)
|
||||
val |= 0x40;
|
||||
/*endif*/
|
||||
if (offered_modulations & V8_MOD_V21)
|
||||
val |= 0x80;
|
||||
/*endif*/
|
||||
buf[ptr++] = val;
|
||||
}
|
||||
|
||||
/*endif*/
|
||||
if (s->parms.protocol)
|
||||
buf[ptr++] = (s->parms.protocol << 5) | V8_PROTOCOLS_TAG;
|
||||
/*endif*/
|
||||
if (s->parms.pstn_access)
|
||||
buf[ptr++] = (s->parms.pstn_access << 5) | V8_PSTN_ACCESS_TAG;
|
||||
/*endif*/
|
||||
if (s->parms.pcm_modem_availability)
|
||||
buf[ptr++] = (s->parms.pcm_modem_availability << 5) | V8_PCM_MODEM_AVAILABILITY_TAG;
|
||||
/*endif*/
|
||||
if (s->parms.t66 >= 0)
|
||||
buf[ptr++] = (s->parms.t66 << 5) | V8_T66_TAG;
|
||||
/*endif*/
|
||||
/* No NSF */
|
||||
//buf[ptr++] = (0 << 5) | V8_NSF_TAG;
|
||||
span_log_buf(&s->logging, SPAN_LOG_FLOW, (s->calling_party) ? "<CM: " : "<JM: ", &buf[1], ptr - 1);
|
||||
|
@ -743,23 +812,25 @@ SPAN_DECLARE(int) v8_tx(v8_state_t *s, int16_t *amp, int max_len)
|
|||
len = 0;
|
||||
if (s->modem_connect_tone_tx_on)
|
||||
{
|
||||
if (s->modem_connect_tone_tx_on == (ms_to_samples(75) + 2))
|
||||
if (s->modem_connect_tone_tx_on == (milliseconds_to_samples(75) + 2))
|
||||
{
|
||||
if (s->fsk_tx_on)
|
||||
{
|
||||
/* The initial silence is over */
|
||||
s->modem_connect_tone_tx_on = 0;
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
else if (s->modem_connect_tone_tx_on == (ms_to_samples(75) + 1))
|
||||
else if (s->modem_connect_tone_tx_on == (milliseconds_to_samples(75) + 1))
|
||||
{
|
||||
/* Send the ANSam tone */
|
||||
len = modem_connect_tones_tx(&s->ansam_tx, amp, max_len);
|
||||
if (len < max_len)
|
||||
{
|
||||
span_log(&s->logging, SPAN_LOG_FLOW, "ANSam or ANSam/ ended\n");
|
||||
s->modem_connect_tone_tx_on = ms_to_samples(75);
|
||||
s->modem_connect_tone_tx_on = milliseconds_to_samples(75);
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -768,10 +839,13 @@ SPAN_DECLARE(int) v8_tx(v8_state_t *s, int16_t *amp, int max_len)
|
|||
len = s->modem_connect_tone_tx_on;
|
||||
else
|
||||
len = max_len;
|
||||
/*endif*/
|
||||
vec_zeroi16(amp, len);
|
||||
s->modem_connect_tone_tx_on -= len;
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
if (s->fsk_tx_on && len < max_len)
|
||||
{
|
||||
len += fsk_tx(&s->v21tx, &[len], max_len - len);
|
||||
|
@ -781,33 +855,38 @@ SPAN_DECLARE(int) v8_tx(v8_state_t *s, int16_t *amp, int max_len)
|
|||
s->fsk_tx_on = false;
|
||||
//s->state = V8_PARKED;
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
if (s->state != V8_PARKED && len < max_len)
|
||||
{
|
||||
vec_zeroi16(&[len], max_len - len);
|
||||
len = max_len;
|
||||
}
|
||||
/*endif*/
|
||||
return len;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void send_v92(v8_state_t *s)
|
||||
static void conditionally_send_v92(v8_state_t *s)
|
||||
{
|
||||
int i;
|
||||
uint8_t buf[2];
|
||||
|
||||
if (s->result.v92 >= 0)
|
||||
if (s->parms.v92 >= 0)
|
||||
{
|
||||
/* Send 2 V.92 packets */
|
||||
for (i = 0; i < 2; i++)
|
||||
{
|
||||
v8_put_preamble(s);
|
||||
buf[0] = V8_V92_SYNC_OCTET;
|
||||
buf[1] = s->result.v92;
|
||||
buf[1] = s->parms.v92;
|
||||
span_log_buf(&s->logging, SPAN_LOG_FLOW, "<V.92: ", &buf[1], 1);
|
||||
v8_put_bytes(s, buf, 2);
|
||||
}
|
||||
/*endfor*/
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -825,6 +904,7 @@ static void send_ci(v8_state_t *s)
|
|||
span_log_buf(&s->logging, SPAN_LOG_FLOW, "<CI: ", &buf[1], 1);
|
||||
v8_put_bytes(s, buf, 2);
|
||||
}
|
||||
/*endfor*/
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -839,7 +919,9 @@ static void handle_modem_connect_tone(v8_state_t *s, int tone)
|
|||
/* Set the Te interval. The spec. says 500ms is the minimum,
|
||||
but gives reasons why 1 second is a better value (V.8/8.1.1). */
|
||||
s->state = V8_HEARD_ANSAM;
|
||||
s->ci_timer = ms_to_samples(1000);
|
||||
s->ci_timer = milliseconds_to_samples(2*Te_TIMEOUT);
|
||||
s->negotiation_timer = milliseconds_to_samples(5000);
|
||||
v8_decode_init(s);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -850,6 +932,7 @@ static void handle_modem_connect_tone(v8_state_t *s, int tone)
|
|||
s->result.status = V8_STATUS_NON_V8_CALL;
|
||||
report_event(s);
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
|
@ -868,6 +951,7 @@ SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
|
|||
/* Wait 1 second before sending the first CI packet */
|
||||
if ((s->negotiation_timer -= len) > 0)
|
||||
break;
|
||||
/*endif*/
|
||||
fsk_tx_restart(&s->v21tx, &preset_fsk_specs[FSK_V21CH1]);
|
||||
send_ci(s);
|
||||
s->state = V8_CI_ON;
|
||||
|
@ -881,12 +965,15 @@ SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
|
|||
handle_modem_connect_tone(s, tone);
|
||||
break;
|
||||
}
|
||||
/*endif*/
|
||||
if (!s->fsk_tx_on)
|
||||
{
|
||||
s->state = V8_CI_OFF;
|
||||
s->ci_timer = ms_to_samples(500);
|
||||
s->ci_timer = milliseconds_to_samples(Te_TIMEOUT);
|
||||
s->negotiation_timer = milliseconds_to_samples(5000);
|
||||
break;
|
||||
}
|
||||
/*endif*/
|
||||
break;
|
||||
case V8_CI_OFF:
|
||||
residual_samples = modem_connect_tones_rx(&s->ansam_rx, amp, len);
|
||||
|
@ -896,6 +983,7 @@ SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
|
|||
handle_modem_connect_tone(s, tone);
|
||||
break;
|
||||
}
|
||||
/*endif*/
|
||||
if ((s->ci_timer -= len) <= 0)
|
||||
{
|
||||
if (++s->ci_count >= 10)
|
||||
|
@ -914,28 +1002,30 @@ SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
|
|||
s->state = V8_CI_ON;
|
||||
s->fsk_tx_on = true;
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
break;
|
||||
case V8_AWAIT_ANSAM:
|
||||
residual_samples = modem_connect_tones_rx(&s->ansam_rx, amp, len);
|
||||
/* Check if an ANSam or ANSam/ tone has been detected */
|
||||
if ((tone = modem_connect_tones_rx_get(&s->ansam_rx)) != MODEM_CONNECT_TONES_NONE)
|
||||
handle_modem_connect_tone(s, tone);
|
||||
/*endif*/
|
||||
break;
|
||||
case V8_HEARD_ANSAM:
|
||||
/* We have heard the ANSam or ANSam/ signal, but we still need to wait for the
|
||||
end of the Te timeout period to comply with the spec. */
|
||||
if ((s->ci_timer -= len) <= 0)
|
||||
{
|
||||
v8_decode_init(s);
|
||||
s->negotiation_timer = ms_to_samples(5000);
|
||||
fsk_tx_restart(&s->v21tx, &preset_fsk_specs[FSK_V21CH1]);
|
||||
send_v92(s);
|
||||
conditionally_send_v92(s);
|
||||
send_cm_jm(s);
|
||||
s->state = V8_CM_ON;
|
||||
s->fsk_tx_on = true;
|
||||
s->state = V8_CM_ON;
|
||||
}
|
||||
break;
|
||||
/*endif*/
|
||||
/* Fall through */
|
||||
case V8_CM_ON:
|
||||
residual_samples = fsk_rx(&s->v21rx, amp, len);
|
||||
if (s->got_cm_jm)
|
||||
|
@ -951,6 +1041,7 @@ SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
|
|||
s->fsk_tx_on = true;
|
||||
break;
|
||||
}
|
||||
/*endif*/
|
||||
if ((s->negotiation_timer -= len) <= 0)
|
||||
{
|
||||
/* Timeout */
|
||||
|
@ -959,20 +1050,23 @@ SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
|
|||
s->result.status = V8_STATUS_FAILED;
|
||||
report_event(s);
|
||||
}
|
||||
/*endif*/
|
||||
if (queue_contents(s->tx_queue) < 10)
|
||||
{
|
||||
/* Send CM again */
|
||||
send_cm_jm(s);
|
||||
}
|
||||
/*endif*/
|
||||
break;
|
||||
case V8_CJ_ON:
|
||||
residual_samples = fsk_rx(&s->v21rx, amp, len);
|
||||
if (!s->fsk_tx_on)
|
||||
{
|
||||
#if 0
|
||||
s->negotiation_timer = ms_to_samples(75);
|
||||
s->negotiation_timer = milliseconds_to_samples(75);
|
||||
s->state = V8_SIGC;
|
||||
}
|
||||
/*endif*/
|
||||
break;
|
||||
case V8_SIGC:
|
||||
if ((s->negotiation_timer -= len) <= 0)
|
||||
|
@ -984,6 +1078,7 @@ SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
|
|||
s->result.status = V8_STATUS_V8_CALL;
|
||||
report_event(s);
|
||||
}
|
||||
/*endif*/
|
||||
break;
|
||||
case V8_CM_WAIT:
|
||||
residual_samples = fsk_rx(&s->v21rx, amp, len);
|
||||
|
@ -997,13 +1092,14 @@ SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
|
|||
/* Stop sending ANSam or ANSam/ and send JM instead */
|
||||
fsk_tx_init(&s->v21tx, &preset_fsk_specs[FSK_V21CH2], get_bit, s);
|
||||
/* Set the timeout for JM */
|
||||
s->negotiation_timer = ms_to_samples(5000);
|
||||
s->negotiation_timer = milliseconds_to_samples(5000);
|
||||
s->state = V8_JM_ON;
|
||||
send_cm_jm(s);
|
||||
s->modem_connect_tone_tx_on = ms_to_samples(75);
|
||||
s->modem_connect_tone_tx_on = milliseconds_to_samples(75);
|
||||
s->fsk_tx_on = true;
|
||||
break;
|
||||
}
|
||||
/*endif*/
|
||||
if ((s->negotiation_timer -= len) <= 0)
|
||||
{
|
||||
/* Timeout */
|
||||
|
@ -1012,6 +1108,7 @@ SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
|
|||
s->result.status = V8_STATUS_FAILED;
|
||||
report_event(s);
|
||||
}
|
||||
/*endif*/
|
||||
break;
|
||||
case V8_JM_ON:
|
||||
residual_samples = fsk_rx(&s->v21rx, amp, len);
|
||||
|
@ -1020,10 +1117,11 @@ SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
|
|||
span_log(&s->logging, SPAN_LOG_FLOW, "CJ recognised\n");
|
||||
/* Stop sending JM, flushing anything left in the buffer, and wait 75 ms */
|
||||
queue_flush(s->tx_queue);
|
||||
s->negotiation_timer = ms_to_samples(75);
|
||||
s->negotiation_timer = milliseconds_to_samples(75);
|
||||
s->state = V8_SIGA;
|
||||
break;
|
||||
}
|
||||
/*endif*/
|
||||
if ((s->negotiation_timer -= len) <= 0)
|
||||
{
|
||||
/* Timeout */
|
||||
|
@ -1033,11 +1131,13 @@ SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
|
|||
report_event(s);
|
||||
break;
|
||||
}
|
||||
/*endif*/
|
||||
if (queue_contents(s->tx_queue) < 10)
|
||||
{
|
||||
/* Send JM */
|
||||
send_cm_jm(s);
|
||||
}
|
||||
/*endif*/
|
||||
break;
|
||||
case V8_SIGA:
|
||||
if (!s->fsk_tx_on)
|
||||
|
@ -1049,11 +1149,13 @@ SPAN_DECLARE(int) v8_rx(v8_state_t *s, const int16_t *amp, int len)
|
|||
s->result.status = V8_STATUS_V8_CALL;
|
||||
report_event(s);
|
||||
}
|
||||
/*endif*/
|
||||
break;
|
||||
case V8_PARKED:
|
||||
residual_samples = len;
|
||||
break;
|
||||
}
|
||||
/*endswitch*/
|
||||
return residual_samples;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -1085,30 +1187,34 @@ SPAN_DECLARE(int) v8_restart(v8_state_t *s, bool calling_party, v8_parms_t *parm
|
|||
if (s->result.send_ci)
|
||||
{
|
||||
s->state = V8_WAIT_1S;
|
||||
s->negotiation_timer = ms_to_samples(1000);
|
||||
s->negotiation_timer = milliseconds_to_samples(1000);
|
||||
s->ci_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
s->state = V8_AWAIT_ANSAM;
|
||||
}
|
||||
/*endif*/
|
||||
modem_connect_tones_rx_init(&s->ansam_rx, MODEM_CONNECT_TONES_ANS_PR, NULL, NULL);
|
||||
fsk_tx_init(&s->v21tx, &preset_fsk_specs[FSK_V21CH1], get_bit, s);
|
||||
s->modem_connect_tone_tx_on = ms_to_samples(75) + 2;
|
||||
s->modem_connect_tone_tx_on = milliseconds_to_samples(75) + 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Send the ANSam or ANSam/ tone */
|
||||
s->state = V8_CM_WAIT;
|
||||
s->negotiation_timer = ms_to_samples(200 + 5000);
|
||||
s->negotiation_timer = milliseconds_to_samples(200 + 5000);
|
||||
v8_decode_init(s);
|
||||
modem_connect_tones_tx_init(&s->ansam_tx, s->parms.modem_connect_tone);
|
||||
s->modem_connect_tone_tx_on = ms_to_samples(75) + 1;
|
||||
s->modem_connect_tone_tx_on = milliseconds_to_samples(75) + 1;
|
||||
}
|
||||
/*endif*/
|
||||
if (s->tx_queue)
|
||||
queue_free(s->tx_queue);
|
||||
/*endif*/
|
||||
if ((s->tx_queue = queue_init(NULL, 1024, 0)) == NULL)
|
||||
return -1;
|
||||
/*endif*/
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -1123,7 +1229,9 @@ SPAN_DECLARE(v8_state_t *) v8_init(v8_state_t *s,
|
|||
{
|
||||
if ((s = (v8_state_t *) span_alloc(sizeof(*s))) == NULL)
|
||||
return NULL;
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
memset(s, 0, sizeof(*s));
|
||||
span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
|
||||
span_log_set_protocol(&s->logging, "V.8");
|
||||
|
|
|
@ -188,6 +188,10 @@ static int modem_tests(int use_gui, int log_audio, int test_sending)
|
|||
bert_set_report(bert[i], 100000, reporter, (void *) (intptr_t) i);
|
||||
if ((data_modems_state[i] = data_modems_init(NULL,
|
||||
calling_party,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
put_msg,
|
||||
get_msg,
|
||||
NULL)) == NULL)
|
||||
|
|
|
@ -67,6 +67,61 @@ int16_t wave_buffer[4096];
|
|||
|
||||
data_modems_state_t *data_modem_state;
|
||||
|
||||
int answered = false;
|
||||
int done = false;
|
||||
|
||||
static int modem_call_control(data_modems_state_t *s, void *user_data, int op, const char *num)
|
||||
{
|
||||
printf("\nModem control - %s", at_modem_control_to_str(op));
|
||||
switch (op)
|
||||
{
|
||||
case AT_MODEM_CONTROL_CALL:
|
||||
printf(" %s", num);
|
||||
data_modems_call_event(s, AT_CALL_EVENT_CONNECTED);
|
||||
break;
|
||||
case AT_MODEM_CONTROL_ANSWER:
|
||||
answered = true;
|
||||
data_modems_call_event(s, AT_CALL_EVENT_ANSWERED);
|
||||
break;
|
||||
case AT_MODEM_CONTROL_HANGUP:
|
||||
done = true;
|
||||
break;
|
||||
case AT_MODEM_CONTROL_OFFHOOK:
|
||||
break;
|
||||
case AT_MODEM_CONTROL_DTR:
|
||||
printf(" %d", (int) (intptr_t) num);
|
||||
break;
|
||||
case AT_MODEM_CONTROL_RTS:
|
||||
printf(" %d", (int) (intptr_t) num);
|
||||
break;
|
||||
case AT_MODEM_CONTROL_CTS:
|
||||
printf(" %d", (int) (intptr_t) num);
|
||||
break;
|
||||
case AT_MODEM_CONTROL_CAR:
|
||||
printf(" %d", (int) (intptr_t) num);
|
||||
break;
|
||||
case AT_MODEM_CONTROL_RNG:
|
||||
printf(" %d", (int) (intptr_t) num);
|
||||
break;
|
||||
case AT_MODEM_CONTROL_DSR:
|
||||
printf(" %d", (int) (intptr_t) num);
|
||||
break;
|
||||
case AT_MODEM_CONTROL_SETID:
|
||||
printf(" %d", (int) (intptr_t) num);
|
||||
break;
|
||||
case AT_MODEM_CONTROL_RESTART:
|
||||
printf(" %d", (int) (intptr_t) num);
|
||||
break;
|
||||
case AT_MODEM_CONTROL_DTE_TIMEOUT:
|
||||
printf(" %d", (int) (intptr_t) num);
|
||||
break;
|
||||
}
|
||||
/*endswitch*/
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int get_msg(void *user_data, uint8_t msg[], int len)
|
||||
{
|
||||
return 0;
|
||||
|
@ -79,17 +134,31 @@ static void put_msg(void *user_data, const uint8_t msg[], int len)
|
|||
printf("Status %s\n", signal_status_to_str(len));
|
||||
else
|
||||
printf("Put %d '%s'\n", len, msg);
|
||||
/*endif*/
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static void terminal_callback(void *user_data, const uint8_t msg[], int len)
|
||||
{
|
||||
data_modems_state_t *s;
|
||||
int i;
|
||||
|
||||
s = (data_modems_state_t *) user_data;
|
||||
printf("terminal callback %d\n", len);
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
printf("0x%x ", msg[i]);
|
||||
}
|
||||
printf("\n");
|
||||
at_interpreter(&s->at_state, msg, len);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
static int termios_callback(void *user_data, struct termios *termios)
|
||||
{
|
||||
data_modems_state_t *s;
|
||||
|
||||
s = (data_modems_state_t *) user_data;
|
||||
printf("termios callback\n");
|
||||
return 0;
|
||||
}
|
||||
|
@ -116,7 +185,9 @@ static int rx_callback(void *user_data, const int16_t amp[], int samples)
|
|||
{
|
||||
for (i = 0; i < samples; i++)
|
||||
wave_buffer[2*i] = amp[i];
|
||||
/*endfor*/
|
||||
}
|
||||
/*endif*/
|
||||
return out_samples;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -137,10 +208,13 @@ static int tx_callback(void *user_data, int16_t amp[], int samples)
|
|||
{
|
||||
if (out_samples < samples)
|
||||
memset(&[out_samples], 0, (samples - out_samples)*2);
|
||||
/*endif*/
|
||||
for (i = 0; i < samples; i++)
|
||||
wave_buffer[2*i + 1] = amp[i];
|
||||
/*endfor*/
|
||||
sf_writef_short(wave_handle, wave_buffer, samples);
|
||||
}
|
||||
/*endif*/
|
||||
return samples;
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
@ -153,6 +227,10 @@ static int modem_tests(int use_gui, int log_audio, bool calling_party)
|
|||
/* Now set up and run the modems */
|
||||
if ((data_modem_state = data_modems_init(NULL,
|
||||
calling_party,
|
||||
terminal_write,
|
||||
NULL,
|
||||
modem_call_control,
|
||||
NULL,
|
||||
put_msg,
|
||||
get_msg,
|
||||
NULL)) == NULL)
|
||||
|
@ -160,6 +238,7 @@ static int modem_tests(int use_gui, int log_audio, bool calling_party)
|
|||
fprintf(stderr, " Cannot start the data modem\n");
|
||||
exit(2);
|
||||
}
|
||||
/*endif*/
|
||||
logging = data_modems_get_logging_state(data_modem_state);
|
||||
span_log_set_level(logging, SPAN_LOG_DEBUG | SPAN_LOG_SHOW_TAG | SPAN_LOG_SHOW_DATE);
|
||||
span_log_set_tag(logging, "Modem");
|
||||
|
@ -180,6 +259,9 @@ static int modem_tests(int use_gui, int log_audio, bool calling_party)
|
|||
fprintf(stderr, " Cannot start the socket harness\n");
|
||||
exit(2);
|
||||
}
|
||||
/*endif*/
|
||||
|
||||
data_modems_set_at_tx_handler(data_modem_state, terminal_write, s);
|
||||
|
||||
wave_handle = NULL;
|
||||
if (log_audio)
|
||||
|
@ -189,9 +271,11 @@ static int modem_tests(int use_gui, int log_audio, bool calling_party)
|
|||
fprintf(stderr, " Cannot create audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
|
||||
exit(2);
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
|
||||
socket_harness_run(s);
|
||||
socket_harness_run(s, calling_party);
|
||||
|
||||
if (log_audio)
|
||||
{
|
||||
|
@ -200,7 +284,9 @@ static int modem_tests(int use_gui, int log_audio, bool calling_party)
|
|||
fprintf(stderr, " Cannot close audio file '%s'\n", OUTPUT_WAVE_FILE_NAME);
|
||||
exit(2);
|
||||
}
|
||||
/*endif*/
|
||||
}
|
||||
/*endif*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -242,10 +328,13 @@ int main(int argc, char *argv[])
|
|||
exit(2);
|
||||
break;
|
||||
}
|
||||
/*endswitch*/
|
||||
}
|
||||
/*endwhile*/
|
||||
|
||||
if (modem_tests(use_gui, log_audio, calling_party))
|
||||
exit(2);
|
||||
/*endif*/
|
||||
printf("Tests passed\n");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -79,7 +79,16 @@ static void log_signal(int signum)
|
|||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
int socket_harness_run(socket_harness_state_t *s)
|
||||
int terminal_write(void *user_data, const char *buf, int len)
|
||||
{
|
||||
socket_harness_state_t *s;
|
||||
|
||||
s = (socket_harness_state_t *) user_data;
|
||||
return write(s->pty_fd, buf, len);
|
||||
}
|
||||
/*- End of function --------------------------------------------------------*/
|
||||
|
||||
int socket_harness_run(socket_harness_state_t *s, int kick)
|
||||
{
|
||||
struct timeval tmo;
|
||||
fd_set rset;
|
||||
|
@ -91,6 +100,23 @@ int socket_harness_run(socket_harness_state_t *s)
|
|||
int tx_samples;
|
||||
int ret;
|
||||
|
||||
if (kick)
|
||||
{
|
||||
samples = 160;
|
||||
tx_samples = s->tx_callback(s->user_data, outbuf, samples);
|
||||
if (tx_samples < samples)
|
||||
memset(&outbuf[tx_samples], 0, (samples - tx_samples)*2);
|
||||
|
||||
if ((count = write(s->audio_fd, outbuf, samples*2)) < 0)
|
||||
{
|
||||
if (errno != EAGAIN)
|
||||
{
|
||||
fprintf(stderr, "Error: audio write: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
/* TODO: */
|
||||
}
|
||||
}
|
||||
while (keep_running)
|
||||
{
|
||||
//if (s->modem->event)
|
||||
|
@ -131,7 +157,6 @@ int socket_harness_run(socket_harness_state_t *s)
|
|||
fprintf(stderr, "Error: select: %s\n", strerror(errno));
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
{
|
||||
/* Timeout */
|
||||
|
|
|
@ -53,7 +53,9 @@ typedef struct socket_harness_state_s
|
|||
modem_t modem;
|
||||
} socket_harness_state_t;
|
||||
|
||||
int socket_harness_run(socket_harness_state_t *s);
|
||||
int socket_harness_run(socket_harness_state_t *s, int kick);
|
||||
|
||||
int terminal_write(void *user_data, const char *buf, int len);
|
||||
|
||||
socket_harness_state_t *socket_harness_init(socket_harness_state_t *s,
|
||||
const char *socket_name,
|
||||
|
|
Loading…
Reference in New Issue