Asterisk - The Open Source Telephony Project  21.4.1
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"

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.nosp@m.ter@.nosp@m.digiu.nosp@m.m.co.nosp@m.m
Note
Includes code and algorithms from the Zapata library.

Definition in file tdd.c.

Macro Definition Documentation

#define PUT_AUDIO_SAMPLE (   y)
Value:
do { \
int __pas_idx = (short)(rint(8192.0 * (y))); \
*(buf++) = AST_LIN2MU(__pas_idx); \
bytes++; \
} while(0)

Definition at line 242 of file tdd.c.

#define PUT_BYTE (   a)
Value:
do { \
*(buf++) = (a); \
bytes++; \
} while(0)

Definition at line 237 of file tdd.c.

#define PUT_TDD_MARKMS
Value:
do { \
int x; \
for (x = 0; x < 8; x++) \
PUT_AUDIO_SAMPLE(tdd_getcarrier(&cr, &ci, 1)); \
} while(0)

Definition at line 248 of file tdd.c.

Function Documentation

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.

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 }
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, and fsk_serial().

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 }
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
int fsk_serial(fsk_data *fskd, short *buffer, int *len, int *outbyte)
Retrieve a serial byte into outbyte. Buffer is a pointer into a series of shorts and len records the ...
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.

Referenced by dahdi_setoption().

219 {
220  ast_free(tdd);
221 }
int tdd_gen_holdtone ( unsigned char *  buf)

Generate TDD hold tone

Todo:
How big should this be?

Definition at line 285 of file tdd.c.

286 {
287  int bytes = 0;
288  float scont = 0.0, cr = 1.0, ci=0.0;
289  while (scont < tddsb * 10.0) {
290  PUT_AUDIO_SAMPLE(tdd_getcarrier(&cr, &ci, 1));
291  scont += 1.0;
292  }
293  return bytes;
294 }
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 296 of file tdd.c.

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

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

Definition at line 94 of file tdd.c.

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 }
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, fsk_data::bw, fsk_data::f_mark_idx, fsk_data::f_space_idx, fsk_data::hdlc, fsk_data::instop, fsk_data::nbit, fsk_data::nstop, fsk_data::parity, fsk_data::pcola, fsk_data::pllispb, and fsk_data::spb.

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 }
float nstop
int instop
Definition: fskmodem_int.h:46
int pllispb
Definition: fskmodem_int.h:59
Definition: tdd.c:47
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
int f_space_idx
int f_mark_idx