aboutsummaryrefslogtreecommitdiffstats
path: root/src/nmt/nmt.h
blob: 7a8c1d7675619b78a8c75af13b2705b606c4defa (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
#include "../common/sender.h"
#include "../common/compandor.h"
#include "../common/dtmf.h"
#include "dms.h"

enum dsp_mode {
	DSP_MODE_DIALTONE,	/* stream dial tone to mobile phone */
	DSP_MODE_AUDIO,		/* stream audio */
	DSP_MODE_SILENCE,	/* stream nothing */
	DSP_MODE_FRAME,		/* send frames */
	DSP_MODE_DTMF,		/* send DTMF tones */
};

enum nmt_chan_type {
	CHAN_TYPE_CC,		/* calling channel */
	CHAN_TYPE_TC,		/* traffic channel */
	CHAN_TYPE_CC_TC,	/* combined CC + TC */
	CHAN_TYPE_TEST,		/* test channel */
};

enum nmt_state {
	STATE_NULL,		/* power off state */
	STATE_IDLE,		/* channel is not in use */
	STATE_ROAMING_IDENT,	/* seizure received, waiting for identity */
	STATE_ROAMING_CONFIRM,	/* identity received, sending confirm */
	STATE_MO_IDENT,		/* seizure of mobile originated call, waiting for identity */
	STATE_MO_CONFIRM,	/* identity received, sending confirm */
	STATE_MO_DIALING,	/* receiving digits from phone */
	STATE_MO_COMPLETE,	/* all digits received, completing call */
	STATE_MT_PAGING,	/* paging mobile phone */
	STATE_MT_CHANNEL,	/* assigning traffic channel */
	STATE_MT_IDENT,		/* waiting for identity */
	STATE_MT_RINGING,	/* mobile phone is ringing, waiting for answer */
	STATE_MT_COMPLETE,	/* mobile phone has answered, completing call */
	STATE_ACTIVE,		/* during active call */
	STATE_MO_RELEASE,	/* acknowlegde release from mobile phone */
	STATE_MT_RELEASE,	/* sending release toward mobile phone */
};

enum nmt_active_state {
	ACTIVE_STATE_VOICE,	/* normal conversation */
	ACTIVE_STATE_MFT_IN,	/* ack MFT converter in */
	ACTIVE_STATE_MFT,	/* receive digits in MFT mode */
	ACTIVE_STATE_MFT_OUT,	/* ack MFT converter out */
};

enum nmt_direction {
	MTX_TO_MS,
	MTX_TO_BS,
	MTX_TO_XX,
	BS_TO_MTX,
	MS_TO_MTX,
	XX_TO_MTX,
};

typedef struct nmt_sysinfo {
	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 */
	uint8_t			area_no;		/* Area no. 1..4, 0 = no Area no. */
} nmt_sysinfo_t;

typedef struct nmt_subscriber {
	/* NOTE: country must be followed by number, so both represent a string */
	char			country;		/* country digit */
	char			number[7];		/* phone suffix */
	char			password[4];		/* phone's password + '\0' */
	int			coinbox;		/* phone is a coinbox and accept tariff information */
} nmt_subscriber_t;

const char *nmt_dir_name(enum nmt_direction dir);

typedef struct nmt {
	sender_t		sender;
	nmt_sysinfo_t		sysinfo;
	compandor_t		cstate;
	dtmf_t			dtmf;

	/* sender's states */
	enum nmt_state		state;
	enum nmt_active_state	active_state;
	nmt_subscriber_t	subscriber;		/* current subscriber */
	struct timer		timer;
	int			rx_frame_count;		/* receive frame counter */
	int			tx_frame_count;		/* transmit frame counter */
	char			dialing[33];		/* dialed digits */
	int			page_try;		/* number of paging try */
	int			mft_num;		/* counter for digit for MFT */

	/* special state for paging on different CC */
	struct nmt		*page_for_nmt;		/* only page and assign channel for nmt instance as set */
	int			mt_channel;		/* channel to use */

	/* features */
	int			compandor;		/* if compandor shall be used */
	int			supervisory;		/* if set, use supervisory signal 1..4 */

	/* dsp states */
	enum dsp_mode		dsp_mode;		/* current mode: audio, durable tone 0 or 1, paging */
	int			samples_per_bit;	/* number of samples for one bit (1200 Baud) */
	int			super_samples;		/* number of samples in buffer for supervisory detection */
	int			fsk_coeff[2];		/* coefficient k = 2*cos(2*PI*f/samplerate), k << 15 */
	int			super_coeff[5];		/* coefficient for supervisory signal */
	int16_t			*fsk_sine[2][2];	/* 4 pointers to 4 precalc. sine curves */
	int			fsk_polarity;		/* current polarity state of bit */
	int			samples_per_chunk;	/* how many samples lasts one chunk */
	int16_t			*fsk_filter_spl;	/* array with samples_per_chunk */
	int			fsk_filter_pos;		/* current sample position in filter_spl */
	int			fsk_filter_step;	/* number of samples for each analyzation */
	int			fsk_filter_bit;		/* last bit, so we detect a bit change */
	int			fsk_filter_sample;	/* count until it is time to sample bit */
	uint16_t		fsk_filter_sync;	/* shift register to detect sync */
	int			fsk_filter_in_sync;	/* if we are in sync and receive bits */
	int			fsk_filter_mute;	/* mute count down after sync */
	char			fsk_filter_frame[141];	/* receive frame (one extra byte to terminate string) */
	int			fsk_filter_count;	/* next bit to receive */
	double			fsk_filter_level[256];	/* level infos */
	double			fsk_filter_quality[256];/* quality infos */
	int16_t			*super_filter_spl;	/* array with sample buffer for supervisory detection */
	int			super_filter_pos;	/* current sample position in filter_spl */
	double			super_phaseshift256[4];	/* how much the phase of sine wave changes per sample */
	double			super_phase256;		/* current phase */
	double			dial_phaseshift256;	/* how much the phase of sine wave changes per sample */
	double			dial_phase256;		/* current phase */
	int			frame;			/* set, if there is a valid frame */
	int16_t			*frame_spl;		/* 166 * fsk_bit_length */
	int			frame_pos;		/* current sample position in frame_spl */
	uint64_t		rx_sample_count;	/* sample counter */
	uint64_t		rx_sample_count_current;/* sample counter of current frame */
	uint64_t		rx_sample_count_last;	/* sample counter of last frame */
	int			super_detected;		/* current detection state flag */
	int			super_detect_count;	/* current number of consecutive detections/losses */

	/* DMS states */
	int			dms_call;		/* indicates that this call is a DMS call */
	dms_t			dms;			/* DMS states */
} 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);
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 *sounddev, int samplerate, int cross_channels, double rx_gain, int pre_emphasis, int de_emphasis, const char *write_wave, const char *read_wave, uint8_t ms_power, uint8_t traffic_area, uint8_t area_no, int compandor, int supervisory, int loopback);
void nmt_destroy(sender_t *sender);
void nmt_receive_frame(nmt_t *nmt, const char *bits, double quality, double level, double frames_elapsed);
const char *nmt_get_frame(nmt_t *nmt);
void nmt_rx_super(nmt_t *nmt, int tone, double quality);