diff --git a/src/amps/amps.c b/src/amps/amps.c index 3a33215..38bec7b 100644 --- a/src/amps/amps.c +++ b/src/amps/amps.c @@ -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(&s->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); diff --git a/src/amps/amps.h b/src/amps/amps.h index 9087be5..b43caac 100644 --- a/src/amps/amps.h +++ b/src/amps/amps.h @@ -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 */ diff --git a/src/amps/dsp.c b/src/amps/dsp.c index 9ce9c93..8f4c84a 100644 --- a/src/amps/dsp.c +++ b/src/amps/dsp.c @@ -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(&s->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(&s->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(&s->sender.dispmeas, "SAT Level", "%.1f %%", DISPLAY_MEAS_AVG, DISPLAY_MEAS_LEFT, 0.0, 150.0, 100.0); + amps->dmp_sat_quality = display_measurements_add(&s->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(&s->sat_goertzel[amps->sat], samples, length, 0, &result[0], 1); audio_goertzel(&s->sat_goertzel[3], samples, length, 0, &result[1], 1); audio_goertzel(&s->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; diff --git a/src/libdisplay/display.h b/src/libdisplay/display.h index f22fe3e..b3762de 100644 --- a/src/libdisplay/display.h +++ b/src/libdisplay/display.h @@ -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 diff --git a/src/libdisplay/display_measurements.c b/src/libdisplay/display_measurements.c index 76c6ac3..8659886 100644 --- a/src/libdisplay/display_measurements.c +++ b/src/libdisplay/display_measurements.c @@ -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); } diff --git a/src/nmt/dsp.c b/src/nmt/dsp.c index 00965ed..1a9c49f 100644 --- a/src/nmt/dsp.c +++ b/src/nmt/dsp.c @@ -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++; diff --git a/src/nmt/nmt.h b/src/nmt/nmt.h index d644a79..70c8bab 100644 --- a/src/nmt/nmt.h +++ b/src/nmt/nmt.h @@ -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 */