5
|
1 /*
|
|
2 * SpanDSP - a series of DSP components for telephony
|
|
3 *
|
|
4 * v22bis_rx.c - ITU V.22bis modem receive 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_rx.c,v 1.32 2006/11/19 14:07:26 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 <inttypes.h>
|
|
37 #include <string.h>
|
|
38 #include <stdio.h>
|
|
39 #include <stdlib.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/vector_float.h"
|
|
50 #include "spandsp/async.h"
|
|
51 #include "spandsp/power_meter.h"
|
|
52 #include "spandsp/arctan2.h"
|
|
53 #include "spandsp/complex.h"
|
|
54 #include "spandsp/dds.h"
|
|
55 #include "spandsp/complex_filters.h"
|
|
56
|
|
57 #include "spandsp/v29rx.h"
|
|
58 #include "spandsp/v22bis.h"
|
|
59
|
|
60 #define ms_to_symbols(t) (((t)*600)/1000)
|
|
61
|
|
62 #define EQUALIZER_DELTA 0.25f
|
|
63
|
|
64 /*
|
|
65 The basic method used by the V.22bis receiver is:
|
|
66
|
|
67 Put each sample into the pulse-shaping and phase shift filter buffer
|
|
68
|
|
69 At T/2 rate:
|
|
70 Filter and demodulate the contents of the input filter buffer, producing a sample
|
|
71 in the equalizer filter buffer.
|
|
72
|
|
73 Tune the symbol timing based on the latest 3 samples in the equalizer buffer. This
|
|
74 updates the decision points for taking the T/2 samples.
|
|
75
|
|
76 Equalize the contents of the equalizer buffer, producing a demodulated constellation
|
|
77 point.
|
|
78
|
|
79 Find the nearest constellation point to the received position. This is our received
|
|
80 symbol.
|
|
81
|
|
82 Tune the local carrier, based on the angular mismatch between the actual signal and
|
|
83 the decision.
|
|
84
|
|
85 Tune the equalizer, based on the mismatch between the actual signal and the decision.
|
|
86
|
|
87 Descramble and output the bits represented by the decision.
|
|
88 */
|
|
89
|
|
90 enum
|
|
91 {
|
|
92 V22BIS_TRAINING_STAGE_NORMAL_OPERATION,
|
|
93 V22BIS_TRAINING_STAGE_SYMBOL_ACQUISITION,
|
|
94 V22BIS_TRAINING_STAGE_LOG_PHASE,
|
|
95 V22BIS_TRAINING_STAGE_UNSCRAMBLED_ONES,
|
|
96 V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011,
|
|
97 V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200,
|
|
98 V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_2400,
|
|
99 V22BIS_TRAINING_STAGE_WAIT_FOR_START_1,
|
|
100 V22BIS_TRAINING_STAGE_WAIT_FOR_START_2,
|
|
101 V22BIS_TRAINING_STAGE_PARKED
|
|
102 };
|
|
103
|
|
104 /* Raised root cosine pulse shaping; Beta = 0.75; 4 symbols either
|
|
105 side of the centre. We cannot simplify this by using only half
|
|
106 the filter, as each variant are each skewed by a n/PULSESHAPER_COEFF_SETS of a
|
|
107 sample. Only one is symmetric. */
|
|
108 //#define PULSESHAPER_GAIN 159.37711522f
|
|
109 #define PULSESHAPER_GAIN 39.98830768f
|
|
110 #define PULSESHAPER_COEFF_SETS 12
|
|
111 static const complexf_t pulseshaper_1200[PULSESHAPER_COEFF_SETS][V22BIS_RX_FILTER_STEPS] =
|
|
112 {
|
|
113 {
|
|
114 { 0.0079885982f, -0.0245863758f}, /* Filter 0 */
|
|
115 { 0.0511994623f, -0.0166357141f},
|
|
116 { 0.0660513043f, 0.0479890816f},
|
|
117 {-0.0000000000f, 0.1045738682f},
|
|
118 {-0.0949529186f, 0.0689873323f},
|
|
119 {-0.1091215536f, -0.0354557447f},
|
|
120 {-0.0284108873f, -0.0874397159f},
|
|
121 { 0.0266686007f, -0.0367061794f},
|
|
122 {-0.0269077960f, -0.0000000000f},
|
|
123 {-0.0733404681f, -0.1009444892f},
|
|
124 { 0.0759629756f, -0.2337899953f},
|
|
125 { 0.3664972484f, -0.1190821752f},
|
|
126 { 0.4341508448f, 0.3154290617f},
|
|
127 {-0.0000000001f, 0.6913219094f},
|
|
128 {-0.6796512008f, 0.4937954843f},
|
|
129 {-0.9258067012f, -0.3008128405f},
|
|
130 {-0.3345100582f, -1.0295161009f},
|
|
131 { 0.6816816330f, -0.9382542372f},
|
|
132 { 1.1997879744f, 0.0000000000f},
|
|
133 { 0.7052176595f, 0.9706488252f},
|
|
134 {-0.3583812416f, 1.1029839516f},
|
|
135 {-1.0295161009f, 0.3345100582f},
|
|
136 {-0.7875382304f, -0.5721800327f},
|
|
137 {-0.0000000001f, -0.8400950432f},
|
|
138 { 0.5592911839f, -0.4063488245f},
|
|
139 { 0.5103749037f, 0.1658308655f},
|
|
140 { 0.1190821752f, 0.3664972484f},
|
|
141 {-0.1444901675f, 0.1988736391f},
|
|
142 {-0.1247742549f, 0.0000000000f},
|
|
143 {-0.0158160049f, -0.0217688642f},
|
|
144 {-0.0140205137f, 0.0431507044f},
|
|
145 {-0.0874397159f, 0.0284108873f},
|
|
146 {-0.0928243399f, -0.0674408302f},
|
|
147 {-0.0000000000f, -0.1173682660f},
|
|
148 { 0.0846020356f, -0.0614669770f},
|
|
149 { 0.0776479617f, 0.0252293516f},
|
|
150 { 0.0166357141f, 0.0511994623f},
|
|
151 },
|
|
152 {
|
|
153 { 0.0086805914f, -0.0267161131f}, /* Filter 1 */
|
|
154 { 0.0534664392f, -0.0173722990f},
|
|
155 { 0.0678047314f, 0.0492630191f},
|
|
156 {-0.0000000000f, 0.1061014757f},
|
|
157 {-0.0953093544f, 0.0692462996f},
|
|
158 {-0.1081032082f, -0.0351248607f},
|
|
159 {-0.0275043193f, -0.0846495852f},
|
|
160 { 0.0237129591f, -0.0326380879f},
|
|
161 {-0.0341038331f, -0.0000000000f},
|
|
162 {-0.0787785500f, -0.1084293649f},
|
|
163 { 0.0793628618f, -0.2442537695f},
|
|
164 { 0.3781612813f, -0.1228720471f},
|
|
165 { 0.4445744753f, 0.3230022490f},
|
|
166 {-0.0000000001f, 0.7040774226f},
|
|
167 {-0.6892225146f, 0.5007494688f},
|
|
168 {-0.9354411960f, -0.3039432764f},
|
|
169 {-0.3369024098f, -1.0368790627f},
|
|
170 { 0.6845118403f, -0.9421496987f},
|
|
171 { 1.2013363838f, 0.0000000000f},
|
|
172 { 0.7041431069f, 0.9691697955f},
|
|
173 {-0.3568129838f, 1.0981574059f},
|
|
174 {-1.0219419003f, 0.3320490718f},
|
|
175 {-0.7792053819f, -0.5661258698f},
|
|
176 {-0.0000000001f, -0.8281568289f},
|
|
177 { 0.5489386916f, -0.3988272846f},
|
|
178 { 0.4981442094f, 0.1618568748f},
|
|
179 { 0.1153177992f, 0.3549116850f},
|
|
180 {-0.1380993575f, 0.1900774688f},
|
|
181 {-0.1156847477f, 0.0000000000f},
|
|
182 {-0.0116915042f, -0.0160919763f},
|
|
183 {-0.0155188413f, 0.0477620810f},
|
|
184 {-0.0900719389f, 0.0292661469f},
|
|
185 {-0.0935767666f, -0.0679875016f},
|
|
186 {-0.0000000000f, -0.1168202460f},
|
|
187 { 0.0833092555f, -0.0605277158f},
|
|
188 { 0.0755547658f, 0.0245492328f},
|
|
189 { 0.0158989299f, 0.0489318743f},
|
|
190 },
|
|
191 {
|
|
192 { 0.0093799150f, -0.0288684089f}, /* Filter 2 */
|
|
193 { 0.0557304025f, -0.0181079060f},
|
|
194 { 0.0695286095f, 0.0505154915f},
|
|
195 {-0.0000000000f, 0.1075555831f},
|
|
196 {-0.0955764726f, 0.0694403723f},
|
|
197 {-0.1069486886f, -0.0347497351f},
|
|
198 {-0.0265459362f, -0.0816999897f},
|
|
199 { 0.0206513591f, -0.0284241568f},
|
|
200 {-0.0414781198f, -0.0000000000f},
|
|
201 {-0.0843107775f, -0.1160438284f},
|
|
202 { 0.0828017443f, -0.2548375726f},
|
|
203 { 0.3898994923f, -0.1266860217f},
|
|
204 { 0.4550133944f, 0.3305865824f},
|
|
205 {-0.0000000001f, 0.7167864442f},
|
|
206 {-0.6987025142f, 0.5076370835f},
|
|
207 {-0.9449097514f, -0.3070197999f},
|
|
208 {-0.3392250240f, -1.0440272093f},
|
|
209 { 0.6871879101f, -0.9458330274f},
|
|
210 { 1.2026044130f, 0.0000000000f},
|
|
211 { 0.7029046416f, 0.9674652219f},
|
|
212 {-0.3551651835f, 1.0930860043f},
|
|
213 {-1.0141602755f, 0.3295206726f},
|
|
214 {-0.7707393169f, -0.5599749088f},
|
|
215 {-0.0000000001f, -0.8161166310f},
|
|
216 { 0.5385575294f, -0.3912849724f},
|
|
217 { 0.4859414399f, 0.1578919441f},
|
|
218 { 0.1115802750f, 0.3434087634f},
|
|
219 {-0.1317866892f, 0.1813888103f},
|
|
220 {-0.1067595631f, 0.0000000000f},
|
|
221 {-0.0076726158f, -0.0105604501f},
|
|
222 {-0.0169618148f, 0.0522031002f},
|
|
223 {-0.0925478712f, 0.0300706252f},
|
|
224 {-0.0942174047f, -0.0684529543f},
|
|
225 {-0.0000000000f, -0.1161677912f},
|
|
226 { 0.0819620788f, -0.0595489368f},
|
|
227 { 0.0734324455f, 0.0238596480f},
|
|
228 { 0.0151627110f, 0.0466660261f},
|
|
229 },
|
|
230 {
|
|
231 { 0.0100859674f, -0.0310414154f}, /* Filter 3 */
|
|
232 { 0.0579889156f, -0.0188417397f},
|
|
233 { 0.0712205172f, 0.0517447330f},
|
|
234 {-0.0000000000f, 0.1089330688f},
|
|
235 {-0.0957518741f, 0.0695678070f},
|
|
236 {-0.1056557149f, -0.0343296230f},
|
|
237 {-0.0255352631f, -0.0785894617f},
|
|
238 { 0.0174835511f, -0.0240640435f},
|
|
239 {-0.0490297712f, -0.0000000000f},
|
|
240 {-0.0899358466f, -0.1237860769f},
|
|
241 { 0.0862785354f, -0.2655380368f},
|
|
242 { 0.4017075598f, -0.1305226982f},
|
|
243 { 0.4654633999f, 0.3381789625f},
|
|
244 {-0.0000000001f, 0.7294434309f},
|
|
245 {-0.7080869079f, 0.5144552588f},
|
|
246 {-0.9542079568f, -0.3100409508f},
|
|
247 {-0.3414767087f, -1.0509572029f},
|
|
248 { 0.6897085309f, -0.9493023753f},
|
|
249 { 1.2035913467f, 0.0000000000f},
|
|
250 { 0.7015029192f, 0.9655358791f},
|
|
251 {-0.3534386754f, 1.0877723694f},
|
|
252 {-1.0061750412f, 0.3269260824f},
|
|
253 {-0.7621439099f, -0.5537299514f},
|
|
254 {-0.0000000001f, -0.8039799333f},
|
|
255 { 0.5281522870f, -0.3837251067f},
|
|
256 { 0.4737714827f, 0.1539376825f},
|
|
257 { 0.1078709438f, 0.3319926262f},
|
|
258 {-0.1255540103f, 0.1728102714f},
|
|
259 {-0.0980006009f, 0.0000000000f},
|
|
260 {-0.0037596615f, -0.0051747300f},
|
|
261 {-0.0183496606f, 0.0564744473f},
|
|
262 {-0.0948692262f, 0.0308248810f},
|
|
263 {-0.0947483405f, -0.0688387007f},
|
|
264 {-0.0000000000f, -0.1154139340f},
|
|
265 { 0.0805630460f, -0.0585324802f},
|
|
266 { 0.0712837577f, 0.0231614988f},
|
|
267 { 0.0144278063f, 0.0444042198f},
|
|
268 },
|
|
269 {
|
|
270 { 0.0107981311f, -0.0332332328f}, /* Filter 4 */
|
|
271 { 0.0602394938f, -0.0195729975f},
|
|
272 { 0.0728780255f, 0.0529489815f},
|
|
273 {-0.0000000000f, 0.1102307960f},
|
|
274 {-0.0958332121f, 0.0696269050f},
|
|
275 {-0.1042220443f, -0.0338637941f},
|
|
276 {-0.0244718455f, -0.0753165931f},
|
|
277 { 0.0142093524f, -0.0195574965f},
|
|
278 {-0.0567577891f, -0.0000000000f},
|
|
279 {-0.0956523716f, -0.1316542029f},
|
|
280 { 0.0897921249f, -0.2763517499f},
|
|
281 { 0.4135811031f, -0.1343806386f},
|
|
282 { 0.4759201407f, 0.3457762301f},
|
|
283 {-0.0000000001f, 0.7420427203f},
|
|
284 {-0.7173712850f, 0.5212007165f},
|
|
285 {-0.9633312821f, -0.3130052984f},
|
|
286 {-0.3436563909f, -1.0576655865f},
|
|
287 { 0.6920724511f, -0.9525560141f},
|
|
288 { 1.2042965889f, 0.0000000000f},
|
|
289 { 0.6999385953f, 0.9633828402f},
|
|
290 {-0.3516343236f, 1.0822191238f},
|
|
291 {-0.9979898930f, 0.3242665529f},
|
|
292 {-0.7534233332f, -0.5473940969f},
|
|
293 {-0.0000000001f, -0.7917523384f},
|
|
294 { 0.5177274346f, -0.3761509955f},
|
|
295 { 0.4616391361f, 0.1499956548f},
|
|
296 { 0.1041911170f, 0.3206672966f},
|
|
297 {-0.1194031686f, 0.1643443555f},
|
|
298 {-0.0894096494f, 0.0000000000f},
|
|
299 { 0.0000471013f, 0.0000648294f},
|
|
300 {-0.0196826290f, 0.0605769046f},
|
|
301 {-0.0970377848f, 0.0315294862f},
|
|
302 {-0.0951716974f, -0.0691462904f},
|
|
303 {-0.0000000000f, -0.1145617142f},
|
|
304 { 0.0791146755f, -0.0574801750f},
|
|
305 { 0.0691114515f, 0.0224556718f},
|
|
306 { 0.0136949494f, 0.0421487205f},
|
|
307 },
|
|
308 {
|
|
309 { 0.0115157729f, -0.0354419053f}, /* Filter 5 */
|
|
310 { 0.0624796189f, -0.0203008596f},
|
|
311 { 0.0744986683f, 0.0541264527f},
|
|
312 {-0.0000000000f, 0.1114456356f},
|
|
313 {-0.0958181471f, 0.0696159601f},
|
|
314 {-0.1026455015f, -0.0333515443f},
|
|
315 {-0.0233552568f, -0.0718800873f},
|
|
316 { 0.0108286384f, -0.0149043426f},
|
|
317 {-0.0646610633f, -0.0000000000f},
|
|
318 {-0.1014589071f, -0.1396462023f},
|
|
319 { 0.0933413655f, -0.2872751951f},
|
|
320 { 0.4255155921f, -0.1382583976f},
|
|
321 { 0.4863792956f, 0.3533752263f},
|
|
322 {-0.0000000001f, 0.7545788884f},
|
|
323 {-0.7265513539f, 0.5278704762f},
|
|
324 {-0.9722753763f, -0.3159114122f},
|
|
325 {-0.3457630277f, -1.0641491413f},
|
|
326 { 0.6942784786f, -0.9555923343f},
|
|
327 { 1.2047197819f, 0.0000000000f},
|
|
328 { 0.6982125044f, 0.9610070586f},
|
|
329 {-0.3497529626f, 1.0764288902f},
|
|
330 {-0.9896088243f, 0.3215433955f},
|
|
331 {-0.7445815802f, -0.5409702063f},
|
|
332 {-0.0000000001f, -0.7794392109f},
|
|
333 { 0.5072873235f, -0.3685658276f},
|
|
334 { 0.4495492578f, 0.1460674107f},
|
|
335 { 0.1005420759f, 0.3094367087f},
|
|
336 {-0.1133359149f, 0.1559935063f},
|
|
337 {-0.0809883848f, 0.0000000000f},
|
|
338 { 0.0037474802f, 0.0051579643f},
|
|
339 {-0.0209610034f, 0.0645113364f},
|
|
340 {-0.0990553871f, 0.0321850479f},
|
|
341 {-0.0954896435f, -0.0693772882f},
|
|
342 {-0.0000000000f, -0.1136142015f},
|
|
343 { 0.0776194856f, -0.0563938580f},
|
|
344 { 0.0669182166f, 0.0217430461f},
|
|
345 { 0.0129648596f, 0.0399017334f},
|
|
346 },
|
|
347 {
|
|
348 { 0.0122382389f, -0.0376654267f}, /* Filter 6 */
|
|
349 { 0.0647067279f, -0.0210244898f},
|
|
350 { 0.0760799870f, 0.0552753434f},
|
|
351 {-0.0000000000f, 0.1125744730f},
|
|
352 {-0.0957043841f, 0.0695333034f},
|
|
353 {-0.1009239629f, -0.0327921845f},
|
|
354 {-0.0221851002f, -0.0682787150f},
|
|
355 { 0.0073413476f, -0.0101044979f},
|
|
356 {-0.0727383792f, -0.0000000000f},
|
|
357 {-0.1073539481f, -0.1477600336f},
|
|
358 { 0.0969250873f, -0.2983047366f},
|
|
359 { 0.4375065267f, -0.1421544850f},
|
|
360 { 0.4968364835f, 0.3609728217f},
|
|
361 {-0.0000000001f, 0.7670462132f},
|
|
362 {-0.7356228828f, 0.5344613194f},
|
|
363 {-0.9810359478f, -0.3187578917f},
|
|
364 {-0.3477955461f, -1.0704045296f},
|
|
365 { 0.6963254809f, -0.9584097862f},
|
|
366 { 1.2048609257f, 0.0000000000f},
|
|
367 { 0.6963254809f, 0.9584097862f},
|
|
368 {-0.3477955461f, 1.0704045296f},
|
|
369 {-0.9810359478f, 0.3187578917f},
|
|
370 {-0.7356228828f, -0.5344613194f},
|
|
371 {-0.0000000001f, -0.7670462132f},
|
|
372 { 0.4968364835f, -0.3609728217f},
|
|
373 { 0.4375065267f, 0.1421544850f},
|
|
374 { 0.0969250873f, 0.2983047366f},
|
|
375 {-0.1073539481f, 0.1477600336f},
|
|
376 {-0.0727383792f, 0.0000000000f},
|
|
377 { 0.0073413476f, 0.0101044979f},
|
|
378 {-0.0221851002f, 0.0682787150f},
|
|
379 {-0.1009239629f, 0.0327921845f},
|
|
380 {-0.0957043841f, -0.0695333034f},
|
|
381 {-0.0000000000f, -0.1125744730f},
|
|
382 { 0.0760799870f, -0.0552753434f},
|
|
383 { 0.0647067279f, 0.0210244898f},
|
|
384 { 0.0122382389f, 0.0376654267f},
|
|
385 },
|
|
386 {
|
|
387 { 0.0129648596f, -0.0399017334f}, /* Filter 7 */
|
|
388 { 0.0669182166f, -0.0217430461f},
|
|
389 { 0.0776194856f, 0.0563938580f},
|
|
390 {-0.0000000000f, 0.1136142015f},
|
|
391 {-0.0954896435f, 0.0693772882f},
|
|
392 {-0.0990553871f, -0.0321850479f},
|
|
393 {-0.0209610034f, -0.0645113364f},
|
|
394 { 0.0037474802f, -0.0051579643f},
|
|
395 {-0.0809883848f, -0.0000000000f},
|
|
396 {-0.1133359149f, -0.1559935063f},
|
|
397 { 0.1005420759f, -0.3094367087f},
|
|
398 { 0.4495492578f, -0.1460674107f},
|
|
399 { 0.5072873235f, 0.3685658276f},
|
|
400 {-0.0000000001f, 0.7794392109f},
|
|
401 {-0.7445815802f, 0.5409702063f},
|
|
402 {-0.9896088243f, -0.3215433955f},
|
|
403 {-0.3497529626f, -1.0764288902f},
|
|
404 { 0.6982125044f, -0.9610070586f},
|
|
405 { 1.2047197819f, 0.0000000000f},
|
|
406 { 0.6942784786f, 0.9555923343f},
|
|
407 {-0.3457630277f, 1.0641491413f},
|
|
408 {-0.9722753763f, 0.3159114122f},
|
|
409 {-0.7265513539f, -0.5278704762f},
|
|
410 {-0.0000000001f, -0.7545788884f},
|
|
411 { 0.4863792956f, -0.3533752263f},
|
|
412 { 0.4255155921f, 0.1382583976f},
|
|
413 { 0.0933413655f, 0.2872751951f},
|
|
414 {-0.1014589071f, 0.1396462023f},
|
|
415 {-0.0646610633f, 0.0000000000f},
|
|
416 { 0.0108286384f, 0.0149043426f},
|
|
417 {-0.0233552568f, 0.0718800873f},
|
|
418 {-0.1026455015f, 0.0333515443f},
|
|
419 {-0.0958181471f, -0.0696159601f},
|
|
420 {-0.0000000000f, -0.1114456356f},
|
|
421 { 0.0744986683f, -0.0541264527f},
|
|
422 { 0.0624796189f, 0.0203008596f},
|
|
423 { 0.0115157729f, 0.0354419053f},
|
|
424 },
|
|
425 {
|
|
426 { 0.0136949494f, -0.0421487205f}, /* Filter 8 */
|
|
427 { 0.0691114515f, -0.0224556718f},
|
|
428 { 0.0791146755f, 0.0574801750f},
|
|
429 {-0.0000000000f, 0.1145617142f},
|
|
430 {-0.0951716974f, 0.0691462904f},
|
|
431 {-0.0970377848f, -0.0315294862f},
|
|
432 {-0.0196826290f, -0.0605769046f},
|
|
433 { 0.0000471013f, -0.0000648294f},
|
|
434 {-0.0894096494f, -0.0000000000f},
|
|
435 {-0.1194031686f, -0.1643443555f},
|
|
436 { 0.1041911170f, -0.3206672966f},
|
|
437 { 0.4616391361f, -0.1499956548f},
|
|
438 { 0.5177274346f, 0.3761509955f},
|
|
439 {-0.0000000001f, 0.7917523384f},
|
|
440 {-0.7534233332f, 0.5473940969f},
|
|
441 {-0.9979898930f, -0.3242665529f},
|
|
442 {-0.3516343236f, -1.0822191238f},
|
|
443 { 0.6999385953f, -0.9633828402f},
|
|
444 { 1.2042965889f, 0.0000000000f},
|
|
445 { 0.6920724511f, 0.9525560141f},
|
|
446 {-0.3436563909f, 1.0576655865f},
|
|
447 {-0.9633312821f, 0.3130052984f},
|
|
448 {-0.7173712850f, -0.5212007165f},
|
|
449 {-0.0000000001f, -0.7420427203f},
|
|
450 { 0.4759201407f, -0.3457762301f},
|
|
451 { 0.4135811031f, 0.1343806386f},
|
|
452 { 0.0897921249f, 0.2763517499f},
|
|
453 {-0.0956523716f, 0.1316542029f},
|
|
454 {-0.0567577891f, 0.0000000000f},
|
|
455 { 0.0142093524f, 0.0195574965f},
|
|
456 {-0.0244718455f, 0.0753165931f},
|
|
457 {-0.1042220443f, 0.0338637941f},
|
|
458 {-0.0958332121f, -0.0696269050f},
|
|
459 {-0.0000000000f, -0.1102307960f},
|
|
460 { 0.0728780255f, -0.0529489815f},
|
|
461 { 0.0602394938f, 0.0195729975f},
|
|
462 { 0.0107981311f, 0.0332332328f},
|
|
463 },
|
|
464 {
|
|
465 { 0.0144278063f, -0.0444042198f}, /* Filter 9 */
|
|
466 { 0.0712837577f, -0.0231614988f},
|
|
467 { 0.0805630460f, 0.0585324802f},
|
|
468 {-0.0000000000f, 0.1154139340f},
|
|
469 {-0.0947483405f, 0.0688387007f},
|
|
470 {-0.0948692262f, -0.0308248810f},
|
|
471 {-0.0183496606f, -0.0564744473f},
|
|
472 {-0.0037596615f, 0.0051747300f},
|
|
473 {-0.0980006009f, -0.0000000000f},
|
|
474 {-0.1255540103f, -0.1728102714f},
|
|
475 { 0.1078709438f, -0.3319926262f},
|
|
476 { 0.4737714827f, -0.1539376825f},
|
|
477 { 0.5281522870f, 0.3837251067f},
|
|
478 {-0.0000000001f, 0.8039799333f},
|
|
479 {-0.7621439099f, 0.5537299514f},
|
|
480 {-1.0061750412f, -0.3269260824f},
|
|
481 {-0.3534386754f, -1.0877723694f},
|
|
482 { 0.7015029192f, -0.9655358791f},
|
|
483 { 1.2035913467f, 0.0000000000f},
|
|
484 { 0.6897085309f, 0.9493023753f},
|
|
485 {-0.3414767087f, 1.0509572029f},
|
|
486 {-0.9542079568f, 0.3100409508f},
|
|
487 {-0.7080869079f, -0.5144552588f},
|
|
488 {-0.0000000001f, -0.7294434309f},
|
|
489 { 0.4654633999f, -0.3381789625f},
|
|
490 { 0.4017075598f, 0.1305226982f},
|
|
491 { 0.0862785354f, 0.2655380368f},
|
|
492 {-0.0899358466f, 0.1237860769f},
|
|
493 {-0.0490297712f, 0.0000000000f},
|
|
494 { 0.0174835511f, 0.0240640435f},
|
|
495 {-0.0255352631f, 0.0785894617f},
|
|
496 {-0.1056557149f, 0.0343296230f},
|
|
497 {-0.0957518741f, -0.0695678070f},
|
|
498 {-0.0000000000f, -0.1089330688f},
|
|
499 { 0.0712205172f, -0.0517447330f},
|
|
500 { 0.0579889156f, 0.0188417397f},
|
|
501 { 0.0100859674f, 0.0310414154f},
|
|
502 },
|
|
503 {
|
|
504 { 0.0151627110f, -0.0466660261f}, /* Filter 10 */
|
|
505 { 0.0734324455f, -0.0238596480f},
|
|
506 { 0.0819620788f, 0.0595489368f},
|
|
507 {-0.0000000000f, 0.1161677912f},
|
|
508 {-0.0942174047f, 0.0684529543f},
|
|
509 {-0.0925478712f, -0.0300706252f},
|
|
510 {-0.0169618148f, -0.0522031002f},
|
|
511 {-0.0076726158f, 0.0105604501f},
|
|
512 {-0.1067595631f, -0.0000000000f},
|
|
513 {-0.1317866892f, -0.1813888103f},
|
|
514 { 0.1115802750f, -0.3434087634f},
|
|
515 { 0.4859414399f, -0.1578919441f},
|
|
516 { 0.5385575294f, 0.3912849724f},
|
|
517 {-0.0000000001f, 0.8161166310f},
|
|
518 {-0.7707393169f, 0.5599749088f},
|
|
519 {-1.0141602755f, -0.3295206726f},
|
|
520 {-0.3551651835f, -1.0930860043f},
|
|
521 { 0.7029046416f, -0.9674652219f},
|
|
522 { 1.2026044130f, 0.0000000000f},
|
|
523 { 0.6871879101f, 0.9458330274f},
|
|
524 {-0.3392250240f, 1.0440272093f},
|
|
525 {-0.9449097514f, 0.3070197999f},
|
|
526 {-0.6987025142f, -0.5076370835f},
|
|
527 {-0.0000000001f, -0.7167864442f},
|
|
528 { 0.4550133944f, -0.3305865824f},
|
|
529 { 0.3898994923f, 0.1266860217f},
|
|
530 { 0.0828017443f, 0.2548375726f},
|
|
531 {-0.0843107775f, 0.1160438284f},
|
|
532 {-0.0414781198f, 0.0000000000f},
|
|
533 { 0.0206513591f, 0.0284241568f},
|
|
534 {-0.0265459362f, 0.0816999897f},
|
|
535 {-0.1069486886f, 0.0347497351f},
|
|
536 {-0.0955764726f, -0.0694403723f},
|
|
537 {-0.0000000000f, -0.1075555831f},
|
|
538 { 0.0695286095f, -0.0505154915f},
|
|
539 { 0.0557304025f, 0.0181079060f},
|
|
540 { 0.0093799150f, 0.0288684089f},
|
|
541 },
|
|
542 {
|
|
543 { 0.0158989299f, -0.0489318743f}, /* Filter 11 */
|
|
544 { 0.0755547658f, -0.0245492328f},
|
|
545 { 0.0833092555f, 0.0605277158f},
|
|
546 {-0.0000000000f, 0.1168202460f},
|
|
547 {-0.0935767666f, 0.0679875016f},
|
|
548 {-0.0900719389f, -0.0292661469f},
|
|
549 {-0.0155188413f, -0.0477620810f},
|
|
550 {-0.0116915042f, 0.0160919763f},
|
|
551 {-0.1156847477f, -0.0000000000f},
|
|
552 {-0.1380993575f, -0.1900774688f},
|
|
553 { 0.1153177992f, -0.3549116850f},
|
|
554 { 0.4981442094f, -0.1618568748f},
|
|
555 { 0.5489386916f, 0.3988272846f},
|
|
556 {-0.0000000001f, 0.8281568289f},
|
|
557 {-0.7792053819f, 0.5661258698f},
|
|
558 {-1.0219419003f, -0.3320490718f},
|
|
559 {-0.3568129838f, -1.0981574059f},
|
|
560 { 0.7041431069f, -0.9691697955f},
|
|
561 { 1.2013363838f, 0.0000000000f},
|
|
562 { 0.6845118403f, 0.9421496987f},
|
|
563 {-0.3369024098f, 1.0368790627f},
|
|
564 {-0.9354411960f, 0.3039432764f},
|
|
565 {-0.6892225146f, -0.5007494688f},
|
|
566 {-0.0000000001f, -0.7040774226f},
|
|
567 { 0.4445744753f, -0.3230022490f},
|
|
568 { 0.3781612813f, 0.1228720471f},
|
|
569 { 0.0793628618f, 0.2442537695f},
|
|
570 {-0.0787785500f, 0.1084293649f},
|
|
571 {-0.0341038331f, 0.0000000000f},
|
|
572 { 0.0237129591f, 0.0326380879f},
|
|
573 {-0.0275043193f, 0.0846495852f},
|
|
574 {-0.1081032082f, 0.0351248607f},
|
|
575 {-0.0953093544f, -0.0692462996f},
|
|
576 {-0.0000000000f, -0.1061014757f},
|
|
577 { 0.0678047314f, -0.0492630191f},
|
|
578 { 0.0534664392f, 0.0173722990f},
|
|
579 { 0.0086805914f, 0.0267161131f},
|
|
580 },
|
|
581 };
|
|
582
|
|
583 static const complexf_t pulseshaper_2400[PULSESHAPER_COEFF_SETS][V22BIS_RX_FILTER_STEPS] =
|
|
584 {
|
|
585 {
|
|
586 { 0.0209144205f, 0.0151952161f}, /* Filter 0 */
|
|
587 {-0.0435528643f, 0.0316430070f},
|
|
588 {-0.0252293516f, -0.0776479617f},
|
|
589 { 0.1045738682f, 0.0000000001f},
|
|
590 {-0.0362687893f, 0.1116238534f},
|
|
591 {-0.0928243399f, -0.0674408302f},
|
|
592 { 0.0743806660f, -0.0540407188f},
|
|
593 { 0.0140205137f, 0.0431507044f},
|
|
594 { 0.0269077960f, 0.0000000000f},
|
|
595 {-0.0385573655f, 0.1186673641f},
|
|
596 {-0.1988736391f, -0.1444901675f},
|
|
597 { 0.3117611706f, -0.2265077531f},
|
|
598 { 0.1658308655f, 0.5103749037f},
|
|
599 {-0.6913219094f, -0.0000000002f},
|
|
600 { 0.2596036494f, -0.7989778519f},
|
|
601 { 0.7875382304f, 0.5721800327f},
|
|
602 {-0.8757586479f, 0.6362759471f},
|
|
603 {-0.3583812416f, -1.1029839516f},
|
|
604 { 1.1997879744f, 0.0000000000f},
|
|
605 {-0.3707548678f, 1.1410661936f},
|
|
606 {-0.9382542372f, -0.6816816330f},
|
|
607 { 0.8757586479f, -0.6362759471f},
|
|
608 { 0.3008128405f, 0.9258067012f},
|
|
609 {-0.8400950432f, 0.0000000002f},
|
|
610 { 0.2136302292f, -0.6574862003f},
|
|
611 { 0.4341508448f, 0.3154290617f},
|
|
612 {-0.3117611706f, 0.2265077531f},
|
|
613 {-0.0759629756f, -0.2337899953f},
|
|
614 { 0.1247742549f, -0.0000000001f},
|
|
615 {-0.0083149662f, 0.0255908351f},
|
|
616 { 0.0367061794f, 0.0266686007f},
|
|
617 {-0.0743806660f, 0.0540407188f},
|
|
618 {-0.0354557447f, -0.1091215536f},
|
|
619 { 0.1173682660f, -0.0000000001f},
|
|
620 {-0.0323151015f, 0.0994556621f},
|
|
621 {-0.0660513043f, -0.0479890816f},
|
|
622 { 0.0435528643f, -0.0316430070f},
|
|
623 },
|
|
624 {
|
|
625 { 0.0227260832f, 0.0165114664f}, /* Filter 1 */
|
|
626 {-0.0454812683f, 0.0330440775f},
|
|
627 {-0.0258991010f, -0.0797092393f},
|
|
628 { 0.1061014757f, 0.0000000001f},
|
|
629 {-0.0364049338f, 0.1120428666f},
|
|
630 {-0.0919580832f, -0.0668114573f},
|
|
631 { 0.0720072389f, -0.0523163229f},
|
|
632 { 0.0124666411f, 0.0383683741f},
|
|
633 { 0.0341038331f, 0.0000000000f},
|
|
634 {-0.0414163321f, 0.1274663657f},
|
|
635 {-0.2077746689f, -0.1509571373f},
|
|
636 { 0.3216831982f, -0.2337165177f},
|
|
637 { 0.1698123366f, 0.5226286054f},
|
|
638 {-0.7040774226f, -0.0000000002f},
|
|
639 { 0.2632595599f, -0.8102296591f},
|
|
640 { 0.7957338095f, 0.5781344771f},
|
|
641 {-0.8820219636f, 0.6408264637f},
|
|
642 {-0.3598691821f, -1.1075633764f},
|
|
643 { 1.2013363838f, 0.0000000000f},
|
|
644 {-0.3701899350f, 1.1393274069f},
|
|
645 {-0.9341484904f, -0.6786985993f},
|
|
646 { 0.8693157434f, -0.6315948367f},
|
|
647 { 0.2976299822f, 0.9160109162f},
|
|
648 {-0.8281568289f, 0.0000000002f},
|
|
649 { 0.2096759230f, -0.6453161240f},
|
|
650 { 0.4237467945f, 0.3078700602f},
|
|
651 {-0.3019059300f, 0.2193474919f},
|
|
652 {-0.0726031289f, -0.2234494686f},
|
|
653 { 0.1156847477f, -0.0000000001f},
|
|
654 {-0.0061465879f, 0.0189172514f},
|
|
655 { 0.0406288542f, 0.0295185894f},
|
|
656 {-0.0766197667f, 0.0556675196f},
|
|
657 {-0.0357431434f, -0.1100060865f},
|
|
658 { 0.1168202460f, -0.0000000001f},
|
|
659 {-0.0318213031f, 0.0979359001f},
|
|
660 {-0.0642707273f, -0.0466954149f},
|
|
661 { 0.0416239388f, -0.0302415621f},
|
|
662 },
|
|
663 {
|
|
664 { 0.0245569348f, 0.0178416576f}, /* Filter 2 */
|
|
665 {-0.0474071130f, 0.0344432816f},
|
|
666 {-0.0265575647f, -0.0817357823f},
|
|
667 { 0.1075555831f, 0.0000000001f},
|
|
668 {-0.0365069620f, 0.1123568788f},
|
|
669 {-0.0909759924f, -0.0660979301f},
|
|
670 { 0.0694981664f, -0.0504933707f},
|
|
671 { 0.0108570615f, 0.0334145986f},
|
|
672 { 0.0414781198f, 0.0000000000f},
|
|
673 {-0.0443248004f, 0.1364177018f},
|
|
674 {-0.2167777866f, -0.1574982852f},
|
|
675 { 0.3316683173f, -0.2409711480f},
|
|
676 { 0.1737996489f, 0.5349003077f},
|
|
677 {-0.7167864442f, -0.0000000002f},
|
|
678 { 0.2668806314f, -0.8213740587f},
|
|
679 { 0.8037882447f, 0.5839863420f},
|
|
680 {-0.8881026506f, 0.6452443004f},
|
|
681 {-0.3612760901f, -1.1118934155f},
|
|
682 { 1.2026044130f, 0.0000000000f},
|
|
683 {-0.3695388138f, 1.1373236179f},
|
|
684 {-0.9298345447f, -0.6755643487f},
|
|
685 { 0.8626962900f, -0.6267855763f},
|
|
686 { 0.2943962216f, 0.9060583711f},
|
|
687 {-0.8161166310f, 0.0000000002f},
|
|
688 { 0.2057106793f, -0.6331123710f},
|
|
689 { 0.4133664668f, 0.3003283143f},
|
|
690 {-0.2921209633f, 0.2122382969f},
|
|
691 {-0.0692843646f, -0.2132353336f},
|
|
692 { 0.1067595631f, -0.0000000001f},
|
|
693 {-0.0040337327f, 0.0124145532f},
|
|
694 { 0.0444066115f, 0.0322632901f},
|
|
695 {-0.0787259191f, 0.0571977310f},
|
|
696 {-0.0359878466f, -0.1107592061f},
|
|
697 { 0.1161677912f, -0.0000000001f},
|
|
698 {-0.0313067287f, 0.0963522047f},
|
|
699 {-0.0624653697f, -0.0453837477f},
|
|
700 { 0.0396964923f, -0.0288411900f},
|
|
701 },
|
|
702 {
|
|
703 { 0.0264054053f, 0.0191846490f}, /* Filter 3 */
|
|
704 {-0.0493283160f, 0.0358391218f},
|
|
705 {-0.0272038169f, -0.0837247372f},
|
|
706 { 0.1089330688f, 0.0000000001f},
|
|
707 {-0.0365739614f, 0.1125630811f},
|
|
708 {-0.0898761228f, -0.0652988255f},
|
|
709 { 0.0668521896f, -0.0485709570f},
|
|
710 { 0.0091916462f, 0.0282889791f},
|
|
711 { 0.0490297712f, 0.0000000000f},
|
|
712 {-0.0472820736f, 0.1455192566f},
|
|
713 {-0.2258801460f, -0.1641115248f},
|
|
714 { 0.3417128623f, -0.2482689321f},
|
|
715 { 0.1777911931f, 0.5471850634f},
|
|
716 {-0.7294434309f, -0.0000000002f},
|
|
717 { 0.2704651356f, -0.8324060440f},
|
|
718 { 0.8116977811f, 0.5897329450f},
|
|
719 {-0.8939976096f, 0.6495273113f},
|
|
720 {-0.3626012504f, -1.1159719229f},
|
|
721 { 1.2035913467f, 0.0000000000f},
|
|
722 {-0.3688018918f, 1.1350555420f},
|
|
723 {-0.9253144860f, -0.6722803116f},
|
|
724 { 0.8559035659f, -0.6218503714f},
|
|
725 { 0.2911130786f, 0.8959538937f},
|
|
726 {-0.8039799333f, 0.0000000002f},
|
|
727 { 0.2017362267f, -0.6208803058f},
|
|
728 { 0.4030140936f, 0.2928068638f},
|
|
729 {-0.2824097872f, 0.2051827312f},
|
|
730 {-0.0660076514f, -0.2031506598f},
|
|
731 { 0.0980006009f, -0.0000000001f},
|
|
732 {-0.0019765710f, 0.0060832603f},
|
|
733 { 0.0480400361f, 0.0349031277f},
|
|
734 {-0.0807005838f, 0.0586324073f},
|
|
735 {-0.0361906476f, -0.1113833562f},
|
|
736 { 0.1154139340f, -0.0000000001f},
|
|
737 {-0.0307723451f, 0.0947075412f},
|
|
738 {-0.0606375895f, -0.0440557860f},
|
|
739 { 0.0377724878f, -0.0274433177f},
|
|
740 },
|
|
741 {
|
|
742 { 0.0282698758f, 0.0205392670f}, /* Filter 4 */
|
|
743 {-0.0512427762f, 0.0372300558f},
|
|
744 {-0.0278369281f, -0.0856732503f},
|
|
745 { 0.1102307960f, 0.0000000001f},
|
|
746 {-0.0366050303f, 0.1126586944f},
|
|
747 {-0.0886565670f, -0.0644127652f},
|
|
748 { 0.0640681237f, -0.0465482138f},
|
|
749 { 0.0074702986f, 0.0229912158f},
|
|
750 { 0.0567577891f, 0.0000000000f},
|
|
751 {-0.0502874292f, 0.1547687948f},
|
|
752 {-0.2350788414f, -0.1707947701f},
|
|
753 { 0.3518131077f, -0.2556071877f},
|
|
754 { 0.1817853153f, 0.5594776869f},
|
|
755 {-0.7420427203f, -0.0000000002f},
|
|
756 { 0.2740114331f, -0.8433204889f},
|
|
757 { 0.8194585443f, 0.5953714848f},
|
|
758 {-0.8997041583f, 0.6536732912f},
|
|
759 {-0.3638440073f, -1.1197967529f},
|
|
760 { 1.2042965889f, 0.0000000000f},
|
|
761 {-0.3679794967f, 1.1325244904f},
|
|
762 {-0.9205905795f, -0.6688482165f},
|
|
763 { 0.8489409089f, -0.6167916656f},
|
|
764 { 0.2877821028f, 0.8857022524f},
|
|
765 {-0.7917523384f, 0.0000000002f},
|
|
766 { 0.1977542788f, -0.6086250544f},
|
|
767 { 0.3926937282f, 0.2853086889f},
|
|
768 {-0.2727758884f, 0.1981832832f},
|
|
769 {-0.0627739578f, -0.1931983829f},
|
|
770 { 0.0894096494f, -0.0000000000f},
|
|
771 { 0.0000247626f, -0.0000762115f},
|
|
772 { 0.0515297912f, 0.0374385864f},
|
|
773 {-0.0825452656f, 0.0599726476f},
|
|
774 {-0.0363523550f, -0.1118810475f},
|
|
775 { 0.1145617142f, -0.0000000001f},
|
|
776 {-0.0302191172f, 0.0930048823f},
|
|
777 {-0.0587897114f, -0.0427132249f},
|
|
778 { 0.0358538441f, -0.0260493420f},
|
|
779 },
|
|
780 {
|
|
781 { 0.0301486850f, 0.0219043009f}, /* Filter 5 */
|
|
782 {-0.0531483367f, 0.0386145264f},
|
|
783 {-0.0284559596f, -0.0875784382f},
|
|
784 { 0.1114456356f, 0.0000000001f},
|
|
785 {-0.0365992747f, 0.1126409844f},
|
|
786 {-0.0873154774f, -0.0634384081f},
|
|
787 { 0.0611448549f, -0.0444243364f},
|
|
788 { 0.0056929523f, 0.0175211057f},
|
|
789 { 0.0646610633f, 0.0000000000f},
|
|
790 {-0.0533401072f, 0.1641639620f},
|
|
791 {-0.2443708777f, -0.1775458306f},
|
|
792 { 0.3619651794f, -0.2629830837f},
|
|
793 { 0.1857803613f, 0.5717731118f},
|
|
794 {-0.7545788884f, -0.0000000002f},
|
|
795 { 0.2775179148f, -0.8541123271f},
|
|
796 { 0.8270668387f, 0.6008992195f},
|
|
797 {-0.9052193165f, 0.6576803327f},
|
|
798 {-0.3650037944f, -1.1233661175f},
|
|
799 { 1.2047197819f, 0.0000000000f},
|
|
800 {-0.3670720458f, 1.1297315359f},
|
|
801 {-0.9156650901f, -0.6652696729f},
|
|
802 { 0.8418115377f, -0.6116119027f},
|
|
803 { 0.2844048440f, 0.8753081560f},
|
|
804 {-0.7794392109f, 0.0000000002f},
|
|
805 { 0.1937665194f, -0.5963520408f},
|
|
806 { 0.3824094236f, 0.2778367102f},
|
|
807 {-0.2632225752f, 0.1912423968f},
|
|
808 {-0.0595842153f, -0.1833813637f},
|
|
809 { 0.0809883848f, -0.0000000000f},
|
|
810 { 0.0019701670f, -0.0060635507f},
|
|
811 { 0.0548766218f, 0.0398701988f},
|
|
812 {-0.0842615440f, 0.0612195991f},
|
|
813 {-0.0364737995f, -0.1122548133f},
|
|
814 { 0.1136142015f, -0.0000000001f},
|
|
815 {-0.0296480060f, 0.0912471786f},
|
|
816 {-0.0569240339f, -0.0413577296f},
|
|
817 { 0.0339424424f, -0.0246606283f},
|
|
818 },
|
|
819 {
|
|
820 { 0.0320401229f, 0.0232785121f}, /* Filter 6 */
|
|
821 {-0.0550428294f, 0.0399909541f},
|
|
822 {-0.0290599689f, -0.0894373879f},
|
|
823 { 0.1125744730f, 0.0000000001f},
|
|
824 {-0.0365558229f, 0.1125072464f},
|
|
825 {-0.0858510509f, -0.0623744428f},
|
|
826 { 0.0580813438f, -0.0421985686f},
|
|
827 { 0.0038595749f, 0.0118785501f},
|
|
828 { 0.0727383792f, 0.0000000000f},
|
|
829 {-0.0564393103f, 0.1737023294f},
|
|
830 {-0.2537531555f, -0.1843624711f},
|
|
831 { 0.3721652627f, -0.2703939080f},
|
|
832 { 0.1897746474f, 0.5840663314f},
|
|
833 {-0.7670462132f, -0.0000000002f},
|
|
834 { 0.2809829414f, -0.8647765517f},
|
|
835 { 0.8345190287f, 0.6063135862f},
|
|
836 {-0.9105405211f, 0.6615464091f},
|
|
837 {-0.3660799563f, -1.1266783476f},
|
|
838 { 1.2048609257f, 0.0000000000f},
|
|
839 {-0.3660799563f, 1.1266783476f},
|
|
840 {-0.9105405211f, -0.6615464091f},
|
|
841 { 0.8345190287f, -0.6063135862f},
|
|
842 { 0.2809829414f, 0.8647765517f},
|
|
843 {-0.7670462132f, 0.0000000002f},
|
|
844 { 0.1897746474f, -0.5840663314f},
|
|
845 { 0.3721652627f, 0.2703939080f},
|
|
846 {-0.2537531555f, 0.1843624711f},
|
|
847 {-0.0564393103f, -0.1737023294f},
|
|
848 { 0.0727383792f, -0.0000000000f},
|
|
849 { 0.0038595749f, -0.0118785501f},
|
|
850 { 0.0580813438f, 0.0421985686f},
|
|
851 {-0.0858510509f, 0.0623744428f},
|
|
852 {-0.0365558229f, -0.1125072464f},
|
|
853 { 0.1125744730f, -0.0000000001f},
|
|
854 {-0.0290599689f, 0.0894373879f},
|
|
855 {-0.0550428294f, -0.0399909541f},
|
|
856 { 0.0320401229f, -0.0232785121f},
|
|
857 },
|
|
858 {
|
|
859 { 0.0339424424f, 0.0246606283f}, /* Filter 7 */
|
|
860 {-0.0569240339f, 0.0413577296f},
|
|
861 {-0.0296480060f, -0.0912471786f},
|
|
862 { 0.1136142015f, 0.0000000001f},
|
|
863 {-0.0364737995f, 0.1122548133f},
|
|
864 {-0.0842615440f, -0.0612195991f},
|
|
865 { 0.0548766218f, -0.0398701988f},
|
|
866 { 0.0019701670f, 0.0060635507f},
|
|
867 { 0.0809883848f, 0.0000000000f},
|
|
868 {-0.0595842153f, 0.1833813637f},
|
|
869 {-0.2632225752f, -0.1912423968f},
|
|
870 { 0.3824094236f, -0.2778367102f},
|
|
871 { 0.1937665194f, 0.5963520408f},
|
|
872 {-0.7794392109f, -0.0000000002f},
|
|
873 { 0.2844048440f, -0.8753081560f},
|
|
874 { 0.8418115377f, 0.6116119027f},
|
|
875 {-0.9156650901f, 0.6652696729f},
|
|
876 {-0.3670720458f, -1.1297315359f},
|
|
877 { 1.2047197819f, 0.0000000000f},
|
|
878 {-0.3650037944f, 1.1233661175f},
|
|
879 {-0.9052193165f, -0.6576803327f},
|
|
880 { 0.8270668387f, -0.6008992195f},
|
|
881 { 0.2775179148f, 0.8541123271f},
|
|
882 {-0.7545788884f, 0.0000000002f},
|
|
883 { 0.1857803613f, -0.5717731118f},
|
|
884 { 0.3619651794f, 0.2629830837f},
|
|
885 {-0.2443708777f, 0.1775458306f},
|
|
886 {-0.0533401072f, -0.1641639620f},
|
|
887 { 0.0646610633f, -0.0000000000f},
|
|
888 { 0.0056929523f, -0.0175211057f},
|
|
889 { 0.0611448549f, 0.0444243364f},
|
|
890 {-0.0873154774f, 0.0634384081f},
|
|
891 {-0.0365992747f, -0.1126409844f},
|
|
892 { 0.1114456356f, -0.0000000001f},
|
|
893 {-0.0284559596f, 0.0875784382f},
|
|
894 {-0.0531483367f, -0.0386145264f},
|
|
895 { 0.0301486850f, -0.0219043009f},
|
|
896 },
|
|
897 {
|
|
898 { 0.0358538441f, 0.0260493420f}, /* Filter 8 */
|
|
899 {-0.0587897114f, 0.0427132249f},
|
|
900 {-0.0302191172f, -0.0930048823f},
|
|
901 { 0.1145617142f, 0.0000000001f},
|
|
902 {-0.0363523550f, 0.1118810475f},
|
|
903 {-0.0825452656f, -0.0599726476f},
|
|
904 { 0.0515297912f, -0.0374385864f},
|
|
905 { 0.0000247626f, 0.0000762115f},
|
|
906 { 0.0894096494f, 0.0000000000f},
|
|
907 {-0.0627739578f, 0.1931983829f},
|
|
908 {-0.2727758884f, -0.1981832832f},
|
|
909 { 0.3926937282f, -0.2853086889f},
|
|
910 { 0.1977542788f, 0.6086250544f},
|
|
911 {-0.7917523384f, -0.0000000002f},
|
|
912 { 0.2877821028f, -0.8857022524f},
|
|
913 { 0.8489409089f, 0.6167916656f},
|
|
914 {-0.9205905795f, 0.6688482165f},
|
|
915 {-0.3679794967f, -1.1325244904f},
|
|
916 { 1.2042965889f, 0.0000000000f},
|
|
917 {-0.3638440073f, 1.1197967529f},
|
|
918 {-0.8997041583f, -0.6536732912f},
|
|
919 { 0.8194585443f, -0.5953714848f},
|
|
920 { 0.2740114331f, 0.8433204889f},
|
|
921 {-0.7420427203f, 0.0000000002f},
|
|
922 { 0.1817853153f, -0.5594776869f},
|
|
923 { 0.3518131077f, 0.2556071877f},
|
|
924 {-0.2350788414f, 0.1707947701f},
|
|
925 {-0.0502874292f, -0.1547687948f},
|
|
926 { 0.0567577891f, -0.0000000000f},
|
|
927 { 0.0074702986f, -0.0229912158f},
|
|
928 { 0.0640681237f, 0.0465482138f},
|
|
929 {-0.0886565670f, 0.0644127652f},
|
|
930 {-0.0366050303f, -0.1126586944f},
|
|
931 { 0.1102307960f, -0.0000000001f},
|
|
932 {-0.0278369281f, 0.0856732503f},
|
|
933 {-0.0512427762f, -0.0372300558f},
|
|
934 { 0.0282698758f, -0.0205392670f},
|
|
935 },
|
|
936 {
|
|
937 { 0.0377724878f, 0.0274433177f}, /* Filter 9 */
|
|
938 {-0.0606375895f, 0.0440557860f},
|
|
939 {-0.0307723451f, -0.0947075412f},
|
|
940 { 0.1154139340f, 0.0000000001f},
|
|
941 {-0.0361906476f, 0.1113833562f},
|
|
942 {-0.0807005838f, -0.0586324073f},
|
|
943 { 0.0480400361f, -0.0349031277f},
|
|
944 {-0.0019765710f, -0.0060832603f},
|
|
945 { 0.0980006009f, 0.0000000001f},
|
|
946 {-0.0660076514f, 0.2031506598f},
|
|
947 {-0.2824097872f, -0.2051827312f},
|
|
948 { 0.4030140936f, -0.2928068638f},
|
|
949 { 0.2017362267f, 0.6208803058f},
|
|
950 {-0.8039799333f, -0.0000000002f},
|
|
951 { 0.2911130786f, -0.8959538937f},
|
|
952 { 0.8559035659f, 0.6218503714f},
|
|
953 {-0.9253144860f, 0.6722803116f},
|
|
954 {-0.3688018918f, -1.1350555420f},
|
|
955 { 1.2035913467f, 0.0000000000f},
|
|
956 {-0.3626012504f, 1.1159719229f},
|
|
957 {-0.8939976096f, -0.6495273113f},
|
|
958 { 0.8116977811f, -0.5897329450f},
|
|
959 { 0.2704651356f, 0.8324060440f},
|
|
960 {-0.7294434309f, 0.0000000002f},
|
|
961 { 0.1777911931f, -0.5471850634f},
|
|
962 { 0.3417128623f, 0.2482689321f},
|
|
963 {-0.2258801460f, 0.1641115248f},
|
|
964 {-0.0472820736f, -0.1455192566f},
|
|
965 { 0.0490297712f, -0.0000000000f},
|
|
966 { 0.0091916462f, -0.0282889791f},
|
|
967 { 0.0668521896f, 0.0485709570f},
|
|
968 {-0.0898761228f, 0.0652988255f},
|
|
969 {-0.0365739614f, -0.1125630811f},
|
|
970 { 0.1089330688f, -0.0000000001f},
|
|
971 {-0.0272038169f, 0.0837247372f},
|
|
972 {-0.0493283160f, -0.0358391218f},
|
|
973 { 0.0264054053f, -0.0191846490f},
|
|
974 },
|
|
975 {
|
|
976 { 0.0396964923f, 0.0288411900f}, /* Filter 10 */
|
|
977 {-0.0624653697f, 0.0453837477f},
|
|
978 {-0.0313067287f, -0.0963522047f},
|
|
979 { 0.1161677912f, 0.0000000001f},
|
|
980 {-0.0359878466f, 0.1107592061f},
|
|
981 {-0.0787259191f, -0.0571977310f},
|
|
982 { 0.0444066115f, -0.0322632901f},
|
|
983 {-0.0040337327f, -0.0124145532f},
|
|
984 { 0.1067595631f, 0.0000000001f},
|
|
985 {-0.0692843646f, 0.2132353336f},
|
|
986 {-0.2921209633f, -0.2122382969f},
|
|
987 { 0.4133664668f, -0.3003283143f},
|
|
988 { 0.2057106793f, 0.6331123710f},
|
|
989 {-0.8161166310f, -0.0000000002f},
|
|
990 { 0.2943962216f, -0.9060583711f},
|
|
991 { 0.8626962900f, 0.6267855763f},
|
|
992 {-0.9298345447f, 0.6755643487f},
|
|
993 {-0.3695388138f, -1.1373236179f},
|
|
994 { 1.2026044130f, 0.0000000000f},
|
|
995 {-0.3612760901f, 1.1118934155f},
|
|
996 {-0.8881026506f, -0.6452443004f},
|
|
997 { 0.8037882447f, -0.5839863420f},
|
|
998 { 0.2668806314f, 0.8213740587f},
|
|
999 {-0.7167864442f, 0.0000000002f},
|
|
1000 { 0.1737996489f, -0.5349003077f},
|
|
1001 { 0.3316683173f, 0.2409711480f},
|
|
1002 {-0.2167777866f, 0.1574982852f},
|
|
1003 {-0.0443248004f, -0.1364177018f},
|
|
1004 { 0.0414781198f, -0.0000000000f},
|
|
1005 { 0.0108570615f, -0.0334145986f},
|
|
1006 { 0.0694981664f, 0.0504933707f},
|
|
1007 {-0.0909759924f, 0.0660979301f},
|
|
1008 {-0.0365069620f, -0.1123568788f},
|
|
1009 { 0.1075555831f, -0.0000000001f},
|
|
1010 {-0.0265575647f, 0.0817357823f},
|
|
1011 {-0.0474071130f, -0.0344432816f},
|
|
1012 { 0.0245569348f, -0.0178416576f},
|
|
1013 },
|
|
1014 {
|
|
1015 { 0.0416239388f, 0.0302415621f}, /* Filter 11 */
|
|
1016 {-0.0642707273f, 0.0466954149f},
|
|
1017 {-0.0318213031f, -0.0979359001f},
|
|
1018 { 0.1168202460f, 0.0000000001f},
|
|
1019 {-0.0357431434f, 0.1100060865f},
|
|
1020 {-0.0766197667f, -0.0556675196f},
|
|
1021 { 0.0406288542f, -0.0295185894f},
|
|
1022 {-0.0061465879f, -0.0189172514f},
|
|
1023 { 0.1156847477f, 0.0000000001f},
|
|
1024 {-0.0726031289f, 0.2234494686f},
|
|
1025 {-0.3019059300f, -0.2193474919f},
|
|
1026 { 0.4237467945f, -0.3078700602f},
|
|
1027 { 0.2096759230f, 0.6453161240f},
|
|
1028 {-0.8281568289f, -0.0000000002f},
|
|
1029 { 0.2976299822f, -0.9160109162f},
|
|
1030 { 0.8693157434f, 0.6315948367f},
|
|
1031 {-0.9341484904f, 0.6786985993f},
|
|
1032 {-0.3701899350f, -1.1393274069f},
|
|
1033 { 1.2013363838f, 0.0000000000f},
|
|
1034 {-0.3598691821f, 1.1075633764f},
|
|
1035 {-0.8820219636f, -0.6408264637f},
|
|
1036 { 0.7957338095f, -0.5781344771f},
|
|
1037 { 0.2632595599f, 0.8102296591f},
|
|
1038 {-0.7040774226f, 0.0000000002f},
|
|
1039 { 0.1698123366f, -0.5226286054f},
|
|
1040 { 0.3216831982f, 0.2337165177f},
|
|
1041 {-0.2077746689f, 0.1509571373f},
|
|
1042 {-0.0414163321f, -0.1274663657f},
|
|
1043 { 0.0341038331f, -0.0000000000f},
|
|
1044 { 0.0124666411f, -0.0383683741f},
|
|
1045 { 0.0720072389f, 0.0523163229f},
|
|
1046 {-0.0919580832f, 0.0668114573f},
|
|
1047 {-0.0364049338f, -0.1120428666f},
|
|
1048 { 0.1061014757f, -0.0000000001f},
|
|
1049 {-0.0258991010f, 0.0797092393f},
|
|
1050 {-0.0454812683f, -0.0330440775f},
|
|
1051 { 0.0227260832f, -0.0165114664f},
|
|
1052 },
|
|
1053 };
|
|
1054
|
|
1055 static const uint8_t space_map_v22bis[6][6] =
|
|
1056 {
|
|
1057 {11, 9, 9, 6, 6, 7},
|
|
1058 {10, 8, 8, 4, 4, 5},
|
|
1059 {10, 8, 8, 4, 4, 5},
|
|
1060 {13, 12, 12, 0, 0, 2},
|
|
1061 {13, 12, 12, 0, 0, 2},
|
|
1062 {15, 14, 14, 1, 1, 3}
|
|
1063 };
|
|
1064
|
|
1065 float v22bis_rx_carrier_frequency(v22bis_state_t *s)
|
|
1066 {
|
|
1067 return dds_frequencyf(s->rx_carrier_phase_rate);
|
|
1068 }
|
|
1069 /*- End of function --------------------------------------------------------*/
|
|
1070
|
|
1071 float v22bis_rx_symbol_timing_correction(v22bis_state_t *s)
|
|
1072 {
|
|
1073 return (float) s->total_baud_timing_correction/((float) PULSESHAPER_COEFF_SETS*40.0f/(3.0f*2.0f));
|
|
1074 }
|
|
1075 /*- End of function --------------------------------------------------------*/
|
|
1076
|
|
1077 float v22bis_rx_signal_power(v22bis_state_t *s)
|
|
1078 {
|
|
1079 return power_meter_dbm0(&s->rx_power);
|
|
1080 }
|
|
1081 /*- End of function --------------------------------------------------------*/
|
|
1082
|
|
1083 int v22bis_rx_equalizer_state(v22bis_state_t *s, complexf_t **coeffs)
|
|
1084 {
|
|
1085 *coeffs = s->eq_coeff;
|
|
1086 return 2*V22BIS_EQUALIZER_LEN + 1;
|
|
1087 }
|
|
1088 /*- End of function --------------------------------------------------------*/
|
|
1089
|
|
1090 static void equalizer_reset(v22bis_state_t *s)
|
|
1091 {
|
|
1092 int i;
|
|
1093
|
|
1094 /* Start with an equalizer based on everything being perfect */
|
|
1095 for (i = 0; i < 2*V22BIS_EQUALIZER_LEN + 1; i++)
|
|
1096 s->eq_coeff[i] = complex_setf(0.0f, 0.0f);
|
|
1097 s->eq_coeff[V22BIS_EQUALIZER_LEN] = complex_setf(3.0f, 0.0f);
|
|
1098 for (i = 0; i <= V22BIS_EQUALIZER_MASK; i++)
|
|
1099 s->eq_buf[i] = complex_setf(0.0f, 0.0f);
|
|
1100
|
|
1101 s->eq_coeff[V22BIS_EQUALIZER_LEN - 6].re = -0.02f;
|
|
1102 s->eq_coeff[V22BIS_EQUALIZER_LEN - 5].re = 0.035f;
|
|
1103 s->eq_coeff[V22BIS_EQUALIZER_LEN - 4].re = 0.08f;
|
|
1104 s->eq_coeff[V22BIS_EQUALIZER_LEN - 3].re = -0.30f;
|
|
1105 s->eq_coeff[V22BIS_EQUALIZER_LEN - 2].re = -0.37f;
|
|
1106 s->eq_coeff[V22BIS_EQUALIZER_LEN - 1].re = 0.09f;
|
|
1107 s->eq_coeff[V22BIS_EQUALIZER_LEN].re = 3.19f;
|
|
1108 s->eq_coeff[V22BIS_EQUALIZER_LEN + 1].re = 0.09f;
|
|
1109 s->eq_coeff[V22BIS_EQUALIZER_LEN + 2].re = -0.37f;
|
|
1110 s->eq_coeff[V22BIS_EQUALIZER_LEN + 3].re = -0.30f;
|
|
1111 s->eq_coeff[V22BIS_EQUALIZER_LEN + 5].re = 0.035f;
|
|
1112 s->eq_coeff[V22BIS_EQUALIZER_LEN + 6].re = -0.02f;
|
|
1113
|
|
1114 s->eq_put_step = 20 - 1;
|
|
1115 s->eq_step = 0;
|
|
1116 s->eq_delta = EQUALIZER_DELTA/(2*V22BIS_EQUALIZER_LEN + 1);
|
|
1117 }
|
|
1118 /*- End of function --------------------------------------------------------*/
|
|
1119
|
|
1120 static complexf_t equalizer_get(v22bis_state_t *s)
|
|
1121 {
|
|
1122 int i;
|
|
1123 int p;
|
|
1124 complexf_t z;
|
|
1125 complexf_t z1;
|
|
1126
|
|
1127 /* Get the next equalized value. */
|
|
1128 z = complex_setf(0.0f, 0.0f);
|
|
1129 p = s->eq_step - 1;
|
|
1130 for (i = 0; i < 2*V22BIS_EQUALIZER_LEN + 1; i++)
|
|
1131 {
|
|
1132 p = (p - 1) & V22BIS_EQUALIZER_MASK;
|
|
1133 z1 = complex_mulf(&s->eq_coeff[i], &s->eq_buf[p]);
|
|
1134 z = complex_addf(&z, &z1);
|
|
1135 }
|
|
1136 return z;
|
|
1137 }
|
|
1138 /*- End of function --------------------------------------------------------*/
|
|
1139
|
|
1140 static void tune_equalizer(v22bis_state_t *s, const complexf_t *z, const complexf_t *target)
|
|
1141 {
|
|
1142 int i;
|
|
1143 int p;
|
|
1144 complexf_t ez;
|
|
1145 complexf_t z1;
|
|
1146
|
|
1147 /* Find the x and y mismatch from the exact constellation position. */
|
|
1148 ez = complex_subf(target, z);
|
|
1149 ez.re *= s->eq_delta;
|
|
1150 ez.im *= s->eq_delta;
|
|
1151
|
|
1152 p = s->eq_step - 1;
|
|
1153 for (i = 0; i < 2*V22BIS_EQUALIZER_LEN + 1; i++)
|
|
1154 {
|
|
1155 p = (p - 1) & V22BIS_EQUALIZER_MASK;
|
|
1156 z1 = complex_conjf(&s->eq_buf[p]);
|
|
1157 z1 = complex_mulf(&ez, &z1);
|
|
1158 s->eq_coeff[i] = complex_addf(&s->eq_coeff[i], &z1);
|
|
1159 /* If we don't leak a little bit we seem to get some wandering adaption */
|
|
1160 s->eq_coeff[i].re *= 0.9999f;
|
|
1161 s->eq_coeff[i].im *= 0.9999f;
|
|
1162 }
|
|
1163 }
|
|
1164 /*- End of function --------------------------------------------------------*/
|
|
1165
|
|
1166 static __inline__ void track_carrier(v22bis_state_t *s, const complexf_t *z, const complexf_t *target)
|
|
1167 {
|
|
1168 float error;
|
|
1169
|
|
1170 /* For small errors the imaginary part of the difference between the actual and the target
|
|
1171 positions is proportional to the phase error, for any particular target. However, the
|
|
1172 different amplitudes of the various target positions scale things. */
|
|
1173 error = z->im*target->re - z->re*target->im;
|
|
1174
|
|
1175 s->rx_carrier_phase_rate += (int32_t) (s->carrier_track_i*error);
|
|
1176 s->rx_carrier_phase += (int32_t) (s->carrier_track_p*error);
|
|
1177 //span_log(&s->logging, SPAN_LOG_FLOW, "Im = %15.5f f = %15.5f\n", error, dds_frequencyf(s->carrier_phase_rate));
|
|
1178 }
|
|
1179 /*- End of function --------------------------------------------------------*/
|
|
1180
|
|
1181 static __inline__ void put_bit(v22bis_state_t *s, int bit)
|
|
1182 {
|
|
1183 int out_bit;
|
|
1184
|
|
1185 bit &= 1;
|
|
1186
|
|
1187 /* Descramble the bit */
|
|
1188 s->rx_scramble_reg = (s->rx_scramble_reg << 1) | bit;
|
|
1189 out_bit = (bit ^ (s->rx_scramble_reg >> 15) ^ (s->rx_scramble_reg >> 18)) & 1;
|
|
1190 if (s->rx_scrambler_pattern_count >= 64)
|
|
1191 {
|
|
1192 out_bit ^= 1;
|
|
1193 s->rx_scrambler_pattern_count = 0;
|
|
1194 }
|
|
1195 if (bit)
|
|
1196 s->rx_scrambler_pattern_count++;
|
|
1197 else
|
|
1198 s->rx_scrambler_pattern_count = 0;
|
|
1199
|
|
1200 s->put_bit(s->user_data, out_bit);
|
|
1201 }
|
|
1202 /*- End of function --------------------------------------------------------*/
|
|
1203
|
|
1204 static void decode_baud(v22bis_state_t *s, int nearest)
|
|
1205 {
|
|
1206 static const uint8_t phase_steps[4] =
|
|
1207 {
|
|
1208 1, 0, 2, 3
|
|
1209 };
|
|
1210 int raw_bits;
|
|
1211
|
|
1212 raw_bits = phase_steps[((nearest - s->rx_constellation_state) >> 2) & 3];
|
|
1213 /* The first two bits are the quadrant */
|
|
1214 put_bit(s, raw_bits);
|
|
1215 put_bit(s, raw_bits >> 1);
|
|
1216 if (s->bit_rate == 2400)
|
|
1217 {
|
|
1218 /* The other two bits are the position within the quadrant */
|
|
1219 put_bit(s, nearest >> 1);
|
|
1220 put_bit(s, nearest);
|
|
1221 }
|
|
1222 s->rx_constellation_state = nearest;
|
|
1223 }
|
|
1224 /*- End of function --------------------------------------------------------*/
|
|
1225
|
|
1226 static __inline__ int find_quadrant(const complexf_t *z)
|
|
1227 {
|
|
1228 int b1;
|
|
1229 int b2;
|
|
1230
|
|
1231 #if 0
|
|
1232 /* Split along the axes, as follows:
|
|
1233 1 0
|
|
1234 2 3
|
|
1235 */
|
|
1236 b1 = (z->re <= 0.0f);
|
|
1237 b2 = (z->im <= 0.0f);
|
|
1238 return (b2 << 1) | (b1 ^ b2);
|
|
1239 #endif
|
|
1240 /* Split the space along the two diagonals, as follows:
|
|
1241 \ 1 /
|
|
1242 2 0
|
|
1243 / 3 \
|
|
1244 */
|
|
1245 b1 = (z->im > z->re);
|
|
1246 b2 = (z->im < -z->re);
|
|
1247 return (b2 << 1) | (b1 ^ b2);
|
|
1248 }
|
|
1249 /*- End of function --------------------------------------------------------*/
|
|
1250
|
|
1251 static void process_half_baud(v22bis_state_t *s, const complexf_t *sample)
|
|
1252 {
|
|
1253 complexf_t a;
|
|
1254 complexf_t b;
|
|
1255 complexf_t c;
|
|
1256
|
|
1257 complexf_t z;
|
|
1258 complexf_t zz;
|
|
1259 const complexf_t *target;
|
|
1260 float p;
|
|
1261 float q;
|
|
1262 int re;
|
|
1263 int im;
|
|
1264 int nearest;
|
|
1265
|
|
1266 z.re = sample->re;
|
|
1267 z.im = sample->im;
|
|
1268
|
|
1269 /* Add a sample to the equalizer's circular buffer, but don't calculate anything
|
|
1270 at this time. */
|
|
1271 s->eq_buf[s->eq_step] = z;
|
|
1272 s->eq_step = (s->eq_step + 1) & V22BIS_EQUALIZER_MASK;
|
|
1273
|
|
1274 /* On alternate insertions we have a whole baud and must process it. */
|
|
1275 if ((s->rx_baud_phase ^= 1))
|
|
1276 return;
|
|
1277
|
|
1278 /* Perform a Gardner test for baud alignment on the three most recent samples. */
|
|
1279 #if 0
|
|
1280 p = s->eq_buf[(s->eq_step - 3) & V22BIS_EQUALIZER_MASK].re
|
|
1281 - s->eq_buf[(s->eq_step - 1) & V22BIS_EQUALIZER_MASK].re;
|
|
1282 p *= s->eq_buf[(s->eq_step - 2) & V22BIS_EQUALIZER_MASK].re;
|
|
1283
|
|
1284 q = s->eq_buf[(s->eq_step - 3) & V22BIS_EQUALIZER_MASK].im
|
|
1285 - s->eq_buf[(s->eq_step - 1) & V22BIS_EQUALIZER_MASK].im;
|
|
1286 q *= s->eq_buf[(s->eq_step - 2) & V22BIS_EQUALIZER_MASK].im;
|
|
1287 #else
|
|
1288 if (s->sixteen_way_decisions)
|
|
1289 {
|
|
1290 p = s->eq_buf[(s->eq_step - 3) & V22BIS_EQUALIZER_MASK].re
|
|
1291 - s->eq_buf[(s->eq_step - 1) & V22BIS_EQUALIZER_MASK].re;
|
|
1292 p *= s->eq_buf[(s->eq_step - 2) & V22BIS_EQUALIZER_MASK].re;
|
|
1293
|
|
1294 q = s->eq_buf[(s->eq_step - 3) & V22BIS_EQUALIZER_MASK].im
|
|
1295 - s->eq_buf[(s->eq_step - 1) & V22BIS_EQUALIZER_MASK].im;
|
|
1296 q *= s->eq_buf[(s->eq_step - 2) & V22BIS_EQUALIZER_MASK].im;
|
|
1297 }
|
|
1298 else
|
|
1299 {
|
|
1300 /* Rotate the points to the 45 degree positions, to maximise the effectiveness of the Gardner algorithm */
|
|
1301 zz = complex_setf(cosf(26.57f*3.14159f/180.0f), sinf(26.57f*3.14159f/180.0f));
|
|
1302 a = complex_mulf(&s->eq_buf[(s->eq_step - 3) & V22BIS_EQUALIZER_MASK], &zz);
|
|
1303 b = complex_mulf(&s->eq_buf[(s->eq_step - 2) & V22BIS_EQUALIZER_MASK], &zz);
|
|
1304 c = complex_mulf(&s->eq_buf[(s->eq_step - 1) & V22BIS_EQUALIZER_MASK], &zz);
|
|
1305 p = (a.re - c.re)*b.re;
|
|
1306 q = (a.im - c.im)*b.im;
|
|
1307 }
|
|
1308 #endif
|
|
1309
|
|
1310 p += q;
|
|
1311 s->gardner_integrate += ((p + q) > 0.0f) ? s->gardner_step : -s->gardner_step;
|
|
1312
|
|
1313 if (abs(s->gardner_integrate) >= 16)
|
|
1314 {
|
|
1315 /* This integrate and dump approach avoids rapid changes of the equalizer put step.
|
|
1316 Rapid changes, without hysteresis, are bad. They degrade the equalizer performance
|
|
1317 when the true symbol boundary is close to a sample boundary. */
|
|
1318 s->eq_put_step += (s->gardner_integrate/16);
|
|
1319 s->total_baud_timing_correction += (s->gardner_integrate/16);
|
|
1320 span_log(&s->logging, SPAN_LOG_FLOW, "Gardner kick %d [total %d]\n", s->gardner_integrate, s->total_baud_timing_correction);
|
|
1321 if (s->qam_report)
|
|
1322 s->qam_report(s->qam_user_data, NULL, NULL, s->gardner_integrate);
|
|
1323 s->gardner_integrate = 0;
|
|
1324 }
|
|
1325
|
|
1326 z = equalizer_get(s);
|
|
1327 printf("VVV %15.5f %15.5f\n", z.re, z.im);
|
|
1328
|
|
1329 span_log(&s->logging, SPAN_LOG_FLOW, "VVV %p %d\n", s->user_data, s->rx_training);
|
|
1330 if (s->sixteen_way_decisions)
|
|
1331 {
|
|
1332 re = (int) (z.re + 3.0f);
|
|
1333 if (re > 5)
|
|
1334 re = 5;
|
|
1335 else if (re < 0)
|
|
1336 re = 0;
|
|
1337 im = (int) (z.im + 3.0f);
|
|
1338 if (im > 5)
|
|
1339 im = 5;
|
|
1340 else if (im < 0)
|
|
1341 im = 0;
|
|
1342 nearest = space_map_v22bis[re][im];
|
|
1343 }
|
|
1344 else
|
|
1345 {
|
|
1346 zz = complex_setf(3.0f/sqrtf(10.0f), -1.0f/sqrtf(10.0f));
|
|
1347 zz = complex_mulf(&z, &zz);
|
|
1348 nearest = (find_quadrant(&zz) << 2) | 0x01;
|
|
1349 printf("Trackit %15.5f %15.5f %15.5f %15.5f %d\n", z.re, z.im, zz.re, zz.im, nearest);
|
|
1350 }
|
|
1351
|
|
1352 switch (s->rx_training)
|
|
1353 {
|
|
1354 case V22BIS_TRAINING_STAGE_NORMAL_OPERATION:
|
|
1355 /* Normal operation. */
|
|
1356 track_carrier(s, &z, &v22bis_constellation[nearest]);
|
|
1357 tune_equalizer(s, &z, &v22bis_constellation[nearest]);
|
|
1358 decode_baud(s, nearest);
|
|
1359 target = &v22bis_constellation[s->rx_constellation_state];
|
|
1360 break;
|
|
1361 case V22BIS_TRAINING_STAGE_SYMBOL_ACQUISITION:
|
|
1362 /* Allow time for the Gardner algorithm to settle the symbol timing. */
|
|
1363 target = &z;
|
|
1364 if (++s->rx_training_count >= 40)
|
|
1365 {
|
|
1366 s->gardner_step = 4;
|
|
1367 if (s->caller)
|
|
1368 {
|
|
1369 s->rx_training = V22BIS_TRAINING_STAGE_UNSCRAMBLED_ONES;
|
|
1370 }
|
|
1371 else
|
|
1372 {
|
|
1373 if (s->bit_rate == 2400)
|
|
1374 s->rx_training = V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011;
|
|
1375 else
|
|
1376 s->rx_training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
|
|
1377 }
|
|
1378 break;
|
|
1379 }
|
|
1380
|
|
1381 /* QAM and Gardner only play nicely with heavy damping, so we need to change to
|
|
1382 a slow rate of symbol timing adaption. However, it must not be so slow that it
|
|
1383 cannot track the worst case timing error specified in V.22bis. This should be 0.01%,
|
|
1384 but since we might be off in the opposite direction from the source, the total
|
|
1385 error could be higher. */
|
|
1386 if (s->rx_training_count == 30)
|
|
1387 s->gardner_step = 32;
|
|
1388 break;
|
|
1389 case V22BIS_TRAINING_STAGE_UNSCRAMBLED_ONES:
|
|
1390 /* The answering modem should initially receive unscrambled ones at 1200bps */
|
|
1391 track_carrier(s, &z, &v22bis_constellation[nearest]);
|
|
1392 target = &z;
|
|
1393 if (nearest == ((s->rx_constellation_state - 4) & 0x0F))
|
|
1394 s->detected_unscrambled_ones++;
|
|
1395 if (nearest == ((s->rx_constellation_state + 4) & 0x0F))
|
|
1396 s->detected_unscrambled_zeros++;
|
|
1397 s->rx_constellation_state = nearest;
|
|
1398 span_log(&s->logging, SPAN_LOG_FLOW, "TWIDDLING THUMBS - %d\n", s->rx_training_count);
|
|
1399 if (++s->rx_training_count == ms_to_symbols(155 + 456))
|
|
1400 {
|
|
1401 if (s->detected_unscrambled_ones >= 250 || s->detected_unscrambled_zeros >= 250)
|
|
1402 s->detected_unscrambled_ones_or_zeros = TRUE;
|
|
1403 }
|
|
1404 if (s->rx_training_count == ms_to_symbols(155 + 457))
|
|
1405 {
|
|
1406 /* We should only bother looking for the 2400bps marker if we are allowed to use
|
|
1407 2400bps */
|
|
1408 s->rx_training_count = 0;
|
|
1409 if (s->bit_rate == 2400)
|
|
1410 s->rx_training = V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011;
|
|
1411 else
|
|
1412 s->rx_training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
|
|
1413 }
|
|
1414 break;
|
|
1415 case V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011:
|
|
1416 s->sixteen_way_decisions = TRUE;
|
|
1417 /* If we can actually find this it means we can use 2400bps. If we find unscrambled ones, it means we
|
|
1418 we must use 1200bps. */
|
|
1419 track_carrier(s, &z, &v22bis_constellation[nearest]);
|
|
1420 tune_equalizer(s, &z, &v22bis_constellation[nearest]);
|
|
1421 target = &z;
|
|
1422 //s->carrier_track_i = 1000.0f;
|
|
1423 //s->carrier_track_p = 1000000.0f;
|
|
1424 #if 0
|
|
1425 if (++s->rx_training_count > ms_to_symbols(800))
|
|
1426 {
|
|
1427 s->detected_unscrambled_0011_ending = TRUE;
|
|
1428 s->rx_training = V22BIS_TRAINING_STAGE_UNSCRAMBLED_ONES;
|
|
1429 }
|
|
1430 #else
|
|
1431 if (++s->rx_training_count == 1)
|
|
1432 {
|
|
1433 s->detected_unscrambled_zeros = nearest;
|
|
1434 s->detected_unscrambled_ones = 0;
|
|
1435 }
|
|
1436 else
|
|
1437 {
|
|
1438 span_log(&s->logging, SPAN_LOG_FLOW, "0x%X 0x%X 0x%X\n", s->detected_unscrambled_zeros, nearest, (s->detected_unscrambled_zeros + nearest) & 0x0F);
|
|
1439 if ((s->rx_training_count & 1) == 0)
|
|
1440 {
|
|
1441 span_log(&s->logging, SPAN_LOG_FLOW, "AAA\n");
|
|
1442 if (((s->detected_unscrambled_zeros + nearest) & 0x0F) == 0x06)
|
|
1443 s->detected_unscrambled_ones = 1;
|
|
1444 else if (((s->detected_unscrambled_zeros + nearest) & 0x0F) == 0x02)
|
|
1445 s->detected_unscrambled_ones = -1;
|
|
1446 else
|
|
1447 {
|
|
1448 span_log(&s->logging, SPAN_LOG_FLOW, "AAA 1\n");
|
|
1449 if (s->detected_unscrambled_ones > 5 || s->detected_unscrambled_ones < -5)
|
|
1450 s->detected_unscrambled_0011_ending = TRUE;
|
|
1451 else
|
|
1452 s->bit_rate = 1200;
|
|
1453 s->rx_training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
|
|
1454 }
|
|
1455 }
|
|
1456 else
|
|
1457 {
|
|
1458 span_log(&s->logging, SPAN_LOG_FLOW, "BBB\n");
|
|
1459 if (((s->detected_unscrambled_zeros + nearest) & 0x0F) == 0x06)
|
|
1460 s->detected_unscrambled_ones = 1;
|
|
1461 else if (((s->detected_unscrambled_zeros + nearest) & 0x0F) == 0x02)
|
|
1462 s->detected_unscrambled_ones = -1;
|
|
1463 else
|
|
1464 {
|
|
1465 span_log(&s->logging, SPAN_LOG_FLOW, "BBB 1\n");
|
|
1466 if (s->detected_unscrambled_ones > 5 || s->detected_unscrambled_ones < -5)
|
|
1467 s->detected_unscrambled_0011_ending = TRUE;
|
|
1468 else
|
|
1469 s->bit_rate = 1200;
|
|
1470 s->rx_training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200;
|
|
1471 }
|
|
1472 }
|
|
1473 }
|
|
1474 #endif
|
|
1475 break;
|
|
1476 case V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200:
|
|
1477 track_carrier(s, &z, &v22bis_constellation[nearest]);
|
|
1478 tune_equalizer(s, &z, &v22bis_constellation[nearest]);
|
|
1479 target = &z;
|
|
1480 span_log(&s->logging, SPAN_LOG_FLOW, "S11 0x%02x\n", nearest);
|
|
1481 if (++s->rx_training_count > ms_to_symbols(900))
|
|
1482 {
|
|
1483 s->detected_scrambled_ones_or_zeros_at_1200bps = TRUE;
|
|
1484 s->rx_training = V22BIS_TRAINING_STAGE_NORMAL_OPERATION;
|
|
1485 }
|
|
1486 if (s->bit_rate == 2400 && s->rx_training_count == ms_to_symbols(450))
|
|
1487 s->sixteen_way_decisions = TRUE;
|
|
1488 break;
|
|
1489 case V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_2400:
|
|
1490 track_carrier(s, &z, &v22bis_constellation[nearest]);
|
|
1491 tune_equalizer(s, &z, &v22bis_constellation[nearest]);
|
|
1492 s->sixteen_way_decisions = TRUE;
|
|
1493 target = &z;
|
|
1494 break;
|
|
1495 case V22BIS_TRAINING_STAGE_PARKED:
|
|
1496 default:
|
|
1497 /* We failed to train! */
|
|
1498 /* Park here until the carrier drops. */
|
|
1499 target = &z;
|
|
1500 break;
|
|
1501 }
|
|
1502 if (s->qam_report)
|
|
1503 s->qam_report(s->qam_user_data, &z, target, s->rx_constellation_state);
|
|
1504 }
|
|
1505 /*- End of function --------------------------------------------------------*/
|
|
1506
|
|
1507 int v22bis_rx(v22bis_state_t *s, const int16_t amp[], int len)
|
|
1508 {
|
|
1509 int i;
|
|
1510 int j;
|
|
1511 int step;
|
|
1512 complexf_t z;
|
|
1513 complexf_t zz;
|
|
1514 int32_t power;
|
|
1515 complexf_t sample;
|
|
1516 float ii;
|
|
1517 float qq;
|
|
1518
|
|
1519 for (i = 0; i < len; i++)
|
|
1520 {
|
|
1521 /* Complex bandpass filter the signal, using a pair of FIRs, and RRC coeffs shifted
|
|
1522 to centre at 1200Hz or 2400Hz. The filters support 12 fractional phase shifts, to
|
|
1523 permit signal extraction very close to the middle of a symbol. */
|
|
1524 s->rx_rrc_filter[s->rx_rrc_filter_step] =
|
|
1525 s->rx_rrc_filter[s->rx_rrc_filter_step + V22BIS_RX_FILTER_STEPS] = amp[i];
|
|
1526 if (++s->rx_rrc_filter_step >= V22BIS_RX_FILTER_STEPS)
|
|
1527 s->rx_rrc_filter_step = 0;
|
|
1528
|
|
1529 /* Calculate the I filter, with an arbitrary phase step, just so we can calculate
|
|
1530 the signal power. */
|
|
1531 /* TODO: get rid of this */
|
|
1532 if (s->caller)
|
|
1533 {
|
|
1534 ii = pulseshaper_2400[6][0].re*s->rx_rrc_filter[s->rx_rrc_filter_step];
|
|
1535 for (j = 1; j < V22BIS_RX_FILTER_STEPS; j++)
|
|
1536 ii += pulseshaper_2400[6][j].re*s->rx_rrc_filter[j + s->rx_rrc_filter_step];
|
|
1537 }
|
|
1538 else
|
|
1539 {
|
|
1540 ii = pulseshaper_1200[6][0].re*s->rx_rrc_filter[s->rx_rrc_filter_step];
|
|
1541 for (j = 1; j < V22BIS_RX_FILTER_STEPS; j++)
|
|
1542 ii += pulseshaper_1200[6][j].re*s->rx_rrc_filter[j + s->rx_rrc_filter_step];
|
|
1543 }
|
|
1544 power = power_meter_update(&(s->rx_power), (int16_t) (ii/10.0f));
|
|
1545 if (s->carrier_present)
|
|
1546 {
|
|
1547 /* Look for power below -48dBm0 to turn the carrier off */
|
|
1548 if (power < s->carrier_off_power)
|
|
1549 {
|
|
1550 v22bis_rx_restart(s, s->bit_rate);
|
|
1551 s->put_bit(s->user_data, PUTBIT_CARRIER_DOWN);
|
|
1552 continue;
|
|
1553 }
|
|
1554 }
|
|
1555 else
|
|
1556 {
|
|
1557 /* Look for power exceeding -43dBm0 to turn the carrier on */
|
|
1558 if (power < s->carrier_on_power)
|
|
1559 continue;
|
|
1560 s->carrier_present = TRUE;
|
|
1561 s->put_bit(s->user_data, PUTBIT_CARRIER_UP);
|
|
1562 }
|
|
1563 if (s->rx_training != V22BIS_TRAINING_STAGE_PARKED)
|
|
1564 {
|
|
1565 /* Only spend effort processing this data if the modem is not
|
|
1566 parked, after training failure. */
|
|
1567 z = dds_complexf(&(s->rx_carrier_phase), s->rx_carrier_phase_rate);
|
|
1568 if (s->rx_training == V22BIS_TRAINING_STAGE_SYMBOL_ACQUISITION)
|
|
1569 {
|
|
1570 /* Only AGC during the initial symbol acquisition, and then lock the gain. */
|
|
1571 s->agc_scaling = 0.018f*3.60f/sqrtf(power);
|
|
1572 }
|
|
1573 /* Put things into the equalization buffer at T/2 rate. The Gardner algorithm
|
|
1574 will fiddle the step to align this with the symbols. */
|
|
1575 if ((s->eq_put_step -= PULSESHAPER_COEFF_SETS) <= 0)
|
|
1576 {
|
|
1577 /* Pulse shape while still at the carrier frequency, using a quadrature
|
|
1578 pair of filters. This results in a properly bandpass filtered complex
|
|
1579 signal, which can be brought directly to bandband by complex mixing.
|
|
1580 No further filtering, to remove mixer harmonics, is needed. */
|
|
1581 step = -s->eq_put_step;
|
|
1582 if (step > PULSESHAPER_COEFF_SETS - 1)
|
|
1583 step = PULSESHAPER_COEFF_SETS - 1;
|
|
1584 s->eq_put_step += PULSESHAPER_COEFF_SETS*40/(3*2);
|
|
1585 if (s->caller)
|
|
1586 {
|
|
1587 ii = pulseshaper_2400[step][0].re*s->rx_rrc_filter[s->rx_rrc_filter_step];
|
|
1588 qq = pulseshaper_2400[step][0].im*s->rx_rrc_filter[s->rx_rrc_filter_step];
|
|
1589 for (j = 1; j < V22BIS_RX_FILTER_STEPS; j++)
|
|
1590 {
|
|
1591 ii += pulseshaper_2400[step][j].re*s->rx_rrc_filter[j + s->rx_rrc_filter_step];
|
|
1592 qq += pulseshaper_2400[step][j].im*s->rx_rrc_filter[j + s->rx_rrc_filter_step];
|
|
1593 }
|
|
1594 }
|
|
1595 else
|
|
1596 {
|
|
1597 ii = pulseshaper_1200[step][0].re*s->rx_rrc_filter[s->rx_rrc_filter_step];
|
|
1598 qq = pulseshaper_1200[step][0].im*s->rx_rrc_filter[s->rx_rrc_filter_step];
|
|
1599 for (j = 1; j < V22BIS_RX_FILTER_STEPS; j++)
|
|
1600 {
|
|
1601 ii += pulseshaper_1200[step][j].re*s->rx_rrc_filter[j + s->rx_rrc_filter_step];
|
|
1602 qq += pulseshaper_1200[step][j].im*s->rx_rrc_filter[j + s->rx_rrc_filter_step];
|
|
1603 }
|
|
1604 }
|
|
1605 sample.re = ii*s->agc_scaling;
|
|
1606 sample.im = qq*s->agc_scaling;
|
|
1607 /* Shift to baseband - since this is done in a full complex form, the
|
|
1608 result is clean, and requires no further filtering apart from the
|
|
1609 equalizer. */
|
|
1610 zz.re = sample.re*z.re - sample.im*z.im;
|
|
1611 zz.im = -sample.re*z.im - sample.im*z.re;
|
|
1612 process_half_baud(s, &zz);
|
|
1613 }
|
|
1614 }
|
|
1615 }
|
|
1616 return 0;
|
|
1617 }
|
|
1618 /*- End of function --------------------------------------------------------*/
|
|
1619
|
|
1620 int v22bis_rx_restart(v22bis_state_t *s, int bit_rate)
|
|
1621 {
|
|
1622 /* If bit_rate is 2400, the real bit rate is negotiated. If bit_rate
|
|
1623 is 1200, the real bit rate is forced to 1200. */
|
|
1624 s->bit_rate = bit_rate;
|
|
1625 vec_zerof(s->rx_rrc_filter, sizeof(s->rx_rrc_filter)/sizeof(s->rx_rrc_filter[0]));
|
|
1626 s->rx_rrc_filter_step = 0;
|
|
1627 s->rx_scramble_reg = 0;
|
|
1628 s->rx_scrambler_pattern_count = 0;
|
|
1629 s->rx_training = V22BIS_TRAINING_STAGE_SYMBOL_ACQUISITION;
|
|
1630 s->rx_training_count = 0;
|
|
1631 s->carrier_present = FALSE;
|
|
1632
|
|
1633 s->rx_carrier_phase_rate = dds_phase_ratef((s->caller) ? 2400.0f : 1200.0f);
|
|
1634 s->rx_carrier_phase = 0;
|
|
1635 power_meter_init(&(s->rx_power), 5);
|
|
1636 s->carrier_on_power = power_meter_level_dbm0(-43);
|
|
1637 s->carrier_off_power = power_meter_level_dbm0(-48);
|
|
1638 s->agc_scaling = 0.0005f*0.025f;
|
|
1639
|
|
1640 s->rx_constellation_state = 0;
|
|
1641 s->sixteen_way_decisions = FALSE;
|
|
1642
|
|
1643 equalizer_reset(s);
|
|
1644
|
|
1645 s->detected_unscrambled_ones = 0;
|
|
1646 s->detected_unscrambled_zeros = 0;
|
|
1647 s->gardner_integrate = 0;
|
|
1648 s->gardner_step = 256;
|
|
1649 s->rx_baud_phase = 0;
|
|
1650 s->carrier_track_i = 8000.0f;
|
|
1651 s->carrier_track_p = 8000000.0f;
|
|
1652 return 0;
|
|
1653 }
|
|
1654 /*- End of function --------------------------------------------------------*/
|
|
1655
|
|
1656 void v22bis_rx_set_qam_report_handler(v22bis_state_t *s, qam_report_handler_t *handler, void *user_data)
|
|
1657 {
|
|
1658 s->qam_report = handler;
|
|
1659 s->qam_user_data = user_data;
|
|
1660 }
|
|
1661 /*- End of function --------------------------------------------------------*/
|
|
1662 /*- End of file ------------------------------------------------------------*/
|