NMT-900 System implementation
NMT can now be run as 450 or 900 Network.
This commit is contained in:
parent
0c9de251be
commit
3274812eab
|
@ -541,22 +541,21 @@ Setup of a base station
|
|||
|
||||
<p>
|
||||
Before running the base station, you need to select a network.
|
||||
The network is defined by the system (NMT-450 or NMT-900) and the Traffic Area (TA).
|
||||
The NMT-450 is default.
|
||||
To make the phone access the network, it needs to have the same network selected.
|
||||
Check out what networks are available:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
|
||||
# nmt -Y list
|
||||
TA Short Country (Provider)
|
||||
------------------------------------------------------------------------
|
||||
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)
|
||||
# nmt -N 450 -Y list
|
||||
TA from TA to YY Code Channels Short Country (Provider)
|
||||
--------------------------------------------------------------------------------
|
||||
DK,1 DK,9 51..59 1-399 Denmark (Tele Danmark Mobile)
|
||||
SE,1 SE,9 61..69 1-399 Sweden (Telia Mobitel)
|
||||
NO,1 NO,9 71..79 1-399 Norway (Telenor Mobil)
|
||||
FI,1 FI,9 81..89 1-399 Finland (Telecom Finland)
|
||||
...
|
||||
|
||||
</pre>
|
||||
|
|
|
@ -32,7 +32,7 @@ struct nmt_frequency {
|
|||
};
|
||||
|
||||
/* channel allocation used in scandinavian countries */
|
||||
static struct nmt_frequency frq_scandinavia[] = {
|
||||
static struct nmt_frequency frq_450_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 },
|
||||
|
@ -40,45 +40,69 @@ static struct nmt_frequency frq_scandinavia[] = {
|
|||
{ 0, 0, 0.0, 0.0, 0.0, 0.0, 0 }
|
||||
};
|
||||
|
||||
static struct nmt_frequency frq_900_scandinavia[] = {
|
||||
{ 1, 1000, 935.0125, 0.025, 1.0, 45.0, 0 },
|
||||
{ 1025,2023, 935.025, 0.025, 1.0, 45.0, 0 },
|
||||
{ 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[] = {
|
||||
static struct nmt_frequency frq_450_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 }
|
||||
};
|
||||
|
||||
static struct nmt_frequency frq_900_nl[] = {
|
||||
{ 1, 1000, 935.0125, 0.025, 1.0, 45.0, 0 },
|
||||
{ 0, 0, 0.0, 0.0, 0.0, 0.0, 0 }
|
||||
};
|
||||
|
||||
/* channel allocation used in Malaysia */
|
||||
static struct nmt_frequency frq_mal[] = {
|
||||
static struct nmt_frequency frq_450_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[] = {
|
||||
static struct nmt_frequency frq_450_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[] = {
|
||||
static struct nmt_frequency frq_450_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[] = {
|
||||
static struct nmt_frequency frq_450_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[] = {
|
||||
static struct nmt_frequency frq_450_cz_sk[] = {
|
||||
{ 1, 222, 465.730, -0.020, 0.8, 10.0, 0 },
|
||||
{ 0, 0, 0.0, 0.0, 0.0, 0.0, 0 }
|
||||
};
|
||||
|
||||
/* channel allocation used in Turkey */
|
||||
static struct nmt_frequency frq_900_tr[] = {
|
||||
{ 1, 180, 461.500, 0.025, 1.0, 10.0, 0 },
|
||||
{ 0, 0, 0.0, 0.0, 0.0, 0.0, 0 }
|
||||
};
|
||||
|
||||
/* channel allocation used in France */
|
||||
static struct nmt_frequency frq_900_f[] = {
|
||||
{ 1, 540, 430.050, 0.025, 1.0, -10.0, 0 },
|
||||
{ 0, 0, 0.0, 0.0, 0.0, 0.0, 0 }
|
||||
};
|
||||
|
||||
/* country selector */
|
||||
static struct nmt_country {
|
||||
int tested;
|
||||
int system; /* 450 or 900 */
|
||||
int tested; /* tested with a real phone */
|
||||
int y; /* country code of traffic area */
|
||||
int first_ta, last_ta; /* range of used traffic areas */
|
||||
const char *short_name;
|
||||
|
@ -86,47 +110,64 @@ static struct nmt_country {
|
|||
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 },
|
||||
{ 1, 1, 1,9, "NL", "Netherlands", "Royal Dutch Post & Telecom", frq_nl_l_b },
|
||||
{ 1, 1, 15,15, "L", "Luxemburg", "Enterprise des P&T Luxembourg",frq_nl_l_b },
|
||||
{ 1, 2, 1,9, "B", "Belgium", "Belgacom Mobile", frq_nl_l_b },
|
||||
{ 1, 7, 1,9, "CZ", "Czech Republic", "Eurotel Prague", frq_cz_sk },
|
||||
{ 1, 6, 1,9, "SK", "Slovakia", "Eurotel Bratislava", frq_cz_sk },
|
||||
/* 450 */
|
||||
{ 450, 1, 5, 1,9, "DK", "Denmark", "Tele Danmark Mobile", frq_450_scandinavia },
|
||||
{ 450, 1, 6, 1,9, "SE", "Sweden", "Telia Mobitel", frq_450_scandinavia },
|
||||
{ 450, 1, 7, 1,9, "NO", "Norway", "Telenor Mobil", frq_450_scandinavia },
|
||||
{ 450, 1, 8, 1,9, "FI", "Finland", "Telecom Finland", frq_450_scandinavia },
|
||||
{ 450, 1, 8, 1,9, "IS", "Iceland", "Post & Telecom", frq_450_scandinavia },
|
||||
{ 450, 1, 5, 1,9, "FO", "Faroe Island", "Faroese Telecom", frq_450_scandinavia },
|
||||
{ 450, 1, 7, 1,9, "EE", "Estonia", "Eesti Mobiiltelefon", frq_450_scandinavia },
|
||||
{ 450, 1, 5, 1,9, "LV", "Latvia", "Latvian Mobile Telephone", frq_450_scandinavia },
|
||||
{ 450, 1, 8, 1,9, "LT", "Lithuania", "COMLIET", frq_450_scandinavia },
|
||||
{ 450, 1, 6, 1,9, "BY", "Belarus", "Belcel", frq_450_scandinavia },
|
||||
{ 450, 1, 5, 1,9, "MO", "OSS/Moscow", "Moscow Cellular Comm.", frq_450_scandinavia },
|
||||
{ 450, 1, 6, 1,9, "STP", "OSS/St Petersburg", "Delta Telecom", frq_450_scandinavia },
|
||||
{ 450, 1, 6, 1,9, "STP", "OSS/Leningrads Dist.", "Delta Telecom", frq_450_scandinavia },
|
||||
{ 450, 1, 7, 1,9, "CAR", "OSS/Carelian Rep.", "Telecom Finland", frq_450_scandinavia },
|
||||
{ 450, 1, 5, 1,9, "MUR", "OSS/Murmansk", "Telecom Finland", frq_450_scandinavia },
|
||||
{ 450, 1, 5, 1,9, "LED", "OSS/Leningrads Dist.", "Telecom Finland", frq_450_scandinavia },
|
||||
{ 450, 1, 5, 1,9, "KAL", "Kaliningrad", "Telecom Finland", frq_450_scandinavia },
|
||||
{ 450, 1, 7, 1,9, "PL", "Poland", "CENTERTEL", frq_450_scandinavia },
|
||||
{ 450, 1, 6, 1,9, "BG", "Bulgaria", "MOBIFON", frq_450_scandinavia },
|
||||
{ 450, 1, 5, 1,9, "RO", "Romania", "Telefonica Romania", frq_450_scandinavia },
|
||||
{ 450, 1, 6, 1,9, "UA", "Ukraine", "Ukraine Mobile Comm.", frq_450_scandinavia },
|
||||
{ 450, 1, 1, 1,9, "RU1", "", "", frq_450_scandinavia },
|
||||
{ 450, 1, 2, 1,9, "RU2", "", "", frq_450_scandinavia },
|
||||
{ 450, 1, 3, 1,9, "RU3", "", "", frq_450_scandinavia },
|
||||
{ 450, 1, 4, 1,9, "RU4", "", "", frq_450_scandinavia },
|
||||
{ 450, 1, 1, 1,9, "NL", "Netherlands", "Royal Dutch Post & Telecom", frq_450_nl_l_b },
|
||||
{ 450, 1, 1, 15,15, "L", "Luxemburg", "Enterprise des P&T Luxembourg",frq_450_nl_l_b },
|
||||
{ 450, 1, 2, 1,9, "B", "Belgium", "Belgacom Mobile", frq_450_nl_l_b },
|
||||
{ 450, 1, 7, 1,9, "CZ", "Czech Republic", "Eurotel Prague", frq_450_cz_sk },
|
||||
{ 450, 1, 6, 1,9, "SK", "Slovakia", "Eurotel Bratislava", frq_450_cz_sk },
|
||||
/* 900 */
|
||||
{ 900, 1, 1, 1,9, "DK", "Denmark", "Tele Danmark Mobile", frq_900_scandinavia },
|
||||
{ 900, 1, 2, 1,9, "SE", "Sweden", "Telia Mobitel", frq_900_scandinavia },
|
||||
{ 900, 1, 3, 1,9, "NO", "Norway", "Telenor Mobil", frq_900_scandinavia },
|
||||
{ 900, 1, 4, 1,9, "FI", "Finland", "Telecom Finland", frq_900_scandinavia },
|
||||
/* untested... */
|
||||
{ 0, 8, 8,8, "MAL", "Malaysia", "Jabatan Telekom Malaysia", frq_mal },
|
||||
{ 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 },
|
||||
{ 0, 0, 0,0, NULL, NULL, NULL, NULL }
|
||||
{ 450, 0, 8, 8,8, "MAL", "Malaysia", "Jabatan Telekom Malaysia", frq_450_mal },
|
||||
{ 450, 0, 4, 1,9, "T", "Thailand", "Telephone Organization of Thailand",frq_450_t_ri },
|
||||
{ 450, 0, 8, 1,9, "E", "Spain", "Telefonica Servicios Moviles", frq_450_e },
|
||||
{ 450, 0, 8, 1,1, "RI", "Indonesia", "PT Mobisel", frq_450_t_ri },
|
||||
{ 450, 0, 0, 1,3, "A", "Austria", "PTV", frq_450_a },
|
||||
{ 450, 0, 9, 1,3, "A2", "Austria 2", "PTV", frq_450_a },
|
||||
{ 900, 0, 5, 1,9, "CH", "Switzerland", "PTT", frq_900_scandinavia },
|
||||
{ 900, 0, 6, 1,15, "NL", "Netherlands", "Royal Dutch Post & Telecom", frq_900_nl },
|
||||
{ 900, 0, 1, 1,9, "TR", "Turkey", "Turkcell", frq_900_tr },
|
||||
{ 900, 0, 0, 1,9, "F0", "France (Group 0)", "France Telecom", frq_900_f },
|
||||
{ 900, 0, 1, 1,9, "F1", "France (Group 1)", "France Telecom", frq_900_f },
|
||||
{ 900, 0, 2, 1,9, "F2", "France (Group 2)", "France Telecom", frq_900_f },
|
||||
{ 900, 0, 3, 1,9, "F3", "France (Group 3)", "France Telecom", frq_900_f },
|
||||
{ 900, 0, 4, 1,9, "F4", "France (Group 4)", "France Telecom", frq_900_f },
|
||||
{ 900, 0, 5, 1,9, "F5", "France (Group 5)", "France Telecom", frq_900_f },
|
||||
{ 900, 0, 6, 1,9, "F6", "France (Group 6)", "France Telecom", frq_900_f },
|
||||
{ 900, 0, 7, 1,9, "F7", "France (Group 7)", "France Telecom", frq_900_f },
|
||||
{ 0,0, 0, 0,0, NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
void nmt_country_list(void)
|
||||
void nmt_country_list(int nmt_system)
|
||||
{
|
||||
int i, j;
|
||||
int ch_from = 0, ch_to = 0;
|
||||
|
@ -135,6 +176,8 @@ void nmt_country_list(void)
|
|||
printf("TA from\tTA to\tYY Code\tChannels\tShort\tCountry (Provider)\n");
|
||||
printf("--------------------------------------------------------------------------------\n");
|
||||
for (i = 0; nmt_country[i].short_name; i++) {
|
||||
if (nmt_system != nmt_country[i].system)
|
||||
continue;
|
||||
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);
|
||||
|
@ -155,11 +198,13 @@ void nmt_country_list(void)
|
|||
}
|
||||
}
|
||||
|
||||
int nmt_country_by_short_name(const char *short_name)
|
||||
int nmt_country_by_short_name(int nmt_system, const char *short_name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; nmt_country[i].short_name; i++) {
|
||||
if (nmt_system != nmt_country[i].system)
|
||||
continue;
|
||||
if (!strcasecmp(nmt_country[i].short_name, short_name))
|
||||
return nmt_country[i].y;
|
||||
}
|
||||
|
@ -167,11 +212,13 @@ int nmt_country_by_short_name(const char *short_name)
|
|||
return -1;
|
||||
}
|
||||
|
||||
const char *nmt_long_name_by_short_name(const char *short_name)
|
||||
const char *nmt_long_name_by_short_name(int nmt_system, const char *short_name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; nmt_country[i].short_name; i++) {
|
||||
if (nmt_system != nmt_country[i].system)
|
||||
continue;
|
||||
if (!strcasecmp(nmt_country[i].short_name, short_name))
|
||||
return nmt_country[i].long_name;
|
||||
}
|
||||
|
@ -179,11 +226,13 @@ const char *nmt_long_name_by_short_name(const char *short_name)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int nmt_ta_by_short_name(const char *short_name, int ta)
|
||||
int nmt_ta_by_short_name(int nmt_system, const char *short_name, int ta)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; nmt_country[i].short_name; i++) {
|
||||
if (nmt_system != nmt_country[i].system)
|
||||
continue;
|
||||
if (!strcasecmp(nmt_country[i].short_name, short_name) && ta >= nmt_country[i].first_ta && ta <= nmt_country[i].last_ta)
|
||||
return ta;
|
||||
}
|
||||
|
@ -193,12 +242,14 @@ int nmt_ta_by_short_name(const char *short_name, int ta)
|
|||
|
||||
/* 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)
|
||||
double nmt_channel2freq(int nmt_system, 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 (nmt_system != nmt_country[i].system)
|
||||
continue;
|
||||
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
|
||||
|
|
|
@ -1,7 +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);
|
||||
void nmt_country_list(int nmt_system);
|
||||
int nmt_country_by_short_name(int nmt_system, const char *short_name);
|
||||
const char *nmt_long_name_by_short_name(int nmt_system, const char *short_name);
|
||||
int nmt_ta_by_short_name(int nmt_system, const char *short_name, int ta);
|
||||
double nmt_channel2freq(int nmt_system, const char *short_name, int channel, int uplink, double *deviation_factor, int *scandinavia, int *tested);
|
||||
|
||||
|
|
279
src/nmt/frame.c
279
src/nmt/frame.c
|
@ -29,41 +29,116 @@
|
|||
#include "frame.h"
|
||||
#include "hagelbarger.h"
|
||||
|
||||
uint64_t nmt_encode_channel(int channel, int power)
|
||||
uint64_t nmt_encode_channel(int nmt_system, int channel, int power)
|
||||
{
|
||||
uint64_t value = 0;
|
||||
|
||||
if (channel >= 200) {
|
||||
value |= 0x800;
|
||||
channel -= 200;
|
||||
if (nmt_system == 450) {
|
||||
if (channel >= 200) {
|
||||
value |= 0x800;
|
||||
channel -= 200;
|
||||
}
|
||||
if (channel >= 100) {
|
||||
value |= 0x100;
|
||||
channel -= 100;
|
||||
}
|
||||
value |= channel % 10;
|
||||
value |= (channel / 10) << 4;
|
||||
value |= power << 9;
|
||||
} else {
|
||||
/* interleaved channels are indicated in traffic area */
|
||||
if (value > 1000)
|
||||
value -= 1000;
|
||||
value |= channel;
|
||||
/* if channel >= 512, set upper bit */
|
||||
if (value & 0x200)
|
||||
value = value - 0x200 + 0x800;
|
||||
value |= power << 9;
|
||||
}
|
||||
if (channel >= 100) {
|
||||
value |= 0x100;
|
||||
channel -= 100;
|
||||
}
|
||||
value |= channel % 10;
|
||||
value |= (channel / 10) << 4;
|
||||
value |= power << 9;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
int nmt_decode_channel(uint64_t value, int *channel, int *power)
|
||||
int nmt_decode_channel(int nmt_system, uint64_t value, int *channel, int *power)
|
||||
{
|
||||
if ((value & 0x00f) > 0x009)
|
||||
return -1;
|
||||
if ((value & 0x0f0) > 0x090)
|
||||
return -1;
|
||||
if (nmt_system == 450) {
|
||||
if ((value & 0x00f) > 0x009)
|
||||
return -1;
|
||||
if ((value & 0x0f0) > 0x090)
|
||||
return -1;
|
||||
|
||||
*channel = (value & 0x00f) +
|
||||
((value & 0x0f0) >> 4) * 10 +
|
||||
((value & 0x100) >> 8) * 100 +
|
||||
((value & 0x800) >> 11) * 200;
|
||||
*channel = (value & 0x00f) +
|
||||
((value & 0x0f0) >> 4) * 10 +
|
||||
((value & 0x100) >> 8) * 100 +
|
||||
((value & 0x800) >> 11) * 200;
|
||||
} else {
|
||||
*channel = (value & 0x1ff) +
|
||||
((value & 0x800) >> 2);
|
||||
}
|
||||
*power = (value & 0x600) >> 9;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t nmt_encode_tc(int nmt_system, int channel, int power)
|
||||
{
|
||||
uint64_t value = 0;
|
||||
|
||||
if (nmt_system == 450) {
|
||||
if (channel >= 200) {
|
||||
value |= 0x800;
|
||||
channel -= 200;
|
||||
}
|
||||
if (channel >= 100) {
|
||||
value |= 0x100;
|
||||
channel -= 100;
|
||||
}
|
||||
value |= channel % 10;
|
||||
value |= (channel / 10) << 4;
|
||||
value |= power << 9;
|
||||
} else {
|
||||
value = channel;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static int nmt_decode_tc(int nmt_system, uint64_t value, int *channel, int *power)
|
||||
{
|
||||
if (nmt_system == 450) {
|
||||
if ((value & 0x00f) > 0x009)
|
||||
return -1;
|
||||
if ((value & 0x0f0) > 0x090)
|
||||
return -1;
|
||||
|
||||
*channel = (value & 0x00f) +
|
||||
((value & 0x0f0) >> 4) * 10 +
|
||||
((value & 0x100) >> 8) * 100 +
|
||||
((value & 0x800) >> 11) * 200;
|
||||
*power = (value & 0x600) >> 9;
|
||||
} else {
|
||||
*channel = value & 0x3ff;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint64_t nmt_encode_traffic_area(int nmt_system, int channel, uint8_t traffic_area)
|
||||
{
|
||||
uint64_t value = 0;
|
||||
|
||||
if (nmt_system == 450) {
|
||||
value = traffic_area;
|
||||
} else {
|
||||
/* upper bit is used for indication of interleaved channel */
|
||||
value = traffic_area & 0x7f;
|
||||
if (channel > 1000)
|
||||
value |= 0x80;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
void nmt_value2digits(uint64_t value, char *digits, int num)
|
||||
{
|
||||
int digit, i;
|
||||
|
@ -214,24 +289,30 @@ static struct nmt_frame {
|
|||
} nmt_frame[] = {
|
||||
/* Define Digits Dir. Prefix Nr. Description */
|
||||
{ NMT_MESSAGE_1a, "NNNPYYHHHHHHHHHH", MTX_TO_MS, 12, "1a", "Calling channel indication" },
|
||||
{ NMT_MESSAGE_1a_a, "NNNPYYHHHHHHHHHH", MTX_TO_MS, 11, "1a'", "Calling channel indication (for MS group A)" },
|
||||
{ NMT_MESSAGE_1a_b, "NNNPYYHHHHHHHHHH", MTX_TO_MS, 13, "1a''", "Calling channel indication (for MS group B)" },
|
||||
{ NMT_MESSAGE_1b, "NNNPYYHHHHHHHHHH", MTX_TO_MS, 4, "1b", "Combined calling and traffic channel indication" },
|
||||
{ NMT_MESSAGE_2a, "NNNPYYZXXXXXXHHH", MTX_TO_MS, 12, "2a", "Call to mobile subscriber on calling channel" },
|
||||
{ NMT_MESSAGE_2b, "NNNPYYZXXXXXXnnn", MTX_TO_MS, 12, "2b", "Traffic channel allocation on calling channel" },
|
||||
{ NMT_MESSAGE_2c, "NNNPYYZXXXXXXHHH", MTX_TO_MS, 12, "2c", "Queueing information to MS with priority on calling channel" },
|
||||
{ NMT_MESSAGE_2d, "NNNPYYZXXXXXXHHH", MTX_TO_MS, 12, "2d", "Traffic channel scanning order on calling channel" },
|
||||
{ NMT_MESSAGE_2e, "NNNPYYZXXXXXXHHH", MTX_TO_MS, 4, "2e", "Alternative type of call to MS on combinded CC/TC" },
|
||||
{ NMT_MESSAGE_2f, "NNNPYYZXXXXXXHHH", MTX_TO_MS, 12, "2f", "Queuing information to ordinary MS" },
|
||||
{ NMT_MESSAGE_3a, "NNNPYYZXXXXXXnnn", MTX_TO_MS, 5, "3a", "Traffic channel allocation on traffic channel" },
|
||||
{ NMT_MESSAGE_3b, "NNNPYYZXXXXXXHHH", MTX_TO_MS, 5, "3b", "Identity request on traffic channel" },
|
||||
{ NMT_MESSAGE_3c, "NNNPYYZXXXXXXnnn", MTX_TO_MS, 9, "3c", "Traffic channel allocation on traffic channel, short procedure" },
|
||||
{ NMT_MESSAGE_3d, "NNNPYYZXXXXXXnnn", MTX_TO_MS, 7, "3d", "Traffic channel allocation on access channel" },
|
||||
{ NMT_MESSAGE_4, "NNNPYYJJJJJJJHHH", MTX_TO_MS, 3, "4", "Free traffic channel indication" },
|
||||
{ NMT_MESSAGE_4b, "NNNPYYJJJJJJJHHH", MTX_TO_MS, 7, "4b", "Access channel indication" },
|
||||
{ NMT_MESSAGE_5a, "NNNPYYZXXXXXXLLL", MTX_TO_MS, 6, "5a", "Line signal" },
|
||||
{ NMT_MESSAGE_5b, "NNNPYYZXXXXXXLQQ", MTX_TO_MS, 6, "5b", "Line signal: Answer to coin-box" },
|
||||
{ NMT_MESSAGE_6, "JJJPJJJJJJJJJJJJ", MTX_TO_XX, 0, "6", "Idle frame" },
|
||||
{ NMT_MESSAGE_7, "NNNPYYCCCCCCCJJJ", MTX_TO_MS, 8, "7", "Authentication request" },
|
||||
{ NMT_MESSAGE_8, "NNNPYYMHHHHHHHWW", MTX_TO_MS, 1, "8", "A-subscriber number" },
|
||||
{ NMT_MESSAGE_10a, "NNNPZXXXXXXTJJJJ", MS_TO_MTX, 1, "10a", "Call acknowledgment from MS on calling channel (shortened frame)" },
|
||||
{ NMT_MESSAGE_10a, "NNNPZXXXXXXTJJJJ", MS_TO_MTX, 1, "10a", "Call acknowledgment from MS on calling channel and access on access channel (shortened frame)" },
|
||||
{ NMT_MESSAGE_10b, "NNNPZXXXXXXTYKKK", MS_TO_MTX, 1, "10b", "Seizure from ordinary MS and identity on traffic channel" },
|
||||
{ NMT_MESSAGE_10c, "NNNPZXXXXXXTYKKK", MS_TO_MTX, 6, "10c", "Seizure and identity from called MS on traffic channel" },
|
||||
{ NMT_MESSAGE_10d, "NNNPZXXXXXXTJJJJ", MS_TO_MTX, 6, "10c", "Call acknowledgement from MS on the alternative type of call on combined CC/TC (shortened frame)" },
|
||||
{ NMT_MESSAGE_11a, "NNNPZXXXXXXTYKKK", MS_TO_MTX, 14, "11a", "Roaming updating seizure and identity on traffic channel" },
|
||||
{ NMT_MESSAGE_11b, "NNNPZXXXXXXTYKKK", MS_TO_MTX, 15, "11b", "Seizure and call achnowledgment on calling channel from MS with priority (shortened frame)" },
|
||||
{ NMT_MESSAGE_12, "NNNPZXXXXXXTYKKK", MS_TO_MTX, 11, "12", "Seizure from coin-box on traffic channel" },
|
||||
|
@ -288,12 +369,12 @@ static const char *param_hex(uint64_t value, int __attribute__((unused)) ndigits
|
|||
return result;
|
||||
}
|
||||
|
||||
static const char *param_channel_no(uint64_t value, int __attribute__((unused)) ndigits, enum nmt_direction __attribute__((unused)) direction)
|
||||
static const char *param_channel_no_450(uint64_t value, int __attribute__((unused)) ndigits, enum nmt_direction __attribute__((unused)) direction)
|
||||
{
|
||||
static char result[32];
|
||||
int rc, channel, power;
|
||||
|
||||
rc = nmt_decode_channel(value, &channel, &power);
|
||||
rc = nmt_decode_channel(450, value, &channel, &power);
|
||||
if (rc < 0)
|
||||
sprintf(result, "invalid(%" PRIu64 ")", value);
|
||||
else
|
||||
|
@ -302,6 +383,48 @@ static const char *param_channel_no(uint64_t value, int __attribute__((unused))
|
|||
return result;
|
||||
}
|
||||
|
||||
static const char *param_channel_no_900(uint64_t value, int __attribute__((unused)) ndigits, enum nmt_direction __attribute__((unused)) direction)
|
||||
{
|
||||
static char result[32];
|
||||
int rc, channel, power;
|
||||
|
||||
rc = nmt_decode_channel(900, value, &channel, &power);
|
||||
if (rc < 0)
|
||||
sprintf(result, "invalid(%" PRIu64 ")", value);
|
||||
else
|
||||
sprintf(result, "channel=%d power=%d", channel, power);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char *param_tc_no_450(uint64_t value, int __attribute__((unused)) ndigits, enum nmt_direction __attribute__((unused)) direction)
|
||||
{
|
||||
static char result[32];
|
||||
int rc, channel, power;
|
||||
|
||||
rc = nmt_decode_tc(450, value, &channel, &power);
|
||||
if (rc < 0)
|
||||
sprintf(result, "invalid(%" PRIu64 ")", value);
|
||||
else
|
||||
sprintf(result, "channel=%d power=%d", channel, power);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char *param_tc_no_900(uint64_t value, int __attribute__((unused)) ndigits, enum nmt_direction __attribute__((unused)) direction)
|
||||
{
|
||||
static char result[32];
|
||||
int rc, channel;
|
||||
|
||||
rc = nmt_decode_tc(900, value, &channel, NULL);
|
||||
if (rc < 0)
|
||||
sprintf(result, "invalid(%" PRIu64 ")", value);
|
||||
else
|
||||
sprintf(result, "channel=%d", channel);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char *param_country(uint64_t value, int __attribute__((unused)) ndigits, enum nmt_direction __attribute__((unused)) direction)
|
||||
{
|
||||
static char result[32];
|
||||
|
@ -310,7 +433,7 @@ static const char *param_country(uint64_t value, int __attribute__((unused)) ndi
|
|||
case 0:
|
||||
return "no additional info";
|
||||
case 1:
|
||||
return "Netherlands / Luxemburg / Malaysia";
|
||||
return "Netherlands / Luxemburg / Malaysia / Switzerland";
|
||||
case 2:
|
||||
return "Belgium";
|
||||
case 4:
|
||||
|
@ -347,7 +470,7 @@ static const char *param_number(uint64_t value, int ndigits, enum nmt_direction
|
|||
return result;
|
||||
}
|
||||
|
||||
static const char *param_ta(uint64_t value, int ndigits, enum nmt_direction __attribute__((unused)) direction)
|
||||
static const char *param_ta_450(uint64_t value, int ndigits, enum nmt_direction __attribute__((unused)) direction)
|
||||
{
|
||||
static char result[32];
|
||||
|
||||
|
@ -357,6 +480,18 @@ static const char *param_ta(uint64_t value, int ndigits, enum nmt_direction __at
|
|||
return result;
|
||||
}
|
||||
|
||||
static const char *param_ta_900(uint64_t value, int __attribute__((unused)) ndigits, enum nmt_direction __attribute__((unused)) direction)
|
||||
{
|
||||
static char result[32];
|
||||
|
||||
if ((value & 0x80))
|
||||
sprintf(result, "%" PRIu64 " (Channel No. + 1000)", value & 0x7f);
|
||||
else
|
||||
sprintf(result, "%" PRIu64, value);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static const char *param_line_signal(uint64_t value, int __attribute__((unused)) ndigits, enum nmt_direction direction)
|
||||
{
|
||||
char *desc = "Spare";
|
||||
|
@ -477,34 +612,38 @@ static const char *param_password(uint64_t value, int ndigits, enum nmt_directio
|
|||
}
|
||||
|
||||
static struct nmt_parameter {
|
||||
int system;
|
||||
char digit;
|
||||
const char *description;
|
||||
const char *(*decoder)(uint64_t value, int ndigits, enum nmt_direction direction);
|
||||
} nmt_parameter[] = {
|
||||
{ 'N', "Channel No.", param_channel_no },
|
||||
{ 'n', "TC No.", param_channel_no },
|
||||
{ 'Y', "Traffic area", param_ta },
|
||||
{ 'Z', "Mobile subscriber country", param_country },
|
||||
{ 'X', "Mobile subscriber No.", param_number },
|
||||
{ 'Q', "Tariff class", param_integer },
|
||||
{ 'L', "Line signal", param_line_signal },
|
||||
{ 'S', "Digit signals", param_digit },
|
||||
{ 'J', "Idle information", param_hex },
|
||||
{ 'A', "Channel activation", param_hex },
|
||||
{ 'V', "Management order", param_hex },
|
||||
{ 'r', "Measurement results", param_hex },
|
||||
{ 'P', "Prefix", param_integer },
|
||||
{ 'f', "Supervisory signal", param_supervisory },
|
||||
{ 'K', "Mobile subscriber password", param_password },
|
||||
{ 'T', "Area info", param_hex },
|
||||
{ 'H', "Additional info", param_hex },
|
||||
{ 'C', "Random challenge", param_hex },
|
||||
{ 'R', "Signed response", param_hex },
|
||||
{ 'l', "Limit strength evaluation", param_hex },
|
||||
{ 'c', "c", param_hex },
|
||||
{ 'M', "Sequence Number", param_integer },
|
||||
{ 'W', "Checksum", param_hex },
|
||||
{ 0, NULL, NULL }
|
||||
{ 450, 'N', "Channel No.", param_channel_no_450 },
|
||||
{ 900, 'N', "Channel No.", param_channel_no_900 },
|
||||
{ 450, 'n', "TC No.", param_tc_no_450 },
|
||||
{ 900, 'n', "TC No.", param_tc_no_900 },
|
||||
{ 450, 'Y', "Traffic area", param_ta_450 },
|
||||
{ 900, 'Y', "Traffic area", param_ta_900 },
|
||||
{ 0, 'Z', "Mobile subscriber country", param_country },
|
||||
{ 0, 'X', "Mobile subscriber No.", param_number },
|
||||
{ 0, 'Q', "Tariff class", param_integer },
|
||||
{ 0, 'L', "Line signal", param_line_signal },
|
||||
{ 0, 'S', "Digit signals", param_digit },
|
||||
{ 0, 'J', "Idle information", param_hex },
|
||||
{ 0, 'A', "Channel activation", param_hex },
|
||||
{ 0, 'V', "Management order", param_hex },
|
||||
{ 0, 'r', "Measurement results", param_hex },
|
||||
{ 0, 'P', "Prefix", param_integer },
|
||||
{ 0, 'f', "Supervisory signal", param_supervisory },
|
||||
{ 0, 'K', "Mobile subscriber password", param_password },
|
||||
{ 0, 'T', "Area info", param_hex },
|
||||
{ 0, 'H', "Additional info", param_hex },
|
||||
{ 0, 'C', "Random challenge", param_hex },
|
||||
{ 0, 'R', "Signed response", param_hex },
|
||||
{ 0, 'l', "Limit strength evaluation", param_hex },
|
||||
{ 0, 'c', "c", param_hex },
|
||||
{ 0, 'M', "Sequence Number", param_integer },
|
||||
{ 0, 'W', "Checksum", param_hex },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
/* Depending on P-value, direction and additional info, frame index (used for
|
||||
|
@ -582,7 +721,16 @@ enum nmt_mt decode_frame_mt(const uint8_t *digits, enum nmt_direction direction,
|
|||
return NMT_MESSAGE_21b;
|
||||
return NMT_MESSAGE_4;
|
||||
case 4:
|
||||
return NMT_MESSAGE_1b;
|
||||
switch((digits[13] << 8) + (digits[14] << 4) + digits[15]) {
|
||||
case 0x3f3:
|
||||
case 0x3f4:
|
||||
case 0x3f5:
|
||||
case 0x3f6:
|
||||
case 0x000:
|
||||
return NMT_MESSAGE_2e;
|
||||
default:
|
||||
return NMT_MESSAGE_1b;
|
||||
}
|
||||
case 5:
|
||||
if (digits[6] == 15)
|
||||
return NMT_MESSAGE_21c;
|
||||
|
@ -601,7 +749,16 @@ enum nmt_mt decode_frame_mt(const uint8_t *digits, enum nmt_direction direction,
|
|||
return NMT_MESSAGE_5b;
|
||||
return NMT_MESSAGE_5a;
|
||||
case 7:
|
||||
break;
|
||||
switch((digits[13] << 8) + (digits[14] << 4) + digits[15]) {
|
||||
case 0x3f3:
|
||||
case 0x3f4:
|
||||
case 0x3f5:
|
||||
case 0x3f6:
|
||||
case 0x000:
|
||||
return NMT_MESSAGE_4b;
|
||||
default:
|
||||
return NMT_MESSAGE_3d;
|
||||
}
|
||||
case 8:
|
||||
return NMT_MESSAGE_7;
|
||||
case 9:
|
||||
|
@ -609,7 +766,7 @@ enum nmt_mt decode_frame_mt(const uint8_t *digits, enum nmt_direction direction,
|
|||
case 10:
|
||||
return NMT_MESSAGE_30;
|
||||
case 11:
|
||||
break;
|
||||
return NMT_MESSAGE_1a_a;
|
||||
case 12:
|
||||
/* no subscriber */
|
||||
if (digits[6] == 0)
|
||||
|
@ -637,7 +794,7 @@ enum nmt_mt decode_frame_mt(const uint8_t *digits, enum nmt_direction direction,
|
|||
return NMT_MESSAGE_2b;
|
||||
}
|
||||
case 13:
|
||||
break;
|
||||
return NMT_MESSAGE_1a_b;
|
||||
case 14:
|
||||
if (digits[13] != 15)
|
||||
break;
|
||||
|
@ -697,7 +854,7 @@ int init_frame(void)
|
|||
}
|
||||
|
||||
/* decode 16 digits frame */
|
||||
static void disassemble_frame(frame_t *frame, const uint8_t *digits, enum nmt_direction direction, int callack)
|
||||
static void disassemble_frame(int nmt_system, frame_t *frame, const uint8_t *digits, enum nmt_direction direction, int callack)
|
||||
{
|
||||
enum nmt_mt mt;
|
||||
int i, j, ndigits;
|
||||
|
@ -804,6 +961,8 @@ static void disassemble_frame(frame_t *frame, const uint8_t *digits, enum nmt_di
|
|||
}
|
||||
if (debuglevel <= DEBUG_DEBUG) {
|
||||
for (j = 0; nmt_parameter[j].digit; j++) {
|
||||
if (nmt_parameter[j].system != 0 && nmt_parameter[j].system != nmt_system)
|
||||
continue;
|
||||
if (nmt_parameter[j].digit == digit) {
|
||||
PDEBUG(DFRAME, DEBUG_DEBUG, " %c: %s\n", digit, nmt_parameter[j].decoder(value, ndigits, direction));
|
||||
}
|
||||
|
@ -823,7 +982,7 @@ static void disassemble_frame(frame_t *frame, const uint8_t *digits, enum nmt_di
|
|||
}
|
||||
|
||||
/* encode 16 digits frame */
|
||||
static void assemble_frame(frame_t *frame, uint8_t *digits, int debug)
|
||||
static void assemble_frame(int nmt_system, frame_t *frame, uint8_t *digits, int debug)
|
||||
{
|
||||
enum nmt_mt mt;
|
||||
int i, j;
|
||||
|
@ -956,6 +1115,8 @@ static void assemble_frame(frame_t *frame, uint8_t *digits, int debug)
|
|||
i++;
|
||||
}
|
||||
for (j = 0; nmt_parameter[j].digit; j++) {
|
||||
if (nmt_parameter[j].system != 0 && nmt_parameter[j].system != nmt_system)
|
||||
continue;
|
||||
if (nmt_parameter[j].digit == digit) {
|
||||
PDEBUG(DFRAME, DEBUG_DEBUG, " %c: %s\n", digit, nmt_parameter[j].decoder(value, ndigits, direction));
|
||||
}
|
||||
|
@ -973,13 +1134,13 @@ static void assemble_frame(frame_t *frame, uint8_t *digits, int debug)
|
|||
/* encode frame to bits
|
||||
* debug can be turned on or off
|
||||
*/
|
||||
const char *encode_frame(frame_t *frame, int debug)
|
||||
const char *encode_frame(int nmt_system, frame_t *frame, int debug)
|
||||
{
|
||||
uint8_t digits[16], message[9], code[18];
|
||||
static char bits[166];
|
||||
int i;
|
||||
|
||||
assemble_frame(frame, digits, debug);
|
||||
assemble_frame(nmt_system, frame, digits, debug);
|
||||
|
||||
/* hagelbarger code */
|
||||
message[8] = 0x00;
|
||||
|
@ -994,7 +1155,7 @@ const char *encode_frame(frame_t *frame, int debug)
|
|||
}
|
||||
|
||||
/* decode bits to frame */
|
||||
int decode_frame(frame_t *frame, const char *bits, enum nmt_direction direction, int callack)
|
||||
int decode_frame(int nmt_system, frame_t *frame, const char *bits, enum nmt_direction direction, int callack)
|
||||
{
|
||||
uint8_t digits[16], message[8], code[19];
|
||||
int i;
|
||||
|
@ -1009,7 +1170,7 @@ int decode_frame(frame_t *frame, const char *bits, enum nmt_direction direction,
|
|||
digits[i * 2 + 1] = message[i] & 0x0f;
|
||||
}
|
||||
|
||||
disassemble_frame(frame, digits, direction, callack);
|
||||
disassemble_frame(nmt_system, frame, digits, direction, callack);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1,16 +1,21 @@
|
|||
|
||||
enum nmt_mt {
|
||||
NMT_MESSAGE_1a = 0,
|
||||
NMT_MESSAGE_1a_a,
|
||||
NMT_MESSAGE_1a_b,
|
||||
NMT_MESSAGE_1b,
|
||||
NMT_MESSAGE_2a,
|
||||
NMT_MESSAGE_2b,
|
||||
NMT_MESSAGE_2c,
|
||||
NMT_MESSAGE_2d,
|
||||
NMT_MESSAGE_2e,
|
||||
NMT_MESSAGE_2f,
|
||||
NMT_MESSAGE_3a,
|
||||
NMT_MESSAGE_3b,
|
||||
NMT_MESSAGE_3c,
|
||||
NMT_MESSAGE_3d,
|
||||
NMT_MESSAGE_4,
|
||||
NMT_MESSAGE_4b,
|
||||
NMT_MESSAGE_5a,
|
||||
NMT_MESSAGE_5b,
|
||||
NMT_MESSAGE_6,
|
||||
|
@ -19,6 +24,7 @@ enum nmt_mt {
|
|||
NMT_MESSAGE_10a,
|
||||
NMT_MESSAGE_10b,
|
||||
NMT_MESSAGE_10c,
|
||||
NMT_MESSAGE_10d,
|
||||
NMT_MESSAGE_11a,
|
||||
NMT_MESSAGE_11b,
|
||||
NMT_MESSAGE_12,
|
||||
|
@ -77,8 +83,10 @@ typedef struct frame {
|
|||
|
||||
int init_frame(void);
|
||||
|
||||
uint64_t nmt_encode_channel(int channel, int power);
|
||||
int nmt_decode_channel(uint64_t value, int *channel, int *power);
|
||||
uint64_t nmt_encode_channel(int nmt_system, int channel, int power);
|
||||
int nmt_decode_channel(int nmt_system, uint64_t value, int *channel, int *power);
|
||||
uint64_t nmt_encode_tc(int nmt_system, int channel, int power);
|
||||
uint64_t nmt_encode_traffic_area(int nmt_system, int channel, uint8_t traffic_area);
|
||||
void nmt_value2digits(uint64_t value, char *digits, int num);
|
||||
uint64_t nmt_digits2value(const char *digits, int num);
|
||||
char nmt_value2digit(uint64_t value);
|
||||
|
@ -86,6 +94,6 @@ uint16_t nmt_encode_area_no(uint8_t area_no);
|
|||
|
||||
const char *nmt_frame_name(enum nmt_mt mt);
|
||||
|
||||
const char *encode_frame(frame_t *frame, int debug);
|
||||
int decode_frame(frame_t *frame, const char *bits, enum nmt_direction direction, int callack);
|
||||
const char *encode_frame(int nmt_system, frame_t *frame, int debug);
|
||||
int decode_frame(int nmt_system, frame_t *frame, const char *bits, enum nmt_direction direction, int callack);
|
||||
|
||||
|
|
|
@ -44,9 +44,10 @@
|
|||
static int sms_deliver_fd = -1;
|
||||
|
||||
/* settings */
|
||||
int nmt_system = 450;
|
||||
int num_chan_type = 0;
|
||||
enum nmt_chan_type chan_type[MAX_SENDER] = { CHAN_TYPE_CC_TC };
|
||||
int ms_power = 1; /* 1..3 */
|
||||
int ms_power = 1; /* 0..3 */
|
||||
char country[16] = "";
|
||||
char traffic_area[3] = "";
|
||||
char area_no = 0;
|
||||
|
@ -58,13 +59,19 @@ int send_callerid = 0;
|
|||
|
||||
void print_help(const char *arg0)
|
||||
{
|
||||
print_help_common(arg0, "-Y <traffic area> | list [-I 1] [-0 1] ");
|
||||
print_help_common(arg0, "[-N 900] -Y <traffic area> | list [-I 1] [-0 1] ");
|
||||
/* - - */
|
||||
printf(" -N --nmt-system 450/900\n");
|
||||
printf(" Give NMT type as first paramer. (default = '%d')\n", nmt_system);
|
||||
printf(" Note: This option must be given at first!\n");
|
||||
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(" Give channel type, use 'list' to get a list. (default = '%s')\n", chan_type_short_name(nmt_system, chan_type[0]));
|
||||
printf(" -P --ms-power <power level>\n");
|
||||
printf(" Give power level of the mobile station 1..3. (default = '%d')\n", ms_power);
|
||||
printf(" 3 = 15 W / 7 W (handheld), 2 = 1.5 W, 1 = 150 mW\n");
|
||||
printf(" Give power level of the mobile station 0..3. (default = '%d')\n", ms_power);
|
||||
if (nmt_system == 450)
|
||||
printf(" NMT-450: 3 = 15 W / 7 W (handheld), 2 = 1.5 W, 1/0 = 150 mW\n");
|
||||
else
|
||||
printf(" NMT-900: 3/2 = 6 W, 1 = 1.5 W, 0 = 150 mW\n");
|
||||
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");
|
||||
|
@ -97,6 +104,7 @@ static int handle_options(int argc, char **argv)
|
|||
int skip_args = 0;
|
||||
|
||||
static struct option long_options_special[] = {
|
||||
{"nmt-system", 1, 0, 'N'},
|
||||
{"channel-type", 1, 0, 'T'},
|
||||
{"ms-power", 1, 0, 'P'},
|
||||
{"traffic-area", 1, 0, 'Y'},
|
||||
|
@ -108,10 +116,11 @@ static int handle_options(int argc, char **argv)
|
|||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
set_options_common("T:P:Y:A:C:0:S:I:", long_options_special);
|
||||
set_options_common("N:T:P:Y:A:C:0:S:I:", long_options_special);
|
||||
|
||||
while (1) {
|
||||
int option_index = 0, c, rc;
|
||||
static int first_option = 1;
|
||||
|
||||
c = getopt_long(argc, argv, optstring, long_options, &option_index);
|
||||
|
||||
|
@ -119,12 +128,26 @@ static int handle_options(int argc, char **argv)
|
|||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'T':
|
||||
if (!strcmp(optarg, "list")) {
|
||||
nmt_channel_list();
|
||||
case 'N':
|
||||
nmt_system = atoi(optarg);
|
||||
if (nmt_system != 450 && nmt_system != 900) {
|
||||
fprintf(stderr, "Error, NMT system type '%s' unknown. Please use '-N 450' for NMT-450 or '-N 900' for NMT-900.\n", optarg);
|
||||
exit(0);
|
||||
}
|
||||
rc = nmt_channel_by_short_name(optarg);
|
||||
if (nmt_system == 900)
|
||||
ms_power = 0;
|
||||
if (!first_option) {
|
||||
fprintf(stderr, "Please specify the NMT system (-N) as first command line option!\n");
|
||||
exit(0);
|
||||
}
|
||||
skip_args += 2;
|
||||
break;
|
||||
case 'T':
|
||||
if (!strcmp(optarg, "list")) {
|
||||
nmt_channel_list(nmt_system);
|
||||
exit(0);
|
||||
}
|
||||
rc = nmt_channel_by_short_name(nmt_system, optarg);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Error, channel type '%s' unknown. Please use '-t list' to get a list. I suggest to use the default.\n", optarg);
|
||||
exit(0);
|
||||
|
@ -136,14 +159,14 @@ static int handle_options(int argc, char **argv)
|
|||
ms_power = atoi(optarg);
|
||||
if (ms_power > 3)
|
||||
ms_power = 3;
|
||||
if (ms_power < 1)
|
||||
ms_power = 1;
|
||||
if (ms_power < 0)
|
||||
ms_power = 0;
|
||||
skip_args += 2;
|
||||
break;
|
||||
case 'Y':
|
||||
|
||||
if (!strcmp(optarg, "list")) {
|
||||
nmt_country_list();
|
||||
nmt_country_list(nmt_system);
|
||||
exit(0);
|
||||
}
|
||||
/* digits */
|
||||
|
@ -155,7 +178,7 @@ static int handle_options(int argc, char **argv)
|
|||
exit(0);
|
||||
}
|
||||
*p++ = '\0';
|
||||
rc = nmt_country_by_short_name(country);
|
||||
rc = nmt_country_by_short_name(nmt_system, country);
|
||||
if (rc < 0) {
|
||||
error_ta:
|
||||
fprintf(stderr, "Invalid traffic area '%s', use '-Y list' for a list of valid areas\n", optarg);
|
||||
|
@ -163,7 +186,7 @@ error_ta:
|
|||
}
|
||||
traffic_area[0] = rc + '0';
|
||||
if (p[strlen(p) - 1] != '!') {
|
||||
rc = nmt_ta_by_short_name(country, atoi(p));
|
||||
rc = nmt_ta_by_short_name(nmt_system, country, atoi(p));
|
||||
if (rc < 0)
|
||||
goto error_ta;
|
||||
}
|
||||
|
@ -203,6 +226,7 @@ error_ta:
|
|||
default:
|
||||
opt_switch_common(c, argv[0], &skip_args);
|
||||
}
|
||||
first_option = 0;
|
||||
}
|
||||
|
||||
free(long_options);
|
||||
|
@ -378,15 +402,15 @@ int main(int argc, char *argv[])
|
|||
|
||||
/* create transceiver instance */
|
||||
for (i = 0; i < num_kanal; i++) {
|
||||
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, read_tx_wave, ms_power, nmt_digits2value(traffic_area, 2), area_no, compandor, supervisory[i], smsc_number, send_callerid, loopback);
|
||||
rc = nmt_create(nmt_system, 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, read_tx_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;
|
||||
}
|
||||
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);
|
||||
printf("base station on channel %d ready, please tune transmitter to %.4f MHz and receiver to %.4f MHz.\n", kanal[i], nmt_channel2freq(nmt_system, country, kanal[i], 0, NULL, NULL, NULL) / 1e6, nmt_channel2freq(nmt_system, country, kanal[i], 1, NULL, NULL, NULL) / 1e6);
|
||||
}
|
||||
|
||||
nmt_check_channels();
|
||||
nmt_check_channels(nmt_system);
|
||||
|
||||
main_common(&quit, latency, interval, myhandler, station_id, 7);
|
||||
|
||||
|
|
141
src/nmt/nmt.c
141
src/nmt/nmt.c
|
@ -119,7 +119,7 @@ void nmt_display_status(void)
|
|||
display_status_start();
|
||||
for (sender = sender_head; sender; sender = sender->next) {
|
||||
nmt = (nmt_t *) sender;
|
||||
display_status_channel(nmt->sender.kanal, chan_type_short_name(nmt->sysinfo.chan_type), nmt_state_name(nmt->state));
|
||||
display_status_channel(nmt->sender.kanal, chan_type_short_name(nmt->sysinfo.system, nmt->sysinfo.chan_type), nmt_state_name(nmt->state));
|
||||
if (nmt->trans)
|
||||
display_status_subscriber(nmt->trans->subscriber.number, NULL);
|
||||
}
|
||||
|
@ -136,32 +136,41 @@ static void nmt_new_state(nmt_t *nmt, enum nmt_state new_state)
|
|||
}
|
||||
|
||||
static struct nmt_channels {
|
||||
int system;
|
||||
enum nmt_chan_type chan_type;
|
||||
const char *short_name;
|
||||
const char *long_name;
|
||||
} nmt_channels[] = {
|
||||
{ CHAN_TYPE_CC, "CC", "calling channel (incomming calls)" },
|
||||
{ CHAN_TYPE_TC, "TC", "traffic channel (outgoing calls)" },
|
||||
{ CHAN_TYPE_CC_TC, "CC/TC","combined calling & traffic channel (both way calls)" },
|
||||
{ CHAN_TYPE_TEST, "TEST", "test channel" },
|
||||
{ 0, NULL, NULL }
|
||||
{ 0, CHAN_TYPE_CC, "CC", "calling channel (incomming calls)" },
|
||||
{ 900, CHAN_TYPE_CCA, "CCA", "calling channel for group A mobiles with odd secret key (incomming calls)" },
|
||||
{ 900, CHAN_TYPE_CCB, "CCB", "calling channel for group B mobiles with even secret key (incomming calls)" },
|
||||
{ 0, CHAN_TYPE_TC, "TC", "traffic channel (outgoing calls)" },
|
||||
{ 900, CHAN_TYPE_AC_TC, "AC/TC","combined access & traffic channel (outgoing calls)" },
|
||||
{ 0, CHAN_TYPE_CC_TC, "CC/TC","combined calling & traffic channel (both way calls)" },
|
||||
{ 0, CHAN_TYPE_TEST, "TEST", "test channel" },
|
||||
{ 0, 0, NULL, NULL }
|
||||
};
|
||||
|
||||
void nmt_channel_list(void)
|
||||
void nmt_channel_list(int nmt_system)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("Type\tDescription\n");
|
||||
printf("------------------------------------------------------------------------\n");
|
||||
for (i = 0; nmt_channels[i].long_name; i++)
|
||||
for (i = 0; nmt_channels[i].long_name; i++) {
|
||||
if (nmt_channels[i].system != 0 && nmt_channels[i].system != nmt_system)
|
||||
continue;
|
||||
printf("%s\t%s\n", nmt_channels[i].short_name, nmt_channels[i].long_name);
|
||||
}
|
||||
}
|
||||
|
||||
int nmt_channel_by_short_name(const char *short_name)
|
||||
int nmt_channel_by_short_name(int nmt_system, const char *short_name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; nmt_channels[i].short_name; i++) {
|
||||
if (nmt_channels[i].system != 0 && nmt_channels[i].system != nmt_system)
|
||||
continue;
|
||||
if (!strcasecmp(nmt_channels[i].short_name, short_name))
|
||||
return nmt_channels[i].chan_type;
|
||||
}
|
||||
|
@ -169,11 +178,13 @@ int nmt_channel_by_short_name(const char *short_name)
|
|||
return -1;
|
||||
}
|
||||
|
||||
const char *chan_type_short_name(enum nmt_chan_type chan_type)
|
||||
const char *chan_type_short_name(int nmt_system, enum nmt_chan_type chan_type)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; nmt_channels[i].short_name; i++) {
|
||||
if (nmt_channels[i].system != 0 && nmt_channels[i].system != nmt_system)
|
||||
continue;
|
||||
if (nmt_channels[i].chan_type == chan_type)
|
||||
return nmt_channels[i].short_name;
|
||||
}
|
||||
|
@ -181,11 +192,13 @@ const char *chan_type_short_name(enum nmt_chan_type chan_type)
|
|||
return "invalid";
|
||||
}
|
||||
|
||||
const char *chan_type_long_name(enum nmt_chan_type chan_type)
|
||||
const char *chan_type_long_name(int nmt_system, enum nmt_chan_type chan_type)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; nmt_channels[i].long_name; i++) {
|
||||
if (nmt_channels[i].system != 0 && nmt_channels[i].system != nmt_system)
|
||||
continue;
|
||||
if (nmt_channels[i].chan_type == chan_type)
|
||||
return nmt_channels[i].long_name;
|
||||
}
|
||||
|
@ -231,7 +244,7 @@ static int dialstring2number(const char *dialstring, char *ms_country, char *ms_
|
|||
static void nmt_timeout(struct timer *timer);
|
||||
|
||||
/* Create transceiver instance and link to a list. */
|
||||
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, const char *read_tx_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(int nmt_system, 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, const char *read_tx_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;
|
||||
|
@ -240,7 +253,7 @@ int nmt_create(const char *country, int channel, enum nmt_chan_type chan_type, c
|
|||
int tested;
|
||||
|
||||
/* check channel matching and set deviation factor */
|
||||
if (nmt_channel2freq(country, channel, 0, &deviation_factor, &scandinavia, &tested) == 0.0) {
|
||||
if (nmt_channel2freq(nmt_system, 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;
|
||||
}
|
||||
|
@ -270,13 +283,14 @@ int nmt_create(const char *country, int channel, enum nmt_chan_type chan_type, c
|
|||
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(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, read_tx_wave, loopback, 0, PAGING_SIGNAL_NONE);
|
||||
rc = sender_create(&nmt->sender, channel, nmt_channel2freq(nmt_system, country, channel, 0, NULL, NULL, NULL), nmt_channel2freq(nmt_system, 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, read_tx_wave, loopback, 0, PAGING_SIGNAL_NONE);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DNMT, DEBUG_ERROR, "Failed to init transceiver process!\n");
|
||||
goto error;
|
||||
}
|
||||
|
||||
timer_init(&nmt->timer, nmt_timeout, nmt);
|
||||
nmt->sysinfo.system = nmt_system;
|
||||
nmt->sysinfo.chan_type = chan_type;
|
||||
nmt->sysinfo.ms_power = ms_power;
|
||||
nmt->sysinfo.traffic_area = traffic_area;
|
||||
|
@ -310,9 +324,9 @@ int nmt_create(const char *country, int channel, enum nmt_chan_type chan_type, c
|
|||
/* go into idle state */
|
||||
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));
|
||||
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, "Created channel #%d of type '%s' = %s\n", channel, chan_type_short_name(nmt_system, chan_type), chan_type_long_name(nmt_system, chan_type));
|
||||
if (nmt_long_name_by_short_name(nmt_system, country))
|
||||
PDEBUG(DNMT, DEBUG_NOTICE, " -> Using country '%s'\n", nmt_long_name_by_short_name(nmt_system, 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);
|
||||
|
@ -327,32 +341,64 @@ error:
|
|||
return rc;
|
||||
}
|
||||
|
||||
void nmt_check_channels(void)
|
||||
void nmt_check_channels(int __attribute__((unused)) nmt_system)
|
||||
{
|
||||
sender_t *sender;
|
||||
nmt_t *nmt;
|
||||
int cc = 0, tc = 0;
|
||||
int cca = 0, ccb = 0, tc = 0;
|
||||
int note = 0;
|
||||
|
||||
for (sender = sender_head; sender; sender = sender->next) {
|
||||
nmt = (nmt_t *) sender;
|
||||
if (nmt->sysinfo.chan_type == CHAN_TYPE_CC)
|
||||
cc = 1;
|
||||
if (nmt->sysinfo.chan_type == CHAN_TYPE_CC) {
|
||||
cca = 1;
|
||||
ccb = 1;
|
||||
}
|
||||
if (nmt->sysinfo.chan_type == CHAN_TYPE_CCA)
|
||||
cca = 1;
|
||||
if (nmt->sysinfo.chan_type == CHAN_TYPE_CCB)
|
||||
ccb = 1;
|
||||
if (nmt->sysinfo.chan_type == CHAN_TYPE_TC)
|
||||
tc = 1;
|
||||
if (nmt->sysinfo.chan_type == CHAN_TYPE_AC_TC)
|
||||
tc = 1;
|
||||
if (nmt->sysinfo.chan_type == CHAN_TYPE_CC_TC) {
|
||||
cc = 1;
|
||||
cca = 1;
|
||||
ccb = 1;
|
||||
tc = 1;
|
||||
}
|
||||
}
|
||||
if (cc && !tc) {
|
||||
if ((cca || ccb) && !tc) {
|
||||
if (note)
|
||||
PDEBUG(DNMT, DEBUG_NOTICE, "\n");
|
||||
PDEBUG(DNMT, DEBUG_NOTICE, "*** Selected channel(s) can be used for calling only.\n");
|
||||
PDEBUG(DNMT, DEBUG_NOTICE, "*** No call from the mobile phone is possible on this channel.\n");
|
||||
PDEBUG(DNMT, DEBUG_NOTICE, "*** Use combined 'CC/TC' instead!\n");
|
||||
note = 1;
|
||||
}
|
||||
if (tc && !cc) {
|
||||
if (tc && !(cca || ccb)) {
|
||||
if (note)
|
||||
PDEBUG(DNMT, DEBUG_NOTICE, "\n");
|
||||
PDEBUG(DNMT, DEBUG_NOTICE, "*** Selected channel(s) can be used for traffic only.\n");
|
||||
PDEBUG(DNMT, DEBUG_NOTICE, "*** No call to the mobile phone is possible on this channel.\n");
|
||||
PDEBUG(DNMT, DEBUG_NOTICE, "*** Use combined 'CC/TC' instead!\n");
|
||||
note = 1;
|
||||
}
|
||||
if (cca && !ccb) {
|
||||
if (note)
|
||||
PDEBUG(DNMT, DEBUG_NOTICE, "\n");
|
||||
PDEBUG(DNMT, DEBUG_NOTICE, "*** Selected channel(s) can be used for calling of MS type A only.\n");
|
||||
PDEBUG(DNMT, DEBUG_NOTICE, "*** No call from the MS type B phone is possible on this channel.\n");
|
||||
PDEBUG(DNMT, DEBUG_NOTICE, "*** Use combined 'CC' or 'CC/TC' instead!\n");
|
||||
note = 1;
|
||||
}
|
||||
if (!cca && ccb) {
|
||||
if (note)
|
||||
PDEBUG(DNMT, DEBUG_NOTICE, "\n");
|
||||
PDEBUG(DNMT, DEBUG_NOTICE, "*** Selected channel(s) can be used for calling of MS type B only.\n");
|
||||
PDEBUG(DNMT, DEBUG_NOTICE, "*** No call from the MS type A phone is possible on this channel.\n");
|
||||
PDEBUG(DNMT, DEBUG_NOTICE, "*** Use combined 'CC' or 'CC/TC' instead!\n");
|
||||
note = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -378,7 +424,7 @@ void nmt_go_idle(nmt_t *nmt)
|
|||
dms_reset(nmt);
|
||||
sms_reset(nmt);
|
||||
|
||||
PDEBUG_CHAN(DNMT, DEBUG_INFO, "Entering IDLE state, sending idle frames on %s.\n", chan_type_long_name(nmt->sysinfo.chan_type));
|
||||
PDEBUG_CHAN(DNMT, DEBUG_INFO, "Entering IDLE state, sending idle frames on %s.\n", chan_type_long_name(nmt->sysinfo.system, nmt->sysinfo.chan_type));
|
||||
nmt->trans = NULL; /* remove transaction before state change, so status is shown correctly */
|
||||
nmt_new_state(nmt, STATE_IDLE);
|
||||
nmt_set_dsp_mode(nmt, DSP_MODE_FRAME);
|
||||
|
@ -446,8 +492,8 @@ static int match_channel(nmt_t *nmt, frame_t *frame)
|
|||
int channel, power;
|
||||
|
||||
/* check channel match */
|
||||
nmt_decode_channel(frame->channel_no, &channel, &power);
|
||||
if (channel != nmt->sender.kanal) {
|
||||
nmt_decode_channel(nmt->sysinfo.system, frame->channel_no, &channel, &power);
|
||||
if ((channel & 0x3ff) != (nmt->sender.kanal & 0x3ff)) {
|
||||
PDEBUG_CHAN(DNMT, DEBUG_NOTICE, "Frame for different channel %d received, ignoring.\n", channel);
|
||||
return 0;
|
||||
}
|
||||
|
@ -505,8 +551,8 @@ static void tx_ident(nmt_t *nmt, frame_t *frame)
|
|||
transaction_t *trans = nmt->trans;
|
||||
|
||||
frame->mt = NMT_MESSAGE_3b;
|
||||
frame->channel_no = nmt_encode_channel(nmt->sender.kanal, nmt->sysinfo.ms_power);
|
||||
frame->traffic_area = nmt->sysinfo.traffic_area;
|
||||
frame->channel_no = nmt_encode_channel(nmt->sysinfo.system, nmt->sender.kanal, nmt->sysinfo.ms_power);
|
||||
frame->traffic_area = nmt_encode_traffic_area(nmt->sysinfo.system, nmt->sender.kanal, nmt->sysinfo.traffic_area);
|
||||
frame->ms_country = nmt_digits2value(&trans->subscriber.country, 1);
|
||||
frame->ms_number = nmt_digits2value(trans->subscriber.number, 6);
|
||||
frame->additional_info = nmt_encode_area_no(nmt->sysinfo.area_no);
|
||||
|
@ -517,8 +563,8 @@ static void set_line_signal(nmt_t *nmt, frame_t *frame, uint8_t signal)
|
|||
transaction_t *trans = nmt->trans;
|
||||
|
||||
frame->mt = NMT_MESSAGE_5a;
|
||||
frame->channel_no = nmt_encode_channel(nmt->sender.kanal, nmt->sysinfo.ms_power);
|
||||
frame->traffic_area = nmt->sysinfo.traffic_area;
|
||||
frame->channel_no = nmt_encode_channel(nmt->sysinfo.system, nmt->sender.kanal, nmt->sysinfo.ms_power);
|
||||
frame->traffic_area = nmt_encode_traffic_area(nmt->sysinfo.system, nmt->sender.kanal, nmt->sysinfo.traffic_area);
|
||||
frame->ms_country = nmt_digits2value(&trans->subscriber.country, 1);
|
||||
frame->ms_number = nmt_digits2value(trans->subscriber.number, 6);
|
||||
frame->line_signal = (signal << 8) | (signal << 4) | signal;
|
||||
|
@ -547,8 +593,8 @@ static int encode_a_number(nmt_t *nmt, frame_t *frame, int index, enum number_ty
|
|||
|
||||
/* encode */
|
||||
frame->mt = NMT_MESSAGE_8;
|
||||
frame->channel_no = nmt_encode_channel(nmt->sender.kanal, nmt->sysinfo.ms_power);
|
||||
frame->traffic_area = nmt->sysinfo.traffic_area;
|
||||
frame->channel_no = nmt_encode_channel(nmt->sysinfo.system, nmt->sender.kanal, nmt->sysinfo.ms_power);
|
||||
frame->traffic_area = nmt_encode_traffic_area(nmt->sysinfo.system, nmt->sender.kanal, nmt->sysinfo.traffic_area);
|
||||
frame->seq_number = index;
|
||||
if (index == 0) {
|
||||
/* number type */
|
||||
|
@ -614,9 +660,18 @@ static void tx_idle(nmt_t *nmt, frame_t *frame)
|
|||
case CHAN_TYPE_CC:
|
||||
frame->mt = NMT_MESSAGE_1a;
|
||||
break;
|
||||
case CHAN_TYPE_CCA:
|
||||
frame->mt = NMT_MESSAGE_1a_a;
|
||||
break;
|
||||
case CHAN_TYPE_CCB:
|
||||
frame->mt = NMT_MESSAGE_1a_b;
|
||||
break;
|
||||
case CHAN_TYPE_TC:
|
||||
frame->mt = NMT_MESSAGE_4;
|
||||
break;
|
||||
case CHAN_TYPE_AC_TC:
|
||||
frame->mt = NMT_MESSAGE_4b;
|
||||
break;
|
||||
case CHAN_TYPE_CC_TC:
|
||||
frame->mt = NMT_MESSAGE_1b;
|
||||
break;
|
||||
|
@ -624,8 +679,8 @@ static void tx_idle(nmt_t *nmt, frame_t *frame)
|
|||
frame->mt = NMT_MESSAGE_30;
|
||||
break;
|
||||
}
|
||||
frame->channel_no = nmt_encode_channel(nmt->sender.kanal, nmt->sysinfo.ms_power);
|
||||
frame->traffic_area = nmt->sysinfo.traffic_area;
|
||||
frame->channel_no = nmt_encode_channel(nmt->sysinfo.system, nmt->sender.kanal, nmt->sysinfo.ms_power);
|
||||
frame->traffic_area = nmt_encode_traffic_area(nmt->sysinfo.system, nmt->sender.kanal, nmt->sysinfo.traffic_area);
|
||||
frame->additional_info = nmt_encode_area_no(nmt->sysinfo.area_no);
|
||||
}
|
||||
|
||||
|
@ -663,6 +718,7 @@ static void rx_idle(nmt_t *nmt, frame_t *frame)
|
|||
break;
|
||||
case NMT_MESSAGE_10b: /* seizure from ordinary MS */
|
||||
case NMT_MESSAGE_12: /* seizure from coinbox MS */
|
||||
case NMT_MESSAGE_10a: /* access signal */
|
||||
if (!match_channel(nmt, frame))
|
||||
break;
|
||||
if (!match_area(nmt, frame))
|
||||
|
@ -973,8 +1029,8 @@ static void tx_mt_paging(nmt_t *nmt, frame_t *frame)
|
|||
transaction_t *trans = nmt->trans;
|
||||
|
||||
frame->mt = NMT_MESSAGE_2a;
|
||||
frame->channel_no = nmt_encode_channel(nmt->sender.kanal, nmt->sysinfo.ms_power);
|
||||
frame->traffic_area = nmt->sysinfo.traffic_area;
|
||||
frame->channel_no = nmt_encode_channel(nmt->sysinfo.system, nmt->sender.kanal, nmt->sysinfo.ms_power);
|
||||
frame->traffic_area = nmt_encode_traffic_area(nmt->sysinfo.system, nmt->sender.kanal, nmt->sysinfo.traffic_area);
|
||||
frame->ms_country = nmt_digits2value(&trans->subscriber.country, 1);
|
||||
frame->ms_number = nmt_digits2value(trans->subscriber.number, 6);
|
||||
frame->additional_info = nmt_encode_area_no(nmt->sysinfo.area_no);
|
||||
|
@ -1004,6 +1060,7 @@ static void rx_mt_paging(nmt_t *nmt, frame_t *frame)
|
|||
|
||||
switch (frame->mt) {
|
||||
case NMT_MESSAGE_10a: /* call acknowledgment */
|
||||
case NMT_MESSAGE_10d: /* call ack on alternate type */
|
||||
if (!match_channel(nmt, frame))
|
||||
break;
|
||||
if (!match_subscriber(trans, frame))
|
||||
|
@ -1034,11 +1091,11 @@ static void tx_mt_channel(nmt_t *nmt, frame_t *frame)
|
|||
transaction_t *trans = nmt->trans;
|
||||
|
||||
frame->mt = NMT_MESSAGE_2b;
|
||||
frame->channel_no = nmt_encode_channel(nmt->sender.kanal, nmt->sysinfo.ms_power);
|
||||
frame->traffic_area = nmt->sysinfo.traffic_area;
|
||||
frame->channel_no = nmt_encode_channel(nmt->sysinfo.system, nmt->sender.kanal, nmt->sysinfo.ms_power);
|
||||
frame->traffic_area = nmt_encode_traffic_area(nmt->sysinfo.system, nmt->sender.kanal, nmt->sysinfo.traffic_area);
|
||||
frame->ms_country = nmt_digits2value(&trans->subscriber.country, 1);
|
||||
frame->ms_number = nmt_digits2value(trans->subscriber.number, 6);
|
||||
frame->tc_no = nmt_encode_channel(nmt->sender.kanal, nmt->sysinfo.ms_power);
|
||||
frame->tc_no = nmt_encode_tc(nmt->sysinfo.system, nmt->sender.kanal, nmt->sysinfo.ms_power);
|
||||
PDEBUG_CHAN(DNMT, DEBUG_INFO, "Send channel activation to mobile.\n");
|
||||
nmt_new_state(nmt, STATE_MT_IDENT);
|
||||
}
|
||||
|
@ -1477,7 +1534,7 @@ void nmt_receive_frame(nmt_t *nmt, const char *bits, double quality, double leve
|
|||
|
||||
PDEBUG_CHAN(DDSP, DEBUG_INFO, "RX Level: %.0f%% Quality=%.0f\n", level * 100.0, quality * 100.0);
|
||||
|
||||
rc = decode_frame(&frame, bits, (nmt->sender.loopback) ? MTX_TO_XX : XX_TO_MTX, (nmt->state == STATE_MT_PAGING));
|
||||
rc = decode_frame(nmt->sysinfo.system, &frame, bits, (nmt->sender.loopback) ? MTX_TO_XX : XX_TO_MTX, (nmt->state == STATE_MT_PAGING));
|
||||
if (rc < 0) {
|
||||
PDEBUG_CHAN(DNMT, (nmt->sender.loopback) ? DEBUG_NOTICE : DEBUG_DEBUG, "Received invalid frame.\n");
|
||||
return;
|
||||
|
@ -1661,7 +1718,7 @@ const char *nmt_get_frame(nmt_t *nmt)
|
|||
if (nmt->dsp_mode != DSP_MODE_FRAME)
|
||||
return NULL;
|
||||
|
||||
bits = encode_frame(&frame, debug);
|
||||
bits = encode_frame(nmt->sysinfo.system, &frame, debug);
|
||||
|
||||
PDEBUG_CHAN(DNMT, DEBUG_DEBUG, "Sending frame %s.\n", nmt_frame_name(frame.mt));
|
||||
return bits;
|
||||
|
|
|
@ -17,7 +17,10 @@ enum dsp_mode {
|
|||
|
||||
enum nmt_chan_type {
|
||||
CHAN_TYPE_CC, /* calling channel */
|
||||
CHAN_TYPE_CCA, /* calling channel type A mobiles */
|
||||
CHAN_TYPE_CCB, /* calling channel type B mobiles */
|
||||
CHAN_TYPE_TC, /* traffic channel */
|
||||
CHAN_TYPE_AC_TC, /* combined AC + TC */
|
||||
CHAN_TYPE_CC_TC, /* combined CC + TC */
|
||||
CHAN_TYPE_TEST, /* test channel */
|
||||
};
|
||||
|
@ -59,6 +62,7 @@ enum nmt_direction {
|
|||
};
|
||||
|
||||
typedef struct nmt_sysinfo {
|
||||
int system; /* 450 or 900 */
|
||||
enum nmt_chan_type chan_type; /* channel type */
|
||||
int ms_power; /* ms power level 3 = full */
|
||||
uint8_t traffic_area; /* two digits traffic area, encoded as YY */
|
||||
|
@ -137,12 +141,12 @@ typedef struct nmt {
|
|||
struct timer sms_timer;
|
||||
} nmt_t;
|
||||
|
||||
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);
|
||||
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, const char *read_tx_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_channel_list(int nmt_system);
|
||||
int nmt_channel_by_short_name(int nmt_system, const char *short_name);
|
||||
const char *chan_type_short_name(int nmt_system, enum nmt_chan_type chan_type);
|
||||
const char *chan_type_long_name(int nmt_system, enum nmt_chan_type chan_type);
|
||||
int nmt_create(int nmt_system, 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, const char *read_tx_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(int nmt_system);
|
||||
void nmt_destroy(sender_t *sender);
|
||||
void nmt_go_idle(nmt_t *nmt);
|
||||
void nmt_receive_frame(nmt_t *nmt, const char *bits, double quality, double level, double frames_elapsed);
|
||||
|
|
Loading…
Reference in New Issue