Rework of displaying supervisory info: NMT and AMPS

Using lower rate to show debug info of supervisory signal.

Display supervisory info for NMT and AMPS at measurement display screen.
This commit is contained in:
Andreas Eversberg 2018-08-31 20:05:38 +02:00
parent eac19ddab1
commit 56d8df5351
7 changed files with 83 additions and 34 deletions

View File

@ -571,20 +571,13 @@ int amps_create(int channel, enum amps_chan_type chan_type, const char *audiodev
goto error;
}
/* init audio processing */
rc = dsp_init_sender(amps, tolerant);
if (rc < 0) {
PDEBUG(DAMPS, DEBUG_ERROR, "Failed to init audio processing!\n");
goto error;
}
if (polarity < 0)
amps->flip_polarity = 1;
amps->chan_type = chan_type;
memcpy(&amps->si, si, sizeof(amps->si));
amps->sat = sat;
if (polarity < 0)
amps->flip_polarity = 1;
amps->pre_emphasis = pre_emphasis;
amps->de_emphasis = de_emphasis;
/* the AMPS uses a frequency rage of 300..3000 Hz, but we still use the default low pass filter, wich is not too far above */
@ -592,6 +585,13 @@ int amps_create(int channel, enum amps_chan_type chan_type, const char *audiodev
if (rc < 0)
goto error;
/* init audio processing */
rc = dsp_init_sender(amps, tolerant);
if (rc < 0) {
PDEBUG(DAMPS, DEBUG_ERROR, "Failed to init audio processing!\n");
goto error;
}
/* go into idle state */
amps_go_idle(amps);

View File

@ -50,6 +50,8 @@ typedef struct amps {
/* display measurements */
dispmeasparam_t *dmp_frame_level;
dispmeasparam_t *dmp_frame_quality;
dispmeasparam_t *dmp_sat_level;
dispmeasparam_t *dmp_sat_quality;
/* system info */
amps_si si;
@ -144,6 +146,7 @@ typedef struct amps {
int sat_filter_pos; /* current sample position in filter_spl */
double sat_phaseshift65536[3]; /* how much the phase of sine wave changes per sample */
double sat_phase65536; /* current phase */
int sat_print; /* counts when to print result */
int dtx_state; /* 1 = high (fast sat detection) */
int sat_detected; /* current detection state flag (delayed detection) */
int sat_detect_count; /* current number of consecutive detections/losses */

View File

@ -117,6 +117,7 @@
#define TACS_BITRATE 8000
#define SAT_DURATION 0.05 /* duration of SAT signal measurement */
#define SAT_QUALITY 0.85 /* quality needed to detect SAT signal */
#define SAT_PRINT 10 /* print sat measurement every 0.5 seconds */
#define DTX_LEVEL 0.50 /* SAT level needed to mute/unmute */
#define SIG_QUALITY 0.80 /* quality needed to detect Signaling Tone */
#define SAT_DETECT_COUNT 5 /* number of measures to detect SAT signal (specs say 250ms) */
@ -269,6 +270,10 @@ int dsp_init_sender(amps_t *amps, int tolerant)
amps->dmp_frame_level = display_measurements_add(&amps->sender.dispmeas, "Frame Level", "%.1f %% (last)", DISPLAY_MEAS_LAST, DISPLAY_MEAS_LEFT, 0.0, 150.0, 100.0);
amps->dmp_frame_quality = display_measurements_add(&amps->sender.dispmeas, "Frame Quality", "%.1f %% (last)", DISPLAY_MEAS_LAST, DISPLAY_MEAS_LEFT, 0.0, 100.0, 100.0);
if (amps->chan_type == CHAN_TYPE_VC || amps->chan_type == CHAN_TYPE_CC_PC_VC) {
amps->dmp_sat_level = display_measurements_add(&amps->sender.dispmeas, "SAT Level", "%.1f %%", DISPLAY_MEAS_AVG, DISPLAY_MEAS_LEFT, 0.0, 150.0, 100.0);
amps->dmp_sat_quality = display_measurements_add(&amps->sender.dispmeas, "SAT Quality", "%.1f %%", DISPLAY_MEAS_AVG, DISPLAY_MEAS_LEFT, 0.0, 100.0, 100.0);
}
return 0;
@ -733,35 +738,54 @@ static void sender_receive_frame(amps_t *amps, sample_t *samples, int length)
/* compare supervisory signal against noise floor on 5800 Hz */
static void sat_decode(amps_t *amps, sample_t *samples, int length)
{
double result[3], quality[2];
double result[3], sat_quality, sig_quality, sat_level, sig_level;
audio_goertzel(&amps->sat_goertzel[amps->sat], samples, length, 0, &result[0], 1);
audio_goertzel(&amps->sat_goertzel[3], samples, length, 0, &result[1], 1);
audio_goertzel(&amps->sat_goertzel[4], samples, length, 0, &result[2], 1);
quality[0] = (result[0] - result[1]) / result[0];
if (quality[0] < 0)
quality[0] = 0;
quality[1] = (result[2] - result[1]) / result[2];
if (quality[1] < 0)
quality[1] = 0;
/* normalize sat level and signaling tone level */
sat_level = result[0] / ((!tacs) ? AMPS_SAT_DEVIATION : TACS_SAT_DEVIATION) / 0.63662;
sig_level = result[2] / ((!tacs) ? AMPS_FSK_DEVIATION : TACS_FSK_DEVIATION) / 0.63662;
PDEBUG_CHAN(DDSP, DEBUG_NOTICE, "SAT level %.2f%% quality %.0f%%\n", result[0] / ((!tacs) ? AMPS_SAT_DEVIATION : TACS_SAT_DEVIATION) / 0.63662 * 100.0, quality[0] * 100.0);
if (amps->sender.loopback || debuglevel == DEBUG_DEBUG) {
PDEBUG_CHAN(DDSP, debuglevel, "Signaling Tone level %.2f%% quality %.0f%%\n", result[2] / ((!tacs) ? AMPS_FSK_DEVIATION : TACS_FSK_DEVIATION) / 0.63662 * 100.0, quality[1] * 100.0);
/* get normalized quality of SAT and signaling tone */
sat_quality = (result[0] - result[1]) / result[0];
if (sat_quality < 0)
sat_quality = 0;
sig_quality = (result[2] - result[1]) / result[2];
if (sig_quality < 0)
sig_quality = 0;
/* debug SAT */
if (++amps->sat_print == SAT_PRINT) {
PDEBUG_CHAN(DDSP, DEBUG_NOTICE, "SAT level %.2f%% quality %.0f%%\n", sat_level * 100.0, sat_quality * 100.0);
amps->sat_print = 0;
}
if (quality[0] > SAT_QUALITY && result[0] / ((!tacs) ? AMPS_SAT_DEVIATION : TACS_SAT_DEVIATION) / 0.63662 > DTX_LEVEL)
/* update measurements (if dmp_* params are NULL, we omit this) */
display_measurements_update(amps->dmp_sat_level, sat_level * 100.0, 0.0);
display_measurements_update(amps->dmp_sat_quality, sat_quality * 100.0, 0.0);
/* debug signaling tone */
if (amps->sender.loopback || debuglevel == DEBUG_DEBUG) {
PDEBUG_CHAN(DDSP, debuglevel, "Signaling Tone level %.2f%% quality %.0f%%\n", sig_level * 100.0, sig_quality * 100.0);
}
/* mute if SAT quality or level is below threshold */
if (sat_quality > SAT_QUALITY && sat_level > DTX_LEVEL)
amps->dtx_state = 1;
else
amps->dtx_state = 0;
if (quality[0] > SAT_QUALITY) {
/* detect SAT */
if (sat_quality > SAT_QUALITY) {
if (amps->sat_detected == 0) {
amps->sat_detect_count++;
if (amps->sat_detect_count == SAT_DETECT_COUNT) {
amps->sat_detected = 1;
amps->sat_detect_count = 0;
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "SAT signal detected with level=%.0f%%, quality=%.0f%%.\n", result[0] / 0.63662 * 100.0, quality[0] * 100.0);
amps_rx_sat(amps, 1, quality[0]);
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "SAT signal detected with level=%.0f%%, quality=%.0f%%.\n", sat_level * 100.0, sat_quality * 100.0);
amps_rx_sat(amps, 1, sat_quality);
}
} else
amps->sat_detect_count = 0;
@ -777,14 +801,16 @@ static void sat_decode(amps_t *amps, sample_t *samples, int length)
} else
amps->sat_detect_count = 0;
}
if (quality[1] > SIG_QUALITY) {
/* detect signaling tone */
if (sig_quality > SIG_QUALITY) {
if (amps->sig_detected == 0) {
amps->sig_detect_count++;
if (amps->sig_detect_count == SIG_DETECT_COUNT) {
amps->sig_detected = 1;
amps->sig_detect_count = 0;
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Signaling Tone detected with level=%.0f%%, quality=%.0f%%.\n", result[2] / 0.63662 * 100.0, quality[1] * 100.0);
amps_rx_signaling_tone(amps, 1, quality[1]);
PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Signaling Tone detected with level=%.0f%%, quality=%.0f%%.\n", sig_level * 100.0, sig_quality * 100.0);
amps_rx_signaling_tone(amps, 1, sig_quality);
}
} else
amps->sig_detect_count = 0;

View File

@ -1,5 +1,6 @@
#define DISPLAY_INTERVAL 0.04 /* time (in seconds) for each interval */
#define DISPLAY_PARAM_HISTORIES 25 /* number of intervals (should result in one seconds) */
#define DISPLAY_MEAS_INTERVAL 0.1 /* time (in seconds) for each measurement values interval */
#define DISPLAY_INTERVAL 0.04 /* time (in seconds) for each other interval */
#define DISPLAY_PARAM_HISTORIES 10 /* number of intervals (should result in one seconds) */
#define MAX_DISPLAY_WIDTH 1024

View File

@ -347,9 +347,9 @@ void display_measurements(double elapsed)
/* count and check if we need to display this time */
time_elapsed += elapsed;
if (time_elapsed < DISPLAY_INTERVAL)
if (time_elapsed < DISPLAY_MEAS_INTERVAL)
return;
time_elapsed = fmod(time_elapsed, DISPLAY_INTERVAL);
time_elapsed = fmod(time_elapsed, DISPLAY_MEAS_INTERVAL);
print_measurements(1);
}

View File

@ -66,6 +66,7 @@
#define DIALTONE_HZ 425.0 /* dial tone frequency */
#define TX_PEAK_DIALTONE 1.0 /* dial tone peak FIXME: Not found in the specs! */
#define SUPER_DURATION 0.25 /* duration of supervisory signal measurement */
#define SUPER_PRINT 2 /* print supervisory signal measurement every 0.5 seconds */
#define SUPER_LOST_COUNT 4 /* number of measures to loose supervisory signal */
#define SUPER_DETECT_COUNT 6 /* number of measures to detect supervisory signal */
#define MUTE_DURATION 0.280 /* a tiny bit more than two frames */
@ -153,6 +154,10 @@ int dsp_init_sender(nmt_t *nmt, double deviation_factor)
nmt->dmp_frame_level = display_measurements_add(&nmt->sender.dispmeas, "Frame Level", "%.1f %% (last)", DISPLAY_MEAS_LAST, DISPLAY_MEAS_LEFT, 0.0, 150.0, 100.0);
nmt->dmp_frame_quality = display_measurements_add(&nmt->sender.dispmeas, "Frame Quality", "%.1f %% (last)", DISPLAY_MEAS_LAST, DISPLAY_MEAS_LEFT, 0.0, 100.0, 100.0);
if (nmt->sysinfo.chan_type == CHAN_TYPE_TC || nmt->sysinfo.chan_type == CHAN_TYPE_AC_TC || nmt->sysinfo.chan_type == CHAN_TYPE_CC_TC) {
nmt->dmp_super_level = display_measurements_add(&nmt->sender.dispmeas, "Super Level", "%.1f %%", DISPLAY_MEAS_AVG, DISPLAY_MEAS_LEFT, 0.0, 150.0, 100.0);
nmt->dmp_super_quality = display_measurements_add(&nmt->sender.dispmeas, "Super Quality", "%.1f %%", DISPLAY_MEAS_AVG, DISPLAY_MEAS_LEFT, 0.0, 100.0, 100.0);
}
return 0;
}
@ -257,17 +262,28 @@ static void fsk_receive_bit(void *inst, int bit, double quality, double level)
/* compare supervisory signal against noise floor on 3900 Hz */
static void super_decode(nmt_t *nmt, sample_t *samples, int length)
{
double result[2], quality;
double result[2], level, quality;
audio_goertzel(&nmt->super_goertzel[nmt->supervisory - 1], samples, length, 0, &result[0], 1);
audio_goertzel(&nmt->super_goertzel[4], samples, length, 0, &result[1], 1); /* noise floor detection */
/* normalize supervisory level */
level = result[0] / 0.63662 / TX_PEAK_SUPER;
quality = (result[0] - result[1]) / result[0];
if (quality < 0)
quality = 0;
if (nmt->state == STATE_ACTIVE)
PDEBUG_CHAN(DDSP, DEBUG_NOTICE, "Supervisory level %.0f%% quality %.0f%%\n", result[0] / 0.63662 / TX_PEAK_SUPER * 100.0, quality * 100.0);
if (nmt->state == STATE_ACTIVE) {
if (++nmt->super_print == SUPER_PRINT) {
nmt->super_print = 0;
PDEBUG_CHAN(DDSP, DEBUG_NOTICE, "Supervisory level %.0f%% quality %.0f%%\n", level * 100.0, quality * 100.0);
}
/* update measurements (if dmp_* params are NULL, we omit this) */
display_measurements_update(nmt->dmp_super_level, level * 100.0, 0.0);
display_measurements_update(nmt->dmp_super_quality, quality * 100.0, 0.0);
}
if (quality > 0.7) {
if (nmt->super_detected == 0) {
nmt->super_detect_count++;

View File

@ -94,6 +94,8 @@ typedef struct nmt {
/* display measurements */
dispmeasparam_t *dmp_frame_level;
dispmeasparam_t *dmp_frame_quality;
dispmeasparam_t *dmp_super_level;
dispmeasparam_t *dmp_super_quality;
/* features */
int compandor; /* if compandor shall be used */
@ -109,6 +111,7 @@ typedef struct nmt {
int super_filter_pos; /* current sample position in filter_spl */
double super_phaseshift65536[4];/* how much the phase of sine wave changes per sample */
double super_phase65536; /* current phase */
int super_print; /* counts when to print result */
double dial_phaseshift65536; /* how much the phase of sine wave changes per sample */
double dial_phase65536; /* current phase */
uint16_t rx_sync; /* shift register to detect sync */