Asterisk - The Open Source Telephony Project GIT-master-a358458
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.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

◆ 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.

◆ PUT_BYTE

#define PUT_BYTE (   a)
Value:
do { \
*(buf++) = (a); \
bytes++; \
} while(0)
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.

◆ 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)
static float tdd_getcarrier(float *cr, float *ci, int bit)
Definition: tdd.c:223
#define PUT_AUDIO_SAMPLE(y)
Definition: tdd.c:242

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.

◆ TDD_SPACE

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

Definition at line 61 of file tdd.c.

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.

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)

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

Referenced by dahdi_setoption().

◆ tdd_decode_baudot()

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

Definition at line 64 of file tdd.c.

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}
int modo
Definition: tdd.c:53
static struct test_val d

References d, and tdd_state::modo.

Referenced by tdd_feed().

◆ 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.

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_free(a)
Definition: astmm.h:180
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
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 ...
#define LOG_ERROR
#define LOG_NOTICE
#define LOG_WARNING
int mode
Definition: tdd.c:54
short oldstuff[4096]
Definition: tdd.c:50
int oldlen
Definition: tdd.c:51
fsk_data fskd
Definition: tdd.c:48
static int tdd_decode_baudot(struct tdd_state *tdd, unsigned char data)
Definition: tdd.c:64
static struct test_val b
static struct test_val c
#define AST_MULAW(a)
Definition: ulaw.h:85

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().

◆ 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.

219{
220 ast_free(tdd);
221}

References ast_free.

Referenced by dahdi_setoption().

◆ tdd_gen_holdtone()

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}
static float tddsb
Definition: tdd.c:59

References PUT_AUDIO_SAMPLE, tdd_getcarrier(), and tddsb.

◆ 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 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}
const char * str
Definition: app_jack.c:147
int charnum
Definition: tdd.c:55
#define PUT_TDD(byte)
Definition: tdd.c:271

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

Referenced by dahdi_sendtext().

◆ tdd_getcarrier()

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

Definition at line 223 of file tdd.c.

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

References di, and dr.

Referenced by tdd_gen_holdtone().

◆ 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.

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}
unsigned int cos
Definition: chan_iax2.c:356
#define M_PI
Definition: resample.c:83
#define TDD_SPACE
Definition: tdd.c:61
#define TDD_MARK
Definition: tdd.c:62

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

Referenced by asterisk_daemon().

◆ 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.

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 fskmodem_init(fsk_data *fskd)
Definition: fskmodem_int.c:195
int f_mark_idx
float nstop
int pllispb2
Definition: fskmodem_int.h:61
float cont
int instop
Definition: fskmodem_int.h:46
int pllispb
Definition: fskmodem_int.h:59
int pllids
Definition: fskmodem_int.h:60
int f_space_idx
Definition: tdd.c:47
int pos
Definition: tdd.c:52

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().

Variable Documentation

◆ di

float di[4]
static

◆ dr

float dr[4]
static

◆ tddsb

float tddsb = 176.0
static

Definition at line 59 of file tdd.c.

Referenced by tdd_gen_holdtone().