aboutsummaryrefslogtreecommitdiffstats
path: root/src/amps
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2017-05-25 09:57:22 +0200
committerAndreas Eversberg <jolly@eversberg.eu>2017-06-10 13:08:19 +0200
commitbb64c6b3ba80f8ef844bae59e270ca9e3b43d1fd (patch)
tree24986a074f932ed0842291004c1fd4b96d20cf78 /src/amps
parent2c1ab897232fdcbf11a9a9cc74562a1d7221a517 (diff)
AMPS: Add DTX support
When DTX is enabled (-S dtx=2 or 3), a missing SAT tone causes the receiver to mute audio and insert a low level of comfort noise. Also the missing SAT tone will not cause the connection to be terminated.
Diffstat (limited to 'src/amps')
-rw-r--r--src/amps/amps.c13
-rw-r--r--src/amps/amps.h5
-rw-r--r--src/amps/dsp.c47
-rw-r--r--src/amps/main.c19
-rw-r--r--src/amps/sysinfo.c4
-rw-r--r--src/amps/sysinfo.h2
-rw-r--r--src/amps/transaction.h1
7 files changed, 65 insertions, 26 deletions
diff --git a/src/amps/amps.c b/src/amps/amps.c
index a7a04d9..d180a4f 100644
--- a/src/amps/amps.c
+++ b/src/amps/amps.c
@@ -680,7 +680,10 @@ void amps_rx_sat(amps_t *amps, int tone, double quality)
if (tone) {
timer_stop(&trans->timer);
} else {
- timer_start(&trans->timer, SAT_TO2);
+ if (!trans->dtx)
+ timer_start(&trans->timer, SAT_TO2);
+ else
+ timer_stop(&trans->timer);
}
}
@@ -769,6 +772,14 @@ reject:
trans_new_state(trans, TRANS_CALL_MT_ASSIGN);
trans->chan = vc->sender.kanal;
}
+ /* if we support DTX and also the phone does, we set DTX state of transaction */
+ if (amps->si.word2.dtx) {
+ if ((scm & 4)) {
+ PDEBUG(DAMPS, DEBUG_INFO, " -> Use DTX for this call\n");
+ trans->dtx = 1;
+ } else
+ PDEBUG(DAMPS, DEBUG_INFO, " -> Requested DTX, but not supported by phone\n");
+ }
} else
PDEBUG_CHAN(DAMPS, DEBUG_NOTICE, "Unsupported RECC messages: ORDER: %d ORDQ: %d MSG TYPE: %d (See Table 4 of specs.)\n", order, ordq, msg_type);
}
diff --git a/src/amps/amps.h b/src/amps/amps.h
index 1c5ddeb..db5fa64 100644
--- a/src/amps/amps.h
+++ b/src/amps/amps.h
@@ -139,9 +139,10 @@ typedef struct amps {
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 sat_detected; /* current detection state flag */
+ 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 */
+ int sig_detected; /* current detection state flag (delayed detection) */
int sig_detect_count; /* current number of consecutive detections/losses */
double test_phaseshift65536; /* how much the phase of sine wave changes per sample */
double test_phase65536; /* current phase */
diff --git a/src/amps/dsp.c b/src/amps/dsp.c
index 94ea774..ece14aa 100644
--- a/src/amps/dsp.c
+++ b/src/amps/dsp.c
@@ -107,17 +107,17 @@
#define SAT_DEVIATION (2000.0 / DBM0_DEVIATION) /* no emphasis */
#define MAX_DISPLAY (8000.0 / DBM0_DEVIATION) /* no emphasis */
#define BITRATE 10000
-#define SIG_TONE_CROSSINGS 2000 /* 2000 crossings are 100ms @ 10 KHz */
-#define SIG_TONE_MINBITS 950 /* minimum bit durations to detect signaling tone (1000 is perfect for 100 ms) */
-#define SIG_TONE_MAXBITS 1050 /* as above, maximum bits */
-#define SAT_DURATION 0.100 /* duration of SAT signal measurement */
-#define SAT_QUALITY 0.85 /* quality needed to detect sat */
-#define SAT_DETECT_COUNT 3 /* number of measures to detect SAT signal (specs say 250ms) */
-#define SAT_LOST_COUNT 3 /* number of measures to loose SAT signal (specs say 250ms) */
-#define SIG_DETECT_COUNT 3 /* number of measures to detect Signaling Tone */
-#define SIG_LOST_COUNT 2 /* number of measures to loose Signaling Tone */
+#define SAT_DURATION 0.05 /* duration of SAT signal measurement */
+#define SAT_QUALITY 0.85 /* quality needed to detect SAT signal */
+#define DTX_LEVEL 0.50 /* SAT level needed to mute/unmute */
+#define SIG_QUALITY 0.80 /* quality needed to detect Signaling Tone */
+#define SAT_DETECT_COUNT 5 /* number of measures to detect SAT signal (specs say 250ms) */
+#define SAT_LOST_COUNT 5 /* number of measures to loose SAT signal (specs say 250ms) */
+#define SIG_DETECT_COUNT 6 /* number of measures to detect Signaling Tone */
+#define SIG_LOST_COUNT 4 /* number of measures to loose Signaling Tone */
#define CUT_OFF_HIGHPASS 300.0 /* cut off frequency for high pass filter to remove dc level from sound card / sample */
#define BEST_QUALITY 0.68 /* Best possible RX quality */
+#define COMFORT_NOISE 0.02 /* audio level of comfort noise (relative to ISDN level) */
static sample_t ramp_up[256], ramp_down[256];
@@ -423,6 +423,18 @@ done:
return count;
}
+/* send comfort noise */
+static void comfort_noise(sample_t *samples, int length)
+{
+ int i;
+ int16_t r;
+
+ for (i = 0; i < length; i++) {
+ r = random();
+ samples[i] = (double)r / 32768.0 * COMFORT_NOISE;
+ }
+}
+
/* Generate audio stream with SAT signal. Keep phase for next call of function. */
static void sat_encode(amps_t *amps, sample_t *samples, int length)
{
@@ -716,7 +728,7 @@ static void sender_receive_frame(amps_t *amps, sample_t *samples, int length)
}
-/* decode signaling tone */
+/* decode SAT and signaling tone */
/* compare supervisory signal against noise floor on 5800 Hz */
static void sat_decode(amps_t *amps, sample_t *samples, int length)
{
@@ -737,6 +749,10 @@ static void sat_decode(amps_t *amps, sample_t *samples, int length)
if (amps->sender.loopback || debuglevel == DEBUG_DEBUG) {
PDEBUG_CHAN(DDSP, debuglevel, "Signaling Tone level %.2f%% quality %.0f%%\n", result[2] / FSK_DEVIATION / 0.63662 * 100.0, quality[1] * 100.0);
}
+ if (quality[0] > SAT_QUALITY && result[0] / SAT_DEVIATION / 0.63662 > DTX_LEVEL)
+ amps->dtx_state = 1;
+ else
+ amps->dtx_state = 0;
if (quality[0] > SAT_QUALITY) {
if (amps->sat_detected == 0) {
amps->sat_detect_count++;
@@ -760,7 +776,7 @@ static void sat_decode(amps_t *amps, sample_t *samples, int length)
} else
amps->sat_detect_count = 0;
}
- if (quality[1] > 0.8) {
+ if (quality[1] > SIG_QUALITY) {
if (amps->sig_detected == 0) {
amps->sig_detect_count++;
if (amps->sig_detect_count == SIG_DETECT_COUNT) {
@@ -785,11 +801,6 @@ static void sat_decode(amps_t *amps, sample_t *samples, int length)
}
}
-/* decode signaling/audio */
-/* Count SIG_TONE_CROSSINGS of zero crossings, then check if the elapsed bit
- * time is between SIG_TONE_MINBITS and SIG_TONE_MAXBITS. If it is, the
- * frequency is close to the singalling tone, so it is detected
- */
static void sender_receive_audio(amps_t *amps, sample_t *samples, int length)
{
transaction_t *trans = amps->trans_list;
@@ -813,7 +824,7 @@ static void sender_receive_audio(amps_t *amps, sample_t *samples, int length)
/* receive audio, but only if call established and SAT detected */
if ((amps->dsp_mode == DSP_MODE_AUDIO_RX_AUDIO_TX || amps->dsp_mode == DSP_MODE_AUDIO_RX_FRAME_TX)
- && trans && trans->callref && trans->sat_detected) {
+ && trans && trans->callref) {
int pos, count;
int i;
@@ -828,6 +839,8 @@ static void sender_receive_audio(amps_t *amps, sample_t *samples, int length)
for (i = 0; i < count; i++) {
spl[pos++] = samples[i];
if (pos == 160) {
+ if (amps->dtx_state == 0)
+ comfort_noise(spl, 160);
call_tx_audio(trans->callref, spl, 160);
pos = 0;
}
diff --git a/src/amps/main.c b/src/amps/main.c
index 6585306..e4dc243 100644
--- a/src/amps/main.c
+++ b/src/amps/main.c
@@ -43,7 +43,7 @@
int num_chan_type = 0;
enum amps_chan_type chan_type[MAX_SENDER] = { CHAN_TYPE_CC_PC_VC };
const char *flip_polarity = "";
-int ms_power = 4, dcc = 0, scc = 0, sid = 40, regh = 1, regr = 1, pureg = 1, pdreg = 1, locaid = -1, regincr = 300, bis = 0;
+int ms_power = 4, dtx = 0, dcc = 0, scc = 0, sid = 40, regh = 1, regr = 1, pureg = 1, pdreg = 1, locaid = -1, regincr = 300, bis = 0;
int tolerant = 0;
void print_help(const char *arg0)
@@ -61,6 +61,10 @@ void print_help(const char *arg0)
printf(" Give power level of the mobile station 0..7. (default = '%d')\n", ms_power);
printf(" 0 = 4 W; 1 = 1.6 W; 2 = 630 mW; 3 = 250 mW;\n");
printf(" 4 = 100 mW; 5 = 40 mW; 6 = 16 mW; 7 = 6.3 mW\n");
+ printf(" -D --dtx <parameter>\n");
+ printf(" Give DTX parameter for Discontinuous Transmission. (default = '%d')\n", dtx);
+ printf(" 0 = disable DTX; 1 = reserved;\n");
+ printf(" 2 = 8 dB attenuation in low state; 3 = transmitter off\n");
printf(" -S --sysinfo sid=<System ID> | sid=list\n");
printf(" Give system ID of cell broadcast (default = '%d')\n", sid);
printf(" If it changes, phone re-registers. Use 'sid=list' to get a full list.\n");
@@ -106,12 +110,13 @@ static int handle_options(int argc, char **argv)
{"channel-type", 1, 0, 'T'},
{"flip-polarity", 1, 0, 'F'},
{"ms-power", 1, 0, 'P'},
+ {"dtx", 1, 0, 'D'},
{"sysinfo", 1, 0, 'S'},
{"tolerant", 0, 0, 'O'},
{0, 0, 0, 0}
};
- set_options_common("T:F:P:S:O", long_options_special);
+ set_options_common("T:F:P:D:S:O", long_options_special);
while (1) {
int option_index = 0, c;
@@ -154,6 +159,14 @@ static int handle_options(int argc, char **argv)
ms_power = 0;
skip_args += 2;
break;
+ case 'D':
+ dtx = atoi(optarg);
+ if (dtx > 3)
+ dtx = 3;
+ if (dtx < 0)
+ dtx = 0;
+ skip_args += 2;
+ break;
case 'S':
p = strchr(optarg, '=');
if (!p) {
@@ -360,7 +373,7 @@ int main(int argc, char *argv[])
for (i = 0; i < num_kanal; i++) {
amps_si si;
- init_sysinfo(&si, ms_power, ms_power, dcc, sid >> 1, regh, regr, pureg, pdreg, locaid, regincr, bis);
+ init_sysinfo(&si, ms_power, ms_power, dtx, dcc, sid >> 1, regh, regr, pureg, pdreg, locaid, regincr, bis);
rc = amps_create(kanal[i], 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, &si, sid, scc, polarity, tolerant, loopback);
if (rc < 0) {
fprintf(stderr, "Failed to create \"Sender\" instance. Quitting!\n");
diff --git a/src/amps/sysinfo.c b/src/amps/sysinfo.c
index 45826ce..064abbf 100644
--- a/src/amps/sysinfo.c
+++ b/src/amps/sysinfo.c
@@ -42,7 +42,7 @@ static struct sysinfo_acc_attempt default_acc_attempt = {
10,
};
-void init_sysinfo(amps_si *si, int cmac, int vmac, int dcc, int sid1, int regh, int regr, int pureg, int pdreg, int locaid, int regincr, int bis)
+void init_sysinfo(amps_si *si, int cmac, int vmac, int dtx, int dcc, int sid1, int regh, int regr, int pureg, int pdreg, int locaid, int regincr, int bis)
{
int i;
@@ -70,7 +70,7 @@ void init_sysinfo(amps_si *si, int cmac, int vmac, int dcc, int sid1, int regh,
si->word2.e = 1;
si->word2.regh = regh;
si->word2.regr = regr;
- si->word2.dtx = 0; /* DTX seems not to work with Dynatac 8000 */
+ si->word2.dtx = dtx; /* DTX seems not to work with my White Dynatac 8000 */
si->word2.n_1 = 20;
si->word2.rcf = (bis) ? 0 : 1; /* must be set to ignore B/I bit */
si->word2.cpa = 1; /* must be set for combined CC+PC */
diff --git a/src/amps/sysinfo.h b/src/amps/sysinfo.h
index b786add..211c128 100644
--- a/src/amps/sysinfo.h
+++ b/src/amps/sysinfo.h
@@ -108,7 +108,7 @@ typedef struct system_information {
int count; /* count message train */
} amps_si;
-void init_sysinfo(amps_si *si, int cmac, int vmac, int dcc, int sid1, int regh, int regr, int pureg, int pdreg, int locaid, int regincr, int bis);
+void init_sysinfo(amps_si *si, int cmac, int vmac, int dtx, int dcc, int sid1, int regh, int regr, int pureg, int pdreg, int locaid, int regincr, int bis);
void prepare_sysinfo(amps_si *si);
uint64_t get_sysinfo(amps_si *si);
diff --git a/src/amps/transaction.h b/src/amps/transaction.h
index 5240991..79fd467 100644
--- a/src/amps/transaction.h
+++ b/src/amps/transaction.h
@@ -36,6 +36,7 @@ typedef struct transaction {
enum amps_trans_state state; /* state of transaction */
struct timer timer; /* for varous timeouts */
int sat_detected; /* state if we detected SAT */
+ int dtx; /* if set, DTX is used with this call */
} transaction_t;
transaction_t *create_transaction(amps_t *amps, enum amps_trans_state trans_state, uint32_t min1, uint16_t min2, uint8_t msg_type, uint8_t ordq, uint8_t order, uint16_t chan);