comparison spandsp-0.0.3/spandsp-0.0.3/src/v29rx.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 * v29rx.c - ITU V.29 modem receive part
5 *
6 * Written by Steve Underwood <steveu@coppice.org>
7 *
8 * Copyright (C) 2003 Steve Underwood
9 *
10 * All rights reserved.
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2, as
14 * published by the Free Software Foundation.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 *
25 * $Id: v29rx.c,v 1.100 2006/11/28 16:59:57 steveu Exp $
26 */
27
28 /*! \file */
29
30 #ifdef HAVE_CONFIG_H
31 #include <config.h>
32 #endif
33
34 #include <inttypes.h>
35 #include <string.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #if defined(HAVE_TGMATH_H)
39 #include <tgmath.h>
40 #endif
41 #if defined(HAVE_MATH_H)
42 #include <math.h>
43 #endif
44
45 #include "spandsp/telephony.h"
46 #include "spandsp/logging.h"
47 #include "spandsp/complex.h"
48 #include "spandsp/vector_float.h"
49 #include "spandsp/complex_vector_float.h"
50 #include "spandsp/async.h"
51 #include "spandsp/power_meter.h"
52 #include "spandsp/arctan2.h"
53 #include "spandsp/dds.h"
54 #include "spandsp/complex_filters.h"
55
56 #include "spandsp/v29rx.h"
57
58 #define CARRIER_NOMINAL_FREQ 1700.0f
59 #define BAUD_RATE 2400
60 #define EQUALIZER_DELTA 0.21f
61
62 /* Segments of the training sequence */
63 #define V29_TRAINING_SEG_2_LEN 128
64 #define V29_TRAINING_SEG_3_LEN 384
65 #define V29_TRAINING_SEG_4_LEN 48
66
67 enum
68 {
69 TRAINING_STAGE_NORMAL_OPERATION = 0,
70 TRAINING_STAGE_SYMBOL_ACQUISITION,
71 TRAINING_STAGE_LOG_PHASE,
72 TRAINING_STAGE_WAIT_FOR_CDCD,
73 TRAINING_STAGE_TRAIN_ON_CDCD,
74 TRAINING_STAGE_TRAIN_ON_CDCD_AND_TEST,
75 TRAINING_STAGE_TEST_ONES,
76 TRAINING_STAGE_PARKED
77 };
78
79 static const complexf_t v29_constellation[16] =
80 {
81 { 3.0f, 0.0f}, /* 0deg low */
82 { 1.0f, 1.0f}, /* 45deg low */
83 { 0.0f, 3.0f}, /* 90deg low */
84 {-1.0f, 1.0f}, /* 135deg low */
85 {-3.0f, 0.0f}, /* 180deg low */
86 {-1.0f, -1.0f}, /* 225deg low */
87 { 0.0f, -3.0f}, /* 270deg low */
88 { 1.0f, -1.0f}, /* 315deg low */
89 { 5.0f, 0.0f}, /* 0deg high */
90 { 3.0f, 3.0f}, /* 45deg high */
91 { 0.0f, 5.0f}, /* 90deg high */
92 {-3.0f, 3.0f}, /* 135deg high */
93 {-5.0f, 0.0f}, /* 180deg high */
94 {-3.0f, -3.0f}, /* 225deg high */
95 { 0.0f, -5.0f}, /* 270deg high */
96 { 3.0f, -3.0f} /* 315deg high */
97 };
98
99 static const uint8_t space_map_9600[20][20] =
100 {
101 {13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11},
102 {13, 13, 13, 13, 13, 13, 13, 12, 12, 12, 12, 12, 12, 11, 11, 11, 11, 11, 11, 11},
103 {13, 13, 13, 13, 13, 13, 13, 4, 4, 4, 4, 4, 4, 11, 11, 11, 11, 11, 11, 11},
104 {13, 13, 13, 13, 13, 13, 13, 4, 4, 4, 4, 4, 4, 11, 11, 11, 11, 11, 11, 11},
105 {13, 13, 13, 13, 13, 13, 13, 4, 4, 4, 4, 4, 4, 11, 11, 11, 11, 11, 11, 11},
106 {13, 13, 13, 13, 13, 13, 13, 5, 4, 4, 4, 4, 3, 11, 11, 11, 11, 11, 11, 11},
107 {14, 13, 13, 13, 13, 13, 5, 5, 5, 5, 3, 3, 3, 3, 11, 11, 11, 11, 11, 10},
108 {14, 14, 6, 6, 6, 5, 5, 5, 5, 5, 3, 3, 3, 3, 3, 2, 2, 2, 10, 10},
109 {14, 14, 6, 6, 6, 6, 5, 5, 5, 5, 3, 3, 3, 3, 2, 2, 2, 2, 10, 10},
110 {14, 14, 6, 6, 6, 6, 5, 5, 5, 5, 3, 3, 3, 3, 2, 2, 2, 2, 10, 10},
111 {14, 14, 6, 6, 6, 6, 7, 7, 7, 7, 1, 1, 1, 1, 2, 2, 2, 2, 10, 10},
112 {14, 14, 6, 6, 6, 6, 7, 7, 7, 7, 1, 1, 1, 1, 2, 2, 2, 2, 10, 10},
113 {14, 14, 6, 6, 6, 7, 7, 7, 7, 7, 1, 1, 1, 1, 1, 2, 2, 2, 10, 10},
114 {14, 15, 15, 15, 15, 15, 7, 7, 7, 7, 1, 1, 1, 1, 9, 9, 9, 9, 9, 10},
115 {15, 15, 15, 15, 15, 15, 15, 7, 0, 0, 0, 0, 1, 9, 9, 9, 9, 9, 9, 9},
116 {15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9},
117 {15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9},
118 {15, 15, 15, 15, 15, 15, 15, 0, 0, 0, 0, 0, 0, 9, 9, 9, 9, 9, 9, 9},
119 {15, 15, 15, 15, 15, 15, 15, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9},
120 {15, 15, 15, 15, 15, 15, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9}
121 };
122
123 /* Raised root cosine pulse shaping; Beta = 0.5; 4 symbols either
124 side of the centre. We cannot simplify this by using only half
125 the filter, as each variant are each skewed by n/PULSESHAPER_COEFF_SETS of a
126 sample. Only one is symmetric. */
127 #define PULSESHAPER_GAIN 10.00736638f
128 #define PULSESHAPER_COEFF_SETS 48
129 static const complexf_t pulseshaper[PULSESHAPER_COEFF_SETS][V29_RX_FILTER_STEPS] =
130 {
131 {
132 {-0.0006054906f, -0.0076934875f}, /* Filter 0 */
133 { 0.0036800486f, -0.0011957203f},
134 {-0.0058580399f, -0.0095594523f},
135 { 0.0088272477f, -0.0088272477f},
136 {-0.0070156625f, -0.0042992035f},
137 { 0.0051634535f, -0.0158914757f},
138 {-0.0145681539f, -0.0011465386f},
139 {-0.0064674675f, -0.0408339830f},
140 {-0.0136664375f, 0.0056608238f},
141 {-0.0772003348f, -0.1062571451f},
142 { 0.0857393910f, -0.1003879288f},
143 {-0.1385128868f, -0.0705758409f},
144 { 0.1555698727f, -0.6479951549f},
145 { 1.0773601675f, 0.0000000000f},
146 { 0.2515047363f, 1.0475926203f},
147 {-0.5937739316f, 0.3025429295f},
148 {-0.1009610161f, -0.1182101618f},
149 {-0.0775987390f, 0.1068055014f},
150 {-0.1213433119f, -0.0502620455f},
151 { 0.0023140483f, -0.0146103259f},
152 {-0.0412155371f, 0.0032437331f},
153 {-0.0045157276f, -0.0138979805f},
154 {-0.0142470087f, 0.0087305782f},
155 {-0.0058181901f, -0.0058181901f},
156 {-0.0065226701f, 0.0106440302f},
157 {-0.0106628561f, -0.0034645720f},
158 {-0.0003035921f, 0.0038575039f},
159 },
160 {
161 {-0.0003235976f, -0.0041116977f}, /* Filter 1 */
162 { 0.0034317849f, -0.0011150545f},
163 {-0.0059948336f, -0.0097826794f},
164 { 0.0086437458f, -0.0086437458f},
165 {-0.0074140419f, -0.0045433307f},
166 { 0.0050851588f, -0.0156505094f},
167 {-0.0154601145f, -0.0012167374f},
168 {-0.0064469783f, -0.0407046190f},
169 {-0.0156933045f, 0.0065003796f},
170 {-0.0783633460f, -0.1078578927f},
171 { 0.0839596331f, -0.0983041000f},
172 {-0.1466635902f, -0.0747288317f},
173 { 0.1581236518f, -0.6586324102f},
174 { 1.0822215889f, 0.0000000000f},
175 { 0.2503251863f, 1.0426794408f},
176 {-0.5839878512f, 0.2975566724f},
177 {-0.0950902426f, -0.1113363693f},
178 {-0.0791302548f, 0.1089134521f},
179 {-0.1194691818f, -0.0494857553f},
180 { 0.0019760247f, -0.0124761291f},
181 {-0.0413061980f, 0.0032508683f},
182 {-0.0042392071f, -0.0130469379f},
183 {-0.0144455612f, 0.0088522513f},
184 {-0.0054839934f, -0.0054839934f},
185 {-0.0066522258f, 0.0108554460f},
186 {-0.0104075179f, -0.0033816075f},
187 {-0.0003235976f, 0.0041116977f},
188 },
189 {
190 {-0.0003431146f, -0.0043596842f}, /* Filter 2 */
191 { 0.0031779221f, -0.0010325695f},
192 {-0.0061279979f, -0.0099999837f},
193 { 0.0084521727f, -0.0084521727f},
194 {-0.0078074148f, -0.0047843899f},
195 { 0.0050005298f, -0.0153900482f},
196 {-0.0163511406f, -0.0012868627f},
197 {-0.0064201364f, -0.0405351459f},
198 {-0.0177497724f, 0.0073521965f},
199 {-0.0794957450f, -0.1094165063f},
200 { 0.0820917217f, -0.0961170567f},
201 {-0.1549087286f, -0.0789299396f},
202 { 0.1606663689f, -0.6692235895f},
203 { 1.0868898157f, 0.0000000000f},
204 { 0.2491014054f, 1.0375820265f},
205 {-0.5741661901f, 0.2925522861f},
206 {-0.0892910248f, -0.1045463576f},
207 {-0.0805830641f, 0.1109130726f},
208 {-0.1175509420f, -0.0486911944f},
209 { 0.0016433282f, -0.0103755662f},
210 {-0.0413575411f, 0.0032549091f},
211 {-0.0039628985f, -0.0121965475f},
212 {-0.0146266493f, 0.0089632222f},
213 {-0.0051463192f, -0.0051463192f},
214 {-0.0067756751f, 0.0110568969f},
215 {-0.0101460989f, -0.0032966674f},
216 {-0.0003431146f, 0.0043596842f},
217 },
218 {
219 {-0.0003621305f, -0.0046013044f}, /* Filter 3 */
220 { 0.0029186307f, -0.0009483206f},
221 {-0.0062573914f, -0.0102111348f},
222 { 0.0082526365f, -0.0082526365f},
223 {-0.0081953754f, -0.0050221325f},
224 { 0.0049095725f, -0.0151101104f},
225 {-0.0172404079f, -0.0013568495f},
226 {-0.0063868556f, -0.0403250190f},
227 {-0.0198348595f, 0.0082158678f},
228 {-0.0805962556f, -0.1109312291f},
229 { 0.0801351139f, -0.0938261634f},
230 {-0.1632463544f, -0.0831781721f},
231 { 0.1631971552f, -0.6797650728f},
232 { 1.0913630919f, 0.0000000000f},
233 { 0.2478338529f, 1.0323022902f},
234 {-0.5643122679f, 0.2875314620f},
235 {-0.0835646644f, -0.0978416511f},
236 {-0.0819577515f, 0.1128051674f},
237 {-0.1155905906f, -0.0478791903f},
238 { 0.0013161074f, -0.0083095754f},
239 {-0.0413701808f, 0.0032559039f},
240 {-0.0036870475f, -0.0113475654f},
241 {-0.0147903020f, 0.0090635087f},
242 {-0.0048055043f, -0.0048055043f},
243 {-0.0068929555f, 0.0112482810f},
244 {-0.0098788669f, -0.0032098384f},
245 {-0.0003621305f, 0.0046013044f},
246 },
247 {
248 {-0.0003806334f, -0.0048364061f}, /* Filter 4 */
249 { 0.0026540877f, -0.0008623654f},
250 {-0.0063828750f, -0.0104159053f},
251 { 0.0080452535f, -0.0080452535f},
252 {-0.0085775184f, -0.0052563101f},
253 { 0.0048122983f, -0.0148107313f},
254 {-0.0181270820f, -0.0014266323f},
255 {-0.0063470532f, -0.0400737166f},
256 {-0.0219475497f, 0.0090909727f},
257 {-0.0816636012f, -0.1124003042f},
258 { 0.0780893017f, -0.0914308250f},
259 {-0.1716744668f, -0.0874725099f},
260 { 0.1657151424f, -0.6902532446f},
261 { 1.0956397332f, 0.0000000000f},
262 { 0.2465230038f, 1.0268422107f},
263 {-0.5544294025f, 0.2824958906f},
264 {-0.0779124236f, -0.0912237273f},
265 {-0.0832549311f, 0.1145905820f},
266 {-0.1135901216f, -0.0470505689f},
267 { 0.0009945051f, -0.0062790582f},
268 {-0.0413447525f, 0.0032539026f},
269 {-0.0034118961f, -0.0105007365f},
270 {-0.0149365628f, 0.0091531374f},
271 {-0.0044618854f, -0.0044618854f},
272 {-0.0070040103f, 0.0114295060f},
273 {-0.0096060925f, -0.0031212087f},
274 {-0.0003806334f, 0.0048364061f},
275 },
276 {
277 {-0.0003986119f, -0.0050648440f}, /* Filter 5 */
278 { 0.0023844759f, -0.0007747632f},
279 {-0.0065043116f, -0.0106140718f},
280 { 0.0078301476f, -0.0078301476f},
281 {-0.0089534403f, -0.0054866753f},
282 { 0.0047087245f, -0.0144919637f},
283 {-0.0190103194f, -0.0014961446f},
284 {-0.0063006503f, -0.0397807405f},
285 {-0.0240867927f, 0.0099770762f},
286 {-0.0826965057f, -0.1138219754f},
287 { 0.0759538132f, -0.0889304892f},
288 {-0.1801910135f, -0.0918119071f},
289 { 0.1682194641f, -0.7006844950f},
290 { 1.0997181284f, 0.0000000000f},
291 { 0.2451693490f, 1.0212038328f},
292 {-0.5445209082f, 0.2774472605f},
293 {-0.0723355236f, -0.0846940164f},
294 {-0.0844752467f, 0.1162702023f},
295 {-0.1115515226f, -0.0462061535f},
296 { 0.0006786580f, -0.0042848780f},
297 {-0.0412819110f, 0.0032489569f},
298 {-0.0031376826f, -0.0096567942f},
299 {-0.0150654901f, 0.0092321442f},
300 {-0.0041157984f, -0.0041157984f},
301 {-0.0071087889f, 0.0116004892f},
302 {-0.0093280490f, -0.0030308668f},
303 {-0.0003986119f, 0.0050648440f},
304 },
305 {
306 {-0.0004160550f, -0.0052864799f}, /* Filter 6 */
307 { 0.0021099840f, -0.0006855754f},
308 {-0.0066215668f, -0.0108054149f},
309 { 0.0076074506f, -0.0076074506f},
310 {-0.0093227386f, -0.0057129815f},
311 { 0.0045988736f, -0.0141538775f},
312 {-0.0198892682f, -0.0015653194f},
313 {-0.0062475719f, -0.0394456164f},
314 {-0.0262515049f, 0.0108737293f},
315 {-0.0836936943f, -0.1151944878f},
316 { 0.0737282126f, -0.0863246457f},
317 {-0.1887938905f, -0.0961952919f},
318 { 0.1707092554f, -0.7110552220f},
319 { 1.1035967397f, 0.0000000000f},
320 { 0.2437733949f, 1.0153892656f},
321 {-0.5345900940f, 0.2723872580f},
322 {-0.0668351454f, -0.0782539010f},
323 {-0.0856193708f, 0.1178449541f},
324 {-0.1094767749f, -0.0453467649f},
325 { 0.0003686970f, -0.0023278610f},
326 {-0.0411823301f, 0.0032411197f},
327 {-0.0028646414f, -0.0088164597f},
328 {-0.0151771562f, 0.0093005733f},
329 {-0.0037675783f, -0.0037675783f},
330 {-0.0072072465f, 0.0117611574f},
331 {-0.0090450120f, -0.0029389025f},
332 {-0.0004160550f, 0.0052864799f},
333 },
334 {
335 {-0.0004329524f, -0.0055011823f}, /* Filter 7 */
336 { 0.0018308065f, -0.0005948651f},
337 {-0.0067345088f, -0.0109897195f},
338 { 0.0073773020f, -0.0073773020f},
339 {-0.0096850130f, -0.0059349836f},
340 { 0.0044827743f, -0.0137965606f},
341 {-0.0207630684f, -0.0016340889f},
342 {-0.0061877467f, -0.0390678953f},
343 {-0.0284405684f, 0.0117804691f},
344 {-0.0846538939f, -0.1165160891f},
345 { 0.0714121011f, -0.0836128276f},
346 {-0.1974809435f, -0.1006215665f},
347 { 0.1731836536f, -0.7213618325f},
348 { 1.1072741035f, 0.0000000000f},
349 { 0.2423356631f, 1.0094006816f},
350 {-0.5246402627f, 0.2673175657f},
351 {-0.0614124285f, -0.0719047153f},
352 {-0.0866880040f, 0.1193158015f},
353 {-0.1073678519f, -0.0444732204f},
354 { 0.0000647469f, -0.0004087959f},
355 {-0.0410467015f, 0.0032304455f},
356 {-0.0025930028f, -0.0079804420f},
357 {-0.0152716480f, 0.0093584780f},
358 {-0.0034175587f, -0.0034175587f},
359 {-0.0072993441f, 0.0119114470f},
360 {-0.0087572594f, -0.0028454060f},
361 {-0.0004329524f, 0.0055011823f},
362 },
363 {
364 {-0.0004492944f, -0.0057088271f}, /* Filter 8 */
365 { 0.0015471436f, -0.0005026974f},
366 {-0.0068430082f, -0.0111667745f},
367 { 0.0071398493f, -0.0071398493f},
368 {-0.0100398656f, -0.0061524375f},
369 { 0.0043604608f, -0.0134201184f},
370 {-0.0216308523f, -0.0017023850f},
371 {-0.0061211077f, -0.0386471532f},
372 {-0.0306528326f, 0.0126968190f},
373 {-0.0855758340f, -0.1177850307f},
374 { 0.0690051173f, -0.0807946117f},
375 {-0.2062499680f, -0.1050896077f},
376 { 0.1756417989f, -0.7316007446f},
377 { 1.1107488316f, 0.0000000000f},
378 { 0.2408566902f, 1.0032403162f},
379 {-0.5146747091f, 0.2622398626f},
380 {-0.0560684714f, -0.0656477454f},
381 {-0.0876818748f, 0.1206837473f},
382 {-0.1052267179f, -0.0435863337f},
383 {-0.0002330732f, 0.0014715664f},
384 {-0.0408757346f, 0.0032169901f},
385 {-0.0023229930f, -0.0071494373f},
386 {-0.0153490660f, 0.0094059197f},
387 {-0.0030660718f, -0.0030660718f},
388 {-0.0073850485f, 0.0120513039f},
389 {-0.0084650709f, -0.0027504683f},
390 {-0.0004492944f, 0.0057088271f},
391 },
392 {
393 {-0.0004650718f, -0.0059092972f}, /* Filter 9 */
394 { 0.0012592008f, -0.0004091391f},
395 {-0.0069469389f, -0.0113363740f},
396 { 0.0068952472f, -0.0068952472f},
397 {-0.0103869007f, -0.0063651009f},
398 { 0.0042319732f, -0.0130246742f},
399 {-0.0224917457f, -0.0017701388f},
400 {-0.0060475918f, -0.0381829922f},
401 {-0.0328871136f, 0.0136222885f},
402 {-0.0864582472f, -0.1189995684f},
403 { 0.0665069376f, -0.0778696190f},
404 {-0.2150987105f, -0.1095982672f},
405 { 0.1780828343f, -0.7417683886f},
406 { 1.1140196110f, 0.0000000000f},
407 { 0.2393370276f, 0.9969104659f},
408 {-0.5046967186f, 0.2571558224f},
409 {-0.0508043306f, -0.0594842284f},
410 {-0.0886017384f, 0.1219498309f},
411 {-0.1030553278f, -0.0426869144f},
412 {-0.0005246505f, 0.0033125128f},
413 {-0.0406701557f, 0.0032008107f},
414 {-0.0020548339f, -0.0063241284f},
415 {-0.0154095242f, 0.0094429686f},
416 {-0.0027134480f, -0.0027134480f},
417 {-0.0074643325f, 0.0121806836f},
418 {-0.0081687281f, -0.0026541806f},
419 {-0.0004650718f, 0.0059092972f},
420 },
421 {
422 {-0.0004802758f, -0.0061024829f}, /* Filter 10 */
423 { 0.0009671895f, -0.0003142589f},
424 {-0.0070461774f, -0.0114983165f},
425 { 0.0066436583f, -0.0066436583f},
426 {-0.0107257260f, -0.0065727333f},
427 { 0.0040973574f, -0.0126103693f},
428 {-0.0233448674f, -0.0018372809f},
429 {-0.0059671403f, -0.0376750413f},
430 {-0.0351421949f, 0.0145563737f},
431 {-0.0872998705f, -0.1201579635f},
432 { 0.0639172763f, -0.0748375152f},
433 {-0.2240248692f, -0.1141463722f},
434 { 0.1805059061f, -0.7518612089f},
435 { 1.1170852055f, 0.0000000000f},
436 { 0.2377772412f, 0.9904134878f},
437 {-0.4947095655f, 0.2520671138f},
438 {-0.0456210210f, -0.0534153526f},
439 {-0.0894483767f, 0.1231151286f},
440 {-0.1008556255f, -0.0417757679f},
441 {-0.0008098779f, 0.0051133675f},
442 {-0.0404307068f, 0.0031819656f},
443 {-0.0017887430f, -0.0055051847f},
444 {-0.0154531504f, 0.0094697028f},
445 {-0.0023600156f, -0.0023600156f},
446 {-0.0075371745f, 0.0122995509f},
447 {-0.0078685137f, -0.0025566351f},
448 {-0.0004802758f, 0.0061024829f},
449 },
450 {
451 {-0.0004948985f, -0.0062882817f}, /* Filter 11 */
452 { 0.0006713257f, -0.0002181269f},
453 {-0.0071406035f, -0.0116524059f},
454 { 0.0063852527f, -0.0063852526f},
455 {-0.0110559525f, -0.0067750964f},
456 { 0.0039566651f, -0.0121773631f},
457 {-0.0241893313f, -0.0019037417f},
458 {-0.0058796987f, -0.0371229566f},
459 {-0.0374168281f, 0.0154985577f},
460 {-0.0880994453f, -0.1212584838f},
461 { 0.0612358868f, -0.0716980115f},
462 {-0.2330260947f, -0.1187327256f},
463 { 0.1829101645f, -0.7618756659f},
464 { 1.1199444556f, 0.0000000000f},
465 { 0.2361779109f, 0.9837517978f},
466 {-0.4847165122f, 0.2469753988f},
467 {-0.0405195152f, -0.0474422567f},
468 {-0.0902225974f, 0.1241807520f},
469 {-0.0986295432f, -0.0408536944f},
470 {-0.0010886543f, 0.0068734926f},
471 {-0.0401581456f, 0.0031605146f},
472 {-0.0015249332f, -0.0046932617f},
473 {-0.0154800853f, 0.0094862085f},
474 {-0.0020061005f, -0.0020061005f},
475 {-0.0076035587f, 0.0124078801f},
476 {-0.0075647115f, -0.0024579238f},
477 {-0.0004948985f, 0.0062882817f},
478 },
479 {
480 {-0.0005089323f, -0.0064665981f}, /* Filter 12 */
481 { 0.0003718310f, -0.0001208152f},
482 {-0.0072301003f, -0.0117984513f},
483 { 0.0061202077f, -0.0061202077f},
484 {-0.0113771948f, -0.0069719540f},
485 { 0.0038099540f, -0.0117258328f},
486 {-0.0250242456f, -0.0019694508f},
487 {-0.0057852169f, -0.0365264219f},
488 {-0.0397097323f, 0.0164483097f},
489 {-0.0888557186f, -0.1222994047f},
490 { 0.0584625613f, -0.0684508645f},
491 {-0.2420999907f, -0.1233561066f},
492 { 0.1852947639f, -0.7718082372f},
493 { 1.1225962793f, 0.0000000000f},
494 { 0.2345396308f, 0.9769278702f},
495 {-0.4747208072f, 0.2418823327f},
496 {-0.0355007435f, -0.0415660302f},
497 {-0.0909252334f, 0.1251478474f},
498 {-0.0963790005f, -0.0399214891f},
499 {-0.0013608847f, 0.0085922877f},
500 {-0.0398532442f, 0.0031365183f},
501 {-0.0012636128f, -0.0038890004f},
502 {-0.0154904827f, 0.0094925800f},
503 {-0.0016520262f, -0.0016520262f},
504 {-0.0076634750f, 0.0125056546f},
505 {-0.0072576065f, -0.0023581393f},
506 {-0.0005089323f, 0.0064665981f},
507 },
508 {
509 {-0.0005223703f, -0.0066373443f}, /* Filter 13 */
510 { 0.0000689315f, -0.0000223972f},
511 {-0.0073145539f, -0.0119362671f},
512 { 0.0058487082f, -0.0058487082f},
513 {-0.0116890717f, -0.0071630723f},
514 { 0.0036572876f, -0.0112559738f},
515 {-0.0258487141f, -0.0020343379f},
516 {-0.0056836493f, -0.0358851497f},
517 {-0.0420195954f, 0.0174050863f},
518 {-0.0895674434f, -0.1232790098f},
519 { 0.0555971318f, -0.0650958776f},
520 {-0.2512441154f, -0.1280152709f},
521 { 0.1876588631f, -0.7816554194f},
522 { 1.1250396727f, 0.0000000000f},
523 { 0.2328630086f, 0.9699442360f},
524 {-0.4647256838f, 0.2367895630f},
525 {-0.0305655940f, -0.0357877124f},
526 {-0.0915571420f, 0.1260175949f},
527 {-0.0941059032f, -0.0389799414f},
528 {-0.0016264798f, 0.0102691896f},
529 {-0.0395167881f, 0.0031100387f},
530 {-0.0010049855f, -0.0030930272f},
531 {-0.0154845091f, 0.0094889194f},
532 {-0.0012981133f, -0.0012981133f},
533 {-0.0077169192f, 0.0125928676f},
534 {-0.0069474841f, -0.0022573744f},
535 {-0.0005223703f, 0.0066373443f},
536 },
537 {
538 {-0.0005352062f, -0.0068004397f}, /* Filter 14 */
539 {-0.0002371416f, 0.0000770520f},
540 {-0.0073938544f, -0.0120656738f},
541 { 0.0055709463f, -0.0055709463f},
542 {-0.0119912063f, -0.0073482207f},
543 { 0.0034987353f, -0.0107680002f},
544 {-0.0266618369f, -0.0020983321f},
545 {-0.0055749551f, -0.0351988812f},
546 {-0.0443450744f, 0.0183683312f},
547 {-0.0902333798f, -0.1241955926f},
548 { 0.0526394697f, -0.0616329003f},
549 {-0.2604559819f, -0.1327089513f},
550 { 0.1900016262f, -0.7914137299f},
551 { 1.1272737104f, 0.0000000000f},
552 { 0.2311486652f, 0.9628034819f},
553 {-0.4547343588f, 0.2316987286f},
554 {-0.0257149117f, -0.0301082932f},
555 {-0.0921192046f, 0.1267912077f},
556 {-0.0918121426f, -0.0380298346f},
557 {-0.0018853566f, 0.0119036728f},
558 {-0.0391495767f, 0.0030811385f},
559 {-0.0007492498f, -0.0023059539f},
560 {-0.0154623431f, 0.0094753361f},
561 {-0.0009446795f, -0.0009446795f},
562 {-0.0077638924f, 0.0126695210f},
563 {-0.0066346301f, -0.0021557220f},
564 {-0.0005352062f, 0.0068004397f},
565 },
566 {
567 {-0.0005474342f, -0.0069558110f}, /* Filter 15 */
568 {-0.0005461525f, 0.0001774557f},
569 {-0.0074678951f, -0.0121864973f},
570 { 0.0052871211f, -0.0052871211f},
571 {-0.0122832268f, -0.0075271711f},
572 { 0.0033343726f, -0.0102621437f},
573 {-0.0274627107f, -0.0021613622f},
574 {-0.0054590979f, -0.0344673874f},
575 {-0.0466847952f, 0.0193374753f},
576 {-0.0908522954f, -0.1250474569f},
577 { 0.0495894870f, -0.0580618293f},
578 {-0.2697330596f, -0.1374358585f},
579 { 0.1923222223f, -0.8010797080f},
580 { 1.1292975460f, 0.0000000000f},
581 { 0.2293972347f, 0.9555082489f},
582 {-0.4447500311f, 0.2266114595f},
583 {-0.0209494991f, -0.0245287119f},
584 {-0.0926123259f, 0.1274699310f},
585 {-0.0894995944f, -0.0370719458f},
586 {-0.0021374375f, 0.0134952491f},
587 {-0.0387524213f, 0.0030498817f},
588 {-0.0004965997f, -0.0015283766f},
589 {-0.0154241758f, 0.0094519471f},
590 {-0.0005920390f, -0.0005920390f},
591 {-0.0078044017f, 0.0127356261f},
592 {-0.0063193305f, -0.0020532749f},
593 {-0.0005474342f, 0.0069558110f},
594 },
595 {
596 {-0.0005590491f, -0.0071033921f}, /* Filter 16 */
597 {-0.0008578611f, 0.0002787360f},
598 {-0.0075365733f, -0.0122985698f},
599 { 0.0049974389f, -0.0049974388f},
600 {-0.0125647661f, -0.0076996986f},
601 { 0.0031642806f, -0.0097386544f},
602 {-0.0282504297f, -0.0022233570f},
603 {-0.0053360461f, -0.0336904691f},
604 {-0.0490373539f, 0.0203119370f},
605 {-0.0914229663f, -0.1258329180f},
606 { 0.0464471360f, -0.0543826090f},
607 {-0.2790727745f, -0.1421946809f},
608 { 0.1946198263f, -0.8106499175f},
609 { 1.1311104123f, 0.0000000000f},
610 { 0.2276093640f, 0.9480612314f},
611 {-0.4347758804f, 0.2215293759f},
612 {-0.0162701156f, -0.0190498578f},
613 {-0.0930374331f, 0.1280550409f},
614 {-0.0871701184f, -0.0361070452f},
615 {-0.0023826511f, 0.0150434671f},
616 {-0.0383261449f, 0.0030163330f},
617 {-0.0002472237f, -0.0007608763f},
618 {-0.0153702098f, 0.0094188767f},
619 {-0.0002405024f, -0.0002405024f},
620 {-0.0078384594f, 0.0127912031f},
621 {-0.0060018711f, -0.0019501261f},
622 {-0.0005590491f, 0.0071033921f},
623 },
624 {
625 {-0.0005700463f, -0.0072431248f}, /* Filter 17 */
626 {-0.0011720231f, 0.0003808134f},
627 {-0.0075997900f, -0.0124017301f},
628 { 0.0047021127f, -0.0047021127f},
629 {-0.0128354632f, -0.0078655819f},
630 { 0.0029885467f, -0.0091978010f},
631 {-0.0290240862f, -0.0022842451f},
632 {-0.0052057731f, -0.0328679578f},
633 {-0.0514013169f, 0.0212911226f},
634 {-0.0919441775f, -0.1265503037f},
635 { 0.0432124100f, -0.0505952315f},
636 {-0.2884725105f, -0.1469840856f},
637 { 0.1968936193f, -0.8201209469f},
638 { 1.1327116219f, 0.0000000000f},
639 { 0.2257857123f, 0.9404651753f},
640 {-0.4248150656f, 0.2164540873f},
641 {-0.0116774779f, -0.0136725700f},
642 {-0.0933954755f, 0.1285478440f},
643 {-0.0848255565f, -0.0351358959f},
644 {-0.0026209319f, 0.0165479125f},
645 {-0.0378715811f, 0.0029805581f},
646 {-0.0000013054f, -0.0000040177f},
647 {-0.0153006596f, 0.0093762563f},
648 { 0.0001096232f, 0.0001096232f},
649 {-0.0078660833f, 0.0128362814f},
650 {-0.0056825374f, -0.0018463683f},
651 {-0.0005700463f, 0.0072431248f},
652 },
653 {
654 {-0.0005804218f, -0.0073749578f}, /* Filter 18 */
655 {-0.0014883899f, 0.0004836072f},
656 {-0.0076574502f, -0.0124958231f},
657 { 0.0044013628f, -0.0044013628f},
658 {-0.0130949624f, -0.0080246033f},
659 { 0.0028072639f, -0.0086398699f},
660 {-0.0297827710f, -0.0023439549f},
661 {-0.0050682571f, -0.0319997159f},
662 {-0.0537752213f, 0.0222744260f},
663 {-0.0924147241f, -0.1271979554f},
664 { 0.0398853435f, -0.0466997371f},
665 {-0.2979296109f, -0.1518027189f},
666 { 0.1991427888f, -0.8294894121f},
667 { 1.1341005677f, 0.0000000000f},
668 { 0.2239269510f, 0.9327228772f},
669 {-0.4148707237f, 0.2113871920f},
670 {-0.0071722592f, -0.0083976366f},
671 {-0.0936874236f, 0.1289496760f},
672 {-0.0824677330f, -0.0341592535f},
673 {-0.0028522199f, 0.0180082079f},
674 {-0.0373895741f, 0.0029426233f},
675 { 0.0002409767f, 0.0007416500f},
676 {-0.0152157506f, 0.0093242240f},
677 { 0.0004580348f, 0.0004580348f},
678 {-0.0078872970f, 0.0128708989f},
679 {-0.0053616143f, -0.0017420941f},
680 {-0.0005804218f, 0.0073749578f},
681 },
682 {
683 {-0.0005901721f, -0.0074988473f}, /* Filter 19 */
684 {-0.0018067093f, 0.0005870354f},
685 {-0.0077094631f, -0.0125807004f},
686 { 0.0040954155f, -0.0040954155f},
687 {-0.0133429149f, -0.0081765487f},
688 { 0.0026205314f, -0.0080651662f},
689 {-0.0305255746f, -0.0024024148f},
690 {-0.0049234813f, -0.0310856377f},
691 {-0.0561575756f, 0.0232612294f},
692 {-0.0928334114f, -0.1277742292f},
693 { 0.0364660122f, -0.0426962145f},
694 {-0.3074413786f, -0.1566492066f},
695 { 0.2013665292f, -0.8387519577f},
696 { 1.1352767227f, 0.0000000000f},
697 { 0.2220337633f, 0.9248371830f},
698 {-0.4049459681f, 0.2063302764f},
699 {-0.0027550900f, -0.0032257959f},
700 {-0.0939142683f, 0.1292619011f},
701 {-0.0800984531f, -0.0331778656f},
702 {-0.0030764613f, 0.0194240122f},
703 {-0.0368809773f, 0.0029025959f},
704 { 0.0004794497f, 0.0014755944f},
705 {-0.0151157193f, 0.0092629247f},
706 { 0.0008044337f, 0.0008044337f},
707 {-0.0079021290f, 0.0128951026f},
708 {-0.0050393858f, -0.0016373957f},
709 {-0.0005901721f, 0.0074988473f},
710 },
711 {
712 {-0.0005992944f, -0.0076147568f}, /* Filter 20 */
713 {-0.0021267251f, 0.0006910149f},
714 {-0.0077557420f, -0.0126562207f},
715 { 0.0037845040f, -0.0037845040f},
716 {-0.0135789777f, -0.0083212083f},
717 { 0.0024284540f, -0.0074740128f},
718 {-0.0312515874f, -0.0024595533f},
719 {-0.0047714341f, -0.0301256492f},
720 {-0.0585468603f, 0.0242509035f},
721 {-0.0931990565f, -0.1282774964f},
722 { 0.0329545338f, -0.0385848015f},
723 {-0.3170050775f, -0.1615221547f},
724 { 0.2035640423f, -0.8479052583f},
725 { 1.1362396407f, 0.0000000000f},
726 { 0.2201068440f, 0.9168109865f},
727 {-0.3950438879f, 0.2012849146f},
728 { 0.0015734425f, 0.0018422645f},
729 {-0.0940770209f, 0.1294859108f},
730 {-0.0777195022f, -0.0321924719f},
731 {-0.0032936077f, 0.0207950209f},
732 {-0.0363466528f, 0.0028605436f},
733 { 0.0007139459f, 0.0021972995f},
734 {-0.0150008130f, 0.0091925101f},
735 { 0.0011485255f, 0.0011485255f},
736 {-0.0079106134f, 0.0129089479f},
737 {-0.0047161348f, -0.0015323651f},
738 {-0.0005992944f, 0.0076147568f},
739 },
740 {
741 {-0.0006077863f, -0.0077226571f}, /* Filter 21 */
742 {-0.0024481778f, 0.0007954612f},
743 {-0.0077962045f, -0.0127222494f},
744 { 0.0034688681f, -0.0034688681f},
745 {-0.0138028157f, -0.0084583763f},
746 { 0.0022311426f, -0.0068667508f},
747 {-0.0319599006f, -0.0025152987f},
748 {-0.0046121088f, -0.0291197091f},
749 {-0.0609415283f, 0.0252428075f},
750 {-0.0935104881f, -0.1287061452f},
751 { 0.0293510677f, -0.0343656849f},
752 {-0.3266179339f, -0.1664201496f},
753 { 0.2057345372f, -0.8569460203f},
754 { 1.1369889562f, 0.0000000000f},
755 { 0.2181468989f, 0.9086472276f},
756 {-0.3851675459f, 0.1962526670f},
757 { 0.0058127944f, 0.0068059078f},
758 {-0.0941767115f, 0.1296231230f},
759 {-0.0753326453f, -0.0312038034f},
760 {-0.0035036167f, 0.0221209652f},
761 {-0.0357874706f, 0.0028165350f},
762 { 0.0009443030f, 0.0029062658f},
763 {-0.0148712891f, 0.0091131377f},
764 { 0.0014900206f, 0.0014900206f},
765 {-0.0079127895f, 0.0129124989f},
766 {-0.0043921429f, -0.0014270937f},
767 {-0.0006077863f, 0.0077226571f},
768 },
769 {
770 {-0.0006156462f, -0.0078225266f}, /* Filter 22 */
771 {-0.0027708045f, 0.0009002890f},
772 {-0.0078307725f, -0.0127786593f},
773 { 0.0031487534f, -0.0031487534f},
774 {-0.0140141002f, -0.0085878517f},
775 { 0.0020287139f, -0.0062437395f},
776 {-0.0326496069f, -0.0025695798f},
777 {-0.0044455042f, -0.0280678087f},
778 {-0.0633400059f, 0.0262362895f},
779 {-0.0937665479f, -0.1290585813f},
780 { 0.0256558155f, -0.0300391005f},
781 {-0.3362771370f, -0.1713417594f},
782 { 0.2078772313f, -0.8658709834f},
783 { 1.1375243848f, 0.0000000000f},
784 { 0.2161546447f, 0.9003488919f},
785 {-0.3753199780f, 0.1912350805f},
786 { 0.0099624646f, 0.0116645474f},
787 {-0.0942143887f, 0.1296749813f},
788 {-0.0729396259f, -0.0302125823f},
789 {-0.0037064513f, 0.0234016123f},
790 {-0.0352043080f, 0.0027706391f},
791 { 0.0011703644f, 0.0036020111f},
792 {-0.0147274152f, 0.0090249716f},
793 { 0.0018286340f, 0.0018286340f},
794 {-0.0079087015f, 0.0129058279f},
795 {-0.0040676902f, -0.0013216727f},
796 {-0.0006156462f, 0.0078225266f},
797 },
798 {
799 {-0.0006228729f, -0.0079143505f}, /* Filter 23 */
800 {-0.0030943393f, 0.0010054118f},
801 {-0.0078593727f, -0.0128253306f},
802 { 0.0028244120f, -0.0028244120f},
803 {-0.0142125109f, -0.0087094379f},
804 { 0.0018212906f, -0.0056053560f},
805 {-0.0333198014f, -0.0026223252f},
806 {-0.0042716241f, -0.0269699732f},
807 {-0.0657406925f, 0.0272306864f},
808 {-0.0939660909f, -0.1293332287f},
809 { 0.0218690212f, -0.0256053340f},
810 {-0.3459798404f, -0.1762855337f},
811 { 0.2099913501f, -0.8746769223f},
812 { 1.1378457233f, 0.0000000000f},
813 { 0.2141308087f, 0.8919190081f},
814 {-0.3655041913f, 0.1862336874f},
815 { 0.0140219952f, 0.0164176470f},
816 {-0.0941911192f, 0.1296429536f},
817 {-0.0705421655f, -0.0292195216f},
818 {-0.0039020802f, 0.0246367649f},
819 {-0.0345980484f, 0.0027229255f},
820 { 0.0013919788f, 0.0042840703f},
821 {-0.0145694683f, 0.0089281816f},
822 { 0.0021640858f, 0.0021640858f},
823 {-0.0078983989f, 0.0128890156f},
824 {-0.0037430549f, -0.0012161922f},
825 {-0.0006228729f, 0.0079143505f},
826 },
827 {
828 {-0.0006294658f, -0.0079981214f}, /* Filter 24 */
829 {-0.0034185133f, 0.0011107423f},
830 {-0.0078819362f, -0.0128621510f},
831 { 0.0024961016f, -0.0024961016f},
832 {-0.0143977349f, -0.0088229433f},
833 { 0.0016090008f, -0.0049519954f},
834 {-0.0339695814f, -0.0026734640f},
835 {-0.0040904779f, -0.0258262610f},
836 {-0.0681419627f, 0.0282253251f},
837 {-0.0941079866f, -0.1295285313f},
838 { 0.0179909715f, -0.0210647211f},
839 {-0.3557231633f, -0.1812500047f},
840 { 0.2120761281f, -0.8833606476f},
841 { 1.1379528497f, 0.0000000000f},
842 { 0.2120761281f, 0.8833606476f},
843 {-0.3557231633f, 0.1812500047f},
844 { 0.0179909715f, 0.0210647211f},
845 {-0.0941079866f, 0.1295285313f},
846 {-0.0681419627f, -0.0282253251f},
847 {-0.0040904779f, 0.0258262610f},
848 {-0.0339695814f, 0.0026734640f},
849 { 0.0016090008f, 0.0049519954f},
850 {-0.0143977349f, 0.0088229433f},
851 { 0.0024961016f, 0.0024961016f},
852 {-0.0078819362f, 0.0128621510f},
853 {-0.0034185133f, -0.0011107423f},
854 {-0.0006294658f, 0.0079981214f},
855 },
856 {
857 {-0.0006354249f, -0.0080738393f}, /* Filter 25 */
858 {-0.0037430549f, 0.0012161922f},
859 {-0.0078983989f, -0.0128890156f},
860 { 0.0021640858f, -0.0021640858f},
861 {-0.0145694683f, -0.0089281816f},
862 { 0.0013919788f, -0.0042840703f},
863 {-0.0345980484f, -0.0027229255f},
864 {-0.0039020802f, -0.0246367649f},
865 {-0.0705421655f, 0.0292195216f},
866 {-0.0941911192f, -0.1296429536f},
867 { 0.0140219952f, -0.0164176470f},
868 {-0.3655041913f, -0.1862336874f},
869 { 0.2141308087f, -0.8919190081f},
870 { 1.1378457233f, 0.0000000000f},
871 { 0.2099913501f, 0.8746769223f},
872 {-0.3459798404f, 0.1762855337f},
873 { 0.0218690212f, 0.0256053340f},
874 {-0.0939660909f, 0.1293332287f},
875 {-0.0657406925f, -0.0272306864f},
876 {-0.0042716241f, 0.0269699732f},
877 {-0.0333198014f, 0.0026223252f},
878 { 0.0018212906f, 0.0056053560f},
879 {-0.0142125109f, 0.0087094379f},
880 { 0.0028244120f, 0.0028244120f},
881 {-0.0078593727f, 0.0128253306f},
882 {-0.0030943393f, -0.0010054118f},
883 {-0.0006354249f, 0.0080738393f},
884 },
885 {
886 {-0.0006407508f, -0.0081415109f}, /* Filter 26 */
887 {-0.0040676902f, 0.0013216727f},
888 {-0.0079087015f, -0.0129058279f},
889 { 0.0018286340f, -0.0018286340f},
890 {-0.0147274152f, -0.0090249716f},
891 { 0.0011703644f, -0.0036020111f},
892 {-0.0352043080f, -0.0027706391f},
893 {-0.0037064513f, -0.0234016123f},
894 {-0.0729396259f, 0.0302125823f},
895 {-0.0942143887f, -0.1296749813f},
896 { 0.0099624646f, -0.0116645474f},
897 {-0.3753199780f, -0.1912350805f},
898 { 0.2161546447f, -0.9003488919f},
899 { 1.1375243848f, 0.0000000000f},
900 { 0.2078772313f, 0.8658709834f},
901 {-0.3362771370f, 0.1713417594f},
902 { 0.0256558155f, 0.0300391005f},
903 {-0.0937665479f, 0.1290585813f},
904 {-0.0633400059f, -0.0262362895f},
905 {-0.0044455042f, 0.0280678087f},
906 {-0.0326496069f, 0.0025695798f},
907 { 0.0020287139f, 0.0062437395f},
908 {-0.0140141002f, 0.0085878517f},
909 { 0.0031487534f, 0.0031487534f},
910 {-0.0078307725f, 0.0127786593f},
911 {-0.0027708045f, -0.0009002890f},
912 {-0.0006407508f, 0.0081415109f},
913 },
914 {
915 {-0.0006454445f, -0.0082011502f}, /* Filter 27 */
916 {-0.0043921429f, 0.0014270937f},
917 {-0.0079127895f, -0.0129124989f},
918 { 0.0014900206f, -0.0014900206f},
919 {-0.0148712891f, -0.0091131377f},
920 { 0.0009443030f, -0.0029062658f},
921 {-0.0357874706f, -0.0028165350f},
922 {-0.0035036167f, -0.0221209652f},
923 {-0.0753326453f, 0.0312038034f},
924 {-0.0941767115f, -0.1296231230f},
925 { 0.0058127944f, -0.0068059078f},
926 {-0.3851675459f, -0.1962526670f},
927 { 0.2181468989f, -0.9086472276f},
928 { 1.1369889562f, 0.0000000000f},
929 { 0.2057345372f, 0.8569460203f},
930 {-0.3266179339f, 0.1664201496f},
931 { 0.0293510677f, 0.0343656849f},
932 {-0.0935104881f, 0.1287061452f},
933 {-0.0609415283f, -0.0252428075f},
934 {-0.0046121088f, 0.0291197091f},
935 {-0.0319599006f, 0.0025152987f},
936 { 0.0022311426f, 0.0068667508f},
937 {-0.0138028157f, 0.0084583763f},
938 { 0.0034688681f, 0.0034688681f},
939 {-0.0077962045f, 0.0127222494f},
940 {-0.0024481778f, -0.0007954612f},
941 {-0.0006454445f, 0.0082011502f},
942 },
943 {
944 {-0.0006495077f, -0.0082527783f}, /* Filter 28 */
945 {-0.0047161348f, 0.0015323651f},
946 {-0.0079106134f, -0.0129089479f},
947 { 0.0011485255f, -0.0011485255f},
948 {-0.0150008130f, -0.0091925101f},
949 { 0.0007139459f, -0.0021972995f},
950 {-0.0363466528f, -0.0028605436f},
951 {-0.0032936077f, -0.0207950209f},
952 {-0.0777195022f, 0.0321924719f},
953 {-0.0940770209f, -0.1294859108f},
954 { 0.0015734425f, -0.0018422645f},
955 {-0.3950438879f, -0.2012849146f},
956 { 0.2201068440f, -0.9168109865f},
957 { 1.1362396407f, 0.0000000000f},
958 { 0.2035640423f, 0.8479052583f},
959 {-0.3170050775f, 0.1615221547f},
960 { 0.0329545338f, 0.0385848015f},
961 {-0.0931990565f, 0.1282774964f},
962 {-0.0585468603f, -0.0242509035f},
963 {-0.0047714341f, 0.0301256492f},
964 {-0.0312515874f, 0.0024595533f},
965 { 0.0024284540f, 0.0074740128f},
966 {-0.0135789777f, 0.0083212083f},
967 { 0.0037845040f, 0.0037845040f},
968 {-0.0077557420f, 0.0126562207f},
969 {-0.0021267251f, -0.0006910149f},
970 {-0.0006495077f, 0.0082527783f},
971 },
972 {
973 {-0.0006529426f, -0.0082964229f}, /* Filter 29 */
974 {-0.0050393858f, 0.0016373957f},
975 {-0.0079021290f, -0.0128951026f},
976 { 0.0008044337f, -0.0008044337f},
977 {-0.0151157193f, -0.0092629247f},
978 { 0.0004794497f, -0.0014755944f},
979 {-0.0368809773f, -0.0029025959f},
980 {-0.0030764613f, -0.0194240122f},
981 {-0.0800984531f, 0.0331778656f},
982 {-0.0939142683f, -0.1292619011f},
983 {-0.0027550900f, 0.0032257959f},
984 {-0.4049459681f, -0.2063302764f},
985 { 0.2220337633f, -0.9248371830f},
986 { 1.1352767227f, 0.0000000000f},
987 { 0.2013665292f, 0.8387519577f},
988 {-0.3074413786f, 0.1566492066f},
989 { 0.0364660122f, 0.0426962145f},
990 {-0.0928334114f, 0.1277742292f},
991 {-0.0561575756f, -0.0232612294f},
992 {-0.0049234813f, 0.0310856377f},
993 {-0.0305255746f, 0.0024024148f},
994 { 0.0026205314f, 0.0080651662f},
995 {-0.0133429149f, 0.0081765487f},
996 { 0.0040954155f, 0.0040954155f},
997 {-0.0077094631f, 0.0125807004f},
998 {-0.0018067093f, -0.0005870354f},
999 {-0.0006529426f, 0.0082964229f},
1000 },
1001 {
1002 {-0.0006557520f, -0.0083321188f}, /* Filter 30 */
1003 {-0.0053616143f, 0.0017420941f},
1004 {-0.0078872970f, -0.0128708989f},
1005 { 0.0004580348f, -0.0004580348f},
1006 {-0.0152157506f, -0.0093242240f},
1007 { 0.0002409767f, -0.0007416500f},
1008 {-0.0373895741f, -0.0029426233f},
1009 {-0.0028522199f, -0.0180082079f},
1010 {-0.0824677330f, 0.0341592535f},
1011 {-0.0936874236f, -0.1289496760f},
1012 {-0.0071722592f, 0.0083976366f},
1013 {-0.4148707237f, -0.2113871920f},
1014 { 0.2239269510f, -0.9327228772f},
1015 { 1.1341005677f, 0.0000000000f},
1016 { 0.1991427888f, 0.8294894121f},
1017 {-0.2979296109f, 0.1518027189f},
1018 { 0.0398853435f, 0.0466997371f},
1019 {-0.0924147241f, 0.1271979554f},
1020 {-0.0537752213f, -0.0222744260f},
1021 {-0.0050682571f, 0.0319997159f},
1022 {-0.0297827710f, 0.0023439549f},
1023 { 0.0028072639f, 0.0086398699f},
1024 {-0.0130949624f, 0.0080246033f},
1025 { 0.0044013628f, 0.0044013628f},
1026 {-0.0076574502f, 0.0124958231f},
1027 {-0.0014883899f, -0.0004836072f},
1028 {-0.0006557520f, 0.0083321188f},
1029 },
1030 {
1031 {-0.0006579390f, -0.0083599075f}, /* Filter 31 */
1032 {-0.0056825374f, 0.0018463683f},
1033 {-0.0078660833f, -0.0128362814f},
1034 { 0.0001096232f, -0.0001096232f},
1035 {-0.0153006596f, -0.0093762563f},
1036 {-0.0000013054f, 0.0000040177f},
1037 {-0.0378715811f, -0.0029805581f},
1038 {-0.0026209319f, -0.0165479125f},
1039 {-0.0848255565f, 0.0351358959f},
1040 {-0.0933954755f, -0.1285478440f},
1041 {-0.0116774779f, 0.0136725700f},
1042 {-0.4248150656f, -0.2164540873f},
1043 { 0.2257857123f, -0.9404651753f},
1044 { 1.1327116219f, 0.0000000000f},
1045 { 0.1968936193f, 0.8201209469f},
1046 {-0.2884725105f, 0.1469840856f},
1047 { 0.0432124100f, 0.0505952315f},
1048 {-0.0919441775f, 0.1265503037f},
1049 {-0.0514013169f, -0.0212911226f},
1050 {-0.0052057731f, 0.0328679578f},
1051 {-0.0290240862f, 0.0022842451f},
1052 { 0.0029885467f, 0.0091978010f},
1053 {-0.0128354632f, 0.0078655819f},
1054 { 0.0047021127f, 0.0047021127f},
1055 {-0.0075997900f, 0.0124017301f},
1056 {-0.0011720231f, -0.0003808134f},
1057 {-0.0006579390f, 0.0083599075f},
1058 },
1059 {
1060 {-0.0006595075f, -0.0083798372f}, /* Filter 32 */
1061 {-0.0060018711f, 0.0019501261f},
1062 {-0.0078384594f, -0.0127912031f},
1063 {-0.0002405024f, 0.0002405024f},
1064 {-0.0153702098f, -0.0094188767f},
1065 {-0.0002472237f, 0.0007608763f},
1066 {-0.0383261449f, -0.0030163330f},
1067 {-0.0023826511f, -0.0150434671f},
1068 {-0.0871701184f, 0.0361070452f},
1069 {-0.0930374331f, -0.1280550409f},
1070 {-0.0162701156f, 0.0190498578f},
1071 {-0.4347758804f, -0.2215293759f},
1072 { 0.2276093640f, -0.9480612314f},
1073 { 1.1311104123f, 0.0000000000f},
1074 { 0.1946198263f, 0.8106499175f},
1075 {-0.2790727745f, 0.1421946809f},
1076 { 0.0464471360f, 0.0543826090f},
1077 {-0.0914229663f, 0.1258329180f},
1078 {-0.0490373539f, -0.0203119370f},
1079 {-0.0053360461f, 0.0336904691f},
1080 {-0.0282504297f, 0.0022233570f},
1081 { 0.0031642806f, 0.0097386544f},
1082 {-0.0125647661f, 0.0076996986f},
1083 { 0.0049974389f, 0.0049974388f},
1084 {-0.0075365733f, 0.0122985698f},
1085 {-0.0008578611f, -0.0002787360f},
1086 {-0.0006595075f, 0.0083798372f},
1087 },
1088 {
1089 {-0.0006604618f, -0.0083919627f}, /* Filter 33 */
1090 {-0.0063193305f, 0.0020532749f},
1091 {-0.0078044017f, -0.0127356261f},
1092 {-0.0005920390f, 0.0005920390f},
1093 {-0.0154241758f, -0.0094519471f},
1094 {-0.0004965997f, 0.0015283766f},
1095 {-0.0387524213f, -0.0030498817f},
1096 {-0.0021374375f, -0.0134952491f},
1097 {-0.0894995944f, 0.0370719458f},
1098 {-0.0926123259f, -0.1274699310f},
1099 {-0.0209494991f, 0.0245287119f},
1100 {-0.4447500311f, -0.2266114595f},
1101 { 0.2293972347f, -0.9555082489f},
1102 { 1.1292975460f, 0.0000000000f},
1103 { 0.1923222223f, 0.8010797080f},
1104 {-0.2697330596f, 0.1374358585f},
1105 { 0.0495894870f, 0.0580618293f},
1106 {-0.0908522954f, 0.1250474569f},
1107 {-0.0466847952f, -0.0193374753f},
1108 {-0.0054590979f, 0.0344673874f},
1109 {-0.0274627107f, 0.0021613622f},
1110 { 0.0033343726f, 0.0102621437f},
1111 {-0.0122832268f, 0.0075271711f},
1112 { 0.0052871211f, 0.0052871211f},
1113 {-0.0074678951f, 0.0121864973f},
1114 {-0.0005461525f, -0.0001774557f},
1115 {-0.0006604618f, 0.0083919627f},
1116 },
1117 {
1118 {-0.0006608067f, -0.0083963451f}, /* Filter 34 */
1119 {-0.0066346301f, 0.0021557220f},
1120 {-0.0077638924f, -0.0126695210f},
1121 {-0.0009446795f, 0.0009446795f},
1122 {-0.0154623431f, -0.0094753361f},
1123 {-0.0007492498f, 0.0023059539f},
1124 {-0.0391495767f, -0.0030811385f},
1125 {-0.0018853566f, -0.0119036728f},
1126 {-0.0918121426f, 0.0380298346f},
1127 {-0.0921192046f, -0.1267912077f},
1128 {-0.0257149117f, 0.0301082932f},
1129 {-0.4547343588f, -0.2316987286f},
1130 { 0.2311486652f, -0.9628034819f},
1131 { 1.1272737104f, 0.0000000000f},
1132 { 0.1900016262f, 0.7914137299f},
1133 {-0.2604559819f, 0.1327089513f},
1134 { 0.0526394697f, 0.0616329003f},
1135 {-0.0902333798f, 0.1241955926f},
1136 {-0.0443450744f, -0.0183683312f},
1137 {-0.0055749551f, 0.0351988812f},
1138 {-0.0266618369f, 0.0020983321f},
1139 { 0.0034987353f, 0.0107680002f},
1140 {-0.0119912063f, 0.0073482207f},
1141 { 0.0055709463f, 0.0055709463f},
1142 {-0.0073938544f, 0.0120656738f},
1143 {-0.0002371416f, -0.0000770520f},
1144 {-0.0006608067f, 0.0083963451f},
1145 },
1146 {
1147 {-0.0006605475f, -0.0083930522f}, /* Filter 35 */
1148 {-0.0069474841f, 0.0022573744f},
1149 {-0.0077169192f, -0.0125928676f},
1150 {-0.0012981133f, 0.0012981133f},
1151 {-0.0154845091f, -0.0094889194f},
1152 {-0.0010049855f, 0.0030930272f},
1153 {-0.0395167881f, -0.0031100387f},
1154 {-0.0016264798f, -0.0102691896f},
1155 {-0.0941059032f, 0.0389799414f},
1156 {-0.0915571420f, -0.1260175949f},
1157 {-0.0305655940f, 0.0357877124f},
1158 {-0.4647256838f, -0.2367895630f},
1159 { 0.2328630086f, -0.9699442360f},
1160 { 1.1250396727f, 0.0000000000f},
1161 { 0.1876588631f, 0.7816554194f},
1162 {-0.2512441154f, 0.1280152709f},
1163 { 0.0555971318f, 0.0650958776f},
1164 {-0.0895674434f, 0.1232790098f},
1165 {-0.0420195954f, -0.0174050863f},
1166 {-0.0056836493f, 0.0358851497f},
1167 {-0.0258487141f, 0.0020343379f},
1168 { 0.0036572876f, 0.0112559738f},
1169 {-0.0116890717f, 0.0071630723f},
1170 { 0.0058487082f, 0.0058487082f},
1171 {-0.0073145539f, 0.0119362671f},
1172 { 0.0000689315f, 0.0000223972f},
1173 {-0.0006605475f, 0.0083930522f},
1174 },
1175 {
1176 {-0.0006596901f, -0.0083821579f}, /* Filter 36 */
1177 {-0.0072576065f, 0.0023581393f},
1178 {-0.0076634750f, -0.0125056546f},
1179 {-0.0016520262f, 0.0016520262f},
1180 {-0.0154904827f, -0.0094925800f},
1181 {-0.0012636128f, 0.0038890004f},
1182 {-0.0398532442f, -0.0031365183f},
1183 {-0.0013608847f, -0.0085922877f},
1184 {-0.0963790005f, 0.0399214891f},
1185 {-0.0909252334f, -0.1251478474f},
1186 {-0.0355007435f, 0.0415660302f},
1187 {-0.4747208072f, -0.2418823327f},
1188 { 0.2345396308f, -0.9769278702f},
1189 { 1.1225962793f, 0.0000000000f},
1190 { 0.1852947639f, 0.7718082372f},
1191 {-0.2420999907f, 0.1233561066f},
1192 { 0.0584625613f, 0.0684508645f},
1193 {-0.0888557186f, 0.1222994047f},
1194 {-0.0397097323f, -0.0164483097f},
1195 {-0.0057852169f, 0.0365264219f},
1196 {-0.0250242456f, 0.0019694508f},
1197 { 0.0038099540f, 0.0117258328f},
1198 {-0.0113771948f, 0.0069719540f},
1199 { 0.0061202077f, 0.0061202077f},
1200 {-0.0072301003f, 0.0117984513f},
1201 { 0.0003718310f, 0.0001208152f},
1202 {-0.0006596901f, 0.0083821579f},
1203 },
1204 {
1205 {-0.0006582408f, -0.0083637423f}, /* Filter 37 */
1206 {-0.0075647115f, 0.0024579238f},
1207 {-0.0076035587f, -0.0124078801f},
1208 {-0.0020061005f, 0.0020061005f},
1209 {-0.0154800853f, -0.0094862085f},
1210 {-0.0015249332f, 0.0046932617f},
1211 {-0.0401581456f, -0.0031605146f},
1212 {-0.0010886543f, -0.0068734926f},
1213 {-0.0986295432f, 0.0408536944f},
1214 {-0.0902225974f, -0.1241807520f},
1215 {-0.0405195152f, 0.0474422567f},
1216 {-0.4847165122f, -0.2469753988f},
1217 { 0.2361779109f, -0.9837517978f},
1218 { 1.1199444556f, 0.0000000000f},
1219 { 0.1829101645f, 0.7618756659f},
1220 {-0.2330260947f, 0.1187327256f},
1221 { 0.0612358868f, 0.0716980115f},
1222 {-0.0880994453f, 0.1212584838f},
1223 {-0.0374168281f, -0.0154985577f},
1224 {-0.0058796987f, 0.0371229566f},
1225 {-0.0241893313f, 0.0019037417f},
1226 { 0.0039566651f, 0.0121773631f},
1227 {-0.0110559525f, 0.0067750964f},
1228 { 0.0063852527f, 0.0063852526f},
1229 {-0.0071406035f, 0.0116524059f},
1230 { 0.0006713257f, 0.0002181269f},
1231 {-0.0006582408f, 0.0083637423f},
1232 },
1233 {
1234 {-0.0006562063f, -0.0083378917f}, /* Filter 38 */
1235 {-0.0078685137f, 0.0025566351f},
1236 {-0.0075371745f, -0.0122995509f},
1237 {-0.0023600156f, 0.0023600156f},
1238 {-0.0154531504f, -0.0094697028f},
1239 {-0.0017887430f, 0.0055051847f},
1240 {-0.0404307068f, -0.0031819656f},
1241 {-0.0008098779f, -0.0051133675f},
1242 {-0.1008556255f, 0.0417757679f},
1243 {-0.0894483767f, -0.1231151286f},
1244 {-0.0456210210f, 0.0534153526f},
1245 {-0.4947095655f, -0.2520671138f},
1246 { 0.2377772412f, -0.9904134878f},
1247 { 1.1170852055f, 0.0000000000f},
1248 { 0.1805059061f, 0.7518612089f},
1249 {-0.2240248692f, 0.1141463722f},
1250 { 0.0639172763f, 0.0748375152f},
1251 {-0.0872998705f, 0.1201579635f},
1252 {-0.0351421949f, -0.0145563737f},
1253 {-0.0059671403f, 0.0376750413f},
1254 {-0.0233448674f, 0.0018372809f},
1255 { 0.0040973574f, 0.0126103693f},
1256 {-0.0107257260f, 0.0065727333f},
1257 { 0.0066436583f, 0.0066436583f},
1258 {-0.0070461774f, 0.0114983165f},
1259 { 0.0009671895f, 0.0003142589f},
1260 {-0.0006562063f, 0.0083378917f},
1261 },
1262 {
1263 {-0.0006535939f, -0.0083046980f}, /* Filter 39 */
1264 {-0.0081687281f, 0.0026541806f},
1265 {-0.0074643325f, -0.0121806836f},
1266 {-0.0027134480f, 0.0027134480f},
1267 {-0.0154095242f, -0.0094429686f},
1268 {-0.0020548339f, 0.0063241284f},
1269 {-0.0406701557f, -0.0032008107f},
1270 {-0.0005246505f, -0.0033125128f},
1271 {-0.1030553278f, 0.0426869144f},
1272 {-0.0886017384f, -0.1219498309f},
1273 {-0.0508043306f, 0.0594842284f},
1274 {-0.5046967186f, -0.2571558224f},
1275 { 0.2393370276f, -0.9969104659f},
1276 { 1.1140196110f, 0.0000000000f},
1277 { 0.1780828343f, 0.7417683886f},
1278 {-0.2150987105f, 0.1095982672f},
1279 { 0.0665069376f, 0.0778696190f},
1280 {-0.0864582472f, 0.1189995684f},
1281 {-0.0328871136f, -0.0136222885f},
1282 {-0.0060475918f, 0.0381829922f},
1283 {-0.0224917457f, 0.0017701388f},
1284 { 0.0042319732f, 0.0130246742f},
1285 {-0.0103869007f, 0.0063651009f},
1286 { 0.0068952472f, 0.0068952472f},
1287 {-0.0069469389f, 0.0113363740f},
1288 { 0.0012592008f, 0.0004091391f},
1289 {-0.0006535939f, 0.0083046980f},
1290 },
1291 {
1292 {-0.0006504113f, -0.0082642593f}, /* Filter 40 */
1293 {-0.0084650709f, 0.0027504683f},
1294 {-0.0073850485f, -0.0120513039f},
1295 {-0.0030660718f, 0.0030660718f},
1296 {-0.0153490660f, -0.0094059197f},
1297 {-0.0023229930f, 0.0071494373f},
1298 {-0.0408757346f, -0.0032169901f},
1299 {-0.0002330732f, -0.0014715664f},
1300 {-0.1052267179f, 0.0435863337f},
1301 {-0.0876818748f, -0.1206837473f},
1302 {-0.0560684714f, 0.0656477454f},
1303 {-0.5146747091f, -0.2622398626f},
1304 { 0.2408566902f, -1.0032403162f},
1305 { 1.1107488316f, 0.0000000000f},
1306 { 0.1756417989f, 0.7316007446f},
1307 {-0.2062499680f, 0.1050896077f},
1308 { 0.0690051173f, 0.0807946117f},
1309 {-0.0855758340f, 0.1177850307f},
1310 {-0.0306528326f, -0.0126968190f},
1311 {-0.0061211077f, 0.0386471532f},
1312 {-0.0216308523f, 0.0017023850f},
1313 { 0.0043604608f, 0.0134201184f},
1314 {-0.0100398656f, 0.0061524375f},
1315 { 0.0071398493f, 0.0071398493f},
1316 {-0.0068430082f, 0.0111667745f},
1317 { 0.0015471436f, 0.0005026974f},
1318 {-0.0006504113f, 0.0082642593f},
1319 },
1320 {
1321 {-0.0006466667f, -0.0082166790f}, /* Filter 41 */
1322 {-0.0087572594f, 0.0028454060f},
1323 {-0.0072993441f, -0.0119114470f},
1324 {-0.0034175587f, 0.0034175587f},
1325 {-0.0152716480f, -0.0093584780f},
1326 {-0.0025930028f, 0.0079804420f},
1327 {-0.0410467015f, -0.0032304455f},
1328 { 0.0000647469f, 0.0004087959f},
1329 {-0.1073678519f, 0.0444732204f},
1330 {-0.0866880040f, -0.1193158015f},
1331 {-0.0614124285f, 0.0719047153f},
1332 {-0.5246402627f, -0.2673175657f},
1333 { 0.2423356631f, -1.0094006816f},
1334 { 1.1072741035f, 0.0000000000f},
1335 { 0.1731836536f, 0.7213618325f},
1336 {-0.1974809435f, 0.1006215665f},
1337 { 0.0714121011f, 0.0836128276f},
1338 {-0.0846538939f, 0.1165160891f},
1339 {-0.0284405684f, -0.0117804691f},
1340 {-0.0061877467f, 0.0390678953f},
1341 {-0.0207630684f, 0.0016340889f},
1342 { 0.0044827743f, 0.0137965606f},
1343 {-0.0096850130f, 0.0059349836f},
1344 { 0.0073773020f, 0.0073773020f},
1345 {-0.0067345088f, 0.0109897195f},
1346 { 0.0018308065f, 0.0005948651f},
1347 {-0.0006466667f, 0.0082166790f},
1348 },
1349 {
1350 {-0.0006423686f, -0.0081620664f}, /* Filter 42 */
1351 {-0.0090450120f, 0.0029389025f},
1352 {-0.0072072465f, -0.0117611574f},
1353 {-0.0037675783f, 0.0037675783f},
1354 {-0.0151771562f, -0.0093005733f},
1355 {-0.0028646414f, 0.0088164597f},
1356 {-0.0411823301f, -0.0032411197f},
1357 { 0.0003686970f, 0.0023278610f},
1358 {-0.1094767749f, 0.0453467649f},
1359 {-0.0856193708f, -0.1178449541f},
1360 {-0.0668351454f, 0.0782539010f},
1361 {-0.5345900940f, -0.2723872580f},
1362 { 0.2437733949f, -1.0153892656f},
1363 { 1.1035967397f, 0.0000000000f},
1364 { 0.1707092554f, 0.7110552220f},
1365 {-0.1887938905f, 0.0961952919f},
1366 { 0.0737282126f, 0.0863246457f},
1367 {-0.0836936943f, 0.1151944878f},
1368 {-0.0262515049f, -0.0108737293f},
1369 {-0.0062475719f, 0.0394456164f},
1370 {-0.0198892682f, 0.0015653194f},
1371 { 0.0045988736f, 0.0141538775f},
1372 {-0.0093227386f, 0.0057129815f},
1373 { 0.0076074506f, 0.0076074506f},
1374 {-0.0066215668f, 0.0108054149f},
1375 { 0.0021099840f, 0.0006855754f},
1376 {-0.0006423686f, 0.0081620664f},
1377 },
1378 {
1379 {-0.0006375260f, -0.0081005359f}, /* Filter 43 */
1380 {-0.0093280490f, 0.0030308668f},
1381 {-0.0071087889f, -0.0116004892f},
1382 {-0.0041157984f, 0.0041157984f},
1383 {-0.0150654901f, -0.0092321442f},
1384 {-0.0031376826f, 0.0096567942f},
1385 {-0.0412819110f, -0.0032489569f},
1386 { 0.0006786580f, 0.0042848780f},
1387 {-0.1115515226f, 0.0462061535f},
1388 {-0.0844752467f, -0.1162702023f},
1389 {-0.0723355236f, 0.0846940164f},
1390 {-0.5445209082f, -0.2774472605f},
1391 { 0.2451693490f, -1.0212038328f},
1392 { 1.0997181284f, 0.0000000000f},
1393 { 0.1682194641f, 0.7006844950f},
1394 {-0.1801910135f, 0.0918119071f},
1395 { 0.0759538132f, 0.0889304892f},
1396 {-0.0826965057f, 0.1138219754f},
1397 {-0.0240867927f, -0.0099770762f},
1398 {-0.0063006503f, 0.0397807405f},
1399 {-0.0190103194f, 0.0014961446f},
1400 { 0.0047087245f, 0.0144919637f},
1401 {-0.0089534403f, 0.0054866753f},
1402 { 0.0078301476f, 0.0078301476f},
1403 {-0.0065043116f, 0.0106140718f},
1404 { 0.0023844759f, 0.0007747632f},
1405 {-0.0006375260f, 0.0081005359f},
1406 },
1407 {
1408 {-0.0006321484f, -0.0080322075f}, /* Filter 44 */
1409 {-0.0096060925f, 0.0031212087f},
1410 {-0.0070040103f, -0.0114295060f},
1411 {-0.0044618854f, 0.0044618854f},
1412 {-0.0149365628f, -0.0091531374f},
1413 {-0.0034118961f, 0.0105007365f},
1414 {-0.0413447525f, -0.0032539026f},
1415 { 0.0009945051f, 0.0062790582f},
1416 {-0.1135901216f, 0.0470505689f},
1417 {-0.0832549311f, -0.1145905820f},
1418 {-0.0779124236f, 0.0912237273f},
1419 {-0.5544294025f, -0.2824958906f},
1420 { 0.2465230038f, -1.0268422107f},
1421 { 1.0956397332f, 0.0000000000f},
1422 { 0.1657151424f, 0.6902532446f},
1423 {-0.1716744668f, 0.0874725099f},
1424 { 0.0780893017f, 0.0914308250f},
1425 {-0.0816636012f, 0.1124003042f},
1426 {-0.0219475497f, -0.0090909727f},
1427 {-0.0063470532f, 0.0400737166f},
1428 {-0.0181270820f, 0.0014266323f},
1429 { 0.0048122983f, 0.0148107313f},
1430 {-0.0085775184f, 0.0052563101f},
1431 { 0.0080452535f, 0.0080452535f},
1432 {-0.0063828750f, 0.0104159053f},
1433 { 0.0026540877f, 0.0008623654f},
1434 {-0.0006321484f, 0.0080322075f},
1435 },
1436 {
1437 {-0.0006262457f, -0.0079572062f}, /* Filter 45 */
1438 {-0.0098788669f, 0.0032098384f},
1439 {-0.0068929555f, -0.0112482810f},
1440 {-0.0048055043f, 0.0048055043f},
1441 {-0.0147903020f, -0.0090635087f},
1442 {-0.0036870475f, 0.0113475654f},
1443 {-0.0413701808f, -0.0032559039f},
1444 { 0.0013161074f, 0.0083095754f},
1445 {-0.1155905906f, 0.0478791903f},
1446 {-0.0819577515f, -0.1128051674f},
1447 {-0.0835646644f, 0.0978416511f},
1448 {-0.5643122679f, -0.2875314620f},
1449 { 0.2478338529f, -1.0323022902f},
1450 { 1.0913630919f, 0.0000000000f},
1451 { 0.1631971552f, 0.6797650728f},
1452 {-0.1632463544f, 0.0831781721f},
1453 { 0.0801351139f, 0.0938261634f},
1454 {-0.0805962556f, 0.1109312291f},
1455 {-0.0198348595f, -0.0082158678f},
1456 {-0.0063868556f, 0.0403250190f},
1457 {-0.0172404079f, 0.0013568495f},
1458 { 0.0049095725f, 0.0151101104f},
1459 {-0.0081953754f, 0.0050221325f},
1460 { 0.0082526365f, 0.0082526365f},
1461 {-0.0062573914f, 0.0102111348f},
1462 { 0.0029186307f, 0.0009483206f},
1463 {-0.0006262457f, 0.0079572062f},
1464 },
1465 {
1466 {-0.0006198280f, -0.0078756618f}, /* Filter 46 */
1467 {-0.0101460989f, 0.0032966674f},
1468 {-0.0067756751f, -0.0110568969f},
1469 {-0.0051463192f, 0.0051463192f},
1470 {-0.0146266493f, -0.0089632222f},
1471 {-0.0039628985f, 0.0121965475f},
1472 {-0.0413575411f, -0.0032549091f},
1473 { 0.0016433282f, 0.0103755662f},
1474 {-0.1175509420f, 0.0486911944f},
1475 {-0.0805830641f, -0.1109130726f},
1476 {-0.0892910248f, 0.1045463576f},
1477 {-0.5741661901f, -0.2925522861f},
1478 { 0.2491014054f, -1.0375820265f},
1479 { 1.0868898157f, 0.0000000000f},
1480 { 0.1606663689f, 0.6692235895f},
1481 {-0.1549087286f, 0.0789299396f},
1482 { 0.0820917217f, 0.0961170567f},
1483 {-0.0794957450f, 0.1094165063f},
1484 {-0.0177497724f, -0.0073521965f},
1485 {-0.0064201364f, 0.0405351459f},
1486 {-0.0163511406f, 0.0012868627f},
1487 { 0.0050005298f, 0.0153900482f},
1488 {-0.0078074148f, 0.0047843899f},
1489 { 0.0084521727f, 0.0084521727f},
1490 {-0.0061279979f, 0.0099999837f},
1491 { 0.0031779221f, 0.0010325695f},
1492 {-0.0006198280f, 0.0078756618f},
1493 },
1494 {
1495 {-0.0006129060f, -0.0077877091f}, /* Filter 47 */
1496 {-0.0104075179f, 0.0033816075f},
1497 {-0.0066522258f, -0.0108554460f},
1498 {-0.0054839934f, 0.0054839934f},
1499 {-0.0144455612f, -0.0088522513f},
1500 {-0.0042392071f, 0.0130469379f},
1501 {-0.0413061980f, -0.0032508683f},
1502 { 0.0019760247f, 0.0124761291f},
1503 {-0.1194691818f, 0.0494857553f},
1504 {-0.0791302548f, -0.1089134521f},
1505 {-0.0950902426f, 0.1113363693f},
1506 {-0.5839878512f, -0.2975566724f},
1507 { 0.2503251863f, -1.0426794408f},
1508 { 1.0822215889f, 0.0000000000f},
1509 { 0.1581236518f, 0.6586324102f},
1510 {-0.1466635902f, 0.0747288317f},
1511 { 0.0839596331f, 0.0983041000f},
1512 {-0.0783633460f, 0.1078578927f},
1513 {-0.0156933045f, -0.0065003796f},
1514 {-0.0064469783f, 0.0407046190f},
1515 {-0.0154601145f, 0.0012167374f},
1516 { 0.0050851588f, 0.0156505094f},
1517 {-0.0074140419f, 0.0045433307f},
1518 { 0.0086437458f, 0.0086437458f},
1519 {-0.0059948336f, 0.0097826794f},
1520 { 0.0034317849f, 0.0011150545f},
1521 {-0.0006129060f, 0.0077877091f},
1522 },
1523 };
1524
1525 /* Coefficients for the band edge symbol timing synchroniser */
1526 #define SYNC_LOW_BAND_EDGE_COEFF_0 1.829281f /* 2*alpha*cos(low_edge) */
1527 #define SYNC_LOW_BAND_EDGE_COEFF_1 -0.980100f /* -alpha^2 */
1528 #define SYNC_HIGH_BAND_EDGE_COEFF_0 -1.285907f /* 2*alpha*cos(high_edge) */
1529 #define SYNC_HIGH_BAND_EDGE_COEFF_1 -0.980100f /* -alpha^2 */
1530 #define SYNC_CROSS_CORR_COEFF_A -0.932131f /* -alpha^2*sin(freq_diff) */
1531 #define SYNC_CROSS_CORR_COEFF_B 0.752802f /* alpha*sin(high_edge) */
1532 #define SYNC_CROSS_CORR_COEFF_C -0.378857f /* -alpha*sin(low_edge) */
1533
1534 float v29_rx_carrier_frequency(v29_rx_state_t *s)
1535 {
1536 return dds_frequencyf(s->carrier_phase_rate);
1537 }
1538 /*- End of function --------------------------------------------------------*/
1539
1540 float v29_rx_symbol_timing_correction(v29_rx_state_t *s)
1541 {
1542 return (float) s->total_baud_timing_correction/((float) PULSESHAPER_COEFF_SETS*10.0f/3.0f);
1543 }
1544 /*- End of function --------------------------------------------------------*/
1545
1546 void v29_rx_signal_cutoff(v29_rx_state_t *s, float cutoff)
1547 {
1548 /* The 0.4 factor allows for the gain of the DC blocker */
1549 s->carrier_on_power = (int32_t) (power_meter_level_dbm0(cutoff + 2.5f)*0.4f);
1550 s->carrier_off_power = (int32_t) (power_meter_level_dbm0(cutoff - 2.5f)*0.4f);
1551 }
1552 /*- End of function --------------------------------------------------------*/
1553
1554 float v29_rx_signal_power(v29_rx_state_t *s)
1555 {
1556 return power_meter_dbm0(&s->power);
1557 }
1558 /*- End of function --------------------------------------------------------*/
1559
1560 int v29_rx_equalizer_state(v29_rx_state_t *s, complexf_t **coeffs)
1561 {
1562 *coeffs = s->eq_coeff;
1563 return V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN;
1564 }
1565 /*- End of function --------------------------------------------------------*/
1566
1567 static void equalizer_save(v29_rx_state_t *s)
1568 {
1569 cvec_copyf(s->eq_coeff_save, s->eq_coeff, V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
1570 }
1571 /*- End of function --------------------------------------------------------*/
1572
1573 static void equalizer_restore(v29_rx_state_t *s)
1574 {
1575 cvec_copyf(s->eq_coeff, s->eq_coeff_save, V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
1576 cvec_zerof(s->eq_buf, V29_EQUALIZER_MASK);
1577
1578 s->eq_put_step = PULSESHAPER_COEFF_SETS*10/(3*2) - 1;
1579 s->eq_step = 0;
1580 s->eq_delta = EQUALIZER_DELTA/(V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
1581 }
1582 /*- End of function --------------------------------------------------------*/
1583
1584 static void equalizer_reset(v29_rx_state_t *s)
1585 {
1586 /* Start with an equalizer based on everything being perfect */
1587 cvec_zerof(s->eq_coeff, V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
1588 s->eq_coeff[V29_EQUALIZER_PRE_LEN] = complex_setf(3.0f, 0.0f);
1589 cvec_zerof(s->eq_buf, V29_EQUALIZER_MASK);
1590
1591 s->eq_put_step = PULSESHAPER_COEFF_SETS*10/(3*2) - 1;
1592 s->eq_step = 0;
1593 s->eq_delta = EQUALIZER_DELTA/(V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN);
1594 }
1595 /*- End of function --------------------------------------------------------*/
1596
1597 static __inline__ complexf_t equalizer_get(v29_rx_state_t *s)
1598 {
1599 int i;
1600 int p;
1601 complexf_t z;
1602 complexf_t z1;
1603
1604 /* Get the next equalized value. */
1605 z = complex_setf(0.0f, 0.0f);
1606 p = s->eq_step - 1;
1607 for (i = 0; i < V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN; i++)
1608 {
1609 p = (p - 1) & V29_EQUALIZER_MASK;
1610 z1 = complex_mulf(&s->eq_coeff[i], &s->eq_buf[p]);
1611 z = complex_addf(&z, &z1);
1612 }
1613 return z;
1614 }
1615 /*- End of function --------------------------------------------------------*/
1616
1617 static void tune_equalizer(v29_rx_state_t *s, const complexf_t *z, const complexf_t *target)
1618 {
1619 int i;
1620 int p;
1621 complexf_t ez;
1622 complexf_t z1;
1623
1624 /* Find the x and y mismatch from the exact constellation position. */
1625 ez = complex_subf(target, z);
1626 ez.re *= s->eq_delta;
1627 ez.im *= s->eq_delta;
1628
1629 p = s->eq_step - 1;
1630 for (i = 0; i < V29_EQUALIZER_PRE_LEN + 1 + V29_EQUALIZER_POST_LEN; i++)
1631 {
1632 p = (p - 1) & V29_EQUALIZER_MASK;
1633 z1 = complex_conjf(&s->eq_buf[p]);
1634 z1 = complex_mulf(&ez, &z1);
1635 s->eq_coeff[i] = complex_addf(&s->eq_coeff[i], &z1);
1636 /* Leak a little to tame uncontrolled wandering */
1637 s->eq_coeff[i].re *= 0.9999f;
1638 s->eq_coeff[i].im *= 0.9999f;
1639 }
1640 }
1641 /*- End of function --------------------------------------------------------*/
1642
1643 static int scrambled_training_bit(v29_rx_state_t *s)
1644 {
1645 int bit;
1646
1647 /* Segment 3 of the training sequence - the scrambled CDCD part. */
1648 /* Apply the 1 + x^-6 + x^-7 scrambler */
1649 bit = s->training_scramble_reg & 1;
1650 s->training_scramble_reg >>= 1;
1651 if (bit ^ (s->training_scramble_reg & 1))
1652 s->training_scramble_reg |= 0x40;
1653 return bit;
1654 }
1655 /*- End of function --------------------------------------------------------*/
1656
1657 static __inline__ int find_quadrant(const complexf_t *z)
1658 {
1659 int b1;
1660 int b2;
1661
1662 /* Split the space along the two diagonals. */
1663 b1 = (z->im > z->re);
1664 b2 = (z->im < -z->re);
1665 return (b2 << 1) | (b1 ^ b2);
1666 }
1667 /*- End of function --------------------------------------------------------*/
1668
1669 static __inline__ void track_carrier(v29_rx_state_t *s, const complexf_t *z, const complexf_t *target)
1670 {
1671 float error;
1672
1673 /* The initial coarse carrier frequency and phase estimation should have
1674 got us in the right ballpark. Now we need to fine tune fairly quickly,
1675 to get the receovered carrier more precisely on target. Then we need to
1676 fine tune in a more damped way to keep us on target. The goal is to have
1677 things running really well by the time the training is complete.
1678 We assume the frequency of the oscillators at the two ends drift only
1679 very slowly. The PSTN has rather limited doppler problems. :-) Any
1680 remaining FDM in the network should also drift slowly. */
1681 /* For small errors the imaginary part of the difference between the actual and the target
1682 positions is proportional to the phase error, for any particular target. However, the
1683 different amplitudes of the various target positions scale things. This isn't all bad,
1684 as the angular error for the larger amplitude constellation points is probably
1685 a more reliable indicator, and we are weighting it as such. */
1686 error = z->im*target->re - z->re*target->im;
1687
1688 /* Use a proportional-integral approach to tracking the carrier. The PI
1689 parameters are coarser at first, until we get precisely on target. Then,
1690 the filter will be damped more to keep us on target. */
1691 s->carrier_phase_rate += (int32_t) (s->carrier_track_i*error);
1692 s->carrier_phase += (int32_t) (s->carrier_track_p*error);
1693 //span_log(&s->logging, SPAN_LOG_FLOW, "Im = %15.5f f = %15.5f\n", error, dds_frequencyf(s->carrier_phase_rate));
1694 }
1695 /*- End of function --------------------------------------------------------*/
1696
1697 static __inline__ void put_bit(v29_rx_state_t *s, int bit)
1698 {
1699 int out_bit;
1700
1701 bit &= 1;
1702
1703 /* Descramble the bit */
1704 out_bit = (bit ^ (s->scramble_reg >> 17) ^ (s->scramble_reg >> 22)) & 1;
1705 s->scramble_reg = (s->scramble_reg << 1) | bit;
1706
1707 /* We need to strip the last part of the training - the test period of all 1s -
1708 before we let data go to the application. */
1709 if (s->in_training == TRAINING_STAGE_NORMAL_OPERATION)
1710 {
1711 s->put_bit(s->user_data, out_bit);
1712 }
1713 else
1714 {
1715 //span_log(&s->logging, SPAN_LOG_FLOW, "bit %5d %d\n", s->training_cd, out_bit);
1716 /* The bits during the final stage of training should be all ones. However,
1717 buggy modems mean you cannot rely on this. Therefore we don't bother
1718 testing for ones, but just rely on a constellation mismatch measurement. */
1719 }
1720 }
1721 /*- End of function --------------------------------------------------------*/
1722
1723 static void decode_baud(v29_rx_state_t *s, complexf_t *z)
1724 {
1725 static const uint8_t phase_steps_9600[8] =
1726 {
1727 4, 0, 2, 6, 7, 3, 1, 5
1728 };
1729 static const uint8_t phase_steps_4800[4] =
1730 {
1731 0, 2, 3, 1
1732 };
1733 int nearest;
1734 int raw_bits;
1735 int i;
1736 int re;
1737 int im;
1738
1739 switch (s->bit_rate)
1740 {
1741 case 9600:
1742 default:
1743 re = (int) ((z->re + 5.0f)*2.0f);
1744 if (re > 19)
1745 re = 19;
1746 else if (re < 0)
1747 re = 0;
1748 im = (int) ((z->im + 5.0f)*2.0f);
1749 if (im > 19)
1750 im = 19;
1751 else if (im < 0)
1752 im = 0;
1753 nearest = space_map_9600[re][im];
1754 /* Deal with the amplitude bit */
1755 put_bit(s, nearest >> 3);
1756 raw_bits = phase_steps_9600[(nearest - s->constellation_state) & 7];
1757 for (i = 0; i < 3; i++)
1758 {
1759 put_bit(s, raw_bits);
1760 raw_bits >>= 1;
1761 }
1762 break;
1763 case 7200:
1764 /* We can reuse the space map for 9600, but drop the top bit */
1765 re = (int) ((z->re + 5.0f)*2.0f);
1766 if (re > 19)
1767 re = 19;
1768 else if (re < 0)
1769 re = 0;
1770 im = (int) ((z->im + 5.0f)*2.0f);
1771 if (im > 19)
1772 im = 19;
1773 else if (im < 0)
1774 im = 0;
1775 nearest = space_map_9600[re][im] & 7;
1776 raw_bits = phase_steps_9600[(nearest - s->constellation_state) & 7];
1777 for (i = 0; i < 3; i++)
1778 {
1779 put_bit(s, raw_bits);
1780 raw_bits >>= 1;
1781 }
1782 break;
1783 case 4800:
1784 nearest = find_quadrant(z) << 1;
1785 raw_bits = phase_steps_4800[((nearest - s->constellation_state) >> 1) & 3];
1786 put_bit(s, raw_bits);
1787 put_bit(s, raw_bits >> 1);
1788 break;
1789 }
1790 track_carrier(s, z, &v29_constellation[nearest]);
1791 if (--s->eq_skip <= 0)
1792 {
1793 /* Once we are in the data the equalization should not need updating.
1794 However, the line characteristics may slowly drift. We, therefore,
1795 tune up on the occassional sample, keeping the compute down. */
1796 s->eq_skip = 10;
1797 tune_equalizer(s, z, &v29_constellation[nearest]);
1798 }
1799 s->constellation_state = nearest;
1800 }
1801 /*- End of function --------------------------------------------------------*/
1802
1803 static void process_half_baud(v29_rx_state_t *s, complexf_t *sample)
1804 {
1805 static const int cdcd_pos[6] =
1806 {
1807 0, 11,
1808 0, 3,
1809 0, 2
1810 };
1811 complexf_t z;
1812 complexf_t zz;
1813 const complexf_t *target;
1814 float v;
1815 float p;
1816 int bit;
1817 int i;
1818 int j;
1819 int32_t angle;
1820 int32_t ang;
1821
1822 /* This routine processes every half a baud, as we put things into the equalizer at the T/2 rate.
1823 This routine adapts the position of the half baud samples, which the caller takes. */
1824
1825 /* Add a sample to the equalizer's circular buffer, but don't calculate anything
1826 at this time. */
1827 s->eq_buf[s->eq_step] = *sample;
1828 s->eq_step = (s->eq_step + 1) & V29_EQUALIZER_MASK;
1829
1830 /* On alternate insertions we have a whole baud, and must process it. */
1831 if ((s->baud_half ^= 1))
1832 return;
1833
1834 /* Symbol timing synchronisation */
1835 /* Cross correlate */
1836 v = s->symbol_sync_low[1]*s->symbol_sync_high[1]*SYNC_CROSS_CORR_COEFF_A
1837 + s->symbol_sync_low[0]*s->symbol_sync_high[1]*SYNC_CROSS_CORR_COEFF_B
1838 + s->symbol_sync_low[1]*s->symbol_sync_high[0]*SYNC_CROSS_CORR_COEFF_C;
1839
1840 /* Filter away any DC component */
1841 p = v - s->symbol_sync_dc_filter[1];
1842 s->symbol_sync_dc_filter[1] = s->symbol_sync_dc_filter[0];
1843 s->symbol_sync_dc_filter[0] = v;
1844 /* A little integration will now filter away much of the noise */
1845 s->baud_phase -= p;
1846
1847 i = 0;
1848 if (s->baud_phase > 1000.0f)
1849 i = 5;
1850 else if (s->baud_phase < -1000.0f)
1851 i = -5;
1852 else if (s->baud_phase > 100.0f)
1853 i = 1;
1854 else if (s->baud_phase < -100.0f)
1855 i = -1;
1856
1857 //printf("v = %10.5f %5d - %f %f %d %d\n", v, i, p, s->baud_phase, s->total_baud_timing_correction);
1858
1859 if (i)
1860 {
1861 s->eq_put_step += i;
1862 s->total_baud_timing_correction += i;
1863 }
1864
1865 z = equalizer_get(s);
1866
1867 switch (s->in_training)
1868 {
1869 case TRAINING_STAGE_NORMAL_OPERATION:
1870 /* Normal operation. */
1871 decode_baud(s, &z);
1872 target = &v29_constellation[s->constellation_state];
1873 break;
1874 case TRAINING_STAGE_SYMBOL_ACQUISITION:
1875 /* Allow time for symbol synchronisation to settle the symbol timing. */
1876 target = &z;
1877 if (++s->training_count >= 60)
1878 {
1879 /* Record the current phase angle */
1880 s->in_training = TRAINING_STAGE_LOG_PHASE;
1881 s->angles[0] =
1882 s->start_angles[0] = arctan2(z.im, z.re);
1883 }
1884 break;
1885 case TRAINING_STAGE_LOG_PHASE:
1886 /* Record the current alternate phase angle */
1887 target = &z;
1888 s->angles[1] =
1889 s->start_angles[1] = arctan2(z.im, z.re);
1890 s->training_count = 1;
1891 s->in_training = TRAINING_STAGE_WAIT_FOR_CDCD;
1892 break;
1893 case TRAINING_STAGE_WAIT_FOR_CDCD:
1894 target = &z;
1895 angle = arctan2(z.im, z.re);
1896 /* Look for the initial ABAB sequence to display a phase reversal, which will
1897 signal the start of the scrambled CDCD segment */
1898 ang = angle - s->angles[(s->training_count - 1) & 0xF];
1899 s->angles[(s->training_count + 1) & 0xF] = angle;
1900 if ((ang > 0x20000000 || ang < -0x20000000) && s->training_count >= 13)
1901 {
1902 /* We seem to have a phase reversal */
1903 /* Slam the carrier frequency into line, based on the total phase drift over the last
1904 section. Use the shift from the odd bits and the shift from the even bits to get
1905 better jitter suppression. We need to scale here, or at the maximum specified
1906 frequency deviation we could overflow, and get a silly answer. */
1907 /* Step back a few symbols so we don't get ISI distorting things. */
1908 i = (s->training_count - 8) & ~1;
1909 /* Avoid the possibility of a divide by zero */
1910 if (i)
1911 {
1912 j = i & 0xF;
1913 ang = (s->angles[j] - s->start_angles[0])/i
1914 + (s->angles[j | 0x1] - s->start_angles[1])/i;
1915 s->carrier_phase_rate += 3*(ang/20);
1916 }
1917 span_log(&s->logging, SPAN_LOG_FLOW, "Coarse carrier frequency %7.2f\n", dds_frequencyf(s->carrier_phase_rate));
1918 /* Check if the carrier frequency is plausible */
1919 if (s->carrier_phase_rate < dds_phase_ratef(CARRIER_NOMINAL_FREQ - 20.0f)
1920 ||
1921 s->carrier_phase_rate > dds_phase_ratef(CARRIER_NOMINAL_FREQ + 20.0f))
1922 {
1923 span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n");
1924 /* Park this modem */
1925 s->in_training = TRAINING_STAGE_PARKED;
1926 s->put_bit(s->user_data, PUTBIT_TRAINING_FAILED);
1927 break;
1928 }
1929 /* Make a step shift in the phase, to pull it into line. We need to rotate the equalizer
1930 buffer, as well as the carrier phase, for this to play out nicely. */
1931 p = angle*2.0f*3.14159f/(65536.0f*65536.0f);
1932 zz = complex_setf(cosf(p), -sinf(p));
1933 for (i = 0; i <= V29_EQUALIZER_MASK; i++)
1934 s->eq_buf[i] = complex_mulf(&s->eq_buf[i], &zz);
1935 s->carrier_phase += angle;
1936 /* We have just seen the first bit of the scrambled sequence, so skip it. */
1937 bit = scrambled_training_bit(s);
1938 s->training_count = 1;
1939 s->in_training = TRAINING_STAGE_TRAIN_ON_CDCD;
1940 break;
1941 }
1942 if (++s->training_count > V29_TRAINING_SEG_2_LEN)
1943 {
1944 /* This is bogus. There are not this many bauds in this section
1945 of a real training sequence. */
1946 span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (sequence failed)\n");
1947 /* Park this modem */
1948 s->in_training = TRAINING_STAGE_PARKED;
1949 s->put_bit(s->user_data, PUTBIT_TRAINING_FAILED);
1950 }
1951 break;
1952 case TRAINING_STAGE_TRAIN_ON_CDCD:
1953 /* Train on the scrambled CDCD section. */
1954 bit = scrambled_training_bit(s);
1955 //span_log(&s->logging, SPAN_LOG_FLOW, "%5d %15.5f, %15.5f %15.5f, %15.5f\n", s->training_count, z.re, z.im, v29_constellation[cdcd_pos[s->training_cd + bit]].re, v29_constellation[cdcd_pos[s->training_cd + bit]].im);
1956 s->constellation_state = cdcd_pos[s->training_cd + bit];
1957 target = &v29_constellation[s->constellation_state];
1958 track_carrier(s, &z, target);
1959 tune_equalizer(s, &z, target);
1960 if (++s->training_count >= V29_TRAINING_SEG_3_LEN - 48)
1961 {
1962 s->in_training = TRAINING_STAGE_TRAIN_ON_CDCD_AND_TEST;
1963 s->training_error = 0.0f;
1964 s->carrier_track_i = 200.0f;
1965 s->carrier_track_p = 1000000.0f;
1966 }
1967 break;
1968 case TRAINING_STAGE_TRAIN_ON_CDCD_AND_TEST:
1969 /* Continue training on the scrambled CDCD section, but measure the quality of training too. */
1970 bit = scrambled_training_bit(s);
1971 //span_log(&s->logging, SPAN_LOG_FLOW, "%5d %15.5f, %15.5f %15.5f, %15.5f\n", s->training_count, z.re, z.im, v29_constellation[cdcd_pos[s->training_cd + bit]].re, v29_constellation[cdcd_pos[s->training_cd + bit]].im);
1972 s->constellation_state = cdcd_pos[s->training_cd + bit];
1973 target = &v29_constellation[s->constellation_state];
1974 track_carrier(s, &z, target);
1975 tune_equalizer(s, &z, target);
1976 /* Measure the training error */
1977 zz = complex_subf(&z, target);
1978 s->training_error += powerf(&zz);
1979 if (++s->training_count >= V29_TRAINING_SEG_3_LEN)
1980 {
1981 span_log(&s->logging, SPAN_LOG_FLOW, "Constellation mismatch %f\n", s->training_error);
1982 if (s->training_error < 100.0f)
1983 {
1984 s->training_count = 0;
1985 s->training_cd = 0;
1986 s->training_error = 0.0f;
1987 s->constellation_state = 0;
1988 s->in_training = TRAINING_STAGE_TEST_ONES;
1989 }
1990 else
1991 {
1992 span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (convergence failed)\n");
1993 /* Park this modem */
1994 s->in_training = TRAINING_STAGE_PARKED;
1995 s->put_bit(s->user_data, PUTBIT_TRAINING_FAILED);
1996 }
1997 }
1998 break;
1999 case TRAINING_STAGE_TEST_ONES:
2000 /* We are in the test phase, where we check that we can receive reliably.
2001 We should get a run of 1's, 48 symbols (192 bits at 9600bps) long. */
2002 //span_log(&s->logging, SPAN_LOG_FLOW, "%5d %15.5f, %15.5f\n", s->training_count, z.re, z.im);
2003 decode_baud(s, &z);
2004 target = &v29_constellation[s->constellation_state];
2005 /* Measure the training error */
2006 zz = complex_subf(&z, target);
2007 s->training_error += powerf(&zz);
2008 if (++s->training_count >= V29_TRAINING_SEG_4_LEN)
2009 {
2010 if (s->training_error < 50.0f)
2011 {
2012 /* We are up and running */
2013 span_log(&s->logging, SPAN_LOG_FLOW, "Training succeeded (constellation mismatch %f)\n", s->training_error);
2014 s->put_bit(s->user_data, PUTBIT_TRAINING_SUCCEEDED);
2015 /* Apply some lag to the carrier off condition, to ensure the last few bits get pushed through
2016 the processing. */
2017 s->carrier_present = 60;
2018 s->in_training = TRAINING_STAGE_NORMAL_OPERATION;
2019 equalizer_save(s);
2020 s->carrier_phase_rate_save = s->carrier_phase_rate;
2021 s->agc_scaling_save = s->agc_scaling;
2022 }
2023 else
2024 {
2025 /* Training has failed */
2026 span_log(&s->logging, SPAN_LOG_FLOW, "Training failed (constellation mismatch %f)\n", s->training_error);
2027 /* Park this modem */
2028 s->put_bit(s->user_data, PUTBIT_TRAINING_FAILED);
2029 s->in_training = TRAINING_STAGE_PARKED;
2030 }
2031 }
2032 break;
2033 case TRAINING_STAGE_PARKED:
2034 default:
2035 /* We failed to train! */
2036 /* Park here until the carrier drops. */
2037 target = &z;
2038 break;
2039 }
2040 if (s->qam_report)
2041 s->qam_report(s->qam_user_data, &z, target, s->constellation_state);
2042 }
2043 /*- End of function --------------------------------------------------------*/
2044
2045 int v29_rx(v29_rx_state_t *s, const int16_t amp[], int len)
2046 {
2047 int i;
2048 int j;
2049 int step;
2050 complexf_t z;
2051 complexf_t zz;
2052 complexf_t sample;
2053 int32_t power;
2054 float v;
2055
2056 for (i = 0; i < len; i++)
2057 {
2058 s->rrc_filter[s->rrc_filter_step] =
2059 s->rrc_filter[s->rrc_filter_step + V29_RX_FILTER_STEPS] = amp[i];
2060 if (++s->rrc_filter_step >= V29_RX_FILTER_STEPS)
2061 s->rrc_filter_step = 0;
2062
2063 /* There should be no DC in the signal, but sometimes there is.
2064 We need to measure the power with the DC blocked, but not using
2065 a slow to respond DC blocker. Use the most elementary HPF. */
2066 power = power_meter_update(&(s->power), (amp[i] - s->last_sample) >> 1);
2067 s->last_sample = amp[i];
2068 if (s->carrier_present)
2069 {
2070 /* Look for power below turn-off threshold to turn the carrier off */
2071 if (power < s->carrier_off_power)
2072 {
2073 if (--s->carrier_present <= 0)
2074 {
2075 /* Count down a short delay, to ensure we push the last
2076 few bits through the filters before stopping. */
2077 v29_rx_restart(s, s->bit_rate, FALSE);
2078 s->put_bit(s->user_data, PUTBIT_CARRIER_DOWN);
2079 continue;
2080 }
2081 }
2082 }
2083 else
2084 {
2085 /* Look for power exceeding turn-on threshold to turn the carrier on */
2086 if (power < s->carrier_on_power)
2087 continue;
2088 s->carrier_present = 1;
2089 s->put_bit(s->user_data, PUTBIT_CARRIER_UP);
2090 }
2091 if (s->in_training != TRAINING_STAGE_PARKED)
2092 {
2093 /* Only spend effort processing this data if the modem is not
2094 parked, after training failure. */
2095 s->eq_put_step -= PULSESHAPER_COEFF_SETS;
2096 step = -s->eq_put_step;
2097 if (step > PULSESHAPER_COEFF_SETS - 1)
2098 step = PULSESHAPER_COEFF_SETS - 1;
2099 if (step < 0)
2100 step += PULSESHAPER_COEFF_SETS;
2101 zz.re = pulseshaper[step][0].re*s->rrc_filter[s->rrc_filter_step];
2102 for (j = 1; j < V29_RX_FILTER_STEPS; j++)
2103 zz.re += pulseshaper[step][j].re*s->rrc_filter[j + s->rrc_filter_step];
2104 sample.re = zz.re*s->agc_scaling;
2105
2106 /* Symbol timing synchronisation band edge filters */
2107 /* Low Nyquist band edge filter */
2108 v = s->symbol_sync_low[0]*SYNC_LOW_BAND_EDGE_COEFF_0 + s->symbol_sync_low[1]*SYNC_LOW_BAND_EDGE_COEFF_1 + sample.re;
2109 s->symbol_sync_low[1] = s->symbol_sync_low[0];
2110 s->symbol_sync_low[0] = v;
2111 /* High Nyquist band edge filter */
2112 v = s->symbol_sync_high[0]*SYNC_HIGH_BAND_EDGE_COEFF_0 + s->symbol_sync_high[1]*SYNC_HIGH_BAND_EDGE_COEFF_1 + sample.re;
2113 s->symbol_sync_high[1] = s->symbol_sync_high[0];
2114 s->symbol_sync_high[0] = v;
2115
2116 z = dds_complexf(&(s->carrier_phase), s->carrier_phase_rate);
2117
2118 /* Put things into the equalization buffer at T/2 rate. The symbol synchronisation
2119 will fiddle the step to align this with the symbols. */
2120 if (s->eq_put_step <= 0)
2121 {
2122 if (s->in_training == TRAINING_STAGE_SYMBOL_ACQUISITION)
2123 {
2124 /* Only AGC during the initial training */
2125 s->agc_scaling = (1.0f/PULSESHAPER_GAIN)*5.0f*0.72f/sqrtf(power);
2126 }
2127 /* Pulse shape while still at the carrier frequency, using a quadrature
2128 pair of filters. This results in a properly bandpass filtered complex
2129 signal, which can be brought directly to bandband by complex mixing.
2130 No further filtering, to remove mixer harmonics, is needed. */
2131 step = -s->eq_put_step;
2132 if (step > PULSESHAPER_COEFF_SETS - 1)
2133 step = PULSESHAPER_COEFF_SETS - 1;
2134 zz.im = pulseshaper[step][0].im*s->rrc_filter[s->rrc_filter_step];
2135 for (j = 1; j < V29_RX_FILTER_STEPS; j++)
2136 zz.im += pulseshaper[step][j].im*s->rrc_filter[j + s->rrc_filter_step];
2137 sample.re = zz.re*s->agc_scaling;
2138 sample.im = zz.im*s->agc_scaling;
2139 s->eq_put_step += PULSESHAPER_COEFF_SETS*10/(3*2);
2140 /* Shift to baseband - since this is done in a full complex form, the
2141 result is clean, and requires no further filtering, apart from the
2142 equalizer. */
2143 zz.re = sample.re*z.re - sample.im*z.im;
2144 zz.im = -sample.re*z.im - sample.im*z.re;
2145 process_half_baud(s, &zz);
2146 }
2147 }
2148 }
2149 return 0;
2150 }
2151 /*- End of function --------------------------------------------------------*/
2152
2153 void v29_rx_set_put_bit(v29_rx_state_t *s, put_bit_func_t put_bit, void *user_data)
2154 {
2155 s->put_bit = put_bit;
2156 s->user_data = user_data;
2157 }
2158 /*- End of function --------------------------------------------------------*/
2159
2160 int v29_rx_restart(v29_rx_state_t *s, int rate, int old_train)
2161 {
2162 switch (rate)
2163 {
2164 case 9600:
2165 s->training_cd = 0;
2166 break;
2167 case 7200:
2168 s->training_cd = 2;
2169 break;
2170 case 4800:
2171 s->training_cd = 4;
2172 break;
2173 default:
2174 return -1;
2175 }
2176 s->bit_rate = rate;
2177
2178 vec_zerof(s->rrc_filter, sizeof(s->rrc_filter)/sizeof(s->rrc_filter[0]));
2179 s->rrc_filter_step = 0;
2180
2181 s->scramble_reg = 0;
2182 s->training_scramble_reg = 0x2A;
2183 s->in_training = TRAINING_STAGE_SYMBOL_ACQUISITION;
2184 s->training_count = 0;
2185 s->carrier_present = 0;
2186 s->old_train = old_train;
2187
2188 s->carrier_phase = 0;
2189 s->carrier_track_i = 8000.0f;
2190 s->carrier_track_p = 8000000.0f;
2191
2192 power_meter_init(&(s->power), 4);
2193
2194 s->constellation_state = 0;
2195
2196 if (s->old_train)
2197 {
2198 s->carrier_phase_rate = s->carrier_phase_rate_save;
2199 s->agc_scaling = s->agc_scaling_save;
2200 equalizer_restore(s);
2201 }
2202 else
2203 {
2204 s->carrier_phase_rate = dds_phase_ratef(CARRIER_NOMINAL_FREQ);
2205 s->agc_scaling = 0.0005f;
2206 equalizer_reset(s);
2207 }
2208 s->eq_skip = 0;
2209 s->last_sample = 0;
2210
2211 /* Initialise the working data for symbol timing synchronisation */
2212 s->symbol_sync_low[0] = 0.0f;
2213 s->symbol_sync_low[1] = 0.0f;
2214 s->symbol_sync_high[0] = 0.0f;
2215 s->symbol_sync_high[1] = 0.0f;
2216 s->symbol_sync_dc_filter[0] = 0.0f;
2217 s->symbol_sync_dc_filter[1] = 0.0f;
2218 s->baud_phase = 0.0f;
2219 s->baud_half = 0;
2220
2221 s->total_baud_timing_correction = 0;
2222
2223 return 0;
2224 }
2225 /*- End of function --------------------------------------------------------*/
2226
2227 v29_rx_state_t *v29_rx_init(v29_rx_state_t *s, int rate, put_bit_func_t put_bit, void *user_data)
2228 {
2229 if (s == NULL)
2230 {
2231 if ((s = (v29_rx_state_t *) malloc(sizeof(*s))) == NULL)
2232 return NULL;
2233 }
2234
2235 memset(s, 0, sizeof(*s));
2236 s->put_bit = put_bit;
2237 s->user_data = user_data;
2238 /* The V.29 spec says the thresholds should be -31dBm and -26dBm, but that makes little
2239 sense. V.17 uses -48dBm and -43dBm, and there seems no good reason to cut off at a
2240 higher level (though at 9600bps and 7200bps, TCM should put V.17 sensitivity several
2241 dB ahead of V.29). */
2242 /* The thresholds should be on at -26dBm0 and off at -31dBm0 */
2243 v29_rx_signal_cutoff(s, -28.5f);
2244 span_log_init(&s->logging, SPAN_LOG_NONE, NULL);
2245 span_log_set_protocol(&s->logging, "V.29");
2246
2247 v29_rx_restart(s, rate, FALSE);
2248 return s;
2249 }
2250 /*- End of function --------------------------------------------------------*/
2251
2252 int v29_rx_release(v29_rx_state_t *s)
2253 {
2254 free(s);
2255 return 0;
2256 }
2257 /*- End of function --------------------------------------------------------*/
2258
2259 void v29_rx_set_qam_report_handler(v29_rx_state_t *s, qam_report_handler_t *handler, void *user_data)
2260 {
2261 s->qam_report = handler;
2262 s->qam_user_data = user_data;
2263 }
2264 /*- End of function --------------------------------------------------------*/
2265 /*- End of file ------------------------------------------------------------*/

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