mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 20:37:33 +00:00
fix(dmr): choose timing phase by sync variance
This commit is contained in:
+46
-10
@@ -158,7 +158,7 @@ type
|
|||||||
procedure LoseSync;
|
procedure LoseSync;
|
||||||
function Digitize(Phase: Integer; Symbol: Double): Byte;
|
function Digitize(Phase: Integer; Symbol: Double): Byte;
|
||||||
function SliceSymbol(Symbol, OuterLevel: Double): Byte;
|
function SliceSymbol(Symbol, OuterLevel: Double): Byte;
|
||||||
function SyncEyeOpening(Phase: Integer): Double;
|
function SyncPhaseQuality(Phase: Integer): Double;
|
||||||
procedure CalibrateSyncLevels(Phase: Integer);
|
procedure CalibrateSyncLevels(Phase: Integer);
|
||||||
procedure StartBurstTracking(Phase: Integer);
|
procedure StartBurstTracking(Phase: Integer);
|
||||||
procedure CompleteBurst;
|
procedure CompleteBurst;
|
||||||
@@ -627,13 +627,49 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TDMRDecoder.SyncEyeOpening(Phase: Integer): Double;
|
function TDMRDecoder.SyncPhaseQuality(Phase: Integer): Double;
|
||||||
var
|
var
|
||||||
i: Integer;
|
i, P, PositiveCount, NegativeCount: Integer;
|
||||||
|
V, PositiveMean, NegativeMean, ErrorSum, Scale: Double;
|
||||||
begin
|
begin
|
||||||
Result := 1.0e300;
|
PositiveMean := 0;
|
||||||
|
NegativeMean := 0;
|
||||||
|
PositiveCount := 0;
|
||||||
|
NegativeCount := 0;
|
||||||
|
P := (FHistoryPos[Phase] + DMR_SYNC_END_DIBIT + 1 - 24) mod
|
||||||
|
(DMR_SYNC_END_DIBIT + 1);
|
||||||
for i := 0 to 23 do
|
for i := 0 to 23 do
|
||||||
Result := Min(Result, FMagHistory[Phase, i]);
|
begin
|
||||||
|
V := FSymbolHistory[Phase, P];
|
||||||
|
if V >= 0 then
|
||||||
|
begin
|
||||||
|
PositiveMean := PositiveMean + V;
|
||||||
|
Inc(PositiveCount);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
NegativeMean := NegativeMean - V;
|
||||||
|
Inc(NegativeCount);
|
||||||
|
end;
|
||||||
|
P := (P + 1) mod (DMR_SYNC_END_DIBIT + 1);
|
||||||
|
end;
|
||||||
|
if (PositiveCount = 0) or (NegativeCount = 0) then Exit(-1.0e300);
|
||||||
|
PositiveMean := PositiveMean / PositiveCount;
|
||||||
|
NegativeMean := NegativeMean / NegativeCount;
|
||||||
|
ErrorSum := 0;
|
||||||
|
P := (FHistoryPos[Phase] + DMR_SYNC_END_DIBIT + 1 - 24) mod
|
||||||
|
(DMR_SYNC_END_DIBIT + 1);
|
||||||
|
for i := 0 to 23 do
|
||||||
|
begin
|
||||||
|
V := FSymbolHistory[Phase, P];
|
||||||
|
if V >= 0 then ErrorSum := ErrorSum + Sqr(V - PositiveMean)
|
||||||
|
else ErrorSum := ErrorSum + Sqr((-V) - NegativeMean);
|
||||||
|
P := (P + 1) mod (DMR_SYNC_END_DIBIT + 1);
|
||||||
|
end;
|
||||||
|
Scale := Sqr(0.5 * (PositiveMean + NegativeMean));
|
||||||
|
if Scale <= 1.0e-18 then Exit(-1.0e300);
|
||||||
|
// Higher is better: zero denotes perfectly compact outer-level clusters.
|
||||||
|
Result := -ErrorSum / (24.0 * Scale);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TDMRDecoder.CalibrateSyncLevels(Phase: Integer);
|
procedure TDMRDecoder.CalibrateSyncLevels(Phase: Integer);
|
||||||
@@ -789,14 +825,14 @@ begin
|
|||||||
FStatusLock.Enter;
|
FStatusLock.Enter;
|
||||||
try
|
try
|
||||||
// Adjacent timing hypotheses recognize the same physical burst within one
|
// Adjacent timing hypotheses recognize the same physical burst within one
|
||||||
// sample period. Keep the phase with the largest 24-symbol eye opening,
|
// sample period. Keep the phase whose known positive/negative sync levels
|
||||||
// not merely the first phase that happened to match the sign pattern.
|
// form the tightest clusters, not merely the first sign-pattern match.
|
||||||
if (FLastSyncSample <> 0) and
|
if (FLastSyncSample <> 0) and
|
||||||
(FSampleNo - FLastSyncSample <= DMR_SAMPLES_PER_SYM * 2) then
|
(FSampleNo - FLastSyncSample <= DMR_SAMPLES_PER_SYM * 2) then
|
||||||
begin
|
begin
|
||||||
if SyncEyeOpening(Phase) > FBestSyncQuality then
|
if SyncPhaseQuality(Phase) > FBestSyncQuality then
|
||||||
begin
|
begin
|
||||||
FBestSyncQuality := SyncEyeOpening(Phase);
|
FBestSyncQuality := SyncPhaseQuality(Phase);
|
||||||
FSyncKind := Kind;
|
FSyncKind := Kind;
|
||||||
FInverted := Inverted;
|
FInverted := Inverted;
|
||||||
CalibrateSyncLevels(Phase);
|
CalibrateSyncLevels(Phase);
|
||||||
@@ -809,7 +845,7 @@ begin
|
|||||||
Inc(FSyncCount);
|
Inc(FSyncCount);
|
||||||
FLastSyncTick := NowTick;
|
FLastSyncTick := NowTick;
|
||||||
FLastSyncSample := FSampleNo;
|
FLastSyncSample := FSampleNo;
|
||||||
FBestSyncQuality := SyncEyeOpening(Phase);
|
FBestSyncQuality := SyncPhaseQuality(Phase);
|
||||||
CalibrateSyncLevels(Phase);
|
CalibrateSyncLevels(Phase);
|
||||||
if Kind in [dskMSData, dskMSVoice] then FMobileActiveBurst := True;
|
if Kind in [dskMSData, dskMSVoice] then FMobileActiveBurst := True;
|
||||||
StartBurstTracking(Phase);
|
StartBurstTracking(Phase);
|
||||||
|
|||||||
Reference in New Issue
Block a user