comparison spandsp-0.0.6pre17/src/v18.c @ 4:26cd8f1ef0b1

import spandsp-0.0.6pre17
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 15:50:58 +0200
parents
children
comparison
equal deleted inserted replaced
3:c6c5a16ce2f2 4:26cd8f1ef0b1
1 /*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * v18.c - V.18 text telephony for the deaf.
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2004-2009 Steve Underwood
9 *
10 * All rights reserved.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 2.1,
14 * as published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 * $Id: v18.c,v 1.12 2009/11/04 15:52:06 steveu Exp $
26 */
27
28 /*! \file */
29
30 #if defined(HAVE_CONFIG_H)
31 #include "config.h"
32 #endif
33
34 #include <inttypes.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <string.h>
38 #include <memory.h>
39 #if defined(HAVE_TGMATH_H)
40 #include <tgmath.h>
41 #endif
42 #if defined(HAVE_MATH_H)
43 #include <math.h>
44 #endif
45 #include "floating_fudge.h"
46
47 #include "spandsp/telephony.h"
48 #include "spandsp/logging.h"
49 #include "spandsp/queue.h"
50 #include "spandsp/async.h"
51 #include "spandsp/complex.h"
52 #include "spandsp/dds.h"
53 #include "spandsp/tone_detect.h"
54 #include "spandsp/tone_generate.h"
55 #include "spandsp/super_tone_rx.h"
56 #include "spandsp/power_meter.h"
57 #include "spandsp/fsk.h"
58 #include "spandsp/dtmf.h"
59 #include "spandsp/modem_connect_tones.h"
60 #include "spandsp/v8.h"
61 #include "spandsp/v18.h"
62
63 #include "spandsp/private/logging.h"
64 #include "spandsp/private/queue.h"
65 #include "spandsp/private/tone_generate.h"
66 #include "spandsp/private/async.h"
67 #include "spandsp/private/fsk.h"
68 #include "spandsp/private/dtmf.h"
69 #include "spandsp/private/modem_connect_tones.h"
70 #include "spandsp/private/v18.h"
71
72 #include <stdlib.h>
73
74 /*! The baudot code to shift from alpha to digits and symbols */
75 #define BAUDOT_FIGURE_SHIFT 0x1B
76 /*! The baudot code to shift from digits and symbols to alpha */
77 #define BAUDOT_LETTER_SHIFT 0x1F
78
79 struct dtmf_to_ascii_s
80 {
81 const char *dtmf;
82 char ascii;
83 };
84
85 static const struct dtmf_to_ascii_s dtmf_to_ascii[] =
86 {
87 {"###1", 'C'},
88 {"###2", 'F'},
89 {"###3", 'I'},
90 {"###4", 'L'},
91 {"###5", 'O'},
92 {"###6", 'R'},
93 {"###7", 'U'},
94 {"###8", 'X'},
95 {"###9", ';'},
96 {"###0", '!'},
97 {"##*1", 'A'},
98 {"##*2", 'D'},
99 {"##*3", 'G'},
100 {"##*4", 'J'},
101 {"##*5", 'M'},
102 {"##*6", 'P'},
103 {"##*7", 'S'},
104 {"##*8", 'V'},
105 {"##*9", 'Y'},
106 {"##1", 'B'},
107 {"##2", 'E'},
108 {"##3", 'H'},
109 {"##4", 'K'},
110 {"##5", 'N'},
111 {"##6", 'Q'},
112 {"##7", 'T'},
113 {"##8", 'W'},
114 {"##9", 'Z'},
115 {"##0", ' '},
116 #if defined(WIN32)
117 {"#*1", 'X'}, // (Note 1) 111 1011
118 {"#*2", 'X'}, // (Note 1) 111 1100
119 {"#*3", 'X'}, // (Note 1) 111 1101
120 {"#*4", 'X'}, // (Note 1) 101 1011
121 {"#*5", 'X'}, // (Note 1) 101 1100
122 {"#*6", 'X'}, // (Note 1) 101 1101
123 #else
124 {"#*1", 'æ'}, // (Note 1) 111 1011
125 {"#*2", 'ø'}, // (Note 1) 111 1100
126 {"#*3", 'å'}, // (Note 1) 111 1101
127 {"#*4", 'Æ'}, // (Note 1) 101 1011
128 {"#*5", 'Ø'}, // (Note 1) 101 1100
129 {"#*6", 'Å'}, // (Note 1) 101 1101
130 #endif
131 {"#0", '?'},
132 {"#1", 'c'},
133 {"#2", 'f'},
134 {"#3", 'i'},
135 {"#4", 'l'},
136 {"#5", 'o'},
137 {"#6", 'r'},
138 {"#7", 'u'},
139 {"#8", 'x'},
140 {"#9", '.'},
141 {"*#0", '0'},
142 {"*#1", '1'},
143 {"*#2", '2'},
144 {"*#3", '3'},
145 {"*#4", '4'},
146 {"*#5", '5'},
147 {"*#6", '6'},
148 {"*#7", '7'},
149 {"*#8", '8'},
150 {"*#9", '9'},
151 {"**1", '+'},
152 {"**2", '-'},
153 {"**3", '='},
154 {"**4", ':'},
155 {"**5", '%'},
156 {"**6", '('},
157 {"**7", ')'},
158 {"**8", ','},
159 {"**9", '\n'},
160 {"*0", '\b'},
161 {"*1", 'a'},
162 {"*2", 'd'},
163 {"*3", 'g'},
164 {"*4", 'j'},
165 {"*5", 'm'},
166 {"*6", 'p'},
167 {"*7", 's'},
168 {"*8", 'v'},
169 {"*9", 'y'},
170 {"0", ' '},
171 {"1", 'b'},
172 {"2", 'e'},
173 {"3", 'h'},
174 {"4", 'k'},
175 {"5", 'n'},
176 {"6", 'q'},
177 {"7", 't'},
178 {"8", 'w'},
179 {"9", 'z'},
180 {"", '\0'}
181 };
182
183 static const char *ascii_to_dtmf[128] =
184 {
185 "", /* NULL */
186 "", /* SOH */
187 "", /* STX */
188 "", /* ETX */
189 "", /* EOT */
190 "", /* ENQ */
191 "", /* ACK */
192 "", /* BEL */
193 "*0", /* BACK SPACE */
194 "0", /* HT >> SPACE */
195 "**9", /* LF */
196 "**9", /* VT >> LF */
197 "**9", /* FF >> LF */
198 "", /* CR */
199 "", /* SO */
200 "", /* SI */
201 "", /* DLE */
202 "", /* DC1 */
203 "", /* DC2 */
204 "", /* DC3 */
205 "", /* DC4 */
206 "", /* NAK */
207 "", /* SYN */
208 "", /* ETB */
209 "", /* CAN */
210 "", /* EM */
211 "#0", /* SUB >> ? */
212 "", /* ESC */
213 "**9", /* IS4 >> LF */
214 "**9", /* IS3 >> LF */
215 "**9", /* IS2 >> LF */
216 "0", /* IS1 >> SPACE */
217 "0", /* SPACE */
218 "###0", /* ! */
219 "", /* " */
220 "", /* # */
221 "", /* $ */
222 "**5", /* % */
223 "**1", /* & >> + */
224 "", /* ’ */
225 "**6", /* ( */
226 "**7", /* ) */
227 "#9", /* _ >> . */
228 "**1", /* + */
229 "**8", /* , */
230 "**2", /* - */
231 "#9", /* . */
232 "", /* / */
233 "*#0", /* 0 */
234 "*#1", /* 1 */
235 "*#2", /* 2 */
236 "*#3", /* 3 */
237 "*#4", /* 4 */
238 "*#5", /* 5 */
239 "*#6", /* 6 */
240 "*#7", /* 7 */
241 "*#8", /* 8 */
242 "*#9", /* 9 */
243 "**4", /* : */
244 "###9", /* ; */
245 "**6", /* < >> ( */
246 "**3", /* = */
247 "**7", /* > >> ) */
248 "#0", /* ? */
249 "###8", /* @ >> X */
250 "##*1", /* A */
251 "##1", /* B */
252 "###1", /* C */
253 "##*2", /* D */
254 "##2", /* E */
255 "###2", /* F */
256 "##*3", /* G */
257 "##3", /* H */
258 "###3", /* I */
259 "##*4", /* J */
260 "##4", /* K */
261 "###4", /* L */
262 "##*5", /* M */
263 "##5", /* N */
264 "###5", /* O */
265 "##*6", /* P */
266 "##6", /* Q */
267 "###6", /* R */
268 "##*7", /* S */
269 "##7", /* T */
270 "###7", /* U */
271 "##*8", /* V */
272 "##8", /* W */
273 "###8", /* X */
274 "##*9", /* Y */
275 "##9", /* Z */
276 "#*4", /* Æ (National code) */
277 "#*5", /* Ø (National code) */
278 "#*6", /* Å (National code) */
279 "", /* ^ */
280 "0", /* _ >> SPACE */
281 "", /* ’ */
282 "*1", /* a */
283 "1", /* b */
284 "#1", /* c */
285 "*2", /* d */
286 "2", /* e */
287 "#2", /* f */
288 "*3", /* g */
289 "3", /* h */
290 "#3", /* i */
291 "*4", /* j */
292 "4", /* k */
293 "#4", /* l */
294 "*5", /* m */
295 "5", /* n */
296 "#5", /* o */
297 "*6", /* p */
298 "6", /* q */
299 "#6", /* r */
300 "*7", /* s */
301 "7", /* t */
302 "#7", /* u */
303 "*8", /* v */
304 "8", /* w */
305 "#8", /* x */
306 "*9", /* y */
307 "9", /* z */
308 "#*1", /* æ (National code) */
309 "#*2", /* ø (National code) */
310 "#*3", /* å (National code) */
311 "0", /* ~ >> SPACE */
312 "*0" /* DEL >> BACK SPACE */
313 };
314
315 static int cmp(const void *s, const void *t)
316 {
317 const char *ss;
318 struct dtmf_to_ascii_s *tt;
319
320 ss = (const char *) s;
321 tt = (struct dtmf_to_ascii_s *) t;
322 return strncmp(ss, tt->dtmf, strlen(tt->dtmf));
323 }
324
325 SPAN_DECLARE(int) v18_encode_dtmf(v18_state_t *s, char dtmf[], const char msg[])
326 {
327 const char *t;
328 char *u;
329 const char *v;
330
331 t = msg;
332 u = dtmf;
333 while (*t)
334 {
335 v = ascii_to_dtmf[*t & 0x7F];
336 while (*v)
337 *u++ = *v++;
338 t++;
339 }
340 *u = '\0';
341
342 return u - dtmf;
343 }
344 /*- End of function --------------------------------------------------------*/
345
346 SPAN_DECLARE(int) v18_decode_dtmf(v18_state_t *s, char msg[], const char dtmf[])
347 {
348 int entries;
349 const char *t;
350 char *u;
351 struct dtmf_to_ascii_s *ss;
352
353 entries = sizeof(dtmf_to_ascii)/sizeof(dtmf_to_ascii[0]) - 1;
354 t = dtmf;
355 u = msg;
356 while (*t)
357 {
358 ss = bsearch(t, dtmf_to_ascii, entries, sizeof(dtmf_to_ascii[0]), cmp);
359 if (ss)
360 {
361 t += strlen(ss->dtmf);
362 *u++ = ss->ascii;
363 }
364 else
365 {
366 /* Can't match the code. Let's assume this is a code we just don't know, and skip over it */
367 while (*t == '#' || *t == '*')
368 t++;
369 if (*t)
370 t++;
371 }
372 }
373 *u = '\0';
374 return u - msg;
375 }
376 /*- End of function --------------------------------------------------------*/
377
378 SPAN_DECLARE(uint16_t) v18_encode_baudot(v18_state_t *s, uint8_t ch)
379 {
380 static const uint8_t conv[128] =
381 {
382 0xFF, /* NUL */
383 0xFF, /* SOH */
384 0xFF, /* STX */
385 0xFF, /* ETX */
386 0xFF, /* EOT */
387 0xFF, /* ENQ */
388 0xFF, /* ACK */
389 0xFF, /* BEL */
390 0x00, /* BS */
391 0x44, /* HT >> SPACE */
392 0x42, /* LF */
393 0x42, /* VT >> LF */
394 0x42, /* FF >> LF */
395 0x48, /* CR */
396 0xFF, /* SO */
397 0xFF, /* SI */
398 0xFF, /* DLE */
399 0xFF, /* DC1 */
400 0xFF, /* DC2 */
401 0xFF, /* DC3 */
402 0xFF, /* DC4 */
403 0xFF, /* NAK */
404 0xFF, /* SYN */
405 0xFF, /* ETB */
406 0xFF, /* CAN */
407 0xFF, /* EM */
408 0x99, /* SUB >> ? */
409 0xFF, /* ESC */
410 0x42, /* IS4 >> LF */
411 0x42, /* IS3 >> LF */
412 0x42, /* IS2 >> LF */
413 0x44, /* IS1 >> SPACE */
414 0x44, /* */
415 0x8D, /* ! */
416 0x91, /* " */
417 0x89, /* # >> $ */
418 0x89, /* $ */
419 0x9D, /* % >> / */
420 0x9A, /* & >> + */
421 0x8B, /* ' */
422 0x8F, /* ( */
423 0x92, /* ) */
424 0x9C, /* * >> . */
425 0x9A, /* + */
426 0x8C, /* , */
427 0x83, /* - */
428 0x9C, /* . */
429 0x9D, /* / */
430 0x96, /* 0 */
431 0x97, /* 1 */
432 0x93, /* 2 */
433 0x81, /* 3 */
434 0x8A, /* 4 */
435 0x90, /* 5 */
436 0x95, /* 6 */
437 0x87, /* 7 */
438 0x86, /* 8 */
439 0x98, /* 9 */
440 0x8E, /* : */
441 0x9E, /* ; */
442 0x8F, /* < >> )*/
443 0x94, /* = */
444 0x92, /* > >> ( */
445 0x99, /* ? */
446 0x1D, /* @ >> X */
447 0x03, /* A */
448 0x19, /* B */
449 0x0E, /* C */
450 0x09, /* D */
451 0x01, /* E */
452 0x0D, /* F */
453 0x1A, /* G */
454 0x14, /* H */
455 0x06, /* I */
456 0x0B, /* J */
457 0x0F, /* K */
458 0x12, /* L */
459 0x1C, /* M */
460 0x0C, /* N */
461 0x18, /* O */
462 0x16, /* P */
463 0x17, /* Q */
464 0x0A, /* R */
465 0x05, /* S */
466 0x10, /* T */
467 0x07, /* U */
468 0x1E, /* V */
469 0x13, /* W */
470 0x1D, /* X */
471 0x15, /* Y */
472 0x11, /* Z */
473 0x8F, /* [ >> (*/
474 0x9D, /* \ >> / */
475 0x92, /* ] >> ) */
476 0x8B, /* ^ >> ' */
477 0x44, /* _ >> Space */
478 0x8B, /* ` >> ' */
479 0x03, /* a */
480 0x19, /* b */
481 0x0E, /* c */
482 0x09, /* d */
483 0x01, /* e */
484 0x0D, /* f */
485 0x1A, /* g */
486 0x14, /* h */
487 0x06, /* i */
488 0x0B, /* j */
489 0x0F, /* k */
490 0x12, /* l */
491 0x1C, /* m */
492 0x0C, /* n */
493 0x18, /* o */
494 0x16, /* p */
495 0x17, /* q */
496 0x0A, /* r */
497 0x05, /* s */
498 0x10, /* t */
499 0x07, /* u */
500 0x1E, /* v */
501 0x13, /* w */
502 0x1D, /* x */
503 0x15, /* y */
504 0x11, /* z */
505 0x8F, /* { >> ( */
506 0x8D, /* | >> ! */
507 0x92, /* } >> ) */
508 0x44, /* ~ >> Space */
509 0xFF, /* DEL */
510 };
511 uint16_t shift;
512
513 if (ch == 0x7F)
514 {
515 /* DLE is a special character meaning "force a
516 change to the letter character set */
517 shift = BAUDOT_LETTER_SHIFT;
518 return 0;
519 }
520 ch = conv[ch];
521 /* Is it a non-existant code? */
522 if (ch == 0xFF)
523 return 0;
524 /* Is it a code present in both character sets? */
525 if ((ch & 0x40))
526 return 0x8000 | (ch & 0x1F);
527 /* Need to allow for a possible character set change. */
528 if ((ch & 0x80))
529 {
530 if (s->baudot_tx_shift == 1)
531 return ch & 0x1F;
532 s->baudot_tx_shift = 1;
533 shift = BAUDOT_FIGURE_SHIFT;
534 }
535 else
536 {
537 if (s->baudot_tx_shift == 0)
538 return ch & 0x1F;
539 s->baudot_tx_shift = 0;
540 shift = BAUDOT_LETTER_SHIFT;
541 }
542 return 0x8000 | (shift << 5) | (ch & 0x1F);
543 }
544 /*- End of function --------------------------------------------------------*/
545
546 SPAN_DECLARE(uint8_t) v18_decode_baudot(v18_state_t *s, uint8_t ch)
547 {
548 static const uint8_t conv[2][32] =
549 {
550 {"\bE\nA SIU\rDRJNFCKTZLWHYPQOBG^MXV^"},
551 {"\b3\n- -87\r$4',!:(5\")2=6019?+^./;^"}
552 };
553
554 switch (ch)
555 {
556 case BAUDOT_FIGURE_SHIFT:
557 s->baudot_rx_shift = 1;
558 break;
559 case BAUDOT_LETTER_SHIFT:
560 s->baudot_rx_shift = 0;
561 break;
562 default:
563 return conv[s->baudot_rx_shift][ch];
564 }
565 /* return 0 if we did not produce a character */
566 return 0;
567 }
568 /*- End of function --------------------------------------------------------*/
569
570 static void v18_rx_dtmf(void *user_data, const char digits[], int len)
571 {
572 v18_state_t *s;
573
574 s = (v18_state_t *) user_data;
575 }
576 /*- End of function --------------------------------------------------------*/
577
578 static int v18_tdd_get_async_byte(void *user_data)
579 {
580 v18_state_t *s;
581 int ch;
582
583 s = (v18_state_t *) user_data;
584 if ((ch = queue_read_byte(&s->queue.queue)) >= 0)
585 {
586 int space;
587 int cont;
588 space = queue_free_space(&s->queue.queue);
589 cont = queue_contents(&s->queue.queue);
590 return ch;
591 }
592 if (s->tx_signal_on)
593 {
594 /* The FSK should now be switched off. */
595 s->tx_signal_on = FALSE;
596 }
597 return 0x1F;
598 }
599 /*- End of function --------------------------------------------------------*/
600
601 static void v18_tdd_put_async_byte(void *user_data, int byte)
602 {
603 v18_state_t *s;
604 uint8_t octet;
605
606 s = (v18_state_t *) user_data;
607 //printf("Rx byte %x\n", byte);
608 if (byte < 0)
609 {
610 /* Special conditions */
611 span_log(&s->logging, SPAN_LOG_FLOW, "V.18 signal status is %s (%d)\n", signal_status_to_str(byte), byte);
612 switch (byte)
613 {
614 case SIG_STATUS_CARRIER_UP:
615 s->consecutive_ones = 0;
616 s->bit_pos = 0;
617 s->in_progress = 0;
618 s->rx_msg_len = 0;
619 break;
620 case SIG_STATUS_CARRIER_DOWN:
621 if (s->rx_msg_len > 0)
622 {
623 /* Whatever we have to date constitutes the message */
624 s->rx_msg[s->rx_msg_len] = '\0';
625 s->put_msg(s->user_data, s->rx_msg, s->rx_msg_len);
626 s->rx_msg_len = 0;
627 }
628 break;
629 default:
630 span_log(&s->logging, SPAN_LOG_WARNING, "Unexpected special put byte value - %d!\n", byte);
631 break;
632 }
633 return;
634 }
635 if ((octet = v18_decode_baudot(s, (uint8_t) (byte & 0x1F))))
636 s->rx_msg[s->rx_msg_len++] = octet;
637 if (s->rx_msg_len >= 256)
638 {
639 s->rx_msg[s->rx_msg_len] = '\0';
640 s->put_msg(s->user_data, s->rx_msg, s->rx_msg_len);
641 s->rx_msg_len = 0;
642 }
643 }
644 /*- End of function --------------------------------------------------------*/
645
646 SPAN_DECLARE_NONSTD(int) v18_tx(v18_state_t *s, int16_t *amp, int max_len)
647 {
648 int len;
649 int lenx;
650
651 len = tone_gen(&(s->alert_tone_gen), amp, max_len);
652 if (s->tx_signal_on)
653 {
654 switch (s->mode)
655 {
656 case V18_MODE_DTMF:
657 if (len < max_len)
658 len += dtmf_tx(&(s->dtmftx), amp, max_len - len);
659 break;
660 default:
661 if (len < max_len)
662 {
663 if ((lenx = fsk_tx(&(s->fsktx), amp + len, max_len - len)) <= 0)
664 s->tx_signal_on = FALSE;
665 len += lenx;
666 }
667 break;
668 }
669 }
670 return len;
671 }
672 /*- End of function --------------------------------------------------------*/
673
674 SPAN_DECLARE_NONSTD(int) v18_rx(v18_state_t *s, const int16_t amp[], int len)
675 {
676 switch (s->mode)
677 {
678 case V18_MODE_DTMF:
679 /* Apply a message timeout. */
680 s->in_progress -= len;
681 if (s->in_progress <= 0)
682 s->rx_msg_len = 0;
683 dtmf_rx(&(s->dtmfrx), amp, len);
684 break;
685 default:
686 fsk_rx(&(s->fskrx), amp, len);
687 break;
688 }
689 return 0;
690 }
691 /*- End of function --------------------------------------------------------*/
692
693 SPAN_DECLARE(int) v18_put(v18_state_t *s, const char msg[], int len)
694 {
695 char buf[256 + 1];
696 int x;
697 int n;
698 int i;
699
700 /* This returns the number of characters that would not fit in the buffer.
701 The buffer will only be loaded if the whole string of digits will fit,
702 in which case zero is returned. */
703 if (len < 0)
704 {
705 if ((len = strlen(msg)) == 0)
706 return 0;
707 }
708 switch (s->mode)
709 {
710 case V18_MODE_5BIT_45:
711 case V18_MODE_5BIT_50:
712 for (i = 0; i < len; i++)
713 {
714 n = 0;
715 if ((x = v18_encode_baudot(s, msg[i])))
716 {
717 if ((x & 0x3E0))
718 buf[n++] = (uint8_t) ((x >> 5) & 0x1F);
719 buf[n++] = (uint8_t) (x & 0x1F);
720 /* TODO: Deal with out of space condition */
721 if (queue_write(&s->queue.queue, (const uint8_t *) buf, n) < 0)
722 return i;
723 s->tx_signal_on = TRUE;
724 }
725 }
726 return len;
727 case V18_MODE_DTMF:
728 break;
729 }
730 return -1;
731 }
732 /*- End of function --------------------------------------------------------*/
733
734 SPAN_DECLARE(logging_state_t *) v18_get_logging_state(v18_state_t *s)
735 {
736 return &s->logging;
737 }
738 /*- End of function --------------------------------------------------------*/
739
740 SPAN_DECLARE(v18_state_t *) v18_init(v18_state_t *s,
741 int calling_party,
742 int mode,
743 put_msg_func_t put_msg,
744 void *user_data)
745 {
746 if (s == NULL)
747 {
748 if ((s = (v18_state_t *) malloc(sizeof(*s))) == NULL)
749 return NULL;
750 }
751 memset(s, 0, sizeof(*s));
752 s->calling_party = calling_party;
753 s->mode = mode;
754 s->put_msg = put_msg;
755 s->user_data = user_data;
756
757 switch (s->mode)
758 {
759 case V18_MODE_5BIT_45:
760 fsk_tx_init(&(s->fsktx), &preset_fsk_specs[FSK_WEITBRECHT], async_tx_get_bit, &(s->asynctx));
761 async_tx_init(&(s->asynctx), 5, ASYNC_PARITY_NONE, 2, FALSE, v18_tdd_get_async_byte, s);
762 /* Schedule an explicit shift at the start of baudot transmission */
763 s->baudot_tx_shift = 2;
764 /* TDD uses 5 bit data, no parity and 1.5 stop bits. We scan for the first stop bit, and
765 ride over the fraction. */
766 fsk_rx_init(&(s->fskrx), &preset_fsk_specs[FSK_WEITBRECHT], FSK_FRAME_MODE_5N1_FRAMES, v18_tdd_put_async_byte, s);
767 s->baudot_rx_shift = 0;
768 break;
769 case V18_MODE_5BIT_50:
770 fsk_tx_init(&(s->fsktx), &preset_fsk_specs[FSK_WEITBRECHT50], async_tx_get_bit, &(s->asynctx));
771 async_tx_init(&(s->asynctx), 5, ASYNC_PARITY_NONE, 2, FALSE, v18_tdd_get_async_byte, s);
772 /* Schedule an explicit shift at the start of baudot transmission */
773 s->baudot_tx_shift = 2;
774 /* TDD uses 5 bit data, no parity and 1.5 stop bits. We scan for the first stop bit, and
775 ride over the fraction. */
776 fsk_rx_init(&(s->fskrx), &preset_fsk_specs[FSK_WEITBRECHT50], FSK_FRAME_MODE_5N1_FRAMES, v18_tdd_put_async_byte, s);
777 s->baudot_rx_shift = 0;
778 break;
779 case V18_MODE_DTMF:
780 dtmf_tx_init(&(s->dtmftx));
781 dtmf_rx_init(&(s->dtmfrx), v18_rx_dtmf, s);
782 break;
783 case V18_MODE_EDT:
784 break;
785 case V18_MODE_BELL103:
786 break;
787 case V18_MODE_V23VIDEOTEX:
788 break;
789 case V18_MODE_V21TEXTPHONE:
790 break;
791 case V18_MODE_V18TEXTPHONE:
792 break;
793 }
794 queue_init(&s->queue.queue, 128, QUEUE_READ_ATOMIC | QUEUE_WRITE_ATOMIC);
795 return s;
796 }
797 /*- End of function --------------------------------------------------------*/
798
799 SPAN_DECLARE(int) v18_release(v18_state_t *s)
800 {
801 return 0;
802 }
803 /*- End of function --------------------------------------------------------*/
804
805 SPAN_DECLARE(int) v18_free(v18_state_t *s)
806 {
807 free(s);
808 return 0;
809 }
810 /*- End of function --------------------------------------------------------*/
811
812 SPAN_DECLARE(const char *) v18_mode_to_str(int mode)
813 {
814 switch (mode)
815 {
816 case V18_MODE_NONE:
817 return "None";
818 case V18_MODE_5BIT_45:
819 return "Weitbrecht TDD (45.45bps)";
820 case V18_MODE_5BIT_50:
821 return "Weitbrecht TDD (50bps)";
822 case V18_MODE_DTMF:
823 return "DTMF";
824 case V18_MODE_EDT:
825 return "EDT";
826 case V18_MODE_BELL103:
827 return "Bell 103";
828 case V18_MODE_V23VIDEOTEX:
829 return "Videotex";
830 case V18_MODE_V21TEXTPHONE:
831 return "V.21";
832 case V18_MODE_V18TEXTPHONE:
833 return "V.18 text telephone";
834 }
835 return "???";
836 }
837 /*- End of function --------------------------------------------------------*/
838 /*- End of file ------------------------------------------------------------*/

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.