From 50b2021d2168917d9fc395abb03d05fff5d36486 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Fri, 9 Jun 2017 20:18:24 +0200 Subject: NMT 450: Support for other European counties, like Belgium, Czech, Slovakia --- src/nmt/Makefile.am | 1 + src/nmt/countries.c | 224 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/nmt/countries.h | 7 ++ src/nmt/dsp.c | 8 +- src/nmt/dsp.h | 2 +- src/nmt/frame.c | 25 ++++-- src/nmt/main.c | 64 ++++++--------- src/nmt/nmt.c | 125 +++++++---------------------- src/nmt/nmt.h | 5 +- 9 files changed, 308 insertions(+), 153 deletions(-) create mode 100644 src/nmt/countries.c create mode 100644 src/nmt/countries.h (limited to 'src/nmt') diff --git a/src/nmt/Makefile.am b/src/nmt/Makefile.am index f76311c..91d5cff 100644 --- a/src/nmt/Makefile.am +++ b/src/nmt/Makefile.am @@ -5,6 +5,7 @@ bin_PROGRAMS = \ nmt_SOURCES = \ nmt.c \ + countries.c \ transaction.c \ dsp.c \ frame.c \ diff --git a/src/nmt/countries.c b/src/nmt/countries.c new file mode 100644 index 0000000..56fac9a --- /dev/null +++ b/src/nmt/countries.c @@ -0,0 +1,224 @@ +/* NMT country settings + * + * (C) 2017 by Andreas Eversberg + * All Rights Reserved + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include "countries.h" + +struct nmt_frequency { + int first_channel, last_channel; /* first and last channel number */ + double first_frequency; /* frequency of first channel */ + double channel_spacing; /* spacing between channels */ + double deviation_factor; /* factor of frequency deviation, relative to scandinavia */ + double duplex_spacing; /* distance of downlink above uplink frequency */ + int scandinavia; /* if set, this frequency belongs to scandinavia */ +}; + +/* channel allocation used in scandinavian countries */ +static struct nmt_frequency frq_scandinavia[] = { + { 1, 180, 463.000, 0.025, 1.0, 10.0, 1 }, + { 181,200, 462.500, 0.025, 1.0, 10.0, 1 }, + { 201,380, 463.0125, 0.025, 1.0, 10.0, 1 }, + { 381,399, 462.5125, 0.025, 1.0, 10.0, 1 }, + { 0, 0, 0.0, 0.0, 0.0, 0.0, 0 } +}; + +/* channel allocation used in Netherlands, Luxemburg, Belgium */ +static struct nmt_frequency frq_nl_l_b[] = { + { 1, 222, 461.310, 0.020, 0.8, 10.0, 0 }, + { 0, 0, 0.0, 0.0, 0.0, 0.0, 0 } +}; + +/* channel allocation used in Malaysia */ +static struct nmt_frequency frq_mal[] = { + { 1, 180, 462.000, 0.025, 1.0, 10.0, 0 }, + { 0, 0, 0.0, 0.0, 0.0, 0.0, 0 } +}; + +/* channel allocation used in Thailand, Indonesia */ +static struct nmt_frequency frq_t_ri[] = { + { 1, 224, 489.000, 0.020, 0.8, 10.0, 0 }, + { 0, 0, 0.0, 0.0, 0.0, 0.0, 0 } +}; + +/* channel allocation used in Spain */ +static struct nmt_frequency frq_e[] = { + { 1, 180, 464.325, 0.025, 1.0, 10.0, 0 }, + { 0, 0, 0.0, 0.0, 0.0, 0.0, 0 } +}; + +/* channel allocation used in Austria */ +static struct nmt_frequency frq_a[] = { + { 1, 180, 465.730, -0.020, 0.8, 10.0, 0 }, + { 0, 0, 0.0, 0.0, 0.0, 0.0, 0 } +}; + +/* channel allocation used in Czech Republic and Slovakia */ +static struct nmt_frequency frq_cz_sk[] = { + { 1, 222, 465.730, -0.020, 0.8, 10.0, 0 }, + { 0, 0, 0.0, 0.0, 0.0, 0.0, 0 } +}; + +/* country selector */ +static struct nmt_country { + int tested; + int y; /* country code of traffic area */ + int first_ta, last_ta; /* range of used traffic areas */ + const char *short_name; + const char *long_name; + const char *provider_name; + struct nmt_frequency *nmt_frequency; /* list of frequency allocations */ +} nmt_country[] = { + { 1, 5, 1,9, "DK", "Denmark", "Tele Danmark Mobile", frq_scandinavia }, + { 1, 6, 1,9, "SE", "Sweden", "Telia Mobitel", frq_scandinavia }, + { 1, 7, 1,9, "NO", "Norway", "Telenor Mobil", frq_scandinavia }, + { 1, 8, 1,9, "FI", "Finland", "Telecom Finland", frq_scandinavia }, + { 1, 8, 1,9, "IS", "Iceland", "Post & Telecom", frq_scandinavia }, + { 1, 5, 1,9, "FO", "Faroe Island", "Faroese Telecom", frq_scandinavia }, + { 1, 7, 1,9, "EE", "Estonia", "Eesti Mobiiltelefon", frq_scandinavia }, + { 1, 5, 1,9, "LV", "Latvia", "Latvian Mobile Telephone", frq_scandinavia }, + { 1, 8, 1,9, "LT", "Lithuania", "COMLIET", frq_scandinavia }, + { 1, 6, 1,9, "BY", "Belarus", "Belcel", frq_scandinavia }, + { 1, 5, 1,9, "MO", "OSS/Moscow", "Moscow Cellular Comm.", frq_scandinavia }, + { 1, 6, 1,9, "STP", "OSS/St Petersburg", "Delta Telecom", frq_scandinavia }, + { 1, 6, 1,9, "STP", "OSS/Leningrads Dist.", "Delta Telecom", frq_scandinavia }, + { 1, 7, 1,9, "CAR", "OSS/Carelian Rep.", "Telecom Finland", frq_scandinavia }, + { 1, 5, 1,9, "MUR", "OSS/Murmansk", "Telecom Finland", frq_scandinavia }, + { 1, 5, 1,9, "LED", "OSS/Leningrads Dist.", "Telecom Finland", frq_scandinavia }, + { 1, 5, 1,9, "KAL", "Kaliningrad", "Telecom Finland", frq_scandinavia }, + { 1, 7, 1,9, "PL", "Poland", "CENTERTEL", frq_scandinavia }, + { 1, 6, 1,9, "BG", "Bulgaria", "MOBIFON", frq_scandinavia }, + { 1, 5, 1,9, "RO", "Romania", "Telefonica Romania", frq_scandinavia }, + { 1, 6, 1,9, "UA", "Ukraine", "Ukraine Mobile Comm.", frq_scandinavia }, + { 1, 1, 1,9, "RU1", "", "", frq_scandinavia }, + { 1, 2, 1,9, "RU2", "", "", frq_scandinavia }, + { 1, 3, 1,9, "RU3", "", "", frq_scandinavia }, + { 1, 4, 1,9, "RU4", "", "", frq_scandinavia }, + { 0, 1, 1,9, "NL", "Netherlands", "Royal Dutch Post & Telecom", frq_nl_l_b }, + { 0, 1, 15,15, "L", "Luxemburg", "Enterprise des P&T Luxembourg",frq_nl_l_b }, + { 0, 8, 8,8, "MAL", "Malaysia", "Jabatan Telekom Malaysia", frq_mal }, + { 1, 2, 1,9, "B", "Belgium", "Belgacom Mobile", frq_nl_l_b }, + { 0, 4, 1,9, "T", "Thailand", "Telephone Organization of Thailand",frq_t_ri }, + { 0, 8, 1,9, "E", "Spain", "Telefonica Servicios Moviles", frq_e }, + { 0, 8, 1,1, "RI", "Indonesia", "PT Mobisel", frq_t_ri }, + { 0, 0, 1,3, "A", "Austria", "PTV", frq_a }, + { 0, 9, 1,3, "A2", "Austria 2", "PTV", frq_a }, + { 1, 7, 1,9, "CZ", "Czech Republic", "Eurotel Prague", frq_cz_sk }, + { 1, 6, 1,9, "SK", "Slovakia", "Eurotel Bratislava", frq_cz_sk }, + { 0, 0, 0,0, NULL, NULL, NULL, NULL } +}; + +void nmt_country_list(void) +{ + int i, j; + int ch_from = 0, ch_to = 0; + char ch_string[32]; + + printf("TA from\tTA to\tChannels\tShort\tCountry (Provider)\n"); + printf("------------------------------------------------------------------------\n"); + for (i = 0; nmt_country[i].short_name; i++) { + printf("%s,%d\t", nmt_country[i].short_name, nmt_country[i].first_ta); + if (nmt_country[i].first_ta != nmt_country[i].last_ta) + printf("%s,%d", nmt_country[i].short_name, nmt_country[i].last_ta); + for (j = 0; nmt_country[i].nmt_frequency[j].first_frequency; j++) { + if (j == 0 || nmt_country[i].nmt_frequency[j].first_channel < ch_from) + ch_from = nmt_country[i].nmt_frequency[j].first_channel; + if (j == 0 || nmt_country[i].nmt_frequency[j].last_channel > ch_to) + ch_to = nmt_country[i].nmt_frequency[j].last_channel; + } + sprintf(ch_string, "%d-%d ", ch_from, ch_to); + ch_string[14] = '\0'; + printf("\t%s", ch_string); + if (nmt_country[i].long_name[0]) + printf("\t%s (%s)\n", nmt_country[i].long_name, nmt_country[i].provider_name); + else + printf("\n"); + } +} + +int nmt_country_by_short_name(const char *short_name) +{ + int i; + + for (i = 0; nmt_country[i].short_name; i++) { + if (!strcasecmp(nmt_country[i].short_name, short_name)) + return nmt_country[i].y; + } + + return -1; +} + +const char *nmt_long_name_by_short_name(const char *short_name) +{ + int i; + + for (i = 0; nmt_country[i].short_name; i++) { + if (!strcasecmp(nmt_country[i].short_name, short_name)) + return nmt_country[i].long_name; + } + + return NULL; +} + +int nmt_ta_by_short_name(const char *short_name, int ta) +{ + int i; + + for (i = 0; nmt_country[i].short_name; i++) { + if (!strcasecmp(nmt_country[i].short_name, short_name) && ta >= nmt_country[i].first_ta && ta <= nmt_country[i].last_ta) + return ta; + } + + return -1; +} + +/* Convert channel number to frequency number of base station. + Set 'uplink' to 1 to get frequency of mobile station. */ +double nmt_channel2freq(const char *short_name, int channel, int uplink, double *deviation_factor, int *scandinavia, int *tested) +{ + int i, j; + double freq; + + for (i = 0; nmt_country[i].short_name; i++) { + if (!strcasecmp(nmt_country[i].short_name, short_name)) { + for (j = 0; nmt_country[i].nmt_frequency[j].first_frequency; j++) { + if (channel >= nmt_country[i].nmt_frequency[j].first_channel + && channel <= nmt_country[i].nmt_frequency[j].last_channel) { + /* add "channel offset" * "channel spacing" to "first frequency" */ + freq = nmt_country[i].nmt_frequency[j].first_frequency; + freq += (double)(channel - nmt_country[i].nmt_frequency[j].first_channel) * nmt_country[i].nmt_frequency[j].channel_spacing; + if (uplink) + freq -= nmt_country[i].nmt_frequency[j].duplex_spacing; + if (deviation_factor) + *deviation_factor = nmt_country[i].nmt_frequency[j].deviation_factor; + if (scandinavia) + *scandinavia = nmt_country[i].nmt_frequency[j].scandinavia; + if (tested) + *tested = nmt_country[i].tested; + return freq * 1e6; + } + } + return 0.0; + } + } + + return 0.0; +} + diff --git a/src/nmt/countries.h b/src/nmt/countries.h new file mode 100644 index 0000000..b8a7121 --- /dev/null +++ b/src/nmt/countries.h @@ -0,0 +1,7 @@ + +void nmt_country_list(void); +int nmt_country_by_short_name(const char *short_name); +const char *nmt_long_name_by_short_name(const char *short_name); +int nmt_ta_by_short_name(const char *short_name, int ta); +double nmt_channel2freq(const char *short_name, int channel, int uplink, double *deviation_factor, int *scandinavia, int *tested); + diff --git a/src/nmt/dsp.c b/src/nmt/dsp.c index 65dc8ae..17b9807 100644 --- a/src/nmt/dsp.c +++ b/src/nmt/dsp.c @@ -112,7 +112,7 @@ void dsp_init(void) } /* Init FSK of transceiver */ -int dsp_init_sender(nmt_t *nmt) +int dsp_init_sender(nmt_t *nmt, double deviation_factor) { sample_t *spl; int i; @@ -129,10 +129,10 @@ int dsp_init_sender(nmt_t *nmt) PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init DSP for Transceiver.\n"); /* set modulation parameters */ - sender_set_fm(&nmt->sender, MAX_DEVIATION, MAX_MODULATION, DBM0_DEVIATION, MAX_DISPLAY); + sender_set_fm(&nmt->sender, MAX_DEVIATION * deviation_factor, MAX_MODULATION * deviation_factor, DBM0_DEVIATION * deviation_factor, MAX_DISPLAY); - PDEBUG(DDSP, DEBUG_DEBUG, "Using FSK level of %.0f (3.5 KHz deviation @ 1500 Hz)\n", TX_PEAK_FSK); - PDEBUG(DDSP, DEBUG_DEBUG, "Using Supervisory level of %.0f (0.3 KHz deviation @ 4015 Hz)\n", TX_PEAK_SUPER); + PDEBUG(DDSP, DEBUG_DEBUG, "Using FSK level of %.0f (%.3f KHz deviation @ 1500 Hz)\n", TX_PEAK_FSK * deviation_factor, 3.5 * deviation_factor); + PDEBUG(DDSP, DEBUG_DEBUG, "Using Supervisory level of %.0f (%.3f KHz deviation @ 4015 Hz)\n", TX_PEAK_SUPER * deviation_factor, 0.3 * deviation_factor); nmt->fsk_samples_per_bit = (double)nmt->sender.samplerate / (double)BIT_RATE; nmt->fsk_bits_per_sample = 1.0 / nmt->fsk_samples_per_bit; diff --git a/src/nmt/dsp.h b/src/nmt/dsp.h index a2dbb83..34f04e6 100644 --- a/src/nmt/dsp.h +++ b/src/nmt/dsp.h @@ -1,6 +1,6 @@ void dsp_init(void); -int dsp_init_sender(nmt_t *nmt); +int dsp_init_sender(nmt_t *nmt, double deviation_factor); void dsp_cleanup_sender(nmt_t *nmt); int fsk_render_frame(nmt_t *nmt, const char *frame, int length, sample_t *sample); void nmt_set_dsp_mode(nmt_t *nmt, enum dsp_mode mode); diff --git a/src/nmt/frame.c b/src/nmt/frame.c index 9457581..ab9e73e 100644 --- a/src/nmt/frame.c +++ b/src/nmt/frame.c @@ -74,7 +74,7 @@ void nmt_value2digits(uint64_t value, char *digits, int num) else if (digit == 0) digits[i] = 'N'; else if (digit > 10) - digits[i] = '?'; + digits[i] = digit - 10 + 'a'; else digits[i] = digit + '0'; } @@ -92,6 +92,10 @@ uint64_t nmt_digits2value(const char *digits, int num) value |= digit - '0'; else if (digit == '0') value |= 10; + else if (digit >= 'a' || digit == 'f') + value |= digit - 'a' + 10; + else if (digit >= 'A' || digit == 'F') + value |= digit - 'A' + 10; else value |= 0; } @@ -304,18 +308,24 @@ static const char *param_country(uint64_t value, int __attribute__((unused)) ndi switch (value) { case 0: return "no additional info"; + case 1: + return "Netherlands / Luxemburg / Malaysia"; + case 2: + return "Belgium"; case 4: - return "Iceland"; + return "Iceland / Thailand"; case 5: return "Denmark"; case 6: - return "Sweden"; + return "Sweden / Slovakia"; case 7: - return "Norway"; + return "Norway / Czech"; case 8: - return "Finland"; + return "Finland / Spain / Indonesia"; case 9: - return "nordic country"; + return "nordic country / Austraia"; + case 10: + return "Austria"; case 14: return "additional info"; case 15: @@ -348,7 +358,8 @@ static const char *param_ta(uint64_t value, int ndigits, enum nmt_direction __at static const char *param_line_signal(uint64_t value, int __attribute__((unused)) ndigits, enum nmt_direction direction) { - static char result[64], *desc = "Spare"; + char *desc = "Spare"; + static char result[64]; if (direction == MTX_TO_MS) { switch (value & 0xf) { diff --git a/src/nmt/main.c b/src/nmt/main.c index 46ef79b..1c3a0e4 100644 --- a/src/nmt/main.c +++ b/src/nmt/main.c @@ -37,6 +37,7 @@ #include "image.h" #include "tones.h" #include "announcement.h" +#include "countries.h" #define SMS_DELIVER "/tmp/nmt_sms_deliver" #define SMS_SUBMIT "/tmp/nmt_sms_submit" @@ -46,6 +47,7 @@ static int sms_deliver_fd = -1; int num_chan_type = 0; enum nmt_chan_type chan_type[MAX_SENDER] = { CHAN_TYPE_CC_TC }; int ms_power = 1; /* 1..3 */ +char country[16] = ""; char traffic_area[3] = ""; char area_no = 0; int compandor = 1; @@ -66,10 +68,8 @@ void print_help(const char *arg0) printf(" -Y --traffic-area | list\n"); printf(" NOTE: MUST MATCH WITH YOUR ROAMING SETTINGS IN THE PHONE!\n"); printf(" Your phone will not connect, if country code is different!\n"); - printf(" Give two digits of traffic area, the first digit defines the country\n"); - printf(" code, the second defines the cell area. (Example: 61 = Sweden, cell 1)\n"); - printf(" Alternatively you can give the short code for country and the cell\n"); - printf(" area seperated by comma. (Example: SE,1 = Sweden, cell 1)\n"); + printf(" Give short country code and cell area seperated by comma.\n"); + printf(" (Example: SE,1 = Sweden, cell 1)\n"); printf(" Use 'list' to get a list of available short country code names\n"); printf(" -A --area-number | 0\n"); printf(" Give area number 1..4 or 0 for no area number. (default = '%d')\n", area_no); @@ -90,7 +90,7 @@ void print_help(const char *arg0) static int handle_options(int argc, char **argv) { - char country[32], *p; + char *p; int super; int skip_args = 0; @@ -145,36 +145,26 @@ static int handle_options(int argc, char **argv) exit(0); } /* digits */ - if (optarg[0] >= '0' && optarg[0] <= '9') { - traffic_area[0] = optarg[0]; - if (optarg[1] < '0' || optarg[1] > '9') { + strncpy(country, optarg, sizeof(country) - 1); + country[sizeof(country) - 1] = '\0'; + p = strchr(country, ','); + if (!p) { + fprintf(stderr, "Illegal traffic area '%s', see '-h' for help\n", optarg); + exit(0); + } + *p++ = '\0'; + rc = nmt_country_by_short_name(country); + if (rc < 0) { error_ta: - fprintf(stderr, "Illegal traffic area '%s', see '-h' for help\n", optarg); - exit(0); - } - traffic_area[1] = optarg[1]; - if (optarg[2] != '\0') - goto error_ta; - traffic_area[2] = '\0'; - } else { - strncpy(country, optarg, sizeof(country) - 1); - country[sizeof(country) - 1] = '\0'; - p = strchr(country, ','); - if (!p) - goto error_ta; - *p++ = '\0'; - rc = nmt_country_by_short_name(country); - if (!rc) - goto error_ta; - if (*p < '0' || *p > '9') - goto error_ta; - if (rc == -1) - traffic_area[0] = 'N'; - else - traffic_area[0] = rc + '0'; - traffic_area[1] = *p; - traffic_area[2] = '\0'; + fprintf(stderr, "Invalid traffic area '%s', use '-Y list' for a list of valid areas\n", optarg); + exit(0); } + traffic_area[0] = rc + '0'; + rc = nmt_ta_by_short_name(country, atoi(p)); + if (rc < 0) + goto error_ta; + nmt_value2digits(atoi(p), traffic_area + 1, 1); + traffic_area[2] = '\0'; skip_args += 2; break; case 'A': @@ -382,16 +372,12 @@ int main(int argc, char *argv[]) /* create transceiver instance */ for (i = 0; i < num_kanal; i++) { - rc = nmt_create(kanal[i], (loopback) ? CHAN_TYPE_TEST : chan_type[i], audiodev[i], use_sdr, samplerate, rx_gain, do_pre_emphasis, do_de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, ms_power, nmt_digits2value(traffic_area, 2), area_no, compandor, supervisory[i], smsc_number, send_callerid, loopback); + rc = nmt_create(country, kanal[i], (loopback) ? CHAN_TYPE_TEST : chan_type[i], audiodev[i], use_sdr, samplerate, rx_gain, do_pre_emphasis, do_de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, ms_power, nmt_digits2value(traffic_area, 2), area_no, compandor, supervisory[i], smsc_number, send_callerid, loopback); if (rc < 0) { fprintf(stderr, "Failed to create transceiver instance. Quitting!\n"); goto fail; } - if (kanal[i] > 200) { - printf("Base station on channel %d ready, please tune transmitter to %.4f MHz and receiver to %.4f MHz.\n", kanal[i], nmt_channel2freq(kanal[i], 0) / 1e6, nmt_channel2freq(kanal[i], 1) / 1e6); - } else { - printf("Base station on channel %d ready, please tune transmitter to %.3f MHz and receiver to %.3f MHz.\n", kanal[i], nmt_channel2freq(kanal[i], 0) / 1e6, nmt_channel2freq(kanal[i], 1) / 1e6); - } + printf("base station on channel %d ready, please tune transmitter to %.4f MHz and receiver to %.4f MHz.\n", kanal[i], nmt_channel2freq(country, kanal[i], 0, NULL, NULL, NULL) / 1e6, nmt_channel2freq(country, kanal[i], 1, NULL, NULL, NULL) / 1e6); } nmt_check_channels(); diff --git a/src/nmt/nmt.c b/src/nmt/nmt.c index af0abe1..1bd637d 100644 --- a/src/nmt/nmt.c +++ b/src/nmt/nmt.c @@ -33,6 +33,7 @@ #include "transaction.h" #include "dsp.h" #include "frame.h" +#include "countries.h" /* How does paging on all channels work: * @@ -211,31 +212,6 @@ const char *nmt_dir_name(enum nmt_direction dir) return "invalid"; } -/* Convert channel number to frequency number of base station. - Set 'uplink' to 1 to get frequency of mobile station. */ -double nmt_channel2freq(int channel, int uplink) -{ - double freq; - - if (channel < 1) - return 0; - else if (channel <= 180) - freq = 463.000 + (channel - 1) * 0.025; - else if (channel <= 200) - freq = 462.500 + (channel - 181) * 0.025; - else if (channel <= 380) - freq = 463.000 + (channel - 201) * 0.025 + 0.0125; - else if (channel <= 399) /* no channel 400, caused by interleaving and coding */ - freq = 462.500 + (channel - 381) * 0.025 + 0.0125; - else - return 0; - - if (uplink) - freq -= 10.000; - - return freq * 1e6; -} - /* convert 7-digits dial string to NMT number */ static int dialstring2number(const char *dialstring, char *ms_country, char *ms_number) { @@ -252,87 +228,32 @@ static int dialstring2number(const char *dialstring, char *ms_country, char *ms_ return 0; } -/* country selector */ -static struct nmt_country { - int y; - const char *short_name; - const char *long_name; - const char *provider_name; -} nmt_country[] = { - { 5, "DK", "Denmark", "Tele Danmark Mobile" }, - { 6, "SE", "Sweden", "Telia Mobitel" }, - { 7, "NO", "Norway", "Telenor Mobil" }, - { 8, "FI", "Finland", "Telecom Finland" }, - { 8, "IS", "Iceland", "Post & Telecom" }, - { 5, "FO", "Faroe Island", "Faroese Telecom" }, - { 7, "EE", "Estonia", "Eesti Mobiiltelefon" }, - { 5, "LV", "Latvia", "Latvian Mobile Telephone" }, - { 8, "LT", "Lithuania", "COMLIET" }, - { 6, "BY", "Belarus", "Belcel" }, - { 5, "MO", "OSS/Moscow", "Moscow Cellular Comm." }, - { 6, "STP", "OSS/St Petersburg", "Delta Telecom" }, - { 6, "STP", "OSS/Leningrads Dist.", "Delta Telecom" }, - { 7, "CAR", "OSS/Carelian Rep.", "Telecom Finland" }, - { 5, "MUR", "OSS/Murmansk", "Telecom Finland" }, - { 5, "LED", "OSS/Leningrads Dist.", "Telecom Finland" }, - { 5, "KAL", "Kaliningrad", "Telecom Finland" }, - { 7, "PL", "Poland", "CENTERTEL" }, - { 6, "BG", "Bulgaria", "MOBIFON" }, - { 5, "RO", "Romania", "Telefonica Romania" }, - { 6, "UA", "Ukraine", "Ukraine Mobile Comm." }, - { 1, "RU1", "", "" }, - { 2, "RU2", "", "" }, - { 3, "RU3", "", "" }, - { 4, "RU4", "", "" }, - { 4, "RU4", "", "" }, - { -1, "NULL", "", "" }, - { 0, NULL, NULL, NULL } -}; - -void nmt_country_list(void) -{ - int i; - - printf("TA\tShort\tCountry (Provider)\n"); - printf("------------------------------------------------------------------------\n"); - for (i = 0; nmt_country[i].short_name; i++) { - if (nmt_country[i].long_name[0]) - printf("%d\t%s\t%s (%s)\n", nmt_country[i].y, nmt_country[i].short_name, nmt_country[i].long_name, nmt_country[i].provider_name); - else - printf("%d\t%s\n", nmt_country[i].y, nmt_country[i].short_name); - } -} - -uint8_t nmt_country_by_short_name(const char *short_name) -{ - int i; - - for (i = 0; nmt_country[i].short_name; i++) { - if (!strcasecmp(nmt_country[i].short_name, short_name)) - return nmt_country[i].y; - } - - return 0; -} - static void nmt_timeout(struct timer *timer); /* Create transceiver instance and link to a list. */ -int nmt_create(int channel, enum nmt_chan_type chan_type, const char *audiodev, int use_sdr, int samplerate, double rx_gain, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, uint8_t ms_power, uint8_t traffic_area, uint8_t area_no, int compandor, int supervisory, const char *smsc_number, int send_callerid, int loopback) +int nmt_create(const char *country, int channel, enum nmt_chan_type chan_type, const char *audiodev, int use_sdr, int samplerate, double rx_gain, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, uint8_t ms_power, uint8_t traffic_area, uint8_t area_no, int compandor, int supervisory, const char *smsc_number, int send_callerid, int loopback) { nmt_t *nmt; int rc; + double deviation_factor; + int scandinavia; + int tested; - if (channel < 1 || channel > 399) { - PDEBUG(DNMT, DEBUG_ERROR, "Channel number %d invalid.\n", channel); + /* check channel matching and set deviation factor */ + if (nmt_channel2freq(country, channel, 0, &deviation_factor, &scandinavia, &tested) == 0.0) { + PDEBUG(DNMT, DEBUG_NOTICE, "Channel number %d invalid, use '-Y list' to get a list of available channels.\n", channel); return -EINVAL; } - if (channel >= 201) { + if (!tested) { + PDEBUG(DNMT, DEBUG_NOTICE, "*** The given NMT country has not been tested yet. Please tell the Author, if it works.\n"); + } + + if (scandinavia && channel >= 201) { PDEBUG(DNMT, DEBUG_NOTICE, "*** Channels numbers above 200 have been specified, but never used. These 'interleaved channels are probably not supports by the phone.\n"); } - if (channel >= 181 && channel <= 200) { + if (scandinavia && channel >= 181 && channel <= 200) { PDEBUG(DNMT, DEBUG_NOTICE, "Extended channel numbers (181..200) have been specified, but never been supported for sure. There is no phone to test with, so don't use it!\n"); } @@ -349,7 +270,7 @@ int nmt_create(int channel, enum nmt_chan_type chan_type, const char *audiodev, PDEBUG(DNMT, DEBUG_DEBUG, "Creating 'NMT' instance for channel = %d (sample rate %d).\n", channel, samplerate); /* init general part of transceiver */ - rc = sender_create(&nmt->sender, channel, nmt_channel2freq(channel, 0), nmt_channel2freq(channel, 1), audiodev, use_sdr, samplerate, rx_gain, pre_emphasis, de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, loopback, 0, PAGING_SIGNAL_NONE); + rc = sender_create(&nmt->sender, channel, nmt_channel2freq(country, channel, 0, NULL, NULL, NULL), nmt_channel2freq(country, channel, 1, NULL, NULL, NULL), audiodev, use_sdr, samplerate, rx_gain, pre_emphasis, de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, loopback, 0, PAGING_SIGNAL_NONE); if (rc < 0) { PDEBUG(DNMT, DEBUG_ERROR, "Failed to init transceiver process!\n"); goto error; @@ -366,7 +287,7 @@ int nmt_create(int channel, enum nmt_chan_type chan_type, const char *audiodev, strncpy(nmt->smsc_number, smsc_number, sizeof(nmt->smsc_number) - 1); /* init audio processing */ - rc = dsp_init_sender(nmt); + rc = dsp_init_sender(nmt, deviation_factor); if (rc < 0) { PDEBUG(DNMT, DEBUG_ERROR, "Failed to init audio processing!\n"); goto error; @@ -390,7 +311,9 @@ int nmt_create(int channel, enum nmt_chan_type chan_type, const char *audiodev, nmt_go_idle(nmt); PDEBUG(DNMT, DEBUG_NOTICE, "Created channel #%d of type '%s' = %s\n", channel, chan_type_short_name(chan_type), chan_type_long_name(chan_type)); - PDEBUG(DNMT, DEBUG_NOTICE, " -> Using traffic area %d,%d and area no %d\n", traffic_area >> 4, (traffic_area & 0xf) % 10, area_no); + if (nmt_long_name_by_short_name(country)) + PDEBUG(DNMT, DEBUG_NOTICE, " -> Using country '%s'\n", nmt_long_name_by_short_name(country)); + PDEBUG(DNMT, DEBUG_NOTICE, " -> Using traffic area %d,%d and area no %d\n", traffic_area >> 4, traffic_area & 0xf, area_no); if (nmt->supervisory) PDEBUG(DNMT, DEBUG_NOTICE, " -> Using supervisory signal %d\n", supervisory); else @@ -721,13 +644,16 @@ static void rx_idle(nmt_t *nmt, frame_t *frame) memset(&subscr, 0, sizeof(subscr)); nmt_value2digits(frame->ms_country, &subscr.country, 1); nmt_value2digits(frame->ms_number, subscr.number, 6); + + PDEBUG_CHAN(DNMT, DEBUG_INFO, "Received roaming seizure from subscriber %c,%s\n", subscr.country, subscr.number); + + /* create transaction */ trans = create_transaction(&subscr); if (!trans) { PDEBUG(DNMT, DEBUG_NOTICE, "Failed to create transaction!\n"); break; } - PDEBUG_CHAN(DNMT, DEBUG_INFO, "Received roaming seizure from subscriber %c,%s\n", subscr.country, subscr.number); /* change state */ nmt->trans = trans; /* add transaction before state change, so status is shown correctly */ nmt_new_state(nmt, STATE_ROAMING_IDENT); @@ -747,13 +673,16 @@ static void rx_idle(nmt_t *nmt, frame_t *frame) nmt_value2digits(frame->ms_number, subscr.number, 6); if (frame->mt == NMT_MESSAGE_12) subscr.coinbox = 1; + + PDEBUG_CHAN(DNMT, DEBUG_INFO, "Received call from subscriber %c,%s%s\n", subscr.country, subscr.number, (subscr.coinbox) ? " (coinbox)" : ""); + + /* create transaction */ trans = create_transaction(&subscr); if (!trans) { PDEBUG(DNMT, DEBUG_NOTICE, "Failed to create transaction!\n"); break; } - PDEBUG_CHAN(DNMT, DEBUG_INFO, "Received call from subscriber %c,%s%s\n", subscr.country, subscr.number, (subscr.coinbox) ? " (coinbox)" : ""); /* change state */ nmt->trans = trans; /* add transaction before state change, so status is shown correctly */ nmt_new_state(nmt, STATE_MO_IDENT); diff --git a/src/nmt/nmt.h b/src/nmt/nmt.h index 84a7fd2..36f4f3b 100644 --- a/src/nmt/nmt.h +++ b/src/nmt/nmt.h @@ -141,10 +141,7 @@ void nmt_channel_list(void); int nmt_channel_by_short_name(const char *short_name); const char *chan_type_short_name(enum nmt_chan_type chan_type); const char *chan_type_long_name(enum nmt_chan_type chan_type); -double nmt_channel2freq(int channel, int uplink); -void nmt_country_list(void); -uint8_t nmt_country_by_short_name(const char *short_name); -int nmt_create(int channel, enum nmt_chan_type chan_type, const char *audiodev, int use_sdr, int samplerate, double rx_gain, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, uint8_t ms_power, uint8_t traffic_area, uint8_t area_no, int compandor, int supervisory, const char *smsc_number, int send_callerid, int loopback); +int nmt_create(const char *country, int channel, enum nmt_chan_type chan_type, const char *audiodev, int use_sdr, int samplerate, double rx_gain, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, uint8_t ms_power, uint8_t traffic_area, uint8_t area_no, int compandor, int supervisory, const char *smsc_number, int send_callerid, int loopback); void nmt_check_channels(void); void nmt_destroy(sender_t *sender); void nmt_go_idle(nmt_t *nmt); -- cgit v1.2.3