Mercurial > hg > audiostuff
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spandsp-0.0.3/spandsp-0.0.3/src/v22bis_rx.c Fri Jun 25 16:00:21 2010 +0200 @@ -0,0 +1,1662 @@ +/* + * SpanDSP - a series of DSP components for telephony + * + * v22bis_rx.c - ITU V.22bis modem receive part + * + * Written by Steve Underwood <steveu@coppice.org> + * + * Copyright (C) 2004 Steve Underwood + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id: v22bis_rx.c,v 1.32 2006/11/19 14:07:26 steveu Exp $ + */ + +/*! \file */ + +/* THIS IS A WORK IN PROGRESS - NOT YET FUNCTIONAL! */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <inttypes.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#if defined(HAVE_TGMATH_H) +#include <tgmath.h> +#endif +#if defined(HAVE_MATH_H) +#include <math.h> +#endif + +#include "spandsp/telephony.h" +#include "spandsp/logging.h" +#include "spandsp/vector_float.h" +#include "spandsp/async.h" +#include "spandsp/power_meter.h" +#include "spandsp/arctan2.h" +#include "spandsp/complex.h" +#include "spandsp/dds.h" +#include "spandsp/complex_filters.h" + +#include "spandsp/v29rx.h" +#include "spandsp/v22bis.h" + +#define ms_to_symbols(t) (((t)*600)/1000) + +#define EQUALIZER_DELTA 0.25f + +/* +The basic method used by the V.22bis receiver is: + + Put each sample into the pulse-shaping and phase shift filter buffer + + At T/2 rate: + Filter and demodulate the contents of the input filter buffer, producing a sample + in the equalizer filter buffer. + + Tune the symbol timing based on the latest 3 samples in the equalizer buffer. This + updates the decision points for taking the T/2 samples. + + Equalize the contents of the equalizer buffer, producing a demodulated constellation + point. + + Find the nearest constellation point to the received position. This is our received + symbol. + + Tune the local carrier, based on the angular mismatch between the actual signal and + the decision. + + Tune the equalizer, based on the mismatch between the actual signal and the decision. + + Descramble and output the bits represented by the decision. +*/ + +enum +{ + V22BIS_TRAINING_STAGE_NORMAL_OPERATION, + V22BIS_TRAINING_STAGE_SYMBOL_ACQUISITION, + V22BIS_TRAINING_STAGE_LOG_PHASE, + V22BIS_TRAINING_STAGE_UNSCRAMBLED_ONES, + V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011, + V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200, + V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_2400, + V22BIS_TRAINING_STAGE_WAIT_FOR_START_1, + V22BIS_TRAINING_STAGE_WAIT_FOR_START_2, + V22BIS_TRAINING_STAGE_PARKED +}; + +/* Raised root cosine pulse shaping; Beta = 0.75; 4 symbols either + side of the centre. We cannot simplify this by using only half + the filter, as each variant are each skewed by a n/PULSESHAPER_COEFF_SETS of a + sample. Only one is symmetric. */ +//#define PULSESHAPER_GAIN 159.37711522f +#define PULSESHAPER_GAIN 39.98830768f +#define PULSESHAPER_COEFF_SETS 12 +static const complexf_t pulseshaper_1200[PULSESHAPER_COEFF_SETS][V22BIS_RX_FILTER_STEPS] = +{ + { + { 0.0079885982f, -0.0245863758f}, /* Filter 0 */ + { 0.0511994623f, -0.0166357141f}, + { 0.0660513043f, 0.0479890816f}, + {-0.0000000000f, 0.1045738682f}, + {-0.0949529186f, 0.0689873323f}, + {-0.1091215536f, -0.0354557447f}, + {-0.0284108873f, -0.0874397159f}, + { 0.0266686007f, -0.0367061794f}, + {-0.0269077960f, -0.0000000000f}, + {-0.0733404681f, -0.1009444892f}, + { 0.0759629756f, -0.2337899953f}, + { 0.3664972484f, -0.1190821752f}, + { 0.4341508448f, 0.3154290617f}, + {-0.0000000001f, 0.6913219094f}, + {-0.6796512008f, 0.4937954843f}, + {-0.9258067012f, -0.3008128405f}, + {-0.3345100582f, -1.0295161009f}, + { 0.6816816330f, -0.9382542372f}, + { 1.1997879744f, 0.0000000000f}, + { 0.7052176595f, 0.9706488252f}, + {-0.3583812416f, 1.1029839516f}, + {-1.0295161009f, 0.3345100582f}, + {-0.7875382304f, -0.5721800327f}, + {-0.0000000001f, -0.8400950432f}, + { 0.5592911839f, -0.4063488245f}, + { 0.5103749037f, 0.1658308655f}, + { 0.1190821752f, 0.3664972484f}, + {-0.1444901675f, 0.1988736391f}, + {-0.1247742549f, 0.0000000000f}, + {-0.0158160049f, -0.0217688642f}, + {-0.0140205137f, 0.0431507044f}, + {-0.0874397159f, 0.0284108873f}, + {-0.0928243399f, -0.0674408302f}, + {-0.0000000000f, -0.1173682660f}, + { 0.0846020356f, -0.0614669770f}, + { 0.0776479617f, 0.0252293516f}, + { 0.0166357141f, 0.0511994623f}, + }, + { + { 0.0086805914f, -0.0267161131f}, /* Filter 1 */ + { 0.0534664392f, -0.0173722990f}, + { 0.0678047314f, 0.0492630191f}, + {-0.0000000000f, 0.1061014757f}, + {-0.0953093544f, 0.0692462996f}, + {-0.1081032082f, -0.0351248607f}, + {-0.0275043193f, -0.0846495852f}, + { 0.0237129591f, -0.0326380879f}, + {-0.0341038331f, -0.0000000000f}, + {-0.0787785500f, -0.1084293649f}, + { 0.0793628618f, -0.2442537695f}, + { 0.3781612813f, -0.1228720471f}, + { 0.4445744753f, 0.3230022490f}, + {-0.0000000001f, 0.7040774226f}, + {-0.6892225146f, 0.5007494688f}, + {-0.9354411960f, -0.3039432764f}, + {-0.3369024098f, -1.0368790627f}, + { 0.6845118403f, -0.9421496987f}, + { 1.2013363838f, 0.0000000000f}, + { 0.7041431069f, 0.9691697955f}, + {-0.3568129838f, 1.0981574059f}, + {-1.0219419003f, 0.3320490718f}, + {-0.7792053819f, -0.5661258698f}, + {-0.0000000001f, -0.8281568289f}, + { 0.5489386916f, -0.3988272846f}, + { 0.4981442094f, 0.1618568748f}, + { 0.1153177992f, 0.3549116850f}, + {-0.1380993575f, 0.1900774688f}, + {-0.1156847477f, 0.0000000000f}, + {-0.0116915042f, -0.0160919763f}, + {-0.0155188413f, 0.0477620810f}, + {-0.0900719389f, 0.0292661469f}, + {-0.0935767666f, -0.0679875016f}, + {-0.0000000000f, -0.1168202460f}, + { 0.0833092555f, -0.0605277158f}, + { 0.0755547658f, 0.0245492328f}, + { 0.0158989299f, 0.0489318743f}, + }, + { + { 0.0093799150f, -0.0288684089f}, /* Filter 2 */ + { 0.0557304025f, -0.0181079060f}, + { 0.0695286095f, 0.0505154915f}, + {-0.0000000000f, 0.1075555831f}, + {-0.0955764726f, 0.0694403723f}, + {-0.1069486886f, -0.0347497351f}, + {-0.0265459362f, -0.0816999897f}, + { 0.0206513591f, -0.0284241568f}, + {-0.0414781198f, -0.0000000000f}, + {-0.0843107775f, -0.1160438284f}, + { 0.0828017443f, -0.2548375726f}, + { 0.3898994923f, -0.1266860217f}, + { 0.4550133944f, 0.3305865824f}, + {-0.0000000001f, 0.7167864442f}, + {-0.6987025142f, 0.5076370835f}, + {-0.9449097514f, -0.3070197999f}, + {-0.3392250240f, -1.0440272093f}, + { 0.6871879101f, -0.9458330274f}, + { 1.2026044130f, 0.0000000000f}, + { 0.7029046416f, 0.9674652219f}, + {-0.3551651835f, 1.0930860043f}, + {-1.0141602755f, 0.3295206726f}, + {-0.7707393169f, -0.5599749088f}, + {-0.0000000001f, -0.8161166310f}, + { 0.5385575294f, -0.3912849724f}, + { 0.4859414399f, 0.1578919441f}, + { 0.1115802750f, 0.3434087634f}, + {-0.1317866892f, 0.1813888103f}, + {-0.1067595631f, 0.0000000000f}, + {-0.0076726158f, -0.0105604501f}, + {-0.0169618148f, 0.0522031002f}, + {-0.0925478712f, 0.0300706252f}, + {-0.0942174047f, -0.0684529543f}, + {-0.0000000000f, -0.1161677912f}, + { 0.0819620788f, -0.0595489368f}, + { 0.0734324455f, 0.0238596480f}, + { 0.0151627110f, 0.0466660261f}, + }, + { + { 0.0100859674f, -0.0310414154f}, /* Filter 3 */ + { 0.0579889156f, -0.0188417397f}, + { 0.0712205172f, 0.0517447330f}, + {-0.0000000000f, 0.1089330688f}, + {-0.0957518741f, 0.0695678070f}, + {-0.1056557149f, -0.0343296230f}, + {-0.0255352631f, -0.0785894617f}, + { 0.0174835511f, -0.0240640435f}, + {-0.0490297712f, -0.0000000000f}, + {-0.0899358466f, -0.1237860769f}, + { 0.0862785354f, -0.2655380368f}, + { 0.4017075598f, -0.1305226982f}, + { 0.4654633999f, 0.3381789625f}, + {-0.0000000001f, 0.7294434309f}, + {-0.7080869079f, 0.5144552588f}, + {-0.9542079568f, -0.3100409508f}, + {-0.3414767087f, -1.0509572029f}, + { 0.6897085309f, -0.9493023753f}, + { 1.2035913467f, 0.0000000000f}, + { 0.7015029192f, 0.9655358791f}, + {-0.3534386754f, 1.0877723694f}, + {-1.0061750412f, 0.3269260824f}, + {-0.7621439099f, -0.5537299514f}, + {-0.0000000001f, -0.8039799333f}, + { 0.5281522870f, -0.3837251067f}, + { 0.4737714827f, 0.1539376825f}, + { 0.1078709438f, 0.3319926262f}, + {-0.1255540103f, 0.1728102714f}, + {-0.0980006009f, 0.0000000000f}, + {-0.0037596615f, -0.0051747300f}, + {-0.0183496606f, 0.0564744473f}, + {-0.0948692262f, 0.0308248810f}, + {-0.0947483405f, -0.0688387007f}, + {-0.0000000000f, -0.1154139340f}, + { 0.0805630460f, -0.0585324802f}, + { 0.0712837577f, 0.0231614988f}, + { 0.0144278063f, 0.0444042198f}, + }, + { + { 0.0107981311f, -0.0332332328f}, /* Filter 4 */ + { 0.0602394938f, -0.0195729975f}, + { 0.0728780255f, 0.0529489815f}, + {-0.0000000000f, 0.1102307960f}, + {-0.0958332121f, 0.0696269050f}, + {-0.1042220443f, -0.0338637941f}, + {-0.0244718455f, -0.0753165931f}, + { 0.0142093524f, -0.0195574965f}, + {-0.0567577891f, -0.0000000000f}, + {-0.0956523716f, -0.1316542029f}, + { 0.0897921249f, -0.2763517499f}, + { 0.4135811031f, -0.1343806386f}, + { 0.4759201407f, 0.3457762301f}, + {-0.0000000001f, 0.7420427203f}, + {-0.7173712850f, 0.5212007165f}, + {-0.9633312821f, -0.3130052984f}, + {-0.3436563909f, -1.0576655865f}, + { 0.6920724511f, -0.9525560141f}, + { 1.2042965889f, 0.0000000000f}, + { 0.6999385953f, 0.9633828402f}, + {-0.3516343236f, 1.0822191238f}, + {-0.9979898930f, 0.3242665529f}, + {-0.7534233332f, -0.5473940969f}, + {-0.0000000001f, -0.7917523384f}, + { 0.5177274346f, -0.3761509955f}, + { 0.4616391361f, 0.1499956548f}, + { 0.1041911170f, 0.3206672966f}, + {-0.1194031686f, 0.1643443555f}, + {-0.0894096494f, 0.0000000000f}, + { 0.0000471013f, 0.0000648294f}, + {-0.0196826290f, 0.0605769046f}, + {-0.0970377848f, 0.0315294862f}, + {-0.0951716974f, -0.0691462904f}, + {-0.0000000000f, -0.1145617142f}, + { 0.0791146755f, -0.0574801750f}, + { 0.0691114515f, 0.0224556718f}, + { 0.0136949494f, 0.0421487205f}, + }, + { + { 0.0115157729f, -0.0354419053f}, /* Filter 5 */ + { 0.0624796189f, -0.0203008596f}, + { 0.0744986683f, 0.0541264527f}, + {-0.0000000000f, 0.1114456356f}, + {-0.0958181471f, 0.0696159601f}, + {-0.1026455015f, -0.0333515443f}, + {-0.0233552568f, -0.0718800873f}, + { 0.0108286384f, -0.0149043426f}, + {-0.0646610633f, -0.0000000000f}, + {-0.1014589071f, -0.1396462023f}, + { 0.0933413655f, -0.2872751951f}, + { 0.4255155921f, -0.1382583976f}, + { 0.4863792956f, 0.3533752263f}, + {-0.0000000001f, 0.7545788884f}, + {-0.7265513539f, 0.5278704762f}, + {-0.9722753763f, -0.3159114122f}, + {-0.3457630277f, -1.0641491413f}, + { 0.6942784786f, -0.9555923343f}, + { 1.2047197819f, 0.0000000000f}, + { 0.6982125044f, 0.9610070586f}, + {-0.3497529626f, 1.0764288902f}, + {-0.9896088243f, 0.3215433955f}, + {-0.7445815802f, -0.5409702063f}, + {-0.0000000001f, -0.7794392109f}, + { 0.5072873235f, -0.3685658276f}, + { 0.4495492578f, 0.1460674107f}, + { 0.1005420759f, 0.3094367087f}, + {-0.1133359149f, 0.1559935063f}, + {-0.0809883848f, 0.0000000000f}, + { 0.0037474802f, 0.0051579643f}, + {-0.0209610034f, 0.0645113364f}, + {-0.0990553871f, 0.0321850479f}, + {-0.0954896435f, -0.0693772882f}, + {-0.0000000000f, -0.1136142015f}, + { 0.0776194856f, -0.0563938580f}, + { 0.0669182166f, 0.0217430461f}, + { 0.0129648596f, 0.0399017334f}, + }, + { + { 0.0122382389f, -0.0376654267f}, /* Filter 6 */ + { 0.0647067279f, -0.0210244898f}, + { 0.0760799870f, 0.0552753434f}, + {-0.0000000000f, 0.1125744730f}, + {-0.0957043841f, 0.0695333034f}, + {-0.1009239629f, -0.0327921845f}, + {-0.0221851002f, -0.0682787150f}, + { 0.0073413476f, -0.0101044979f}, + {-0.0727383792f, -0.0000000000f}, + {-0.1073539481f, -0.1477600336f}, + { 0.0969250873f, -0.2983047366f}, + { 0.4375065267f, -0.1421544850f}, + { 0.4968364835f, 0.3609728217f}, + {-0.0000000001f, 0.7670462132f}, + {-0.7356228828f, 0.5344613194f}, + {-0.9810359478f, -0.3187578917f}, + {-0.3477955461f, -1.0704045296f}, + { 0.6963254809f, -0.9584097862f}, + { 1.2048609257f, 0.0000000000f}, + { 0.6963254809f, 0.9584097862f}, + {-0.3477955461f, 1.0704045296f}, + {-0.9810359478f, 0.3187578917f}, + {-0.7356228828f, -0.5344613194f}, + {-0.0000000001f, -0.7670462132f}, + { 0.4968364835f, -0.3609728217f}, + { 0.4375065267f, 0.1421544850f}, + { 0.0969250873f, 0.2983047366f}, + {-0.1073539481f, 0.1477600336f}, + {-0.0727383792f, 0.0000000000f}, + { 0.0073413476f, 0.0101044979f}, + {-0.0221851002f, 0.0682787150f}, + {-0.1009239629f, 0.0327921845f}, + {-0.0957043841f, -0.0695333034f}, + {-0.0000000000f, -0.1125744730f}, + { 0.0760799870f, -0.0552753434f}, + { 0.0647067279f, 0.0210244898f}, + { 0.0122382389f, 0.0376654267f}, + }, + { + { 0.0129648596f, -0.0399017334f}, /* Filter 7 */ + { 0.0669182166f, -0.0217430461f}, + { 0.0776194856f, 0.0563938580f}, + {-0.0000000000f, 0.1136142015f}, + {-0.0954896435f, 0.0693772882f}, + {-0.0990553871f, -0.0321850479f}, + {-0.0209610034f, -0.0645113364f}, + { 0.0037474802f, -0.0051579643f}, + {-0.0809883848f, -0.0000000000f}, + {-0.1133359149f, -0.1559935063f}, + { 0.1005420759f, -0.3094367087f}, + { 0.4495492578f, -0.1460674107f}, + { 0.5072873235f, 0.3685658276f}, + {-0.0000000001f, 0.7794392109f}, + {-0.7445815802f, 0.5409702063f}, + {-0.9896088243f, -0.3215433955f}, + {-0.3497529626f, -1.0764288902f}, + { 0.6982125044f, -0.9610070586f}, + { 1.2047197819f, 0.0000000000f}, + { 0.6942784786f, 0.9555923343f}, + {-0.3457630277f, 1.0641491413f}, + {-0.9722753763f, 0.3159114122f}, + {-0.7265513539f, -0.5278704762f}, + {-0.0000000001f, -0.7545788884f}, + { 0.4863792956f, -0.3533752263f}, + { 0.4255155921f, 0.1382583976f}, + { 0.0933413655f, 0.2872751951f}, + {-0.1014589071f, 0.1396462023f}, + {-0.0646610633f, 0.0000000000f}, + { 0.0108286384f, 0.0149043426f}, + {-0.0233552568f, 0.0718800873f}, + {-0.1026455015f, 0.0333515443f}, + {-0.0958181471f, -0.0696159601f}, + {-0.0000000000f, -0.1114456356f}, + { 0.0744986683f, -0.0541264527f}, + { 0.0624796189f, 0.0203008596f}, + { 0.0115157729f, 0.0354419053f}, + }, + { + { 0.0136949494f, -0.0421487205f}, /* Filter 8 */ + { 0.0691114515f, -0.0224556718f}, + { 0.0791146755f, 0.0574801750f}, + {-0.0000000000f, 0.1145617142f}, + {-0.0951716974f, 0.0691462904f}, + {-0.0970377848f, -0.0315294862f}, + {-0.0196826290f, -0.0605769046f}, + { 0.0000471013f, -0.0000648294f}, + {-0.0894096494f, -0.0000000000f}, + {-0.1194031686f, -0.1643443555f}, + { 0.1041911170f, -0.3206672966f}, + { 0.4616391361f, -0.1499956548f}, + { 0.5177274346f, 0.3761509955f}, + {-0.0000000001f, 0.7917523384f}, + {-0.7534233332f, 0.5473940969f}, + {-0.9979898930f, -0.3242665529f}, + {-0.3516343236f, -1.0822191238f}, + { 0.6999385953f, -0.9633828402f}, + { 1.2042965889f, 0.0000000000f}, + { 0.6920724511f, 0.9525560141f}, + {-0.3436563909f, 1.0576655865f}, + {-0.9633312821f, 0.3130052984f}, + {-0.7173712850f, -0.5212007165f}, + {-0.0000000001f, -0.7420427203f}, + { 0.4759201407f, -0.3457762301f}, + { 0.4135811031f, 0.1343806386f}, + { 0.0897921249f, 0.2763517499f}, + {-0.0956523716f, 0.1316542029f}, + {-0.0567577891f, 0.0000000000f}, + { 0.0142093524f, 0.0195574965f}, + {-0.0244718455f, 0.0753165931f}, + {-0.1042220443f, 0.0338637941f}, + {-0.0958332121f, -0.0696269050f}, + {-0.0000000000f, -0.1102307960f}, + { 0.0728780255f, -0.0529489815f}, + { 0.0602394938f, 0.0195729975f}, + { 0.0107981311f, 0.0332332328f}, + }, + { + { 0.0144278063f, -0.0444042198f}, /* Filter 9 */ + { 0.0712837577f, -0.0231614988f}, + { 0.0805630460f, 0.0585324802f}, + {-0.0000000000f, 0.1154139340f}, + {-0.0947483405f, 0.0688387007f}, + {-0.0948692262f, -0.0308248810f}, + {-0.0183496606f, -0.0564744473f}, + {-0.0037596615f, 0.0051747300f}, + {-0.0980006009f, -0.0000000000f}, + {-0.1255540103f, -0.1728102714f}, + { 0.1078709438f, -0.3319926262f}, + { 0.4737714827f, -0.1539376825f}, + { 0.5281522870f, 0.3837251067f}, + {-0.0000000001f, 0.8039799333f}, + {-0.7621439099f, 0.5537299514f}, + {-1.0061750412f, -0.3269260824f}, + {-0.3534386754f, -1.0877723694f}, + { 0.7015029192f, -0.9655358791f}, + { 1.2035913467f, 0.0000000000f}, + { 0.6897085309f, 0.9493023753f}, + {-0.3414767087f, 1.0509572029f}, + {-0.9542079568f, 0.3100409508f}, + {-0.7080869079f, -0.5144552588f}, + {-0.0000000001f, -0.7294434309f}, + { 0.4654633999f, -0.3381789625f}, + { 0.4017075598f, 0.1305226982f}, + { 0.0862785354f, 0.2655380368f}, + {-0.0899358466f, 0.1237860769f}, + {-0.0490297712f, 0.0000000000f}, + { 0.0174835511f, 0.0240640435f}, + {-0.0255352631f, 0.0785894617f}, + {-0.1056557149f, 0.0343296230f}, + {-0.0957518741f, -0.0695678070f}, + {-0.0000000000f, -0.1089330688f}, + { 0.0712205172f, -0.0517447330f}, + { 0.0579889156f, 0.0188417397f}, + { 0.0100859674f, 0.0310414154f}, + }, + { + { 0.0151627110f, -0.0466660261f}, /* Filter 10 */ + { 0.0734324455f, -0.0238596480f}, + { 0.0819620788f, 0.0595489368f}, + {-0.0000000000f, 0.1161677912f}, + {-0.0942174047f, 0.0684529543f}, + {-0.0925478712f, -0.0300706252f}, + {-0.0169618148f, -0.0522031002f}, + {-0.0076726158f, 0.0105604501f}, + {-0.1067595631f, -0.0000000000f}, + {-0.1317866892f, -0.1813888103f}, + { 0.1115802750f, -0.3434087634f}, + { 0.4859414399f, -0.1578919441f}, + { 0.5385575294f, 0.3912849724f}, + {-0.0000000001f, 0.8161166310f}, + {-0.7707393169f, 0.5599749088f}, + {-1.0141602755f, -0.3295206726f}, + {-0.3551651835f, -1.0930860043f}, + { 0.7029046416f, -0.9674652219f}, + { 1.2026044130f, 0.0000000000f}, + { 0.6871879101f, 0.9458330274f}, + {-0.3392250240f, 1.0440272093f}, + {-0.9449097514f, 0.3070197999f}, + {-0.6987025142f, -0.5076370835f}, + {-0.0000000001f, -0.7167864442f}, + { 0.4550133944f, -0.3305865824f}, + { 0.3898994923f, 0.1266860217f}, + { 0.0828017443f, 0.2548375726f}, + {-0.0843107775f, 0.1160438284f}, + {-0.0414781198f, 0.0000000000f}, + { 0.0206513591f, 0.0284241568f}, + {-0.0265459362f, 0.0816999897f}, + {-0.1069486886f, 0.0347497351f}, + {-0.0955764726f, -0.0694403723f}, + {-0.0000000000f, -0.1075555831f}, + { 0.0695286095f, -0.0505154915f}, + { 0.0557304025f, 0.0181079060f}, + { 0.0093799150f, 0.0288684089f}, + }, + { + { 0.0158989299f, -0.0489318743f}, /* Filter 11 */ + { 0.0755547658f, -0.0245492328f}, + { 0.0833092555f, 0.0605277158f}, + {-0.0000000000f, 0.1168202460f}, + {-0.0935767666f, 0.0679875016f}, + {-0.0900719389f, -0.0292661469f}, + {-0.0155188413f, -0.0477620810f}, + {-0.0116915042f, 0.0160919763f}, + {-0.1156847477f, -0.0000000000f}, + {-0.1380993575f, -0.1900774688f}, + { 0.1153177992f, -0.3549116850f}, + { 0.4981442094f, -0.1618568748f}, + { 0.5489386916f, 0.3988272846f}, + {-0.0000000001f, 0.8281568289f}, + {-0.7792053819f, 0.5661258698f}, + {-1.0219419003f, -0.3320490718f}, + {-0.3568129838f, -1.0981574059f}, + { 0.7041431069f, -0.9691697955f}, + { 1.2013363838f, 0.0000000000f}, + { 0.6845118403f, 0.9421496987f}, + {-0.3369024098f, 1.0368790627f}, + {-0.9354411960f, 0.3039432764f}, + {-0.6892225146f, -0.5007494688f}, + {-0.0000000001f, -0.7040774226f}, + { 0.4445744753f, -0.3230022490f}, + { 0.3781612813f, 0.1228720471f}, + { 0.0793628618f, 0.2442537695f}, + {-0.0787785500f, 0.1084293649f}, + {-0.0341038331f, 0.0000000000f}, + { 0.0237129591f, 0.0326380879f}, + {-0.0275043193f, 0.0846495852f}, + {-0.1081032082f, 0.0351248607f}, + {-0.0953093544f, -0.0692462996f}, + {-0.0000000000f, -0.1061014757f}, + { 0.0678047314f, -0.0492630191f}, + { 0.0534664392f, 0.0173722990f}, + { 0.0086805914f, 0.0267161131f}, + }, +}; + +static const complexf_t pulseshaper_2400[PULSESHAPER_COEFF_SETS][V22BIS_RX_FILTER_STEPS] = +{ + { + { 0.0209144205f, 0.0151952161f}, /* Filter 0 */ + {-0.0435528643f, 0.0316430070f}, + {-0.0252293516f, -0.0776479617f}, + { 0.1045738682f, 0.0000000001f}, + {-0.0362687893f, 0.1116238534f}, + {-0.0928243399f, -0.0674408302f}, + { 0.0743806660f, -0.0540407188f}, + { 0.0140205137f, 0.0431507044f}, + { 0.0269077960f, 0.0000000000f}, + {-0.0385573655f, 0.1186673641f}, + {-0.1988736391f, -0.1444901675f}, + { 0.3117611706f, -0.2265077531f}, + { 0.1658308655f, 0.5103749037f}, + {-0.6913219094f, -0.0000000002f}, + { 0.2596036494f, -0.7989778519f}, + { 0.7875382304f, 0.5721800327f}, + {-0.8757586479f, 0.6362759471f}, + {-0.3583812416f, -1.1029839516f}, + { 1.1997879744f, 0.0000000000f}, + {-0.3707548678f, 1.1410661936f}, + {-0.9382542372f, -0.6816816330f}, + { 0.8757586479f, -0.6362759471f}, + { 0.3008128405f, 0.9258067012f}, + {-0.8400950432f, 0.0000000002f}, + { 0.2136302292f, -0.6574862003f}, + { 0.4341508448f, 0.3154290617f}, + {-0.3117611706f, 0.2265077531f}, + {-0.0759629756f, -0.2337899953f}, + { 0.1247742549f, -0.0000000001f}, + {-0.0083149662f, 0.0255908351f}, + { 0.0367061794f, 0.0266686007f}, + {-0.0743806660f, 0.0540407188f}, + {-0.0354557447f, -0.1091215536f}, + { 0.1173682660f, -0.0000000001f}, + {-0.0323151015f, 0.0994556621f}, + {-0.0660513043f, -0.0479890816f}, + { 0.0435528643f, -0.0316430070f}, + }, + { + { 0.0227260832f, 0.0165114664f}, /* Filter 1 */ + {-0.0454812683f, 0.0330440775f}, + {-0.0258991010f, -0.0797092393f}, + { 0.1061014757f, 0.0000000001f}, + {-0.0364049338f, 0.1120428666f}, + {-0.0919580832f, -0.0668114573f}, + { 0.0720072389f, -0.0523163229f}, + { 0.0124666411f, 0.0383683741f}, + { 0.0341038331f, 0.0000000000f}, + {-0.0414163321f, 0.1274663657f}, + {-0.2077746689f, -0.1509571373f}, + { 0.3216831982f, -0.2337165177f}, + { 0.1698123366f, 0.5226286054f}, + {-0.7040774226f, -0.0000000002f}, + { 0.2632595599f, -0.8102296591f}, + { 0.7957338095f, 0.5781344771f}, + {-0.8820219636f, 0.6408264637f}, + {-0.3598691821f, -1.1075633764f}, + { 1.2013363838f, 0.0000000000f}, + {-0.3701899350f, 1.1393274069f}, + {-0.9341484904f, -0.6786985993f}, + { 0.8693157434f, -0.6315948367f}, + { 0.2976299822f, 0.9160109162f}, + {-0.8281568289f, 0.0000000002f}, + { 0.2096759230f, -0.6453161240f}, + { 0.4237467945f, 0.3078700602f}, + {-0.3019059300f, 0.2193474919f}, + {-0.0726031289f, -0.2234494686f}, + { 0.1156847477f, -0.0000000001f}, + {-0.0061465879f, 0.0189172514f}, + { 0.0406288542f, 0.0295185894f}, + {-0.0766197667f, 0.0556675196f}, + {-0.0357431434f, -0.1100060865f}, + { 0.1168202460f, -0.0000000001f}, + {-0.0318213031f, 0.0979359001f}, + {-0.0642707273f, -0.0466954149f}, + { 0.0416239388f, -0.0302415621f}, + }, + { + { 0.0245569348f, 0.0178416576f}, /* Filter 2 */ + {-0.0474071130f, 0.0344432816f}, + {-0.0265575647f, -0.0817357823f}, + { 0.1075555831f, 0.0000000001f}, + {-0.0365069620f, 0.1123568788f}, + {-0.0909759924f, -0.0660979301f}, + { 0.0694981664f, -0.0504933707f}, + { 0.0108570615f, 0.0334145986f}, + { 0.0414781198f, 0.0000000000f}, + {-0.0443248004f, 0.1364177018f}, + {-0.2167777866f, -0.1574982852f}, + { 0.3316683173f, -0.2409711480f}, + { 0.1737996489f, 0.5349003077f}, + {-0.7167864442f, -0.0000000002f}, + { 0.2668806314f, -0.8213740587f}, + { 0.8037882447f, 0.5839863420f}, + {-0.8881026506f, 0.6452443004f}, + {-0.3612760901f, -1.1118934155f}, + { 1.2026044130f, 0.0000000000f}, + {-0.3695388138f, 1.1373236179f}, + {-0.9298345447f, -0.6755643487f}, + { 0.8626962900f, -0.6267855763f}, + { 0.2943962216f, 0.9060583711f}, + {-0.8161166310f, 0.0000000002f}, + { 0.2057106793f, -0.6331123710f}, + { 0.4133664668f, 0.3003283143f}, + {-0.2921209633f, 0.2122382969f}, + {-0.0692843646f, -0.2132353336f}, + { 0.1067595631f, -0.0000000001f}, + {-0.0040337327f, 0.0124145532f}, + { 0.0444066115f, 0.0322632901f}, + {-0.0787259191f, 0.0571977310f}, + {-0.0359878466f, -0.1107592061f}, + { 0.1161677912f, -0.0000000001f}, + {-0.0313067287f, 0.0963522047f}, + {-0.0624653697f, -0.0453837477f}, + { 0.0396964923f, -0.0288411900f}, + }, + { + { 0.0264054053f, 0.0191846490f}, /* Filter 3 */ + {-0.0493283160f, 0.0358391218f}, + {-0.0272038169f, -0.0837247372f}, + { 0.1089330688f, 0.0000000001f}, + {-0.0365739614f, 0.1125630811f}, + {-0.0898761228f, -0.0652988255f}, + { 0.0668521896f, -0.0485709570f}, + { 0.0091916462f, 0.0282889791f}, + { 0.0490297712f, 0.0000000000f}, + {-0.0472820736f, 0.1455192566f}, + {-0.2258801460f, -0.1641115248f}, + { 0.3417128623f, -0.2482689321f}, + { 0.1777911931f, 0.5471850634f}, + {-0.7294434309f, -0.0000000002f}, + { 0.2704651356f, -0.8324060440f}, + { 0.8116977811f, 0.5897329450f}, + {-0.8939976096f, 0.6495273113f}, + {-0.3626012504f, -1.1159719229f}, + { 1.2035913467f, 0.0000000000f}, + {-0.3688018918f, 1.1350555420f}, + {-0.9253144860f, -0.6722803116f}, + { 0.8559035659f, -0.6218503714f}, + { 0.2911130786f, 0.8959538937f}, + {-0.8039799333f, 0.0000000002f}, + { 0.2017362267f, -0.6208803058f}, + { 0.4030140936f, 0.2928068638f}, + {-0.2824097872f, 0.2051827312f}, + {-0.0660076514f, -0.2031506598f}, + { 0.0980006009f, -0.0000000001f}, + {-0.0019765710f, 0.0060832603f}, + { 0.0480400361f, 0.0349031277f}, + {-0.0807005838f, 0.0586324073f}, + {-0.0361906476f, -0.1113833562f}, + { 0.1154139340f, -0.0000000001f}, + {-0.0307723451f, 0.0947075412f}, + {-0.0606375895f, -0.0440557860f}, + { 0.0377724878f, -0.0274433177f}, + }, + { + { 0.0282698758f, 0.0205392670f}, /* Filter 4 */ + {-0.0512427762f, 0.0372300558f}, + {-0.0278369281f, -0.0856732503f}, + { 0.1102307960f, 0.0000000001f}, + {-0.0366050303f, 0.1126586944f}, + {-0.0886565670f, -0.0644127652f}, + { 0.0640681237f, -0.0465482138f}, + { 0.0074702986f, 0.0229912158f}, + { 0.0567577891f, 0.0000000000f}, + {-0.0502874292f, 0.1547687948f}, + {-0.2350788414f, -0.1707947701f}, + { 0.3518131077f, -0.2556071877f}, + { 0.1817853153f, 0.5594776869f}, + {-0.7420427203f, -0.0000000002f}, + { 0.2740114331f, -0.8433204889f}, + { 0.8194585443f, 0.5953714848f}, + {-0.8997041583f, 0.6536732912f}, + {-0.3638440073f, -1.1197967529f}, + { 1.2042965889f, 0.0000000000f}, + {-0.3679794967f, 1.1325244904f}, + {-0.9205905795f, -0.6688482165f}, + { 0.8489409089f, -0.6167916656f}, + { 0.2877821028f, 0.8857022524f}, + {-0.7917523384f, 0.0000000002f}, + { 0.1977542788f, -0.6086250544f}, + { 0.3926937282f, 0.2853086889f}, + {-0.2727758884f, 0.1981832832f}, + {-0.0627739578f, -0.1931983829f}, + { 0.0894096494f, -0.0000000000f}, + { 0.0000247626f, -0.0000762115f}, + { 0.0515297912f, 0.0374385864f}, + {-0.0825452656f, 0.0599726476f}, + {-0.0363523550f, -0.1118810475f}, + { 0.1145617142f, -0.0000000001f}, + {-0.0302191172f, 0.0930048823f}, + {-0.0587897114f, -0.0427132249f}, + { 0.0358538441f, -0.0260493420f}, + }, + { + { 0.0301486850f, 0.0219043009f}, /* Filter 5 */ + {-0.0531483367f, 0.0386145264f}, + {-0.0284559596f, -0.0875784382f}, + { 0.1114456356f, 0.0000000001f}, + {-0.0365992747f, 0.1126409844f}, + {-0.0873154774f, -0.0634384081f}, + { 0.0611448549f, -0.0444243364f}, + { 0.0056929523f, 0.0175211057f}, + { 0.0646610633f, 0.0000000000f}, + {-0.0533401072f, 0.1641639620f}, + {-0.2443708777f, -0.1775458306f}, + { 0.3619651794f, -0.2629830837f}, + { 0.1857803613f, 0.5717731118f}, + {-0.7545788884f, -0.0000000002f}, + { 0.2775179148f, -0.8541123271f}, + { 0.8270668387f, 0.6008992195f}, + {-0.9052193165f, 0.6576803327f}, + {-0.3650037944f, -1.1233661175f}, + { 1.2047197819f, 0.0000000000f}, + {-0.3670720458f, 1.1297315359f}, + {-0.9156650901f, -0.6652696729f}, + { 0.8418115377f, -0.6116119027f}, + { 0.2844048440f, 0.8753081560f}, + {-0.7794392109f, 0.0000000002f}, + { 0.1937665194f, -0.5963520408f}, + { 0.3824094236f, 0.2778367102f}, + {-0.2632225752f, 0.1912423968f}, + {-0.0595842153f, -0.1833813637f}, + { 0.0809883848f, -0.0000000000f}, + { 0.0019701670f, -0.0060635507f}, + { 0.0548766218f, 0.0398701988f}, + {-0.0842615440f, 0.0612195991f}, + {-0.0364737995f, -0.1122548133f}, + { 0.1136142015f, -0.0000000001f}, + {-0.0296480060f, 0.0912471786f}, + {-0.0569240339f, -0.0413577296f}, + { 0.0339424424f, -0.0246606283f}, + }, + { + { 0.0320401229f, 0.0232785121f}, /* Filter 6 */ + {-0.0550428294f, 0.0399909541f}, + {-0.0290599689f, -0.0894373879f}, + { 0.1125744730f, 0.0000000001f}, + {-0.0365558229f, 0.1125072464f}, + {-0.0858510509f, -0.0623744428f}, + { 0.0580813438f, -0.0421985686f}, + { 0.0038595749f, 0.0118785501f}, + { 0.0727383792f, 0.0000000000f}, + {-0.0564393103f, 0.1737023294f}, + {-0.2537531555f, -0.1843624711f}, + { 0.3721652627f, -0.2703939080f}, + { 0.1897746474f, 0.5840663314f}, + {-0.7670462132f, -0.0000000002f}, + { 0.2809829414f, -0.8647765517f}, + { 0.8345190287f, 0.6063135862f}, + {-0.9105405211f, 0.6615464091f}, + {-0.3660799563f, -1.1266783476f}, + { 1.2048609257f, 0.0000000000f}, + {-0.3660799563f, 1.1266783476f}, + {-0.9105405211f, -0.6615464091f}, + { 0.8345190287f, -0.6063135862f}, + { 0.2809829414f, 0.8647765517f}, + {-0.7670462132f, 0.0000000002f}, + { 0.1897746474f, -0.5840663314f}, + { 0.3721652627f, 0.2703939080f}, + {-0.2537531555f, 0.1843624711f}, + {-0.0564393103f, -0.1737023294f}, + { 0.0727383792f, -0.0000000000f}, + { 0.0038595749f, -0.0118785501f}, + { 0.0580813438f, 0.0421985686f}, + {-0.0858510509f, 0.0623744428f}, + {-0.0365558229f, -0.1125072464f}, + { 0.1125744730f, -0.0000000001f}, + {-0.0290599689f, 0.0894373879f}, + {-0.0550428294f, -0.0399909541f}, + { 0.0320401229f, -0.0232785121f}, + }, + { + { 0.0339424424f, 0.0246606283f}, /* Filter 7 */ + {-0.0569240339f, 0.0413577296f}, + {-0.0296480060f, -0.0912471786f}, + { 0.1136142015f, 0.0000000001f}, + {-0.0364737995f, 0.1122548133f}, + {-0.0842615440f, -0.0612195991f}, + { 0.0548766218f, -0.0398701988f}, + { 0.0019701670f, 0.0060635507f}, + { 0.0809883848f, 0.0000000000f}, + {-0.0595842153f, 0.1833813637f}, + {-0.2632225752f, -0.1912423968f}, + { 0.3824094236f, -0.2778367102f}, + { 0.1937665194f, 0.5963520408f}, + {-0.7794392109f, -0.0000000002f}, + { 0.2844048440f, -0.8753081560f}, + { 0.8418115377f, 0.6116119027f}, + {-0.9156650901f, 0.6652696729f}, + {-0.3670720458f, -1.1297315359f}, + { 1.2047197819f, 0.0000000000f}, + {-0.3650037944f, 1.1233661175f}, + {-0.9052193165f, -0.6576803327f}, + { 0.8270668387f, -0.6008992195f}, + { 0.2775179148f, 0.8541123271f}, + {-0.7545788884f, 0.0000000002f}, + { 0.1857803613f, -0.5717731118f}, + { 0.3619651794f, 0.2629830837f}, + {-0.2443708777f, 0.1775458306f}, + {-0.0533401072f, -0.1641639620f}, + { 0.0646610633f, -0.0000000000f}, + { 0.0056929523f, -0.0175211057f}, + { 0.0611448549f, 0.0444243364f}, + {-0.0873154774f, 0.0634384081f}, + {-0.0365992747f, -0.1126409844f}, + { 0.1114456356f, -0.0000000001f}, + {-0.0284559596f, 0.0875784382f}, + {-0.0531483367f, -0.0386145264f}, + { 0.0301486850f, -0.0219043009f}, + }, + { + { 0.0358538441f, 0.0260493420f}, /* Filter 8 */ + {-0.0587897114f, 0.0427132249f}, + {-0.0302191172f, -0.0930048823f}, + { 0.1145617142f, 0.0000000001f}, + {-0.0363523550f, 0.1118810475f}, + {-0.0825452656f, -0.0599726476f}, + { 0.0515297912f, -0.0374385864f}, + { 0.0000247626f, 0.0000762115f}, + { 0.0894096494f, 0.0000000000f}, + {-0.0627739578f, 0.1931983829f}, + {-0.2727758884f, -0.1981832832f}, + { 0.3926937282f, -0.2853086889f}, + { 0.1977542788f, 0.6086250544f}, + {-0.7917523384f, -0.0000000002f}, + { 0.2877821028f, -0.8857022524f}, + { 0.8489409089f, 0.6167916656f}, + {-0.9205905795f, 0.6688482165f}, + {-0.3679794967f, -1.1325244904f}, + { 1.2042965889f, 0.0000000000f}, + {-0.3638440073f, 1.1197967529f}, + {-0.8997041583f, -0.6536732912f}, + { 0.8194585443f, -0.5953714848f}, + { 0.2740114331f, 0.8433204889f}, + {-0.7420427203f, 0.0000000002f}, + { 0.1817853153f, -0.5594776869f}, + { 0.3518131077f, 0.2556071877f}, + {-0.2350788414f, 0.1707947701f}, + {-0.0502874292f, -0.1547687948f}, + { 0.0567577891f, -0.0000000000f}, + { 0.0074702986f, -0.0229912158f}, + { 0.0640681237f, 0.0465482138f}, + {-0.0886565670f, 0.0644127652f}, + {-0.0366050303f, -0.1126586944f}, + { 0.1102307960f, -0.0000000001f}, + {-0.0278369281f, 0.0856732503f}, + {-0.0512427762f, -0.0372300558f}, + { 0.0282698758f, -0.0205392670f}, + }, + { + { 0.0377724878f, 0.0274433177f}, /* Filter 9 */ + {-0.0606375895f, 0.0440557860f}, + {-0.0307723451f, -0.0947075412f}, + { 0.1154139340f, 0.0000000001f}, + {-0.0361906476f, 0.1113833562f}, + {-0.0807005838f, -0.0586324073f}, + { 0.0480400361f, -0.0349031277f}, + {-0.0019765710f, -0.0060832603f}, + { 0.0980006009f, 0.0000000001f}, + {-0.0660076514f, 0.2031506598f}, + {-0.2824097872f, -0.2051827312f}, + { 0.4030140936f, -0.2928068638f}, + { 0.2017362267f, 0.6208803058f}, + {-0.8039799333f, -0.0000000002f}, + { 0.2911130786f, -0.8959538937f}, + { 0.8559035659f, 0.6218503714f}, + {-0.9253144860f, 0.6722803116f}, + {-0.3688018918f, -1.1350555420f}, + { 1.2035913467f, 0.0000000000f}, + {-0.3626012504f, 1.1159719229f}, + {-0.8939976096f, -0.6495273113f}, + { 0.8116977811f, -0.5897329450f}, + { 0.2704651356f, 0.8324060440f}, + {-0.7294434309f, 0.0000000002f}, + { 0.1777911931f, -0.5471850634f}, + { 0.3417128623f, 0.2482689321f}, + {-0.2258801460f, 0.1641115248f}, + {-0.0472820736f, -0.1455192566f}, + { 0.0490297712f, -0.0000000000f}, + { 0.0091916462f, -0.0282889791f}, + { 0.0668521896f, 0.0485709570f}, + {-0.0898761228f, 0.0652988255f}, + {-0.0365739614f, -0.1125630811f}, + { 0.1089330688f, -0.0000000001f}, + {-0.0272038169f, 0.0837247372f}, + {-0.0493283160f, -0.0358391218f}, + { 0.0264054053f, -0.0191846490f}, + }, + { + { 0.0396964923f, 0.0288411900f}, /* Filter 10 */ + {-0.0624653697f, 0.0453837477f}, + {-0.0313067287f, -0.0963522047f}, + { 0.1161677912f, 0.0000000001f}, + {-0.0359878466f, 0.1107592061f}, + {-0.0787259191f, -0.0571977310f}, + { 0.0444066115f, -0.0322632901f}, + {-0.0040337327f, -0.0124145532f}, + { 0.1067595631f, 0.0000000001f}, + {-0.0692843646f, 0.2132353336f}, + {-0.2921209633f, -0.2122382969f}, + { 0.4133664668f, -0.3003283143f}, + { 0.2057106793f, 0.6331123710f}, + {-0.8161166310f, -0.0000000002f}, + { 0.2943962216f, -0.9060583711f}, + { 0.8626962900f, 0.6267855763f}, + {-0.9298345447f, 0.6755643487f}, + {-0.3695388138f, -1.1373236179f}, + { 1.2026044130f, 0.0000000000f}, + {-0.3612760901f, 1.1118934155f}, + {-0.8881026506f, -0.6452443004f}, + { 0.8037882447f, -0.5839863420f}, + { 0.2668806314f, 0.8213740587f}, + {-0.7167864442f, 0.0000000002f}, + { 0.1737996489f, -0.5349003077f}, + { 0.3316683173f, 0.2409711480f}, + {-0.2167777866f, 0.1574982852f}, + {-0.0443248004f, -0.1364177018f}, + { 0.0414781198f, -0.0000000000f}, + { 0.0108570615f, -0.0334145986f}, + { 0.0694981664f, 0.0504933707f}, + {-0.0909759924f, 0.0660979301f}, + {-0.0365069620f, -0.1123568788f}, + { 0.1075555831f, -0.0000000001f}, + {-0.0265575647f, 0.0817357823f}, + {-0.0474071130f, -0.0344432816f}, + { 0.0245569348f, -0.0178416576f}, + }, + { + { 0.0416239388f, 0.0302415621f}, /* Filter 11 */ + {-0.0642707273f, 0.0466954149f}, + {-0.0318213031f, -0.0979359001f}, + { 0.1168202460f, 0.0000000001f}, + {-0.0357431434f, 0.1100060865f}, + {-0.0766197667f, -0.0556675196f}, + { 0.0406288542f, -0.0295185894f}, + {-0.0061465879f, -0.0189172514f}, + { 0.1156847477f, 0.0000000001f}, + {-0.0726031289f, 0.2234494686f}, + {-0.3019059300f, -0.2193474919f}, + { 0.4237467945f, -0.3078700602f}, + { 0.2096759230f, 0.6453161240f}, + {-0.8281568289f, -0.0000000002f}, + { 0.2976299822f, -0.9160109162f}, + { 0.8693157434f, 0.6315948367f}, + {-0.9341484904f, 0.6786985993f}, + {-0.3701899350f, -1.1393274069f}, + { 1.2013363838f, 0.0000000000f}, + {-0.3598691821f, 1.1075633764f}, + {-0.8820219636f, -0.6408264637f}, + { 0.7957338095f, -0.5781344771f}, + { 0.2632595599f, 0.8102296591f}, + {-0.7040774226f, 0.0000000002f}, + { 0.1698123366f, -0.5226286054f}, + { 0.3216831982f, 0.2337165177f}, + {-0.2077746689f, 0.1509571373f}, + {-0.0414163321f, -0.1274663657f}, + { 0.0341038331f, -0.0000000000f}, + { 0.0124666411f, -0.0383683741f}, + { 0.0720072389f, 0.0523163229f}, + {-0.0919580832f, 0.0668114573f}, + {-0.0364049338f, -0.1120428666f}, + { 0.1061014757f, -0.0000000001f}, + {-0.0258991010f, 0.0797092393f}, + {-0.0454812683f, -0.0330440775f}, + { 0.0227260832f, -0.0165114664f}, + }, +}; + +static const uint8_t space_map_v22bis[6][6] = +{ + {11, 9, 9, 6, 6, 7}, + {10, 8, 8, 4, 4, 5}, + {10, 8, 8, 4, 4, 5}, + {13, 12, 12, 0, 0, 2}, + {13, 12, 12, 0, 0, 2}, + {15, 14, 14, 1, 1, 3} +}; + +float v22bis_rx_carrier_frequency(v22bis_state_t *s) +{ + return dds_frequencyf(s->rx_carrier_phase_rate); +} +/*- End of function --------------------------------------------------------*/ + +float v22bis_rx_symbol_timing_correction(v22bis_state_t *s) +{ + return (float) s->total_baud_timing_correction/((float) PULSESHAPER_COEFF_SETS*40.0f/(3.0f*2.0f)); +} +/*- End of function --------------------------------------------------------*/ + +float v22bis_rx_signal_power(v22bis_state_t *s) +{ + return power_meter_dbm0(&s->rx_power); +} +/*- End of function --------------------------------------------------------*/ + +int v22bis_rx_equalizer_state(v22bis_state_t *s, complexf_t **coeffs) +{ + *coeffs = s->eq_coeff; + return 2*V22BIS_EQUALIZER_LEN + 1; +} +/*- End of function --------------------------------------------------------*/ + +static void equalizer_reset(v22bis_state_t *s) +{ + int i; + + /* Start with an equalizer based on everything being perfect */ + for (i = 0; i < 2*V22BIS_EQUALIZER_LEN + 1; i++) + s->eq_coeff[i] = complex_setf(0.0f, 0.0f); + s->eq_coeff[V22BIS_EQUALIZER_LEN] = complex_setf(3.0f, 0.0f); + for (i = 0; i <= V22BIS_EQUALIZER_MASK; i++) + s->eq_buf[i] = complex_setf(0.0f, 0.0f); + + s->eq_coeff[V22BIS_EQUALIZER_LEN - 6].re = -0.02f; + s->eq_coeff[V22BIS_EQUALIZER_LEN - 5].re = 0.035f; + s->eq_coeff[V22BIS_EQUALIZER_LEN - 4].re = 0.08f; + s->eq_coeff[V22BIS_EQUALIZER_LEN - 3].re = -0.30f; + s->eq_coeff[V22BIS_EQUALIZER_LEN - 2].re = -0.37f; + s->eq_coeff[V22BIS_EQUALIZER_LEN - 1].re = 0.09f; + s->eq_coeff[V22BIS_EQUALIZER_LEN].re = 3.19f; + s->eq_coeff[V22BIS_EQUALIZER_LEN + 1].re = 0.09f; + s->eq_coeff[V22BIS_EQUALIZER_LEN + 2].re = -0.37f; + s->eq_coeff[V22BIS_EQUALIZER_LEN + 3].re = -0.30f; + s->eq_coeff[V22BIS_EQUALIZER_LEN + 5].re = 0.035f; + s->eq_coeff[V22BIS_EQUALIZER_LEN + 6].re = -0.02f; + + s->eq_put_step = 20 - 1; + s->eq_step = 0; + s->eq_delta = EQUALIZER_DELTA/(2*V22BIS_EQUALIZER_LEN + 1); +} +/*- End of function --------------------------------------------------------*/ + +static complexf_t equalizer_get(v22bis_state_t *s) +{ + int i; + int p; + complexf_t z; + complexf_t z1; + + /* Get the next equalized value. */ + z = complex_setf(0.0f, 0.0f); + p = s->eq_step - 1; + for (i = 0; i < 2*V22BIS_EQUALIZER_LEN + 1; i++) + { + p = (p - 1) & V22BIS_EQUALIZER_MASK; + z1 = complex_mulf(&s->eq_coeff[i], &s->eq_buf[p]); + z = complex_addf(&z, &z1); + } + return z; +} +/*- End of function --------------------------------------------------------*/ + +static void tune_equalizer(v22bis_state_t *s, const complexf_t *z, const complexf_t *target) +{ + int i; + int p; + complexf_t ez; + complexf_t z1; + + /* Find the x and y mismatch from the exact constellation position. */ + ez = complex_subf(target, z); + ez.re *= s->eq_delta; + ez.im *= s->eq_delta; + + p = s->eq_step - 1; + for (i = 0; i < 2*V22BIS_EQUALIZER_LEN + 1; i++) + { + p = (p - 1) & V22BIS_EQUALIZER_MASK; + z1 = complex_conjf(&s->eq_buf[p]); + z1 = complex_mulf(&ez, &z1); + s->eq_coeff[i] = complex_addf(&s->eq_coeff[i], &z1); + /* If we don't leak a little bit we seem to get some wandering adaption */ + s->eq_coeff[i].re *= 0.9999f; + s->eq_coeff[i].im *= 0.9999f; + } +} +/*- End of function --------------------------------------------------------*/ + +static __inline__ void track_carrier(v22bis_state_t *s, const complexf_t *z, const complexf_t *target) +{ + float error; + + /* For small errors the imaginary part of the difference between the actual and the target + positions is proportional to the phase error, for any particular target. However, the + different amplitudes of the various target positions scale things. */ + error = z->im*target->re - z->re*target->im; + + s->rx_carrier_phase_rate += (int32_t) (s->carrier_track_i*error); + s->rx_carrier_phase += (int32_t) (s->carrier_track_p*error); + //span_log(&s->logging, SPAN_LOG_FLOW, "Im = %15.5f f = %15.5f\n", error, dds_frequencyf(s->carrier_phase_rate)); +} +/*- End of function --------------------------------------------------------*/ + +static __inline__ void put_bit(v22bis_state_t *s, int bit) +{ + int out_bit; + + bit &= 1; + + /* Descramble the bit */ + s->rx_scramble_reg = (s->rx_scramble_reg << 1) | bit; + out_bit = (bit ^ (s->rx_scramble_reg >> 15) ^ (s->rx_scramble_reg >> 18)) & 1; + if (s->rx_scrambler_pattern_count >= 64) + { + out_bit ^= 1; + s->rx_scrambler_pattern_count = 0; + } + if (bit) + s->rx_scrambler_pattern_count++; + else + s->rx_scrambler_pattern_count = 0; + + s->put_bit(s->user_data, out_bit); +} +/*- End of function --------------------------------------------------------*/ + +static void decode_baud(v22bis_state_t *s, int nearest) +{ + static const uint8_t phase_steps[4] = + { + 1, 0, 2, 3 + }; + int raw_bits; + + raw_bits = phase_steps[((nearest - s->rx_constellation_state) >> 2) & 3]; + /* The first two bits are the quadrant */ + put_bit(s, raw_bits); + put_bit(s, raw_bits >> 1); + if (s->bit_rate == 2400) + { + /* The other two bits are the position within the quadrant */ + put_bit(s, nearest >> 1); + put_bit(s, nearest); + } + s->rx_constellation_state = nearest; +} +/*- End of function --------------------------------------------------------*/ + +static __inline__ int find_quadrant(const complexf_t *z) +{ + int b1; + int b2; + +#if 0 + /* Split along the axes, as follows: + 1 0 + 2 3 + */ + b1 = (z->re <= 0.0f); + b2 = (z->im <= 0.0f); + return (b2 << 1) | (b1 ^ b2); +#endif + /* Split the space along the two diagonals, as follows: + \ 1 / + 2 0 + / 3 \ + */ + b1 = (z->im > z->re); + b2 = (z->im < -z->re); + return (b2 << 1) | (b1 ^ b2); +} +/*- End of function --------------------------------------------------------*/ + +static void process_half_baud(v22bis_state_t *s, const complexf_t *sample) +{ + complexf_t a; + complexf_t b; + complexf_t c; + + complexf_t z; + complexf_t zz; + const complexf_t *target; + float p; + float q; + int re; + int im; + int nearest; + + z.re = sample->re; + z.im = sample->im; + + /* Add a sample to the equalizer's circular buffer, but don't calculate anything + at this time. */ + s->eq_buf[s->eq_step] = z; + s->eq_step = (s->eq_step + 1) & V22BIS_EQUALIZER_MASK; + + /* On alternate insertions we have a whole baud and must process it. */ + if ((s->rx_baud_phase ^= 1)) + return; + + /* Perform a Gardner test for baud alignment on the three most recent samples. */ +#if 0 + p = s->eq_buf[(s->eq_step - 3) & V22BIS_EQUALIZER_MASK].re + - s->eq_buf[(s->eq_step - 1) & V22BIS_EQUALIZER_MASK].re; + p *= s->eq_buf[(s->eq_step - 2) & V22BIS_EQUALIZER_MASK].re; + + q = s->eq_buf[(s->eq_step - 3) & V22BIS_EQUALIZER_MASK].im + - s->eq_buf[(s->eq_step - 1) & V22BIS_EQUALIZER_MASK].im; + q *= s->eq_buf[(s->eq_step - 2) & V22BIS_EQUALIZER_MASK].im; +#else + if (s->sixteen_way_decisions) + { + p = s->eq_buf[(s->eq_step - 3) & V22BIS_EQUALIZER_MASK].re + - s->eq_buf[(s->eq_step - 1) & V22BIS_EQUALIZER_MASK].re; + p *= s->eq_buf[(s->eq_step - 2) & V22BIS_EQUALIZER_MASK].re; + + q = s->eq_buf[(s->eq_step - 3) & V22BIS_EQUALIZER_MASK].im + - s->eq_buf[(s->eq_step - 1) & V22BIS_EQUALIZER_MASK].im; + q *= s->eq_buf[(s->eq_step - 2) & V22BIS_EQUALIZER_MASK].im; + } + else + { + /* Rotate the points to the 45 degree positions, to maximise the effectiveness of the Gardner algorithm */ + zz = complex_setf(cosf(26.57f*3.14159f/180.0f), sinf(26.57f*3.14159f/180.0f)); + a = complex_mulf(&s->eq_buf[(s->eq_step - 3) & V22BIS_EQUALIZER_MASK], &zz); + b = complex_mulf(&s->eq_buf[(s->eq_step - 2) & V22BIS_EQUALIZER_MASK], &zz); + c = complex_mulf(&s->eq_buf[(s->eq_step - 1) & V22BIS_EQUALIZER_MASK], &zz); + p = (a.re - c.re)*b.re; + q = (a.im - c.im)*b.im; + } +#endif + + p += q; + s->gardner_integrate += ((p + q) > 0.0f) ? s->gardner_step : -s->gardner_step; + + if (abs(s->gardner_integrate) >= 16) + { + /* This integrate and dump approach avoids rapid changes of the equalizer put step. + Rapid changes, without hysteresis, are bad. They degrade the equalizer performance + when the true symbol boundary is close to a sample boundary. */ + s->eq_put_step += (s->gardner_integrate/16); + s->total_baud_timing_correction += (s->gardner_integrate/16); +span_log(&s->logging, SPAN_LOG_FLOW, "Gardner kick %d [total %d]\n", s->gardner_integrate, s->total_baud_timing_correction); + if (s->qam_report) + s->qam_report(s->qam_user_data, NULL, NULL, s->gardner_integrate); + s->gardner_integrate = 0; + } + + z = equalizer_get(s); +printf("VVV %15.5f %15.5f\n", z.re, z.im); + +span_log(&s->logging, SPAN_LOG_FLOW, "VVV %p %d\n", s->user_data, s->rx_training); + if (s->sixteen_way_decisions) + { + re = (int) (z.re + 3.0f); + if (re > 5) + re = 5; + else if (re < 0) + re = 0; + im = (int) (z.im + 3.0f); + if (im > 5) + im = 5; + else if (im < 0) + im = 0; + nearest = space_map_v22bis[re][im]; + } + else + { + zz = complex_setf(3.0f/sqrtf(10.0f), -1.0f/sqrtf(10.0f)); + zz = complex_mulf(&z, &zz); + nearest = (find_quadrant(&zz) << 2) | 0x01; + printf("Trackit %15.5f %15.5f %15.5f %15.5f %d\n", z.re, z.im, zz.re, zz.im, nearest); + } + + switch (s->rx_training) + { + case V22BIS_TRAINING_STAGE_NORMAL_OPERATION: + /* Normal operation. */ + track_carrier(s, &z, &v22bis_constellation[nearest]); + tune_equalizer(s, &z, &v22bis_constellation[nearest]); + decode_baud(s, nearest); + target = &v22bis_constellation[s->rx_constellation_state]; + break; + case V22BIS_TRAINING_STAGE_SYMBOL_ACQUISITION: + /* Allow time for the Gardner algorithm to settle the symbol timing. */ + target = &z; + if (++s->rx_training_count >= 40) + { + s->gardner_step = 4; + if (s->caller) + { + s->rx_training = V22BIS_TRAINING_STAGE_UNSCRAMBLED_ONES; + } + else + { + if (s->bit_rate == 2400) + s->rx_training = V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011; + else + s->rx_training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200; + } + break; + } + + /* QAM and Gardner only play nicely with heavy damping, so we need to change to + a slow rate of symbol timing adaption. However, it must not be so slow that it + cannot track the worst case timing error specified in V.22bis. This should be 0.01%, + but since we might be off in the opposite direction from the source, the total + error could be higher. */ + if (s->rx_training_count == 30) + s->gardner_step = 32; + break; + case V22BIS_TRAINING_STAGE_UNSCRAMBLED_ONES: + /* The answering modem should initially receive unscrambled ones at 1200bps */ + track_carrier(s, &z, &v22bis_constellation[nearest]); + target = &z; + if (nearest == ((s->rx_constellation_state - 4) & 0x0F)) + s->detected_unscrambled_ones++; + if (nearest == ((s->rx_constellation_state + 4) & 0x0F)) + s->detected_unscrambled_zeros++; + s->rx_constellation_state = nearest; +span_log(&s->logging, SPAN_LOG_FLOW, "TWIDDLING THUMBS - %d\n", s->rx_training_count); + if (++s->rx_training_count == ms_to_symbols(155 + 456)) + { + if (s->detected_unscrambled_ones >= 250 || s->detected_unscrambled_zeros >= 250) + s->detected_unscrambled_ones_or_zeros = TRUE; + } + if (s->rx_training_count == ms_to_symbols(155 + 457)) + { + /* We should only bother looking for the 2400bps marker if we are allowed to use + 2400bps */ + s->rx_training_count = 0; + if (s->bit_rate == 2400) + s->rx_training = V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011; + else + s->rx_training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200; + } + break; + case V22BIS_TRAINING_STAGE_UNSCRAMBLED_0011: +s->sixteen_way_decisions = TRUE; + /* If we can actually find this it means we can use 2400bps. If we find unscrambled ones, it means we + we must use 1200bps. */ + track_carrier(s, &z, &v22bis_constellation[nearest]); + tune_equalizer(s, &z, &v22bis_constellation[nearest]); + target = &z; + //s->carrier_track_i = 1000.0f; + //s->carrier_track_p = 1000000.0f; +#if 0 + if (++s->rx_training_count > ms_to_symbols(800)) + { + s->detected_unscrambled_0011_ending = TRUE; + s->rx_training = V22BIS_TRAINING_STAGE_UNSCRAMBLED_ONES; + } +#else + if (++s->rx_training_count == 1) + { + s->detected_unscrambled_zeros = nearest; + s->detected_unscrambled_ones = 0; + } + else + { +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); + if ((s->rx_training_count & 1) == 0) + { +span_log(&s->logging, SPAN_LOG_FLOW, "AAA\n"); + if (((s->detected_unscrambled_zeros + nearest) & 0x0F) == 0x06) + s->detected_unscrambled_ones = 1; + else if (((s->detected_unscrambled_zeros + nearest) & 0x0F) == 0x02) + s->detected_unscrambled_ones = -1; + else + { +span_log(&s->logging, SPAN_LOG_FLOW, "AAA 1\n"); + if (s->detected_unscrambled_ones > 5 || s->detected_unscrambled_ones < -5) + s->detected_unscrambled_0011_ending = TRUE; + else + s->bit_rate = 1200; + s->rx_training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200; + } + } + else + { +span_log(&s->logging, SPAN_LOG_FLOW, "BBB\n"); + if (((s->detected_unscrambled_zeros + nearest) & 0x0F) == 0x06) + s->detected_unscrambled_ones = 1; + else if (((s->detected_unscrambled_zeros + nearest) & 0x0F) == 0x02) + s->detected_unscrambled_ones = -1; + else + { +span_log(&s->logging, SPAN_LOG_FLOW, "BBB 1\n"); + if (s->detected_unscrambled_ones > 5 || s->detected_unscrambled_ones < -5) + s->detected_unscrambled_0011_ending = TRUE; + else + s->bit_rate = 1200; + s->rx_training = V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200; + } + } + } +#endif + break; + case V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_1200: + track_carrier(s, &z, &v22bis_constellation[nearest]); + tune_equalizer(s, &z, &v22bis_constellation[nearest]); + target = &z; +span_log(&s->logging, SPAN_LOG_FLOW, "S11 0x%02x\n", nearest); + if (++s->rx_training_count > ms_to_symbols(900)) + { + s->detected_scrambled_ones_or_zeros_at_1200bps = TRUE; + s->rx_training = V22BIS_TRAINING_STAGE_NORMAL_OPERATION; + } + if (s->bit_rate == 2400 && s->rx_training_count == ms_to_symbols(450)) + s->sixteen_way_decisions = TRUE; + break; + case V22BIS_TRAINING_STAGE_SCRAMBLED_ONES_AT_2400: + track_carrier(s, &z, &v22bis_constellation[nearest]); + tune_equalizer(s, &z, &v22bis_constellation[nearest]); + s->sixteen_way_decisions = TRUE; + target = &z; + break; + case V22BIS_TRAINING_STAGE_PARKED: + default: + /* We failed to train! */ + /* Park here until the carrier drops. */ + target = &z; + break; + } + if (s->qam_report) + s->qam_report(s->qam_user_data, &z, target, s->rx_constellation_state); +} +/*- End of function --------------------------------------------------------*/ + +int v22bis_rx(v22bis_state_t *s, const int16_t amp[], int len) +{ + int i; + int j; + int step; + complexf_t z; + complexf_t zz; + int32_t power; + complexf_t sample; + float ii; + float qq; + + for (i = 0; i < len; i++) + { + /* Complex bandpass filter the signal, using a pair of FIRs, and RRC coeffs shifted + to centre at 1200Hz or 2400Hz. The filters support 12 fractional phase shifts, to + permit signal extraction very close to the middle of a symbol. */ + s->rx_rrc_filter[s->rx_rrc_filter_step] = + s->rx_rrc_filter[s->rx_rrc_filter_step + V22BIS_RX_FILTER_STEPS] = amp[i]; + if (++s->rx_rrc_filter_step >= V22BIS_RX_FILTER_STEPS) + s->rx_rrc_filter_step = 0; + + /* Calculate the I filter, with an arbitrary phase step, just so we can calculate + the signal power. */ + /* TODO: get rid of this */ + if (s->caller) + { + ii = pulseshaper_2400[6][0].re*s->rx_rrc_filter[s->rx_rrc_filter_step]; + for (j = 1; j < V22BIS_RX_FILTER_STEPS; j++) + ii += pulseshaper_2400[6][j].re*s->rx_rrc_filter[j + s->rx_rrc_filter_step]; + } + else + { + ii = pulseshaper_1200[6][0].re*s->rx_rrc_filter[s->rx_rrc_filter_step]; + for (j = 1; j < V22BIS_RX_FILTER_STEPS; j++) + ii += pulseshaper_1200[6][j].re*s->rx_rrc_filter[j + s->rx_rrc_filter_step]; + } + power = power_meter_update(&(s->rx_power), (int16_t) (ii/10.0f)); + if (s->carrier_present) + { + /* Look for power below -48dBm0 to turn the carrier off */ + if (power < s->carrier_off_power) + { + v22bis_rx_restart(s, s->bit_rate); + s->put_bit(s->user_data, PUTBIT_CARRIER_DOWN); + continue; + } + } + else + { + /* Look for power exceeding -43dBm0 to turn the carrier on */ + if (power < s->carrier_on_power) + continue; + s->carrier_present = TRUE; + s->put_bit(s->user_data, PUTBIT_CARRIER_UP); + } + if (s->rx_training != V22BIS_TRAINING_STAGE_PARKED) + { + /* Only spend effort processing this data if the modem is not + parked, after training failure. */ + z = dds_complexf(&(s->rx_carrier_phase), s->rx_carrier_phase_rate); + if (s->rx_training == V22BIS_TRAINING_STAGE_SYMBOL_ACQUISITION) + { + /* Only AGC during the initial symbol acquisition, and then lock the gain. */ + s->agc_scaling = 0.018f*3.60f/sqrtf(power); + } + /* Put things into the equalization buffer at T/2 rate. The Gardner algorithm + will fiddle the step to align this with the symbols. */ + if ((s->eq_put_step -= PULSESHAPER_COEFF_SETS) <= 0) + { + /* Pulse shape while still at the carrier frequency, using a quadrature + pair of filters. This results in a properly bandpass filtered complex + signal, which can be brought directly to bandband by complex mixing. + No further filtering, to remove mixer harmonics, is needed. */ + step = -s->eq_put_step; + if (step > PULSESHAPER_COEFF_SETS - 1) + step = PULSESHAPER_COEFF_SETS - 1; + s->eq_put_step += PULSESHAPER_COEFF_SETS*40/(3*2); + if (s->caller) + { + ii = pulseshaper_2400[step][0].re*s->rx_rrc_filter[s->rx_rrc_filter_step]; + qq = pulseshaper_2400[step][0].im*s->rx_rrc_filter[s->rx_rrc_filter_step]; + for (j = 1; j < V22BIS_RX_FILTER_STEPS; j++) + { + ii += pulseshaper_2400[step][j].re*s->rx_rrc_filter[j + s->rx_rrc_filter_step]; + qq += pulseshaper_2400[step][j].im*s->rx_rrc_filter[j + s->rx_rrc_filter_step]; + } + } + else + { + ii = pulseshaper_1200[step][0].re*s->rx_rrc_filter[s->rx_rrc_filter_step]; + qq = pulseshaper_1200[step][0].im*s->rx_rrc_filter[s->rx_rrc_filter_step]; + for (j = 1; j < V22BIS_RX_FILTER_STEPS; j++) + { + ii += pulseshaper_1200[step][j].re*s->rx_rrc_filter[j + s->rx_rrc_filter_step]; + qq += pulseshaper_1200[step][j].im*s->rx_rrc_filter[j + s->rx_rrc_filter_step]; + } + } + sample.re = ii*s->agc_scaling; + sample.im = qq*s->agc_scaling; + /* Shift to baseband - since this is done in a full complex form, the + result is clean, and requires no further filtering apart from the + equalizer. */ + zz.re = sample.re*z.re - sample.im*z.im; + zz.im = -sample.re*z.im - sample.im*z.re; + process_half_baud(s, &zz); + } + } + } + return 0; +} +/*- End of function --------------------------------------------------------*/ + +int v22bis_rx_restart(v22bis_state_t *s, int bit_rate) +{ + /* If bit_rate is 2400, the real bit rate is negotiated. If bit_rate + is 1200, the real bit rate is forced to 1200. */ + s->bit_rate = bit_rate; + vec_zerof(s->rx_rrc_filter, sizeof(s->rx_rrc_filter)/sizeof(s->rx_rrc_filter[0])); + s->rx_rrc_filter_step = 0; + s->rx_scramble_reg = 0; + s->rx_scrambler_pattern_count = 0; + s->rx_training = V22BIS_TRAINING_STAGE_SYMBOL_ACQUISITION; + s->rx_training_count = 0; + s->carrier_present = FALSE; + + s->rx_carrier_phase_rate = dds_phase_ratef((s->caller) ? 2400.0f : 1200.0f); + s->rx_carrier_phase = 0; + power_meter_init(&(s->rx_power), 5); + s->carrier_on_power = power_meter_level_dbm0(-43); + s->carrier_off_power = power_meter_level_dbm0(-48); + s->agc_scaling = 0.0005f*0.025f; + + s->rx_constellation_state = 0; + s->sixteen_way_decisions = FALSE; + + equalizer_reset(s); + + s->detected_unscrambled_ones = 0; + s->detected_unscrambled_zeros = 0; + s->gardner_integrate = 0; + s->gardner_step = 256; + s->rx_baud_phase = 0; + s->carrier_track_i = 8000.0f; + s->carrier_track_p = 8000000.0f; + return 0; +} +/*- End of function --------------------------------------------------------*/ + +void v22bis_rx_set_qam_report_handler(v22bis_state_t *s, qam_report_handler_t *handler, void *user_data) +{ + s->qam_report = handler; + s->qam_user_data = user_data; +} +/*- End of function --------------------------------------------------------*/ +/*- End of file ------------------------------------------------------------*/