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);