#2494 P25P1 and NXDN Decoder Enhancements. (#2514)

- Updates P25P1 C4FM decoder to use same pattern developed for NXDN.
- Both share the C4FM symbol processor and equalizer.
- P25P1 updated with Garner style timing error detector
- NXDN filters updated to use a combined RRC and inverse sync filter all in one.
- P25P1 replaces RRC with band limiting filter
- P25P1 enhanced with dynamic PLL balance updates to combat multi-path fading, in addition to the sync detection training window.
- Decoder PPM error reports now only sent after 2x consecutive sync detections to prevent tuner PPM corrections from noisy/isolated false sync detects.
- Soft error correction added to both P25P1 and IDEN.

Co-authored-by: denny <dennis.sheirer@gmail.com>
This commit is contained in:
Denny Sheirer
2026-10-25 09:44:50 -04:00
committed by GitHub
parent df739f525f
commit 5635341d12
51 changed files with 4035 additions and 1504 deletions

View File

@@ -39,7 +39,7 @@ public class SourceConfigTunerMultipleFrequency extends SourceConfiguration
private List<Long> mFrequencies = new ArrayList<>();
private String mPreferredTuner;
private Long mPreferredFrequency;
private int mFrequencyRotationDelay = ChannelRotationMonitor.CHANNEL_ROTATION_DELAY_MINIMUM;
private int mFrequencyRotationDelay = ChannelRotationMonitor.CHANNEL_ROTATION_DELAY_DEFAULT;
public SourceConfigTunerMultipleFrequency()
{

View File

@@ -45,7 +45,7 @@ public class ChannelRotationMonitor extends Module implements ISourceEventProvid
Listener<DecoderStateEvent>
{
public static final int CHANNEL_ROTATION_DELAY_MINIMUM = 200;
public static final int CHANNEL_ROTATION_DELAY_DEFAULT = 500;
public static final int CHANNEL_ROTATION_DELAY_DEFAULT = 1000;
public static final int CHANNEL_ROTATION_DELAY_MAXIMUM = 2000;
private final static Logger mLog = LoggerFactory.getLogger(ChannelRotationMonitor.class);

View File

@@ -36,8 +36,9 @@ import java.util.concurrent.TimeUnit;
public class ChannelFrequencyErrorManager implements ISourceEventListener, Listener<SourceEvent>
{
private static final long MAXIMUM_CHANNEL_ERROR_CORRECTION_PER_INTERVAL = 10; //Hertz
private static final long TIMER_INTERVAL_MILLISECONDS = 500;
private final FloatAveragingBuffer mRequestedCorrectAveragingBuffer = new FloatAveragingBuffer(6, 2);
private static final long TIMER_INTERVAL_MILLISECONDS = 1000;
private static final float ERROR_PROCESSING_GAIN = 0.3f;
private final FloatAveragingBuffer mRequestedCorrectAveragingBuffer = new FloatAveragingBuffer(12, 2);
private final TunerChannelSource mTunerChannelSource;
private final TunerFrequencyErrorManager mParent;
private ScheduledFuture<?> mScheduledFuture;
@@ -135,7 +136,7 @@ public class ChannelFrequencyErrorManager implements ISourceEventListener, Liste
if(partialCorrection != 0)
{
mAppliedFrequencyCorrection += partialCorrection;
mAppliedFrequencyCorrection += (long)(partialCorrection * ERROR_PROCESSING_GAIN);
mTunerChannelSource.setFrequencyCorrection(mAppliedFrequencyCorrection);
mRequestedCorrectAveragingBuffer.reset();
}

View File

@@ -66,7 +66,7 @@ public class ComplexWaveSource extends Source implements IControllableFileSource
{
if(file == null || !file.exists() || !supports(file))
{
throw new IOException("Empty or null file");
throw new IOException("Empty or null file: " + file);
}
if(!supports(file))