mirror of
https://git.vladimir.cc/vladimir/ewsdr.git
synced 2026-08-25 19:45:09 +00:00
feat(dmr): decode CACH and slot type
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
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;
|
||||
|
||||
var
|
||||
Burst: TDMRDibitBurst;
|
||||
Info: TDMRBurstInfo;
|
||||
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');
|
||||
|
||||
WriteLn('DMR CACH and Slot Type tests passed');
|
||||
end.
|
||||
Reference in New Issue
Block a user