From 5cfd585eea3678e00d02bfd75d161e9dd711b705 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Tue, 14 Jul 2026 20:46:07 +0300 Subject: [PATCH] chore(dmr): remove test and tool directories --- BUILD.MD | 6 -- tests/dmr_bindings_test.pas | 36 -------- tests/dmr_frontend_test.pas | 180 ------------------------------------ tests/dmr_protocol_test.pas | 176 ----------------------------------- 4 files changed, 398 deletions(-) delete mode 100644 tests/dmr_bindings_test.pas delete mode 100644 tests/dmr_frontend_test.pas delete mode 100644 tests/dmr_protocol_test.pas diff --git a/BUILD.MD b/BUILD.MD index ace3302..bedeca0 100644 --- a/BUILD.MD +++ b/BUILD.MD @@ -8,9 +8,3 @@ lazbuild -B --ws=cocoa ewsdr.lpr # Optional DMR AMBE+2 adapter (requires mbelib development files) cmake -S native/dmr -B build/dmr -DCMAKE_BUILD_TYPE=Release cmake --build build/dmr - -# DMR receive/protocol tests -fpc -Fu. -FE/tmp tests/dmr_protocol_test.pas -/tmp/dmr_protocol_test -fpc -Fu. -FE/tmp tests/dmr_frontend_test.pas -LD_LIBRARY_PATH=build/dmr /tmp/dmr_frontend_test diff --git a/tests/dmr_bindings_test.pas b/tests/dmr_bindings_test.pas deleted file mode 100644 index abd5941..0000000 --- a/tests/dmr_bindings_test.pas +++ /dev/null @@ -1,36 +0,0 @@ -program dmr_bindings_test; - -{$MODE Delphi} - -uses - SysUtils, DMRBindings; - -var - Decoder: Pointer; - Bits: array[0..DMR_AMBE_BITS - 1] of Byte; - PCM: array[0..DMR_PCM_SAMPLES - 1] of Single; - Info: TDMRMbeResult; -begin - if not DMRLoad then - begin - WriteLn(DMRLastError); - Halt(1); - end; - // Several simultaneous slice decoders share one dynamically loaded adapter. - if not DMRLoad then Halt(4); - DMRUnload; - if not DMRLoaded then Halt(5); - Decoder := DMRMbeCreate(3); - if Decoder = nil then Halt(2); - try - FillChar(Bits, SizeOf(Bits), 0); - Bits[0] := 2; // ABI must reject values other than 0/1 before mbelib. - if DMRMbeDecode(Decoder, @Bits[0], @PCM[0], @Info) <> -2 then Halt(3); - DMRMbeReset(Decoder); - finally - DMRMbeDestroy(Decoder); - DMRUnload; - end; - if DMRLoaded then Halt(6); - WriteLn('DMR native bindings tests passed'); -end. diff --git a/tests/dmr_frontend_test.pas b/tests/dmr_frontend_test.pas deleted file mode 100644 index a43f1e3..0000000 --- a/tests/dmr_frontend_test.pas +++ /dev/null @@ -1,180 +0,0 @@ -program dmr_frontend_test; - -{$MODE Delphi} - -uses - {$IFDEF UNIX}cthreads,{$ENDIF} - Classes, SysUtils, DMRDecoder; - -const - BS_VOICE_SYNC = '131111333113313313113313'; - DMR_TEST_SUPERFRAME_SAMPLES = DMR_INPUT_RATE * 360 div 1000; - -type - TAudioSink = class - public - CallCount: Integer; - SampleCount: Integer; - procedure AudioReady(const PCM: array of Single; Count: Integer); - end; - -procedure TAudioSink.AudioReady(const PCM: array of Single; Count: Integer); -begin - Inc(CallCount); - Inc(SampleCount, Count); -end; - -procedure FeedSync(D: TDMRDecoder; const Pattern: string; Invert: Boolean); -var - L, R: array of Single; - i, j, p: Integer; - V: Single; -begin - // Three leading samples ensure the detector really searches all ten timing - // hypotheses instead of relying on an aligned first sample. - SetLength(L, 3 + Length(Pattern) * DMR_SAMPLES_PER_SYM + 20); - SetLength(R, Length(L)); - p := 3; - for i := 1 to Length(Pattern) do - begin - if Pattern[i] = '1' then V := 0.7 else V := -0.7; - if Invert then V := -V; - for j := 0 to DMR_SAMPLES_PER_SYM - 1 do - begin - L[p] := V; - R[p] := V; - Inc(p); - end; - end; - D.FeedAudio(L, R, Length(L)); -end; - -procedure FeedConfirmedSync(D: TDMRDecoder; const Pattern: string; - Invert: Boolean); -var - L, R: array of Single; - GapSamples, RepeatIndex: Integer; -begin - GapSamples := DMR_TEST_SUPERFRAME_SAMPLES - - (3 + Length(Pattern) * DMR_SAMPLES_PER_SYM + 20); - SetLength(L, GapSamples); - SetLength(R, GapSamples); - for RepeatIndex := 1 to 3 do - begin - FeedSync(D, Pattern, Invert); - if RepeatIndex < 3 then D.FeedAudio(L, R, GapSamples); - end; -end; - -procedure TestBurst(D: TDMRDecoder); -const - DC_OFFSET = 0.12; -var - Want, Got: array[0..DMR_BURST_DIBITS - 1] of Byte; - L, R: array of Single; - i, j, p: Integer; - V: Single; - Seq: QWord; - Status: TDMRStatus; -begin - for i := 0 to High(Want) do Want[i] := Byte((i * 3 + 1) and 3); - for i := 1 to Length(BS_VOICE_SYNC) do - if BS_VOICE_SYNC[i] = '1' then Want[65 + i] := 1 - else Want[65 + i] := 3; - - SetLength(L, 3 + (DMR_BURST_DIBITS + 2) * DMR_SAMPLES_PER_SYM); - SetLength(R, Length(L)); - // One complete preceding symbol mirrors a continuous stream and fills the - // 90-dibit history even for the latest timing hypothesis. - V := 0.70 + DC_OFFSET; // Want[0] = 1 - p := 3 + DMR_SAMPLES_PER_SYM; - for j := 0 to p - 1 do begin L[j] := V; R[j] := V; end; - for i := 0 to High(Want) do - begin - case Want[i] of - 0: V := 0.23 + DC_OFFSET; - 1: V := 0.70 + DC_OFFSET; - 2: V := -0.23 + DC_OFFSET; - else - V := -0.70 + DC_OFFSET; - end; - for j := 0 to DMR_SAMPLES_PER_SYM - 1 do - begin - L[p] := V; R[p] := V; Inc(p); - end; - end; - // Hold the last level for one symbol so every one of the ten timing - // hypotheses has enough tail samples to close dibit 143. - for j := 0 to DMR_SAMPLES_PER_SYM - 1 do - begin - L[p] := V; R[p] := V; Inc(p); - end; - D.FeedAudio(L, R, Length(L)); - Sleep(80); - if not D.GetLastBurst(Got, Seq) then - begin - D.GetStatus(Status); - WriteLn('burst was not assembled; sync=', Status.SyncCount, - ' bursts=', Status.BurstCount, ' pos=', Status.BurstDibits); - Halt(3); - end; - for i := 0 to High(Want) do - if Got[i] <> Want[i] then - begin - WriteLn('burst dibit mismatch at ', i, ': ', Got[i], ' <> ', Want[i]); - Halt(4); - end; -end; - -var - D: TDMRDecoder; - S: TDMRStatus; - Sink: TAudioSink; -begin - Sink := TAudioSink.Create; - D := TDMRDecoder.Create; - try - D.OnAudio := Sink.AudioReady; - D.SetEnabled(True); - FeedConfirmedSync(D, BS_VOICE_SYNC, False); - Sleep(50); - D.GetStatus(S); - if (not S.Synced) or (S.SyncKind <> dskBSVoice) or S.Inverted then - begin - WriteLn('normal sync failed'); - Halt(1); - end; - - D.SetEnabled(False); - D.SetInverted(True); - D.SetEnabled(True); - FeedConfirmedSync(D, BS_VOICE_SYNC, True); - Sleep(50); - D.GetStatus(S); - if (not S.Synced) or (S.SyncKind <> dskBSVoice) or (not S.Inverted) then - begin - WriteLn('inverted sync failed'); - Halt(2); - end; - - D.SetEnabled(False); - D.SetInverted(False); - D.SetEnabled(True); - FeedConfirmedSync(D, BS_VOICE_SYNC, False); - Sleep(50); - TestBurst(D); - D.GetStatus(S); - if S.VocoderAvailable and - ((Sink.CallCount <> 3) or - (Sink.SampleCount <> 3 * DMR_VOICE_FRAME_SAMPLES)) then - begin - WriteLn('AMBE callback failed: calls=', Sink.CallCount, - ' samples=', Sink.SampleCount); - Halt(5); - end; - WriteLn('DMR front-end sync tests passed'); - finally - D.Free; - Sink.Free; - end; -end. diff --git a/tests/dmr_protocol_test.pas b/tests/dmr_protocol_test.pas deleted file mode 100644 index bb15daf..0000000 --- a/tests/dmr_protocol_test.pas +++ /dev/null @@ -1,176 +0,0 @@ -program dmr_protocol_test; - -{$MODE Delphi} - -uses - SysUtils, DMRProtocol; - -const - CACH_INTERLEAVE: array[0..23] of Byte = ( - 0, 7, 8, 9, 1, 10, - 11, 12, 2, 13, 14, 15, - 3, 16, 4, 17, 18, 19, - 5, 20, 21, 22, 6, 23 - ); - -procedure PutCACH(var Burst: TDMRDibitBurst; Value: Byte); -var - Code: TDMRBit7; - Deinterleaved, Transmitted: array[0..23] of Byte; - i: Integer; -begin - FillChar(Deinterleaved, SizeOf(Deinterleaved), 0); - Code := DMRHamming74Encode(Value); - for i := 0 to 6 do Deinterleaved[i] := Code[i]; - for i := 0 to 23 do Transmitted[i] := Deinterleaved[CACH_INTERLEAVE[i]]; - for i := 0 to 11 do - Burst[i] := (Transmitted[2 * i] shl 1) or Transmitted[2 * i + 1]; -end; - -procedure PutSlotType(var Burst: TDMRDibitBurst; Value: Byte); -var - Code: TDMRBit20; - i, k: Integer; -begin - Code := DMRGolay208Encode(Value); - k := 0; - for i := 61 to 65 do - begin - Burst[i] := (Code[k] shl 1) or Code[k + 1]; - Inc(k, 2); - end; - for i := 90 to 94 do - begin - Burst[i] := (Code[k] shl 1) or Code[k + 1]; - Inc(k, 2); - end; -end; - -procedure Check(Condition: Boolean; const Message_: string); -begin - if not Condition then - begin - WriteLn(Message_); - Halt(1); - end; -end; - -procedure PutUInt(var Bits: TDMRBit96; Start, Count: Integer; Value: LongWord); -var - i: Integer; -begin - for i := 0 to Count - 1 do - Bits[Start + i] := (Value shr (Count - 1 - i)) and 1; -end; - -procedure XorPayloadByte(var Bits: TDMRBit96; ByteIndex: Integer; Value: Byte); -var - i: Integer; -begin - for i := 0 to 7 do - Bits[ByteIndex * 8 + i] := Bits[ByteIndex * 8 + i] xor - ((Value shr (7 - i)) and 1); -end; - -var - Burst: TDMRDibitBurst; - Info: TDMRBurstInfo; - Payload: TDMRBit96; - Frames: TDMRAMBEFrames; - VoiceDibits: array[0..107] of Byte; - i: Integer; -begin - FillChar(Burst, SizeOf(Burst), 0); - // TACT: AT=1, slot=1 (TS2), LCSS=2. Slot Type: CC=9, data header=6. - PutCACH(Burst, $0E); - PutSlotType(Burst, $96); - DMRParseBurst(Burst, Info); - Check(Info.CACH.Valid, 'valid CACH rejected'); - Check(Info.CACH.AccessType and (Info.CACH.Slot = 1) and - (Info.CACH.LCSS = 2), 'TACT fields decoded incorrectly'); - Check(Info.SlotType.Valid, 'valid Slot Type rejected'); - Check((Info.SlotType.ColorCode = 9) and (Info.SlotType.DataType = 6), - 'Slot Type fields decoded incorrectly'); - - // Hamming(7,4) corrects one bit and Golay(20,8) corrects two. - Burst[0] := Burst[0] xor 2; - Burst[61] := Burst[61] xor 2; - Burst[92] := Burst[92] xor 1; - DMRParseBurst(Burst, Info); - Check(Info.CACH.Valid and (Info.CACH.CorrectedBits = 1), - 'CACH one-bit correction failed'); - Check(Info.CACH.AccessType and (Info.CACH.Slot = 1) and - (Info.CACH.LCSS = 2), 'corrected TACT fields are wrong'); - Check(Info.SlotType.Valid and (Info.SlotType.CorrectedBits = 2), - 'Slot Type two-bit correction failed'); - Check((Info.SlotType.ColorCode = 9) and (Info.SlotType.DataType = 6), - 'corrected Slot Type fields are wrong'); - - // A third Slot Type error exceeds the guaranteed correction radius. - Burst[94] := Burst[94] xor 1; - DMRParseBurst(Burst, Info); - Check(not Info.SlotType.Valid, 'uncorrectable Slot Type accepted'); - - // Full Link Control is carried in a BPTC(196,96) voice LC header. - FillChar(Payload, SizeOf(Payload), 0); - PutUInt(Payload, 2, 6, 0); // group voice channel user LC - PutUInt(Payload, 8, 8, 0); // standard feature set - PutUInt(Payload, 16, 8, $21); // service options - PutUInt(Payload, 24, 24, 12345); // target/talkgroup - PutUInt(Payload, 48, 24, 678901);// source radio - DMRFullLCSetParity(Payload, 1); - DMRBPTC19696Encode(Payload, Burst); - PutCACH(Burst, $04); // TS2, LCSS=0 - PutSlotType(Burst, $91); // CC9, voice LC header - DMRParseBurst(Burst, Info); - Check(Info.BPTCValid, 'valid BPTC(196,96) rejected'); - for i := 0 to High(Payload) do - Check(Info.Payload96[i] = Payload[i], 'BPTC payload mismatch at bit ' + - IntToStr(i)); - Check(Info.LinkControl.Decoded and (Info.LinkControl.Opcode = 0) and - (Info.LinkControl.FeatureSetID = 0) and - (Info.LinkControl.ServiceOptions = $21) and - (Info.LinkControl.TargetID = 12345) and - (Info.LinkControl.SourceID = 678901), 'Full LC fields decoded incorrectly'); - - // Product-code row/column correction recovers an isolated air-interface bit. - Burst[20] := Burst[20] xor 2; - DMRParseBurst(Burst, Info); - Check(Info.BPTCValid and Info.LinkControl.Decoded and - (Info.LinkControl.TargetID = 12345) and - (Info.LinkControl.SourceID = 678901), 'BPTC one-bit correction failed'); - - // The outer RS(12,9) code repairs one damaged byte after clean BPTC decode. - XorPayloadByte(Payload, 2, $5A); - DMRBPTC19696Encode(Payload, Burst); - PutCACH(Burst, $04); - PutSlotType(Burst, $91); - DMRParseBurst(Burst, Info); - Check(Info.LinkControl.Decoded and - (Info.LinkControl.RSCorrectedBytes = 1) and - (Info.LinkControl.ServiceOptions = $21), 'Full LC RS correction failed'); - - // Two damaged RS symbols exceed the RS(12,9) correction radius. - XorPayloadByte(Payload, 3, $A5); - DMRBPTC19696Encode(Payload, Burst); - PutSlotType(Burst, $91); - DMRParseBurst(Burst, Info); - Check(not Info.LinkControl.Decoded, 'invalid Full LC RS checksum accepted'); - - // Three AMBE frames occupy 36 + 18/18 + 36 dibits around the centre sync. - FillChar(Burst, SizeOf(Burst), 0); - for i := 12 to 65 do Burst[i] := (i * 3 + 1) and 3; - for i := 90 to 143 do Burst[i] := (i * 3 + 2) and 3; - for i := 0 to 53 do VoiceDibits[i] := Burst[12 + i]; - for i := 0 to 53 do VoiceDibits[54 + i] := Burst[90 + i]; - DMRExtractAMBEFrames(Burst, Frames); - for i := 12 to 65 do Burst[i] := 0; - for i := 90 to 143 do Burst[i] := 0; - DMRInsertAMBEFrames(Frames, Burst); - for i := 0 to 53 do Check(Burst[12 + i] = VoiceDibits[i], - 'AMBE frame 1/2 interleave mismatch'); - for i := 0 to 53 do Check(Burst[90 + i] = VoiceDibits[54 + i], - 'AMBE frame 2/3 interleave mismatch'); - - WriteLn('DMR protocol, FEC, Full LC and AMBE extraction tests passed'); -end.