mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 17:27:32 +00:00
feat(dmr): add diagnostic capture probes
This commit is contained in:
+45
-1
@@ -31,6 +31,7 @@ const
|
||||
|
||||
type
|
||||
TDMRAudioEvent = procedure(const PCM: array of Single; Count: Integer) of object;
|
||||
TDMRBurstEvent = procedure(const Dibits: array of Byte; Count: Integer) of object;
|
||||
|
||||
TDMRSyncKind = (
|
||||
dskNone,
|
||||
@@ -68,6 +69,11 @@ type
|
||||
SelectedSlot: Integer;
|
||||
VoiceFrameCount: QWord;
|
||||
VoiceErrorCount: QWord;
|
||||
BestSyncDistance: Integer;
|
||||
BestSyncPhase: Integer;
|
||||
BestCandidateKind: TDMRSyncKind;
|
||||
SymbolOuterLevel: Single;
|
||||
SignalMean: Single;
|
||||
end;
|
||||
|
||||
TDMRDecoder = class;
|
||||
@@ -121,8 +127,12 @@ type
|
||||
FLastSelectedVoiceTick: QWord;
|
||||
FVoiceFrameCount, FVoiceErrorCount: QWord;
|
||||
FOnAudio: TDMRAudioEvent;
|
||||
FOnBurst: TDMRBurstEvent;
|
||||
FBurstCount: QWord;
|
||||
FRMSSq: Double;
|
||||
FSignalMean: Double;
|
||||
FBestSyncDistance, FBestSyncPhase: Integer;
|
||||
FBestCandidateKind: TDMRSyncKind;
|
||||
|
||||
FSyncKind: TDMRSyncKind;
|
||||
FInputInverted: Boolean;
|
||||
@@ -152,6 +162,7 @@ type
|
||||
class function SyncKindName(Kind: TDMRSyncKind): string; static;
|
||||
property Enabled: Boolean read FEnabled;
|
||||
property OnAudio: TDMRAudioEvent read FOnAudio write FOnAudio;
|
||||
property OnBurst: TDMRBurstEvent read FOnBurst write FOnBurst;
|
||||
end;
|
||||
|
||||
implementation
|
||||
@@ -191,6 +202,17 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function PopCount24(V: LongWord): Integer;
|
||||
begin
|
||||
V := V and DMR_SYNC_MASK;
|
||||
Result := 0;
|
||||
while V <> 0 do
|
||||
begin
|
||||
V := V and (V - 1);
|
||||
Inc(Result);
|
||||
end;
|
||||
end;
|
||||
|
||||
constructor TDMRDecoderThread.Create(AOwner: TDMRDecoder);
|
||||
begin
|
||||
inherited Create(True);
|
||||
@@ -300,6 +322,10 @@ begin
|
||||
FWindowSum := 0;
|
||||
FSampleNo := 0;
|
||||
FRMSSq := 0;
|
||||
FSignalMean := 0;
|
||||
FBestSyncDistance := 25;
|
||||
FBestSyncPhase := -1;
|
||||
FBestCandidateKind := dskNone;
|
||||
FStatusLock.Enter;
|
||||
try
|
||||
FSyncKind := dskNone;
|
||||
@@ -379,6 +405,7 @@ var
|
||||
Sym: Double;
|
||||
begin
|
||||
FRMSSq := FRMSSq + 0.001 * (S * S - FRMSSq);
|
||||
FSignalMean := FSignalMean + 0.001 * (S - FSignalMean);
|
||||
FWindowSum := FWindowSum - FSampleWindow[FWindowPos] + S;
|
||||
FSampleWindow[FWindowPos] := S;
|
||||
FWindowPos := (FWindowPos + 1) mod DMR_SAMPLES_PER_SYM;
|
||||
@@ -395,7 +422,7 @@ end;
|
||||
|
||||
procedure TDMRDecoder.ProcessSymbol(Phase: Integer; Symbol: Double);
|
||||
var
|
||||
i: Integer;
|
||||
i, Distance: Integer;
|
||||
Pat: LongWord;
|
||||
Dibit: Byte;
|
||||
V: Double;
|
||||
@@ -430,6 +457,16 @@ begin
|
||||
for i := 0 to High(SYNC_TEXT) do
|
||||
begin
|
||||
Pat := SyncBits(SYNC_TEXT[i]);
|
||||
if FHistoryCount[Phase] >= 24 then
|
||||
begin
|
||||
Distance := PopCount24(FSyncShift[Phase] xor Pat);
|
||||
if Distance < FBestSyncDistance then
|
||||
begin
|
||||
FBestSyncDistance := Distance;
|
||||
FBestSyncPhase := Phase;
|
||||
FBestCandidateKind := SYNC_KIND[i];
|
||||
end;
|
||||
end;
|
||||
if FSyncShift[Phase] = Pat then
|
||||
begin
|
||||
NoteSync(Phase, SYNC_KIND[i], FInputInverted);
|
||||
@@ -478,6 +515,7 @@ procedure TDMRDecoder.CompleteBurst;
|
||||
begin
|
||||
Move(FCurrentBurst[0], FLastBurst[0], SizeOf(FLastBurst));
|
||||
DMRParseBurst(FLastBurst, FLastBurstInfo);
|
||||
if Assigned(FOnBurst) then FOnBurst(FLastBurst, Length(FLastBurst));
|
||||
if FLastBurstInfo.SlotType.Valid and
|
||||
(FSyncKind in [dskBSData, dskMSData, dskDirectTS1Data,
|
||||
dskDirectTS2Data]) then
|
||||
@@ -644,6 +682,12 @@ begin
|
||||
S.SelectedSlot := FSelectedSlot;
|
||||
S.VoiceFrameCount := FVoiceFrameCount;
|
||||
S.VoiceErrorCount := FVoiceErrorCount;
|
||||
S.BestSyncDistance := FBestSyncDistance;
|
||||
S.BestSyncPhase := FBestSyncPhase;
|
||||
S.BestCandidateKind := FBestCandidateKind;
|
||||
if FBestSyncPhase >= 0 then
|
||||
S.SymbolOuterLevel := FOuterLevel[FBestSyncPhase];
|
||||
S.SignalMean := FSignalMean;
|
||||
finally
|
||||
FStatusLock.Leave;
|
||||
end;
|
||||
|
||||
Reference in New Issue
Block a user