mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 19:45:09 +00:00
fix(dmr): calibrate slicer from sync symbols
This commit is contained in:
+45
-7
@@ -108,12 +108,15 @@ type
|
||||
FOuterLevel: array[0..DMR_SAMPLES_PER_SYM - 1] of Double;
|
||||
FDibitHistory: array[0..DMR_SAMPLES_PER_SYM - 1,
|
||||
0..DMR_SYNC_END_DIBIT] of Byte;
|
||||
FSymbolHistory: array[0..DMR_SAMPLES_PER_SYM - 1,
|
||||
0..DMR_SYNC_END_DIBIT] of Double;
|
||||
FHistoryPos: array[0..DMR_SAMPLES_PER_SYM - 1] of Integer;
|
||||
FHistoryCount: array[0..DMR_SAMPLES_PER_SYM - 1] of Integer;
|
||||
FMagHistory: array[0..DMR_SAMPLES_PER_SYM - 1, 0..23] of Double;
|
||||
FMagPos: array[0..DMR_SAMPLES_PER_SYM - 1] of Integer;
|
||||
FMagSum: array[0..DMR_SAMPLES_PER_SYM - 1] of Double;
|
||||
FBestSyncQuality: Double;
|
||||
FFixedOuterLevel: Double;
|
||||
FTrackPhase: Integer;
|
||||
FCurrentBurst: TDMRDibitBurst;
|
||||
FCurrentBurstPos: Integer;
|
||||
@@ -150,6 +153,8 @@ type
|
||||
procedure NoteSync(Phase: Integer; Kind: TDMRSyncKind; Inverted: Boolean);
|
||||
procedure LoseSync;
|
||||
function Digitize(Phase: Integer; Symbol: Double): Byte;
|
||||
function SliceSymbol(Symbol, OuterLevel: Double): Byte;
|
||||
function SyncEyeOpening(Phase: Integer): Double;
|
||||
procedure StartBurstTracking(Phase: Integer);
|
||||
procedure CompleteBurst;
|
||||
procedure DecodeVoiceBurst;
|
||||
@@ -302,12 +307,14 @@ begin
|
||||
FillChar(FSyncShift, SizeOf(FSyncShift), 0);
|
||||
FillChar(FOuterLevel, SizeOf(FOuterLevel), 0);
|
||||
FillChar(FDibitHistory, SizeOf(FDibitHistory), 0);
|
||||
FillChar(FSymbolHistory, SizeOf(FSymbolHistory), 0);
|
||||
FillChar(FHistoryPos, SizeOf(FHistoryPos), 0);
|
||||
FillChar(FHistoryCount, SizeOf(FHistoryCount), 0);
|
||||
FillChar(FMagHistory, SizeOf(FMagHistory), 0);
|
||||
FillChar(FMagPos, SizeOf(FMagPos), 0);
|
||||
FillChar(FMagSum, SizeOf(FMagSum), 0);
|
||||
FBestSyncQuality := 0;
|
||||
FFixedOuterLevel := 0;
|
||||
FillChar(FCurrentBurst, SizeOf(FCurrentBurst), 0);
|
||||
FillChar(FLastBurst, SizeOf(FLastBurst), 0);
|
||||
FillChar(FLastBurstInfo, SizeOf(FLastBurstInfo), 0);
|
||||
@@ -456,6 +463,7 @@ begin
|
||||
// Keep the 90 dibits ending at sync. Once the timing phase is selected this
|
||||
// supplies burst positions 0..89 without waiting for another frame.
|
||||
FDibitHistory[Phase, FHistoryPos[Phase]] := Dibit;
|
||||
FSymbolHistory[Phase, FHistoryPos[Phase]] := V;
|
||||
FHistoryPos[Phase] := (FHistoryPos[Phase] + 1) mod (DMR_SYNC_END_DIBIT + 1);
|
||||
if FHistoryCount[Phase] < DMR_SYNC_END_DIBIT + 1 then Inc(FHistoryCount[Phase]);
|
||||
|
||||
@@ -571,21 +579,33 @@ begin
|
||||
end;
|
||||
FTrackPhase := -1;
|
||||
FCurrentBurstPos := 0;
|
||||
FFixedOuterLevel := 0;
|
||||
FMobileActiveBurst := True;
|
||||
DMRMbeReset(FMbe);
|
||||
end;
|
||||
|
||||
function TDMRDecoder.Digitize(Phase: Integer; Symbol: Double): Byte;
|
||||
var
|
||||
A, Threshold: Double;
|
||||
A: Double;
|
||||
begin
|
||||
if (Phase = FTrackPhase) and (FFixedOuterLevel > 1.0e-9) then
|
||||
Exit(SliceSymbol(Symbol, FFixedOuterLevel));
|
||||
|
||||
A := Abs(Symbol);
|
||||
if FOuterLevel[Phase] <= 1.0e-9 then FOuterLevel[Phase] := A
|
||||
else if A > FOuterLevel[Phase] then
|
||||
FOuterLevel[Phase] := A
|
||||
else
|
||||
FOuterLevel[Phase] := FOuterLevel[Phase] + 0.001 * (A - FOuterLevel[Phase]);
|
||||
Threshold := 0.625 * FOuterLevel[Phase];
|
||||
Result := SliceSymbol(Symbol, FOuterLevel[Phase]);
|
||||
end;
|
||||
|
||||
function TDMRDecoder.SliceSymbol(Symbol, OuterLevel: Double): Byte;
|
||||
var
|
||||
A, Threshold: Double;
|
||||
begin
|
||||
A := Abs(Symbol);
|
||||
Threshold := (2.0 / 3.0) * OuterLevel;
|
||||
if Symbol >= 0 then
|
||||
begin
|
||||
if A >= Threshold then Result := 1 else Result := 0; // +3 / +1
|
||||
@@ -596,6 +616,15 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function TDMRDecoder.SyncEyeOpening(Phase: Integer): Double;
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
Result := 1.0e300;
|
||||
for i := 0 to 23 do
|
||||
Result := Min(Result, FMagHistory[Phase, i]);
|
||||
end;
|
||||
|
||||
procedure TDMRDecoder.StartBurstTracking(Phase: Integer);
|
||||
var
|
||||
i, P: Integer;
|
||||
@@ -605,7 +634,10 @@ begin
|
||||
P := FHistoryPos[Phase]; // oldest item; ring is exactly 90 dibits full
|
||||
for i := 0 to DMR_SYNC_END_DIBIT do
|
||||
begin
|
||||
FCurrentBurst[i] := FDibitHistory[Phase, P];
|
||||
// All 24 DMR sync dibits are known outer levels. Once they calibrate the
|
||||
// eye, re-slice the already buffered pre-sync payload with the same level.
|
||||
FCurrentBurst[i] := SliceSymbol(FSymbolHistory[Phase, P],
|
||||
FFixedOuterLevel);
|
||||
P := (P + 1) mod (DMR_SYNC_END_DIBIT + 1);
|
||||
end;
|
||||
FCurrentBurstPos := DMR_SYNC_END_DIBIT + 1;
|
||||
@@ -718,11 +750,13 @@ begin
|
||||
if (FLastSyncSample <> 0) and
|
||||
(FSampleNo - FLastSyncSample <= DMR_SAMPLES_PER_SYM * 2) then
|
||||
begin
|
||||
if FMagSum[Phase] > FBestSyncQuality then
|
||||
if SyncEyeOpening(Phase) > FBestSyncQuality then
|
||||
begin
|
||||
FBestSyncQuality := FMagSum[Phase];
|
||||
FBestSyncQuality := SyncEyeOpening(Phase);
|
||||
FSyncKind := Kind;
|
||||
FInverted := Inverted;
|
||||
FFixedOuterLevel := FMagSum[Phase] / 24.0;
|
||||
FOuterLevel[Phase] := FFixedOuterLevel;
|
||||
StartBurstTracking(Phase);
|
||||
end;
|
||||
Exit;
|
||||
@@ -732,7 +766,9 @@ begin
|
||||
Inc(FSyncCount);
|
||||
FLastSyncTick := NowTick;
|
||||
FLastSyncSample := FSampleNo;
|
||||
FBestSyncQuality := FMagSum[Phase];
|
||||
FBestSyncQuality := SyncEyeOpening(Phase);
|
||||
FFixedOuterLevel := FMagSum[Phase] / 24.0;
|
||||
FOuterLevel[Phase] := FFixedOuterLevel;
|
||||
if Kind in [dskMSData, dskMSVoice] then FMobileActiveBurst := True;
|
||||
StartBurstTracking(Phase);
|
||||
finally
|
||||
@@ -795,7 +831,9 @@ begin
|
||||
S.BestSyncDistance := FBestSyncDistance;
|
||||
S.BestSyncPhase := FBestSyncPhase;
|
||||
S.BestCandidateKind := FBestCandidateKind;
|
||||
if FBestSyncPhase >= 0 then
|
||||
if FFixedOuterLevel > 0 then
|
||||
S.SymbolOuterLevel := FFixedOuterLevel
|
||||
else if FBestSyncPhase >= 0 then
|
||||
S.SymbolOuterLevel := FOuterLevel[FBestSyncPhase];
|
||||
S.SignalMean := FSignalMean;
|
||||
finally
|
||||
|
||||
Reference in New Issue
Block a user