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.
This commit is contained in:
Andreas Eversberg 2016-05-10 19:25:07 +02:00
parent 021c34a899
commit e2a9c2c6a5
9 changed files with 211 additions and 98 deletions

View File

@ -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)) {

View File

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

View File

@ -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 {

View File

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

View File

@ -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 <rx ppm>,<tx ppm>\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 <power level>\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;

View File

@ -2,27 +2,58 @@
#include <string.h>
#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;
}

View File

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

View File

@ -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;
}

View File

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