NMT 450: Support for other European counties, like Belgium, Czech, Slovakia
This commit is contained in:
parent
dbdedfe1a1
commit
50b2021d21
|
@ -5,6 +5,7 @@ bin_PROGRAMS = \
|
|||
|
||||
nmt_SOURCES = \
|
||||
nmt.c \
|
||||
countries.c \
|
||||
transaction.c \
|
||||
dsp.c \
|
||||
frame.c \
|
||||
|
|
|
@ -0,0 +1,224 @@
|
|||
/* NMT country settings
|
||||
*
|
||||
* (C) 2017 by Andreas Eversberg <jolly@eversberg.eu>
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 <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 <area no> | 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') {
|
||||
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';
|
||||
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, "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();
|
||||
|
|
125
src/nmt/nmt.c
125
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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue