diff options
author | Andreas Eversberg <jolly@eversberg.eu> | 2016-10-30 09:25:45 +0100 |
---|---|---|
committer | Andreas Eversberg <jolly@eversberg.eu> | 2016-10-30 09:37:14 +0100 |
commit | 63f39e105b5356a2d096ef78b9a436d4041a2502 (patch) | |
tree | 6333eb82142cfbe0f4c43800042c37caf2380879 /src | |
parent | b70f4ecebc242e72dd3e1cd2c8a85afcf118afa1 (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.c | 97 | ||||
-rw-r--r-- | src/amps/amps.h | 2 | ||||
-rw-r--r-- | src/amps/dsp.c | 57 | ||||
-rw-r--r-- | src/amps/frame.c | 4 | ||||
-rw-r--r-- | src/amps/main.c | 2 |
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(&s->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); |