diff --git a/src/cnetz/cnetz.c b/src/cnetz/cnetz.c index 2286e46..0921723 100644 --- a/src/cnetz/cnetz.c +++ b/src/cnetz/cnetz.c @@ -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; diff --git a/src/cnetz/cnetz.h b/src/cnetz/cnetz.h index b5be755..1856db4 100644 --- a/src/cnetz/cnetz.h +++ b/src/cnetz/cnetz.h @@ -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); diff --git a/src/cnetz/dsp.c b/src/cnetz/dsp.c index 00f1ed0..2c2ca4e 100644 --- a/src/cnetz/dsp.c +++ b/src/cnetz/dsp.c @@ -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; diff --git a/src/cnetz/dsp.h b/src/cnetz/dsp.h index 7528e18..4e66f26 100644 --- a/src/cnetz/dsp.h +++ b/src/cnetz/dsp.h @@ -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); diff --git a/src/cnetz/fsk_demod.c b/src/cnetz/fsk_demod.c index 99d3dc4..2f56bf0 100644 --- a/src/cnetz/fsk_demod.c +++ b/src/cnetz/fsk_demod.c @@ -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); diff --git a/src/cnetz/fsk_demod.h b/src/cnetz/fsk_demod.h index d8d645f..3410268 100644 --- a/src/cnetz/fsk_demod.h +++ b/src/cnetz/fsk_demod.h @@ -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) */ }; diff --git a/src/cnetz/main.c b/src/cnetz/main.c index 0d4ee87..b4578e8 100644 --- a/src/cnetz/main.c +++ b/src/cnetz/main.c @@ -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;