comparison spandsp-0.0.6pre17/src/v22bis_tx.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 * 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 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: v22bis_tx.c,v 1.64 2009/11/04 15:52:06 steveu Exp $
26 */
27
28 /*! \file */
29
30 /* THIS IS A WORK IN PROGRESS - It is basically functional, but it is not feature
31 complete, and doesn't reliably sync over the signal and noise level ranges it should! */
32
33 #if defined(HAVE_CONFIG_H)
34 #include "config.h"
35 #endif
36
37 #include <stdio.h>
38 #include <inttypes.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #if defined(HAVE_TGMATH_H)
42 #include <tgmath.h>
43 #endif
44 #if defined(HAVE_MATH_H)
45 #include <math.h>
46 #endif
47 #include "floating_fudge.h"
48
49 #include "spandsp/telephony.h"
50 #include "spandsp/fast_convert.h"
51 #include "spandsp/logging.h"
52 #include "spandsp/complex.h"
53 #include "spandsp/vector_float.h"
54 #include "spandsp/complex_vector_float.h"
55 #include "spandsp/async.h"
56 #include "spandsp/dds.h"
57 #include "spandsp/power_meter.h"
58
59 #include "spandsp/v29rx.h"
60 #include "spandsp/v22bis.h"
61
62 #include "spandsp/private/logging.h"
63 #include "spandsp/private/v22bis.h"
64
65 #if defined(SPANDSP_USE_FIXED_POINTx)
66 #include "v22bis_tx_fixed_rrc.h"
67 #else
68 #include "v22bis_tx_floating_rrc.h"
69 #endif
70
71 /* Quoting from the V.22bis spec.
72
73 6.3.1.1 Interworking at 2400 bit/s
74
75 6.3.1.1.1 Calling modem
76
77 a) On connection to line the calling modem shall be conditioned to receive signals
78 in the high channel at 1200 bit/s and transmit signals in the low channel at 1200 bit/s
79 in accordance with section 2.5.2.2. It shall apply an ON condition to circuit 107 in accordance
80 with Recommendation V.25. The modem shall initially remain silent.
81
82 b) After 155 +-10 ms of unscrambled binary 1 has been detected, the modem shall remain silent
83 for a further 456 +-10 ms then transmit an unscrambled repetitive double dibit pattern of 00
84 and 11 at 1200 bit/s for 100 +-3 ms. Following this signal the modem shall transmit scrambled
85 binary 1 at 1200 bit/s.
86
87 c) If the modem detects scrambled binary 1 in the high channel at 1200 bit/s for 270 +-40 ms,
88 the handshake shall continue in accordance with section 6.3.1.2.1 c) and d). However, if unscrambled
89 repetitive double dibit 00 and 11 at 1200 bit/s is detected in the high channel, then at the
90 end of receipt of this signal the modem shall apply an ON condition to circuit 112.
91
92 d) 600 +-10 ms after circuit 112 has been turned ON the modem shall begin transmitting scrambled
93 binary 1 at 2400 bit/s, and 450 +-10 ms after circuit 112 has been turned ON the receiver may
94 begin making 16-way decisions.
95
96 e) Following transmission of scrambled binary 1 at 2400 bit/s for 200 +-10 ms, circuit 106 shall
97 be conditioned to respond to circuit 105 and the modem shall be ready to transmit data at
98 2400 bit/s.
99
100 f) When 32 consecutive bits of scrambled binary 1 at 2400 bit/s have been detected in the high
101 channel the modem shall be ready to receive data at 2400 bit/s and shall apply an ON condition
102 to circuit 109.
103
104 6.3.1.1.2 Answering modem
105
106 a) On connection to line the answering modem shall be conditioned to transmit signals in the high
107 channel at 1200 bit/s in accordance with section 2.5.2.2 and receive signals in the low channel at
108 1200 bit/s. Following transmission of the answer sequence in accordance with Recommendation
109 V.25, the modem shall apply an ON condition to circuit 107 and then transmit unscrambled
110 binary 1 at 1200 bit/s.
111
112 b) If the modem detects scrambled binary 1 or 0 in the low channel at 1200 bit/s for 270 +-40 ms,
113 the handshake shall continue in accordance with section 6.3.1.2.2 b) and c). However, if unscrambled
114 repetitive double dibit 00 and 11 at 1200 bit/s is detected in the low channel, at the end of
115 receipt of this signal the modem shall apply an ON condition to circuit 112 and then transmit
116 an unscrambled repetitive double dibit pattern of 00 and 11 at 1200 bit/s for 100 +-3 ms.
117 Following these signals the modem shall transmit scrambled binary 1 at 1200 bit/s.
118
119 c) 600 +-10 ms after circuit 112 has been turned ON the modem shall begin transmitting scrambled
120 binary 1 at 2400 bit/s, and 450 +-10 ms after circuit 112 has been turned ON the receiver may
121 begin making 16-way decisions.
122
123 d) Following transmission of scrambled binary 1 at 2400 bit/s for 200 +-10 ms, circuit 106 shall
124 be conditioned to respond to circuit 105 and the modem shall be ready to transmit data at
125 2400 bit/s.
126
127 e) When 32 consecutive bits of scrambled binary 1 at 2400 bit/s have been detected in the low
128 channel the modem shall be ready to receive data at 2400 bit/s and shall apply an ON
129 condition to circuit 109.
130
131 6.3.1.2 Interworking at 1200 bit/s
132
133 The following handshake is identical to the Recommendation V.22 alternative A and B handshake.
134
135 6.3.1.2.1 Calling modem
136
137 a) On connection to line the calling modem shall be conditioned to receive signals in the high
138 channel at 1200 bit/s and transmit signals in the low channel at 1200 bit/s in accordance
139 with section 2.5.2.2. It shall apply an ON condition to circuit 107 in accordance with
140 Recommendation V.25. The modem shall initially remain silent.
141
142 b) After 155 +-10 ms of unscrambled binary 1 has been detected, the modem shall remain silent
143 for a further 456 +-10 ms then transmit scrambled binary 1 at 1200 bit/s (a preceding V.22 bis
144 signal, as shown in Figure 7/V.22 bis, would not affect the operation of a V.22 answer modem).
145
146 c) On detection of scrambled binary 1 in the high channel at 1200 bit/s for 270 +-40 ms the modem
147 shall be ready to receive data at 1200 bit/s and shall apply an ON condition to circuit 109 and
148 an OFF condition to circuit 112.
149
150 d) 765 +-10 ms after circuit 109 has been turned ON, circuit 106 shall be conditioned to respond
151 to circuit 105 and the modem shall be ready to transmit data at 1200 bit/s.
152
153 6.3.1.2.2 Answering modem
154
155 a) On connection to line the answering modem shall be conditioned to transmit signals in the high
156 channel at 1200 bit/s in accordance with section 2.5.2.2 and receive signals in the low channel at
157 1200 bit/s.
158
159 Following transmission of the answer sequence in accordance with V.25 the modem shall apply
160 an ON condition to circuit 107 and then transmit unscrambled binary 1 at 1200 bit/s.
161
162 b) On detection of scrambled binary 1 or 0 in the low channel at 1200 bit/s for 270 +-40 ms the
163 modem shall apply an OFF condition to circuit 112 and shall then transmit scrambled binary 1
164 at 1200 bit/s.
165
166 c) After scrambled binary 1 has been transmitted at 1200 bit/s for 765 +-10 ms the modem shall be
167 ready to transmit and receive data at 1200 bit/s, shall condition circuit 106 to respond to
168 circuit 105 and shall apply an ON condition to circuit 109.
169
170 Note - Manufacturers may wish to note that in certain countries, for national purposes, modems are
171 in service which emit an answering tone of 2225 Hz instead of unscrambled binary 1.
172
173
174 V.22bis to V.22bis
175 ------------------
176 Calling party
177 S1 scrambled 1's scrambled 1's data
178 at 1200bps at 2400bps
179 |---------------------------------------------------------|XXXXXXXX|XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|XXXXXXXXXXXXXX|XXXXXXXXXXXXX
180 |<155+-10>|<456+-10>|<100+-3>| |<------600+-10------>|<---200+-10-->|
181 ^ | ^<----450+-100---->|[16 way decisions begin]
182 | | |
183 | v |
184 | |<------450+-100----->|[16 way decisions begin]
185 | |<----------600+-10-------->|
186 |<2150+-350>|<--3300+-700->|<75+-20>| |<100+-3>| |<---200+-10-->
187 |-----------|XXXXXXXXXXXXXX|--------|XXXXXXXXXXXXXXXXXXXXXXXXXXXX|XXXXXXXX|XXXXXXXXXXXXXXXXXX|XXXXXXXXXXXXXX|XXXXXXXXXXXXX
188 silence 2100Hz unscrambled 1's S1 scrambled 1's scrambled 1's data
189 at 1200bps at 1200bps at 2400bps
190 Answering party
191
192 S1 = Unscrambled double dibit 00 and 11 at 1200bps
193 When the 2400bps section starts, both sides should look for 32 bits of continuous ones, as a test of integrity.
194
195
196
197
198 V.22 to V.22bis
199 ---------------
200 Calling party
201 scrambled 1's data
202 at 1200bps
203 |---------------------------------------------------------|XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|XXXXXXXXXXXXX
204 |<155+-10>|<456+-10>| |<270+-40>|<--------765+-10-------->|
205 ^ | ^
206 | | |
207 | | |
208 | | |
209 | v |
210 |<2150+-350>|<--3300+-700->|<75+-20>| |<270+-40>|<---------765+-10-------->|
211 |-----------|XXXXXXXXXXXXXX|--------|XXXXXXXXXXXXXXXXXXXXXXXXXXXXX|XXXXXXXXXXXXXXXXXXXXXXXXXX|XXXXXXXXXXXXX
212 silence 2100Hz unscrambled 1's scrambled 1's data
213 at 1200bps at 1200bps
214 Answering party
215
216 Both ends should accept unscrambled binary 1 or binary 0 as the preamble.
217
218
219
220
221 V.22bis to V.22
222 ---------------
223 Calling party
224 S1 scrambled 1's data
225 at 1200bps
226 |---------------------------------------------------------|XXXXXXXX|XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|XXXXXXXXXXXXX
227 |<155+-10>|<456+-10>|<100+-3>| |<-270+-40-><------765+-10------>|
228 ^ | ^
229 | | |
230 | v |
231 | |
232 | |
233 |<2150+-350>|<--3300+-700->|<75+-20>| |<-270+-40->|<------765+-10----->|
234 |-----------|XXXXXXXXXXXXXX|--------|XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX|XXXXXXXXXXXXXXXXXXXX|XXXXXXXXXXXXX
235 silence 2100Hz unscrambled 1's scrambled 1's data
236 at 1200bps at 1200bps
237 Answering party
238
239 Both ends should accept unscrambled binary 1 or binary 0 as the preamble.
240 */
241
242 #define ms_to_symbols(t) (((t)*600)/1000)
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}, /* 1200bps 00 */
253 { 1.0f, 3.0f},
254 { 3.0f, 3.0f},
255 {-1.0f, 1.0f},
256 {-1.0f, 3.0f}, /* 1200bps 01 */
257 {-3.0f, 1.0f},
258 {-3.0f, 3.0f},
259 {-1.0f, -1.0f},
260 {-3.0f, -1.0f}, /* 1200bps 10 */
261 {-1.0f, -3.0f},
262 {-3.0f, -3.0f},
263 { 1.0f, -1.0f},
264 { 1.0f, -3.0f}, /* 1200bps 11 */
265 { 3.0f, -1.0f},
266 { 3.0f, -3.0f}
267 };
268
269 static int fake_get_bit(void *user_data)
270 {
271 return 1;
272 }
273 /*- End of function --------------------------------------------------------*/
274
275 static __inline__ int scramble(v22bis_state_t *s, int bit)
276 {
277 int out_bit;
278
279 if (s->tx.scrambler_pattern_count >= 64)
280 {
281 bit ^= 1;
282 s->tx.scrambler_pattern_count = 0;
283 }
284 out_bit = (bit ^ (s->tx.scramble_reg >> 13) ^ (s->tx.scramble_reg >> 16)) & 1;
285 s->tx.scramble_reg = (s->tx.scramble_reg << 1) | out_bit;
286
287 if (out_bit == 1)
288 s->tx.scrambler_pattern_count++;
289 else
290 s->tx.scrambler_pattern_count = 0;
291 return out_bit;
292 }
293 /*- End of function --------------------------------------------------------*/
294
295 static __inline__ int get_scrambled_bit(v22bis_state_t *s)
296 {
297 int bit;
298
299 if ((bit = s->tx.current_get_bit(s->get_bit_user_data)) == SIG_STATUS_END_OF_DATA)
300 {
301 /* Fill out this symbol with ones, and prepare to send
302 the rest of the shutdown sequence. */
303 s->tx.current_get_bit = fake_get_bit;
304 s->tx.shutdown = 1;
305 bit = 1;
306 }
307 return scramble(s, bit);
308 }
309 /*- End of function --------------------------------------------------------*/
310
311 static complexf_t training_get(v22bis_state_t *s)
312 {
313 complexf_t z;
314 int bits;
315
316 /* V.22bis training sequence */
317 switch (s->tx.training)
318 {
319 case V22BIS_TX_TRAINING_STAGE_INITIAL_TIMED_SILENCE:
320 /* The answerer waits 75ms, then sends unscrambled ones */
321 if (++s->tx.training_count >= ms_to_symbols(75))
322 {
323 /* Initial 75ms of silence is over */
324 span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting U11 1200\n");
325 s->tx.training_count = 0;
326 s->tx.training = V22BIS_TX_TRAINING_STAGE_U11;
327 }
328 /* Fall through */
329 case V22BIS_TX_TRAINING_STAGE_INITIAL_SILENCE:
330 /* Silence */
331 s->tx.constellation_state = 0;
332 z = complex_setf(0.0f, 0.0f);
333 break;
334 case V22BIS_TX_TRAINING_STAGE_U11:
335 /* Send continuous unscrambled ones at 1200bps (i.e. 270 degree phase steps). */
336 /* Only the answering modem sends unscrambled ones. It is the first thing exchanged between the modems. */
337 s->tx.constellation_state = (s->tx.constellation_state + phase_steps[3]) & 3;
338 z = v22bis_constellation[(s->tx.constellation_state << 2) | 0x01];
339 break;
340 case V22BIS_TX_TRAINING_STAGE_U0011:
341 /* Continuous unscrambled double dibit 00 11 at 1200bps. This is termed the S1 segment in
342 the V.22bis spec. It is only sent to request or accept 2400bps mode, and lasts 100+-3ms. After this
343 timed burst, we unconditionally change to sending scrambled ones at 1200bps. */
344 s->tx.constellation_state = (s->tx.constellation_state + phase_steps[3*(s->tx.training_count & 1)]) & 3;
345 z = v22bis_constellation[(s->tx.constellation_state << 2) | 0x01];
346 if (++s->tx.training_count >= ms_to_symbols(100))
347 {
348 span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting S11 after U0011\n");
349 if (s->calling_party)
350 {
351 s->tx.training_count = 0;
352 s->tx.training = V22BIS_TX_TRAINING_STAGE_S11;
353 }
354 else
355 {
356 s->tx.training_count = ms_to_symbols(756 - (600 - 100));
357 s->tx.training = V22BIS_TX_TRAINING_STAGE_TIMED_S11;
358 }
359 }
360 break;
361 case V22BIS_TX_TRAINING_STAGE_TIMED_S11:
362 /* A timed period of scrambled ones at 1200bps. */
363 if (++s->tx.training_count >= ms_to_symbols(756))
364 {
365 if (s->negotiated_bit_rate == 2400)
366 {
367 span_log(&s->logging, SPAN_LOG_FLOW, "+++ starting S1111 (C)\n");
368 s->tx.training_count = 0;
369 s->tx.training = V22BIS_TX_TRAINING_STAGE_S1111;
370 }
371 else
372 {
373 span_log(&s->logging, SPAN_LOG_FLOW, "+++ Tx normal operation (1200)\n");
374 s->tx.training_count = 0;
375 s->tx.training = V22BIS_TX_TRAINING_STAGE_NORMAL_OPERATION;
376 v22bis_report_status_change(s, SIG_STATUS_TRAINING_SUCCEEDED);
377 s->tx.current_get_bit = s->get_bit;
378 }
379 }
380 /* Fall through */
381 case V22BIS_TX_TRAINING_STAGE_S11:
382 /* Scrambled ones at 1200bps. */
383 bits = scramble(s, 1);
384 bits = (bits << 1) | scramble(s, 1);
385 s->tx.constellation_state = (s->tx.constellation_state + phase_steps[bits]) & 3;
386 z = v22bis_constellation[(s->tx.constellation_state << 2) | 0x01];
387 break;
388 case V22BIS_TX_TRAINING_STAGE_S1111:
389 /* Scrambled ones at 2400bps. We send a timed 200ms burst, and switch to normal operation at 2400bps */
390 bits = scramble(s, 1);
391 bits = (bits << 1) | scramble(s, 1);
392 s->tx.constellation_state = (s->tx.constellation_state + phase_steps[bits]) & 3;
393 bits = scramble(s, 1);
394 bits = (bits << 1) | scramble(s, 1);
395 z = v22bis_constellation[(s->tx.constellation_state << 2) | bits];
396 if (++s->tx.training_count >= ms_to_symbols(200))
397 {
398 /* We have completed training. Now handle some real work. */
399 span_log(&s->logging, SPAN_LOG_FLOW, "+++ Tx normal operation (2400)\n");
400 s->tx.training_count = 0;
401 s->tx.training = V22BIS_TX_TRAINING_STAGE_NORMAL_OPERATION;
402 v22bis_report_status_change(s, SIG_STATUS_TRAINING_SUCCEEDED);
403 s->tx.current_get_bit = s->get_bit;
404 }
405 break;
406 case V22BIS_TX_TRAINING_STAGE_PARKED:
407 default:
408 z = complex_setf(0.0f, 0.0f);
409 break;
410 }
411 return z;
412 }
413 /*- End of function --------------------------------------------------------*/
414
415 static complexf_t getbaud(v22bis_state_t *s)
416 {
417 int bits;
418
419 if (s->tx.training)
420 {
421 /* Send the training sequence */
422 return training_get(s);
423 }
424
425 /* There is no graceful shutdown procedure defined for V.22bis. Just
426 send some ones, to ensure we get the real data bits through, even
427 with bad ISI. */
428 if (s->tx.shutdown)
429 {
430 if (++s->tx.shutdown > 10)
431 return complex_setf(0.0f, 0.0f);
432 }
433 /* The first two bits define the quadrant */
434 bits = get_scrambled_bit(s);
435 bits = (bits << 1) | get_scrambled_bit(s);
436 s->tx.constellation_state = (s->tx.constellation_state + phase_steps[bits]) & 3;
437 if (s->negotiated_bit_rate == 1200)
438 {
439 bits = 0x01;
440 }
441 else
442 {
443 /* The other two bits define the position within the quadrant */
444 bits = get_scrambled_bit(s);
445 bits = (bits << 1) | get_scrambled_bit(s);
446 }
447 return v22bis_constellation[(s->tx.constellation_state << 2) | bits];
448 }
449 /*- End of function --------------------------------------------------------*/
450
451 SPAN_DECLARE_NONSTD(int) v22bis_tx(v22bis_state_t *s, int16_t amp[], int len)
452 {
453 complexf_t x;
454 complexf_t z;
455 int i;
456 int sample;
457 float famp;
458
459 if (s->tx.shutdown > 10)
460 return 0;
461 for (sample = 0; sample < len; sample++)
462 {
463 if ((s->tx.baud_phase += 3) >= 40)
464 {
465 s->tx.baud_phase -= 40;
466 s->tx.rrc_filter[s->tx.rrc_filter_step] =
467 s->tx.rrc_filter[s->tx.rrc_filter_step + V22BIS_TX_FILTER_STEPS] = getbaud(s);
468 if (++s->tx.rrc_filter_step >= V22BIS_TX_FILTER_STEPS)
469 s->tx.rrc_filter_step = 0;
470 }
471 /* Root raised cosine pulse shaping at baseband */
472 x = complex_setf(0.0f, 0.0f);
473 for (i = 0; i < V22BIS_TX_FILTER_STEPS; i++)
474 {
475 x.re += tx_pulseshaper[39 - s->tx.baud_phase][i]*s->tx.rrc_filter[i + s->tx.rrc_filter_step].re;
476 x.im += tx_pulseshaper[39 - s->tx.baud_phase][i]*s->tx.rrc_filter[i + s->tx.rrc_filter_step].im;
477 }
478 /* Now create and modulate the carrier */
479 z = dds_complexf(&(s->tx.carrier_phase), s->tx.carrier_phase_rate);
480 famp = (x.re*z.re - x.im*z.im)*s->tx.gain;
481 if (s->tx.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))
482 {
483 /* Add the guard tone */
484 famp += dds_modf(&(s->tx.guard_phase), s->tx.guard_phase_rate, s->tx.guard_level, 0);
485 }
486 /* Don't bother saturating. We should never clip. */
487 amp[sample] = (int16_t) lfastrintf(famp);
488 }
489 return sample;
490 }
491 /*- End of function --------------------------------------------------------*/
492
493 SPAN_DECLARE(void) v22bis_tx_power(v22bis_state_t *s, float power)
494 {
495 float l;
496
497 if (s->tx.guard_phase_rate == dds_phase_ratef(550.0f))
498 {
499 l = 1.6f*powf(10.0f, (power - 1.0f - DBM0_MAX_POWER)/20.0f);
500 s->tx.gain = l*32768.0f/(TX_PULSESHAPER_GAIN*3.0f);
501 l = powf(10.0f, (power - 1.0f - 3.0f - DBM0_MAX_POWER)/20.0f);
502 s->tx.guard_level = l*32768.0f;
503 }
504 else if(s->tx.guard_phase_rate == dds_phase_ratef(1800.0f))
505 {
506 l = 1.6f*powf(10.0f, (power - 1.0f - 1.0f - DBM0_MAX_POWER)/20.0f);
507 s->tx.gain = l*32768.0f/(TX_PULSESHAPER_GAIN*3.0f);
508 l = powf(10.0f, (power - 1.0f - 6.0f - DBM0_MAX_POWER)/20.0f);
509 s->tx.guard_level = l*32768.0f;
510 }
511 else
512 {
513 l = 1.6f*powf(10.0f, (power - DBM0_MAX_POWER)/20.0f);
514 s->tx.gain = l*32768.0f/(TX_PULSESHAPER_GAIN*3.0f);
515 s->tx.guard_level = 0;
516 }
517 }
518 /*- End of function --------------------------------------------------------*/
519
520 static int v22bis_tx_restart(v22bis_state_t *s)
521 {
522 cvec_zerof(s->tx.rrc_filter, sizeof(s->tx.rrc_filter)/sizeof(s->tx.rrc_filter[0]));
523 s->tx.rrc_filter_step = 0;
524 s->tx.scramble_reg = 0;
525 s->tx.scrambler_pattern_count = 0;
526 if (s->calling_party)
527 s->tx.training = V22BIS_TX_TRAINING_STAGE_INITIAL_SILENCE;
528 else
529 s->tx.training = V22BIS_TX_TRAINING_STAGE_INITIAL_TIMED_SILENCE;
530 s->tx.training_count = 0;
531 s->tx.carrier_phase = 0;
532 s->tx.guard_phase = 0;
533 s->tx.baud_phase = 0;
534 s->tx.constellation_state = 0;
535 s->tx.current_get_bit = fake_get_bit;
536 s->tx.shutdown = 0;
537 return 0;
538 }
539 /*- End of function --------------------------------------------------------*/
540
541 SPAN_DECLARE(void) v22bis_set_get_bit(v22bis_state_t *s, get_bit_func_t get_bit, void *user_data)
542 {
543 s->get_bit = get_bit;
544 s->get_bit_user_data = user_data;
545 }
546 /*- End of function --------------------------------------------------------*/
547
548 SPAN_DECLARE(void) v22bis_set_put_bit(v22bis_state_t *s, put_bit_func_t put_bit, void *user_data)
549 {
550 s->put_bit = put_bit;
551 s->put_bit_user_data = user_data;
552 }
553 /*- End of function --------------------------------------------------------*/
554
555 SPAN_DECLARE(void) v22bis_set_modem_status_handler(v22bis_state_t *s, modem_tx_status_func_t handler, void *user_data)
556 {
557 s->status_handler = handler;
558 s->status_user_data = user_data;
559 }
560 /*- End of function --------------------------------------------------------*/
561
562 SPAN_DECLARE(logging_state_t *) v22bis_get_logging_state(v22bis_state_t *s)
563 {
564 return &s->logging;
565 }
566 /*- End of function --------------------------------------------------------*/
567
568 SPAN_DECLARE(int) v22bis_restart(v22bis_state_t *s, int bit_rate)
569 {
570 switch (bit_rate)
571 {
572 case 2400:
573 case 1200:
574 break;
575 default:
576 return -1;
577 }
578 s->bit_rate = bit_rate;
579 s->negotiated_bit_rate = 1200;
580 if (v22bis_tx_restart(s))
581 return -1;
582 return v22bis_rx_restart(s);
583 }
584 /*- End of function --------------------------------------------------------*/
585
586 SPAN_DECLARE(int) v22bis_request_retrain(v22bis_state_t *s, int bit_rate)
587 {
588 /* TODO: support bit rate switching */
589 switch (bit_rate)
590 {
591 case 2400:
592 case 1200:
593 break;
594 default:
595 return -1;
596 }
597 /* TODO: support bit rate changes */
598 /* Retrain is only valid when we are normal operation at 2400bps */
599 if (s->rx.training != V22BIS_RX_TRAINING_STAGE_NORMAL_OPERATION
600 ||
601 s->tx.training != V22BIS_TX_TRAINING_STAGE_NORMAL_OPERATION
602 ||
603 s->negotiated_bit_rate != 2400)
604 {
605 return -1;
606 }
607 /* Send things back into the training process at the appropriate point.
608 The far end should detect the S1 signal, and reciprocate. */
609 span_log(&s->logging, SPAN_LOG_FLOW, "+++ Initiating a retrain\n");
610 s->rx.pattern_repeats = 0;
611 s->rx.training_count = 0;
612 s->rx.training = V22BIS_RX_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
613 s->tx.training_count = 0;
614 s->tx.training = V22BIS_TX_TRAINING_STAGE_U0011;
615 v22bis_equalizer_coefficient_reset(s);
616 v22bis_report_status_change(s, SIG_STATUS_MODEM_RETRAIN_OCCURRED);
617 return 0;
618 }
619 /*- End of function --------------------------------------------------------*/
620
621 SPAN_DECLARE(int) v22bis_remote_loopback(v22bis_state_t *s, int enable)
622 {
623 /* TODO: */
624 return -1;
625 }
626 /*- End of function --------------------------------------------------------*/
627
628 SPAN_DECLARE(int) v22bis_current_bit_rate(v22bis_state_t *s)
629 {
630 return s->negotiated_bit_rate;
631 }
632 /*- End of function --------------------------------------------------------*/
633
634 SPAN_DECLARE(v22bis_state_t *) v22bis_init(v22bis_state_t *s,
635 int bit_rate,
636 int guard,
637 int calling_party,
638 get_bit_func_t get_bit,
639 void *get_bit_user_data,
640 put_bit_func_t put_bit,
641 void *put_bit_user_data)
642 {
643 switch (bit_rate)
644 {
645 case 2400:
646 case 1200:
647 break;
648 default:
649 return NULL;
650 }
651 if (s == NULL)
652 {
653 if ((s = (v22bis_state_t *) malloc(sizeof(*s))) == NULL)
654 return NULL;
655 }
656 memset(s, 0, sizeof(*s));
657 span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
658 span_log_set_protocol(&s->logging, "V.22bis");
659 s->bit_rate = bit_rate;
660 s->calling_party = calling_party;
661
662 s->get_bit = get_bit;
663 s->get_bit_user_data = get_bit_user_data;
664 s->put_bit = put_bit;
665 s->put_bit_user_data = put_bit_user_data;
666
667 if (s->calling_party)
668 {
669 s->tx.carrier_phase_rate = dds_phase_ratef(1200.0f);
670 }
671 else
672 {
673 s->tx.carrier_phase_rate = dds_phase_ratef(2400.0f);
674 switch (guard)
675 {
676 case V22BIS_GUARD_TONE_550HZ:
677 s->tx.guard_phase_rate = dds_phase_ratef(550.0f);
678 break;
679 case V22BIS_GUARD_TONE_1800HZ:
680 s->tx.guard_phase_rate = dds_phase_ratef(1800.0f);
681 break;
682 default:
683 s->tx.guard_phase_rate = 0;
684 break;
685 }
686 }
687 v22bis_tx_power(s, -14.0f);
688 v22bis_restart(s, s->bit_rate);
689 return s;
690 }
691 /*- End of function --------------------------------------------------------*/
692
693 SPAN_DECLARE(int) v22bis_release(v22bis_state_t *s)
694 {
695 return 0;
696 }
697 /*- End of function --------------------------------------------------------*/
698
699 SPAN_DECLARE(int) v22bis_free(v22bis_state_t *s)
700 {
701 free(s);
702 return 0;
703 }
704 /*- End of function --------------------------------------------------------*/
705 /*- End of file ------------------------------------------------------------*/

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