Mercurial > hg > audiostuff
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 ------------------------------------------------------------*/ |