diff options
Diffstat (limited to 'src/cnetz')
-rw-r--r-- | src/cnetz/Makefile.am | 16 | ||||
-rw-r--r-- | src/cnetz/cnetz.c | 702 | ||||
-rw-r--r-- | src/cnetz/cnetz.h | 31 | ||||
-rw-r--r-- | src/cnetz/database.c | 97 | ||||
-rw-r--r-- | src/cnetz/database.h | 4 | ||||
-rw-r--r-- | src/cnetz/dsp.c | 265 | ||||
-rw-r--r-- | src/cnetz/dsp.h | 2 | ||||
-rw-r--r-- | src/cnetz/fsk_demod.c | 82 | ||||
-rw-r--r-- | src/cnetz/fsk_demod.h | 4 | ||||
-rw-r--r-- | src/cnetz/image.c | 95 | ||||
-rw-r--r-- | src/cnetz/main.c | 127 | ||||
-rw-r--r-- | src/cnetz/stations.c | 4493 | ||||
-rw-r--r-- | src/cnetz/stations.h | 2 | ||||
-rw-r--r-- | src/cnetz/sysinfo.c | 11 | ||||
-rw-r--r-- | src/cnetz/sysinfo.h | 6 | ||||
-rw-r--r-- | src/cnetz/telegramm.c | 127 | ||||
-rw-r--r-- | src/cnetz/telegramm.h | 2 | ||||
-rw-r--r-- | src/cnetz/transaction.c | 140 | ||||
-rw-r--r-- | src/cnetz/transaction.h | 25 |
19 files changed, 3146 insertions, 3085 deletions
diff --git a/src/cnetz/Makefile.am b/src/cnetz/Makefile.am index 28ae31a..fcf96da 100644 --- a/src/cnetz/Makefile.am +++ b/src/cnetz/Makefile.am @@ -1,8 +1,13 @@ -AM_CPPFLAGS = -Wall -Wextra -g $(all_includes) +AM_CPPFLAGS = -Wall -Wextra -Wmissing-prototypes -g $(all_includes) bin_PROGRAMS = \ cnetz +noinst_LIBRARIES = libcnetztones.a + +libcnetztones_a_SOURCES = \ + ansage.c + cnetz_SOURCES = \ cnetz.c \ transaction.c \ @@ -12,27 +17,28 @@ cnetz_SOURCES = \ dsp.c \ fsk_demod.c \ image.c \ - ansage.c \ stations.c \ main.c cnetz_LDADD = \ $(COMMON_LA) \ ../anetz/libgermanton.a \ + libcnetztones.a \ $(top_builddir)/src/liboptions/liboptions.a \ - $(top_builddir)/src/libdebug/libdebug.a \ $(top_builddir)/src/libmobile/libmobile.a \ $(top_builddir)/src/libdisplay/libdisplay.a \ $(top_builddir)/src/libcompandor/libcompandor.a \ $(top_builddir)/src/libjitter/libjitter.a \ - $(top_builddir)/src/libtimer/libtimer.a \ $(top_builddir)/src/libsamplerate/libsamplerate.a \ $(top_builddir)/src/libscrambler/libscrambler.a \ $(top_builddir)/src/libemphasis/libemphasis.a \ $(top_builddir)/src/libfm/libfm.a \ $(top_builddir)/src/libfilter/libfilter.a \ $(top_builddir)/src/libwave/libwave.a \ - $(top_builddir)/src/libmncc/libmncc.a \ $(top_builddir)/src/libsample/libsample.a \ + $(top_builddir)/src/libaaimage/libaaimage.a \ + $(top_builddir)/src/liblogging/liblogging.a \ + $(LIBOSMOCORE_LIBS) \ + $(LIBOSMOCC_LIBS) \ -lm if HAVE_ALSA diff --git a/src/cnetz/cnetz.c b/src/cnetz/cnetz.c index df0968b..b3771d7 100644 --- a/src/cnetz/cnetz.c +++ b/src/cnetz/cnetz.c @@ -42,7 +42,7 @@ * If no SpK is available, the call is rejected. If queue (Warteschlange) is * enabled, WSK(R) is scheduled. After transmission, the state changes to * TRANS_MT_QUEUE. Upon timeout (no channel becomes available), the call is - * rejected by scheduling VA(R). Upon available channel the call proceeeds with + * rejected by scheduling VA(R). Upon available channel the call proceeds with * VAK(R) as described above. * * If an MO (mobile originating) call is made (received VWG(K)), a transaction @@ -57,11 +57,11 @@ * (Warteschlange) is enabled, WWBP(R) is scheduled. After transmission, the * state is changed to TRANS_MO_QUEUE. Upon timeout (no channel becomes * available), the call is rejected by scheduling VA(R). Upon available channel - * the call proceeeds with VAG(R) as described above. + * the call proceeds with VAG(R) as described above. * * Switching to SpK is performed two time slots after transmitting VAK(R) or * VAG(R). The timer is started. The schedulers schedules 8 times BQ(K) and - * awaits at least one BEL(K). If BEK(K) is received, the timer is stoped. If + * awaits at least one BEL(K). If BEK(K) is received, the timer is stopped. If * BQ(K) was sent at least 8 times and if timer is stopped, the scheduler * schedules VHQ(K). If no BEL(K) was received, AFK(K) is scheduled N_AFKT * times, then the process on OgK (WBP+VAG or VAK) is repeated N times. @@ -114,7 +114,7 @@ /* * Notes on the combined channel hack: * - * For combined SpK+OgK hack, the channel is used as SpK as last choise. This + * For combined SpK+OgK hack, the channel is used as SpK as last choice. This * allows to use only one transceiver for making C-Netz to work. Also it allows * to use all transceivers for simultanious phone calls. Some phones may not * work with that. @@ -126,7 +126,7 @@ * The encoder generates a precise clocked signal using correction value given * by command line. For multichannel, the second sound card's channel (slave) is * synced to the first one (master), if calculation of signal phase might drift - * due to routing errors. + * due to rounding errors. * * The decoder is synced to the phone, whenever it receives a valid frame. * @@ -143,9 +143,12 @@ #include <math.h> #include <inttypes.h> #include "../libsample/sample.h" -#include "../libdebug/debug.h" +#include "../liblogging/logging.h" #include "../libmobile/call.h" -#include "../libmncc/cause.h" +#include "../libmobile/cause.h" +#include "../libmobile/get_time.h" +#include "../libmobile/console.h" +#include <osmocom/cc/message.h> #include "cnetz.h" #include "database.h" #include "sysinfo.h" @@ -156,11 +159,15 @@ /* uncomment this to do echo debugging (-l) on Speech Channel */ //#define DEBUG_SPK +#define FLOAT_TO_TIMEOUT(f) floor(f), ((f) - floor(f)) * 1000000 + #define CUT_OFF_EMPHASIS_CNETZ 796.0 /* 200 uS time constant */ -/* Call reference for calls from mobile station to network - This offset of 0x400000000 is required for MNCC interface. */ -static int new_callref = 0x40000000; +/* OgK list of alternative channels, NOT including 131 */ +cnetz_t *ogk_list[16]; +int ogk_list_count = 0; +int ogk_list_index = 0; + /* Convert channel number to frequency number of base station. Set 'unterband' to 1 to get frequency of mobile station. */ @@ -181,6 +188,28 @@ double cnetz_kanal2freq(int kanal, int unterband) return freq * 1e6; } +/* check if number is a valid station ID */ +const char *cnetz_number_valid(const char *number) +{ + /* assume that the number has valid length(s) and digits */ + + if (number[0] > '7') + return "Digit 1 (mobile country code) exceeds 7."; + if (number[7]) { + if ((number[1] - '0') == 0) + return "Digit 2 and 3 (mobile network code) of 8-digit number must be at least 10."; + if ((number[1] - '0') * 10 + (number[2] - '0') > 31) + return "Digit 2 and 3 (mobile network code) of 8-digit number exceed 31."; + if (atoi(number + 3) > 65535) + return "Digit 4 to 8 (mobile subscriber suffix) of 8-digit number exceed 65535."; + } else { + if (atoi(number + 2) > 65535) + return "Digit 3 to 7 (mobile subscriber suffix) of 7-digit number exceed 65535."; + } + + return NULL; +} + /* convert power level to P-bits by selecting next higher level */ static uint8_t cnetz_power2bits(int power) { @@ -201,7 +230,7 @@ static uint8_t cnetz_power2bits(int power) } } -const char *cnetz_state_name(enum cnetz_state state) +static const char *cnetz_state_name(enum cnetz_state state) { static char invalid[16]; @@ -238,13 +267,13 @@ static void cnetz_new_state(cnetz_t *cnetz, enum cnetz_state new_state) { if (cnetz->state == new_state) return; - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "State change: %s -> %s\n", cnetz_state_name(cnetz->state), cnetz_state_name(new_state)); + LOGP_CHAN(DCNETZ, LOGL_INFO, "State change: %s -> %s\n", cnetz_state_name(cnetz->state), cnetz_state_name(new_state)); cnetz->state = new_state; cnetz_display_status(); } /* Convert ISDN cause to 'Ausloesegrund' of C-Netz mobile station */ -uint8_t cnetz_cause_isdn2cnetz(int cause) +static uint8_t cnetz_cause_isdn2cnetz(int cause) { switch (cause) { case CAUSE_NORMAL: @@ -267,65 +296,71 @@ int cnetz_init(void) } /* Create transceiver instance and link to a list. */ -int cnetz_create(const char *kanal, enum cnetz_chan_type chan_type, const char *audiodev, int use_sdr, enum demod_type demod, int samplerate, double rx_gain, int challenge_valid, uint64_t challenge, int response_valid, uint64_t response, int warteschlange, int metering, double speech_deviation, 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, const char *read_tx_wave, int loopback) +int cnetz_create(const char *kanal_name, enum cnetz_chan_type chan_type, const char *device, int use_sdr, enum demod_type demod, int samplerate, double rx_gain, double tx_gain, int challenge_valid, uint64_t challenge, int response_valid, uint64_t response, int warteschlange, int metering, double speech_deviation, 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, const char *read_tx_wave, int loopback) { sender_t *sender; cnetz_t *cnetz; + int kanal; int rc; - if ((atoi(kanal) & 1) && (atoi(kanal) < 3 || atoi(kanal) > 1147)) { - PDEBUG(DCNETZ, DEBUG_ERROR, "Channel ('Kanal') number %s invalid. For odd channel numbers, use channel 3 ... 1147.\n", kanal); + kanal = atoi(kanal_name); + if ((kanal & 1) && (kanal < 3 || kanal > 1147)) { + LOGP(DCNETZ, LOGL_ERROR, "Channel ('Kanal') number %d invalid. For odd channel numbers, use channel 3 ... 1147.\n", kanal); return -EINVAL; } - if ((atoi(kanal) & 1) && atoi(kanal) > 947) { - PDEBUG(DCNETZ, DEBUG_NOTICE, "You defined an extended frequency channel %s, only newer phones support this!\n", kanal); + if ((kanal & 1) && kanal > 947) { + LOGP(DCNETZ, LOGL_NOTICE, "You defined an extended frequency channel %d, only newer phones support this!\n", kanal); } - if (!(atoi(kanal) & 1) && (atoi(kanal) < 4 || atoi(kanal) > 918)) { - PDEBUG(DCNETZ, DEBUG_ERROR, "Channel ('Kanal') number %s invalid. For even channel numbers, use channel 4 ... 918.\n", kanal); + if (!(kanal & 1) && (kanal < 4 || kanal > 918)) { + LOGP(DCNETZ, LOGL_ERROR, "Channel ('Kanal') number %d invalid. For even channel numbers, use channel 4 ... 918.\n", kanal); return -EINVAL; } - if (!(atoi(kanal) & 1) && atoi(kanal) > 758) { - PDEBUG(DCNETZ, DEBUG_NOTICE, "You defined an extended frequency %s, only newer phones support this!\n", kanal); - } - - /* OgK must be on channel 131 */ - if ((chan_type == CHAN_TYPE_OGK || chan_type == CHAN_TYPE_OGK_SPK) && atoi(kanal) != CNETZ_OGK_KANAL) { - PDEBUG(DCNETZ, DEBUG_NOTICE, "You must use channel %d for calling channel ('Orga-Kanal') or for combined calling + traffic channel!\n", CNETZ_OGK_KANAL); - return -EINVAL; + if (!(kanal & 1) && kanal > 758) { + LOGP(DCNETZ, LOGL_NOTICE, "You defined an extended frequency channel %d, only newer phones support this!\n", kanal); } /* SpK must be on channel other than 131 */ - if (chan_type == CHAN_TYPE_SPK && atoi(kanal) == CNETZ_OGK_KANAL) { - PDEBUG(DCNETZ, DEBUG_NOTICE, "You must not use channel %d for traffic channel!\n", CNETZ_OGK_KANAL); + if (chan_type == CHAN_TYPE_SPK && kanal == CNETZ_STD_OGK_KANAL) { + LOGP(DCNETZ, LOGL_NOTICE, "You must not use channel %d for traffic channel!\n", CNETZ_STD_OGK_KANAL); return -EINVAL; } /* warn if we combine SpK and OgK, this is not supported by standard */ if (chan_type == CHAN_TYPE_OGK_SPK) { - PDEBUG(DCNETZ, DEBUG_NOTICE, "You selected channel %d ('Orga-Kanal') for combined calling + traffic channel. Some phones will reject this.\n", CNETZ_OGK_KANAL); + LOGP(DCNETZ, LOGL_NOTICE, "You selected channel %d ('Orga-Kanal') for combined control + traffic channel. Some phones will reject this.\n", kanal); } for (sender = sender_head; sender; sender = sender->next) { cnetz = (cnetz_t *)sender; - if (!!strcmp(sender->audiodev, audiodev)) { - PDEBUG(DCNETZ, DEBUG_NOTICE, "To be able to sync multiple channels, all channels must be on the same sound device!\n"); + if (!!strcmp(sender->device, device)) { + LOGP(DCNETZ, LOGL_NOTICE, "To be able to sync multiple channels, all channels must be on the same sound device!\n"); return -EINVAL; } } cnetz = calloc(1, sizeof(cnetz_t)); if (!cnetz) { - PDEBUG(DCNETZ, DEBUG_ERROR, "No memory!\n"); + LOGP(DCNETZ, LOGL_ERROR, "No memory!\n"); return -ENOMEM; } - PDEBUG(DCNETZ, DEBUG_DEBUG, "Creating 'C-Netz' instance for 'Kanal' = %s (sample rate %d).\n", kanal, samplerate); + LOGP(DCNETZ, LOGL_DEBUG, "Creating 'C-Netz' instance for 'Kanal' = %d (sample rate %d).\n", kanal, samplerate); + + cnetz->kanal = kanal; + if ((chan_type == CHAN_TYPE_OGK || chan_type == CHAN_TYPE_OGK_SPK) && kanal != CNETZ_STD_OGK_KANAL) { + if (ogk_list_count == 16) { + LOGP(DCNETZ, LOGL_ERROR, "No more than 16 non-standard OGK are allowed!\n"); + rc = -EINVAL; + goto error; + } + ogk_list[ogk_list_count++] = cnetz; + } /* init general part of transceiver */ /* do not enable emphasis, since it is done by cnetz code, not by common sender code */ - rc = sender_create(&cnetz->sender, kanal, cnetz_kanal2freq(atoi(kanal), 0), cnetz_kanal2freq(atoi(kanal), 1), audiodev, use_sdr, samplerate, rx_gain, 0, 0, write_rx_wave, write_tx_wave, read_rx_wave, read_tx_wave, loopback, PAGING_SIGNAL_NONE); + rc = sender_create(&cnetz->sender, kanal_name, cnetz_kanal2freq(kanal, 0), cnetz_kanal2freq(kanal, 1), device, use_sdr, samplerate, rx_gain, tx_gain, 0, 0, write_rx_wave, write_tx_wave, read_rx_wave, read_tx_wave, loopback, PAGING_SIGNAL_NONE); if (rc < 0) { - PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to init transceiver process!\n"); + LOGP(DCNETZ, LOGL_ERROR, "Failed to init transceiver process!\n"); goto error; } @@ -340,7 +375,7 @@ int cnetz_create(const char *kanal, enum cnetz_chan_type chan_type, const char * /* init audio processing */ rc = dsp_init_sender(cnetz, measure_speed, clock_speed, demod, speech_deviation); if (rc < 0) { - PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to init signal processing!\n"); + LOGP(DCNETZ, LOGL_ERROR, "Failed to init signal processing!\n"); goto error; } @@ -377,42 +412,46 @@ int cnetz_create(const char *kanal, enum cnetz_chan_type chan_type, const char * goto error; /* go into idle state */ - cnetz_set_dsp_mode(cnetz, DSP_MODE_OGK); - cnetz_set_sched_dsp_mode(cnetz, DSP_MODE_OGK, 0); + if (chan_type == CHAN_TYPE_OGK || chan_type == CHAN_TYPE_OGK_SPK) + cnetz_set_dsp_mode(cnetz, DSP_MODE_OGK); + else + cnetz_set_dsp_mode(cnetz, DSP_MODE_OFF); cnetz_go_idle(cnetz); #ifdef DEBUG_SPK - transaction_t *trans = create_transaction(cnetz, TRANS_DS, 2, 2, 22002, -1, -1); + transaction_t *trans = create_transaction(cnetz, TRANS_DS, 2, 2, 22002, -1, -1, NAN); trans->mo_call = 1; - cnetz_set_sched_dsp_mode(cnetz, DSP_MODE_SPK_K, 2); + cnetz_set_sched_dsp_mode(cnetz, DSP_MODE_SPK_K, (cnetz->sched_ts + 2) & 31); #else /* create transaction for speech channel loopback */ if (loopback && chan_type == CHAN_TYPE_SPK) { - transaction_t *trans = create_transaction(cnetz, TRANS_VHQ_K, 2, 2, 22002, -1, -1); + transaction_t *trans = create_transaction(cnetz, TRANS_VHQ_K, 2, 2, 22002, -1, -1, NAN); trans->mo_call = 1; cnetz_set_dsp_mode(cnetz, DSP_MODE_SPK_K); - cnetz_set_sched_dsp_mode(cnetz, DSP_MODE_SPK_K, 0); + cnetz_set_sched_dsp_mode(cnetz, DSP_MODE_SPK_K, (cnetz->sched_ts + 1) & 31); } #endif #if 0 /* debug flushing transactions */ transaction_t *trans1, *trans2; - trans1 = create_transaction(cnetz, 99, 6, 2, 15784, -1, -1); + trans1 = create_transaction(cnetz, 99, 6, 2, 15784, -1, -1, NAN); destroy_transaction(trans1); - trans1 = create_transaction(cnetz, 99, 6, 2, 15784, -1, -1); + trans1 = create_transaction(cnetz, 99, 6, 2, 15784, -1, -1, NAN); destroy_transaction(trans1); - trans1 = create_transaction(cnetz, 99, 6, 2, 15784, -1, -1); - trans2 = create_transaction(cnetz, 99, 2, 2, 22002, -1, -1); + trans1 = create_transaction(cnetz, 99, 6, 2, 15784, -1, -1, NAN); + trans2 = create_transaction(cnetz, 99, 2, 2, 22002, -1, -1, NAN); unlink_transaction(trans1); link_transaction(trans1, cnetz); cnetz_flush_other_transactions(cnetz, trans1); - trans2 = create_transaction(cnetz, 99, 2, 2, 22002, -1, -1); + trans2 = create_transaction(cnetz, 99, 2, 2, 22002, -1, -1, NAN); cnetz_flush_other_transactions(cnetz, trans2); #endif - PDEBUG(DCNETZ, DEBUG_NOTICE, "Created 'Kanal' #%s of type '%s' = %s\n", kanal, chan_type_short_name(chan_type), chan_type_long_name(chan_type)); - PDEBUG(DNMT, DEBUG_NOTICE, " -> Using cell ID: Nat=%d FuVst=%d Rest=%d Name='%s'\n", si.fuz_nat, si.fuz_fuvst, si.fuz_rest, get_station_name(si.fuz_nat, si.fuz_fuvst, si.fuz_rest)); + LOGP(DCNETZ, LOGL_NOTICE, "Created 'Kanal' #%d of type '%s' = %s\n", kanal, chan_type_short_name(chan_type), chan_type_long_name(chan_type)); + const char *name, *long_name; + name = get_station_name(si.fuz_nat, si.fuz_fuvst, si.fuz_rest, &long_name); + LOGP(DCNETZ, LOGL_NOTICE, " -> Using cell ID: Nat=%d FuVst=%d Rest=%d Name='%s' Long Name='%s'\n", si.fuz_nat, si.fuz_fuvst, si.fuz_rest, name, long_name); return 0; @@ -428,11 +467,11 @@ void cnetz_destroy(sender_t *sender) cnetz_t *cnetz = (cnetz_t *) sender; transaction_t *trans; - PDEBUG(DCNETZ, DEBUG_DEBUG, "Destroying 'C-Netz' instance for 'Kanal' = %s.\n", sender->kanal); + LOGP(DCNETZ, LOGL_DEBUG, "Destroying 'C-Netz' instance for 'Kanal' = %s.\n", sender->kanal); while ((trans = search_transaction(cnetz, ~0))) { const char *rufnummer = transaction2rufnummer(trans); - PDEBUG(DCNETZ, DEBUG_NOTICE, "Removing pending transaction for subscriber '%s'\n", rufnummer); + LOGP(DCNETZ, LOGL_NOTICE, "Removing pending transaction for subscriber '%s'\n", rufnummer); destroy_transaction(trans); } @@ -450,9 +489,9 @@ static cnetz_t *search_free_spk(int extended) cnetz = (cnetz_t *) sender; /* ignore extended frequency, if not supported */ if (!extended) { - if ((atoi(sender->kanal) & 1) && atoi(sender->kanal) > 947) + if ((cnetz->kanal & 1) && cnetz->kanal > 947) continue; - if (!(atoi(sender->kanal) & 1) && atoi(sender->kanal) > 758) + if (!(cnetz->kanal & 1) && cnetz->kanal > 758) continue; } /* ignore busy channel */ @@ -469,7 +508,7 @@ static cnetz_t *search_free_spk(int extended) return ogk_spk; } -static cnetz_t *search_ogk(void) +static cnetz_t *search_ogk(int kanal) { sender_t *sender; cnetz_t *cnetz; @@ -479,6 +518,8 @@ static cnetz_t *search_ogk(void) /* ignore busy channel */ if (cnetz->state != CNETZ_IDLE) continue; + if (cnetz->kanal != kanal) + continue; if (cnetz->chan_type == CHAN_TYPE_OGK) return cnetz; if (cnetz->chan_type == CHAN_TYPE_OGK_SPK) @@ -491,39 +532,40 @@ static cnetz_t *search_ogk(void) /* Abort connection, if any and send idle broadcast */ void cnetz_go_idle(cnetz_t *cnetz) { - cnetz_t *ogk; transaction_t *trans; if (cnetz->state == CNETZ_IDLE) return; if (cnetz->trans_list) { - PDEBUG(DCNETZ, DEBUG_ERROR, "Releasing but still having transaction, please fix!\n"); + LOGP(DCNETZ, LOGL_ERROR, "Releasing but still having transaction, please fix!\n"); if (cnetz->trans_list->callref) call_up_release(cnetz->trans_list->callref, CAUSE_NORMAL); destroy_transaction(cnetz->trans_list); } - PDEBUG(DCNETZ, DEBUG_INFO, "Entering IDLE state on channel %s.\n", cnetz->sender.kanal); + LOGP(DCNETZ, LOGL_INFO, "Entering IDLE state on channel %s.\n", cnetz->sender.kanal); cnetz_new_state(cnetz, CNETZ_IDLE); + cnetz->sched_lr_debugged = 0; + cnetz->sched_mlr_debugged = 0; /* set scheduler to OgK or turn off SpK */ if (cnetz->dsp_mode == DSP_MODE_SPK_K || cnetz->dsp_mode == DSP_MODE_SPK_V) { - /* go idle after next frame/slot */ - cnetz_set_sched_dsp_mode(cnetz, (atoi(cnetz->sender.kanal) == CNETZ_OGK_KANAL) ? DSP_MODE_OGK : DSP_MODE_OFF, 1); + /* switch next frame after distributed signaling boundary (multiple of 8 slots) */ + cnetz_set_sched_dsp_mode(cnetz, (cnetz->chan_type == CHAN_TYPE_OGK || cnetz->chan_type == CHAN_TYPE_OGK_SPK) ? DSP_MODE_OGK : DSP_MODE_OFF, (cnetz->sched_ts + 8) & 24); } else { - cnetz_set_sched_dsp_mode(cnetz, (atoi(cnetz->sender.kanal) == CNETZ_OGK_KANAL) ? DSP_MODE_OGK : DSP_MODE_OFF, 0); - cnetz_set_dsp_mode(cnetz, (atoi(cnetz->sender.kanal) == CNETZ_OGK_KANAL) ? DSP_MODE_OGK : DSP_MODE_OFF); + /* switch next frame */ + cnetz_set_sched_dsp_mode(cnetz, (cnetz->chan_type == CHAN_TYPE_OGK || cnetz->chan_type == CHAN_TYPE_OGK_SPK) ? DSP_MODE_OGK : DSP_MODE_OFF, (cnetz->sched_ts + 1) & 31); + cnetz_set_dsp_mode(cnetz, (cnetz->chan_type == CHAN_TYPE_OGK || cnetz->chan_type == CHAN_TYPE_OGK_SPK) ? DSP_MODE_OGK : DSP_MODE_OFF); } /* check for first phone in queue and trigger completion of call (becoming idle means that SpK is now available) */ - ogk = search_ogk(); - trans = search_transaction(ogk, TRANS_MT_QUEUE | TRANS_MO_QUEUE); + trans = search_transaction_queue(); if (trans) { - PDEBUG(DCNETZ, DEBUG_NOTICE, "Now channel available for queued subscriber '%s'.\n", transaction2rufnummer(trans)); + LOGP(DCNETZ, LOGL_NOTICE, "Now channel is available for queued subscriber '%s'.\n", transaction2rufnummer(trans)); trans_new_state(trans, (trans->state == TRANS_MT_QUEUE) ? TRANS_MT_DELAY : TRANS_MO_DELAY); - timer_stop(&trans->timer); - timer_start(&trans->timer, 2.0); + osmo_timer_del(&trans->timer); + osmo_timer_schedule(&trans->timer, 3,0); /* Wait at least one frame cycles (2.4s) until timeout */ } } @@ -533,120 +575,68 @@ static void cnetz_release(transaction_t *trans, uint8_t cause) trans_new_state(trans, (trans->cnetz->dsp_mode == DSP_MODE_OGK) ? TRANS_VA : TRANS_AF); trans->repeat = 0; trans->release_cause = cause; - trans->cnetz->sched_switch_mode = 0; - timer_stop(&trans->timer); -} - -/* Receive audio from call instance. */ -void call_down_audio(int callref, sample_t *samples, int count) -{ - sender_t *sender; - cnetz_t *cnetz; - - for (sender = sender_head; sender; sender = sender->next) { - cnetz = (cnetz_t *) sender; - if (cnetz->trans_list && cnetz->trans_list->callref == callref) - break; - } - if (!sender) - return; - - if (cnetz->dsp_mode == DSP_MODE_SPK_V) { - /* store as is, since we convert rate when processing FSK frames */ - jitter_save(&cnetz->sender.dejitter, samples, count); - } + trans->cnetz->sched_dsp_mode_ts = -1; + osmo_timer_del(&trans->timer); } -void call_down_clock(void) {} - int call_down_setup(int callref, const char __attribute__((unused)) *caller_id, enum number_type __attribute__((unused)) caller_type, const char *dialing) { - sender_t *sender; - cnetz_t *cnetz, *spk; + cnetz_t *ogk, *spk; int rc; int extended; transaction_t *trans; uint8_t futln_nat; uint8_t futln_fuvst; int futln_rest; /* use int for checking size > 65535 */ - int len; - int i; - - /* 1. check if number is invalid, return INVALNUMBER */ - len = strlen(dialing); - if (len >= 11 && !strncmp(dialing, "0161", 4)) { - dialing += 4; - len -= 4; - } - if (len < 7 || len > 8) { -inval: - PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call to invalid number '%s', rejecting!\n", dialing); - return -CAUSE_INVALNUMBER; - } - for (i = 0; i < len; i++) { - if (dialing[i] < '0' || dialing[i] > '9') - goto inval; - } + int ogk_kanal; + /* 1. split number into elements */ futln_nat = dialing[0] - '0'; - if (len == 7) - futln_fuvst = dialing[1] - '0'; - else { + if (dialing[7]) { futln_fuvst = (dialing[1] - '0') * 10 + (dialing[2] - '0'); - if (futln_fuvst > 31) { - PDEBUG(DCNETZ, DEBUG_NOTICE, "Digit 2 and 3 '%02d' must not exceed '31', but they do!\n", futln_fuvst); - goto inval; - } - } - futln_rest = atoi(dialing + len - 5); - if (futln_rest > 65535) { - PDEBUG(DCNETZ, DEBUG_NOTICE, "Last 5 digits '%05d' must not exceed '65535', but they do!\n", futln_rest); - goto inval; + futln_rest = atoi(dialing + 3); + } else { + futln_fuvst = dialing[1] - '0'; + futln_rest = atoi(dialing + 2); } /* 2. check if the subscriber is attached */ - rc = find_db(futln_nat, futln_fuvst, futln_rest, NULL, &extended); + rc = find_db(futln_nat, futln_fuvst, futln_rest, &ogk_kanal, NULL, &extended); if (rc < 0) { - PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call to not attached subscriber, rejecting!\n"); + LOGP(DCNETZ, LOGL_NOTICE, "Outgoing call to not attached subscriber, rejecting!\n"); return -CAUSE_OUTOFORDER; } /* 3. check if given number is already in a call, return BUSY */ - for (sender = sender_head; sender; sender = sender->next) { - cnetz = (cnetz_t *) sender; - /* search transaction for this number */ - trans = search_transaction_number(cnetz, futln_nat, futln_fuvst, futln_rest); - if (trans) - break; - } - if (sender) { - PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call to busy number, rejecting!\n"); + trans = search_transaction_number_global(futln_nat, futln_fuvst, futln_rest); + if (trans) { + LOGP(DCNETZ, LOGL_NOTICE, "Outgoing call to busy number, rejecting!\n"); return -CAUSE_BUSY; } /* 4. check if we have no OgK, return NOCHANNEL */ - cnetz = search_ogk(); - if (!cnetz) { - PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call, but OgK is currently busy, rejecting!\n"); + ogk = search_ogk(ogk_kanal); + if (!ogk) { + LOGP(DCNETZ, LOGL_NOTICE, "Outgoing call, but OgK is currently busy, rejecting!\n"); return -CAUSE_NOCHANNEL; } /* 5. check if all senders are busy, return NOCHANNEL */ spk = search_free_spk(extended); if (!spk) { - if (!cnetz->warteschlange) { - PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call, but no free channel, rejecting!\n"); + if (!ogk->warteschlange) { + LOGP(DCNETZ, LOGL_NOTICE, "Outgoing call, but no free channel, rejecting!\n"); return -CAUSE_NOCHANNEL; } else - PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call, but no free channel, queuing call!\n"); + LOGP(DCNETZ, LOGL_NOTICE, "Outgoing call, but no free channel, queuing call!\n"); } - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Call to mobile station, paging station id '%s'\n", dialing); + LOGP(DCNETZ, LOGL_INFO, "Call to mobile station, paging station id '%s'\n", dialing); /* 6. trying to page mobile station */ - trans = create_transaction(cnetz, (spk) ? TRANS_VAK : TRANS_WSK, dialing[0] - '0', dialing[1] - '0', atoi(dialing + 2), -1, -1); + trans = create_transaction(ogk, (spk) ? TRANS_VAK : TRANS_WSK, futln_nat, futln_fuvst, futln_rest, -1, -1, NAN); if (!trans) { - PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n"); + LOGP(DCNETZ, LOGL_ERROR, "Failed to create transaction\n"); return -CAUSE_TEMPFAIL; } trans->callref = callref; @@ -655,8 +645,35 @@ inval: return 0; } -void call_down_answer(int __attribute__((unused)) callref) +void call_down_answer(int callref, struct timeval *tv_meter) { + sender_t *sender; + cnetz_t *cnetz; + transaction_t *trans; + + LOGP(DCNETZ, LOGL_INFO, "Call has been answered by network.\n"); + + for (sender = sender_head; sender; sender = sender->next) { + cnetz = (cnetz_t *) sender; + trans = search_transaction_callref(cnetz, callref); + if (trans) + break; + } + if (!sender) { + LOGP(DCNETZ, LOGL_NOTICE, "Incoming answer, but no callref!\n"); + return; + } + + /* At least tone second! */ + if (tv_meter->tv_sec) { + LOGP(DCNETZ, LOGL_INFO, "Network starts metering pulses every %lu.%03lu seconds.\n", tv_meter->tv_sec, tv_meter->tv_usec / 1000); + trans->meter_start = get_time(); + trans->metering_time = (double)tv_meter->tv_sec + (double)tv_meter->tv_usec / 1000000.0; + } else if (cnetz->metering) { + LOGP(DCNETZ, LOGL_INFO, "Command line options starts metering pulses every %d seconds.\n", cnetz->metering); + trans->meter_start = get_time(); + trans->metering_time = (double)cnetz->metering; + } } /* Call control sends disconnect (with tones). @@ -669,7 +686,7 @@ void call_down_disconnect(int callref, int cause) cnetz_t *cnetz; transaction_t *trans; - PDEBUG(DCNETZ, DEBUG_INFO, "Call has been disconnected by network.\n"); + LOGP(DCNETZ, LOGL_INFO, "Call has been disconnected by network.\n"); for (sender = sender_head; sender; sender = sender->next) { cnetz = (cnetz_t *) sender; @@ -679,7 +696,7 @@ void call_down_disconnect(int callref, int cause) break; } if (!sender) { - PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing disconnect, but no callref!\n"); + LOGP(DCNETZ, LOGL_NOTICE, "Outgoing disconnect, but no callref!\n"); call_up_release(callref, CAUSE_INVALCALLREF); return; } @@ -688,15 +705,17 @@ void call_down_disconnect(int callref, int cause) switch (cnetz->dsp_mode) { case DSP_MODE_SPK_V: + /* stop metering */ + trans->meter_end = get_time(); return; case DSP_MODE_SPK_K: - PDEBUG(DCNETZ, DEBUG_INFO, "Call control disconnects on speech channel, releasing towards mobile station.\n"); + LOGP(DCNETZ, LOGL_INFO, "Call control disconnects on speech channel, releasing towards mobile station.\n"); cnetz_release(trans, cnetz_cause_isdn2cnetz(cause)); call_up_release(callref, cause); trans->callref = 0; break; default: - PDEBUG(DCNETZ, DEBUG_INFO, "Call control disconnects on organisation channel, removing transaction.\n"); + LOGP(DCNETZ, LOGL_INFO, "Call control disconnects on organisation channel, removing transaction.\n"); call_up_release(callref, cause); trans->callref = 0; if (trans->state == TRANS_MT_QUEUE || trans->state == TRANS_MT_DELAY) { @@ -716,7 +735,7 @@ void call_down_release(int callref, int cause) cnetz_t *cnetz; transaction_t *trans; - PDEBUG(DCNETZ, DEBUG_INFO, "Call has been released by network, releasing call.\n"); + LOGP(DCNETZ, LOGL_INFO, "Call has been released by network, releasing call.\n"); for (sender = sender_head; sender; sender = sender->next) { cnetz = (cnetz_t *) sender; @@ -726,7 +745,7 @@ void call_down_release(int callref, int cause) break; } if (!sender) { - PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing release, but no callref!\n"); + LOGP(DCNETZ, LOGL_NOTICE, "Outgoing release, but no callref!\n"); /* don't send release, because caller already released */ return; } @@ -736,11 +755,11 @@ void call_down_release(int callref, int cause) switch (cnetz->dsp_mode) { case DSP_MODE_SPK_K: case DSP_MODE_SPK_V: - PDEBUG(DCNETZ, DEBUG_INFO, "Call control releases on speech channel, releasing towards mobile station.\n"); + LOGP(DCNETZ, LOGL_INFO, "Call control releases on speech channel, releasing towards mobile station.\n"); cnetz_release(trans, cnetz_cause_isdn2cnetz(cause)); break; default: - PDEBUG(DCNETZ, DEBUG_INFO, "Call control releases on organisation channel, removing transaction.\n"); + LOGP(DCNETZ, LOGL_INFO, "Call control releases on organisation channel, removing transaction.\n"); if (trans->state == TRANS_MT_QUEUE) { cnetz_release(trans, cnetz_cause_isdn2cnetz(cause)); } else { @@ -750,19 +769,19 @@ void call_down_release(int callref, int cause) } } -int cnetz_meldeaufruf(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest) +int cnetz_meldeaufruf(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int ogk_kanal) { cnetz_t *cnetz; transaction_t *trans; - cnetz = search_ogk(); + cnetz = search_ogk(ogk_kanal); if (!cnetz) { - PDEBUG(DCNETZ, DEBUG_NOTICE, "'Meldeaufruf', but OgK is currently busy!\n"); + LOGP(DCNETZ, LOGL_NOTICE, "'Meldeaufruf', but OgK is currently busy!\n"); return -CAUSE_NOCHANNEL; } - trans = create_transaction(cnetz, TRANS_MA, futln_nat, futln_fuvst, futln_rest, -1, -1); + trans = create_transaction(cnetz, TRANS_MA, futln_nat, futln_fuvst, futln_rest, -1, -1, NAN); if (!trans) { - PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n"); + LOGP(DCNETZ, LOGL_ERROR, "Failed to create transaction\n"); return -CAUSE_TEMPFAIL; } @@ -827,29 +846,20 @@ const char *chan_type_long_name(enum cnetz_chan_type chan_type) } /* Timeout handling */ -void transaction_timeout(struct timer *timer) +void transaction_timeout(void *data) { - transaction_t *trans = (transaction_t *)timer->priv; + transaction_t *trans = data; cnetz_t *cnetz = trans->cnetz; switch (trans->state) { - case TRANS_WAF: - PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "No response after dialing request 'Wahlaufforderung'\n"); - if (trans->try == N) { - trans_new_state(trans, TRANS_WBN); - break; - } - trans->try++; - trans_new_state(trans, TRANS_VWG); - break; case TRANS_MT_QUEUE: - PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Phone in queue, but still no channel available, releasing call!\n"); + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Phone in queue, but still no channel available, releasing call!\n"); call_up_release(trans->callref, CAUSE_NOCHANNEL); trans->callref = 0; cnetz_release(trans, CNETZ_CAUSE_GASSENBESETZT); break; case TRANS_MO_QUEUE: - PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Phone in queue, but still no channel available, releasing!\n"); + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Phone in queue, but still no channel available, releasing!\n"); cnetz_release(trans, CNETZ_CAUSE_GASSENBESETZT); break; case TRANS_MT_DELAY: @@ -859,12 +869,12 @@ void transaction_timeout(struct timer *timer) trans_new_state(trans, TRANS_VAG); break; case TRANS_BQ: - PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "No response after channel allocation 'Belegung Quittung'\n"); + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "No response after channel allocation 'Belegung Quittung'\n"); trans_new_state(trans, TRANS_AF); trans->repeat = 0; break; case TRANS_ZFZ: - PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "No response after sending random number 'Zufallszahl'\n"); + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "No response after sending random number 'Zufallszahl'\n"); if (trans->callref) { call_up_release(trans->callref, CAUSE_TEMPFAIL); trans->callref = 0; @@ -872,7 +882,7 @@ void transaction_timeout(struct timer *timer) cnetz_release(trans, CNETZ_CAUSE_FUNKTECHNISCH); break; case TRANS_AP: - PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "No response after waiting for challenge response 'Autorisierungsparameter'\n"); + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "No response after waiting for challenge response 'Autorisierungsparameter'\n"); if (trans->callref) { call_up_release(trans->callref, CAUSE_TEMPFAIL); trans->callref = 0; @@ -882,9 +892,9 @@ void transaction_timeout(struct timer *timer) case TRANS_VHQ_K: case TRANS_VHQ_V: if (cnetz->dsp_mode != DSP_MODE_SPK_V) - PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "No response while holding call 'Quittung Verbindung halten'\n"); + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "No response while holding call 'Quittung Verbindung halten'\n"); else - PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Lost signal from 'FuTln' (mobile station)\n"); + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Lost signal from 'FuTln' (mobile station)\n"); if (trans->callref) { call_up_release(trans->callref, CAUSE_TEMPFAIL); trans->callref = 0; @@ -892,31 +902,25 @@ void transaction_timeout(struct timer *timer) cnetz_release(trans, CNETZ_CAUSE_FUNKTECHNISCH); break; case TRANS_DS: - PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "No response after connect 'Durchschalten'\n"); + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "No response after connect 'Durchschalten'\n"); call_up_release(trans->callref, CAUSE_TEMPFAIL); trans->callref = 0; cnetz_release(trans, CNETZ_CAUSE_FUNKTECHNISCH); break; case TRANS_RTA: - PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "No response after ringing order 'Rufton anschalten'\n"); + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "No response after ringing order 'Rufton anschalten'\n"); call_up_release(trans->callref, CAUSE_TEMPFAIL); trans->callref = 0; cnetz_release(trans, CNETZ_CAUSE_FUNKTECHNISCH); break; case TRANS_AHQ: - PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "No response after answer 'Abhebequittung'\n"); + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "No response after answer 'Abhebequittung'\n"); call_up_release(trans->callref, CAUSE_TEMPFAIL); trans->callref = 0; cnetz_release(trans, CNETZ_CAUSE_FUNKTECHNISCH); break; - case TRANS_MFT: - PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "No response after keepalive order 'Meldeaufruf'\n"); - /* no response to availability check */ - trans->page_failed = 1; - destroy_transaction(trans); - break; default: - PDEBUG_CHAN(DCNETZ, DEBUG_ERROR, "Timeout unhandled in state %" PRIu64 "\n", trans->state); + LOGP_CHAN(DCNETZ, LOGL_ERROR, "Timeout unhandled in state %" PRIu64 "\n", trans->state); } } @@ -948,13 +952,13 @@ void cnetz_sync_frame(cnetz_t *cnetz, double sync, int block) } /* if more than +- one bit out of sync */ if (offset < -0.5 || offset > 0.5) { - PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Frame sync offset = %.2f, correcting!\n", offset); + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Frame sync offset = %.2f, correcting!\n", offset); fsk_correct_sync(&cnetz->fsk_demod, offset); return; } /* resync by some fraction of received sync error */ - PDEBUG_CHAN(DCNETZ, DEBUG_DEBUG, "Frame sync offset = %.2f, correcting.\n", offset); + LOGP_CHAN(DCNETZ, LOGL_DEBUG, "Frame sync offset = %.2f, correcting.\n", offset); fsk_correct_sync(&cnetz->fsk_demod, offset / 2.0); } @@ -984,6 +988,7 @@ const telegramm_t *cnetz_transmit_telegramm_rufblock(cnetz_t *cnetz) telegramm.fuz_fuvst_nr = si.fuz_fuvst; telegramm.fuz_rest_nr = si.fuz_rest; telegramm.kennung_fufst = si.kennung_fufst; + telegramm.bahn_bs = si.bahn_bs; telegramm.nachbarschafts_prioritaets_bit = si.nachbar_prio; telegramm.bewertung_nach_pegel_und_entfernung = si.bewertung; telegramm.entfernungsangabe_der_fufst = si.entfernung; @@ -992,7 +997,7 @@ const telegramm_t *cnetz_transmit_telegramm_rufblock(cnetz_t *cnetz) telegramm.grenzwert_fuer_umschalten = si.grenz_umschalten; telegramm.grenze_fuer_ausloesen = si.grenz_ausloesen; - trans = search_transaction(cnetz, TRANS_EM | TRANS_UM | TRANS_WBN | TRANS_WBP | TRANS_VAG | TRANS_VAK | TRANS_ATQ | TRANS_VA | TRANS_WSK); + trans = search_transaction(cnetz, TRANS_EM | TRANS_UM | TRANS_WBN | TRANS_WBP | TRANS_VAG | TRANS_VAK | TRANS_ATQ | TRANS_ATQ_IDLE | TRANS_VA | TRANS_WSK); if (trans) { telegramm.futln_nationalitaet = trans->futln_nat; telegramm.futln_heimat_fuvst_nr = trans->futln_fuvst; @@ -1000,18 +1005,18 @@ const telegramm_t *cnetz_transmit_telegramm_rufblock(cnetz_t *cnetz) telegramm.ausloesegrund = trans->release_cause; switch (trans->state) { case TRANS_EM: - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending acknowledgment 'Einbuchquittung' to Attachment request.\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending acknowledgment 'Einbuchquittung' to Attachment request.\n"); telegramm.opcode = OPCODE_EBQ_R; destroy_transaction(trans); break; case TRANS_UM: - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending acknowledgment 'Umbuchquittung' to Roaming requuest.\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending acknowledgment 'Umbuchquittung' to Roaming requuest.\n"); telegramm.opcode = OPCODE_UBQ_R; destroy_transaction(trans); break; case TRANS_WBN: wbn: - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending call reject 'Wahlbestaetigung negativ'.\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending call reject 'Wahlbestaetigung negativ'.\n"); telegramm.opcode = OPCODE_WBN_R; destroy_transaction(trans); cnetz_go_idle(cnetz); @@ -1020,17 +1025,17 @@ wbn: spk = search_free_spk(trans->extended); /* Accept call if channel available, otherwise reject or queue call */ if (spk) { - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending call accept 'Wahlbestaetigung positiv'.\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending call accept 'Wahlbestaetigung positiv'.\n"); telegramm.opcode = OPCODE_WBP_R; trans_new_state(trans, TRANS_VAG); } else if (cnetz->warteschlange) { /* queue call if no channel is available, but queue allowed */ - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "No free channel, sending call accept in queue 'Wahlbestaetigung positiv in Warteschlage'.\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "No free channel, sending call accept in queue 'Wahlbestaetigung positiv in Warteschlage'.\n"); telegramm.opcode = OPCODE_WWBP_R; trans_new_state(trans, TRANS_MO_QUEUE); - timer_start(&trans->timer, T_VAG2); /* Maximum time to hold queue */ + osmo_timer_schedule(&trans->timer, T_VAG2); /* Maximum time to hold queue */ } else { - PDEBUG(DCNETZ, DEBUG_NOTICE, "No free channel anymore, rejecting call!\n"); + LOGP(DCNETZ, LOGL_NOTICE, "No free channel anymore, rejecting call!\n"); trans_new_state(trans, TRANS_WBN); goto wbn; } @@ -1039,36 +1044,36 @@ wbn: case TRANS_VAK: vak: if (trans->state == TRANS_VAG) { - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending channel assignment 'Verbindungsaufbau gehend'.\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending channel assignment 'Verbindungsaufbau gehend'.\n"); telegramm.opcode = OPCODE_VAG_R; } else { - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending channel assignment 'Verbindungsaufbau kommend'.\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending channel assignment 'Verbindungsaufbau kommend'.\n"); telegramm.opcode = OPCODE_VAK_R; } trans_new_state(trans, TRANS_BQ); trans->repeat = 0; - timer_start(&trans->timer, 0.150 + 0.0375 * F_BQ); /* two slots + F_BQ frames */ + osmo_timer_schedule(&trans->timer, FLOAT_TO_TIMEOUT(0.150 + 0.0375 * F_BQ)); /* two slots + F_BQ frames */ /* select channel */ spk = search_free_spk(trans->extended); if (!spk) { - PDEBUG(DCNETZ, DEBUG_NOTICE, "No free channel anymore, rejecting call!\n"); + LOGP(DCNETZ, LOGL_NOTICE, "No free channel anymore, rejecting call!\n"); destroy_transaction(trans); cnetz_go_idle(cnetz); break; } if (spk == cnetz) { - PDEBUG(DCNETZ, DEBUG_INFO, "Staying on combined calling + traffic channel %s\n", spk->sender.kanal); + LOGP(DCNETZ, LOGL_INFO, "Staying on combined control + traffic channel %s\n", spk->sender.kanal); } else { - PDEBUG(DCNETZ, DEBUG_INFO, "Assigning phone to traffic channel %s\n", spk->sender.kanal); + LOGP(DCNETZ, LOGL_INFO, "Assigning phone to traffic channel %s\n", spk->sender.kanal); /* sync RX time to current OgK time */ fsk_copy_sync(&spk->fsk_demod, &cnetz->fsk_demod); } /* set channel */ - telegramm.frequenz_nr = atoi(spk->sender.kanal); + telegramm.frequenz_nr = spk->kanal; /* change state to busy */ cnetz_new_state(spk, CNETZ_BUSY); /* schedule switching two slots ahead */ - cnetz_set_sched_dsp_mode(spk, DSP_MODE_SPK_K, 2); + cnetz_set_sched_dsp_mode(spk, DSP_MODE_SPK_K, (cnetz->sched_ts + 2) & 31); /* relink */ unlink_transaction(trans); link_transaction(trans, spk); @@ -1076,12 +1081,13 @@ vak: cnetz_flush_other_transactions(spk, trans); break; case TRANS_ATQ: - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending acknowledgment 'Quittung fuer Ausloesen des FuTelG im OgK-Betrieb' to release request.\n"); + case TRANS_ATQ_IDLE: + LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending acknowledgment 'Quittung fuer Ausloesen des FuTelG im OgK-Betrieb' to release request.\n"); telegramm.opcode = OPCODE_ATQ_R; destroy_transaction(trans); break; case TRANS_VA: - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Vorzeitiges Ausloesen' to queued mobile station\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Vorzeitiges Ausloesen' to queued mobile station\n"); telegramm.opcode = OPCODE_VA_R; destroy_transaction(trans); break; @@ -1092,10 +1098,10 @@ vak: trans_new_state(trans, TRANS_VAK); goto vak; } - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "No free channel, sending incoming call in queue 'Warteschglange kommend'.\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "No free channel, sending incoming call in queue 'Warteschglange kommend'.\n"); telegramm.opcode = OPCODE_WSK_R; trans_new_state(trans, TRANS_MT_QUEUE); - timer_start(&trans->timer, T_VAK); /* Maximum time to hold queue */ + osmo_timer_schedule(&trans->timer, T_VAK); /* Maximum time to hold queue */ call_up_alerting(trans->callref); default: ; /* LR */ @@ -1114,33 +1120,54 @@ const telegramm_t *cnetz_transmit_telegramm_meldeblock(cnetz_t *cnetz) memset(&telegramm, 0, sizeof(telegramm)); telegramm.opcode = OPCODE_MLR_M; telegramm.max_sendeleistung = cnetz_power2bits(cnetz->ms_power); - telegramm.ogk_verkehrsanteil = 0; /* must be 0 or phone might not respond to messages in different slot */ + telegramm.ogk_verkehrsanteil = 0; /* must be 0 or some phone might not respond to messages in different slots */ telegramm.teilnehmergruppensperre = si.teilnehmergruppensperre; telegramm.anzahl_gesperrter_teilnehmergruppen = si.anzahl_gesperrter_teilnehmergruppen; - telegramm.ogk_vorschlag = CNETZ_OGK_KANAL; + if (ogk_list_count) { + /* if we have alternative OGKs, we cycle through the list and indicate their channels */ + telegramm.ogk_vorschlag = ogk_list[ogk_list_index]->kanal; + if (++ogk_list_index == ogk_list_count) + ogk_list_index = 0; + } else + telegramm.ogk_vorschlag = CNETZ_STD_OGK_KANAL; telegramm.fuz_rest_nr = si.fuz_rest; - trans = search_transaction(cnetz, TRANS_VWG | TRANS_MA); +next_candidate: + trans = search_transaction(cnetz, TRANS_VWG | TRANS_WAF | TRANS_MA | TRANS_MFT); if (trans) { switch (trans->state) { + case TRANS_WAF: + /* no response to dial request (try again or drop connection) */ + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "No response after dialing request 'Wahlaufforderung'\n"); + if (trans->try == N) { + trans_new_state(trans, TRANS_WBN); + goto next_candidate; + } + trans->try++; + trans_new_state(trans, TRANS_VWG); + /* FALLTHRU */ case TRANS_VWG: - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending acknowledgment 'Wahlaufforderung' to outging call\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending acknowledgment 'Wahlaufforderung' to outging call\n"); telegramm.opcode = OPCODE_WAF_M; telegramm.futln_nationalitaet = trans->futln_nat; telegramm.futln_heimat_fuvst_nr = trans->futln_fuvst; telegramm.futln_rest_nr = trans->futln_rest; trans_new_state(trans, TRANS_WAF); - timer_start(&trans->timer, 1.0); /* Wait two slot cycles until resending */ break; case TRANS_MA: - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending keepalive request 'Meldeaufruf'\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending keepalive request 'Meldeaufruf'\n"); telegramm.opcode = OPCODE_MA_M; telegramm.futln_nationalitaet = trans->futln_nat; telegramm.futln_heimat_fuvst_nr = trans->futln_fuvst; telegramm.futln_rest_nr = trans->futln_rest; trans_new_state(trans, TRANS_MFT); - timer_start(&trans->timer, 1.0); /* Wait two slot cycles until timeout */ break; + case TRANS_MFT: + /* no response to availability check */ + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "No response after keepalive order 'Meldeaufruf'\n"); + trans->page_failed = 1; + destroy_transaction(trans); + goto next_candidate; default: ; /* MLR */ } @@ -1162,20 +1189,22 @@ void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, telegramm_t *telegramm, int blo break; rufnummer = telegramm2rufnummer(telegramm); if (si.authentifikationsbit && telegramm->chipkarten_futelg_bit) - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received Attachment 'Einbuchen' message from Subscriber '%s' with chip card's ID %d (vendor id %d, hardware version %d, software version %d)\n", rufnummer, telegramm->kartenkennung, telegramm->herstellerkennung, telegramm->hardware_des_futelg, telegramm->software_des_futelg); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Received Attachment 'Einbuchen' message from Subscriber '%s' with chip card's ID %d (vendor id %d, hardware version %d, software version %d)\n", rufnummer, telegramm->kartenkennung, telegramm->herstellerkennung, telegramm->hardware_des_futelg, telegramm->software_des_futelg); else - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received Attachment 'Einbuchen' message from Subscriber '%s' with %s card's security code %d\n", rufnummer, (telegramm->chipkarten_futelg_bit) ? "chip":"magnet", telegramm->sicherungs_code); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Received Attachment 'Einbuchen' message from Subscriber '%s' with %s card's security code %d\n", rufnummer, (telegramm->chipkarten_futelg_bit) ? "chip":"magnet", telegramm->sicherungs_code); if (telegramm->erweitertes_frequenzbandbit) - PDEBUG(DCNETZ, DEBUG_INFO, " -> Phone support extended frequency band\n"); + LOGP(DCNETZ, LOGL_INFO, " -> Phone supports extended frequency band\n"); if (cnetz->state != CNETZ_IDLE) { - PDEBUG(DCNETZ, DEBUG_NOTICE, "Ignoring Attachment from subscriber '%s', because we are busy becoming SpK.\n", rufnummer); + LOGP(DCNETZ, LOGL_NOTICE, "Ignoring Attachment from subscriber '%s', because we are busy becoming SpK.\n", rufnummer); break; } - trans = create_transaction(cnetz, TRANS_EM, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, telegramm->chipkarten_futelg_bit, telegramm->erweitertes_frequenzbandbit); + console_inscription(rufnummer); + trans = create_transaction(cnetz, TRANS_EM, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, telegramm->chipkarten_futelg_bit, telegramm->erweitertes_frequenzbandbit, cnetz->rf_level_db); if (!trans) { - PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n"); + LOGP(DCNETZ, LOGL_ERROR, "Failed to create transaction\n"); break; } + cnetz = trans->cnetz; /* cnetz may change, due to stronger reception on different OgK */ valid_frame = 1; break; case OPCODE_UM_R: @@ -1183,20 +1212,22 @@ void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, telegramm_t *telegramm, int blo break; rufnummer = telegramm2rufnummer(telegramm); if (si.authentifikationsbit && telegramm->chipkarten_futelg_bit) - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received Roaming 'Umbuchen' message from Subscriber '%s' with chip card's ID %d (vendor id %d, hardware version %d, software version %d)\n", rufnummer, telegramm->kartenkennung, telegramm->herstellerkennung, telegramm->hardware_des_futelg, telegramm->software_des_futelg); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Received Roaming 'Umbuchen' message from Subscriber '%s' with chip card's ID %d (vendor id %d, hardware version %d, software version %d)\n", rufnummer, telegramm->kartenkennung, telegramm->herstellerkennung, telegramm->hardware_des_futelg, telegramm->software_des_futelg); else - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received Roaming 'Umbuchen' message from Subscriber '%s' with %s card's security code %d\n", rufnummer, (telegramm->chipkarten_futelg_bit) ? "chip":"magnet", telegramm->sicherungs_code); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Received Roaming 'Umbuchen' message from Subscriber '%s' with %s card's security code %d\n", rufnummer, (telegramm->chipkarten_futelg_bit) ? "chip":"magnet", telegramm->sicherungs_code); if (telegramm->erweitertes_frequenzbandbit) - PDEBUG(DCNETZ, DEBUG_INFO, " -> Phone support extended frequency band\n"); + LOGP(DCNETZ, LOGL_INFO, " -> Phone supports extended frequency band\n"); if (cnetz->state != CNETZ_IDLE) { - PDEBUG(DCNETZ, DEBUG_NOTICE, "Ignoring Roaming from subscriber '%s', because we are busy becoming SpK.\n", rufnummer); + LOGP(DCNETZ, LOGL_NOTICE, "Ignoring Roaming from subscriber '%s', because we are busy becoming SpK.\n", rufnummer); break; } - trans = create_transaction(cnetz, TRANS_UM, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, telegramm->chipkarten_futelg_bit, telegramm->erweitertes_frequenzbandbit); + console_inscription(rufnummer); + trans = create_transaction(cnetz, TRANS_UM, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, telegramm->chipkarten_futelg_bit, telegramm->erweitertes_frequenzbandbit, cnetz->rf_level_db); if (!trans) { - PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n"); + LOGP(DCNETZ, LOGL_ERROR, "Failed to create transaction\n"); break; } + cnetz = trans->cnetz; /* cnetz may change, due to stronger reception on different OgK */ valid_frame = 1; break; case OPCODE_UWG_R: @@ -1204,39 +1235,43 @@ void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, telegramm_t *telegramm, int blo if (!match_fuz(telegramm)) break; rufnummer = telegramm2rufnummer(telegramm); - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received Roaming request 'Umbuchantrag' message from Subscriber '%s' on queue\n", rufnummer); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Received Roaming request 'Umbuchantrag' message from Subscriber '%s' on queue\n", rufnummer); break; case OPCODE_VWG_R: case OPCODE_SRG_R: + case OPCODE_NUG_R: if (!match_fuz(telegramm)) break; rufnummer = telegramm2rufnummer(telegramm); if (opcode == OPCODE_VWG_R) - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received outgoing Call 'Verbindungswunsch gehend' message from Subscriber '%s'\n", rufnummer); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Received outgoing Call 'Verbindungswunsch gehend' message from Subscriber '%s'\n", rufnummer); + else if (opcode == OPCODE_SRG_R) + LOGP_CHAN(DCNETZ, LOGL_INFO, "Received outgoing emergency Call 'Sonderruf gehend' message from Subscriber '%s'\n", rufnummer); else - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received outgoing emergency Call 'Sonderruf gehend' message from Subscriber '%s'\n", rufnummer); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Received outgoing Call 'Verbindungswunsch gehend bei Nachbarschaftsunterstuetzung' message from Subscriber '%s'\n", rufnummer); if (cnetz->state != CNETZ_IDLE) { - PDEBUG(DCNETZ, DEBUG_NOTICE, "Ignoring Call from subscriber '%s', because we are busy becoming SpK.\n", rufnummer); + LOGP(DCNETZ, LOGL_NOTICE, "Ignoring Call from subscriber '%s', because we are busy becoming SpK.\n", rufnummer); break; } - trans = create_transaction(cnetz, TRANS_VWG, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, -1, telegramm->erweitertes_frequenzbandbit); + trans = create_transaction(cnetz, TRANS_VWG, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, -1, telegramm->erweitertes_frequenzbandbit, cnetz->rf_level_db); if (!trans) { - PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n"); + LOGP(DCNETZ, LOGL_ERROR, "Failed to create transaction\n"); break; } + cnetz = trans->cnetz; /* cnetz may change, due to stronger reception on different OgK */ trans->try = 1; valid_frame = 1; break; case OPCODE_WUE_M: trans = search_transaction(cnetz, TRANS_WAF | TRANS_WBP | TRANS_VAG | TRANS_MO_QUEUE); if (!trans) { - PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Received dialing digits 'Wahluebertragung' message without transaction, ignoring!\n"); + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Received dialing digits 'Wahluebertragung' message without transaction (on this OgK), ignoring!\n"); break; } rufnummer = transaction2rufnummer(trans); strncpy(trans->dialing, telegramm->wahlziffern, sizeof(trans->dialing) - 1); - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received dialing digits 'Wahluebertragung' message from Subscriber '%s' to Number '%s'\n", rufnummer, trans->dialing); - timer_stop(&trans->timer); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Received dialing digits 'Wahluebertragung' message from Subscriber '%s' to Number '%s'\n", rufnummer, trans->dialing); + osmo_timer_del(&trans->timer); trans_new_state(trans, TRANS_WBP); trans->try = 1; /* try */ valid_frame = 1; @@ -1245,18 +1280,31 @@ void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, telegramm_t *telegramm, int blo if (!match_fuz(telegramm)) break; rufnummer = telegramm2rufnummer(telegramm); - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received release 'Ausloesen des FuTelG im OgK-Betrieb bei WS' message from Subscriber '%s'\n", rufnummer); - trans = search_transaction_number(cnetz, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Received release 'Ausloesen des FuTelG im OgK-Betrieb bei WS' message from Subscriber '%s'\n", rufnummer); + trans = search_transaction_number_global(telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr); if (!trans) { + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "There is no transaction, so we assume that the phone did not receive previous release.\n"); /* create transaction, in case the phone repeats the release after we have acked it */ - trans = create_transaction(cnetz, TRANS_ATQ, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, -1, -1); + trans = create_transaction(cnetz, TRANS_ATQ_IDLE, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, -1, -1, cnetz->rf_level_db); if (!trans) { - PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n"); + LOGP(DCNETZ, LOGL_ERROR, "Failed to create transaction\n"); break; } + cnetz = trans->cnetz; /* cnetz may change, due to stronger reception on different OgK */ } else { - timer_stop(&trans->timer); - trans_new_state(trans, TRANS_ATQ); + if (cnetz == trans->cnetz) { + osmo_timer_del(&trans->timer); + trans_new_state(trans, TRANS_ATQ); + } else + if (trans->state == TRANS_ATQ_IDLE) { + trans = create_transaction(cnetz, TRANS_ATQ_IDLE, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, -1, -1, cnetz->rf_level_db); + if (!trans) { + LOGP(DCNETZ, LOGL_ERROR, "Failed to create transaction\n"); + break; + } + cnetz = trans->cnetz; /* cnetz may change, due to stronger reception on different OgK */ + } else + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Received release 'Ausloesen des FuTelG im OgK-Betrieb bei WS' message without transaction (on this OgK), ignoring!\n"); } valid_frame = 1; break; @@ -1265,16 +1313,16 @@ void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, telegramm_t *telegramm, int blo break; trans = search_transaction_number(cnetz, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr); if (!trans) { - PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Received acknowledge 'Meldung Funktelefonteilnehmer' message without transaction, ignoring!\n"); + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Received acknowledge 'Meldung Funktelefonteilnehmer' message without transaction (on this OgK), ignoring!\n"); break; } rufnummer = transaction2rufnummer(trans); - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received acknowledge 'Meldung Funktelefonteilnehmer' message from Subscriber '%s'\n", rufnummer); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Received acknowledge 'Meldung Funktelefonteilnehmer' message from Subscriber '%s'\n", rufnummer); destroy_transaction(trans); valid_frame = 1; break; default: - PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Received unexpected Telegramm (opcode %d = %s)\n", opcode, telegramm_name(opcode)); + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Received unexpected Telegramm (opcode %d = %s)\n", opcode, telegramm_name(opcode)); } if (cnetz->sender.loopback) { @@ -1295,11 +1343,14 @@ const telegramm_t *cnetz_transmit_telegramm_spk_k(cnetz_t *cnetz) { static telegramm_t telegramm; transaction_t *trans = cnetz->trans_list; + int ogk_kanal; cnetz_t *ogk; + int rc; - memset(&telegramm, 0, sizeof(telegramm)); if (!trans) - return &telegramm; + return NULL; + + memset(&telegramm, 0, sizeof(telegramm)); telegramm.max_sendeleistung = cnetz_power2bits(cnetz->ms_power); telegramm.sendeleistungsanpassung = (cnetz->ms_power < 8) ? 1 : 0; @@ -1310,104 +1361,96 @@ const telegramm_t *cnetz_transmit_telegramm_spk_k(cnetz_t *cnetz) telegramm.futln_nationalitaet = trans->futln_nat; telegramm.futln_heimat_fuvst_nr = trans->futln_fuvst; telegramm.futln_rest_nr = trans->futln_rest; - telegramm.frequenz_nr = atoi(cnetz->sender.kanal); + telegramm.frequenz_nr = cnetz->kanal; telegramm.bedingte_genauigkeit_der_fufst = si.genauigkeit; telegramm.zufallszahl = cnetz->challenge; + telegramm.bahn_bs = si.bahn_bs; switch (trans->state) { case TRANS_BQ: - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Belegungsquittung' on traffic channel\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Belegungsquittung' on traffic channel\n"); telegramm.opcode = OPCODE_BQ_K; - if (++trans->repeat >= 8 && !timer_running(&trans->timer)) { + if (++trans->repeat >= 8 && !osmo_timer_pending(&trans->timer)) { if (cnetz->challenge_valid) { if (si.authentifikationsbit == 0) { - PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Cannot authenticate, because base station does not support it. (Authentication disabled in sysinfo.)\n"); + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Cannot authenticate, because base station does not support it. (Authentication disabled in sysinfo.)\n"); goto no_auth; } if (trans->futelg_bit == 0) { - PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Cannot authenticate, because mobile station does not support it. (Mobile station has magnetic card.)\n"); + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Cannot authenticate, because mobile station does not support it. (Mobile station has magnetic card.)\n"); goto no_auth; } - PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Perform authentication with subscriber's card, use challenge: 0x%016" PRIx64 "\n", telegramm.zufallszahl); + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Perform authentication with subscriber's card, use challenge: 0x%016" PRIx64 "\n", telegramm.zufallszahl); trans_new_state(trans, TRANS_ZFZ); - timer_start(&trans->timer, 0.0375 * F_ZFZ); /* F_ZFZ frames */ + osmo_timer_schedule(&trans->timer, FLOAT_TO_TIMEOUT(0.0375 * F_ZFZ)); /* F_ZFZ frames */ } else { no_auth: trans_new_state(trans, TRANS_VHQ_K); - timer_start(&trans->timer, 0.0375 * F_VHQK); /* F_VHQK frames */ + osmo_timer_schedule(&trans->timer, FLOAT_TO_TIMEOUT(0.0375 * F_VHQK)); /* F_VHQK frames */ } trans->repeat = 0; } break; case TRANS_ZFZ: - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Zufallszahl' on traffic channel (0x%016" PRIx64 ").\n", telegramm.zufallszahl); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Zufallszahl' on traffic channel (0x%016" PRIx64 ").\n", telegramm.zufallszahl); telegramm.opcode = OPCODE_ZFZ_K; break; case TRANS_AP: - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Quittung Verbindung halten' on traffic channel\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Quittung Verbindung halten' on traffic channel\n"); telegramm.opcode = OPCODE_VHQ_K; break; case TRANS_VHQ_K: if (!cnetz->sender.loopback) - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Quittung Verbindung halten' on traffic channel\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Quittung Verbindung halten' on traffic channel\n"); telegramm.opcode = OPCODE_VHQ_K; /* continue until next sub frame, so we send DS from first block of next sub frame. */ - if (!cnetz->sender.loopback && (cnetz->sched_ts & 7) == 7 && cnetz->sched_r_m && !timer_running(&trans->timer)) { + if (!cnetz->sender.loopback && (cnetz->sched_ts & 7) == 7 && cnetz->sched_r_m && !osmo_timer_pending(&trans->timer)) { /* next sub frame */ if (trans->mo_call) { - int rc; - trans->callref = ++new_callref; - rc = call_up_setup(trans->callref, transaction2rufnummer(trans), trans->dialing); - if (rc < 0) { - PDEBUG(DCNETZ, DEBUG_NOTICE, "Call rejected (cause %d), releasing.\n", -rc); - trans->callref = 0; - cnetz_release(trans, cnetz_cause_isdn2cnetz(-rc)); - goto call_failed; - } + trans->callref = call_up_setup(transaction2rufnummer(trans), trans->dialing, OSMO_CC_NETWORK_CNETZ_NONE, ""); trans_new_state(trans, TRANS_DS); trans->repeat = 0; - timer_start(&trans->timer, 0.0375 * F_DS); /* F_DS frames */ + osmo_timer_schedule(&trans->timer, FLOAT_TO_TIMEOUT(0.0375 * F_DS)); /* F_DS frames */ } if (trans->mt_call) { trans_new_state(trans, TRANS_RTA); - timer_start(&trans->timer, 0.0375 * F_RTA); /* F_RTA frames */ + osmo_timer_schedule(&trans->timer, FLOAT_TO_TIMEOUT(0.0375 * F_RTA)); /* F_RTA frames */ trans->repeat = 0; call_up_alerting(trans->callref); } } break; case TRANS_DS: - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Durchschalten' on traffic channel\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Durchschalten' on traffic channel\n"); telegramm.opcode = OPCODE_DSB_K; /* send exactly a sub frame (8 time slots) */ - if ((cnetz->sched_ts & 7) == 7 && cnetz->sched_r_m && !timer_running(&trans->timer)) { + if ((cnetz->sched_ts & 7) == 7 && cnetz->sched_r_m && !osmo_timer_pending(&trans->timer)) { /* next sub frame */ trans_new_state(trans, TRANS_VHQ_V); trans->repeat = 0; - cnetz_set_sched_dsp_mode(cnetz, DSP_MODE_SPK_V, 1); + cnetz_set_sched_dsp_mode(cnetz, DSP_MODE_SPK_V, (cnetz->sched_ts + 1) & 31); #ifndef DEBUG_SPK - timer_start(&trans->timer, 0.075 + 0.6 * F_VHQ); /* one slot + F_VHQ frames */ + osmo_timer_schedule(&trans->timer, FLOAT_TO_TIMEOUT(0.075 + 0.6 * F_VHQ)); /* one slot + F_VHQ frames */ #endif } break; case TRANS_RTA: - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Rufton anschalten' on traffic channel\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Rufton anschalten' on traffic channel\n"); telegramm.opcode = OPCODE_RTA_K; break; case TRANS_AHQ: - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Abhebe Quittung' on traffic channel\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Abhebe Quittung' on traffic channel\n"); telegramm.opcode = OPCODE_AHQ_K; if ((cnetz->sched_ts & 7) == 7 && cnetz->sched_r_m) { /* next sub frame */ trans_new_state(trans, TRANS_VHQ_V); trans->repeat = 0; - cnetz_set_sched_dsp_mode(cnetz, DSP_MODE_SPK_V, 1); - timer_start(&trans->timer, 0.075 + 0.6 * F_VHQ); /* one slot + F_VHQ frames */ + cnetz_set_sched_dsp_mode(cnetz, DSP_MODE_SPK_V, (cnetz->sched_ts + 1) & 31); + osmo_timer_schedule(&trans->timer, FLOAT_TO_TIMEOUT(0.075 + 0.6 * F_VHQ)); /* one slot + F_VHQ frames */ } break; case TRANS_AF: -call_failed: - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Ausloesen durch FuFSt' on traffic channel\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Ausloesen durch FuFSt' on traffic channel\n"); telegramm.opcode = OPCODE_AF_K; if (++trans->repeat < N_AFKT) break; @@ -1418,7 +1461,7 @@ call_failed: break; } if (trans->try == N) { - PDEBUG(DCNETZ, DEBUG_INFO, "Maximum retries, removing transaction\n"); + LOGP(DCNETZ, LOGL_INFO, "Maximum retries, removing transaction\n"); /* no response to incomming call */ trans->page_failed = 1; cnetz_release(trans, CNETZ_CAUSE_FUNKTECHNISCH); @@ -1434,9 +1477,15 @@ call_failed: /* idle channel */ cnetz_go_idle(cnetz); /* alloc ogk again */ - ogk = search_ogk(); + rc = find_db(trans->futln_nat, trans->futln_fuvst, trans->futln_rest, &ogk_kanal, NULL, NULL); + if (rc < 0) { + LOGP(DCNETZ, LOGL_NOTICE, "Cannot find subscriber in database anymore, releasing!\n"); + goto no_ogk; + } + ogk = search_ogk(ogk_kanal); if (!ogk) { - PDEBUG(DCNETZ, DEBUG_NOTICE, "Cannot retry, because currently no OgK available (busy)\n"); + LOGP(DCNETZ, LOGL_NOTICE, "Cannot retry, because currently no OgK available (busy)\n"); +no_ogk: cnetz_release(trans, CNETZ_CAUSE_FUNKTECHNISCH); if (trans->callref) call_up_release(trans->callref, CAUSE_NOCHANNEL); @@ -1444,7 +1493,7 @@ call_failed: destroy_transaction(trans); break; } - PDEBUG(DCNETZ, DEBUG_INFO, "Retry to assign channel.\n"); + LOGP(DCNETZ, LOGL_INFO, "Retry to assign channel.\n"); /* attach call to OgK */ link_transaction(trans, ogk); /* change state */ @@ -1455,7 +1504,7 @@ call_failed: trans->try++; break; case TRANS_AT: - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Auslosen durch FuFst' on traffic channel\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Auslosen durch FuFst' on traffic channel\n"); telegramm.opcode = OPCODE_AF_K; if (++trans->repeat == 1) { destroy_transaction(trans); @@ -1485,11 +1534,11 @@ void cnetz_receive_telegramm_spk_k(cnetz_t *cnetz, telegramm_t *telegramm) if (!match_futln(telegramm, trans->futln_nat, trans->futln_fuvst, trans->futln_rest)) { break; } - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received allocation 'Belegung' message.\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Received allocation 'Belegung' message.\n"); valid_frame = 1; if (trans->state != TRANS_BQ) break; - timer_stop(&trans->timer); + osmo_timer_del(&trans->timer); trans->try = 0; break; case OPCODE_DSQ_K: @@ -1499,35 +1548,35 @@ void cnetz_receive_telegramm_spk_k(cnetz_t *cnetz, telegramm_t *telegramm) if (!match_futln(telegramm, trans->futln_nat, trans->futln_fuvst, trans->futln_rest)) { break; } - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received assignment confirm 'Durchschaltung Quittung' message.\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Received assignment confirm 'Durchschaltung Quittung' message.\n"); valid_frame = 1; if (trans->state != TRANS_DS) break; cnetz->scrambler = telegramm->betriebs_art; cnetz->scrambler_switch = 0; - timer_stop(&trans->timer); + osmo_timer_del(&trans->timer); break; case OPCODE_ZFZQ_K: - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received random number acknowledge 'Zufallszahlquittung' message.\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Received random number acknowledge 'Zufallszahlquittung' message.\n"); valid_frame = 1; if (trans->state != TRANS_ZFZ) break; if (cnetz->challenge != telegramm->zufallszahl) { - PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Received random number acknowledge (0x%016" PRIx64 ") does not match the transmitted one (0x%016" PRIx64 "), ignoring!\n", telegramm->zufallszahl, cnetz->challenge); + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Received random number acknowledge (0x%016" PRIx64 ") does not match the transmitted one (0x%016" PRIx64 "), ignoring!\n", telegramm->zufallszahl, cnetz->challenge); break; } - timer_stop(&trans->timer); + osmo_timer_del(&trans->timer); trans_new_state(trans, TRANS_AP); - timer_start(&trans->timer, T_AP); /* 750 milliseconds */ + osmo_timer_schedule(&trans->timer, T_AP); /* 750 milliseconds */ break; case OPCODE_AP_K: - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received challenge response 'Autorisierungsparameter' message (0x%016" PRIx64 ").\n", telegramm->authorisierungsparameter); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Received challenge response 'Autorisierungsparameter' message (0x%016" PRIx64 ").\n", telegramm->authorisierungsparameter); valid_frame = 1; if (trans->state != TRANS_AP) break; /* if authentication response from card does not match */ if (cnetz->response_valid && telegramm->authorisierungsparameter != cnetz->response) { - PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Received challenge response (0x%016" PRIx64 ") does not match the expected one (0x%016" PRIx64 "), releasing!\n", telegramm->authorisierungsparameter, cnetz->response); + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Received challenge response (0x%016" PRIx64 ") does not match the expected one (0x%016" PRIx64 "), releasing!\n", telegramm->authorisierungsparameter, cnetz->response); if (trans->callref) { call_up_release(trans->callref, CAUSE_TEMPFAIL); /* jolly guesses that */ trans->callref = 0; @@ -1535,10 +1584,10 @@ void cnetz_receive_telegramm_spk_k(cnetz_t *cnetz, telegramm_t *telegramm) cnetz_release(trans, CNETZ_CAUSE_GASSENBESETZT); /* when authentication is not valid */ break; } - PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Completed authentication with subscriber's card, challenge response: 0x%016" PRIx64 "\n", telegramm->authorisierungsparameter); - timer_stop(&trans->timer); + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Completed authentication with subscriber's card, challenge response: 0x%016" PRIx64 "\n", telegramm->authorisierungsparameter); + osmo_timer_del(&trans->timer); trans_new_state(trans, TRANS_VHQ_K); - timer_start(&trans->timer, 0.0375 * F_VHQK); /* F_VHQK frames */ + osmo_timer_schedule(&trans->timer, FLOAT_TO_TIMEOUT(0.0375 * F_VHQK)); /* F_VHQK frames */ break; case OPCODE_VH_K: if (!match_fuz(telegramm)) { @@ -1547,11 +1596,11 @@ void cnetz_receive_telegramm_spk_k(cnetz_t *cnetz, telegramm_t *telegramm) if (!match_futln(telegramm, trans->futln_nat, trans->futln_fuvst, trans->futln_rest)) { break; } - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received connection hold 'Verbindung halten' message.\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Received connection hold 'Verbindung halten' message.\n"); valid_frame = 1; if (trans->state != TRANS_VHQ_K) break; - timer_stop(&trans->timer); + osmo_timer_del(&trans->timer); break; case OPCODE_RTAQ_K: if (!match_fuz(telegramm)) { @@ -1561,10 +1610,10 @@ void cnetz_receive_telegramm_spk_k(cnetz_t *cnetz, telegramm_t *telegramm) break; } valid_frame = 1; - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received ringback 'Rufton anschalten Quittung' message.\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Received ringback 'Rufton anschalten Quittung' message.\n"); if (trans->state != TRANS_RTA) break; - timer_start(&trans->timer, 0.0375 * F_RTA); /* F_RTA frames */ + osmo_timer_schedule(&trans->timer, FLOAT_TO_TIMEOUT(0.0375 * F_RTA)); /* F_RTA frames */ break; case OPCODE_AH_K: if (!match_fuz(telegramm)) { @@ -1573,7 +1622,7 @@ void cnetz_receive_telegramm_spk_k(cnetz_t *cnetz, telegramm_t *telegramm) if (!match_futln(telegramm, trans->futln_nat, trans->futln_fuvst, trans->futln_rest)) { break; } - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received answer frame 'Abheben' message.\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Received answer frame 'Abheben' message.\n"); valid_frame = 1; /* if already received this frame, or if we are already on VHQ or if we are releasing */ if (trans->state == TRANS_AHQ || trans->state == TRANS_VHQ_K || trans->state == TRANS_VHQ_V || trans->state == TRANS_AF) @@ -1582,7 +1631,7 @@ void cnetz_receive_telegramm_spk_k(cnetz_t *cnetz, telegramm_t *telegramm) cnetz->scrambler_switch = 0; trans_new_state(trans, TRANS_AHQ); trans->repeat = 0; - timer_stop(&trans->timer); + osmo_timer_del(&trans->timer); call_up_answer(trans->callref, transaction2rufnummer(trans)); break; case OPCODE_AT_K: @@ -1592,21 +1641,21 @@ void cnetz_receive_telegramm_spk_k(cnetz_t *cnetz, telegramm_t *telegramm) if (!match_futln(telegramm, trans->futln_nat, trans->futln_fuvst, trans->futln_rest)) { break; } - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received release frame 'Ausloesen durch FuTln' message.\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Received release frame 'Ausloesen durch FuTln' message.\n"); valid_frame = 1; /* if already received this frame, if we are releasing */ if (trans->state == TRANS_AT || trans->state == TRANS_AF) break; trans_new_state(trans, TRANS_AT); trans->repeat = 0; - timer_stop(&trans->timer); + osmo_timer_del(&trans->timer); if (trans->callref) { call_up_release(trans->callref, CAUSE_NORMAL); trans->callref = 0; } break; default: - PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Received unexpected Telegramm (opcode %d = %s)\n", opcode, telegramm_name(opcode)); + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Received unexpected Telegramm (opcode %d = %s)\n", opcode, telegramm_name(opcode)); } if (valid_frame) @@ -1620,15 +1669,16 @@ const telegramm_t *cnetz_transmit_telegramm_spk_v(cnetz_t *cnetz) transaction_t *trans = cnetz->trans_list; int meter = 0; - memset(&telegramm, 0, sizeof(telegramm)); if (!trans) - return &telegramm; + return NULL; + + memset(&telegramm, 0, sizeof(telegramm)); - if (cnetz->metering) { - double now = get_time(); - if (!trans->call_start) - trans->call_start = now; - meter = (now - trans->call_start) / (double)cnetz->metering + 1; + if (trans->metering_time) { + /* get end time. if not set, use current time. (still running) */ + double end = (trans->meter_end) ? : get_time(); + /* add one unit, because when metering is started, the first unit is counted. */ + meter = (end - trans->meter_start) / (double)trans->metering_time + 1.0; } telegramm.max_sendeleistung = cnetz_power2bits(cnetz->ms_power); @@ -1641,7 +1691,7 @@ const telegramm_t *cnetz_transmit_telegramm_spk_v(cnetz_t *cnetz) telegramm.futln_nationalitaet = trans->futln_nat; telegramm.futln_heimat_fuvst_nr = trans->futln_fuvst; telegramm.futln_rest_nr = trans->futln_rest; - telegramm.frequenz_nr = atoi(cnetz->sender.kanal); + telegramm.frequenz_nr = cnetz->kanal; telegramm.entfernung = si.entfernung; telegramm.bedingte_genauigkeit_der_fufst = si.genauigkeit; telegramm.gueltigkeit_des_gebuehrenstandes = 0; @@ -1650,15 +1700,15 @@ const telegramm_t *cnetz_transmit_telegramm_spk_v(cnetz_t *cnetz) switch (trans->state) { case TRANS_VHQ_V: if ((cnetz->sched_ts & 8) == 0) { /* sub frame 1 and 3 */ - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Quittung Verbindung halten 1' on traffic channel\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Quittung Verbindung halten 1' on traffic channel\n"); telegramm.opcode = OPCODE_VHQ1_V; } else { /* sub frame 2 and 4 */ - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Quittung Verbindung halten 2' on traffic channel\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Quittung Verbindung halten 2' on traffic channel\n"); telegramm.opcode = OPCODE_VHQ2_V; } break; case TRANS_AF: - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Ausloesen durch FuFSt' on traffic channel\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending 'Ausloesen durch FuFSt' on traffic channel\n"); telegramm.opcode = OPCODE_AF_V; if (++trans->repeat == N_AFV) { destroy_transaction(trans); @@ -1666,7 +1716,7 @@ const telegramm_t *cnetz_transmit_telegramm_spk_v(cnetz_t *cnetz) } break; case TRANS_AT: - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending acknowledge to 'Ausloesen durch FuTln' on traffic channel\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Sending acknowledge to 'Ausloesen durch FuTln' on traffic channel\n"); telegramm.opcode = OPCODE_AF_V; if (++trans->repeat == 1) { destroy_transaction(trans); @@ -1700,16 +1750,16 @@ void cnetz_receive_telegramm_spk_v(cnetz_t *cnetz, telegramm_t *telegramm) } if (trans->state != TRANS_VHQ_V) break; - timer_start(&trans->timer, 0.6 * F_VHQ); /* F_VHQ frames */ + osmo_timer_schedule(&trans->timer, FLOAT_TO_TIMEOUT(0.6 * F_VHQ)); /* F_VHQ frames */ switch (opcode) { case OPCODE_VH_V: - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received supervisory frame 'Verbindung halten' message%s.\n", (telegramm->test_telefonteilnehmer_geraet) ? ", phone is a test-phone" : ""); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Received supervisory frame 'Verbindung halten' message%s.\n", (telegramm->test_telefonteilnehmer_geraet) ? ", phone is a test-phone" : ""); break; case OPCODE_USAI_V: - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received internal handover request frame 'Umschaltantrag intern' message%s.\n", (telegramm->test_telefonteilnehmer_geraet) ? ", phone is a test-phone" : ""); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Received internal handover request frame 'Umschaltantrag intern' message%s.\n", (telegramm->test_telefonteilnehmer_geraet) ? ", phone is a test-phone" : ""); break; case OPCODE_USAE_V: - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received external handover request frame 'Umschaltantrag extern' message%s.\n", (telegramm->test_telefonteilnehmer_geraet) ? ", phone is a test-phone" : ""); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Received external handover request frame 'Umschaltantrag extern' message%s.\n", (telegramm->test_telefonteilnehmer_geraet) ? ", phone is a test-phone" : ""); break; } valid_frame = 1; @@ -1730,21 +1780,21 @@ void cnetz_receive_telegramm_spk_v(cnetz_t *cnetz, telegramm_t *telegramm) if (!match_futln(telegramm, trans->futln_nat, trans->futln_fuvst, trans->futln_rest)) { break; } - PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received release frame 'Ausloesen durch FuTln' message.\n"); + LOGP_CHAN(DCNETZ, LOGL_INFO, "Received release frame 'Ausloesen durch FuTln' message.\n"); valid_frame = 1; /* if already received this frame, if we are releasing */ if (trans->state == TRANS_AT || trans->state == TRANS_AF) break; trans_new_state(trans, TRANS_AT); trans->repeat = 0; - timer_stop(&trans->timer); + osmo_timer_del(&trans->timer); if (trans->callref) { call_up_release(trans->callref, CAUSE_NORMAL); trans->callref = 0; } break; default: - PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Received unexpected Telegramm (opcode %d = %s)\n", opcode, telegramm_name(opcode)); + LOGP_CHAN(DCNETZ, LOGL_NOTICE, "Received unexpected Telegramm (opcode %d = %s)\n", opcode, telegramm_name(opcode)); } if (valid_frame) diff --git a/src/cnetz/cnetz.h b/src/cnetz/cnetz.h index 88e621f..b9bbafe 100644 --- a/src/cnetz/cnetz.h +++ b/src/cnetz/cnetz.h @@ -1,16 +1,16 @@ #include "../libcompandor/compandor.h" -#include "../libtimer/timer.h" +#include <osmocom/core/timer.h> #include "../libmobile/sender.h" #include "../libscrambler/scrambler.h" typedef struct cnetz cnetz_t; #include "fsk_demod.h" #include "transaction.h" -#define CNETZ_OGK_KANAL 131 +#define CNETZ_STD_OGK_KANAL 131 /* dsp modes of transmission */ enum dsp_mode { - DSP_SCHED_NONE = 0, /* use for sheduling: nothing to shedule */ + DSP_SCHED_NONE = 0, /* use for scheduling: nothing to schedule */ DSP_MODE_OFF, /* send nothing on unused SpK */ DSP_MODE_OGK, /* send "Telegramm" on OgK */ DSP_MODE_SPK_K, /* send concentrated "Telegramm" SpK */ @@ -40,9 +40,9 @@ enum cnetz_state { #define N_AFKT 6 /* number of release frames to send during concentrated signaling */ #define N_AFV 4 /* number of release frames to send during distributed signaling */ #define N 3 /* now many times we repeat a message on OgK */ -#define T_VAG2 180 /* time on outgoing queue */ -#define T_VAK 60 /* time on incoming queue */ -#define T_AP 750 /* Time to wait for SIM card's authentication reply */ +#define T_VAG2 180,0 /* time on outgoing queue */ +#define T_VAK 60,0 /* time on incoming queue */ +#define T_AP 0,750000 /* Time to wait for SIM card's authentication reply */ /* clear causes */ #define CNETZ_CAUSE_GASSENBESETZT 0 /* network congested */ @@ -66,6 +66,7 @@ struct clock_speed { /* instance of cnetz sender */ struct cnetz { sender_t sender; + int kanal; /* channel number */ enum cnetz_chan_type chan_type; /* channel type */ scrambler_t scrambler_tx; /* mirror what we transmit to MS */ scrambler_t scrambler_rx; /* mirror what we receive from MS */ @@ -81,7 +82,7 @@ struct cnetz { int response_valid; /* expect authorizaton response */ uint64_t response; /* authorization response */ int warteschlange; /* use queue */ - int metering; /* use metering pulses in seconds 0 = off */ + int metering; /* send metering units in seconds 0 = off */ /* all cnetz states */ enum cnetz_state state; /* main state of sender */ @@ -94,11 +95,14 @@ struct cnetz { int sched_ts; /* current time slot */ int sched_last_ts; /* last timeslot we transmitted, to sync time of the receiver */ 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 */ + enum dsp_mode sched_dsp_mode; /* what mode shall be switched to */ + int sched_dsp_mode_ts; /* time slot when to switch mode (-1 = don't switch) */ + int sched_lr_debugged; /* indicator to prevent debugging all idle frames */ + int sched_mlr_debugged; /* indicator to prevent debugging all idle frames */ /* dsp states */ enum dsp_mode dsp_mode; /* current mode: audio, "Telegramm", .... */ + double rf_level_db; /* current RF level or nan, if not applicable */ iir_filter_t lp; /* low pass filter to eliminate noise above 5280 Hz */ fsk_fm_demod_t fsk_demod; /* demod process */ double fsk_deviation; /* deviation of FSK signal on sound card */ @@ -123,8 +127,8 @@ struct cnetz { double frame_last_phase; /* master's bit phase of last frame sync */ /* audio offset removal */ - double offset_factor; /* filer alpha of high-pass filter */ - double offset_y_last; /* last stored sample */ + double offset_last; /* last sample value of last frame */ + int offset_range; /* range of samples to ramp the offset */ /* measurements */ int measure_speed; /* measure clock speed */ @@ -133,17 +137,18 @@ struct cnetz { transaction_t *trans_list; /* list of transactions */ }; +const char *cnetz_number_valid(const char *number); double cnetz_kanal2freq(int kanal, int unterband); void cnetz_channel_list(void); 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(const char *kanal, enum cnetz_chan_type chan_type, const char *audiodev, int use_sdr, enum demod_type demod, int samplerate, double rx_gain, int challenge_valid, uint64_t challenge, int response_valid, uint64_t response, int warteschlange, int metering, double speech_deviation, 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, const char *read_tx_wave, int loopback); +int cnetz_create(const char *kanal, enum cnetz_chan_type chan_type, const char *device, int use_sdr, enum demod_type demod, int samplerate, double rx_gain, double tx_gain, int challenge_valid, uint64_t challenge, int response_valid, uint64_t response, int warteschlange, int metering, double speech_deviation, 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, const char *read_tx_wave, int loopback); void cnetz_destroy(sender_t *sender); void cnetz_go_idle(cnetz_t *cnetz); 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); +int cnetz_meldeaufruf(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int ogk_kanal); const struct telegramm *cnetz_transmit_telegramm_rufblock(cnetz_t *cnetz); const struct telegramm *cnetz_transmit_telegramm_meldeblock(cnetz_t *cnetz); void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, struct telegramm *telegramm, int block); diff --git a/src/cnetz/database.c b/src/cnetz/database.c index c6d3765..4bdfb2c 100644 --- a/src/cnetz/database.c +++ b/src/cnetz/database.c @@ -22,32 +22,47 @@ #include <stdlib.h> #include <string.h> #include "../libsample/sample.h" -#include "../libdebug/debug.h" +#include "../liblogging/logging.h" +#include "../libmobile/get_time.h" #include "cnetz.h" #include "database.h" +#include "sysinfo.h" /* the network specs say: check every 1 - 6.5 minutes for availability * remove from database after 3 subsequent failures * the phone will register 20 minutes after no call / no paging from network. */ -#define MELDE_INTERVAL 120.0 -#define MELDE_WIEDERHOLUNG 60.0 -#define MELDE_MAXIMAL 3 +#define MELDE_WIEDERHOLUNG 60.0 /* when busy */ typedef struct cnetz_database { struct cnetz_database *next; + int ogk_kanal; /* available on which channel */ uint8_t futln_nat; /* who ... */ uint8_t futln_fuvst; uint16_t futln_rest; int futelg_bit; /* chip card inside */ int extended; /* mobile supports extended frequencies */ - struct timer timer; /* timer for next availability check */ + int eingebucht; /* set if still available */ + double last_seen; + int busy; /* set if currently in a call */ + struct osmo_timer_list timer; /* timer for next availability check */ int retry; /* counts number of retries */ } cnetz_db_t; cnetz_db_t *cnetz_db_head; +static const char *print_meldeaufrufe(int versuche) +{ + static char text[32]; + + if (versuche <= 0) + return "infinite"; + + sprintf(text, "%d", versuche); + return text; +} + /* destroy transaction */ static void remove_db(cnetz_db_t *db) { @@ -58,43 +73,43 @@ static void remove_db(cnetz_db_t *db) while (*dbp && *dbp != db) dbp = &((*dbp)->next); if (!(*dbp)) { - PDEBUG(DDB, DEBUG_ERROR, "Subscriber not in list, please fix!!\n"); + LOGP(DDB, LOGL_ERROR, "Subscriber not in list, please fix!!\n"); abort(); } *dbp = db->next; - PDEBUG(DDB, DEBUG_INFO, "Removing subscriber '%d,%d,%d' from database.\n", db->futln_nat, db->futln_fuvst, db->futln_rest); + LOGP(DDB, LOGL_INFO, "Removing subscriber '%d,%d,%05d' from database.\n", db->futln_nat, db->futln_fuvst, db->futln_rest); - timer_exit(&db->timer); + osmo_timer_del(&db->timer); free(db); } /* Timeout handling */ -static void db_timeout(struct timer *timer) +static void db_timeout(void *data) { - cnetz_db_t *db = (cnetz_db_t *)timer->priv; + cnetz_db_t *db = data; int rc; - PDEBUG(DDB, DEBUG_INFO, "Check, if subscriber '%d,%d,%d' is still available.\n", db->futln_nat, db->futln_fuvst, db->futln_rest); + LOGP(DDB, LOGL_INFO, "Check, if subscriber '%d,%d,%05d' is still available.\n", db->futln_nat, db->futln_fuvst, db->futln_rest); - rc = cnetz_meldeaufruf(db->futln_nat, db->futln_fuvst, db->futln_rest); + rc = cnetz_meldeaufruf(db->futln_nat, db->futln_fuvst, db->futln_rest, db->ogk_kanal); if (rc < 0) { /* OgK is used for speech, but this never happens in a real * network. We just assume that the phone has responded and * assume we had a response. */ - PDEBUG(DDB, DEBUG_INFO, "OgK busy, so we assume a positive response.\n"); - timer_start(&db->timer, MELDE_INTERVAL); /* when to check avaiability again */ + LOGP(DDB, LOGL_INFO, "OgK busy, so we assume a positive response.\n"); + osmo_timer_schedule(&db->timer, si.meldeinterval,0); /* when to check avaiability again */ db->retry = 0; } } /* create/update db entry */ -int update_db(cnetz_t __attribute__((unused)) *cnetz, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int *futelg_bit, int *extended, int busy, int failed) +int update_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int ogk_kanal, int *futelg_bit, int *extended, int busy, int failed) { cnetz_db_t *db, **dbp; - /* search transaction for this subsriber */ + /* search transaction for this subscriber */ db = cnetz_db_head; while (db) { if (db->futln_nat == futln_nat @@ -106,11 +121,12 @@ int update_db(cnetz_t __attribute__((unused)) *cnetz, uint8_t futln_nat, uint8_t if (!db) { db = calloc(1, sizeof(*db)); if (!db) { - PDEBUG(DDB, DEBUG_ERROR, "No memory!\n"); + LOGP(DDB, LOGL_ERROR, "No memory!\n"); return 0; } - timer_init(&db->timer, db_timeout, db); + osmo_timer_setup(&db->timer, db_timeout, db); + db->eingebucht = 1; db->futln_nat = futln_nat; db->futln_fuvst = futln_fuvst; db->futln_rest = futln_rest; @@ -121,30 +137,37 @@ int update_db(cnetz_t __attribute__((unused)) *cnetz, uint8_t futln_nat, uint8_t dbp = &((*dbp)->next); *dbp = db; - PDEBUG(DDB, DEBUG_INFO, "Adding subscriber '%d,%d,%d' to database.\n", db->futln_nat, db->futln_fuvst, db->futln_rest); + LOGP(DDB, LOGL_INFO, "Adding subscriber '%d,%d,%05d' to database.\n", db->futln_nat, db->futln_fuvst, db->futln_rest); } + if (ogk_kanal) + db->ogk_kanal = ogk_kanal; + if (futelg_bit && *futelg_bit >= 0) db->futelg_bit = *futelg_bit; if (extended && *extended >= 0) db->extended = *extended; + db->busy = busy; if (busy) { - PDEBUG(DDB, DEBUG_INFO, "Subscriber '%d,%d,%d' busy now.\n", db->futln_nat, db->futln_fuvst, db->futln_rest); - timer_stop(&db->timer); + LOGP(DDB, LOGL_INFO, "Subscriber '%d,%d,%05d' on OGK channel #%d is busy now.\n", db->futln_nat, db->futln_fuvst, db->futln_rest, db->ogk_kanal); + osmo_timer_del(&db->timer); } else if (!failed) { - PDEBUG(DDB, DEBUG_INFO, "Subscriber '%d,%d,%d' idle now.\n", db->futln_nat, db->futln_fuvst, db->futln_rest); - timer_start(&db->timer, MELDE_INTERVAL); /* when to check avaiability (again) */ + LOGP(DDB, LOGL_INFO, "Subscriber '%d,%d,%05d' on OGK channel #%d is idle now.\n", db->futln_nat, db->futln_fuvst, db->futln_rest, db->ogk_kanal); + osmo_timer_schedule(&db->timer, si.meldeinterval,0); /* when to check avaiability (again) */ db->retry = 0; + db->eingebucht = 1; + db->last_seen = get_time(); } else { db->retry++; - PDEBUG(DDB, DEBUG_NOTICE, "Paging subscriber '%d,%d,%d' failed (try %d of %d).\n", db->futln_nat, db->futln_fuvst, db->futln_rest, db->retry, MELDE_MAXIMAL); - if (db->retry == MELDE_MAXIMAL) { - remove_db(db); + LOGP(DDB, LOGL_NOTICE, "Paging subscriber '%d,%d,%05d' on OGK channel #%d failed (try %d of %s).\n", db->futln_nat, db->futln_fuvst, db->futln_rest, db->ogk_kanal, db->retry, print_meldeaufrufe(si.meldeaufrufe)); + if (si.meldeaufrufe && db->retry == si.meldeaufrufe) { + LOGP(DDB, LOGL_INFO, "Marking subscriber as gone.\n"); + db->eingebucht = 0; return db->extended; } - timer_start(&db->timer, MELDE_WIEDERHOLUNG); /* when to do retry */ + osmo_timer_schedule(&db->timer, (si.meldeinterval < MELDE_WIEDERHOLUNG) ? si.meldeinterval : MELDE_WIEDERHOLUNG,0); /* when to do retry */ } if (futelg_bit) @@ -154,14 +177,17 @@ int update_db(cnetz_t __attribute__((unused)) *cnetz, uint8_t futln_nat, uint8_t return 0; } -int find_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int *futelg_bit, int *extended) +int find_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int *ogk_kanal, int *futelg_bit, int *extended) { cnetz_db_t *db = cnetz_db_head; while (db) { - if (db->futln_nat == futln_nat + if (db->eingebucht + && db->futln_nat == futln_nat && db->futln_fuvst == futln_fuvst && db->futln_rest == futln_rest) { + if (ogk_kanal) + *ogk_kanal = db->ogk_kanal; if (futelg_bit) *futelg_bit = db->futelg_bit; if (extended) @@ -182,15 +208,22 @@ void flush_db(void) void dump_db(void) { cnetz_db_t *db = cnetz_db_head; + double now = get_time(); + int last; + char attached[16]; - PDEBUG(DDB, DEBUG_NOTICE, "Dump of subscriber database:\n"); + LOGP(DDB, LOGL_NOTICE, "Dump of subscriber database:\n"); if (!db) { - PDEBUG(DDB, DEBUG_NOTICE, " - No subscribers attached!\n"); + LOGP(DDB, LOGL_NOTICE, " - No subscribers attached!\n"); return; } + LOGP(DDB, LOGL_NOTICE, "Subscriber\tAttached\tBusy\t\tLast seen\tMeldeaufrufe\n"); + LOGP(DDB, LOGL_NOTICE, "-------------------------------------------------------------------------------\n"); while (db) { - PDEBUG(DDB, DEBUG_NOTICE, " - Subscriber '%d,%d,%d' is attached.\n", db->futln_nat, db->futln_fuvst, db->futln_rest); + last = (db->busy) ? 0 : (uint32_t)(now - db->last_seen); + sprintf(attached, "YES (OGK %d)", db->ogk_kanal); + LOGP(DDB, LOGL_NOTICE, "%d,%d,%05d\t%s\t%s\t\t%02d:%02d:%02d \t%d/%s\n", db->futln_nat, db->futln_fuvst, db->futln_rest, (db->eingebucht) ? attached : "-no-\t", (db->busy) ? "YES" : "-no-", last / 3600, (last / 60) % 60, last % 60, db->retry, print_meldeaufrufe(si.meldeaufrufe)); db = db->next; } } diff --git a/src/cnetz/database.h b/src/cnetz/database.h index a1339a0..7cd1c16 100644 --- a/src/cnetz/database.h +++ b/src/cnetz/database.h @@ -1,6 +1,6 @@ -int update_db(cnetz_t *cnetz, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int *futelg_bit, int *extended, int busy, int failed); -int find_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int *futelg_bit, int *extended); +int update_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int ogk_kanal, int *futelg_bit, int *extended, int busy, int failed); +int find_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int *ogk_kanal, int *futelg_bit, int *extended); void flush_db(void); void dump_db(void); diff --git a/src/cnetz/dsp.c b/src/cnetz/dsp.c index 91f967c..af29c62 100644 --- a/src/cnetz/dsp.c +++ b/src/cnetz/dsp.c @@ -26,8 +26,9 @@ #include <math.h> #include <errno.h> #include "../libsample/sample.h" -#include "../libdebug/debug.h" +#include "../liblogging/logging.h" #include "../libmobile/call.h" +#include "../libmobile/get_time.h" #include "cnetz.h" #include "sysinfo.h" #include "telegramm.h" @@ -46,18 +47,37 @@ #define MAX_DISPLAY 1.4 /* something above speech level, no emphasis */ #define BITRATE 5280.0 /* bits per second */ #define BLOCK_BITS 198 /* duration of one time slot including pause at beginning and end */ -#define CUT_OFF_OFFSET 300.0 /* cut off frequency for offset filter (level correction between subsequent audio chunks) */ #ifdef TEST_SCRAMBLE -jitter_t scrambler_test_jb; +test_echo_t scrambler_test_echo = {}; scrambler_t scrambler_test_scrambler1; scrambler_t scrambler_test_scrambler2; #endif -static sample_t ramp_up[256], ramp_down[256]; +static const char *cnetz_dsp_mode_name(enum dsp_mode mode) +{ + static char invalid[16]; + + switch (mode) { + case DSP_SCHED_NONE: + return "SCHED_NONE"; + case DSP_MODE_OFF: + return "OFF"; + case DSP_MODE_OGK: + return "OGK"; + case DSP_MODE_SPK_K: + return "SPK_K"; + case DSP_MODE_SPK_V: + return "SPK_V"; + } + + sprintf(invalid, "invalid(%d)", mode); + return invalid; +} void dsp_init(void) { + compandor_init(); } static void dsp_init_ramp(cnetz_t *cnetz) @@ -65,17 +85,17 @@ static void dsp_init_ramp(cnetz_t *cnetz) double c; int i; - PDEBUG(DDSP, DEBUG_DEBUG, "Generating smooth ramp table.\n"); + LOGP(DDSP, LOGL_DEBUG, "Generating smooth ramp table.\n"); for (i = 0; i < 256; i++) { - c = cos((double)i / 256.0 * PI); /* use square-root of cosine ramp. tests showed that phones are more - * happy with that. */ + * happy with that. (This is not correct pulse shaping!) */ + c = cos((double)i / 256.0 * PI); if (c < 0) c = -sqrt(-c); else c = sqrt(c); - ramp_down[i] = c * (double)cnetz->fsk_deviation; - ramp_up[i] = -ramp_down[i]; + cnetz->fsk_ramp_down[i] = c * (double)cnetz->fsk_deviation; + cnetz->fsk_ramp_up[i] = -cnetz->fsk_ramp_down[i]; } } @@ -84,9 +104,8 @@ int dsp_init_sender(cnetz_t *cnetz, int measure_speed, double clock_speed[2], en { int rc = 0; double size; - double RC, dt; - PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init FSK for 'Sender'.\n"); + LOGP_CHAN(DDSP, LOGL_DEBUG, "Init FSK for 'Sender'.\n"); /* set modulation parameters */ sender_set_fm(&cnetz->sender, MAX_DEVIATION, MAX_MODULATION, speech_deviation, MAX_DISPLAY); @@ -97,25 +116,25 @@ int dsp_init_sender(cnetz_t *cnetz, int measure_speed, double clock_speed[2], en } if (clock_speed[0] > 1000 || clock_speed[0] < -1000 || clock_speed[1] > 1000 || clock_speed[1] < -1000) { - PDEBUG(DDSP, DEBUG_ERROR, "Clock speed %.1f,%.1f ppm out of range! Plese use range between +-1000 ppm!\n", clock_speed[0], clock_speed[1]); + LOGP_CHAN(DDSP, LOGL_ERROR, "Clock speed %.1f,%.1f ppm out of range! Please use range between +-1000 ppm!\n", clock_speed[0], clock_speed[1]); return -EINVAL; } - PDEBUG(DDSP, DEBUG_INFO, "Using clock speed of %.1f ppm (RX) and %.1f ppm (TX) to correct sound card's clock.\n", clock_speed[0], clock_speed[1]); + LOGP_CHAN(DDSP, LOGL_INFO, "Using clock speed of %.1f ppm (RX) and %.1f ppm (TX) to correct sound card's clock.\n", clock_speed[0], clock_speed[1]); cnetz->fsk_bitduration = (double)cnetz->sender.samplerate / ((double)BITRATE / (1.0 + clock_speed[1] / 1000000.0)); cnetz->fsk_tx_bitstep = 1.0 / cnetz->fsk_bitduration; - PDEBUG(DDSP, DEBUG_DEBUG, "Use %.4f samples for one bit duration @ %d.\n", cnetz->fsk_bitduration, cnetz->sender.samplerate); + LOGP_CHAN(DDSP, LOGL_DEBUG, "Use %.4f samples for one bit duration @ %d.\n", cnetz->fsk_bitduration, cnetz->sender.samplerate); size = cnetz->fsk_bitduration * (double)BLOCK_BITS * 16.0; /* 16 blocks for distributed frames */ cnetz->fsk_tx_buffer_size = size * 1.1; /* more to compensate clock speed */ cnetz->fsk_tx_buffer = calloc(sizeof(sample_t), cnetz->fsk_tx_buffer_size); if (!cnetz->fsk_tx_buffer) { - PDEBUG(DDSP, DEBUG_ERROR, "No memory!\n"); + LOGP_CHAN(DDSP, LOGL_ERROR, "No memory!\n"); rc = -ENOMEM; goto error; } - /* create devation and ramp */ + /* create deviation and ramp */ cnetz->fsk_deviation = FSK_DEVIATION; dsp_init_ramp(cnetz); @@ -125,13 +144,13 @@ int dsp_init_sender(cnetz_t *cnetz, int measure_speed, double clock_speed[2], en /* create speech buffer */ cnetz->dsp_speech_buffer = calloc(sizeof(sample_t), (int)(cnetz->fsk_bitduration * 70.0)); /* more to compensate clock speed. we just need it to fill 62 bits (60 bits, including pause bits). */ if (!cnetz->dsp_speech_buffer) { - PDEBUG(DDSP, DEBUG_ERROR, "No memory!\n"); + LOGP_CHAN(DDSP, LOGL_ERROR, "No memory!\n"); rc = -ENOMEM; goto error; } /* 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 */ + init_samplerate(&cnetz->sender.srstate, 8000.0, (double)cnetz->sender.samplerate / (1.1 / (1.0 + clock_speed[0] / 1000000.0)), 3300.0); /* 66 <-> 60 */ rc = fsk_fm_init(&cnetz->fsk_demod, cnetz, cnetz->sender.samplerate, (double)BITRATE / (1.0 + clock_speed[0] / 1000000.0), demod); if (rc < 0) @@ -141,31 +160,25 @@ int dsp_init_sender(cnetz_t *cnetz, int measure_speed, double clock_speed[2], en scrambler_setup(&cnetz->scrambler_tx, (double)cnetz->sender.samplerate / 1.1); scrambler_setup(&cnetz->scrambler_rx, (double)cnetz->sender.samplerate / 1.1); - /* reinit jitter buffer for 8000 kHz */ - jitter_destroy(&cnetz->sender.dejitter); - rc = jitter_create(&cnetz->sender.dejitter, 8000 / 5); - if (rc < 0) - goto error; - /* init compandor, according to C-Netz specs, attack and recovery time * shall not exceed according to ITU G.162 */ - init_compandor(&cnetz->cstate, 8000, 5.0, 22.5); + setup_compandor(&cnetz->cstate, 8000, 5.0, 22.5); - /* use this filter to compensate level changes between two subsequent audio chunks */ - RC = 1.0 / (CUT_OFF_OFFSET * 2.0 *3.14); - dt = 1.0 / cnetz->sender.samplerate; - cnetz->offset_factor = RC / (RC + dt); + /* use duration of one bit to ramp level of last frame to current frame */ + cnetz->offset_range = ceil(cnetz->fsk_bitduration); #ifdef TEST_SCRAMBLE - rc = jitter_create(&scrambler_test_jb, cnetz->sender.samplerate / 5); + rc = test_echo_alloc(&scrambler_test_echo, cnetz->sender.samplerate / 20); if (rc < 0) { - PDEBUG(DDSP, DEBUG_ERROR, "Failed to init jitter buffer for scrambler test!\n"); + LOGP_CHAN(DDSP, LOGL_ERROR, "Failed to init echo buffer for scrambler test!\n"); exit(0); } scrambler_setup(&scrambler_test_scrambler1, cnetz->sender.samplerate); scrambler_setup(&scrambler_test_scrambler2, cnetz->sender.samplerate); #endif + cnetz->sched_dsp_mode_ts = -1; + return 0; error: @@ -176,7 +189,7 @@ error: void dsp_cleanup_sender(cnetz_t *cnetz) { - PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Cleanup FSK for 'Sender'.\n"); + LOGP_CHAN(DDSP, LOGL_DEBUG, "Cleanup FSK for 'Sender'.\n"); if (cnetz->fsk_tx_buffer) { free(cnetz->fsk_tx_buffer); @@ -206,7 +219,7 @@ void calc_clock_speed(cnetz_t *cnetz, double samples, int tx, int result) ti = get_time(); - /* skip some time to avoid false mesurement due to filling of buffers */ + /* skip some time to avoid false measurement due to filling of buffers */ if (cs->meas_ti == 0.0) { cs->meas_ti = ti + 1.0; return; @@ -244,7 +257,7 @@ void calc_clock_speed(cnetz_t *cnetz, double samples, int tx, int result) speed_ppm_avg[index] += cs->speed_ppm[index][(cs->idx[index] - i - 1) & 0xff]; speed_ppm_avg[index] /= (double)cs->num[index]; } - PDEBUG_CHAN(DDSP, DEBUG_NOTICE, "Clock: RX=%.3f TX=%.3f; Signal: RX=%.3f TX=%.3f ppm\n", speed_ppm_avg[0], speed_ppm_avg[1], speed_ppm_avg[2], speed_ppm_avg[3]); + LOGP_CHAN(DDSP, LOGL_NOTICE, "Clock: RX=%.3f TX=%.3f; Signal: RX=%.3f TX=%.3f ppm\n", speed_ppm_avg[0], speed_ppm_avg[1], speed_ppm_avg[2], speed_ppm_avg[3]); } static int fsk_nothing_encode(cnetz_t *cnetz) @@ -308,14 +321,14 @@ static int fsk_block_encode(cnetz_t *cnetz, const char *bits, int ogk) if (bits[i] == '1') { /* ramp up from 0 */ do { - *spl++ = ramp_up[(uint8_t)phase] / 2 + deviation / 2; + *spl++ = cnetz->fsk_ramp_up[(uint8_t)phase] / 2 + deviation / 2; phase += bitstep; } while (phase < 256.0); phase -= 256.0; } else { /* ramp down from 0 */ do { - *spl++ = ramp_down[(uint8_t)phase] / 2 - deviation / 2; + *spl++ = cnetz->fsk_ramp_down[(uint8_t)phase] / 2 - deviation / 2; phase += bitstep; } while (phase < 256.0); phase -= 256.0; @@ -332,7 +345,7 @@ static int fsk_block_encode(cnetz_t *cnetz, const char *bits, int ogk) } else { /* ramp down */ do { - *spl++ = ramp_down[(uint8_t)phase]; + *spl++ = cnetz->fsk_ramp_down[(uint8_t)phase]; phase += bitstep; } while (phase < 256.0); phase -= 256.0; @@ -342,7 +355,7 @@ static int fsk_block_encode(cnetz_t *cnetz, const char *bits, int ogk) if (bits[i] == '1') { /* ramp up */ do { - *spl++ = ramp_up[(uint8_t)phase]; + *spl++ = cnetz->fsk_ramp_up[(uint8_t)phase]; phase += bitstep; } while (phase < 256.0); phase -= 256.0; @@ -362,14 +375,14 @@ static int fsk_block_encode(cnetz_t *cnetz, const char *bits, int ogk) if (last == '0') { /* ramp up to 0 */ do { - *spl++ = ramp_up[(uint8_t)phase] / 2 - deviation / 2; + *spl++ = cnetz->fsk_ramp_up[(uint8_t)phase] / 2 - deviation / 2; phase += bitstep; } while (phase < 256.0); phase -= 256.0; } else { /* ramp down to 0 */ do { - *spl++ = ramp_down[(uint8_t)phase] / 2 + deviation / 2; + *spl++ = cnetz->fsk_ramp_down[(uint8_t)phase] / 2 + deviation / 2; phase += bitstep; } while (phase < 256.0); phase -= 256.0; @@ -408,7 +421,7 @@ static int fsk_block_encode(cnetz_t *cnetz, const char *bits, int ogk) * the marker is placed in the middle of the 6th bit. * because we have a transition (ramp) in the middle of each bit. * the phone will see the position of the marker as start of the 6th bit. - * the marker marks the pont where the speech is ramped up, so the phone + * the marker marks the point where the speech is ramped up, so the phone * will see the speech completely ramped up after the 6th bit */ static int fsk_distributed_encode(cnetz_t *cnetz, const char *bits) @@ -458,14 +471,14 @@ static int fsk_distributed_encode(cnetz_t *cnetz, const char *bits) if (bits[i * 4 + j] == '1') { /* ramp up from 0 */ do { - *spl++ = ramp_up[(uint8_t)phase] / 2 + deviation / 2; + *spl++ = cnetz->fsk_ramp_up[(uint8_t)phase] / 2 + deviation / 2; phase += bitstep; } while (phase < 256.0); phase -= 256.0; } else { /* ramp down from 0 */ do { - *spl++ = ramp_down[(uint8_t)phase] / 2 - deviation / 2; + *spl++ = cnetz->fsk_ramp_down[(uint8_t)phase] / 2 - deviation / 2; phase += bitstep; } while (phase < 256.0); phase -= 256.0; @@ -482,7 +495,7 @@ static int fsk_distributed_encode(cnetz_t *cnetz, const char *bits) } else { /* ramp down */ do { - *spl++ = ramp_down[(uint8_t)phase]; + *spl++ = cnetz->fsk_ramp_down[(uint8_t)phase]; phase += bitstep; } while (phase < 256.0); phase -= 256.0; @@ -492,7 +505,7 @@ static int fsk_distributed_encode(cnetz_t *cnetz, const char *bits) if (bits[i * 4 + j] == '1') { /* ramp up */ do { - *spl++ = ramp_up[(uint8_t)phase]; + *spl++ = cnetz->fsk_ramp_up[(uint8_t)phase]; phase += bitstep; } while (phase < 256.0); phase -= 256.0; @@ -512,14 +525,14 @@ static int fsk_distributed_encode(cnetz_t *cnetz, const char *bits) if (last == '0') { /* ramp up to 0 */ do { - *spl++ = ramp_up[(uint8_t)phase] / 2 - deviation / 2; + *spl++ = cnetz->fsk_ramp_up[(uint8_t)phase] / 2 - deviation / 2; phase += bitstep; } while (phase < 256.0); phase -= 256.0; } else { /* ramp down to 0 */ do { - *spl++ = ramp_down[(uint8_t)phase] / 2 + deviation / 2; + *spl++ = cnetz->fsk_ramp_down[(uint8_t)phase] / 2 + deviation / 2; phase += bitstep; } while (phase < 256.0); phase -= 256.0; @@ -547,10 +560,12 @@ static int fsk_distributed_encode(cnetz_t *cnetz, const char *bits) /* decode samples and hut for bit changes * use deviation to find greatest slope of the signal (bit change) */ -void sender_receive(sender_t *sender, sample_t *samples, int length, double __attribute__((unused)) rf_level_db) +void sender_receive(sender_t *sender, sample_t *samples, int length, double rf_level_db) { cnetz_t *cnetz = (cnetz_t *) sender; + cnetz->rf_level_db = rf_level_db; + /* measure rx sample speed */ calc_clock_speed(cnetz, length, 0, 0); @@ -558,7 +573,7 @@ void sender_receive(sender_t *sender, sample_t *samples, int length, double __at #ifdef TEST_UNSCRAMBLE scrambler(&scrambler_test_scrambler1, samples, length); #endif - jitter_save(&scrambler_test_jb, samples, length); + test_echo_store(&scrambler_test_echo, samples, length); return; #endif @@ -574,12 +589,15 @@ void sender_receive(sender_t *sender, sample_t *samples, int length, double __at static int shrink_speech(cnetz_t *cnetz, sample_t *speech_buffer) { int speech_length; + int16_t spl[100]; - jitter_load(&cnetz->sender.dejitter, speech_buffer, 100); + jitter_load_samples(&cnetz->sender.dejitter, (uint8_t *)spl, 100, sizeof(*spl), jitter_conceal_s16, NULL); + int16_to_samples_speech(speech_buffer, spl, 100); /* 1. compress dynamics */ compress_audio(&cnetz->cstate, speech_buffer, 100); /* 2. upsample */ - speech_length = samplerate_upsample(&cnetz->sender.srstate, speech_buffer, 100, speech_buffer); + speech_length = samplerate_upsample_output_num(&cnetz->sender.srstate, 100); + samplerate_upsample(&cnetz->sender.srstate, speech_buffer, 100, speech_buffer, speech_length); /* 3. scramble */ if (cnetz->scrambler) scrambler(&cnetz->scrambler_tx, speech_buffer, speech_length); @@ -627,60 +645,66 @@ again: * because one has a phase wrap before and the other after a sample. * then we do it next super frame cycle */ if (master->frame_last_scount == cnetz->fsk_tx_scount) { - PDEBUG(DDSP, DEBUG_DEBUG, "Sync phase of slave to master: master=%.15f, slave=%.15f, diff=%.15f\n", master->frame_last_phase, cnetz->fsk_tx_phase, master->frame_last_phase - cnetz->fsk_tx_phase); + LOGP(DDSP, LOGL_DEBUG, "Sync phase of slave to master: master=%.15f, slave=%.15f, diff=%.15f\n", master->frame_last_phase, cnetz->fsk_tx_phase, master->frame_last_phase - cnetz->fsk_tx_phase); cnetz->fsk_tx_phase = master->frame_last_phase; } else { - PDEBUG(DDSP, DEBUG_DEBUG, "Not sync phase of slave to master: Sample counts during frame change are different, ignoring this time!\n"); + LOGP(DDSP, LOGL_DEBUG, "Not sync phase of slave to master: Sample counts during frame change are different, ignoring this time!\n"); } } } /* switch to speech channel */ - if (cnetz->sched_switch_mode && cnetz->sched_r_m == 0) { - if (--cnetz->sched_switch_mode == 0) { + if (cnetz->sched_dsp_mode_ts >= 0 && cnetz->sched_r_m == 0) { + if (cnetz->sched_dsp_mode_ts == cnetz->sched_ts) { /* OgK / SpK(K) / SpK(V) */ - PDEBUG_CHAN(DDSP, DEBUG_INFO, "Switching channel (mode)\n"); + LOGP_CHAN(DDSP, LOGL_INFO, "Now switching channel mode to %s at timeslot %d\n", cnetz_dsp_mode_name(cnetz->sched_dsp_mode), cnetz->sched_dsp_mode_ts); + cnetz->sched_dsp_mode_ts = -1; cnetz_set_dsp_mode(cnetz, cnetz->sched_dsp_mode); } } switch (cnetz->dsp_mode) { case DSP_MODE_OGK: - /* if automatic polarity selection is used, toggle between - * two polarities (every 4 slots) until a response is received - * then continue to use the time slots of that polarity - */ - if (cnetz->auto_polarity) - cnetz->negative_polarity = (cnetz->sched_ts & 7) >> 2; - /* send on timeslots depending on the polarity: - * positive polarity: 0, 8, 16, 24 - * negative polarity: 4, 12, 20, 28 - */ - if (((cnetz->sched_ts & 7) == 0 && cnetz->negative_polarity == 0) - || ((cnetz->sched_ts & 7) == 4 && cnetz->negative_polarity == 1)) { + if (((si.timeslots >> cnetz->sched_ts) & 1)) { if (cnetz->sched_r_m == 0) { + /* if automatic polarity selection is used, toggle between two polarities (every transmitted slot) until a response is received then continue to use the time slots of that polarity */ + if (cnetz->auto_polarity) + cnetz->negative_polarity = (cnetz->sched_ts & 7) >> 2; /* set last time slot, so we know to which time slot the message from mobile station belongs to */ cnetz->sched_last_ts = cnetz->sched_ts; - PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Transmitting 'Rufblock' at timeslot %d\n", cnetz->sched_ts); bits = cnetz_encode_telegramm(cnetz); + if (bits) { + LOGP_CHAN(DDSP, LOGL_DEBUG, "Transmitting 'Rufblock' at timeslot %d\n", cnetz->sched_ts); + fsk_block_encode(cnetz, bits, 1); + } else + fsk_nothing_encode(cnetz); } else { - PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Transmitting 'Meldeblock' at timeslot %d\n", cnetz->sched_ts); bits = cnetz_encode_telegramm(cnetz); + if (bits) { + LOGP_CHAN(DDSP, LOGL_DEBUG, "Transmitting 'Meldeblock' at timeslot %d\n", cnetz->sched_ts); + fsk_block_encode(cnetz, bits, 1); + } else + fsk_nothing_encode(cnetz); } - fsk_block_encode(cnetz, bits, 1); } else { fsk_nothing_encode(cnetz); } break; case DSP_MODE_SPK_K: - PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Transmitting 'Konzentrierte Signalisierung'\n"); bits = cnetz_encode_telegramm(cnetz); - fsk_block_encode(cnetz, bits, 0); + if (bits) { + LOGP_CHAN(DDSP, LOGL_DEBUG, "Transmitting 'Konzentrierte Signalisierung' at timeslot %d.%d\n", cnetz->sched_ts, cnetz->sched_r_m * 5); + fsk_block_encode(cnetz, bits, 0); + } else + fsk_nothing_encode(cnetz); break; case DSP_MODE_SPK_V: - PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Transmitting 'Verteilte Signalisierung'\n"); bits = cnetz_encode_telegramm(cnetz); - fsk_distributed_encode(cnetz, bits); + if (bits) { + LOGP_CHAN(DDSP, LOGL_DEBUG, "Transmitting 'Verteilte Signalisierung' starting at timeslot %d\n", cnetz->sched_ts); + fsk_distributed_encode(cnetz, bits); + } else + fsk_nothing_encode(cnetz); break; case DSP_MODE_OFF: default: @@ -718,7 +742,7 @@ again: /* ramp before speech */ for (j = 0; j < begin; j++) { /* ramp up from 0 to speech level */ - speech_buffer[j] = speech_buffer[begin] * (ramp_up[j * 256 / begin] / cnetz->fsk_deviation / 2.0 + 0.5); + speech_buffer[j] = speech_buffer[begin] * (cnetz->fsk_ramp_up[j * 256 / begin] / cnetz->fsk_deviation / 2.0 + 0.5); } speech_length += begin; /* add one bit duration before speech*/ /* ramp after speech */ @@ -729,7 +753,7 @@ again: speech_length = end; /* shorten 'speech_length', if greater than 'end' */ for (j = 0; j < begin; j++) { /* ramp down from speech level to 0 */ - speech_buffer[end + j] = speech_buffer[end - 1] * (ramp_down[j * 256 / begin] / cnetz->fsk_deviation / 2.0 + 0.5); + speech_buffer[end + j] = speech_buffer[end - 1] * (cnetz->fsk_ramp_down[j * 256 / begin] / cnetz->fsk_deviation / 2.0 + 0.5); } speech_length += begin; /* add one bit duration after speech */ speech_pos = 0; @@ -773,7 +797,7 @@ void sender_send(sender_t *sender, sample_t *samples, uint8_t *power, int length calc_clock_speed(cnetz, length, 1, 0); #ifdef TEST_SCRAMBLE - jitter_load(&scrambler_test_jb, samples, length); + test_echo_load(&scrambler_test_echo, samples, length); scrambler(&scrambler_test_scrambler2, samples, length); return; #endif @@ -792,7 +816,8 @@ void unshrink_speech(cnetz_t *cnetz, sample_t *speech_buffer, int count) { sample_t *spl; int pos, i; - double x, y, x_last, y_last, factor; + int range; + double offset; /* check if we still have a transaction * this might not be true, if we just released transaction, but still @@ -801,21 +826,13 @@ void unshrink_speech(cnetz_t *cnetz, sample_t *speech_buffer, int count) if (!cnetz->trans_list) return; - /* fix offset between speech blocks by using high pass filter */ - /* use first sample as previous sample, so we don't have a level jump between two subsequent audio chunks */ - x_last = speech_buffer[0]; - y_last = cnetz->offset_y_last; - factor = cnetz->offset_factor; - for (i = 0; i < count; i++) { - /* change level */ - x = speech_buffer[i]; - /* high-pass to remove low level frequencies, caused by level jump between audio chunks */ - y = factor * (y_last + x - x_last); - x_last = x; - y_last = y; - speech_buffer[i] = y; + /* ramp from level of last frame to level of current frame */ + range = cnetz->offset_range; + offset = speech_buffer[0] - cnetz->offset_last; + for (i = 0; i < range; i++) { + speech_buffer[i] -= offset * (1.0 - (double)i / (double)range); } - cnetz->offset_y_last = y_last; + cnetz->offset_last = speech_buffer[count - 1]; /* 4. de-emphasis is done by cnetz code, not by common code */ /* de-emphasis is only used when scrambler is off, see FTZ 171 TR 60 Clause 4 */ @@ -843,39 +860,51 @@ void unshrink_speech(cnetz_t *cnetz, sample_t *speech_buffer, int count) cnetz->sender.rxbuf_pos = pos; } -const char *cnetz_dsp_mode_name(enum dsp_mode mode) +void cnetz_set_dsp_mode(cnetz_t *cnetz, enum dsp_mode mode) { - static char invalid[16]; - - switch (mode) { - case DSP_SCHED_NONE: - return "SCHED_NONE"; - case DSP_MODE_OFF: - return "OFF"; - case DSP_MODE_OGK: - return "OGK"; - case DSP_MODE_SPK_K: - return "SPK_K"; - case DSP_MODE_SPK_V: - return "SPK_V"; + if (mode != cnetz->dsp_mode) { + LOGP_CHAN(DDSP, LOGL_INFO, "DSP mode %s -> %s\n", cnetz_dsp_mode_name(cnetz->dsp_mode), cnetz_dsp_mode_name(mode)); + cnetz->dsp_mode = mode; } + if (mode == DSP_MODE_SPK_V && cnetz->dsp_mode != mode) + jitter_reset(&cnetz->sender.dejitter); - sprintf(invalid, "invalid(%d)", mode); - return invalid; -} - -void cnetz_set_dsp_mode(cnetz_t *cnetz, enum dsp_mode mode) -{ - PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "DSP mode %s -> %s\n", cnetz_dsp_mode_name(cnetz->dsp_mode), cnetz_dsp_mode_name(mode)); - cnetz->dsp_mode = mode; /* we must get rid of partly received frame */ fsk_demod_reset(&cnetz->fsk_demod); } -void cnetz_set_sched_dsp_mode(cnetz_t *cnetz, enum dsp_mode mode, int frames_ahead) +void cnetz_set_sched_dsp_mode(cnetz_t *cnetz, enum dsp_mode mode, int timeslot) { - PDEBUG_CHAN(DDSP, DEBUG_DEBUG, " Schedule DSP mode %s -> %s in %d frames\n", cnetz_dsp_mode_name(cnetz->dsp_mode), cnetz_dsp_mode_name(mode), frames_ahead); + if (cnetz->sched_dsp_mode_ts < 0 && mode == cnetz->dsp_mode) { + LOGP_CHAN(DDSP, LOGL_INFO, "Schedule DSP mode %s not required, we are already in that mode\n", cnetz_dsp_mode_name(mode)); + return; + } + LOGP_CHAN(DDSP, LOGL_INFO, "Schedule DSP mode %s -> %s at timeslot %d\n", cnetz_dsp_mode_name(cnetz->dsp_mode), cnetz_dsp_mode_name(mode), timeslot); cnetz->sched_dsp_mode = mode; - cnetz->sched_switch_mode = frames_ahead; + cnetz->sched_dsp_mode_ts = timeslot; } +/* Receive audio from call instance. */ +void call_down_audio(void *decoder, void *decoder_priv, int callref, uint16_t sequence, uint8_t marker, uint32_t timestamp, uint32_t ssrc, uint8_t *payload, int payload_len) +{ + sender_t *sender; + cnetz_t *cnetz; + + for (sender = sender_head; sender; sender = sender->next) { + cnetz = (cnetz_t *) sender; + if (cnetz->trans_list && cnetz->trans_list->callref == callref) + break; + } + if (!sender) + return; + + if (cnetz->dsp_mode == DSP_MODE_SPK_V) { + jitter_frame_t *jf; + jf = jitter_frame_alloc(decoder, decoder_priv, payload, payload_len, marker, sequence, timestamp, ssrc); + if (jf) + jitter_save(&cnetz->sender.dejitter, jf); + } +} + +void call_down_clock(void) {} + diff --git a/src/cnetz/dsp.h b/src/cnetz/dsp.h index f5e3506..7af7c94 100644 --- a/src/cnetz/dsp.h +++ b/src/cnetz/dsp.h @@ -5,5 +5,5 @@ 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); void cnetz_set_dsp_mode(cnetz_t *cnetz, enum dsp_mode mode); -void cnetz_set_sched_dsp_mode(cnetz_t *cnetz, enum dsp_mode mode, int frames_ahead); +void cnetz_set_sched_dsp_mode(cnetz_t *cnetz, enum dsp_mode mode, int timeslot); diff --git a/src/cnetz/fsk_demod.c b/src/cnetz/fsk_demod.c index 42865df..9386b60 100644 --- a/src/cnetz/fsk_demod.c +++ b/src/cnetz/fsk_demod.c @@ -39,13 +39,13 @@ * 0-level of the phone's transmitter is. (level of carrier frequency) Also we * use receiver and sound card that cause any level to return to 0 after some * time, Even if the transmitter still transmits a level above or below the - * carrier frequnecy. Insted we look at the change of the received signal. An + * carrier frequnecy. Instead we look at the change of the received signal. An * upward change indicates 1. An downward change indicates 0. (This may also be * reversed, if we find out, that we received a sync sequence in reversed * polarity.) If there is no significant change in level, we keep the value of * last change, regardless of what level we actually receive. * - * To determine a change from noise, we use a theshold. This is set to half of + * To determine a change from noise, we use a threshold. This is set to half of * the level of last received change. This means that the next change may be * down to a half lower. There is a special case during distributed signaling. * The first level change of each data chunk raises or falls from 0-level @@ -65,7 +65,7 @@ * determine the highest slope, the highest difference between subsequent * samples is used. For every sample we move the window one bit to the right * (next sample), check if change level matches the threshold and highest slope - * is in the middle and so forth. Only if the highes slope is exactly in the + * is in the middle and so forth. Only if the highest slope is exactly in the * middle, we declare a change. This means that we detect a slope about half of * a bit duration later. * @@ -121,7 +121,10 @@ * if debug is set to 1, debugging will start at program start */ //#define DEBUG_DECODER -//static int debug = 0; + +#ifdef DEBUG_DECODER +static int debug = 0; +#endif #include <stdio.h> #include <stdint.h> @@ -129,7 +132,7 @@ #include <string.h> #include <math.h> #include "../libsample/sample.h" -#include "../libdebug/debug.h" +#include "../liblogging/logging.h" #include "cnetz.h" #include "dsp.h" #include "telegramm.h" @@ -140,7 +143,7 @@ int fsk_fm_init(fsk_fm_demod_t *fsk, cnetz_t *cnetz, int samplerate, double bitr memset(fsk, 0, sizeof(*fsk)); if (samplerate < 48000) { - PDEBUG(DDSP, DEBUG_ERROR, "Sample rate must be at least 48000 Hz!\n"); + LOGP(DDSP, LOGL_ERROR, "Sample rate must be at least 48000 Hz!\n"); return -1; } @@ -149,13 +152,13 @@ int fsk_fm_init(fsk_fm_demod_t *fsk, cnetz_t *cnetz, int samplerate, double bitr switch (demod) { case FSK_DEMOD_SLOPE: - PDEBUG(DDSP, DEBUG_INFO, "Detecting level change by looking at slope (good for sound cards)\n"); + LOGP(DDSP, LOGL_INFO, "Detecting level change by looking at slope (good for sound cards)\n"); break; case FSK_DEMOD_LEVEL: - PDEBUG(DDSP, DEBUG_INFO, "Detecting level change by looking zero crosssing (good for SDR)\n"); + LOGP(DDSP, LOGL_INFO, "Detecting level change by looking zero crosssing (good for SDR)\n"); break; default: - PDEBUG(DDSP, DEBUG_ERROR, "Wrong demod type, please fix!\n"); + LOGP(DDSP, LOGL_ERROR, "Wrong demod type, please fix!\n"); abort(); } @@ -163,7 +166,7 @@ int fsk_fm_init(fsk_fm_demod_t *fsk, cnetz_t *cnetz, int samplerate, double bitr half = (int)((double)samplerate / bitrate / 2.0 + 0.5); fsk->bit_buffer_spl = calloc(sizeof(fsk->bit_buffer_spl[0]), len); if (!fsk->bit_buffer_spl) { - PDEBUG(DDSP, DEBUG_ERROR, "No mem!\n"); + LOGP(DDSP, LOGL_ERROR, "No mem!\n"); goto error; } @@ -174,7 +177,7 @@ int fsk_fm_init(fsk_fm_demod_t *fsk, cnetz_t *cnetz, int samplerate, double bitr fsk->speech_size = samplerate * 60 / bitrate + 10; /* 60 bits duration, add 10 to be safe */ fsk->speech_buffer = calloc(sizeof(fsk->speech_buffer[0]), fsk->speech_size); if (!fsk->speech_buffer) { - PDEBUG(DDSP, DEBUG_ERROR, "No mem!\n"); + LOGP(DDSP, LOGL_ERROR, "No mem!\n"); goto error; } @@ -182,7 +185,7 @@ int fsk_fm_init(fsk_fm_demod_t *fsk, cnetz_t *cnetz, int samplerate, double bitr #ifdef DEBUG_DECODER char debug_filename[256]; - sprintf(debug_filename, "/tmp/debug_decoder_channel_%d.txt", cnetz->sender.kanal); + sprintf(debug_filename, "/tmp/debug_decoder_channel_%s.txt", cnetz->sender.kanal); fsk->debug_fp = fopen(debug_filename, "w"); if (!fsk->debug_fp) { fprintf(stderr, "Failed to open decoder debug file '%s'!\n", debug_filename); @@ -342,12 +345,12 @@ static inline void got_bit(fsk_fm_demod_t *fsk, int bit, double change_level) case FSK_SYNC_NONE: fsk->rx_sync = (fsk->rx_sync << 1) | bit; /* use half level of last change for threshold change detection. - * if there is no change detected for 5 bits, set theshold to + * if there is no change detected for 5 bits, set threshold to * 1 percent, so the 7 pause bits before a frame will make sure * that the change is below noise level, so the first sync * bit is detected. then the change is set and adjusted * for all other bits in the sync sequence. - * after sync, the theshold is set to half of the average of + * after sync, the threshold is set to half of the average of * all changes in the sync sequence */ if (change_level > 0.0) { fsk->level_threshold = change_level / 2.0; @@ -414,17 +417,6 @@ static inline void find_change_slope(fsk_fm_demod_t *fsk) sample_t threshold; int i; -#ifdef DEBUG_DECODER - /* show deviation of middle sample in windows (in a range of bandwidth) */ - if (debug) { - fprintf(fsk->debug_fp, "%s", - debug_amplitude( - fsk->bit_buffer_spl[(fsk->bit_buffer_pos + fsk->bit_buffer_half) % fsk->bit_buffer_len] - ) - ); - } -#endif - /* get level range (level_min and level_max) and also * get maximum slope (change_max) and where it was * (change_at) and what direction it went (change_positive) @@ -492,10 +484,6 @@ static inline void find_change_slope(fsk_fm_demod_t *fsk) } fsk->next_bit -= fsk->bits_per_sample; -#ifdef DEBUG_DECODER - if (debug) - fprintf(fsk->debug_fp, "\n"); -#endif } /* find bit change by looking at zero crossing */ @@ -507,12 +495,6 @@ static inline void find_change_level(fsk_fm_demod_t *fsk) /* get bit in the middle of the buffer */ s = fsk->bit_buffer_spl[(fsk->bit_buffer_pos + fsk->bit_buffer_half) % fsk->bit_buffer_len]; -#ifdef DEBUG_DECODER - /* show deviation */ - if (debug) - fprintf(fsk->debug_fp, "%s", debug_amplitude(s)); -#endif - /* just sample first bit in distributed mode */ if (fsk->cnetz->dsp_mode == DSP_MODE_SPK_V && fsk->bit_count == 0) { if (fmod(fsk->bit_time, BITS_PER_SPK_BLOCK) < 1.5) @@ -569,10 +551,6 @@ static inline void find_change_level(fsk_fm_demod_t *fsk) fsk->next_bit -= fsk->bits_per_sample; done: -#ifdef DEBUG_DECODER - if (debug) - fprintf(fsk->debug_fp, "\n"); -#endif return; } @@ -580,7 +558,7 @@ done: void fsk_fm_demod(fsk_fm_demod_t *fsk, sample_t *samples, int length) { int i; - double t; + double t = 0.0; /* process signaling block, sample by sample */ for (i = 0; i < length; i++) { @@ -590,6 +568,14 @@ void fsk_fm_demod(fsk_fm_demod_t *fsk, sample_t *samples, int length) if (fsk->bit_buffer_pos == fsk->bit_buffer_len) fsk->bit_buffer_pos = 0; +#ifdef DEBUG_DECODER + /* show deviation of center sample in window */ + if (debug) + fprintf(fsk->debug_fp, "%s", debug_amplitude(fsk->bit_buffer_spl[(fsk->bit_buffer_pos + fsk->bit_buffer_half) % fsk->bit_buffer_len])); + if (debug && fmod(fsk->bit_time - fsk->bits_per_sample, 1.0) > fmod(fsk->bit_time, 1.0)) + fprintf(fsk->debug_fp, " -bitchange-"); +#endif + /* for each sample process buffer */ if (fsk->cnetz->dsp_mode != DSP_MODE_SPK_V) { if (fsk->demod_type == FSK_DEMOD_SLOPE) @@ -611,7 +597,7 @@ void fsk_fm_demod(fsk_fm_demod_t *fsk, sample_t *samples, int length) fsk->next_bit = 1.0 - fsk->bits_per_sample; #ifdef DEBUG_DECODER if (debug && fsk->bit_count) - fprintf(fsk->debug_fp, "---- SPK(V) BLOCK START ----\n"); + fprintf(fsk->debug_fp, "\n---- SPK(V) BLOCK START ----"); #endif fsk->bit_count = 0; } else @@ -622,13 +608,21 @@ void fsk_fm_demod(fsk_fm_demod_t *fsk, sample_t *samples, int length) find_change_level(fsk); } else if (t >= 5.5 && t < 65.5) { +#ifdef DEBUG_DECODER + if (debug && !fsk->speech_count) + fprintf(fsk->debug_fp, " (start recording speech)"); +#endif /* get audio for the duration of 60 bits */ /* prevent overflow, if speech_size != 0 and SPK_V * has been restarted. */ if (fsk->speech_count < fsk->speech_size) - fsk->speech_buffer[fsk->speech_count++] = samples[i]; + fsk->speech_buffer[fsk->speech_count++] = fsk->bit_buffer_spl[(fsk->bit_buffer_pos + fsk->bit_buffer_half) % fsk->bit_buffer_len]; } else if (t >= 65.5) { +#ifdef DEBUG_DECODER + if (debug && fsk->speech_count) + fprintf(fsk->debug_fp, " (stop recording speech)"); +#endif if (fsk->speech_count) { unshrink_speech(fsk->cnetz, fsk->speech_buffer, fsk->speech_count); fsk->speech_count = 0; @@ -641,6 +635,10 @@ void fsk_fm_demod(fsk_fm_demod_t *fsk, sample_t *samples, int length) if (fsk->bit_time >= BITS_PER_SUPERFRAME) { fsk->bit_time -= BITS_PER_SUPERFRAME; } +#ifdef DEBUG_DECODER + if (debug && samples) + fprintf(fsk->debug_fp, "\n"); +#endif /* another clock is used to measure actual super frame time */ fsk->bit_time_uncorrected += fsk->bits_per_sample; if (fsk->bit_time_uncorrected >= BITS_PER_SUPERFRAME) { diff --git a/src/cnetz/fsk_demod.h b/src/cnetz/fsk_demod.h index 2d33c80..fda73a5 100644 --- a/src/cnetz/fsk_demod.h +++ b/src/cnetz/fsk_demod.h @@ -1,6 +1,6 @@ -#define BITS_PER_SUPERFRAME 12672.0 /* super frame (Oberrahmen) has duration of excactly 2.4 seconds */ -#define BITS_PER_BLOCK 198.0 /* block has duration of excactly 37.5 milli seconds */ +#define BITS_PER_SUPERFRAME 12672.0 /* super frame (Oberrahmen) has duration of exactly 2.4 seconds */ +#define BITS_PER_BLOCK 198.0 /* block has duration of exactly 37.5 milli seconds */ #define BITS_PER_SPK_BLOCK 66.0 /* spk block has a duration of exactly 12.5 milli seconds */ /* fsk rx sync state */ diff --git a/src/cnetz/image.c b/src/cnetz/image.c index b2313c8..a9be2c7 100644 --- a/src/cnetz/image.c +++ b/src/cnetz/image.c @@ -1,80 +1,39 @@ #include <stdio.h> -#include <string.h> -#include "../libmobile/image.h" -const char *image[] = { - "@g _\n" - " @y______________@g ( )\n" - " @y/ \\@g / /\n" - " @y(@w Die Mauer ist@y )@g / /\n" - " @y\\@w gefallen!@y /@g / /\n" - " @y\\_______ __/@g / /\n" - " @y\\ |@g / /\n" - " @wC-NETZ@g @y\\|@g / /\n" +const char *aaimage[] = { + "@w _\n" + " @y______________@w ( )\n" + " @y/ \\@w / /\n" + " @y(@W Die Mauer ist@y )@w / /\n" + " @y\\@W gefallen!@y /@w / /\n" + " @y\\_______ __/@w / /\n" + " @y\\ |@w / /\n" + " @WC-NETZ@w @y\\|@w / /\n" " __________________/_/_\n" " / oo /|\n" " / o o o / |\n" " / oo / |\n" " / ________________ / |\n" - " / / @G021250993@g / / /\n" + " / / @g021250993@w / / /\n" " / /_______________/ / /\n" - " / @b______ ______@g / / @c___@g\n" - " / @b/_@G(@b_@G)@b_/ /_@r(@b_@r)@b_/@g / / @c\\ \\__ @r___/@g\n" - " / @b____ ____ ____@g / / @c_ ) / @r__/ )@g\n" - " / @b/_@w1@b_/ /_@w2@b_/ /_@w3@b_/@g / / @c( \\/ \\@r/ |@g\n" - " / @b____ ____ ____@g / / @c| @r| \\@g\n" - " / @b/_@w4@b_/ /_@w5@b_/ /_@w6@b_/@g / / @c/ @r\\ |@g\n" - " / @b____ ____ ____@g / / @c| BRD @r/ DDR )@g\n" - " / @b/_@w7@b_/ /_@w8@b_/ /_@w9@b_/@g / / @c_| @r/ |@g\n" - " / @b____ ____ ____@g / / @c\\ @r| |@g\n" - " / @b/_@w*@b_/ /_@w0@b_/ /_@w#@b_/@g / / @c/ @r/ ___/@g\n" - " / / / @c| @r\\________/@g\n" - " / o o / / @c\\ \\@g\n" - " /_____________________/ / @c| \\@g\n" - " | | / @c\\___ \\_@g\n" - " | = = | / @c/ /@g\n" - " | = = | / @c/ __ (@g\n" - " |______________________|/ @c|___________/ \\)@g\n" + " / @B______ ______@w / / @c___@w\n" + " / @B/_@g(@B_@g)@B_/ /_@r(@B_@r)@B_/@w / / @c\\ \\__ @r___/@w\n" + " / @B____ ____ ____@w / / @c_ ) / @r__/ )@w\n" + " / @B/_@W1@B_/ /_@W2@B_/ /_@W3@B_/@w / / @c( \\/ \\@r/ |@w\n" + " / @B____ ____ ____@w / / @c| @r| \\@w\n" + " / @B/_@W4@B_/ /_@W5@B_/ /_@W6@B_/@w / / @c/ @r\\ |@w\n" + " / @B____ ____ ____@w / / @c| BRD @r/ DDR )@w\n" + " / @B/_@W7@B_/ /_@W8@B_/ /_@W9@B_/@w / / @c_| @r/ |@w\n" + " / @B____ ____ ____@w / / @c\\ @r| |@w\n" + " / @B/_@W*@B_/ /_@W0@B_/ /_@W#@B_/@w / / @c/ @r/ ___/@w\n" + " / / / @c| @r\\________/@w\n" + " / o o / / @c\\ \\@w\n" + " /_____________________/ / @c| \\@w\n" + " | | / @c\\___ \\_@w\n" + " | = = | / @c/ /@w\n" + " | = = | / @c/ __ (@w\n" + " |______________________|/ @c|___________/ \\)@w\n" "@w", NULL }; -void print_image(void) -{ - int i, j; - - for (i = 0; image[i]; i++) { - for (j = 0; j < (int)strlen(image[i]); j++) { - if (image[i][j] == '@') { - j++; - switch(image[i][j]) { - case 'g': /* gray */ - printf("\033[0;37m"); - break; - case 'G': /* green */ - printf("\033[0;32m"); - break; - case 'c': /* cyan */ - printf("\033[0;36m"); - break; - case 'w': /* white */ - printf("\033[1;37m"); - break; - case 'y': /* yellow */ - printf("\033[0;33m"); - break; - case 'r': /* red */ - printf("\033[0;31m"); - break; - case 'b': /* blue */ - printf("\033[1;34m"); - break; - } - } else - printf("%c", image[i][j]); - } - printf("\n"); - } - printf("\033[0;39m"); -} - diff --git a/src/cnetz/main.c b/src/cnetz/main.c index 265e433..f3b58c7 100644 --- a/src/cnetz/main.c +++ b/src/cnetz/main.c @@ -24,7 +24,7 @@ #include <errno.h> #include "../libsample/sample.h" #include "../libmobile/main_mobile.h" -#include "../libdebug/debug.h" +#include "../liblogging/logging.h" #include "../libmobile/call.h" #include "../anetz/freiton.h" #include "../anetz/besetztton.h" @@ -44,18 +44,20 @@ 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; -const char *flip_polarity = "auto"; +const char *flip_polarity = ""; int ms_power = 6; /* 1..8 */ int warteschlange = 1; int challenge_valid; uint64_t challenge; int response_valid; uint64_t response; +uint32_t timeslots = 4; /* 1 up to 8 */ uint8_t fuz_nat = 1; uint8_t fuz_fuvst = 4; uint8_t fuz_rest = 66; const char *fuz_name = NULL; uint8_t kennung_fufst = 1; /* normal prio */ +uint8_t bahn_bs = 0; /* normal */ uint8_t authentifikationsbit = 0; uint8_t ws_kennung = 0; /* no queue */ uint8_t fuvst_sperren = 0; /* no blocking registration/calls */ @@ -71,9 +73,11 @@ uint8_t reduzierung = 0; /* factor 4 */ uint8_t nachbar_prio = 0; int8_t futln_sperre_start = -1; /* no blocking */ int8_t futln_sperre_end = -1; /* no range */ +int meldeinterval = 120; /* when to ask the phone about beeing alive */ +int meldeaufrufe = 3; /* how many times to ask phone about beeing alive */ enum demod_type demod = FSK_DEMOD_AUTO; int metering = 20; -double speech_deviation = 4000.0; /* best results with all my equipment */ +double speech_deviation = 2400.0; /* best results with older equipment (not C5) */ void print_help(const char *arg0) { @@ -81,6 +85,10 @@ void print_help(const char *arg0) /* - - */ printf(" -T --channel-type <channel type> | list\n"); printf(" Give channel type, use 'list' to get a list. (default = '%s')\n", chan_type_short_name(chan_type[0])); + printf(" You must define at least one OgK at channel 131. This channel may be a\n"); + printf(" a combined OgK+SpK channel, but this works with older phones only.\n"); + printf(" You must define additionally one or more SpK, in order to make calls.\n"); + printf(" You may define alternative OgK, the phones will attach to it then.\n"); printf(" -M --measure-speed\n"); printf(" Measures clock speed. THIS IS REQUIRED! See documentation!\n"); printf(" -C --clock-speed <rx ppm>,<tx ppm>\n"); @@ -94,15 +102,15 @@ void print_help(const char *arg0) printf(" generates a negative signal rather than a positive one. If auto, the\n"); printf(" base station uses double time slots with alternating polarity.\n"); printf(" Once a mobile registers, the correct polarity is selected and used.\n"); - printf(" (default = %s)\n", flip_polarity); - printf(" Note: This has no effect with SDR.\n"); + printf(" (default = %s)\n", (flip_polarity[0]) ? flip_polarity : "auto"); + printf(" Note: Correct polarity is selected for SDR by default.\n"); printf(" -P --ms-power <power level>\n"); printf(" Give power level of the mobile station: 1, 2, 4, 6, 8 (default = '%d')\n", ms_power); printf(" 1 = 7.5-20 W; 2 = 4-8 W; 4 = 0.5-1 W; 6 = 50-125 mW; 8 = 2-10 mW\n"); printf(" Power level 8 starts with level 6 and is then reduced on SpK.\n"); printf(" -A --authentication <challenge>\n"); printf(" Enable authorization flag on the base station and use given challenge\n"); - printf(" as autorization random. Depending on the key inside the card you will\n"); + printf(" as authorization random. Depending on the key inside the card you will\n"); printf(" get a response. Any response is accepted. Phone must have smart card!\n"); printf(" The challenge can be any 64 bit (hex) number like: 0x0123456789abcdef\n"); printf(" Note: Authentication is automatically enabled for the base station\n"); @@ -114,12 +122,18 @@ void print_help(const char *arg0) printf(" Enable queue support. If no channel is available, calls will be kept\n"); printf(" in a queue for maximum of 60 seconds. (default = %d)\n", warteschlange); printf(" -G --gebuehren <seconds> | 0\n"); - printf(" Increment metering counter every given number of seconds.\n"); + printf(" Increment metering counter every given number of seconds.\n"); printf(" To turn off, use 0. (default = %d)\n", metering); + printf(" If metering pulses are sent via Osmo-CC interface, pulses are always\n"); + printf(" increment metering counter. This overrides this option.\n"); printf(" -V --voice-deviation <2400..4000 Hz>\n"); - printf(" It is unclear what the actual voice deviation is. Please decrease, if\n"); - printf(" mobile's microphone is too loud and speaker is too quiet.\n"); + printf(" It is unclear what the actual voice deviation is. Please increase, if\n"); + printf(" mobile's earpiece is too quiet and the microphone is too loud.\n"); printf(" (default = %.0f)\n", speech_deviation); + printf(" -S --sysinfo timeslots=1|2|4|8\n"); + printf(" Set number of timeslots of OgK broadcast. There are 32 time slots per\n"); + printf(" frame, but only up to 8 slots can be used, because of processing\n"); + printf(" delay. (default = %d)\n", timeslots); printf(" -S --sysinfo fuz-nat=<nat>\n"); printf(" Set country ID of base station. All IDs were used inside Germany only.\n"); printf(" (default = %d)\n", fuz_nat); @@ -139,10 +153,16 @@ void print_help(const char *arg0) printf(" 2 = Higher priority base station.\n"); printf(" 3 = Highest priority base station.\n"); printf(" Note: Priority has no effect, because there is only one base station.\n"); - printf(" -A --sysinfo authentifikationsbit=auth>\n"); + printf(" -S --sysinfo bahn-bs=<value>\n"); + printf(" Set special tunnel base station mode for train mobile phones only.\n"); + printf(" (default = %d)\n", kennung_fufst); + printf(" 0 = Disable (every phone is allowed)\n"); + printf(" 1 = Enable (only train phones are allowed)\n"); + printf(" Note: Enableing this will force priority to 0 (Test base station).\n"); + printf(" -S --sysinfo auth=<auth>\n"); printf(" Enable authentication flag 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. Useful get the vendor IDs of the phone.\n"); + printf(" we just accept any card. Useful to get the vendor IDs of the phone.\n"); printf(" 0 = Disable. Even chip card phones behave like magnetic card phones.\n"); printf(" 1 = Enable. Chip card phones send their card ID.\n"); printf(" (default = %d)\n", authentifikationsbit); @@ -211,6 +231,12 @@ void print_help(const char *arg0) } else { printf(" (default = %d-%d)\n", futln_sperre_start, futln_sperre_end); } + printf(" -S --sysinfo meldeinterval=<seconds>\n"); + printf(" Time to wait until pinging the phone wether it is still available.\n"); + printf(" (default = %d)\n", meldeinterval); + printf(" -S --sysinfo meldeaufrufe=<count>\n"); + printf(" Number of times we try to ping mobile until we assume it is gone.\n"); + printf(" Use '0' for infinite tries. (default = %d)\n", meldeaufrufe); 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"); @@ -220,8 +246,7 @@ void print_help(const char *arg0) 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"); + main_mobile_print_station_id(); main_mobile_print_hotkeys(); printf("Press 'i' key to dump list of currently attached subscribers.\n"); } @@ -341,6 +366,9 @@ static int handle_options(int short_option, int argi, char **argv) return -EINVAL; } p++; + if (!strncasecmp(argv[argi], "timeslots=", p - argv[argi])) { + timeslots = atoi_limit(p, 1, 8); + } else if (!strncasecmp(argv[argi], "fuz-nat=", p - argv[argi])) { fuz_nat = atoi_limit(p, 0, 7); } else @@ -367,11 +395,14 @@ error_fuz: fuz_rest = atoi_limit(p, 0, 255); } else if (!strncasecmp(argv[argi], "fuz-name=", p - argv[argi])) { - fuz_name = strdup(p); + fuz_name = options_strdup(p); } else if (!strncasecmp(argv[argi], "kennung-fufst=", p - argv[argi])) { kennung_fufst = atoi_limit(p, 0, 3); } else + if (!strncasecmp(argv[argi], "bahn-bs=", p - argv[argi])) { + bahn_bs = atoi_limit(p, 0, 1); + } else if (!strncasecmp(argv[argi], "auth=", p - argv[argi])) { authentifikationsbit = atoi_limit(p, 0, 1); } else @@ -425,6 +456,12 @@ error_fuz: futln_sperre_end = atoi(q) & 0xf; } } else + if (!strncasecmp(argv[argi], "meldeinterval=", p - argv[argi])) { + meldeinterval = atoi_limit(p, 1, 20 * 60); + } else + if (!strncasecmp(argv[argi], "meldeaufrufe=", p - argv[argi])) { + meldeaufrufe = atoi_limit(p, 0, 1000000); + } else { fprintf(stderr, "Given sysinfo parameter '%s' unknown, use '-h' for help!\n", argv[argi]); return -EINVAL; @@ -449,10 +486,24 @@ error_fuz: return 1; } +static const struct number_lengths number_lengths[] = { + { 7, "regular number format" }, + { 8, "extended number format" }, + { 0, NULL } +}; + +static const char *number_prefixes[] = { + "0161xxxxxxx", + "0161xxxxxxxx", + "+49161xxxxxxx", + "+49161xxxxxxxx", + NULL +}; + int main(int argc, char *argv[]) { int rc, argi; - const char *station_id = ""; + const char *station_id = NULL; int mandatory = 0; int polarity; int teilnehmergruppensperre = 0; @@ -466,11 +517,11 @@ int main(int argc, char *argv[]) init_station(); - main_mobile_init(); + main_mobile_init("0123456789", number_lengths, number_prefixes, cnetz_number_valid); /* handle options / config file */ add_options(); - rc = options_config_file("~/.osmocom/analog/cnetz.conf", handle_options); + rc = options_config_file(argc, argv, "~/.osmocom/analog/cnetz.conf", handle_options); if (rc < 0) return 0; argi = options_command_line(argc, argv, handle_options); @@ -479,10 +530,9 @@ int main(int argc, char *argv[]) if (argi < argc) { station_id = argv[argi]; - if (strlen(station_id) != 7) { - printf("Given station ID '%s' does not have 7 digits\n", station_id); - return 0; - } + rc = main_mobile_number_ask(station_id, "station ID"); + if (rc) + return rc; } /* resolve name of base station */ @@ -501,18 +551,16 @@ int main(int argc, char *argv[]) return -EINVAL; } } - /* set or complete name (in case of prefix was given) */ - fuz_name = get_station_name(fuz_nat, fuz_fuvst, fuz_rest); if (!num_kanal) { - printf("No channel (\"Kanal\") is specified, I suggest channel %d.\n\n", CNETZ_OGK_KANAL); + printf("No channel (\"Kanal\") is specified, I suggest channel %d.\n\n", CNETZ_STD_OGK_KANAL); mandatory = 1; } if (use_sdr) { - /* set audiodev */ + /* set device */ for (i = 0; i < num_kanal; i++) - audiodev[i] = "sdr"; - num_audiodev = num_kanal; + dsp_device[i] = "sdr"; + num_device = num_kanal; /* set channel types for more than 1 channel */ if (num_kanal > 1 && num_chan_type == 0) { chan_type[0] = CHAN_TYPE_OGK; @@ -521,9 +569,9 @@ int main(int argc, char *argv[]) num_chan_type = num_kanal; } } - if (num_kanal == 1 && num_audiodev == 0) - num_audiodev = 1; /* use default */ - if (num_kanal != num_audiodev) { + if (num_kanal == 1 && num_device == 0) + num_device = 1; /* use default */ + if (num_kanal != num_device) { fprintf(stderr, "You need to specify as many sound devices as you have channels.\n"); exit(0); } @@ -556,7 +604,13 @@ int main(int argc, char *argv[]) } if (anzahl_gesperrter_teilnehmergruppen) printf("Blocked subscriber with number's last 4 bits from 0x%x to 0x%x\n", teilnehmergruppensperre, (teilnehmergruppensperre + anzahl_gesperrter_teilnehmergruppen - 1) & 0xf); - init_sysinfo(fuz_nat, fuz_fuvst, fuz_rest, kennung_fufst, authentifikationsbit, ws_kennung, fuvst_sperren, grenz_einbuchen, grenz_umschalten, grenz_ausloesen, mittel_umschalten, mittel_ausloesen, genauigkeit, bewertung, entfernung, reduzierung, nachbar_prio, teilnehmergruppensperre, anzahl_gesperrter_teilnehmergruppen); + switch(timeslots) { + case 1: timeslots=0x00000001; break; + case 2: timeslots=0x00010001; break; + case 4: timeslots=0x01010101; break; + default: timeslots=0x11111111; + } + init_sysinfo(timeslots, fuz_nat, fuz_fuvst, fuz_rest, kennung_fufst, bahn_bs, authentifikationsbit, ws_kennung, fuvst_sperren, grenz_einbuchen, grenz_umschalten, grenz_ausloesen, mittel_umschalten, mittel_ausloesen, genauigkeit, bewertung, entfernung, reduzierung, nachbar_prio, teilnehmergruppensperre, anzahl_gesperrter_teilnehmergruppen, meldeinterval, meldeaufrufe); dsp_init(); rc = init_telegramm(); if (rc < 0) { @@ -566,7 +620,7 @@ int main(int argc, char *argv[]) init_coding(); cnetz_init(); - /* check for mandatory OgK */ + /* check for mandatory standard OgK */ for (i = 0; i < num_kanal; i++) { if (chan_type[i] == CHAN_TYPE_OGK || chan_type[i] == CHAN_TYPE_OGK_SPK) break; @@ -610,7 +664,7 @@ int main(int argc, char *argv[]) polarity = 1; /* positive */ if (!strcmp(flip_polarity, "yes")) polarity = -1; /* negative */ - if (use_sdr && polarity == 0) + if (use_sdr && !flip_polarity[0]) polarity = 1; /* SDR is always positive */ /* demodulation algorithm */ @@ -626,7 +680,7 @@ int main(int argc, char *argv[]) /* create transceiver instance */ for (i = 0; i < num_kanal; i++) { - rc = cnetz_create(kanal[i], chan_type[i], audiodev[i], use_sdr, demod, samplerate, rx_gain, challenge_valid, challenge, response_valid, response, warteschlange, metering, speech_deviation, 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, read_tx_wave, loopback); + rc = cnetz_create(kanal[i], chan_type[i], dsp_device[i], use_sdr, demod, dsp_samplerate, rx_gain, tx_gain, challenge_valid, challenge, response_valid, response, warteschlange, metering, speech_deviation, 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, read_tx_wave, loopback); if (rc < 0) { fprintf(stderr, "Failed to create \"Sender\" instance. Quitting!\n"); goto fail; @@ -638,7 +692,7 @@ int main(int argc, char *argv[]) } } - main_mobile(&quit, latency, interval, NULL, station_id, 7); + main_mobile_loop("cnetz", &quit, NULL, station_id); fail: flush_db(); @@ -648,8 +702,11 @@ fail: cnetz_destroy(sender_head); /* exits */ + main_mobile_exit(); fm_exit(); + options_free(); + return 0; } diff --git a/src/cnetz/stations.c b/src/cnetz/stations.c index 1293cda..4cbe292 100644 --- a/src/cnetz/stations.c +++ b/src/cnetz/stations.c @@ -7,2391 +7,2190 @@ /* The list of cell towers is ripped from BSA61 phone's firmware */ static struct cnetz_stations { - char standort[64]; + char long_name[32], name[8]; uint8_t nat, fuvst, rest; - int in1991, in1999; } cnetz_stations[] = { -/* Standort Nat FuVST Rest 1991 1999 */ - { "Oberh.32", 1, 2, 1, 0, 1999, }, - { "Oberh. 0", 1, 2, 5, 0, 1999, }, - { "Wupp.18", 1, 2, 6, 0, 1999, }, - { "Oberh.21", 1, 2, 7, 1991, 1999, }, - { "Duisb.21", 1, 2, 8, 1991, 1999, }, - { "Heilighs", 1, 2, 9, 1991, 1999, }, - { "Essen 1", 1, 2, 10, 0, 1999, }, - { "Velb.Lan", 1, 2, 11, 1991, 1999, }, - { "Duisb.40", 1, 2, 12, 1991, 1999, }, - { "Bottrop0", 1, 2, 13, 1991, 1999, }, - { "Gelsenk1", 1, 2, 14, 1991, 1999, }, - { "Essen 35", 1, 2, 15, 1991, 1999, }, - { "Duisb.25", 1, 2, 16, 1991, 1999, }, - { "VelbNev2", 1, 2, 17, 1991, 1999, }, - { "Wupp. 30", 1, 2, 18, 1991, 1999, }, - { "Essen 28", 1, 2, 19, 1991, 1999, }, - { "Kirchhl4", 1, 2, 20, 0, 1999, }, - { "Gelsenk7", 1, 2, 21, 1991, 1999, }, - { "Wupp. 34", 1, 2, 22, 1991, 1999, }, - { "Wupp. 35", 1, 2, 23, 0, 1999, }, - { "Oberh.23", 1, 2, 24, 0, 1999, }, - { "Neviges4", 1, 2, 25, 0, 1999, }, - { "Duisb.42", 1, 2, 26, 0, 1999, }, - { "Rheinhsn", 1, 2, 27, 0, 1999, }, - { "Essen 12", 1, 2, 28, 0, 1999, }, - { "Homberg1", 1, 2, 29, 0, 1999, }, - { "ReesMehr", 1, 2, 30, 0, 1999, }, - { "Essen 13", 1, 2, 31, 1991, 1999, }, - { "Essen 15", 1, 2, 32, 1991, 1999, }, - { "Heiden 1", 1, 2, 33, 0, 1999, }, - { "Voerde 2", 1, 2, 34, 1991, 1999, }, - { "Duisb. 0", 1, 2, 35, 1991, 1999, }, - { "Velbert1", 1, 2, 36, 1991, 1999, }, - { "Oberh.26", 1, 2, 37, 1991, 1999, }, - { "Gelsnk58", 1, 2, 38, 0, 1999, }, - { "Essen 8", 1, 2, 39, 0, 1999, }, - { "Wupp. 8", 1, 2, 40, 0, 1999, }, - { "Oberh.18", 1, 2, 41, 0, 1999, }, - { "Oberh.30", 1, 2, 43, 0, 1999, }, - { "Wesel 0", 1, 2, 44, 0, 1999, }, - { "Borken 0", 1, 2, 45, 0, 1999, }, - { "Velen 20", 1, 2, 46, 0, 1999, }, - { "Bocholt0", 1, 2, 47, 0, 1999, }, - { "Huenxe 1", 1, 2, 48, 0, 1999, }, - { "Isselbg1", 1, 2, 49, 0, 1999, }, - { "EmElten1", 1, 2, 50, 0, 1999, }, - { "Bochum 3", 1, 2, 51, 0, 1999, }, - { "Dorsten0", 1, 2, 52, 0, 1999, }, - { "Schermb2", 1, 2, 53, 0, 1999, }, - { "Raesfeld", 1, 2, 54, 0, 1999, }, - { "Wupp. 4", 1, 2, 55, 0, 1999, }, - { "Hueckwg2", 1, 2, 57, 0, 1999, }, - { "Herne 1", 1, 2, 58, 0, 1999, }, - { "Bochum47", 1, 2, 59, 0, 1999, }, - { "Hattingn", 1, 2, 60, 0, 1999, }, - { "Sprockhv", 1, 2, 61, 0, 1999, }, - { "Gladbk20", 1, 2, 62, 0, 1999, }, - { "Ahaus 0", 1, 2, 63, 0, 1999, }, - { "Bochum 1", 1, 2, 64, 0, 1999, }, - { "Herten", 1, 2, 66, 0, 1999, }, - { "Oberh. 1", 1, 2, 68, 1991, 1999, }, - { "Wulfen 0", 1, 2, 70, 0, 1999, }, - { "Essen0Ke", 1, 2, 76, 1991, 1999, }, - { "Vreden 0", 1, 2, 79, 0, 1999, }, - { "Gronau 0", 1, 2, 81, 0, 1999, }, - { "Dinslak2", 1, 2, 82, 1991, 1999, }, - { "Bochum78", 1, 2, 84, 0, 1999, }, - { "Bochum 0", 1, 2, 88, 0, 1999, }, - { "Ob9 Bake", 1, 2, 89, 1991, 1999, }, - { "Coesfeld", 1, 2, 92, 0, 1999, }, - { "Schoepp1", 1, 2, 93, 0, 1999, }, - { "Stadtloh", 1, 2, 98, 0, 1999, }, - { "Wupp2Bak", 1, 2, 99, 1991, 1999, }, - { "Neuss 10", 2, 2, 1, 0, 1999, }, - { "Dssd57Me", 2, 2, 2, 0, 1999, }, - { "Neuss 7", 2, 2, 4, 0, 1999, }, - { "Ratingn5", 2, 2, 6, 0, 1999, }, - { "Solingn2", 2, 2, 7, 0, 1999, }, - { "Dssd 18", 2, 2, 8, 0, 1999, }, - { "Dssd 58", 2, 2, 9, 0, 1999, }, - { "Neuss 14", 2, 2, 10, 1991, 1999, }, - { "NeussNor", 2, 2, 11, 1991, 1999, }, - { "Dssd 30", 2, 2, 12, 1991, 1999, }, - { "Langenf3", 2, 2, 13, 0, 1999, }, - { "Dssd 75", 2, 2, 14, 0, 1999, }, - { "Mettman7", 2, 2, 15, 0, 1999, }, - { "Dssd 19", 2, 2, 17, 0, 1999, }, - { "Grevenb3", 2, 2, 18, 0, 1999, }, - { "Grevenb2", 2, 2, 19, 0, 1999, }, - { "Ratingn1", 2, 2, 20, 1991, 1999, }, - { "Dssd 40", 2, 2, 22, 0, 1999, }, - { "Neuss 8", 2, 2, 23, 1991, 1999, }, - { "Dssd 4", 2, 2, 24, 1991, 1999, }, - { "Hilden 6", 2, 2, 26, 1991, 1999, }, - { "Dssd 12", 2, 2, 27, 1991, 1999, }, - { "Ratingn3", 2, 2, 29, 0, 1999, }, - { "Remsch.4", 2, 2, 30, 0, 1999, }, - { "Krefeld4", 2, 2, 31, 0, 1999, }, - { "MeerbuL0", 2, 2, 33, 0, 1999, }, - { "Remsch.4", 2, 2, 34, 1991, 0, }, - { "Osterat1", 2, 2, 35, 0, 1999, }, - { "Krefeld5", 2, 2, 36, 0, 1999, }, - { "MeerbuB1", 2, 2, 37, 1991, 1999, }, - { "Dssd 27", 2, 2, 38, 1991, 1999, }, - { "Dssd 53", 2, 2, 39, 1991, 1999, }, - { "Dormag.", 2, 2, 40, 1991, 0, }, - { "Lev.Opl.", 2, 2, 41, 1991, 0, }, - { "Willich1", 2, 2, 42, 0, 1999, }, - { "Solingn1", 2, 2, 43, 1991, 1999, }, - { "Mgl 18", 2, 2, 44, 0, 1999, }, - { "Haan", 2, 2, 45, 0, 1999, }, - { "Krefeld7", 2, 2, 46, 0, 1999, }, - { "Dssd 9", 2, 2, 47, 0, 1999, }, - { "Dssd 2", 2, 2, 49, 0, 1999, }, - { "Langnf89", 2, 2, 52, 0, 1999, }, - { "Mettman2", 2, 2, 66, 1991, 1999, }, - { "Wupp. 23", 2, 2, 78, 0, 1999, }, - { "Dssd10Ba", 2, 2, 88, 1991, 1999, }, - { "Bursche.", 2, 2, 93, 1991, 0, }, - { "Aachen 9", 3, 2, 1, 0, 1999, }, - { "Krefld19", 3, 2, 2, 1991, 1999, }, - { "Mgl 60", 3, 2, 3, 0, 1999, }, - { "Mgl 3", 3, 2, 4, 1991, 1999, }, - { "Viersen4", 3, 2, 5, 1991, 1999, }, - { "Bedburg0", 3, 2, 8, 0, 1999, }, - { "Grev.Ka.", 3, 2, 11, 1991, 0, }, - { "Mgl.Rhy8", 3, 2, 13, 0, 1999, }, - { "Selfkant", 3, 2, 15, 0, 1999, }, - { "WillAnr0", 3, 2, 17, 0, 1999, }, - { "Wuersel2", 3, 2, 19, 0, 1999, }, - { "Mgl 8", 3, 2, 22, 0, 1999, }, - { "Huertgwd", 3, 2, 25, 1991, 0, }, - { "Langerw1", 3, 2, 26, 0, 1999, }, - { "Xanten 1", 3, 2, 27, 1991, 1999, }, - { "Wesel", 3, 2, 28, 1991, 0, }, - { "Kleve 7", 3, 2, 29, 1991, 1999, }, - { "Elten", 3, 2, 30, 1991, 0, }, - { "Geldern0", 3, 2, 31, 1991, 1999, }, - { "Moers 0", 3, 2, 32, 1991, 1999, }, - { "Viersen0", 3, 2, 33, 0, 1999, }, - { "Juechen1", 3, 2, 36, 0, 1999, }, - { "Nettetal", 3, 2, 40, 1991, 1999, }, - { "Viersen1", 3, 2, 42, 1991, 1999, }, - { "Schwalm9", 3, 2, 43, 1991, 1999, }, - { "Juechen4", 3, 2, 44, 1991, 1999, }, - { "MglRhey7", 3, 2, 45, 1991, 1999, }, - { "Stolbg.4", 3, 2, 46, 1991, 1999, }, - { "Stolbg.3", 3, 2, 47, 1991, 0, }, - { "Eschwei2", 3, 2, 48, 1991, 1999, }, - { "Alsdorf3", 3, 2, 49, 1991, 1999, }, - { "AaKornel", 3, 2, 50, 1991, 1999, }, - { "Aachn700", 3, 2, 51, 0, 1999, }, - { "Aachn120", 3, 2, 52, 1991, 1999, }, - { "Aachn500", 3, 2, 53, 1991, 1999, }, - { "Erkelenz", 3, 2, 54, 1991, 1999, }, - { "Schleidn", 3, 2, 56, 1991, 0, }, - { "Geilenk0", 3, 2, 57, 1991, 1999, }, - { "Heinsbg0", 3, 2, 58, 1991, 1999, }, - { "Juelich3", 3, 2, 59, 1991, 1999, }, - { "Simmerat", 3, 2, 61, 1991, 0, }, - { "Nettersh", 3, 2, 62, 1991, 0, }, - { "Kevelaer", 3, 2, 63, 0, 1999, }, - { "Straelen", 3, 2, 64, 1991, 1999, }, - { "NeukVluy", 3, 2, 65, 1991, 1999, }, - { "Bocholt0", 3, 2, 66, 1991, 0, }, - { "Kalkar 7", 3, 2, 67, 0, 1999, }, - { "Krefeld4", 3, 2, 69, 1991, 0, }, - { "Willich", 3, 2, 71, 1991, 0, }, - { "Wegberg", 3, 2, 77, 0, 1999, }, - { "Grev.br.", 3, 2, 79, 1991, 0, }, - { "HerzgRa2", 3, 2, 80, 0, 1999, }, - { "Kevela10", 3, 2, 81, 0, 1999, }, - { "Sonsbeck", 3, 2, 82, 0, 1999, }, - { "Mgl 401", 3, 2, 84, 0, 1999, }, - { "Aachen 1", 3, 2, 86, 1991, 1999, }, - { "Kempen 4", 3, 2, 87, 0, 1999, }, - { "Linnich1", 3, 2, 88, 0, 1999, }, - { "Goch 0", 3, 2, 90, 0, 1999, }, - { "Rheinbg2", 3, 2, 98, 0, 1999, }, - { "Aldenhov", 3, 2, 99, 0, 1999, }, - { "Dtmd3Bak", 4, 2, 1, 1991, 1999, }, - { "Gevelsb.", 4, 2, 12, 1991, 0, }, - { "Hagen 2", 4, 2, 13, 1991, 0, }, - { "Witten12", 4, 2, 14, 1991, 0, }, - { "Bochum 0", 4, 2, 17, 1991, 0, }, - { "Herne 1", 4, 2, 18, 1991, 0, }, - { "Holzwi.", 4, 2, 25, 1991, 0, }, - { "Cast.Ra.", 4, 2, 27, 1991, 0, }, - { "Dortm.10", 4, 2, 28, 1991, 0, }, - { "Lethma.7", 4, 2, 29, 1991, 0, }, - { "Witten10", 4, 2, 31, 1991, 0, }, - { "Luenen 0", 4, 2, 33, 1991, 0, }, - { "Boenen", 4, 2, 34, 1991, 0, }, - { "Iserlohn", 4, 2, 36, 1991, 0, }, - { "Menden11", 4, 2, 37, 1991, 0, }, - { "Kamen", 4, 2, 38, 1991, 0, }, - { "Werne", 4, 2, 39, 1991, 0, }, - { "Hamm", 4, 2, 40, 1991, 0, }, - { "Dtmd-Sc.", 4, 2, 49, 1991, 0, }, - { "Schwerte", 4, 2, 73, 1991, 0, }, - { "Recklhs.", 4, 2, 74, 1991, 0, }, - { "Datteln", 4, 2, 80, 1991, 0, }, - { "Wattensc", 4, 2, 83, 1991, 0, }, - { "Stiepel", 4, 2, 84, 1991, 0, }, - { "Altenbg0", 5, 2, 1, 0, 1999, }, - { "Lennest1", 5, 2, 2, 1991, 1999, }, - { "Attendo7", 5, 2, 3, 1991, 1999, }, - { "Marl 0", 5, 2, 4, 1991, 0, }, - { "NeheimH7", 5, 2, 5, 1991, 1999, }, - { "Muenst42", 5, 2, 6, 1991, 1999, }, - { "Marsberg", 5, 2, 7, 0, 1999, }, - { "Lippst.0", 5, 2, 8, 1991, 1999, }, - { "Roelvede", 5, 2, 9, 0, 1999, }, - { "Mesched7", 5, 2, 10, 0, 1999, }, - { "Hallenb7", 5, 2, 11, 0, 1999, }, - { "Soest 10", 5, 2, 12, 0, 1999, }, - { "Schalksm", 5, 2, 13, 0, 1999, }, - { "Olsberg7", 5, 2, 14, 0, 1999, }, - { "Ostbever", 5, 2, 15, 0, 1999, }, - { "Arnsberg", 5, 2, 16, 0, 1999, }, - { "Beckum 3", 5, 2, 17, 1991, 1999, }, - { "Sendenh", 5, 2, 18, 1991, 1999, }, - { "Altena 8", 5, 2, 19, 0, 1999, }, - { "Ahlen 0", 5, 2, 20, 0, 1999, }, - { "Luedinh2", 5, 2, 21, 1991, 1999, }, - { "Mesched1", 5, 2, 22, 1991, 1999, }, - { "Werl 0", 5, 2, 23, 1991, 1999, }, - { "Moehnese", 5, 2, 24, 1991, 1999, }, - { "SchmBoed", 5, 2, 25, 1991, 1999, }, - { "Winterbg", 5, 2, 26, 1991, 1999, }, - { "CastRaux", 5, 2, 27, 0, 1999, }, - { "MSNienbe", 5, 2, 28, 0, 1999, }, - { "Letmathe", 5, 2, 29, 0, 1999, }, - { "Lueden.2", 5, 2, 30, 1991, 1999, }, - { "Witten10", 5, 2, 31, 1991, 1999, }, - { "Meinerzh", 5, 2, 32, 1991, 1999, }, - { "Luenen 0", 5, 2, 33, 1991, 1999, }, - { "Plettenb", 5, 2, 34, 1991, 1999, }, - { "Werdohl7", 5, 2, 35, 1991, 1999, }, - { "Nottuln2", 5, 2, 36, 1991, 1999, }, - { "Telgte 0", 5, 2, 37, 1991, 1999, }, - { "Ruethen0", 5, 2, 38, 0, 1999, }, - { "Emsdettn", 5, 2, 39, 0, 1999, }, - { "OeldeStr", 5, 2, 40, 1991, 1999, }, - { "MSAlbach", 5, 2, 41, 1991, 1999, }, - { "Coesfeld", 5, 2, 42, 1991, 0, }, - { "Greven 0", 5, 2, 43, 1991, 1999, }, - { "Brechten", 5, 2, 44, 1991, 1999, }, - { "Dorlar 1", 5, 2, 45, 0, 1999, }, - { "Halver 6", 5, 2, 46, 0, 1999, }, - { "Herschd3", 5, 2, 47, 0, 1999, }, - { "Dtmd.230", 5, 2, 49, 0, 1999, }, - { "Aschebg2", 5, 2, 50, 0, 1999, }, - { "Warendf0", 5, 2, 51, 0, 1999, }, - { "Gevelsb7", 5, 2, 52, 0, 1999, }, - { "Duelmen0", 5, 2, 54, 0, 1999, }, - { "Sundern1", 5, 2, 55, 1991, 1999, }, - { "Bueren 1", 5, 2, 56, 1991, 1999, }, - { "Bril.Mes", 5, 2, 57, 1991, 1999, }, - { "Dtmd. 10", 5, 2, 58, 0, 1999, }, - { "Witten91", 5, 2, 59, 0, 1999, }, - { "Unna 3", 5, 2, 60, 0, 1999, }, - { "HagnDahl", 5, 2, 61, 0, 1999, }, - { "Haltern7", 5, 2, 62, 0, 1999, }, - { "Herdecke", 5, 2, 63, 0, 1999, }, - { "Boenen 0", 5, 2, 64, 0, 1999, }, - { "Holzwick", 5, 2, 65, 0, 1999, }, - { "Hamm 1", 5, 2, 66, 0, 1999, }, - { "Menden11", 5, 2, 67, 0, 1999, }, - { "Kamen 0", 5, 2, 68, 0, 1999, }, - { "Werne 0", 5, 2, 69, 0, 1999, }, - { "Waltrop1", 5, 2, 70, 0, 1999, }, - { "HammUent", 5, 2, 71, 0, 1999, }, - { "Hagen 2", 5, 2, 72, 0, 1999, }, - { "Schwert4", 5, 2, 73, 0, 1999, }, - { "Recklhs1", 5, 2, 74, 0, 1999, }, - { "Breckerf", 5, 2, 75, 0, 1999, }, - { "Balve 7", 5, 2, 76, 0, 1999, }, - { "Gevelsb5", 5, 2, 77, 0, 1999, }, - { "Dtmd. 85", 5, 2, 78, 0, 1999, }, - { "Iserlo13", 5, 2, 79, 0, 1999, }, - { "Datteln3", 5, 2, 80, 0, 1999, }, - { "Haltern2", 5, 2, 84, 0, 1999, }, - { "Hagen 9", 5, 2, 85, 0, 1999, }, - { "Witten12", 5, 2, 87, 0, 1999, }, - { "Schoepp.", 5, 2, 93, 1991, 0, }, - { "Herschd1", 5, 2, 94, 1991, 1999, }, - { "Marl 0", 5, 2, 96, 0, 1999, }, - { "Frechen0", 6, 2, 1, 0, 1999, }, - { "Kln35Mes", 6, 2, 2, 0, 1999, }, - { "BergGld4", 6, 2, 3, 0, 1999, }, - { "Niedkass", 6, 2, 4, 1991, 1999, }, - { "Kln 0", 6, 2, 5, 1991, 1999, }, - { "Kln 8 Ba", 6, 2, 6, 1991, 1999, }, - { "Bonn 460", 6, 2, 7, 0, 1999, }, - { "Kln 27", 6, 2, 8, 1991, 1999, }, - { "Merten 1", 6, 2, 9, 1991, 1999, }, - { "Frechen8", 6, 2, 10, 0, 1999, }, - { "KerpHorr", 6, 2, 11, 0, 1999, }, - { "Erftstad", 6, 2, 12, 1991, 1999, }, - { "Kln 34", 6, 2, 13, 0, 1999, }, - { "Pulheim0", 6, 2, 14, 1991, 1999, }, - { "KlnPrz50", 6, 2, 15, 1991, 1999, }, - { "Bergheim", 6, 2, 16, 1991, 1999, }, - { "Kln 860", 6, 2, 17, 0, 1999, }, - { "KwtObpl1", 6, 2, 18, 0, 1999, }, - { "Siegb.70", 6, 2, 19, 0, 1999, }, - { "Rommersk", 6, 2, 20, 1991, 0, }, - { "BergGld2", 6, 2, 21, 1991, 1999, }, - { "Kln 170", 6, 2, 22, 1991, 1999, }, - { "Kln 25", 6, 2, 23, 1991, 1999, }, - { "Kln 370", 6, 2, 24, 1991, 1999, }, - { "Kln 430", 6, 2, 25, 1991, 1999, }, - { "Kln 760", 6, 2, 26, 1991, 1999, }, - { "Kln 640", 6, 2, 27, 1991, 1999, }, - { "Kln 28", 6, 2, 28, 1991, 1999, }, - { "Bruehl99", 6, 2, 29, 1991, 1999, }, - { "KerpVill", 6, 2, 30, 0, 1999, }, - { "Kln 350", 6, 2, 31, 0, 1999, }, - { "Bonn 0", 6, 2, 33, 0, 1999, }, - { "Bonn 320", 6, 2, 34, 0, 1999, }, - { "Bonn 620", 6, 2, 35, 0, 1999, }, - { "Bonn 670", 6, 2, 36, 0, 1999, }, - { "Siegb.41", 6, 2, 37, 0, 1999, }, - { "Siegb.20", 6, 2, 38, 0, 1999, }, - { "Lohmar 2", 6, 2, 39, 0, 1999, }, - { "Siegb.0", 6, 2, 40, 0, 1999, }, - { "Lohmar 1", 6, 2, 41, 0, 1999, }, - { "Bonn 13", 6, 2, 42, 0, 1999, }, - { "Dueren30", 6, 2, 43, 0, 1999, }, - { "Heimbach", 6, 2, 44, 0, 1999, }, - { "Huertgw4", 6, 2, 45, 0, 1999, }, - { "KerpBuir", 6, 2, 46, 0, 1999, }, - { "Monschau", 6, 2, 47, 0, 1999, }, - { "Hennef 1", 6, 2, 48, 0, 1999, }, - { "Nideggen", 6, 2, 49, 0, 1999, }, - { "Zuelpich", 6, 2, 50, 0, 1999, }, - { "Rheinba2", 6, 2, 51, 0, 1999, }, - { "Euskir.4", 6, 2, 52, 0, 1999, }, - { "WeilersW", 6, 2, 53, 0, 1999, }, - { "BadMstEi", 6, 2, 54, 0, 1999, }, - { "Mechern4", 6, 2, 55, 0, 1999, }, - { "Schleid1", 6, 2, 56, 0, 1999, }, - { "KwtObpl0", 6, 2, 57, 0, 1999, }, - { "Noerveni", 6, 2, 58, 0, 1999, }, - { "Dormagn7", 6, 2, 60, 0, 1999, }, - { "Simmerat", 6, 2, 61, 0, 1999, }, - { "Nettersh", 6, 2, 62, 0, 1999, }, - { "SchlGem3", 6, 2, 63, 0, 1999, }, - { "Wermelsk", 6, 2, 64, 0, 1999, }, - { "Bursch.3", 6, 2, 65, 0, 1999, }, - { "Wesseli0", 6, 2, 66, 1991, 1999, }, - { "Huerth 0", 6, 2, 67, 1991, 1999, }, - { "Roesrat2", 6, 2, 68, 1991, 1999, }, - { "Bursch10", 6, 2, 69, 0, 1999, }, - { "Kln 23", 6, 2, 70, 1991, 1999, }, - { "Dormagen", 6, 2, 71, 0, 1999, }, - { "Bonn 2", 6, 2, 72, 0, 1999, }, - { "RommersK", 6, 2, 73, 0, 1999, }, - { "Bonn 630", 6, 2, 76, 0, 1999, }, - { "Bensberg", 6, 2, 78, 1991, 1999, }, - { "Frechen", 6, 2, 81, 1991, 0, }, - { "Leverk0", 6, 2, 91, 1991, 1999, }, - { "Overath5", 7, 2, 1, 1991, 1999, }, - { "Dierdorf", 7, 2, 2, 1991, 1999, }, - { "Koen./Ob", 7, 2, 3, 1991, 0, }, - { "Daun_4", 7, 2, 4, 1991, 1999, }, - { "Much 1", 7, 2, 6, 0, 1999, }, - { "Saffig10", 7, 2, 7, 1991, 1999, }, - { "GummBa40", 7, 2, 8, 0, 1999, }, - { "Asbach10", 7, 2, 9, 0, 1999, }, - { "Eitorf 2", 7, 2, 10, 0, 1999, }, - { "Windhgn", 7, 2, 11, 1991, 1999, }, - { "BdHonn80", 7, 2, 12, 1991, 1999, }, - { "Nuembr10", 7, 2, 13, 1991, 1999, }, - { "Kobl. 10", 7, 2, 14, 1991, 1999, }, - { "HoehrGre", 7, 2, 15, 1991, 1999, }, - { "Montab.3", 7, 2, 16, 0, 1999, }, - { "Vettels.", 7, 2, 17, 1991, 0, }, - { "Weibern2", 7, 2, 18, 1991, 1999, }, - { "BdMarie1", 7, 2, 19, 1991, 1999, }, - { "BdBertri", 7, 2, 20, 1991, 1999, }, - { "BlankeA5", 7, 2, 21, 0, 1999, }, - { "Wissen 2", 7, 2, 22, 0, 1999, }, - { "Betzdorf", 7, 2, 23, 1991, 1999, }, - { "Eschenb.", 7, 2, 24, 1991, 0, }, - { "Wendn186", 7, 2, 26, 0, 1999, }, - { "Puderb.3", 7, 2, 28, 0, 1999, }, - { "Kuerten3", 7, 2, 30, 1991, 1999, }, - { "BdHonn.0", 7, 2, 31, 1991, 1999, }, - { "Euskir.4", 7, 2, 32, 1991, 0, }, - { "Wipperf2", 7, 2, 33, 0, 1999, }, - { "Kuerten1", 7, 2, 34, 1991, 1999, }, - { "GummBa.0", 7, 2, 35, 0, 1999, }, - { "Bonn 670", 7, 2, 36, 1991, 0, }, - { "Windeck2", 7, 2, 37, 1991, 1999, }, - { "BdNeuena", 7, 2, 38, 1991, 1999, }, - { "Linz 4", 7, 2, 39, 0, 1999, }, - { "Lennestd", 7, 2, 40, 1991, 0, }, - { "Kreuztal", 7, 2, 41, 1991, 1999, }, - { "Bonn 13", 7, 2, 42, 1991, 0, }, - { "BdBerleb", 7, 2, 43, 1991, 1999, }, - { "BdLaasph", 7, 2, 44, 0, 1999, }, - { "Nethphen", 7, 2, 45, 0, 1999, }, - { "Olpe 0", 7, 2, 47, 0, 1999, }, - { "DrolshgB", 7, 2, 48, 0, 1999, }, - { "Hilchenb", 7, 2, 49, 0, 1999, }, - { "Freudnbg", 7, 2, 50, 0, 1999, }, - { "Burbach3", 7, 2, 51, 0, 1999, }, - { "WaldbrBd", 7, 2, 52, 0, 1999, }, - { "EllenzP2", 7, 2, 53, 0, 1999, }, - { "Insul 2", 7, 2, 54, 0, 1999, }, - { "Linz 2", 7, 2, 55, 0, 1999, }, - { "WildbgH1", 7, 2, 56, 0, 1999, }, - { "Kelberg3", 7, 2, 57, 0, 1999, }, - { "Kesseli1", 7, 2, 58, 0, 1999, }, - { "Eckenh.3", 7, 2, 59, 0, 1999, }, - { "Rengsdf4", 7, 2, 60, 0, 1999, }, - { "Mendig 3", 7, 2, 61, 0, 1999, }, - { "Cochem 1", 7, 2, 62, 0, 1999, }, - { "Mayen 3", 7, 2, 63, 0, 1999, }, - { "Neuwied2", 7, 2, 64, 0, 1999, }, - { "Hachenbg", 7, 2, 65, 0, 1999, }, - { "Westerbg", 7, 2, 66, 0, 1999, }, - { "Asbach 5", 7, 2, 67, 0, 1999, }, - { "Loef 1", 7, 2, 68, 0, 1999, }, - { "Engelsk6", 7, 2, 69, 0, 1999, }, - { "Altenki0", 7, 2, 70, 0, 1999, }, - { "Siegen15", 7, 2, 71, 0, 1999, }, - { "Bonn 2 K", 7, 2, 72, 1991, 0, }, - { "NeunkSe1", 7, 2, 73, 0, 1999, }, - { "Ochtend2", 7, 2, 74, 0, 1999, }, - { "Weilers.", 7, 2, 77, 1991, 0, }, - { "Bad Ems1", 7, 2, 79, 0, 1999, }, - { "Marienh1", 7, 2, 80, 0, 1999, }, - { "GummBa16", 7, 2, 82, 0, 1999, }, - { "FlammerF", 7, 2, 83, 0, 1999, }, - { "Waldbro1", 7, 2, 84, 0, 1999, }, - { "Bendorf1", 7, 2, 85, 0, 1999, }, - { "Engelsk3", 7, 2, 86, 0, 1999, }, - { "Selters2", 7, 2, 87, 0, 1999, }, - { "Adenau 7", 7, 2, 88, 0, 1999, }, - { "KaisEsch", 7, 2, 89, 0, 1999, }, - { "Nassau 1", 7, 2, 90, 0, 1999, }, - { "BdMarie2", 7, 2, 91, 0, 1999, }, - { "Antweil1", 7, 2, 92, 0, 1999, }, - { "Ruppich3", 7, 2, 93, 0, 1999, }, - { "Lindlar1", 7, 2, 95, 0, 1999, }, - { "Siegen 1", 7, 2, 96, 1991, 1999, }, - { "GummBa13", 7, 2, 97, 1991, 1999, }, - { "Lohmar 1", 7, 2, 98, 1991, 0, }, - { "Rheinbr0", 7, 2, 99, 0, 1999, }, - { "Raegelin", 1, 3, 1, 1991, 1999, }, - { "Rostock", 1, 3, 2, 1991, 0, }, - { "Fuerstnb", 1, 3, 3, 1991, 1999, }, - { "Massow", 1, 3, 4, 1991, 1999, }, - { "Beeskow", 1, 3, 5, 0, 1999, }, - { "Finowfur", 1, 3, 6, 0, 1999, }, - { "Bernau 6", 1, 3, 7, 0, 1999, }, - { "Ziesar 0", 1, 3, 8, 1991, 1999, }, - { "Wittenbg", 1, 3, 9, 1991, 1999, }, - { "WerderHv", 1, 3, 10, 1991, 1999, }, - { "Seelow 0", 1, 3, 11, 1991, 1999, }, - { "Tresebur", 1, 3, 12, 0, 1999, }, - { "Briesen", 1, 3, 13, 0, 1999, }, - { "Perlebg5", 1, 3, 14, 0, 1999, }, - { "Mnchebg4", 1, 3, 15, 0, 1999, }, - { "Herzfeld", 1, 3, 16, 0, 1999, }, - { "Storkow4", 1, 3, 17, 0, 1999, }, - { "Neubra14", 1, 3, 18, 0, 1999, }, - { "Treuenbr", 1, 3, 19, 0, 1999, }, - { "Prenzlau", 1, 3, 20, 0, 1999, }, - { "Pasewalk", 1, 3, 22, 0, 1999, }, - { "NaumbgRi", 1, 3, 23, 0, 1999, }, - { "Ratheno4", 1, 3, 24, 0, 1999, }, - { "BApitzSt", 1, 3, 26, 0, 1999, }, - { "Jaegerst", 1, 3, 27, 0, 1999, }, - { "Templin2", 1, 3, 28, 0, 1999, }, - { "Luckenw2", 1, 3, 29, 0, 1999, }, - { "Lehnin 0", 1, 3, 30, 0, 1999, }, - { "Frankf10", 1, 3, 31, 0, 1999, }, - { "Michendf", 1, 3, 32, 0, 1999, }, - { "Trebbin2", 1, 3, 33, 0, 1999, }, - { "Gramzow0", 1, 3, 35, 0, 1999, }, - { "BdFreien", 1, 3, 36, 0, 1999, }, - { "Falknhg4", 1, 3, 37, 0, 1999, }, - { "Fuerstw7", 1, 3, 38, 0, 1999, }, - { "Angermue", 1, 3, 39, 0, 1999, }, - { "Wittsto5", 1, 3, 40, 0, 1999, }, - { "Dambeck2", 1, 3, 41, 0, 1999, }, - { "Neuzelle", 1, 3, 42, 0, 1999, }, - { "Raben 1", 1, 3, 43, 0, 1999, }, - { "Toepchin", 1, 3, 44, 0, 1999, }, - { "Brandenb", 1, 3, 45, 0, 1999, }, - { "Jueterbo", 1, 3, 46, 0, 1999, }, - { "Krahne", 1, 3, 47, 0, 1999, }, - { "Lieberos", 1, 3, 48, 0, 1999, }, - { "Wiesenbu", 1, 3, 49, 0, 1999, }, - { "Mirow 1", 1, 3, 50, 0, 1999, }, - { "Rhinow 1", 1, 3, 51, 0, 1999, }, - { "Rheinsb3", 1, 3, 52, 0, 1999, }, - { "Petkus 3", 1, 3, 53, 0, 1999, }, - { "Blanken1", 1, 3, 54, 0, 1999, }, - { "Neustrel", 1, 3, 55, 0, 1999, }, - { "Greiffen", 1, 3, 57, 0, 1999, }, - { "Pritzwal", 1, 3, 58, 0, 1999, }, - { "Schwedt6", 1, 3, 59, 0, 1999, }, - { "Schmoell", 1, 3, 62, 0, 1999, }, - { "Woldegk4", 1, 3, 65, 0, 1999, }, - { "Neurupp6", 1, 3, 66, 0, 1999, }, - { "Belzig 2", 1, 3, 67, 0, 1999, }, - { "Gransee1", 1, 3, 69, 0, 1999, }, - { "Kyritz 4", 1, 3, 70, 0, 1999, }, - { "GrDoelln", 1, 3, 71, 0, 1999, }, - { "Premnitz", 1, 3, 72, 0, 1999, }, - { "Gloewen2", 1, 3, 73, 0, 1999, }, - { "Luebben2", 1, 3, 74, 0, 1999, }, - { "Bestense", 1, 3, 76, 0, 1999, }, - { "Pausin 1", 1, 3, 77, 0, 1999, }, - { "Golssen0", 1, 3, 78, 0, 1999, }, - { "Luebenau", 1, 3, 79, 0, 1999, }, - { "AltMahls", 1, 3, 80, 0, 1999, }, - { "Eichhors", 1, 3, 81, 0, 1999, }, - { "Muehlnbk", 1, 3, 83, 0, 1999, }, - { "Hennings", 1, 3, 84, 0, 1999, }, - { "Ludwigsf", 1, 3, 86, 0, 1999, }, - { "Ruedersd", 1, 3, 87, 0, 1999, }, - { "Strausbg", 1, 3, 88, 0, 1999, }, - { "Zossen", 1, 3, 89, 0, 1999, }, - { "Mahlow 4", 1, 3, 90, 0, 1999, }, - { "Bernau 3", 1, 3, 91, 0, 1999, }, - { "Oranienb", 1, 3, 92, 0, 1999, }, - { "Falkense", 1, 3, 93, 0, 1999, }, - { "Liebenwa", 1, 3, 94, 0, 1999, }, - { "Eberswal", 1, 3, 96, 0, 1999, }, - { "Erkner 5", 1, 3, 97, 0, 1999, }, - { "KWusterh", 1, 3, 98, 0, 1999, }, - { "Fichtenw", 1, 3, 99, 0, 1999, }, - { "B23 Bake", 2, 3, 1, 1991, 1999, }, - { "Schoenho", 2, 3, 2, 1991, 1999, }, - { "Ruegener", 2, 3, 3, 1991, 1999, }, - { "Habersaa", 2, 3, 4, 1991, 1999, }, - { "Stresema", 2, 3, 5, 1991, 1999, }, - { "Wilkestr", 2, 3, 6, 1991, 1999, }, - { "Skalitze", 2, 3, 7, 1991, 1999, }, - { "Luederit", 2, 3, 8, 1991, 1999, }, - { "Erasmuss", 2, 3, 9, 1991, 1999, }, - { "Winterfe", 2, 3, 10, 1991, 1999, }, - { "Wernerwe", 2, 3, 11, 1991, 1999, }, - { "KMarxStr", 2, 3, 12, 1991, 1999, }, - { "Oranienb", 2, 3, 13, 1991, 1999, }, - { "AugustVi", 2, 3, 14, 1991, 1999, }, - { "Rathauss", 2, 3, 15, 1991, 1999, }, - { "Schmarge", 2, 3, 16, 1991, 1999, }, - { "Tempelho", 2, 3, 17, 1991, 1999, }, - { "Hanneman", 2, 3, 18, 1991, 1999, }, - { "Streitst", 2, 3, 19, 1991, 1999, }, - { "Kettinge", 2, 3, 20, 1991, 1999, }, - { "Forststr", 2, 3, 21, 1991, 1999, }, - { "Hindenbu", 2, 3, 22, 1991, 1999, }, - { "Lobeckst", 2, 3, 23, 1991, 1999, }, - { "AltStral", 2, 3, 24, 0, 1999, }, - { "Schaefer", 2, 3, 25, 0, 1999, }, - { "Elsastr", 2, 3, 28, 0, 1999, }, - { "FranzJac", 2, 3, 29, 1991, 1999, }, - { "Schnellr", 2, 3, 30, 0, 1999, }, - { "KoepeniA", 2, 3, 31, 0, 1999, }, - { "Amanlisw", 2, 3, 32, 0, 1999, }, - { "BitterSt", 2, 3, 33, 0, 1999, }, - { "ErnstBar", 2, 3, 34, 0, 1999, }, - { "Flankens", 2, 3, 35, 0, 1999, }, - { "LilliHen", 2, 3, 36, 1991, 1999, }, - { "Buchholz", 2, 3, 37, 0, 1999, }, - { "RudowChs", 2, 3, 38, 0, 1999, }, - { "OGeschke", 2, 3, 39, 0, 1999, }, - { "Rochstr", 2, 3, 40, 1991, 1999, }, - { "EReuterP", 2, 3, 41, 0, 1999, }, - { "Birkholz", 2, 3, 44, 1991, 0, }, - { "Schoenef", 2, 3, 48, 0, 1999, }, - { "Coppistr", 2, 3, 49, 1991, 1999, }, - { "Prenzlau", 2, 3, 57, 1991, 1999, }, - { "Lieberma", 2, 3, 58, 1991, 1999, }, - { "Herzberg", 2, 3, 59, 1991, 1999, }, - { "Masurena", 2, 3, 60, 1991, 1999, }, - { "Scholzpl", 2, 3, 61, 1991, 1999, }, - { "Flotowst", 2, 3, 64, 0, 1999, }, - { "Breitest", 2, 3, 65, 0, 1999, }, - { "KMarxAle", 2, 3, 70, 0, 1999, }, - { "AVUS", 2, 3, 95, 0, 1999, }, - { "Kaatsch1", 2, 3, 97, 1991, 1999, }, - { "Kaatsch2", 2, 3, 98, 1991, 1999, }, - { "B.Schaef", 2, 3, 99, 1991, 0, }, - { "Teicha 2", 3, 3, 1, 1991, 1999, }, - { "Greifenh", 3, 3, 2, 0, 1999, }, - { "Mrkranst", 3, 3, 4, 0, 1999, }, - { "Groitsch", 3, 3, 6, 0, 1999, }, - { "Graefenh", 3, 3, 7, 0, 1999, }, - { "Liebertw", 3, 3, 8, 0, 1999, }, - { "Torgau 4", 3, 3, 9, 0, 1999, }, - { "Bitterf", 3, 3, 10, 0, 1999, }, - { "Oschatz", 3, 3, 11, 0, 1999, }, - { "L-Sttz", 3, 3, 12, 0, 1999, }, - { "Halle 15", 3, 3, 13, 0, 1999, }, - { "Grimma 6", 3, 3, 14, 0, 1999, }, - { "Weissenf", 3, 3, 15, 0, 1999, }, - { "L-Uni", 3, 3, 16, 0, 1999, }, - { "L-Doelz", 3, 3, 17, 0, 1999, }, - { "L-Gaschw", 3, 3, 18, 0, 1999, }, - { "L-Lausen", 3, 3, 19, 0, 1999, }, - { "L-Seehsn", 3, 3, 20, 0, 1999, }, - { "L-Schkeu", 3, 3, 21, 0, 1999, }, - { "Koethen8", 3, 3, 22, 0, 1999, }, - { "Brandis2", 3, 3, 23, 0, 1999, }, - { "Delitzs1", 3, 3, 24, 0, 1999, }, - { "L-Holz", 3, 3, 25, 0, 1999, }, - { "Nebra 3", 3, 3, 26, 0, 1999, }, - { "Zeitz 9", 3, 3, 27, 0, 1999, }, - { "Querfurt", 3, 3, 28, 0, 1999, }, - { "Cobbelsd", 3, 3, 36, 0, 1999, }, - { "L-Stahm", 3, 3, 37, 0, 1999, }, - { "Altenbrg", 3, 3, 38, 0, 1999, }, - { "L-Connew", 3, 3, 40, 0, 1999, }, - { "L-Taucha", 3, 3, 41, 0, 1999, }, - { "L-Eutri", 3, 3, 42, 0, 1999, }, - { "L-Schoen", 3, 3, 43, 0, 1999, }, - { "Dommitz1", 3, 3, 44, 0, 1999, }, - { "L-Adler", 3, 3, 45, 0, 1999, }, - { "Naumburg", 3, 3, 46, 0, 1999, }, - { "L-Gohlis", 3, 3, 47, 0, 1999, }, - { "H-Seeben", 3, 3, 48, 0, 1999, }, - { "Sangerh", 3, 3, 49, 0, 1999, }, - { "H-Bruckd", 3, 3, 50, 0, 1999, }, - { "Colditz", 3, 3, 52, 0, 1999, }, - { "Hartha 1", 3, 3, 56, 0, 1999, }, - { "Dessau S", 3, 3, 58, 0, 1999, }, - { "Eisleben", 3, 3, 59, 0, 1999, }, - { "H-Teutsc", 3, 3, 60, 0, 1999, }, - { "H-Silber", 3, 3, 61, 0, 1999, }, - { "H-Neu", 3, 3, 62, 0, 1999, }, - { "Mersebrg", 3, 3, 63, 0, 1999, }, - { "Schmoell", 3, 3, 70, 0, 1999, }, - { "Eilenbrg", 3, 3, 71, 0, 1999, }, - { "Hayn 2", 3, 3, 72, 0, 1999, }, - { "Dessau 1", 3, 3, 73, 0, 1999, }, - { "Borna 0", 3, 3, 74, 0, 1999, }, - { "Belgern", 3, 3, 75, 0, 1999, }, - { "Hettstdt", 3, 3, 76, 0, 1999, }, - { "BDueben5", 3, 3, 77, 0, 1999, }, - { "H-Peiss", 3, 3, 78, 0, 1999, }, - { "H-Heide", 3, 3, 79, 0, 1999, }, - { "Oelzsch1", 3, 3, 80, 0, 1999, }, - { "Doebeln", 3, 3, 81, 0, 1999, }, - { "Coswig A", 3, 3, 82, 0, 1999, }, - { "Mockreh", 3, 3, 83, 0, 1999, }, - { "L-Leutsc", 3, 3, 84, 0, 1999, }, - { "Hohenmoe", 3, 3, 85, 0, 1999, }, - { "Wittenbg", 3, 3, 86, 0, 1999, }, - { "BdDuerrn", 3, 3, 87, 0, 1999, }, - { "Kropstd", 3, 3, 88, 0, 1999, }, - { "L-Markle", 3, 3, 89, 0, 1999, }, - { "D-Gompi", 4, 3, 1, 1991, 1999, }, - { "Crinitz", 4, 3, 2, 0, 1999, }, - { "D-Dachs", 4, 3, 3, 0, 1999, }, - { "Weisswas", 4, 3, 4, 0, 1999, }, - { "Drebkau1", 4, 3, 5, 0, 1999, }, - { "Senftenb", 4, 3, 7, 0, 1999, }, - { "Radeburg", 4, 3, 8, 0, 1999, }, - { "Meissen5", 4, 3, 9, 0, 1999, }, - { "Pirna 7", 4, 3, 10, 0, 1999, }, - { "Koenigsw", 4, 3, 11, 0, 1999, }, - { "D-Radeb", 4, 3, 12, 0, 1999, }, - { "D-Postpl", 4, 3, 13, 0, 1999, }, - { "Pulsnitz", 4, 3, 14, 0, 1999, }, - { "Loebau 5", 4, 3, 15, 0, 1999, }, - { "Neukirch", 4, 3, 16, 0, 1999, }, - { "Nst-Ung", 4, 3, 17, 0, 1999, }, - { "Goerlitz", 4, 3, 18, 0, 1999, }, - { "Zittau 5", 4, 3, 19, 0, 1999, }, - { "Altenbg", 4, 3, 20, 0, 1999, }, - { "Riesa 4", 4, 3, 21, 0, 1999, }, - { "Burkau 2", 4, 3, 22, 0, 1999, }, - { "D-Goenns", 4, 3, 23, 0, 1999, }, - { "Jessen 2", 4, 3, 24, 0, 1999, }, - { "Dippold", 4, 3, 25, 0, 1999, }, - { "D-Heiden", 4, 3, 26, 0, 1999, }, - { "Hoyersw", 4, 3, 27, 0, 1999, }, - { "D-Goppel", 4, 3, 28, 0, 1999, }, - { "D-Dorfh", 4, 3, 29, 0, 1999, }, - { "D-Stries", 4, 3, 30, 0, 1999, }, - { "Elsterw5", 4, 3, 31, 0, 1999, }, - { "Sprembg", 4, 3, 33, 0, 1999, }, - { "D-Klotzs", 4, 3, 34, 0, 1999, }, - { "Herzberg", 4, 3, 35, 0, 1999, }, - { "D-Prohli", 4, 3, 36, 0, 1999, }, - { "Niesky 4", 4, 3, 37, 0, 1999, }, - { "D-Neust", 4, 3, 39, 0, 1999, }, - { "Burkhard", 4, 3, 40, 0, 1999, }, - { "Guben 2", 4, 3, 41, 0, 1999, }, - { "Bautzen", 4, 3, 42, 0, 1999, }, - { "BdSchand", 4, 3, 43, 0, 1999, }, - { "Forst 2", 4, 3, 44, 0, 1999, }, - { "Bischofw", 4, 3, 45, 0, 1999, }, - { "Cottbus8", 4, 3, 46, 0, 1999, }, - { "Ortrand", 4, 3, 47, 0, 1999, }, - { "Tharandt", 4, 3, 48, 0, 1999, }, - { "Drachhau", 4, 3, 49, 0, 1999, }, - { "Kamenz 5", 4, 3, 51, 0, 1999, }, - { "Grossenh", 4, 3, 52, 0, 1999, }, - { "Lommatz", 4, 3, 54, 0, 1999, }, - { "Pirna 5", 4, 3, 55, 0, 1999, }, - { "Glashuet", 4, 3, 56, 0, 1999, }, - { "Coswig 4", 4, 3, 57, 0, 1999, }, - { "Wilsdruf", 4, 3, 59, 0, 1999, }, - { "Finster3", 4, 3, 60, 0, 1999, }, - { "Neugersd", 4, 3, 61, 0, 1999, }, - { "Uhyst 1", 4, 3, 64, 0, 1999, }, - { "Pulsnit6", 4, 3, 66, 0, 1999, }, - { "Doberlug", 4, 3, 88, 0, 1999, }, - { "Klettb", 5, 3, 1, 1991, 1999, }, - { "Grossfa1", 5, 3, 2, 1991, 1999, }, - { "Zella-Me", 5, 3, 3, 1991, 1999, }, - { "Juechsen", 5, 3, 4, 1991, 1999, }, - { "Grossbr", 5, 3, 5, 1991, 1999, }, - { "Eisenb 6", 5, 3, 6, 0, 1999, }, - { "Schleusi", 5, 3, 7, 0, 1999, }, - { "Eisenbg4", 5, 3, 8, 0, 1999, }, - { "Gera 11", 5, 3, 9, 0, 1999, }, - { "H.Reuth", 5, 3, 10, 0, 1999, }, - { "Jena 5", 5, 3, 11, 0, 1999, }, - { "N-Kleina", 5, 3, 12, 0, 1999, }, - { "Saalburg", 5, 3, 13, 0, 1999, }, - { "Jena 6", 5, 3, 14, 0, 1999, }, - { "Ruhla 4", 5, 3, 15, 0, 1999, }, - { "Creuzbrg", 5, 3, 16, 0, 1999, }, - { "Nordhsn", 5, 3, 17, 0, 1999, }, - { "Camburg", 5, 3, 18, 0, 1999, }, - { "BdFranke", 5, 3, 19, 0, 1999, }, - { "Gera 13", 5, 3, 20, 0, 1999, }, - { "Sondersh", 5, 3, 21, 0, 1999, }, - { "Hermsdf", 5, 3, 22, 0, 1999, }, - { "Weimar14", 5, 3, 23, 0, 1999, }, - { "E-Schwer", 5, 3, 24, 0, 1999, }, - { "Arnsger", 5, 3, 25, 0, 1999, }, - { "Arnstadt", 5, 3, 26, 0, 1999, }, - { "Suhl 2", 5, 3, 27, 0, 1999, }, - { "B Koesen", 5, 3, 29, 0, 1999, }, - { "Hildburg", 5, 3, 30, 0, 1999, }, - { "Ilmenau", 5, 3, 31, 0, 1999, }, - { "E-Flug", 5, 3, 32, 0, 1999, }, - { "E-Fuchs", 5, 3, 33, 0, 1999, }, - { "E-Andrea", 5, 3, 34, 0, 1999, }, - { "E-Chami", 5, 3, 35, 0, 1999, }, - { "NeuhausR", 5, 3, 36, 0, 1999, }, - { "Meininge", 5, 3, 37, 0, 1999, }, - { "E-FZA", 5, 3, 38, 0, 1999, }, - { "E-EVST 4", 5, 3, 39, 0, 1999, }, - { "Muehlhsn", 5, 3, 40, 0, 1999, }, - { "Blankenh", 5, 3, 41, 0, 1999, }, - { "Schmalka", 5, 3, 42, 0, 1999, }, - { "Heuthen", 5, 3, 43, 0, 1999, }, - { "Kaltenn", 5, 3, 44, 0, 1999, }, - { "Berga 1", 5, 3, 45, 0, 1999, }, - { "Oberhof", 5, 3, 46, 0, 1999, }, - { "Poessn", 5, 3, 47, 0, 1999, }, - { "Apolda 2", 5, 3, 48, 0, 1999, }, - { "BdLaSalz", 5, 3, 49, 0, 1999, }, - { "Soemmerd", 5, 3, 50, 0, 1999, }, - { "Triebes", 5, 3, 51, 0, 1999, }, - { "Lobenst", 5, 3, 52, 0, 1999, }, - { "Rudolst", 5, 3, 53, 0, 1999, }, - { "Schleiz", 5, 3, 54, 0, 1999, }, - { "Stadtrod", 5, 3, 55, 0, 1999, }, - { "Wernshsn", 5, 3, 56, 0, 1999, }, - { "Steinb-H", 5, 3, 58, 0, 1999, }, - { "Geisa 3", 5, 3, 59, 0, 1999, }, - { "Bleiche7", 5, 3, 60, 0, 1999, }, - { "Inselsbg", 5, 3, 61, 0, 1999, }, - { "Steinach", 5, 3, 62, 0, 1999, }, - { "Stadtilm", 5, 3, 63, 0, 1999, }, - { "Waltersh", 5, 3, 65, 0, 1999, }, - { "Gotha 6", 5, 3, 66, 0, 1999, }, - { "Eisenach", 5, 3, 67, 0, 1999, }, - { "Kahla 1", 5, 3, 68, 0, 1999, }, - { "Heiligst", 5, 3, 69, 0, 1999, }, - { "Thimmend", 5, 3, 70, 0, 1999, }, - { "Buttelst", 5, 3, 71, 0, 1999, }, - { "Koenigse", 5, 3, 72, 0, 1999, }, - { "Erfurt30", 5, 3, 73, 0, 1999, }, - { "Schoenbr", 5, 3, 74, 0, 1999, }, - { "Kindelbr", 5, 3, 75, 0, 1999, }, - { "Schlothe", 5, 3, 79, 0, 1999, }, - { "Bischofs", 5, 3, 91, 0, 1999, }, - { "Ludwigst", 5, 3, 92, 0, 1999, }, - { "Unsleben", 5, 3, 93, 0, 1999, }, - { "M-Sudenb", 6, 3, 1, 0, 1999, }, - { "M-Cracau", 6, 3, 2, 0, 1999, }, - { "M-Neust", 6, 3, 3, 0, 1999, }, - { "M-Bied", 6, 3, 4, 0, 1999, }, - { "M-Olvens", 6, 3, 5, 0, 1999, }, - { "M-Buckau", 6, 3, 6, 0, 1999, }, - { "Moeser 1", 6, 3, 7, 0, 1999, }, - { "M-Mitte", 6, 3, 8, 0, 1999, }, - { "M-Schoen", 6, 3, 9, 0, 1999, }, - { "Leitzkau", 6, 3, 10, 0, 1999, }, - { "Stendal", 6, 3, 11, 0, 1999, }, - { "Haldensl", 6, 3, 12, 0, 1999, }, - { "Oschersl", 6, 3, 13, 0, 1999, }, - { "Werniger", 6, 3, 14, 0, 1999, }, - { "Halberst", 6, 3, 15, 0, 1999, }, - { "Erxleben", 6, 3, 16, 0, 1999, }, - { "Altengra", 6, 3, 17, 0, 1999, }, - { "Genthin", 6, 3, 18, 0, 1999, }, - { "Burg 0", 6, 3, 19, 0, 1999, }, - { "Lindau A", 6, 3, 20, 0, 1999, }, - { "Kamern 2", 6, 3, 21, 0, 1999, }, - { "Niedernd", 6, 3, 22, 0, 1999, }, - { "Egeln", 6, 3, 23, 0, 1999, }, - { "Burg 5", 6, 3, 24, 0, 1999, }, - { "Fleetm 1", 6, 3, 25, 0, 1999, }, - { "Dolle 1", 6, 3, 26, 0, 1999, }, - { "Osterbg", 6, 3, 27, 0, 1999, }, - { "Frose", 6, 3, 28, 0, 1999, }, - { "Harzger", 6, 3, 29, 0, 1999, }, - { "Koennern", 6, 3, 30, 0, 1999, }, - { "Elbinger", 6, 3, 31, 0, 1999, }, - { "Wanzlebe", 6, 3, 32, 0, 1999, }, - { "Moorsleb", 6, 3, 33, 0, 1999, }, - { "Tangerm", 6, 3, 34, 0, 1999, }, - { "Bernburg", 6, 3, 35, 0, 1999, }, - { "Salzwdel", 6, 3, 36, 0, 1999, }, - { "Zerbst 4", 6, 3, 39, 0, 1999, }, - { "Aschersl", 6, 3, 48, 0, 1999, }, - { "Tangerh", 6, 3, 49, 0, 1999, }, - { "Kloetze", 6, 3, 52, 0, 1999, }, - { "Mieste", 6, 3, 55, 0, 1999, }, - { "Thale", 6, 3, 88, 0, 1999, }, - { "Seehsn", 6, 3, 93, 0, 1999, }, - { "Blankenb", 6, 3, 95, 0, 1999, }, - { "Gardel", 6, 3, 96, 0, 1999, }, - { "Gernrode", 6, 3, 97, 0, 1999, }, - { "Hasself", 6, 3, 98, 0, 1999, }, - { "Baerenst", 7, 3, 1, 0, 1999, }, - { "Auerbach", 7, 3, 2, 0, 1999, }, - { "BdElster", 7, 3, 3, 0, 1999, }, - { "Marienbg", 7, 3, 4, 0, 1999, }, - { "C-Toten", 7, 3, 5, 0, 1999, }, - { "Reichenb", 7, 3, 6, 0, 1999, }, - { "Bergen 1", 7, 3, 7, 0, 1999, }, - { "Rochlitz", 7, 3, 8, 0, 1999, }, - { "C-Reich", 7, 3, 9, 0, 1999, }, - { "Frankenb", 7, 3, 10, 0, 1999, }, - { "Ebersbru", 7, 3, 11, 0, 1999, }, - { "Schwarzb", 7, 3, 12, 0, 1999, }, - { "Freiberg", 7, 3, 13, 0, 1999, }, - { "Frauenst", 7, 3, 14, 0, 1999, }, - { "Glauchau", 7, 3, 15, 0, 1999, }, - { "Plauen", 7, 3, 16, 0, 1999, }, - { "Werdau", 7, 3, 17, 0, 1999, }, - { "Mittweid", 7, 3, 18, 0, 1999, }, - { "Zschopau", 7, 3, 19, 0, 1999, }, - { "C-BKH", 7, 3, 20, 0, 1999, }, - { "C-Hecker", 7, 3, 21, 0, 1999, }, - { "C-Landr", 7, 3, 22, 0, 1999, }, - { "Nossen 5", 7, 3, 23, 0, 1999, }, - { "C-Leuker", 7, 3, 24, 0, 1999, }, - { "C-Numer", 7, 3, 25, 0, 1999, }, - { "Hainich1", 7, 3, 26, 0, 1999, }, - { "Zwoenitz", 7, 3, 27, 0, 1999, }, - { "Zwickau", 7, 3, 28, 0, 1999, }, - { "C-28Usti", 7, 3, 29, 0, 1999, }, - { "Floeha 4", 7, 3, 30, 0, 1999, }, - { "Crimmi", 7, 3, 31, 0, 1999, }, - { "Eibenst", 7, 3, 32, 0, 1999, }, - { "C-Center", 7, 3, 33, 0, 1999, }, - { "Olbernh", 7, 3, 35, 0, 1999, }, - { "Hartenst", 7, 3, 36, 0, 1999, }, - { "Greiz 2", 7, 3, 37, 0, 1999, }, - { "Penig 2", 7, 3, 38, 0, 1999, }, - { "Thalheim", 7, 3, 39, 0, 1999, }, - { "Reinfeld", 1, 4, 3, 1991, 1999, }, - { "Hemmoor1", 1, 4, 4, 1991, 0, }, - { "Cuxhaven", 1, 4, 5, 1991, 0, }, - { "Bremen38", 1, 4, 6, 1991, 0, }, - { "VerdenWa", 1, 4, 7, 1991, 0, }, - { "Hoya 1", 1, 4, 8, 1991, 0, }, - { "Gudow 10", 1, 4, 9, 1991, 1999, }, - { "Travemue", 1, 4, 10, 1991, 1999, }, - { "Kiel 2", 1, 4, 11, 1991, 1999, }, - { "Fleckeby", 1, 4, 12, 1991, 0, }, - { "Vechta L", 1, 4, 14, 1991, 0, }, - { "Jever 0", 1, 4, 15, 1991, 0, }, - { "Rendsbur", 1, 4, 17, 1991, 1999, }, - { "Nortorf4", 1, 4, 18, 0, 1999, }, - { "Freienwi", 1, 4, 19, 1991, 1999, }, - { "Westerld", 1, 4, 20, 1991, 1999, }, - { "Bremerh.", 1, 4, 21, 1991, 0, }, - { "Heide 2", 1, 4, 22, 1991, 1999, }, - { "Henstedt", 1, 4, 23, 1991, 1999, }, - { "Bredsted", 1, 4, 24, 1991, 1999, }, - { "Leer 1", 1, 4, 25, 1991, 0, }, - { "Krum.Gr.", 1, 4, 26, 1991, 0, }, - { "Hamberg.", 1, 4, 28, 1991, 0, }, - { "Bassum 3", 1, 4, 29, 1991, 0, }, - { "Brunsbue", 1, 4, 30, 1991, 1999, }, - { "Luebeck2", 1, 4, 31, 1991, 1999, }, - { "Luebeck4", 1, 4, 32, 0, 1999, }, - { "Itzehoe2", 1, 4, 36, 0, 1999, }, - { "Findorff", 1, 4, 37, 1991, 0, }, - { "Ritterhu", 1, 4, 38, 1991, 0, }, - { "Delmenho", 1, 4, 39, 1991, 0, }, - { "Glueckst", 1, 4, 40, 1991, 1999, }, - { "Weyhe 0", 1, 4, 41, 1991, 0, }, - { "Tenever", 1, 4, 42, 1991, 0, }, - { "Lilienth", 1, 4, 43, 1991, 0, }, - { "Ploen 2", 1, 4, 44, 0, 1999, }, - { "Hude 0", 1, 4, 45, 1991, 0, }, - { "Fehmarn1", 1, 4, 46, 0, 1999, }, - { "Oldenbu1", 1, 4, 47, 1991, 0, }, - { "Oldenbu0", 1, 4, 48, 1991, 0, }, - { "GrKneten", 1, 4, 49, 1991, 0, }, - { "Hartenho", 1, 4, 50, 0, 1999, }, - { "Luenebg.", 1, 4, 51, 1991, 0, }, - { "DaeHagen", 1, 4, 52, 0, 1999, }, - { "Luebeck9", 1, 4, 53, 0, 1999, }, - { "Egestorf", 1, 4, 54, 1991, 0, }, - { "Ulzburg4", 1, 4, 55, 1991, 1999, }, - { "Luebek23", 1, 4, 56, 1991, 1999, }, - { "Schoenwa", 1, 4, 57, 1991, 1999, }, - { "Ratzebur", 1, 4, 58, 1991, 1999, }, - { "Schwarzb", 1, 4, 59, 1991, 1999, }, - { "Stade", 1, 4, 60, 1991, 0, }, - { "Elmshorn", 1, 4, 61, 1991, 1999, }, - { "Eckrnfd5", 1, 4, 62, 0, 1999, }, - { "Osterjor", 1, 4, 63, 1991, 0, }, - { "Wedel 9", 1, 4, 64, 1991, 0, }, - { "Norden 0", 1, 4, 65, 1991, 0, }, - { "Husum 0", 1, 4, 66, 1991, 1999, }, - { "Walle", 1, 4, 67, 1991, 0, }, - { "Woltmers", 1, 4, 68, 1991, 0, }, - { "Grolland", 1, 4, 69, 1991, 0, }, - { "Huckelri", 1, 4, 70, 1991, 0, }, - { "Hochh.Wi", 1, 4, 71, 1991, 0, }, - { "Marne 0", 1, 4, 72, 1991, 1999, }, - { "Neumuens", 1, 4, 73, 0, 1999, }, - { "Kloecknr", 1, 4, 74, 1991, 0, }, - { "HochDuen", 1, 4, 75, 1991, 0, }, - { "Suederlu", 1, 4, 76, 1991, 1999, }, - { "Ippener0", 1, 4, 77, 1991, 0, }, - { "Hatten10", 1, 4, 79, 1991, 0, }, - { "Kirchtim", 1, 4, 80, 1991, 0, }, - { "Garding1", 1, 4, 81, 1991, 1999, }, - { "Hohenfel", 1, 4, 82, 0, 1999, }, - { "Ahrensb1", 1, 4, 83, 0, 1999, }, - { "Edewecht", 1, 4, 84, 1991, 0, }, - { "Berne 0", 1, 4, 85, 1991, 0, }, - { "Schlesw4", 1, 4, 86, 0, 1999, }, - { "Bremervo", 1, 4, 87, 1991, 0, }, - { "Osterhol", 1, 4, 88, 1991, 0, }, - { "Wangerla", 1, 4, 89, 1991, 0, }, - { "Wankendf", 1, 4, 90, 1991, 1999, }, - { "Varel 1", 1, 4, 92, 1991, 0, }, - { "Friesoyt", 1, 4, 93, 1991, 0, }, - { "Wyk", 1, 4, 94, 0, 1999, }, - { "BdSegebe", 1, 4, 95, 1991, 1999, }, - { "Kappeln1", 1, 4, 96, 1991, 1999, }, - { "Helgolan", 1, 4, 97, 1991, 0, }, - { "Suelfeld", 1, 4, 99, 0, 1999, }, - { "HH22Bake", 2, 4, 1, 1991, 1999, }, - { "Buxtehud", 2, 4, 2, 1991, 1999, }, - { "Buchholz", 2, 4, 3, 0, 1999, }, - { "Egestorf", 2, 4, 4, 0, 1999, }, - { "Luenebu3", 2, 4, 5, 0, 1999, }, - { "Marxen 2", 2, 4, 6, 0, 1999, }, - { "Wulfsn10", 2, 4, 8, 0, 1999, }, - { "Pinnebg7", 2, 4, 9, 0, 1999, }, - { "Barsbuet", 2, 4, 10, 0, 1999, }, - { "Poppenbu", 2, 4, 11, 0, 1999, }, - { "Allermoe", 2, 4, 12, 0, 1999, }, - { "Harburg", 2, 4, 13, 1991, 1999, }, - { "Sauensik", 2, 4, 14, 0, 1999, }, - { "Betzendf", 2, 4, 15, 0, 1999, }, - { "Poppenbu", 2, 4, 16, 1991, 0, }, - { "Tostedt0", 2, 4, 17, 1991, 1999, }, - { "PhilipsM", 2, 4, 18, 0, 1999, }, - { "Klockman", 2, 4, 24, 0, 1999, }, - { "Bauerbgw", 2, 4, 25, 0, 1999, }, - { "Trittau", 2, 4, 26, 0, 1999, }, - { "Postamt2", 2, 4, 27, 1991, 1999, }, - { "Wandsbek", 2, 4, 28, 0, 1999, }, - { "Schulgar", 2, 4, 30, 1991, 1999, }, - { "Altona", 2, 4, 31, 1991, 1999, }, - { "FH Seefa", 2, 4, 32, 1991, 1999, }, - { "FernVst", 2, 4, 33, 1991, 1999, }, - { "Hoheluft", 2, 4, 34, 1991, 1999, }, - { "Modezent", 2, 4, 35, 1991, 1999, }, - { "Langnhor", 2, 4, 36, 0, 1999, }, - { "AchternB", 2, 4, 37, 1991, 1999, }, - { "Finkenwd", 2, 4, 38, 1991, 1999, }, - { "Waltersh", 2, 4, 39, 1991, 1999, }, - { "Wilhelms", 2, 4, 40, 1991, 1999, }, - { "Rotenbuo", 2, 4, 41, 1991, 1999, }, - { "Hamm", 2, 4, 42, 1991, 1999, }, - { "Steilsho", 2, 4, 43, 1991, 1999, }, - { "Ammersbk", 2, 4, 44, 0, 1999, }, - { "NeuWulms", 2, 4, 47, 1991, 1999, }, - { "Seevetal", 2, 4, 48, 1991, 1999, }, - { "Rosengar", 2, 4, 49, 1991, 1999, }, - { "RLindeWg", 2, 4, 50, 1991, 1999, }, - { "Elmshorn", 2, 4, 51, 1991, 0, }, - { "Norderst", 2, 4, 52, 1991, 1999, }, - { "FA4BBz26", 2, 4, 53, 1991, 1999, }, - { "Randowst", 2, 4, 54, 0, 1999, }, - { "Marschac", 2, 4, 56, 0, 1999, }, - { "Harsefld", 2, 4, 57, 1991, 0, }, - { "Winsen 0", 2, 4, 58, 1991, 1999, }, - { "Ahrensbu", 2, 4, 60, 1991, 1999, }, - { "Wittsmoo", 2, 4, 62, 1991, 0, }, - { "Wedel 11", 2, 4, 64, 0, 1999, }, - { "HH Phi.M", 2, 4, 65, 1991, 0, }, - { "HH Radow", 2, 4, 66, 1991, 0, }, - { "Marmstor", 2, 4, 68, 0, 1999, }, - { "Hollenst", 2, 4, 69, 0, 1999, }, - { "Uetersn2", 2, 4, 70, 0, 1999, }, - { "Schiffdf", 3, 4, 1, 0, 1999, }, - { "Emden 0", 3, 4, 2, 0, 1999, }, - { "Bd Zwahn", 3, 4, 4, 0, 1999, }, - { "Wardenbu", 3, 4, 5, 0, 1999, }, - { "HB38Bake", 3, 4, 6, 0, 1999, }, - { "VerWal 1", 3, 4, 7, 0, 1999, }, - { "Hoya 1", 3, 4, 8, 0, 1999, }, - { "HeesBoit", 3, 4, 9, 0, 1999, }, - { "Aurich", 3, 4, 10, 0, 1999, }, - { "Borkum 0", 3, 4, 11, 0, 1999, }, - { "Doerpen0", 3, 4, 12, 0, 1999, }, - { "Vechta-L", 3, 4, 14, 0, 1999, }, - { "Jever 0", 3, 4, 15, 0, 1999, }, - { "Rotenbur", 3, 4, 16, 0, 1999, }, - { "Wilhelmh", 3, 4, 18, 0, 1999, }, - { "Cuxhaven", 3, 4, 23, 0, 1999, }, - { "Harsefel", 3, 4, 24, 0, 1999, }, - { "Leer 1", 3, 4, 25, 0, 1999, }, - { "Helgolan", 3, 4, 26, 0, 1999, }, - { "Hemmoor1", 3, 4, 27, 0, 1999, }, - { "Hambergn", 3, 4, 28, 0, 1999, }, - { "Bassum 3", 3, 4, 29, 0, 1999, }, - { "Stade 1", 3, 4, 30, 0, 1999, }, - { "Bremen 0", 3, 4, 31, 0, 1999, }, - { "Ottersbg", 3, 4, 33, 0, 1999, }, - { "Visselho", 3, 4, 34, 0, 1999, }, - { "Westerst", 3, 4, 35, 0, 1999, }, - { "Findorf", 3, 4, 37, 0, 1999, }, - { "Ritterhu", 3, 4, 38, 0, 1999, }, - { "Delmenho", 3, 4, 39, 0, 1999, }, - { "Stuhr", 3, 4, 40, 0, 1999, }, - { "Weyhe 0", 3, 4, 41, 0, 1999, }, - { "TeneverH", 3, 4, 42, 0, 1999, }, - { "Lilienth", 3, 4, 43, 0, 1999, }, - { "Hude 0", 3, 4, 45, 0, 1999, }, - { "Oldenbu1", 3, 4, 47, 0, 1999, }, - { "Oldenbu0", 3, 4, 48, 0, 1999, }, - { "Norden 0", 3, 4, 65, 0, 1999, }, - { "Walle", 3, 4, 67, 0, 1999, }, - { "Woltmers", 3, 4, 68, 0, 1999, }, - { "Grolland", 3, 4, 69, 0, 1999, }, - { "Huckelri", 3, 4, 70, 0, 1999, }, - { "HidWisch", 3, 4, 71, 0, 1999, }, - { "Kloecknr", 3, 4, 74, 0, 1999, }, - { "GrohnerD", 3, 4, 75, 0, 1999, }, - { "GrIppenr", 3, 4, 77, 0, 1999, }, - { "Sulingen", 3, 4, 78, 0, 1999, }, - { "Hatten10", 3, 4, 79, 0, 1999, }, - { "Zeven 2", 3, 4, 80, 0, 1999, }, - { "Berne 0", 3, 4, 85, 0, 1999, }, - { "Bremervo", 3, 4, 87, 0, 1999, }, - { "Osterhol", 3, 4, 88, 0, 1999, }, - { "Wangerla", 3, 4, 89, 0, 1999, }, - { "Wildesha", 3, 4, 90, 0, 1999, }, - { "Langeoog", 3, 4, 91, 0, 1999, }, - { "Varel 1", 3, 4, 92, 0, 1999, }, - { "Friesoyt", 3, 4, 93, 0, 1999, }, - { "Kirchlin", 3, 4, 94, 0, 1999, }, - { "Papenbur", 3, 4, 95, 0, 1999, }, - { "Cloppenb", 3, 4, 96, 0, 1999, }, - { "WittmBur", 3, 4, 98, 0, 1999, }, - { "BDoberan", 4, 4, 1, 0, 1999, }, - { "Crivitz3", 4, 4, 2, 0, 1999, }, - { "Wolgast3", 4, 4, 3, 0, 1999, }, - { "Schwaan3", 4, 4, 4, 0, 1999, }, - { "Rostok26", 4, 4, 5, 0, 1999, }, - { "Tessin 3", 4, 4, 6, 0, 1999, }, - { "Broderst", 4, 4, 7, 0, 1999, }, - { "Grimmen", 4, 4, 8, 0, 1999, }, - { "Sassnitz", 4, 4, 9, 0, 1999, }, - { "Rostok10", 4, 4, 10, 0, 1999, }, - { "Tribsees", 4, 4, 11, 0, 1999, }, - { "Barth 3", 4, 4, 12, 0, 1999, }, - { "Stralsun", 4, 4, 13, 0, 1999, }, - { "Rostok11", 4, 4, 14, 0, 1999, }, - { "Ribnitz", 4, 4, 15, 0, 1999, }, - { "Kroeplin", 4, 4, 16, 0, 1999, }, - { "Greifswa", 4, 4, 17, 0, 1999, }, - { "Bergen", 4, 4, 18, 0, 1999, }, - { "Guestrow", 4, 4, 19, 0, 1999, }, - { "Schwer20", 4, 4, 20, 0, 1999, }, - { "Bennin 1", 4, 4, 21, 0, 1999, }, - { "Ludwlust", 4, 4, 24, 0, 1999, }, - { "Parchim5", 4, 4, 25, 0, 1999, }, - { "Bernitt1", 4, 4, 26, 0, 1999, }, - { "Wittenb2", 4, 4, 27, 0, 1999, }, - { "Wismar 6", 4, 4, 28, 0, 1999, }, - { "GrGodem1", 4, 4, 29, 0, 1999, }, - { "Sternber", 4, 4, 30, 0, 1999, }, - { "Camps 6", 4, 4, 31, 0, 1999, }, - { "Schwer 4", 4, 4, 32, 0, 1999, }, - { "Rastow 2", 4, 4, 33, 0, 1999, }, - { "Marnitz2", 4, 4, 34, 0, 1999, }, - { "Goldberg", 4, 4, 35, 0, 1999, }, - { "Grevesm5", 4, 4, 36, 0, 1999, }, - { "Gamelin1", 4, 4, 37, 0, 1999, }, - { "Redefin", 4, 4, 38, 0, 1999, }, - { "Roggendf", 4, 4, 39, 0, 1999, }, - { "Heringsd", 4, 4, 40, 0, 1999, }, - { "Torgelow", 4, 4, 42, 0, 1999, }, - { "Zuessow", 4, 4, 43, 0, 1999, }, - { "Lalendor", 4, 4, 44, 0, 1999, }, - { "Krakow 4", 4, 4, 45, 0, 1999, }, - { "Goehren2", 4, 4, 46, 0, 1999, }, - { "Anklam 2", 4, 4, 47, 0, 1999, }, - { "Burow 1", 4, 4, 48, 0, 1999, }, - { "Waren 5", 4, 4, 49, 0, 1999, }, - { "Jarmen 7", 4, 4, 52, 0, 1999, }, - { "Malchin5", 4, 4, 53, 0, 1999, }, - { "Friedld3", 4, 4, 56, 0, 1999, }, - { "Stavenh0", 4, 4, 57, 0, 1999, }, - { "Ueckerm3", 4, 4, 58, 0, 1999, }, - { "Schoenb5", 4, 4, 65, 0, 1999, }, - { "Demmin 0", 4, 4, 66, 0, 1999, }, - { "Altenkn7", 4, 4, 99, 0, 1999, }, - { "BadOeyn0", 1, 5, 2, 0, 1999, }, - { "BadSalz5", 1, 5, 3, 0, 1999, }, - { "Bohmte 0", 1, 5, 4, 0, 1999, }, - { "Buende 2", 1, 5, 5, 0, 1999, }, - { "Delbruek", 1, 5, 6, 0, 1999, }, - { "Extertal", 1, 5, 7, 0, 1999, }, - { "BadPyrm1", 1, 5, 9, 1991, 1999, }, - { "Luedge R", 1, 5, 10, 1991, 1999, }, - { "Ibbenbue", 1, 5, 11, 1991, 1999, }, - { "Bramsche", 1, 5, 12, 1991, 1999, }, - { "Barnst.0", 1, 5, 13, 0, 1999, }, - { "Herford4", 1, 5, 14, 0, 1999, }, - { "Luebbeke", 1, 5, 16, 1991, 1999, }, - { "Lingen 0", 1, 5, 17, 1991, 1999, }, - { "Bielefd0", 1, 5, 18, 0, 1999, }, - { "Lindern", 1, 5, 19, 1991, 1999, }, - { "Oerlingh", 1, 5, 20, 1991, 1999, }, - { "Guetersl", 1, 5, 21, 1991, 0, }, - { "GtlohFr0", 1, 5, 22, 1991, 1999, }, - { "Paderbrn", 1, 5, 23, 1991, 1999, }, - { "Hoevelhf", 1, 5, 24, 1991, 1999, }, - { "Lemgo 2", 1, 5, 25, 1991, 1999, }, - { "BdIburg2", 1, 5, 26, 1991, 1999, }, - { "Dissen 1", 1, 5, 27, 1991, 1999, }, - { "Melle 1", 1, 5, 28, 1991, 1999, }, - { "Fuersten", 1, 5, 29, 1991, 1999, }, - { "BdBenth2", 1, 5, 30, 1991, 1999, }, - { "Uchte 0", 1, 5, 32, 0, 1999, }, - { "BlfJoell", 1, 5, 33, 0, 1999, }, - { "BdLippsp", 1, 5, 34, 0, 1999, }, - { "Steinhgn", 1, 5, 35, 0, 1999, }, - { "Spenge 0", 1, 5, 37, 0, 1999, }, - { "Berge 0", 1, 5, 38, 0, 1999, }, - { "Minden 0", 1, 5, 40, 0, 1999, }, - { "Osnabr 8", 1, 5, 41, 0, 1999, }, - { "Osnabr 0", 1, 5, 42, 0, 1999, }, - { "Rahden 0", 1, 5, 44, 0, 1999, }, - { "Rheda-Wb", 1, 5, 45, 0, 1999, }, - { "Emlichhm", 1, 5, 48, 0, 1999, }, - { "Tecklenb", 1, 5, 50, 0, 1999, }, - { "Blomberg", 1, 5, 52, 0, 1999, }, - { "BDriburg", 1, 5, 54, 0, 1999, }, - { "Harsewin", 1, 5, 55, 0, 1999, }, - { "HornBadM", 1, 5, 56, 0, 1999, }, - { "Nordhorn", 1, 5, 59, 0, 1999, }, - { "Gtloh 0", 1, 5, 60, 0, 1999, }, - { "Damme 1", 1, 5, 61, 1991, 1999, }, - { "Meppen 0", 1, 5, 62, 1991, 1999, }, - { "Rheine 0", 1, 5, 63, 1991, 1999, }, - { "Bielefd1", 1, 5, 92, 1991, 1999, }, - { "Minden 2", 1, 5, 95, 1991, 1999, }, - { "Han 790", 2, 5, 1, 0, 1999, }, - { "Barsingh", 2, 5, 2, 1991, 1999, }, - { "Bergen 1", 2, 5, 3, 1991, 1999, }, - { "Celle 0", 2, 5, 4, 1991, 1999, }, - { "Salzhmdf", 2, 5, 5, 1991, 1999, }, - { "Peine 1", 2, 5, 6, 1991, 1999, }, - { "Sibbess1", 2, 5, 7, 1991, 1999, }, - { "Brswg 3", 2, 5, 9, 1991, 1999, }, - { "Wietze 2", 2, 5, 10, 1991, 1999, }, - { "Wolfsbg1", 2, 5, 11, 1991, 1999, }, - { "Sprakens", 2, 5, 12, 1991, 1999, }, - { "Wesendf", 2, 5, 13, 0, 1999, }, - { "Alfeld40", 2, 5, 14, 1991, 1999, }, - { "Mori.Fr.", 2, 5, 15, 1991, 0, }, - { "Zierenb.", 2, 5, 16, 1991, 0, }, - { "Semmenst", 2, 5, 17, 1991, 1999, }, - { "HildBoer", 2, 5, 18, 1991, 1999, }, - { "Eschede", 2, 5, 19, 1991, 1999, }, - { "Loccum 0", 2, 5, 21, 0, 1999, }, - { "Zernien", 2, 5, 22, 1991, 1999, }, - { "Gartow 1", 2, 5, 23, 1991, 1999, }, - { "Bispin41", 2, 5, 24, 0, 1999, }, - { "Hann. 4", 2, 5, 26, 1991, 1999, }, - { "Gradestr", 2, 5, 27, 1991, 1999, }, - { "NeueLand", 2, 5, 28, 1991, 1999, }, - { "StudWH", 2, 5, 29, 1991, 1999, }, - { "LinGilde", 2, 5, 30, 1991, 1999, }, - { "Hanomag", 2, 5, 31, 1991, 1999, }, - { "Uetze", 2, 5, 32, 1991, 1999, }, - { "Garbsen", 2, 5, 33, 1991, 1999, }, - { "Wedemark", 2, 5, 34, 1991, 1999, }, - { "Burgwdl0", 2, 5, 35, 1991, 1999, }, - { "Schwarm", 2, 5, 36, 0, 1999, }, - { "Lehrte 2", 2, 5, 37, 1991, 1999, }, - { "Sarstedt", 2, 5, 38, 1991, 1999, }, - { "Ronnenbg", 2, 5, 39, 1991, 1999, }, - { "Walsrode", 2, 5, 40, 1991, 1999, }, - { "Gifhorn0", 2, 5, 41, 1991, 1999, }, - { "Hitzack1", 2, 5, 42, 0, 1999, }, - { "Hildeshm", 2, 5, 43, 0, 1999, }, - { "Bleckede", 2, 5, 44, 0, 1999, }, - { "Einbeck2", 2, 5, 46, 0, 1999, }, - { "Brswg701", 2, 5, 48, 0, 1999, }, - { "Hameln10", 2, 5, 49, 1991, 1999, }, - { "Schnever", 2, 5, 50, 0, 1999, }, - { "Helmstdt", 2, 5, 51, 1991, 1999, }, - { "Han 610", 2, 5, 52, 0, 1999, }, - { "Herzberg", 2, 5, 53, 1991, 0, }, - { "Brswg 36", 2, 5, 54, 1991, 1999, }, - { "Stadthgn", 2, 5, 55, 0, 1999, }, - { "Nienburg", 2, 5, 58, 1991, 1999, }, - { "Linsburg", 2, 5, 60, 1991, 1999, }, - { "Springe3", 2, 5, 61, 0, 1999, }, - { "Han 860", 2, 5, 62, 1991, 1999, }, - { "Eschersh", 2, 5, 63, 0, 1999, }, - { "Holle 40", 2, 5, 64, 0, 1999, }, - { "Munster1", 2, 5, 65, 1991, 1999, }, - { "Bgdf-Ehl", 2, 5, 66, 0, 1999, }, - { "Salzg 40", 2, 5, 67, 1991, 1999, }, - { "Burgdorf", 2, 5, 68, 1991, 1999, }, - { "Seesen 1", 2, 5, 69, 1991, 1999, }, - { "Kreiens1", 2, 5, 70, 0, 1999, }, - { "Kassel", 2, 5, 72, 1991, 0, }, - { "Eschwege", 2, 5, 73, 1991, 0, }, - { "Obernk 2", 2, 5, 74, 1991, 1999, }, - { "Melsung5", 2, 5, 75, 1991, 0, }, - { "Uelzen 3", 2, 5, 76, 1991, 1999, }, - { "Jerxheim", 2, 5, 78, 1991, 1999, }, - { "Wunstorf", 2, 5, 80, 0, 1999, }, - { "Brome 0", 2, 5, 82, 0, 1999, }, - { "Salzg 0", 2, 5, 84, 0, 1999, }, - { "Wendebg", 2, 5, 85, 0, 1999, }, - { "Han 730", 2, 5, 86, 1991, 1999, }, - { "Soltau 2", 2, 5, 87, 0, 1999, }, - { "Irxleben", 2, 5, 88, 1991, 0, }, - { "Claustal", 2, 5, 90, 0, 1999, }, - { "Goslar41", 2, 5, 91, 0, 1999, }, - { "Koenigsl", 2, 5, 92, 0, 1999, }, - { "Torfhaus", 2, 5, 93, 0, 1999, }, - { "Einbeck2", 2, 5, 94, 1991, 0, }, - { "Sibb2 DB", 2, 5, 95, 0, 1999, }, - { "HanMesse", 2, 5, 97, 0, 1999, }, - { "Hoever", 2, 5, 98, 0, 1999, }, - { "Homberg1", 3, 5, 1, 0, 1999, }, - { "Morschen", 3, 5, 2, 0, 1999, }, - { "Spangenb", 3, 5, 3, 0, 1999, }, - { "Baunatal", 3, 5, 5, 0, 1999, }, - { "Korbach0", 3, 5, 8, 0, 1999, }, - { "Arolsen0", 3, 5, 9, 0, 1999, }, - { "Zierenb3", 3, 5, 10, 0, 1999, }, - { "Hofgeism", 3, 5, 11, 0, 1999, }, - { "BKarlshf", 3, 5, 12, 0, 1999, }, - { "Fritzlar", 3, 5, 13, 0, 1999, }, - { "Warburg2", 3, 5, 14, 0, 1999, }, - { "Willebad", 3, 5, 15, 0, 1999, }, - { "Gtngn 2", 3, 5, 17, 0, 1999, }, - { "Moringen", 3, 5, 18, 0, 1999, }, - { "Zierenb1", 3, 5, 19, 0, 1999, }, - { "Grossalm", 3, 5, 21, 0, 1999, }, - { "Kassel 1", 3, 5, 22, 0, 1999, }, - { "Herzberg", 3, 5, 25, 0, 1999, }, - { "Neuhaus2", 3, 5, 26, 0, 1999, }, - { "Rosdrf40", 3, 5, 27, 0, 1999, }, - { "Osterrod", 3, 5, 28, 0, 1999, }, - { "Eschwege", 3, 5, 30, 0, 1999, }, - { "Sontra 2", 3, 5, 31, 0, 1999, }, - { "Melsgn5", 3, 5, 32, 0, 1999, }, - { "Muenden2", 3, 5, 33, 0, 1999, }, - { "Rehagn40", 3, 5, 34, 0, 1999, }, - { "BSachsa1", 3, 5, 35, 0, 1999, }, - { "Muenden3", 3, 5, 38, 0, 1999, }, - { "Northeim", 3, 5, 39, 0, 1999, }, - { "Vellmar", 3, 5, 41, 0, 1999, }, - { "Brnlage", 3, 5, 43, 0, 1999, }, - { "Waldkapl", 3, 5, 44, 0, 1999, }, - { "Edertal", 3, 5, 45, 0, 1999, }, - { "Brakel 2", 3, 5, 46, 0, 1999, }, - { "HessLich", 3, 5, 47, 0, 1999, }, - { "Duderst", 3, 5, 48, 0, 1999, }, - { "BSAllend", 3, 5, 49, 0, 1999, }, - { "BWildngn", 3, 5, 51, 0, 1999, }, - { "Woelfte", 3, 5, 54, 0, 1999, }, - { "Kalefeld", 3, 5, 55, 0, 1999, }, - { "Kassel 4", 3, 5, 56, 0, 1999, }, - { "Buchbg99", 3, 5, 58, 0, 1999, }, - { "Worms_7", 1, 6, 1, 1991, 1999, }, - { "Westhofn", 1, 6, 2, 1991, 1999, }, - { "Benshm_0", 1, 6, 3, 1991, 1999, }, - { "Waibstdt", 1, 6, 4, 1991, 1999, }, - { "Seeheim2", 1, 6, 5, 1991, 1999, }, - { "Mosbach6", 1, 6, 6, 1991, 1999, }, - { "Eberbach", 1, 6, 7, 1991, 1999, }, - { "Lambrech", 1, 6, 8, 1991, 1999, }, - { "Weidenth", 1, 6, 9, 1991, 1999, }, - { "BdKrznch", 1, 6, 10, 1991, 1999, }, - { "Annweile", 1, 6, 11, 1991, 1999, }, - { "Wilhelms", 1, 6, 12, 1991, 1999, }, - { "Alzey_1", 1, 6, 13, 1991, 1999, }, - { "Mudau 1", 1, 6, 14, 1991, 1999, }, - { "Klautern", 1, 6, 15, 1991, 1999, }, - { "Pirmas.", 1, 6, 16, 1991, 0, }, - { "Konken 3", 1, 6, 17, 1991, 0, }, - { "BdBergza", 1, 6, 22, 1991, 1999, }, - { "Kell", 1, 6, 23, 1991, 0, }, - { "Wiesloch", 1, 6, 24, 0, 1999, }, - { "Hockenhm", 1, 6, 25, 1991, 1999, }, - { "Beerfldn", 1, 6, 26, 1991, 1999, }, - { "Hardberg", 1, 6, 27, 0, 1999, }, - { "Ahorn 1", 1, 6, 28, 0, 1999, }, - { "Scheffle", 1, 6, 29, 0, 1999, }, - { "Michlstd", 1, 6, 30, 1991, 1999, }, - { "Friedrfd", 1, 6, 31, 1991, 1999, }, - { "Lindnfls", 1, 6, 32, 1991, 1999, }, - { "Sob.Eck.", 1, 6, 33, 1991, 0, }, - { "Moeckmue", 1, 6, 34, 1991, 1999, }, - { "Meishm_6", 1, 6, 35, 1991, 1999, }, - { "Odernhm", 1, 6, 36, 1991, 1999, }, - { "Guntbl_3", 1, 6, 37, 1991, 1999, }, - { "Flonheim", 1, 6, 38, 1991, 1999, }, - { "Neutsch", 1, 6, 40, 1991, 1999, }, - { "Gerolste", 1, 6, 41, 1991, 0, }, - { "Schoena3", 1, 6, 42, 0, 1999, }, - { "Neckarg1", 1, 6, 43, 0, 1999, }, - { "Neckarg2", 1, 6, 44, 0, 1999, }, - { "Meckeshm", 1, 6, 45, 0, 1999, }, - { "Schoenau", 1, 6, 46, 1991, 1999, }, - { "Lebach 3", 1, 6, 47, 1991, 0, }, - { "Sulzbh10", 1, 6, 48, 1991, 0, }, - { "Voelklin", 1, 6, 49, 1991, 0, }, - { "Hardheim", 1, 6, 51, 0, 1999, }, - { "Buchen 0", 1, 6, 52, 0, 1999, }, - { "Maxdorf0", 1, 6, 53, 0, 1999, }, - { "Guntbl_1", 1, 6, 54, 0, 1999, }, - { "Bensh_13", 1, 6, 55, 1991, 1999, }, - { "Weinheim", 1, 6, 56, 0, 1999, }, - { "Winwlr_2", 1, 6, 57, 0, 1999, }, - { "Winwlr_8", 1, 6, 58, 0, 1999, }, - { "Neustadt", 1, 6, 60, 1991, 1999, }, - { "LU 505", 1, 6, 61, 1991, 1999, }, - { "Speyer 5", 1, 6, 62, 1991, 1999, }, - { "Landau 8", 1, 6, 63, 1991, 1999, }, - { "Heidelbg", 1, 6, 64, 1991, 1999, }, - { "Dahn_3", 1, 6, 65, 0, 1999, }, - { "Schwetzi", 1, 6, 66, 1991, 1999, }, - { "Ladenbg6", 1, 6, 67, 1991, 1999, }, - { "Lamperth", 1, 6, 68, 1991, 1999, }, - { "Pfeiffer", 1, 6, 69, 1991, 1999, }, - { "Neuhofen", 1, 6, 70, 1991, 1999, }, - { "Ilveshm", 1, 6, 71, 1991, 1999, }, - { "DiakoKrH", 1, 6, 72, 1991, 1999, }, - { "GrosKrWe", 1, 6, 73, 1991, 1999, }, - { "K.M.Wein", 1, 6, 74, 1991, 0, }, - { "Maimarkt", 1, 6, 75, 1991, 1999, }, - { "Siloturm", 1, 6, 76, 1991, 1999, }, - { "Kaeferta", 1, 6, 77, 1991, 1999, }, - { "Viernhm", 1, 6, 78, 1991, 1999, }, - { "Neunki.", 1, 6, 79, 1991, 0, }, - { "Mettl.M.", 1, 6, 80, 1991, 0, }, - { "Zweibrue", 1, 6, 82, 1991, 0, }, - { "Adelshei", 1, 6, 83, 0, 1999, }, - { "Gernsh_4", 1, 6, 84, 0, 1999, }, - { "Alsenz_7", 1, 6, 85, 0, 1999, }, - { "Frankent", 1, 6, 86, 1991, 1999, }, - { "Gruenstd", 1, 6, 87, 1991, 1999, }, - { "BdDuerk2", 1, 6, 88, 1991, 1999, }, - { "BdDuerk0", 1, 6, 89, 0, 1999, }, - { "Khmbolan", 1, 6, 90, 0, 1999, }, - { "Hasmersh", 1, 6, 91, 0, 1999, }, - { "EnkAlsnb", 1, 6, 93, 0, 1999, }, - { "Miltnbg2", 1, 6, 94, 0, 1999, }, - { "Miltnbg4", 1, 6, 95, 0, 1999, }, - { "Rockhsn", 1, 6, 96, 0, 1999, }, - { "DB Pfing", 1, 6, 97, 1991, 1999, }, - { "MA4 Bake", 1, 6, 99, 1991, 1999, }, - { "F16_INIT", 2, 6, 1, 1991, 1999, }, - { "Dieburg", 2, 6, 2, 0, 1999, }, - { "GrUmstdt", 2, 6, 3, 0, 1999, }, - { "Brensbch", 2, 6, 4, 0, 1999, }, - { "Heusenst", 2, 6, 5, 0, 1999, }, - { "Floershm", 2, 6, 6, 0, 1999, }, - { "Gr-Gerau", 2, 6, 7, 0, 1999, }, - { "Langen", 2, 6, 8, 1991, 1999, }, - { "Moerf-Wal", 2, 6, 9, 1991, 1999, }, - { "Rodgau", 2, 6, 10, 1991, 1999, }, - { "Darmst21", 2, 6, 11, 0, 1999, }, - { "Darmst_2", 2, 6, 12, 0, 1999, }, - { "Reusselsh", 2, 6, 13, 0, 1999, }, - { "Hofh-Wal", 2, 6, 15, 0, 1999, }, - { "Eppst_2", 2, 6, 16, 0, 1999, }, - { "Wiesb_1", 2, 6, 17, 0, 1999, }, - { "Wiesb_33", 2, 6, 18, 0, 1999, }, - { "Wiesb_34", 2, 6, 19, 0, 1999, }, - { "Wiesb_35", 2, 6, 20, 0, 1999, }, - { "Klstrbch", 2, 6, 21, 0, 1999, }, - { "Mnz_Kstl", 2, 6, 22, 0, 1999, }, - { "Mainz_3", 2, 6, 23, 0, 1999, }, - { "Mainz_4", 2, 6, 24, 0, 1999, }, - { "Mainz_5", 2, 6, 25, 0, 1999, }, - { "Mainz_26", 2, 6, 26, 0, 1999, }, - { "Niedrhsn", 2, 6, 27, 0, 1999, }, - { "Eppst_1", 2, 6, 28, 0, 1999, }, - { "Roedrmk7", 2, 6, 30, 0, 1999, }, - { "Kastell2", 2, 6, 31, 0, 1999, }, - { "Lorch_3", 2, 6, 32, 0, 1999, }, - { "Oppenhm", 2, 6, 34, 0, 1999, }, - { "Pfungstd", 2, 6, 35, 0, 1999, }, - { "BadSoden", 2, 6, 36, 1991, 1999, }, - { "Kronberg", 2, 6, 37, 1991, 1999, }, - { "F-Zeil", 2, 6, 38, 1991, 1999, }, - { "F-Rohmer", 2, 6, 39, 1991, 1999, }, - { "F-Raimnd", 2, 6, 40, 1991, 1999, }, - { "F-Giess", 2, 6, 41, 1991, 1999, }, - { "Koenigst", 2, 6, 42, 1991, 1999, }, - { "F-DanzPl", 2, 6, 43, 1991, 1999, }, - { "NeuIsnbg", 2, 6, 44, 1991, 1999, }, - { "F-StbHhl", 2, 6, 45, 1991, 1999, }, - { "Kriftel", 2, 6, 46, 1991, 1999, }, - { "Kelkheim", 2, 6, 47, 1991, 1999, }, - { "Oberursl", 2, 6, 48, 1991, 1999, }, - { "F-Berkhm", 2, 6, 49, 1991, 1999, }, - { "F-Diestw", 2, 6, 50, 1991, 1999, }, - { "F-MnzLSt", 2, 6, 51, 1991, 1999, }, - { "F-Lyoner", 2, 6, 52, 1991, 1999, }, - { "F-Oeser", 2, 6, 53, 1991, 1999, }, - { "BdVilbel", 2, 6, 54, 1991, 1999, }, - { "F-Orber", 2, 6, 55, 1991, 1999, }, - { "F-Flughf", 2, 6, 56, 1991, 1999, }, - { "Lorch_4", 2, 6, 58, 0, 1999, }, - { "OF-Jahns", 2, 6, 61, 1991, 1999, }, - { "Nastaett", 2, 6, 62, 0, 1999, }, - { "Babenhsn", 2, 6, 63, 0, 1999, }, - { "ObRamstd", 2, 6, 65, 0, 1999, }, - { "Breuberg", 2, 6, 66, 0, 1999, }, - { "ObrWesel", 2, 6, 72, 0, 1999, }, - { "Pfalzfd", 2, 6, 73, 0, 1999, }, - { "Rhnboell", 2, 6, 74, 0, 1999, }, - { "Ruedeshm", 2, 6, 75, 0, 1999, }, - { "Eltville", 2, 6, 76, 0, 1999, }, - { "Wintrbch", 2, 6, 77, 0, 1999, }, - { "Boppard", 2, 6, 78, 0, 1999, }, - { "OF-Krkhs", 2, 6, 79, 1991, 1999, }, - { "Strombg", 2, 6, 80, 0, 1999, }, - { "Trebur1", 2, 6, 81, 0, 1999, }, - { "Ffm Sued", 2, 6, 83, 0, 1999, }, - { "MainTaZ", 2, 6, 84, 0, 1999, }, - { "BHombg0", 3, 6, 1, 0, 1999, }, - { "Friedb1", 3, 6, 2, 1991, 1999, }, - { "Schottn", 3, 6, 3, 1991, 1999, }, - { "Gelnhsn", 3, 6, 4, 1991, 1999, }, - { "BSchwa3", 3, 6, 5, 0, 1999, }, - { "Friedb0", 3, 6, 6, 1991, 1999, }, - { "Biedk_2", 3, 6, 7, 1991, 1999, }, - { "Biedk_3", 3, 6, 10, 0, 1999, }, - { "Birstein", 3, 6, 11, 1991, 1999, }, - { "Weibersb", 3, 6, 12, 1991, 1999, }, - { "Kalbach1", 3, 6, 13, 0, 1999, }, - { "Driedorf", 3, 6, 14, 0, 1999, }, - { "Lich_2", 3, 6, 15, 1991, 1999, }, - { "Mz 3", 3, 6, 16, 1991, 0, }, - { "Hilders", 3, 6, 17, 1991, 1999, }, - { "Frankbg", 3, 6, 18, 1991, 1999, }, - { "Friedwd", 3, 6, 19, 1991, 1999, }, - { "Mz Kaste", 3, 6, 20, 1991, 0, }, - { "Hanau_1", 3, 6, 21, 1991, 1999, }, - { "Gemuen1", 3, 6, 22, 1991, 1999, }, - { "Gruenbg0", 3, 6, 23, 1991, 1999, }, - { "Hanau_7", 3, 6, 24, 1991, 1999, }, - { "Hungen2", 3, 6, 25, 1991, 1999, }, - { "Gemnden1", 3, 6, 26, 1991, 1999, }, - { "Biebert", 3, 6, 27, 1991, 1999, }, - { "Marburg", 3, 6, 28, 1991, 1999, }, - { "HainaKl", 3, 6, 29, 1991, 1999, }, - { "Weilbg6", 3, 6, 30, 1991, 1999, }, - { "Fulda_3", 3, 6, 31, 1991, 1999, }, - { "Bd_Hersf", 3, 6, 32, 1991, 1999, }, - { "Schlue_3", 3, 6, 33, 1991, 1999, }, - { "Neuenst", 3, 6, 34, 1991, 1999, }, - { "Ebersbg", 3, 6, 35, 1991, 1999, }, - { "Lautrbch", 3, 6, 36, 1991, 1999, }, - { "Gruenbg1", 3, 6, 37, 0, 1999, }, - { "Ortenbg", 3, 6, 38, 0, 1999, }, - { "Alsfeld", 3, 6, 39, 1991, 1999, }, - { "Altenstd", 3, 6, 40, 1991, 0, }, - { "Katzelnb", 3, 6, 41, 1991, 1999, }, - { "Babenhs3", 3, 6, 42, 1991, 0, }, - { "Aarbgn_1", 3, 6, 43, 1991, 1999, }, - { "Aarberg3", 3, 6, 44, 1991, 0, }, - { "BSchwa_2", 3, 6, 45, 1991, 1999, }, - { "Schlabad", 3, 6, 46, 1991, 1999, }, - { "Lich_Eb", 3, 6, 47, 1991, 1999, }, - { "AB14Hoes", 3, 6, 48, 0, 1999, }, - { "Schwlmst", 3, 6, 50, 1991, 1999, }, - { "Nentrhsn", 3, 6, 51, 1991, 1999, }, - { "Reichlsh", 3, 6, 52, 0, 1999, }, - { "Woelfshm", 3, 6, 53, 0, 1999, }, - { "Limburg", 3, 6, 54, 1991, 1999, }, - { "Rotenbg", 3, 6, 55, 0, 1999, }, - { "Burgsinn", 3, 6, 56, 0, 1999, }, - { "Schlitz", 3, 6, 57, 0, 1999, }, - { "Wildeck", 3, 6, 58, 0, 1999, }, - { "Friedrdf", 3, 6, 59, 1991, 1999, }, - { "Taunuss", 3, 6, 60, 1991, 1999, }, - { "Giessen0", 3, 6, 61, 1991, 1999, }, - { "Linden_5", 3, 6, 62, 1991, 1999, }, - { "Breitnbc", 3, 6, 63, 0, 1999, }, - { "BdBrueck", 3, 6, 64, 0, 1999, }, - { "Buseck_6", 3, 6, 65, 0, 1999, }, - { "Eckhhsn", 3, 6, 66, 0, 1999, }, - { "Steinau", 3, 6, 68, 1991, 1999, }, - { "Nidda_3", 3, 6, 69, 0, 1999, }, - { "Braunfls", 3, 6, 70, 0, 1999, }, - { "Lselbold", 3, 6, 71, 1991, 1999, }, - { "Usingen", 3, 6, 72, 0, 1999, }, - { "Ehringsh", 3, 6, 74, 0, 1999, }, - { "Seligstd", 3, 6, 75, 0, 1999, }, - { "BdNauhm2", 3, 6, 77, 0, 1999, }, - { "AB11Gail", 3, 6, 78, 0, 1999, }, - { "AB13Glat", 3, 6, 79, 0, 1999, }, - { "GrAuheim", 3, 6, 80, 0, 1999, }, - { "Dillenbg", 3, 6, 81, 1991, 1999, }, - { "Eschenbg", 3, 6, 82, 1991, 1999, }, - { "Herlesh1", 3, 6, 83, 1991, 1999, }, - { "Idstein", 3, 6, 84, 1991, 1999, }, - { "Herborn", 3, 6, 85, 1991, 1999, }, - { "Selters", 3, 6, 86, 1991, 1999, }, - { "BadCambg", 3, 6, 87, 1991, 1999, }, - { "Karben1", 3, 6, 88, 0, 1999, }, - { "Lohr 2", 3, 6, 89, 0, 1999, }, - { "Neuhof", 3, 6, 90, 1991, 1999, }, - { "Esselbac", 3, 6, 91, 0, 1999, }, - { "Moembris", 3, 6, 92, 0, 1999, }, - { "Obernbu1", 3, 6, 93, 0, 1999, }, - { "Wetzlar", 3, 6, 94, 0, 1999, }, - { "Guxhgn 1", 3, 6, 95, 0, 1999, }, - { "Ndraula", 3, 6, 96, 0, 1999, }, - { "Huenfeld", 3, 6, 97, 0, 1999, }, - { "Wiesen 1", 3, 6, 98, 0, 1999, }, - { "Faulbach", 3, 6, 99, 0, 1999, }, - { "Saarbr_2", 4, 6, 1, 0, 1999, }, - { "Welschb", 4, 6, 2, 0, 1999, }, - { "Hallschl", 4, 6, 3, 0, 1999, }, - { "Marpngn", 4, 6, 4, 0, 1999, }, - { "Konz", 4, 6, 5, 0, 1999, }, - { "Simmern3", 4, 6, 7, 0, 1999, }, - { "Saarloui", 4, 6, 8, 0, 1999, }, - { "Saarbr_5", 4, 6, 9, 0, 1999, }, - { "Perl 1", 4, 6, 11, 0, 1999, }, - { "Gemuendn", 4, 6, 13, 0, 1999, }, - { "Pirmasns", 4, 6, 16, 0, 1999, }, - { "Konken_3", 4, 6, 17, 0, 1999, }, - { "GlMnchwl", 4, 6, 18, 0, 1999, }, - { "RbchStgn", 4, 6, 19, 0, 1999, }, - { "Lndstuhl", 4, 6, 20, 0, 1999, }, - { "Weilerb", 4, 6, 21, 0, 1999, }, - { "Trier_1", 4, 6, 22, 0, 1999, }, - { "Kell_1", 4, 6, 23, 0, 1999, }, - { "Blieskst", 4, 6, 24, 0, 1999, }, - { "Bernk-Ks", 4, 6, 25, 0, 1999, }, - { "Pruem_2", 4, 6, 26, 0, 1999, }, - { "Idar-Ob", 4, 6, 27, 0, 1999, }, - { "Brchmbch", 4, 6, 28, 0, 1999, }, - { "Dellfeld", 4, 6, 30, 0, 1999, }, - { "Homburg0", 4, 6, 31, 0, 1999, }, - { "Kastell3", 4, 6, 32, 0, 1999, }, - { "SchbKueb", 4, 6, 33, 0, 1999, }, - { "StWendel", 4, 6, 34, 0, 1999, }, - { "Heuswlr", 4, 6, 35, 0, 1999, }, - { "Saarbr_1", 4, 6, 36, 0, 1999, }, - { "Neumg_Dr", 4, 6, 37, 0, 1999, }, - { "Bitburg", 4, 6, 38, 0, 1999, }, - { "Wolfstn", 4, 6, 39, 0, 1999, }, - { "Saarburg", 4, 6, 40, 0, 1999, }, - { "Gerolstn", 4, 6, 41, 0, 1999, }, - { "Kirn_7", 4, 6, 44, 0, 1999, }, - { "Merzig_3", 4, 6, 46, 0, 1999, }, - { "Lebach_3", 4, 6, 47, 0, 1999, }, - { "Sulzbach", 4, 6, 48, 0, 1999, }, - { "Voelklng", 4, 6, 49, 0, 1999, }, - { "Zweibrck", 4, 6, 50, 0, 1999, }, - { "Buedlich", 4, 6, 54, 0, 1999, }, - { "Klblittd", 4, 6, 56, 0, 1999, }, - { "Meishm_7", 4, 6, 59, 0, 1999, }, - { "HWeidtal", 4, 6, 60, 0, 1999, }, - { "Dillingn", 4, 6, 61, 0, 1999, }, - { "Thleiwlr", 4, 6, 62, 0, 1999, }, - { "Trulben2", 4, 6, 64, 0, 1999, }, - { "Kirchbg1", 4, 6, 78, 0, 1999, }, - { "Neunkrch", 4, 6, 79, 0, 1999, }, - { "Mettlach", 4, 6, 80, 0, 1999, }, - { "Beuron 1", 1, 7, 1, 1991, 1999, }, - { "AlLaufn1", 1, 7, 2, 1991, 1999, }, - { "Oberndf3", 1, 7, 3, 1991, 1999, }, - { "Schwenni", 1, 7, 4, 1991, 1999, }, - { "Rottweil", 1, 7, 5, 1991, 1999, }, - { "AlEbing2", 1, 7, 6, 1991, 1999, }, - { "Baiersb1", 1, 7, 7, 1991, 1999, }, - { "Balingn1", 1, 7, 8, 1991, 1999, }, - { "Gosheim1", 1, 7, 9, 1991, 1999, }, - { "Tuttlin2", 1, 7, 10, 1991, 1999, }, - { "Konstan0", 1, 7, 11, 1991, 1999, }, - { "Waldbg 2", 1, 7, 12, 1991, 1999, }, - { "Deggenh3", 1, 7, 13, 1991, 1999, }, - { "Sigmari4", 1, 7, 14, 1991, 1999, }, - { "Donaues5", 1, 7, 15, 1991, 1999, }, - { "Singen 0", 1, 7, 16, 1991, 1999, }, - { "Klettga6", 1, 7, 17, 1991, 1999, }, - { "Rickenb1", 1, 7, 18, 1991, 1999, }, - { "Bodman 3", 1, 7, 19, 1991, 1999, }, - { "Sauldf 1", 1, 7, 20, 1991, 1999, }, - { "Hilzingn", 1, 7, 21, 0, 1999, }, - { "Stockac6", 1, 7, 22, 1991, 1999, }, - { "Aichste2", 1, 7, 23, 1991, 1999, }, - { "Voehrnb4", 1, 7, 24, 1991, 1999, }, - { "Radolfzl", 1, 7, 25, 1991, 1999, }, - { "Schoemb2", 1, 7, 26, 1991, 1999, }, - { "Nagold 0", 1, 7, 27, 1991, 1999, }, - { "Rottenb3", 1, 7, 28, 1991, 1999, }, - { "Heching6", 1, 7, 29, 1991, 1999, }, - { "Ammerbu2", 1, 7, 30, 1991, 1999, }, - { "Allensb1", 1, 7, 31, 1991, 1999, }, - { "Villin10", 1, 7, 32, 1991, 1999, }, - { "Tiegen 0", 1, 7, 33, 1991, 1999, }, - { "Mengen 1", 1, 7, 34, 1991, 1999, }, - { "BdSchus1", 1, 7, 35, 1991, 1999, }, - { "Ravensb0", 1, 7, 36, 1991, 1999, }, - { "Friedrh0", 1, 7, 37, 1991, 1999, }, - { "Nagold 1", 1, 7, 38, 1991, 1999, }, - { "Baiersb3", 1, 7, 39, 0, 1999, }, - { "Grafnhsn", 1, 7, 40, 0, 1999, }, - { "BadSaeck", 1, 7, 41, 1991, 1999, }, - { "Immensta", 1, 7, 42, 1991, 1999, }, - { "Altenst2", 1, 7, 43, 1991, 1999, }, - { "St.Georg", 1, 7, 44, 1991, 1999, }, - { "Sulz 3", 1, 7, 45, 1991, 1999, }, - { "Murg2 CH", 1, 7, 46, 1991, 1999, }, - { "Tengen 2", 1, 7, 47, 1991, 1999, }, - { "Waldshut", 1, 7, 48, 1991, 1999, }, - { "Leutkir0", 1, 7, 49, 1991, 1999, }, - { "Triberg2", 1, 7, 50, 1991, 1999, }, - { "Furtwan2", 1, 7, 51, 1991, 1999, }, - { "Tettnang", 1, 7, 52, 1991, 1999, }, - { "Ostrach2", 1, 7, 53, 1991, 1999, }, - { "Haigerl0", 1, 7, 54, 1991, 1999, }, - { "Laichi41", 1, 7, 55, 1991, 0, }, - { "Alpirsb4", 1, 7, 56, 1991, 1999, }, - { "Pfullen1", 1, 7, 57, 1991, 1999, }, - { "Rottwei7", 1, 7, 58, 1991, 1999, }, - { "Guenzb70", 1, 7, 59, 1991, 0, }, - { "Baiersb2", 1, 7, 60, 0, 1999, }, - { "BdWurza1", 1, 7, 61, 1991, 1999, }, - { "Wangen 1", 1, 7, 62, 1991, 1999, }, - { "Markdf 1", 1, 7, 63, 1991, 1999, }, - { "Burladi1", 1, 7, 64, 0, 1999, }, - { "Gammerti", 1, 7, 65, 0, 1999, }, - { "Kissleg2", 1, 7, 66, 1991, 1999, }, - { "Kressbr3", 1, 7, 67, 1991, 1999, }, - { "Freuden0", 1, 7, 69, 0, 1999, }, - { "Geisingn", 1, 7, 70, 1991, 1999, }, - { "Isny 0", 1, 7, 71, 1991, 1999, }, - { "Schelkli", 1, 7, 72, 1991, 0, }, - { "Deggin71", 1, 7, 73, 1991, 0, }, - { "Ochsenha", 1, 7, 74, 1991, 0, }, - { "Ulm D2", 1, 7, 76, 1991, 0, }, - { "Ulm D126", 1, 7, 77, 1991, 0, }, - { "Langenau", 1, 7, 78, 1991, 0, }, - { "Schramb1", 1, 7, 79, 0, 1999, }, - { "Blaustei", 1, 7, 80, 1991, 0, }, - { "Nersinge", 1, 7, 81, 1991, 0, }, - { "Ulm D151", 1, 7, 82, 1991, 0, }, - { "Blaube41", 1, 7, 83, 1991, 0, }, - { "Ulm D172", 1, 7, 84, 1991, 0, }, - { "Ulm D141", 1, 7, 85, 1991, 0, }, - { "Erbach41", 1, 7, 86, 1991, 0, }, - { "Eigelt.2", 1, 7, 87, 1991, 1999, }, - { "Weissenh", 1, 7, 88, 1991, 0, }, - { "Ehingen1", 1, 7, 89, 1991, 0, }, - { "Laupheim", 1, 7, 90, 1991, 0, }, - { "Illertis", 1, 7, 91, 1991, 0, }, - { "Biberbac", 1, 7, 92, 1991, 0, }, - { "Talheim4", 1, 7, 93, 1991, 1999, }, - { "Heiligb0", 1, 7, 94, 1991, 1999, }, - { "Spaichi3", 1, 7, 95, 1991, 1999, }, - { "Blumbg5", 1, 7, 96, 1991, 1999, }, - { "Lindau 7", 1, 7, 97, 1991, 0, }, - { "Obertal2", 1, 7, 98, 0, 1999, }, - { "Engen 4", 1, 7, 99, 0, 1999, }, - { "Besighm", 2, 7, 1, 0, 1999, }, - { "Adelberg", 2, 7, 2, 0, 1999, }, - { "Wildberg", 2, 7, 3, 0, 1999, }, - { "Tuebing7", 2, 7, 4, 1991, 1999, }, - { "Backnang", 2, 7, 5, 0, 1999, }, - { "Goeppin0", 2, 7, 6, 0, 1999, }, - { "Weilhm 1", 2, 7, 7, 0, 1999, }, - { "Tuebing6", 2, 7, 8, 1991, 1999, }, - { "Reutlin0", 2, 7, 10, 1991, 1999, }, - { "Metzing4", 2, 7, 12, 1991, 1999, }, - { "Trochte2", 2, 7, 13, 1991, 1999, }, - { "Ebersbch", 2, 7, 14, 0, 1999, }, - { "Marbac41", 2, 7, 15, 0, 1999, }, - { "BdLiebzl", 2, 7, 16, 0, 1999, }, - { "BdUrach2", 2, 7, 17, 1991, 1999, }, - { "Lichtst2", 2, 7, 18, 1991, 1999, }, - { "Muensin1", 2, 7, 19, 1991, 1999, }, - { "Suessen0", 2, 7, 20, 0, 1999, }, - { "Weinsbg0", 2, 7, 21, 0, 1999, }, - { "Wendli18", 2, 7, 22, 0, 1999, }, - { "Gomadin1", 2, 7, 23, 1991, 1999, }, - { "Backng43", 2, 7, 24, 0, 1999, }, - { "Maulbr42", 2, 7, 25, 0, 1999, }, - { "Ditzing5", 2, 7, 26, 0, 1999, }, - { "Neuens41", 2, 7, 27, 0, 1999, }, - { "Nksulm72", 2, 7, 28, 0, 1999, }, - { "Heilbr41", 2, 7, 29, 0, 1999, }, - { "S41Mitte", 2, 7, 30, 1991, 1999, }, - { "Schwai42", 2, 7, 31, 0, 1999, }, - { "S31Bahnp", 2, 7, 32, 1991, 1999, }, - { "Heilbr 1", 2, 7, 33, 0, 1999, }, - { "Besigh42", 2, 7, 34, 0, 1999, }, - { "S580Merc", 2, 7, 35, 1991, 1999, }, - { "Waiblin3", 2, 7, 36, 1991, 1999, }, - { "Winnend0", 2, 7, 37, 1991, 1999, }, - { "Bracken1", 2, 7, 38, 0, 1999, }, - { "Waiblin4", 2, 7, 39, 1991, 1999, }, - { "Leonbg41", 2, 7, 40, 0, 1999, }, - { "S582 Kas", 2, 7, 41, 1991, 1999, }, - { "BdWimp41", 2, 7, 42, 0, 1999, }, - { "S45 Essl", 2, 7, 43, 1991, 1999, }, - { "Calw 3", 2, 7, 44, 1991, 1999, }, - { "Loewnstn", 2, 7, 45, 0, 1999, }, - { "Sindelfi", 2, 7, 46, 1991, 1999, }, - { "S26Moehr", 2, 7, 47, 1991, 1999, }, - { "S62 Vaih", 2, 7, 48, 1991, 1999, }, - { "WeildStd", 2, 7, 49, 1991, 1999, }, - { "Leonbg 5", 2, 7, 50, 1991, 1999, }, - { "SchwGmd2", 2, 7, 51, 1991, 1999, }, - { "S10Maybc", 2, 7, 52, 1991, 1999, }, - { "Schornd0", 2, 7, 53, 0, 1999, }, - { "Muench51", 2, 7, 54, 1991, 1999, }, - { "Vaihing1", 2, 7, 55, 1991, 1999, }, - { "S589Flug", 2, 7, 56, 1991, 1999, }, - { "Waldenb3", 2, 7, 57, 1991, 1999, }, - { "Ludwbg 2", 2, 7, 58, 1991, 1999, }, - { "S7 FMT", 2, 7, 59, 1991, 1999, }, - { "Plochgn1", 2, 7, 60, 1991, 1999, }, - { "S49Muens", 2, 7, 61, 1991, 1999, }, - { "S0 FA1", 2, 7, 62, 1991, 1999, }, - { "S344Denk", 2, 7, 63, 1991, 1999, }, - { "Ludwbg 3", 2, 7, 64, 1991, 1999, }, - { "Sachse42", 2, 7, 65, 1991, 1999, }, - { "S361Schb", 2, 7, 66, 1991, 1999, }, - { "Vaihin45", 2, 7, 67, 1991, 1999, }, - { "Moensh43", 2, 7, 68, 1991, 1999, }, - { "Ntenzlin", 2, 7, 69, 0, 1999, }, - { "Echterdi", 2, 7, 70, 0, 1999, }, - { "Gomaring", 2, 7, 71, 0, 1999, }, - { "Beilstei", 2, 7, 72, 0, 1999, }, - { "Spraitba", 2, 7, 74, 0, 1999, }, - { "Sulzbach", 2, 7, 75, 0, 1999, }, - { "Lenningn", 2, 7, 76, 0, 1999, }, - { "BadBoll0", 2, 7, 77, 0, 1999, }, - { "Heilbr18", 2, 7, 79, 0, 1999, }, - { "Weinsb42", 2, 7, 80, 0, 1999, }, - { "Lorch 1", 2, 7, 82, 0, 1999, }, - { "Nuerti41", 2, 7, 87, 1991, 1999, }, - { "Marbch71", 2, 7, 89, 1991, 1999, }, - { "Kirchhm0", 2, 7, 90, 1991, 1999, }, - { "Remseck1", 2, 7, 91, 0, 1999, }, - { "Ehningn4", 2, 7, 92, 1991, 1999, }, - { "Ksrsbch1", 2, 7, 93, 0, 1999, }, - { "Neuffen0", 2, 7, 94, 0, 1999, }, - { "DB Oderd", 2, 7, 96, 0, 1999, }, - { "DB Markg", 2, 7, 97, 0, 1999, }, - { "BdnBdn 5", 3, 7, 1, 1991, 1999, }, - { "Pforzhm7", 3, 7, 2, 1991, 1999, }, - { "Loerrac4", 3, 7, 3, 1991, 1999, }, - { "Badenwr1", 3, 7, 4, 1991, 1999, }, - { "Titisee4", 3, 7, 5, 1991, 1999, }, - { "Vogtsbg1", 3, 7, 6, 1991, 1999, }, - { "Grenzach", 3, 7, 7, 0, 1999, }, - { "Hausach1", 3, 7, 8, 1991, 1999, }, - { "Willsta1", 3, 7, 9, 1991, 1999, }, - { "BdHerrn3", 3, 7, 10, 1991, 1999, }, - { "Hagsfeld", 3, 7, 11, 0, 1999, }, - { "Rastatt6", 3, 7, 12, 1991, 1999, }, - { "FrbgTien", 3, 7, 13, 0, 1999, }, - { "Gaggena0", 3, 7, 14, 1991, 1999, }, - { "Efringen", 3, 7, 15, 0, 1999, }, - { "Lichten0", 3, 7, 16, 1991, 1999, }, - { "Eppingn2", 3, 7, 17, 1991, 1999, }, - { "BdRappe0", 3, 7, 18, 1991, 1999, }, - { "Kirchar2", 3, 7, 19, 1991, 1999, }, - { "Oberkir3", 3, 7, 20, 0, 1999, }, - { "Oppenau2", 3, 7, 21, 0, 1999, }, - { "Offenbg0", 3, 7, 22, 0, 1999, }, - { "Lahr 0", 3, 7, 23, 1991, 1999, }, - { "Ettenhm3", 3, 7, 24, 1991, 1999, }, - { "Achern 2", 3, 7, 25, 0, 1999, }, - { "Schwana0", 3, 7, 26, 1991, 1999, }, - { "OberdFle", 3, 7, 27, 0, 1999, }, - { "Pforzhm2", 3, 7, 28, 1991, 1999, }, - { "Freibg51", 3, 7, 29, 1991, 1999, }, - { "Denzlgn0", 3, 7, 30, 1991, 1999, }, - { "Schopfhe", 3, 7, 31, 0, 1999, }, - { "Gengenba", 3, 7, 32, 0, 1999, }, - { "Kirchzn4", 3, 7, 33, 1991, 1999, }, - { "Karlsbad", 3, 7, 34, 1991, 0, }, - { "Waldkch0", 3, 7, 35, 1991, 1999, }, - { "Emmendn0", 3, 7, 36, 1991, 1999, }, - { "Pforzh71", 3, 7, 37, 0, 1999, }, - { "Rheinfe0", 3, 7, 38, 0, 1999, }, - { "BrUntgro", 3, 7, 39, 0, 1999, }, - { "Loerrach", 3, 7, 40, 0, 1999, }, - { "Walzbct1", 3, 7, 41, 1991, 1999, }, - { "KA0 HPA", 3, 7, 42, 1991, 1999, }, - { "Oestrgn1", 3, 7, 43, 1991, 1999, }, - { "KA1 Mba", 3, 7, 44, 1991, 1999, }, - { "Neureut", 3, 7, 45, 1991, 1999, }, - { "Siemens", 3, 7, 46, 1991, 1999, }, - { "Eichstet", 3, 7, 47, 1991, 1999, }, - { "Tho.Mann", 3, 7, 48, 1991, 1999, }, - { "Schlieng", 3, 7, 49, 1991, 1999, }, - { "KlrhDurl", 3, 7, 50, 1991, 0, }, - { "Durmers0", 3, 7, 51, 1991, 1999, }, - { "Malsch 2", 3, 7, 52, 1991, 1999, }, - { "Bruchsal", 3, 7, 53, 1991, 1999, }, - { "Soellngn", 3, 7, 54, 0, 1999, }, - { "Freibg58", 3, 7, 55, 0, 1999, }, - { "Freibg11", 3, 7, 56, 0, 1999, }, - { "Sinshm 7", 3, 7, 57, 1991, 1999, }, - { "Schluchs", 3, 7, 58, 0, 1999, }, - { "Bdn-Bdn0", 3, 7, 59, 0, 1999, }, - { "BdSchoe5", 3, 7, 60, 1991, 1999, }, - { "Linknhm3", 3, 7, 61, 0, 1999, }, - { "BdnBdn 4", 3, 7, 62, 0, 1999, }, - { "St.Blas1", 3, 7, 63, 1991, 1999, }, - { "Wiesloch", 3, 7, 65, 1991, 0, }, - { "Kehl 0", 3, 7, 66, 0, 1999, }, - { "Marxzell", 3, 7, 67, 0, 1999, }, - { "Bretten3", 3, 7, 68, 1991, 1999, }, - { "Muellhm7", 3, 7, 70, 0, 1999, }, - { "Stockach", 3, 7, 73, 1991, 0, }, - { "Sulzburg", 3, 7, 75, 1991, 1999, }, - { "Neuenbg1", 3, 7, 76, 1991, 1999, }, - { "Landau 2", 3, 7, 77, 1991, 1999, }, - { "Forbach4", 3, 7, 79, 0, 1999, }, - { "Germersh", 3, 7, 80, 0, 1999, }, - { "Waghaeu2", 3, 7, 81, 1991, 1999, }, - { "Rheinst3", 3, 7, 82, 1991, 1999, }, - { "Woerth 0", 3, 7, 83, 1991, 1999, }, - { "Ruelzhm3", 3, 7, 84, 1991, 1999, }, - { "Zell iW1", 3, 7, 85, 0, 1999, }, - { "Todtnau3", 3, 7, 86, 1991, 1999, }, - { "Maulbr41", 3, 7, 87, 0, 1999, }, - { "Koenigs2", 3, 7, 88, 1991, 1999, }, - { "Buehl0", 3, 7, 90, 1991, 1999, }, - { "Schoena2", 3, 7, 91, 0, 1999, }, - { "Karlsbd2", 3, 7, 92, 1991, 1999, }, - { "Kenzing3", 3, 7, 93, 0, 1999, }, - { "Schoemb1", 3, 7, 95, 1991, 1999, }, - { "Wildbad3", 3, 7, 96, 1991, 1999, }, - { "Enzkloe1", 3, 7, 97, 1991, 1999, }, - { "Abtsgm41", 4, 7, 1, 0, 1999, }, - { "Bopfingn", 4, 7, 2, 0, 1999, }, - { "Weiker41", 4, 7, 3, 0, 1999, }, - { "Heidenh2", 4, 7, 4, 0, 1999, }, - { "Lauterst", 4, 7, 5, 0, 1999, }, - { "Niedstet", 4, 7, 6, 0, 1999, }, - { "SHASulzd", 4, 7, 7, 0, 1999, }, - { "Gaildf42", 4, 7, 8, 0, 1999, }, - { "Mainhdt1", 4, 7, 9, 0, 1999, }, - { "Schoen41", 4, 7, 10, 0, 1999, }, - { "SchHall0", 4, 7, 11, 0, 1999, }, - { "BdMerge2", 4, 7, 12, 0, 1999, }, - { "Forchtb1", 4, 7, 14, 0, 1999, }, - { "Oehrin41", 4, 7, 15, 0, 1999, }, - { "BdMerg41", 4, 7, 16, 0, 1999, }, - { "Cregling", 4, 7, 17, 0, 1999, }, - { "Braunsba", 4, 7, 18, 0, 1999, }, - { "Schopflo", 4, 7, 19, 0, 1999, }, - { "Kuenzels", 4, 7, 20, 0, 1999, }, - { "Lonsee41", 4, 7, 21, 0, 1999, }, - { "Laichign", 4, 7, 22, 0, 1999, }, - { "Fichtnau", 4, 7, 24, 0, 1999, }, - { "Crailsh2", 4, 7, 25, 0, 1999, }, - { "Untrgroe", 4, 7, 26, 0, 1999, }, - { "Wiesenst", 4, 7, 27, 0, 1999, }, - { "Geislin0", 4, 7, 32, 0, 1999, }, - { "Riedlgn2", 4, 7, 33, 0, 1999, }, - { "Aichste3", 4, 7, 37, 0, 1999, }, - { "Ukochn41", 4, 7, 38, 0, 1999, }, - { "Ellwang1", 4, 7, 40, 0, 1999, }, - { "Gerstetn", 4, 7, 41, 0, 1999, }, - { "Heubach1", 4, 7, 45, 0, 1999, }, - { "Lonsee 1", 4, 7, 46, 0, 1999, }, - { "Nereshm1", 4, 7, 47, 0, 1999, }, - { "Lauchhm", 4, 7, 48, 0, 1999, }, - { "Nersingn", 4, 7, 49, 0, 1999, }, - { "Schnelld", 4, 7, 50, 0, 1999, }, - { "Ebnat 41", 4, 7, 51, 0, 1999, }, - { "Jungingn", 4, 7, 53, 0, 1999, }, - { "Laichi41", 4, 7, 55, 0, 1999, }, - { "Aalen 42", 4, 7, 57, 0, 1999, }, - { "Herbrech", 4, 7, 68, 0, 1999, }, - { "UL1 Bake", 4, 7, 70, 0, 1999, }, - { "Schoen43", 4, 7, 71, 0, 1999, }, - { "Schelkl1", 4, 7, 72, 0, 1999, }, - { "Deggin71", 4, 7, 73, 0, 1999, }, - { "Ochsenh1", 4, 7, 74, 0, 1999, }, - { "Giengen", 4, 7, 75, 0, 1999, }, - { "Seligwlr", 4, 7, 76, 0, 1999, }, - { "Boefingn", 4, 7, 77, 0, 1999, }, - { "Langena1", 4, 7, 78, 0, 1999, }, - { "Oehring3", 4, 7, 79, 0, 1999, }, - { "Blaust41", 4, 7, 80, 0, 1999, }, - { "Ulm 151", 4, 7, 82, 0, 1999, }, - { "Blaube41", 4, 7, 83, 0, 1999, }, - { "Ulm 172", 4, 7, 84, 0, 1999, }, - { "Ulm 141", 4, 7, 85, 0, 1999, }, - { "Erbach41", 4, 7, 86, 0, 1999, }, - { "Senden 0", 4, 7, 87, 0, 1999, }, - { "Weisenh0", 4, 7, 88, 0, 1999, }, - { "Lauphm 0", 4, 7, 90, 0, 1999, }, - { "Illerti0", 4, 7, 91, 0, 1999, }, - { "Biberac6", 4, 7, 92, 0, 1999, }, - { "Ehingen0", 4, 7, 93, 0, 1999, }, - { "Langenb1", 4, 7, 95, 0, 1999, }, - { "Weisweil", 6, 7, 99, 1991, 0, }, - { "Oammerga", 1, 8, 1, 0, 1999, }, - { "Schwinde", 1, 8, 2, 0, 1999, }, - { "BdAiblin", 1, 8, 3, 0, 1999, }, - { "Teisendf", 1, 8, 4, 1991, 1999, }, - { "Miesbach", 1, 8, 5, 0, 1999, }, - { "Oberaudf", 1, 8, 6, 0, 1999, }, - { "Ramsau 1", 1, 8, 7, 1991, 1999, }, - { "Reit iWi", 1, 8, 8, 1991, 1999, }, - { "BdReich2", 1, 8, 9, 1991, 1999, }, - { "Landau 3", 1, 8, 10, 1991, 1999, }, - { "Tann 2", 1, 8, 11, 1991, 1999, }, - { "Neufahrn", 1, 8, 12, 0, 1999, }, - { "Attenkir", 1, 8, 13, 0, 1999, }, - { "Olching", 1, 8, 14, 1991, 1999, }, - { "Seeshaup", 1, 8, 15, 0, 1999, }, - { "Wolfrats", 1, 8, 16, 1991, 1999, }, - { "Starnbe5", 1, 8, 17, 1991, 1999, }, - { "Tittmoni", 1, 8, 18, 1991, 1999, }, - { "Herrschi", 1, 8, 19, 1991, 1999, }, - { "Icking", 1, 8, 20, 1991, 1999, }, - { "BdReich1", 1, 8, 21, 1991, 1999, }, - { "Passau11", 1, 8, 22, 1991, 1999, }, - { "Pfarrkir", 1, 8, 23, 1991, 1999, }, - { "Anger", 1, 8, 24, 1991, 1999, }, - { "Obernzel", 1, 8, 25, 1991, 1999, }, - { "Hohenpbg", 1, 8, 26, 1991, 1999, }, - { "Garmisch", 1, 8, 27, 1991, 1999, }, - { "Grainet", 1, 8, 28, 1991, 1999, }, - { "Glonn 1", 1, 8, 29, 1991, 1999, }, - { "Taufkirc", 1, 8, 30, 0, 1999, }, - { "Freyung1", 1, 8, 31, 1991, 1999, }, - { "Mainburg", 1, 8, 32, 0, 1999, }, - { "Diessen2", 1, 8, 33, 0, 1999, }, - { "Berchtes", 1, 8, 34, 1991, 1999, }, - { "Ffeldbr2", 1, 8, 35, 0, 1999, }, - { "Neufinsi", 1, 8, 36, 0, 1999, }, - { "Murnau70", 1, 8, 37, 0, 1999, }, - { "Landsber", 1, 8, 38, 0, 1999, }, - { "Dingolf2", 1, 8, 39, 0, 1999, }, - { "Grafing", 1, 8, 40, 1991, 1999, }, - { "Muehldf", 1, 8, 41, 0, 1999, }, - { "Grassau2", 1, 8, 42, 0, 1999, }, - { "Ergoldsb", 1, 8, 43, 0, 1999, }, - { "Weyarn 3", 1, 8, 44, 0, 1999, }, - { "Hausham", 1, 8, 45, 0, 1999, }, - { "Freising", 1, 8, 46, 0, 1999, }, - { "Kochel 4", 1, 8, 47, 0, 1999, }, - { "Woerth 1", 1, 8, 48, 0, 1999, }, - { "Holzki62", 1, 8, 49, 0, 1999, }, - { "Dachau91", 1, 8, 50, 0, 1999, }, - { "Flughafn", 1, 8, 51, 0, 1999, }, - { "Petershs", 1, 8, 52, 1991, 1999, }, - { "Roehrmos", 1, 8, 53, 1991, 1999, }, - { "Ruhpold1", 1, 8, 54, 1991, 1999, }, - { "Geltendf", 1, 8, 55, 0, 1999, }, - { "Trostber", 1, 8, 56, 0, 1999, }, - { "Dorfen 1", 1, 8, 57, 1991, 1999, }, - { "Neufins.", 1, 8, 58, 1991, 0, }, - { "Dachau 3", 1, 8, 59, 1991, 1999, }, - { "Vilsbibg", 1, 8, 60, 1991, 1999, }, - { "Mallersd", 1, 8, 61, 0, 1999, }, - { "Mammendf", 1, 8, 62, 0, 1999, }, - { "Traunstn", 1, 8, 63, 1991, 1999, }, - { "MSchwab0", 1, 8, 64, 0, 1999, }, - { "Bernbeur", 1, 8, 65, 1991, 1999, }, - { "Landshut", 1, 8, 66, 1991, 1999, }, - { "Holzki 3", 1, 8, 67, 1991, 1999, }, - { "Rosenhm", 1, 8, 68, 1991, 1999, }, - { "Schnaits", 1, 8, 69, 1991, 1999, }, - { "Waakirch", 1, 8, 70, 1991, 1999, }, - { "Wasserbg", 1, 8, 71, 1991, 1999, }, - { "Prien", 1, 8, 72, 1991, 1999, }, - { "Waldkrai", 1, 8, 73, 1991, 1999, }, - { "Burghaus", 1, 8, 74, 1991, 1999, }, - { "Kirchsee", 1, 8, 75, 1991, 1999, }, - { "Ffeldbr0", 1, 8, 76, 0, 1999, }, - { "Moosinni", 1, 8, 77, 0, 1999, }, - { "Sulzemos", 1, 8, 78, 0, 1999, }, - { "Vilshofn", 1, 8, 79, 0, 1999, }, - { "BayrZell", 1, 8, 80, 0, 1999, }, - { "Reischac", 1, 8, 81, 0, 1999, }, - { "Simbach2", 1, 8, 84, 0, 1999, }, - { "Hauzenbg", 1, 8, 85, 0, 1999, }, - { "Sindlsdf", 1, 8, 86, 0, 1999, }, - { "Zolling", 1, 8, 90, 0, 1999, }, - { "Griesbch", 1, 8, 91, 0, 1999, }, - { "Kochel 1", 1, 8, 92, 0, 1999, }, - { "Isen 1", 1, 8, 93, 1991, 1999, }, - { "Tegernse", 1, 8, 94, 0, 1999, }, - { "Gangkofn", 1, 8, 95, 0, 1999, }, - { "Lenggrie", 1, 8, 96, 0, 1999, }, - { "Mitteln.", 1, 8, 97, 1991, 0, }, - { "Augsburg", 1, 8, 98, 1991, 0, }, - { "Pfeffenh", 1, 8, 99, 1991, 1999, }, - { "Planegg", 2, 8, 2, 0, 1999, }, - { "Studentn", 2, 8, 3, 0, 1999, }, - { "Ahornstr", 2, 8, 4, 0, 1999, }, - { "Oberhach", 2, 8, 5, 0, 1999, }, - { "Saurlach", 2, 8, 6, 0, 1999, }, - { "Vaterst1", 2, 8, 10, 0, 1999, }, - { "M18 Bake", 2, 8, 29, 1991, 1999, }, - { "Blumenst", 2, 8, 30, 1991, 1999, }, - { "Isabella", 2, 8, 31, 1991, 1999, }, - { "Arabella", 2, 8, 32, 1991, 1999, }, - { "Kirchens", 2, 8, 33, 1991, 1999, }, - { "Werinher", 2, 8, 34, 1991, 1999, }, - { "Blutenbu", 2, 8, 37, 1991, 1999, }, - { "Neuherbe", 2, 8, 38, 1991, 1999, }, - { "Am Luess", 2, 8, 39, 1991, 1999, }, - { "Rennbahn", 2, 8, 40, 1991, 1999, }, - { "HeinrLue", 2, 8, 41, 1991, 1999, }, - { "Seybotst", 2, 8, 42, 1991, 1999, }, - { "Baierbst", 2, 8, 43, 1991, 1999, }, - { "M.HansGW", 2, 8, 44, 1991, 0, }, - { "Winfried", 2, 8, 45, 1991, 1999, }, - { "M.Bresla", 2, 8, 46, 1991, 0, }, - { "M.Feldmo", 2, 8, 47, 1991, 0, }, - { "Thalkirc", 2, 8, 48, 1991, 1999, }, - { "PhRidler", 2, 8, 49, 1991, 1999, }, - { "M.Unterf", 2, 8, 50, 1991, 0, }, - { "Garching", 2, 8, 52, 0, 1999, }, - { "Gilching", 2, 8, 54, 0, 1999, }, - { "Germerin", 2, 8, 55, 1991, 1999, }, - { "Untersch", 2, 8, 57, 0, 1999, }, - { "Hoehenki", 2, 8, 58, 0, 1999, }, - { "Baierbrn", 2, 8, 61, 0, 1999, }, - { "Stiftsbo", 2, 8, 84, 0, 1999, }, - { "Alzeyers", 2, 8, 85, 0, 1999, }, - { "Augsbg 1", 3, 8, 1, 0, 1999, }, - { "Augsbg 3", 3, 8, 2, 0, 1999, }, - { "Augsbg10", 3, 8, 3, 0, 1999, }, - { "Pfronten", 3, 8, 4, 0, 1999, }, - { "Dilling0", 3, 8, 5, 0, 1999, }, - { "Affing 2", 3, 8, 6, 0, 1999, }, - { "Aichach", 3, 8, 7, 0, 1999, }, - { "Eichstae", 3, 8, 8, 0, 1999, }, - { "Dirlewng", 3, 8, 9, 0, 1999, }, - { "Eurasbg1", 3, 8, 10, 0, 1999, }, - { "Buchloe1", 3, 8, 11, 0, 1999, }, - { "Krumbach", 3, 8, 12, 0, 1999, }, - { "Meiting0", 3, 8, 13, 0, 1999, }, - { "Mittelnf", 3, 8, 14, 0, 1999, }, - { "Schrobhs", 3, 8, 15, 0, 1999, }, - { "Schwabmn", 3, 8, 16, 0, 1999, }, - { "Thannhsn", 3, 8, 17, 0, 1999, }, - { "Welden 3", 3, 8, 18, 0, 1999, }, - { "Ziemetsh", 3, 8, 19, 0, 1999, }, - { "Guenzb70", 3, 8, 20, 0, 1999, }, - { "Oberstd0", 3, 8, 21, 0, 1999, }, - { "Nesslwan", 3, 8, 22, 0, 1999, }, - { "Neuburg1", 3, 8, 23, 0, 1999, }, - { "Obrstauf", 3, 8, 24, 0, 1999, }, - { "Groenbch", 3, 8, 25, 0, 1999, }, - { "Zusmars2", 3, 8, 26, 0, 1999, }, - { "Fuessen2", 3, 8, 27, 0, 1999, }, - { "Lindau 1", 3, 8, 28, 0, 1999, }, - { "Augsbg 2", 3, 8, 29, 0, 1999, }, - { "Augsb907", 3, 8, 30, 0, 1999, }, - { "Stammham", 3, 8, 33, 0, 1999, }, - { "Ottobeu3", 3, 8, 34, 0, 1999, }, - { "Pfaffen5", 3, 8, 35, 0, 1999, }, - { "Pfaffen0", 3, 8, 36, 0, 1999, }, - { "Burgau 0", 3, 8, 37, 0, 1999, }, - { "Schweitk", 3, 8, 38, 0, 1999, }, - { "IngolZuc", 3, 8, 39, 0, 1999, }, - { "Vohburg1", 3, 8, 40, 0, 1999, }, - { "Wolnzach", 3, 8, 41, 0, 1999, }, - { "Tapfheim", 3, 8, 42, 0, 1999, }, - { "Unterrin", 3, 8, 43, 0, 1999, }, - { "Kaisheim", 3, 8, 44, 0, 1999, }, - { "Altensta", 3, 8, 51, 0, 1999, }, - { "Aitrang2", 3, 8, 52, 0, 1999, }, - { "Babenhsn", 3, 8, 54, 0, 1999, }, - { "Gruenenb", 3, 8, 55, 0, 1999, }, - { "Immensta", 3, 8, 57, 0, 1999, }, - { "Kaufbeur", 3, 8, 58, 0, 1999, }, - { "Memmingn", 3, 8, 59, 0, 1999, }, - { "Oguenzbg", 3, 8, 61, 0, 1999, }, - { "Sonthofn", 3, 8, 67, 0, 1999, }, - { "Weiler 1", 3, 8, 68, 0, 1999, }, - { "Wiggensb", 3, 8, 70, 0, 1999, }, - { "Neuburg", 3, 8, 78, 0, 1999, }, - { "Poernbch", 3, 8, 81, 0, 1999, }, - { "Arnstein", 1, 9, 1, 0, 1999, }, - { "BdSteben", 1, 9, 2, 0, 1999, }, - { "Bayr.Eis", 1, 9, 3, 0, 1999, }, - { "Berg 2", 1, 9, 4, 0, 1999, }, - { "Rottendf", 1, 9, 5, 0, 1999, }, - { "Werneck2", 1, 9, 6, 0, 1999, }, - { "Bayreuth", 1, 9, 7, 0, 1999, }, - { "Kulmbach", 1, 9, 8, 0, 1999, }, - { "Trockau", 1, 9, 9, 1991, 0, }, - { "Pressig", 1, 9, 10, 0, 1999, }, - { "Bi.gruen", 1, 9, 11, 0, 1999, }, - { "Hof 2", 1, 9, 12, 1991, 1999, }, - { "Kist 1", 1, 9, 13, 0, 1999, }, - { "Bodenwhr", 1, 9, 14, 0, 1999, }, - { "Burgleng", 1, 9, 15, 0, 1999, }, - { "Burgwind", 1, 9, 16, 0, 1999, }, - { "Buttenhm", 1, 9, 17, 0, 1999, }, - { "Iphofen", 1, 9, 18, 1991, 1999, }, - { "Cham", 1, 9, 19, 0, 1999, }, - { "Tauberbh", 1, 9, 20, 1991, 1999, }, - { "Unterple", 1, 9, 21, 1991, 1999, }, - { "Uettingn", 1, 9, 22, 1991, 1999, }, - { "Erbendor", 1, 9, 23, 0, 1999, }, - { "Deggendf", 1, 9, 24, 0, 1999, }, - { "ObThulb3", 1, 9, 25, 0, 1999, }, - { "Laaber", 1, 9, 26, 0, 1999, }, - { "Seubersd", 1, 9, 27, 0, 1999, }, - { "Riedenbu", 1, 9, 28, 0, 1999, }, - { "Obwerrn", 1, 9, 29, 0, 1999, }, - { "Abensber", 1, 9, 31, 0, 1999, }, - { "Hemau", 1, 9, 32, 0, 1999, }, - { "Hirschau", 1, 9, 33, 0, 1999, }, - { "Hofheim", 1, 9, 34, 0, 1999, }, - { "Karlstdt", 1, 9, 35, 0, 1999, }, - { "Kelheim", 1, 9, 36, 0, 1999, }, - { "Bamberg6", 1, 9, 37, 0, 1999, }, - { "Obaurach", 1, 9, 38, 0, 1999, }, - { "Pfarrwei", 1, 9, 39, 0, 1999, }, - { "Kirchlau", 1, 9, 40, 0, 1999, }, - { "Schessli", 1, 9, 41, 0, 1999, }, - { "Zapfendf", 1, 9, 42, 0, 1999, }, - { "Beratzhs", 1, 9, 43, 0, 1999, }, - { "Rehau 1", 1, 9, 44, 0, 1999, }, - { "NeustdCO", 1, 9, 45, 0, 1999, }, - { "Kronach", 1, 9, 46, 0, 1999, }, - { "Langquai", 1, 9, 47, 0, 1999, }, - { "Amberg", 1, 9, 48, 0, 1999, }, - { "Pleystei", 1, 9, 49, 0, 1999, }, - { "LaudaKoe", 1, 9, 50, 0, 1999, }, - { "Lichtenf", 1, 9, 51, 0, 1999, }, - { "Muenners", 1, 9, 53, 0, 1999, }, - { "Meeder", 1, 9, 54, 0, 1999, }, - { "BdKissin", 1, 9, 55, 0, 1999, }, - { "Hammelbu", 1, 9, 56, 1991, 1999, }, - { "Mktheid2", 1, 9, 59, 0, 1999, }, - { "Straubin", 1, 9, 60, 0, 1999, }, - { "Schoefwg", 1, 9, 61, 0, 1999, }, - { "Koetztin", 1, 9, 62, 0, 1999, }, - { "Illschwa", 1, 9, 64, 0, 1999, }, - { "Oberbach", 1, 9, 66, 0, 1999, }, - { "Oberviec", 1, 9, 67, 0, 1999, }, - { "Ochsnft3", 1, 9, 68, 0, 1999, }, - { "Pfatter", 1, 9, 69, 0, 1999, }, - { "Regensb1", 1, 9, 70, 0, 1999, }, - { "Regensb4", 1, 9, 71, 0, 1999, }, - { "Schweinf", 1, 9, 72, 0, 1999, }, - { "Selb 1", 1, 9, 73, 0, 1999, }, - { "Stallwan", 1, 9, 74, 0, 1999, }, - { "BdKoenig", 1, 9, 75, 0, 1999, }, - { "Alladorf", 1, 9, 76, 0, 1999, }, - { "Tirschen", 1, 9, 77, 0, 1999, }, - { "Waldmuen", 1, 9, 78, 0, 1999, }, - { "Weiden", 1, 9, 79, 0, 1999, }, - { "WGamburg", 1, 9, 80, 0, 1999, }, - { "Wiesenth", 1, 9, 81, 0, 1999, }, - { "Wuerzbg2", 1, 9, 82, 0, 1999, }, - { "Wunsiedl", 1, 9, 83, 0, 1999, }, - { "Zell2 OF", 1, 9, 84, 0, 1999, }, - { "Trockau1", 1, 9, 85, 0, 1999, }, - { "Mitterfs", 1, 9, 87, 0, 1999, }, - { "Nabburg2", 1, 9, 88, 0, 1999, }, - { "Obernses", 1, 9, 90, 0, 1999, }, - { "Roding 1", 1, 9, 91, 0, 1999, }, - { "Gerchsh1", 1, 9, 93, 0, 1999, }, - { "Coburg", 1, 9, 94, 0, 1999, }, - { "DB Karls", 1, 9, 96, 0, 1999, }, - { "DB Wuerz", 1, 9, 97, 0, 1999, }, - { "Waldsass", 1, 9, 98, 0, 1999, }, - { "Zell 1BW", 1, 9, 99, 0, 1999, }, - { "Nuernbg0", 2, 9, 1, 0, 1999, }, - { "Miltenb.", 2, 9, 2, 1991, 0, }, - { "Unterri.", 2, 9, 3, 1991, 0, }, - { "N5 Bake", 2, 9, 4, 1991, 1999, }, - { "Nennslin", 2, 9, 5, 1991, 1999, }, - { "Betzenst", 2, 9, 6, 1991, 1999, }, - { "Alladorf", 2, 9, 7, 1991, 0, }, - { "Zell", 2, 9, 8, 1991, 0, }, - { "Schnaitt", 2, 9, 9, 1991, 1999, }, - { "Wiesent.", 2, 9, 11, 1991, 0, }, - { "Regensb.", 2, 9, 12, 1991, 0, }, - { "Hemau", 2, 9, 13, 1991, 0, }, - { "Rothenbu", 2, 9, 14, 1991, 1999, }, - { "Buttenh.", 2, 9, 15, 1991, 0, }, - { "Hofheim", 2, 9, 16, 1991, 0, }, - { "Meeder", 2, 9, 17, 1991, 0, }, - { "Weiden", 2, 9, 18, 1991, 0, }, - { "Roth 0", 2, 9, 19, 1991, 1999, }, - { "Altdorf", 2, 9, 20, 1991, 1999, }, - { "Feucht", 2, 9, 21, 0, 1999, }, - { "Bischof.", 2, 9, 22, 1991, 0, }, - { "Ansbach", 2, 9, 23, 1991, 1999, }, - { "Deggend.", 2, 9, 25, 1991, 0, }, - { "Bay.Eis.", 2, 9, 26, 1991, 0, }, - { "OPD", 2, 9, 27, 1991, 1999, }, - { "Marienbg", 2, 9, 28, 1991, 1999, }, - { "Nbg Thus", 2, 9, 29, 1991, 0, }, - { "BfArbeit", 2, 9, 30, 1991, 1999, }, - { "HeizKW", 2, 9, 31, 1991, 1999, }, - { "Eschenbc", 2, 9, 32, 0, 1999, }, - { "M.Verlag", 2, 9, 33, 1991, 1999, }, - { "Lauf", 2, 9, 34, 1991, 1999, }, - { "Postbaur", 2, 9, 35, 1991, 1999, }, - { "Schwaba5", 2, 9, 36, 1991, 1999, }, - { "HerzogAu", 2, 9, 37, 1991, 1999, }, - { "Langenzn", 2, 9, 38, 1991, 1999, }, - { "Erlangn1", 2, 9, 39, 1991, 1999, }, - { "Kronach", 2, 9, 40, 1991, 0, }, - { "FuerthCi", 2, 9, 41, 0, 1999, }, - { "Stadeln", 2, 9, 42, 0, 1999, }, - { "Tr.Adler", 2, 9, 43, 1991, 1999, }, - { "Siegelsd", 2, 9, 44, 1991, 1999, }, - { "Rosstal", 2, 9, 45, 1991, 1999, }, - { "ER98 GWE", 2, 9, 46, 0, 1999, }, - { "Burglen.", 2, 9, 47, 1991, 0, }, - { "Cham", 2, 9, 48, 1991, 0, }, - { "SulzbRos", 2, 9, 49, 0, 1999, }, - { "Obervie.", 2, 9, 50, 1991, 0, }, - { "Eckental", 2, 9, 51, 0, 1999, }, - { "Gemuend.", 2, 9, 52, 1991, 0, }, - { "Pumpwerk", 2, 9, 53, 0, 1999, }, - { "Wendelst", 2, 9, 54, 0, 1999, }, - { "Schweinf", 2, 9, 55, 1991, 0, }, - { "ER60Tenn", 2, 9, 56, 0, 1999, }, - { "Wunsied.", 2, 9, 57, 1991, 0, }, - { "BPolizei", 2, 9, 58, 0, 1999, }, - { "Hessdorf", 2, 9, 60, 0, 1999, }, - { "Treuchtl", 2, 9, 61, 0, 1999, }, - { "Solnhofn", 2, 9, 62, 0, 1999, }, - { "Pommelsb", 2, 9, 63, 0, 1999, }, - { "Neustadt", 2, 9, 64, 1991, 1999, }, - { "Langenfd", 2, 9, 65, 1991, 1999, }, - { "AlbThaer", 2, 9, 66, 0, 1999, }, - { "Graefenb", 2, 9, 67, 0, 1999, }, - { "Hoechstd", 2, 9, 68, 0, 1999, }, - { "Ebermann", 2, 9, 69, 0, 1999, }, - { "Schwaba0", 2, 9, 70, 0, 1999, }, - { "Uffenhm", 2, 9, 71, 0, 1999, }, - { "Wilherms", 2, 9, 72, 0, 1999, }, - { "Thalmae2", 2, 9, 73, 0, 1999, }, - { "Wittelsh", 2, 9, 74, 0, 1999, }, - { "Windsbac", 2, 9, 76, 0, 1999, }, - { "Gunzenhs", 2, 9, 78, 0, 1999, }, - { "Allersbg", 2, 9, 79, 0, 1999, }, - { "Wiesentl", 2, 9, 80, 0, 1999, }, - { "Esselb.", 2, 9, 81, 1991, 0, }, - { "Forchhei", 2, 9, 82, 0, 1999, }, - { "Heilsbrn", 2, 9, 85, 0, 1999, }, - { "Altenbg", 2, 9, 86, 0, 1999, }, - { "Muehlhsn", 2, 9, 88, 0, 1999, }, - { "Kelheim", 2, 9, 91, 1991, 0, }, - { "Kipfenbg", 2, 9, 93, 0, 1999, }, - { "Burgbern", 2, 9, 94, 1991, 1999, }, - { "Lichtenf", 2, 9, 98, 1991, 0, }, - { "Greding", 2, 9, 99, 1991, 1999, }, - { "FTZ Example",1, 1, 38, 1991, 0, }, /* use in FTZ standard as example */ - { "", 0, 0, 0, 0, 0, }, +/* Langer-Name Kurzer Name, Nat FuVST Rest */ + { "Oberhausen 32", "OB32", 1, 2, 1, }, + { "Oberhausen 0 <prov.>", "OB0", 1, 2, 5, }, + { "Wuppertal 18", "WUP18", 1, 2, 6, }, + { "Oberhausen 21", "OB21", 1, 2, 7, }, + { "Duisburg 21", "DUI21", 1, 2, 8, }, + { "Heiligenhaus 0", "HEIL0", 1, 2, 9, }, + { "Essen 1 <Fernmeldeamt>", "ES1", 1, 2, 10, }, + { "Velbert-Langenberg 2", "VELL2", 1, 2, 11, }, + { "Duisburg 40 <Ers.f.OB16>", "DUI40", 1, 2, 12, }, + { "Bottrop 0", "BOT0", 1, 2, 13, }, + { "Gelsenkirchen 1", "GSK1", 1, 2, 14, }, + { "Essen 35", "ES35X", 1, 2, 15, }, + { "Duisburg 25", "DUI25", 1, 2, 16, }, + { "Velbert-Neviges", "VELN", 1, 2, 17, }, + { "Wuppertal 30", "WUP30", 1, 2, 18, }, + { "Essen 28 (Borbeck)", "ESBCK", 1, 2, 19, }, + { "Kirchhellen 4", "KIRCH", 1, 2, 20, }, + { "Gelsenkirchen 7", "GSK7", 1, 2, 21, }, + { "Wuppertal 34", "WUP34", 1, 2, 22, }, + { "Wuppertal 35 <Rheinshagen>", "WUPE11", 1, 2, 23, }, + { "Oberhausen 23", "OB23", 1, 2, 24, }, + { "Velbert-Neviges 4", "WFRTH3", 1, 2, 25, }, + { "Duisburg 42 <Ers.f.DUI39>", "DUI42", 1, 2, 26, }, + { "Rheinhausen 0", "RHSN0", 1, 2, 27, }, + { "Essen 12", "ES12", 1, 2, 28, }, + { "Homberg 1", "HOMB1", 1, 2, 29, }, + { "Rees-Mehr 0", "REME0", 1, 2, 30, }, + { "Essen 13", "ES13", 1, 2, 31, }, + { "Essen 15", "ES15", 1, 2, 32, }, + { "Heiden 1", "HEID0", 1, 2, 33, }, + { "Voerde 2", "VOER2", 1, 2, 34, }, + { "Duisburg 0", "DUI0", 1, 2, 35, }, + { "Velbert 1 <20 Grad geneigt>", "VEL1", 1, 2, 36, }, + { "Oberhausen 26", "OB26", 1, 2, 37, }, + { "Gelsenkirchen 58", "GSK58", 1, 2, 38, }, + { "Essen 8", "ES8", 1, 2, 39, }, + { "Wuppertal 8 (Hahnerberg)", "WUP8", 1, 2, 40, }, + { "Oberhausen 18 (Heimaterde)", "OB18", 1, 2, 41, }, + { "Oberhausen 30 (Osterfeld)", "OB30", 1, 2, 43, }, + { "Wesel 0 <Mischbake>", "WSL", 1, 2, 44, }, + { "Borken 0", "BOR0", 1, 2, 45, }, + { "Velen 20", "RSDF", 1, 2, 46, }, + { "Bocholt 0", "BOH0", 1, 2, 47, }, + { "Huenxe 1", "HXE0", 1, 2, 48, }, + { "Isselburg 1", "ISSB99", 1, 2, 49, }, + { "Emmerich-Elten 1", "ELT1X", 1, 2, 50, }, + { "Bochum-Wattenscheid 3", "BOC3", 1, 2, 51, }, + { "Dorsten 0", "DSTN0", 1, 2, 52, }, + { "Schermbeck 2", "SBCK", 1, 2, 53, }, + { "Raesfeld 2 (Erle)", "RAEF0", 1, 2, 54, }, + { "Wuppertal 4 (Beyenburg)", "WUP4", 1, 2, 55, }, + { "Hueckeswagen 2", "HUECK1", 1, 2, 57, }, + { "Herne 1", "HER", 1, 2, 58, }, + { "Bochum 47", "BOC47", 1, 2, 59, }, + { "Hattingen 9 (Holthausen)", "HATT", 1, 2, 60, }, + { "Sprockhoevel 71 (12Grad gen.)", "HATT71", 1, 2, 61, }, + { "Gladbeck 20", "GLAD20", 1, 2, 62, }, + { "Ahaus 0", "AH0", 1, 2, 63, }, + { "Bochum 1 <Ant. 20 grad gen.>", "BOC1", 1, 2, 64, }, + { "Herten 0.80D1 <Zeche Ewald>", "HERT", 1, 2, 66, }, + { "Oberhausen 1", "OB1", 1, 2, 68, }, + { "Dorsten-Wulfen 0", "DORS0", 1, 2, 70, }, + { "Essen 0 (Kettwig)", "ESKTW", 1, 2, 76, }, + { "Vreden 0", "VRDN0", 1, 2, 79, }, + { "Gronau 0", "GRON0", 1, 2, 81, }, + { "Dinslaken 2", "DIN2", 1, 2, 82, }, + { "Bochum 78 (Stiepel)<neu>", "BOC78", 1, 2, 84, }, + { "Bochum 0", "BOC0", 1, 2, 88, }, + { "Oberhausen 9 (Bake)", "OB9", 1, 2, 89, }, + { "Coesfeld 0", "COE0", 1, 2, 92, }, + { "Schoeppingen 1", "SPP12", 1, 2, 93, }, + { "Stadtlohn 1", "STLN1", 1, 2, 98, }, + { "Wuppertal 2 (Bake)", "WUP2", 1, 2, 99, }, + { "Raegelin 1", "DKOW", 1, 3, 1, }, + { "Fuerstenberg 1", "FTBG", 1, 3, 3, }, + { "Maerkisch-Buchholz 3", "MAS", 1, 3, 4, }, + { "Beeskow 0", "BEES", 1, 3, 5, }, + { "Finowfurt 1", "EBSW", 1, 3, 6, }, + { "Blnklz 503 Bernau 6 (B-Aue)", "BKLZ37", 1, 3, 7, }, + { "Ziesar 0 <Ers.f.TRANS3>", "ZIES0", 1, 3, 8, }, + { "Wittenberge 4", "WIBG", 1, 3, 9, }, + { "Blnklz 505(Werder Havel 1)", "TRANS5", 1, 3, 10, }, + { "Seelow 4", "SEEL", 1, 3, 11, }, + { "Blnklz 313(Treseburger Str)", "BKLZ47", 1, 3, 12, }, + { "Briesen 0", "BRIE", 1, 3, 13, }, + { "Perleberg 4", "PLBG", 1, 3, 14, }, + { "Muencheberg 4", "MUEN4", 1, 3, 15, }, + { "Herzfelde 3", "HF3", 1, 3, 16, }, + { "Storkow 4 <Ers.f.STOR>", "STORK", 1, 3, 17, }, + { "Neubrandenburg 14", "NBBG", 1, 3, 18, }, + { "Treuenbrietzen 0", "TREUB", 1, 3, 19, }, + { "Prenzlau 3", "PZL", 1, 3, 20, }, + { "Pasewalk 2", "PAWA2", 1, 3, 22, }, + { "NaumbgRi ???", "???", 1, 3, 23, }, + { "Rathenow 4", "RATH4", 1, 3, 24, }, + { "Blnklz 414(B.-Apitz-Str7)", "BKLZ54", 1, 3, 26, }, + { "Blnklz 406(Jaegerstieg)", "B25", 1, 3, 27, }, + { "Templin 2", "TPL", 1, 3, 28, }, + { "Luckenwalde 2", "LCKW", 1, 3, 29, }, + { "Lehnin 0", "LEHN0", 1, 3, 30, }, + { "Frankfurt/Oder 10", "FFO", 1, 3, 31, }, + { "Blnklz 604 (Michendorf)", "MICHD", 1, 3, 32, }, + { "Trebbin 2", "LWD", 1, 3, 33, }, + { "Gramzow 2", "GRAM0", 1, 3, 35, }, + { "Bad Freienwalde 0", "PLF", 1, 3, 36, }, + { "Falkenhage 4", "PRD", 1, 3, 37, }, + { "Fuerstenwalde 7", "RBG", 1, 3, 38, }, + { "Angermuende 7", "TLF", 1, 3, 39, }, + { "Wittstock 5", "WTT", 1, 3, 40, }, + { "Dambeck 2", "WOZ", 1, 3, 41, }, + { "Neuzelle 3", "EIHS", 1, 3, 42, }, + { "Raben 1", "RAB", 1, 3, 43, }, + { "Toepchin 3", "TOEP3", 1, 3, 44, }, + { "Brandenburg 16", "BDB", 1, 3, 45, }, + { "Jueterbog 4", "JTB", 1, 3, 46, }, + { "Brandenburg 2<Ers.f.TRANS4>", "KRAN", 1, 3, 47, }, + { "Lieberose 1", "LIEB99", 1, 3, 48, }, + { "Wiesenburg Mark 0", "WIESB", 1, 3, 49, }, + { "Mirow 1", "MIROW", 1, 3, 50, }, + { "Rhinow 1", "RNOW", 1, 3, 51, }, + { "Rheinsberg 3", "ZHLN", 1, 3, 52, }, + { "Petkus 3", "PETK", 1, 3, 53, }, + { "Blankensee 1", "KEUL", 1, 3, 54, }, + { "Neustrelitz 6", "NEUST6", 1, 3, 55, }, + { "Greifenberg 1", "GREI1", 1, 3, 57, }, + { "Pritzwalk 6", "PTZW", 1, 3, 58, }, + { "Schwedt 6", "SCHDT", 1, 3, 59, }, + { "Schmoelln 1", "SMLL", 1, 3, 62, }, + { "Woldegk 4", "WOCK", 1, 3, 65, }, + { "Neuruppin 6", "NRP", 1, 3, 66, }, + { "Belzig 2", "BELZ", 1, 3, 67, }, + { "Gransee 1", "GRAS", 1, 3, 69, }, + { "Kyritz 4", "KYRZ", 1, 3, 70, }, + { "Gross Doelln 0", "GDOE", 1, 3, 71, }, + { "Premnitz 0", "RATH", 1, 3, 72, }, + { "Gloewen 2", "GLOE2", 1, 3, 73, }, + { "Luebben 2", "LBN", 1, 3, 74, }, + { "Blnklz 502(Bestensee 3)", "BKLZ38", 1, 3, 76, }, + { "Blnklz 504(Pausin 1)", "BKLZ39", 1, 3, 77, }, + { "Golssen 0", "GOLN0", 1, 3, 78, }, + { "Luebbenau 2", "LUEB2", 1, 3, 79, }, + { "Blnklz 410(Alt-Mahlsdorf)", "BKLZ51", 1, 3, 80, }, + { "Blnklz 412(Eichhorster S.)", "BKLZ53", 1, 3, 81, }, + { "Blnklz 416(Muehlenbeck 2)", "BKLZ55", 1, 3, 83, }, + { "Blnklz 417(Hennigsdorf 0)", "BKLZ63", 1, 3, 84, }, + { "Blnklz 506(Ludwigsfelde 3)", "BKLZ57", 1, 3, 86, }, + { "Blnklz 507(Ruedersdorf 1)", "BKLZ58", 1, 3, 87, }, + { "Blnklz 508(Strausberg 1)", "BKLZ59", 1, 3, 88, }, + { "Blnklz 509(Zossen 5)", "BKLZ60", 1, 3, 89, }, + { "Blnklz 510(Mahlow 4)", "BKLZ72", 1, 3, 90, }, + { "Blnklz 511(Bernau 3)", "BKLZ64", 1, 3, 91, }, + { "Blnklz 513(Oranienburg 3)", "BKLZ65", 1, 3, 92, }, + { "Blnklz 514(Falkensee 1)", "BKLZ66", 1, 3, 93, }, + { "Liebenwalde 2", "LIEBW2", 1, 3, 94, }, + { "Eberswalde 8", "EBSW8", 1, 3, 96, }, + { "Blnklz 512(Erkner 8)", "BKLZ81", 1, 3, 97, }, + { "Blnklz 515(KWH 2)", "BKLZ74", 1, 3, 98, }, + { "Blnklz 605(Fichtenwalde 1)", "BKLZ70", 1, 3, 99, }, + { "Reinfeld 10", "REIF10", 1, 4, 3, }, + { "Gudow 10", "GUD0", 1, 4, 9, }, + { "Travemuende 7", "TRV7", 1, 4, 10, }, + { "Kiel 2", "KIL2", 1, 4, 11, }, + { "Rendsburg 2 (Preus.Elekt)", "RDB", 1, 4, 17, }, + { "Nortorf 4", "NORTO4", 1, 4, 18, }, + { "Freienwill 4", "FRW4", 1, 4, 19, }, + { "Westerland 0", "WLD0", 1, 4, 20, }, + { "Heide Holst 2", "HEI2", 1, 4, 22, }, + { "Hennstedt b Itzehoe 1", "HNI1", 1, 4, 23, }, + { "Bredstedt 3", "BST3", 1, 4, 24, }, + { "Brunsbuettel 1", "BRB1", 1, 4, 30, }, + { "Luebeck 2", "LCK2", 1, 4, 31, }, + { "Luebeck 4", "LCK4", 1, 4, 32, }, + { "Itzehoe 2 (Polizei)", "ITZH", 1, 4, 36, }, + { "Glueckstadt 1", "GLS1", 1, 4, 40, }, + { "Ploen 1", "PLN2", 1, 4, 44, }, + { "Burg/Fehmarn 1", "FEHM1", 1, 4, 46, }, + { "Hartenholm 0", "HHLM0", 1, 4, 50, }, + { "Daenischenhagen 1", "DAEN1", 1, 4, 52, }, + { "Luebeck 9", "LCK9", 1, 4, 53, }, + { "Henstedt-Ulzburg 4", "HNU4", 1, 4, 55, }, + { "Luebeck 23", "LCK23", 1, 4, 56, }, + { "Schoenwalde 1", "SCE1", 1, 4, 57, }, + { "Ratzeburg 1", "RATZ1", 1, 4, 58, }, + { "Schwarzenbek 1", "SWB1", 1, 4, 59, }, + { "Elmshorn 10", "EHN10", 1, 4, 61, }, + { "Eckernfoerde 5", "ECKF5", 1, 4, 62, }, + { "Husum 0", "HUS0", 1, 4, 66, }, + { "Marne 0", "MARN0", 1, 4, 72, }, + { "Neumuenster 10", "NEUM10", 1, 4, 73, }, + { "Suederluegum 1", "SUED1", 1, 4, 76, }, + { "Garding 1", "GARD1", 1, 4, 81, }, + { "Hohenfelde 0", "HFLD0", 1, 4, 82, }, + { "Ahrensboek 1", "ABK0", 1, 4, 83, }, + { "Schleswig 4", "SLWG4", 1, 4, 86, }, + { "Wankendorf", "WAN", 1, 4, 90, }, + { "Wyk/Foehr 0", "WYK", 1, 4, 94, }, + { "Bad Segeberg 0", "BSE0", 1, 4, 95, }, + { "Kappeln 1", "KPN1", 1, 4, 96, }, + { "Suelfeld 1", "SFD1", 1, 4, 99, }, + { "Hamburg 22 (Lagerstr.2)", "H22", 2, 4, 1, }, + { "Buxtehude 0", "BUX0", 2, 4, 2, }, + { "Buchholz 0 (Nordheide)", "BUCH0", 2, 4, 3, }, + { "Egestorf 1", "EGT1", 2, 4, 4, }, + { "Lueneburg 3", "LUE3", 2, 4, 5, }, + { "Marxen 2 (Ramelsloh)", "MARX2", 2, 4, 6, }, + { "Wulfsen 10", "WULF10", 2, 4, 8, }, + { "Pinneberg 7 (Z 31)", "HHKL31", 2, 4, 9, }, + { "Hamburg 291 (Barsbuet. Z 43)", "HHKL43", 2, 4, 10, }, + { "Hamburg 141 (Poppenbue.Z 41)", "PBTL", 2, 4, 11, }, + { "Hamburg 184 (Allerm. Z 42)", "H159", 2, 4, 12, }, + { "Hamburg 282 (PA90 Harb.Z44)", "HRBG", 2, 4, 13, }, + { "Sauensiek 0", "SAUS0", 2, 4, 14, }, + { "Betzendorf 1", "BETZ1", 2, 4, 15, }, + { "Tostedt 0", "TOST0", 2, 4, 17, }, + { "Hamburg 256 (Philips Z 38)", "HHKL38", 2, 4, 18, }, + { "Hamburg 316 (Klockm. Z 56)", "HHKL56", 2, 4, 24, }, + { "Hamburg 650 (Bauerbgwg Z66)", "HHKL66", 2, 4, 25, }, + { "Trittau 10", "TTAU10", 2, 4, 26, }, + { "Hamburg 104 (PA2 Z 0)", "HHKL0", 2, 4, 27, }, + { "Hamburg PA701(Wandsb. Z 67)", "HHKL67", 2, 4, 28, }, + { "Hamburg 105 (Schulgwg.Z 12)", "HHKL12", 2, 4, 30, }, + { "Hamburg 261 (Altona Z 13)", "HHKL13", 2, 4, 31, }, + { "Hamburg 257 (Fachhsch.Z 14)", "HHKL14", 2, 4, 32, }, + { "Hamburg 1 (FVSt Z 15)", "HHKL15", 2, 4, 33, }, + { "Hamburg 12 (FVSt 42 Z 16)", "HHKL16", 2, 4, 34, }, + { "Hamburg 133 (Modezent.Z 21)", "HHKL21", 2, 4, 35, }, + { "Hamburg 531 (Langenh. Z 69)", "LANGH", 2, 4, 36, }, + { "Hamburg 259 (Acht.Born Z23)", "HHKL23", 2, 4, 37, }, + { "Hamburg 77 (Finkenw. Z 24)", "HHKL24", 2, 4, 38, }, + { "Hamburg 76 (Waltersh.Z 25)", "HHKL25", 2, 4, 39, }, + { "Hamburg 5891B (Wilhelmsb.)", "WILHB", 2, 4, 40, }, + { "Hamburg 60 (Rothenb. Z 27)", "HHKL27", 2, 4, 41, }, + { "Hamburg 6 (Hamm Z 28)", "HHKL28", 2, 4, 42, }, + { "Hamburg 46 (Steilsh. Z 29)", "HHKL29", 2, 4, 43, }, + { "Hamburg 326 (Ammersbk.Z 70)", "OHLS", 2, 4, 44, }, + { "Hamburg 263 (NeuWulmst.Z34)", "HHKL34", 2, 4, 47, }, + { "Seevetal 3 (Z 35)", "HHKL35", 2, 4, 48, }, + { "Rosengarten 1 (Z 36)", "HHKL36", 2, 4, 49, }, + { "Hamburg 24 (R.LindeWg.Z37)", "HHKL37", 2, 4, 50, }, + { "Hamburg 65 (Norderst.Z 39)", "HHKL39", 2, 4, 52, }, + { "Hamburg 260 (FA 4 Z 11)", "HHKL11", 2, 4, 53, }, + { "Hamburg 258 (Randowstr.Z22)", "HHKL22", 2, 4, 54, }, + { "Marschacht 10", "MSCH0", 2, 4, 56, }, + { "Winsen/Luhe 0", "WINS0", 2, 4, 58, }, + { "Ahrensburg 11 (Z 46)", "SIK1", 2, 4, 60, }, + { "Wedel 11", "WDL11", 2, 4, 64, }, + { "Hamburg 306 (Marmstorf Z47)", "HHKL70", 2, 4, 68, }, + { "Hollenstedt 10", "HSTD1", 2, 4, 69, }, + { "Uetersen 2", "UETS2", 2, 4, 70, }, + { "Bad Oeynhausen", "BOEY0", 1, 5, 2, }, + { "Bad Salzuflen 5", "SUFL", 1, 5, 3, }, + { "Bohmte 0", "BOTE0", 1, 5, 4, }, + { "Buende 2", "BUEN2", 1, 5, 5, }, + { "Delbrueck 1", "DELB", 1, 5, 6, }, + { "Extertal 2", "EXT2", 1, 5, 7, }, + { "Bad Pyrmont 1", "PYR1", 1, 5, 9, }, + { "Luegde-Rischenau 1", "LGR1", 1, 5, 10, }, + { "Ibbenbueren 4", "IBB", 1, 5, 11, }, + { "Bramsche-Engter 1", "BME1", 1, 5, 12, }, + { "Barnstorf 0", "BARN0", 1, 5, 13, }, + { "Herford 4", "HFS", 1, 5, 14, }, + { "Luebbecke 1", "LBBK1", 1, 5, 16, }, + { "Lingen 0", "LIN", 1, 5, 17, }, + { "Bielefeld 0", "BFD0", 1, 5, 18, }, + { "Lindern 1", "LRN1", 1, 5, 19, }, + { "Oerlinghausen 2", "OERL2", 1, 5, 20, }, + { "Guetersloh-Friedrichsdorf 0", "GTL99", 1, 5, 22, }, + { "Paderborn 0", "PB0", 1, 5, 23, }, + { "Hoevelhof 0", "HOEVH", 1, 5, 24, }, + { "Lemgo 2", "LEMG2", 1, 5, 25, }, + { "Bad Iburg 2", "BIB2", 1, 5, 26, }, + { "Dissen 1", "DIS1", 1, 5, 27, }, + { "Melle-Buer 1", "MLB1", 1, 5, 28, }, + { "Fuerstenau 0", "FUE0", 1, 5, 29, }, + { "Bad Bentheim 2", "BBM2", 1, 5, 30, }, + { "Uchte 0", "UCH0", 1, 5, 32, }, + { "Bielefeld-Joellenbeck 0", "BFDJ", 1, 5, 33, }, + { "Bad Lippspringe 0", "BLPS0", 1, 5, 34, }, + { "Steinhagen 0", "STHG0", 1, 5, 35, }, + { "Spenge 0", "SPENG0", 1, 5, 37, }, + { "Berge 0", "BERGE", 1, 5, 38, }, + { "Minden 0", "MIN0", 1, 5, 40, }, + { "Osnabrueck 8", "OS8", 1, 5, 41, }, + { "Osnabrueck 0", "OS0", 1, 5, 42, }, + { "Rahden 0", "RAHD0", 1, 5, 44, }, + { "Rheda-Wiedenbrueck 7", "RHDA4", 1, 5, 45, }, + { "Emlichheim 0", "WILS1", 1, 5, 48, }, + { "Tecklenburg 1", "TE1", 1, 5, 50, }, + { "Blomberg 99 (Nassengrund)", "BGNG99", 1, 5, 52, }, + { "Bad Driburg 99", "BDBG99", 1, 5, 54, }, + { "Harsewinkel 97", "HARS99", 1, 5, 55, }, + { "Horn Bad Meinberg 1", "BMBG1", 1, 5, 56, }, + { "Nordhorn 0", "NDHN0", 1, 5, 59, }, + { "Guetersloh 0", "GTLH0", 1, 5, 60, }, + { "Damme 1", "DAM1", 1, 5, 61, }, + { "Meppen 0", "MEP0", 1, 5, 62, }, + { "Rheine 0", "RHE0", 1, 5, 63, }, + { "Bielefeld 1", "BFD1", 1, 5, 92, }, + { "Minden 2", "MIN2", 1, 5, 95, }, + { "Worms 7 (Autobahn)", "FKLZ52", 1, 6, 1, }, + { "Westhofen Rheinhess 1", "FKLZ54", 1, 6, 2, }, + { "Bensheim 0", "FKLZ56", 1, 6, 3, }, + { "Seeheim 2", "FKLZ57", 1, 6, 5, }, + { "Mosbach Baden 6", "HNKL21", 1, 6, 6, }, + { "Eberbach 1", "HNKL22", 1, 6, 7, }, + { "Lambrecht Pfalz 1", "LAMB1", 1, 6, 8, }, + { "Weidenthal Pfalz 3", "WDTL3", 1, 6, 9, }, + { "Bad Kreuznach 5<wird opt>", "BKZ5", 1, 6, 10, }, + { "Annweiler a Trifels 1", "ANNW", 1, 6, 11, }, + { "Wilhelmsfeld 2", "WHF2", 1, 6, 12, }, + { "Alzey 1", "FKLZ51", 1, 6, 13, }, + { "Mudau 1", "MUD1", 1, 6, 14, }, + { "Kaiserslautern 2", "KL2", 1, 6, 15, }, + { "Bad Bergzabern 5", "BBZN2", 1, 6, 22, }, + { "Wiesloch 3", "KAKL35", 1, 6, 24, }, + { "Hockenheim 2", "HOCK2", 1, 6, 25, }, + { "Beerfelden 1", "AISCH", 1, 6, 26, }, + { "Hartberg 5 (HR)", "HARTB5", 1, 6, 27, }, + { "Ahorn Baden 1", "EUB1", 1, 6, 28, }, + { "Schefflenz 2 (Rittersb.)", "SFL2", 1, 6, 29, }, + { "Michelstadt 7", "MICH1", 1, 6, 30, }, + { "Mannheim 12(Friedrichsfeld)", "KAKL55", 1, 6, 31, }, + { "Lindenfels 1", "FKLZ55", 1, 6, 32, }, + { "Moeckmuehl 1", "HNKL01", 1, 6, 34, }, + { "Meisenheim 6", "MEIS6", 1, 6, 35, }, + { "Odernheim 2", "ODH2", 1, 6, 36, }, + { "Guntersblum 3", "GUN3", 1, 6, 37, }, + { "Flonheim 1", "FLON1", 1, 6, 38, }, + { "Neutsch (Ruhrgas)", "NEUT", 1, 6, 40, }, + { "Schoenau 3 (Hl.Kreuz.)", "WHF1", 1, 6, 42, }, + { "Neckargemuend 1", "NEG", 1, 6, 43, }, + { "Neckargemuend 2", "NEG2", 1, 6, 44, }, + { "Meckesheim 2", "MEH2", 1, 6, 45, }, + { "Mannheim 178 (Schoenau)", "MA178", 1, 6, 46, }, + { "Hardheim 1", "HAD", 1, 6, 51, }, + { "Buchen Odenw 0", "BUC", 1, 6, 52, }, + { "Maxdorf 0", "KAKL44", 1, 6, 53, }, + { "Guntersblum 1", "GUN1", 1, 6, 54, }, + { "Bensheim 13", "FKLZ74", 1, 6, 55, }, + { "Weinheim 2", "KAKL52", 1, 6, 56, }, + { "Winnweiler 2 (Imsbach)(KL2)", "IMB1", 1, 6, 57, }, + { "Winnweiler 8 (KL2)", "WIW8", 1, 6, 58, }, + { "Neustadt a d Weinstrasse 0", "KAKL06", 1, 6, 60, }, + { "Ludwigshafen a Rhein 505", "KAKL01", 1, 6, 61, }, + { "Speyer 5", "KAKL07", 1, 6, 62, }, + { "Landau i d Pfalz 8", "KAKL10", 1, 6, 63, }, + { "Heidelberg 0", "KAKL26", 1, 6, 64, }, + { "Dahn 3", "DAHN3", 1, 6, 65, }, + { "Schwetzingen 0", "KAKL36", 1, 6, 66, }, + { "Ladenburg 6", "KAKL37", 1, 6, 67, }, + { "Lampertheim 0", "KAKL38", 1, 6, 68, }, + { "Mannheim 52 (Pfeiffersw.)", "KAKL41", 1, 6, 69, }, + { "Neuhofen Pfalz 0", "KAKL43", 1, 6, 70, }, + { "Mannheim 149 (Ilvesheim)", "KAKL29", 1, 6, 71, }, + { "Mannheim 198 (Diak.-Kkh.)", "KAKL32", 1, 6, 72, }, + { "Mannheim 199 (Grosskraftw.)", "KAKL31", 1, 6, 73, }, + { "Mannheim 201 (Maimarktg.)", "KAKL30", 1, 6, 75, }, + { "Mannheim 202 (VDOe)", "KAKL33", 1, 6, 76, }, + { "Mannheim 173 (Kaefertal)", "KAKL28", 1, 6, 77, }, + { "Viernheim 2", "KAKL39", 1, 6, 78, }, + { "Adelsheim 4 <ers. Seckach1>", "ADH1", 1, 6, 83, }, + { "Gernsheim Rhein 4", "FKLZ75", 1, 6, 84, }, + { "Alsenz 7", "ALE", 1, 6, 85, }, + { "Frankenthal 0", "KAKL02", 1, 6, 86, }, + { "Gruenstadt 0", "KAKL03", 1, 6, 87, }, + { "Bad Duerkheim 2", "KAKL04", 1, 6, 88, }, + { "Bad Duerkheim 0", "KAKL45", 1, 6, 89, }, + { "Kirchheimbolanden 5", "KIB", 1, 6, 90, }, + { "Hassmersheim 1 (Gundelsheim)", "HAH1", 1, 6, 91, }, + { "Enkenbach-Alsenborn 4", "ENK4", 1, 6, 93, }, + { "Miltenberg 2", "MIL2", 1, 6, 94, }, + { "Miltenberg 4", "MIL4", 1, 6, 95, }, + { "Rockenhausen 6 (KL2)", "ROK6", 1, 6, 96, }, + { "Mannheim 499 (Pfingstb. No)", "BAHN01", 1, 6, 97, }, + { "Mannheim 4", "MA4", 1, 6, 99, }, + { "Beuron 1", "BEU1", 1, 7, 1, }, + { "Albstadt-Laufen 1", "ALB1", 1, 7, 2, }, + { "Oberndorf 3", "OBD1", 1, 7, 3, }, + { "Schwenningen P01", "SWE1", 1, 7, 4, }, + { "Rottweil 0", "RW0", 1, 7, 5, }, + { "Albstadt-Ebingen 2", "ALB3", 1, 7, 6, }, + { "Baiersbronn 1", "BAI1", 1, 7, 7, }, + { "Balingen 1", "BAL1", 1, 7, 8, }, + { "Gosheim 1", "GOSM1", 1, 7, 9, }, + { "Tuttlingen 2", "TUT2", 1, 7, 10, }, + { "Konstanz 0", "KON0", 1, 7, 11, }, + { "Waldburg 2", "WAB2", 1, 7, 12, }, + { "Deggenhausertal 3", "DHT3", 1, 7, 13, }, + { "Sigmaringen 4", "SIGM4", 1, 7, 14, }, + { "Donaueschingen 5", "DOE5", 1, 7, 15, }, + { "Singen 0", "SIN0", 1, 7, 16, }, + { "Klettgau 6", "KLG6", 1, 7, 17, }, + { "Rickenbach 1", "RIK1", 1, 7, 18, }, + { "Bodman-Ludwigshafen 3", "BOD3X", 1, 7, 19, }, + { "Sauldorf 1", "SAU1", 1, 7, 20, }, + { "Hilzingen 1", "HILZ1", 1, 7, 21, }, + { "Stockach 6", "STO2", 1, 7, 22, }, + { "Aichstetten 2", "AIST2", 1, 7, 23, }, + { "Voehrenbach 4", "VOEH4", 1, 7, 24, }, + { "Radolfzell 1", "RAD1", 1, 7, 25, }, + { "Schoemberg-Balingen 2", "SBA2", 1, 7, 26, }, + { "Nagold-Hochdorf 0", "NAH", 1, 7, 27, }, + { "Rottenburg 3", "ROTT3", 1, 7, 28, }, + { "Hechingen 6", "HECH6", 1, 7, 29, }, + { "Ammerbuch 2", "SKLZ03", 1, 7, 30, }, + { "Allensbach 1", "ALLB", 1, 7, 31, }, + { "Villingen 10", "VILL10", 1, 7, 32, }, + { "Tiengen 0", "TIEN0", 1, 7, 33, }, + { "Mengen 1", "MENG1", 1, 7, 34, }, + { "Bad Schussenried 1", "BSCH1", 1, 7, 35, }, + { "Ravensburg 0", "RAV0", 1, 7, 36, }, + { "Friedrichshafen 0", "TET2", 1, 7, 37, }, + { "Nagold 1", "NAG1", 1, 7, 38, }, + { "Baiersbronn 3", "BAI3", 1, 7, 39, }, + { "Grafenhausen 1", "GRAF", 1, 7, 40, }, + { "Bad Saeckingen 0", "BSK0", 1, 7, 41, }, + { "Immenstaad 0", "IMM", 1, 7, 42, }, + { "Altensteig 2", "ALTST2", 1, 7, 43, }, + { "St. Georgen 1", "STG1", 1, 7, 44, }, + { "Sulz 3", "SU3", 1, 7, 45, }, + { "Murg 2", "MURG2", 1, 7, 46, }, + { "Tengen 2", "TEN2", 1, 7, 47, }, + { "Waldshut 4", "WAL4", 1, 7, 48, }, + { "Leutkirch 0", "LEUT0", 1, 7, 49, }, + { "Triberg 2", "TRI2", 1, 7, 50, }, + { "Furtwangen 2", "FURT2", 1, 7, 51, }, + { "Tettnang 4", "TET4", 1, 7, 52, }, + { "Ostrach 2", "OST2", 1, 7, 53, }, + { "Haigerloch 0", "HAIG0", 1, 7, 54, }, + { "Alpirsbach 4", "ALPI1", 1, 7, 56, }, + { "Pfullendorf 1 <Prov.>", "PFUL3", 1, 7, 57, }, + { "Rottweil 7", "RW7", 1, 7, 58, }, + { "Baiersbronn 2", "BAI2", 1, 7, 60, }, + { "Bad Wurzach 1", "BWU1", 1, 7, 61, }, + { "Wangen 1", "WANG1", 1, 7, 62, }, + { "Markdorf 1", "MARK1", 1, 7, 63, }, + { "Burladingen 1", "BURL1", 1, 7, 64, }, + { "Gammertingen 3", "GAMT3", 1, 7, 65, }, + { "Kisslegg 2", "KISS2", 1, 7, 66, }, + { "Kressbronn 3", "KRES3", 1, 7, 67, }, + { "Freudenstadt 0", "DORN4", 1, 7, 69, }, + { "Geisingen 1", "GEIS1", 1, 7, 70, }, + { "Isny 0", "ISNY0", 1, 7, 71, }, + { "Schramberg 1", "SBG1", 1, 7, 79, }, + { "Eigeltingen 2", "EIG2", 1, 7, 87, }, + { "Talheim 4", "TAL4", 1, 7, 93, }, + { "Heiligenberg 0", "HEILB0", 1, 7, 94, }, + { "Spaichingen 3", "SPAI3", 1, 7, 95, }, + { "Blumberg 5", "BLUM5", 1, 7, 96, }, + { "Baiersbronn-Obertal 2", "VOK", 1, 7, 98, }, + { "Engen 4", "BARG", 1, 7, 99, }, + { "Oberammergau 1", "OAG1", 1, 8, 1, }, + { "Schwindegg 1", "SCHW1", 1, 8, 2, }, + { "Bad Aibling 0", "BAIB0", 1, 8, 3, }, + { "Teisendorf 3", "TEIS3", 1, 8, 4, }, + { "Miesbach 4 (Ers.f.Bruckmuehl)", "BRU2", 1, 8, 5, }, + { "Oberaudorf 2", "OADO2", 1, 8, 6, }, + { "Ramsau 1", "RAMS1", 1, 8, 7, }, + { "Reit im Winkl 0", "RIW0", 1, 8, 8, }, + { "Bad Reichenhall 2", "BREI2", 1, 8, 9, }, + { "Landau/Isar 3", "EAUF1", 1, 8, 10, }, + { "Tann 2", "TANN2", 1, 8, 11, }, + { "Neufahrn 81", "ALHN99", 1, 8, 12, }, + { "Attenkirchen 1", "ATK99", 1, 8, 13, }, + { "Olching 0 (Wolfstrasse)", "MKLZ28", 1, 8, 14, }, + { "Seeshaupt 1", "SH99", 1, 8, 15, }, + { "Wolfratshausen 2", "MKLZ32", 1, 8, 16, }, + { "Starnberg 5 (Wangen)", "MKLZ31", 1, 8, 17, }, + { "Tittmoning 1 (Froschham)", "TITT1", 1, 8, 18, }, + { "Herrsching 1 (Widdersberg)", "HSG1", 1, 8, 19, }, + { "Wolfratshausen 1", "ICKI99", 1, 8, 20, }, + { "Bad Reichenhall 1 <Prov.>", "BREI", 1, 8, 21, }, + { "Passau 11 (Dommelstadl)", "DST1", 1, 8, 22, }, + { "Pfarrkirchen Niederbay 1", "PFI1", 1, 8, 23, }, + { "Anger 1", "AN1", 1, 8, 24, }, + { "Obernzell", "OZEL", 1, 8, 25, }, + { "Hohenpeissenberg 2", "HHP2", 1, 8, 26, }, + { "Garmisch-Partenkirchen 4", "GAR4X", 1, 8, 27, }, + { "Grainet 1", "GRN1", 1, 8, 28, }, + { "Glonn 1", "GLN1", 1, 8, 29, }, + { "Taufkirchen/Vils 2", "TKI99", 1, 8, 30, }, + { "Freyung 1", "FYG1", 1, 8, 31, }, + { "Mainburg 1", "MNBG1", 1, 8, 32, }, + { "Diessen 2", "DSN2", 1, 8, 33, }, + { "Berchtesgaden 15", "BGN15", 1, 8, 34, }, + { "Fuerstenfeldbruck 2", "MKLZ30", 1, 8, 35, }, + { "Markt Schwaben 1(Neufinsing)", "MKLZ22", 1, 8, 36, }, + { "Murnau 70 (Ohlstadt)", "MUR70", 1, 8, 37, }, + { "Landsberg 3 (Poessing)", "LBG99", 1, 8, 38, }, + { "Dingolfing 2 (Brunn)", "DGF2", 1, 8, 39, }, + { "Grafing 21 (Ebersberg)", "GRAF21", 1, 8, 40, }, + { "Muehldorf 0", "MDF0", 1, 8, 41, }, + { "Grassau 2", "GSU2", 1, 8, 42, }, + { "Ergoldsbach 2", "EGB2", 1, 8, 43, }, + { "Weyarn 3", "WYN3", 1, 8, 44, }, + { "Hausham 99 (Schliersbergalm)", "HHM99", 1, 8, 45, }, + { "Freising 3 (Schiesspl.)", "FRS99", 1, 8, 46, }, + { "Kochel am See 4 (Kreutalm)", "KAS98", 1, 8, 47, }, + { "Woerth 1 <Ers. f. Adlk. 1>", "WTH1", 1, 8, 48, }, + { "Holzkirchen 62", "HKI62", 1, 8, 49, }, + { "Dachau 91(Bayernw.i.Karlsf.)", "DACH99", 1, 8, 50, }, + { "Hallbergmoos 2 (FMG)", "HBGM99", 1, 8, 51, }, + { "Petershausen 1", "PHSN1", 1, 8, 52, }, + { "Roehrmoos 2", "RMS2", 1, 8, 53, }, + { "Ruhpolding 1 (Rauschberg)", "RPD1", 1, 8, 54, }, + { "Geltendorf 1 (Wasserbeh.)", "GDF99", 1, 8, 55, }, + { "Trostberg 3", "TBG1", 1, 8, 56, }, + { "Dorfen 1", "DORF1", 1, 8, 57, }, + { "Dachau 3 (Krankenhaus)", "MKLZ25", 1, 8, 59, }, + { "Vilsbiburg 2", "VILS2", 1, 8, 60, }, + { "Mallersdorf 2", "MALL2", 1, 8, 61, }, + { "Mammendorf 1 (Hattenhofen)", "MAMM99", 1, 8, 62, }, + { "Traunstein 2", "TS2", 1, 8, 63, }, + { "Markt Schwaben 0", "MSBN0", 1, 8, 64, }, + { "Bernbeuren 1", "BBN1", 1, 8, 65, }, + { "Landshut 1", "LA1", 1, 8, 66, }, + { "Holzkirchen 3", "HKI3", 1, 8, 67, }, + { "Rosenheim Oberbay 0", "RO0", 1, 8, 68, }, + { "Schnaitsee 1", "SNE1", 1, 8, 69, }, + { "Waakirchen 0", "WAA", 1, 8, 70, }, + { "Wasserburg 1", "WSBG1", 1, 8, 71, }, + { "Prien 1", "PRI1", 1, 8, 72, }, + { "Waldkraiburg 0", "MHLD0", 1, 8, 73, }, + { "Burghausen 5", "BHS99", 1, 8, 74, }, + { "Kirchseeon 0", "KISE0", 1, 8, 75, }, + { "Fuerstenfeldbruck 0", "FFB0", 1, 8, 76, }, + { "Moosinning 1", "MOSI1", 1, 8, 77, }, + { "Sulzemoos 1 (BAB-P.)", "SULZ98", 1, 8, 78, }, + { "Vilshofen 1", "VIH1", 1, 8, 79, }, + { "Bayrischzell", "BAYZ", 1, 8, 80, }, + { "Reischach 1", "REI", 1, 8, 81, }, + { "Simbach/Inn 2", "SIM2", 1, 8, 84, }, + { "Hauzenberg 2", "HAUZ2", 1, 8, 85, }, + { "Sindelsdorf 10", "SIDO10", 1, 8, 86, }, + { "Zolling 1 (Grossenviecht)", "ZOLL99", 1, 8, 90, }, + { "Griesbach 1 (OBAG)", "GRIB1", 1, 8, 91, }, + { "Kochel am See 1", "KAS1", 1, 8, 92, }, + { "Isen 1", "IS1", 1, 8, 93, }, + { "Tegernsee 1 (Ringberg)", "RING", 1, 8, 94, }, + { "Gangkofen-Kollbach 1", "GKKB1", 1, 8, 95, }, + { "Lenggries 0", "LGS0", 1, 8, 96, }, + { "Pfeffenhausen 1", "PFE1", 1, 8, 99, }, + { "Arnstein 2", "ARN", 1, 9, 1, }, + { "Bad Steben 1", "SCHNB", 1, 9, 2, }, + { "Bayerisch Eisenstein 1", "BYS1X", 1, 9, 3, }, + { "Berg 2", "EISE", 1, 9, 4, }, + { "Rottendorf 3", "BIEB", 1, 9, 5, }, + { "Werneck 2", "WNECK2", 1, 9, 6, }, + { "Bayreuth-Oschenberg 1", "BYR1", 1, 9, 7, }, + { "Kulmbach 4", "KULM", 1, 9, 8, }, + { "Pressig 1", "PRES", 1, 9, 10, }, + { "Bischofsgruen 2", "BIGR2", 1, 9, 11, }, + { "Hof-Labyrinth 2", "HOF2", 1, 9, 12, }, + { "Kist 1", "KIST", 1, 9, 13, }, + { "Bodenwoehr 1", "BDWR1", 1, 9, 14, }, + { "Burglengenfeld 3", "BLF3", 1, 9, 15, }, + { "Burgwindheim 1", "BUW1", 1, 9, 16, }, + { "Buttenheim 1", "BUT1", 1, 9, 17, }, + { "Iphofen 2", "IPHN2", 1, 9, 18, }, + { "Cham 1", "CHA1", 1, 9, 19, }, + { "Tauberbischofsheim 4", "TBIO4", 1, 9, 20, }, + { "Unterpleichfeld 2", "UPLF2", 1, 9, 21, }, + { "Uettingen 4", "UETT4", 1, 9, 22, }, + { "Erbendorf 1", "ERBN1", 1, 9, 23, }, + { "Deggendorf 1", "DGD1", 1, 9, 24, }, + { "Oberthulba 3", "KN51", 1, 9, 25, }, + { "Laaber 5", "LAAB5", 1, 9, 26, }, + { "Seubersdorf 2", "SEUB2", 1, 9, 27, }, + { "Riedenburg 2", "RIED2", 1, 9, 28, }, + { "Oberwerrn 51", "OBW51", 1, 9, 29, }, + { "Abensberg 1", "ABBG1", 1, 9, 31, }, + { "Hemau 3", "HEM3", 1, 9, 32, }, + { "Hirschau 1", "HIR1", 1, 9, 33, }, + { "Hofheim 1", "HFH1X", 1, 9, 34, }, + { "Karlstadt 3", "KARL", 1, 9, 35, }, + { "Kelheim 2", "KLH2", 1, 9, 36, }, + { "Bamberg 6", "BAMB", 1, 9, 37, }, + { "Oberaurach 1", "ZEIL1", 1, 9, 38, }, + { "Pfarrweisach 1", "PFWA1", 1, 9, 39, }, + { "Kirchlauter 1", "KLTR1", 1, 9, 40, }, + { "Schesslitz 2", "SCHZ2", 1, 9, 41, }, + { "Zapfendorf 2", "ZAPF1", 1, 9, 42, }, + { "Beratzhausen 1", "BZHS1", 1, 9, 43, }, + { "Rehau 1", "REHA1", 1, 9, 44, }, + { "Neustadt/Coburg 1", "NEUST1", 1, 9, 45, }, + { "Kronach 1", "KRN1", 1, 9, 46, }, + { "Langquaid 1", "LANG1", 1, 9, 47, }, + { "Amberg 0", "AMB0", 1, 9, 48, }, + { "Pleystein 1", "PLEY1", 1, 9, 49, }, + { "Lauda-Koenigshofen 3", "LDK3", 1, 9, 50, }, + { "Lichtenfels 2", "LIFS99", 1, 9, 51, }, + { "Muennerstadt 1", "MUENR1", 1, 9, 53, }, + { "Meeder 1", "MED1", 1, 9, 54, }, + { "Bad Kissingen 1", "BKG1", 1, 9, 55, }, + { "Hammelburg 8", "HMBG8", 1, 9, 56, }, + { "Marktheidenfeld 2", "MHF2", 1, 9, 59, }, + { "Straubing 0", "STBG0", 1, 9, 60, }, + { "Schoefweg 1", "SCHOE1", 1, 9, 61, }, + { "Koetzting 1", "KOETZ1", 1, 9, 62, }, + { "Illschwang 3", "ILLS3", 1, 9, 64, }, + { "Oberbach 1", "OBB1X", 1, 9, 66, }, + { "Oberviechtach 2", "OVT2", 1, 9, 67, }, + { "Ochsenfurt 3", "OCHS3", 1, 9, 68, }, + { "Pfatter 0", "PFAT0", 1, 9, 69, }, + { "Regensburg 1", "R1", 1, 9, 70, }, + { "Regensburg 4", "RBG42", 1, 9, 71, }, + { "Schweinfurt 30", "SW30", 1, 9, 72, }, + { "Selb 1", "SELB1", 1, 9, 73, }, + { "Stallwang 2", "STALL2", 1, 9, 74, }, + { "Bad Koenigshofen 1", "KHF1", 1, 9, 75, }, + { "Alladorf 1", "AL1", 1, 9, 76, }, + { "Tirschenreuth 0", "TIR0", 1, 9, 77, }, + { "Waldmuenchen 1", "WMCHN1", 1, 9, 78, }, + { "Weiden 1", "WDN1", 1, 9, 79, }, + { "Werbach-Gamburg 2 <pr GAM3>", "WERBG2", 1, 9, 80, }, + { "Wiesentheid 1", "WSD1X", 1, 9, 81, }, + { "Wuerzburg 2", "WUE2", 1, 9, 82, }, + { "Wunsiedel-Koesseine 2", "WUNS2", 1, 9, 83, }, + { "Zell-Waldstein 2", "ZLL2", 1, 9, 84, }, + { "Trockau 1", "TROK1", 1, 9, 85, }, + { "Mitterfels 1", "MITF1", 1, 9, 87, }, + { "Nabburg 2", "NABB2", 1, 9, 88, }, + { "Obernsees 1", "OBS1", 1, 9, 90, }, + { "Roding 1", "ROD1", 1, 9, 91, }, + { "Gerchsheim 1", "GERH1", 1, 9, 93, }, + { "Coburg 5", "ECKBG", 1, 9, 94, }, + { "Karlstadt-Wiesenfeld 1", "BAHN12", 1, 9, 96, }, + { "Wuerzburg 74", "BAHN13", 1, 9, 97, }, + { "Waldsassen 1", "WASA1", 1, 9, 98, }, + { "Zell/Opf. 1", "ZELL1", 1, 9, 99, }, + { "Neuss 10", "NEU10", 2, 2, 1, }, + { "Duesseldorf 57 (Messe)", "D98", 2, 2, 2, }, + { "Neuss 7", "NEU7", 2, 2, 4, }, + { "Ratingen 5", "RAT5", 2, 2, 6, }, + { "Solingen 2", "SOL2", 2, 2, 7, }, + { "Duesseldorf 18", "D18", 2, 2, 8, }, + { "Duesseldorf 58", "D99", 2, 2, 9, }, + { "Neuss 14", "NEU14", 2, 2, 10, }, + { "Neuss-Norf 1", "NEUNO1", 2, 2, 11, }, + { "Duesseldorf 30", "D30", 2, 2, 12, }, + { "Langenfeld 3", "LANF3", 2, 2, 13, }, + { "Duesseldorf 75", "D75", 2, 2, 14, }, + { "Mettmann 7", "MTM4", 2, 2, 15, }, + { "Duesseldorf 19", "D19", 2, 2, 17, }, + { "Grevenbroich 3", "GVB3", 2, 2, 18, }, + { "Grevenbroich-Kapellen 2", "GVBK", 2, 2, 19, }, + { "Ratingen 1", "RAT1", 2, 2, 20, }, + { "Duesseldorf 40", "D97", 2, 2, 22, }, + { "Neuss 8", "NEU8", 2, 2, 23, }, + { "Duesseldorf 4", "D4", 2, 2, 24, }, + { "Hilden 6", "HDN6", 2, 2, 26, }, + { "Duesseldorf 12", "D12", 2, 2, 27, }, + { "Ratingen 3", "RAT3", 2, 2, 29, }, + { "Remscheid 4 <geneigt>", "REM4", 2, 2, 30, }, + { "Krefeld 4", "KRF4", 2, 2, 31, }, + { "Lank 0", "LANK", 2, 2, 33, }, + { "Osterath 0", "OSTER0", 2, 2, 35, }, + { "Krefeld 5", "KRF5", 2, 2, 36, }, + { "Meerbusch-Buederich 1", "MEEB1", 2, 2, 37, }, + { "Duesseldorf 27", "D27", 2, 2, 38, }, + { "Duesseldorf 53", "D53", 2, 2, 39, }, + { "Willich 1", "WIL1", 2, 2, 42, }, + { "Solingen 1 <Ant.geneigt>", "SOL1", 2, 2, 43, }, + { "Moenchengladbach 18", "MGL18", 2, 2, 44, }, + { "Haan 0", "HAAN", 2, 2, 45, }, + { "Krefeld 7", "FISCH", 2, 2, 46, }, + { "Duesseldorf 9 (Rheintunnel)", "D9", 2, 2, 47, }, + { "Duesseldorf 2.8046", "D2", 2, 2, 49, }, + { "Langenfeld 89", "LANF", 2, 2, 52, }, + { "Mettmann 2", "MTM2X", 2, 2, 66, }, + { "Wuppertal 23", "WUP23", 2, 2, 78, }, + { "Duesseldorf 10 <Bake>", "D10", 2, 2, 88, }, + { "Aachen 9", "AA99", 3, 2, 1, }, + { "Krefeld 19", "KRF19", 3, 2, 2, }, + { "Moenchengladbach 60", "MGL60", 3, 2, 3, }, + { "Moenchengladbach 3", "MGL3", 3, 2, 4, }, + { "Viersen 4", "VIE4", 3, 2, 5, }, + { "Bedburg 0", "BEDB", 3, 2, 8, }, + { "Moenchengladbach-Rheydt 8", "MGL8", 3, 2, 13, }, + { "Selfkant 0", "SELF", 3, 2, 15, }, + { "Anrath 0", "ANR99", 3, 2, 17, }, + { "Wuerselen 2", "WUERS2", 3, 2, 19, }, + { "Moenchengladbach 8", "MGLB8", 3, 2, 22, }, + { "Langerwehe 1", "LUCH", 3, 2, 26, }, + { "Xanten 1", "XAN1", 3, 2, 27, }, + { "Kleve 7", "KLV7", 3, 2, 29, }, + { "Geldern 0", "GEL0", 3, 2, 31, }, + { "Moers 0", "MOER0", 3, 2, 32, }, + { "Viersen 0", "VIER0", 3, 2, 33, }, + { "Juechen 1", "JUECH1", 3, 2, 36, }, + { "Nettetal-Kaldenkirchen 1", "NETT1", 3, 2, 40, }, + { "Viersen 1", "VIE1", 3, 2, 42, }, + { "Schwalmtal 9", "SCHWA", 3, 2, 43, }, + { "Juechen-Otzenrath 4", "JUECH4", 3, 2, 44, }, + { "Moenchengladbach-Rheydt 7", "MGLR7", 3, 2, 45, }, + { "Stolberg 4", "STOL4", 3, 2, 46, }, + { "Eschweiler 2", "EWLR2", 3, 2, 48, }, + { "Alsdorf 3", "ALSD3", 3, 2, 49, }, + { "Aachen-Kornelimuenster 0", "AAK", 3, 2, 50, }, + { "Aachen 700", "AA7", 3, 2, 51, }, + { "Aachen 120", "AA120", 3, 2, 52, }, + { "Aachen 500 <Ers. f. AA57>", "AA500", 3, 2, 53, }, + { "Erkelenz 0", "ERKL0", 3, 2, 54, }, + { "Geilenkirchen 0", "GEIL0", 3, 2, 57, }, + { "Heinsberg 0", "HEIN0", 3, 2, 58, }, + { "Juelich 3", "JUEL3", 3, 2, 59, }, + { "Kevelaer 98", "KEVL98", 3, 2, 63, }, + { "Straelen 1", "STRAE1", 3, 2, 64, }, + { "Neukirchen-Vluyn 6", "NEUK6", 3, 2, 65, }, + { "Kalkar 7", "KKAR99", 3, 2, 67, }, + { "Wegberg 89 <f. MGL7>", "WEGB89", 3, 2, 77, }, + { "Herzogenrath 2", "HERA2", 3, 2, 80, }, + { "Kevelaer 10", "GOCH89", 3, 2, 81, }, + { "Sonsbeck 0.47B1", "SONS0", 3, 2, 82, }, + { "Moenchengladbach 401", "MGL40", 3, 2, 84, }, + { "Aachen 1 <Mischbake>", "AA1", 3, 2, 86, }, + { "Kempen 4", "KEMP", 3, 2, 87, }, + { "Linnich 1", "LINN", 3, 2, 88, }, + { "Goch 0", "GOCH0", 3, 2, 90, }, + { "Rheinberg 2", "RHBG2", 3, 2, 98, }, + { "Aldenhoven 0", "AHVN", 3, 2, 99, }, + { "Berlin (West) 23 PGiroA", "B23", 2, 3, 1, }, + { "Blnklz 210 GBhf Schoenholz", "BKLZ78", 2, 3, 2, }, + { "Blnklz 101(Ruegenerstr.)", "BKLZ01", 2, 3, 3, }, + { "Blnklz 102(Habersaathstr)", "BKLZ2", 2, 3, 4, }, + { "Blnklz 103(Stresemannstr.)", "BKLZ03", 2, 3, 5, }, + { "Blnklz 407(Wilkestr.15)", "BKLZ24", 2, 3, 6, }, + { "Blnklz 105(Skalitzer Str.)", "BKLZ05", 2, 3, 7, }, + { "Blnklz 201(Luederitzstr.)", "BKLZ06", 2, 3, 8, }, + { "Blnklz 202(Erasmusstr20-24)", "BKLZ07", 2, 3, 9, }, + { "Blnklz 203(Winterfeldstr.)", "BKLZ08", 2, 3, 10, }, + { "Blnklz 307(Wernerwerkdamm)", "BKLZ25", 2, 3, 11, }, + { "Blnklz 205(Karl-Marx-Str.)", "BKLZ10", 2, 3, 12, }, + { "Blnklz 301(Oranienb. Str.)", "BKLZ11", 2, 3, 13, }, + { "Blnklz 302(Auguste V.Allee)", "BKLZ12", 2, 3, 14, }, + { "Blnklz 305(Rathausstr)", "BKLZ15", 2, 3, 15, }, + { "Blnklz 304(Schmargend. Str)", "BKLZ14", 2, 3, 16, }, + { "Blnklz 204(Tempelhofer D.6)", "BKLZ09", 2, 3, 17, }, + { "Blnklz 306(Hannemannstr)", "BKLZ16", 2, 3, 18, }, + { "Blnklz 401(Streitstr)", "BKLZ17", 2, 3, 19, }, + { "Blnklz 405(Kettinger Str.)", "BKLZ22", 2, 3, 20, }, + { "Blnklz 403(Forststr)", "BKLZ19", 2, 3, 21, }, + { "Blnklz 404(Hindenb. Damm)", "BKLZ20", 2, 3, 22, }, + { "Blnklz 104(Lobecks)<gen.Ant>", "BKLZ04", 2, 3, 23, }, + { "Blnklz 211(Alt-Stralau)", "BKLZ40", 2, 3, 24, }, + { "Blnklz 501(Schaeferberg)", "B3", 2, 3, 25, }, + { "Blnklz 212(Elsastrasse 26)", "BKLZ41", 2, 3, 28, }, + { "Blnklz 106(Franz-J)<gen.Ant>", "BKLZ31", 2, 3, 29, }, + { "Blnklz 308(Schnellerstr.)", "BKLZ42", 2, 3, 30, }, + { "Blnklz 309(Koepenicker A.)", "BKLZ43", 2, 3, 31, }, + { "Blnklz 310(Amanlisweg 10)", "BKLZ44", 2, 3, 32, }, + { "Blnklz 311(Bitterfelder Str)", "BKLZ45", 2, 3, 33, }, + { "Blnklz 312(E.-Barlach-Str.)", "BKLZ46", 2, 3, 34, }, + { "Blnklz 420(Flankenschanze)", "BKLZ23", 2, 3, 35, }, + { "Blnklz 107(Lilli-Henoch-Str)", "BKLZ32", 2, 3, 36, }, + { "Blnklz 314(Buchholzer Str)", "BKLZ48", 2, 3, 37, }, + { "Blnklz 408(Rudower Chaus.)", "BKLZ49", 2, 3, 38, }, + { "Blnklz 409(O.-Geschke-Str)", "BKLZ50", 2, 3, 39, }, + { "Blnklz 001(Rochstr)<gen.Ant>", "BKLZ30", 2, 3, 40, }, + { "Blnklz 213(E.-Reuter-Platz)", "BKLZ79", 2, 3, 41, }, + { "Blnklz 418(Schoenefeld)", "BKLZ56", 2, 3, 48, }, + { "Blnklz 206(Coppist)<gen.Ant>", "BKLZ33", 2, 3, 49, }, + { "Blnklz 209(Prenzlauer Pr)", "BKLZ36", 2, 3, 57, }, + { "Blnklz 208(Liebermann.75)", "BKLZ35", 2, 3, 58, }, + { "Blnklz 207(Herzberg.105)", "BKLZ34", 2, 3, 59, }, + { "Blnklz 303(Masurenallee)", "BKLZ13", 2, 3, 60, }, + { "Blnklz 402(Scholzplatz)", "BKLZ18", 2, 3, 61, }, + { "Blnklz 601(Flotowstr.)", "BKLZ75", 2, 3, 64, }, + { "Blnklz 602(Breitestr.)", "BKLZ68", 2, 3, 65, }, + { "Blnklz 002(Karl-Marx-Allee)", "BKLZ71", 2, 3, 70, }, + { "Blnklz 516 (Avus)", "BKLZ77", 2, 3, 95, }, + { "Hamburg 282 (PA90 Harb.Z44)", "HRBG", 2, 4, 13, }, + { "Hannover 790", "HAN790", 2, 5, 1, }, + { "Barsinghausen 2", "BAR2", 2, 5, 2, }, + { "Bergen 1", "BERG1", 2, 5, 3, }, + { "Celle 0", "CE0", 2, 5, 4, }, + { "Salzhemmendorf 1", "SZH1", 2, 5, 5, }, + { "Peine 1", "PEI1", 2, 5, 6, }, + { "Sibbesse 1", "SIB1", 2, 5, 7, }, + { "Braunschweig 3", "BS3", 2, 5, 9, }, + { "Wietze 2", "WIET2", 2, 5, 10, }, + { "Wolfsburg 1", "WOB1", 2, 5, 11, }, + { "Sprakensehl 1", "SPR1", 2, 5, 12, }, + { "Wesendorf 1", "WEDF", 2, 5, 13, }, + { "Alfeld 40", "ALF40", 2, 5, 14, }, + { "Semmenstedt 99", "SEM99", 2, 5, 17, }, + { "Hildesheimer Boerde 99", "HIBO", 2, 5, 18, }, + { "Eschede 1", "ED1", 2, 5, 19, }, + { "Loccum 0", "LOCC0", 2, 5, 21, }, + { "Zernien 1", "ZNN1", 2, 5, 22, }, + { "Gartow 2", "GTO1", 2, 5, 23, }, + { "Bispingen 41", "BISP98", 2, 5, 24, }, + { "Hannover 4 (Hamburger Al)", "HAN4", 2, 5, 26, }, + { "Hannover 951 (Gradestr. 22)", "HAKL10", 2, 5, 27, }, + { "Hannover 2 (Neue Landstr)", "HAKL21", 2, 5, 28, }, + { "Hannover 953 (Bischofshofer)", "HAKL33", 2, 5, 29, }, + { "Hannover 954 (HildesheimerS)", "HAKL41", 2, 5, 30, }, + { "Hannover 210 (Goettinger Str)", "HAKL52", 2, 5, 31, }, + { "Uetze 99", "UETZ99", 2, 5, 32, }, + { "Garbsen 10", "GRB10", 2, 5, 33, }, + { "Wedemark 1", "WED1", 2, 5, 34, }, + { "Burgwedel 0", "BGW1", 2, 5, 35, }, + { "Schwarmstedt 0", "SWST0", 2, 5, 36, }, + { "Lehrte 2", "LEH2", 2, 5, 37, }, + { "Sarstedt 1", "SST1", 2, 5, 38, }, + { "Ronnenberg 9", "RON9", 2, 5, 39, }, + { "Walsrode 1", "WSR1", 2, 5, 40, }, + { "Gifhorn 0", "GIF0", 2, 5, 41, }, + { "Hitzacker 1", "HITZ1", 2, 5, 42, }, + { "Hildesheim 1", "HILD1", 2, 5, 43, }, + { "Bleckede/Barsk.1", "BBK1", 2, 5, 44, }, + { "Einbeck 2", "EINB2", 2, 5, 46, }, + { "Braunschweig 701", "BS4", 2, 5, 48, }, + { "Hameln 10", "HM10", 2, 5, 49, }, + { "Schneverdingen 0", "SVG", 2, 5, 50, }, + { "Helmstedt 2", "HE2", 2, 5, 51, }, + { "Hannover 610", "AWB61", 2, 5, 52, }, + { "Braunschweig 360", "BS36", 2, 5, 54, }, + { "Stadthagen 0", "STDH0", 2, 5, 55, }, + { "Nienburg 0", "NIEN", 2, 5, 58, }, + { "Linsburg 1", "LSB1", 2, 5, 60, }, + { "Springe 3", "SPRG3", 2, 5, 61, }, + { "Hannover 860", "HAN860", 2, 5, 62, }, + { "Eschershausen 40", "EHSN40", 2, 5, 63, }, + { "Holle 40", "HOLL40", 2, 5, 64, }, + { "Munster 1", "MUN1", 2, 5, 65, }, + { "Burgdorf-Ehlershausen 0", "BGDEH0", 2, 5, 66, }, + { "Salzgitter 40", "SZGB", 2, 5, 67, }, + { "Burgdorf 0", "BGD0", 2, 5, 68, }, + { "Seesen 1", "SES1", 2, 5, 69, }, + { "Kreiensen 1 (Orxhausen)", "BAHN05", 2, 5, 70, }, + { "Obernkirchen 2", "OBKN2", 2, 5, 74, }, + { "Uelzen 3", "ULZ3", 2, 5, 76, }, + { "Jerxheim 1", "JH0", 2, 5, 78, }, + { "Wunstorf 2", "WUNT2", 2, 5, 80, }, + { "Brome 0", "BRO0", 2, 5, 82, }, + { "Salzgitter 0", "SZG0", 2, 5, 84, }, + { "Wendeburg 99", "WEN99", 2, 5, 85, }, + { "Hannover 730 (Langenhagen)", "HAN730", 2, 5, 86, }, + { "Soltau 2", "SOLT", 2, 5, 87, }, + { "Clausthal-Zellerfeld 41", "CLT41", 2, 5, 90, }, + { "Goslar 41", "GOS41", 2, 5, 91, }, + { "Koenigslutter 54", "KLUT51", 2, 5, 92, }, + { "Torfhaus 0", "TFH0", 2, 5, 93, }, + { "Sibbesse 2 (Almstedt)", "BAHN04", 2, 5, 95, }, + { "Hannover Messe", "HANMES", 2, 5, 97, }, + { "Hoever 99", "HAN99", 2, 5, 98, }, + { "Dieburg 2", "DBG2", 2, 6, 2, }, + { "Gross-Umstadt 5<Ers FKLZ58>", "GRUM", 2, 6, 3, }, + { "Brensbach 1", "FKLZ59", 2, 6, 4, }, + { "Heusenstamm 4", "FKLZ81", 2, 6, 5, }, + { "Floersheim 1", "FKLZ38", 2, 6, 6, }, + { "Gross-Gerau 6", "FKLZ69", 2, 6, 7, }, + { "Langen i Hess 0", "FKLZ24", 2, 6, 8, }, + { "Moerfelden-Walldorf 5", "FKLZ26", 2, 6, 9, }, + { "Rodgau 3", "FKLZ17", 2, 6, 10, }, + { "Darmstadt 21", "FKLZ63", 2, 6, 11, }, + { "Darmstadt 2", "DA2", 2, 6, 12, }, + { "Ruesselsheim 3", "FKLZ70", 2, 6, 13, }, + { "Hofheim-Wallau 1", "FKLZ37", 2, 6, 15, }, + { "Eppstein 2", "FKLZ18", 2, 6, 16, }, + { "Wiesbaden 1", "WI1", 2, 6, 17, }, + { "Wiesbaden 33", "FKLZ34", 2, 6, 18, }, + { "Wiesbaden 34", "FKLZ32", 2, 6, 19, }, + { "Wiesbaden 35 (Igstadt)", "FKLZ35", 2, 6, 20, }, + { "Kelsterbach 0.9U", "MDR", 2, 6, 21, }, + { "Mainz-Kastel 2", "FKLZ33", 2, 6, 22, }, + { "Mainz 3", "FKLZ29", 2, 6, 23, }, + { "Mainz 4", "FKLZ27", 2, 6, 24, }, + { "Mainz 5", "FKLZ30", 2, 6, 25, }, + { "Mainz 26", "FKLZ28", 2, 6, 26, }, + { "Niedernhausen 4", "FKLZ80", 2, 6, 27, }, + { "Eppstein 1", "EPP1", 2, 6, 28, }, + { "Roedermark 7", "ROEM7", 2, 6, 30, }, + { "Kastellaun 2", "KAST", 2, 6, 31, }, + { "Lorch Rheingau 3", "FKLZ45", 2, 6, 32, }, + { "Oppenheim 1", "FKLZ53", 2, 6, 34, }, + { "Pfungstadt 1", "FKLZ40", 2, 6, 35, }, + { "Bad Soden 3", "FKLZ76", 2, 6, 36, }, + { "Kronberg i Taunus 3", "FKLZ21", 2, 6, 37, }, + { "Frankfurt 000 (Zeil)", "FKLZ01", 2, 6, 38, }, + { "Frankfurt 085 (Rohm)", "FKLZ04", 2, 6, 39, }, + { "Frankfurt 001 (Raim)", "FKLZ03", 2, 6, 40, }, + { "Frankfurt 118 (Giess)", "FKLZ05", 2, 6, 41, }, + { "Koenigstein i Taunus 3", "FKLZ20", 2, 6, 42, }, + { "Frankfurt 111 (D.Pl)", "FKLZ06", 2, 6, 43, }, + { "Neu-Isenburg 0.8Q", "FNI82", 2, 6, 44, }, + { "Frankfurt 120 (St.H)", "FKLZ12", 2, 6, 45, }, + { "Kriftel 0.8V", "HATH", 2, 6, 46, }, + { "Kelkheim Taunus 1", "FKLZ19", 2, 6, 47, }, + { "Oberursel Taunus 2", "FKLZ23", 2, 6, 48, }, + { "Frankfurt 123 (Berk)", "FKLZ13", 2, 6, 49, }, + { "Frankfurt 046 (Diest)", "FKLZ08", 2, 6, 50, }, + { "Frankfurt 88.9L(TGrVSt7/73)", "FKLZ02", 2, 6, 51, }, + { "Frankfurt 121 (Lyon)", "FKLZ10", 2, 6, 52, }, + { "Frankfurt 021 (Oeser)", "FKLZ11", 2, 6, 53, }, + { "Bad Vilbel 4 <ers. B. Vil5>", "FKLZ14", 2, 6, 54, }, + { "Frankfurt 82.8F (Orb)", "FKLZ07", 2, 6, 55, }, + { "Frankfurt 098 (Flugh)", "FKLZ64", 2, 6, 56, }, + { "Lorch Rheingau 4", "FKLZ43", 2, 6, 58, }, + { "Frankfurt 062 (O.Jah)", "FKLZ15", 2, 6, 61, }, + { "Nastaetten 1", "NAST1", 2, 6, 62, }, + { "Babenhausen 3", "FKLZ60", 2, 6, 63, }, + { "Ober-Ramstadt 5", "FKLZ41", 2, 6, 65, }, + { "Breuberg 1", "FKLZ67", 2, 6, 66, }, + { "Oberwesel 1", "OBWS1", 2, 6, 72, }, + { "Pfalzfeld 1", "PFLZ", 2, 6, 73, }, + { "Rheinboellen 2", "RHBO2", 2, 6, 74, }, + { "Ruedesheim a Rhein 2", "RUE2X", 2, 6, 75, }, + { "Eltville 2", "ELTV2", 2, 6, 76, }, + { "Winterbach 1", "ECK1", 2, 6, 77, }, + { "Boppard 1", "BOP1", 2, 6, 78, }, + { "Frankfurt 122 (O.Kr)", "FKLZ16", 2, 6, 79, }, + { "Stromberg 2 (Eckenroder F.)", "STRB2", 2, 6, 80, }, + { "Trebur 1 (SWF SGM)", "TRE1", 2, 6, 81, }, + { "Frankfurt 26.817", "FRSD", 2, 6, 83, }, + { "Main-Taunus-Zentrum", "MTZ", 2, 6, 84, }, + { "Besigheim 71", "HNKL25", 2, 7, 1, }, + { "Adelberg 0", "ADB0", 2, 7, 2, }, + { "Wildberg 71", "WILD", 2, 7, 3, }, + { "Tuebingen 7", "TBN7", 2, 7, 4, }, + { "Backnang 0", "BA0", 2, 7, 5, }, + { "Goeppingen 0", "GOEP41", 2, 7, 6, }, + { "Weilheim 1", "BOLL", 2, 7, 7, }, + { "Tuebingen 6", "TBN6X", 2, 7, 8, }, + { "Reutlingen 0", "REU0", 2, 7, 10, }, + { "Metzingen 4", "ULKL24", 2, 7, 12, }, + { "Trochtelfingen 2", "TCF2", 2, 7, 13, }, + { "Ebersbach 1", "EBRB41", 2, 7, 14, }, + { "Marbach 41", "SKLZ35", 2, 7, 15, }, + { "Bad Liebenzell 2", "BLIEB2", 2, 7, 16, }, + { "Bad Urach 2", "ULKL26", 2, 7, 17, }, + { "Lichtenstein 2", "ULKL25", 2, 7, 18, }, + { "Muensingen 1", "ULKL05", 2, 7, 19, }, + { "Suessen 0", "SUES0", 2, 7, 20, }, + { "Weinsberg 0", "HNKL23", 2, 7, 21, }, + { "Wendlingen 18", "WEND8", 2, 7, 22, }, + { "Gomadingen 1", "GOM1", 2, 7, 23, }, + { "Backnang 43", "BA43X", 2, 7, 24, }, + { "Maulbronn 42", "HNKL14", 2, 7, 25, }, + { "Ditzingen 5 (Siemens)", "DITZ99", 2, 7, 26, }, + { "Neuenstadt 41", "HNKL04", 2, 7, 27, }, + { "Neckarsulm 72", "HNKL07", 2, 7, 28, }, + { "Heilbronn 41", "HNKL08", 2, 7, 29, }, + { "Stuttgart 41 (Mitte)", "SKLZ06", 2, 7, 30, }, + { "Schwaigern 42", "HNKL10", 2, 7, 31, }, + { "Stuttgart 31 (Bahnpost.)", "SKLZ08", 2, 7, 32, }, + { "Heilbronn 1 (MB)", "HNKL11", 2, 7, 33, }, + { "Besigheim 42", "HNKL12", 2, 7, 34, }, + { "Stuttgart 580 (Daimler)", "SKLZ14", 2, 7, 35, }, + { "Waiblingen 3 (Wasserturm)", "SKLZ09", 2, 7, 36, }, + { "Winnenden 0", "SKLZ10", 2, 7, 37, }, + { "Brackenheim 1", "HNKL13", 2, 7, 38, }, + { "Waiblingen 4 (Remsh.-G.)", "SKLZ11", 2, 7, 39, }, + { "Leonberg 41", "LEO41", 2, 7, 40, }, + { "Stuttgart 582 (Th.-H.-K.)", "SKLZ13", 2, 7, 41, }, + { "Bad Wimpfen 41", "HNKL16", 2, 7, 42, }, + { "Stuttgart 45 (Esslingen)", "SKLZ15", 2, 7, 43, }, + { "Calw 3", "CLW3", 2, 7, 44, }, + { "Loewenstein 41", "HNKL17", 2, 7, 45, }, + { "Boeblingen 4 (Sindelf.)", "SKLZ20", 2, 7, 46, }, + { "Stuttgart 26 (Moehringen)", "SKLZ21", 2, 7, 47, }, + { "Stuttgart 62 (Vaihingen)", "SKLZ22", 2, 7, 48, }, + { "Weil der Stadt 41", "SKLZ23", 2, 7, 49, }, + { "Leonberg 5 (Rutesheim)", "SKLZ24", 2, 7, 50, }, + { "Schwaebisch Gmuend 2", "SGMD2", 2, 7, 51, }, + { "Stuttgart 10", "S10", 2, 7, 52, }, + { "Schorndorf 0", "SKLZ12", 2, 7, 53, }, + { "Muenchingen 51", "SKLZ27", 2, 7, 54, }, + { "Vaihingen 1", "SKLZ28", 2, 7, 55, }, + { "Stuttgart 589 (Flughafen)", "SKLZ18", 2, 7, 56, }, + { "Waldenbuch 3", "WBU3", 2, 7, 57, }, + { "Ludwigsburg 2", "SKLZ29", 2, 7, 58, }, + { "Stuttgart 7", "S7", 2, 7, 59, }, + { "Plochingen 1 (Krankenhaus)", "SKLZ16", 2, 7, 60, }, + { "Stuttgart 49 (Muenster)", "SKLZ04", 2, 7, 61, }, + { "Stuttgart 0 (FA 1)", "SKLZ07", 2, 7, 62, }, + { "Stuttgart 344 (Denkendorf)", "SKLZ31", 2, 7, 63, }, + { "Ludwigsburg 3", "SKLZ32", 2, 7, 64, }, + { "Sachsenheim 42", "SKLZ26", 2, 7, 65, }, + { "Stuttgart 361 (Schanbach)", "SKLZ30", 2, 7, 66, }, + { "Vaihingen 45", "HNKL18", 2, 7, 67, }, + { "Moensheim 43", "HNKL15", 2, 7, 68, }, + { "Neckartenzlingen 6", "SKLZ33", 2, 7, 69, }, + { "Stuttgart 179 (Echterd.)", "S179", 2, 7, 70, }, + { "Gomaringen 0", "GORI0", 2, 7, 71, }, + { "Beilstein 1", "BEIL1", 2, 7, 72, }, + { "Spraitbach 0", "SPRT0", 2, 7, 74, }, + { "Sulzbach 41", "SKLZ34", 2, 7, 75, }, + { "Lenningen 74 (Schopfloch)", "LNNG74", 2, 7, 76, }, + { "Bad Boll 0", "BOLL0", 2, 7, 77, }, + { "Heilbronn 18", "HB18", 2, 7, 79, }, + { "Weinsberg 42", "WEIN42", 2, 7, 80, }, + { "Lorch 1", "LRCH1", 2, 7, 82, }, + { "Nuertingen 41", "SKLZ02", 2, 7, 87, }, + { "Marbach 71", "SKLZ05", 2, 7, 89, }, + { "Kirchheim 0", "SKLZ17", 2, 7, 90, }, + { "Remseck 1", "NECK", 2, 7, 91, }, + { "Ehningen 4", "SKLZ19", 2, 7, 92, }, + { "Kaisersbach 1", "KABA1", 2, 7, 93, }, + { "Neuffen 0", "NFF0", 2, 7, 94, }, + { "Oberderdingen-Flehingen 3", "BAHN02", 2, 7, 96, }, + { "Markgroeningen 4 (Glemstal)", "BAHN03", 2, 7, 97, }, + { "Muenchen 852 (Planegg)", "M852", 2, 8, 2, }, + { "Muenchen 173 (Studentenstadt)", "M173", 2, 8, 3, }, + { "Muenchen 44 (Ufg Ahornstr)", "MKLZ34", 2, 8, 4, }, + { "Muenchen 614 (Oberhaching)", "M613", 2, 8, 5, }, + { "Sauerlach 2", "MKLZ29", 2, 8, 6, }, + { "Vaterstetten 1", "VATS1", 2, 8, 10, }, + { "Muenchen 18", "M18", 2, 8, 29, }, + { "Muenchen 108 (Blumenstrasse)", "MKLZ01", 2, 8, 30, }, + { "Muenchen 270 (Isabellastrasse)", "MKLZ02", 2, 8, 31, }, + { "Muenchen 103 (Arabellastrasse)", "MKLZ03", 2, 8, 32, }, + { "Muenchen 104 (Kirchenstrasse)", "MKLZ04", 2, 8, 33, }, + { "Muenchen 113 (Siemens Werinh)", "MKLZ05", 2, 8, 34, }, + { "Muenchen 0 (Blutenburgstrasse)", "MKLZ08", 2, 8, 37, }, + { "Muenchen 109 (Neuherbergstr.)", "MKLZ09", 2, 8, 38, }, + { "Muenchen 430 (Am Luessl 15)", "MKLZ12", 2, 8, 39, }, + { "Muenchen 106 (Rennb.Daglfing)", "MKLZ11", 2, 8, 40, }, + { "Muenchen 670 (Heinrich-Luebke)", "MKLZ13", 2, 8, 41, }, + { "Muenchen 107 (Harlaching KH)", "MKLZ14", 2, 8, 42, }, + { "Muenchen 112 (Baierbr.Str.)", "MKLZ15", 2, 8, 43, }, + { "Muenchen 110 (Winfrieds.Laim)", "MKLZ17", 2, 8, 45, }, + { "Muenchen 105 (Grossm.Thalk.S.)", "MKLZ06", 2, 8, 48, }, + { "Muenchen 111 (Philips Ridler)", "MKLZ07", 2, 8, 49, }, + { "Muenchen 117 (Garching)", "MKLZ20", 2, 8, 52, }, + { "Gilching 4 <Ers. f. M410>", "GIL98", 2, 8, 54, }, + { "Muenchen 114 (Germering)", "MKLZ21", 2, 8, 55, }, + { "Muenchen 22 (Unterschleissh.)", "MKLZ23", 2, 8, 57, }, + { "Hoehenkirchen 2 <ers. MKLZ24>", "HK99", 2, 8, 58, }, + { "Muenchen 115 (Baierbrunn)", "MKLZ27", 2, 8, 61, }, + { "Muenchen 65 (Stiftsbogen)", "MKLZ35", 2, 8, 84, }, + { "Muenchen 51 (Alzeyerstr.)", "MKLZ36", 2, 8, 85, }, + { "Nuernberg 0", "N0", 2, 9, 1, }, + { "Nuernberg 5", "N5", 2, 9, 4, }, + { "Nennslingen 1", "NNL1", 2, 9, 5, }, + { "Betzenstein 1", "BTZ1", 2, 9, 6, }, + { "Schnaittach 2", "SCHNA", 2, 9, 9, }, + { "Rothenburg 1", "RBRG1", 2, 9, 14, }, + { "Roth 0", "ROHT0", 2, 9, 19, }, + { "Altdorf-Autobahnkreuz 52", "ALTD51", 2, 9, 20, }, + { "Feucht 0", "FEU0", 2, 9, 21, }, + { "Ansbach 1", "ANSB", 2, 9, 23, }, + { "Nuernberg-OPD 9", "N1", 2, 9, 27, }, + { "Nuernberg-Marienberg 92", "N11", 2, 9, 28, }, + { "Nuernberg-Bundesanstalt 89", "N13", 2, 9, 30, }, + { "Nuernberg-Heizkraftwerk 91", "N14", 2, 9, 31, }, + { "Eschenbach 1", "EBA1", 2, 9, 32, }, + { "Nuernberg-Mueller Verlag 94", "N16", 2, 9, 33, }, + { "Lauf 1", "N21", 2, 9, 34, }, + { "Postbauer-Heng 1", "N22", 2, 9, 35, }, + { "Schwabach 5", "N23", 2, 9, 36, }, + { "Herzogenaurach 0", "N29", 2, 9, 37, }, + { "Langenzenn 1", "N25", 2, 9, 38, }, + { "Erlangen 1", "N26", 2, 9, 39, }, + { "Fuerth-Sparkasse 902", "N37", 2, 9, 41, }, + { "Fuerth-Stadeln 904", "N35", 2, 9, 42, }, + { "Nuernberg-Triumph Adler 93", "N15", 2, 9, 43, }, + { "Veitsbronn 3", "N27", 2, 9, 44, }, + { "Rosstal 4", "N28", 2, 9, 45, }, + { "Erlangen 98", "ERL99", 2, 9, 46, }, + { "Sulzbach-Rosenberg 0", "SUBA0", 2, 9, 49, }, + { "Eckental 1", "ECKT1", 2, 9, 51, }, + { "Nuernberg-Suedpumpwerk 905", "N31", 2, 9, 53, }, + { "Wendelstein 2", "N33", 2, 9, 54, }, + { "Erlangen 60", "N30", 2, 9, 56, }, + { "Nuernberg-BePo 907", "N32", 2, 9, 58, }, + { "Hessdorf 0", "HESS0", 2, 9, 60, }, + { "Treuchtlingen 1", "TREU1", 2, 9, 61, }, + { "Solnhofen 3", "MOHM", 2, 9, 62, }, + { "Pommelsbrunn 1", "PMBN1", 2, 9, 63, }, + { "Neustadt 3", "NSDA2", 2, 9, 64, }, + { "Langenfeld 1", "LFD1", 2, 9, 65, }, + { "Stein 901", "N34", 2, 9, 66, }, + { "Graefenberg 2", "GRBG2", 2, 9, 67, }, + { "Hoechstadt 4", "HCH4", 2, 9, 68, }, + { "Ebermannstadt 1", "EBMN1", 2, 9, 69, }, + { "Schwabach 0", "SBA99", 2, 9, 70, }, + { "Uffenheim 4", "UFF2", 2, 9, 71, }, + { "Wilhermsdorf 1", "WILH1", 2, 9, 72, }, + { "Thalmaessing 2", "THMA2", 2, 9, 73, }, + { "Wittelshofen 1", "WITH1", 2, 9, 74, }, + { "Windsbach 2", "WNDB2", 2, 9, 76, }, + { "Gunzenhausen 1", "GZHS0", 2, 9, 78, }, + { "Allersberg 1", "ALBG1", 2, 9, 79, }, + { "Wiesenttal 1", "WTAL1", 2, 9, 80, }, + { "Forchheim 2", "PBG99", 2, 9, 82, }, + { "Heilsbronn 1", "HBRO1", 2, 9, 85, }, + { "Oberasbach 690.47", "N36", 2, 9, 86, }, + { "Muehlhausen 3", "MH2", 2, 9, 88, }, + { "Kipfenberg 3", "KIBG3", 2, 9, 93, }, + { "Burgbernheim 2", "BBH2", 2, 9, 94, }, + { "Greding 3", "GDN3", 2, 9, 99, }, + { "Moenchengladbach-Rheydt 8", "MGL8", 3, 2, 13, }, + { "Teicha 2", "PHA", 3, 3, 1, }, + { "Greifenhagen 1", "SSN", 3, 3, 2, }, + { "Markransteadt 2", "MARKR2", 3, 3, 4, }, + { "Groitsch 6", "LPZGRO", 3, 3, 6, }, + { "Graefenhainichen 4", "OSK", 3, 3, 7, }, + { "Liebertwolkwitz", "LIEW", 3, 3, 8, }, + { "Torgau 4", "TORG", 3, 3, 9, }, + { "Bitterfeld 1", "BTTF", 3, 3, 10, }, + { "Oschatz 3", "COL", 3, 3, 11, }, + { "Leipzig 8 (Stoetteritz)", "STTZ", 3, 3, 12, }, + { "Halle 15", "HALL", 3, 3, 13, }, + { "Grimma end", "GRI0", 3, 3, 14, }, + { "Weissenfels 7", "PTT", 3, 3, 15, }, + { "Leipzig 0 (Universitaet HH)", "LPZ", 3, 3, 16, }, + { "Markranstaedt 3 (Doelzig)", "LPZDLZ", 3, 3, 17, }, + { "Gaschwitz 0", "LPZGAS", 3, 3, 18, }, + { "Leipzig 26 (Lausen)", "LPZLAU", 3, 3, 19, }, + { "Leipzig 70 (Seehausen)", "LPZMOC", 3, 3, 20, }, + { "Schkeuditz 2 (end)", "LPZSCH", 3, 3, 21, }, + { "Koethen 8", "KOET", 3, 3, 22, }, + { "Brandis 2 (Machern)", "MAC", 3, 3, 23, }, + { "Delitzsch 1", "DELI", 3, 3, 24, }, + { "Leipzig 3 (Holzhausen)", "LPZHOL", 3, 3, 25, }, + { "Nebra 3", "WGN", 3, 3, 26, }, + { "Zeitz 9", "ZEITZ", 3, 3, 27, }, + { "Querfurt 2", "QUERF", 3, 3, 28, }, + { "Cobbelsdorf 4", "COBB4", 3, 3, 36, }, + { "Leipzig 49 (Stahmeln)", "LPZSTA", 3, 3, 37, }, + { "Altenburg 2", "ALBG", 3, 3, 38, }, + { "Leipzig 10 (Connewitz)", "LPZTV3", 3, 3, 40, }, + { "Taucha 2", "LPZTAU", 3, 3, 41, }, + { "Leipzig 31 (Eutritzsch)", "LPZEUT", 3, 3, 42, }, + { "Leipzig 69 (Schoenefeld)", "LPZSFE", 3, 3, 43, }, + { "Dommitzsch 1 (Roitzsch)", "ROI", 3, 3, 44, }, + { "Leipzig 62 (Adler)", "LPZPLA", 3, 3, 45, }, + { "Naumburg 0", "NAUM", 3, 3, 46, }, + { "Leipzig 73 (Gohlis)", "LPZGOH", 3, 3, 47, }, + { "Halle 2 (Seeben)", "HZ04", 3, 3, 48, }, + { "Sangerhausen 2", "LENG", 3, 3, 49, }, + { "Halle 21 (Bruckdorf)", "HZ01", 3, 3, 50, }, + { "Colditz 1", "COLD1", 3, 3, 52, }, + { "Hartha 1", "HTA", 3, 3, 56, }, + { "Dessau 12.97B1 (Sued)", "DESS12", 3, 3, 58, }, + { "Eisleben 5", "ORIDF", 3, 3, 59, }, + { "Teutschenthal", "TEUTS", 3, 3, 60, }, + { "Halle 33 (Silberhoehe)", "HZ05", 3, 3, 61, }, + { "Halle 39 (Neustadt)", "HZ02", 3, 3, 62, }, + { "Merseburg 0", "MRSB", 3, 3, 63, }, + { "Schmoelln 1", "SMLL1", 3, 3, 70, }, + { "Eilenburg 7", "EBG", 3, 3, 71, }, + { "Hayn 2", "HAY", 3, 3, 72, }, + { "Dessau 1 (Mildensee prov)", "DESS", 3, 3, 73, }, + { "Borna 0", "BORNA", 3, 3, 74, }, + { "Belgern 2", "BELPU", 3, 3, 75, }, + { "Hettstedt 3", "HSDT", 3, 3, 76, }, + { "Bad Dueben 5 (Wellaune)", "BDUEB", 3, 3, 77, }, + { "Halle 37 (Peissen)", "HZ03", 3, 3, 78, }, + { "Halle 14 (Heide-Nord)", "HZ06", 3, 3, 79, }, + { "Oelzschau 1", "BGHN", 3, 3, 80, }, + { "Doebeln 5", "DOEB", 3, 3, 81, }, + { "Coswig-Anhalt 6 (end)", "COSA6", 3, 3, 82, }, + { "Mockrehna 1", "MOCK", 3, 3, 83, }, + { "Leipzig 19 (Leutzsch)", "LPZLEU", 3, 3, 84, }, + { "Hohenmoelsen", "HOML1", 3, 3, 85, }, + { "Wittenberg 0 (end)", "WITTB0", 3, 3, 86, }, + { "Bad Duerrenberg 4.97B1", "BDUE", 3, 3, 87, }, + { "Kropstaedt 1000", "KROP10", 3, 3, 88, }, + { "Leipzig 32 (Markleeberg)", "LPZMMA", 3, 3, 89, }, + { "Schiffdorf 2", "SCHFD2", 3, 4, 1, }, + { "Emden 0", "EM0", 3, 4, 2, }, + { "Bad Zwischenahn 0", "BZW0", 3, 4, 4, }, + { "Wardenburg 0", "WARD0", 3, 4, 5, }, + { "Bremen 38 (Utbremer Str.)", "BRM38", 3, 4, 6, }, + { "Verden-Walle 1", "VWA1", 3, 4, 7, }, + { "Hoya 1", "HOY1", 3, 4, 8, }, + { "Heeslingen-Boitzen 1", "HSL1", 3, 4, 9, }, + { "Aurich", "AURI", 3, 4, 10, }, + { "Borkum 0", "BORK0", 3, 4, 11, }, + { "Doerpen 0", "DOER0", 3, 4, 12, }, + { "Vechta-Langfoerden 1", "VLF1", 3, 4, 14, }, + { "Jever 0", "JEV", 3, 4, 15, }, + { "Rotenburg 0", "ROTB0", 3, 4, 16, }, + { "Wilhelmshaven 0", "WHV0", 3, 4, 18, }, + { "Cuxhaven 10", "CUX10", 3, 4, 23, }, + { "Harsefeld 1", "HSFD1", 3, 4, 24, }, + { "Leer 1", "LEE1", 3, 4, 25, }, + { "Helgoland 0", "HGL0", 3, 4, 26, }, + { "Hemmoor 1/2", "HMO1", 3, 4, 27, }, + { "Hambergen 1", "HMB1", 3, 4, 28, }, + { "Bassum 3", "BAS3", 3, 4, 29, }, + { "Stade 1", "STD1", 3, 4, 30, }, + { "Bremen 0 (Neuenstr.76)", "BRM0", 3, 4, 31, }, + { "Ottersberg 2", "OTT2", 3, 4, 33, }, + { "Visselhoevede 0", "VISS0", 3, 4, 34, }, + { "Westerstede 9", "WSST9", 3, 4, 35, }, + { "Bremen 135 (Findorf)", "BRM135", 3, 4, 37, }, + { "Ritterhude 0", "RTH0", 3, 4, 38, }, + { "Delmenhorst 0", "DLH0", 3, 4, 39, }, + { "Bremen 80 (Stuhr/Seckenh.)", "BRM80", 3, 4, 40, }, + { "Weyhe 0", "WYH0", 3, 4, 41, }, + { "Bremen 136 (Tenever Hochhs)", "BRM136", 3, 4, 42, }, + { "Lilienthal 3", "LLT3", 3, 4, 43, }, + { "Hude Oldb 0", "HUD0", 3, 4, 45, }, + { "Oldenburg 1 (MB)", "OD1", 3, 4, 47, }, + { "Oldenburg 0", "OD0", 3, 4, 48, }, + { "Norden 0", "NDN0", 3, 4, 65, }, + { "Bremen 130 (Walle Hochhaus)", "BRM130", 3, 4, 67, }, + { "Bremen 131 (Woltmershausen)", "BRM131", 3, 4, 68, }, + { "Bremen 51 (Grolland)", "BRM132", 3, 4, 69, }, + { "Bremen 133 (Huckelriede)", "BRM133", 3, 4, 70, }, + { "Bremen 134 (In der Wisch)", "BRM134", 3, 4, 71, }, + { "Bremen 137 (Kloeckner)", "BRM137", 3, 4, 74, }, + { "Bremen 138 (Grohner Duene)", "BRM138", 3, 4, 75, }, + { "Gross Ippener 0", "GIP0", 3, 4, 77, }, + { "Sulingen 0", "SLG0", 3, 4, 78, }, + { "Hatten 10", "HAT0", 3, 4, 79, }, + { "Zeven 2", "ZEV2", 3, 4, 80, }, + { "Berne 0", "BERN0", 3, 4, 85, }, + { "Bremervoerde 0", "BRV0", 3, 4, 87, }, + { "Osterh.-Scharmb.-Garlst.0", "OHZG0", 3, 4, 88, }, + { "Wangerland-Horumersiel 0", "HMS0", 3, 4, 89, }, + { "Wildeshausen 11", "WHS11", 3, 4, 90, }, + { "Langeoog 1", "LOG0", 3, 4, 91, }, + { "Varel 1", "VRL1", 3, 4, 92, }, + { "Friesoythe 0", "FRY0", 3, 4, 93, }, + { "Kirchlinteln 1", "KIRL1", 3, 4, 94, }, + { "Papenburg 0", "PAP0", 3, 4, 95, }, + { "Cloppenburg 0", "CLP0", 3, 4, 96, }, + { "Wittmund-Burhafe 1", "WITB1", 3, 4, 98, }, + { "Homberg 1", "HRE1", 3, 5, 1, }, + { "Morschen 2", "BEIS", 3, 5, 2, }, + { "Spangenberg 1", "SPBG", 3, 5, 3, }, + { "Kassel Baunatal", "KSBT", 3, 5, 5, }, + { "Korbach 0", "KOR0", 3, 5, 8, }, + { "Arolsen 0", "AROL1", 3, 5, 9, }, + { "Zierenberg 3", "ZIE3", 3, 5, 10, }, + { "Hofgeismar 2", "HFGM2", 3, 5, 11, }, + { "Bad Karlshafen 1", "BKFN1", 3, 5, 12, }, + { "Fritzlar 2", "FRITZ2", 3, 5, 13, }, + { "Warburg 2", "WAR2", 3, 5, 14, }, + { "Willebadessen 1", "WBE1", 3, 5, 15, }, + { "Goettingen 2", "GOE2", 3, 5, 17, }, + { "Moringen-Fredelsloh 1", "MOF1", 3, 5, 18, }, + { "Zierenberg 1", "ZIE1", 3, 5, 19, }, + { "Grossalmerode 1", "GRA1X", 3, 5, 21, }, + { "Kassel 1", "KS1", 3, 5, 22, }, + { "Herzberg 0", "HERZ0", 3, 5, 25, }, + { "Holzminden-Neuhaus 2", "HZH2", 3, 5, 26, }, + { "Rosdorf 40", "ROSD40", 3, 5, 27, }, + { "Osterode 40", "OSRR40", 3, 5, 28, }, + { "Eschwege 5", "ESW5", 3, 5, 30, }, + { "Sontra 2", "SONT2", 3, 5, 31, }, + { "Melsungen 5", "MELS5", 3, 5, 32, }, + { "Hann Muenden 2", "HMUE2", 3, 5, 33, }, + { "Reinhardshagen 40", "RAHG40", 3, 5, 34, }, + { "Bad Sachsa 1", "BSA1", 3, 5, 35, }, + { "Hann Muenden 3", "BAHN06", 3, 5, 38, }, + { "Northeim 4", "NORT4", 3, 5, 39, }, + { "Kassel Vellmar", "KSVM", 3, 5, 41, }, + { "Braunlage 40", "BRL40", 3, 5, 43, }, + { "Waldkappel 99", "WALD99", 3, 5, 44, }, + { "Edertal 99", "EDT99", 3, 5, 45, }, + { "Brakel 2", "BRAK2", 3, 5, 46, }, + { "Hessisch Lichtenau 97", "HELI97", 3, 5, 47, }, + { "Duderstadt Wasserwerk", "DUDW", 3, 5, 48, }, + { "Bad Sooden Allendorf 1", "BSAD1", 3, 5, 49, }, + { "Bad Wildungen 1", "BWN1", 3, 5, 51, }, + { "Woelfterode 99", "WROD99", 3, 5, 54, }, + { "Kalefeld 40", "KD40", 3, 5, 55, }, + { "Kassel 4", "KS4", 3, 5, 56, }, + { "Buchenberg 99", "BUBG99", 3, 5, 58, }, + { "Frankfurt 016", "F16", 2, 6, 1, }, + { "Bad Homburg 0 <FDG>", "BHBG0", 3, 6, 1, }, + { "Friedberg 1", "FB1", 3, 6, 2, }, + { "Schotten Hess 1", "STT1", 3, 6, 3, }, + { "Gelnhausen 7", "GN7", 3, 6, 4, }, + { "Bad Schwalbach 3", "FKLZ83", 3, 6, 5, }, + { "Friedberg 0", "FB0", 3, 6, 6, }, + { "Biedenkopf 2 <prov>", "BID2", 3, 6, 7, }, + { "Biedenkopf 3", "BID3", 3, 6, 10, }, + { "Birstein 3", "BIR3", 3, 6, 11, }, + { "Weibersbrunn 2", "WBBR2", 3, 6, 12, }, + { "Kalbach 1", "KALB1", 3, 6, 13, }, + { "Driedorf 2", "DRIE2", 3, 6, 14, }, + { "Lich 2 <Steinbach Bw-Mast>", "LICH0", 3, 6, 15, }, + { "Hilders 2", "HIL2", 3, 6, 17, }, + { "Frankenberg 0", "FRANK0", 3, 6, 18, }, + { "Friedewald 1", "FDWD1", 3, 6, 19, }, + { "Hanau 1", "FKLZ50", 3, 6, 21, }, + { "Gemuenden/Felda 1", "GMF1", 3, 6, 22, }, + { "Gruenberg 0", "GRNB0", 3, 6, 23, }, + { "Hanau 7", "HU7", 3, 6, 24, }, + { "Hungen 2", "HUNG2", 3, 6, 25, }, + { "Gemuenden 1", "GMU1", 3, 6, 26, }, + { "Biebertal 1", "BIT1", 3, 6, 27, }, + { "Marburg 2", "MAR2", 3, 6, 28, }, + { "Haina Kloster 1 <n. Turm>", "HKL1", 3, 6, 29, }, + { "Weilburg 6", "WBG6", 3, 6, 30, }, + { "Fulda 3", "FD3", 3, 6, 31, }, + { "Bad Hersfeld 2", "BHEF2", 3, 6, 32, }, + { "Schluechtern 3", "SLN3", 3, 6, 33, }, + { "Neuenstein Hess 1", "NST1", 3, 6, 34, }, + { "Ebersburg 2", "EBER2", 3, 6, 35, }, + { "Lauterbach 1", "LAT1", 3, 6, 36, }, + { "Gruenberg 1", "GRUEN1", 3, 6, 37, }, + { "Ortenberg 1", "ORT1", 3, 6, 38, }, + { "Alsfeld 1", "ALS1", 3, 6, 39, }, + { "Katzenelnbogen 1", "KATZ1", 3, 6, 41, }, + { "Aarbergen 1", "FKLZ47", 3, 6, 43, }, + { "Bad Schwalbach 2", "FKLZ48", 3, 6, 45, }, + { "Schlangenbad 1", "FKLZ49", 3, 6, 46, }, + { "Lich Hess. Eberstadt 1", "EBST1", 3, 6, 47, }, + { "Aschaffenburg 14", "AB14", 3, 6, 48, }, + { "Schwalmstadt 1", "SSDT1", 3, 6, 50, }, + { "Nentershausen", "NENT", 3, 6, 51, }, + { "Reichelsheim 2", "FKLZ62", 3, 6, 52, }, + { "Woelfersheim 2 <Wbh>", "FKLZ68", 3, 6, 53, }, + { "Limburg 1", "LM1", 3, 6, 54, }, + { "Rotenburg 1 (TVU)", "ROF3", 3, 6, 55, }, + { "Burgsinn 8", "BAHN11", 3, 6, 56, }, + { "Schlitz 3", "SLTZ", 3, 6, 57, }, + { "Wildeck 1", "WECK1", 3, 6, 58, }, + { "Friedrichsdorf 0.8I", "KPTL", 3, 6, 59, }, + { "Taunusstein 2", "FKLZ46", 3, 6, 60, }, + { "Giessen 0", "GI0", 3, 6, 61, }, + { "Linden 5", "GI3", 3, 6, 62, }, + { "Breitenbach 3", "BHERZ", 3, 6, 63, }, + { "Bad Brueckenau 1", "BADBR1", 3, 6, 64, }, + { "Buseck 6.8Q", "BUS6", 3, 6, 65, }, + { "Eckartshausen 2 endg.", "FKLZ72", 3, 6, 66, }, + { "Steinau 1 (Fa ODW)", "STEI1", 3, 6, 68, }, + { "Nidda 3", "NID3", 3, 6, 69, }, + { "Braunfels 5", "BRAU5", 3, 6, 70, }, + { "Langenselbold 0", "LSBD0", 3, 6, 71, }, + { "Usingen 2", "USI2", 3, 6, 72, }, + { "Ehringshausen 1", "EHR1", 3, 6, 74, }, + { "Seligenstadt 2", "FKLZ25", 3, 6, 75, }, + { "Bad Nauheim 2", "BNAU2", 3, 6, 77, }, + { "Aschaffenburg 11", "AB11", 3, 6, 78, }, + { "Aschaffenburg 13", "AB13", 3, 6, 79, }, + { "Hanau-Grossauheim 5", "HUAU", 3, 6, 80, }, + { "Dillenburg 1", "DILB1", 3, 6, 81, }, + { "Eschenburg 1", "ESCH1", 3, 6, 82, }, + { "Herleshausen 1", "HERL1", 3, 6, 83, }, + { "Idstein 2", "FKLZ36", 3, 6, 84, }, + { "Herborn Hess. 3", "HRBN3", 3, 6, 85, }, + { "Selters 3", "SELT3", 3, 6, 86, }, + { "Bad Camberg 3", "BCA3", 3, 6, 87, }, + { "Karben 1", "FKLZ65", 3, 6, 88, }, + { "Lohr 2", "LOHR2", 3, 6, 89, }, + { "Neuhof-Fulda 3(Landruecken)", "BAHN10", 3, 6, 90, }, + { "Esselbach 2", "ESB2", 3, 6, 91, }, + { "Moembris 4", "MOEM4", 3, 6, 92, }, + { "Obernburg 1", "OBG99", 3, 6, 93, }, + { "Wetzlar 3", "WZ3", 3, 6, 94, }, + { "Guxhagen 1 (Koerle)", "BAHN07", 3, 6, 95, }, + { "Niederaula 3 (Kirchheim)", "BAHN08", 3, 6, 96, }, + { "Huenfeld 2 (Dietershan)", "BAHN09", 3, 6, 97, }, + { "Wiesen 1", "WIES1", 3, 6, 98, }, + { "Faulbach 2", "FAUL2", 3, 6, 99, }, + { "Baden-Baden 5", "BAD5", 3, 7, 1, }, + { "Pforzheim 7", "PFO7", 3, 7, 2, }, + { "Loerrach 4", "LOR4X", 3, 7, 3, }, + { "Badenweiler 1", "BAW1", 3, 7, 4, }, + { "Titisee-Neustadt 4", "TITI4", 3, 7, 5, }, + { "Vogtsburg 1", "VO1", 3, 7, 6, }, + { "Grenzach-Whylen 1", "GRWY1", 3, 7, 7, }, + { "Hausach 1", "HAU1", 3, 7, 8, }, + { "Willstaett 1", "WST1", 3, 7, 9, }, + { "Bad Herrenalb 3", "BHA3", 3, 7, 10, }, + { "Karlsruhe 7 (Hagsfeld)", "KA7", 3, 7, 11, }, + { "Rastatt 6", "RAST6", 3, 7, 12, }, + { "Freiburg-Tiengen P01", "FRT3", 3, 7, 13, }, + { "Gaggenau 0", "GAG", 3, 7, 14, }, + { "Efringen-Kirchen 4", "EFI4", 3, 7, 15, }, + { "Lichtenau 0", "LICHT", 3, 7, 16, }, + { "Eppingen 2", "HNKL09", 3, 7, 17, }, + { "Bad Rappenau 0", "HNKL03", 3, 7, 18, }, + { "Kirchhardt 2", "HNKL05", 3, 7, 19, }, + { "Oberkirch 3", "OBK3", 3, 7, 20, }, + { "Oppenau 2", "OPP2", 3, 7, 21, }, + { "Offenburg 0", "OG", 3, 7, 22, }, + { "Lahr 0", "LAHR", 3, 7, 23, }, + { "Ettenheim 3", "ETT3", 3, 7, 24, }, + { "Achern 2", "ACH2", 3, 7, 25, }, + { "Schwanau 0", "SCNA", 3, 7, 26, }, + { "Oberderdingen-Flehingen 1", "ODF1", 3, 7, 27, }, + { "Pforzheim 2", "PFO2", 3, 7, 28, }, + { "Freiburg 51", "FR51", 3, 7, 29, }, + { "Denzlingen 0", "DENZ0", 3, 7, 30, }, + { "Schopfheim 2", "SPFH2", 3, 7, 31, }, + { "Gengenbach 2", "GEN2", 3, 7, 32, }, + { "Kirchzarten 4", "KIZN4", 3, 7, 33, }, + { "Waldkirch 0", "WAK0", 3, 7, 35, }, + { "Emmendingen 0", "EMMD0", 3, 7, 36, }, + { "Pforzheim 71 (Sonnenhof)", "PFO71", 3, 7, 37, }, + { "Rheinfelden 0", "RF0", 3, 7, 38, }, + { "Bruchsal-Untergrombach 2", "BRUG2", 3, 7, 39, }, + { "Loerrach 5", "LOR5", 3, 7, 40, }, + { "Walzbachtal 1", "KAKL21", 3, 7, 41, }, + { "Karlsruhe 0 (Haupt-PA)", "KAKL12", 3, 7, 42, }, + { "Oestringen 1", "KAKL48", 3, 7, 43, }, + { "Karlsruhe 1 (MB)", "KAKL40", 3, 7, 44, }, + { "Karlsruhe 170 (Neureut)", "KAKL14", 3, 7, 45, }, + { "Karlsruhe 83 (Siemens)", "KAKL15", 3, 7, 46, }, + { "Eichstetten 1", "EICHN1", 3, 7, 47, }, + { "Karlsruhe 88 (Th.-M.-Str.)", "KAKL16", 3, 7, 48, }, + { "Schliengen 3", "SCHLI3", 3, 7, 49, }, + { "Durmersheim 0", "KAKL42", 3, 7, 51, }, + { "Malsch 2", "KAKL19", 3, 7, 52, }, + { "Bruchsal 6", "KAKL22", 3, 7, 53, }, + { "Soellingen P01", "SOEL", 3, 7, 54, }, + { "Freiburg 58", "FR58", 3, 7, 55, }, + { "Freiburg-Industr. Nord P11", "FR11", 3, 7, 56, }, + { "Sinsheim 7", "KAKL23", 3, 7, 57, }, + { "Schluchsee 1", "SLSE1", 3, 7, 58, }, + { "Baden-Baden 0", "BAD0", 3, 7, 59, }, + { "Bad Schoenborn 5", "BSCHB5", 3, 7, 60, }, + { "Linkenheim-Hochstetten 3", "LIHO3", 3, 7, 61, }, + { "Baden-Baden 4", "BAD4", 3, 7, 62, }, + { "St. Blasien 1", "STB1", 3, 7, 63, }, + { "Kehl 0", "KEHL0", 3, 7, 66, }, + { "Marxzell 1", "MARXZ1", 3, 7, 67, }, + { "Bretten 3", "KAKL51", 3, 7, 68, }, + { "Muellheim 7", "MULL7", 3, 7, 70, }, + { "Sulzburg 4", "SULBG4", 3, 7, 75, }, + { "Neuenbuerg 1", "NEUBG1", 3, 7, 76, }, + { "Landau 2", "LAN2", 3, 7, 77, }, + { "Forbach 4", "FOR3", 3, 7, 79, }, + { "Germersheim 2", "KAKL53", 3, 7, 80, }, + { "Waghaeusel 2", "KAKL24", 3, 7, 81, }, + { "Rheinstetten 3", "RHEI3", 3, 7, 82, }, + { "Woerth a Rhein 0", "KAKL11", 3, 7, 83, }, + { "Ruelzheim 3", "KAKL09", 3, 7, 84, }, + { "Zell i.W. 1", "ZLIW1", 3, 7, 85, }, + { "Todtnau 3", "TODT3", 3, 7, 86, }, + { "Maulbronn 41", "MAUL", 3, 7, 87, }, + { "Koenigsbach-Stein 2", "KLSTB", 3, 7, 88, }, + { "Buehl 0", "BUE2", 3, 7, 90, }, + { "Schoenau 2", "SNAU2", 3, 7, 91, }, + { "Karlsbad 2 (Noettingen)", "NOETT", 3, 7, 92, }, + { "Kenzingen 3", "KEN3", 3, 7, 93, }, + { "Schoemberg-Calw 1", "SCA1", 3, 7, 95, }, + { "Wildbad 3 <Prov.>", "WILB1", 3, 7, 96, }, + { "Enzkloesterle 1", "ENZ1", 3, 7, 97, }, + { "Augsburg 1", "AU1", 3, 8, 1, }, + { "Augsburg 3 (Haunstetten)", "AU97", 3, 8, 2, }, + { "Augsburg 10", "AU10X", 3, 8, 3, }, + { "Pfronten 2", "PFN2", 3, 8, 4, }, + { "Dillingen 0", "DLGN0", 3, 8, 5, }, + { "Affing 2", "AFF2", 3, 8, 6, }, + { "Aichach 1", "AIC1", 3, 8, 7, }, + { "Eichstaett 1", "EICH1", 3, 8, 8, }, + { "Dirlewang 3", "DLW92", 3, 8, 9, }, + { "Eurasburg 1", "ERB1", 3, 8, 10, }, + { "Buchloe 1 <Prov. Buchloe 0>", "BULO1", 3, 8, 11, }, + { "Krumbach 2", "KRUM2", 3, 8, 12, }, + { "Meitingen 0", "MTN0", 3, 8, 13, }, + { "Mittelneufnach 1", "MNFN1", 3, 8, 14, }, + { "Schrobenhausen 4", "SBH4", 3, 8, 15, }, + { "Schwabmuenchen 0", "SWM0", 3, 8, 16, }, + { "Thannhausen 2", "THS2", 3, 8, 17, }, + { "Welden 3", "WE3", 3, 8, 18, }, + { "Ziemetshausen 2", "ZMH97", 3, 8, 19, }, + { "Guenzburg 70", "ULKL11", 3, 8, 20, }, + { "Oberstdorf 0", "OBDO0", 3, 8, 21, }, + { "Nesselwang 1", "NSW1", 3, 8, 22, }, + { "Neuburg 1 (IVK)", "NEUB99", 3, 8, 23, }, + { "Oberstaufen 4 (Stiesberg)", "OBST4", 3, 8, 24, }, + { "Groenenbach 1", "GROE1", 3, 8, 25, }, + { "Zusmarshausen 2", "ZUSM2", 3, 8, 26, }, + { "Fuessen 2", "FSN2", 3, 8, 27, }, + { "Lindau 1", "LIND1", 3, 8, 28, }, + { "Augsburg 4 (NCR)", "AU4", 3, 8, 29, }, + { "Augsburg 907", "AU907", 3, 8, 30, }, + { "Stammham 2", "STHA99", 3, 8, 33, }, + { "Ottobeuren 3", "OTTB2", 3, 8, 34, }, + { "Pfaffenhofen a d Ilm 5", "PFA5", 3, 8, 35, }, + { "Pfaffenhofen a d Ilm 0", "PFA0", 3, 8, 36, }, + { "Burgau 0", "BGU0", 3, 8, 37, }, + { "Schweitenkirchen 2", "SKI99", 3, 8, 38, }, + { "Ingolstadt-Zuchering 0", "IGZ", 3, 8, 39, }, + { "Vohburg 1", "VBG1", 3, 8, 40, }, + { "Wolnzach 1", "WOZ1", 3, 8, 41, }, + { "Tapfheim 1", "TAPF1", 3, 8, 42, }, + { "Unterringingen 1", "URR1", 3, 8, 43, }, + { "Kaisheim 3", "KSH98", 3, 8, 44, }, + { "Altenstadt 0 (Iller)", "ULKL04", 3, 8, 51, }, + { "Aitrang 2 (Bergbauer)", "AIT2", 3, 8, 52, }, + { "Babenhausen 1", "BBHN1", 3, 8, 54, }, + { "Gruenenbach 1", "GRB1", 3, 8, 55, }, + { "Immenstadt 1 (Alpe Hochried)", "IMST1", 3, 8, 57, }, + { "Kaufbeuren 7 (Mauerstetten)", "KFN7", 3, 8, 58, }, + { "Memmingen 0", "MEMM0", 3, 8, 59, }, + { "Oberguenzburg 1", "OGB1", 3, 8, 61, }, + { "Sonthofen 1", "SOHO1", 3, 8, 67, }, + { "Weiler 1", "WEIL1", 3, 8, 68, }, + { "Wiggensbach 2", "WIG2", 3, 8, 70, }, + { "Neuburg 2", "NEUB2", 3, 8, 78, }, + { "Poernbach 2", "PNB99", 3, 8, 81, }, + { "Dortmund 85 (Eving)", "DO85", 4, 2, 8, }, + { "Dresden 7 (Gompitz)", "GPZ", 4, 3, 1, }, + { "Crinitz 1", "BBB", 4, 3, 2, }, + { "Dresden 12 (Dachsenberg)", "DACHS", 4, 3, 3, }, + { "Weisswasser 0.47B1", "WSWS", 4, 3, 4, }, + { "Drebkau 1", "KLO", 4, 3, 5, }, + { "Senftenberg 6", "SENF6", 4, 3, 7, }, + { "Radeburg 1", "FRTL", 4, 3, 8, }, + { "Meissen 5 (end)", "MSSN", 4, 3, 9, }, + { "Pirna 7", "PIRN", 4, 3, 10, }, + { "Koenigswartha 1", "KWTA", 4, 3, 11, }, + { "Dresden 3 (Radebeul)", "DRES3", 4, 3, 12, }, + { "Dresden 1 (Postplatz)", "DRES1", 4, 3, 13, }, + { "Pulsnitz 4", "KEU", 4, 3, 14, }, + { "Loebau 5", "LBAU", 4, 3, 15, }, + { "Neukirch 5 (Picho)", "PICHO", 4, 3, 16, }, + { "Neustadt 1 (Unger)", "NEUDT1", 4, 3, 17, }, + { "Goerlitz 7", "GRLZ", 4, 3, 18, }, + { "Zittau 5", "ZTT", 4, 3, 19, }, + { "Altenberg 1 (Lugstein)", "LUGS", 4, 3, 20, }, + { "Riesa 4", "RIESA", 4, 3, 21, }, + { "Burkau 2", "BURK2", 4, 3, 22, }, + { "Dresden 79 (Goennsdorf)", "DRESBU", 4, 3, 23, }, + { "Jessen 2", "JESS", 4, 3, 24, }, + { "Dippoldiswalde 3", "DIPP", 4, 3, 25, }, + { "Heidenau 1", "DRESHE", 4, 3, 26, }, + { "Hoyerswerda 2", "HYWD", 4, 3, 27, }, + { "Dresden 27 ()", "DRESDS", 4, 3, 28, }, + { "Dresden 40 (Dorfhainer Str)", "DRES40", 4, 3, 29, }, + { "Dresden 75 (Striesen)", "DRES24", 4, 3, 30, }, + { "Elsterwerda 5", "HLP", 4, 3, 31, }, + { "Spremberg 5", "SPRE", 4, 3, 33, }, + { "D-Klotzs ???", "???", 4, 3, 34, }, + { "Herzberg 1", "HERZ", 4, 3, 35, }, + { "Dresden 77 (Prohlis)", "DRESNI", 4, 3, 36, }, + { "Niesky 5", "NSKY", 4, 3, 37, }, + { "Dresden 63 (Neustadt)", "DRESNS", 4, 3, 39, }, + { "Burkhardswalde 1", "BUHW", 4, 3, 40, }, + { "Guben 3 <Ers. f. GUBK>", "GUBEN2", 4, 3, 41, }, + { "Bautzen 1", "BZN", 4, 3, 42, }, + { "Bad Schandau 1", "BSD", 4, 3, 43, }, + { "Forst 2", "FORST", 4, 3, 44, }, + { "Bischofswerda 3", "BHW", 4, 3, 45, }, + { "Cottbus 8", "COTT8", 4, 3, 46, }, + { "Ortrand 0", "ORA", 4, 3, 47, }, + { "Tharandt 2", "THAR2", 4, 3, 48, }, + { "Drachhausen 1", "DH", 4, 3, 49, }, + { "Kamenz 5", "KAMZ5", 4, 3, 51, }, + { "Grossenhain 5", "GROS5", 4, 3, 52, }, + { "Lommatzsch 3", "LOMM3", 4, 3, 54, }, + { "Pirna 5", "PIRN5", 4, 3, 55, }, + { "Glashuette 1", "GLAS1", 4, 3, 56, }, + { "Coswig-Sachsen 4", "COSW4", 4, 3, 57, }, + { "Wilsdruff 2", "WILSD2", 4, 3, 59, }, + { "Finsterwalde 3", "FW", 4, 3, 60, }, + { "Neugersdorf 7", "NEUG7", 4, 3, 61, }, + { "Uhyst 1", "UHYS1", 4, 3, 64, }, + { "Pulsnitz 6", "PULS6", 4, 3, 66, }, + { "Doberlug-Kirchhain 2", "DOB2", 4, 3, 88, }, + { "Bad Doberan 5", "BDBN5", 4, 4, 1, }, + { "Crivitz 3", "CRIV", 4, 4, 2, }, + { "Wolgast 3", "WOLG", 4, 4, 3, }, + { "Schwaan 3", "SCHWAN", 4, 4, 4, }, + { "Rostock 26", "LTTK", 4, 4, 5, }, + { "Tessin 3", "TESS", 4, 4, 6, }, + { "Broderstorf 4 <Ers.f.BDD1>", "BDD4", 4, 4, 7, }, + { "Grimmen 2", "GRIM", 4, 4, 8, }, + { "Sassnitz 9 <Ers.f.SASS>", "SASS9", 4, 4, 9, }, + { "Rostock 10", "ROST10", 4, 4, 10, }, + { "Tribsees 3", "TRIB", 4, 4, 11, }, + { "Barth 3", "BART", 4, 4, 12, }, + { "Stralsund 0", "STS", 4, 4, 13, }, + { "Rostock 11", "RWEI", 4, 4, 14, }, + { "Ribnitz-Damgarten 8<Erf.DAS>", "RIBD", 4, 4, 15, }, + { "Kroepelin 2", "KROEP2", 4, 4, 16, }, + { "Greifswald 4", "GRW", 4, 4, 17, }, + { "Bergen 0", "BRN", 4, 4, 18, }, + { "Guestrow 20 <Ers.f.GSW>", "GSW20", 4, 4, 19, }, + { "Schwerin 20", "SRN", 4, 4, 20, }, + { "Bennin 1", "GRAH", 4, 4, 21, }, + { "Ludwigslust 2 <Ers.f.LUDWL>", "LUDWL2", 4, 4, 24, }, + { "Parchim 5", "PARC", 4, 4, 25, }, + { "Bernitt 1", "BZ4", 4, 4, 26, }, + { "Wittenburg 2", "ZIGM", 4, 4, 27, }, + { "Wismar 6", "WISM", 4, 4, 28, }, + { "Gross Godems 1", "STPE", 4, 4, 29, }, + { "Sternberg 2", "STERN", 4, 4, 30, }, + { "Cambs 6", "RMP", 4, 4, 31, }, + { "Schwerin 4", "SRS", 4, 4, 32, }, + { "Rastow 2", "RASW", 4, 4, 33, }, + { "Marnitz 1", "RUBG", 4, 4, 34, }, + { "Goldberg 4 <Ers.f.KKW>", "GOLD4", 4, 4, 35, }, + { "Grevesmuehlen 5", "HBGE", 4, 4, 36, }, + { "Gammelin 1", "BAND", 4, 4, 37, }, + { "Redefin 2", "REDEL", 4, 4, 38, }, + { "Roggendorf 1", "RGND1", 4, 4, 39, }, + { "Heringsdorf 4", "HID4", 4, 4, 40, }, + { "Torgelow 3", "TOR3", 4, 4, 42, }, + { "Zuessow 4", "ZUES4", 4, 4, 43, }, + { "Lalendorf 4", "HOPE2", 4, 4, 44, }, + { "Krakow 4", "KKW4", 4, 4, 45, }, + { "Goehren 2", "GOER2", 4, 4, 46, }, + { "Anklam 2", "ANK", 4, 4, 47, }, + { "Burow 1", "GOL", 4, 4, 48, }, + { "Waren 5", "WAREN", 4, 4, 49, }, + { "Jarmen 7", "JARM", 4, 4, 52, }, + { "Malchin 5", "RZW", 4, 4, 53, }, + { "Friedland 3", "FRIL", 4, 4, 56, }, + { "Stavenhagen 0", "STVH", 4, 4, 57, }, + { "Ueckermuende 3", "UECK", 4, 4, 58, }, + { "Schoenberg 5 <Ers.f.Repeat>", "SCHOEB", 4, 4, 65, }, + { "Demmin 0", "DEMM", 4, 4, 66, }, + { "Altenkirchen 7", "ALTK7", 4, 4, 99, }, + { "Saarbruecken 2 <Winterberg>", "SBW", 4, 6, 1, }, + { "Welschbillig 3", "WBIL3", 4, 6, 2, }, + { "Hallschlag 3", "HASC3", 4, 6, 3, }, + { "Marpingen 1 (Tholey)", "MAPI1", 4, 6, 4, }, + { "Konz 5", "KONZ5", 4, 6, 5, }, + { "Simmern 3", "SIMME3", 4, 6, 7, }, + { "Saarlouis 0", "SLO0", 4, 6, 8, }, + { "Saarbruecken 5 (OPD)", "SB5", 4, 6, 9, }, + { "Perl 1", "PERL", 4, 6, 11, }, + { "Gemuenden 3", "GMU3", 4, 6, 13, }, + { "Pirmasens 2", "PIR2", 4, 6, 16, }, + { "Konken 3", "KKN3", 4, 6, 17, }, + { "Glan-Muenchweiler 3 (KL2)", "GMW4", 4, 6, 18, }, + { "Reichenbach-Steegen 6", "RST6", 4, 6, 19, }, + { "Landstuhl 14", "LST14", 4, 6, 20, }, + { "Weilerbach 4 (KL2)", "WLB4", 4, 6, 21, }, + { "Trier 1", "TR1", 4, 6, 22, }, + { "Kell 1", "KLL1", 4, 6, 23, }, + { "Blieskastel 2", "BLIES2", 4, 6, 24, }, + { "Bernkastel-Kues 1", "BNK1", 4, 6, 25, }, + { "Pruem 2", "PRM2", 4, 6, 26, }, + { "Idar-Oberstein 1", "IDO1", 4, 6, 27, }, + { "Bruchmuehlbach 4", "BMLB4", 4, 6, 28, }, + { "Dellfeld 1", "DELL1", 4, 6, 30, }, + { "Homburg 0", "HBG0", 4, 6, 31, }, + { "Kastellaun 3", "KAST3", 4, 6, 32, }, + { "Schoeneberg - Kuebelberg 0", "KUEB0", 4, 6, 33, }, + { "St. Wendel 4", "STWL4", 4, 6, 34, }, + { "Heusweiler 2", "HSW2", 4, 6, 35, }, + { "Saarbruecken 1 (Klzsbr)", "SB1", 4, 6, 36, }, + { "Neumagen-Dhron 7", "HETZ2", 4, 6, 37, }, + { "Bitburg 0", "BTB0", 4, 6, 38, }, + { "Wolfstein Pfalz 1 (KL2)", "WOS", 4, 6, 39, }, + { "Saarburg 4", "SAA4", 4, 6, 40, }, + { "Gerolstein 1", "GRST", 4, 6, 41, }, + { "Kirn 7", "KIRN7", 4, 6, 44, }, + { "Merzig 3", "MERZ3", 4, 6, 46, }, + { "Lebach 3", "LEB3", 4, 6, 47, }, + { "Sulzbach Saar 10", "SUL10", 4, 6, 48, }, + { "Voelklingen 1", "VKL1", 4, 6, 49, }, + { "Zweibruecken 2", "ZW", 4, 6, 50, }, + { "Buedlich 2", "BUEDL2", 4, 6, 54, }, + { "Klein-Blittersdorf 4", "BLIES", 4, 6, 56, }, + { "Meisenheim 7", "MEIS7", 4, 6, 59, }, + { "Hinterweidenthal 1", "HINT1", 4, 6, 60, }, + { "Dillingen Wasserturm", "DILL", 4, 6, 61, }, + { "Thaleischweiler 1", "THALE1", 4, 6, 62, }, + { "Trulben 2", "TRUL2", 4, 6, 64, }, + { "Kirchberg 1", "KIRB1", 4, 6, 78, }, + { "Neunkirchen Saar 1", "NK", 4, 6, 79, }, + { "Mettlach-Orscholz 1", "METTL1", 4, 6, 80, }, + { "Abtsgmuend 41", "ABT41", 4, 7, 1, }, + { "Bopfingen 41", "BOPF41", 4, 7, 2, }, + { "Weikersheim 41", "WEIK41", 4, 7, 3, }, + { "Heidenheim 2", "HDH2", 4, 7, 4, }, + { "Lauterstein 1", "LAU1", 4, 7, 5, }, + { "Niederstetten 41", "NDST41", 4, 7, 6, }, + { "Schwaebisch Hall 71", "SHALL7", 4, 7, 7, }, + { "Gaildorf 42", "GADF", 4, 7, 8, }, + { "Mainhardt 1", "SKLZ01", 4, 7, 9, }, + { "Schoental 41 (Widdern)", "SCHT41", 4, 7, 10, }, + { "Schwaebisch Hall 0", "SHALL0", 4, 7, 11, }, + { "Bad Mergentheim 2", "DZB2", 4, 7, 12, }, + { "Forchtenberg 1", "HNKL20", 4, 7, 14, }, + { "Oehringen-Ohrnberg 41", "HNKL02", 4, 7, 15, }, + { "Bad Mergentheim 41", "MERG41", 4, 7, 16, }, + { "Creglingen 41", "CREG41", 4, 7, 17, }, + { "Braunsbach 2", "BBCH2", 4, 7, 18, }, + { "Schopfloch 0", "SPFL0", 4, 7, 19, }, + { "Kuenzelsau 41", "KSAU41", 4, 7, 20, }, + { "Lonsee 41", "LONS41", 4, 7, 21, }, + { "Laichingen 75", "LAI75", 4, 7, 22, }, + { "Fichtenau 1", "FICH1", 4, 7, 24, }, + { "Crailsheim 2", "KBG2", 4, 7, 25, }, + { "Untergroeningen 1", "UGRN1", 4, 7, 26, }, + { "Wiesensteig/Nato 1", "WIE1", 4, 7, 27, }, + { "Geislingen 0", "GSLN41", 4, 7, 32, }, + { "Riedlingen 2", "RIE2X", 4, 7, 33, }, + { "Aichstetten 3", "AIST3", 4, 7, 37, }, + { "Aalen 41", "AAL41", 4, 7, 38, }, + { "Ellwangen 1", "ELLW", 4, 7, 40, }, + { "Gerstetten 71", "GERS71", 4, 7, 41, }, + { "Heubach 1", "HEU1", 4, 7, 45, }, + { "Lonsee 1 (Scharenstetten)", "LONS1", 4, 7, 46, }, + { "Neresheim 1", "NER1", 4, 7, 47, }, + { "Lauchheim 1", "LCHM79", 4, 7, 48, }, + { "Nersingen(DASA) 0.47", "NERS", 4, 7, 49, }, + { "Schnelldorf 1", "SNDF1", 4, 7, 50, }, + { "Aalen-Ebnat 41", "EBNT41", 4, 7, 51, }, + { "Ulm 51 (Jungingen)", "ULKL27", 4, 7, 53, }, + { "Laichingen 41", "ULKL03", 4, 7, 55, }, + { "Aalen 42", "AAL42", 4, 7, 57, }, + { "Herbrechtingen 41", "HERB41", 4, 7, 68, }, + { "Ulm 1", "UL1", 4, 7, 70, }, + { "Schoental 43 (Oberkessach)", "SCHT43", 4, 7, 71, }, + { "Schelklingen 1", "ULKL06", 4, 7, 72, }, + { "Deggingen 71", "ULKL07", 4, 7, 73, }, + { "Ochsenhausen 1", "ULKL08", 4, 7, 74, }, + { "Giengen 42", "GIEN42", 4, 7, 75, }, + { "Ulm 2 (Rasth. Seligw.)", "ULKL09", 4, 7, 76, }, + { "Ulm 126", "ULKL10", 4, 7, 77, }, + { "Langenau 1", "ULKL01", 4, 7, 78, }, + { "Oehringen 3", "HNKL06", 4, 7, 79, }, + { "Blaustein 41", "ULKL12", 4, 7, 80, }, + { "Ulm 151", "ULKL14", 4, 7, 82, }, + { "Blaubeuren 41", "ULKL15", 4, 7, 83, }, + { "Ulm 172 (Neu-Ulm)", "ULKL16", 4, 7, 84, }, + { "Ulm 141", "ULKL17", 4, 7, 85, }, + { "Erbach 41", "ULKL18", 4, 7, 86, }, + { "Senden 0", "ULKL19", 4, 7, 87, }, + { "Weissenhorn 0", "ULKL02", 4, 7, 88, }, + { "Laupheim 0", "ULKL21", 4, 7, 90, }, + { "Illertissen 0", "ULKL22", 4, 7, 91, }, + { "Biberach 6", "ULKL23", 4, 7, 92, }, + { "Ehingen 0", "EHI0", 4, 7, 93, }, + { "Langenburg 1", "LGB1", 4, 7, 95, }, + { "Dortmund 3 (Bake)", "DO3", 4, 2, 1, }, + { "Altenberge 0", "ALTB0", 5, 2, 1, }, + { "Lennestadt 1", "LENNE1", 5, 2, 2, }, + { "Attendorn 7", "ATT7", 5, 2, 3, }, + { "Arnsberg-Neheim-Huesten 7", "NHH7", 5, 2, 5, }, + { "Muenster 42 <geneigt>", "MST42", 5, 2, 6, }, + { "Marsberg-Westheim 1", "MARS1", 5, 2, 7, }, + { "Lippstadt 0", "LIPP1", 5, 2, 8, }, + { "Schalksmuehle 10 (Roelvede)", "HGND", 5, 2, 9, }, + { "Meschede-Freienohl 7", "MEF", 5, 2, 10, }, + { "Hallenberg 7", "HLBG7", 5, 2, 11, }, + { "Soest 10 <Pauli Kaserne>", "SOEST", 5, 2, 12, }, + { "Schalksmuehle 7", "SCHLK7", 5, 2, 13, }, + { "Olsberg 7", "OLSB7", 5, 2, 14, }, + { "Ostbevern 10", "OST", 5, 2, 15, }, + { "Arnsberg 0", "ARNS0", 5, 2, 16, }, + { "Beckum 3", "BECK3", 5, 2, 17, }, + { "Sendenhorst 2", "SEN2", 5, 2, 18, }, + { "Altena 8 <Ers.f.ALTN1>", "ALTN8", 5, 2, 19, }, + { "Ahlen 0", "AHL0", 5, 2, 20, }, + { "Luedinghausen 2", "LDH2", 5, 2, 21, }, + { "Meschede 1", "ME1", 5, 2, 22, }, + { "Werl 0", "WERL", 5, 2, 23, }, + { "Moehnesee 5 <5:5:1>", "MOE5", 5, 2, 24, }, + { "Schmallenberg-Boedefeld 1", "SBF1", 5, 2, 25, }, + { "Winterberg 8", "HLB", 5, 2, 26, }, + { "Castrop-Rauxel 3", "CRX3", 5, 2, 27, }, + { "Muenster-Nienberge 0", "MSTN0", 5, 2, 28, }, + { "Vreden 0", "VRDN0", 5, 2, 29, }, + { "Luedenscheid 2", "LS2", 5, 2, 30, }, + { "Gronau 0", "GRON0", 5, 2, 31, }, + { "Meinerzhagen 7", "MZHG7", 5, 2, 32, }, + { "Luenen 0", "LUEN0", 5, 2, 33, }, + { "Plettenberg 10", "PLET10", 5, 2, 34, }, + { "Werdohl 7", "WDHL7", 5, 2, 35, }, + { "Nottuln 2 <20 Grad geneigt>", "NOTT2", 5, 2, 36, }, + { "Telgte 0", "TELG0", 5, 2, 37, }, + { "Ruethen 0", "RUET0", 5, 2, 38, }, + { "Emsdetten 0", "EMS0", 5, 2, 39, }, + { "Oelde 2 (Stromberg)", "OELST2", 5, 2, 40, }, + { "Muenster-Albachten 0", "MST0", 5, 2, 41, }, + { "Greven 0", "GRVN0", 5, 2, 43, }, + { "Brechten 80", "BRE", 5, 2, 44, }, + { "Schmallenberg-Dorlar 1", "DORL1", 5, 2, 45, }, + { "Halver 6 (Rothenbruch)", "HALV", 5, 2, 46, }, + { "Herscheid 3 (Gasmert)", "LSG", 5, 2, 47, }, + { "Dortmund 230", "DO230", 5, 2, 49, }, + { "Ascheberg 2", "ASCHB2", 5, 2, 50, }, + { "Warendorf 0", "WAF0", 5, 2, 51, }, + { "Gevelsberg 7", "GEV7", 5, 2, 52, }, + { "Duelmen 0", "DUEL0", 5, 2, 54, }, + { "Sundern 1", "SUND1", 5, 2, 55, }, + { "Bueren 1", "BUER1", 5, 2, 56, }, + { "Brilon-Messinghausen 1", "BRIM1", 5, 2, 57, }, + { "Dortmund 10", "DO10", 5, 2, 58, }, + { "Witten 91 (Gedern)", "WITTW", 5, 2, 59, }, + { "Unna 3", "UN", 5, 2, 60, }, + { "Hagen-Dahl 9 (Priorei)", "HGNDA9", 5, 2, 61, }, + { "Haltern 7", "HAL7", 5, 2, 62, }, + { "Herdecke 7", "HERD7", 5, 2, 63, }, + { "Boenen 0", "BOE0", 5, 2, 64, }, + { "Holzwickede 1", "HOLZW", 5, 2, 65, }, + { "Hamm 1", "HAMM1", 5, 2, 66, }, + { "Menden 11 (Lahrberg)", "MEN11", 5, 2, 67, }, + { "Kamen 0", "KAM0", 5, 2, 68, }, + { "Werne 0", "WERN0", 5, 2, 69, }, + { "Waltrop 1", "WTRP", 5, 2, 70, }, + { "Hamm 10 (Uentrop)", "HAMM", 5, 2, 71, }, + { "Hagen 2", "HGN2", 5, 2, 72, }, + { "Schwerte 4", "SWT4", 5, 2, 73, }, + { "Recklinghausen 1", "RECK1", 5, 2, 74, }, + { "Breckerfeld 6", "BRCK", 5, 2, 75, }, + { "Balve 7", "BALV7", 5, 2, 76, }, + { "Gevelsberg 5 (Silschede)", "GEVS", 5, 2, 77, }, + { "Dortmund 85 (Eving)", "DO85", 5, 2, 78, }, + { "Iserlohn 13 (Seilerberg)", "ISN13", 5, 2, 79, }, + { "Datteln 3", "DAT3", 5, 2, 80, }, + { "Haltern 2", "HAL2", 5, 2, 84, }, + { "Hagen 9 (TVU Wetter)", "HGN9", 5, 2, 85, }, + { "Witten 12", "WITT12", 5, 2, 87, }, + { "Herscheid 1", "HED1", 5, 2, 94, }, + { "Marl 0", "MARL0", 5, 2, 96, }, + { "Klettbach 1", "HAYN", 5, 3, 1, }, + { "Grossfahner 1", "BIEN", 5, 3, 2, }, + { "Zella-Mehlis 1", "ZEME", 5, 3, 3, }, + { "Juechsen 1", "WNBRN", 5, 3, 4, }, + { "Grossbreitenbach 7", "GBB", 5, 3, 5, }, + { "Eisenberg 6 (Serba)", "ESBG6", 5, 3, 6, }, + { "Schleusingen 4", "SLSN", 5, 3, 7, }, + { "Eisenberg 4", "ESBG", 5, 3, 8, }, + { "Gera 11 (Roschuetz)", "GRO", 5, 3, 9, }, + { "Muenchenbernsdorf1(H.Reuth)", "HRTH", 5, 3, 10, }, + { "Jena 5", "LDGF", 5, 3, 11, }, + { "Neustadt 3 (Kleina)", "KLA", 5, 3, 12, }, + { "Saalburg 2", "KLM", 5, 3, 13, }, + { "Jena 6", "OSSM", 5, 3, 14, }, + { "Ruhla 4", "RUHL", 5, 3, 15, }, + { "Creuzburg 2 (Neuenhof)", "NEUF", 5, 3, 16, }, + { "Nordhausen 1", "NDHN", 5, 3, 17, }, + { "Camburg 2", "CAB", 5, 3, 18, }, + { "Bad Frankenhausen 3", "BFRH", 5, 3, 19, }, + { "Gera 13", "GERA13", 5, 3, 20, }, + { "Sondershausen 5", "SOND", 5, 3, 21, }, + { "Hermsdorf 1", "HDF1", 5, 3, 22, }, + { "Weimar 14", "WEIM", 5, 3, 23, }, + { "Erfurt 20(Schwerborner STR.)", "EKLZ08", 5, 3, 24, }, + { "Arnsgereuth 1", "ARRTH", 5, 3, 25, }, + { "Arnstadt 8", "ARNA", 5, 3, 26, }, + { "Suhl 2", "SUHL", 5, 3, 27, }, + { "Bad Koesen 1000", "KOES", 5, 3, 29, }, + { "Hildburghausen 11", "HILHSN", 5, 3, 30, }, + { "Ilmenau 4", "ILME", 5, 3, 31, }, + { "Erfurt 13 (Flughafen alt)", "EKLZ07", 5, 3, 32, }, + { "Erfurt 7 (Fuchsgrund)", "EKLZ03", 5, 3, 33, }, + { "Erfurt 4 (Andreasstr.)", "EKLZ02", 5, 3, 34, }, + { "Erfurt 3 (Chamissostr.)", "EKLZ01", 5, 3, 35, }, + { "Neuhaus 0", "NEURE", 5, 3, 36, }, + { "Meiningen 5", "MEIN", 5, 3, 37, }, + { "Erfurt 17 (FZA)", "EKLZ05", 5, 3, 38, }, + { "Erfurt 8 (EVST 4)", "EKLZ04", 5, 3, 39, }, + { "Muehlhausen 7 (Eigenrieden)", "EGRD", 5, 3, 40, }, + { "Blankenhain 1", "BLHA1", 5, 3, 41, }, + { "Schmalkalden 6", "SMAL", 5, 3, 42, }, + { "Heuthen 1 (Hockelrein)", "HOCKE", 5, 3, 43, }, + { "Kaltennordheim 2", "KLFE", 5, 3, 44, }, + { "Berga 1", "BERG", 5, 3, 45, }, + { "Oberhof 2", "OBHF", 5, 3, 46, }, + { "Poessneck 5", "PSNK", 5, 3, 47, }, + { "Apolda 2", "APOL", 5, 3, 48, }, + { "Bad Langensalza 4", "BSALZ", 5, 3, 49, }, + { "Soemmerda 0", "SOEM", 5, 3, 50, }, + { "Triebes 2", "ZLRD", 5, 3, 51, }, + { "Lobenstein 4", "LOBS", 5, 3, 52, }, + { "Rudolstadt 4", "RDST", 5, 3, 53, }, + { "Schleiz 2", "SLZ", 5, 3, 54, }, + { "Stadtroda 1", "STRDA1", 5, 3, 55, }, + { "Wernshausen 3 (Pless)", "PLS", 5, 3, 56, }, + { "Steinbach-Hallenberg 2", "STBH", 5, 3, 58, }, + { "Geisa 4", "GEISA", 5, 3, 59, }, + { "Bleicherode7 (Gebraer Kopf)", "SOLL", 5, 3, 60, }, + { "Inselsberg", "INSEL", 5, 3, 61, }, + { "Steinach 3 (Fellberg)", "FELL", 5, 3, 62, }, + { "Stadtilm 4", "STADTI", 5, 3, 63, }, + { "Waltershausen 4", "WALT4", 5, 3, 65, }, + { "Gotha 6", "GTHA6", 5, 3, 66, }, + { "Eisenach 11", "ESNA11", 5, 3, 67, }, + { "Kahla 1", "KAHLA2", 5, 3, 68, }, + { "Heiligenstadt 4", "HLGS4", 5, 3, 69, }, + { "Thimmendorf 1", "THIM1", 5, 3, 70, }, + { "Buttelstedt 3", "BUTT3", 5, 3, 71, }, + { "Koenigsee 2", "KNGS2", 5, 3, 72, }, + { "Erfurt 30", "EKLZ30", 5, 3, 73, }, + { "Schoenbrunn 7", "SHBN7", 5, 3, 74, }, + { "Kindelbrueck (TVU)", "KIND", 5, 3, 75, }, + { "Schlotheim 3", "SCHLT", 5, 3, 79, }, + { "Bischofsheim 2", "BIH2", 5, 3, 91, }, + { "Ludwigsstadt 1", "LUDW1", 5, 3, 92, }, + { "Ostheim 1", "UNSL1", 5, 3, 93, }, + { "Frechen 0", "FCHN0", 6, 2, 1, }, + { "Koeln 35 (Messe)", "K35", 6, 2, 2, }, + { "Bergisch Gladbach 4", "BGLB99", 6, 2, 3, }, + { "Niederkassel 0", "NKS0", 6, 2, 4, }, + { "Koeln 0", "K0", 6, 2, 5, }, + { "Koeln 8 <Bake>", "K8", 6, 2, 6, }, + { "Bonn 460", "BN460", 6, 2, 7, }, + { "Koeln 27", "K27", 6, 2, 8, }, + { "Bornheim-Merten 1", "MTN1", 6, 2, 9, }, + { "Frechen 8 <4.3 W ERP>", "FCHN3", 6, 2, 10, }, + { "Kerpen-Horrem 2", "KERP51", 6, 2, 11, }, + { "Erftstadt 50", "ERF50", 6, 2, 12, }, + { "Koeln 34", "K34", 6, 2, 13, }, + { "Pulheim 0", "PLH0", 6, 2, 14, }, + { "Koeln-Porz 50", "PRZ50", 6, 2, 15, }, + { "Bergheim 2", "BGH2", 6, 2, 16, }, + { "Koeln 860", "HMR", 6, 2, 17, }, + { "Koenigswinter-Oberpleis 1", "KWT1", 6, 2, 18, }, + { "Siegburg 70", "TROI70", 6, 2, 19, }, + { "Bergisch Gladbach 2", "BGLB2", 6, 2, 21, }, + { "Koeln 170", "K17", 6, 2, 22, }, + { "Koeln 25", "K25", 6, 2, 23, }, + { "Koeln 370", "K37", 6, 2, 24, }, + { "Koeln 430", "K43", 6, 2, 25, }, + { "Koeln 760", "K76", 6, 2, 26, }, + { "Koeln 640", "K640", 6, 2, 27, }, + { "Koeln 28", "K850", 6, 2, 28, }, + { "Bruehl 99", "BRHL99", 6, 2, 29, }, + { "Kerpen 3", "VILLE", 6, 2, 30, }, + { "Koeln 350.8001", "K350", 6, 2, 31, }, + { "Bonn 0", "BN0", 6, 2, 33, }, + { "Bonn 320", "BN320", 6, 2, 34, }, + { "Bonn 620", "BN620", 6, 2, 35, }, + { "Bonn 670", "BN670", 6, 2, 36, }, + { "Siegburg 41", "SIGB41", 6, 2, 37, }, + { "Siegburg 20", "SIGB20", 6, 2, 38, }, + { "Lohmar 2", "LOH99", 6, 2, 39, }, + { "Siegburg 0", "SIGB0", 6, 2, 40, }, + { "Lohmar 1 <Mischbake>", "LOH1", 6, 2, 41, }, + { "Bonn 13 (BMPT)", "BN13", 6, 2, 42, }, + { "Dueren 30", "DUER30", 6, 2, 43, }, + { "Heimbach 2", "HEIM2", 6, 2, 44, }, + { "Huertgenwald 4 <Mischbake>", "HGW4", 6, 2, 45, }, + { "Kerpen-Buir 1", "BUIR", 6, 2, 46, }, + { "Monschau 1", "MONS1", 6, 2, 47, }, + { "Hennef 1", "HNNF1", 6, 2, 48, }, + { "Nideggen 4", "NGG4", 6, 2, 49, }, + { "Zuelpich 1", "ZUEL", 6, 2, 50, }, + { "Rheinbach 2", "RHBH", 6, 2, 51, }, + { "Euskirchen 4", "EUSK4", 6, 2, 52, }, + { "Weilerswist 0", "WLW0", 6, 2, 53, }, + { "Bad Muenstereifel 2", "BMST", 6, 2, 54, }, + { "Mechernich 4", "MECH2", 6, 2, 55, }, + { "Schleiden 1", "SLDN1", 6, 2, 56, }, + { "Koenigswinter-Oberpleis 0", "KWT", 6, 2, 57, }, + { "Noervenich 1", "NOER", 6, 2, 58, }, + { "Dormagen 7.80B1", "DOR7", 6, 2, 60, }, + { "Simmerath 3", "SIMM3", 6, 2, 61, }, + { "Nettersheim 4", "NETSH4", 6, 2, 62, }, + { "Schleiden-Gemuend 3", "RURB", 6, 2, 63, }, + { "Wermelskirchen 0", "WEKI0", 6, 2, 64, }, + { "Burscheid 3", "BUR3", 6, 2, 65, }, + { "Wesseling 0", "WESS0", 6, 2, 66, }, + { "Huerth 0", "HRT0", 6, 2, 67, }, + { "Roesrath 2", "RRT", 6, 2, 68, }, + { "Burscheid 10", "BUR10", 6, 2, 69, }, + { "Koeln 23", "K23", 6, 2, 70, }, + { "Leverkusen-Opladen 1", "LEVOP1", 6, 2, 71, }, + { "Bonn 2", "BN2", 6, 2, 72, }, + { "Rommerskirchen 0", "ROMM0", 6, 2, 73, }, + { "Bonn 630", "BN630", 6, 2, 76, }, + { "Bensberg 60", "BNBG60", 6, 2, 78, }, + { "Leverkusen 0", "LEV0", 6, 2, 91, }, + { "Magdeburg 25 (Sudenburg)", "MDB25", 6, 3, 1, }, + { "Magdeburg 22 (Cracau)", "MDB22", 6, 3, 2, }, + { "Magdeburg 24 (Neust. See)", "MDB24", 6, 3, 3, }, + { "Biederitz 1", "BIED1", 6, 3, 4, }, + { "Magdeburg 7 (Olvenstaedt)", "MDB7", 6, 3, 5, }, + { "Magdeburg 23 (Buckau)", "MDB23", 6, 3, 6, }, + { "Moeser 1", "MOESE1", 6, 3, 7, }, + { "Magdeburg 1", "MDB0", 6, 3, 8, }, + { "Magdeburg 10 (Schoenebeck)", "TRANS6", 6, 3, 9, }, + { "Leitzkau 1", "LEIT1", 6, 3, 10, }, + { "Stendal 2", "STD2", 6, 3, 11, }, + { "Haldensleben 4 (end)", "HLDL", 6, 3, 12, }, + { "Oschersleben 0", "OSCH0", 6, 3, 13, }, + { "Wernigerode 0", "WIGR0", 6, 3, 14, }, + { "Halberstadt 2", "HBST", 6, 3, 15, }, + { "Erxleben ueb. Hldln. 1", "ERX1", 6, 3, 16, }, + { "Altengrabow 1", "ALGR1", 6, 3, 17, }, + { "Genthin 0", "GENT0", 6, 3, 18, }, + { "Burg 0", "BURG0", 6, 3, 19, }, + { "Lindau-Anhalt 1", "DEE", 6, 3, 20, }, + { "Kamern 2", "KAME", 6, 3, 21, }, + { "Niederndodeleben 1", "TRANS1", 6, 3, 22, }, + { "Egeln 0", "EGELN0", 6, 3, 23, }, + { "Burg 5", "TRANS2", 6, 3, 24, }, + { "Fleetmark 1", "LUEG", 6, 3, 25, }, + { "Dolle 1", "DLL", 6, 3, 26, }, + { "Osterburg 3", "OTBG3", 6, 3, 27, }, + { "Frose 3 (Hoym)", "HOYM", 6, 3, 28, }, + { "Harzgerode 0", "HGR", 6, 3, 29, }, + { "Koennern 3", "KOENE3", 6, 3, 30, }, + { "Elbingerode 0.97B1", "ELBRD", 6, 3, 31, }, + { "Wanzleben 2", "WANZ2", 6, 3, 32, }, + { "Morsleben", "MORS", 6, 3, 33, }, + { "Tangermuende 0.97B1", "JERI0", 6, 3, 34, }, + { "Bernburg 7", "BBG", 6, 3, 35, }, + { "Salzwedel 8", "SALZ8", 6, 3, 36, }, + { "Zerbst 4", "ZERBST", 6, 3, 39, }, + { "Aschersleben 5 End", "ASCHS0", 6, 3, 48, }, + { "Tangerhuette 0", "TANGER", 6, 3, 49, }, + { "Kloetze", "KLOETZ", 6, 3, 52, }, + { "Mieste 0", "MIEST0", 6, 3, 55, }, + { "Thale", "THAL", 6, 3, 88, }, + { "Seehausen 0", "SEE0", 6, 3, 93, }, + { "Blankenburg 0", "BLABG", 6, 3, 95, }, + { "Gardelegen 0", "GDLG", 6, 3, 96, }, + { "Gernrode 3 (end)", "GERN1", 6, 3, 97, }, + { "Hasselfelde 0", "HASS", 6, 3, 98, }, + { "Overath 5", "OVRT5", 7, 2, 1, }, + { "Dierdorf 10", "DIER2", 7, 2, 2, }, + { "Daun 4", "DAU4", 7, 2, 4, }, + { "Much 1", "MUCH", 7, 2, 6, }, + { "Saffig 10", "SAFF10", 7, 2, 7, }, + { "Gummersbach 40", "GU40", 7, 2, 8, }, + { "Asbach 10 <f. HNNF6>", "ASB10", 7, 2, 9, }, + { "Eitorf 2", "EIT2", 7, 2, 10, }, + { "Windhagen 10", "WINH10", 7, 2, 11, }, + { "Bad Honnef 80", "BHF80", 7, 2, 12, }, + { "Nuembrecht 10", "NUEM10", 7, 2, 13, }, + { "Koblenz 10 <Mischbake>", "KO10", 7, 2, 14, }, + { "Hoehr-Grenzhausen 1 <Misch>", "HGH1", 7, 2, 15, }, + { "Montabaur 3", "MT3", 7, 2, 16, }, + { "Weibern 2 <Mischbake>", "WBN2", 7, 2, 18, }, + { "Bad Marienberg 1 <Mischba.>", "BMA1", 7, 2, 19, }, + { "Bad Bertrich 1", "BER1", 7, 2, 20, }, + { "Blankenheim-Ahr 5", "BHM5", 7, 2, 21, }, + { "Wissen 2", "WISS2", 7, 2, 22, }, + { "Betzdorf 4", "BZD4", 7, 2, 23, }, + { "Wenden 186", "WEDN89", 7, 2, 26, }, + { "Puderbach 3", "PUDB3", 7, 2, 28, }, + { "Kuerten-Duerscheid 3", "KUERT3", 7, 2, 30, }, + { "Bad Honnef 0", "BHF1", 7, 2, 31, }, + { "Wipperfuerth 2", "WIPP2", 7, 2, 33, }, + { "Kuerten 1", "KUERT1", 7, 2, 34, }, + { "Gummersbach 0", "GU0", 7, 2, 35, }, + { "Windeck 2", "WIND1", 7, 2, 37, }, + { "Bad Neuenahr-Ahrweiler 4", "BNA4", 7, 2, 38, }, + { "Linz 4 <Mischbake>", "LNZ", 7, 2, 39, }, + { "Kreuztal 1 <Mischbake>", "KRZT1", 7, 2, 41, }, + { "Bad Berleburg 1", "BBERL1", 7, 2, 43, }, + { "Bad Laasphe 7", "LPHE7", 7, 2, 44, }, + { "Netphen 7", "NETP7", 7, 2, 45, }, + { "Olpe 0", "OE0", 7, 2, 47, }, + { "Drolshagen-Bleche 1", "SCHK", 7, 2, 48, }, + { "Hilchenbach 1", "LUZL", 7, 2, 49, }, + { "Freudenberg 7", "FDB7", 7, 2, 50, }, + { "Burbach 3", "BURB", 7, 2, 51, }, + { "Waldbreitbach 2", "WBB2", 7, 2, 52, }, + { "Ellenz-Poltersdorf 2", "ELLZ2", 7, 2, 53, }, + { "Insul 2", "INSU2", 7, 2, 54, }, + { "Linz 2", "LNZ2", 7, 2, 55, }, + { "Wildbergerhuette 1", "SKHL", 7, 2, 56, }, + { "Kelberg 3 (Hochkelberg)", "HKBG", 7, 2, 57, }, + { "Kesseling 1", "KESS1", 7, 2, 58, }, + { "Reichshof-Eckenhagen 3", "WEHN", 7, 2, 59, }, + { "Rengsdorf 4", "WILR", 7, 2, 60, }, + { "Mendig 3", "MEND", 7, 2, 61, }, + { "Cochem 1", "COC1", 7, 2, 62, }, + { "Mayen 3", "MAY3", 7, 2, 63, }, + { "Neuwied 2", "NEUW0", 7, 2, 64, }, + { "Hachenburg 2", "HACH2", 7, 2, 65, }, + { "Westerburg 1", "WESB1", 7, 2, 66, }, + { "Asbach 5", "ASB5", 7, 2, 67, }, + { "Loef 1", "LOEF1", 7, 2, 68, }, + { "Engelskirchen 6", "ENGK6", 7, 2, 69, }, + { "Altenkirchen 0", "ATK0", 7, 2, 70, }, + { "Siegen 15", "SG99", 7, 2, 71, }, + { "Neunkirchen-Seelscheid 1", "NNK1", 7, 2, 73, }, + { "Ochtendung 2", "OCHT99", 7, 2, 74, }, + { "Bad Ems 1", "BEMS1", 7, 2, 79, }, + { "Marienheide 1", "MARI1", 7, 2, 80, }, + { "Gummersbach 16 <Mischbake>", "GU16", 7, 2, 82, }, + { "Flammersfeld 2", "FLF2", 7, 2, 83, }, + { "Waldbroel 1", "WDBR1", 7, 2, 84, }, + { "Bendorf 1", "BEN1", 7, 2, 85, }, + { "Engelskirchen 3", "ENGK", 7, 2, 86, }, + { "Selters 2", "SELT2", 7, 2, 87, }, + { "Adenau 7 (Nuerburgring)", "ADN7", 7, 2, 88, }, + { "Kaisersesch 2", "KESCH2", 7, 2, 89, }, + { "Nassau 1", "NAS1", 7, 2, 90, }, + { "Bad Marienberg 2", "BMA2", 7, 2, 91, }, + { "Antweiler 1", "ANT1", 7, 2, 92, }, + { "Ruppichteroth 3", "BKRT", 7, 2, 93, }, + { "Lindlar 1", "LINL", 7, 2, 95, }, + { "Siegen 1 <Mischbake>", "SG1", 7, 2, 96, }, + { "Gummersbach 13 <Mischbake>", "GU13", 7, 2, 97, }, + { "Rheinbrohl 0", "RHBL0", 7, 2, 99, }, + { "Baerenstein 1", "BAER2", 7, 3, 1, }, + { "Auerbach 4 (Schnarrtanne)", "SNTN", 7, 3, 2, }, + { "Bad Elster 1 (Reuth)", "REUTH", 7, 3, 3, }, + { "Marienberg 0", "MBG", 7, 3, 4, }, + { "Chemnitz 11 (Totenstein)", "TOT", 7, 3, 5, }, + { "Reichenbach 3", "KUH", 7, 3, 6, }, + { "Bergen 1 (Werda)", "WDA", 7, 3, 7, }, + { "Rochlitz 5", "ROCH", 7, 3, 8, }, + { "Chemnitz 12 (Reichenhain)", "REIHN", 7, 3, 9, }, + { "Frankenberg 4", "FRKN", 7, 3, 10, }, + { "Ebersbrunn 1", "ZWW", 7, 3, 11, }, + { "Schwarzenberg 7", "BNBC", 7, 3, 12, }, + { "Freiberg 2", "FBG", 7, 3, 13, }, + { "Frauenstein 3", "FRAU", 7, 3, 14, }, + { "Glauchau 2", "GLAU", 7, 3, 15, }, + { "Plauen 10", "KEMM", 7, 3, 16, }, + { "Werdau 4 (Niederalbertsd.)", "NDAD", 7, 3, 17, }, + { "Mittweida 1", "MITT1", 7, 3, 18, }, + { "Zschopau 4 (Hohndorf)", "HDRF", 7, 3, 19, }, + { "Chemnitz 32 (BKH-Bettenh.)", "CZ01", 7, 3, 20, }, + { "Chemnitz 29 (Heckert)", "CZ02", 7, 3, 21, }, + { "Chemnitz 17 (Landratsamt)", "CZ08", 7, 3, 22, }, + { "Nossen 5", "NOSS5", 7, 3, 23, }, + { "Chemnitz 22 (Leukersdorf)", "CZ05", 7, 3, 24, }, + { "Chemnitz 33 (Numerik)", "CZ06", 7, 3, 25, }, + { "Hainichen 1 (end)", "HAIN1", 7, 3, 26, }, + { "Zwoenitz 4", "ZWO3", 7, 3, 27, }, + { "Zwickau 1", "ZWWI", 7, 3, 28, }, + { "Chemnitz 28 (Funkfeuer)", "CZ09", 7, 3, 29, }, + { "Floeha 4 (TVU Steinberg)", "STEIN", 7, 3, 30, }, + { "Crimmitzschau 2", "CRIMMI", 7, 3, 31, }, + { "Eibenstock 4", "EIBEN", 7, 3, 32, }, + { "Chemnitz 1010 (Autobahnamt)", "CZ10", 7, 3, 33, }, + { "Olbernhau 3", "LUGA", 7, 3, 35, }, + { "Hartenstein 1000", "HART1", 7, 3, 36, }, + { "Greitz 2", "GRZ2", 7, 3, 37, }, + { "Penig 2", "PEN2", 7, 3, 38, }, + { "Thalheim", "THALH", 7, 3, 39, }, + { "FTZ Example", "FTZ", 1, 1, 38, }, /* use in FTZ standard as example */ + { "", "", 0, 0, 0, }, }; void init_station(void) { - int i, j; - - for (i = 0; cnetz_stations[i].standort[0]; i++) { - for (j = 0; cnetz_stations[i].standort[j]; j++) { - if (cnetz_stations[i].standort[j] == ' ') - cnetz_stations[i].standort[j] = '_'; - } - } } void station_list(void) { int i; - char name[17]; + char name[33]; printf("List of all base stations:\n\n"); - printf("Name Nat FuVst Rest Year used\n"); - printf("-------------------------------------------------\n"); - for (i = 0; cnetz_stations[i].standort[0]; i++) { + printf("Kurz Name Nat FuVst Rest\n"); + printf("------------------------------------------------------------\n"); + for (i = 0; cnetz_stations[i].long_name[0]; i++) { memset(name, ' ', sizeof(name)); + memcpy(name, cnetz_stations[i].name, strlen(cnetz_stations[i].name)); + name[8] = '\0'; + printf("%s", name); + memset(name, ' ', sizeof(name)); + memcpy(name, cnetz_stations[i].long_name, strlen(cnetz_stations[i].long_name)); name[sizeof(name) - 1] = '\0'; - memcpy(name, cnetz_stations[i].standort, strlen(cnetz_stations[i].standort)); - printf("%s%d\t%d\t%d\t", name, cnetz_stations[i].nat, cnetz_stations[i].fuvst, cnetz_stations[i].rest); - if (cnetz_stations[i].in1991) - printf("1991"); - if (cnetz_stations[i].in1991 && cnetz_stations[i].in1999) - printf(","); - if (cnetz_stations[i].in1999) - printf("1999"); - printf("\n"); + printf("%s%d\t%d\t%d\n", name, cnetz_stations[i].nat, cnetz_stations[i].fuvst, cnetz_stations[i].rest); } } -const char *get_station_name(uint8_t nat, uint8_t fuvst, uint8_t rest) +const char *get_station_name(uint8_t nat, uint8_t fuvst, uint8_t rest, const char **long_name) { int i; - for (i = 0; cnetz_stations[i].standort[0]; i++) { + for (i = 0; cnetz_stations[i].long_name[0]; i++) { if (cnetz_stations[i].nat == nat && cnetz_stations[i].fuvst == fuvst - && cnetz_stations[i].rest == rest) - return cnetz_stations[i].standort; + && cnetz_stations[i].rest == rest) { + if (long_name) + *long_name = cnetz_stations[i].long_name; + return cnetz_stations[i].name; + } } - return "unknown"; + if (long_name) + *long_name = "unknown"; + return *long_name; } const char *get_station_id(const char *name, uint8_t *nat, uint8_t *fuvst, uint8_t *rest) { int i, found = -1; - for (i = 0; cnetz_stations[i].standort[0]; i++) { + for (i = 0; cnetz_stations[i].name[0]; i++) { /* check for given prefix */ - if (!strncasecmp(cnetz_stations[i].standort, name, strlen(name))) { + if (!strncasecmp(cnetz_stations[i].name, name, strlen(name)) + || !strncasecmp(cnetz_stations[i].long_name, name, strlen(name)) ) { /* found twice */ if (found >= 0) return "Given station name is ambiguous, use more letters! Use '-S fuz-name=list' to get a list of all stations."; /* found the first time */ found = i; /* check for exact match, so we are done */ - if (strlen(cnetz_stations[i].standort) == strlen(name)) + if (strlen(cnetz_stations[i].name) == strlen(name)) break; } } diff --git a/src/cnetz/stations.h b/src/cnetz/stations.h index 415ab35..981713e 100644 --- a/src/cnetz/stations.h +++ b/src/cnetz/stations.h @@ -1,6 +1,6 @@ void init_station(void); void station_list(void); -const char *get_station_name(uint8_t nat, uint8_t fuvst, uint8_t rest); +const char *get_station_name(uint8_t nat, uint8_t fuvst, uint8_t rest, const char **standort); const char *get_station_id(const char *name, uint8_t *nat, uint8_t *fuvst, uint8_t *rest); diff --git a/src/cnetz/sysinfo.c b/src/cnetz/sysinfo.c index 0c0802d..43a73ef 100644 --- a/src/cnetz/sysinfo.c +++ b/src/cnetz/sysinfo.c @@ -4,10 +4,13 @@ cnetz_si si; -void init_sysinfo(uint8_t fuz_nat, uint8_t fuz_fuvst, uint8_t fuz_rest, uint8_t kennung_fufst, uint8_t authentifikationsbit, uint8_t ws_kennung, uint8_t vermittlungstechnische_sperren, uint8_t grenz_einbuchen, uint8_t grenz_umschalten, uint8_t grenz_ausloesen, uint8_t mittel_umschalten, uint8_t mittel_ausloesen, uint8_t genauigkeit, uint8_t bewertung, uint8_t entfernung, uint8_t reduzierung, uint8_t nachbar_prio, int8_t teilnehmergruppensperre, uint8_t anzahl_gesperrter_teilnehmergruppen) +void init_sysinfo(uint32_t timeslots, uint8_t fuz_nat, uint8_t fuz_fuvst, uint8_t fuz_rest, uint8_t kennung_fufst, uint8_t bahn_bs, uint8_t authentifikationsbit, uint8_t ws_kennung, uint8_t vermittlungstechnische_sperren, uint8_t grenz_einbuchen, uint8_t grenz_umschalten, uint8_t grenz_ausloesen, uint8_t mittel_umschalten, uint8_t mittel_ausloesen, uint8_t genauigkeit, uint8_t bewertung, uint8_t entfernung, uint8_t reduzierung, uint8_t nachbar_prio, int8_t teilnehmergruppensperre, uint8_t anzahl_gesperrter_teilnehmergruppen, int meldeinterval, int meldeaufrufe) { memset(&si, 0, sizeof(si)); + /* timeslot to use */ + si.timeslots = timeslots; + /* ID of base station */ si.fuz_nat = fuz_nat; si.fuz_fuvst = fuz_fuvst; @@ -34,7 +37,10 @@ void init_sysinfo(uint8_t fuz_nat, uint8_t fuz_fuvst, uint8_t fuz_rest, uint8_t /* a low value is tollerant to bad quality */ si.grenz_einbuchen = grenz_einbuchen; /* 1..7 */ + if (bahn_bs) + kennung_fufst = 0; si.kennung_fufst = kennung_fufst; + si.bahn_bs = bahn_bs; si.authentifikationsbit = authentifikationsbit; @@ -49,5 +55,8 @@ void init_sysinfo(uint8_t fuz_nat, uint8_t fuz_fuvst, uint8_t fuz_rest, uint8_t /* deny group of subscribers. (used to balance subscribers between base stations) */ si.teilnehmergruppensperre = teilnehmergruppensperre; si.anzahl_gesperrter_teilnehmergruppen = anzahl_gesperrter_teilnehmergruppen; + + si.meldeinterval = meldeinterval; + si.meldeaufrufe = meldeaufrufe; } diff --git a/src/cnetz/sysinfo.h b/src/cnetz/sysinfo.h index 3e94042..d8c8be1 100644 --- a/src/cnetz/sysinfo.h +++ b/src/cnetz/sysinfo.h @@ -1,5 +1,6 @@ typedef struct system_information { + uint32_t timeslots; /* timeslot map to use */ uint8_t fuz_nat; /* national network ID */ uint8_t fuz_fuvst; /* id of switching center */ uint8_t fuz_rest; /* rest of base station id */ @@ -12,6 +13,7 @@ typedef struct system_information { uint8_t entfernung; uint8_t grenz_einbuchen; uint8_t kennung_fufst; /* prio of base station */ + uint8_t bahn_bs; /* special train base station */ uint8_t authentifikationsbit; /* base station suppoerts authentication */ uint8_t ws_kennung; /* queue setting sof base station */ uint8_t nachbar_prio; @@ -19,9 +21,11 @@ typedef struct system_information { uint8_t reduzierung; int8_t teilnehmergruppensperre; int8_t anzahl_gesperrter_teilnehmergruppen; + int meldeinterval; /* when to retry availability check */ + int meldeaufrufe; /* 0 for infinite */ } cnetz_si; extern cnetz_si si; -void init_sysinfo(uint8_t fuz_nat, uint8_t fuz_fuvst, uint8_t fuz_rest, uint8_t kennung_fufst, uint8_t authentifikationsbit, uint8_t ws_kennung, uint8_t vermittlungstechnische_sperren, uint8_t grenz_einbuchen, uint8_t grenz_umschalten, uint8_t grenz_ausloesen, uint8_t mittel_umschalten, uint8_t mittel_ausloesen, uint8_t genauigkeit, uint8_t bewertung, uint8_t entfernung, uint8_t reduzierung, uint8_t nachbar_prio, int8_t teilnehmergruppensperre, uint8_t anzahl_gesperrter_teilnehmergruppen); +void init_sysinfo(uint32_t timeslots, uint8_t fuz_nat, uint8_t fuz_fuvst, uint8_t fuz_rest, uint8_t kennung_fufst, uint8_t bahn_bs, uint8_t authentifikationsbit, uint8_t ws_kennung, uint8_t vermittlungstechnische_sperren, uint8_t grenz_einbuchen, uint8_t grenz_umschalten, uint8_t grenz_ausloesen, uint8_t mittel_umschalten, uint8_t mittel_ausloesen, uint8_t genauigkeit, uint8_t bewertung, uint8_t entfernung, uint8_t reduzierung, uint8_t nachbar_prio, int8_t teilnehmergruppensperre, uint8_t anzahl_gesperrter_teilnehmergruppen, int meldeinterval, int meldeaufrufe); diff --git a/src/cnetz/telegramm.c b/src/cnetz/telegramm.c index 1a21369..0525f8a 100644 --- a/src/cnetz/telegramm.c +++ b/src/cnetz/telegramm.c @@ -27,7 +27,7 @@ #include <errno.h> #include <math.h> #include "../libsample/sample.h" -#include "../libdebug/debug.h" +#include "../liblogging/logging.h" #include "cnetz.h" #include "dsp.h" #include "sysinfo.h" @@ -46,7 +46,7 @@ static const char *param_ja[] = { static const char *param_betriebsart[] = { "Sprache klar", "Sprache invertiert", - "Illegaler Parameter 2", + "Datenbetrieb", "Illegaler Parameter 3", }; @@ -260,7 +260,7 @@ static struct definition_parameter { { 'H',"OgK-Vorschlag", 10, param_frequenz }, { 'I',"FuZ-Nationalitaet", 3, NULL }, { 'J',"Sendeleistungsanpassung", 1, param_anpassen }, - { 'K',"Frequenz-Nr.", 11, param_frequenz }, + { 'K',"Frequenz-Nr.", 0, param_frequenz }, /* length 10 or 11 */ { 'L',"Art der Signalisierung im OgK", 1, param_signalisierung }, { 'M',"OgK-Verkehrsanteil", 5, param_verkehrsanteil }, { 'N',"FuTln-Nationalitaet", 3, NULL }, @@ -274,6 +274,7 @@ static struct definition_parameter { { 'V',"Sicherungs-Code", 16, NULL }, { 'W',"WS-Kennung", 2, param_wskennung }, { 'X',"Wahlziffer beliebig 16 Ziffern", 64, NULL }, + { 'Y',"Bahn-MS", 1, param_ja }, { 'Z',"Zeitschlitz-Nr.", 5, NULL }, { 'a',"Grenzert fuer Ausloesen", 4, param_ausloesen }, { 'b',"Chipkarten-FuTelG-Bit", 1, param_chipkarte }, @@ -298,6 +299,7 @@ static struct definition_parameter { { 'u',"Grenzwert fuer Umschalten", 4, param_ausloesen }, { 'v',"Vermittlungtechnische Sperren", 2, param_sperren }, { 'w',"Erweitertes Frequenzbandbit", 1, NULL }, + { 'x',"Bahn-BS", 1, param_ja }, { 'y',"Reduzierungsfaktor", 2, param_reduzierung }, { '_',"Illegaler Opcode", 64, NULL }, { 0 ,"", 0, NULL }, @@ -347,12 +349,12 @@ static struct definition_opcode { { "------dJ--------eeeeeeeeIIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "VH(K)", BLOCK_K,"Verbindung halten" }, { "------dJ--------eeeeeeeeIIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "RTAQ(K)", BLOCK_K,"Quittung Rufton anschalten" }, { "------dJBB------eeeeeeeeIIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "AH(K)", BLOCK_K,"Abhebe-Signal" }, - { "-----wdJBBCt----eeeeeeeeIIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "VH(V)", BLOCK_V,"Verbindung halten" }, + { "----YwdJBBCt----eeeeeeeeIIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "VH(V)", BLOCK_V,"Verbindung halten" }, { "------dJ----------------IIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "AT(K)", BLOCK_K,"Ausloesen durch Funktelefonteilnehmer" }, { "------dJBBC-------------IIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "AT(V)", BLOCK_V,"Ausloesen durch Funktelefonteilnehmer" }, { "------dJBB------eeeeeeeeIIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "DSQ(K)", BLOCK_K,"Durchschalten Quittung" }, - { "-----wdJBBCt----eeeeeeeeIIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "USAI(V)", BLOCK_V,"Umschaltantrag intern" }, - { "-----wdJBBCt----eeeeeeeeIIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "USAE(V)", BLOCK_V,"Umschaltantrag extern" }, + { "----YwdJBBCt----eeeeeeeeIIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "USAI(V)", BLOCK_V,"Umschaltantrag intern" }, + { "----YwdJBBCt----eeeeeeeeIIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "USAE(V)", BLOCK_V,"Umschaltantrag extern" }, { "------dJBB--------------IIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "USTLN(K)", BLOCK_K,"Umschalten Funktelefonteilnehmer" }, { "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", NULL, "ZFZQ(K)", BLOCK_K,"Zufallszahlquittung" }, { "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", NULL, "AP(K)", BLOCK_K,"Autorisierungsparameter" }, @@ -366,7 +368,7 @@ static struct definition_opcode { { "PPdZZZZZ----------------IIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "UBQ(R)", BLOCK_R,"Umbuchquittung" }, { "PPdZZZZZ----------------IIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "WSK(R)", BLOCK_R,"Warteschglange kommend" }, { "PP-MMMMMDDDDEEEE------HHHHHHHHHHFFFFFFFF------------------------", NULL, "MLR(M)", BLOCK_M,"Melde-Leer-Ruf" }, - { "PPdZZZZZffflvvWW------yyIIIAAAAAFFFFFFFFkkgprrrrmmmmnnnnuuuuaaaa", NULL, "LR(R)", BLOCK_R,"Leer-Ruf" }, + { "PPdZZZZZffflvvWW-----xyyIIIAAAAAFFFFFFFFkkgprrrrmmmmnnnnuuuuaaaa", NULL, "LR(R)", BLOCK_R,"Leer-Ruf" }, { "PPdZZZZZ----------------IIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "ATQ(R)", BLOCK_R,"Quittung fuer Ausloesen des FuTelG im OgK-Betrieb" }, { "PPdZZZZZ----------------IIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "SAR(R)", BLOCK_R,"Sperraufruf" }, { "PP-MMMMMDDDDEEEE------HHHHHHHHHHFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "WAF(M)", BLOCK_M,"Wahlaufforderung" }, @@ -385,7 +387,7 @@ static struct definition_opcode { { "PP----dJ------cc--------IIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "AF(V)", BLOCK_V,"Ausloesen durch FuFSt in verteilter Signalisierung" }, { "PP----dJ--------eeeeeeeeIIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "DSB(K)", BLOCK_K,"Durchschaltung" }, { "PP----dJ-----KKKKKKKKKKKIIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "DSBI(V)", BLOCK_V,"Umschaltbefehl intern (neuer SpK in der gleichen FuZ)" }, - { "PP----dJ-----KKKKKKKKKKKIIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "USF(K)", BLOCK_K,"Umschalten FuFst" }, + { "PPuuuudJ-xnnnnKKKKKKKKKKIIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "USF(K)", BLOCK_K,"Umschalten FuFst" }, { "PP----dJ-----KKKKKKKKKKKIIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "USBE(V)", BLOCK_V,"Umschaltbefehl extern (neuer SpK in einer anderen Funkzelle)" }, { "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo", NULL, "ZFZ(K)", BLOCK_K,"Zufallszahl" }, { "________________________________________________________________", NULL, "opcode 61",BLOCK_I,"Illegaler Opcode" }, @@ -422,7 +424,7 @@ int init_telegramm(void) printf("Message #%d has invalid digit '%c'\n", i, last_bit); return -1; } - if (parameter->bits != count_bits) { + if (parameter->bits && parameter->bits != count_bits) { printf("Message #%d has digit '%c' with %d bits, but parameter has %d bits\n", i, last_bit, count_bits, parameter->bits); return -1; } @@ -508,13 +510,13 @@ static int encode_dialstring(uint64_t *value, const char *number) max = strlen(number); if (max > 16) { - PDEBUG(DFRAME, DEBUG_NOTICE, "Given number '%s' has more than 16 digits\n", number); + LOGP(DFRAME, LOGL_NOTICE, "Given number '%s' has more than 16 digits\n", number); return -EINVAL; } if (max == 16) { if (number[0] != '0') { - PDEBUG(DFRAME, DEBUG_NOTICE, "Given 16 digit number '%s' does not start with '0'\n", number); + LOGP(DFRAME, LOGL_NOTICE, "Given 16 digit number '%s' does not start with '0'\n", number); return -EINVAL; } *value = 0; @@ -573,7 +575,7 @@ int match_fuz(telegramm_t *telegramm) 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); + LOGP(DFRAME, LOGL_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; } @@ -585,7 +587,7 @@ int match_futln(telegramm_t *telegramm, uint8_t futln_nat, uint8_t futln_fuvst, if (telegramm->futln_nationalitaet != futln_nat || telegramm->futln_heimat_fuvst_nr != futln_fuvst || telegramm->futln_rest_nr != futln_rest) { - PDEBUG(DFRAME, DEBUG_NOTICE, "Ignoring message from mobile phone %d,%d,%d: Mobile station 'Funktelefongeraet' does not match!\n", telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr); + LOGP(DFRAME, LOGL_NOTICE, "Ignoring message from mobile phone %d,%d,%d: Mobile station 'Funktelefongeraet' does not match!\n", telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr); return 0; } @@ -598,19 +600,19 @@ static void debug_parameter(char digit, uint64_t value) parameter = get_parameter(digit); if (!parameter) { - PDEBUG(DFRAME, DEBUG_ERROR, "Digit '%c' not found in definition_parameter list, please fix!\n", digit); + LOGP(DFRAME, LOGL_ERROR, "Digit '%c' not found in definition_parameter list, please fix!\n", digit); abort(); } if (parameter->value_names) - PDEBUG(DFRAME, DEBUG_DEBUG, " (%c) %s : %s\n", digit, parameter->param_name, parameter->value_names[value]); + LOGP(DFRAME, LOGL_DEBUG, " (%c) %s : %s\n", digit, parameter->param_name, parameter->value_names[value]); else if (parameter->bits == 64) - PDEBUG(DFRAME, DEBUG_DEBUG, " (%c) %s : 0x%016" PRIx64 "\n", digit, parameter->param_name, value); + LOGP(DFRAME, LOGL_DEBUG, " (%c) %s : 0x%016" PRIx64 "\n", digit, parameter->param_name, value); else if (digit == 'X') { char wahlziffern[17]; decode_dialstring(wahlziffern, value); - PDEBUG(DFRAME, DEBUG_DEBUG, " (%c) %s : '%s'\n", digit, parameter->param_name, wahlziffern); + LOGP(DFRAME, LOGL_DEBUG, " (%c) %s : '%s'\n", digit, parameter->param_name, wahlziffern); } else - PDEBUG(DFRAME, DEBUG_DEBUG, " (%c) %s : %" PRIu64 "\n", digit, parameter->param_name, value); + LOGP(DFRAME, LOGL_DEBUG, " (%c) %s : %" PRIu64 "\n", digit, parameter->param_name, value); } /* encode telegram to 70 bits @@ -626,11 +628,12 @@ static char *assemble_telegramm(const telegramm_t *telegramm, int debug) int rc; if (telegramm->opcode >= 64) { - PDEBUG(DFRAME, DEBUG_ERROR, "Opcode '0x%x' exceeds bit range, please fix!\n", telegramm->opcode); + LOGP(DFRAME, LOGL_ERROR, "Opcode '0x%x' exceeds bit range, please fix!\n", telegramm->opcode); abort(); } - PDEBUG(DFRAME, DEBUG_DEBUG, "Coding %s %s\n", definition_opcode[telegramm->opcode].message_name, definition_opcode[telegramm->opcode].message_text); + if (debug) + LOGP(DFRAME, LOGL_INFO, "Coding %s %s\n", definition_opcode[telegramm->opcode].message_name, definition_opcode[telegramm->opcode].message_text); /* copy opcode */ for (i = 0; i < 6; i++) @@ -714,10 +717,13 @@ static char *assemble_telegramm(const telegramm_t *telegramm, int debug) case 'X': rc = encode_dialstring(&value, telegramm->wahlziffern); if (rc < 0) { - PDEBUG(DFRAME, DEBUG_ERROR, "Illegal dial string '%s', please fix!\n", telegramm->wahlziffern); + LOGP(DFRAME, LOGL_ERROR, "Illegal dial string '%s', please fix!\n", telegramm->wahlziffern); abort(); } break; + case 'Y': + value = telegramm->bahn_ms; + break; case 'Z': value = telegramm->zeitschlitz_nr; break; @@ -790,6 +796,9 @@ static char *assemble_telegramm(const telegramm_t *telegramm, int debug) case 'w': value = telegramm->erweitertes_frequenzbandbit; break; + case 'x': + value = telegramm->bahn_bs; + break; case 'y': value = telegramm->reduzierungsfaktor; break; @@ -797,10 +806,10 @@ static char *assemble_telegramm(const telegramm_t *telegramm, int debug) value = telegramm->illegaler_opcode; break; default: - PDEBUG(DFRAME, DEBUG_ERROR, "Parameter '%c' does not exist, please fix!\n", parameter); + LOGP(DFRAME, LOGL_ERROR, "Parameter '%c' does not exist, please fix!\n", parameter); abort(); } - if (debug && debuglevel <= DEBUG_DEBUG) + if (debug && loglevel <= LOGL_DEBUG) debug_parameter(parameter, value); val = value; for (j = 0; string[63 - i - j] == parameter; j++) { @@ -808,14 +817,14 @@ static char *assemble_telegramm(const telegramm_t *telegramm, int debug) val >>= 1; } if (val) - PDEBUG(DFRAME, DEBUG_ERROR, "Parameter '%c' value '0x%" PRIx64 "' exceeds bit range!\n", parameter, value); + LOGP(DFRAME, LOGL_ERROR, "Parameter '%c' value '0x%" PRIx64 "' exceeds bit range!\n", parameter, value); i += j - 1; } bits[70] = '\0'; if (debug) { - PDEBUG(DFRAME, DEBUG_DEBUG, "OOOOOO%s\n", string); - PDEBUG(DFRAME, DEBUG_DEBUG, "%s\n", bits); + LOGP(DFRAME, LOGL_DEBUG, "OOOOOO%s\n", string); + LOGP(DFRAME, LOGL_DEBUG, "%s\n", bits); } return bits; @@ -839,7 +848,7 @@ static void disassemble_telegramm(telegramm_t *telegramm, const char *bits, int value = (value << 1) | (bits[i] == '1'); telegramm->opcode = value; - PDEBUG(DFRAME, DEBUG_DEBUG, "Decoding %s %s\n", definition_opcode[telegramm->opcode].message_name, definition_opcode[telegramm->opcode].message_text); + LOGP(DFRAME, LOGL_INFO, "Decoding %s %s\n", definition_opcode[telegramm->opcode].message_name, definition_opcode[telegramm->opcode].message_text); /* copy parameters */ if (auth && bits[1]) /* auth flag and chip card flag */ @@ -855,7 +864,7 @@ static void disassemble_telegramm(telegramm_t *telegramm, const char *bits, int value = (value >> 1) | ((uint64_t)(bits[69 - i - j] == '1') << 63); value >>= 64 - j; i += j - 1; - if (debuglevel <= DEBUG_DEBUG) + if (loglevel <= LOGL_DEBUG) debug_parameter(parameter, value); switch (parameter) { case 'A': @@ -927,6 +936,9 @@ static void disassemble_telegramm(telegramm_t *telegramm, const char *bits, int case 'X': decode_dialstring(telegramm->wahlziffern, value); break; + case 'Y': + telegramm->bahn_ms = value; + break; case 'Z': telegramm->zeitschlitz_nr = value; break; @@ -999,6 +1011,9 @@ static void disassemble_telegramm(telegramm_t *telegramm, const char *bits, int case 'w': telegramm->erweitertes_frequenzbandbit = value; break; + case 'x': + telegramm->bahn_bs = value; + break; case 'y': telegramm->reduzierungsfaktor = value; break; @@ -1006,18 +1021,18 @@ static void disassemble_telegramm(telegramm_t *telegramm, const char *bits, int telegramm->illegaler_opcode = value; break; default: - PDEBUG(DFRAME, DEBUG_ERROR, "Parameter '%c' does not exist, please fix!\n", parameter); + LOGP(DFRAME, LOGL_ERROR, "Parameter '%c' does not exist, please fix!\n", parameter); abort(); } } - if (debuglevel <= DEBUG_DEBUG) { + if (loglevel <= LOGL_DEBUG) { char debug_bits[71]; memcpy(debug_bits, bits, 70); debug_bits[70] = '\0'; - PDEBUG(DFRAME, DEBUG_DEBUG, "OOOOOO%s\n", string); - PDEBUG(DFRAME, DEBUG_DEBUG, "%s\n", debug_bits); + LOGP(DFRAME, LOGL_DEBUG, "OOOOOO%s\n", string); + LOGP(DFRAME, LOGL_DEBUG, "%s\n", debug_bits); } } @@ -1190,7 +1205,7 @@ int init_coding(void) block_code[i] = word; } - /* check if redunancy of a single bit matches the combined redundancy */ + /* check if redundancy of a single bit matches the combined redundancy */ for (i = 0; i < 128; i++) { int r = 0; for (j = 0; j < 7; j++) { @@ -1377,11 +1392,11 @@ static const char *decode(const char *input, int *_bit_errors) fail_str[10] = '\0'; if (failed) - PDEBUG(DFRAME, DEBUG_DEBUG, "Received Telegram with these block errors: '%s' (X = uncorrectable)\n", fail_str); + LOGP(DFRAME, LOGL_DEBUG, "Received Telegram with these block errors: '%s' (X = uncorrectable)\n", fail_str); else if (warn) - PDEBUG(DFRAME, DEBUG_DEBUG, "Received Telegram with these block errors: '%s' (1 / 2 = correctable)\n", fail_str); + LOGP(DFRAME, LOGL_DEBUG, "Received Telegram with these block errors: '%s' (1 / 2 = correctable)\n", fail_str); else - PDEBUG(DFRAME, DEBUG_DEBUG, "Received Telegram with no block errors.\n"); + LOGP(DFRAME, LOGL_DEBUG, "Received Telegram with no block errors.\n"); if (failed) return NULL; @@ -1481,33 +1496,32 @@ void cnetz_decode_telegramm(cnetz_t *cnetz, const char *bits, double level, doub break; } if (i == 70) { - PDEBUG(DFRAME, DEBUG_INFO, "Ignoring mysterious unmodulated telegramm (noise from phone's transmitter)\n"); + LOGP(DFRAME, LOGL_INFO, "Ignoring mysterious unmodulated telegramm (noise from phone's transmitter)\n"); return; } + LOGP_CHAN(DDSP, LOGL_INFO, "RF level: %.1f dB RX Level: %.0f%% Standard deviation: %.0f%% Sync Time: %.2f (TS %.2f) %s\n", cnetz->rf_level_db, fabs(level) / cnetz->fsk_deviation * 100.0, stddev / fabs(level) * 100.0, sync_time, sync_time / 396.0, (level < 0) ? "NEGATIVE (phone's mode)" : "POSITIVE (base station's mode)"); + if (bit_errors) + LOGP_CHAN(DDSP, LOGL_INFO, " -> Frame has %d bit errors.\n", bit_errors); + disassemble_telegramm(&telegramm, bits, si.authentifikationsbit); opcode = telegramm.opcode; telegramm.level = level; telegramm.sync_time = sync_time; - if (bit_errors) - PDEBUG_CHAN(DDSP, DEBUG_INFO, "RX Level: %.0f%% Standard deviation: %.0f%% Sync Time: %.2f (TS %.2f) Bit errors: %d %s\n", fabs(level) / cnetz->fsk_deviation * 100.0, stddev / fabs(level) * 100.0, sync_time, sync_time / 396.0, bit_errors, (level < 0) ? "NEGATIVE (phone's mode)" : "POSITIVE (base station's mode)"); - else - PDEBUG_CHAN(DDSP, DEBUG_INFO, "RX Level: %.0f%% Standard deviation: %.0f%% Sync Time: %.2f (TS %.2f) %s\n", fabs(level) / cnetz->fsk_deviation * 100.0, stddev / fabs(level) * 100.0, sync_time, sync_time / 396.0, (level < 0) ? "NEGATIVE (phone's mode)" : "POSITIVE (base station's mode)"); - if (cnetz->sender.loopback) { - PDEBUG(DFRAME, DEBUG_NOTICE, "Received Telegramm in loopback test mode (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name); + LOGP(DFRAME, LOGL_NOTICE, "Received Telegramm in loopback test mode (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name); cnetz_sync_frame(cnetz, sync_time, -1); return; } if (opcode >= 32) { - PDEBUG(DFRAME, DEBUG_NOTICE, "Received Telegramm that is not used by mobile station, ignoring! (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name); + LOGP(DFRAME, LOGL_NOTICE, "Received Telegramm that is not used by mobile station, ignoring! (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name); return; } if (definition_opcode[opcode].block == BLOCK_I) { - PDEBUG(DFRAME, DEBUG_NOTICE, "Received Telegramm that is an illegal opcode, ignoring! (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name); + LOGP(DFRAME, LOGL_NOTICE, "Received Telegramm that is an illegal opcode, ignoring! (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name); return; } @@ -1530,7 +1544,7 @@ void cnetz_decode_telegramm(cnetz_t *cnetz, const char *bits, double level, doub 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 signaling, ignoring! (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name); + LOGP(DFRAME, LOGL_NOTICE, "Received Telegramm that is not used OgK channel signaling, ignoring! (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name); return; } /* determine block by last timeslot sent and by message type @@ -1543,14 +1557,14 @@ void cnetz_decode_telegramm(cnetz_t *cnetz, const char *bits, double level, doub break; case DSP_MODE_SPK_K: if (definition_opcode[opcode].block != BLOCK_K) { - PDEBUG(DFRAME, DEBUG_NOTICE, "Received Telegramm that is not used for concentrated signaling, ignoring! (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name); + LOGP(DFRAME, LOGL_NOTICE, "Received Telegramm that is not used for concentrated signaling, ignoring! (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name); return; } cnetz_receive_telegramm_spk_k(cnetz, &telegramm); break; case DSP_MODE_SPK_V: if (definition_opcode[opcode].block != BLOCK_V) { - PDEBUG(DFRAME, DEBUG_NOTICE, "Received Telegramm that is not used for distributed signaling, ignoring! (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name); + LOGP(DFRAME, LOGL_NOTICE, "Received Telegramm that is not used for distributed signaling, ignoring! (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name); return; } cnetz_receive_telegramm_spk_v(cnetz, &telegramm); @@ -1565,6 +1579,7 @@ const char *cnetz_encode_telegramm(cnetz_t *cnetz) const telegramm_t *telegramm = NULL; uint8_t opcode; char *bits; + int debug = 1; switch (cnetz->dsp_mode) { case DSP_MODE_OGK: @@ -1583,8 +1598,15 @@ const char *cnetz_encode_telegramm(cnetz_t *cnetz) ; } + if (!telegramm) + return NULL; + opcode = telegramm->opcode; - bits = assemble_telegramm(telegramm, (opcode != OPCODE_LR_R) && (opcode != OPCODE_MLR_M)); + if (opcode == OPCODE_LR_R && cnetz->sched_lr_debugged) + debug = 0; + if (opcode == OPCODE_MLR_M && cnetz->sched_mlr_debugged) + debug = 0; + bits = assemble_telegramm(telegramm, debug); bits = encode(bits); bits = interleave(bits); @@ -1596,6 +1618,13 @@ const char *cnetz_encode_telegramm(cnetz_t *cnetz) bits[i] ^= 1; } + if (opcode == OPCODE_LR_R && !cnetz->sched_lr_debugged) + cnetz->sched_lr_debugged = 1; + if (opcode == OPCODE_MLR_M && !cnetz->sched_mlr_debugged) { + cnetz->sched_mlr_debugged = 1; + LOGP(DFRAME, LOGL_INFO, "Subsequent IDLE frames are not show, to prevent flooding the output.\n"); + } + return bits; } diff --git a/src/cnetz/telegramm.h b/src/cnetz/telegramm.h index 06758aa..06adda8 100644 --- a/src/cnetz/telegramm.h +++ b/src/cnetz/telegramm.h @@ -112,6 +112,8 @@ typedef struct telegramm { uint8_t erweitertes_frequenzbandbit; uint8_t reduzierungsfaktor; uint64_t illegaler_opcode; + uint8_t bahn_ms; + uint8_t bahn_bs; } telegramm_t; int init_telegramm(void); diff --git a/src/cnetz/transaction.c b/src/cnetz/transaction.c index acfe416..f89718b 100644 --- a/src/cnetz/transaction.c +++ b/src/cnetz/transaction.c @@ -20,14 +20,17 @@ #include <stdio.h> #include <stdint.h> #include <stdlib.h> +#include <math.h> #include "../libsample/sample.h" -#include "../libdebug/debug.h" +#include "../liblogging/logging.h" #include "../libmobile/call.h" -#include "../libmncc/cause.h" +#include "../libmobile/cause.h" #include "cnetz.h" #include "telegramm.h" #include "database.h" +static int new_cueue_position = 0; + const char *transaction2rufnummer(transaction_t *trans) { static char rufnummer[32]; /* make GCC happy (overflow check) */ @@ -38,25 +41,35 @@ const char *transaction2rufnummer(transaction_t *trans) } /* create transaction */ -transaction_t *create_transaction(cnetz_t *cnetz, uint64_t state, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int futelg_bit, int extended) +transaction_t *create_transaction(cnetz_t *cnetz, uint64_t state, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int futelg_bit, int extended, double rf_level_db) { - sender_t *sender; - transaction_t *trans = NULL; - cnetz_t *search_cnetz; + transaction_t *trans; - /* search transaction for this subsriber */ - for (sender = sender_head; sender; sender = sender->next) { - search_cnetz = (cnetz_t *) sender; - /* search transaction for this callref */ - trans = search_transaction_number(search_cnetz, futln_nat, futln_fuvst, futln_rest); - if (trans) - break; - } + trans = search_transaction_number_global(futln_nat, futln_fuvst, futln_rest); if (trans) { const char *rufnummer = transaction2rufnummer(trans); int old_callref = trans->callref; cnetz_t *old_cnetz = trans->cnetz; - PDEBUG(DTRANS, DEBUG_NOTICE, "Found alredy pending transaction for subscriber '%s', deleting!\n", rufnummer); + /* both states must be the same and one of the give selection */ + if ((trans->state & state & (TRANS_EM | TRANS_UM | TRANS_VWG | TRANS_ATQ_IDLE))) { + if (!isnan(trans->rf_level_db) && !isnan(rf_level_db) && trans->cnetz->kanal != cnetz->kanal) { + if (rf_level_db > trans->rf_level_db) { + LOGP(DTRANS, LOGL_NOTICE, "Found already pending transaction for subscriber '%s' on channel #%d, but this message on channel #%d is stronger, so we move to that channel!\n", rufnummer, trans->cnetz->kanal, cnetz->kanal); + trans->rf_level_db = rf_level_db; + unlink_transaction(trans); + link_transaction(trans, cnetz); + update_db(trans->futln_nat, trans->futln_fuvst, trans->futln_rest, cnetz->kanal, NULL, NULL, 1, 0); + return trans; + } + if (rf_level_db < trans->rf_level_db) { + LOGP(DTRANS, LOGL_NOTICE, "Found already pending transaction for subscriber '%s' on channel #%d, but this message on channel #%d is weaker, so we ignore that channel!\n", rufnummer, trans->cnetz->kanal, cnetz->kanal); + return trans; + } + } + LOGP(DTRANS, LOGL_NOTICE, "Found already pending transaction for subscriber '%s' on channel #%d, but this message on channel #%d is also received. Try to avoid multiple OgK channels!\n", rufnummer, trans->cnetz->kanal, cnetz->kanal); + return trans; + } + LOGP(DTRANS, LOGL_NOTICE, "Found already pending transaction for subscriber '%s', deleting!\n", rufnummer); destroy_transaction(trans); if (old_cnetz) /* should be... */ cnetz_go_idle(old_cnetz); @@ -66,11 +79,11 @@ transaction_t *create_transaction(cnetz_t *cnetz, uint64_t state, uint8_t futln_ trans = calloc(1, sizeof(*trans)); if (!trans) { - PDEBUG(DTRANS, DEBUG_ERROR, "No memory!\n"); + LOGP(DTRANS, LOGL_ERROR, "No memory!\n"); return NULL; } - timer_init(&trans->timer, transaction_timeout, trans); + osmo_timer_setup(&trans->timer, transaction_timeout, trans); trans_new_state(trans, state); trans->futln_nat = futln_nat; @@ -83,15 +96,17 @@ transaction_t *create_transaction(cnetz_t *cnetz, uint64_t state, uint8_t futln_ trans->mt_call = 1; const char *rufnummer = transaction2rufnummer(trans); - PDEBUG(DTRANS, DEBUG_INFO, "Created transaction for subscriber '%s'\n", rufnummer); + LOGP(DTRANS, LOGL_INFO, "Created transaction for subscriber '%s'\n", rufnummer); link_transaction(trans, cnetz); /* update database: now busy */ - update_db(cnetz, futln_nat, futln_fuvst, futln_rest, &futelg_bit, &extended, 1, 0); + update_db(futln_nat, futln_fuvst, futln_rest, cnetz->kanal, &futelg_bit, &extended, 1, 0); trans->futelg_bit = futelg_bit; trans->extended = extended; + trans->rf_level_db = rf_level_db; + return trans; } @@ -99,14 +114,14 @@ transaction_t *create_transaction(cnetz_t *cnetz, uint64_t state, uint8_t futln_ void destroy_transaction(transaction_t *trans) { /* update database: now idle */ - update_db(trans->cnetz, trans->futln_nat, trans->futln_fuvst, trans->futln_rest, NULL, NULL, 0, trans->page_failed); + update_db(trans->futln_nat, trans->futln_fuvst, trans->futln_rest, 0, NULL, NULL, 0, trans->page_failed); unlink_transaction(trans); const char *rufnummer = transaction2rufnummer(trans); - PDEBUG(DTRANS, DEBUG_INFO, "Destroying transaction for subscriber '%s'\n", rufnummer); + LOGP(DTRANS, LOGL_INFO, "Destroying transaction for subscriber '%s'\n", rufnummer); - timer_exit(&trans->timer); + osmo_timer_del(&trans->timer); trans_new_state(trans, 0); @@ -119,7 +134,7 @@ void link_transaction(transaction_t *trans, cnetz_t *cnetz) transaction_t **transp; /* attach to end of list, so first transaction is served first */ - PDEBUG(DTRANS, DEBUG_DEBUG, "Linking transaction %p to cnetz %p\n", trans, cnetz); + LOGP(DTRANS, LOGL_DEBUG, "Linking transaction %p to cnetz %p\n", trans, cnetz); trans->cnetz = cnetz; trans->next = NULL; transp = &cnetz->trans_list; @@ -135,12 +150,12 @@ void unlink_transaction(transaction_t *trans) transaction_t **transp; /* unlink */ - PDEBUG(DTRANS, DEBUG_DEBUG, "Unlinking transaction %p from cnetz %p\n", trans, trans->cnetz); + LOGP(DTRANS, LOGL_DEBUG, "Unlinking transaction %p from cnetz %p\n", trans, trans->cnetz); transp = &trans->cnetz->trans_list; while (*transp && *transp != trans) transp = &((*transp)->next); if (!(*transp)) { - PDEBUG(DTRANS, DEBUG_ERROR, "Transaction not in list, please fix!!\n"); + LOGP(DTRANS, LOGL_ERROR, "Transaction not in list, please fix!!\n"); abort(); } *transp = trans->next; @@ -155,7 +170,7 @@ transaction_t *search_transaction(cnetz_t *cnetz, uint64_t state_mask) while (trans) { if ((trans->state & state_mask)) { const char *rufnummer = transaction2rufnummer(trans); - PDEBUG(DTRANS, DEBUG_DEBUG, "Found transaction for subscriber '%s'\n", rufnummer); + LOGP(DTRANS, LOGL_DEBUG, "Found transaction for subscriber '%s'\n", rufnummer); return trans; } trans = trans->next; @@ -173,7 +188,7 @@ transaction_t *search_transaction_number(cnetz_t *cnetz, uint8_t futln_nat, uint && trans->futln_fuvst == futln_fuvst && trans->futln_rest == futln_rest) { const char *rufnummer = transaction2rufnummer(trans); - PDEBUG(DTRANS, DEBUG_DEBUG, "Found transaction for subscriber '%s'\n", rufnummer); + LOGP(DTRANS, LOGL_DEBUG, "Found transaction for subscriber '%s'\n", rufnummer); return trans; } trans = trans->next; @@ -182,6 +197,23 @@ transaction_t *search_transaction_number(cnetz_t *cnetz, uint8_t futln_nat, uint return NULL; } +transaction_t *search_transaction_number_global(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest) +{ + sender_t *sender; + cnetz_t *cnetz; + transaction_t *trans = NULL; + + /* search transaction for this subscriber */ + for (sender = sender_head; sender; sender = sender->next) { + cnetz = (cnetz_t *) sender; + /* search transaction for this callref */ + trans = search_transaction_number(cnetz, futln_nat, futln_fuvst, futln_rest); + if (trans) + break; + } + + return trans; +} transaction_t *search_transaction_callref(cnetz_t *cnetz, int callref) { transaction_t *trans = cnetz->trans_list; @@ -192,7 +224,7 @@ transaction_t *search_transaction_callref(cnetz_t *cnetz, int callref) while (trans) { if (trans->callref == callref) { const char *rufnummer = transaction2rufnummer(trans); - PDEBUG(DTRANS, DEBUG_DEBUG, "Found transaction for subscriber '%s'\n", rufnummer); + LOGP(DTRANS, LOGL_DEBUG, "Found transaction for subscriber '%s'\n", rufnummer); return trans; } trans = trans->next; @@ -201,6 +233,42 @@ transaction_t *search_transaction_callref(cnetz_t *cnetz, int callref) return NULL; } +/* get oldest transaction in queue: + * + * oldest means that the queue number is the smallest. + * all candidates (transactions) must be in queue state. + */ +transaction_t *search_transaction_queue(void) +{ + sender_t *sender; + transaction_t *trans, *found = NULL; + cnetz_t *cnetz; + int queue_max = 0; + + for (sender = sender_head; sender; sender = sender->next) { + cnetz = (cnetz_t *) sender; + trans = cnetz->trans_list; + while (trans) { + if ((trans->state & (TRANS_MO_QUEUE | TRANS_MT_QUEUE))) { + /* select if first or lower number */ + if (!found || trans->queue_position < queue_max) { + queue_max = trans->queue_position; + found = trans; + } + } + trans = trans->next; + } + } + + if (found) { + const char *rufnummer = transaction2rufnummer(found); + LOGP(DTRANS, LOGL_DEBUG, "Found oldest transaction in queue for subscriber '%s'\n", rufnummer); + return found; + } + + return NULL; +} + static const char *trans_state_name(uint64_t state) { switch (state) { @@ -252,6 +320,8 @@ static const char *trans_state_name(uint64_t state) return "AT"; case TRANS_ATQ: return "ATQ"; + case TRANS_ATQ_IDLE: + return "ATQ_IDLE"; case TRANS_MO_QUEUE: return "MO_QUEUE"; case TRANS_MT_QUEUE: @@ -261,7 +331,7 @@ static const char *trans_state_name(uint64_t state) case TRANS_MT_DELAY: return "MT_DELAY"; default: - return "<invald transaction state>"; + return "<invalid transaction state>"; } } @@ -301,6 +371,7 @@ const char *trans_short_state_name(uint64_t state) case TRANS_AF: case TRANS_AT: case TRANS_ATQ: + case TRANS_ATQ_IDLE: return "RELEASE"; case TRANS_MO_QUEUE: case TRANS_MO_DELAY: @@ -309,14 +380,17 @@ const char *trans_short_state_name(uint64_t state) case TRANS_MT_DELAY: return "IN QUEUE"; default: - return "<invald transaction state>"; + return "<invalid transaction state>"; } } void trans_new_state(transaction_t *trans, uint64_t state) { - PDEBUG(DTRANS, DEBUG_INFO, "Transaction (%s) state %s -> %s\n", transaction2rufnummer(trans), trans_state_name(trans->state), trans_state_name(state)); + LOGP(DTRANS, LOGL_INFO, "Transaction (%s) state %s -> %s\n", transaction2rufnummer(trans), trans_state_name(trans->state), trans_state_name(state)); trans->state = state; + /* in case of a queue, set new positon */ + if (!trans->queue_position && (state == TRANS_MO_QUEUE || state == TRANS_MT_QUEUE)) + trans->queue_position = ++new_cueue_position; cnetz_display_status(); } @@ -324,12 +398,12 @@ void cnetz_flush_other_transactions(cnetz_t *cnetz, transaction_t *trans) { /* flush after this very trans */ while (trans->next) { - PDEBUG(DTRANS, DEBUG_NOTICE, "Kicking other pending transaction\n"); + LOGP(DTRANS, LOGL_NOTICE, "Kicking other pending transaction\n"); destroy_transaction(trans->next); } /* flush before this very trans */ while (cnetz->trans_list != trans) { - PDEBUG(DTRANS, DEBUG_NOTICE, "Kicking other pending transaction\n"); + LOGP(DTRANS, LOGL_NOTICE, "Kicking other pending transaction\n"); destroy_transaction(cnetz->trans_list); } } diff --git a/src/cnetz/transaction.h b/src/cnetz/transaction.h index edb1832..4a5d70b 100644 --- a/src/cnetz/transaction.h +++ b/src/cnetz/transaction.h @@ -13,7 +13,7 @@ #define TRANS_WBN (1 << 7) /* dialing received, waiting for time slot to reject call */ #define TRANS_VAG (1 << 8) /* establishment of call sent, switching channel */ /* mobile terminated call */ -#define TRANS_WSK (1 << 9) /* incomming call in queue */ +#define TRANS_WSK (1 << 9) /* incoming call in queue */ #define TRANS_VAK (1 << 10) /* establishment of call sent, switching channel */ /* traffic channel */ #define TRANS_BQ (1 << 11) /* accnowledge channel */ @@ -29,11 +29,12 @@ #define TRANS_AF (1 << 20) /* release connection by base station (SpK) */ #define TRANS_AT (1 << 21) /* release connection by mobile station */ #define TRANS_ATQ (1 << 22) /* acknowledge release of MO call in queue */ +#define TRANS_ATQ_IDLE (1 << 23) /* repeat, if call has been released already (mobile sends again) */ /* queue */ -#define TRANS_MO_QUEUE (1 << 23) /* MO queue */ -#define TRANS_MT_QUEUE (1 << 24) /* MT queue */ -#define TRANS_MO_DELAY (1 << 25) /* delay to be sure the channel is free again */ -#define TRANS_MT_DELAY (1 << 26) +#define TRANS_MO_QUEUE (1 << 24) /* MO queue */ +#define TRANS_MT_QUEUE (1 << 25) /* MT queue */ +#define TRANS_MO_DELAY (1 << 26) /* delay to be sure the channel is free again */ +#define TRANS_MT_DELAY (1 << 27) typedef struct transaction { struct transaction *next; /* pointer to next node in list */ @@ -49,23 +50,29 @@ typedef struct transaction { int8_t release_cause; /* reason for release, (c-netz coding) */ int try; /* counts resending messages */ int repeat; /* counts repeating messages */ - struct timer timer; /* for varous timeouts */ + struct osmo_timer_list timer; /* for varous timeouts */ int mo_call; /* flags a moile originating call */ int mt_call; /* flags a moile terminating call */ int page_failed; /* failed to get a response from MS */ - double call_start; /* when did the call start? (used for metering) */ + double metering_time; /* time between units (0.0 if no metering set) */ + double meter_start; /* when did the metering start? (0.0 if not yet started) */ + double meter_end; /* when did the metering end? (0.0 if not yet ended) */ + int queue_position; /* to find next transaction in queue */ + double rf_level_db; /* level of first contact, so we can detect correct channel at multiple receptions */ } transaction_t; const char *transaction2rufnummer(transaction_t *trans); -transaction_t *create_transaction(cnetz_t *cnetz, uint64_t state, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int futelg_bit, int extended); +transaction_t *create_transaction(cnetz_t *cnetz, uint64_t state, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int futelg_bit, int extended, double rf_level_db); void destroy_transaction(transaction_t *trans); void link_transaction(transaction_t *trans, cnetz_t *cnetz); void unlink_transaction(transaction_t *trans); transaction_t *search_transaction(cnetz_t *cnetz, uint64_t state_mask); transaction_t *search_transaction_number(cnetz_t *cnetz, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest); +transaction_t *search_transaction_number_global(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest); transaction_t *search_transaction_callref(cnetz_t *cnetz, int callref); +transaction_t *search_transaction_queue(void); void trans_new_state(transaction_t *trans, uint64_t state); void cnetz_flush_other_transactions(cnetz_t *cnetz, transaction_t *trans); -void transaction_timeout(struct timer *timer); +void transaction_timeout(void *data); const char *trans_short_state_name(uint64_t state); |