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,7 +1,7 @@
/*
* ******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2018 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
@@ -21,6 +21,7 @@
package io.github.dsheirer.gui.preference;
import io.github.dsheirer.gui.preference.directory.DirectoryPreferenceEditor;
import io.github.dsheirer.gui.preference.tuner.ChannelMultipleFrequencyPreferenceEditor;
import io.github.dsheirer.gui.preference.tuner.TunerPreferenceEditor;
import io.github.dsheirer.preference.UserPreferences;
import javafx.scene.Node;
@@ -38,9 +39,11 @@ public class PreferenceEditorFactory
return new DecodeEventViewPreferenceEditor(userPreferences);
case DIRECTORY:
return new DirectoryPreferenceEditor(userPreferences);
case SOURCE_CHANNEL_MULTIPLE_FREQUENCY:
return new ChannelMultipleFrequencyPreferenceEditor(userPreferences);
case TALKGROUP_FORMAT:
return new TalkgroupFormatPreferenceEditor(userPreferences);
case TUNER:
case SOURCE_TUNER_CHANNELIZER:
return new TunerPreferenceEditor(userPreferences);
}

View File

@@ -1,7 +1,7 @@
/*
* ******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2018 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
@@ -27,8 +27,9 @@ public enum PreferenceEditorType
{
CHANNEL_EVENT("Channel Events"),
DIRECTORY("Directories"),
TALKGROUP_FORMAT("Talkgroups"),
TUNER("Tuners");
SOURCE_CHANNEL_MULTIPLE_FREQUENCY("Channel - Multiple Frequency"),
SOURCE_TUNER_CHANNELIZER("Tuner Channelizer"),
TALKGROUP_FORMAT("Talkgroups");
private String mLabel;

View File

@@ -1,7 +1,7 @@
/*
* ******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2018 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
@@ -201,7 +201,8 @@ public class PreferencesEditor extends Application
storageItem.setExpanded(true);
TreeItem<String> sourceItem = new TreeItem<>("Source");
sourceItem.getChildren().add(new TreeItem(PreferenceEditorType.TUNER));
sourceItem.getChildren().add(new TreeItem(PreferenceEditorType.SOURCE_CHANNEL_MULTIPLE_FREQUENCY));
sourceItem.getChildren().add(new TreeItem(PreferenceEditorType.SOURCE_TUNER_CHANNELIZER));
treeRoot.getChildren().add(sourceItem);
sourceItem.setExpanded(true);

View File

@@ -0,0 +1,123 @@
/*
* ******************************************************************************
* 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.gui.preference.tuner;
import io.github.dsheirer.preference.UserPreferences;
import io.github.dsheirer.preference.source.ChannelMultiFrequencyPreference;
import javafx.geometry.Insets;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Spinner;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
/**
* Preference settings for channel source configurations containing multiple frequencies
*/
public class ChannelMultipleFrequencyPreferenceEditor extends HBox
{
private static final String HELP_TEXT = "Rotation delay determines how long a decoder will wait before rotating " +
"to the next frequency in a list for a rotating control channel configuration.";
private static final Insets MARGINS = new Insets(5,5,5,5);
private ChannelMultiFrequencyPreference mChannelMultiFrequencyPreference;
private GridPane mEditorPane;
private Label mRotationDelayLabel;
private Spinner<Integer> mRotationDelaySpinner;
private Button mResetButton;
private Label mHelpText;
public ChannelMultipleFrequencyPreferenceEditor(UserPreferences userPreferences)
{
mChannelMultiFrequencyPreference = userPreferences.getChannelMultiFrequencyPreference();
getChildren().add(getEditorPane());
}
private GridPane getEditorPane()
{
if(mEditorPane == null)
{
mEditorPane = new GridPane();
GridPane.setMargin(getRotationDelaySpinner(), new Insets(5, 5, 5, 5));
mEditorPane.add(getRotationDelaySpinner(), 0, 0);
GridPane.setMargin(getRotationDelayLabel(), new Insets(5, 5, 5, 5));
mEditorPane.add(getRotationDelayLabel(), 1, 0);
GridPane.setMargin(getResetButton(), MARGINS);
mEditorPane.add(getResetButton(), 2, 0);
GridPane.setMargin(getHelpText(), MARGINS);
mEditorPane.add(getHelpText(), 0, 1, 3, 1);
}
return mEditorPane;
}
public Spinner<Integer> getRotationDelaySpinner()
{
if(mRotationDelaySpinner == null)
{
int currentDelay = (int)(mChannelMultiFrequencyPreference.getRotationDelay() / 1000);
mRotationDelaySpinner = new Spinner<>(1, 60, currentDelay, 1);
mRotationDelaySpinner.setEditable(true);
mRotationDelaySpinner.valueProperty().addListener((observable, oldValue, newValue) -> {
mChannelMultiFrequencyPreference.setRotationDelay(newValue * 1000);
});
}
return mRotationDelaySpinner;
}
public Label getRotationDelayLabel()
{
if(mRotationDelayLabel == null)
{
mRotationDelayLabel = new Label("Rotation Delay (seconds)");
}
return mRotationDelayLabel;
}
public Button getResetButton()
{
if(mResetButton == null)
{
mResetButton = new Button("Reset");
mResetButton.setOnAction(event -> {
mChannelMultiFrequencyPreference.resetRotationDelay();
int currentDelay = (int)(mChannelMultiFrequencyPreference.getRotationDelay() / 1000);
getRotationDelaySpinner().getValueFactory().setValue(currentDelay);
});
}
return mResetButton;
}
public Label getHelpText()
{
if(mHelpText == null)
{
mHelpText = new Label(HELP_TEXT);
mHelpText.setWrapText(true);
}
return mHelpText;
}
}

View File

@@ -1,7 +1,7 @@
/*
* ******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2018 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
@@ -21,8 +21,8 @@
package io.github.dsheirer.gui.preference.tuner;
import io.github.dsheirer.preference.UserPreferences;
import io.github.dsheirer.preference.tuner.ChannelizerType;
import io.github.dsheirer.preference.tuner.TunerPreference;
import io.github.dsheirer.preference.source.ChannelizerType;
import io.github.dsheirer.preference.source.TunerPreference;
import javafx.geometry.HPos;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;