mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
#1746 DMR Decoder now supports simplex repeater and DMDC modes of operation.
This commit is contained in:
@@ -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
|
||||
@@ -284,11 +284,27 @@ public class DMRBurstFramer implements Listener<Dibit>
|
||||
}
|
||||
else
|
||||
{
|
||||
//When we don't have sufficient timeslot tracking data, dump the messages to timeslot 0 so that they
|
||||
//don't corrupt the decoder states for either timeslot, until we positively regain timeslot tracking
|
||||
//When we don't have sufficient timeslot tracking data, we either have misaligned timeslots from a
|
||||
//repeater or we have some form of mobile burst. If mobile, process to the correct timeslto, otherwise
|
||||
//dump the messages to timeslot 0 so that the burst doesn't corrupt the decoder states for either
|
||||
// timeslot, until we positively regain timeslot tracking
|
||||
if(burst1 != null)
|
||||
{
|
||||
mBurstDetectListener.burstDetected(burst1, mSyncTrackerTimeslot1.getSyncPattern(), 0);
|
||||
DMRSyncPattern sync1 = mSyncTrackerTimeslot1.getSyncPattern();
|
||||
|
||||
if(sync1.isMobileStationSyncPattern() || sync1.isDirectModeTS1())
|
||||
{
|
||||
mBurstDetectListener.burstDetected(burst1, sync1, 1);
|
||||
}
|
||||
else if(sync1.isDirectModeTS2())
|
||||
{
|
||||
mBurstDetectListener.burstDetected(burst1, sync1, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
mBurstDetectListener.burstDetected(burst1, sync1, 0);
|
||||
}
|
||||
|
||||
mDibitCounter -= BURST_DIBIT_LENGTH;
|
||||
}
|
||||
else
|
||||
@@ -298,7 +314,21 @@ public class DMRBurstFramer implements Listener<Dibit>
|
||||
|
||||
if(burst2 != null)
|
||||
{
|
||||
mBurstDetectListener.burstDetected(burst2, mSyncTrackerTimeslot2.getSyncPattern(), 0);
|
||||
DMRSyncPattern sync2 = mSyncTrackerTimeslot2.getSyncPattern();
|
||||
|
||||
if(sync2.isMobileStationSyncPattern() || sync2.isDirectModeTS1())
|
||||
{
|
||||
mBurstDetectListener.burstDetected(burst2, sync2, 1);
|
||||
}
|
||||
else if(sync2.isDirectModeTS2())
|
||||
{
|
||||
mBurstDetectListener.burstDetected(burst2, sync2, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
mBurstDetectListener.burstDetected(burst2, sync2, 0);
|
||||
}
|
||||
|
||||
mDibitCounter -= BURST_DIBIT_LENGTH;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -445,11 +445,18 @@ public class DMRDecoderState extends TimeslotDecoderState
|
||||
*/
|
||||
private void processVoice(VoiceMessage message)
|
||||
{
|
||||
if(message.getSyncPattern().isDirectMode())
|
||||
if(message.getSyncPattern().isMobileSyncPattern())
|
||||
{
|
||||
updateCurrentCall(DecodeEventType.CALL, "DIRECT MODE", message.getTimestamp());
|
||||
if(message.getSyncPattern().isDirectMode())
|
||||
{
|
||||
updateCurrentCall(DecodeEventType.CALL, "DIRECT MODE", message.getTimestamp());
|
||||
}
|
||||
else
|
||||
{
|
||||
updateCurrentCall(DecodeEventType.CALL, "REPEATER", message.getTimestamp());
|
||||
}
|
||||
|
||||
//Use the timeslot as the talkgroup identifier since DCDM mode doesn't use talkgroups
|
||||
//Use the timeslot as the talkgroup identifier since DCDM & simple repeater modes don't use talkgroups
|
||||
getIdentifierCollection().update(DMRTalkgroup.create(getTimeslot()));
|
||||
}
|
||||
else
|
||||
|
||||
@@ -153,10 +153,8 @@ public class DMRMessageProcessor implements Listener<IMessage>
|
||||
dispatch(message);
|
||||
|
||||
//Extract the Full Link Control message fragment from the Voice with embedded signalling message
|
||||
if(message instanceof VoiceEMBMessage)
|
||||
if(message instanceof VoiceEMBMessage voice)
|
||||
{
|
||||
VoiceEMBMessage voice = (VoiceEMBMessage)message;
|
||||
|
||||
if(message.getTimeslot() == 1)
|
||||
{
|
||||
FullLCMessage flco = mFLCAssemblerTimeslot1.process(voice.getEMB().getLCSS(),
|
||||
|
||||
@@ -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
|
||||
@@ -91,9 +91,17 @@ public enum DMRSyncPattern
|
||||
private static final EnumSet<DMRSyncPattern> CACH_PATTERNS = EnumSet.of(BASE_STATION_DATA, BASE_STATION_VOICE,
|
||||
BS_VOICE_FRAME_B, BS_VOICE_FRAME_C, BS_VOICE_FRAME_D, BS_VOICE_FRAME_E, BS_VOICE_FRAME_F);
|
||||
|
||||
//Direct Mode Sync Patterns
|
||||
private static final EnumSet<DMRSyncPattern> DIRECT_MODE_PATTERNS = EnumSet.of(DIRECT_MODE_DATA_TIMESLOT_1,
|
||||
DIRECT_MODE_DATA_TIMESLOT_2, DIRECT_MODE_VOICE_TIMESLOT_1, DIRECT_MODE_VOICE_TIMESLOT_2);
|
||||
//Direct Mode TS 1 Sync Patterns
|
||||
private static final EnumSet<DMRSyncPattern> DIRECT_MODE_TS1_PATTERNS = EnumSet.of(DIRECT_MODE_VOICE_TIMESLOT_1,
|
||||
DIRECT_MODE_DATA_TIMESLOT_1);
|
||||
|
||||
//Direct Mode TS 2 Sync Patterns
|
||||
private static final EnumSet<DMRSyncPattern> DIRECT_MODE_TS2_PATTERNS = EnumSet.of(DIRECT_MODE_VOICE_TIMESLOT_2,
|
||||
DIRECT_MODE_DATA_TIMESLOT_2);
|
||||
|
||||
//Mobile Station Sync Patterns
|
||||
private static final EnumSet<DMRSyncPattern> MOBILE_STATION_PATTERNS = EnumSet.of(MOBILE_STATION_DATA,
|
||||
MOBILE_STATION_VOICE, MS_VOICE_FRAME_B, MS_VOICE_FRAME_C, MS_VOICE_FRAME_D, MS_VOICE_FRAME_E, MS_VOICE_FRAME_F);
|
||||
|
||||
/**
|
||||
* Pattern that represents the enum entry
|
||||
@@ -140,7 +148,43 @@ public enum DMRSyncPattern
|
||||
*/
|
||||
public boolean isDirectMode()
|
||||
{
|
||||
return DIRECT_MODE_PATTERNS.contains(this);
|
||||
return isDirectModeTS1() || isDirectModeTS2();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this is Direct Mode sync pattern for timestot 1
|
||||
* @return true if DMTS1
|
||||
*/
|
||||
public boolean isDirectModeTS1()
|
||||
{
|
||||
return DIRECT_MODE_TS1_PATTERNS.contains(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this is Direct Mode sync pattern for timestot 2
|
||||
* @return true if DMTS2
|
||||
*/
|
||||
public boolean isDirectModeTS2()
|
||||
{
|
||||
return DIRECT_MODE_TS2_PATTERNS.contains(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this is a mobile station sync pattern
|
||||
* @return true if a mobile station sync pattern.
|
||||
*/
|
||||
public boolean isMobileStationSyncPattern()
|
||||
{
|
||||
return MOBILE_STATION_PATTERNS.contains(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this is a mobile sync pattern, either mobile station or direct mode.
|
||||
* @return true if a mobile sync pattern.
|
||||
*/
|
||||
public boolean isMobileSyncPattern()
|
||||
{
|
||||
return isMobileStationSyncPattern() || isDirectMode();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -48,15 +48,13 @@ public class VoiceAMessage extends VoiceMessage
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if(getSyncPattern().isDirectMode())
|
||||
if(!getSyncPattern().isMobileSyncPattern())
|
||||
{
|
||||
sb.append(getSyncPattern());
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append("CC:- ").append(getSyncPattern());
|
||||
sb.append("CC:- ");
|
||||
}
|
||||
|
||||
sb.append(getSyncPattern());
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ public class VoiceEMBMessage extends VoiceMessage
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if(getEMB().isValid())
|
||||
if(!getSyncPattern().isMobileSyncPattern() && getEMB().isValid())
|
||||
{
|
||||
sb.append("CC:").append(getEMB().getColorCode()).append(" ");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user