Add function to display measurements on screen
Use 'm' key to toggle display.
This commit is contained in:
parent
e84d7a082c
commit
ba036de226
|
@ -46,6 +46,10 @@ typedef struct amps {
|
||||||
enum amps_state state;
|
enum amps_state state;
|
||||||
int channel_busy; /* indicate channel is busy while receiving */
|
int channel_busy; /* indicate channel is busy while receiving */
|
||||||
|
|
||||||
|
/* display measurements */
|
||||||
|
dispmeasparam_t *dmp_frame_level;
|
||||||
|
dispmeasparam_t *dmp_frame_quality;
|
||||||
|
|
||||||
/* system info */
|
/* system info */
|
||||||
amps_si si;
|
amps_si si;
|
||||||
|
|
||||||
|
|
|
@ -268,6 +268,9 @@ int dsp_init_sender(amps_t *amps, int tolerant)
|
||||||
/* be more tolerant when syncing */
|
/* be more tolerant when syncing */
|
||||||
amps->fsk_rx_sync_tolerant = tolerant;
|
amps->fsk_rx_sync_tolerant = tolerant;
|
||||||
|
|
||||||
|
amps->dmp_frame_level = display_measurements_add(&s->sender, "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, "Frame Quality", "%.1f %% (last)", DISPLAY_MEAS_LAST, DISPLAY_MEAS_LEFT, 0.0, 100.0, 100.0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
@ -606,6 +609,10 @@ prepare_frame:
|
||||||
if (amps->fsk_rx_frame_count == amps->fsk_rx_frame_length) {
|
if (amps->fsk_rx_frame_count == amps->fsk_rx_frame_length) {
|
||||||
int more;
|
int more;
|
||||||
|
|
||||||
|
/* update measurements */
|
||||||
|
display_measurements_update(amps->dmp_frame_level, amps->fsk_rx_frame_level / (double)amps->fsk_rx_frame_count * 100.0, 0.0);
|
||||||
|
display_measurements_update(amps->dmp_frame_quality, amps->fsk_rx_frame_quality / (double)amps->fsk_rx_frame_count * 100.0, 0.0);
|
||||||
|
|
||||||
/* a complete frame was received, so we process it */
|
/* a complete frame was received, so we process it */
|
||||||
amps->fsk_rx_frame[amps->fsk_rx_frame_count] = '\0';
|
amps->fsk_rx_frame[amps->fsk_rx_frame_count] = '\0';
|
||||||
more = amps_decode_frame(amps, amps->fsk_rx_frame, amps->fsk_rx_frame_count, amps->fsk_rx_frame_level / (double)amps->fsk_rx_frame_count, amps->fsk_rx_frame_quality / amps->fsk_rx_frame_level, (amps->fsk_rx_sync == FSK_SYNC_NEGATIVE));
|
more = amps_decode_frame(amps, amps->fsk_rx_frame, amps->fsk_rx_frame_count, amps->fsk_rx_frame_level / (double)amps->fsk_rx_frame_count, amps->fsk_rx_frame_quality / amps->fsk_rx_frame_level, (amps->fsk_rx_sync == FSK_SYNC_NEGATIVE));
|
||||||
|
|
|
@ -25,6 +25,10 @@ typedef struct anetz {
|
||||||
char station_id[8]; /* current station ID */
|
char station_id[8]; /* current station ID */
|
||||||
struct timer timer;
|
struct timer timer;
|
||||||
|
|
||||||
|
/* display measurements */
|
||||||
|
dispmeasparam_t *dmp_tone_level;
|
||||||
|
dispmeasparam_t *dmp_tone_quality;
|
||||||
|
|
||||||
/* dsp states */
|
/* dsp states */
|
||||||
enum dsp_mode dsp_mode; /* current mode: audio, durable tone 0 or 1, paging */
|
enum dsp_mode dsp_mode; /* current mode: audio, durable tone 0 or 1, paging */
|
||||||
goertzel_t fsk_tone_goertzel[2]; /* filter for tone decoding */
|
goertzel_t fsk_tone_goertzel[2]; /* filter for tone decoding */
|
||||||
|
|
|
@ -42,6 +42,8 @@
|
||||||
#define TX_PEAK_PAGE (15000.0 / DBM0_DEVIATION) /* 15 kHz, no emphasis */
|
#define TX_PEAK_PAGE (15000.0 / DBM0_DEVIATION) /* 15 kHz, no emphasis */
|
||||||
#define MAX_DISPLAY (15000.0 / DBM0_DEVIATION) /* 15 kHz, no emphasis */
|
#define MAX_DISPLAY (15000.0 / DBM0_DEVIATION) /* 15 kHz, no emphasis */
|
||||||
#define CHUNK_DURATION 0.010 /* 10 ms */
|
#define CHUNK_DURATION 0.010 /* 10 ms */
|
||||||
|
#define TONE_THRESHOLD 0.05
|
||||||
|
#define QUAL_THRESHOLD 0.5
|
||||||
|
|
||||||
// FIXME: how long until we detect a tone?
|
// FIXME: how long until we detect a tone?
|
||||||
#define TONE_DETECT_TH 8 /* chunk intervals to detect continuous tone */
|
#define TONE_DETECT_TH 8 /* chunk intervals to detect continuous tone */
|
||||||
|
@ -108,6 +110,9 @@ int dsp_init_sender(anetz_t *anetz, double page_gain, int page_sequence)
|
||||||
anetz->tone_phaseshift65536 = 65536.0 / ((double)anetz->sender.samplerate / tone);
|
anetz->tone_phaseshift65536 = 65536.0 / ((double)anetz->sender.samplerate / tone);
|
||||||
PDEBUG(DDSP, DEBUG_DEBUG, "TX %.0f Hz phaseshift = %.4f\n", tone, anetz->tone_phaseshift65536);
|
PDEBUG(DDSP, DEBUG_DEBUG, "TX %.0f Hz phaseshift = %.4f\n", tone, anetz->tone_phaseshift65536);
|
||||||
|
|
||||||
|
anetz->dmp_tone_level = display_measurements_add(&anetz->sender, "Tone Level", "%.1f %%", DISPLAY_MEAS_LAST, DISPLAY_MEAS_LEFT, 0.0, 150.0, 100.0);
|
||||||
|
anetz->dmp_tone_quality = display_measurements_add(&anetz->sender, "Tone Quality", "%.1f %%", DISPLAY_MEAS_LAST, DISPLAY_MEAS_LEFT, 0.0, 100.0, 100.0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,7 +128,7 @@ void dsp_cleanup_sender(anetz_t *anetz)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Count duration of tone and indicate detection/loss to protocol handler. */
|
/* Count duration of tone and indicate detection/loss to protocol handler. */
|
||||||
static void fsk_receive_tone(anetz_t *anetz, int tone, int goodtone, double level)
|
static void fsk_receive_tone(anetz_t *anetz, int tone, int goodtone, double level, double quality)
|
||||||
{
|
{
|
||||||
/* lost tone because it is not good anymore or has changed */
|
/* lost tone because it is not good anymore or has changed */
|
||||||
if (!goodtone || tone != anetz->tone_detected) {
|
if (!goodtone || tone != anetz->tone_detected) {
|
||||||
|
@ -145,7 +150,7 @@ static void fsk_receive_tone(anetz_t *anetz, int tone, int goodtone, double leve
|
||||||
if (anetz->tone_count >= TONE_DETECT_TH)
|
if (anetz->tone_count >= TONE_DETECT_TH)
|
||||||
audio_reset_loss(&anetz->sender.loss);
|
audio_reset_loss(&anetz->sender.loss);
|
||||||
if (anetz->tone_count == TONE_DETECT_TH) {
|
if (anetz->tone_count == TONE_DETECT_TH) {
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_INFO, "Detecting continuous %.0f Hz tone. (level = %d%%)\n", fsk_tones[anetz->tone_detected], (int)(level * 100.0 + 0.5));
|
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);
|
anetz_receive_tone(anetz, anetz->tone_detected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -153,7 +158,7 @@ static void fsk_receive_tone(anetz_t *anetz, int tone, int goodtone, double leve
|
||||||
/* Filter one chunk of audio an detect tone, quality and loss of signal. */
|
/* Filter one chunk of audio an detect tone, quality and loss of signal. */
|
||||||
static void fsk_decode_chunk(anetz_t *anetz, sample_t *spl, int max)
|
static void fsk_decode_chunk(anetz_t *anetz, sample_t *spl, int max)
|
||||||
{
|
{
|
||||||
double level, result[2];
|
double level, result[2], quality[2];
|
||||||
|
|
||||||
level = audio_level(spl, max);
|
level = audio_level(spl, max);
|
||||||
|
|
||||||
|
@ -162,22 +167,25 @@ static void fsk_decode_chunk(anetz_t *anetz, sample_t *spl, int max)
|
||||||
|
|
||||||
audio_goertzel(anetz->fsk_tone_goertzel, spl, max, 0, result, 2);
|
audio_goertzel(anetz->fsk_tone_goertzel, spl, max, 0, result, 2);
|
||||||
|
|
||||||
/* show quality of tone */
|
/* normalize quality of tones and level */
|
||||||
if (anetz->sender.loopback) {
|
quality[0] = result[0] / level;
|
||||||
/* adjust level, so we get peak of sine curve */
|
quality[1] = result[1] / level;
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_NOTICE, "Tone %.0f: Level=%3.0f%% Quality=%3.0f%%\n", fsk_tones[1], level / 0.63662 * 100.0 / TX_PEAK_TONE, result[1] / level * 100.0);
|
/* adjust level, so we get peak of sine curve */
|
||||||
}
|
level = level / 0.63662 / TX_PEAK_TONE;
|
||||||
if (level / 0.63 > 0.05 && result[0] / level > 0.5)
|
/* show tones */
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_INFO, "Tone %.0f: Level=%3.0f%% Quality=%3.0f%%\n", fsk_tones[0], level / 0.63662 * 100.0 / TX_PEAK_TONE, result[0] / level * 100.0);
|
display_measurements_update(anetz->dmp_tone_level, level * 100.0, 0.0);
|
||||||
|
display_measurements_update(anetz->dmp_tone_quality, quality[1] * 100.0, 0.0);
|
||||||
|
if ((level > TONE_THRESHOLD && quality[1] > QUAL_THRESHOLD) || anetz->sender.loopback)
|
||||||
|
PDEBUG_CHAN(DDSP, DEBUG_INFO, "Tone %.0f: Level=%3.0f%% Quality=%3.0f%%\n", fsk_tones[1], level * 100.0, quality[1] * 100.0);
|
||||||
|
|
||||||
/* adjust level, so we get peak of sine curve */
|
/* adjust level, so we get peak of sine curve */
|
||||||
/* indicate detected tone */
|
/* indicate detected tone */
|
||||||
if (level / 0.63 > 0.05 && result[0] / level > 0.5)
|
if (level > TONE_THRESHOLD && quality[0] > QUAL_THRESHOLD)
|
||||||
fsk_receive_tone(anetz, 0, 1, level / 0.63662 / TX_PEAK_TONE);
|
fsk_receive_tone(anetz, 0, 1, level, quality[0]);
|
||||||
else if (level / 0.63 > 0.05 && result[1] / level > 0.5)
|
else if (level > TONE_THRESHOLD && quality[1] > QUAL_THRESHOLD)
|
||||||
fsk_receive_tone(anetz, 1, 1, level / 0.63662 / TX_PEAK_TONE);
|
fsk_receive_tone(anetz, 1, 1, level, quality[1]);
|
||||||
else
|
else
|
||||||
fsk_receive_tone(anetz, -1, 0, level / 0.63662 / TX_PEAK_TONE);
|
fsk_receive_tone(anetz, -1, 0, level, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process received audio stream from radio unit. */
|
/* Process received audio stream from radio unit. */
|
||||||
|
|
|
@ -445,16 +445,16 @@ void bnetz_receive_tone(bnetz_t *bnetz, int bit)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* A digit was received. */
|
/* A digit was received. */
|
||||||
void bnetz_receive_telegramm(bnetz_t *bnetz, uint16_t telegramm, double level_avg, double level_dev, double quality_avg)
|
void bnetz_receive_telegramm(bnetz_t *bnetz, uint16_t telegramm, double level_avg, double level_stddev, double quality_avg)
|
||||||
{
|
{
|
||||||
struct impulstelegramm *it;
|
struct impulstelegramm *it;
|
||||||
int digit = 0;
|
int digit = 0;
|
||||||
|
|
||||||
/* drop any telegramm that is too bad */
|
/* drop any telegramm that is too bad */
|
||||||
if (level_dev / level_avg > 0.2)
|
if (level_stddev / level_avg > 0.2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_INFO, "RX Level: average=%.0f%% deviation=%.0f%% Quality: %.0f%%\n", level_avg * 100.0, level_dev / level_avg * 100.0, quality_avg * 100.0);
|
PDEBUG_CHAN(DDSP, DEBUG_INFO, "RX Level: average=%.0f%% standard deviation=%.0f%% Quality: %.0f%%\n", level_avg * 100.0, level_stddev / level_avg * 100.0, quality_avg * 100.0);
|
||||||
|
|
||||||
it = bnetz_telegramm2digit(telegramm);
|
it = bnetz_telegramm2digit(telegramm);
|
||||||
if (it) {
|
if (it) {
|
||||||
|
|
|
@ -75,6 +75,13 @@ typedef struct bnetz {
|
||||||
struct timer timer;
|
struct timer timer;
|
||||||
int trenn_count; /* count number of release messages */
|
int trenn_count; /* count number of release messages */
|
||||||
|
|
||||||
|
/* display measurements */
|
||||||
|
dispmeasparam_t *dmp_tone_level;
|
||||||
|
dispmeasparam_t *dmp_tone_quality;
|
||||||
|
dispmeasparam_t *dmp_frame_level;
|
||||||
|
dispmeasparam_t *dmp_frame_stddev;
|
||||||
|
dispmeasparam_t *dmp_frame_quality;
|
||||||
|
|
||||||
/* dsp states */
|
/* dsp states */
|
||||||
enum dsp_mode dsp_mode; /* current mode: audio, durable tone 0 or 1, "Telegramm" */
|
enum dsp_mode dsp_mode; /* current mode: audio, durable tone 0 or 1, "Telegramm" */
|
||||||
fsk_t fsk; /* fsk modem instance */
|
fsk_t fsk; /* fsk modem instance */
|
||||||
|
|
|
@ -112,6 +112,12 @@ int dsp_init_sender(bnetz_t *bnetz)
|
||||||
bnetz->meter_phaseshift65536 = 65536.0 / ((double)bnetz->sender.samplerate / METERING_HZ);
|
bnetz->meter_phaseshift65536 = 65536.0 / ((double)bnetz->sender.samplerate / METERING_HZ);
|
||||||
PDEBUG(DDSP, DEBUG_DEBUG, "dial_phaseshift = %.4f\n", bnetz->meter_phaseshift65536);
|
PDEBUG(DDSP, DEBUG_DEBUG, "dial_phaseshift = %.4f\n", bnetz->meter_phaseshift65536);
|
||||||
|
|
||||||
|
bnetz->dmp_tone_level = display_measurements_add(&bnetz->sender, "Tone Level", "%.1f %%", DISPLAY_MEAS_LAST, DISPLAY_MEAS_LEFT, 0.0, 150.0, 100.0);
|
||||||
|
bnetz->dmp_tone_quality = display_measurements_add(&bnetz->sender, "Tone Quality", "%.1f %%", DISPLAY_MEAS_LAST, DISPLAY_MEAS_LEFT, 0.0, 100.0, 100.0);
|
||||||
|
bnetz->dmp_frame_level = display_measurements_add(&bnetz->sender, "Frame Level", "%.1f %% (last)", DISPLAY_MEAS_LAST, DISPLAY_MEAS_LEFT, 0.0, 150.0, 100.0);
|
||||||
|
bnetz->dmp_frame_stddev = display_measurements_add(&bnetz->sender, "Frame Stddev", "%.1f %% (last)", DISPLAY_MEAS_LAST, DISPLAY_MEAS_LEFT, 0.0, 100.0, 100.0);
|
||||||
|
bnetz->dmp_frame_quality = display_measurements_add(&bnetz->sender, "Frame Quality", "%.1f %% (last)", DISPLAY_MEAS_LAST, DISPLAY_MEAS_LEFT, 0.0, 100.0, 100.0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,13 +167,17 @@ static void fsk_receive_tone(bnetz_t *bnetz, int bit, int goodtone, double level
|
||||||
/* Collect 16 data bits (digit) and check for sync mark '01110'. */
|
/* Collect 16 data bits (digit) and check for sync mark '01110'. */
|
||||||
static void fsk_receive_bit(void *inst, int bit, double quality, double level)
|
static void fsk_receive_bit(void *inst, int bit, double quality, double level)
|
||||||
{
|
{
|
||||||
double level_avg, level_dev, quality_avg;
|
double level_avg, level_stddev, quality_avg;
|
||||||
bnetz_t *bnetz = (bnetz_t *)inst;
|
bnetz_t *bnetz = (bnetz_t *)inst;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* normalize FSK level */
|
/* normalize FSK level */
|
||||||
level /= TX_PEAK_FSK;
|
level /= TX_PEAK_FSK;
|
||||||
|
|
||||||
|
/* update measurements */
|
||||||
|
display_measurements_update(bnetz->dmp_tone_level, level * 100.0 , 0.0);
|
||||||
|
display_measurements_update(bnetz->dmp_tone_quality, quality * 100.0, 0.0);
|
||||||
|
|
||||||
/* continuous tone detection */
|
/* continuous tone detection */
|
||||||
if (level > 0.10 && quality > 0.10) {
|
if (level > 0.10 && quality > 0.10) {
|
||||||
fsk_receive_tone(bnetz, bit, 1, level, quality);
|
fsk_receive_tone(bnetz, bit, 1, level, quality);
|
||||||
|
@ -188,7 +198,7 @@ static void fsk_receive_bit(void *inst, int bit, double quality, double level)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* average level and quality */
|
/* average level and quality */
|
||||||
level_avg = level_dev = quality_avg = 0;
|
level_avg = level_stddev = quality_avg = 0;
|
||||||
for (i = 0; i < 16; i++) {
|
for (i = 0; i < 16; i++) {
|
||||||
level_avg += bnetz->rx_telegramm_level[bnetz->rx_telegramm_qualidx];
|
level_avg += bnetz->rx_telegramm_level[bnetz->rx_telegramm_qualidx];
|
||||||
quality_avg += bnetz->rx_telegramm_quality[bnetz->rx_telegramm_qualidx];
|
quality_avg += bnetz->rx_telegramm_quality[bnetz->rx_telegramm_qualidx];
|
||||||
|
@ -198,14 +208,19 @@ static void fsk_receive_bit(void *inst, int bit, double quality, double level)
|
||||||
level_avg /= 16.0; quality_avg /= 16.0;
|
level_avg /= 16.0; quality_avg /= 16.0;
|
||||||
for (i = 0; i < 16; i++) {
|
for (i = 0; i < 16; i++) {
|
||||||
level = bnetz->rx_telegramm_level[bnetz->rx_telegramm_qualidx];
|
level = bnetz->rx_telegramm_level[bnetz->rx_telegramm_qualidx];
|
||||||
level_dev += (level - level_avg) * (level - level_avg);
|
level_stddev += (level - level_avg) * (level - level_avg);
|
||||||
if (++bnetz->rx_telegramm_qualidx == 16)
|
if (++bnetz->rx_telegramm_qualidx == 16)
|
||||||
bnetz->rx_telegramm_qualidx = 0;
|
bnetz->rx_telegramm_qualidx = 0;
|
||||||
}
|
}
|
||||||
level_dev = sqrt(level_dev / 16.0);
|
level_stddev = sqrt(level_stddev / 16.0);
|
||||||
|
|
||||||
/* send telegramm */
|
/* update measurements */
|
||||||
bnetz_receive_telegramm(bnetz, bnetz->rx_telegramm, level_avg, level_dev, quality_avg);
|
display_measurements_update(bnetz->dmp_frame_level, level_avg * 100.0 , 0.0);
|
||||||
|
display_measurements_update(bnetz->dmp_frame_stddev, level_stddev / level_avg * 100.0, 0.0);
|
||||||
|
display_measurements_update(bnetz->dmp_frame_quality, quality_avg * 100.0, 0.0);
|
||||||
|
|
||||||
|
/* receive telegramm */
|
||||||
|
bnetz_receive_telegramm(bnetz, bnetz->rx_telegramm, level_avg, level_stddev, quality_avg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process received audio stream from radio unit. */
|
/* Process received audio stream from radio unit. */
|
||||||
|
|
|
@ -192,6 +192,9 @@ int fsk_fm_init(fsk_fm_demod_t *fsk, cnetz_t *cnetz, int samplerate, double bitr
|
||||||
printf("**** Writing decoder debug file '%s' ****\n", debug_filename);
|
printf("**** Writing decoder debug file '%s' ****\n", debug_filename);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
fsk->dmp_frame_level = display_measurements_add(&cnetz->sender, "Frame Level", "%.1f %% (last)", DISPLAY_MEAS_LAST, DISPLAY_MEAS_LEFT, 0.0, 150.0, 100.0);
|
||||||
|
fsk->dmp_frame_stddev = display_measurements_add(&cnetz->sender, "Frame Stddev", "%.1f %% (last)", DISPLAY_MEAS_LAST, DISPLAY_MEAS_LEFT, 0.0, 100.0, 100.0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
@ -393,6 +396,9 @@ got_sync:
|
||||||
/* received 662 bits after start of block (10 SPK blocks + 1 bit (== 2 level changes)) */
|
/* received 662 bits after start of block (10 SPK blocks + 1 bit (== 2 level changes)) */
|
||||||
fsk->sync_time = fmod(fsk->sync_time - (66*10+2) + BITS_PER_SUPERFRAME, BITS_PER_SUPERFRAME);
|
fsk->sync_time = fmod(fsk->sync_time - (66*10+2) + BITS_PER_SUPERFRAME, BITS_PER_SUPERFRAME);
|
||||||
}
|
}
|
||||||
|
/* update measurements */
|
||||||
|
display_measurements_update(fsk->dmp_frame_level, fabs(fsk->sync_level) / fsk->cnetz->fsk_deviation * 100.0, 0.0);
|
||||||
|
display_measurements_update(fsk->dmp_frame_stddev, fsk->sync_stddev / fabs(fsk->sync_level) * 100.0, 0.0);
|
||||||
/* receive frame */
|
/* receive frame */
|
||||||
cnetz_decode_telegramm(fsk->cnetz, fsk->rx_buffer, fsk->sync_level, fsk->sync_time, fsk->sync_stddev);
|
cnetz_decode_telegramm(fsk->cnetz, fsk->rx_buffer, fsk->sync_level, fsk->sync_time, fsk->sync_stddev);
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,10 @@ typedef struct fsk_fm_demod {
|
||||||
double change_when[256]; /* ring buffer to store time when level has changed */
|
double change_when[256]; /* ring buffer to store time when level has changed */
|
||||||
uint8_t change_pos; /* index for next write */
|
uint8_t change_pos; /* index for next write */
|
||||||
|
|
||||||
|
/* display measurements */
|
||||||
|
dispmeasparam_t *dmp_frame_level;
|
||||||
|
dispmeasparam_t *dmp_frame_stddev;
|
||||||
|
|
||||||
/* debug */
|
/* debug */
|
||||||
FILE *debug_fp; /* file pointer for debugging output */
|
FILE *debug_fp; /* file pointer for debugging output */
|
||||||
} fsk_fm_demod_t;
|
} fsk_fm_demod_t;
|
||||||
|
|
|
@ -19,7 +19,8 @@ libcommon_a_SOURCES = \
|
||||||
fft.c \
|
fft.c \
|
||||||
fm_modulation.c \
|
fm_modulation.c \
|
||||||
fsk.c \
|
fsk.c \
|
||||||
display_wave.c
|
display_wave.c \
|
||||||
|
display_measurements.c
|
||||||
|
|
||||||
libmobile_a_SOURCES = \
|
libmobile_a_SOURCES = \
|
||||||
sender.c \
|
sender.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);
|
// 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_wave_limit_scroll(1);
|
||||||
display_status_limit_scroll(1);
|
display_status_limit_scroll(1);
|
||||||
|
display_measurements_limit_scroll(1);
|
||||||
#ifdef HAVE_SDR
|
#ifdef HAVE_SDR
|
||||||
display_iq_limit_scroll(1);
|
display_iq_limit_scroll(1);
|
||||||
display_spectrum_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);
|
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_wave_limit_scroll(0);
|
||||||
display_status_limit_scroll(0);
|
display_status_limit_scroll(0);
|
||||||
|
display_measurements_limit_scroll(0);
|
||||||
#ifdef HAVE_SDR
|
#ifdef HAVE_SDR
|
||||||
display_iq_limit_scroll(0);
|
display_iq_limit_scroll(0);
|
||||||
display_spectrum_limit_scroll(0);
|
display_spectrum_limit_scroll(0);
|
||||||
|
|
|
@ -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
|
#define MAX_DISPLAY_WIDTH 1024
|
||||||
|
|
||||||
|
@ -11,6 +12,40 @@ typedef struct display_wave {
|
||||||
sample_t buffer[MAX_DISPLAY_WIDTH];
|
sample_t buffer[MAX_DISPLAY_WIDTH];
|
||||||
} dispwav_t;
|
} 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
|
#define MAX_DISPLAY_IQ 1024
|
||||||
|
|
||||||
typedef struct display_iq {
|
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_subscriber(const char *number, const char *state);
|
||||||
void display_status_end(void);
|
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_init(int samplerate);
|
||||||
void display_iq_on(int on);
|
void display_iq_on(int on);
|
||||||
void display_iq_limit_scroll(int on);
|
void display_iq_limit_scroll(int on);
|
||||||
|
|
|
@ -26,8 +26,6 @@
|
||||||
#include "sample.h"
|
#include "sample.h"
|
||||||
#include "sender.h"
|
#include "sender.h"
|
||||||
|
|
||||||
#define DISPLAY_INTERVAL 0.04
|
|
||||||
|
|
||||||
/* must be odd value! */
|
/* must be odd value! */
|
||||||
#define SIZE 23
|
#define SIZE 23
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ static int line_count = 0;
|
||||||
static int lines_total = 0;
|
static int lines_total = 0;
|
||||||
static char screen[MAX_HEIGHT_STATUS][MAX_DISPLAY_WIDTH];
|
static char screen[MAX_HEIGHT_STATUS][MAX_DISPLAY_WIDTH];
|
||||||
|
|
||||||
void print_status(int on)
|
static void print_status(int on)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i, j;
|
||||||
int w, h;
|
int w, h;
|
||||||
|
|
|
@ -26,8 +26,6 @@
|
||||||
#include "sample.h"
|
#include "sample.h"
|
||||||
#include "sender.h"
|
#include "sender.h"
|
||||||
|
|
||||||
#define DISPLAY_INTERVAL 0.04
|
|
||||||
|
|
||||||
#define HEIGHT 11
|
#define HEIGHT 11
|
||||||
|
|
||||||
static int num_sender = 0;
|
static int num_sender = 0;
|
||||||
|
|
|
@ -152,10 +152,11 @@ void main_mobile_print_help(const char *arg0, const char *ext_usage)
|
||||||
void main_mobile_print_hotkeys(void)
|
void main_mobile_print_hotkeys(void)
|
||||||
{
|
{
|
||||||
printf("\n");
|
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 'h' key to hangup.\n");
|
||||||
printf("Press 'w' key to toggle display of RX wave form.\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 'c' key to toggle display of channel status.\n");
|
||||||
|
printf("Press 'm' key to toggle display of measurement value.\n");
|
||||||
#ifdef HAVE_SDR
|
#ifdef HAVE_SDR
|
||||||
sdr_config_print_hotkeys();
|
sdr_config_print_hotkeys();
|
||||||
#endif
|
#endif
|
||||||
|
@ -524,35 +525,49 @@ next_char:
|
||||||
*quit = 1;
|
*quit = 1;
|
||||||
goto next_char;
|
goto next_char;
|
||||||
case 'w':
|
case 'w':
|
||||||
/* toggle display */
|
/* toggle wave display */
|
||||||
|
display_status_on(0);
|
||||||
|
display_measurements_on(0);
|
||||||
#ifdef HAVE_SDR
|
#ifdef HAVE_SDR
|
||||||
display_iq_on(0);
|
display_iq_on(0);
|
||||||
display_spectrum_on(0);
|
display_spectrum_on(0);
|
||||||
#endif
|
#endif
|
||||||
display_status_on(0);
|
|
||||||
display_wave_on(-1);
|
display_wave_on(-1);
|
||||||
goto next_char;
|
goto next_char;
|
||||||
case 'c':
|
case 'c':
|
||||||
/* toggle display */
|
/* toggle call state display */
|
||||||
|
display_wave_on(0);
|
||||||
|
display_measurements_on(0);
|
||||||
#ifdef HAVE_SDR
|
#ifdef HAVE_SDR
|
||||||
display_iq_on(0);
|
display_iq_on(0);
|
||||||
display_spectrum_on(0);
|
display_spectrum_on(0);
|
||||||
#endif
|
#endif
|
||||||
display_wave_on(0);
|
|
||||||
display_status_on(-1);
|
display_status_on(-1);
|
||||||
goto next_char;
|
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
|
#ifdef HAVE_SDR
|
||||||
case 'q':
|
case 'q':
|
||||||
/* toggle display */
|
/* toggle IQ display */
|
||||||
display_wave_on(0);
|
display_wave_on(0);
|
||||||
display_status_on(0);
|
display_status_on(0);
|
||||||
|
display_measurements_on(0);
|
||||||
display_spectrum_on(0);
|
display_spectrum_on(0);
|
||||||
display_iq_on(-1);
|
display_iq_on(-1);
|
||||||
goto next_char;
|
goto next_char;
|
||||||
case 's':
|
case 's':
|
||||||
/* toggle spectrum */
|
/* toggle spectrum display */
|
||||||
display_wave_on(0);
|
display_wave_on(0);
|
||||||
display_status_on(0);
|
display_status_on(0);
|
||||||
|
display_measurements_on(0);
|
||||||
display_iq_on(0);
|
display_iq_on(0);
|
||||||
display_spectrum_on(-1);
|
display_spectrum_on(-1);
|
||||||
goto next_char;
|
goto next_char;
|
||||||
|
@ -569,6 +584,8 @@ next_char:
|
||||||
if (myhandler)
|
if (myhandler)
|
||||||
myhandler();
|
myhandler();
|
||||||
|
|
||||||
|
display_measurements((double)interval / 1000.0);
|
||||||
|
|
||||||
now = get_time();
|
now = get_time();
|
||||||
|
|
||||||
/* sleep interval */
|
/* sleep interval */
|
||||||
|
|
|
@ -32,8 +32,7 @@ enum paging_signal;
|
||||||
#include "sample.h"
|
#include "sample.h"
|
||||||
#include "fm_modulation.h"
|
#include "fm_modulation.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "wave.h"
|
#include "sender.h"
|
||||||
#include "display.h"
|
|
||||||
#include "sdr_config.h"
|
#include "sdr_config.h"
|
||||||
#include "sdr.h"
|
#include "sdr.h"
|
||||||
#ifdef HAVE_UHD
|
#ifdef HAVE_UHD
|
||||||
|
@ -68,6 +67,9 @@ typedef struct sdr_chan {
|
||||||
double rx_frequency; /* frequency used */
|
double rx_frequency; /* frequency used */
|
||||||
fm_mod_t mod; /* modulator instance */
|
fm_mod_t mod; /* modulator instance */
|
||||||
fm_demod_t demod; /* demodulator instance */
|
fm_demod_t demod; /* demodulator instance */
|
||||||
|
dispmeasparam_t *dmp_rf_level;
|
||||||
|
dispmeasparam_t *dmp_freq_offset;
|
||||||
|
dispmeasparam_t *dmp_deviation;
|
||||||
} sdr_chan_t;
|
} sdr_chan_t;
|
||||||
|
|
||||||
typedef struct sdr {
|
typedef struct sdr {
|
||||||
|
@ -340,6 +342,15 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
|
||||||
goto error;
|
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) {
|
if (sdr_config->swap_links) {
|
||||||
|
@ -747,7 +758,7 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels)
|
||||||
#endif
|
#endif
|
||||||
if (count <= 0)
|
if (count <= 0)
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sdr->wave_rx_rec.fp) {
|
if (sdr->wave_rx_rec.fp) {
|
||||||
sample_t *spl_list[2] = { sdr->wavespl0, sdr->wavespl1 };
|
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);
|
display_spectrum(buff, count);
|
||||||
|
|
||||||
if (channels) {
|
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);
|
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;
|
return count;
|
||||||
|
|
|
@ -44,7 +44,7 @@ int sender_create(sender_t *sender, int kanal, double sendefrequenz, double empf
|
||||||
|
|
||||||
sender->kanal = kanal;
|
sender->kanal = kanal;
|
||||||
sender->sendefrequenz = sendefrequenz;
|
sender->sendefrequenz = sendefrequenz;
|
||||||
sender->empfangsfrequenz = empfangsfrequenz;
|
sender->empfangsfrequenz = (loopback) ? sendefrequenz : empfangsfrequenz;
|
||||||
strncpy(sender->audiodev, audiodev, sizeof(sender->audiodev) - 1);
|
strncpy(sender->audiodev, audiodev, sizeof(sender->audiodev) - 1);
|
||||||
sender->samplerate = samplerate;
|
sender->samplerate = samplerate;
|
||||||
sender->rx_gain = rx_gain;
|
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;
|
sender_tailp = &sender->next;
|
||||||
|
|
||||||
display_wave_init(sender, samplerate);
|
display_wave_init(sender, samplerate);
|
||||||
|
display_measurements_init(sender, samplerate);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
error:
|
error:
|
||||||
|
@ -157,7 +158,6 @@ int sender_open_audio(int latspl)
|
||||||
{
|
{
|
||||||
sender_t *master, *inst;
|
sender_t *master, *inst;
|
||||||
int channels;
|
int channels;
|
||||||
double paging_frequency = 0.0;
|
|
||||||
int i;
|
int i;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -171,13 +171,10 @@ int sender_open_audio(int latspl)
|
||||||
for (inst = master; inst; inst = inst->slave) {
|
for (inst = master; inst; inst = inst->slave) {
|
||||||
channels++;
|
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) {
|
for (i = 0, inst = master; inst; i++, inst = inst->slave) {
|
||||||
tx_f[i] = inst->sendefrequenz;
|
tx_f[i] = inst->sendefrequenz;
|
||||||
if (inst->loopback)
|
rx_f[i] = inst->empfangsfrequenz;
|
||||||
rx_f[i] = inst->sendefrequenz;
|
|
||||||
else
|
|
||||||
rx_f[i] = inst->empfangsfrequenz;
|
|
||||||
if (inst->ruffrequenz)
|
if (inst->ruffrequenz)
|
||||||
paging_frequency = inst->ruffrequenz;
|
paging_frequency = inst->ruffrequenz;
|
||||||
}
|
}
|
||||||
|
@ -438,3 +435,15 @@ void sender_paging(sender_t *sender, int on)
|
||||||
sender->paging_on = 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -84,6 +84,9 @@ typedef struct sender {
|
||||||
|
|
||||||
/* display wave */
|
/* display wave */
|
||||||
dispwav_t dispwav; /* display wave form */
|
dispwav_t dispwav; /* display wave form */
|
||||||
|
|
||||||
|
/* display measurements */
|
||||||
|
dispmeas_t dispmeas; /* display measurements */
|
||||||
} sender_t;
|
} sender_t;
|
||||||
|
|
||||||
/* list of all senders */
|
/* 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_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_receive(sender_t *sender, sample_t *samples, int count);
|
||||||
void sender_paging(sender_t *sender, int on);
|
void sender_paging(sender_t *sender, int on);
|
||||||
|
sender_t *get_sender_by_empfangsfrequenz(double freq);
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <math.h>
|
||||||
#include <alsa/asoundlib.h>
|
#include <alsa/asoundlib.h>
|
||||||
#include "sample.h"
|
#include "sample.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
@ -30,6 +31,8 @@ typedef struct sound {
|
||||||
double spl_deviation; /* how much deviation is one sample step */
|
double spl_deviation; /* how much deviation is one sample step */
|
||||||
double paging_phaseshift; /* phase to shift every sample */
|
double paging_phaseshift; /* phase to shift every sample */
|
||||||
double paging_phase; /* current phase */
|
double paging_phase; /* current phase */
|
||||||
|
double rx_frequency[2]; /* rx frequency of radio connected to channel */
|
||||||
|
dispmeasparam_t *dmp[2];
|
||||||
} sound_t;
|
} sound_t;
|
||||||
|
|
||||||
static int set_hw_params(snd_pcm_t *handle, int samplerate, int *channels)
|
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)
|
if (rc < 0)
|
||||||
goto error;
|
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;
|
return sound;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
@ -344,6 +359,7 @@ int sound_read(void *inst, sample_t **samples, int num, int channels)
|
||||||
double spl_deviation = sound->spl_deviation;
|
double spl_deviation = sound->spl_deviation;
|
||||||
int16_t buff[num << 1];
|
int16_t buff[num << 1];
|
||||||
int32_t spl;
|
int32_t spl;
|
||||||
|
int32_t max[2], a;
|
||||||
int in, rc;
|
int in, rc;
|
||||||
int i, ii;
|
int i, ii;
|
||||||
|
|
||||||
|
@ -372,25 +388,51 @@ int sound_read(void *inst, sample_t **samples, int num, int channels)
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rc == 0)
|
||||||
|
return rc;
|
||||||
|
|
||||||
if (sound->cchannels == 2) {
|
if (sound->cchannels == 2) {
|
||||||
if (channels < 2) {
|
if (channels < 2) {
|
||||||
for (i = 0, ii = 0; i < rc; i++) {
|
for (i = 0, ii = 0; i < rc; i++) {
|
||||||
spl = buff[ii++];
|
spl = buff[ii++];
|
||||||
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;
|
samples[0][i] = (double)spl * spl_deviation;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (i = 0, ii = 0; i < rc; i++) {
|
for (i = 0, ii = 0; i < rc; i++) {
|
||||||
samples[0][i] = (double)buff[ii++] * spl_deviation;
|
spl = buff[ii++];
|
||||||
samples[1][i] = (double)buff[ii++] * spl_deviation;
|
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 {
|
} else {
|
||||||
for (i = 0, ii = 0; i < rc; i++) {
|
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;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -152,6 +152,9 @@ int dsp_init_sender(nmt_t *nmt, double deviation_factor)
|
||||||
/* dtmf */
|
/* dtmf */
|
||||||
dtmf_init(&nmt->dtmf, 8000);
|
dtmf_init(&nmt->dtmf, 8000);
|
||||||
|
|
||||||
|
nmt->dmp_frame_level = display_measurements_add(&nmt->sender, "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, "Frame Quality", "%.1f %% (last)", DISPLAY_MEAS_LAST, DISPLAY_MEAS_LEFT, 0.0, 100.0, 100.0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,6 +245,10 @@ static void fsk_receive_bit(void *inst, int bit, double quality, double level)
|
||||||
}
|
}
|
||||||
level /= 140.0; quality /= 140.0;
|
level /= 140.0; quality /= 140.0;
|
||||||
|
|
||||||
|
/* update measurements */
|
||||||
|
display_measurements_update(nmt->dmp_frame_level, level * 100.0, 0.0);
|
||||||
|
display_measurements_update(nmt->dmp_frame_quality, quality * 100.0, 0.0);
|
||||||
|
|
||||||
/* send telegramm */
|
/* send telegramm */
|
||||||
frames_elapsed = (nmt->rx_bits_count_current - nmt->rx_bits_count_last + 83) / 166; /* round to nearest frame */
|
frames_elapsed = (nmt->rx_bits_count_current - nmt->rx_bits_count_last + 83) / 166; /* round to nearest frame */
|
||||||
/* convert level so that received level at TX_PEAK_FSK results in 1.0 (100%) */
|
/* convert level so that received level at TX_PEAK_FSK results in 1.0 (100%) */
|
||||||
|
|
|
@ -90,6 +90,10 @@ typedef struct nmt {
|
||||||
char dialing[33]; /* dialed digits */
|
char dialing[33]; /* dialed digits */
|
||||||
int mft_num; /* counter for digit for MFT */
|
int mft_num; /* counter for digit for MFT */
|
||||||
|
|
||||||
|
/* display measurements */
|
||||||
|
dispmeasparam_t *dmp_frame_level;
|
||||||
|
dispmeasparam_t *dmp_frame_quality;
|
||||||
|
|
||||||
/* features */
|
/* features */
|
||||||
int compandor; /* if compandor shall be used */
|
int compandor; /* if compandor shall be used */
|
||||||
int supervisory; /* if set, use supervisory signal 1..4 */
|
int supervisory; /* if set, use supervisory signal 1..4 */
|
||||||
|
|
|
@ -109,6 +109,13 @@ int dsp_init_sender(r2000_t *r2000)
|
||||||
iir_highpass_init(&r2000->super_tx_hp, SUPER_CUTOFF_H, r2000->sender.samplerate, 2);
|
iir_highpass_init(&r2000->super_tx_hp, SUPER_CUTOFF_H, r2000->sender.samplerate, 2);
|
||||||
iir_highpass_init(&r2000->super_rx_hp, SUPER_CUTOFF_H, r2000->sender.samplerate, 2);
|
iir_highpass_init(&r2000->super_rx_hp, SUPER_CUTOFF_H, r2000->sender.samplerate, 2);
|
||||||
|
|
||||||
|
r2000->dmp_frame_level = display_measurements_add(&r2000->sender, "Frame Level", "%.1f %% (last)", DISPLAY_MEAS_LAST, DISPLAY_MEAS_LEFT, 0.0, 150.0, 100.0);
|
||||||
|
r2000->dmp_frame_quality = display_measurements_add(&r2000->sender, "Frame Quality", "%.1f %% (last)", DISPLAY_MEAS_LAST, DISPLAY_MEAS_LEFT, 0.0, 100.0, 100.0);
|
||||||
|
if (r2000->sysinfo.chan_type == CHAN_TYPE_TC || r2000->sysinfo.chan_type == CHAN_TYPE_CC_TC) {
|
||||||
|
r2000->dmp_super_level = display_measurements_add(&r2000->sender, "Super Level", "%.1f %%", DISPLAY_MEAS_AVG, DISPLAY_MEAS_LEFT, 0.0, 150.0, 100.0);
|
||||||
|
r2000->dmp_super_quality = display_measurements_add(&r2000->sender, "Super Quality", "%.1f %%", DISPLAY_MEAS_AVG, DISPLAY_MEAS_LEFT, 0.0, 100.0, 100.0);
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,6 +197,10 @@ static void fsk_receive_bit(void *inst, int bit, double quality, double level)
|
||||||
}
|
}
|
||||||
level /= (double)r2000->rx_max; quality /= (double)r2000->rx_max;
|
level /= (double)r2000->rx_max; quality /= (double)r2000->rx_max;
|
||||||
|
|
||||||
|
/* update measurements */
|
||||||
|
display_measurements_update(r2000->dmp_frame_level, level * 100.0, 0.0);
|
||||||
|
display_measurements_update(r2000->dmp_frame_quality, quality * 100.0, 0.0);
|
||||||
|
|
||||||
/* send frame to upper layer */
|
/* send frame to upper layer */
|
||||||
r2000_receive_frame(r2000, r2000->rx_frame, quality, level);
|
r2000_receive_frame(r2000, r2000->rx_frame, quality, level);
|
||||||
}
|
}
|
||||||
|
@ -202,6 +213,10 @@ static void super_receive_bit(void *inst, int bit, double quality, double level)
|
||||||
/* normalize supervisory level */
|
/* normalize supervisory level */
|
||||||
level /= TX_PEAK_SUPER;
|
level /= TX_PEAK_SUPER;
|
||||||
|
|
||||||
|
/* update measurements (if dmp_* params are NULL, we omit this) */
|
||||||
|
display_measurements_update(r2000->dmp_super_level, level * 100.0, 0.0);
|
||||||
|
display_measurements_update(r2000->dmp_super_quality, quality * 100.0, 0.0);
|
||||||
|
|
||||||
/* store bit */
|
/* store bit */
|
||||||
r2000->super_rx_word = (r2000->super_rx_word << 1) | bit;
|
r2000->super_rx_word = (r2000->super_rx_word << 1) | bit;
|
||||||
r2000->super_rx_level[r2000->super_rx_index] = level;
|
r2000->super_rx_level[r2000->super_rx_index] = level;
|
||||||
|
|
|
@ -73,6 +73,12 @@ typedef struct r2000 {
|
||||||
int page_try; /* the try number of calling the mobile */
|
int page_try; /* the try number of calling the mobile */
|
||||||
int tx_frame_count; /* to count repeated frames */
|
int tx_frame_count; /* to count repeated frames */
|
||||||
|
|
||||||
|
/* display measurements */
|
||||||
|
dispmeasparam_t *dmp_frame_level;
|
||||||
|
dispmeasparam_t *dmp_frame_quality;
|
||||||
|
dispmeasparam_t *dmp_super_level;
|
||||||
|
dispmeasparam_t *dmp_super_quality;
|
||||||
|
|
||||||
/* features */
|
/* features */
|
||||||
int compandor; /* if compandor shall be used */
|
int compandor; /* if compandor shall be used */
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@ int num_kanal = 1; /* only one channel used for debugging */
|
||||||
void clear_console_text() {}
|
void clear_console_text() {}
|
||||||
void print_console_text() {}
|
void print_console_text() {}
|
||||||
void display_status_limit_scroll() {}
|
void display_status_limit_scroll() {}
|
||||||
|
void *get_sender_by_empfangsfrequenz() { return NULL; }
|
||||||
|
|
||||||
static double __attribute__((__unused__)) modulation = 0.7; /* level of modulation for I/Q amplitudes */
|
static double __attribute__((__unused__)) modulation = 0.7; /* level of modulation for I/Q amplitudes */
|
||||||
static double frequency = 0.0;
|
static double frequency = 0.0;
|
||||||
|
|
Loading…
Reference in New Issue