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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
|
#include "../common/goertzel.h"
#include "../common/sender.h"
#include "../common/compandor.h"
#include "sysinfo.h"
#include "transaction.h"
enum dsp_mode {
DSP_MODE_OFF, /* channel not active (VC) */
DSP_MODE_AUDIO_RX_AUDIO_TX, /* stream audio */
DSP_MODE_AUDIO_RX_FRAME_TX, /* stream audio, send frames */
DSP_MODE_FRAME_RX_FRAME_TX, /* send and decode frames */
};
enum amps_chan_type {
CHAN_TYPE_CC, /* control channel */
CHAN_TYPE_PC, /* paging channel */
CHAN_TYPE_CC_PC, /* combined CC + PC */
CHAN_TYPE_VC, /* voice channel */
CHAN_TYPE_CC_PC_VC, /* combined CC + PC + TC */
};
enum amps_state {
STATE_NULL, /* power off state */
STATE_IDLE, /* channel is not in use */
STATE_BUSY, /* channel busy (call) */
};
enum fsk_rx_sync {
FSK_SYNC_NONE, /* we are not in sync and wait for valid dotting sequence */
FSK_SYNC_DOTTING, /* we received a valid dotting sequence and check for sync sequence */
FSK_SYNC_POSITIVE, /* we have valid sync and read all the bits of the frame */
FSK_SYNC_NEGATIVE, /* as above, but negative sync (high frequency deviation detected as low signal) */
};
#define FSK_MAX_BITS 1032 /* maximum number of bits to process (FVC with dotting+sync) */
typedef struct amps {
sender_t sender;
compandor_t cstate;
int pre_emphasis; /* use pre_emphasis by this instance */
int de_emphasis; /* use de_emphasis by this instance */
emphasis_t estate;
/* sender's states */
enum amps_chan_type chan_type;
enum amps_state state;
int channel_busy; /* indicate channel is busy while receiving */
/* display measurements */
dispmeasparam_t *dmp_frame_level;
dispmeasparam_t *dmp_frame_quality;
/* system info */
amps_si si;
/* cell nr selection */
int cell_auto; /* if set, cell_nr is selected automatically */
/* dsp states */
enum dsp_mode dsp_mode; /* current mode: audio, durable tone 0 or 1, paging */
int flip_polarity; /* 1 = flip */
double fsk_deviation; /* deviation of FSK signal on sound card */
sample_t fsk_ramp_up[256]; /* samples of upward ramp shape */
sample_t fsk_ramp_down[256]; /* samples of downward ramp shape */
double fsk_bitduration; /* duration of one bit in samples */
double fsk_bitstep; /* fraction of one bit each sample */
/* tx bits generation */
char fsk_tx_frame[FSK_MAX_BITS + 1]; /* +1 because 0-termination */
int fsk_tx_frame_pos; /* current position sending bits */
sample_t *fsk_tx_buffer; /* tx buffer for one data block */
int fsk_tx_buffer_size; /* size of tx buffer (in samples) */
int fsk_tx_buffer_length; /* usage of buffer (in samples) */
int fsk_tx_buffer_pos; /* current position sending buffer */
double fsk_tx_phase; /* current bit position */
char fsk_tx_last_bit; /* save last bit of frame (for next frame's ramp) */
/* high-pass filter to remove DC offset from RX signal */
double highpass_factor; /* high pass filter factor */
double highpass_x_last; /* last input value */
double highpass_y_last; /* last output value */
/* rx detection of bits and sync */
sample_t fsk_rx_last_sample; /* last sample (for level change detection) */
double fsk_rx_elapsed; /* bit duration since last level change */
enum fsk_rx_sync fsk_rx_sync; /* sync state */
uint16_t fsk_rx_sync_register; /* shift register to detect sync word */
int fsk_rx_sync_tolerant; /* be more tolerant to sync */
/* the dotting buffer stores the elapsed samples, so we can calculate
* an average time of zero-crossings during dotting sequence.
* this buffer wrapps every 256 values */
double fsk_rx_dotting_elapsed[256]; /* dotting buffer with elapsed samples since last zero-crossing */
uint8_t fsk_rx_dotting_pos; /* position of next value in dotting buffer */
int fsk_rx_dotting_life; /* counter to expire when no sync was found after dotting */
double fsk_rx_dotting_average; /* last average slope position of dotting sequnece. */
/* the ex buffer holds the duration of one bit, and wrapps every
* bit. */
double fsk_rx_bitcount; /* counts the bit. if it reaches or exceeds 1, the bit is complete and the next bit starts */
sample_t *fsk_rx_window; /* rx buffer for one bit */
int fsk_rx_window_length; /* length of rx buffer */
int fsk_rx_window_half; /* half of length of rx buffer */
int fsk_rx_window_begin; /* where to begin detecting level */
int fsk_rx_window_end; /* where to end detecting level */
int fsk_rx_window_pos; /* current position in buffer */
/* the rx bufffer received one frame until rx length */
char fsk_rx_frame[FSK_MAX_BITS + 1]; /* +1 because 0-termination */
int fsk_rx_frame_length; /* length of expected frame */
int fsk_rx_frame_count; /* count number of received bit */
double fsk_rx_frame_level; /* sum of level of all bits */
double fsk_rx_frame_quality; /* sum of quality of all bits */
/* RECC frame states */
int rx_recc_nawc; /* counts down received words */
int rx_recc_word_count; /* counts up received words */
uint32_t rx_recc_min1; /* mobile id */
uint16_t rx_recc_min2;
uint8_t rx_recc_msg_type; /* message (3 values) */
uint8_t rx_recc_ordq;
uint8_t rx_recc_order;
uint32_t rx_recc_esn;
uint32_t rx_recc_scm;
uint8_t rx_recc_mpci;
char rx_recc_dialing[33]; /* received dial string */
/* FOCC frame states */
int rx_focc_word_count; /* counts received words */
int tx_focc_frame_count; /* used to schedule system informations */
int tx_focc_send; /* if set, send message words */
uint32_t tx_focc_min1; /* mobile id */
uint16_t tx_focc_min2;
int tx_focc_chan; /* channel to assign for voice call */
uint8_t tx_focc_msg_type; /* message (3 values) */
uint8_t tx_focc_ordq;
uint8_t tx_focc_order;
int tx_focc_word_count; /* counts transmitted words in a muli word message */
int tx_focc_word_repeat; /* countrs repeats of mulit word message */
/* FVC frame states */
int tx_fvc_send; /* if set, send message words */
int tx_fvc_chan; /* channel to assign for voice call */
uint8_t tx_fvc_msg_type; /* message (3 values) */
uint8_t tx_fvc_ordq;
uint8_t tx_fvc_order;
/* SAT tone */
int sat; /* use SAT tone 0..2 */
int sat_samples; /* number of samples in buffer for supervisory detection */
goertzel_t sat_goertzel[5]; /* filter for SAT signal decoding */
sample_t *sat_filter_spl; /* array with sample buffer for supervisory detection */
int sat_filter_pos; /* current sample position in filter_spl */
double sat_phaseshift65536[3]; /* how much the phase of sine wave changes per sample */
double sat_phase65536; /* current phase */
int dtx_state; /* 1 = high (fast sat detection) */
int sat_detected; /* current detection state flag (delayed detection) */
int sat_detect_count; /* current number of consecutive detections/losses */
int sig_detected; /* current detection state flag (delayed detection) */
int sig_detect_count; /* current number of consecutive detections/losses */
transaction_t *trans_list; /* list of transactions */
/* delay measurement in loopback mode */
double when_received; /* time stamp of received frame start (start of dotting) */
double when_transmitted[16]; /* time stamps of filler frames with different count */
int when_count; /* counter of the filler frame */
} amps_t;
void amps_channel_list(void);
int amps_channel_by_short_name(const char *short_name);
const char *chan_type_short_name(enum amps_chan_type chan_type);
const char *chan_type_long_name(enum amps_chan_type chan_type);
double amps_channel2freq(int channel, int uplink);
enum amps_chan_type amps_channel2type(int channel);
const char *amps_channel2band(int channel);
const char *amps_min22number(uint16_t min2);
const char *amps_min12number(uint32_t min1);
void amps_number2min(const char *number, uint32_t *min1, uint16_t *min2);
const char *amps_min2number(uint32_t min1, uint16_t min2);
const char *amps_scm(uint8_t scm);
int amps_create(int channel, enum amps_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, amps_si *si, uint16_t sid, uint8_t sat, int polarity, int tolerant, int loopback);
void amps_destroy(sender_t *sender);
void amps_go_idle(amps_t *amps);
void amps_rx_signaling_tone(amps_t *amps, int tone, double quality);
void amps_rx_sat(amps_t *amps, int tone, double quality);
void amps_rx_recc(amps_t *amps, uint8_t scm, uint8_t mpci, uint32_t esn, uint32_t min1, uint16_t min2, uint8_t msg_type, uint8_t ordq, uint8_t order, const char *dialing);
transaction_t *amps_tx_frame_focc(amps_t *amps);
transaction_t *amps_tx_frame_fvc(amps_t *amps);
void amps_display_status();
|