C-Netz: Make demodulation algorithm (slope or leve) slectable via option

By default (auto), the algorithm is selected, depending on sound card
or SDR usage. For testing and debugging purpose, the algorithm can be
forced.
This commit is contained in:
Andreas Eversberg 2017-05-19 19:11:59 +02:00
parent c086e66b7c
commit 76a3484c5c
7 changed files with 55 additions and 12 deletions

View File

@ -216,7 +216,7 @@ int cnetz_init(void)
static void cnetz_go_idle(cnetz_t *cnetz);
/* Create transceiver instance and link to a list. */
int cnetz_create(int kanal, enum cnetz_chan_type chan_type, const char *audiodev, int use_sdr, int samplerate, double rx_gain, int auth, int ms_power, int measure_speed, double clock_speed[2], int polarity, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, int loopback)
int cnetz_create(int kanal, enum cnetz_chan_type chan_type, const char *audiodev, int use_sdr, enum demod_type demod, int samplerate, double rx_gain, int auth, int ms_power, int measure_speed, double clock_speed[2], int polarity, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, int loopback)
{
sender_t *sender;
cnetz_t *cnetz;
@ -290,7 +290,7 @@ int cnetz_create(int kanal, enum cnetz_chan_type chan_type, const char *audiodev
#endif
/* init audio processing */
rc = dsp_init_sender(cnetz, measure_speed, clock_speed, use_sdr);
rc = dsp_init_sender(cnetz, measure_speed, clock_speed, demod);
if (rc < 0) {
PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to init signal processing!\n");
goto error;

View File

@ -127,7 +127,7 @@ int cnetz_channel_by_short_name(const char *short_name);
const char *chan_type_short_name(enum cnetz_chan_type chan_type);
const char *chan_type_long_name(enum cnetz_chan_type chan_type);
int cnetz_init(void);
int cnetz_create(int kanal, enum cnetz_chan_type chan_type, const char *audiodev, int use_sdr, int samplerate, double rx_gain, int auth, int ms_power, int measure_speed, double clock_speed[2], int polarity, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, int loopback);
int cnetz_create(int kanal, enum cnetz_chan_type chan_type, const char *audiodev, int use_sdr, enum demod_type demod, int samplerate, double rx_gain, int auth, int ms_power, int measure_speed, double clock_speed[2], int polarity, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, int loopback);
void cnetz_destroy(sender_t *sender);
void cnetz_sync_frame(cnetz_t *cnetz, double sync, int ts);
int cnetz_meldeaufruf(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest);

View File

@ -83,7 +83,7 @@ static void dsp_init_ramp(cnetz_t *cnetz)
}
/* Init transceiver instance. */
int dsp_init_sender(cnetz_t *cnetz, int measure_speed, double clock_speed[2], int use_sdr)
int dsp_init_sender(cnetz_t *cnetz, int measure_speed, double clock_speed[2], enum demod_type demod)
{
int rc = 0;
double size;
@ -136,7 +136,7 @@ int dsp_init_sender(cnetz_t *cnetz, int measure_speed, double clock_speed[2], in
/* reinit the sample rate to shrink/expand audio */
init_samplerate(&cnetz->sender.srstate, 8000.0, (double)cnetz->sender.samplerate / 1.1, 3300.0); /* 66 <-> 60 */
rc = fsk_fm_init(&cnetz->fsk_demod, cnetz, cnetz->sender.samplerate, (double)BITRATE / (1.0 + clock_speed[0] / 1000000.0), (use_sdr) ? FSK_DEMOD_LEVEL : FSK_DEMOD_SLOPE);
rc = fsk_fm_init(&cnetz->fsk_demod, cnetz, cnetz->sender.samplerate, (double)BITRATE / (1.0 + clock_speed[0] / 1000000.0), demod);
if (rc < 0)
goto error;

View File

@ -1,6 +1,6 @@
void dsp_init(void);
int dsp_init_sender(cnetz_t *cnetz, int measure_speed, double clock_speed[2], int use_sdr);
int dsp_init_sender(cnetz_t *cnetz, int measure_speed, double clock_speed[2], enum demod_type demod);
void dsp_cleanup_sender(cnetz_t *cnetz);
void calc_clock_speed(cnetz_t *cnetz, double samples, int tx, int result);
void unshrink_speech(cnetz_t *cnetz, sample_t *speech_buffer, int count);

View File

@ -135,7 +135,7 @@
#include "dsp.h"
#include "telegramm.h"
int fsk_fm_init(fsk_fm_demod_t *fsk, cnetz_t *cnetz, int samplerate, double bitrate, enum demod_type demod_type)
int fsk_fm_init(fsk_fm_demod_t *fsk, cnetz_t *cnetz, int samplerate, double bitrate, enum demod_type demod)
{
int len, half;
@ -146,12 +146,19 @@ int fsk_fm_init(fsk_fm_demod_t *fsk, cnetz_t *cnetz, int samplerate, double bitr
}
fsk->cnetz = cnetz;
fsk->demod_type = demod_type;
fsk->demod_type = demod;
if (demod_type == FSK_DEMOD_SLOPE)
switch (demod) {
case FSK_DEMOD_SLOPE:
PDEBUG(DDSP, DEBUG_INFO, "Detecting level change by looking at slope (good for sound cards)\n");
if (demod_type == FSK_DEMOD_LEVEL)
break;
case FSK_DEMOD_LEVEL:
PDEBUG(DDSP, DEBUG_INFO, "Detecting level change by looking zero crosssing (good for SDR)\n");
break;
default:
PDEBUG(DDSP, DEBUG_ERROR, "Wrong demod type, please fix!\n");
abort();
}
len = (int)((double)samplerate / bitrate + 0.5);
half = (int)((double)samplerate / bitrate / 2.0 + 0.5);

View File

@ -11,6 +11,7 @@ enum fsk_sync {
};
enum demod_type {
FSK_DEMOD_AUTO, /* auto selection of the demod type below */
FSK_DEMOD_SLOPE, /* check for highest slope (good for sound cards) */
FSK_DEMOD_LEVEL, /* check for zero crossing (good for SDR) */
};

View File

@ -47,6 +47,7 @@ int set_clock_speed = 0;
const char *flip_polarity = "auto";
int ms_power = 0; /* 0..3 */
int auth = 0;
enum demod_type demod = FSK_DEMOD_AUTO;
void print_help(const char *arg0)
{
@ -75,6 +76,15 @@ void print_help(const char *arg0)
printf(" Enable authentication on the base station. Since we cannot\n");
printf(" authenticate, because we don't know the secret key and the algorithm,\n");
printf(" we just accept any card. With this we get the vendor IDs of the phone.\n");
printf(" -D --demod auto | slope | level\n");
printf(" Adjust demodulation algorithm. Use 'slope' to detect a level change\n");
printf(" by finding the highest slope of a bit transition. It is useful, if\n");
printf(" the receiver drifts to 0 after a while, due to DC decoupling. This\n");
printf(" happens in every analog receiver and in every sound card input.\n");
printf(" Use 'level' to detect a level change by passing zero level. This\n");
printf(" requires a DC coupled signal, which is produced by SDR.\n");
printf(" Use 'auto' to select 'slope' for sound card input and 'level' for SDR\n");
printf(" input. (default = '%s')\n", (demod == FSK_DEMOD_LEVEL) ? "level" : (demod == FSK_DEMOD_SLOPE) ? "slope" : "auto");
printf("\nstation-id: Give 7 digit station-id, you don't need to enter it for every\n");
printf(" start of this program.\n");
print_hotkeys_common();
@ -94,10 +104,11 @@ static int handle_options(int argc, char **argv)
{"flip-polarity", 1, 0, 'F'},
{"ms-power", 1, 0, 'P'},
{"authentication", 0, 0, 'A'},
{"demod", 1, 0, 'D'},
{0, 0, 0, 0}
};
set_options_common("T:MS:F:N:P:AV", long_options_special);
set_options_common("T:MS:F:N:P:AD:", long_options_special);
while (1) {
int option_index = 0, c;
@ -161,6 +172,19 @@ static int handle_options(int argc, char **argv)
auth = 1;
skip_args += 1;
break;
case 'D':
if (!strcasecmp(optarg, "auto"))
demod = FSK_DEMOD_AUTO;
else if (!strcasecmp(optarg, "slope"))
demod = FSK_DEMOD_SLOPE;
else if (!strcasecmp(optarg, "level"))
demod = FSK_DEMOD_LEVEL;
else {
fprintf(stderr, "Given demodulation type '%s' is illegal, see help!\n", optarg);
exit(0);
}
skip_args += 2;
break;
default:
opt_switch_common(c, argv[0], &skip_args);
}
@ -299,9 +323,20 @@ int main(int argc, char *argv[])
if (use_sdr && polarity == 0)
polarity = 1; /* SDR is always positive */
/* demodulation algorithm */
if (demod == FSK_DEMOD_AUTO)
demod = (use_sdr) ? FSK_DEMOD_LEVEL : FSK_DEMOD_SLOPE;
if (demod == FSK_DEMOD_LEVEL && !use_sdr) {
fprintf(stderr, "*******************************************************************************\n");
fprintf(stderr, "I strongly suggest to use 'slope' demodulation algorithm!!!\n");
fprintf(stderr, "Using sound card will cause the DC levels to return to 0. Using 'level' assumes\n");
fprintf(stderr, "that a frequency offset never returns to 0. (Use this only with SDR.)\n");
fprintf(stderr, "*******************************************************************************\n");
}
/* create transceiver instance */
for (i = 0; i < num_kanal; i++) {
rc = cnetz_create(kanal[i], chan_type[i], audiodev[i], use_sdr, samplerate, rx_gain, auth, ms_power, (i == 0) ? measure_speed : 0, clock_speed, polarity, do_pre_emphasis, do_de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, loopback);
rc = cnetz_create(kanal[i], chan_type[i], audiodev[i], use_sdr, demod, samplerate, rx_gain, auth, ms_power, (i == 0) ? measure_speed : 0, clock_speed, polarity, do_pre_emphasis, do_de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, loopback);
if (rc < 0) {
fprintf(stderr, "Failed to create \"Sender\" instance. Quitting!\n");
goto fail;