aboutsummaryrefslogtreecommitdiffstats
path: root/src/anetz
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2017-10-09 20:49:14 +0200
committerAndreas Eversberg <jolly@eversberg.eu>2017-10-22 19:23:08 +0200
commitb32e0ab6025a025850dc0079fa6596a96d7295a6 (patch)
tree199098e532a80417d5a3a18e80172280ccb84cad /src/anetz
parentf7a0e4622bed9551bb0999d3c54bb69249065d38 (diff)
Implementation of RX level squelch (for A-Netz and B-Netz)
Use -S <dB> for setting RF level or use -S auto for auto level. When squelch closes, audio is muted. If squelch is closed for some seconds (depending on network), call is released. (RF loss condition) The previous loss detection has been removed
Diffstat (limited to 'src/anetz')
-rw-r--r--src/anetz/anetz.c10
-rw-r--r--src/anetz/anetz.h6
-rw-r--r--src/anetz/dsp.c32
-rw-r--r--src/anetz/dsp.h2
-rw-r--r--src/anetz/main.c23
5 files changed, 44 insertions, 29 deletions
diff --git a/src/anetz/anetz.c b/src/anetz/anetz.c
index 1d58efe..27eb1b0 100644
--- a/src/anetz/anetz.c
+++ b/src/anetz/anetz.c
@@ -186,7 +186,7 @@ static void anetz_timeout(struct timer *timer);
static void anetz_go_idle(anetz_t *anetz);
/* Create transceiver instance and link to a list. */
-int anetz_create(int kanal, const char *audiodev, int use_sdr, int samplerate, double rx_gain, double page_gain, int page_sequence, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, const char *read_tx_wave, int loopback, double loss_volume)
+int anetz_create(int kanal, const char *audiodev, int use_sdr, int samplerate, double rx_gain, double page_gain, int page_sequence, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, const char *read_tx_wave, int loopback, double squelch_db)
{
anetz_t *anetz;
int rc;
@@ -205,14 +205,14 @@ int anetz_create(int kanal, const char *audiodev, int use_sdr, int samplerate, d
PDEBUG(DANETZ, DEBUG_DEBUG, "Creating 'A-Netz' instance for 'Kanal' = %d (sample rate %d).\n", kanal, samplerate);
/* init general part of transceiver */
- rc = sender_create(&anetz->sender, kanal, anetz_kanal2freq(kanal, 0), anetz_kanal2freq(kanal, 1), audiodev, use_sdr, samplerate, rx_gain, pre_emphasis, de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, read_tx_wave, loopback, loss_volume, PAGING_SIGNAL_NONE);
+ rc = sender_create(&anetz->sender, kanal, anetz_kanal2freq(kanal, 0), anetz_kanal2freq(kanal, 1), audiodev, use_sdr, samplerate, rx_gain, pre_emphasis, de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, read_tx_wave, loopback, PAGING_SIGNAL_NONE);
if (rc < 0) {
PDEBUG(DANETZ, DEBUG_ERROR, "Failed to init 'Sender' processing!\n");
goto error;
}
/* init audio processing */
- rc = dsp_init_sender(anetz, page_gain, page_sequence);
+ rc = dsp_init_sender(anetz, page_gain, page_sequence, squelch_db);
if (rc < 0) {
PDEBUG(DANETZ, DEBUG_ERROR, "Failed to init signal processing!\n");
goto error;
@@ -282,10 +282,10 @@ static void anetz_page(anetz_t *anetz, const char *dial_string, double *freq)
}
/* Loss of signal was detected, release active call. */
-void anetz_loss_indication(anetz_t *anetz)
+void anetz_loss_indication(anetz_t *anetz, double loss_time)
{
if (anetz->state == ANETZ_GESPRAECH) {
- PDEBUG_CHAN(DANETZ, DEBUG_NOTICE, "Detected loss of signal, releasing.\n");
+ PDEBUG_CHAN(DANETZ, DEBUG_NOTICE, "Detected loss of signal after %.1f seconds, releasing.\n", loss_time);
anetz_release(anetz);
call_in_release(anetz->callref, CAUSE_TEMPFAIL);
anetz->callref = 0;
diff --git a/src/anetz/anetz.h b/src/anetz/anetz.h
index b43c5be..7f0cac5 100644
--- a/src/anetz/anetz.h
+++ b/src/anetz/anetz.h
@@ -1,3 +1,4 @@
+#include "../common/squelch.h"
#include "../common/goertzel.h"
#include "../common/sender.h"
@@ -46,13 +47,14 @@ typedef struct anetz {
int paging_tone; /* current tone (0..3) in sequenced mode */
int paging_count; /* current sample count of tone in seq. mode */
int paging_transition; /* set to number of samples during transition */
+ squelch_t squelch; /* squelch detection process */
} anetz_t;
double anetz_kanal2freq(int kanal, int unterband);
int anetz_init(void);
-int anetz_create(int kanal, const char *audiodev, int use_sdr, int samplerate, double rx_gain, double page_gain, int page_sequence, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, const char *read_tx_wave, int loopback, double loss_volume);
+int anetz_create(int kanal, const char *audiodev, int use_sdr, int samplerate, double rx_gain, double page_gain, int page_sequence, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, const char *read_tx_wave, int loopback, double squelch_db);
void anetz_destroy(sender_t *sender);
-void anetz_loss_indication(anetz_t *anetz);
+void anetz_loss_indication(anetz_t *anetz, double loss_time);
void anetz_receive_tone(anetz_t *anetz, int bit);
diff --git a/src/anetz/dsp.c b/src/anetz/dsp.c
index 266f4d6..4d60110 100644
--- a/src/anetz/dsp.c
+++ b/src/anetz/dsp.c
@@ -49,8 +49,8 @@
#define TONE_DETECT_TH 8 /* chunk intervals to detect continuous tone */
/* carrier loss detection */
-#define LOSS_INTERVAL 100 /* filter steps (chunk durations) for one second interval */
-#define LOSS_TIME 12 /* duration of signal loss before release */
+#define MUTE_TIME 0.1 /* time to mute after loosing signal */
+#define LOSS_TIME 12.0 /* duration of signal loss before release (what was the actual duration ???) */
/* two signaling tones */
static double fsk_tones[2] = {
@@ -77,7 +77,7 @@ void dsp_init(void)
}
/* Init transceiver instance. */
-int dsp_init_sender(anetz_t *anetz, double page_gain, int page_sequence)
+int dsp_init_sender(anetz_t *anetz, double page_gain, int page_sequence, double squelch_db)
{
sample_t *spl;
int i;
@@ -85,14 +85,15 @@ int dsp_init_sender(anetz_t *anetz, double page_gain, int page_sequence)
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init DSP for 'Sender'.\n");
+ /* init squelch */
+ squelch_init(&anetz->squelch, anetz->sender.kanal, squelch_db, MUTE_TIME, LOSS_TIME);
+
/* set modulation parameters */
sender_set_fm(&anetz->sender, MAX_DEVIATION * page_gain, MAX_MODULATION, DBM0_DEVIATION, MAX_DISPLAY);
anetz->page_gain = page_gain;
anetz->page_sequence = page_sequence;
- audio_init_loss(&anetz->sender.loss, LOSS_INTERVAL, anetz->sender.loss_volume, LOSS_TIME);
-
anetz->samples_per_chunk = anetz->sender.samplerate * CHUNK_DURATION;
PDEBUG(DDSP, DEBUG_DEBUG, "Using %d samples per chunk duration.\n", anetz->samples_per_chunk);
spl = calloc(anetz->samples_per_chunk, sizeof(sample_t));
@@ -147,24 +148,19 @@ static void fsk_receive_tone(anetz_t *anetz, int tone, int goodtone, double leve
anetz->tone_count++;
- if (anetz->tone_count >= TONE_DETECT_TH)
- audio_reset_loss(&anetz->sender.loss);
if (anetz->tone_count == TONE_DETECT_TH) {
PDEBUG_CHAN(DDSP, DEBUG_INFO, "Detecting continuous %.0f Hz tone. (level = %.0f%%, quality =%.0f%%)\n", fsk_tones[anetz->tone_detected], level * 100.0, quality * 100.0);
anetz_receive_tone(anetz, anetz->tone_detected);
}
}
-/* Filter one chunk of audio an detect tone, quality and loss of signal. */
+/* Filter one chunk of audio an detect tone and quality of signal. */
static void fsk_decode_chunk(anetz_t *anetz, sample_t *spl, int max)
{
double level, result[2], quality[2];
level = audio_level(spl, max);
- if (audio_detect_loss(&anetz->sender.loss, level))
- anetz_loss_indication(anetz);
-
audio_goertzel(anetz->fsk_tone_goertzel, spl, max, 0, result, 2);
/* normalize quality of tones and level */
@@ -189,13 +185,25 @@ static void fsk_decode_chunk(anetz_t *anetz, sample_t *spl, int max)
}
/* Process received audio stream from radio unit. */
-void sender_receive(sender_t *sender, sample_t *samples, int length)
+void sender_receive(sender_t *sender, sample_t *samples, int length, double rf_level_db)
{
anetz_t *anetz = (anetz_t *) sender;
sample_t *spl;
int max, pos;
int i;
+ /* process signal mute/loss, also for signalling tone */
+ switch (squelch(&anetz->squelch, rf_level_db, (double)length / (double)anetz->sender.samplerate)) {
+ case SQUELCH_LOSS:
+ anetz_loss_indication(anetz, LOSS_TIME);
+ // fall through:
+ case SQUELCH_MUTE:
+ memset(samples, 0, sizeof(*samples) * length);
+ break;
+ default:
+ break;
+ }
+
/* write received samples to decode buffer */
max = anetz->samples_per_chunk;
pos = anetz->fsk_filter_pos;
diff --git a/src/anetz/dsp.h b/src/anetz/dsp.h
index aff93a9..04ea2a8 100644
--- a/src/anetz/dsp.h
+++ b/src/anetz/dsp.h
@@ -1,6 +1,6 @@
void dsp_init(void);
-int dsp_init_sender(anetz_t *anetz, double page_gain, int page_seqeuence);
+int dsp_init_sender(anetz_t *anetz, double page_gain, int page_seqeuence, double squelch_db);
void dsp_cleanup_sender(anetz_t *anetz);
void dsp_set_paging(anetz_t *anetz, double *freq);
void anetz_set_dsp_mode(anetz_t *anetz, enum dsp_mode mode, int detect_reset);
diff --git a/src/anetz/main.c b/src/anetz/main.c
index e144f8a..ab386ec 100644
--- a/src/anetz/main.c
+++ b/src/anetz/main.c
@@ -39,7 +39,7 @@
/* settings */
double page_gain = 1;
int page_sequence = 0;
-double lossdetect = 0;
+double squelch_db = -INFINITY;
void print_help(const char *arg0)
{
@@ -55,9 +55,11 @@ void print_help(const char *arg0)
printf(" -P --page-sequence 0 | <ms>\n");
printf(" Cycle paging tones, rather than sending simultaniously. Try 100.\n");
printf(" (default = '%d')\n", page_sequence);
- printf(" -L --loss <volume>\n");
- printf(" Detect loss of carrier by detecting steady noise above given volume in\n");
- printf(" percent. (disabled by default)\n");
+ printf(" -S --squelch <dB> | auto\n");
+ printf(" Use given RF level to detect loss of signal. When the signal gets lost\n");
+ printf(" and stays below this level, the connection is released.\n");
+ printf(" Use 'auto' to do automatic noise floor calibration to detect loss.\n");
+ printf(" Only works with SDR! (disabled by default)\n");
printf("\nstation-id: Give (last) 5 digits of station-id, you don't need to enter it\n");
printf(" for every start of this program.\n");
main_mobile_print_hotkeys();
@@ -73,11 +75,11 @@ static int handle_options(int argc, char **argv)
{"geo", 1, 0, 'G'},
{"page-gain", 1, 0, 'V'},
{"page-sequence", 1, 0, 'P'},
- {"loss", 1, 0, 'L'},
+ {"squelch", 1, 0, 'S'},
{0, 0, 0, 0}
};
- main_mobile_set_options("G:V:P:L:", long_options_special);
+ main_mobile_set_options("G:V:P:S:", long_options_special);
while (1) {
int option_index = 0, c;
@@ -109,8 +111,11 @@ static int handle_options(int argc, char **argv)
page_sequence = atoi(optarg);
skip_args += 2;
break;
- case 'L':
- lossdetect = atoi(optarg);
+ case 'S':
+ if (!strcasecmp(optarg, "auto"))
+ squelch_db = 0.0;
+ else
+ squelch_db = atof(optarg);
skip_args += 2;
break;
default:
@@ -179,7 +184,7 @@ int main(int argc, char *argv[])
/* create transceiver instance */
for (i = 0; i < num_kanal; i++) {
- rc = anetz_create(kanal[i], audiodev[i], use_sdr, samplerate, rx_gain, page_gain, page_sequence, do_pre_emphasis, do_de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, read_tx_wave, loopback, lossdetect / 100.0);
+ rc = anetz_create(kanal[i], audiodev[i], use_sdr, samplerate, rx_gain, page_gain, page_sequence, do_pre_emphasis, do_de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, read_tx_wave, loopback, squelch_db);
if (rc < 0) {
fprintf(stderr, "Failed to create \"Sender\" instance. Quitting!\n");
goto fail;