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 cd01f677..0d5ac81b 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 @@ import java.util.List;
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 class BPTC_196_96
}
}
+ //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 d24a223e..6ff10e04 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.DataMessage;
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;
@@ -673,10 +673,10 @@ public class DMRDecoderState extends TimeslotDecoderState
updateRestChannel(((CapacityPlusNeighbors)csbk).getRestChannel());
}
break;
- case MOTOROLA_CAPPLUS_SYSTEM_STATUS:
- if(csbk instanceof CapacityPlusSystemStatus)
+ case MOTOROLA_CAPPLUS_SITE_STATUS:
+ 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 bf54f344..7fd234b1 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 @@ public class DMRMessageFramer implements Listener, IDMRBurstDetectListene
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 class DMRMessageFramer implements Listener, IDMRBurstDetectListene
// 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 class DMRMessageFramer implements Listener, IDMRBurstDetectListene
//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 1661f27d..0ac7d227 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 class DMRMessageProcessor implements Listener
}
}
+ //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 @@ public class DMRMessageProcessor implements Listener
{
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 9117b954..07088f10 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 class DMRLogicalChannel extends DMRChannel
{
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 79b2581b..7d3127b5 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 @@ import io.github.dsheirer.module.decode.dmr.message.DMRBurst;
*/
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 abstract class DataMessage extends DMRBurst
{
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. The message length from the BPTC decoder is set to 96 and these 3x bits are appended to
+ * the end as overage. 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 6c9d1c41..a7c56e5d 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.CACH;
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 abstract class DataMessageWithLinkControl extends DataMessage
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 4e6acbc5..60a6924b 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.bits.CorrectedBinaryMessage;
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 class IDLEMessage extends DataMessage
{
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 a31199a7..ad5e9b35 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.bits.CorrectedBinaryMessage;
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 class UnknownDataMessage extends DataMessage
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 15696a83..4026b5e6 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 abstract class DataBlock extends DataMessage
{
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 a2f91f1f..1005574d 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.CapacityP
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;
@@ -268,8 +268,8 @@ public class CSBKMessageFactory
case MOTOROLA_CAPPLUS_PREAMBLE:
csbk = new CapacityPlusPreamble(pattern, message, cach, slotType, timestamp, timeslot);
break;
- case MOTOROLA_CAPPLUS_SYSTEM_STATUS:
- csbk = new CapacityPlusSystemStatus(pattern, message, cach, slotType, timestamp, timeslot);
+ case MOTOROLA_CAPPLUS_SITE_STATUS:
+ 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/Opcode.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/Opcode.java
index faf087a4..cdccf419 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/Opcode.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/Opcode.java
@@ -87,7 +87,7 @@ public enum Opcode
MOTOROLA_CAPPLUS_NEIGHBOR_REPORT(Vendor.MOTOROLA_CAPACITY_PLUS, 59, "NEIGHBOR REPORT"),
MOTOROLA_CAPPLUS_CSBKO_60(Vendor.MOTOROLA_CAPACITY_PLUS, 60, "CSBKO 60"),
MOTOROLA_CAPPLUS_PREAMBLE(Vendor.MOTOROLA_CAPACITY_PLUS, 61, "PREAMBLE"),
- MOTOROLA_CAPPLUS_SYSTEM_STATUS(Vendor.MOTOROLA_CAPACITY_PLUS, 62, "SYSTEM STATUS"),
+ MOTOROLA_CAPPLUS_SITE_STATUS(Vendor.MOTOROLA_CAPACITY_PLUS, 62, "SITE STATUS"),
HYTERA_08_ACKNOWLEDGE(Vendor.HYTERA_8, 32, "HYTERA 08 ACKNOWLEDGE"),
HYTERA_08_ANNOUNCEMENT(Vendor.HYTERA_8, 40, "HYTERA 08 ANNOUNCEMENT"),
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 d43af5e9..99c5610f 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.DMRSyncPattern;
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 class UnknownCSBKMessage extends CSBKMessage
}
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 7f2ee4b0..17ad6c59 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 class Hytera08Acknowledge extends CSBKMessage
}
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 8d324e82..c8a4b625 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 class Hytera68Acknowledge extends CSBKMessage
}
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 b272ceb5..6412c40a 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 class HyteraAloha extends CSBKMessage
}
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 f1be96ca..a5c0edbf 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 class HyteraAnnouncement extends CSBKMessage
}
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 09192d04..f735819d 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 class HyteraCsbko44 extends CSBKMessage
}
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 ee6a562b..e6b96398 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 class HyteraCsbko47 extends CSBKMessage
}
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 f70f66bf..ca3b5205 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 class HyteraSmsAvailableNotification extends CSBKMessage
}
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 62649aeb..26d04c78 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.DMRSyncPattern;
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 class HyteraXPTSiteState extends CSBKMessage
}
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 64e2a1de..32fc3fd2 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 class CapacityMaxAloha extends CSBKMessage
}
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 a16cb2bc..446cd86b 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 class CapacityPlusCSBKO_60 extends CSBKMessage
}
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 e5e3b0f3..b663f5c6 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 class CapacityPlusDataRevertWindowAnnouncement extends CSBKMessage
}
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 0d0f2a43..9518a49e 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 class CapacityPlusDataRevertWindowGrant extends CSBKMessage
}
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 e3175ac6..9f4dc5b3 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
@@ -40,8 +40,7 @@ public class CapacityPlusNeighbors extends CSBKMessage implements ITimeslotFrequ
{
private static final int[] LC_START_STOP = 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_TIMESLOT = new int[]{23};
+ private static final int[] REST_LSN = new int[]{19, 20, 21, 22, 23};
private static final int ASYNC = 24;
private static final int[] SITE = new int[]{25, 26, 27, 28};
private static final int[] NEIGHBOR_COUNT = new int[]{29, 30, 31};
@@ -89,6 +88,10 @@ public class CapacityPlusNeighbors extends CSBKMessage implements ITimeslotFrequ
}
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());
@@ -274,13 +277,19 @@ public class CapacityPlusNeighbors extends CSBKMessage implements ITimeslotFrequ
return LCSS.fromValue(getMessage().getInt(LC_START_STOP));
}
+ /**
+ * Rest LSN
+ * @return Logical Slot Number 1-16
+ */
+ public int getRestLSN()
+ {
+ return getMessage().getInt(REST_LSN);
+ }
+
/**
* Rest repeater
*/
- public int getRestRepeater()
- {
- return getMessage().getInt(REST_REPEATER) + 1;
- }
+ public int getRestRepeater() { return (int) Math.ceil(getRestLSN() / 2.0); }
/**
* Rest timeslot
@@ -288,7 +297,7 @@ public class CapacityPlusNeighbors extends CSBKMessage implements ITimeslotFrequ
*/
public int getRestTimeslot()
{
- return getMessage().getInt(REST_TIMESLOT) + 1;
+ return (getRestLSN() % 2 == 0) ? 2 : 1;
}
/**
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 00000000..867f633b
--- /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 d9d7eba0..00000000
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/csbk/motorola/CapacityPlusSystemStatus.java
+++ /dev/null
@@ -1,157 +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_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 Channel Repeater
- */
- public int getRestRepeater()
- {
- return getMessage().getInt(REST_REPEATER) + 1;
- }
-
- /**
- * Rest Channel Timeslot
- * @return 1 or 2
- */
- public int getRestTimeslot()
- {
- return getMessage().getInt(REST_TIMESLOT) + 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 953295e6..ded57642 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 class ConnectPlusCSBKO_16 extends CSBKMessage
}
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 64f14961..01984039 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.identifier.DMRRadio;
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 class ConnectPlusDataChannelGrant extends CSBKMessage implements ITimeslo
}
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 8ec0f56d..6213c4ae 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 class ConnectPlusDataRevertWindowAnnouncement extends CSBKMessage
}
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 ee59381c..73bc3c4a 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 class ConnectPlusDataRevertWindowGrant extends CSBKMessage
}
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 a352d9cf..76965fe7 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 class ConnectPlusNeighborReport extends CSBKMessage
}
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 5319e047..32a9136a 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 class ConnectPlusOTAAnnouncement extends CSBKMessage implements ITimeslot
}
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 cc1e533a..d37c5fe6 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 class ConnectPlusRegistrationRequest extends CSBKMessage
}
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 d182dd62..552b1a12 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 class ConnectPlusRegistrationResponse extends CSBKMessage
}
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 3a374700..1acd93ed 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 class ConnectPlusTalkgroupAffiliation extends CSBKMessage
}
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 c99315fd..4719fcb2 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.identifier.DMRRadio;
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 class ConnectPlusTerminateChannelGrant extends CSBKMessage
}
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 4bcd3ab9..e16986c3 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 class ConnectPlusVoiceChannelUser extends CSBKMessage implements ITimeslo
}
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 00000000..58bae217
--- /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 367474d6..63c320ba 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 class Aloha extends CSBKMessage
}
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 b388cd29..da7e2466 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 class Clear extends CSBKMessage implements ITimeslotFrequencyReceiver
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 e1be3736..b8c791c8 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 class MoveTSCC extends CSBKMessage
}
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 13a22952..387e6bc2 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 class Preamble extends CSBKMessage
}
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 eff96c2a..aa476e29 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 class Protect extends CSBKMessage
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 32f6caf7..2cc099d5 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 class Acknowledge extends CSBKMessage
}
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 2a43c766..3cdcc7e9 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 class AuthenticateRegisterRadioCheck extends Ahoy
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 1671394d..25226f5c 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.DMRSyncPattern;
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 class CancelCall extends Ahoy
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 fc6b5a4f..ba886f7a 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.DMRSyncPattern;
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 class ServiceRadioCheck extends Ahoy
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 cba0f789..29757be8 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 class StunReviveKill extends Ahoy
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 c091ebc7..af9d57c2 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 class UnknownAhoy extends Ahoy
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 f05fc1c7..4e6d2ab6 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.SlotType;
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 class Announcement extends CSBKMessage
}
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 9982e24f..859bf907 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.identifier.DMRTalkgroup;
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 class BroadcastTalkgroupVoiceChannelGrant extends ChannelGrant
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 b83c50b7..5b68cb9a 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 class DuplexPrivateDataChannelGrant extends ChannelGrant
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 daa58f9e..eab51690 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 class DuplexPrivateVoiceChannelGrant extends ChannelGrant
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 980dc118..58400f5d 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 class PrivateDataChannelGrant extends ChannelGrant
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 410462b1..74492622 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 class PrivateVoiceChannelGrant extends ChannelGrant
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 9355dd42..49e54257 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.identifier.DMRTalkgroup;
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 class TalkgroupDataChannelGrant extends ChannelGrant
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 40c19117..3406e685 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.identifier.DMRTalkgroup;
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 class TalkgroupVoiceChannelGrant extends ChannelGrant
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 daf4662a..0923ce63 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 class MBCHeader extends CSBKMessage
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 38dcde62..5b286f24 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/full/motorola/CapacityPlusWideAreaVoiceChannelUser.java b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/lc/full/motorola/CapacityPlusWideAreaVoiceChannelUser.java
index 14bec291..361093b6 100644
--- a/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/lc/full/motorola/CapacityPlusWideAreaVoiceChannelUser.java
+++ b/src/main/java/io/github/dsheirer/module/decode/dmr/message/data/lc/full/motorola/CapacityPlusWideAreaVoiceChannelUser.java
@@ -38,8 +38,9 @@ public class CapacityPlusWideAreaVoiceChannelUser extends CapacityPlusVoiceChann
{
private static final int[] UNKNOWN_1 = new int[]{24, 25, 26, 27, 28, 29, 30, 31};
private static final int[] GROUP_ADDRESS = new int[]{40, 41, 42, 43, 44, 45, 46, 47};
- private static final int[] REST_REPEATER = new int[]{51, 52, 53, 54};
- private static final int[] REST_TIMESLOT = new int[]{55};
+ //private static final int[] REST_REPEATER = new int[]{51, 52, 53, 54};
+ //private static final int[] REST_TIMESLOT = new int[]{55};
+ private static final int[] REST_LSN = new int[]{52, 53, 54, 55};
private static final int[] SOURCE_ADDRESS = new int[]{56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71};
private static final int[] UNKNOWN_3 = new int[]{72, 73, 74, 75, 76, 77, 78, 79};
@@ -126,21 +127,27 @@ public class CapacityPlusWideAreaVoiceChannelUser extends CapacityPlusVoiceChann
return mRestChannel;
}
+ /**
+ * Rest LSN
+ * @return Logical Slot Number 1-16
+ */
+ public int getRestLSN()
+ {
+ return getMessage().getInt(REST_LSN);
+ }
+
/**
* Rest channel timeslot
*/
public int getRestTimeslot()
{
- return getMessage().getInt(REST_TIMESLOT) + 1;
+ return (getRestLSN() % 2 == 0) ? 2 : 1;
}
/**
* Rest channel repeater number
*/
- public int getRestRepeater()
- {
- return getMessage().getInt(REST_REPEATER) + 1;
- }
+ public int getRestRepeater() { return (int) Math.ceil(getRestLSN() / 2.0); }
/**
* Indicates if this message has a reset channel defined.
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 c83f365a..f8896947 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.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.identifier.DMRSite;
-
import java.util.ArrayList;
import java.util.List;
@@ -35,8 +34,9 @@ import java.util.List;
public class CapacityPlusRestChannel extends ShortLCMessage implements ITimeslotFrequencyReceiver
{
private static final int[] UNKNOWN = new int[]{12, 13, 14};
- private static final int[] REST_REPEATER = new int[]{15, 16, 17, 18};
- private static final int[] REST_TIMESLOT = new int[]{19};
+ //private static final int[] REST_REPEATER = new int[]{15, 16, 17, 18};
+ private static final int[] REST_LSN = new int[]{15, 16, 17, 18, 19};
+ //private static final int[] REST_TIMESLOT = new int[]{19};
private static final int[] SITE = new int[]{20, 21, 22, 23, 24};
private static final int[] UNKNOWN_2 = new int[]{25, 26, 27};
@@ -63,7 +63,7 @@ public class CapacityPlusRestChannel extends ShortLCMessage implements ITimeslot
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();
}
@@ -94,20 +94,26 @@ public class CapacityPlusRestChannel extends ShortLCMessage implements ITimeslot
return mRestChannel;
}
+ /**
+ * Rest LSN
+ * @return Logical Slot Number 1-16
+ */
+ public int getRestLSN()
+ {
+ return getMessage().getInt(REST_LSN);
+ }
+
/**
* Rest repeater
*/
- public int getRestRepeater()
- {
- return getMessage().getInt(REST_REPEATER) + 1;
- }
+ public int getRestRepeater() { return (int) Math.ceil(getRestLSN() / 2.0); }
/**
* Rest timeslot
*/
public int getRestTimeslot()
{
- return getMessage().getInt(REST_TIMESLOT) + 1;
+ return (getRestLSN() % 2 == 0) ? 2 : 1;
}
/**
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 bd930105..4b865312 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 class MBCContinuationBlock extends DataMessage
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 4a16c11a..c73fe647 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.identifier.Identifier;
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 class UnknownMultiCSBK extends MultiCSBK
}
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 24bbb4eb..199b40ed 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.CACH;
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 class USBData extends DataMessage
}
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());