Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Macros | Functions | Variables
tdd.c File Reference

TTY/TDD Generation support. More...

#include "asterisk.h"
#include <time.h>
#include <math.h>
#include <ctype.h>
#include "asterisk/logger.h"
#include "asterisk/ulaw.h"
#include "asterisk/tdd.h"
#include "asterisk/fskmodem.h"
#include "asterisk/utils.h"
#include "ecdisa.h"
Include dependency graph for tdd.c:

Go to the source code of this file.

Data Structures

struct  tdd_state
 

Macros

#define PUT_AUDIO_SAMPLE(y)
 
#define PUT_BYTE(a)
 
#define PUT_TDD(byte)
 
#define PUT_TDD_BAUD(bit)
 
#define PUT_TDD_MARKMS
 
#define PUT_TDD_STOP
 
#define TDD_MARK   1400.0 /* 1400 hz for "1" */
 
#define TDD_SPACE   1800.0 /* 1800 hz for "0" */
 

Functions

int ast_tdd_gen_ecdisa (unsigned char *outbuf, int len)
 
static int tdd_decode_baudot (struct tdd_state *tdd, unsigned char data)
 
int tdd_feed (struct tdd_state *tdd, unsigned char *ubuf, int len)
 
void tdd_free (struct tdd_state *tdd)
 
int tdd_gen_holdtone (unsigned char *buf)
 
int tdd_generate (struct tdd_state *tdd, unsigned char *buf, const char *str)
 
static float tdd_getcarrier (float *cr, float *ci, int bit)
 
void tdd_init (void)
 
struct tdd_statetdd_new (void)
 

Variables

static float di [4]
 
static float dr [4]
 
static float tddsb = 176.0
 

Detailed Description

TTY/TDD Generation support.

Author
Mark Spencer marks[email protected][email protected][email protected]digiu[email protected]m.co[email protected]m
Note
Includes code and algorithms from the Zapata library.

Definition in file tdd.c.

Macro Definition Documentation

◆ PUT_AUDIO_SAMPLE

#define PUT_AUDIO_SAMPLE (   y)
Value:
do { \
int __pas_idx = (short)(rint(8192.0 * (y))); \
*(buf++) = AST_LIN2MU(__pas_idx); \
bytes++; \
} while(0)
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define AST_LIN2MU(a)
Definition: ulaw.h:49

Definition at line 242 of file tdd.c.

Referenced by tdd_gen_holdtone().

◆ PUT_BYTE

#define PUT_BYTE (   a)
Value:
do { \
*(buf++) = (a); \
bytes++; \
} while(0)
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
static struct test_val a

Definition at line 237 of file tdd.c.

◆ PUT_TDD

#define PUT_TDD (   byte)

Definition at line 271 of file tdd.c.

Referenced by tdd_generate().

◆ PUT_TDD_BAUD

#define PUT_TDD_BAUD (   bit)

Definition at line 254 of file tdd.c.

◆ PUT_TDD_MARKMS

#define PUT_TDD_MARKMS
Value:
do { \
int x; \
for (x = 0; x < 8; x++) \
} while(0)
#define PUT_AUDIO_SAMPLE(y)
Definition: tdd.c:242
static float tdd_getcarrier(float *cr, float *ci, int bit)
Definition: tdd.c:223

Definition at line 248 of file tdd.c.

◆ PUT_TDD_STOP

#define PUT_TDD_STOP

Definition at line 262 of file tdd.c.

◆ TDD_MARK

#define TDD_MARK   1400.0 /* 1400 hz for "1" */

Definition at line 62 of file tdd.c.

Referenced by tdd_init().

◆ TDD_SPACE

#define TDD_SPACE   1800.0 /* 1800 hz for "0" */

Definition at line 61 of file tdd.c.

Referenced by tdd_init().

Function Documentation

◆ ast_tdd_gen_ecdisa()

int ast_tdd_gen_ecdisa ( unsigned char *  outbuf,
int  len 
)

Generate Echo Canceller disable tone (2100HZ)

Parameters
outbufThis is the buffer to receive the tone data
lenThis is the length (in samples) of the tone data to generate Returns 0 if no error, and -1 if error.

Definition at line 148 of file tdd.c.

References ecdisa, len(), and tdd_state::pos.

Referenced by dahdi_setoption().

149 {
150  int pos = 0;
151  int cnt;
152  while (len) {
153  cnt = len > sizeof(ecdisa) ? sizeof(ecdisa) : len;
154  memcpy(outbuf + pos, ecdisa, cnt);
155  pos += cnt;
156  len -= cnt;
157  }
158  return 0;
159 }
static unsigned char ecdisa[80]
Definition: ecdisa.h:3
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)

◆ tdd_decode_baudot()

static int tdd_decode_baudot ( struct tdd_state tdd,
unsigned char  data 
)
static

Definition at line 64 of file tdd.c.

References d, and tdd_state::modo.

Referenced by tdd_feed().

65 {
66  static char ltrs[32] = { '<','E','\n','A',' ','S','I','U',
67  '\n','D','R','J','N','F','C','K',
68  'T','Z','L','W','H','Y','P','Q',
69  'O','B','G','^','M','X','V','^' };
70  static char figs[32] = { '<','3','\n','-',' ','\'','8','7',
71  '\n','$','4','\'',',','!',':','(',
72  '5','\"',')','2','=','6','0','1',
73  '9','?','+','^','.','/',';','^' };
74  int d = 0; /* return 0 if not decodeable */
75  if (data < 32) {
76  switch (data) {
77  case 0x1f:
78  tdd->modo = 0;
79  break;
80  case 0x1b:
81  tdd->modo = 1;
82  break;
83  default:
84  if (tdd->modo == 0)
85  d = ltrs[data];
86  else
87  d = figs[data];
88  break;
89  }
90  }
91  return d;
92 }
static struct test_val d
int modo
Definition: tdd.c:53

◆ tdd_feed()

int tdd_feed ( struct tdd_state tdd,
unsigned char *  ubuf,
int  samples 
)

Read samples into the state machine, and return character (if any).

Parameters
tddWhich state machine to act upon
ubufcontaining your samples
samplesnumber of samples contained within the buffer.

Send received audio to the TDD demodulator. Returns -1 on error, 0 for "needs more samples", and > 0 (the character) if reception of a character is complete.

Definition at line 161 of file tdd.c.

References ast_calloc, ast_free, ast_log, AST_MULAW, b, buf, c, fsk_serial(), tdd_state::fskd, len(), LOG_ERROR, LOG_NOTICE, LOG_WARNING, tdd_state::mode, tdd_state::oldlen, tdd_state::oldstuff, and tdd_decode_baudot().

Referenced by dahdi_read().

162 {
163  int mylen = len;
164  int olen;
165  int b = 'X';
166  int res;
167  int c,x;
168  short *buf = ast_calloc(1, 2 * len + tdd->oldlen);
169  short *obuf = buf;
170  if (!buf) {
171  ast_log(LOG_WARNING, "Out of memory\n");
172  return -1;
173  }
174  memcpy(buf, tdd->oldstuff, tdd->oldlen);
175  mylen += tdd->oldlen / 2;
176  for (x = 0; x < len; x++)
177  buf[x + tdd->oldlen / 2] = AST_MULAW(ubuf[x]);
178  c = res = 0;
179  while (mylen >= 1320) { /* has to have enough to work on */
180  olen = mylen;
181  res = fsk_serial(&tdd->fskd, buf, &mylen, &b);
182  if (mylen < 0) {
183  ast_log(LOG_ERROR, "fsk_serial made mylen < 0 (%d) (olen was %d)\n", mylen, olen);
184  ast_free(obuf);
185  return -1;
186  }
187  buf += (olen - mylen);
188  if (res < 0) {
189  ast_log(LOG_NOTICE, "fsk_serial failed\n");
190  ast_free(obuf);
191  return -1;
192  }
193  if (res == 1) {
194  /* Ignore invalid bytes */
195  if (b > 0x7f)
196  continue;
197  c = tdd_decode_baudot(tdd, b);
198  if ((c < 1) || (c > 126))
199  continue; /* if not valid */
200  break;
201  }
202  }
203  if (mylen) {
204  memcpy(tdd->oldstuff, buf, mylen * 2);
205  tdd->oldlen = mylen * 2;
206  } else
207  tdd->oldlen = 0;
208  ast_free(obuf);
209  if (res) {
210  tdd->mode = 2;
211 /* put it in mode where it
212  reliably puts teleprinter in correct shift mode */
213  return(c);
214  }
215  return 0;
216 }
int oldlen
Definition: tdd.c:51
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
#define LOG_WARNING
Definition: logger.h:274
static struct test_val c
#define ast_log
Definition: astobj2.c:42
#define AST_MULAW(a)
Definition: ulaw.h:85
#define LOG_ERROR
Definition: logger.h:285
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
#define LOG_NOTICE
Definition: logger.h:263
static int tdd_decode_baudot(struct tdd_state *tdd, unsigned char data)
Definition: tdd.c:64
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
short oldstuff[4096]
Definition: tdd.c:50
fsk_data fskd
Definition: tdd.c:48
int mode
Definition: tdd.c:54
static struct test_val b
int fsk_serial(fsk_data *fskd, short *buffer, int *len, int *outbyte)

◆ tdd_free()

void tdd_free ( struct tdd_state tdd)

Free a TDD state machine

Parameters
tddThis is the tdd_state state machine to free This function frees tdd_state tdd.

Definition at line 218 of file tdd.c.

References ast_free.

Referenced by dahdi_setoption().

219 {
220  ast_free(tdd);
221 }
#define ast_free(a)
Definition: astmm.h:182

◆ tdd_gen_holdtone()

int tdd_gen_holdtone ( unsigned char *  buf)

Generate TDD hold tone

Parameters
outbuf,bufResult buffer
Todo:
How big should this be?

Definition at line 286 of file tdd.c.

References PUT_AUDIO_SAMPLE, tdd_getcarrier(), and tddsb.

287 {
288  int bytes = 0;
289  float scont = 0.0, cr = 1.0, ci=0.0;
290  while (scont < tddsb * 10.0) {
291  PUT_AUDIO_SAMPLE(tdd_getcarrier(&cr, &ci, 1));
292  scont += 1.0;
293  }
294  return bytes;
295 }
#define PUT_AUDIO_SAMPLE(y)
Definition: tdd.c:242
static float tddsb
Definition: tdd.c:59
static float tdd_getcarrier(float *cr, float *ci, int bit)
Definition: tdd.c:223

◆ tdd_generate()

int tdd_generate ( struct tdd_state tdd,
unsigned char *  buf,
const char *  string 
)

Generates a CallerID FSK stream in ulaw format suitable for transmission.

Parameters
tddtdd structure
bufBuffer to use. This needs to be large enough to accomodate all the generated samples.
stringThis is the string to send. This function creates a stream of TDD data in ulaw format. It returns the size (in bytes) of the data (if it returns a size of 0, there is probably an error)

Baudot letters

Baudot figures

Definition at line 297 of file tdd.c.

References c, tdd_state::charnum, tdd_state::mode, and PUT_TDD.

Referenced by dahdi_sendtext().

298 {
299  int bytes = 0;
300  int i,x;
301  char c;
302  /*! Baudot letters */
303  static unsigned char lstr[31] = "\000E\nA SIU\rDRJNFCKTZLWHYPQOBG\000MXV";
304  /*! Baudot figures */
305  static unsigned char fstr[31] = "\0003\n- \00787\r$4',!:(5\")2\0006019?+\000./;";
306  /* Initial carriers (real/imaginary) */
307  float cr = 1.0;
308  float ci = 0.0;
309  float scont = 0.0;
310 
311  for(x = 0; str[x]; x++) {
312  /* Do synch for each 72th character */
313  if ( (tdd->charnum++) % 72 == 0)
314  PUT_TDD(tdd->mode ? 27 /* FIGS */ : 31 /* LTRS */);
315 
316  c = toupper(str[x]);
317 #if 0
318  printf("%c",c); fflush(stdout);
319 #endif
320  if (c == 0) { /* send null */
321  PUT_TDD(0);
322  continue;
323  }
324  if (c == '\r') { /* send c/r */
325  PUT_TDD(8);
326  continue;
327  }
328  if (c == '\n') { /* send c/r and l/f */
329  PUT_TDD(8);
330  PUT_TDD(2);
331  continue;
332  }
333  if (c == ' ') { /* send space */
334  PUT_TDD(4);
335  continue;
336  }
337  for (i = 0; i < 31; i++) {
338  if (lstr[i] == c)
339  break;
340  }
341  if (i < 31) { /* if we found it */
342  if (tdd->mode) { /* if in figs mode, change it */
343  PUT_TDD(31); /* Send LTRS */
344  tdd->mode = 0;
345  }
346  PUT_TDD(i);
347  continue;
348  }
349  for (i = 0; i < 31; i++) {
350  if (fstr[i] == c)
351  break;
352  }
353  if (i < 31) { /* if we found it */
354  if (tdd->mode != 1) { /* if in ltrs mode, change it */
355  PUT_TDD(27); /* send FIGS */
356  tdd->mode = 1;
357  }
358  PUT_TDD(i); /* send byte */
359  continue;
360  }
361  }
362  return bytes;
363 }
int charnum
Definition: tdd.c:55
static struct test_val c
const char * str
Definition: app_jack.c:147
#define PUT_TDD(byte)
Definition: tdd.c:271
int mode
Definition: tdd.c:54

◆ tdd_getcarrier()

static float tdd_getcarrier ( float *  cr,
float *  ci,
int  bit 
)
inlinestatic

Definition at line 223 of file tdd.c.

References di, and dr.

Referenced by tdd_gen_holdtone().

224 {
225  /* Move along. There's nothing to see here... */
226  float t;
227  t = *cr * dr[bit] - *ci * di[bit];
228  *ci = *cr * di[bit] + *ci * dr[bit];
229  *cr = t;
230 
231  t = 2.0 - (*cr * *cr + *ci * *ci);
232  *cr *= t;
233  *ci *= t;
234  return *cr;
235 }
static float dr[4]
Definition: tdd.c:58
static float di[4]
Definition: tdd.c:58

◆ tdd_init()

void tdd_init ( void  )

CallerID Initialization Initializes the TDD system. Mostly stuff for inverse FFT

Definition at line 94 of file tdd.c.

References cos, di, dr, M_PI, TDD_MARK, and TDD_SPACE.

Referenced by asterisk_daemon().

95 {
96  /* Initialize stuff for inverse FFT */
97  dr[0] = cos(TDD_SPACE * 2.0 * M_PI / 8000.0);
98  di[0] = sin(TDD_SPACE * 2.0 * M_PI / 8000.0);
99  dr[1] = cos(TDD_MARK * 2.0 * M_PI / 8000.0);
100  di[1] = sin(TDD_MARK * 2.0 * M_PI / 8000.0);
101 }
static float dr[4]
Definition: tdd.c:58
unsigned int cos
Definition: chan_iax2.c:352
#define M_PI
Definition: resample.c:83
#define TDD_SPACE
Definition: tdd.c:61
static float di[4]
Definition: tdd.c:58
#define TDD_MARK
Definition: tdd.c:62

◆ tdd_new()

struct tdd_state* tdd_new ( void  )

Create a TDD state machine This function returns a malloc'd instance of the tdd_state data structure. Returns a pointer to a malloc'd tdd_state structure, or NULL on error.

Definition at line 103 of file tdd.c.

References ast_calloc, ast_log, fsk_data::bw, tdd_state::charnum, fsk_data::cont, fsk_data::f_mark_idx, fsk_data::f_space_idx, tdd_state::fskd, fskmodem_init(), fsk_data::hdlc, fsk_data::instop, fsk_data::ispb, LOG_WARNING, tdd_state::mode, fsk_data::nbit, fsk_data::nstop, fsk_data::parity, fsk_data::pcola, fsk_data::pllids, fsk_data::pllispb, fsk_data::pllispb2, tdd_state::pos, fsk_data::spb, fsk_data::state, fsk_data::x0, and fsk_data::xi0.

Referenced by dahdi_setoption().

104 {
105  struct tdd_state *tdd;
106  tdd = ast_calloc(1, sizeof(*tdd));
107  if (tdd) {
108 #ifdef INTEGER_CALLERID
109  tdd->fskd.ispb = 176; /* 45.5 baud */
110  /* Set up for 45.5 / 8000 freq *32 to allow ints */
111  tdd->fskd.pllispb = (int)((8000 * 32 * 2) / 90);
112  tdd->fskd.pllids = tdd->fskd.pllispb / 32;
113  tdd->fskd.pllispb2 = tdd->fskd.pllispb / 2;
114  tdd->fskd.hdlc = 0; /* Async */
115  tdd->fskd.nbit = 5; /* 5 bits */
116  tdd->fskd.instop = 1; /* integer rep of 1.5 stop bits */
117  tdd->fskd.parity = 0; /* No parity */
118  tdd->fskd.bw=0; /* Filter 75 Hz */
119  tdd->fskd.f_mark_idx = 0; /* 1400 Hz */
120  tdd->fskd.f_space_idx = 1; /* 1800 Hz */
121  tdd->fskd.xi0 = 0;
122  tdd->fskd.state = 0;
123  tdd->pos = 0;
124  tdd->mode = 0;
125  fskmodem_init(&tdd->fskd);
126 #else
127  tdd->fskd.spb = 176; /* 45.5 baud */
128  tdd->fskd.hdlc = 0; /* Async */
129  tdd->fskd.nbit = 5; /* 5 bits */
130  tdd->fskd.nstop = 1.5; /* 1.5 stop bits */
131  tdd->fskd.parity = 0; /* No parity */
132  tdd->fskd.bw=0; /* Filter 75 Hz */
133  tdd->fskd.f_mark_idx = 0; /* 1400 Hz */
134  tdd->fskd.f_space_idx = 1; /* 1800 Hz */
135  tdd->fskd.pcola = 0; /* No clue */
136  tdd->fskd.cont = 0; /* Digital PLL reset */
137  tdd->fskd.x0 = 0.0;
138  tdd->fskd.state = 0;
139  tdd->pos = 0;
140  tdd->mode = 2;
141 #endif
142  tdd->charnum = 0;
143  } else
144  ast_log(LOG_WARNING, "Out of memory\n");
145  return tdd;
146 }
int charnum
Definition: tdd.c:55
#define LOG_WARNING
Definition: logger.h:274
int pllids
Definition: fskmodem_int.h:60
int fskmodem_init(fsk_data *fskd)
Definition: fskmodem_int.c:195
float cont
float nstop
#define ast_log
Definition: astobj2.c:42
int instop
Definition: fskmodem_int.h:46
int pllispb
Definition: fskmodem_int.h:59
int pllispb2
Definition: fskmodem_int.h:61
Definition: tdd.c:47
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
int f_space_idx
fsk_data fskd
Definition: tdd.c:48
int mode
Definition: tdd.c:54
int f_mark_idx
int pos
Definition: tdd.c:52

Variable Documentation

◆ di

float di[4]
static

◆ dr

float dr[4]
static

Definition at line 58 of file tdd.c.

Referenced by append_transaction(), dundi_prop_precache(), tdd_getcarrier(), and tdd_init().

◆ tddsb

float tddsb = 176.0
static

Definition at line 59 of file tdd.c.

Referenced by tdd_gen_holdtone().