Missing data modems files. They are a work in progress at this time, so don't

expect any functionality.
This commit is contained in:
Steve Underwood 2014-05-06 21:21:33 +08:00
parent 29ea8e9979
commit 68a3250a69
3 changed files with 868 additions and 0 deletions

View File

@ -0,0 +1,641 @@
/*
* SpanDSP - a series of DSP components for telephony
*
* data_modems.c - the analogue modem set for data processing
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2003, 2005, 2006, 2008, 2011, 2013 Steve Underwood
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*! \file */
#if defined(HAVE_CONFIG_H)
#include "config.h"
#endif
#include <inttypes.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#if defined(HAVE_TGMATH_H)
#include <tgmath.h>
#endif
#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 <assert.h>
#include <fcntl.h>
#include <time.h>
#if defined(LOG_FAX_AUDIO)
#include <unistd.h>
#endif
#include "spandsp/telephony.h"
#include "spandsp/alloc.h"
#include "spandsp/logging.h"
#include "spandsp/bit_operations.h"
#include "spandsp/dc_restore.h"
#include "spandsp/queue.h"
#include "spandsp/power_meter.h"
#include "spandsp/complex.h"
#include "spandsp/tone_detect.h"
#include "spandsp/tone_generate.h"
#include "spandsp/async.h"
#include "spandsp/silence_gen.h"
#include "spandsp/fsk.h"
#include "spandsp/v29rx.h"
#include "spandsp/v22bis.h"
#if defined(SPANDSP_SUPPORT_V32BIS)
#include "spandsp/v17tx.h"
#include "spandsp/v17rx.h"
#include "spandsp/modem_echo.h"
#include "spandsp/v32bis.h"
#endif
#if defined(SPANDSP_SUPPORT_V34)
#include "spandsp/bitstream.h"
#include "spandsp/v34.h"
#endif
#include "spandsp/super_tone_rx.h"
#include "spandsp/modem_connect_tones.h"
#include "spandsp/hdlc.h"
#include "spandsp/v42.h"
#include "spandsp/v42bis.h"
#include "spandsp/v8.h"
#include "spandsp/data_modems.h"
#include "spandsp/private/logging.h"
#include "spandsp/private/silence_gen.h"
#include "spandsp/private/power_meter.h"
#include "spandsp/private/fsk.h"
#include "spandsp/private/v22bis.h"
#if defined(SPANDSP_SUPPORT_V32BIS)
#include "spandsp/private/v17tx.h"
#include "spandsp/private/v17rx.h"
#include "spandsp/private/modem_echo.h"
#include "spandsp/private/v32bis.h"
#endif
#if defined(SPANDSP_SUPPORT_V34)
#include "spandsp/private/bitstream.h"
#include "spandsp/private/v34.h"
#endif
#include "spandsp/private/modem_connect_tones.h"
#include "spandsp/private/hdlc.h"
#include "spandsp/private/v42.h"
#include "spandsp/private/v42bis.h"
#include "spandsp/private/v8.h"
#include "spandsp/private/async.h"
#include "spandsp/private/data_modems.h"
SPAN_DECLARE(const char *) data_modems_modulation_to_str(int modulation_scheme)
{
switch (modulation_scheme)
{
case DATA_MODEM_NONE:
return "None";
case DATA_MODEM_FLUSH:
return "Flush";
case DATA_MODEM_SILENCE:
return "Silence";
case DATA_MODEM_CED_TONE:
return "CED";
case DATA_MODEM_CNG_TONE:
return "CNG";
case DATA_MODEM_V8:
return "V.8";
case DATA_MODEM_BELL103:
return "B103 duplex";
case DATA_MODEM_BELL202:
return "B202 duplex";
case DATA_MODEM_V21:
return "V.21 duplex";
case DATA_MODEM_V23:
return "V.23 duplex";
case DATA_MODEM_V22BIS:
return "V.22/V.22bis duplex";
case DATA_MODEM_V32BIS:
return "V.32/V.32bis duplex";
case DATA_MODEM_V34:
return "V.34 duplex";
}
return "???";
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(logging_state_t *) data_modems_get_logging_state(data_modems_state_t *s)
{
return &s->logging;
}
/*- End of function --------------------------------------------------------*/
static int async_get_byte(void *user_data)
{
data_modems_state_t *s;
uint8_t msg[1];
s = (data_modems_state_t *) user_data;
s->get_msg(s->user_data, msg, 1);
return msg[0];
}
/*- End of function --------------------------------------------------------*/
static void async_put_byte(void *user_data, int byte)
{
data_modems_state_t *s;
uint8_t msg[1];
s = (data_modems_state_t *) user_data;
msg[0] = byte;
if (byte < 0)
s->put_msg(s->user_data, msg, byte);
s->put_msg(s->user_data, msg, 1);
}
/*- End of function --------------------------------------------------------*/
static void tone_callback(void *user_data, int tone, int level, int delay)
{
printf("%s declared (%ddBm0)\n", modem_connect_tone_to_str(tone), level);
}
/*- End of function --------------------------------------------------------*/
static void log_supported_modulations(data_modems_state_t *s, int modulation_schemes)
{
const char *comma;
int i;
comma = "";
span_log(&s->logging, SPAN_LOG_FLOW, " ");
for (i = 0; i < 32; i++)
{
if ((modulation_schemes & (1 << i)))
{
span_log(&s->logging, SPAN_LOG_FLOW | SPAN_LOG_SUPPRESS_LABELLING, "%s%s", comma, v8_modulation_to_str(modulation_schemes & (1 << i)));
comma = ", ";
}
}
span_log(&s->logging, SPAN_LOG_FLOW | SPAN_LOG_SUPPRESS_LABELLING, " supported\n");
}
/*- End of function --------------------------------------------------------*/
static void v8_handler(void *user_data, v8_parms_t *result)
{
data_modems_state_t *s;
s = (data_modems_state_t *) user_data;
switch (result->status)
{
case V8_STATUS_IN_PROGRESS:
span_log(&s->logging, SPAN_LOG_FLOW, "V.8 negotiation in progress\n");
return;
case V8_STATUS_V8_OFFERED:
span_log(&s->logging, SPAN_LOG_FLOW, "V.8 offered by the other party\n");
break;
case V8_STATUS_V8_CALL:
span_log(&s->logging, SPAN_LOG_FLOW, "V.8 call negotiation successful\n");
break;
case V8_STATUS_NON_V8_CALL:
span_log(&s->logging, SPAN_LOG_FLOW, "Non-V.8 call negotiation successful\n");
break;
case V8_STATUS_FAILED:
span_log(&s->logging, SPAN_LOG_FLOW, "V.8 call negotiation failed\n");
return;
default:
span_log(&s->logging, SPAN_LOG_FLOW, "Unexpected V.8 status %d\n", result->status);
break;
}
/*endswitch*/
span_log(&s->logging, SPAN_LOG_FLOW, " Modem connect tone '%s' (%d)\n", modem_connect_tone_to_str(result->modem_connect_tone), result->modem_connect_tone);
span_log(&s->logging, SPAN_LOG_FLOW, " Call function '%s' (%d)\n", v8_call_function_to_str(result->call_function), result->call_function);
span_log(&s->logging, SPAN_LOG_FLOW, " Far end modulations 0x%X\n", result->modulations);
log_supported_modulations(s, result->modulations);
span_log(&s->logging, SPAN_LOG_FLOW, " Protocol '%s' (%d)\n", v8_protocol_to_str(result->protocol), result->protocol);
span_log(&s->logging, SPAN_LOG_FLOW, " PSTN access '%s' (%d)\n", v8_pstn_access_to_str(result->pstn_access), result->pstn_access);
span_log(&s->logging, SPAN_LOG_FLOW, " PCM modem availability '%s' (%d)\n", v8_pcm_modem_availability_to_str(result->pcm_modem_availability), result->pcm_modem_availability);
if (result->t66 >= 0)
span_log(&s->logging, SPAN_LOG_FLOW, " T.66 '%s' (%d)\n", v8_t66_to_str(result->t66), result->t66);
/*endif*/
if (result->nsf >= 0)
span_log(&s->logging, SPAN_LOG_FLOW, " NSF %d\n", result->nsf);
/*endif*/
switch (result->status)
{
case V8_STATUS_V8_OFFERED:
/* V.8 mode has been offered. */
span_log(&s->logging, SPAN_LOG_FLOW, " Offered\n");
/* We now need to edit the offered list of usable modem modulations to reflect
the set of modulations both ends share */
//result->call_function = V8_CALL_T30_TX;
result->modulations &= (V8_MOD_V21
| V8_MOD_V22
| V8_MOD_V23HDX
| V8_MOD_V23
#if defined(SPANDSP_SUPPORT_V32BIS)
| V8_MOD_V32
#endif
#if defined(SPANDSP_SUPPORT_V34)
| V8_MOD_V34
#endif
| 0);
span_log(&s->logging, SPAN_LOG_FLOW, " Mutual modulations 0x%X\n", result->modulations);
log_supported_modulations(s, result->modulations);
break;
case V8_STATUS_V8_CALL:
span_log(&s->logging, SPAN_LOG_FLOW, " Call\n");
if (result->call_function == V8_CALL_V_SERIES)
{
/* Negotiations OK */
if (result->protocol == V8_PROTOCOL_LAPM_V42)
{
}
/*endif*/
#if defined(SPANDSP_SUPPORT_V34)
if ((result->modulations & V8_MOD_V34))
{
s->queued_baud_rate = 2400;
s->queued_bit_rate = 28800;
s->queued_modem = DATA_MODEM_V34;
}
else
#endif
#if defined(SPANDSP_SUPPORT_V32BIS)
if ((result->modulations & V8_MOD_V32))
{
s->queued_baud_rate = 2400;
s->queued_bit_rate = 14400;
s->queued_modem = DATA_MODEM_V32BIS;
}
else
#endif
if ((result->modulations & V8_MOD_V22))
{
s->queued_baud_rate = 600;
s->queued_bit_rate = 2400;
s->queued_modem = DATA_MODEM_V22BIS;
}
else if ((result->modulations & V8_MOD_V21))
{
s->queued_baud_rate = 300;
s->queued_bit_rate = 300;
s->queued_modem = DATA_MODEM_V21;
}
else
{
s->queued_modem = DATA_MODEM_NONE;
}
/*endif*/
span_log(&s->logging, SPAN_LOG_FLOW, " Negotiated modulation '%s' %d\n", data_modems_modulation_to_str(s->queued_modem), s->queued_modem);
}
/*endif*/
break;
case V8_STATUS_NON_V8_CALL:
span_log(&s->logging, SPAN_LOG_FLOW, " Non-V.8 call\n");
s->queued_modem = DATA_MODEM_V22BIS;
break;
default:
span_log(&s->logging, SPAN_LOG_FLOW, " Huh? %d\n", result->status);
break;
}
/*endswitch*/
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) data_modems_set_async_mode(data_modems_state_t *s,
int data_bits,
int parity_bit,
int stop_bits)
{
async_tx_init(&s->async_tx,
data_bits,
parity_bit,
stop_bits,
s->use_v14,
&async_get_byte,
s);
async_rx_init(&s->async_rx,
data_bits,
parity_bit,
stop_bits,
s->use_v14,
&async_put_byte,
s);
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(void) data_modems_set_modem_type(data_modems_state_t *s, int which, int baud_rate, int bit_rate)
{
const fsk_spec_t *fsk_rx_spec;
const fsk_spec_t *fsk_tx_spec;
v8_parms_t v8_parms;
logging_state_t *logging;
int level;
switch (which)
{
case DATA_MODEM_SILENCE:
s->rx_handler = (span_rx_handler_t) &span_dummy_rx;
s->rx_fillin_handler = (span_rx_fillin_handler_t) &span_dummy_rx_fillin;
s->rx_user_data = NULL;
s->tx_handler = (span_tx_handler_t) &silence_gen;
s->tx_user_data = &s->modems.silence_gen;
silence_gen_init(&s->modems.silence_gen, 0);
break;
case DATA_MODEM_CNG_TONE:
s->rx_handler = (span_rx_handler_t) &modem_connect_tones_rx;
s->rx_fillin_handler = (span_rx_fillin_handler_t) &span_dummy_rx_fillin;
s->rx_user_data = &s->modems.tones.rx;
s->tx_handler = (span_tx_handler_t) &modem_connect_tones_tx;
s->tx_user_data = &s->modems.tones.tx;
modem_connect_tones_rx_init(&s->modems.tones.rx,
MODEM_CONNECT_TONES_FAX_CNG,
tone_callback,
s);
modem_connect_tones_tx_init(&s->modems.tones.tx, MODEM_CONNECT_TONES_FAX_CNG);
break;
case DATA_MODEM_V8:
s->rx_handler = (span_rx_handler_t) &v8_rx;
s->rx_fillin_handler = (span_rx_fillin_handler_t) &span_dummy_rx_fillin;
s->rx_user_data = &s->modems.v8;
s->tx_handler = (span_tx_handler_t) &v8_tx;
s->tx_user_data = &s->modems.v8;
if (s->calling_party)
v8_parms.modem_connect_tone = MODEM_CONNECT_TONES_NONE;
else
v8_parms.modem_connect_tone = MODEM_CONNECT_TONES_ANSAM_PR;
v8_parms.send_ci = false;
v8_parms.v92 = -1;
v8_parms.call_function = V8_CALL_V_SERIES;
#if 0
v8_parms.modulations = V8_MOD_V17
| V8_MOD_V21
| V8_MOD_V22
| V8_MOD_V23HDX
| V8_MOD_V23
| V8_MOD_V27TER
| V8_MOD_V29
| 0;
v8_parms.protocol = V8_PROTOCOL_LAPM_V42;
#elif 1
v8_parms.modulations = V8_MOD_V21
| V8_MOD_V22
| V8_MOD_V23HDX
| V8_MOD_V23
#if defined(SPANDSP_SUPPORT_V32BIS)
| V8_MOD_V32
#endif
#if defined(SPANDSP_SUPPORT_V34)
| V8_MOD_V34
#endif
| 0;
v8_parms.protocol = V8_PROTOCOL_LAPM_V42;
#endif
v8_parms.pcm_modem_availability = 0;
v8_parms.pstn_access = 0;
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");
break;
case DATA_MODEM_BELL103:
s->rx_handler = (span_rx_handler_t) &fsk_rx;
s->rx_fillin_handler = (span_rx_fillin_handler_t) &fsk_rx_fillin;
s->rx_user_data = &s->modems.fsk.rx;
s->tx_handler = (span_tx_handler_t) &fsk_tx;
s->tx_user_data = &s->modems.fsk.tx;
if (s->calling_party)
{
fsk_rx_spec = &preset_fsk_specs[FSK_BELL103CH2];
fsk_tx_spec = &preset_fsk_specs[FSK_BELL103CH1];
}
else
{
fsk_rx_spec = &preset_fsk_specs[FSK_BELL103CH1];
fsk_tx_spec = &preset_fsk_specs[FSK_BELL103CH2];
}
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;
case DATA_MODEM_V21:
s->rx_handler = (span_rx_handler_t) &fsk_rx;
s->rx_fillin_handler = (span_rx_fillin_handler_t) &fsk_rx_fillin;
s->rx_user_data = &s->modems.fsk.rx;
s->tx_handler = (span_tx_handler_t) &fsk_tx;
s->tx_user_data = &s->modems.fsk.tx;
if (s->calling_party)
{
fsk_rx_spec = &preset_fsk_specs[FSK_V21CH2];
fsk_tx_spec = &preset_fsk_specs[FSK_V21CH1];
}
else
{
fsk_rx_spec = &preset_fsk_specs[FSK_V21CH1];
fsk_tx_spec = &preset_fsk_specs[FSK_V21CH2];
}
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;
case DATA_MODEM_BELL202:
s->rx_handler = (span_rx_handler_t) &fsk_rx;
s->rx_fillin_handler = (span_rx_fillin_handler_t) &fsk_rx_fillin;
s->rx_user_data = &s->modems.fsk.rx;
s->tx_handler = (span_tx_handler_t) &fsk_tx;
s->tx_user_data = &s->modems.fsk.tx;
if (s->calling_party)
{
fsk_rx_spec = &preset_fsk_specs[FSK_BELL202];
fsk_tx_spec = &preset_fsk_specs[FSK_BELL202];
}
else
{
fsk_rx_spec = &preset_fsk_specs[FSK_BELL202];
fsk_tx_spec = &preset_fsk_specs[FSK_BELL202];
}
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;
case DATA_MODEM_V23:
s->rx_handler = (span_rx_handler_t) &fsk_rx;
s->rx_fillin_handler = (span_rx_fillin_handler_t) &fsk_rx_fillin;
s->rx_user_data = &s->modems.fsk.rx;
s->tx_handler = (span_tx_handler_t) &fsk_tx;
s->tx_user_data = &s->modems.fsk.tx;
if (s->calling_party)
{
fsk_rx_spec = &preset_fsk_specs[FSK_V23CH2];
fsk_tx_spec = &preset_fsk_specs[FSK_V23CH1];
}
else
{
fsk_rx_spec = &preset_fsk_specs[FSK_V23CH1];
fsk_tx_spec = &preset_fsk_specs[FSK_V23CH2];
}
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;
case DATA_MODEM_V22BIS:
s->rx_handler = (span_rx_handler_t) &v22bis_rx;
s->rx_fillin_handler = (span_rx_fillin_handler_t) &v22bis_rx_fillin;
s->rx_user_data = &s->modems.v22bis;
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");
break;
#if defined(SPANDSP_SUPPORT_V32BIS)
case DATA_MODEM_V32BIS:
s->rx_handler = (span_rx_handler_t) &v32bis_rx;
s->rx_fillin_handler = (span_rx_fillin_handler_t) &v32bis_rx_fillin;
s->rx_user_data = &s->modems.v32bis;
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");
break;
#endif
#if defined(SPANDSP_SUPPORT_V34)
case DATA_MODEM_V34:
s->rx_handler = (span_rx_handler_t) &v34_rx;
s->rx_fillin_handler = (span_rx_fillin_handler_t) &v34_rx_fillin;
s->rx_user_data = &s->modems.v34;
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");
break;
#endif
}
s->current_modem = which;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) data_modems_rx(data_modems_state_t *s, const int16_t amp[], int len)
{
int res;
if (s->rx_handler == NULL)
return len;
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);
return res;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) data_modems_rx_fillin(data_modems_state_t *s, int len)
{
if (s->rx_fillin_handler == NULL)
return len;
return s->rx_fillin_handler(s->rx_user_data, len);
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) data_modems_tx(data_modems_state_t *s, int16_t amp[], int max_len)
{
int len;
for (len = 0; len < max_len; )
{
if (s->tx_handler == NULL)
break;
len += s->tx_handler(s->tx_user_data, &amp[len], max_len - len);
}
return len;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) data_modems_restart(data_modems_state_t *s)
{
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(data_modems_state_t *) data_modems_init(data_modems_state_t *s,
bool calling_party,
put_msg_func_t put_msg,
get_msg_func_t get_msg,
void *user_data)
{
if (s == NULL)
{
if ((s = (data_modems_state_t *) span_alloc(sizeof(*s))) == NULL)
return NULL;
}
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->put_msg = put_msg;
s->get_msg = get_msg;
s->user_data = user_data;
v42bis_init(&s->v42bis, 3, 512, 6, NULL, s, 512, put_msg, s, 512);
v42_init(&s->v42, true, true, NULL, (put_msg_func_t) v42bis_decompress, &s->v42bis);
data_modems_set_async_mode(s, 8, 1, 1);
s->get_bit = async_tx_get_bit;
s->get_user_data = &s->async_tx;
s->put_bit = async_rx_put_bit;
s->put_user_data = &s->async_rx;
s->calling_party = calling_party;
data_modems_set_modem_type(s, DATA_MODEM_V8, 0, 0);
s->queued_modem = s->current_modem;
s->rx_signal_present = false;
return s;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) data_modems_release(data_modems_state_t *s)
{
return 0;
}
/*- End of function --------------------------------------------------------*/
SPAN_DECLARE(int) data_modems_free(data_modems_state_t *s)
{
if (s)
span_free(s);
return 0;
}
/*- End of function --------------------------------------------------------*/
/*- End of file ------------------------------------------------------------*/

View File

@ -0,0 +1,95 @@
/*
* SpanDSP - a series of DSP components for telephony
*
* data_modems.h - definitions for the analogue modem set for data processing
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2011 Steve Underwood
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*! \file */
#if !defined(_SPANDSP_DATA_MODEMS_H_)
#define _SPANDSP_DATA_MODEMS_H_
enum
{
DATA_MODEM_NONE = -1,
DATA_MODEM_FLUSH = 0,
DATA_MODEM_SILENCE,
DATA_MODEM_CED_TONE,
DATA_MODEM_CNG_TONE,
DATA_MODEM_V8,
DATA_MODEM_BELL103,
DATA_MODEM_BELL202,
DATA_MODEM_V21,
DATA_MODEM_V23,
DATA_MODEM_V22BIS,
DATA_MODEM_V32BIS,
DATA_MODEM_V34
};
/*!
The set of modems needed for data, plus the auxilliary stuff, like tone generation.
*/
typedef struct data_modems_state_s data_modems_state_t;
#if defined(__cplusplus)
extern "C"
{
#endif
/* N.B. the following are currently a work in progress */
SPAN_DECLARE(const char *) data_modems_modulation_to_str(int modulation_scheme);
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(int) data_modems_restart(data_modems_state_t *s);
SPAN_DECLARE(void) data_modems_set_async_mode(data_modems_state_t *s,
int data_bits,
int parity_bits,
int stop_bits);
SPAN_DECLARE(void) data_modems_set_modem_type(data_modems_state_t *s, int which, int baud_rate, int bit_rate);
SPAN_DECLARE(int) data_modems_rx(data_modems_state_t *s, const int16_t amp[], int len);
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(data_modems_state_t *) data_modems_init(data_modems_state_t *s,
bool calling_party,
put_msg_func_t put_msg,
get_msg_func_t get_msg,
void *user_data);
SPAN_DECLARE(int) data_modems_release(data_modems_state_t *s);
SPAN_DECLARE(int) data_modems_free(data_modems_state_t *s);
#if defined(__cplusplus)
}
#endif
#endif
/*- End of file ------------------------------------------------------------*/

View File

@ -0,0 +1,132 @@
/*
* SpanDSP - a series of DSP components for telephony
*
* private/data_modems.h - definitions for the analogue modem set for data processing
*
* Written by Steve Underwood <steveu@coppice.org>
*
* Copyright (C) 2011 Steve Underwood
*
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 2.1,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*! \file */
#if !defined(_SPANDSP_PRIVATE_DATA_MODEMS_H_)
#define _SPANDSP_PRIVATE_DATA_MODEMS_H_
/*!
The set of modems needed for data, plus the auxilliary stuff, like tone generation.
*/
struct data_modems_state_s
{
bool calling_party;
/*! True is talker echo protection should be sent for the modems which support this */
bool use_tep;
/*! If true, transmit silence when there is nothing else to transmit. If false return only
the actual generated audio. Note that this only affects untimed silences. Timed silences
(e.g. the 75ms silence between V.21 and a high speed modem) will alway be transmitted as
silent audio. */
bool transmit_on_idle;
get_bit_func_t get_bit;
void *get_user_data;
put_bit_func_t put_bit;
void *put_user_data;
void *user_data;
put_msg_func_t put_msg;
get_msg_func_t get_msg;
v42_state_t v42;
v42bis_state_t v42bis;
int use_v14;
async_tx_state_t async_tx;
async_rx_state_t async_rx;
union
{
v8_state_t v8;
struct
{
/*! \brief Tone generator */
modem_connect_tones_tx_state_t tx;
/*! \brief Tone detector */
modem_connect_tones_rx_state_t rx;
} tones;
struct
{
/*! \brief FSK transmit modem context used for 103, V.21 and V.23. */
fsk_tx_state_t tx;
/*! \brief FSK receive modem context used for 103, V.21 and V.23. */
fsk_rx_state_t rx;
} fsk;
/*! \brief V.22bis modem context */
v22bis_state_t v22bis;
#if defined(SPANDSP_SUPPORT_V32BIS)
/*! \brief V.32bis modem context */
v32bis_state_t v32bis;
#endif
#if defined(SPANDSP_SUPPORT_V34)
/*! \brief V.22bis modem context */
v34_state_t v34;
#endif
/*! \brief Used to insert timed silences. */
silence_gen_state_t silence_gen;
} modems;
/*! \brief */
dc_restore_state_t dc_restore;
int current_modem;
int queued_modem;
int queued_baud_rate;
int queued_bit_rate;
/*! \brief The currently select receiver type */
int current_rx_type;
/*! \brief The currently select transmitter type */
int current_tx_type;
/*! \brief True if a carrier is present. Otherwise false. */
bool rx_signal_present;
/*! \brief True if a modem has trained correctly. */
bool rx_trained;
/*! \brief True if an HDLC frame has been received correctly. */
bool rx_frame_received;
/*! The current receive signal handler */
span_rx_handler_t rx_handler;
/*! The current receive missing signal fill-in handler */
span_rx_fillin_handler_t rx_fillin_handler;
void *rx_user_data;
/*! The current transmit signal handler */
span_tx_handler_t tx_handler;
void *tx_user_data;
/*! \brief Audio logging file handle for received audio. */
int audio_rx_log;
/*! \brief Audio logging file handle for transmitted audio. */
int audio_tx_log;
/*! \brief Error and flow logging control */
logging_state_t logging;
};
#endif
/*- End of file ------------------------------------------------------------*/