aboutsummaryrefslogtreecommitdiffstats
path: root/src/common
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2017-09-25 18:46:50 +0200
committerAndreas Eversberg <jolly@eversberg.eu>2017-10-12 19:46:30 +0200
commitba036de22680c5f46983f30144c23d212245842f (patch)
treef511133326644feb457810c524a2ff317aa945c3 /src/common
parente84d7a082c20b591a06fdfd38ccdbe458e276631 (diff)
Add function to display measurements on screen
Use 'm' key to toggle display.
Diffstat (limited to 'src/common')
-rw-r--r--src/common/Makefile.am3
-rw-r--r--src/common/debug.c2
-rw-r--r--src/common/display.h45
-rw-r--r--src/common/display_iq.c2
-rw-r--r--src/common/display_measurements.c359
-rw-r--r--src/common/display_status.c2
-rw-r--r--src/common/display_wave.c2
-rw-r--r--src/common/main_mobile.c31
-rw-r--r--src/common/sdr.c46
-rw-r--r--src/common/sender.c23
-rw-r--r--src/common/sender.h4
-rw-r--r--src/common/sound_alsa.c48
12 files changed, 539 insertions, 28 deletions
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index 6cb64b6..0edd221 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -19,7 +19,8 @@ libcommon_a_SOURCES = \
fft.c \
fm_modulation.c \
fsk.c \
- display_wave.c
+ display_wave.c \
+ display_measurements.c
libmobile_a_SOURCES = \
sender.c \
diff --git a/src/common/debug.c b/src/common/debug.c
index 512596a..d2eedb8 100644
--- a/src/common/debug.c
+++ b/src/common/debug.c
@@ -100,6 +100,7 @@ void _printdebug(const char *file, const char __attribute__((unused)) *function,
// printf("%s%s:%d %s() %s: %s\033[0;39m", debug_cat[cat].color, file, line, function, debug_level[level], buffer);
display_wave_limit_scroll(1);
display_status_limit_scroll(1);
+ display_measurements_limit_scroll(1);
#ifdef HAVE_SDR
display_iq_limit_scroll(1);
display_spectrum_limit_scroll(1);
@@ -107,6 +108,7 @@ void _printdebug(const char *file, const char __attribute__((unused)) *function,
printf("%s%s:%d %s: %s\033[0;39m", debug_cat[cat].color, file, line, debug_level[level], buffer);
display_wave_limit_scroll(0);
display_status_limit_scroll(0);
+ display_measurements_limit_scroll(0);
#ifdef HAVE_SDR
display_iq_limit_scroll(0);
display_spectrum_limit_scroll(0);
diff --git a/src/common/display.h b/src/common/display.h
index 850e4d8..386a2d7 100644
--- a/src/common/display.h
+++ b/src/common/display.h
@@ -1,4 +1,5 @@
-#define DISPLAY_INTERVAL 0.04
+#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 MAX_DISPLAY_WIDTH 1024
@@ -11,6 +12,40 @@ typedef struct display_wave {
sample_t buffer[MAX_DISPLAY_WIDTH];
} dispwav_t;
+enum display_measurements_type {
+ DISPLAY_MEAS_LAST, /* display last value */
+ DISPLAY_MEAS_PEAK, /* display peak value */
+ DISPLAY_MEAS_PEAK2PEAK, /* display peak value of min..max range */
+ DISPLAY_MEAS_AVG, /* display average value */
+};
+
+enum display_measurements_bar {
+ DISPLAY_MEAS_LEFT, /* bar graph from left */
+ DISPLAY_MEAS_CENTER, /* bar graph from center */
+};
+
+typedef struct display_measurements_param {
+ struct display_measurements_param *next;
+ char name[32]; /* parameter name (e.g. 'Deviation') */
+ char format[32]; /* unit name (e.g. "%.2f KHz") */
+ enum display_measurements_type type;
+ enum display_measurements_bar bar;
+ double min; /* minimum value */
+ double max; /* maximum value */
+ double mark; /* mark (target) value */
+ double value; /* current value (peak, sum...) */
+ double value2; /* max value for min..max range */
+ double last; /* last valid value (used for DISPLAY_MEAS_LAST) */
+ int value_count; /* count number of values of one interval */
+ double value_history[DISPLAY_PARAM_HISTORIES]; /* history of values of last second */
+ double value2_history[DISPLAY_PARAM_HISTORIES]; /* stores max for min..max range */
+ int value_history_pos; /* next history value to write */
+} dispmeasparam_t;
+
+typedef struct display_measurements {
+ dispmeasparam_t *head;
+} dispmeas_t;
+
#define MAX_DISPLAY_IQ 1024
typedef struct display_iq {
@@ -44,6 +79,14 @@ void display_status_channel(int channel, const char *type, const char *state);
void display_status_subscriber(const char *number, const char *state);
void display_status_end(void);
+void display_measurements_init(sender_t *sender, int samplerate);
+void display_measurements_exit(sender_t *sender);
+void display_measurements_on(int on);
+void display_measurements_limit_scroll(int on);
+dispmeasparam_t *display_measurements_add(sender_t *sender, char *name, char *format, enum display_measurements_type type, enum display_measurements_bar bar, double min, double max, double mark);
+void display_measurements_update(dispmeasparam_t *param, double value, double value2);
+void display_measurements(double elapsed);
+
void display_iq_init(int samplerate);
void display_iq_on(int on);
void display_iq_limit_scroll(int on);
diff --git a/src/common/display_iq.c b/src/common/display_iq.c
index 14e17a4..c63a455 100644
--- a/src/common/display_iq.c
+++ b/src/common/display_iq.c
@@ -26,8 +26,6 @@
#include "sample.h"
#include "sender.h"
-#define DISPLAY_INTERVAL 0.04
-
/* must be odd value! */
#define SIZE 23
diff --git a/src/common/display_measurements.c b/src/common/display_measurements.c
new file mode 100644
index 0000000..103384d
--- /dev/null
+++ b/src/common/display_measurements.c
@@ -0,0 +1,359 @@
+/* display measurements functions
+ *
+ * (C) 2017 by Andreas Eversberg <jolly@eversberg.eu>
+ * All Rights Reserved
+ *
+ * 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/>.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <sys/ioctl.h>
+#include <math.h>
+#include "sample.h"
+#include "sender.h"
+
+#define MAX_NAME_LEN 16
+#define MAX_UNIT_LEN 16
+
+static int has_init = 0;
+static int measurements_on = 0;
+double time_elapsed = 0.0;
+static int lines_total = 0;
+static char line[MAX_DISPLAY_WIDTH];
+static char line_color[MAX_DISPLAY_WIDTH];
+
+void display_measurements_init(sender_t *sender, int __attribute__((unused)) samplerate)
+{
+ dispmeas_t *disp = &sender->dispmeas;
+
+ memset(disp, 0, sizeof(*disp));
+ has_init = 1;
+ lines_total = 0;
+ time_elapsed = 0.0;
+}
+
+void display_measurements_exit(sender_t *sender)
+{
+ dispmeas_t *disp = &sender->dispmeas;
+ dispmeasparam_t *param = disp->head, *temp;
+
+ while (param) {
+ temp = param;
+ param = param->next;
+ free(temp);
+ }
+ disp->head = NULL;
+ has_init = 0;
+}
+
+static int color;
+
+static void display_line(int on, int w)
+{
+ int j;
+
+ if (on) {
+ for (j = 0; j < w; j++) {
+ if (line_color[j] != color && line[j] != ' ') {
+ color = line_color[j];
+ printf("\033[%d;3%dm", color / 10, color % 10);
+ }
+ putchar(line[j]);
+ }
+ } else {
+ for (j = 0; j < w; j++)
+ putchar(' ');
+ }
+ putchar('\n');
+ lines_total++;
+}
+
+static void print_measurements(int on)
+{
+ sender_t *sender;
+ dispmeasparam_t *param;
+ int i, j;
+ int width, h;
+ char text[128];
+ double value = 0.0, value2 = 0.0, hold, hold2;
+ int bar_width, bar_left, bar_right, bar_hold, bar_mark;
+
+ get_win_size(&width, &h);
+
+ /* no display, if bar graph is less than one character */
+ bar_width = width - MAX_NAME_LEN - MAX_UNIT_LEN;
+ if (bar_width < 1)
+ return;
+
+ lines_total = 0;
+ color = -1;
+ printf("\0337\033[H");
+ for (sender = sender_head; sender; sender = sender->next) {
+ memset(line, ' ', width);
+ memset(line_color, 7, width);
+ sprintf(line, "(chan %d", sender->kanal);
+ *strchr(line, '\0') = ')';
+ display_line(on, width);
+ for (param = sender->dispmeas.head; param; param = param->next) {
+ memset(line, ' ', width);
+ memset(line_color, 7, width);
+ memset(line_color, 3, MAX_NAME_LEN); /* yellow */
+ switch (param->type) {
+ case DISPLAY_MEAS_LAST:
+ value = param->value;
+ param->value = -NAN;
+ break;
+ case DISPLAY_MEAS_PEAK:
+ /* peak value */
+ value = param->value;
+ param->value = -NAN;
+ param->value_count = 0;
+ break;
+ case DISPLAY_MEAS_PEAK2PEAK:
+ /* peak to peak value */
+ value = param->value;
+ value2 = param->value2;
+ param->value = -NAN;
+ param->value2 = -NAN;
+ param->value_count = 0;
+ break;
+ case DISPLAY_MEAS_AVG:
+ /* average value */
+ if (param->value_count)
+ value = param->value / (double)param->value_count;
+ else
+ value = -NAN;
+ param->value = 0.0;
+ param->value_count = 0;
+ break;
+ }
+ /* add current value to history */
+ param->value_history[param->value_history_pos++] = value;
+ param->value2_history[param->value_history_pos++] = value2;
+ param->value_history_pos %= DISPLAY_PARAM_HISTORIES;
+ /* calculate hold values */
+ hold = -NAN;
+ hold2 = -NAN;
+ switch (param->type) {
+ case DISPLAY_MEAS_LAST:
+ /* if we have valid value, we update 'last' */
+ if (!isnan(value)) {
+ param->last = value;
+ hold = value;
+ } else
+ hold = param->last;
+ break;
+ case DISPLAY_MEAS_PEAK:
+ for (i = 0; i < DISPLAY_PARAM_HISTORIES; i++) {
+ if (isnan(param->value_history[i]))
+ continue;
+ if (isnan(hold) || param->value_history[i] > hold)
+ hold = param->value_history[i];
+ }
+ break;
+ case DISPLAY_MEAS_PEAK2PEAK:
+ for (i = 0; i < DISPLAY_PARAM_HISTORIES; i++) {
+ if (isnan(param->value_history[i]))
+ continue;
+ if (isnan(hold) || param->value_history[i] < hold)
+ hold = param->value_history[i];
+ if (isnan(hold2) || param->value2_history[i] > hold2)
+ hold2 = param->value2_history[i];
+ }
+ if (!isnan(hold))
+ hold = hold2 - hold;
+ if (!isnan(value))
+ value = value2 - value;
+ break;
+ case DISPLAY_MEAS_AVG:
+ for (i = 0, j = 0; i < DISPLAY_PARAM_HISTORIES; i++) {
+ if (isnan(param->value_history[i]))
+ continue;
+ if (j == 0)
+ hold = 0.0;
+ hold += param->value_history[i];
+ j++;
+ }
+ if (j)
+ hold /= j;
+ break;
+ }
+ /* "Deviation ::::::::::............ 4.5 KHz" */
+ strncpy(line, param->name, (strlen(param->name) < MAX_NAME_LEN) ? strlen(param->name) : MAX_NAME_LEN);
+ if (isinf(value) || isnan(value)) {
+ bar_left = -1;
+ bar_right = -1;
+ } else if (param->bar == DISPLAY_MEAS_CENTER) {
+ if (value >= 0.0) {
+ bar_left = (-param->min) / (param->max - param->min) * ((double)bar_width - 1.0);
+ bar_right = (value - param->min) / (param->max - param->min) * ((double)bar_width - 1.0);
+ } else {
+ bar_left = (value - param->min) / (param->max - param->min) * ((double)bar_width - 1.0);
+ bar_right = (-param->min) / (param->max - param->min) * ((double)bar_width - 1.0);
+ }
+ } else {
+ bar_left = -1;
+ bar_right = (value - param->min) / (param->max - param->min) * ((double)bar_width - 1.0);
+ }
+ if (isinf(hold) || isnan(hold))
+ bar_hold = -1;
+ else
+ bar_hold = (hold - param->min) / (param->max - param->min) * ((double)bar_width - 1.0);
+ if (isinf(param->mark))
+ bar_mark = -1;
+ else
+ bar_mark = (param->mark - param->min) / (param->max - param->min) * ((double)bar_width - 1.0);
+ for (i = 0; i < bar_width; i++) {
+ line[i + MAX_NAME_LEN] = ':';
+ if (i == bar_hold)
+ line_color[i + MAX_NAME_LEN] = 13;
+ else if (i == bar_mark)
+ line_color[i + MAX_NAME_LEN] = 14;
+ else if (i >= bar_left && i <= bar_right)
+ line_color[i + MAX_NAME_LEN] = 2;
+ else
+ line_color[i + MAX_NAME_LEN] = 4;
+ }
+ sprintf(text, param->format, hold);
+ if (isnan(hold))
+ memset(line_color + width - MAX_UNIT_LEN, 4, MAX_UNIT_LEN); /* blue */
+ else
+ memset(line_color + width - MAX_UNIT_LEN, 3, MAX_UNIT_LEN); /* yellow */
+ strncpy(line + width - MAX_UNIT_LEN + 1, text, (strlen(text) < MAX_UNIT_LEN) ? strlen(text) : MAX_UNIT_LEN);
+ display_line(on, width);
+ }
+ }
+ /* reset color and position */
+ printf("\033[0;39m\0338"); fflush(stdout);
+}
+
+void display_measurements_on(int on)
+{
+ if (measurements_on)
+ print_measurements(0);
+
+ if (on < 0)
+ measurements_on = 1 - measurements_on;
+ else
+ measurements_on = on;
+}
+
+void display_measurements_limit_scroll(int on)
+{
+ int w, h;
+
+ if (!measurements_on)
+ return;
+
+ get_win_size(&w, &h);
+
+ printf("\0337");
+ printf("\033[%d;%dr", (on) ? lines_total + 1 : 1, h);
+ printf("\0338");
+}
+
+/* add new parameter on startup to the list of measurements */
+dispmeasparam_t *display_measurements_add(sender_t *sender, char *name, char *format, enum display_measurements_type type, enum display_measurements_bar bar, double min, double max, double mark)
+{
+ dispmeas_t *disp = &sender->dispmeas;
+ dispmeasparam_t *param, **param_p = &disp->head;
+ int i;
+
+ if (!has_init) {
+ fprintf(stderr, "Not initialized prior adding measurement, please fix!\n");
+ abort();
+ }
+
+ while (*param_p)
+ param_p = &((*param_p)->next);
+ *param_p = calloc(sizeof(dispmeasparam_t), 1);
+ if (!*param_p)
+ return NULL;
+ param = *param_p;
+ strncpy(param->name, name, sizeof(param->name) - 1);
+ strncpy(param->format, format, sizeof(param->format) - 1);
+ param->type = type;
+ param->bar = bar;
+ param->min = min;
+ param->max = max;
+ param->mark = mark;
+ param->value = -NAN;
+ param->value2 = -NAN;
+ param->last = -NAN;
+ for (i = 0; i < DISPLAY_PARAM_HISTORIES; i++)
+ param->value_history[i] = -NAN;
+ param->value_count = 0;
+
+ return param;
+}
+
+void display_measurements_update(dispmeasparam_t *param, double value, double value2)
+{
+ /* special case where we do not have an instance of the parameter */
+ if (!param)
+ return;
+
+ if (!has_init) {
+ fprintf(stderr, "Not initialized prior updating measurement value, please fix!\n");
+ abort();
+ }
+
+ switch (param->type) {
+ case DISPLAY_MEAS_LAST:
+ param->value = value;
+ break;
+ case DISPLAY_MEAS_PEAK:
+ if (isnan(param->value) || value > param->value)
+ param->value = value;
+ break;
+ case DISPLAY_MEAS_PEAK2PEAK:
+ if (param->value_count == 0 || value < param->value)
+ param->value = value;
+ if (param->value_count == 0 || value2 > param->value2)
+ param->value2 = value2;
+ param->value_count++;
+ break;
+ case DISPLAY_MEAS_AVG:
+ param->value += value;
+ param->value_count++;
+ break;
+ default:
+ fprintf(stderr, "Paramer '%s' has unknown type %d, please fix!\n", param->name, param->type);
+ abort();
+ }
+}
+
+void display_measurements(double elapsed)
+{
+ if (!measurements_on)
+ return;
+
+ if (!has_init) {
+ fprintf(stderr, "Not initialized prior display measurement values, please fix!\n");
+ abort();
+ }
+
+ /* count and check if we need to display this time */
+ time_elapsed += elapsed;
+ if (time_elapsed < DISPLAY_INTERVAL)
+ return;
+ time_elapsed = fmod(time_elapsed, DISPLAY_INTERVAL);
+
+ print_measurements(1);
+}
+
diff --git a/src/common/display_status.c b/src/common/display_status.c
index 64ec79c..66ff9ac 100644
--- a/src/common/display_status.c
+++ b/src/common/display_status.c
@@ -30,7 +30,7 @@ static int line_count = 0;
static int lines_total = 0;
static char screen[MAX_HEIGHT_STATUS][MAX_DISPLAY_WIDTH];
-void print_status(int on)
+static void print_status(int on)
{
int i, j;
int w, h;
diff --git a/src/common/display_wave.c b/src/common/display_wave.c
index b42c584..1d729b2 100644
--- a/src/common/display_wave.c
+++ b/src/common/display_wave.c
@@ -26,8 +26,6 @@
#include "sample.h"
#include "sender.h"
-#define DISPLAY_INTERVAL 0.04
-
#define HEIGHT 11
static int num_sender = 0;
diff --git a/src/common/main_mobile.c b/src/common/main_mobile.c
index 60ff519..f906d6d 100644
--- a/src/common/main_mobile.c
+++ b/src/common/main_mobile.c
@@ -152,10 +152,11 @@ void main_mobile_print_help(const char *arg0, const char *ext_usage)
void main_mobile_print_hotkeys(void)
{
printf("\n");
- printf("Press digits '0'..'9' and then 'd' key to dial towards mobile station\n");
+ printf("Press digits '0'..'9' and then 'd' key to dial towards mobile station.\n");
printf("Press 'h' key to hangup.\n");
printf("Press 'w' key to toggle display of RX wave form.\n");
printf("Press 'c' key to toggle display of channel status.\n");
+ printf("Press 'm' key to toggle display of measurement value.\n");
#ifdef HAVE_SDR
sdr_config_print_hotkeys();
#endif
@@ -524,35 +525,49 @@ next_char:
*quit = 1;
goto next_char;
case 'w':
- /* toggle display */
+ /* toggle wave display */
+ display_status_on(0);
+ display_measurements_on(0);
#ifdef HAVE_SDR
display_iq_on(0);
display_spectrum_on(0);
#endif
- display_status_on(0);
display_wave_on(-1);
goto next_char;
case 'c':
- /* toggle display */
+ /* toggle call state display */
+ display_wave_on(0);
+ display_measurements_on(0);
#ifdef HAVE_SDR
display_iq_on(0);
display_spectrum_on(0);
#endif
- display_wave_on(0);
display_status_on(-1);
goto next_char;
+ case 'm':
+ /* toggle measurements display */
+ display_wave_on(0);
+ display_status_on(0);
+#ifdef HAVE_SDR
+ display_iq_on(0);
+ display_spectrum_on(0);
+#endif
+ display_measurements_on(-1);
+ goto next_char;
#ifdef HAVE_SDR
case 'q':
- /* toggle display */
+ /* toggle IQ display */
display_wave_on(0);
display_status_on(0);
+ display_measurements_on(0);
display_spectrum_on(0);
display_iq_on(-1);
goto next_char;
case 's':
- /* toggle spectrum */
+ /* toggle spectrum display */
display_wave_on(0);
display_status_on(0);
+ display_measurements_on(0);
display_iq_on(0);
display_spectrum_on(-1);
goto next_char;
@@ -569,6 +584,8 @@ next_char:
if (myhandler)
myhandler();
+ display_measurements((double)interval / 1000.0);
+
now = get_time();
/* sleep interval */
diff --git a/src/common/sdr.c b/src/common/sdr.c
index 1e32c74..2e40833 100644
--- a/src/common/sdr.c
+++ b/src/common/sdr.c
@@ -32,8 +32,7 @@ enum paging_signal;
#include "sample.h"
#include "fm_modulation.h"
#include "timer.h"
-#include "wave.h"
-#include "display.h"
+#include "sender.h"
#include "sdr_config.h"
#include "sdr.h"
#ifdef HAVE_UHD
@@ -68,6 +67,9 @@ typedef struct sdr_chan {
double rx_frequency; /* frequency used */
fm_mod_t mod; /* modulator instance */
fm_demod_t demod; /* demodulator instance */
+ dispmeasparam_t *dmp_rf_level;
+ dispmeasparam_t *dmp_freq_offset;
+ dispmeasparam_t *dmp_deviation;
} sdr_chan_t;
typedef struct sdr {
@@ -340,6 +342,15 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
goto error;
}
}
+ /* init measurements display */
+ for (c = 0; c < channels; c++) {
+ sender_t *sender = get_sender_by_empfangsfrequenz(sdr->chan[c].rx_frequency);
+ if (!sender)
+ continue;
+ sdr->chan[c].dmp_rf_level = display_measurements_add(sender, "RF Level", "%.1f dB", DISPLAY_MEAS_AVG, DISPLAY_MEAS_LEFT, -96.0, 0.0, -INFINITY);
+ sdr->chan[c].dmp_freq_offset = display_measurements_add(sender, "Freq. Offset", "%+.2f KHz", DISPLAY_MEAS_AVG, DISPLAY_MEAS_CENTER, -max_deviation / 1000.0 * 2.0, max_deviation / 1000.0 * 2.0, 0.0);
+ sdr->chan[c].dmp_deviation = display_measurements_add(sender, "Deviation", "%.2f KHz", DISPLAY_MEAS_PEAK2PEAK, DISPLAY_MEAS_LEFT, 0.0, max_deviation / 1000.0 * 1.5, max_deviation / 1000.0);
+ }
}
if (sdr_config->swap_links) {
@@ -747,7 +758,7 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels)
#endif
if (count <= 0)
return count;
-}
+ }
if (sdr->wave_rx_rec.fp) {
sample_t *spl_list[2] = { sdr->wavespl0, sdr->wavespl1 };
@@ -769,8 +780,35 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels)
display_spectrum(buff, count);
if (channels) {
- for (c = 0; c < channels; c++)
+ for (c = 0; c < channels; c++) {
fm_demodulate_complex(&sdr->chan[c].demod, samples[c], count, buff, sdr->modbuff_I, sdr->modbuff_Q);
+ sender_t *sender = get_sender_by_empfangsfrequenz(sdr->chan[c].rx_frequency);
+ if (!sender || !count)
+ continue;
+ double min, max, avg;
+ avg = 0.0;
+ for (s = 0; s < count; s++) {
+ /* average the square length of vector */
+ avg += sdr->modbuff_I[s] * sdr->modbuff_I[s] + sdr->modbuff_Q[s] * sdr->modbuff_Q[s];
+ }
+ avg = sqrt(avg /(double)count); /* RMS */
+ avg = log10(avg) * 20;
+ display_measurements_update(sdr->chan[c].dmp_rf_level, avg, 0.0);
+ min = 0.0;
+ max = 0.0;
+ avg = 0.0;
+ for (s = 0; s < count; s++) {
+ avg += samples[c][s];
+ if (s == 0 || samples[c][s] > max)
+ max = samples[c][s];
+ if (s == 0 || samples[c][s] < min)
+ min = samples[c][s];
+ }
+ avg /= (double)count;
+ display_measurements_update(sdr->chan[c].dmp_freq_offset, avg / 1000.0, 0.0);
+ /* use half min and max, because we want the deviation above/below (+-) center frequency. */
+ display_measurements_update(sdr->chan[c].dmp_deviation, min / 2.0 / 1000.0, max / 2.0 / 1000.0);
+ }
}
return count;
diff --git a/src/common/sender.c b/src/common/sender.c
index 4d1b54e..9cd8c0b 100644
--- a/src/common/sender.c
+++ b/src/common/sender.c
@@ -44,7 +44,7 @@ int sender_create(sender_t *sender, int kanal, double sendefrequenz, double empf
sender->kanal = kanal;
sender->sendefrequenz = sendefrequenz;
- sender->empfangsfrequenz = empfangsfrequenz;
+ sender->empfangsfrequenz = (loopback) ? sendefrequenz : empfangsfrequenz;
strncpy(sender->audiodev, audiodev, sizeof(sender->audiodev) - 1);
sender->samplerate = samplerate;
sender->rx_gain = rx_gain;
@@ -145,6 +145,7 @@ int sender_create(sender_t *sender, int kanal, double sendefrequenz, double empf
sender_tailp = &sender->next;
display_wave_init(sender, samplerate);
+ display_measurements_init(sender, samplerate);
return 0;
error:
@@ -157,7 +158,6 @@ int sender_open_audio(int latspl)
{
sender_t *master, *inst;
int channels;
- double paging_frequency = 0.0;
int i;
int rc;
@@ -171,13 +171,10 @@ int sender_open_audio(int latspl)
for (inst = master; inst; inst = inst->slave) {
channels++;
}
- double tx_f[channels], rx_f[channels];
+ double tx_f[channels], rx_f[channels], paging_frequency = 0.0;
for (i = 0, inst = master; inst; i++, inst = inst->slave) {
tx_f[i] = inst->sendefrequenz;
- if (inst->loopback)
- rx_f[i] = inst->sendefrequenz;
- else
- rx_f[i] = inst->empfangsfrequenz;
+ rx_f[i] = inst->empfangsfrequenz;
if (inst->ruffrequenz)
paging_frequency = inst->ruffrequenz;
}
@@ -438,3 +435,15 @@ void sender_paging(sender_t *sender, int on)
sender->paging_on = on;
}
+sender_t *get_sender_by_empfangsfrequenz(double freq)
+{
+ sender_t *sender;
+
+ for (sender = sender_head; sender; sender = sender->next) {
+ if (sender->empfangsfrequenz == freq)
+ return sender;
+ }
+
+ return NULL;
+}
+
diff --git a/src/common/sender.h b/src/common/sender.h
index 3a3136b..ca53de4 100644
--- a/src/common/sender.h
+++ b/src/common/sender.h
@@ -84,6 +84,9 @@ typedef struct sender {
/* display wave */
dispwav_t dispwav; /* display wave form */
+
+ /* display measurements */
+ dispmeas_t dispmeas; /* display measurements */
} sender_t;
/* list of all senders */
@@ -99,4 +102,5 @@ void process_sender_audio(sender_t *sender, int *quit, int latspl);
void sender_send(sender_t *sender, sample_t *samples, uint8_t *power, int count);
void sender_receive(sender_t *sender, sample_t *samples, int count);
void sender_paging(sender_t *sender, int on);
+sender_t *get_sender_by_empfangsfrequenz(double freq);
diff --git a/src/common/sound_alsa.c b/src/common/sound_alsa.c
index 2719d07..a9c3ae1 100644
--- a/src/common/sound_alsa.c
+++ b/src/common/sound_alsa.c
@@ -19,6 +19,7 @@
#include <stdlib.h>
#include <stdint.h>
+#include <math.h>
#include <alsa/asoundlib.h>
#include "sample.h"
#include "debug.h"
@@ -30,6 +31,8 @@ typedef struct sound {
double spl_deviation; /* how much deviation is one sample step */
double paging_phaseshift; /* phase to shift every sample */
double paging_phase; /* current phase */
+ double rx_frequency[2]; /* rx frequency of radio connected to channel */
+ dispmeasparam_t *dmp[2];
} sound_t;
static int set_hw_params(snd_pcm_t *handle, int samplerate, int *channels)
@@ -185,6 +188,18 @@ void *sound_open(const char *audiodev, double __attribute__((unused)) *tx_freque
if (rc < 0)
goto error;
+ if (rx_frequency) {
+ sender_t *sender;
+ int i;
+ for (i = 0; i < channels; i++) {
+ sound->rx_frequency[i] = rx_frequency[i];
+ sender = get_sender_by_empfangsfrequenz(sound->rx_frequency[i]);
+ if (!sender)
+ continue;
+ sound->dmp[i] = display_measurements_add(sender, "RX Level", "%.1f dB", DISPLAY_MEAS_PEAK, DISPLAY_MEAS_LEFT, -96.0, 0.0, -INFINITY);
+ }
+ }
+
return sound;
error:
@@ -344,6 +359,7 @@ int sound_read(void *inst, sample_t **samples, int num, int channels)
double spl_deviation = sound->spl_deviation;
int16_t buff[num << 1];
int32_t spl;
+ int32_t max[2], a;
int in, rc;
int i, ii;
@@ -372,25 +388,51 @@ int sound_read(void *inst, sample_t **samples, int num, int channels)
return rc;
}
+ if (rc == 0)
+ return rc;
+
if (sound->cchannels == 2) {
if (channels < 2) {
for (i = 0, ii = 0; i < rc; i++) {
spl = buff[ii++];
spl += buff[ii++];
+ a = (spl >= 0) ? spl : -spl;
+ if (i == 0 || a > max[0])
+ max[0] = a;
samples[0][i] = (double)spl * spl_deviation;
}
} else {
for (i = 0, ii = 0; i < rc; i++) {
- samples[0][i] = (double)buff[ii++] * spl_deviation;
- samples[1][i] = (double)buff[ii++] * spl_deviation;
+ spl = buff[ii++];
+ a = (spl >= 0) ? spl : -spl;
+ if (i == 0 || a > max[0])
+ max[0] = a;
+ samples[0][i] = (double)spl * spl_deviation;
+ spl = buff[ii++];
+ a = (spl >= 0) ? spl : -spl;
+ if (i == 0 || a > max[1])
+ max[1] = a;
+ samples[1][i] = (double)spl * spl_deviation;
}
}
} else {
for (i = 0, ii = 0; i < rc; i++) {
- samples[0][i] = (double)buff[ii++] * spl_deviation;
+ spl = buff[ii++];
+ a = (spl >= 0) ? spl : -spl;
+ if (i == 0 || a > max[0])
+ max[0] = a;
+ samples[0][i] = (double)spl * spl_deviation;
}
}
+ sender_t *sender;
+ for (i = 0; i < channels; i++) {
+ sender = get_sender_by_empfangsfrequenz(sound->rx_frequency[i]);
+ if (!sender)
+ continue;
+ display_measurements_update(sound->dmp[i], log10((double)max[i] / 32768.0) * 20, 0.0);
+ }
+
return rc;
}