Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#1618 DMR Decoder Message Enhancements #1622

Merged
merged 1 commit into from
Aug 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

125 changes: 125 additions & 0 deletions src/main/java/io/github/dsheirer/edac/BPTC_16_2.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2023 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/

package io.github.dsheirer.edac;

import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.bits.CorrectedBinaryMessage;

/**
* Block Product Turbo Code 16/2 for decoding a DMR Voice Frame F payload from the 32-bit EMB field.
* <p>
* See ETSI TS 102 361-1 B.2.2.1 and B.2.2.2
*/
public class BPTC_16_2
{
private static final int[] DEINTERLEAVE = new int[]{0, 24, 1, 25, 2, 26, 3, 27, 4, 28, 5, 29, 6, 30, 7, 31, 8, 16,
9, 17, 10, 18, 11, 19, 12, 20, 13, 21, 14, 22, 15, 23};

/**
* Unscramble and perform FEC checks per paragraph B.2.2.1 for Non-Reverse Channel Single Burst
*
* @param message with 32 interleaved bits.
* @return descrambled and error checked message or null if the process fails or there are too many errors.
*/
public static CorrectedBinaryMessage decodeShortBurst(CorrectedBinaryMessage message)
{
CorrectedBinaryMessage deinterleaved = deinterleave(message);
int fec = Hamming16.checkAndCorrect(deinterleaved, 0);

if(fec == 2) //0 or 1 is good, 2 = uncorrectable errors
{
return null;
}

//Check for even parity. Bits 0-15 should be the same as bits 16-31.
for(int x = 0; x < 16; x++)
{
if(deinterleaved.get(x) ^ deinterleaved.get(x + 16))
{
return null;
}
}

return deinterleaved;
}

/**
* Unscramble and perform FEC checks per paragraph B.2.2.2 for Reverse Channel Single Burst
*
* @param binaryMessage with 32 interleaved bits.
* @return descrambled and error checked message or null if the process fails or there are too many errors.
*/
public static CorrectedBinaryMessage decodeReverseChannel(CorrectedBinaryMessage message)
{
CorrectedBinaryMessage deinterleaved = deinterleave(message);
System.out.println(" DEINTER: " + deinterleaved.toHexString());
int fec = Hamming16.checkAndCorrect(deinterleaved, 0);
System.out.println(" DECODED: " + deinterleaved.toHexString());
System.out.println("FEC:" + fec);
if(fec == 2) //0 or 1 is good, 2 = uncorrectable errors
{
return null;
}

//Check for odd parity. Bits 0-15 should be opposite of bits 16-31.
for(int x = 0; x < 16; x++)
{
if(deinterleaved.get(x) == deinterleaved.get(x + 16))
{
return null;
}
}

return deinterleaved;
}

/**
* Performs deinterleave of the interleaved message.
*
* @param original to deinterleave
* @return deinterleaved message
*/
public static CorrectedBinaryMessage deinterleave(CorrectedBinaryMessage original)
{
CorrectedBinaryMessage delinterleaved = new CorrectedBinaryMessage(32);
for(int x = 0; x < 32; x++)
{
if(original.get(x))
{
delinterleaved.set(DEINTERLEAVE[x]);
}
}

return delinterleaved;
}

public static void main(String[] args)
{
String[] msgs = new String[]{"05030A03", "35003A00", "1C6D2C9E"};

for(String msg : msgs)
{
CorrectedBinaryMessage original = new CorrectedBinaryMessage(BinaryMessage.loadHex(msg));
System.out.println("ORIGINAL: " + original.toHexString());
CorrectedBinaryMessage decoded = decodeReverseChannel(original);
System.out.println("-------------------------");
}
}
}
28 changes: 15 additions & 13 deletions src/main/java/io/github/dsheirer/edac/CRCUtil.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2022 Dennis Sheirer
* Copyright (C) 2014-2023 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -226,17 +226,19 @@ public static void main(String[] args)
{
mLog.debug("Starting");

//DMR message
// String raw = "100110010001000000001001000000001111011011010000011001010000000000000000000000001100001000001011";
String raw = "101010000000000000110110100000101101011011010000011001111100000000000011100101001001111010001110";
mLog.debug(raw);
raw = "101010000000000000110110100000101101011011010000011001111100000000000011100101000000000000000000";
BinaryMessage message = BinaryMessage.load(raw);
mLog.debug(message.toString());

long polynomial = 0x11021l;
decode(message, 0, 80, polynomial, 16);
mLog.debug(message.toString());
mLog.debug("Finished");
long poly = 0x13l;
long[] checksums = generate(32, 4, poly, 0, true);

StringBuilder sb = new StringBuilder();
sb.append("private static int[] CHECKSUMS = new int[]{");
for(long checksum: checksums)
{
sb.append("0x").append(Long.toHexString(checksum).toUpperCase());
sb.append(",");
}

sb.append("};");

System.out.println("Checksums:\n" + sb);
}
}
53 changes: 32 additions & 21 deletions src/main/java/io/github/dsheirer/edac/Golay24.java
Original file line number Diff line number Diff line change
@@ -1,31 +1,29 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2023 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* ****************************************************************************
*/

package io.github.dsheirer.edac;

import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* -----------------------------------------------------------------------
* Galois24 decoder based on Hank Wallace's tutorial/algorithm located at:
* http://www.aqdi.com/golay.htm
******************************************************************************/

/**
* Galois 24/12/7 decoder
*/
Expand Down Expand Up @@ -160,4 +158,17 @@ private static int getSyndrome(BinaryMessage message, int startIndex)

return (checksum ^ calculated);
}

public static void main(String[] args)
{
// CorrectedBinaryMessage bm = new CorrectedBinaryMessage(BinaryMessage.loadHex("F3BB20"));
// CorrectedBinaryMessage bm = new CorrectedBinaryMessage(BinaryMessage.loadHex("F0C5C0"));
CorrectedBinaryMessage bm = new CorrectedBinaryMessage(BinaryMessage.loadHex("AFAC00"));

System.out.println("M:" + bm.toHexString());
int a = Golay24.checkAndCorrect(bm, 0);
System.out.println("M:" + bm.toHexString());

System.out.println("A:" + a);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,12 @@ private TextField getFindText()
if(mFindText == null)
{
mFindText = new TextField();
mFindText.setOnKeyPressed(event -> {
if(event.getCode().equals(KeyCode.ENTER))
{
getFindButton().fire();
}
});
mFindText.textProperty().addListener((observable, oldValue, newValue) -> updateFilters());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@
import io.github.dsheirer.module.decode.dmr.message.data.lc.full.hytera.HyteraGroupVoiceChannelUser;
import io.github.dsheirer.module.decode.dmr.message.data.lc.full.hytera.HyteraUnitToUnitVoiceChannelUser;
import io.github.dsheirer.module.decode.dmr.message.data.lc.full.motorola.CapacityPlusEncryptedVoiceChannelUser;
import io.github.dsheirer.module.decode.dmr.message.data.lc.full.motorola.CapacityPlusGroupVoiceChannelUser;
import io.github.dsheirer.module.decode.dmr.message.data.lc.full.motorola.CapacityPlusWideAreaVoiceChannelUser;
import io.github.dsheirer.module.decode.dmr.message.data.lc.full.motorola.MotorolaGroupVoiceChannelUser;
import io.github.dsheirer.module.decode.dmr.message.data.lc.shorty.CapacityPlusRestChannel;
import io.github.dsheirer.module.decode.dmr.message.data.packet.DMRPacketMessage;
import io.github.dsheirer.module.decode.dmr.message.data.packet.UDTShortMessageService;
Expand Down Expand Up @@ -646,12 +646,12 @@ private void processCSBK(CSBKMessage csbk)
}
else
{
DecodeEvent event = mDetectedCallEventsMap.get(channel.getLogicalSlotNumber());
DecodeEvent event = mDetectedCallEventsMap.get(channel.getValue());

if(isStale(event, csbk.getTimestamp(), csbk.getIdentifiers()))
{
event = getDecodeEvent(csbk, DecodeEventType.DATA_CALL, channel, mergedIdentifiers);
mDetectedCallEventsMap.put(channel.getLogicalSlotNumber(), event);
mDetectedCallEventsMap.put(channel.getValue(), event);
}
else
{
Expand Down Expand Up @@ -679,12 +679,12 @@ private void processCSBK(CSBKMessage csbk)
}
else
{
DecodeEvent event = mDetectedCallEventsMap.get(channel.getLogicalSlotNumber());
DecodeEvent event = mDetectedCallEventsMap.get(channel.getValue());

if(isStale(event, csbk.getTimestamp(), csbk.getIdentifiers()))
{
event = getDecodeEvent(csbk, DecodeEventType.CALL_GROUP, channel, mergedIdentifiers);
mDetectedCallEventsMap.put(channel.getLogicalSlotNumber(), event);
mDetectedCallEventsMap.put(channel.getValue(), event);
}
else
{
Expand All @@ -711,12 +711,12 @@ private void processCSBK(CSBKMessage csbk)
}
else
{
DecodeEvent event = mDetectedCallEventsMap.get(channel.getLogicalSlotNumber());
DecodeEvent event = mDetectedCallEventsMap.get(channel.getValue());

if(isStale(event, csbk.getTimestamp(), csbk.getIdentifiers()))
{
event = getDecodeEvent(csbk, DecodeEventType.CALL_UNIT_TO_UNIT, channel, mergedIdentifiers);
mDetectedCallEventsMap.put(channel.getLogicalSlotNumber(), event);
mDetectedCallEventsMap.put(channel.getValue(), event);
}
else
{
Expand Down Expand Up @@ -756,12 +756,12 @@ private void processCSBK(CSBKMessage csbk)
}
else
{
DecodeEvent event = mDetectedCallEventsMap.get(channel.getLogicalSlotNumber());
DecodeEvent event = mDetectedCallEventsMap.get(channel.getValue());

if(isStale(event, csbk.getTimestamp(), csbk.getIdentifiers()))
{
event = getDecodeEvent(csbk, DecodeEventType.DATA_CALL, channel, mergedIdentifiers);
mDetectedCallEventsMap.put(channel.getLogicalSlotNumber(), event);
mDetectedCallEventsMap.put(channel.getValue(), event);
}
else
{
Expand Down Expand Up @@ -807,12 +807,12 @@ private void processCSBK(CSBKMessage csbk)
}
else
{
DecodeEvent detectedEvent = mDetectedCallEventsMap.get(channel.getLogicalSlotNumber());
DecodeEvent detectedEvent = mDetectedCallEventsMap.get(channel.getValue());

if(isStale(detectedEvent, csbk.getTimestamp(), csbk.getIdentifiers()))
{
detectedEvent = getDecodeEvent(csbk, DecodeEventType.CALL_GROUP, channel, mergedIdentifiers);
mDetectedCallEventsMap.put(channel.getLogicalSlotNumber(), detectedEvent);
mDetectedCallEventsMap.put(channel.getValue(), detectedEvent);
}
else
{
Expand Down Expand Up @@ -979,10 +979,8 @@ private void processLinkControl(LCMessage message, boolean isTerminator)
}
break;
case FULL_CAPACITY_PLUS_GROUP_VOICE_CHANNEL_USER:
if(message instanceof CapacityPlusGroupVoiceChannelUser cpgvcu)
if(message instanceof MotorolaGroupVoiceChannelUser cpgvcu)
{
updateRestChannel(cpgvcu.getRestChannel());

if(isTerminator)
{
getIdentifierCollection().remove(Role.FROM);
Expand Down
Loading
Loading