@@ -950,8 +950,8 @@ static void GenerateQPSK()
950950 // preambleCounter = 1;
951951
952952 bitI = lastBit == symbols [ 0 ] ? symbols [ symbols . Length - 1 ] : symbols [ 0 ] ;
953- // bitQ = 1f;
954- bitQ = bitI ;
953+ bitQ = 1f ;
954+ // bitQ = bitI;
955955
956956 lastBit = bitI ;
957957
@@ -1562,7 +1562,7 @@ static void Const()
15621562 //dc.DrawRectangle(dotBrush, null, new System.Windows.Rect(x, y, 5, 5));
15631563 if ( i < 500 * channels )
15641564 dc . DrawEllipse ( dotBrushSync , null , new System . Windows . Point ( x , y ) , 2 , 2 ) ;
1565- else if ( i > samples . Length / 2 )
1565+ else if ( i > ( samples . Length - ( 500 * channels ) ) / 2 )
15661566 dc . DrawEllipse ( dotBrush2 , null , new System . Windows . Point ( x , y ) , 2 , 2 ) ;
15671567 else
15681568 dc . DrawEllipse ( dotBrush , null , new System . Windows . Point ( x , y ) , 2 , 2 ) ;
@@ -1611,7 +1611,7 @@ static void AWGN()
16111611 // 18.0 dB @ 16000Hz
16121612 // 21.0 dB @ 8000Hz
16131613 int sampleRate = 8000 ;
1614- double snrDbBase = 38 .0f;
1614+ double snrDbBase = 24 .0f;
16151615 double snrDb = 10.0 * Math . Log10 ( ( 1.0 / sampleRate ) * ( Math . Pow ( 10 , snrDbBase / 10.0 ) ) / ( 1.0 / 8000 ) ) ;
16161616 double snrLin = ( float ) Math . Pow ( 10 , ( snrDb / 10.0 ) ) ;
16171617
@@ -1807,6 +1807,7 @@ static void DecisionDirected()
18071807 Integrator intAngle = new Integrator ( 0.2f , ( 1f / baud ) * 5f ) ;
18081808 Integrator intMagnitude = new Integrator ( 0.1f , ( 1f / baud ) * 20f ) ;
18091809 intMagnitude . SetValue ( 1f ) ;
1810+
18101811 //BiQuadraticFilter bandpass = new BiQuadraticFilter(BiQuadraticFilter.Type.LOWPASS, 5000, sampleRate, 0.707);
18111812 AGC agc = new AGC ( 0.707f , 15f ) ;
18121813
@@ -1835,11 +1836,10 @@ static void DecisionDirected()
18351836 bool isSyncMode = true ;
18361837
18371838 double avgErr = 0f ;
1839+ double lastAvgErr = 0f ;
1840+ double errDeriv = 0f ;
18381841 long symbolCount = 0 ;
1839- float angleDiv = 1f ;
18401842 float phaseAngleDiff = 0f ;
1841- float lastAngleDiff = 0f ;
1842- float lastLastAngleDiff = 0f ;
18431843
18441844 using ( Stream fs = File . Create ( Path . Combine ( Environment . GetFolderPath ( Environment . SpecialFolder . Desktop ) , "SignalTest" , "SignalTest_1.pcm32f" ) ) )
18451845 {
@@ -1938,7 +1938,7 @@ static void DecisionDirected()
19381938
19391939 if ( flipFlop ^= true )
19401940 {
1941-
1941+
19421942
19431943 //bitOutI = Math.Max(Math.Min(bitOutI, 1.2f), -1.2f);
19441944 //bitOutQ = Math.Max(Math.Min(bitOutQ, 1.2f), -1.2f);
@@ -1951,7 +1951,7 @@ static void DecisionDirected()
19511951 fs . Write ( BitConverter . GetBytes ( ( float ) avgErr ) , 0 , 4 ) ;
19521952 //fs.Write(BitConverter.GetBytes(agc.AverageAmplitude), 0, 4);
19531953 //fs.Write(BitConverter.GetBytes(isSyncMode ? 0f : 0.707f), 0, 4);
1954- fs . Write ( BitConverter . GetBytes ( phaseAngleDiff ) , 0 , 4 ) ;
1954+ fs . Write ( BitConverter . GetBytes ( ( float ) errDeriv ) , 0 , 4 ) ;
19551955
19561956
19571957 // Find the closest constellation point
@@ -1975,14 +1975,20 @@ static void DecisionDirected()
19751975 double magDiff = ( constMag - curMag ) * 1f ;
19761976 //magDiff -= (magDiff < 0 ? -1f : 1f) * ((magDiff * magDiff) / 1f);
19771977
1978+ // Calculate phase angle difference
1979+ double tempX , tempY ;
1980+ ComplexMultiply ( bitOutI , bitOutQ , constPt . I , - constPt . Q , out tempX , out tempY ) ;
1981+
1982+ double phaseAngle = Math . Atan2 ( tempY , tempX ) ;
1983+
19781984
19791985 constGain = intMagnitude . Process ( ( float ) ( magDiff ) ) ;
19801986 //constGain = 1.29f;
19811987 if ( constGain < 0.01f )
19821988 constGain = 0.01f ;
19831989 if ( constGain > 2.0f )
19841990 constGain = 2.0f ;
1985-
1991+
19861992
19871993 curMag = Math . Sqrt ( ( bitOutI * bitOutI ) + ( bitOutQ * bitOutQ ) ) ;
19881994 Console . WriteLine ( "M {0,5:F2} {1,5:F2} {2,5:F2}" , curMag , constMag , constGain ) ;
@@ -1994,100 +2000,35 @@ static void DecisionDirected()
19942000 //distance /= 0.09123958466923193863236701446514;
19952001
19962002 avgErr = ( avgErr * 0.95 ) + ( distance * 0.05 ) ;
1997- Console . WriteLine ( "E {0,7:F4} {1,7:F4}" , distance , avgErr ) ;
1998-
1999- if ( Math . Sign ( curAngle ) == Math . Sign ( constAngle ) ) // && (!isSyncMode || (bitOutI > 0.5f || bitOutQ > 0.5f)))
2000- {
2001- double angleDiff = ( curAngle - constAngle ) * 1f ; // / 3.1419526535897932384;
2002-
2003- double angleDiffDiff = angleDiff - lastAngleDiff ;
2004- //double lastAngleDiffDiff = lastAngleDiff - lastLastAngleDiff;
2005-
2006- //if (angleDiffDiff > 1.2f)
2007- // angleDiffDiff -= 1.57079632f;
2008- //if (angleDiffDiff < 1.3f)
2009- // angleDiffDiff += 1.57079632f;
2010-
2011- //angleDiffDiff = Math.Min(Math.Max(angleDiffDiff, -1.2), 1.2);
2012-
2013- double diffRatio = Math . Abs ( angleDiffDiff ) / Math . Abs ( lastLastAngleDiff ) ;
2014-
2015- // Correct for phase angle polarity swaps
2016- if ( Math . Abs ( angleDiffDiff ) > 0.6f && Math . Sign ( angleDiffDiff ) != Math . Sign ( lastLastAngleDiff ) )
2017- angleDiffDiff += 1.57079632f * Math . Sign ( lastAngleDiff ) ;
2018-
2019-
2020-
2021- //if ((angleDiffDiff - lastAngleDiffDiff) > 1.3f)
2022- // angleDiffDiff -= 1.57079632f;
2023-
2024- //phaseAngleDiff = (float)angleDiff / 3.1415926535897932384f;
2025-
2026- //if (Math.Abs(angleDiffDiff) > 0.6)
2027- {
2028- angleDiffDiff -= Math . Sign ( angleDiffDiff ) * ( ( angleDiffDiff * angleDiffDiff ) * 0.5f ) ;
2029-
2030- }
2031- phaseAngleDiff = ( float ) angleDiffDiff ;
2003+ errDeriv = ( errDeriv * 0.90 ) + ( ( avgErr - lastAvgErr ) * 0.10 ) ;
2004+ lastAvgErr = avgErr ;
2005+ Console . WriteLine ( "E {0,7:F4} {1,7:F4} {2,7:F4}" , distance , avgErr , errDeriv ) ;
20322006
2007+ phaseAngleDiff = ( float ) phaseAngle ;
20332008
2034- //angleDiffDiff *= 1.5f;
2035- //angleDiffDiffCounter += (float)angleDiffDiff;
2036- //diffCount++;
2037- lastLastAngleDiff = ( float ) angleDiffDiff ;
2038- lastAngleDiff = ( float ) angleDiff ;
2039- //angleDiff -= (angleDiff < 0 ? -1f : 1f) * ((angleDiff * angleDiff) / 3f);
2040- //angleDiff = Math.Min(Math.Max(angleDiff, -0.25f), 0.25f);
2041- //if (i >= 2000)
2042- // angleDiff /= 2;
2043-
2044- // TODO: Add actual sync/preamble detector
2045- if ( isSyncMode && symbolCount >= 400 )
2046- //if (isSyncMode && symbolCount > 10 && avgErr < 0.2f)
2047- //if (isSyncMode && i >= 30000)
2048- {
2049- isSyncMode = false ;
2050- agc . AdaptGain = false ;
2051-
2052- // Once we have a good estimate of carrier offset, only allow small tweaks
2053- intAngle . IntegratorGain = ( 1f / baud ) * 0.5f ;
2054- intAngle . ProportionalGain = 0.1f ;
2055- //intRatio.IntegratorGain *= 0.5f;
2056- //intRatio.ProportionalGain *= 0.5f;
2057- //ratioScale *= 0.5f;
2058- }
2059- //if (sampleCount >= 500)
2060- // angleDiff /= 2f;
2061-
2062- //phaseAngleDiff = (float)angleDiff / 3.1415926535897932384f;
2063- //phaseAngleDiff = (float)angleDiffDiff;
2064-
2065- //angleDiff -= Math.Sign(angleDiff) * ((angleDiff * angleDiff) * 0.7f);
2066-
2067- // NOTE: It appears the divisor on angleDiff should be higher for lower baud rates?
2068- // Actually, it seems to not have a linear relation to baud rate
2069- float phaseError = ( float ) angleDiffDiff + ( float ) angleDiff * 1.0f ;
2070- //phaseError -= Math.Sign(phaseError) * ((phaseError * phaseError) * 0.7f);
2071-
2072- float angleFilter = intAngle . Process ( ( float ) phaseError ) ;
2073-
2074- //angleFilter += (float)(rTest.NextDouble() * 2 - 1) * 5f;
2075-
2076- Console . WriteLine ( "A {0,5:F2} {1,5:F2} {2,9:F6}" , angleDiff , angleFilter , angleDiffDiff ) ;
2077- Console . WriteLine ( "S {0,5} {1,9:N0}" , isSyncMode , symbolCount ) ;
2009+ // TODO: Add actual sync/preamble detector
2010+ if ( isSyncMode && symbolCount >= 400 )
2011+ //if (isSyncMode && symbolCount > 10 && avgErr < 0.2f)
2012+ //if (isSyncMode && i >= 30000)
2013+ {
2014+ isSyncMode = false ;
2015+ agc . AdaptGain = false ;
2016+
2017+ // Once we have a good estimate of carrier offset, only allow small tweaks
2018+ //intAngle.IntegratorGain = (1f / baud) * 0.5f;
2019+ intAngle . IntegratorGain *= 0.5f ;
2020+ //intAngle.ProportionalGain = 0.1f;
2021+ //intRatio.IntegratorGain *= 0.5f;
2022+ //intRatio.ProportionalGain *= 0.5f;
2023+ //ratioScale *= 0.5f;
2024+ }
20782025
2079- carrier . Tune ( angleFilter ) ;
2080- //carrier.SetCenterFrequency(angleFilter);
2026+ float angleFilter = intAngle . Process ( ( float ) phaseAngle ) ;
20812027
2082- //if (i % 10 == 0)
2083- //{
2084- // //Console.WriteLine(carrier.GetFrequency(0));
2085- //}
2086- }
2087- else
2088- {
2028+ Console . WriteLine ( "A {0,5:F2} {1,5:F2}" , phaseAngle , angleFilter ) ;
2029+ Console . WriteLine ( "S {0,5} {1,9:N0}" , isSyncMode , symbolCount ) ;
20892030
2090- }
2031+ carrier . Tune ( angleFilter ) ;
20912032 symbolCount ++ ;
20922033 }
20932034 }
@@ -2201,6 +2142,14 @@ static double Sinc(double x, double scale)
22012142 return Math . Sin ( phi * x ) / ( phi * x ) ;
22022143 }
22032144
2145+ static void ComplexMultiply ( double aR , double aI , double bR , double bI , out double resultR , out double resultI )
2146+ {
2147+ //resultR = (aR * bR) - (aI * bI);
2148+ //resultI = (aR + aI) * (bR + bI) - (aR * bR) - (aI * bI);
2149+ resultR = ( aR * bR ) - ( aI * bI ) ;
2150+ resultI = ( aR * bI ) + ( aI * bR ) ;
2151+ }
2152+
22042153
22052154 static double [ ] _rrcImpulse ;
22062155 static void GenerateImpulseRRC ( double sampleRate , double symbolLengthSec , int symbolSpan , double rolloff )
0 commit comments