mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 18:43:51 +00:00
feat(dmr): decode full link control
This commit is contained in:
@@ -55,9 +55,28 @@ begin
|
||||
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;
|
||||
i: Integer;
|
||||
begin
|
||||
FillChar(Burst, SizeOf(Burst), 0);
|
||||
// TACT: AT=1, slot=1 (TS2), LCSS=2. Slot Type: CC=9, data header=6.
|
||||
@@ -90,5 +109,51 @@ begin
|
||||
DMRParseBurst(Burst, Info);
|
||||
Check(not Info.SlotType.Valid, 'uncorrectable Slot Type accepted');
|
||||
|
||||
WriteLn('DMR CACH and Slot Type tests passed');
|
||||
// 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');
|
||||
|
||||
WriteLn('DMR CACH, Slot Type, BPTC and Full LC tests passed');
|
||||
end.
|
||||
|
||||
Reference in New Issue
Block a user