aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2016-10-30 09:25:45 +0100
committerAndreas Eversberg <jolly@eversberg.eu>2016-10-30 09:37:14 +0100
commit63f39e105b5356a2d096ef78b9a436d4041a2502 (patch)
tree6333eb82142cfbe0f4c43800042c37caf2380879 /src
parentb70f4ecebc242e72dd3e1cd2c8a85afcf118afa1 (diff)
AMPS: Fixes for multi transceiver support
- Fix channel assignment - Voice channel sends test tone when idle - Changed paging timeout - Minor fix of SCC field in 2 messages
Diffstat (limited to 'src')
-rw-r--r--src/amps/amps.c97
-rw-r--r--src/amps/amps.h2
-rw-r--r--src/amps/dsp.c57
-rw-r--r--src/amps/frame.c4
-rw-r--r--src/amps/main.c2
5 files changed, 121 insertions, 41 deletions
diff --git a/src/amps/amps.c b/src/amps/amps.c
index 1ccd66f..3404441 100644
--- a/src/amps/amps.c
+++ b/src/amps/amps.c
@@ -36,8 +36,8 @@
#define SAT_TO1 5.0 /* 5 sec to detect after setup */
#define SAT_TO2 5.0 /* 5 sec lost until abort (specs say 5) */
#define PAGE_TRIES 2 /* how many times to page the phone */
-#define PAGE_TO1 5.0 /* max time to wait for paging reply */
-#define PAGE_TO2 7.0 /* max time to wait for last paging reply */
+#define PAGE_TO1 8.0 /* max time to wait for paging reply */
+#define PAGE_TO2 4.0 /* max time to wait for last paging reply */
#define ALERT_TO 60.0 /* max time to wait for answer */
#define RELEASE_TIMER 5.0 /* max time to send release messages */
@@ -297,6 +297,22 @@ const char *chan_type_long_name(enum amps_chan_type chan_type)
return "invalid";
}
+static amps_t *search_channel(int channel)
+{
+ sender_t *sender;
+ amps_t *amps;
+
+ for (sender = sender_head; sender; sender = sender->next) {
+ if (sender->kanal != channel)
+ continue;
+ amps = (amps_t *) sender;
+ if (amps->state == STATE_IDLE)
+ return amps;
+ }
+
+ return NULL;
+}
+
static amps_t *search_free_vc(void)
{
sender_t *sender;
@@ -306,10 +322,10 @@ static amps_t *search_free_vc(void)
amps = (amps_t *) sender;
if (amps->state != STATE_IDLE)
continue;
- /* return first free SpK */
+ /* return first free voice channel */
if (amps->chan_type == CHAN_TYPE_VC)
return amps;
- /* remember OgK/SpK combined channel as second alternative */
+ /* remember combined voice/control/paging channel as second alternative */
if (amps->chan_type == CHAN_TYPE_CC_PC_VC)
cc_pc_vc = amps;
}
@@ -354,11 +370,17 @@ int amps_create(int channel, enum amps_chan_type chan_type, const char *sounddev
return -EINVAL;
}
+ /* no paging channel (without control channel) support */
+ if (chan_type == CHAN_TYPE_PC) {
+ PDEBUG(DAMPS, DEBUG_ERROR, "Dedicated paging channel currently not supported. Please select CC/PC or CC/PC/VC instead.\n");
+ return -EINVAL;
+ }
+
/* check if there is only one paging channel */
if (chan_type == CHAN_TYPE_PC || chan_type == CHAN_TYPE_CC_PC || chan_type == CHAN_TYPE_CC_PC_VC) {
for (sender = sender_head; sender; sender = sender->next) {
amps = (amps_t *)sender;
- if (amps->chan_type == CHAN_TYPE_PC || chan_type == CHAN_TYPE_CC_PC || chan_type == CHAN_TYPE_CC_PC_VC) {
+ if (amps->chan_type == CHAN_TYPE_PC || amps->chan_type == CHAN_TYPE_CC_PC || amps->chan_type == CHAN_TYPE_CC_PC_VC) {
PDEBUG(DAMPS, DEBUG_ERROR, "Only one paging channel is currently supported. Please check your channel types.\n");
return -EINVAL;
}
@@ -377,11 +399,11 @@ int amps_create(int channel, enum amps_chan_type chan_type, const char *sounddev
/* check if sid machtes channel band */
band = amps_channel2band(channel);
- if (band == 'A' && (sid & 1) == 0) {
+ if (band == 'A' && (sid & 1) == 0 && chan_type != CHAN_TYPE_VC) {
PDEBUG(DAMPS, DEBUG_ERROR, "Channel number %d belongs to system A, but your SID %d is even and belongs to system B. Please give odd SID.\n", channel, sid);
return -EINVAL;
}
- if (band == 'B' && (sid & 1) == 1) {
+ if (band == 'B' && (sid & 1) == 1 && chan_type != CHAN_TYPE_VC) {
PDEBUG(DAMPS, DEBUG_ERROR, "Channel number %d belongs to system B, but your SID %d is odd and belongs to system A. Please give even SID.\n", channel, sid);
return -EINVAL;
}
@@ -479,13 +501,19 @@ static void amps_go_idle(amps_t *amps)
destroy_transaction(amps->trans_list);
}
- PDEBUG(DAMPS, DEBUG_INFO, "Entering IDLE state, sending Overhead/Filler frames on %s.\n", chan_type_long_name(amps->chan_type));
- if (amps->sender.loopback)
- frame_length = 441; /* bits after sync (FOCC) */
- else
- frame_length = 247; /* bits after sync (RECC) */
amps_new_state(amps, STATE_IDLE);
- amps_set_dsp_mode(amps, DSP_MODE_FRAME_RX_FRAME_TX, frame_length);
+
+ if (amps->chan_type != CHAN_TYPE_VC) {
+ PDEBUG(DAMPS, DEBUG_INFO, "Entering IDLE state, sending Overhead/Filler frames on %s.\n", chan_type_long_name(amps->chan_type));
+ if (amps->sender.loopback)
+ frame_length = 441; /* bits after sync (FOCC) */
+ else
+ frame_length = 247; /* bits after sync (RECC) */
+ amps_set_dsp_mode(amps, DSP_MODE_FRAME_RX_FRAME_TX, frame_length);
+ } else {
+ PDEBUG(DAMPS, DEBUG_INFO, "Entering IDLE state, sending test tone on %s.\n", chan_type_long_name(amps->chan_type));
+ amps_set_dsp_mode(amps, DSP_MODE_OFF, 0);
+ }
}
/* Abort connection towards mobile station by sending FOCC/FVC pattern. */
@@ -913,18 +941,18 @@ void transaction_timeout(struct timer *timer)
}
/* assigning voice channel and moving transaction+callref to that channel */
-static void assign_voice_channel(transaction_t *trans)
+static amps_t *assign_voice_channel(transaction_t *trans)
{
amps_t *amps = trans->amps, *vc;
const char *callerid = amps_min2number(trans->min1, trans->min2);
int callref = ++new_callref;
int rc;
- vc = search_free_vc();
+ vc = search_channel(trans->chan);
if (!vc) {
- PDEBUG(DAMPS, DEBUG_NOTICE, "No free channel, rejecting call\n");
+ PDEBUG(DAMPS, DEBUG_NOTICE, "Channel %d is not free anymore, rejecting call\n", trans->chan);
amps_release(trans, CAUSE_NOCHANNEL);
- return;
+ return NULL;
}
if (vc == amps)
@@ -938,7 +966,7 @@ static void assign_voice_channel(transaction_t *trans)
if (rc < 0) {
PDEBUG(DAMPS, DEBUG_NOTICE, "Call rejected (cause %d), releasing.\n", rc);
amps_release(trans, 0);
- return;
+ return NULL;
}
trans->callref = callref;
}
@@ -950,11 +978,14 @@ static void assign_voice_channel(transaction_t *trans)
link_transaction(trans, vc);
/* flush all other transactions, if any (in case of combined VC + CC) */
amps_flush_other_transactions(vc, trans);
+
+ return vc;
}
transaction_t *amps_tx_frame_focc(amps_t *amps)
{
transaction_t *trans;
+ amps_t *vc;
again:
trans = amps->trans_list;
@@ -981,22 +1012,28 @@ again:
trans_new_state(trans, TRANS_CALL_MO_ASSIGN_SEND);
return trans;
case TRANS_CALL_MO_ASSIGN_SEND:
- trans_new_state(trans, TRANS_CALL);
- amps_set_dsp_mode(amps, DSP_MODE_AUDIO_RX_AUDIO_TX, 0);
- assign_voice_channel(trans);
+ vc = assign_voice_channel(trans);
+ if (vc) {
+ PDEBUG(DAMPS, DEBUG_INFO, "Assignment complete, voice connected\n");
+ trans_new_state(trans, TRANS_CALL);
+ amps_set_dsp_mode(vc, DSP_MODE_AUDIO_RX_AUDIO_TX, 0);
+ }
return NULL;
case TRANS_CALL_MT_ASSIGN:
PDEBUG(DAMPS, DEBUG_INFO, "Assigning channel to call to mobile station\n");
trans_new_state(trans, TRANS_CALL_MT_ASSIGN_SEND);
return trans;
case TRANS_CALL_MT_ASSIGN_SEND:
- trans_new_state(trans, TRANS_CALL_MT_ALERT);
- trans->chan = 0;
- trans->msg_type = 0;
- trans->ordq = 0;
- trans->order = 1;
- amps_set_dsp_mode(amps, DSP_MODE_AUDIO_RX_FRAME_TX, 0);
- assign_voice_channel(trans);
+ vc = assign_voice_channel(trans);
+ if (vc) {
+ PDEBUG(DAMPS, DEBUG_INFO, "Assignment complete, next: sending altering on VC\n");
+ trans->chan = 0;
+ trans->msg_type = 0;
+ trans->ordq = 0;
+ trans->order = 1;
+ trans_new_state(trans, TRANS_CALL_MT_ALERT);
+ amps_set_dsp_mode(vc, DSP_MODE_AUDIO_RX_FRAME_TX, 0);
+ }
return NULL;
case TRANS_PAGE:
PDEBUG(DAMPS, DEBUG_INFO, "Paging the phone\n");
@@ -1022,14 +1059,16 @@ again:
switch (trans->state) {
case TRANS_CALL_RELEASE:
- PDEBUG(DAMPS, DEBUG_INFO, "Releasing call to mobile station\n");
+ PDEBUG(DAMPS, DEBUG_INFO, "Releasing call towards mobile station\n");
trans_new_state(trans, TRANS_CALL_RELEASE_SEND);
return trans;
case TRANS_CALL_RELEASE_SEND:
+ PDEBUG(DAMPS, DEBUG_INFO, "Release call was sent, destroying call\n");
destroy_transaction(trans);
amps_go_idle(amps);
goto again;
case TRANS_CALL_MT_ALERT:
+ PDEBUG(DAMPS, DEBUG_INFO, "Sending altering\n");
return trans;
default:
return NULL;
diff --git a/src/amps/amps.h b/src/amps/amps.h
index e219c21..4c47f09 100644
--- a/src/amps/amps.h
+++ b/src/amps/amps.h
@@ -140,6 +140,8 @@ typedef struct amps {
int sat_detect_count; /* current number of consecutive detections/losses */
int sig_detected; /* current detection state flag */
int sig_detect_count; /* current number of consecutive detections/losses */
+ double test_phaseshift256; /* how much the phase of sine wave changes per sample */
+ double test_phase256; /* current phase */
transaction_t *trans_list; /* list of transactions */
diff --git a/src/amps/dsp.c b/src/amps/dsp.c
index 6ced01d..20fc9fd 100644
--- a/src/amps/dsp.c
+++ b/src/amps/dsp.c
@@ -89,6 +89,8 @@
#include "frame.h"
#include "dsp.h"
+#define CHAN amps->sender.kanal
+
/* uncomment this to debug the encoding process */
//#define DEBUG_ENCODER
@@ -124,6 +126,7 @@ static double sat_freq[5] = {
};
static int dsp_sine_sat[256];
+static int dsp_sine_test[256];
static uint8_t dsp_sync_check[0x800];
@@ -137,6 +140,7 @@ void dsp_init(void)
for (i = 0; i < 256; i++) {
s = sin((double)i / 256.0 * 2.0 * PI);
dsp_sine_sat[i] = (int)(s * SAT_DEVIATION);
+ dsp_sine_test[i] = (int)(s * FSK_DEVIATION);
}
/* sync checker */
@@ -245,6 +249,10 @@ int dsp_init_sender(amps_t *amps, int high_pass, int tolerant)
}
sat_reset(amps, "Initial state");
+ /* test tone */
+ amps->test_phaseshift256 = 256.0 / ((double)amps->sender.samplerate / 1000.0);
+ PDEBUG(DDSP, DEBUG_DEBUG, "test_phaseshift256 = %.4f\n", amps->test_phaseshift256);
+
/* use this filter to remove dc level for 0-crossing detection
* if we have de-emphasis, we don't need it, so high_pass is not set. */
if (high_pass) {
@@ -442,6 +450,24 @@ static void sat_encode(amps_t *amps, int16_t *samples, int length)
amps->sat_phase256 = phase;
}
+static void test_tone_encode(amps_t *amps, int16_t *samples, int length)
+{
+ double phaseshift, phase;
+ int i;
+
+ phaseshift = amps->test_phaseshift256;
+ phase = amps->test_phase256;
+
+ for (i = 0; i < length; i++) {
+ *samples++ = dsp_sine_test[((uint8_t)phase) & 0xff];
+ phase += phaseshift;
+ if (phase >= 256)
+ phase -= 256;
+ }
+
+ amps->test_phase256 = phase;
+}
+
/* Provide stream of audio toward radio unit */
void sender_send(sender_t *sender, int16_t *samples, int length)
{
@@ -451,8 +477,8 @@ void sender_send(sender_t *sender, int16_t *samples, int length)
again:
switch (amps->dsp_mode) {
case DSP_MODE_OFF:
- /* silence, if transmitter is off */
- memset(samples, 0, length * sizeof(*samples));
+ /* test tone, if transmitter is off */
+ test_tone_encode(amps, samples, length);
break;
case DSP_MODE_AUDIO_RX_AUDIO_TX:
jitter_load(&amps->sender.audio, samples, length);
@@ -717,9 +743,9 @@ static void sat_decode(amps_t *amps, int16_t *samples, int length)
if (quality[1] < 0)
quality[1] = 0;
- PDEBUG(DDSP, DEBUG_NOTICE, "SAT level %.2f%% quality %.0f%%\n", result[0] * 32767.0 / SAT_DEVIATION / 0.63662 * 100.0, quality[0] * 100.0);
+ PDEBUG_CHAN(DDSP, DEBUG_NOTICE, "SAT level %.2f%% quality %.0f%%\n", result[0] * 32767.0 / SAT_DEVIATION / 0.63662 * 100.0, quality[0] * 100.0);
if (amps->sender.loopback || debuglevel == DEBUG_DEBUG) {
- PDEBUG(DDSP, debuglevel, "Signaling Tone level %.2f%% quality %.0f%%\n", result[2] * 32767.0 / FSK_DEVIATION / 0.63662 * 100.0, quality[1] * 100.0);
+ PDEBUG_CHAN(DDSP, debuglevel, "Signaling Tone level %.2f%% quality %.0f%%\n", result[2] * 32767.0 / FSK_DEVIATION / 0.63662 * 100.0, quality[1] * 100.0);
}
if (quality[0] > SAT_QUALITY) {
if (amps->sat_detected == 0) {
@@ -727,7 +753,7 @@ static void sat_decode(amps_t *amps, int16_t *samples, int length)
if (amps->sat_detect_count == SAT_DETECT_COUNT) {
amps->sat_detected = 1;
amps->sat_detect_count = 0;
- PDEBUG(DDSP, DEBUG_DEBUG, "SAT signal detected with level=%.0f%%, quality=%.0f%%.\n", result[0] / 0.63662 * 100.0, quality[0] * 100.0);
+ PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "SAT signal detected with level=%.0f%%, quality=%.0f%%.\n", result[0] / 0.63662 * 100.0, quality[0] * 100.0);
amps_rx_sat(amps, 1, quality[0]);
}
} else
@@ -738,7 +764,7 @@ static void sat_decode(amps_t *amps, int16_t *samples, int length)
if (amps->sat_detect_count == SAT_LOST_COUNT) {
amps->sat_detected = 0;
amps->sat_detect_count = 0;
- PDEBUG(DDSP, DEBUG_DEBUG, "SAT signal lost.\n");
+ PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "SAT signal lost.\n");
amps_rx_sat(amps, 0, 0.0);
}
} else
@@ -750,7 +776,7 @@ static void sat_decode(amps_t *amps, int16_t *samples, int length)
if (amps->sig_detect_count == SIG_DETECT_COUNT) {
amps->sig_detected = 1;
amps->sig_detect_count = 0;
- PDEBUG(DDSP, DEBUG_DEBUG, "Signaling Tone detected with level=%.0f%%, quality=%.0f%%.\n", result[2] / 0.63662 * 100.0, quality[1] * 100.0);
+ PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Signaling Tone detected with level=%.0f%%, quality=%.0f%%.\n", result[2] / 0.63662 * 100.0, quality[1] * 100.0);
amps_rx_signaling_tone(amps, 1, quality[1]);
}
} else
@@ -761,7 +787,7 @@ static void sat_decode(amps_t *amps, int16_t *samples, int length)
if (amps->sig_detect_count == SIG_LOST_COUNT) {
amps->sig_detected = 0;
amps->sig_detect_count = 0;
- PDEBUG(DDSP, DEBUG_DEBUG, "Signaling Tone lost.\n");
+ PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Signaling Tone lost.\n");
amps_rx_signaling_tone(amps, 0, 0.0);
}
} else
@@ -870,7 +896,7 @@ void sender_receive(sender_t *sender, int16_t *samples, int length)
/* Reset SAT detection states, so ongoing tone will be detected again. */
static void sat_reset(amps_t *amps, const char *reason)
{
- PDEBUG(DDSP, DEBUG_DEBUG, "SAT detector reset: %s.\n", reason);
+ PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "SAT detector reset: %s.\n", reason);
amps->sat_detected = 0;
amps->sat_detect_count = 0;
amps->sig_detected = 0;
@@ -887,11 +913,24 @@ void amps_set_dsp_mode(amps_t *amps, enum dsp_mode mode, int frame_length)
if (mode == DSP_MODE_FRAME_RX_FRAME_TX) {
/* reset SAT detection */
sat_reset(amps, "Change to FOCC");
+ PDEBUG_CHAN(DDSP, DEBUG_INFO, "Change mode to FOCC\n");
}
if (amps->dsp_mode == DSP_MODE_FRAME_RX_FRAME_TX
&& (mode == DSP_MODE_AUDIO_RX_AUDIO_TX || mode == DSP_MODE_AUDIO_RX_FRAME_TX)) {
/* reset SAT detection */
sat_reset(amps, "Change from FOCC to FVC");
+ PDEBUG_CHAN(DDSP, DEBUG_INFO, "Change mode from FOCC to FVC\n");
+ }
+ if (amps->dsp_mode == DSP_MODE_OFF
+ && (mode == DSP_MODE_AUDIO_RX_AUDIO_TX || mode == DSP_MODE_AUDIO_RX_FRAME_TX)) {
+ /* reset SAT detection */
+ sat_reset(amps, "Enable FVC");
+ PDEBUG_CHAN(DDSP, DEBUG_INFO, "Change mode from OFF to FVC\n");
+ }
+ if (mode == DSP_MODE_OFF) {
+ /* reset SAT detection */
+ sat_reset(amps, "Disable FVC");
+ PDEBUG_CHAN(DDSP, DEBUG_INFO, "Change mode from FVC to OFF\n");
}
amps->dsp_mode = mode;
diff --git a/src/amps/frame.c b/src/amps/frame.c
index 06e851f..f7ce9a5 100644
--- a/src/amps/frame.c
+++ b/src/amps/frame.c
@@ -2919,7 +2919,7 @@ static uint64_t amps_encode_word1_extended_address_word_a(uint16_t min2, uint8_t
memset(&frame, 0, sizeof(frame));
frame.ie[AMPS_IE_T1T2] = 2;
- frame.ie[AMPS_IE_SCC] = 11;
+ frame.ie[AMPS_IE_SCC] = 3;
frame.ie[AMPS_IE_MIN2] = min2;
frame.ie[AMPS_IE_EF] = 0;
frame.ie[AMPS_IE_LOCAL_MSG_TYPE] = msg_type;
@@ -2947,7 +2947,7 @@ static uint64_t amps_encode_mobile_station_control_message_word1_a(uint8_t pscc,
memset(&frame, 0, sizeof(frame));
frame.ie[AMPS_IE_T1T2] = 2;
- frame.ie[AMPS_IE_SCC] = 11;
+ frame.ie[AMPS_IE_SCC] = 3;
frame.ie[AMPS_IE_PSCC] = pscc;
frame.ie[AMPS_IE_EF] = 0;
frame.ie[AMPS_IE_LOCAL_MSG_TYPE] = msg_type;
diff --git a/src/amps/main.c b/src/amps/main.c
index 2ad283f..7561a8f 100644
--- a/src/amps/main.c
+++ b/src/amps/main.c
@@ -354,7 +354,7 @@ int main(int argc, char *argv[])
fprintf(stderr, "Failed to create \"Sender\" instance. Quitting!\n");
goto fail;
}
- printf("Base station on channel %d ready, please tune transmitter to %.3f MHz and receiver to %.3f MHz.\n", kanal[i], amps_channel2freq(kanal[i], 0), amps_channel2freq(kanal[i], 1));
+ printf("Base station on channel %d ready (%s), please tune transmitter to %.3f MHz and receiver to %.3f MHz.\n", kanal[i], chan_type_long_name(chan_type[i]), amps_channel2freq(kanal[i], 0), amps_channel2freq(kanal[i], 1));
}
signal(SIGINT,sighandler);