61 Rotating Control Channel Support - P25 Decoder (#475)

* Initial work on add support for rotating control channels.

* Creates multiple frequency editor control.

* Updates channel source editor to allow user to select multi-frequency
configuration and add multiple frequencies.

* Adds full support for rotating control channels to the P25 channelizer.
Users define multiple frequencies in the channel source configuration.
The decoder monitors the state of the channel for a CONTROL state.  If
the state does not stay in the CONTROL state for a user-specified delay
value, then the decoder rotates to the next frequency in the list.  This
behavior continues until the decoder state once again changes to CONTROL.

This is NOT a 'scanner' feature.
This commit is contained in:
Denny Sheirer
2019-01-06 06:59:04 -05:00
committed by GitHub
parent 3a39ae76ba
commit 5481fb7d4d
44 changed files with 2502 additions and 634 deletions

View File

@@ -1,19 +1,17 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* sdr-trunk
* Copyright (C) 2014-2018 Dennis Sheirer
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.
* If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************/
package io.github.dsheirer.source.config;
@@ -21,64 +19,74 @@ import io.github.dsheirer.source.SourceType;
public class SourceConfigFactory
{
public static SourceConfiguration getDefaultSourceConfiguration()
{
return getSourceConfiguration( SourceType.TUNER );
}
public static SourceConfiguration getSourceConfiguration( SourceType source )
{
SourceConfiguration retVal;
public static SourceConfiguration getDefaultSourceConfiguration()
{
return getSourceConfiguration(SourceType.TUNER);
}
switch( source )
{
case TUNER:
retVal = new SourceConfigTuner();
break;
case MIXER:
retVal = new SourceConfigMixer();
break;
case NONE:
default:
retVal = new SourceConfigNone();
break;
}
return retVal;
}
public static SourceConfiguration getSourceConfiguration(SourceType source)
{
SourceConfiguration retVal;
/**
* Creates a copy of the configuration
*/
public static SourceConfiguration copy( SourceConfiguration config )
{
if( config != null )
{
switch( config.getSourceType() )
{
case MIXER:
SourceConfigMixer originalMixer = (SourceConfigMixer)config;
SourceConfigMixer copyMixer = new SourceConfigMixer();
copyMixer.setChannel( originalMixer.getChannel() );
copyMixer.setMixer( originalMixer.getMixer() );
return copyMixer;
case RECORDING:
SourceConfigRecording originalRec = (SourceConfigRecording)config;
SourceConfigRecording copyRec = new SourceConfigRecording();
copyRec.setFrequency( originalRec.getFrequency() );
copyRec.setRecordingAlias( originalRec.getRecordingAlias() );
return copyRec;
case TUNER:
SourceConfigTuner originalTuner = (SourceConfigTuner)config;
SourceConfigTuner copyTuner = new SourceConfigTuner();
copyTuner.setFrequency( originalTuner.getFrequency() );
return copyTuner;
case NONE:
default:
return new SourceConfigNone();
}
}
return null;
}
switch(source)
{
case TUNER:
retVal = new SourceConfigTuner();
break;
case TUNER_MULTIPLE_FREQUENCIES:
retVal = new SourceConfigTunerMultipleFrequency();
break;
case MIXER:
retVal = new SourceConfigMixer();
break;
case NONE:
default:
retVal = new SourceConfigNone();
break;
}
return retVal;
}
/**
* Creates a copy of the configuration
*/
public static SourceConfiguration copy(SourceConfiguration config)
{
if(config != null)
{
switch(config.getSourceType())
{
case MIXER:
SourceConfigMixer originalMixer = (SourceConfigMixer) config;
SourceConfigMixer copyMixer = new SourceConfigMixer();
copyMixer.setChannel(originalMixer.getChannel());
copyMixer.setMixer(originalMixer.getMixer());
return copyMixer;
case RECORDING:
SourceConfigRecording originalRec = (SourceConfigRecording) config;
SourceConfigRecording copyRec = new SourceConfigRecording();
copyRec.setFrequency(originalRec.getFrequency());
copyRec.setRecordingAlias(originalRec.getRecordingAlias());
return copyRec;
case TUNER:
SourceConfigTuner originalTuner = (SourceConfigTuner) config;
SourceConfigTuner copyTuner = new SourceConfigTuner();
copyTuner.setPreferredTuner(originalTuner.getPreferredTuner());
copyTuner.setFrequency(originalTuner.getFrequency());
return copyTuner;
case TUNER_MULTIPLE_FREQUENCIES:
SourceConfigTunerMultipleFrequency originalMulti = (SourceConfigTunerMultipleFrequency) config;
SourceConfigTunerMultipleFrequency copyMulti = new SourceConfigTunerMultipleFrequency();
copyMulti.setPreferredTuner(originalMulti.getPreferredTuner());
copyMulti.setFrequencies(originalMulti.getFrequencies());
return copyMulti;
case NONE:
default:
return new SourceConfigNone();
}
}
return null;
}
}

View File

@@ -1,20 +1,22 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014-2018 Dennis Sheirer
/*
* ******************************************************************************
* sdrtrunk
* 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 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.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
******************************************************************************/
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* *****************************************************************************
*/
package io.github.dsheirer.source.config;
import com.fasterxml.jackson.annotation.JsonIgnore;
@@ -31,7 +33,6 @@ public class SourceConfigTuner extends SourceConfiguration
private static DecimalFormat FREQUENCY_FORMAT = new DecimalFormat("0.00000");
private long mFrequency = 0;
private int mBandwidth = 12500;
private String mPreferredTuner;
public SourceConfigTuner()
@@ -42,9 +43,7 @@ public class SourceConfigTuner extends SourceConfiguration
public SourceConfigTuner(TunerChannel tunerChannel)
{
this();
mFrequency = tunerChannel.getFrequency();
mBandwidth = tunerChannel.getBandwidth();
}
@JacksonXmlProperty(isAttribute = true, localName = "frequency")
@@ -94,8 +93,8 @@ public class SourceConfigTuner extends SourceConfiguration
}
@JsonIgnore
public TunerChannel getTunerChannel()
public TunerChannel getTunerChannel(int bandwidth)
{
return new TunerChannel(mFrequency, mBandwidth);
return new TunerChannel(mFrequency, bandwidth);
}
}

View File

@@ -0,0 +1,127 @@
/*
* ******************************************************************************
* sdrtrunk
* 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 <http://www.gnu.org/licenses/>
* *****************************************************************************
*/
package io.github.dsheirer.source.config;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import io.github.dsheirer.source.SourceType;
import io.github.dsheirer.source.tuner.channel.TunerChannel;
import java.util.ArrayList;
import java.util.List;
/**
* Multiple frequency tuner source configuration is used for a system with a rolling/rotating control
* channel where the control channel rotates across a pre-defined set of channel frequencies.
*/
@JsonSubTypes.Type(value = SourceConfigTunerMultipleFrequency.class, name = "sourceConfigTunerMultipleFrequency")
public class SourceConfigTunerMultipleFrequency extends SourceConfiguration
{
private List<Long> mFrequencies = new ArrayList<>();
private String mPreferredTuner;
public SourceConfigTunerMultipleFrequency()
{
super(SourceType.TUNER_MULTIPLE_FREQUENCIES);
}
/**
* List of frequencies for this configuration
*/
@JacksonXmlProperty(isAttribute = false, localName = "frequency")
public List<Long> getFrequencies()
{
return mFrequencies;
}
/**
* Sets the list of frequencies for this configuration
*/
public void setFrequencies(List<Long> frequencies)
{
mFrequencies = frequencies;
}
/**
* Indicates if this configuration has more than one frequency specified
*/
@JsonIgnore
public boolean hasMultipleFrequencies()
{
return mFrequencies.size() > 1;
}
/**
* Adds a frequency to the list
*/
public void addFrequency(long frequency)
{
mFrequencies.add(frequency);
}
/**
* Preferred tuner to use for this configuration.
* @return tuner name or null
*/
@JacksonXmlProperty(isAttribute = true, localName = "preferred_tuner")
public String getPreferredTuner()
{
return mPreferredTuner;
}
/**
* Indicates if this configuration has a specified preferred tuner
*/
@JsonIgnore
public boolean hasPreferredTuner()
{
return mPreferredTuner != null;
}
/**
* Specifies the preferred tuner to use for this configuration
* @param preferredTuner to use, if available
*/
public void setPreferredTuner(String preferredTuner)
{
mPreferredTuner = preferredTuner;
}
@JsonIgnore
@Override
public String getDescription()
{
return "Frequencies [" + mFrequencies.size() + "]";
}
@JsonIgnore
public TunerChannel getFirstTunerChannel(int bandwidth)
{
if(getFrequencies().size() > 0)
{
return new TunerChannel(getFrequencies().get(0), bandwidth);
}
else
{
return new TunerChannel(0l, bandwidth);
}
}
}

View File

@@ -30,7 +30,7 @@ import io.github.dsheirer.source.SourceType;
@JsonSubTypes.Type(value = SourceConfigNone.class, name = "sourceConfigNone"),
@JsonSubTypes.Type(value = SourceConfigRecording.class, name = "sourceConfigRecording"),
@JsonSubTypes.Type(value = SourceConfigTuner.class, name = "sourceConfigTuner"),
})
@JsonSubTypes.Type(value = SourceConfigTunerMultipleFrequency.class, name = "sourceConfigTunerMultipleFrequency")})
@JacksonXmlRootElement(localName = "source_configuration")
public class SourceConfiguration extends Configuration
{