5
|
1 /*
|
|
2 * SpanDSP - a series of DSP components for telephony
|
|
3 *
|
|
4 * v29tx.h - ITU V.29 modem transmit part
|
|
5 *
|
|
6 * Written by Steve Underwood <steveu@coppice.org>
|
|
7 *
|
|
8 * Copyright (C) 2003 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: v29tx.h,v 1.23 2006/10/24 13:22:02 steveu Exp $
|
|
26 */
|
|
27
|
|
28 /*! \file */
|
|
29
|
|
30 #if !defined(_V29TX_H_)
|
|
31 #define _V29TX_H_
|
|
32
|
|
33 /*! \page v29tx_page The V.29 transmitter
|
|
34 \section v29tx_page_sec_1 What does it do?
|
|
35 The V.29 transmitter implements the transmit side of a V.29 modem. This can
|
|
36 operate at data rates of 9600, 7200 and 4800 bits/s. The audio output is a
|
|
37 stream of 16 bit samples, at 8000 samples/second. The transmit and receive side
|
|
38 of V.29 modems operate independantly. V.29 is mostly used for FAX transmission,
|
|
39 where it provides the standard 9600 and 7200 bits/s rates (the 4800 bits/s mode
|
|
40 is not used for FAX).
|
|
41
|
|
42 \section v29tx_page_sec_2 How does it work?
|
|
43 V.29 uses QAM modulation. The standard method of producing a QAM modulated
|
|
44 signal is to use a sampling rate which is a multiple of the baud rate. The raw
|
|
45 signal is then a series of complex pulses, each an integer number of samples
|
|
46 long. These can be shaped, using a suitable complex filter, and multiplied by a
|
|
47 complex carrier signal to produce the final QAM signal for transmission.
|
|
48
|
|
49 The pulse shaping filter is only vaguely defined by the V.29 spec. Some of the
|
|
50 other ITU modem specs. fully define the filter, typically specifying a root
|
|
51 raised cosine filter, with 50% excess bandwidth. This is a pity, since it
|
|
52 increases the variability of the received signal. However, the receiver's
|
|
53 adaptive equalizer will compensate for these differences. The current
|
|
54 design uses a root raised cosine filter with 25% excess bandwidth. Greater
|
|
55 excess bandwidth will not allow the tranmitted signal to meet the spectral
|
|
56 requirements.
|
|
57
|
|
58 The sampling rate for our transmitter is defined by the channel - 8000 per
|
|
59 second. This is not a multiple of the baud rate (i.e. 2400 baud). The baud
|
|
60 interval is actually 10/3 sample periods. Instead of using a symmetric
|
|
61 FIR to pulse shape the signal, a polyphase filter is used. This consists of
|
|
62 10 sets of coefficients, offering zero to 9/10ths of a baud phase shift as well
|
|
63 as root raised cosine filtering. The appropriate coefficient set is chosen for
|
|
64 each signal sample generated.
|
|
65
|
|
66 The carrier is generated using the DDS method. Using two second order resonators,
|
|
67 started in quadrature, might be more efficient, as it would have less impact on
|
|
68 the processor cache than a table lookup approach. However, the DDS approach
|
|
69 suits the receiver better, so the same signal generator is also used for the
|
|
70 transmitter.
|
|
71
|
|
72 The equation defining QAM modulation is:
|
|
73
|
|
74 s(n) = A*cos(2*pi*f*n + phi(n))
|
|
75
|
|
76 where phi(n) is the phase of the information, and A is the amplitude of the information
|
|
77
|
|
78 using the identity
|
|
79
|
|
80 cos(x + y) = cos(x)*cos(y) - sin(x)*sin(y)
|
|
81
|
|
82 we get
|
|
83
|
|
84 s(n) = A {cos(2*pi*f*n)*cos(phi(n)) - sin(2*pi*f*n)*sin(phi(n))}
|
|
85
|
|
86 substituting with the constellation positions
|
|
87
|
|
88 I(n) = A*cos(phi(n))
|
|
89 Q(n) = A*sin(phi(n))
|
|
90
|
|
91 gives
|
|
92
|
|
93 s(n) = I(n)*cos(2*pi*f*n) - Q(n)*sin(2*pi*f*n)
|
|
94
|
|
95 */
|
|
96
|
|
97 #define V29_TX_FILTER_STEPS 9
|
|
98
|
|
99 /*!
|
|
100 V.29 modem transmit side descriptor. This defines the working state for a
|
|
101 single instance of a V.29 modem transmitter.
|
|
102 */
|
|
103 typedef struct
|
|
104 {
|
|
105 /*! \brief The bit rate of the modem. Valid values are 4800, 7200 and 9600. */
|
|
106 int bit_rate;
|
|
107 /*! \brief The callback function used to get the next bit to be transmitted. */
|
|
108 get_bit_func_t get_bit;
|
|
109 /*! \brief A user specified opaque pointer passed to the callback function. */
|
|
110 void *user_data;
|
|
111
|
|
112 /*! \brief Gain required to achieve the specified output power, not allowing
|
|
113 for the size of the current constellation. */
|
|
114 float base_gain;
|
|
115 /*! \brief Gain required to achieve the specified output power, allowing
|
|
116 for the size of the current constellation. */
|
|
117 float gain;
|
|
118
|
|
119 /*! \brief The route raised cosine (RRC) pulse shaping filter buffer. */
|
|
120 complexf_t rrc_filter[2*V29_TX_FILTER_STEPS];
|
|
121 /*! \brief Current offset into the RRC pulse shaping filter buffer. */
|
|
122 int rrc_filter_step;
|
|
123
|
|
124 /*! \brief The register for the data scrambler. */
|
|
125 unsigned int scramble_reg;
|
|
126 /*! \brief The register for the training scrambler. */
|
|
127 uint8_t training_scramble_reg;
|
|
128 /*! \brief TRUE if transmitting the training sequence, or shutting down transmission.
|
|
129 FALSE if transmitting user data. */
|
|
130 int in_training;
|
|
131 /*! \brief A counter used to track progress through sending the training sequence. */
|
|
132 int training_step;
|
|
133 /*! \brief An offset value into the table of training parameters, used to match the
|
|
134 training pattern to the bit rate. */
|
|
135 int training_offset;
|
|
136
|
|
137 /*! \brief The current phase of the carrier (i.e. the DDS parameter). */
|
|
138 uint32_t carrier_phase;
|
|
139 /*! \brief The update rate for the phase of the carrier (i.e. the DDS increment). */
|
|
140 int32_t carrier_phase_rate;
|
|
141 /*! \brief The current fractional phase of the baud timing. */
|
|
142 int baud_phase;
|
|
143 /*! \brief The code number for the current position in the constellation. */
|
|
144 int constellation_state;
|
|
145 /*! \brief The get_bit function in use at any instant. */
|
|
146 get_bit_func_t current_get_bit;
|
|
147 /*! \brief Error and flow logging control */
|
|
148 logging_state_t logging;
|
|
149 } v29_tx_state_t;
|
|
150
|
|
151 #ifdef __cplusplus
|
|
152 extern "C" {
|
|
153 #endif
|
|
154
|
|
155 /*! Adjust a V.29 modem transmit context's power output.
|
|
156 \brief Adjust a V.29 modem transmit context's output power.
|
|
157 \param s The modem context.
|
|
158 \param power The power level, in dBm0 */
|
|
159 void v29_tx_power(v29_tx_state_t *s, float power);
|
|
160
|
|
161 /*! Initialise a V.29 modem transmit context. This must be called before the first
|
|
162 use of the context, to initialise its contents.
|
|
163 \brief Initialise a V.29 modem transmit context.
|
|
164 \param s The modem context.
|
|
165 \param rate The bit rate of the modem. Valid values are 4800, 7200 and 9600.
|
|
166 \param tep TRUE is the optional TEP tone is to be transmitted.
|
|
167 \param get_bit The callback routine used to get the data to be transmitted.
|
|
168 \param user_data An opaque pointer.
|
|
169 \return A pointer to the modem context, or NULL if there was a problem. */
|
|
170 v29_tx_state_t *v29_tx_init(v29_tx_state_t *s, int rate, int tep, get_bit_func_t get_bit, void *user_data);
|
|
171
|
|
172 /*! Reinitialise an existing V.29 modem transmit context, so it may be reused.
|
|
173 \brief Reinitialise an existing V.29 modem transmit context.
|
|
174 \param s The modem context.
|
|
175 \param rate The bit rate of the modem. Valid values are 4800, 7200 and 9600.
|
|
176 \param tep TRUE is the optional TEP tone is to be transmitted.
|
|
177 \return 0 for OK, -1 for bad parameter */
|
|
178 int v29_tx_restart(v29_tx_state_t *s, int rate, int tep);
|
|
179
|
|
180 /*! Release a V.29 modem transmit context.
|
|
181 \brief Release a V.29 modem transmit context.
|
|
182 \param s The modem context.
|
|
183 \return 0 for OK */
|
|
184 int v29_tx_release(v29_tx_state_t *s);
|
|
185
|
|
186 /*! Change the get_bit function associated with a V.29 modem transmit context.
|
|
187 \brief Change the get_bit function associated with a V.29 modem transmit context.
|
|
188 \param s The modem context.
|
|
189 \param get_bit The callback routine used to get the data to be transmitted.
|
|
190 \param user_data An opaque pointer. */
|
|
191 void v29_tx_set_get_bit(v29_tx_state_t *s, get_bit_func_t get_bit, void *user_data);
|
|
192
|
|
193 /*! Generate a block of V.29 modem audio samples.
|
|
194 \brief Generate a block of V.29 modem audio samples.
|
|
195 \param s The modem context.
|
|
196 \param amp The audio sample buffer.
|
|
197 \param len The number of samples to be generated.
|
|
198 \return The number of samples actually generated.
|
|
199 */
|
|
200 int v29_tx(v29_tx_state_t *s, int16_t *amp, int len);
|
|
201
|
|
202 #ifdef __cplusplus
|
|
203 }
|
|
204 #endif
|
|
205
|
|
206 #endif
|
|
207 /*- End of file ------------------------------------------------------------*/
|