Mercurial > hg > audiostuff
comparison spandsp-0.0.3/spandsp-0.0.3/src/v22bis_rx.c @ 5:f762bf195c4b
import spandsp-0.0.3
author | Peter Meerwald <pmeerw@cosy.sbg.ac.at> |
---|---|
date | Fri, 25 Jun 2010 16:00:21 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
4:26cd8f1ef0b1 | 5:f762bf195c4b |
---|---|
1 /* | |
2 * SpanDSP - a series of DSP components for telephony | |
3 * | |
4 * v22bis_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 ------------------------------------------------------------*/ |