comparison spandsp-0.0.3/spandsp-0.0.3/src/v22bis_tx.c @ 5:f762bf195c4b

import spandsp-0.0.3
author Peter Meerwald <pmeerw@cosy.sbg.ac.at>
date Fri, 25 Jun 2010 16:00:21 +0200
parents
children
comparison
equal deleted inserted replaced
4:26cd8f1ef0b1 5:f762bf195c4b
1 /*
2 * SpanDSP - a series of DSP components for telephony
3 *
4 * v22bis_tx.c - ITU V.22bis modem transmit part
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2004 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 General Public License version 2, as
14 * 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 General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 * $Id: v22bis_tx.c,v 1.34 2006/11/28 16:59:57 steveu Exp $
26 */
27
28 /*! \file */
29
30 /* THIS IS A WORK IN PROGRESS - NOT YET FUNCTIONAL! */
31
32 #ifdef HAVE_CONFIG_H
33 #include <config.h>
34 #endif
35
36 #include <stdio.h>
37 #include <inttypes.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #if defined(HAVE_TGMATH_H)
41 #include <tgmath.h>
42 #endif
43 #if defined(HAVE_MATH_H)
44 #include <math.h>
45 #endif
46
47 #include "spandsp/telephony.h"
48 #include "spandsp/logging.h"
49 #include "spandsp/complex.h"
50 #include "spandsp/vector_float.h"
51 #include "spandsp/complex_vector_float.h"
52 #include "spandsp/async.h"
53 #include "spandsp/dds.h"
54 #include "spandsp/power_meter.h"
55
56 #include "spandsp/v29rx.h"
57 #include "spandsp/v22bis.h"
58
59 /* Quoting from the V.22bis spec.
60
61 6.3.1.1 Interworking at 2400 bit/s
62
63 6.3.1.1.1 Calling modem
64
65 a) On connection to line the calling modem shall be conditioned to receive signals
66 in the high channel at 1200 bit/s and transmit signals in the low channel at 1200 bit/s
67 in accordance with section 2.5.2.2. It shall apply an ON condition to circuit 107 in accordance
68 with Recommendation V.25. The modem shall initially remain silent.
69
70 b) After 155 +-10 ms of unscrambled binary 1 has been detected, the modem shall remain silent
71 for a further 456 +-10 ms then transmit an unscrambled repetitive double dibit pattern of 00
72 and 11 at 1200 bit/s for 100 +-3 ms. Following this signal the modem shall transmit scrambled
73 binary 1 at 1200 bit/s.
74
75 c) If the modem detects scrambled binary 1 in the high channel at 1200 bit/s for 270 +-40 ms,
76 the handshake shall continue in accordance with section 6.3.1.2.1 c) and d). However, if unscrambled
77 repetitive double dibit 00 and 11 at 1200 bit/s is detected in the high channel, then at the
78 end of receipt of this signal the modem shall apply an ON condition to circuit 112.
79
80 d) 600 +-10 ms after circuit 112 has been turned ON the modem shall begin transmitting scrambled
81 binary 1 at 2400 bit/s, and 450 +-10 ms after circuit 112 has been turned ON the receiver may
82 begin making 16-way decisions.
83
84 e) Following transmission of scrambled binary 1 at 2400 bit/s for 200 +-10 ms, circuit 106 shall
85 be conditioned to respond to circuit 105 and the modem shall be ready to transmit data at
86 2400 bit/s.
87
88 f) When 32 consecutive bits of scrambled binary 1 at 2400 bit/s have been detected in the high
89 channel the modem shall be ready to receive data at 2400 bit/s and shall apply an ON condition
90 to circuit 109.
91
92 6.3.1.1.2 Answering modem
93
94 a) On connection to line the answering modem shall be conditioned to transmit signals in the high
95 channel at 1200 bit/s in accordance with section 2.5.2.2 and receive signals in the low channel at
96 1200 bit/s. Following transmission of the answer sequence in accordance with Recommendation
97 V.25, the modem shall apply an ON condition to circuit 107 and then transmit unscrambled
98 binary 1 at 1200 bit/s.
99
100 b) If the modem detects scrambled binary 1 or 0 in the low channel at 1200 bit/s for 270 +-40 ms,
101 the handshake shall continue in accordance with section 6.3.1.2.2 b) and c). However, if unscrambled
102 repetitive double dibit 00 and 11 at 1200 bit/s is detected in the low channel, at the end of
103 receipt of this signal the modem shall apply an ON condition to circuit 112 and then transmit
104 an unscrambled repetitive double dibit pattern of 00 and 11 at 1200 bit/s for 100 +-3 ms.
105 Following these signals the modem shall transmit scrambled binary 1 at 1200 bit/s.
106
107 c) 600 +-10 ms after circuit 112 has been turned ON the modem shall begin transmitting scrambled
108 binary 1 at 2400 bit/s, and 450 +-10 ms after circuit 112 has been turned ON the receiver may
109 begin making 16-way decisions.
110
111 d) Following transmission of scrambled binary 1 at 2400 bit/s for 200 +-10 ms, circuit 106 shall
112 be conditioned to respond to circuit 105 and the modem shall be ready to transmit data at
113 2400 bit/s.
114
115 e) When 32 consecutive bits of scrambled binary 1 at 2400 bit/s have been detected in the low
116 channel the modem shall be ready to receive data at 2400 bit/s and shall apply an ON
117 condition to circuit 109.
118
119 6.3.1.2 Interworking at 1200 bit/s
120
121 The following handshake is identical to the Recommendation V.22 alternative A and B handshake.
122
123 6.3.1.2.1 Calling modem
124
125 a) On connection to line the calling modem shall be conditioned to receive signals in the high
126 channel at 1200 bit/s and transmit signals in the low channel at 1200 bit/s in accordance
127 with section 2.5.2.2. It shall apply an ON condition to circuit 107 in accordance with
128 Recommendation V.25. The modem shall initially remain silent.
129
130 b) After 155 +-10 ms of unscrambled binary 1 has been detected, the modem shall remain silent
131 for a further 456 +-10 ms then transmit scrambled binary 1 at 1200 bit/s (a preceding V.22 bis
132 signal, as shown in Figure 7/V.22 bis, would not affect the operation of a V.22 answer modem).
133
134 c) On detection of scrambled binary 1 in the high channel at 1200 bit/s for 270 +-40 ms the modem
135 shall be ready to receive data at 1200 bit/s and shall apply an ON condition to circuit 109 and
136 an OFF condition to circuit 112.
137
138 d) 765 +-10 ms after circuit 109 has been turned ON, circuit 106 shall be conditioned to respond
139 to circuit 105 and the modem shall be ready to transmit data at 1200 bit/s.
140
141 6.3.1.2.2 Answering modem
142
143 a) On connection to line the answering modem shall be conditioned to transmit signals in the high
144 channel at 1200 bit/s in accordance with section 2.5.2.2 and receive signals in the low channel at
145 1200 bit/s.
146
147 Following transmission of the answer sequence in accordance with V.25 the modem shall apply
148 an ON condition to circuit 107 and then transmit unscrambled binary 1 at 1200 bit/s.
149
150 b) On detection of scrambled binary 1 or 0 in the low channel at 1200 bit/s for 270 +-40 ms the
151 modem shall apply an OFF condition to circuit 112 and shall then transmit scrambled binary 1
152 at 1200 bit/s.
153
154 c) After scrambled binary 1 has been transmitted at 1200 bit/s for 765 +-10 ms the modem shall be
155 ready to transmit and receive data at 1200 bit/s, shall condition circuit 106 to respond to
156 circuit 105 and shall apply an ON condition to circuit 109.
157
158 Note - Manufacturers may wish to note that in certain countries, for national purposes, modems are
159 in service which emit an answering tone of 2225 Hz instead of unscrambled binary 1.
160
161
162 V.22bis to V.22bis
163 ------------------
164 Calling party
165 S1 scrambled 1's scrambled 1's data
166 at 1200bps at 2400bps
167 |---------------------------------------------------------|XXXXXXXX|XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|XXXXXXXXXXXXXX|XXXXXXXXXXXXX
168 |<155+-10>|<456+-10>|<100+-3>| |<------600+-10------>|<---200+-10-->|
169 ^ | ^<----450+-100---->|[16 way decisions begin]
170 | | |
171 | v |
172 | |<------450+-100----->|[16 way decisions begin]
173 | |<----------600+-10-------->|
174 |<2150+-350>|<--3300+-700->|<75+-20>| |<100+-3>| |<---200+-10-->
175 |-----------|XXXXXXXXXXXXXX|--------|XXXXXXXXXXXXXXXXXXXXXXXXXXXX|XXXXXXXX|XXXXXXXXXXXXXXXXXX|XXXXXXXXXXXXXX|XXXXXXXXXXXXX
176 silence 2100Hz unscrambled 1's S1 scrambled 1's scrambled 1's data
177 at 1200bps at 1200bps at 2400bps
178 Answering party
179
180 S1 = Unscrambled double dibit 00 and 11 at 1200bps
181 When the 2400bps section starts, both sides should look for 32 bits of continuous ones, as a test of integrity.
182
183
184
185
186 V.22 to V.22bis
187 ---------------
188 Calling party
189 scrambled 1's data
190 at 1200bps
191 |---------------------------------------------------------|XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|XXXXXXXXXXXXX
192 |<155+-10>|<456+-10>| |<270+-40>|<--------765+-10-------->|
193 ^ | ^
194 | | |
195 | | |
196 | | |
197 | v |
198 |<2150+-350>|<--3300+-700->|<75+-20>| |<270+-40>|<---------765+-10-------->|
199 |-----------|XXXXXXXXXXXXXX|--------|XXXXXXXXXXXXXXXXXXXXXXXXXXXXX|XXXXXXXXXXXXXXXXXXXXXXXXXX|XXXXXXXXXXXXX
200 silence 2100Hz unscrambled 1's scrambled 1's data
201 at 1200bps at 1200bps
202 Answering party
203
204 Both ends should accept unscrambled binary 1 or binary 0 as the preamble.
205
206
207
208
209 V.22bis to V.22
210 ---------------
211 Calling party
212 S1 scrambled 1's data
213 at 1200bps
214 |---------------------------------------------------------|XXXXXXXX|XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|XXXXXXXXXXXXX
215 |<155+-10>|<456+-10>|<100+-3>| |<-270+-40-><------765+-10------>|
216 ^ | ^
217 | | |
218 | v |
219 | |
220 | |
221 |<2150+-350>|<--3300+-700->|<75+-20>| |<-270+-40->|<------765+-10----->|
222 |-----------|XXXXXXXXXXXXXX|--------|XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|XXXXXXXXXXXXXXXXXXXX|XXXXXXXXXXXXX
223 silence 2100Hz unscrambled 1's scrambled 1's data
224 at 1200bps at 1200bps
225 Answering party
226
227 Both ends should accept unscrambled binary 1 or binary 0 as the preamble.
228 */
229
230 #define ms_to_symbols(t) (((t)*600)/1000)
231
232 /* Segments of the training sequence */
233 enum
234 {
235 V22BIS_TRAINING_STAGE_NORMAL_OPERATION = 0,
236 V22BIS_TRAINING_STAGE_INITIAL_SILENCE,
237 V22BIS_TRAINING_STAGE_UNSCRAMBLED_ONES,
238 V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011,
239 V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200,
240 V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_2400,
241 V22BIS_TRAINING_STAGE_PARKED
242 };
243
244 static const int phase_steps[4] =
245 {
246 1, 0, 2, 3
247 };
248
249 const complexf_t v22bis_constellation[16] =
250 {
251 { 1.0f, 1.0f},
252 { 3.0f, 1.0f},
253 { 1.0f, 3.0f},
254 { 3.0f, 3.0f},
255 {-1.0f, 1.0f},
256 {-1.0f, 3.0f},
257 {-3.0f, 1.0f},
258 {-3.0f, 3.0f},
259 {-1.0f, -1.0f},
260 {-3.0f, -1.0f},
261 {-1.0f, -3.0f},
262 {-3.0f, -3.0f},
263 { 1.0f, -1.0f},
264 { 1.0f, -3.0f},
265 { 3.0f, -1.0f},
266 { 3.0f, -3.0f}
267 };
268
269 /* Raised root cosine pulse shaping; Beta = 0.75; 4 symbols either
270 side of the centre. */
271 /* Created with mkshape -r 0.0125 0.75 361 -l and then split up */
272 #define PULSESHAPER_GAIN (40.000612087f/40.0f)
273 #define PULSESHAPER_COEFF_SETS 40
274
275 static const float pulseshaper[PULSESHAPER_COEFF_SETS][V22BIS_TX_FILTER_STEPS] =
276 {
277 {
278 -0.0047287346f, /* Filter 0 */
279 -0.0083947197f,
280 -0.0087380763f,
281 0.0088053673f,
282 0.5108981827f,
283 0.5108981827f,
284 0.0088053673f,
285 -0.0087380763f,
286 -0.0083947197f
287 },
288 {
289 -0.0044638629f, /* Filter 1 */
290 -0.0089241700f,
291 -0.0111288952f,
292 0.0023412184f,
293 0.5623914901f,
294 0.4599551720f,
295 0.0144817755f,
296 -0.0063186648f,
297 -0.0077293609f
298 },
299 {
300 -0.0041048584f, /* Filter 2 */
301 -0.0093040596f,
302 -0.0134459768f,
303 -0.0048558766f,
304 0.6141017035f,
305 0.4098822897f,
306 0.0193317049f,
307 -0.0039145680f,
308 -0.0069438567f
309 },
310 {
311 -0.0036565006f, /* Filter 3 */
312 -0.0095231635f,
313 -0.0156437084f,
314 -0.0127148737f,
315 0.6656848457f,
316 0.3609830295f,
317 0.0233320755f,
318 -0.0015677363f,
319 -0.0060557371f
320 },
321 {
322 -0.0031253709f, /* Filter 4 */
323 -0.0095729633f,
324 -0.0176768181f,
325 -0.0211485021f,
326 0.7167894869f,
327 0.3135419896f,
328 0.0264748749f,
329 0.0006824956f,
330 -0.0050839319f
331 },
332 {
333 -0.0025197700f, /* Filter 5 */
334 -0.0094478866f,
335 -0.0195012095f,
336 -0.0300535107f,
337 0.7670600056f,
338 0.2678225635f,
339 0.0287663895f,
340 0.0027999985f,
341 -0.0040483891f
342 },
343 {
344 -0.0018496023f, /* Filter 6 */
345 -0.0091454978f,
346 -0.0210748106f,
347 -0.0393111426f,
348 0.8161399423f,
349 0.2240649005f,
350 0.0302262769f,
351 0.0047523617f,
352 -0.0029696854f
353 },
354 {
355 -0.0011262266f, /* Filter 7 */
356 -0.0086666380f,
357 -0.0223584207f,
358 -0.0487878398f,
359 0.8636754069f,
360 0.1824841563f,
361 0.0308864956f,
362 0.0065113237f,
363 -0.0018686358f
364 },
365 {
366 -0.0003622774f, /* Filter 8 */
367 -0.0080155088f,
368 -0.0233165437f,
369 -0.0583361774f,
370 0.9093185032f,
371 0.1432690480f,
372 0.0307901140f,
373 0.0080531155f,
374 -0.0007659096f
375 },
376 {
377 0.0004285425f, /* Filter 9 */
378 -0.0071996967f,
379 -0.0239181901f,
380 -0.0677960213f,
381 0.9527307304f,
382 0.1065807242f,
383 0.0299900191f,
384 0.0093587151f,
385 0.0003183408f
386 },
387 {
388 0.0012316933f, /* Filter 10 */
389 -0.0062301368f,
390 -0.0241376359f,
391 -0.0769959031f,
392 0.9935863233f,
393 0.0725519600f,
394 0.0285475474f,
395 0.0104140102f,
396 0.0013648323f
397 },
398 {
399 0.0020320508f, /* Filter 11 */
400 -0.0051210137f,
401 -0.0239551212f,
402 -0.0857546018f,
403 1.0315754934f,
404 0.0412866769f,
405 0.0265310587f,
406 0.0112098711f,
407 0.0023554782f
408 },
409 {
410 0.0028141763f, /* Filter 12 */
411 -0.0038896008f,
412 -0.0233574765f,
413 -0.0938829156f,
414 1.0664075323f,
415 0.0128597894f,
416 0.0240144782f,
417 0.0117421344f,
418 0.0032736852f
419 },
420 {
421 0.0035625973f, /* Filter 13 */
422 -0.0025560369f,
423 -0.0223386620f,
424 -0.1011856112f,
425 1.0978137424f,
426 -0.0126826277f,
427 0.0210758250f,
428 0.0120115019f,
429 0.0041046165f
430 },
431 {
432 0.0042620971f, /* Filter 14 */
433 -0.0011430452f,
434 -0.0209002083f,
435 -0.1074635265f,
436 1.1255501596f,
437 -0.0353228594f,
438 0.0177957527f,
439 0.0120233576f,
440 0.0048354157f
441 },
442 {
443 0.0048980053f, /* Filter 15 */
444 0.0003244045f,
445 -0.0190515462f,
446 -0.1125158080f,
447 1.1494000377f,
448 -0.0550707703f,
449 0.0142561191f,
450 0.0117875105f,
451 0.0054553898f
452 },
453 {
454 0.0054564857f, /* Filter 16 */
455 0.0018194852f,
456 -0.0168102168f,
457 -0.1161422557f,
458 1.1691760633f,
459 -0.0719627404f,
460 0.0105386068f,
461 0.0113178688f,
462 0.0059561483f
463 },
464 {
465 0.0059248154f, /* Filter 17 */
466 0.0033139475f,
467 -0.0142019526f,
468 -0.1181457502f,
469 1.1847222770f,
470 -0.0860603350f,
471 0.0067234125f,
472 0.0106320540f,
473 0.0063316975f
474 },
475 {
476 0.0062916504f, /* Filter 18 */
477 0.0047785946f,
478 -0.0112606234f,
479 -0.1183347329f,
480 1.1959156771f,
481 -0.0974487311f,
482 0.0028880206f,
483 0.0097509621f,
484 0.0065784888f
485 },
486 {
487 0.0065472715f, /* Filter 19 */
488 0.0061837898f,
489 -0.0080280420f,
490 -0.1165257094f,
491 1.2026674866f,
492 -0.1062349247f,
493 -0.0008939235f,
494 0.0086982833f,
495 0.0066954225f
496 },
497 {
498 0.0066838062f, /* Filter 20 */
499 0.0074999881f,
500 -0.0045536271f,
501 -0.1125457458f,
502 1.2049240699f,
503 -0.1125457458f,
504 -0.0045536271f,
505 0.0074999881f,
506 0.0066838062f
507 },
508 {
509 0.0066954225f, /* Filter 21 */
510 0.0086982833f,
511 -0.0008939235f,
512 -0.1062349247f,
513 1.2026674866f,
514 -0.1165257094f,
515 -0.0080280420f,
516 0.0061837898f,
517 0.0065472715f
518 },
519 {
520 0.0065784888f, /* Filter 22 */
521 0.0097509621f,
522 0.0028880206f,
523 -0.0974487311f,
524 1.1959156771f,
525 -0.1183347329f,
526 -0.0112606234f,
527 0.0047785946f,
528 0.0062916504f
529 },
530 {
531 0.0063316975f, /* Filter 23 */
532 0.0106320540f,
533 0.0067234125f,
534 -0.0860603350f,
535 1.1847222770f,
536 -0.1181457502f,
537 -0.0142019526f,
538 0.0033139475f,
539 0.0059248154f
540 },
541 {
542 0.0059561483f, /* Filter 24 */
543 0.0113178688f,
544 0.0105386068f,
545 -0.0719627404f,
546 1.1691760633f,
547 -0.1161422557f,
548 -0.0168102168f,
549 0.0018194852f,
550 0.0054564857f
551 },
552 {
553 0.0054553898f, /* Filter 25 */
554 0.0117875105f,
555 0.0142561191f,
556 -0.0550707703f,
557 1.1494000377f,
558 -0.1125158080f,
559 -0.0190515462f,
560 0.0003244045f,
561 0.0048980053f
562 },
563 {
564 0.0048354157f, /* Filter 26 */
565 0.0120233576f,
566 0.0177957527f,
567 -0.0353228594f,
568 1.1255501596f,
569 -0.1074635265f,
570 -0.0209002083f,
571 -0.0011430452f,
572 0.0042620971f
573 },
574 {
575 0.0041046165f, /* Filter 27 */
576 0.0120115019f,
577 0.0210758250f,
578 -0.0126826277f,
579 1.0978137424f,
580 -0.1011856112f,
581 -0.0223386620f,
582 -0.0025560369f,
583 0.0035625973f
584 },
585 {
586 0.0032736852f, /* Filter 28 */
587 0.0117421344f,
588 0.0240144782f,
589 0.0128597894f,
590 1.0664075323f,
591 -0.0938829156f,
592 -0.0233574765f,
593 -0.0038896008f,
594 0.0028141763f
595 },
596 {
597 0.0023554782f, /* Filter 29 */
598 0.0112098711f,
599 0.0265310587f,
600 0.0412866769f,
601 1.0315754934f,
602 -0.0857546018f,
603 -0.0239551212f,
604 -0.0051210137f,
605 0.0020320508f
606 },
607 {
608 0.0013648323f, /* Filter 30 */
609 0.0104140102f,
610 0.0285475474f,
611 0.0725519600f,
612 0.9935863233f,
613 -0.0769959031f,
614 -0.0241376359f,
615 -0.0062301368f,
616 0.0012316933f
617 },
618 {
619 0.0003183408f, /* Filter 31 */
620 0.0093587151f,
621 0.0299900191f,
622 0.1065807242f,
623 0.9527307304f,
624 -0.0677960213f,
625 -0.0239181901f,
626 -0.0071996967f,
627 0.0004285425f
628 },
629 {
630 -0.0007659096f, /* Filter 32 */
631 0.0080531155f,
632 0.0307901140f,
633 0.1432690480f,
634 0.9093185032f,
635 -0.0583361774f,
636 -0.0233165437f,
637 -0.0080155088f,
638 -0.0003622774f
639 },
640 {
641 -0.0018686358f, /* Filter 33 */
642 0.0065113237f,
643 0.0308864956f,
644 0.1824841563f,
645 0.8636754069f,
646 -0.0487878398f,
647 -0.0223584207f,
648 -0.0086666380f,
649 -0.0011262266f
650 },
651 {
652 -0.0029696854f, /* Filter 34 */
653 0.0047523617f,
654 0.0302262769f,
655 0.2240649005f,
656 0.8161399423f,
657 -0.0393111426f,
658 -0.0210748106f,
659 -0.0091454978f,
660 -0.0018496023f
661 },
662 {
663 -0.0040483891f, /* Filter 35 */
664 0.0027999985f,
665 0.0287663895f,
666 0.2678225635f,
667 0.7670600056f,
668 -0.0300535107f,
669 -0.0195012095f,
670 -0.0094478866f,
671 -0.0025197700f
672 },
673 {
674 -0.0050839319f, /* Filter 36 */
675 0.0006824956f,
676 0.0264748749f,
677 0.3135419896f,
678 0.7167894869f,
679 -0.0211485021f,
680 -0.0176768181f,
681 -0.0095729633f,
682 -0.0031253709f
683 },
684 {
685 -0.0060557371f, /* Filter 37 */
686 -0.0015677363f,
687 0.0233320755f,
688 0.3609830295f,
689 0.6656848457f,
690 -0.0127148737f,
691 -0.0156437084f,
692 -0.0095231635f,
693 -0.0036565006f
694 },
695 {
696 -0.0069438567f, /* Filter 38 */
697 -0.0039145680f,
698 0.0193317049f,
699 0.4098822897f,
700 0.6141017035f,
701 -0.0048558766f,
702 -0.0134459768f,
703 -0.0093040596f,
704 -0.0041048584f
705 },
706 {
707 -0.0077293609f, /* Filter 39 */
708 -0.0063186648f,
709 0.0144817755f,
710 0.4599551720f,
711 0.5623914901f,
712 0.0023412184f,
713 -0.0111288952f,
714 -0.0089241700f,
715 -0.0044638629f
716 },
717 };
718
719 static int fake_get_bit(void *user_data)
720 {
721 return 1;
722 }
723 /*- End of function --------------------------------------------------------*/
724
725 static __inline__ int scramble(v22bis_state_t *s, int bit)
726 {
727 int out_bit;
728
729 out_bit = (bit ^ (s->tx_scramble_reg >> 14) ^ (s->tx_scramble_reg >> 17)) & 1;
730 if (s->tx_scrambler_pattern_count >= 64)
731 {
732 out_bit ^= 1;
733 s->tx_scrambler_pattern_count = 0;
734 }
735 if (out_bit == 1)
736 s->tx_scrambler_pattern_count++;
737 else
738 s->tx_scrambler_pattern_count = 0;
739 s->tx_scramble_reg = (s->tx_scramble_reg << 1) | out_bit;
740 return out_bit;
741 }
742 /*- End of function --------------------------------------------------------*/
743
744 static __inline__ int get_scrambled_bit(v22bis_state_t *s)
745 {
746 int bit;
747
748 if ((bit = s->current_get_bit(s->user_data)) == PUTBIT_END_OF_DATA)
749 {
750 /* Fill out this symbol with ones, and prepare to send
751 the rest of the shutdown sequence. */
752 s->current_get_bit = fake_get_bit;
753 s->shutdown = 1;
754 bit = 1;
755 }
756 return scramble(s, bit);
757 }
758 /*- End of function --------------------------------------------------------*/
759
760 static complexf_t training_get(v22bis_state_t *s)
761 {
762 complexf_t z;
763 int bits;
764
765 /* V.22bis training sequence */
766 switch (s->tx_training)
767 {
768 case V22BIS_TRAINING_STAGE_INITIAL_SILENCE:
769 /* Segment 1: silence */
770 s->tx_constellation_state = 0;
771 z = complex_setf(0.0f, 0.0f);
772 if (s->caller)
773 {
774 /* The caller just waits for a signal from the far end, which should be unscrambled ones */
775 if (s->detected_unscrambled_ones_or_zeros)
776 {
777 if (s->bit_rate == 2400)
778 {
779 /* Try to establish at 2400bps */
780 span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting unscrambled 0011 at 1200 (S1)\n");
781 s->tx_training = V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011;
782 }
783 else
784 {
785 /* Only try at 1200bps */
786 span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting scrambled ones at 1200 (A)\n");
787 s->tx_training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
788 }
789 s->tx_training_count = 0;
790 }
791 }
792 else
793 {
794 /* The answerer waits 75ms, then sends unscrambled ones */
795 if (++s->tx_training_count >= ms_to_symbols(75))
796 {
797 /* Inital 75ms of silence is over */
798 span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting unscrambled ones at 1200\n");
799 s->tx_training = V22BIS_TRAINING_STAGE_UNSCRAMBLED_ONES;
800 s->tx_training_count = 0;
801 }
802 }
803 break;
804 case V22BIS_TRAINING_STAGE_UNSCRAMBLED_ONES:
805 /* Segment 2: Continuous unscrambled ones at 1200bps (i.e. reversals). */
806 /* Only the answering modem sends unscrambled ones. It is the first thing exchanged between the modems. */
807 s->tx_constellation_state = (s->tx_constellation_state + phase_steps[3]) & 3;
808 z = v22bis_constellation[(s->tx_constellation_state << 2) | 0x01];
809 if (s->bit_rate == 2400 && s->detected_unscrambled_0011_ending)
810 {
811 /* We are allowed to use 2400bps, and the far end is requesting 2400bps. Result: we are going to
812 work at 2400bps */
813 span_log(&s->logging, SPAN_LOG_FLOW, "+++ [2400] starting unscrambled 0011 at 1200 (S1)\n");
814 s->tx_training = V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011;
815 s->tx_training_count = 0;
816 break;
817 }
818 if (s->detected_scrambled_ones_or_zeros_at_1200bps)
819 {
820 /* We are going to work at 1200bps. */
821 span_log(&s->logging, SPAN_LOG_FLOW, "+++ [1200] starting scrambled ones at 1200 (B)\n");
822 s->bit_rate = 1200;
823 s->tx_training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
824 s->tx_training_count = 0;
825 break;
826 }
827 break;
828 case V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011:
829 /* Segment 3: Continuous unscrambled double dibit 00 11 at 1200bps. This is termed the S1 segment in
830 the V.22bis spec. It is only sent to request or accept 2400bps mode, and lasts 100+-3ms. After this
831 timed burst, we unconditionally change to sending scrambled ones at 1200bps. */
832 s->tx_constellation_state = (s->tx_constellation_state + phase_steps[(s->tx_training_count & 1) ? 3 : 0]) & 3;
833 span_log(&s->logging, SPAN_LOG_FLOW, "U0011 Tx 0x%02x\n", s->tx_constellation_state);
834 z = v22bis_constellation[(s->tx_constellation_state << 2) | 0x01];
835 if (++s->tx_training_count >= ms_to_symbols(100))
836 {
837 span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting scrambled ones at 1200 (C)\n");
838 s->tx_training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
839 s->tx_training_count = 0;
840 }
841 break;
842 case V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200:
843 /* Segment 4: Scrambled ones at 1200bps. */
844 bits = scramble(s, 1);
845 bits = (bits << 1) | scramble(s, 1);
846 s->tx_constellation_state = (s->tx_constellation_state + phase_steps[bits]) & 3;
847 z = v22bis_constellation[(s->tx_constellation_state << 2) | 0x01];
848 if (s->caller)
849 {
850 if (s->detected_unscrambled_0011_ending)
851 {
852 /* Continue for a further 600+-10ms */
853 if (++s->tx_training_count >= ms_to_symbols(600))
854 {
855 span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting scrambled ones at 2400 (A)\n");
856 s->tx_training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_2400;
857 s->tx_training_count = 0;
858 }
859 }
860 else if (s->detected_scrambled_ones_or_zeros_at_1200bps)
861 {
862 if (s->bit_rate == 2400)
863 {
864 /* Continue for a further 756+-10ms */
865 if (++s->tx_training_count >= ms_to_symbols(756))
866 {
867 span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting scrambled ones at 2400 (B)\n");
868 s->tx_training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_2400;
869 s->tx_training_count = 0;
870 }
871 }
872 else
873 {
874 span_log(&s->logging, SPAN_LOG_FLOW, "+++ finished\n");
875 s->tx_training = V22BIS_TRAINING_STAGE_NORMAL_OPERATION;
876 s->tx_training_count = 0;
877 s->current_get_bit = s->get_bit;
878 }
879 }
880 }
881 else
882 {
883 if (s->bit_rate == 2400)
884 {
885 if (++s->tx_training_count >= ms_to_symbols(500))
886 {
887 span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting scrambled ones at 2400 (C)\n");
888 s->tx_training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_2400;
889 s->tx_training_count = 0;
890 }
891 }
892 else
893 {
894 if (++s->tx_training_count >= ms_to_symbols(756))
895 {
896 span_log(&s->logging, SPAN_LOG_FLOW, "+++ finished\n");
897 s->tx_training = 0;
898 s->tx_training_count = 0;
899 }
900 }
901 }
902 break;
903 case V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_2400:
904 /* Segment 4: Scrambled ones at 2400bps. */
905 bits = scramble(s, 1);
906 bits = (bits << 1) | scramble(s, 1);
907 s->tx_constellation_state = (s->tx_constellation_state + phase_steps[bits]) & 3;
908 bits = scramble(s, 1);
909 bits = (bits << 1) | scramble(s, 1);
910 z = v22bis_constellation[(s->tx_constellation_state << 2) | 0x01];
911 if (++s->tx_training_count >= ms_to_symbols(200))
912 {
913 /* We have completed training. Now handle some real work. */
914 span_log(&s->logging, SPAN_LOG_FLOW, "+++ finished\n");
915 s->tx_training = 0;
916 s->tx_training_count = 0;
917 s->current_get_bit = s->get_bit;
918 }
919 break;
920 case V22BIS_TRAINING_STAGE_PARKED:
921 default:
922 z = complex_setf(0.0f, 0.0f);
923 break;
924 }
925 return z;
926 }
927 /*- End of function --------------------------------------------------------*/
928
929 static complexf_t getbaud(v22bis_state_t *s)
930 {
931 int bits;
932
933 if (s->tx_training)
934 {
935 /* Send the training sequence */
936 return training_get(s);
937 }
938
939 /* There is no graceful shutdown procedure defined for V.22bis. Just
940 send some ones, to ensure we get the real data bits through, even
941 with bad ISI. */
942 if (s->shutdown)
943 {
944 if (++s->shutdown > 10)
945 return complex_setf(0.0f, 0.0f);
946 }
947 /* The first two bits define the quadrant */
948 bits = get_scrambled_bit(s);
949 bits = (bits << 1) | get_scrambled_bit(s);
950 s->tx_constellation_state = (s->tx_constellation_state + phase_steps[bits]) & 3;
951 if (s->bit_rate == 1200)
952 {
953 bits = 0x01;
954 }
955 else
956 {
957 /* The other two bits define the position within the quadrant */
958 bits = get_scrambled_bit(s);
959 bits = (bits << 1) | get_scrambled_bit(s);
960 }
961 return v22bis_constellation[(s->tx_constellation_state << 2) | bits];
962 }
963 /*- End of function --------------------------------------------------------*/
964
965 int v22bis_tx(v22bis_state_t *s, int16_t amp[], int len)
966 {
967 complexf_t x;
968 complexf_t z;
969 int i;
970 int sample;
971 float famp;
972
973 if (s->shutdown > 10)
974 return 0;
975 for (sample = 0; sample < len; sample++)
976 {
977 if ((s->tx_baud_phase += 3) >= 40)
978 {
979 s->tx_baud_phase -= 40;
980 s->tx_rrc_filter[s->tx_rrc_filter_step] =
981 s->tx_rrc_filter[s->tx_rrc_filter_step + V22BIS_TX_FILTER_STEPS] = getbaud(s);
982 if (++s->tx_rrc_filter_step >= V22BIS_TX_FILTER_STEPS)
983 s->tx_rrc_filter_step = 0;
984 }
985 /* Root raised cosine pulse shaping at baseband */
986 x.re = 0.0f;
987 x.im = 0.0f;
988 for (i = 0; i < V22BIS_TX_FILTER_STEPS; i++)
989 {
990 x.re += pulseshaper[39 - s->tx_baud_phase][i]*s->tx_rrc_filter[i + s->tx_rrc_filter_step].re;
991 x.im += pulseshaper[39 - s->tx_baud_phase][i]*s->tx_rrc_filter[i + s->tx_rrc_filter_step].im;
992 }
993 /* Now create and modulate the carrier */
994 z = dds_complexf(&(s->tx_carrier_phase), s->tx_carrier_phase_rate);
995 famp = (x.re*z.re - x.im*z.im)*s->tx_gain;
996 if (s->guard_phase_rate && (s->tx_rrc_filter[s->tx_rrc_filter_step].re != 0.0f || s->tx_rrc_filter[i + s->tx_rrc_filter_step].im != 0.0f))
997 {
998 /* Add the guard tone */
999 famp += dds_modf(&(s->guard_phase), s->guard_phase_rate, s->guard_level, 0);
1000 }
1001 /* Don't bother saturating. We should never clip. */
1002 amp[sample] = (int16_t) lrintf(famp);
1003 }
1004 return sample;
1005 }
1006 /*- End of function --------------------------------------------------------*/
1007
1008 void v22bis_tx_power(v22bis_state_t *s, float power)
1009 {
1010 float l;
1011
1012 l = 1.6f*powf(10.0f, (power - DBM0_MAX_POWER)/20.0f);
1013 s->tx_gain = l*32768.0f/(PULSESHAPER_GAIN*3.0f);
1014 }
1015 /*- End of function --------------------------------------------------------*/
1016
1017 static int v22bis_tx_restart(v22bis_state_t *s, int bit_rate)
1018 {
1019 s->bit_rate = bit_rate;
1020 cvec_zerof(s->tx_rrc_filter, sizeof(s->tx_rrc_filter)/sizeof(s->tx_rrc_filter[0]));
1021 s->tx_rrc_filter_step = 0;
1022 s->tx_scramble_reg = 0;
1023 s->tx_scrambler_pattern_count = 0;
1024 s->tx_training = V22BIS_TRAINING_STAGE_INITIAL_SILENCE;
1025 s->tx_training_count = 0;
1026 s->tx_carrier_phase = 0;
1027 s->guard_phase = 0;
1028 s->tx_baud_phase = 0;
1029 s->tx_constellation_state = 0;
1030 s->current_get_bit = fake_get_bit;
1031 s->shutdown = 0;
1032 return 0;
1033 }
1034 /*- End of function --------------------------------------------------------*/
1035
1036 void v22bis_set_get_bit(v22bis_state_t *s, get_bit_func_t get_bit, void *user_data)
1037 {
1038 s->get_bit = get_bit;
1039 s->user_data = user_data;
1040 }
1041 /*- End of function --------------------------------------------------------*/
1042
1043 void v22bis_set_put_bit(v22bis_state_t *s, put_bit_func_t put_bit, void *user_data)
1044 {
1045 s->put_bit = put_bit;
1046 s->user_data = user_data;
1047 }
1048 /*- End of function --------------------------------------------------------*/
1049
1050 int v22bis_restart(v22bis_state_t *s, int bit_rate)
1051 {
1052 if (v22bis_tx_restart(s, bit_rate))
1053 return -1;
1054 return v22bis_rx_restart(s, bit_rate);
1055 }
1056 /*- End of function --------------------------------------------------------*/
1057
1058 v22bis_state_t *v22bis_init(v22bis_state_t *s,
1059 int bit_rate,
1060 int guard,
1061 int caller,
1062 get_bit_func_t get_bit,
1063 put_bit_func_t put_bit,
1064 void *user_data)
1065 {
1066 if (s == NULL)
1067 {
1068 if ((s = (v22bis_state_t *) malloc(sizeof(*s))) == NULL)
1069 return NULL;
1070 }
1071 memset(s, 0, sizeof(*s));
1072 s->bit_rate = bit_rate;
1073 s->caller = caller;
1074
1075 s->get_bit = get_bit;
1076 s->put_bit = put_bit;
1077 s->user_data = user_data;
1078
1079 if (s->caller)
1080 {
1081 s->tx_carrier_phase_rate = dds_phase_ratef(1200.0f);
1082 }
1083 else
1084 {
1085 s->tx_carrier_phase_rate = dds_phase_ratef(2400.0f);
1086 if (guard)
1087 {
1088 if (guard == 1)
1089 {
1090 s->guard_phase_rate = dds_phase_ratef(550.0f);
1091 s->guard_level = 1500.0f;
1092 }
1093 else
1094 {
1095 s->guard_phase_rate = dds_phase_ratef(1800.0f);
1096 s->guard_level = 1000.0f;
1097 }
1098 }
1099 }
1100 v22bis_tx_power(s, -10.0f);
1101 span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
1102 span_log_set_protocol(&s->logging, "V.22bis");
1103 v22bis_restart(s, s->bit_rate);
1104 return s;
1105 }
1106 /*- End of function --------------------------------------------------------*/
1107 /*- End of file ------------------------------------------------------------*/

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