diff --git a/src/main/java/io/github/dsheirer/edac/BPTC_196_96.java b/src/main/java/io/github/dsheirer/edac/BPTC_196_96.java
index cd01f6775..0d5ac81b4 100644
--- a/src/main/java/io/github/dsheirer/edac/BPTC_196_96.java
+++ b/src/main/java/io/github/dsheirer/edac/BPTC_196_96.java
@@ -1,9 +1,27 @@
+/*
+ * *****************************************************************************
+ * 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
+ * ****************************************************************************
+ */
+
package io.github.dsheirer.edac;
import io.github.dsheirer.bits.BinaryMessage;
import io.github.dsheirer.bits.BitSetFullException;
import io.github.dsheirer.bits.CorrectedBinaryMessage;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@@ -14,7 +32,7 @@
public class BPTC_196_96
{
public static final int BPTC_LENGTH = 196;
- public static final int EXTRACTED_LENGTH = 96;
+ public static final int EXTRACTED_LENGTH = 96; //However, we set the 3x reserved bits in 96, 97, and 98 making the length 99
public static final int MAX_ORIGINAL_INDEX = 136;
public static final int COLUMN_COUNT = 15;
public static final int MESSAGE_COLUMN_COUNT = 12; //Should be 11, but adjusted for the first pad bit
@@ -99,6 +117,11 @@ public static CorrectedBinaryMessage extract(CorrectedBinaryMessage original)
}
}
+ //Transfer bits R2, R1, and R0 to the end - RAS bits
+ extracted.set(96, message.get(0));
+ extracted.set(97, message.get(1));
+ extracted.set(98, message.get(2));
+
return extracted;
}
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/DMRDecoderState.java b/src/main/java/io/github/dsheirer/module/decode/dmr/DMRDecoderState.java
index d24a223e1..5c34c1bd6 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/DMRDecoderState.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/DMRDecoderState.java
@@ -44,7 +44,7 @@
import io.github.dsheirer.module.decode.dmr.message.data.csbk.CSBKMessage;
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.CapacityMaxAloha;
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.CapacityPlusNeighbors;
-import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.CapacityPlusSystemStatus;
+import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.CapacityPlusSiteStatus;
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.ConnectPlusDataChannelGrant;
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.ConnectPlusVoiceChannelUser;
import io.github.dsheirer.module.decode.dmr.message.data.csbk.standard.Aloha;
@@ -674,9 +674,9 @@ private void processCSBK(CSBKMessage csbk)
}
break;
case MOTOROLA_CAPPLUS_SYSTEM_STATUS:
- if(csbk instanceof CapacityPlusSystemStatus)
+ if(csbk instanceof CapacityPlusSiteStatus)
{
- CapacityPlusSystemStatus cpss = (CapacityPlusSystemStatus)csbk;
+ CapacityPlusSiteStatus cpss = (CapacityPlusSiteStatus)csbk;
//Channel rotation monitor normally uses only CONTROL state, so when we detect that we're a
//Capacity plus system, add ACTIVE as an active state to the monitor. This can be requested repeatedly.
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/DMRMessageFramer.java b/src/main/java/io/github/dsheirer/module/decode/dmr/DMRMessageFramer.java
index bf54f344b..7fd234b16 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/DMRMessageFramer.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/DMRMessageFramer.java
@@ -377,7 +377,7 @@ private static Identity getIdentity(LRRPPacket packet)
public static void main(String[] args)
{
- String path = "/media/denny/Lexar/Recordings/DMR/";
+ String path = "/media/denny/T7 Shield/Recordings/DMR/";
//Con+ Traffic + Voice
// String file = path + "20200513_143340_9600BPS_DMR_SaiaNet_Onondaga_Control.bits"; //Enh GPS Revert Window Annce
@@ -385,7 +385,7 @@ public static void main(String[] args)
// String file = path + "20200514_063507_9600BPS_DMR_SaiaNet_Onondaga_LCN_3_Control.bits"; //GPS Window Grant 2579
// String file = path + "20200514_064224_9600BPS_DMR_SaiaNet_Onondaga_LCN_3_Control.bits"; //GPS Window Grant 5056035
// String file = path + "20200514_131623_9600BPS_DMR_SaiaNet_Onondaga_LCN_3_Control.bits"; //GPS Grant: 5074193
- String file = path + "20200514_133947_9600BPS_DMR_SaiaNet_Onondaga_LCN_4.bits"; //<<<<<<<------ Basic Encryption
+// String file = path + "SaiaNet/20200514_133947_9600BPS_DMR_SaiaNet_Onondaga_LCN_4.bits"; //<<<<<<<------ Basic Encryption
// String file = path + "20200514_142249_9600BPS_DMR_SaiaNet_Onondaga_LCN_4.bits";
// String file = path + "20200514_144534_9600BPS_DMR_SaiaNet_Onondaga_LCN_3_Control.bits"; //Con+ Control w/GPS Window Announce
@@ -395,12 +395,16 @@ public static void main(String[] args)
//Cap-Max Tier III CC
// String file = path + "20200710_053632_9600BPS_DMR_Niles_Radio_Coconino_Control.bits";
- //Cap+ Multi-Site 1 - Traffic LCN 2
-// String file = path + "20200716_210133_9600BPS_DMR_Aerowave_Technologies_Dallas_LCN_2.bits";
-// String file = path + "20200716_212309_9600BPS_DMR_Aerowave_Technologies_Dallas_LCN_2.bits";
+ //Cap+ Multi-Site 1 - Data Revert LSN1/2 with CSBKO 62 Site status
+// String file = path + "Texas_Dallas_Aerowave_Capacity_Plus_Multi_Site/20200716_210133_9600BPS_DMR_Aerowave_Technologies_Dallas_LCN_2.bits";
+// String file = path + "Texas_Dallas_Aerowave_Capacity_Plus_Multi_Site/20200716_210845_9600BPS_DMR_Aerowave_Technologies_Dallas_LCN_2.bits";
+// String file = path + "Texas_Dallas_Aerowave_Capacity_Plus_Multi_Site/20200716_212309_9600BPS_DMR_Aerowave_Technologies_Dallas_LCN_2.bits";
- //Cap+ Multi-Site Enhanced GPS Channel
-// String file = path + "20200714_224018_9600BPS_DMR_Farmers_Electric_Cooperative_Hunt_LCN_3.bits"; //This may have PLL mis-align issues
+ //Cap+ Multi-Site Enhanced Data Revert Channel (no CSBKO 62)
+// String file = path + "Texas_Hunt_Farmers_Electric_Capacity_Plus_Multi_Site/20200714_224018_9600BPS_DMR_Farmers_Electric_Cooperative_Hunt_LCN_3.bits"; //This may have PLL mis-align issues
+
+ //Cap+ Multi-Site - Dallas Unknown
+ String file = path + "Texas_Dallas_Unknown_1_Capacity_Plus_Multi_Site/20200716_211233_9600BPS_DMR_Dallas_Unk_Dallas_Unk.bits";
//Hytera Short Data = Proprietary (encrypted)
// String file = path + "20200716_222839_9600BPS_DMR_SystemUnk_SiteUnk_Unk.bits"; //Hytera short data packets
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/DMRMessageProcessor.java b/src/main/java/io/github/dsheirer/module/decode/dmr/DMRMessageProcessor.java
index 1661f27da..0ac7d2271 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/DMRMessageProcessor.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/DMRMessageProcessor.java
@@ -111,6 +111,9 @@ public void receive(IMessage message)
}
}
+ //Now that the message has been (potentially) enriched, dispatch it to the modules
+ dispatch(message);
+
//Extract the Full Link Control message fragment from the Voice with embedded signalling message
if(message instanceof VoiceEMBMessage)
{
@@ -202,9 +205,6 @@ else if((message instanceof IDLEMessage || message instanceof Aloha || message i
{
dispatch(mTalkerAliasAssembler.process(flc));
}
-
- //Now that the message has been (potentially) enriched, dispatch it to the modules
- dispatch(message);
}
/**
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/channel/DMRLogicalChannel.java b/src/main/java/io/github/dsheirer/module/decode/dmr/channel/DMRLogicalChannel.java
index 9117b9542..07088f10f 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/channel/DMRLogicalChannel.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/channel/DMRLogicalChannel.java
@@ -1,23 +1,20 @@
/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2023 Dennis Sheirer
*
- * * ******************************************************************************
- * * Copyright (C) 2014-2019 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
- * * *****************************************************************************
+ * 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
+ * ****************************************************************************
*/
package io.github.dsheirer.module.decode.dmr.channel;
@@ -87,7 +84,7 @@ public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("LSN:").append(getLogicalSlotNumber());
- sb.append(" LCN:").append(getValue());
+// sb.append(" LCN:").append(getValue());
return sb.toString();
}
}
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/DataMessage.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/DataMessage.java
index 79b2581ba..fa660d4b7 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/DataMessage.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/DataMessage.java
@@ -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
@@ -28,6 +28,9 @@
*/
public abstract class DataMessage extends DMRBurst
{
+ //R2, R1, R0 extracted from the BPTC extraction process. Note: message length remains at 96, even though these 3x bits
+ //are set at the end of the message.
+ private static final int[] BPTC_RESERVED_BITS = new int[]{96, 97, 98};
private SlotType mSlotType;
/**
@@ -54,4 +57,24 @@ public SlotType getSlotType()
{
return mSlotType;
}
+
+ /**
+ * 3x reserved bits that are left-over from the BPTC encode/decode process that can be used to hold values like
+ * Moto RAS indicator. These message length from the BPTC decoder is set to 96 and these 3x bits are appended to
+ * the end. However, to keep the message.toString() correct, we specify the length as 96.
+ * @return reserved value.
+ */
+ public int getBPTCReservedBits()
+ {
+ return getMessage().getInt(BPTC_RESERVED_BITS);
+ }
+
+ /**
+ * Indicates if the BPTC reserved bits value is anything other than 0.
+ * @return true if non-zero.
+ */
+ public boolean hasRAS()
+ {
+ return getBPTCReservedBits() != 0;
+ }
}
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/DataMessageWithLinkControl.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/DataMessageWithLinkControl.java
index 6c9d1c419..a7c56e5dd 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/DataMessageWithLinkControl.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/DataMessageWithLinkControl.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2020 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
@@ -26,7 +26,6 @@
import io.github.dsheirer.module.decode.dmr.message.data.lc.LCMessage;
import io.github.dsheirer.module.decode.dmr.message.data.lc.LCMessageFactory;
import io.github.dsheirer.module.decode.dmr.message.type.DataType;
-
import java.util.Collections;
import java.util.List;
@@ -71,6 +70,10 @@ public LCMessage getLCMessage()
public String toString()
{
StringBuilder sb = new StringBuilder();
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(getSlotType());
sb.append(" ").append(getLCMessage());
return sb.toString();
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/IDLEMessage.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/IDLEMessage.java
index 4e6acbc59..60a6924b8 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/IDLEMessage.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/IDLEMessage.java
@@ -1,7 +1,6 @@
/*
- * ******************************************************************************
- * sdrtrunk
- * Copyright (C) 2014-2020 Zhenyu Mao
+ * *****************************************************************************
+ * 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
@@ -15,7 +14,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
- * *****************************************************************************
+ * ****************************************************************************
*/
package io.github.dsheirer.module.decode.dmr.message.data;
@@ -23,7 +22,6 @@
import io.github.dsheirer.identifier.Identifier;
import io.github.dsheirer.module.decode.dmr.DMRSyncPattern;
import io.github.dsheirer.module.decode.dmr.message.CACH;
-
import java.util.Collections;
import java.util.List;
@@ -50,6 +48,12 @@ public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("CC:").append(getSlotType().getColorCode());
+
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
+
sb.append(" IDLE");
return sb.toString();
}
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/UnknownDataMessage.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/UnknownDataMessage.java
index a31199a77..ad5e9b359 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/UnknownDataMessage.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/UnknownDataMessage.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2020 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
@@ -23,7 +23,6 @@
import io.github.dsheirer.identifier.Identifier;
import io.github.dsheirer.module.decode.dmr.DMRSyncPattern;
import io.github.dsheirer.module.decode.dmr.message.CACH;
-
import java.util.Collections;
import java.util.List;
@@ -61,6 +60,11 @@ public String toString()
sb.append("TS").append(getTimeslot());
}
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
+
sb.append(" ").append(getSlotType());
sb.append(" ").append(getMessage().toHexString());
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/block/DataBlock.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/block/DataBlock.java
index 15696a83a..4026b5e6b 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/block/DataBlock.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/block/DataBlock.java
@@ -75,6 +75,11 @@ public String toString()
{
StringBuilder sb = new StringBuilder();
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
+
sb.append(" ").append(getSlotType());
sb.append(" ").append(getMessage().toHexString());
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/CSBKMessageFactory.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/CSBKMessageFactory.java
index a2f91f1f5..1254409dd 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/CSBKMessageFactory.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/CSBKMessageFactory.java
@@ -39,7 +39,7 @@
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.CapacityPlusDataRevertWindowGrant;
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.CapacityPlusNeighbors;
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.CapacityPlusPreamble;
-import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.CapacityPlusSystemStatus;
+import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.CapacityPlusSiteStatus;
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.ConnectPlusCSBKO_16;
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.ConnectPlusDataChannelGrant;
import io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola.ConnectPlusDataRevertWindowAnnouncement;
@@ -269,7 +269,7 @@ public static CSBKMessage create(DMRSyncPattern pattern, CorrectedBinaryMessage
csbk = new CapacityPlusPreamble(pattern, message, cach, slotType, timestamp, timeslot);
break;
case MOTOROLA_CAPPLUS_SYSTEM_STATUS:
- csbk = new CapacityPlusSystemStatus(pattern, message, cach, slotType, timestamp, timeslot);
+ csbk = new CapacityPlusSiteStatus(pattern, message, cach, slotType, timestamp, timeslot);
break;
case MOTOROLA_CAPPLUS_DATA_WINDOW_ANNOUNCEMENT:
csbk = new CapacityPlusDataRevertWindowAnnouncement(pattern, message, cach, slotType, timestamp, timeslot);
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/UnknownCSBKMessage.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/UnknownCSBKMessage.java
index d43af5e96..99c5610f6 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/UnknownCSBKMessage.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/UnknownCSBKMessage.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2020 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
@@ -25,7 +25,6 @@
import io.github.dsheirer.module.decode.dmr.message.CACH;
import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
import io.github.dsheirer.module.decode.dmr.message.type.Vendor;
-
import java.util.Collections;
import java.util.List;
@@ -60,6 +59,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" CSBK *UNKNOWN*");
Vendor vendor = getVendor();
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/Hytera08Acknowledge.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/Hytera08Acknowledge.java
index 7f2ee4b07..17ad6c591 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/Hytera08Acknowledge.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/Hytera08Acknowledge.java
@@ -83,6 +83,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" HYTERA 08 ").append(getAcknowledgeType());
sb.append(" REASON:");
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/Hytera68Acknowledge.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/Hytera68Acknowledge.java
index 8d324e82b..c8a4b6253 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/Hytera68Acknowledge.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/Hytera68Acknowledge.java
@@ -82,6 +82,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" HYTERA 68 ").append(getAcknowledgeType());
sb.append(" REASON:");
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/HyteraAloha.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/HyteraAloha.java
index b272ceb5f..6412c40ab 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/HyteraAloha.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/HyteraAloha.java
@@ -85,6 +85,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" HYTERA ALOHA");
if(hasRadioIdentifier())
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/HyteraAnnouncement.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/HyteraAnnouncement.java
index f1be96cad..a5c0edbf6 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/HyteraAnnouncement.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/HyteraAnnouncement.java
@@ -77,6 +77,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" HYTERA ANNOUNCEMENT-TYPE:").append(getAnnouncementType());
sb.append(" ").append(getSystemIdentityCode().getModel());
sb.append(" NETWORK:").append(getSystemIdentityCode().getNetwork());
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/HyteraCsbko44.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/HyteraCsbko44.java
index 09192d041..f735819d9 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/HyteraCsbko44.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/HyteraCsbko44.java
@@ -67,6 +67,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" HYTERA UNKNOWN CSBKO=44");
sb.append(" MSG:").append(getMessage().toHexString());
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/HyteraCsbko47.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/HyteraCsbko47.java
index ee6a562b6..e6b963986 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/HyteraCsbko47.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/HyteraCsbko47.java
@@ -75,6 +75,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" HYTERA CSBKO=47 ######### UNKNOWN");
sb.append(" FM:").append(getSourceRadio());
sb.append(" TO:").append(getDestinationRadio());
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/HyteraSmsAvailableNotification.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/HyteraSmsAvailableNotification.java
index f70f66bff..ca3b52058 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/HyteraSmsAvailableNotification.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/HyteraSmsAvailableNotification.java
@@ -75,6 +75,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" HYTERA SMS MESSAGE AVAILABLE FOR:").append(getDestinationRadio());
sb.append(" FM:").append(getSourceRadio());
sb.append(" UNK:").append(getUnknown());
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/HyteraXPTSiteState.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/HyteraXPTSiteState.java
index 62649aebd..26d04c781 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/HyteraXPTSiteState.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/hytera/HyteraXPTSiteState.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2020 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
@@ -25,7 +25,6 @@
import io.github.dsheirer.module.decode.dmr.message.CACH;
import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
import io.github.dsheirer.module.decode.dmr.message.data.csbk.CSBKMessage;
-
import java.util.ArrayList;
import java.util.List;
@@ -234,6 +233,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" HYTERA XPT SITE ");
if(isAllChannelsBusy())
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityMaxAloha.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityMaxAloha.java
index 64e2a1de3..32fc3fd28 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityMaxAloha.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityMaxAloha.java
@@ -82,6 +82,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" CSBK CAPACITY-MAX ALOHA");
if(hasRadioIdentifier())
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusCSBKO_60.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusCSBKO_60.java
index a16cb2bce..446cd86bb 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusCSBKO_60.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusCSBKO_60.java
@@ -59,6 +59,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" CSBK CAP+ *UNKNOWN* CSBK:60");
sb.append(" MSG:").append(getMessage().toHexString());
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusDataRevertWindowAnnouncement.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusDataRevertWindowAnnouncement.java
index e5e3b0f30..b663f5c67 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusDataRevertWindowAnnouncement.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusDataRevertWindowAnnouncement.java
@@ -88,6 +88,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" CSBK CAP+ ENHANCED DATA REVERT ANNOUNCEMENT");
sb.append(" WINDOW:").append(getSuperFrame()).append(".").append(getWindow());
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusDataRevertWindowGrant.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusDataRevertWindowGrant.java
index 0d0f2a431..9518a49e6 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusDataRevertWindowGrant.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusDataRevertWindowGrant.java
@@ -71,6 +71,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" CSBK CAP+ ENHANCED DATA REVERT GRANT TO:").append(getTargetAddress());
sb.append(" TRANSMIT IN WINDOW:").append(getSuperFrame()).append(".").append(getWindow());
sb.append(" MSG:").append(getMessage().toHexString());
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusNeighbors.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusNeighbors.java
index d628735f2..9f4dc5b38 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusNeighbors.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusNeighbors.java
@@ -88,6 +88,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" CSBK CAP+ SITE:").append(getSite());
sb.append(" REST ").append(getRestChannel());
sb.append(" FL:").append(getLCSS());
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusSiteStatus.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusSiteStatus.java
new file mode 100644
index 000000000..867f633bb
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusSiteStatus.java
@@ -0,0 +1,325 @@
+/*
+ * *****************************************************************************
+ * 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
+ * ****************************************************************************
+ */
+
+package io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola;
+
+import io.github.dsheirer.bits.CorrectedBinaryMessage;
+import io.github.dsheirer.identifier.Identifier;
+import io.github.dsheirer.module.decode.dmr.DMRSyncPattern;
+import io.github.dsheirer.module.decode.dmr.channel.DMRLogicalChannel;
+import io.github.dsheirer.module.decode.dmr.channel.ITimeslotFrequencyReceiver;
+import io.github.dsheirer.module.decode.dmr.channel.TimeslotFrequency;
+import io.github.dsheirer.module.decode.dmr.message.CACH;
+import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
+import io.github.dsheirer.module.decode.dmr.message.data.csbk.CSBKMessage;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Capacity+ Site Status CSBKO=62 Message
+ */
+public class CapacityPlusSiteStatus extends CSBKMessage implements ITimeslotFrequencyReceiver
+{
+ private static final int[] BYTE = new int[]{0, 1, 2, 3, 4, 5, 6, 7};
+ private static final int[] TWO_BYTES = new int[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
+ private static final int[] SEGMENT_INDICATOR = new int[]{16, 17};
+ private static final int TIMESLOT = 18;
+ private static final int RESERVED = 19;
+ private static final int[] REST_LSN = new int[]{20, 21, 22, 23};
+ private static final int[] LSN_VOICE_BITMAP = new int[]{24, 25, 26, 27, 28, 29, 30, 31};
+ private static final int LSN_1_8_BITMAP_START = 24;
+ private static final int[][] VOICE_TALKGROUPS = new int[][]{{32, 33, 34, 35, 36, 37, 38, 39},
+ {40, 41, 42, 43, 44, 45, 46, 47}, {48, 49, 50, 51, 52, 53, 54, 55}, {56, 57, 58, 59, 60, 61, 62, 63},
+ {64, 65, 66, 67, 68, 69, 70, 71}, {72, 73, 74, 75, 76, 77, 78, 79}};
+
+ private DMRLogicalChannel mRestChannel;
+ private List mIdentifiers;
+
+ /**
+ * Constructs an instance
+ *
+ * @param syncPattern for the CSBK
+ * @param message bits
+ * @param cach for the DMR burst
+ * @param slotType for this message
+ * @param timestamp
+ * @param timeslot
+ */
+ public CapacityPlusSiteStatus(DMRSyncPattern syncPattern, CorrectedBinaryMessage message, CACH cach, SlotType slotType, long timestamp, int timeslot)
+ {
+ super(syncPattern, message, cach, slotType, timestamp, timeslot);
+ }
+
+ @Override
+ public String toString()
+ {
+ StringBuilder sb = new StringBuilder();
+
+ if(!isValid())
+ {
+ sb.append("[CRC-ERROR] ");
+ }
+
+ sb.append("CC:").append(getSlotType().getColorCode());
+
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
+
+ sb.append(" CSBK CAP+ SITE STATUS REST ").append(getRestChannel());
+ sb.append(" ").append(getSegmentIndicator());
+ sb.append(" ");
+
+ if(getSegmentIndicator().isFirst())
+ {
+ sb.append(getActivityFragments());
+ }
+ else
+ {
+ sb.append("CONTINUATION BLOCK");
+ }
+
+ sb.append(" MSG:").append(getMessage().toHexString());
+
+ return sb.toString();
+ }
+
+ /**
+ * Indicates if this message has voice talkgroup activity.
+ *
+ * @return true if voice activity.
+ */
+ private boolean hasVoiceTalkgroups()
+ {
+ return getSegmentIndicator().isFirst() && getMessage().getInt(LSN_VOICE_BITMAP) > 0;
+ }
+
+ /**
+ * Extracts the call activity from the first or first/last fragment.
+ * @return description of call activity.
+ */
+ private String getActivityFragments()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.append("VOICE LSN ");
+ int pointer = LSN_1_8_BITMAP_START;
+
+ //Process voice LSNs 1-8
+ if(getMessage().getInt(BYTE, pointer) > 0)
+ {
+ int lowLsnBitmap = pointer;
+ pointer += 8;
+
+ for(int x = lowLsnBitmap; x < (lowLsnBitmap + 8); x++)
+ {
+ int lsn = x - lowLsnBitmap + 1;
+
+ if(getMessage().get(x))
+ {
+ if(pointer <= 72)
+ {
+ sb.append(lsn).append(":").append(getMessage().getInt(BYTE, pointer)).append(" ");
+ pointer += 8;
+ }
+ else
+ {
+ sb.append(lsn).append(":A ");
+ }
+ }
+ else
+ {
+ sb.append(lsn).append(":* ");
+ }
+ }
+ }
+ else
+ {
+ sb.append("1-8:* ");
+ pointer += 8;
+ }
+
+ //Process voice LSNs 9 - 16
+ if(pointer <= 72 && getMessage().getInt(BYTE, pointer) > 0)
+ {
+ int highLsnBitmap = pointer;
+
+ pointer += 8;
+
+ for(int x = highLsnBitmap; x < (highLsnBitmap + 8); x++)
+ {
+ int lsn = x - highLsnBitmap + 1 + 8;
+
+ if(getMessage().get(x))
+ {
+ if(pointer <= 72)
+ {
+ sb.append(lsn).append(":").append(getMessage().getInt(BYTE, pointer)).append(" ");
+ pointer += 8;
+ }
+ else
+ {
+ sb.append(lsn).append(":A ");
+ }
+ }
+ else
+ {
+ sb.append(lsn).append(":* ");
+ }
+ }
+ }
+ else
+ {
+ sb.append("9-16:* ");
+ pointer += 8;
+ }
+
+ //Process Data and Private Radio IDs - first bit in radio options byte is set to indicate more activity
+ if(pointer <= 72 && getMessage().get(pointer))
+ {
+ sb.append("DATA LSN ");
+ pointer += 8;
+
+ //If we have the data revert channel bitmap ...
+ if(pointer <= 72 && getMessage().getInt(BYTE, pointer) > 0)
+ {
+ int lowDataLsnBitmap = pointer;
+
+ pointer += 8;
+
+ for(int x = lowDataLsnBitmap; x < (lowDataLsnBitmap + 8); x++)
+ {
+ int lsn = x - lowDataLsnBitmap + 1;
+
+ if(getMessage().get(x))
+ {
+ if(pointer <= 64)
+ {
+ sb.append(lsn).append(":").append(getMessage().getInt(TWO_BYTES, pointer)).append(" ");
+ pointer += 16;
+ }
+ else
+ {
+ sb.append(lsn).append(":A ");
+ }
+ }
+ else
+ {
+ sb.append(lsn).append(":* ");
+ }
+ }
+ }
+ else
+ {
+ sb.append("1-8:- ");
+ }
+ }
+
+ return sb.toString();
+ }
+
+
+ /**
+ * Segment indicator for system status message values that are fragmented across multiple system status
+ * messages.
+ */
+ public SegmentIndicator getSegmentIndicator()
+ {
+ return SegmentIndicator.fromValue(getMessage().getInt(SEGMENT_INDICATOR));
+ }
+
+ /**
+ * Current rest channel for this site.
+ */
+ public DMRLogicalChannel getRestChannel()
+ {
+ if(mRestChannel == null)
+ {
+ mRestChannel = new DMRLogicalChannel(getRestRepeater(), getRestTimeslot());
+ }
+
+ return mRestChannel;
+ }
+
+ /**
+ * Rest LSN
+ *
+ * @return Logical Slot Number 1-16
+ */
+ public int getRestLSN()
+ {
+ return getMessage().getInt(REST_LSN);
+ }
+
+ /**
+ * Rest Channel Repeater
+ */
+ public int getRestRepeater()
+ {
+ return (int) Math.ceil(getRestLSN() / 2.0);
+ }
+
+ /**
+ * Rest Channel Timeslot
+ *
+ * @return 1 or 2
+ */
+ public int getRestTimeslot()
+ {
+ return (getRestLSN() % 2 == 0) ? 2 : 1;
+ }
+
+ /**
+ * Logical slot numbers that require slot to frequency mappings.
+ */
+ @Override
+ public int[] getLogicalTimeslotNumbers()
+ {
+ return getRestChannel().getLSNArray();
+ }
+
+ /**
+ * Applies logical slot number to frequency mapping.
+ *
+ * @param timeslotFrequencies that match the logical timeslots
+ */
+ @Override
+ public void apply(List timeslotFrequencies)
+ {
+ for(TimeslotFrequency timeslotFrequency : timeslotFrequencies)
+ {
+ if(getRestChannel().getLogicalSlotNumber() == timeslotFrequency.getNumber())
+ {
+ getRestChannel().setTimeslotFrequency(timeslotFrequency);
+ }
+ }
+ }
+
+ @Override
+ public List getIdentifiers()
+ {
+ if(mIdentifiers == null)
+ {
+ mIdentifiers = new ArrayList<>();
+ mIdentifiers.add(getRestChannel());
+ }
+
+ return mIdentifiers;
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusSystemStatus.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusSystemStatus.java
deleted file mode 100644
index d6598f86e..000000000
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusSystemStatus.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * *****************************************************************************
- * 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
- * ****************************************************************************
- */
-
-package io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola;
-
-import io.github.dsheirer.bits.CorrectedBinaryMessage;
-import io.github.dsheirer.identifier.Identifier;
-import io.github.dsheirer.module.decode.dmr.DMRSyncPattern;
-import io.github.dsheirer.module.decode.dmr.channel.DMRLogicalChannel;
-import io.github.dsheirer.module.decode.dmr.channel.ITimeslotFrequencyReceiver;
-import io.github.dsheirer.module.decode.dmr.channel.TimeslotFrequency;
-import io.github.dsheirer.module.decode.dmr.message.CACH;
-import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
-import io.github.dsheirer.module.decode.dmr.message.data.csbk.CSBKMessage;
-import io.github.dsheirer.module.decode.dmr.message.type.LCSS;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Capacity+ System Status CSBKO=62 Message
- */
-public class CapacityPlusSystemStatus extends CSBKMessage implements ITimeslotFrequencyReceiver
-{
- private static final int[] FRAGMENT_INDICATOR = new int[]{16, 17};
-// private static final int TIMESLOT = 18;
-// private static final int[] REST_REPEATER = new int[]{19, 20, 21, 22};
- private static final int[] REST_LSN = new int[]{20, 21, 22, 23};
- //private static final int[] REST_TIMESLOT = new int[]{23};
-
- private DMRLogicalChannel mRestChannel;
- private List mIdentifiers;
-
- /**
- * Constructs an instance
- *
- * @param syncPattern for the CSBK
- * @param message bits
- * @param cach for the DMR burst
- * @param slotType for this message
- * @param timestamp
- * @param timeslot
- */
- public CapacityPlusSystemStatus(DMRSyncPattern syncPattern, CorrectedBinaryMessage message, CACH cach, SlotType slotType, long timestamp, int timeslot)
- {
- super(syncPattern, message, cach, slotType, timestamp, timeslot);
- }
-
- @Override
- public String toString()
- {
- StringBuilder sb = new StringBuilder();
-
- if(!isValid())
- {
- sb.append("[CRC-ERROR] ");
- }
-
- sb.append("CC:").append(getSlotType().getColorCode());
- sb.append(" CSBK CAP+ SYSTEM STATUS ").append(getFragmentIndicator());
- sb.append(" REST ").append(getRestChannel());
- sb.append(" MSG:").append(getMessage().toHexString());
-
- return sb.toString();
- }
-
- /**
- * Fragment indicator for system status message values that are fragmented across multiple system status
- * messages.
- */
- public LCSS getFragmentIndicator()
- {
- return LCSS.fromValue(getMessage().getInt(FRAGMENT_INDICATOR));
- }
-
- /**
- * Current rest channel for this site.
- */
- public DMRLogicalChannel getRestChannel()
- {
- if(mRestChannel == null)
- {
- mRestChannel = new DMRLogicalChannel(getRestRepeater(), getRestTimeslot());
- }
-
- return mRestChannel;
- }
-
- /**
- * Rest LSN
- * @return Logical Slot Number 1-16
- */
- public int getRestLSN()
- {
- return getMessage().getInt(REST_LSN);
- }
-
- /**
- * Rest Channel Repeater
- */
- public int getRestRepeater() { return (int) Math.ceil(getRestLSN() / 2.0); }
-
- /**
- * Rest Channel Timeslot
- * @return 1 or 2
- */
- public int getRestTimeslot()
- {
- return (getRestLSN() % 2 == 0) ? 2 : 1;
- }
-
- /**
- * Logical slot numbers that require slot to frequency mappings.
- */
- @Override
- public int[] getLogicalTimeslotNumbers()
- {
- return getRestChannel().getLSNArray();
- }
-
- /**
- * Applies logical slot number to frequency mapping.
- *
- * @param timeslotFrequencies that match the logical timeslots
- */
- @Override
- public void apply(List timeslotFrequencies)
- {
- for(TimeslotFrequency timeslotFrequency : timeslotFrequencies)
- {
- if(getRestChannel().getLogicalSlotNumber() == timeslotFrequency.getNumber())
- {
- getRestChannel().setTimeslotFrequency(timeslotFrequency);
- }
- }
- }
-
- @Override
- public List getIdentifiers()
- {
- if(mIdentifiers == null)
- {
- mIdentifiers = new ArrayList<>();
- mIdentifiers.add(getRestChannel());
- }
-
- return mIdentifiers;
- }
-}
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusCSBKO_16.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusCSBKO_16.java
index 953295e63..ded576421 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusCSBKO_16.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusCSBKO_16.java
@@ -71,6 +71,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" CSBK CON+ CSBKO:16 FM:").append(getSourceRadio());
sb.append(" TO:").append(getTargetRadio());
sb.append(" UNK:").append(getUnknown());
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusDataChannelGrant.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusDataChannelGrant.java
index 64f149618..019840393 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusDataChannelGrant.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusDataChannelGrant.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2020 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
@@ -30,7 +30,6 @@
import io.github.dsheirer.module.decode.dmr.message.CACH;
import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
import io.github.dsheirer.module.decode.dmr.message.data.csbk.CSBKMessage;
-
import java.util.ArrayList;
import java.util.List;
@@ -77,6 +76,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" CSBK ").append(getVendor());
sb.append(" DATA CHANNEL GRANT TO:").append(getTargetRadio());
sb.append(" ").append(getChannel());
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusDataRevertWindowAnnouncement.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusDataRevertWindowAnnouncement.java
index 8ec0f56d4..6213c4ae3 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusDataRevertWindowAnnouncement.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusDataRevertWindowAnnouncement.java
@@ -70,6 +70,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" CSBK CON+ ENHANCED DATA REVERT CHANNEL ANNOUNCE WINDOW:");
sb.append(getSuperFrame()).append(".").append(getWindow());
if(hasTargetRadio())
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusDataRevertWindowGrant.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusDataRevertWindowGrant.java
index ee59381c8..73bc3c4ac 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusDataRevertWindowGrant.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusDataRevertWindowGrant.java
@@ -71,6 +71,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" CSBK CON+ ENHANCED DATA REVERT GRANT TO:").append(getTargetRadio());
sb.append(" TRANSMIT IN WINDOW:").append(getSuperFrame()).append(".").append(getWindow());
sb.append(" MSG:").append(getMessage().toHexString());
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusNeighborReport.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusNeighborReport.java
index a352d9cf4..76965fe7f 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusNeighborReport.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusNeighborReport.java
@@ -69,6 +69,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" CSBK CON+ NEIGHBORS:");
List neighbors = getNeighbors();
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusOTAAnnouncement.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusOTAAnnouncement.java
index 5319e0479..32a9136af 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusOTAAnnouncement.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusOTAAnnouncement.java
@@ -77,6 +77,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" CSBK CON+ ANNOUNCE OTA ").append(getMessageType());
sb.append(" VER:").append(getMessageVersion());
sb.append(" AVAILABLE ON ").append(getDataChannel());
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusRegistrationRequest.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusRegistrationRequest.java
index cc1e533a4..d37c5fe64 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusRegistrationRequest.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusRegistrationRequest.java
@@ -71,6 +71,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" CSBK CON+ REGISTRATION REQUEST FM:").append(getSourceRadio());
sb.append(" TO:").append(getTargetRadio());
sb.append(" UNK:").append(getUnknown());
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusRegistrationResponse.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusRegistrationResponse.java
index d182dd628..552b1a12a 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusRegistrationResponse.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusRegistrationResponse.java
@@ -71,6 +71,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" CSBK CON+ REGISTRATION RESPONSE FM:").append(getSourceRadio());
sb.append(" TO:").append(getTargetRadio());
sb.append(" UNK:").append(getUnknown());
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusTalkgroupAffiliation.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusTalkgroupAffiliation.java
index 3a374700a..1acd93edf 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusTalkgroupAffiliation.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusTalkgroupAffiliation.java
@@ -73,6 +73,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" CSBK CON+ AFFILIATE RADIO:").append(getRadio());
sb.append(" TO TALKGROUP:").append(getTalkgroup());
sb.append(" UNK:").append(getUnknown());
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusTerminateChannelGrant.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusTerminateChannelGrant.java
index c99315fdb..4719fcb25 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusTerminateChannelGrant.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusTerminateChannelGrant.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2020 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
@@ -27,7 +27,6 @@
import io.github.dsheirer.module.decode.dmr.message.CACH;
import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
import io.github.dsheirer.module.decode.dmr.message.data.csbk.CSBKMessage;
-
import java.util.ArrayList;
import java.util.List;
@@ -76,6 +75,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" CSBK ").append(getVendor());
sb.append(" TERMINATE CHANNEL GRANT TO:").append(getTargetRadio());
sb.append(" U1:").append(getUnknownField1());
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusVoiceChannelUser.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusVoiceChannelUser.java
index 4bcd3ab99..e16986c38 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusVoiceChannelUser.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/ConnectPlusVoiceChannelUser.java
@@ -79,6 +79,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" CSBK CON+ VOICE CHANNEL USER FM:").append(getRadio());
sb.append(" TO:").append(getTalkgroup());
sb.append(" ").append(getChannel());
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/SegmentIndicator.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/SegmentIndicator.java
new file mode 100644
index 000000000..58bae2173
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/SegmentIndicator.java
@@ -0,0 +1,92 @@
+/*
+ * *****************************************************************************
+ * 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
+ * ****************************************************************************
+ */
+
+package io.github.dsheirer.module.decode.dmr.message.data.csbk.motorola;
+
+/**
+ * Used by Cap+ channel status message to indicate if the channel status payload is a single fragment, or a
+ * multi-sequence fragment.
+ */
+public enum SegmentIndicator
+{
+ /**
+ * Continuation Segment
+ */
+ CONTINUATION_SEGMENT("[--]"),
+
+ /**
+ * Last Segment in a multi-segment sequence
+ */
+ LAST_SEGMENT("[-L]"),
+
+ /**
+ * First Segment in a multi-segment sequence
+ */
+ FIRST_SEGMENT("[F-]"),
+
+ /**
+ * Single Segment.
+ */
+ SINGLE_SEGMENT("[FL]"),
+
+ /**
+ * Unknow Segment
+ */
+ UNKNOWN("[**]");
+
+ private String mLabel;
+
+ /**
+ * Constructs an instance
+ * @param label to display
+ */
+ SegmentIndicator(String label)
+ {
+ mLabel = label;
+ }
+
+ /**
+ * Lookup a segment indicator from the value.
+ * @param value to lookup
+ * @return segment indicator (0-3) or UNKNOWN.
+ */
+ public static SegmentIndicator fromValue(int value)
+ {
+ if(0 <= value && value < 4)
+ {
+ return SegmentIndicator.values()[value];
+ }
+
+ return UNKNOWN;
+ }
+
+ /**
+ * Indicates if this is the first in a multi-segment sequence or if this is a single-segment.
+ */
+ public boolean isFirst()
+ {
+ return this.equals(FIRST_SEGMENT) || this.equals(SINGLE_SEGMENT);
+ }
+
+ @Override
+ public String toString()
+ {
+ return mLabel;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/Aloha.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/Aloha.java
index 367474d6d..63c320ba9 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/Aloha.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/Aloha.java
@@ -82,6 +82,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" ALOHA");
if(hasRadioIdentifier())
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/Clear.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/Clear.java
index b388cd29e..da7e2466e 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/Clear.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/Clear.java
@@ -109,6 +109,11 @@ public String toString()
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
+
if(isEncrypted())
{
sb.append(" ENCRYPTED");
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/MoveTSCC.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/MoveTSCC.java
index e1be3736c..b8c791c8f 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/MoveTSCC.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/MoveTSCC.java
@@ -119,6 +119,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" MOVE TRUNK CONTROL CHANNEL ").append(getChannel());
if(hasRadioIdentifier())
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/Preamble.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/Preamble.java
index 13a229520..387e6bc23 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/Preamble.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/Preamble.java
@@ -75,6 +75,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" CSBK PREAMBLE FM:").append(getSourceAddress());
sb.append(" TO:").append(getTargetAddress());
sb.append(isCSBKPreamble() ? " CSBK" : " DATA");
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/Protect.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/Protect.java
index eff96c2a8..aa476e29d 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/Protect.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/Protect.java
@@ -77,6 +77,11 @@ public String toString()
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
+
if(isEncrypted())
{
sb.append(" ENCRYPTED");
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/acknowledge/Acknowledge.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/acknowledge/Acknowledge.java
index 32f6caf77..2cc099d54 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/acknowledge/Acknowledge.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/acknowledge/Acknowledge.java
@@ -80,6 +80,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" ").append(getAcknowledgeType());
sb.append(" REASON:").append(getReason());
sb.append(" FM:").append(getSourceRadio());
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/ahoy/AuthenticateRegisterRadioCheck.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/ahoy/AuthenticateRegisterRadioCheck.java
index 2a43c7667..3cdcc7e9d 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/ahoy/AuthenticateRegisterRadioCheck.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/ahoy/AuthenticateRegisterRadioCheck.java
@@ -65,6 +65,11 @@ public String toString()
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
+
if(isEncrypted())
{
sb.append(" ENCRYPTED");
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/ahoy/CancelCall.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/ahoy/CancelCall.java
index 1671394dc..25226f5c1 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/ahoy/CancelCall.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/ahoy/CancelCall.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2020 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
@@ -26,7 +26,6 @@
import io.github.dsheirer.module.decode.dmr.identifier.DMRRadio;
import io.github.dsheirer.module.decode.dmr.message.CACH;
import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
-
import java.util.ArrayList;
import java.util.List;
@@ -65,6 +64,11 @@ public String toString()
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
+
if(isEncrypted())
{
sb.append(" ENCRYPTED");
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/ahoy/ServiceRadioCheck.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/ahoy/ServiceRadioCheck.java
index fc6b5a4f6..ba886f7a6 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/ahoy/ServiceRadioCheck.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/ahoy/ServiceRadioCheck.java
@@ -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
@@ -26,7 +26,6 @@
import io.github.dsheirer.module.decode.dmr.identifier.DMRRadio;
import io.github.dsheirer.module.decode.dmr.message.CACH;
import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
-
import java.util.ArrayList;
import java.util.List;
@@ -65,6 +64,11 @@ public String toString()
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
+
if(isEncrypted())
{
sb.append(" ENCRYPTED");
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/ahoy/StunReviveKill.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/ahoy/StunReviveKill.java
index cba0f7895..29757be81 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/ahoy/StunReviveKill.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/ahoy/StunReviveKill.java
@@ -65,6 +65,11 @@ public String toString()
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
+
if(isEncrypted())
{
sb.append(" ENCRYPTED");
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/ahoy/UnknownAhoy.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/ahoy/UnknownAhoy.java
index c091ebc76..af9d57c21 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/ahoy/UnknownAhoy.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/ahoy/UnknownAhoy.java
@@ -65,6 +65,11 @@ public String toString()
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
+
if(isEncrypted())
{
sb.append(" ENCRYPTED");
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/announcement/Announcement.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/announcement/Announcement.java
index f05fc1c7f..4e6d2ab68 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/announcement/Announcement.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/announcement/Announcement.java
@@ -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
@@ -27,7 +27,6 @@
import io.github.dsheirer.module.decode.dmr.message.data.csbk.CSBKMessage;
import io.github.dsheirer.module.decode.dmr.message.type.AnnouncementType;
import io.github.dsheirer.module.decode.dmr.message.type.SystemIdentityCode;
-
import java.util.ArrayList;
import java.util.List;
@@ -73,6 +72,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" ANNOUNCEMENT ").append(getAnnouncementType());
return sb.toString();
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/BroadcastTalkgroupVoiceChannelGrant.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/BroadcastTalkgroupVoiceChannelGrant.java
index 9982e24f9..859bf907e 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/BroadcastTalkgroupVoiceChannelGrant.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/BroadcastTalkgroupVoiceChannelGrant.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2020 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
@@ -29,7 +29,6 @@
import io.github.dsheirer.module.decode.dmr.message.CACH;
import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
import io.github.dsheirer.module.decode.dmr.message.data.mbc.MBCContinuationBlock;
-
import java.util.ArrayList;
import java.util.List;
@@ -88,6 +87,11 @@ public String toString()
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
+
if(isEmergency())
{
sb.append(" EMERGENCY");
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/DuplexPrivateDataChannelGrant.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/DuplexPrivateDataChannelGrant.java
index b83c50b73..5b68cb9ac 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/DuplexPrivateDataChannelGrant.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/DuplexPrivateDataChannelGrant.java
@@ -86,6 +86,11 @@ public String toString()
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
+
if(isEmergency())
{
sb.append(" EMERGENCY");
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/DuplexPrivateVoiceChannelGrant.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/DuplexPrivateVoiceChannelGrant.java
index daa58f9e6..eab51690a 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/DuplexPrivateVoiceChannelGrant.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/DuplexPrivateVoiceChannelGrant.java
@@ -86,6 +86,11 @@ public String toString()
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
+
if(isEmergency())
{
sb.append(" EMERGENCY");
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/PrivateDataChannelGrant.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/PrivateDataChannelGrant.java
index 980dc1189..58400f5dc 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/PrivateDataChannelGrant.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/PrivateDataChannelGrant.java
@@ -86,6 +86,11 @@ public String toString()
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
+
if(isEmergency())
{
sb.append(" EMERGENCY");
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/PrivateVoiceChannelGrant.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/PrivateVoiceChannelGrant.java
index 410462b1b..74492622f 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/PrivateVoiceChannelGrant.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/PrivateVoiceChannelGrant.java
@@ -85,6 +85,11 @@ public String toString()
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
+
if(isEmergency())
{
sb.append(" EMERGENCY");
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/TalkgroupDataChannelGrant.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/TalkgroupDataChannelGrant.java
index 9355dd424..49e542577 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/TalkgroupDataChannelGrant.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/TalkgroupDataChannelGrant.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2020 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
@@ -29,7 +29,6 @@
import io.github.dsheirer.module.decode.dmr.message.CACH;
import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
import io.github.dsheirer.module.decode.dmr.message.data.mbc.MBCContinuationBlock;
-
import java.util.ArrayList;
import java.util.List;
@@ -89,6 +88,11 @@ public String toString()
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
+
if(isEmergency())
{
sb.append(" EMERGENCY");
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/TalkgroupVoiceChannelGrant.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/TalkgroupVoiceChannelGrant.java
index 40c191176..3406e6859 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/TalkgroupVoiceChannelGrant.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/standard/grant/TalkgroupVoiceChannelGrant.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2020 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
@@ -29,7 +29,6 @@
import io.github.dsheirer.module.decode.dmr.message.CACH;
import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
import io.github.dsheirer.module.decode.dmr.message.data.mbc.MBCContinuationBlock;
-
import java.util.ArrayList;
import java.util.List;
@@ -88,6 +87,11 @@ public String toString()
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
+
if(isEmergency())
{
sb.append(" EMERGENCY");
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/header/MBCHeader.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/header/MBCHeader.java
index daf4662a4..0923ce634 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/header/MBCHeader.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/header/MBCHeader.java
@@ -67,6 +67,11 @@ public String toString()
StringBuilder sb = new StringBuilder();
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
+
if(!isValid())
{
sb.append(" [CRC ERROR]");
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/lc/LCOpcode.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/lc/LCOpcode.java
index 38dcde62e..5b286f24a 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/lc/LCOpcode.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/lc/LCOpcode.java
@@ -46,6 +46,12 @@ public enum LCOpcode
FULL_CAPACITY_PLUS_GROUP_VOICE_CHANNEL_USER(Vendor.MOTOROLA_CAPACITY_PLUS, true, 0, "GROUP VOICE CHANNEL USER"),
FULL_CAPACITY_PLUS_WIDE_AREA_VOICE_CHANNEL_USER(Vendor.MOTOROLA_CAPACITY_PLUS, true, 4, "WAN GROUP VOICE CHANNEL USER"),
+ //Cap+ opcodes from https://forums.radioreference.com/threads/understanding-capacity-plus-trunking-some-more.452566/
+ //FLCO 0: Group Call Maintenance
+ //FLCO 3: Private Call Maintenance (TermLC)
+ //FLCO 4: Group Call Grant
+ //FLCO 7: Private Call Grant
+ //FLCO 35: Private Call Maintenance (EMB)
FULL_HYTERA_GROUP_VOICE_CHANNEL_USER(Vendor.HYTERA_68, true, 0, "HYTERA GROUP VOICE CHANNEL USER"),
FULL_HYTERA_UNIT_TO_UNIT_VOICE_CHANNEL_USER(Vendor.HYTERA_68, true, 3, "HYTERA UNIT-TO-UNIT VOICE CHANNEL USER"),
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/lc/shorty/CapacityPlusRestChannel.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/lc/shorty/CapacityPlusRestChannel.java
index d0c86812e..f8896947c 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/lc/shorty/CapacityPlusRestChannel.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/lc/shorty/CapacityPlusRestChannel.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2020 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
@@ -25,7 +25,6 @@
import io.github.dsheirer.module.decode.dmr.channel.ITimeslotFrequencyReceiver;
import io.github.dsheirer.module.decode.dmr.channel.TimeslotFrequency;
import io.github.dsheirer.module.decode.dmr.identifier.DMRSite;
-
import java.util.ArrayList;
import java.util.List;
@@ -64,7 +63,7 @@ public String toString()
sb.append("[CRC ERROR] ");
}
sb.append("SLC MOTOROLA CAP+ SITE:").append(getSite());
- sb.append(" REST CHANNEL:").append(getRestChannel());
+ sb.append(" REST:").append(getRestChannel());
sb.append(" MSG:").append(getMessage().toHexString());
return sb.toString();
}
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/mbc/MBCContinuationBlock.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/mbc/MBCContinuationBlock.java
index bd9301051..4b865312d 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/mbc/MBCContinuationBlock.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/mbc/MBCContinuationBlock.java
@@ -51,6 +51,11 @@ public String toString()
StringBuilder sb = new StringBuilder();
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
+
if(!isValid())
{
sb.append(" [CRC ERROR]");
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/mbc/UnknownMultiCSBK.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/mbc/UnknownMultiCSBK.java
index 4a16c11a1..c73fe6470 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/mbc/UnknownMultiCSBK.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/mbc/UnknownMultiCSBK.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2020 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
@@ -23,7 +23,6 @@
import io.github.dsheirer.module.decode.dmr.message.data.csbk.Opcode;
import io.github.dsheirer.module.decode.dmr.message.data.header.MBCHeader;
import io.github.dsheirer.module.decode.dmr.message.type.Vendor;
-
import java.util.Collections;
import java.util.List;
@@ -54,6 +53,10 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
sb.append(" CSBK *UNKNOWN*");
Vendor vendor = getVendor();
diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/usb/USBData.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/usb/USBData.java
index 24bbb4eb9..199b40edb 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/usb/USBData.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/usb/USBData.java
@@ -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
@@ -29,7 +29,6 @@
import io.github.dsheirer.module.decode.dmr.message.data.DataMessage;
import io.github.dsheirer.module.decode.dmr.message.data.SlotType;
import io.github.dsheirer.module.decode.dmr.message.type.ServiceType;
-
import java.util.ArrayList;
import java.util.List;
@@ -80,6 +79,11 @@ public String toString()
}
sb.append("CC:").append(getSlotType().getColorCode());
+ if(hasRAS())
+ {
+ sb.append(" RAS:").append(getBPTCReservedBits());
+ }
+
sb.append(" USB DATA BLOCK");
sb.append(" TO:").append(getTargetRadio());
sb.append(" SERVICE:").append(getServiceType());