Skip to content

Commit

Permalink
Support for:
Browse files Browse the repository at this point in the history
- Per channel turning on/off signal detection
- Per Source setting signal detection threshold or using auto detection
- Per conventional call signal/noise in JSON / Call Info
- Per conventional call freq_error in JSON / Call Info
  • Loading branch information
robotastic committed Mar 9, 2024
1 parent decc871 commit 673bbe3
Show file tree
Hide file tree
Showing 32 changed files with 135 additions and 84 deletions.
3 changes: 3 additions & 0 deletions docs/CONFIGURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ There is a list of available Plugins [here](./Plugins.md).
| gain || | number | The RF gain setting for the SDR. Use a program like GQRX to find a good value. |
| digitalRecorders | | | number | The number of Digital Recorders to have attached to this source. This is essentially the number of simultaneous calls you can record at the same time in the frequency range that this Source will be tuned to. It is limited by the CPU power of the machine. Some experimentation might be needed to find the appropriate number. *This is only required for Trunk systems. Channels in Conventional systems have dedicated recorders and do not need to be included here.* |
| analogRecorders | | | number | The number of Analog Recorder to have attached to this source. The same as Digital Recorders except for Analog Voice channels. *This is only required for Trunk systems. Channels in Conventional systems have dedicated recorders and do not need to be included here.* |
| signalDetectorThreshold | | | number | If set, a static threshold will be used for the Signal Detector on all conventional recorder. Otherwise, the threshold value for the noise floor will be automatically be determined. Only set this is you are having problems. The value is in dB, but is generally higher than the Squelch value because the power is measured differently |
| ppm | | 0 | number | The tuning error for the SDR in ppm (parts per million), as an alternative to `error` above. Use a program like GQRX to find an accurate value. |
| agc | | false | **true** / **false** | Whether or not to enable the SDR's automatic gain control (if supported). This is false by default. It is not recommended to set this as it often yields worse performance compared to a manual gain setting. |
| gainSettings | | | { "stageName": value} | Set the gain for any stage. The value for this setting should be passed as an object, where the key specifies the name of the gain stage and the value is the amount of gain, as an int. For example:<br /> ````"gainSettings": { "IF": 10, "BB": 11},```` |
Expand Down Expand Up @@ -495,6 +496,8 @@ This file allows for you to specify additional information about conventional ch
| Tag | | The Service Tag for the Talkgroup |
| Comment | | Use this field to capture comments about a talkgroup. It will be ignored by Trunk Recorder. |
| Enable | | Set to 'false' if you do not want this talkgroup/channel to created |
| Signal Detector | | Set to `false` if you do not want to use the Signal Detector for this channel. The Signal Detector scans a source's bandwidth and only enables a channel if a signal over a threshold is detected. If it not used, the channel will always be enabled and the Squelch will be running which uses more CPU. Default is `true`|
| Squelch | | Value in dB to use for the Squelch for this channel. If this is not set then the System Squelch value will be used instead. |


The **Enable** Column is optional and defaults to *True*. It only needs to be added to rows that you do not want to have recorded. For those rows, set **Enable** to *False*.
Expand Down
1 change: 1 addition & 0 deletions trunk-recorder/call.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ class Call {
virtual bool get_duplex() = 0;
virtual double get_signal() = 0;
virtual double get_noise() = 0;
virtual int get_freq_error() = 0;
virtual void set_signal(double s) = 0;
virtual void set_noise(double n) = 0;
virtual std::string get_talkgroup_display() = 0;
Expand Down
8 changes: 8 additions & 0 deletions trunk-recorder/call_concluder/call_concluder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ int create_call_json(Call_Data_t& call_info) {
nlohmann::ordered_json json_data =
{
{"freq", int(call_info.freq)},
{"freq_error", int(call_info.freq_error)},
{"signal", int(call_info.signal)},
{"noise", int(call_info.noise)},
{"tdma_slot", int(call_info.tdma_slot)},
{"phase2_tdma", int(call_info.phase2_tdma)},
{"start_time", call_info.start_time},
{"stop_time", call_info.stop_time},
{"emergency", int(call_info.emergency)},
Expand Down Expand Up @@ -298,6 +303,9 @@ Call_Data_t Call_Concluder::create_call_data(Call *call, System *sys, Config con
call_info.error_count = 0;
call_info.spike_count = 0;
call_info.freq = call->get_freq();
call_info.freq_error = call->get_freq_error();
call_info.signal = call->get_signal();
call_info.noise = call->get_noise();
call_info.encrypted = call->get_encrypted();
call_info.emergency = call->get_emergency();
call_info.priority = call->get_priority();
Expand Down
12 changes: 9 additions & 3 deletions trunk-recorder/call_conventional.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@
#include "recorders/recorder.h"
#include <boost/algorithm/string.hpp>

Call_conventional::Call_conventional(long t, double f, System *s, Config c, double squelch_db) : Call_impl(t, f, s, c) {
Call_conventional::Call_conventional(long t, double f, System *s, Config c, double squelch_db, bool signal_detection) : Call_impl(t, f, s, c) {
this->squelch_db = squelch_db;
this->signal_detection = signal_detection;
BOOST_LOG_TRIVIAL(info) << "[" << sys->get_short_name() << "]\tFreq: " << format_freq(f) << "\tSquelch: " << squelch_db << " dB\tSignal Detection: " << signal_detection;
}

void Call_conventional::restart_call() {
call_num = call_counter++;
idle_count = 0;
signal = 999;
noise = 999;
signal = DB_UNSET;
noise = DB_UNSET;
curr_src_id = -1;
start_time = time(NULL);
stop_time = time(NULL);
Expand Down Expand Up @@ -43,4 +45,8 @@ void Call_conventional::recording_started() {

double Call_conventional::get_squelch_db() {
return squelch_db;
}

bool Call_conventional::get_signal_detection() {
return signal_detection;
}
4 changes: 3 additions & 1 deletion trunk-recorder/call_conventional.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,17 @@ class Recorder;

class Call_conventional : public Call_impl {
public:
Call_conventional(long t, double f, System *s, Config c, double squelch_db);
Call_conventional(long t, double f, System *s, Config c, double squelch_db, bool signal_detection);
time_t get_start_time();
bool is_conventional() { return true; }
void restart_call();
void set_recorder(Recorder *r);
void recording_started();
double get_squelch_db();
bool get_signal_detection();
private:
double squelch_db;
bool signal_detection;
};

#endif
15 changes: 11 additions & 4 deletions trunk-recorder/call_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,12 @@ Call *Call::make(TrunkMessage message, System *s, Config c) {
Call_impl::Call_impl(long t, double f, System *s, Config c) {
config = c;
call_num = call_counter++;
noise = 999;
signal = 999;
noise =
signal = DB_UNSET;
final_length = 0;
idle_count = 0;
curr_freq = 0;
freq_error = 0;
curr_src_id = -1;
talkgroup = t;
sys = s;
Expand Down Expand Up @@ -62,12 +63,13 @@ Call_impl::Call_impl(long t, double f, System *s, Config c) {
Call_impl::Call_impl(TrunkMessage message, System *s, Config c) {
config = c;
call_num = call_counter++;
noise = 999;
signal = 999;
noise = DB_UNSET;
signal = DB_UNSET;
final_length = 0;
idle_count = 0;
curr_src_id = -1;
curr_freq = 0;
freq_error = 0;
talkgroup = message.talkgroup;
sys = s;
start_time = time(NULL);
Expand Down Expand Up @@ -146,6 +148,7 @@ void Call_impl::conclude_call() {
if (was_update) {
BOOST_LOG_TRIVIAL(info) << "[" << sys->get_short_name() << "]\t\033[0;34m" << this->get_call_num() << "C\033[0m\tTG: " << this->get_talkgroup_display() << "\tFreq: " << format_freq(get_freq()) << "\t\u001b[33mCall was UPDATE not GRANT\u001b[0m";
}
freq_error = this->get_recorder()->get_freq_error();
this->get_recorder()->stop();
transmission_list = this->get_recorder()->get_transmission_list();
if (this->get_sigmf_recording() == true) {
Expand Down Expand Up @@ -189,6 +192,10 @@ double Call_impl::get_freq() {
return curr_freq;
}

int Call_impl::get_freq_error() {
return freq_error;
}

double Call_impl::get_final_length() {
return final_length;
}
Expand Down
2 changes: 2 additions & 0 deletions trunk-recorder/call_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ class Call_impl : public Call {
bool get_duplex();
double get_signal();
double get_noise();
int get_freq_error();
void set_signal(double s);
void set_noise(double n);
std::string get_talkgroup_display();
Expand All @@ -102,6 +103,7 @@ class Call_impl : public Call {
double curr_freq;
double noise;
double signal;
int freq_error;
std::vector<Transmission> transmission_list;
System *sys;
std::string short_name;
Expand Down
4 changes: 4 additions & 0 deletions trunk-recorder/config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,10 @@ bool load_config(string config_file, Config &config, gr::top_block_sptr &tb, std
source->set_gain_mode(agc);
}

if (element.contains("signalDetectorThreshold")) {
source->set_signal_detector_threshold(element["signalDetectorThreshold"]);
}

if (element.contains("gainSettings")) {
for (auto it = element["gainSettings"].begin(); it != element["gainSettings"].end(); ++it) {

Expand Down
5 changes: 5 additions & 0 deletions trunk-recorder/global_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include <vector>
#include <json.hpp>

const int DB_UNSET = 999;

struct Transmission {
long source;
long start_time;
Expand Down Expand Up @@ -96,6 +98,9 @@ struct Call_Data_t {
std::string talkgroup_group;
long call_num;
double freq;
int freq_error;
double signal;
double noise;
long start_time;
long stop_time;
long error_count;
Expand Down
12 changes: 3 additions & 9 deletions trunk-recorder/gr_blocks/channelizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ channelizer::channelizer(double input_rate, int samples_per_symbol, double symbo
double resampled_rate;

const float pi = M_PI;
valve = gr::blocks::copy::make(sizeof(gr_complex));
valve->set_enabled(false);

lo = gr::analog::sig_source_c::make(d_input_rate, gr::analog::GR_SIN_WAVE, 0, 1.0, 0.0);
mixer = gr::blocks::multiply_cc::make();
Expand Down Expand Up @@ -147,13 +145,13 @@ channelizer::channelizer(double input_rate, int samples_per_symbol, double symbo
rms_agc = gr::blocks::rms_agc::make(0.45, 0.85);
fll_band_edge = gr::digital::fll_band_edge_cc::make(sps, def_excess_bw, 2 * sps + 1, (2.0 * pi) / sps / 250); // OP25 has this set to 350 instead of 250

connect(self(), 0, valve, 0);

if (double_decim) {
connect(valve, 0, bandpass_filter, 0);
connect(self(), 0, bandpass_filter, 0);
connect(bandpass_filter, 0, mixer, 0);
connect(bfo, 0, mixer, 1);
} else {
connect(valve, 0, mixer, 0);
connect(self(), 0, mixer, 0);
connect(lo, 0, mixer, 1);
}
connect(mixer, 0, lowpass_filter, 0);
Expand Down Expand Up @@ -218,10 +216,6 @@ void channelizer::tune_offset(double f) {
}
}

void channelizer::set_enabled(bool enabled) {
valve->set_enabled(enabled);
}

void channelizer::set_squelch_db(double squelch_db) {
squelch->set_threshold(squelch_db);
}
Expand Down
3 changes: 0 additions & 3 deletions trunk-recorder/gr_blocks/channelizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ class channelizer : public gr::hier_block2 {
std::vector<float> cutoff_filter_coeffs;

gr::analog::pwr_squelch_cc::sptr squelch;
gr::blocks::copy::sptr valve;
gr::digital::fll_band_edge_cc::sptr fll_band_edge;
gr::blocks::rms_agc::sptr rms_agc;

Expand Down Expand Up @@ -88,12 +87,10 @@ class channelizer : public gr::hier_block2 {
static constexpr double smartnet_symbol_rate = 3600;

int get_freq_error();
bool is_enabled();
bool is_squelched();
double get_pwr();
void tune_offset(double f);
void set_samples_per_symbol(int samples_per_symbol);
void set_enabled(bool enabled);
void set_squelch_db(double squelch_db);
void set_analog_squelch(bool analog_squelch);
};
Expand Down
1 change: 1 addition & 0 deletions trunk-recorder/gr_blocks/signal_detector_cvf_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ class signal_detector_cvf_impl : public signal_detector_cvf {
void set_window_type(int d_window);

void set_threshold(float d_threshold) {
d_auto_threshold = false;
signal_detector_cvf_impl::d_threshold = d_threshold;
}

Expand Down
15 changes: 1 addition & 14 deletions trunk-recorder/gr_blocks/xlat_channelizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ xlat_channelizer::xlat_channelizer(double input_rate, int samples_per_symbol, do
// long if_rate = 12500;

const float pi = M_PI;
valve = gr::blocks::copy::make(sizeof(gr_complex));
valve->set_enabled(false);

int decimation = floor(input_rate / channel_rate);
double resampled_rate = float(input_rate) / float(decimation);
Expand Down Expand Up @@ -126,9 +124,6 @@ xlat_channelizer::xlat_channelizer(double input_rate, int samples_per_symbol, do
rms_agc = gr::blocks::rms_agc::make(0.45, 0.85);
fll_band_edge = gr::digital::fll_band_edge_cc::make(sps, def_excess_bw, 2 * sps + 1, (2.0 * pi) / sps / 250); // OP25 has this set to 350 instead of 250

/*
connect(self(), 0, valve, 0);
connect(valve, 0, freq_xlat, 0);*/
connect(self(), 0, freq_xlat, 0);

if (d_conventional) {
Expand Down Expand Up @@ -167,7 +162,7 @@ double xlat_channelizer::get_pwr() {
if (d_conventional) {
return squelch->get_pwr();
} else {
return 999;
return DB_UNSET;
}
}

Expand All @@ -179,14 +174,6 @@ void xlat_channelizer::tune_offset(double f) {
freq_xlat->set_center_freq(-freq);
}

bool xlat_channelizer::is_enabled() {
return valve->enabled();
}

void xlat_channelizer::set_enabled(bool enabled) {
valve->set_enabled(enabled);
}

void xlat_channelizer::set_squelch_db(double squelch_db) {
squelch->set_threshold(squelch_db);
}
Expand Down
4 changes: 1 addition & 3 deletions trunk-recorder/gr_blocks/xlat_channelizer.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#endif

#include "../formatter.h"
#include "../global_structs.h"

class xlat_channelizer : public gr::hier_block2 {
public:
Expand All @@ -54,12 +55,10 @@ class xlat_channelizer : public gr::hier_block2 {
static constexpr double smartnet_symbol_rate = 3600;

int get_freq_error();
bool is_enabled();
bool is_squelched();
double get_pwr();
void tune_offset(double f);
void set_samples_per_symbol(int samples_per_symbol);
void set_enabled(bool enabled);
void set_squelch_db(double squelch_db);
void set_analog_squelch(bool analog_squelch);

Expand All @@ -86,7 +85,6 @@ class xlat_channelizer : public gr::hier_block2 {
std::vector<float> cutoff_filter_coeffs;

gr::analog::pwr_squelch_cc::sptr squelch;
gr::blocks::copy::sptr valve;
gr::digital::fll_band_edge_cc::sptr fll_band_edge;
gr::blocks::rms_agc::sptr rms_agc;

Expand Down
19 changes: 15 additions & 4 deletions trunk-recorder/recorders/analog_recorder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,10 @@ double analog_recorder::get_freq() {
return chan_freq;
}

int analog_recorder::get_freq_error() { // get frequency error from FLL and convert to Hz
return prefilter->get_freq_error();
}

void analog_recorder::set_source(long src) {
wav_sink->set_source(src);
}
Expand Down Expand Up @@ -350,9 +354,8 @@ bool analog_recorder::start(Call *call) {
talkgroup = call->get_talkgroup();
chan_freq = call->get_freq();

Call_conventional *conventional_call = dynamic_cast<Call_conventional *>(call);
squelch_db = conventional_call->get_squelch_db();
prefilter->set_squelch_db(squelch_db);


BOOST_LOG_TRIVIAL(info) << "[" << call->get_short_name() << "]\t\033[0;34m" << call->get_call_num() << "C\033[0m\tTG: " << this->call->get_talkgroup_display() << "\tFreq: " << format_freq(chan_freq) << "\t\u001b[32mStarting Analog Recorder Num [" << rec_num << "]\u001b[0m \tSquelch: " << squelch_db;

// BOOST_LOG_TRIVIAL(error) << "Setting squelch to: " << squelch_db << " block says: " << squelch->threshold();
Expand All @@ -371,10 +374,18 @@ bool analog_recorder::start(Call *call) {

state = ACTIVE;
if (conventional) {
set_enabled(false);
Call_conventional *conventional_call = dynamic_cast<Call_conventional *>(call);
squelch_db = conventional_call->get_squelch_db();
if (conventional_call->get_signal_detection()) {
set_enabled(false);
} else {
set_enabled(true); // If signal detection is not being used, open up the Value/Selector from the start
}
} else {
squelch_db = system->get_squelch_db();
set_enabled(true);
}
prefilter->set_squelch_db(squelch_db);
return true;
}

Expand Down
1 change: 1 addition & 0 deletions trunk-recorder/recorders/analog_recorder.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ class analog_recorder : public gr::hier_block2, public Recorder {
bool start(Call *call);
void stop();
double get_freq();
int get_freq_error();
void set_source(long src);
Source *get_source();
long get_talkgroup();
Expand Down
1 change: 1 addition & 0 deletions trunk-recorder/recorders/dmr_recorder.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class dmr_recorder : virtual public gr::hier_block2, virtual public Recorder {
virtual bool start(Call *call) = 0;
virtual void stop() = 0;
virtual double get_freq() = 0;
virtual int get_freq_error() = 0;
virtual int get_num() = 0;
virtual void set_tdma(bool phase2) = 0;
virtual void switch_tdma(bool phase2) = 0;
Expand Down
Loading

0 comments on commit 673bbe3

Please sign in to comment.