SDRSharper/SDRSharper.Radio/SDRSharp.Radio/SyndromeDetector.cs
SDRSharpR c07e6e6034 SDRSharper (SDRSharp Remake) Full Source (VS2017)
SDRSharper (SDRSharp Remake) Full Source (VS2017)
2018-03-26 14:02:05 -07:00

161 lines
3.3 KiB
C#

namespace SDRSharp.Radio
{
public class SyndromeDetector
{
protected enum BlockSequence
{
GotA,
GotB,
GotC,
GotD,
WaitBitSync,
GotBitSync
}
private const int MaxCorrectableBits = 5;
private const int CheckwordBitsCount = 10;
private readonly RdsDumpGroups _dumpGroups;
private readonly bool _useFec = Utils.GetBooleanSetting("RdsUseFec");
private readonly ushort[] _blocks = new ushort[4];
private BlockSequence _sequence = BlockSequence.WaitBitSync;
private ushort _syndrome;
private uint _raw;
private int _count;
public SyndromeDetector(RdsDumpGroups dumpGroups)
{
this._dumpGroups = dumpGroups;
}
public void Clock(bool b)
{
this._raw <<= 1;
this._raw |= (uint)(b ? 1 : 0);
this._count++;
if (this._sequence == BlockSequence.WaitBitSync)
{
this._syndrome = SyndromeDetector.BuildSyndrome(this._raw);
this._syndrome ^= 984;
this._sequence = ((this._syndrome != 0) ? BlockSequence.WaitBitSync : BlockSequence.GotA);
this._blocks[0] = (ushort)(this._raw >> 10 & 0xFFFF);
this._count = 0;
}
if (this._count == 26)
{
this.ProcessSyndrome();
if (this._sequence == BlockSequence.GotD)
{
this._dumpGroups.AnalyseFrames(this._blocks[0], this._blocks[1], this._blocks[2], this._blocks[3]);
this._sequence = BlockSequence.GotBitSync;
}
this._count = 0;
}
}
private void ProcessSyndrome()
{
this._syndrome = SyndromeDetector.BuildSyndrome(this._raw);
switch (this._sequence)
{
case BlockSequence.GotBitSync:
this._syndrome ^= 984;
this._sequence = BlockSequence.GotA;
break;
case BlockSequence.GotA:
this._syndrome ^= 980;
this._sequence = BlockSequence.GotB;
break;
case BlockSequence.GotB:
this._syndrome ^= (ushort)(((this._blocks[1] & 0x800) == 0) ? 604 : 972);
this._sequence = BlockSequence.GotC;
break;
case BlockSequence.GotC:
this._syndrome ^= 600;
this._sequence = BlockSequence.GotD;
break;
}
int sequence = (int)this._sequence;
if (this._syndrome != 0)
{
if (this._useFec)
{
int num = this.ApplyFEC();
if (this._syndrome != 0 || num > 5)
{
this._sequence = BlockSequence.WaitBitSync;
}
else
{
this._blocks[sequence] = (ushort)(this._raw & 0xFFFF);
}
}
else
{
this._sequence = BlockSequence.WaitBitSync;
}
}
else
{
this._blocks[sequence] = (ushort)(this._raw >> 10 & 0xFFFF);
}
}
private int ApplyFEC()
{
uint num = 33554432u;
int num2 = 0;
for (int i = 0; i < 16; i++)
{
bool flag = (this._syndrome & 0x200) == 512;
bool flag2 = (this._syndrome & 0x20) == 0;
this._raw ^= ((flag && flag2) ? num : 0);
this._syndrome <<= 1;
this._syndrome ^= (ushort)((flag && !flag2) ? 1465 : 0);
num2 += ((flag && flag2) ? 1 : 0);
num >>= 1;
}
this._syndrome &= 1023;
return num2;
}
private static ushort BuildSyndrome(uint raw)
{
ushort[] array = new ushort[16]
{
732,
366,
183,
647,
927,
787,
853,
886,
443,
513,
988,
494,
247,
679,
911,
795
};
uint num = raw & 0x3FFFFFF;
ushort num2 = (ushort)(num >> 16);
for (int i = 0; i < 16; i++)
{
num2 = (ushort)(num2 ^ (((num & 0x8000) == 32768) ? array[i] : 0));
num <<= 1;
}
return num2;
}
}
}