From e2a9c2c6a531bd6db2c6ba0dc5be61ce97ae95c1 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Tue, 10 May 2016 19:25:07 +0200 Subject: [PATCH] Automatic FSK polarity selection on TX side This is done by simulating two cells with different polarities. On first message from mobile station, the cell with the correct polarity is used, the other is disabled. On RX side the polarity is not selected, since FSK decoder detects polarity for every frame. --- src/cnetz/cnetz.c | 107 +++++++++++++++++++++++++----------------- src/cnetz/cnetz.h | 10 ++-- src/cnetz/dsp.c | 24 ++++++---- src/cnetz/dsp.h | 2 +- src/cnetz/main.c | 42 ++++++++++++----- src/cnetz/sysinfo.c | 65 ++++++++++++++++++------- src/cnetz/sysinfo.h | 4 +- src/cnetz/telegramm.c | 53 ++++++++++++++++----- src/cnetz/telegramm.h | 2 +- 9 files changed, 211 insertions(+), 98 deletions(-) diff --git a/src/cnetz/cnetz.c b/src/cnetz/cnetz.c index 33fede5..b9b3a42 100644 --- a/src/cnetz/cnetz.c +++ b/src/cnetz/cnetz.c @@ -112,7 +112,7 @@ static void trans_new_state(transaction_t *trans, int state); static void cnetz_flush_other_transactions(cnetz_t *cnetz, transaction_t *trans); /* Create transceiver instance and link to a list. */ -int cnetz_create(int kanal, enum cnetz_chan_type chan_type, const char *sounddev, int samplerate, int cross_channels, double rx_gain, int auth, int ms_power, int measure_speed, double clock_speed[2], double deviation, double noise, int pre_emphasis, int de_emphasis, const char *write_wave, const char *read_wave, int loopback) +int cnetz_create(int kanal, enum cnetz_chan_type chan_type, const char *sounddev, int samplerate, int cross_channels, double rx_gain, int auth, int ms_power, int measure_speed, double clock_speed[2], int polarity, double noise, int pre_emphasis, int de_emphasis, const char *write_wave, const char *read_wave, int loopback) { sender_t *sender; cnetz_t *cnetz; @@ -180,7 +180,7 @@ int cnetz_create(int kanal, enum cnetz_chan_type chan_type, const char *sounddev #endif /* init audio processing */ - rc = dsp_init_sender(cnetz, measure_speed, clock_speed, deviation, noise); + rc = dsp_init_sender(cnetz, measure_speed, clock_speed, noise); if (rc < 0) { PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to init signal processing!\n"); goto error; @@ -190,6 +190,30 @@ int cnetz_create(int kanal, enum cnetz_chan_type chan_type, const char *sounddev cnetz->auth = auth; cnetz->ms_power = ms_power; + switch (polarity) { + case 1: + /* select cell 0 for positive polarity */ + cnetz->cell_nr = 0; + cnetz->cell_auto = 0; + if (si[cnetz->cell_nr].flip_polarity != 0) { + fprintf(stderr, "cell %d must have positive polarity, please fix!\n", cnetz->cell_nr); + abort(); + } + break; + case 2: + /* select cell 1 for negative polarity */ + cnetz->cell_nr = 1; + cnetz->cell_auto = 0; + if (si[cnetz->cell_nr].flip_polarity != 0) { + fprintf(stderr, "cell %d must have negative polarity, please fix!\n", cnetz->cell_nr); + abort(); + } + break; + default: + /* send two cells and select by the first message from mobile */ + cnetz->cell_auto = 1; + } + cnetz->pre_emphasis = pre_emphasis; cnetz->de_emphasis = de_emphasis; rc = init_emphasis(&cnetz->estate, samplerate); @@ -254,10 +278,7 @@ static void cnetz_go_idle(cnetz_t *cnetz) } /* set scheduler to OgK */ - if (cnetz->sender.kanal == CNETZ_OGK_KANAL) - PDEBUG(DBNETZ, DEBUG_INFO, "Entering IDLE state on channel %d, sending 'Funkzellenkennung' %d,%d,%d.\n", cnetz->sender.kanal, si.fuz_nat, si.fuz_fuvst, si.fuz_rest); - else - PDEBUG(DBNETZ, DEBUG_INFO, "Entering IDLE state on channel %d.\n", cnetz->sender.kanal, si.fuz_nat, si.fuz_fuvst, si.fuz_rest); + PDEBUG(DBNETZ, DEBUG_INFO, "Entering IDLE state on channel %d.\n", cnetz->sender.kanal); cnetz_new_state(cnetz, CNETZ_IDLE); if (cnetz->dsp_mode == DSP_MODE_SPK_K || cnetz->dsp_mode == DSP_MODE_SPK_V) { /* go idle after next frame/slot */ @@ -916,24 +937,24 @@ const telegramm_t *cnetz_transmit_telegramm_rufblock(cnetz_t *cnetz) telegramm.opcode = OPCODE_LR_R; telegramm.max_sendeleistung = cnetz->ms_power; - telegramm.bedingte_genauigkeit_der_fufst = si.genauigkeit; + telegramm.bedingte_genauigkeit_der_fufst = si[cnetz->cell_nr].genauigkeit; telegramm.zeitschlitz_nr = cnetz->sched_ts; - telegramm.grenzwert_fuer_einbuchen_und_umbuchen = si.grenz_einbuchen; + telegramm.grenzwert_fuer_einbuchen_und_umbuchen = si[cnetz->cell_nr].grenz_einbuchen; telegramm.authentifikationsbit = cnetz->auth; - telegramm.vermittlungstechnische_sperren = si.sperre; + telegramm.vermittlungstechnische_sperren = si[cnetz->cell_nr].sperre; telegramm.ws_kennung = 0; - telegramm.reduzierungsfaktor = si.reduzierung; - telegramm.fuz_nationalitaet = si.fuz_nat; - telegramm.fuz_fuvst_nr = si.fuz_fuvst; - telegramm.fuz_rest_nr = si.fuz_rest; - telegramm.kennung_fufst = si.fufst_prio; - telegramm.nachbarschafts_prioritaets_bit = si.nachbar_prio; - telegramm.bewertung_nach_pegel_und_entfernung = si.bewertung; - telegramm.entfernungsangabe_der_fufst = si.entfernung; - telegramm.mittelungsfaktor_fuer_ausloesen = si.mittel_ausloesen; - telegramm.mittelungsfaktor_fuer_umschalten = si.mittel_umschalten; - telegramm.grenzwert_fuer_umschalten = si.grenz_umschalten; - telegramm.grenze_fuer_ausloesen = si.grenz_ausloesen; + telegramm.reduzierungsfaktor = si[cnetz->cell_nr].reduzierung; + telegramm.fuz_nationalitaet = si[cnetz->cell_nr].fuz_nat; + telegramm.fuz_fuvst_nr = si[cnetz->cell_nr].fuz_fuvst; + telegramm.fuz_rest_nr = si[cnetz->cell_nr].fuz_rest; + telegramm.kennung_fufst = si[cnetz->cell_nr].fufst_prio; + telegramm.nachbarschafts_prioritaets_bit = si[cnetz->cell_nr].nachbar_prio; + telegramm.bewertung_nach_pegel_und_entfernung = si[cnetz->cell_nr].bewertung; + telegramm.entfernungsangabe_der_fufst = si[cnetz->cell_nr].entfernung; + telegramm.mittelungsfaktor_fuer_ausloesen = si[cnetz->cell_nr].mittel_ausloesen; + telegramm.mittelungsfaktor_fuer_umschalten = si[cnetz->cell_nr].mittel_umschalten; + telegramm.grenzwert_fuer_umschalten = si[cnetz->cell_nr].grenz_umschalten; + telegramm.grenze_fuer_ausloesen = si[cnetz->cell_nr].grenz_ausloesen; trans = search_transaction(cnetz, TRANS_EM | TRANS_UM | TRANS_WBN | TRANS_WBP | TRANS_VAG | TRANS_VAK); if (trans) { @@ -1020,7 +1041,7 @@ const telegramm_t *cnetz_transmit_telegramm_meldeblock(cnetz_t *cnetz) telegramm.teilnehmersperre = 0; telegramm.anzahl_gesperrter_teilnehmergruppen = 0; telegramm.ogk_vorschlag = CNETZ_OGK_KANAL; - telegramm.fuz_rest_nr = si.fuz_rest; + telegramm.fuz_rest_nr = si[cnetz->cell_nr].fuz_rest; trans = search_transaction(cnetz, TRANS_VWG | TRANS_MA); if (trans) { @@ -1061,7 +1082,7 @@ void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, telegramm_t *telegramm, int blo switch (opcode) { case OPCODE_EM_R: - if (!match_fuz(telegramm)) + if (!match_fuz(cnetz, telegramm, cnetz->cell_nr)) break; rufnummer = telegramm2rufnummer(telegramm); if (cnetz->auth && telegramm->chipkarten_futelg_bit) @@ -1080,7 +1101,7 @@ void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, telegramm_t *telegramm, int blo valid_frame = 1; break; case OPCODE_UM_R: - if (!match_fuz(telegramm)) + if (!match_fuz(cnetz, telegramm, cnetz->cell_nr)) break; rufnummer = telegramm2rufnummer(telegramm); if (cnetz->auth && telegramm->chipkarten_futelg_bit) @@ -1100,7 +1121,7 @@ void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, telegramm_t *telegramm, int blo break; case OPCODE_VWG_R: case OPCODE_SRG_R: - if (!match_fuz(telegramm)) + if (!match_fuz(cnetz, telegramm, cnetz->cell_nr)) break; rufnummer = telegramm2rufnummer(telegramm); PDEBUG(DCNETZ, DEBUG_INFO, "Received outgoing Call 'Verbindungswunsch gehend' message from Subscriber '%s'\n", rufnummer); @@ -1172,15 +1193,15 @@ const telegramm_t *cnetz_transmit_telegramm_spk_k(cnetz_t *cnetz) telegramm.max_sendeleistung = cnetz->ms_power; telegramm.sendeleistungsanpassung = 1; - telegramm.entfernung = si.entfernung; - telegramm.fuz_nationalitaet = si.fuz_nat; - telegramm.fuz_fuvst_nr = si.fuz_fuvst; - telegramm.fuz_rest_nr = si.fuz_rest; + telegramm.entfernung = si[cnetz->cell_nr].entfernung; + telegramm.fuz_nationalitaet = si[cnetz->cell_nr].fuz_nat; + telegramm.fuz_fuvst_nr = si[cnetz->cell_nr].fuz_fuvst; + telegramm.fuz_rest_nr = si[cnetz->cell_nr].fuz_rest; telegramm.futln_nationalitaet = trans->futln_nat; telegramm.futln_heimat_fuvst_nr = trans->futln_fuvst; telegramm.futln_rest_nr = trans->futln_rest; telegramm.frequenz_nr = cnetz->sender.kanal; - telegramm.bedingte_genauigkeit_der_fufst = si.genauigkeit; + telegramm.bedingte_genauigkeit_der_fufst = si[cnetz->cell_nr].genauigkeit; switch (trans->state) { case TRANS_BQ: @@ -1284,7 +1305,7 @@ void cnetz_receive_telegramm_spk_k(cnetz_t *cnetz, telegramm_t *telegramm) switch (opcode) { case OPCODE_BEL_K: - if (!match_fuz(telegramm)) { + if (!match_fuz(cnetz, telegramm, cnetz->cell_nr)) { break; } if (!match_futln(telegramm, trans->futln_nat, trans->futln_fuvst, trans->futln_rest)) { @@ -1297,7 +1318,7 @@ void cnetz_receive_telegramm_spk_k(cnetz_t *cnetz, telegramm_t *telegramm) timer_stop(&trans->timer); break; case OPCODE_DSQ_K: - if (!match_fuz(telegramm)) { + if (!match_fuz(cnetz, telegramm, cnetz->cell_nr)) { break; } if (!match_futln(telegramm, trans->futln_nat, trans->futln_fuvst, trans->futln_rest)) { @@ -1311,7 +1332,7 @@ void cnetz_receive_telegramm_spk_k(cnetz_t *cnetz, telegramm_t *telegramm) timer_stop(&trans->timer); break; case OPCODE_VH_K: - if (!match_fuz(telegramm)) { + if (!match_fuz(cnetz, telegramm, cnetz->cell_nr)) { break; } if (!match_futln(telegramm, trans->futln_nat, trans->futln_fuvst, trans->futln_rest)) { @@ -1324,7 +1345,7 @@ void cnetz_receive_telegramm_spk_k(cnetz_t *cnetz, telegramm_t *telegramm) timer_stop(&trans->timer); break; case OPCODE_RTAQ_K: - if (!match_fuz(telegramm)) { + if (!match_fuz(cnetz, telegramm, cnetz->cell_nr)) { break; } if (!match_futln(telegramm, trans->futln_nat, trans->futln_fuvst, trans->futln_rest)) { @@ -1337,7 +1358,7 @@ void cnetz_receive_telegramm_spk_k(cnetz_t *cnetz, telegramm_t *telegramm) timer_start(&trans->timer, 0.0375 * F_RTA); /* F_RTA frames */ break; case OPCODE_AH_K: - if (!match_fuz(telegramm)) { + if (!match_fuz(cnetz, telegramm, cnetz->cell_nr)) { break; } if (!match_futln(telegramm, trans->futln_nat, trans->futln_fuvst, trans->futln_rest)) { @@ -1355,7 +1376,7 @@ void cnetz_receive_telegramm_spk_k(cnetz_t *cnetz, telegramm_t *telegramm) call_in_answer(cnetz->sender.callref, transaction2rufnummer(trans)); break; case OPCODE_AT_K: - if (!match_fuz(telegramm)) { + if (!match_fuz(cnetz, telegramm, cnetz->cell_nr)) { break; } if (!match_futln(telegramm, trans->futln_nat, trans->futln_fuvst, trans->futln_rest)) { @@ -1396,15 +1417,15 @@ const telegramm_t *cnetz_transmit_telegramm_spk_v(cnetz_t *cnetz) telegramm.sendeleistungsanpassung = 1; telegramm.ankuendigung_gespraechsende = 0; telegramm.gebuehren_stand = 0; - telegramm.fuz_nationalitaet = si.fuz_nat; - telegramm.fuz_fuvst_nr = si.fuz_fuvst; - telegramm.fuz_rest_nr = si.fuz_rest; + telegramm.fuz_nationalitaet = si[cnetz->cell_nr].fuz_nat; + telegramm.fuz_fuvst_nr = si[cnetz->cell_nr].fuz_fuvst; + telegramm.fuz_rest_nr = si[cnetz->cell_nr].fuz_rest; telegramm.futln_nationalitaet = trans->futln_nat; telegramm.futln_heimat_fuvst_nr = trans->futln_fuvst; telegramm.futln_rest_nr = trans->futln_rest; telegramm.frequenz_nr = cnetz->sender.kanal; - telegramm.entfernung = si.entfernung; - telegramm.bedingte_genauigkeit_der_fufst = si.genauigkeit; + telegramm.entfernung = si[cnetz->cell_nr].entfernung; + telegramm.bedingte_genauigkeit_der_fufst = si[cnetz->cell_nr].genauigkeit; telegramm.gueltigkeit_des_gebuehrenstandes = 0; telegramm.ausloesegrund = trans->release_cause; @@ -1449,7 +1470,7 @@ void cnetz_receive_telegramm_spk_v(cnetz_t *cnetz, telegramm_t *telegramm) switch (opcode) { case OPCODE_VH_V: - if (!match_fuz(telegramm)) { + if (!match_fuz(cnetz, telegramm, cnetz->cell_nr)) { break; } if (!match_futln(telegramm, trans->futln_nat, trans->futln_fuvst, trans->futln_rest)) { @@ -1463,7 +1484,7 @@ void cnetz_receive_telegramm_spk_v(cnetz_t *cnetz, telegramm_t *telegramm) cnetz->scrambler = telegramm->betriebs_art; break; case OPCODE_AT_V: - if (!match_fuz(telegramm)) { + if (!match_fuz(cnetz, telegramm, cnetz->cell_nr)) { break; } if (!match_futln(telegramm, trans->futln_nat, trans->futln_fuvst, trans->futln_rest)) { diff --git a/src/cnetz/cnetz.h b/src/cnetz/cnetz.h index 531abb8..41ed12f 100644 --- a/src/cnetz/cnetz.h +++ b/src/cnetz/cnetz.h @@ -110,9 +110,13 @@ typedef struct cnetz { /* all cnetz states */ enum cnetz_state state; /* main state of sender */ + /* cell nr selection */ + int cell_auto; /* if set, cell_nr is selected automatically */ + int cell_nr; /* current cell number to use (sysinfo) */ + /* scheduler */ int sched_ts; /* current time slot */ - int last_tx_timeslot; /* last timeslot we transmitted, so we can match MS timeslot */ + int sched_last_ts[2]; /* last timeslot we transmitted, so we can match MS timeslot */ int sched_r_m; /* Rufblock (0) / Meldeblock (1) */ int sched_switch_mode; /* counts slots until mode is switched */ enum dsp_mode sched_dsp_mode; /* what mode shall be switched to */ @@ -120,7 +124,7 @@ typedef struct cnetz { /* dsp states */ enum dsp_mode dsp_mode; /* current mode: audio, "Telegramm", .... */ fsk_fm_demod_t fsk_demod; /* demod process */ - int16_t fsk_deviation; /* deviation used for digital signal */ + int16_t fsk_deviation; /* deviation of FSK signal on sound card */ int16_t fsk_ramp_up[256]; /* samples of upward ramp shape */ int16_t fsk_ramp_down[256]; /* samples of downward ramp shape */ double fsk_noise; /* send static between OgK frames */ @@ -156,7 +160,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 *sounddev, int samplerate, int cross_channels, double rx_gain, int auth, int ms_power, int measure_speed, double clock_speed[2], double deviation, double noise, int pre_emphasis, int de_emphasis, const char *write_wave, const char *read_wave, int loopback); +int cnetz_create(int kanal, enum cnetz_chan_type chan_type, const char *sounddev, int samplerate, int cross_channels, double rx_gain, int auth, int ms_power, int measure_speed, double clock_speed[2], int polarity, double noise, int pre_emphasis, int de_emphasis, const char *write_wave, const char *read_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 1b5752f..75550a0 100644 --- a/src/cnetz/dsp.c +++ b/src/cnetz/dsp.c @@ -37,6 +37,7 @@ #define PI M_PI +#define FSK_DEVIATION 16384 #define BITRATE 5280.0 /* bits per second */ #define BLOCK_BITS 198 /* duration of one time slot including pause at beginning and end */ @@ -56,7 +57,6 @@ static void dsp_init_ramp(cnetz_t *cnetz) { double c; int i; - int16_t deviation = cnetz->fsk_deviation; PDEBUG(DDSP, DEBUG_DEBUG, "Generating smooth ramp table.\n"); for (i = 0; i < 256; i++) { @@ -67,13 +67,13 @@ static void dsp_init_ramp(cnetz_t *cnetz) else c = sqrt(c); #endif - ramp_down[i] = (int)(c * (double)deviation); + ramp_down[i] = (int)(c * (double)cnetz->fsk_deviation); ramp_up[i] = -ramp_down[i]; } } /* Init transceiver instance. */ -int dsp_init_sender(cnetz_t *cnetz, int measure_speed, double clock_speed[2], double deviation, double noise) +int dsp_init_sender(cnetz_t *cnetz, int measure_speed, double clock_speed[2], double noise) { int rc = 0; double size; @@ -105,9 +105,7 @@ int dsp_init_sender(cnetz_t *cnetz, int measure_speed, double clock_speed[2], do } /* create devation and ramp */ - if (deviation > 1.0) - deviation = 1.0; - cnetz->fsk_deviation = (int16_t)(deviation * 32766.9); /* be sure not to overflow -32767 .. 32767 */ + cnetz->fsk_deviation = FSK_DEVIATION; /* be sure not to overflow -32767 .. 32767 */ dsp_init_ramp(cnetz); cnetz->fsk_noise = noise; @@ -617,10 +615,20 @@ again: switch (cnetz->dsp_mode) { case DSP_MODE_OGK: - if (((1 << cnetz->sched_ts) & si.ogk_timeslot_mask)) { + /* if automatic cell selection is used, toggle between + * two cells until a response for one cell is received + */ + if (cnetz->cell_auto) + cnetz->cell_nr = (cnetz->sched_ts & 7) >> 2; + /* send on timeslots depending on the cell_nr: + * cell 0: 0, 8, 16, 24 + * cell 1: 4, 12, 20, 28 + */ + if (((cnetz->sched_ts & 7) == 0 && cnetz->cell_nr == 0) + || ((cnetz->sched_ts & 7) == 4 && cnetz->cell_nr == 1)) { if (cnetz->sched_r_m == 0) { /* set last time slot, so we can match received message from mobile station */ - cnetz->last_tx_timeslot = cnetz->sched_ts; + cnetz->sched_last_ts[cnetz->cell_nr] = cnetz->sched_ts; PDEBUG(DDSP, DEBUG_DEBUG, "Transmitting 'Rufblock' at timeslot %d\n", cnetz->sched_ts); bits = cnetz_encode_telegramm(cnetz); } else { diff --git a/src/cnetz/dsp.h b/src/cnetz/dsp.h index 2a4f042..0aba3e0 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], double deviation, double noise); +int dsp_init_sender(cnetz_t *cnetz, int measure_speed, double clock_speed[2], double noise); void dsp_cleanup_sender(cnetz_t *cnetz); void calc_clock_speed(cnetz_t *cnetz, uint64_t samples, int tx, int result); diff --git a/src/cnetz/main.c b/src/cnetz/main.c index 2e65756..87e1ec5 100644 --- a/src/cnetz/main.c +++ b/src/cnetz/main.c @@ -45,7 +45,8 @@ enum cnetz_chan_type chan_type[MAX_SENDER] = { CHAN_TYPE_OGK_SPK }; int measure_speed = 0; double clock_speed[2] = { 0.0, 0.0 }; int set_clock_speed = 0; -double deviation = 0.5, noise = 0.0; +const char *flip_polarity = "auto"; +double noise = 0.0; int ms_power = 0; /* 0..3 */ int auth = 0; @@ -60,12 +61,15 @@ void print_help(const char *arg0) printf(" -S --clock-speed ,\n"); printf(" Correct speed of sound card's clock. Use '-M' to measure speed for\n"); printf(" some hours after temperature has settled. The use these results to\n"); - printf(" correct signal processing speed. After adjustment, the clock must match\n"); - printf(" +- 1ppm or better. CORRECTING CLOCK SPEED IS REQUIRED! See\n"); + printf(" correct signal processing speed. After adjustment, the clock must match\n"); + printf(" +- 1ppm or better. CORRECTING CLOCK SPEED IS REQUIRED! See\n"); printf(" documentation on how to measure correct value.\n"); - printf(" -F --flip-polarity\n"); - printf(" Adjust, so the transmitter increases frequency, when positive levels\n"); - printf(" are sent to sound device\n"); + printf(" -F --flip-polarity no | yes auto\n"); + printf(" Flip polarity of transmitted FSK signal. If yes, the sound card\n"); + printf(" generates a negative signal rather than a positive one. If auto, the"); + printf(" base station generates two virtual base stations with both polarities.\n"); + printf(" Once a mobile registers, the correct polarity is selected and used.\n"); + printf(" (default = %s)\n", flip_polarity); printf(" -N --noise 0.0 .. 1.0 (default = %.1f)\n", noise); printf(" Between frames on OgK, send noise at given level. Use 0.0 for Silence.\n"); printf(" -P --ms-power \n"); @@ -87,14 +91,14 @@ static int handle_options(int argc, char **argv) {"channel-type", 1, 0, 't'}, {"measure-speed", 0, 0, 'M'}, {"clock-speed", 1, 0, 'S'}, - {"flip-polarity", 0, 0, 'F'}, + {"flip-polarity", 1, 0, 'F'}, {"noise", 1, 0, 'N'}, {"ms-power", 1, 0, 'P'}, {"authentication", 0, 0, 'A'}, {0, 0, 0, 0} }; - set_options_common("t:MS:FN:P:A", long_options_special); + set_options_common("t:MS:F:N:P:A", long_options_special); while (1) { int option_index = 0, c; @@ -134,8 +138,17 @@ static int handle_options(int argc, char **argv) skip_args += 2; break; case 'F': - deviation = -deviation; - skip_args += 1; + if (!strcasecmp(optarg, "no")) + flip_polarity = "no"; + else if (!strcasecmp(optarg, "yes")) + flip_polarity = "yes"; + else if (!strcasecmp(optarg, "auto")) + flip_polarity = "auto"; + else { + fprintf(stderr, "Given polarity '%s' is illegal, see help!\n", optarg); + exit(0); + } + skip_args += 2; break; case 'N': noise = strtold(optarg, NULL); @@ -169,6 +182,7 @@ int main(int argc, char *argv[]) int skip_args; const char *station_id = ""; int mandatory = 0; + int polarity; int i; /* init common tones */ @@ -251,9 +265,15 @@ int main(int argc, char *argv[]) if (i == num_kanal) fprintf(stderr, "You did not define any SpK (speech) channel. You will not be able to make any call.\n"); + polarity = 0; /* auto */ + if (!strcmp(flip_polarity, "no")) + polarity = 1; /* positive */ + if (!strcmp(flip_polarity, "yes")) + polarity = -1; /* negative */ + /* create transceiver instance */ for (i = 0; i < num_kanal; i++) { - rc = cnetz_create(kanal[i], chan_type[i], sounddev[i], samplerate, cross_channels, rx_gain, auth, ms_power, (i == 0) ? measure_speed : 0, clock_speed, deviation, noise, do_pre_emphasis, do_de_emphasis, write_wave, read_wave, loopback); + rc = cnetz_create(kanal[i], chan_type[i], sounddev[i], samplerate, cross_channels, rx_gain, auth, ms_power, (i == 0) ? measure_speed : 0, clock_speed, polarity, noise, do_pre_emphasis, do_de_emphasis, write_wave, read_wave, loopback); if (rc < 0) { fprintf(stderr, "Failed to create \"Sender\" instance. Quitting!\n"); goto fail; diff --git a/src/cnetz/sysinfo.c b/src/cnetz/sysinfo.c index 67a2764..a211d5c 100644 --- a/src/cnetz/sysinfo.c +++ b/src/cnetz/sysinfo.c @@ -2,27 +2,58 @@ #include #include "sysinfo.h" -cnetz_si si; +cnetz_si si[2]; void init_sysinfo(void) { memset(&si, 0, sizeof(si)); - si.ogk_timeslot_mask = 0x01010101; /* 4 slots per super frame */ - si.fuz_nat = 1; - si.fuz_fuvst = 1; - si.fuz_rest = 38; - si.mittel_umschalten = 5; - si.grenz_umschalten = 0; - si.mittel_ausloesen = 5; - si.grenz_ausloesen = 0; - si.sperre = 0; - si.genauigkeit = 1; /* bedingte Genauigkeit */ - si.entfernung = 3; - si.grenz_einbuchen = 1; /* worst case */ - si.fufst_prio = 1; /* normal pio */ - si.nachbar_prio = 0; - si.bewertung = 1; /* pegel */ - si.reduzierung = 0; + si[0].flip_polarity = 0; + si[1].flip_polarity = 1; + + si[0].fuz_nat = 1; + si[1].fuz_nat = 1; + + si[0].fuz_fuvst = 1; + si[1].fuz_fuvst = 1; + + si[0].fuz_rest = 38; + si[1].fuz_rest = 39; + + si[0].mittel_umschalten = 5; + si[1].mittel_umschalten = 5; + + si[0].grenz_umschalten = 0; + si[1].grenz_umschalten = 0; + + si[0].mittel_ausloesen = 5; + si[1].mittel_ausloesen = 5; + + si[0].grenz_ausloesen = 0; + si[1].grenz_ausloesen = 0; + + si[0].sperre = 0; + si[1].sperre = 0; + + si[0].genauigkeit = 1; /* bedingte Genauigkeit */ + si[1].genauigkeit = 1; /* bedingte Genauigkeit */ + + si[0].entfernung = 3; + si[1].entfernung = 3; + + si[0].grenz_einbuchen = 1; /* worst case */ + si[1].grenz_einbuchen = 1; /* worst case */ + + si[0].fufst_prio = 1; /* normal pio */ + si[1].fufst_prio = 1; /* normal pio */ + + si[0].nachbar_prio = 0; + si[1].nachbar_prio = 0; + + si[0].bewertung = 1; /* pegel */ + si[1].bewertung = 1; /* pegel */ + + si[0].reduzierung = 0; + si[1].reduzierung = 0; } diff --git a/src/cnetz/sysinfo.h b/src/cnetz/sysinfo.h index 2a70dfb..acd9e65 100644 --- a/src/cnetz/sysinfo.h +++ b/src/cnetz/sysinfo.h @@ -1,6 +1,6 @@ typedef struct system_information { - uint32_t ogk_timeslot_mask; /* each bit defines an assigned time slot */ + int flip_polarity; /* use negative polarity for FSK transmission */ uint8_t fuz_nat; /* national network ID */ uint8_t fuz_fuvst; /* id of switching center */ uint8_t fuz_rest; /* rest of base station id */ @@ -18,7 +18,7 @@ typedef struct system_information { uint8_t reduzierung; } cnetz_si; -extern cnetz_si si; +extern cnetz_si si[]; void init_sysinfo(void); diff --git a/src/cnetz/telegramm.c b/src/cnetz/telegramm.c index 174f605..f5fdf07 100644 --- a/src/cnetz/telegramm.c +++ b/src/cnetz/telegramm.c @@ -26,6 +26,7 @@ #include "../common/debug.h" #include "../common/timer.h" #include "cnetz.h" +#include "dsp.h" #include "sysinfo.h" #include "telegramm.h" @@ -570,12 +571,13 @@ static int encode_dialstring(uint64_t *value, const char *number) return 0; } -int match_fuz(telegramm_t *telegramm) +int match_fuz(cnetz_t *cnetz, telegramm_t *telegramm, int cell) { - if (telegramm->fuz_nationalitaet != si.fuz_nat - || telegramm->fuz_fuvst_nr != si.fuz_fuvst - || telegramm->fuz_rest_nr != si.fuz_rest) { - PDEBUG(DFRAME, DEBUG_NOTICE, "Ignoring message from mobile phone %d,%d,%d: Cell 'Funkzelle' does not match!\n", telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr); + if (telegramm->fuz_nationalitaet != si[cell].fuz_nat + || telegramm->fuz_fuvst_nr != si[cell].fuz_fuvst + || telegramm->fuz_rest_nr != si[cell].fuz_rest) { + if (!cnetz->cell_auto) + PDEBUG(DFRAME, DEBUG_NOTICE, "Ignoring message from mobile phone %d,%d,%d: Cell 'Funkzelle' does not match!\n", telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr); return 0; } @@ -618,7 +620,7 @@ static void debug_parameter(char digit, uint64_t value) /* encode telegram to 70 bits * bit order MSB */ -static const char *assemble_telegramm(const telegramm_t *telegramm, int debug) +static char *assemble_telegramm(const telegramm_t *telegramm, int debug) { static char bits[71]; /* + termination char for debug */ char parameter; @@ -1273,7 +1275,7 @@ int detect_sync(uint64_t bitstream) * input: 70 data bits MSB first * output: 10*15 code words (LSB first) * FTZ 171 TR 60 / 5.1.1.3 */ -static const char *encode(const char *input) +static char *encode(const char *input) { static char output[150]; int16_t word; @@ -1389,7 +1391,7 @@ static const char *decode(const char *input, int *_bit_errors) * input: 10*15 code words (LSB first) * output: stream of 33 sync + 1 + 150 interleaved bits * FTZ 171 TR 60 / 5.1.1.2 and 5.1.1.2 */ -static const char *interleave(const char *input) +static char *interleave(const char *input) { static char output[185]; /* + termination char for debug */ int i, j; @@ -1488,9 +1490,9 @@ void cnetz_decode_telegramm(cnetz_t *cnetz, const char *bits, double level, doub telegramm.jitter = jitter; if (bit_errors) - PDEBUG(DDSP, DEBUG_INFO, "RX Level: %.0f%% Jitter: %.2f Sync Time: %.2f Bit errors: %d %s\n", fabs(level * 32767.0 / cnetz->fsk_deviation) * 100.0, jitter, sync_time, bit_errors, (level < 0) ? "NEGATIVE" : "POSITIVE"); + PDEBUG(DDSP, DEBUG_INFO, "RX Level: %.0f%% Jitter: %.2f Sync Time: %.2f (TS %.2f) Bit errors: %d %s\n", fabs(level) * 32767.0 / cnetz->fsk_deviation * 100.0, jitter, sync_time, sync_time / 396.0, bit_errors, (level < 0) ? "NEGATIVE" : "POSITIVE"); else - PDEBUG(DDSP, DEBUG_INFO, "RX Level: %.0f%% Jitter: %.2f Sync Time: %.2f %s\n", fabs(level * 32767.0 / cnetz->fsk_deviation) * 100.0, jitter, sync_time, (level < 0) ? "NEGATIVE" : "POSITIVE"); + PDEBUG(DDSP, DEBUG_INFO, "RX Level: %.0f%% Jitter: %.2f Sync Time: %.2f (TS %.2f) %s\n", fabs(level) * 32767.0 / cnetz->fsk_deviation * 100.0, jitter, sync_time, sync_time / 396.0, (level < 0) ? "NEGATIVE" : "POSITIVE"); if (cnetz->sender.loopback) { PDEBUG(DFRAME, DEBUG_NOTICE, "Received Telegramm in loopback test mode (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name); @@ -1508,13 +1510,32 @@ void cnetz_decode_telegramm(cnetz_t *cnetz, const char *bits, double level, doub return; } + /* auto select cell */ + if (cnetz->cell_auto) { + if (!match_fuz(cnetz, &telegramm, 0)) { + cnetz->cell_nr = 1; +selected: + cnetz->cell_auto = 0; + printf("***********************************************\n"); + printf("*** Autoselecting %stive FSK TX polarity! ***\n", (si[cnetz->cell_nr].flip_polarity) ? "nega" : "posi"); + printf("***********************************************\n"); + } else if (!match_fuz(cnetz, &telegramm, 1)) { + cnetz->cell_nr = 0; + goto selected; + } else { + PDEBUG(DFRAME, DEBUG_NOTICE, "Received Telegramm with no cell number, ignoring!\n"); + return; + } + } + switch (cnetz->dsp_mode) { case DSP_MODE_OGK: if (definition_opcode[opcode].block != BLOCK_R && definition_opcode[opcode].block != BLOCK_M) { PDEBUG(DFRAME, DEBUG_NOTICE, "Received Telegramm that is not used OgK channel signalling, ignoring! (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name); return; } - block = cnetz->last_tx_timeslot * 2; + /* determine block by last timeslot sent and by message type */ + block = cnetz->sched_last_ts[cnetz->cell_nr] * 2; if (definition_opcode[opcode].block == BLOCK_M) block++; cnetz_receive_telegramm_ogk(cnetz, &telegramm, block); @@ -1542,7 +1563,7 @@ const char *cnetz_encode_telegramm(cnetz_t *cnetz) { const telegramm_t *telegramm = NULL; uint8_t opcode; - const char *bits; + char *bits; switch (cnetz->dsp_mode) { case DSP_MODE_OGK: @@ -1566,6 +1587,14 @@ const char *cnetz_encode_telegramm(cnetz_t *cnetz) bits = encode(bits); bits = interleave(bits); + /* invert, if polarity of the cell is negative */ + if (si[cnetz->cell_nr].flip_polarity) { + int i; + + for (i = 0; i < 184; i++) + bits[i] ^= 1; + } + return bits; } diff --git a/src/cnetz/telegramm.h b/src/cnetz/telegramm.h index 61505b9..7f4566b 100644 --- a/src/cnetz/telegramm.h +++ b/src/cnetz/telegramm.h @@ -120,7 +120,7 @@ const char *telegramm_name(uint8_t opcode); const char *telegramm2rufnummer(telegramm_t *telegramm); const char *transaction2rufnummer(transaction_t *trans); -int match_fuz(telegramm_t *telegramm); +int match_fuz(cnetz_t *cnetz, telegramm_t *telegramm, int cell); int match_futln(telegramm_t *telegramm, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest); int detect_sync(uint64_t bitstream);