Wed Jan 8 2020 09:50:21

Asterisk developer's documentation


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 "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)
#define AST_LIN2MU(a)
Definition: ulaw.h:49

Definition at line 243 of file tdd.c.

Referenced by tdd_gen_holdtone().

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

Definition at line 238 of file tdd.c.

#define PUT_TDD (   byte)

Definition at line 272 of file tdd.c.

Referenced by tdd_generate().

#define PUT_TDD_BAUD (   bit)

Definition at line 255 of file tdd.c.

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

Definition at line 249 of file tdd.c.

#define PUT_TDD_STOP

Definition at line 263 of file tdd.c.

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

Definition at line 63 of file tdd.c.

Referenced by tdd_init().

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

Definition at line 62 of file tdd.c.

Referenced by tdd_init().

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 149 of file tdd.c.

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

Referenced by dahdi_setoption().

150 {
151  int pos = 0;
152  int cnt;
153  while (len) {
154  cnt = len > sizeof(ecdisa) ? sizeof(ecdisa) : len;
155  memcpy(outbuf + pos, ecdisa, cnt);
156  pos += cnt;
157  len -= cnt;
158  }
159  return 0;
160 }
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)
static int tdd_decode_baudot ( struct tdd_state tdd,
unsigned char  data 
)
static

Definition at line 65 of file tdd.c.

References tdd_state::modo.

Referenced by tdd_feed().

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

References ast_log(), AST_MULAW, calloc, free, 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().

163 {
164  int mylen = len;
165  int olen;
166  int b = 'X';
167  int res;
168  int c,x;
169  short *buf = calloc(1, 2 * len + tdd->oldlen);
170  short *obuf = buf;
171  if (!buf) {
172  ast_log(LOG_WARNING, "Out of memory\n");
173  return -1;
174  }
175  memcpy(buf, tdd->oldstuff, tdd->oldlen);
176  mylen += tdd->oldlen / 2;
177  for (x = 0; x < len; x++)
178  buf[x + tdd->oldlen / 2] = AST_MULAW(ubuf[x]);
179  c = res = 0;
180  while (mylen >= 1320) { /* has to have enough to work on */
181  olen = mylen;
182  res = fsk_serial(&tdd->fskd, buf, &mylen, &b);
183  if (mylen < 0) {
184  ast_log(LOG_ERROR, "fsk_serial made mylen < 0 (%d) (olen was %d)\n", mylen, olen);
185  free(obuf);
186  return -1;
187  }
188  buf += (olen - mylen);
189  if (res < 0) {
190  ast_log(LOG_NOTICE, "fsk_serial failed\n");
191  free(obuf);
192  return -1;
193  }
194  if (res == 1) {
195  /* Ignore invalid bytes */
196  if (b > 0x7f)
197  continue;
198  c = tdd_decode_baudot(tdd, b);
199  if ((c < 1) || (c > 126))
200  continue; /* if not valid */
201  break;
202  }
203  }
204  if (mylen) {
205  memcpy(tdd->oldstuff, buf, mylen * 2);
206  tdd->oldlen = mylen * 2;
207  } else
208  tdd->oldlen = 0;
209  free(obuf);
210  if (res) {
211  tdd->mode = 2;
212 /* put it in mode where it
213  reliably puts teleprinter in correct shift mode */
214  return(c);
215  }
216  return 0;
217 }
int oldlen
Definition: tdd.c:52
#define LOG_WARNING
Definition: logger.h:144
#define calloc(a, b)
Definition: astmm.h:79
#define AST_MULAW(a)
Definition: ulaw.h:85
#define LOG_ERROR
Definition: logger.h:155
#define free(a)
Definition: astmm.h:94
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
static int tdd_decode_baudot(struct tdd_state *tdd, unsigned char data)
Definition: tdd.c:65
short oldstuff[4096]
Definition: tdd.c:51
fsk_data fskd
Definition: tdd.c:49
int mode
Definition: tdd.c:55
int fsk_serial(fsk_data *fskd, short *buffer, int *len, int *outbyte)
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 219 of file tdd.c.

References free.

Referenced by dahdi_setoption().

220 {
221  free(tdd);
222 }
#define free(a)
Definition: astmm.h:94
int tdd_gen_holdtone ( unsigned char *  buf)

Generate TDD hold tone

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

Definition at line 286 of file tdd.c.

References PUT_AUDIO_SAMPLE, and tdd_getcarrier().

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:243
static float tddsb
Definition: tdd.c:60
static float tdd_getcarrier(float *cr, float *ci, int bit)
Definition: tdd.c:224
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 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:56
const char * str
Definition: app_jack.c:144
#define PUT_TDD(byte)
Definition: tdd.c:272
int mode
Definition: tdd.c:55
static float tdd_getcarrier ( float *  cr,
float *  ci,
int  bit 
)
inlinestatic

Definition at line 224 of file tdd.c.

Referenced by tdd_gen_holdtone().

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

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

Definition at line 95 of file tdd.c.

References cos, M_PI, TDD_MARK, and TDD_SPACE.

Referenced by main().

96 {
97  /* Initialize stuff for inverse FFT */
98  dr[0] = cos(TDD_SPACE * 2.0 * M_PI / 8000.0);
99  di[0] = sin(TDD_SPACE * 2.0 * M_PI / 8000.0);
100  dr[1] = cos(TDD_MARK * 2.0 * M_PI / 8000.0);
101  di[1] = sin(TDD_MARK * 2.0 * M_PI / 8000.0);
102 }
static float dr[4]
Definition: tdd.c:59
#define M_PI
#define TDD_SPACE
Definition: tdd.c:62
static float di[4]
Definition: tdd.c:59
static unsigned int cos
Definition: chan_h323.c:147
#define TDD_MARK
Definition: tdd.c:63
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 104 of file tdd.c.

References ast_log(), fsk_data::bw, calloc, 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().

105 {
106  struct tdd_state *tdd;
107  tdd = calloc(1, sizeof(*tdd));
108  if (tdd) {
109 #ifdef INTEGER_CALLERID
110  tdd->fskd.ispb = 176; /* 45.5 baud */
111  /* Set up for 45.5 / 8000 freq *32 to allow ints */
112  tdd->fskd.pllispb = (int)((8000 * 32 * 2) / 90);
113  tdd->fskd.pllids = tdd->fskd.pllispb / 32;
114  tdd->fskd.pllispb2 = tdd->fskd.pllispb / 2;
115  tdd->fskd.hdlc = 0; /* Async */
116  tdd->fskd.nbit = 5; /* 5 bits */
117  tdd->fskd.instop = 1; /* integer rep of 1.5 stop bits */
118  tdd->fskd.parity = 0; /* No parity */
119  tdd->fskd.bw=0; /* Filter 75 Hz */
120  tdd->fskd.f_mark_idx = 0; /* 1400 Hz */
121  tdd->fskd.f_space_idx = 1; /* 1800 Hz */
122  tdd->fskd.xi0 = 0;
123  tdd->fskd.state = 0;
124  tdd->pos = 0;
125  tdd->mode = 0;
126  fskmodem_init(&tdd->fskd);
127 #else
128  tdd->fskd.spb = 176; /* 45.5 baud */
129  tdd->fskd.hdlc = 0; /* Async */
130  tdd->fskd.nbit = 5; /* 5 bits */
131  tdd->fskd.nstop = 1.5; /* 1.5 stop bits */
132  tdd->fskd.parity = 0; /* No parity */
133  tdd->fskd.bw=0; /* Filter 75 Hz */
134  tdd->fskd.f_mark_idx = 0; /* 1400 Hz */
135  tdd->fskd.f_space_idx = 1; /* 1800 Hz */
136  tdd->fskd.pcola = 0; /* No clue */
137  tdd->fskd.cont = 0; /* Digital PLL reset */
138  tdd->fskd.x0 = 0.0;
139  tdd->fskd.state = 0;
140  tdd->pos = 0;
141  tdd->mode = 2;
142 #endif
143  tdd->charnum = 0;
144  } else
145  ast_log(LOG_WARNING, "Out of memory\n");
146  return tdd;
147 }
int charnum
Definition: tdd.c:56
#define LOG_WARNING
Definition: logger.h:144
int pllids
Definition: fskmodem_int.h:60
int fskmodem_init(fsk_data *fskd)
Definition: fskmodem_int.c:197
#define calloc(a, b)
Definition: astmm.h:79
float cont
float nstop
int instop
Definition: fskmodem_int.h:46
int pllispb
Definition: fskmodem_int.h:59
int pllispb2
Definition: fskmodem_int.h:61
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
Definition: tdd.c:48
int f_space_idx
fsk_data fskd
Definition: tdd.c:49
int mode
Definition: tdd.c:55
int f_mark_idx
int pos
Definition: tdd.c:53

Variable Documentation

float di[4]
static
float dr[4]
static

Definition at line 59 of file tdd.c.

Referenced by append_transaction(), and dundi_prop_precache().

float tddsb = 176.0
static

Definition at line 60 of file tdd.c.